Save logs to disk.

This commit is contained in:
akwizgran
2018-10-08 11:12:15 +01:00
parent ab682c82a3
commit 61407c3e06
8 changed files with 183 additions and 5 deletions

View File

@@ -6,6 +6,7 @@ import org.briarproject.briar.feed.DnsModule;
import org.briarproject.briar.feed.FeedModule;
import org.briarproject.briar.forum.ForumModule;
import org.briarproject.briar.introduction.IntroductionModule;
import org.briarproject.briar.logging.LoggingModule;
import org.briarproject.briar.messaging.MessagingModule;
import org.briarproject.briar.privategroup.PrivateGroupModule;
import org.briarproject.briar.privategroup.invitation.GroupInvitationModule;
@@ -22,6 +23,7 @@ import dagger.Module;
ForumModule.class,
GroupInvitationModule.class,
IntroductionModule.class,
LoggingModule.class,
MessagingModule.class,
PrivateGroupModule.class,
SharingModule.class,

View File

@@ -0,0 +1,64 @@
package org.briarproject.briar.logging;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;
import javax.annotation.concurrent.ThreadSafe;
import static java.util.Locale.US;
@ThreadSafe
@NotNullByDefault
public class BriefLogFormatter extends Formatter {
private final Object lock = new Object();
private final DateFormat dateFormat; // Locking: lock
private final Date date; // Locking: lock
public BriefLogFormatter() {
synchronized (lock) {
dateFormat = new SimpleDateFormat("MM-dd HH:mm:ss.SSS ", US);
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
date = new Date();
}
}
@Override
public String format(LogRecord record) {
String dateString;
synchronized (lock) {
date.setTime(record.getMillis());
dateString = dateFormat.format(date);
}
StringBuilder sb = new StringBuilder(dateString);
sb.append(record.getLevel().getName().charAt(0)).append('/');
String tag = record.getLoggerName();
tag = tag.substring(tag.lastIndexOf('.') + 1);
sb.append(tag).append(": ");
sb.append(record.getMessage());
Throwable t = record.getThrown();
if (t != null) {
sb.append('\n');
appendThrowable(sb, t);
}
sb.append('\n');
return sb.toString();
}
private void appendThrowable(StringBuilder sb, Throwable t) {
sb.append(t);
for (StackTraceElement e : t.getStackTrace())
sb.append("\n at ").append(e);
Throwable cause = t.getCause();
if (cause != null) {
sb.append("\n Caused by: ");
appendThrowable(sb, cause);
}
}
}

View File

@@ -0,0 +1,23 @@
package org.briarproject.briar.logging;
import org.briarproject.briar.api.logging.PersistentLogManager;
import java.util.logging.Formatter;
import dagger.Module;
import dagger.Provides;
@Module
public class LoggingModule {
@Provides
Formatter provideFormatter() {
return new BriefLogFormatter();
}
@Provides
PersistentLogManager providePersistentLogManager(
PersistentLogManagerImpl logManager) {
return logManager;
}
}

View File

@@ -0,0 +1,93 @@
package org.briarproject.briar.logging;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.lifecycle.ShutdownManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.Scheduler;
import org.briarproject.briar.api.logging.PersistentLogManager;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Logger;
import java.util.logging.StreamHandler;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static java.util.Collections.emptyList;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.MINUTES;
@ThreadSafe
@NotNullByDefault
class PersistentLogManagerImpl implements PersistentLogManager {
private static final Logger LOG =
Logger.getLogger(PersistentLogManagerImpl.class.getName());
private static final String LOG_FILE = "briar.log";
private static final String OLD_LOG_FILE = "briar.log.old";
private static final long FLUSH_INTERVAL_MS = MINUTES.toMillis(5);
private final ScheduledExecutorService scheduler;
private final Executor ioExecutor;
private final ShutdownManager shutdownManager;
private final Formatter formatter;
@Inject
PersistentLogManagerImpl(@Scheduler ScheduledExecutorService scheduler,
@IoExecutor Executor ioExecutor, ShutdownManager shutdownManager,
Formatter formatter) {
this.scheduler = scheduler;
this.ioExecutor = ioExecutor;
this.shutdownManager = shutdownManager;
this.formatter = formatter;
}
@Override
public Handler createLogHandler(File dir) throws IOException {
File logFile = new File(dir, LOG_FILE);
File oldLogFile = new File(dir, OLD_LOG_FILE);
if (oldLogFile.exists() && !oldLogFile.delete())
LOG.warning("Failed to delete old log file");
if (logFile.exists() && !logFile.renameTo(oldLogFile))
LOG.warning("Failed to rename log file");
try {
OutputStream out = new FileOutputStream(logFile);
StreamHandler handler = new StreamHandler(out, formatter);
scheduler.scheduleWithFixedDelay(() ->
ioExecutor.execute(handler::flush),
FLUSH_INTERVAL_MS, FLUSH_INTERVAL_MS, MILLISECONDS);
shutdownManager.addShutdownHook(handler::flush);
return handler;
} catch (SecurityException e) {
throw new IOException(e);
}
}
@Override
public Collection<String> getPersistedLog(File dir) throws IOException {
File oldLogFile = new File(dir, OLD_LOG_FILE);
if (oldLogFile.exists()) {
LOG.info("Reading old log file");
List<String> lines = new ArrayList<>();
Scanner s = new Scanner(oldLogFile);
while (s.hasNextLine()) lines.add(s.nextLine());
s.close();
return lines;
} else {
LOG.info("Old log file does not exist");
return emptyList();
}
}
}