From f56443c00bfc8b092f23c148ea6a2c773535825d Mon Sep 17 00:00:00 2001
From: Daniel Gerhardt <code@dgerhardt.net>
Date: Mon, 19 Dec 2016 18:25:34 +0100
Subject: [PATCH] Add DB logging

---
 .../java/de/thm/arsnova/dao/CouchDBDao.java   | 35 ++++----
 .../java/de/thm/arsnova/dao/IDatabaseDao.java | 29 ++++---
 .../de/thm/arsnova/entities/LogEntry.java     | 83 +++++++++++++++++++
 .../de/thm/arsnova/dao/StubDatabaseDao.java   | 24 +++---
 4 files changed, 132 insertions(+), 39 deletions(-)
 create mode 100644 src/main/java/de/thm/arsnova/entities/LogEntry.java

diff --git a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
index 1996ea4e..36fb5955 100644
--- a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
+++ b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
@@ -25,20 +25,7 @@ import com.fourspaces.couchdb.View;
 import com.fourspaces.couchdb.ViewResults;
 import de.thm.arsnova.connector.model.Course;
 import de.thm.arsnova.domain.CourseScore;
-import de.thm.arsnova.entities.Answer;
-import de.thm.arsnova.entities.DbUser;
-import de.thm.arsnova.entities.InterposedQuestion;
-import de.thm.arsnova.entities.InterposedReadingCount;
-import de.thm.arsnova.entities.LoggedIn;
-import de.thm.arsnova.entities.Motd;
-import de.thm.arsnova.entities.MotdList;
-import de.thm.arsnova.entities.PossibleAnswer;
-import de.thm.arsnova.entities.Question;
-import de.thm.arsnova.entities.Session;
-import de.thm.arsnova.entities.SessionInfo;
-import de.thm.arsnova.entities.Statistics;
-import de.thm.arsnova.entities.User;
-import de.thm.arsnova.entities.VisitedSession;
+import de.thm.arsnova.entities.*;
 import de.thm.arsnova.entities.transport.AnswerQueueElement;
 import de.thm.arsnova.entities.transport.ImportExportSession;
 import de.thm.arsnova.entities.transport.ImportExportSession.ImportExportQuestion;
@@ -150,6 +137,26 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 		this.publisher = publisher;
 	}
 
