mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 11:19:04 +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.ForumSharingManager;
|
||||
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.PrivateMessageFactory;
|
||||
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 java.util.concurrent.Executor;
|
||||
import java.util.logging.Formatter;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@@ -165,6 +167,10 @@ public interface AndroidComponent
|
||||
|
||||
FeatureFlags featureFlags();
|
||||
|
||||
PersistentLogManager persistentLogManager();
|
||||
|
||||
Formatter formatter();
|
||||
|
||||
void inject(SignInReminderReceiver 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.DevReportActivity;
|
||||
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.logging.Formatter;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.LogRecord;
|
||||
import java.util.logging.Logger;
|
||||
@@ -36,6 +40,7 @@ import java.util.logging.Logger;
|
||||
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
|
||||
import static java.util.logging.Level.FINE;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.acra.ReportField.ANDROID_VERSION;
|
||||
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.USER_APP_START_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;
|
||||
|
||||
@ReportsCrashes(
|
||||
@@ -120,9 +126,22 @@ public class BriarApplicationImpl extends Application
|
||||
rootLogger.addHandler(logHandler);
|
||||
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");
|
||||
|
||||
applicationComponent = createApplicationComponent();
|
||||
EmojiManager.install(new GoogleEmojiProvider());
|
||||
}
|
||||
|
||||
|
||||
@@ -15,10 +15,12 @@ import org.acra.builder.ReportBuilder;
|
||||
import org.acra.builder.ReportPrimer;
|
||||
import org.briarproject.bramble.api.Pair;
|
||||
import org.briarproject.briar.BuildConfig;
|
||||
import org.briarproject.briar.android.AndroidComponent;
|
||||
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.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
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.content.Context.ACTIVITY_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_SERVICE;
|
||||
import static android.net.ConnectivityManager.TYPE_MOBILE;
|
||||
@@ -81,13 +84,28 @@ public class BriarReportPrimer implements ReportPrimer {
|
||||
// Log
|
||||
BriarApplication app =
|
||||
(BriarApplication) ctx.getApplicationContext();
|
||||
AndroidComponent appComponent = app.getApplicationComponent();
|
||||
PersistentLogManager logManager =
|
||||
appComponent.persistentLogManager();
|
||||
Formatter formatter = appComponent.formatter();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Formatter formatter = new BriefLogFormatter();
|
||||
for (LogRecord record : app.getRecentLogRecords()) {
|
||||
sb.append(formatter.format(record)).append('\n');
|
||||
sb.append(formatter.format(record));
|
||||
}
|
||||
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
|
||||
Object o = ctx.getSystemService(ACTIVITY_SERVICE);
|
||||
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.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,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.briar.android.logging;
|
||||
package org.briarproject.briar.logging;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
@@ -47,6 +47,7 @@ public class BriefLogFormatter extends Formatter {
|
||||
sb.append('\n');
|
||||
appendThrowable(sb, t);
|
||||
}
|
||||
sb.append('\n');
|
||||
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