diff --git a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
index 1e07806414b3337872e7d5654debc7f2d61b654f..061d6ccb982a9b3ce73acc2d64492ea336859d83 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,43 @@ 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 void log(String event, LogEntry.LogLevel level, Object... rawPayload) {
+		if (rawPayload.length % 2 != 0) {
+			throw new IllegalArgumentException("");
+		}
+		Map<String, Object> payload = new HashMap<>();
+		for (int i = 0; i < rawPayload.length; i += 2) {
+			payload.put((String) rawPayload[i], rawPayload[i + 1]);
+		}
+		log(event, payload, LogEntry.LogLevel.INFO);
+	}
+
+	@Override
+	public void log(String event, Object... rawPayload) {
+		log(event, LogEntry.LogLevel.INFO, rawPayload);
+	}
+
 	@Override
 	public List<Session> getMySessions(final User user, final int start, final int limit) {
 		return this.getDatabaseDao().getSessionsForUsername(user.getUsername(), start, limit);
@@ -829,13 +853,18 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 			@CacheEvict(value = "preparationquestions", allEntries = true, condition = "#question.getQuestionVariant().equals('preparation')"),
 			@CacheEvict(value = "flashcardquestions", allEntries = true, condition = "#question.getQuestionVariant().equals('flashcard')") })
 	@Override