+	@Override
+	public void log(String event, Map<String, Object> payload, LogEntry.LogLevel level) {
+		final Document d = new Document();
+		d.put("timestamp", System.currentTimeMillis());
+		d.put("type", "log");
+		d.put("event", event);
+		d.put("level", level.ordinal());
+		d.put("payload", payload);
+		try {
+			database.saveDocument(d);
+		} catch (final IOException e) {
+			LOGGER.error("Logging of '{}' event to database failed.", event);
+		}
+	}
+
+	@Override
+	public void log(String event, Map<String, Object> payload) {
+		log(event, payload, LogEntry.LogLevel.INFO);
+	}
+
 	@Override
 	public List<Session> getMySessions(final User user, final int start, final int limit) {
 		return this.getDatabaseDao().getSessionsForUsername(user.getUsername(), start, limit);
diff --git a/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java b/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
index 4b49f134..9b56e6f8 100644
--- a/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
+++ b/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
@@ -19,26 +19,31 @@ package de.thm.arsnova.dao;
 
 import de.thm.arsnova.connector.model.Course;
 import de.thm.arsnova.domain.CourseScore;
-import de.thm.arsnova.entities.Answer;
-import de.thm.arsnova.entities.DbUser;
-import de.thm.arsnova.entities.InterposedQuestion;
-import de.thm.arsnova.entities.InterposedReadingCount;
-import de.thm.arsnova.entities.LoggedIn;
-import de.thm.arsnova.entities.Motd;
-import de.thm.arsnova.entities.MotdList;
-import de.thm.arsnova.entities.Question;
-import de.thm.arsnova.entities.Session;
-import de.thm.arsnova.entities.SessionInfo;
-import de.thm.arsnova.entities.Statistics;
-import de.thm.arsnova.entities.User;
+import de.thm.arsnova.entities.*;
 import de.thm.arsnova.entities.transport.ImportExportSession;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * All methods the database must support.
  */
 public interface IDatabaseDao {
+	/**
+	 *
+	 * @param event type of the event
+	 * @param payload arbitrary logging data
+	 * @param level severity of the event
+	 */
+	void log(String event, Map<String, Object> payload, LogEntry.LogLevel level);
+
+	/**
+	 *
+	 * @param event type of the event
+	 * @param payload arbitrary logging data
+	 */
+	void log(String event, Map<String, Object> payload);
+
 	Session getSessionFromKeyword(String keyword);
 
 	List<Session> getMySessions(User user, final int start, final int limit);
diff --git a/src/main/java/de/thm/arsnova/entities/LogEntry.java b/src/main/java/de/thm/arsnova/entities/LogEntry.java
new file mode 100644
index 00000000..cac697c5
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/entities/LogEntry.java
@@ -0,0 +1,83 @@
+package de.thm.arsnova.entities;
+
+import java.util.Map;
+
+public class LogEntry {
+	public enum LogLevel {
+		TRACE,
+		DEBUG,
+		INFO,
+		WARN,
+		ERROR,
+		FATAL
+	}
+
+	private String id;
+	private String rev;
+	private long timestamp;
+	private String event;
+	private int level;
+	private Map<String, Object> payload;
+
+	public String getId() {
+		return id;
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	/* CouchDB deserialization */
+	public void set_id(String id) {
+		this.id = id;
+	}
+
+	public String getRev() {
+		return rev;
+	}
+
+	public void setRev(String rev) {
+		this.rev = rev;
+	}
+
+	/* CouchDB deserialization */
+	public void set_rev(String rev) {
+		this.rev = rev;
+	}
+
+	public long getTimestamp() {
+		return timestamp;
+	}
+
+	public void setTimestamp(long timestamp) {
+		this.timestamp = timestamp;
+	}
+
+	public String getEvent() {
+		return event;
+	}
+
+	public void setEvent(String event) {
+		this.event = event;
+	}
+
+	public int getLevel() {
+		return level;
+	}
+
+	public void setLevel(int level) {
+		this.level = level;
+	}
+
+	public void setLevel(LogLevel level) {
+		this.level = level.ordinal();
+	}
+
+	public Map<String, Object> getPayload() {
+		return payload;
+	}
+
+	public void setPayload(Map<String, Object> payload) {
+		this.payload = payload;
+	}
+}
diff --git a/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java b/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java
index acfabb8c..d8d27a62 100644
--- a/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java
+++ b/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java
@@ -19,19 +19,7 @@ package de.thm.arsnova.dao;
 
 import de.thm.arsnova.connector.model.Course;
 import de.thm.arsnova.domain.CourseScore;
-import de.thm.arsnova.entities.Answer;
-import de.thm.arsnova.entities.DbUser;
-import de.thm.arsnova.entities.Feedback;
-import de.thm.arsnova.entities.InterposedQuestion;
-import de.thm.arsnova.entities.InterposedReadingCount;
-import de.thm.arsnova.entities.LoggedIn;
-import de.thm.arsnova.entities.Motd;
-import de.thm.arsnova.entities.MotdList;
-import de.thm.arsnova.entities.Question;
-import de.thm.arsnova.entities.Session;
-import de.thm.arsnova.entities.SessionInfo;
-import de.thm.arsnova.entities.Statistics;
-import de.thm.arsnova.entities.User;
+import de.thm.arsnova.entities.*;
 import de.thm.arsnova.entities.transport.ImportExportSession;
 import de.thm.arsnova.exceptions.NoContentException;
 import de.thm.arsnova.exceptions.NotFoundException;
@@ -119,6 +107,16 @@ public class StubDatabaseDao implements IDatabaseDao {
 		return (stubSessions.get(keyword) == null);
 	}
 
+	@Override
+	public void log(String event, Map<String, Object> payload, LogEntry.LogLevel level) {
+		// TODO Auto-generated method stub
+	}
+
+	@Override
+	public void log(String event, Map<String, Object> payload) {
+		// TODO Auto-generated method stub
+	}
+
 	@Override
 	public Session getSessionFromKeyword(String keyword) {
 		return stubSessions.get(keyword);
-- 
GitLab