mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-22 07:39:53 +01:00
Save logs to disk.
This commit is contained in:
@@ -46,6 +46,7 @@ import org.briarproject.briar.api.feed.FeedManager;
|
|||||||
import org.briarproject.briar.api.forum.ForumManager;
|
import org.briarproject.briar.api.forum.ForumManager;
|
||||||
import org.briarproject.briar.api.forum.ForumSharingManager;
|
import org.briarproject.briar.api.forum.ForumSharingManager;
|
||||||
import org.briarproject.briar.api.introduction.IntroductionManager;
|
import org.briarproject.briar.api.introduction.IntroductionManager;
|
||||||
|
import org.briarproject.briar.api.logging.PersistentLogManager;
|
||||||
import org.briarproject.briar.api.messaging.MessagingManager;
|
import org.briarproject.briar.api.messaging.MessagingManager;
|
||||||
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
|
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
|
||||||
import org.briarproject.briar.api.privategroup.GroupMessageFactory;
|
import org.briarproject.briar.api.privategroup.GroupMessageFactory;
|
||||||
@@ -56,6 +57,7 @@ import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager
|
|||||||
import org.briarproject.briar.api.test.TestDataCreator;
|
import org.briarproject.briar.api.test.TestDataCreator;
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.logging.Formatter;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
@@ -165,6 +167,10 @@ public interface AndroidComponent
|
|||||||
|
|
||||||
FeatureFlags featureFlags();
|
FeatureFlags featureFlags();
|
||||||
|
|
||||||
|
PersistentLogManager persistentLogManager();
|
||||||
|
|
||||||
|
Formatter formatter();
|
||||||
|
|
||||||
void inject(SignInReminderReceiver briarService);
|
void inject(SignInReminderReceiver briarService);
|
||||||
|
|
||||||
void inject(BriarService briarService);
|
void inject(BriarService briarService);
|
||||||
|
|||||||
@@ -27,8 +27,12 @@ import org.briarproject.briar.android.reporting.BriarReportPrimer;
|
|||||||
import org.briarproject.briar.android.reporting.BriarReportSenderFactory;
|
import org.briarproject.briar.android.reporting.BriarReportSenderFactory;
|
||||||
import org.briarproject.briar.android.reporting.DevReportActivity;
|
import org.briarproject.briar.android.reporting.DevReportActivity;
|
||||||
import org.briarproject.briar.android.util.UiUtils;
|
import org.briarproject.briar.android.util.UiUtils;
|
||||||
|
import org.briarproject.briar.api.logging.PersistentLogManager;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.logging.Formatter;
|
||||||
import java.util.logging.Handler;
|
import java.util.logging.Handler;
|
||||||
import java.util.logging.LogRecord;
|
import java.util.logging.LogRecord;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@@ -36,6 +40,7 @@ import java.util.logging.Logger;
|
|||||||
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
|
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
|
||||||
import static java.util.logging.Level.FINE;
|
import static java.util.logging.Level.FINE;
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
|
import static java.util.logging.Level.WARNING;
|
||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
import static org.acra.ReportField.ANDROID_VERSION;
|
import static org.acra.ReportField.ANDROID_VERSION;
|
||||||
import static org.acra.ReportField.APP_VERSION_CODE;
|
import static org.acra.ReportField.APP_VERSION_CODE;
|
||||||
@@ -54,6 +59,7 @@ import static org.acra.ReportField.REPORT_ID;
|
|||||||
import static org.acra.ReportField.STACK_TRACE;
|
import static org.acra.ReportField.STACK_TRACE;
|
||||||
import static org.acra.ReportField.USER_APP_START_DATE;
|
import static org.acra.ReportField.USER_APP_START_DATE;
|
||||||
import static org.acra.ReportField.USER_CRASH_DATE;
|
import static org.acra.ReportField.USER_CRASH_DATE;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
|
import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
|
||||||
|
|
||||||
@ReportsCrashes(
|
@ReportsCrashes(
|
||||||
@@ -120,9 +126,22 @@ public class BriarApplicationImpl extends Application
|
|||||||
rootLogger.addHandler(logHandler);
|
rootLogger.addHandler(logHandler);
|
||||||
rootLogger.setLevel(IS_DEBUG_BUILD ? FINE : INFO);
|
rootLogger.setLevel(IS_DEBUG_BUILD ? FINE : INFO);
|
||||||
|
|
||||||
|
applicationComponent = createApplicationComponent();
|
||||||
|
|
||||||
|
PersistentLogManager logManager =
|
||||||
|
applicationComponent.persistentLogManager();
|
||||||
|
Formatter formatter = applicationComponent.formatter();
|
||||||
|
try {
|
||||||
|
File logDir = getDir("log", MODE_PRIVATE);
|
||||||
|
Handler handler = logManager.createLogHandler(logDir);
|
||||||
|
handler.setFormatter(formatter);
|
||||||
|
rootLogger.addHandler(handler);
|
||||||
|
} catch (IOException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
}
|
||||||
|
|
||||||
LOG.info("Created");
|
LOG.info("Created");
|
||||||
|
|
||||||
applicationComponent = createApplicationComponent();
|
|
||||||
EmojiManager.install(new GoogleEmojiProvider());
|
EmojiManager.install(new GoogleEmojiProvider());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,10 +15,12 @@ import org.acra.builder.ReportBuilder;
|
|||||||
import org.acra.builder.ReportPrimer;
|
import org.acra.builder.ReportPrimer;
|
||||||
import org.briarproject.bramble.api.Pair;
|
import org.briarproject.bramble.api.Pair;
|
||||||
import org.briarproject.briar.BuildConfig;
|
import org.briarproject.briar.BuildConfig;
|
||||||
|
import org.briarproject.briar.android.AndroidComponent;
|
||||||
import org.briarproject.briar.android.BriarApplication;
|
import org.briarproject.briar.android.BriarApplication;
|
||||||
import org.briarproject.briar.android.logging.BriefLogFormatter;
|
import org.briarproject.briar.api.logging.PersistentLogManager;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
@@ -37,6 +39,7 @@ import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE;
|
|||||||
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
|
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
|
||||||
import static android.content.Context.ACTIVITY_SERVICE;
|
import static android.content.Context.ACTIVITY_SERVICE;
|
||||||
import static android.content.Context.CONNECTIVITY_SERVICE;
|
import static android.content.Context.CONNECTIVITY_SERVICE;
|
||||||
|
import static android.content.Context.MODE_PRIVATE;
|
||||||
import static android.content.Context.WIFI_P2P_SERVICE;
|
import static android.content.Context.WIFI_P2P_SERVICE;
|
||||||
import static android.content.Context.WIFI_SERVICE;
|
import static android.content.Context.WIFI_SERVICE;
|
||||||
import static android.net.ConnectivityManager.TYPE_MOBILE;
|
import static android.net.ConnectivityManager.TYPE_MOBILE;
|
||||||
@@ -81,13 +84,28 @@ public class BriarReportPrimer implements ReportPrimer {
|
|||||||
// Log
|
// Log
|
||||||
BriarApplication app =
|
BriarApplication app =
|
||||||
(BriarApplication) ctx.getApplicationContext();
|
(BriarApplication) ctx.getApplicationContext();
|
||||||
|
AndroidComponent appComponent = app.getApplicationComponent();
|
||||||
|
PersistentLogManager logManager =
|
||||||
|
appComponent.persistentLogManager();
|
||||||
|
Formatter formatter = appComponent.formatter();
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
Formatter formatter = new BriefLogFormatter();
|
|
||||||
for (LogRecord record : app.getRecentLogRecords()) {
|
for (LogRecord record : app.getRecentLogRecords()) {
|
||||||
sb.append(formatter.format(record)).append('\n');
|
sb.append(formatter.format(record));
|
||||||
}
|
}
|
||||||
customData.put("Log", sb.toString());
|
customData.put("Log", sb.toString());
|
||||||
|
|
||||||
|
sb = new StringBuilder();
|
||||||
|
try {
|
||||||
|
File logDir = ctx.getDir("log", MODE_PRIVATE);
|
||||||
|
for (String line : logManager.getPersistedLog(logDir)) {
|
||||||
|
sb.append(line).append('\n');
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
sb.append("Could not recover persisted log: ").append(e);
|
||||||
|
}
|
||||||
|
customData.put("Persisted log", sb.toString());
|
||||||
|
|
||||||
// System memory
|
// System memory
|
||||||
Object o = ctx.getSystemService(ACTIVITY_SERVICE);
|
Object o = ctx.getSystemService(ACTIVITY_SERVICE);
|
||||||
ActivityManager am = (ActivityManager) o;
|
ActivityManager am = (ActivityManager) o;
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package org.briarproject.briar.api.logging;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.logging.Handler;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
|
public interface PersistentLogManager {
|
||||||
|
|
||||||
|
Handler createLogHandler(File dir) throws IOException;
|
||||||
|
|
||||||
|
Collection<String> getPersistedLog(File dir) throws IOException;
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import org.briarproject.briar.feed.DnsModule;
|
|||||||
import org.briarproject.briar.feed.FeedModule;
|
import org.briarproject.briar.feed.FeedModule;
|
||||||
import org.briarproject.briar.forum.ForumModule;
|
import org.briarproject.briar.forum.ForumModule;
|
||||||
import org.briarproject.briar.introduction.IntroductionModule;
|
import org.briarproject.briar.introduction.IntroductionModule;
|
||||||
|
import org.briarproject.briar.logging.LoggingModule;
|
||||||
import org.briarproject.briar.messaging.MessagingModule;
|
import org.briarproject.briar.messaging.MessagingModule;
|
||||||
import org.briarproject.briar.privategroup.PrivateGroupModule;
|
import org.briarproject.briar.privategroup.PrivateGroupModule;
|
||||||
import org.briarproject.briar.privategroup.invitation.GroupInvitationModule;
|
import org.briarproject.briar.privategroup.invitation.GroupInvitationModule;
|
||||||
@@ -22,6 +23,7 @@ import dagger.Module;
|
|||||||
ForumModule.class,
|
ForumModule.class,
|
||||||
GroupInvitationModule.class,
|
GroupInvitationModule.class,
|
||||||
IntroductionModule.class,
|
IntroductionModule.class,
|
||||||
|
LoggingModule.class,
|
||||||
MessagingModule.class,
|
MessagingModule.class,
|
||||||
PrivateGroupModule.class,
|
PrivateGroupModule.class,
|
||||||
SharingModule.class,
|
SharingModule.class,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.briarproject.briar.android.logging;
|
package org.briarproject.briar.logging;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
@@ -47,6 +47,7 @@ public class BriefLogFormatter extends Formatter {
|
|||||||
sb.append('\n');
|
sb.append('\n');
|
||||||
appendThrowable(sb, t);
|
appendThrowable(sb, t);
|
||||||
}
|
}
|
||||||
|
sb.append('\n');
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user