-	public void deleteQuestionWithAnswers(final Question question) {
+	public int deleteQuestionWithAnswers(final Question question) {
 		try {
-			deleteAnswers(question);
+			int count = deleteAnswers(question);
 			deleteDocument(question.get_id());
+			log("delete", "type", "question", "answerCount", count);
+
+			return count;
 		} catch (final IOException e) {
 			LOGGER.error("IOException: Could not delete question {}", question.get_id());
 		}
+
+		return 0;
 	}
 
 	@Caching(evict = { @CacheEvict(value = "questions", allEntries = true),
@@ -844,12 +873,12 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 			@CacheEvict(value = "preparationquestions", key = "#session"),
 			@CacheEvict(value = "flashcardquestions", key = "#session") })
 	@Override
-	public void deleteAllQuestionsWithAnswers(final Session session) {
+	public int[] deleteAllQuestionsWithAnswers(final Session session) {
 		final NovaView view = new NovaView("skill_question/by_session");
-		deleteAllQuestionDocumentsWithAnswers(session, view);
+		return deleteAllQuestionDocumentsWithAnswers(session, view);
 	}
 
-	private void deleteAllQuestionDocumentsWithAnswers(final Session session, final NovaView view) {
+	private int[] deleteAllQuestionDocumentsWithAnswers(final Session session, final NovaView view) {
 		view.setStartKeyArray(session.get_id());
 		view.setEndKey(session.get_id(), "{}");
 		final ViewResults results = getDatabase().view(view);
@@ -861,7 +890,12 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 			q.set_rev(d.getJSONObject("value").getString("_rev"));
 			questions.add(q);
 		}
-		deleteAllAnswersWithQuestions(questions);
+
+		int[] count = deleteAllAnswersWithQuestions(questions);
+		log("delete", "type", "question", "questionCount", count[0]);
+		log("delete", "type", "answer", "answerCount", count[1]);
+
+		return count;
 	}
 
 	private void deleteDocument(final String documentId) throws IOException {
@@ -871,7 +905,7 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 
 	@CacheEvict("answers")
 	@Override
-	public void deleteAnswers(final Question question) {
+	public int deleteAnswers(final Question question) {
 		try {
 			final NovaView view = new NovaView("answer/cleanup");
 			view.setKey(question.get_id());
@@ -885,9 +919,14 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 				answersToDelete.add(d);
 			}
 			database.bulkSaveDocuments(answersToDelete.toArray(new Document[answersToDelete.size()]));
+			log("delete", "type", "answer", "answerCount", answersToDelete.size());
+
+			return answersToDelete.size();
 		} catch (final IOException e) {
 			LOGGER.error("IOException: Could not delete answers for question {}", question.get_id());
 		}
+
+		return 0;
 	}
 
 	@Override
@@ -1267,6 +1306,10 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 					case "closedSessions":
 						stats.setClosedSessions(stats.getClosedSessions() + value);
 						break;
+					case "deletedSessions":
+						/* Deleted sessions are not exposed separately for now. */
+						stats.setClosedSessions(stats.getClosedSessions() + value);
+						break;
 					case "answers":
 						stats.setAnswers(stats.getAnswers() + value);
 						break;
@@ -1568,6 +1611,7 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 	public void deleteAnswer(final String answerId) {
 		try {
 			database.deleteDocument(database.getDocument(answerId));
+			log("delete", "type", "answer");
 		} catch (final IOException e) {
 			LOGGER.error("Could not delete answer {} because of {}", answerId, e.getMessage());
 		}
@@ -1577,6 +1621,7 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 	public void deleteInterposedQuestion(final InterposedQuestion question) {
 		try {
 			deleteDocument(question.get_id());
+			log("delete", "type", "comment");
 		} catch (final IOException e) {
 			LOGGER.error("Could not delete interposed question {} because of {}", question.get_id(), e.getMessage());
 		}
@@ -1674,64 +1719,77 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 
 	@Override
 	@Caching(evict = { @CacheEvict("sessions"), @CacheEvict(cacheNames="sessions", key="#p0.keyword") })
-	public void deleteSession(final Session session) {
+	public int[] deleteSession(final Session session) {
+		int[] count = new int[] { 0, 0 };
 		try {
-			deleteAllQuestionsWithAnswers(session);
+			count = deleteAllQuestionsWithAnswers(session);
 			deleteDocument(session.get_id());
 			LOGGER.debug("Deleted session document {} and related data.", session.get_id());
+			log("delete", "type", "session", "id", session.get_id());
 		} catch (final IOException e) {
 			LOGGER.error("Could not delete session {}", session);
 		}
+
+		return count;
 	}
 
 	@Override
-	public boolean deleteInactiveGuestSessions(long lastActivityBefore) {
+	public int[] deleteInactiveGuestSessions(long lastActivityBefore) {
 		NovaView view = new NovaView("session/by_last_activity_for_guests");
 		view.setEndKey(lastActivityBefore);
-		List<Document> results = this.getDatabase().view(view).getResults();
+		final List<Document> results = this.getDatabase().view(view).getResults();
+		int[] count = new int[3];
 
 		for (Document oldDoc : results) {
 			Session s = new Session();
 			s.set_id(oldDoc.getId());
 			s.set_rev(oldDoc.getJSONObject("value").getString("_rev"));
-			deleteSession(s);
+			int[] qaCount = deleteSession(s);
+			count[1] += qaCount[0];
+			count[2] += qaCount[1];
 		}
 
 		if (results.size() > 0) {
 			LOGGER.info("Deleted {} inactive guest sessions.", results.size());
+			log("cleanup", "type", "session", "sessionCount", results.size(), "questionCount", count[1], "answerCount", count[2]);
 		}
+		count[0] = results.size();
 
-		return false;
+		return count;
 	}
 
 	@Override
-	public boolean deleteInactiveGuestVisitedSessionLists(long lastActivityBefore) {
+	public int deleteInactiveGuestVisitedSessionLists(long lastActivityBefore) {
 		try {
 			NovaView view = new NovaView("logged_in/by_last_activity_for_guests");
 			view.setEndKey(lastActivityBefore);
 			List<Document> results = this.getDatabase().view(view).getResults();
+			Map<String, Object> log = new HashMap<>();
 
 			final List<Document> newDocs = new ArrayList<Document>();
-			for (Document oldDoc : results) {
+			for (final Document oldDoc : results) {
 				final Document newDoc = new Document();
 				newDoc.setId(oldDoc.getId());
 				newDoc.setRev(oldDoc.getJSONObject("value").getString("_rev"));
 				newDoc.put("_deleted", true);
 				newDocs.add(newDoc);
 				LOGGER.debug("Marked logged_in document {} for deletion.", oldDoc.getId());
+				/* Use log type 'user' since effectively the user is deleted in case of guests */
+				log("delete", "type", "user", "id", oldDoc.getId());
 			}
 
 			if (newDocs.size() > 0) {
 				getDatabase().bulkSaveDocuments(newDocs.toArray(new Document[newDocs.size()]));
 				LOGGER.info("Deleted {} visited session lists of inactive users.", newDocs.size());
+				log("cleanup", "type", "visitedsessions", "count", newDocs.size());
 			}
 
-			return true;
+			return newDocs.size();
 		} catch (IOException e) {
 			LOGGER.error("Could not delete visited session lists of inactive users.");
 		}
 
-		return false;
+		return 0;
 	}
 
 	@Cacheable("lecturequestions")
@@ -1866,9 +1924,9 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 			@CacheEvict("lecturequestions"),
 			@CacheEvict(value = "answers", allEntries = true)})
 	@Override
-	public void deleteAllLectureQuestionsWithAnswers(final Session session) {
+	public int[] deleteAllLectureQuestionsWithAnswers(final Session session) {
 		final NovaView view = new NovaView("skill_question/lecture_question_by_session");
-		deleteAllQuestionDocumentsWithAnswers(session, view);
+		return deleteAllQuestionDocumentsWithAnswers(session, view);
 	}
 
 	/* TODO: Only evict cache entry for the answer's question. This requires some refactoring. */
@@ -1877,9 +1935,9 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 			@CacheEvict("flashcardquestions"),
 			@CacheEvict(value = "answers", allEntries = true)})
 	@Override
-	public void deleteAllFlashcardsWithAnswers(final Session session) {
+	public int[] deleteAllFlashcardsWithAnswers(final Session session) {
 		final NovaView view = new NovaView("skill_question/flashcard_by_session");
-		deleteAllQuestionDocumentsWithAnswers(session, view);
+		return deleteAllQuestionDocumentsWithAnswers(session, view);
 	}
 
 	/* TODO: Only evict cache entry for the answer's question. This requires some refactoring. */
@@ -1888,9 +1946,9 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 			@CacheEvict("preparationquestions"),
 			@CacheEvict(value = "answers", allEntries = true)})
 	@Override
-	public void deleteAllPreparationQuestionsWithAnswers(final Session session) {
+	public int[] deleteAllPreparationQuestionsWithAnswers(final Session session) {
 		final NovaView view = new NovaView("skill_question/preparation_question_by_session");
-		deleteAllQuestionDocumentsWithAnswers(session, view);
+		return deleteAllQuestionDocumentsWithAnswers(session, view);
 	}
 
 	@Override
@@ -1963,32 +2021,41 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 	}
 
 	@Override
-	public void deleteAllInterposedQuestions(final Session session) {
+	public int deleteAllInterposedQuestions(final Session session) {
 		final NovaView view = new NovaView("interposed_question/by_session");
 		view.setKey(session.get_id());
 		final ViewResults questions = getDatabase().view(view);
-		deleteAllInterposedQuestions(session, questions);
+
+		return deleteAllInterposedQuestions(session, questions);
 	}
 
 	@Override
-	public void deleteAllInterposedQuestions(final Session session, final User user) {
+	public int deleteAllInterposedQuestions(final Session session, final User user) {
 		final NovaView view = new NovaView("interposed_question/by_session_and_creator");
 		view.setKey(session.get_id(), user.getUsername());
 		final ViewResults questions = getDatabase().view(view);
-		deleteAllInterposedQuestions(session, questions);
+
+		return deleteAllInterposedQuestions(session, questions);
 	}
 
-	private void deleteAllInterposedQuestions(final Session session, final ViewResults questions) {
+	private int deleteAllInterposedQuestions(final Session session, final ViewResults questions) {
 		if (questions == null || questions.isEmpty()) {
-			return;
+			return 0;
 		}
-		for (final Document document : questions.getResults()) {
+		List<Document> results = questions.getResults();
+		/* TODO: use bulk delete */
+		for (final Document document : results) {
 			try {
 				deleteDocument(document.getId());
 			} catch (final IOException e) {
 				LOGGER.error("Could not delete all interposed questions {}", session);
 			}
 		}
+
+		/* This does account for failed deletions */
+		log("delete", "type", "comment", "commentCount", results.size());
+
+		return results.size();
 	}
 
 	@Override
@@ -2059,28 +2126,31 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 	/* TODO: Only evict cache entry for the answer's question. This requires some refactoring. */
 	@CacheEvict(value = "answers", allEntries = true)
 	@Override
-	public void deleteAllQuestionsAnswers(final Session session) {
+	public int deleteAllQuestionsAnswers(final Session session) {
 		final List<Question> questions = getQuestions(new NovaView("skill_question/by_session"), session);
 		getDatabaseDao().resetQuestionsRoundState(session, questions);
-		deleteAllAnswersForQuestions(questions);
+
+		return deleteAllAnswersForQuestions(questions);
 	}
 
 	/* TODO: Only evict cache entry for the answer's question. This requires some refactoring. */
 	@CacheEvict(value = "answers", allEntries = true)
 	@Override
-	public void deleteAllPreparationAnswers(final Session session) {
+	public int deleteAllPreparationAnswers(final Session session) {
 		final List<Question> questions = getQuestions(new NovaView("skill_question/preparation_question_by_session"), session);
 		getDatabaseDao().resetQuestionsRoundState(session, questions);
-		deleteAllAnswersForQuestions(questions);
+
+		return deleteAllAnswersForQuestions(questions);
 	}
 
 	/* TODO: Only evict cache entry for the answer's question. This requires some refactoring. */
 	@CacheEvict(value = "answers", allEntries = true)
 	@Override
-	public void deleteAllLectureAnswers(final Session session) {
+	public int deleteAllLectureAnswers(final Session session) {
 		final List<Question> questions = getQuestions(new NovaView("skill_question/lecture_question_by_session"), session);
 		getDatabaseDao().resetQuestionsRoundState(session, questions);
-		deleteAllAnswersForQuestions(questions);
+
+		return deleteAllAnswersForQuestions(questions);
 	}
 
 	@Caching(evict = { @CacheEvict(value = "questions", allEntries = true),
@@ -2107,7 +2177,7 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 		}
 	}
 
-	private boolean deleteAllAnswersForQuestions(List<Question> questions) {
+	private int deleteAllAnswersForQuestions(List<Question> questions) {
 		List<String> questionIds = new ArrayList<String>();
 		for (Question q : questions) {
 			questionIds.add(q.get_id());
@@ -2124,14 +2194,16 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 		}
 		try {
 			getDatabase().bulkSaveDocuments(allAnswers.toArray(new Document[allAnswers.size()]));
+
+			return allAnswers.size();
 		} catch (IOException e) {
 			LOGGER.error("Could not bulk delete answers: {}", e.getMessage());
-			return false;
 		}
-		return true;
+
+		return 0;
 	}
 
-	private boolean deleteAllAnswersWithQuestions(List<Question> questions) {
+	private int[] deleteAllAnswersWithQuestions(List<Question> questions) {
 		List<String> questionIds = new ArrayList<String>();
 		final List<Document> allQuestions = new ArrayList<Document>();
 		for (Question q : questions) {
@@ -2158,11 +2230,13 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 			List<Document> deleteList = new ArrayList<Document>(allAnswers);
 			deleteList.addAll(allQuestions);
 			getDatabase().bulkSaveDocuments(deleteList.toArray(new Document[deleteList.size()]));
+
+			return new int[] { deleteList.size(), result.size() };
 		} catch (IOException e) {
 			LOGGER.error("Could not bulk delete questions and answers: {}", e.getMessage());
-			return false;
 		}
-		return true;
+
+		return new int[] { 0, 0 };
 	}
 
 	@Cacheable("learningprogress")
@@ -2255,9 +2329,10 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 	}
 
 	@Override
-	public boolean deleteUser(DbUser dbUser) {
+	public boolean deleteUser(final DbUser dbUser) {
 		try {
 			this.deleteDocument(dbUser.getId());
+			log("delete", "type", "user", "id", dbUser.getId());
 
 			return true;
 		} catch (IOException e) {
@@ -2268,7 +2343,7 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 	}
 
 	@Override
-	public boolean deleteInactiveUsers(long lastActivityBefore) {
+	public int deleteInactiveUsers(long lastActivityBefore) {
 		try {
 			NovaView view = new NovaView("user/inactive_by_creation");
 			view.setEndKey(lastActivityBefore);
@@ -2287,14 +2362,15 @@ public class CouchDBDao implements IDatabaseDao, ApplicationEventPublisherAware
 			if (newDocs.size() > 0) {
 				getDatabase().bulkSaveDocuments(newDocs.toArray(new Document[newDocs.size()]));
 				LOGGER.info("Deleted {} inactive users.", newDocs.size());
+				log("cleanup", "type", "user", "count", newDocs.size());
 			}
 
-			return true;
+			return newDocs.size();
 		} catch (IOException e) {
 			LOGGER.error("Could not delete inactive users.");
 		}
 
-		return false;
+		return 0;
 	}
 
 	@Override
diff --git a/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java b/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
index 0b8f4b5f8a85629f58cbfef6f9613b9b960f756d..98b77c5cf250aa5baf818d92d795566f5bae02a9 100644
--- a/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
+++ b/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
@@ -19,26 +19,56 @@ 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 {
+	/**
+	 * Logs an event to the database. Arbitrary data can be attached as payload. Database logging should only be used
+	 * if the logged data is later analyzed by the backend itself. Otherwise use the default logging mechanisms.
+	 *
+	 * @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);
+
+	/**
+	 * Logs an event of informational severity to the database. Arbitrary data can be attached as payload. Database
+	 * logging should only be used if the logged data is later analyzed by the backend itself. Otherwise use the default
+	 * logging mechanisms.
+	 *
+	 * @param event type of the event
+	 * @param payload arbitrary logging data
+	 */
+	void log(String event, Map<String, Object> payload);
+
+	/**
+	 * Logs an event to the database. Arbitrary data can be attached as payload. Database logging should only be used
+	 * if the logged data is later analyzed by the backend itself. Otherwise use the default logging mechanisms.
+	 *
+	 * @param event type of the event
+	 * @param level severity of the event
+	 * @param rawPayload key/value pairs of arbitrary logging data
+	 */
+	void log(String event, LogEntry.LogLevel level, Object... rawPayload);
+
+	/**
+	 * Logs an event of informational severity to the database. Arbitrary data can be attached as payload. Database
+	 * logging should only be used if the logged data is later analyzed by the backend itself. Otherwise use the default
+	 * logging mechanisms.
+	 *
+	 * @param event type of the event
+	 * @param rawPayload key/value pairs of arbitrary logging data
+	 */
+	void log(String event, Object... rawPayload);
+
 	Session getSessionFromKeyword(String keyword);
 
 	List<Session> getMySessions(User user, final int start, final int limit);
@@ -80,9 +110,9 @@ public interface IDatabaseDao {
 
 	List<String> getQuestionIds(Session session, User user);
 
-	void deleteQuestionWithAnswers(Question question);
+	int deleteQuestionWithAnswers(Question question);
 
-	void deleteAllQuestionsWithAnswers(Session session);
+	int[] deleteAllQuestionsWithAnswers(Session session);
 
 	List<String> getUnAnsweredQuestionIds(Session session, User user);
 
@@ -126,7 +156,7 @@ public interface IDatabaseDao {
 
 	Question updateQuestion(Question question);
 
-	void deleteAnswers(Question question);
+	int deleteAnswers(Question question);
 
 	Answer saveAnswer(Answer answer, User user, Question question, Session session);
 
@@ -149,11 +179,11 @@ public interface IDatabaseDao {
 	 *
 	 * @param session the session for deletion
 	 */
-	void deleteSession(Session session);
+	int[] deleteSession(Session session);
 
-	boolean deleteInactiveGuestSessions(long lastActivityBefore);
+	int[] deleteInactiveGuestSessions(long lastActivityBefore);
 
-	boolean deleteInactiveGuestVisitedSessionLists(long lastActivityBefore);
+	int deleteInactiveGuestVisitedSessionLists(long lastActivityBefore);
 
 	List<Question> getLectureQuestionsForUsers(Session session);
 
@@ -179,25 +209,25 @@ public interface IDatabaseDao {
 
 	int countPreparationQuestionAnswers(Session session);
 
-	void deleteAllLectureQuestionsWithAnswers(Session session);
+	int[] deleteAllLectureQuestionsWithAnswers(Session session);
 
-	void deleteAllFlashcardsWithAnswers(Session session);
+	int[] deleteAllFlashcardsWithAnswers(Session session);
 
-	void deleteAllPreparationQuestionsWithAnswers(Session session);
+	int[] deleteAllPreparationQuestionsWithAnswers(Session session);
 
 	List<String> getUnAnsweredLectureQuestionIds(Session session, User user);
 
 	List<String> getUnAnsweredPreparationQuestionIds(Session session, User user);
 
-	void deleteAllInterposedQuestions(Session session);
+	int deleteAllInterposedQuestions(Session session);
 
-	void deleteAllInterposedQuestions(Session session, User user);
+	int deleteAllInterposedQuestions(Session session, User user);
 
 	void publishQuestions(Session session, boolean publish, List<Question> questions);
 
 	List<Question> publishAllQuestions(Session session, boolean publish);
 
-	void deleteAllQuestionsAnswers(Session session);
+	int deleteAllQuestionsAnswers(Session session);
 
 	DbUser createOrUpdateUser(DbUser user);
 
@@ -205,7 +235,7 @@ public interface IDatabaseDao {
 
 	boolean deleteUser(DbUser dbUser);
 
-	boolean deleteInactiveUsers(long lastActivityBefore);
+	int deleteInactiveUsers(long lastActivityBefore);
 
 	CourseScore getLearningProgress(Session session);
 
@@ -217,9 +247,9 @@ public interface IDatabaseDao {
 
 	List<SessionInfo> getMyVisitedSessionsInfo(User currentUser, final int start, final int limit);
 
-	void deleteAllPreparationAnswers(Session session);
+	int deleteAllPreparationAnswers(Session session);
 
-	void deleteAllLectureAnswers(Session session);
+	int deleteAllLectureAnswers(Session session);
 
 	SessionInfo importSession(User user, ImportExportSession importSession);
 
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 0000000000000000000000000000000000000000..cac697c5d8df322fa10615f5bef6b123e0fcf374
--- /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 665b5484816f0c7e538a46b10d03512e1ac34625..b13eb440e720d500a9e614dd66bd3ff787ee50a5 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,26 @@ 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 void log(String event, LogEntry.LogLevel level, Object... rawPayload) {
+		// TODO Auto-generated method stub
+	}
+
+	@Override
+	public void log(String event, Object... rawPayload) {
+		// TODO Auto-generated method stub
+	}
+
 	@Override
 	public Session getSessionFromKeyword(String keyword) {
 		return stubSessions.get(keyword);
@@ -292,13 +300,15 @@ public class StubDatabaseDao implements IDatabaseDao {
 	}
 
 	@Override
-	public void deleteQuestionWithAnswers(Question question) {
+	public int deleteQuestionWithAnswers(Question question) {
 		// TODO Auto-generated method stub
+		return 0;
 	}
 
 	@Override
-	public void deleteAnswers(Question question) {
+	public int deleteAnswers(Question question) {
 		// TODO Auto-generated method stub
+		return 0;
 	}
 
 	@Override
@@ -341,26 +351,24 @@ public class StubDatabaseDao implements IDatabaseDao {
 	}
 
 	@Override
-	public void deleteSession(Session session) {
-		// TODO Auto-generated method stub
+	public int[] deleteSession(Session session) {
+		return new int[] { 0,0 };
 	}
 
 	@Override
-	public boolean deleteInactiveGuestSessions(long lastActivityBefore) {
-		// TODO Auto-generated method stub
-		return false;
+	public int[] deleteInactiveGuestSessions(long lastActivityBefore) {
+		return new int[] { 0,0 };
 	}
 
 	@Override
-	public boolean deleteInactiveGuestVisitedSessionLists(long lastActivityBefore) {
+	public int deleteInactiveGuestVisitedSessionLists(long lastActivityBefore) {
 		// TODO Auto-generated method stub
-		return false;
+		return 0;
 	}
 
 	@Override
-	public void deleteAllQuestionsWithAnswers(Session session) {
-		// TODO Auto-generated method stub
-
+	public int[] deleteAllQuestionsWithAnswers(Session session) {
+		return new int[] { 0, 0 };
 	}
 
 	@Override
@@ -394,21 +402,18 @@ public class StubDatabaseDao implements IDatabaseDao {
 	}
 
 	@Override
-	public void deleteAllLectureQuestionsWithAnswers(Session session) {
-		// TODO Auto-generated method stub
-
+	public int[] deleteAllLectureQuestionsWithAnswers(Session session) {
+		return new int[] { 0, 0 };
 	}
 
 	@Override
-	public void deleteAllFlashcardsWithAnswers(Session session) {
-		// TODO Auto-generated method stub
-
+	public int[] deleteAllFlashcardsWithAnswers(Session session) {
+		return new int[] { 0, 0 };
 	}
 
 	@Override
-	public void deleteAllPreparationQuestionsWithAnswers(Session session) {
-		// TODO Auto-generated method stub
-
+	public int[] deleteAllPreparationQuestionsWithAnswers(Session session) {
+		return new int[] { 0, 0 };
 	}
 
 	@Override
@@ -424,8 +429,8 @@ public class StubDatabaseDao implements IDatabaseDao {
 	}
 
 	@Override
-	public void deleteAllInterposedQuestions(Session session) {
-		// TODO Auto-generated method stub
+	public int deleteAllInterposedQuestions(Session session) {
+		return 0;
 	}
 
 	@Override
@@ -441,9 +446,9 @@ public class StubDatabaseDao implements IDatabaseDao {
 	}
 
 	@Override
-	public void deleteAllQuestionsAnswers(Session session) {
+	public int deleteAllQuestionsAnswers(Session session) {
 		// TODO Auto-generated method stub
-
+		return 0;
 	}
 
 	@Override
@@ -471,9 +476,9 @@ public class StubDatabaseDao implements IDatabaseDao {
 	}
 
 	@Override
-	public boolean deleteInactiveUsers(long lastActivityBefore) {
+	public int deleteInactiveUsers(long lastActivityBefore) {
 		// TODO Auto-generated method stub
-		return false;
+		return 0;
 	}
 
 	@Override
@@ -483,9 +488,9 @@ public class StubDatabaseDao implements IDatabaseDao {
 	}
 
 	@Override
-	public void deleteAllInterposedQuestions(Session session, User user) {
+	public int deleteAllInterposedQuestions(Session session, User user) {
 		// TODO Auto-generated method stub
-
+		return 0;
 	}
 
 	@Override
@@ -513,15 +518,15 @@ public class StubDatabaseDao implements IDatabaseDao {
 	}
 
 	@Override
-	public void deleteAllPreparationAnswers(Session session) {
+	public int deleteAllPreparationAnswers(Session session) {
 		// TODO Auto-generated method stub
-
+		return 0;
 	}
 
 	@Override
-	public void deleteAllLectureAnswers(Session session) {
+	public int deleteAllLectureAnswers(Session session) {
 		// TODO Auto-generated method stub
-
+		return 0;
 	}
 
 	@Override