From 3983d5aca45cda0caa9090b0f1f4ff31da8095d1 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Mon, 14 Dec 2020 11:44:25 -0500 Subject: [PATCH] Log the threadId of a log. --- .../logsubmit/LogSectionBlockedThreads.java | 37 ++++++++++++++++++ .../logsubmit/LogSectionThreads.java | 27 ++++++------- .../logsubmit/SubmitDebugLogRepository.java | 2 +- .../core/util/logging/PersistentLogger.java | 39 ++++++++++++++----- 4 files changed, 78 insertions(+), 27 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/logsubmit/LogSectionBlockedThreads.java diff --git a/app/src/main/java/org/thoughtcrime/securesms/logsubmit/LogSectionBlockedThreads.java b/app/src/main/java/org/thoughtcrime/securesms/logsubmit/LogSectionBlockedThreads.java new file mode 100644 index 0000000000..d2860a9878 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/logsubmit/LogSectionBlockedThreads.java @@ -0,0 +1,37 @@ +package org.thoughtcrime.securesms.logsubmit; + +import android.content.Context; + +import androidx.annotation.NonNull; + +import java.util.Map; + +public class LogSectionBlockedThreads implements LogSection { + + @Override + public @NonNull String getTitle() { + return "BLOCKED THREADS"; + } + + @Override + public @NonNull CharSequence getContent(@NonNull Context context) { + Map traces = Thread.getAllStackTraces(); + StringBuilder out = new StringBuilder(); + + for (Map.Entry entry : traces.entrySet()) { + if (entry.getKey().getState() == Thread.State.BLOCKED) { + Thread thread = entry.getKey(); + out.append("-- [").append(thread.getId()).append("] ") + .append(thread.getName()).append(" (").append(thread.getState().toString()).append(")\n"); + + for (StackTraceElement element : entry.getValue()) { + out.append(element.toString()).append("\n"); + } + + out.append("\n"); + } + } + + return out.length() == 0 ? "None" : out; + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/logsubmit/LogSectionThreads.java b/app/src/main/java/org/thoughtcrime/securesms/logsubmit/LogSectionThreads.java index 19a1011b8b..fe08b18da5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/logsubmit/LogSectionThreads.java +++ b/app/src/main/java/org/thoughtcrime/securesms/logsubmit/LogSectionThreads.java @@ -4,34 +4,29 @@ import android.content.Context; import androidx.annotation.NonNull; -import java.util.Map; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; public class LogSectionThreads implements LogSection { @Override public @NonNull String getTitle() { - return "BLOCKED THREADS"; + return "THREADS"; } @Override public @NonNull CharSequence getContent(@NonNull Context context) { - Map traces = Thread.getAllStackTraces(); - StringBuilder out = new StringBuilder(); + StringBuilder builder = new StringBuilder(); - for (Map.Entry entry : traces.entrySet()) { - if (entry.getKey().getState() == Thread.State.BLOCKED) { - Thread thread = entry.getKey(); - out.append("-- [").append(thread.getId()).append("] ") - .append(thread.getName()).append(" (").append(thread.getState().toString()).append(")\n"); + List threads = new ArrayList<>(Thread.getAllStackTraces().keySet()); + Collections.sort(threads, (lhs, rhs) -> Long.compare(lhs.getId(), rhs.getId())); - for (StackTraceElement element : entry.getValue()) { - out.append(element.toString()).append("\n"); - } - - out.append("\n"); - } + for (Thread thread : threads) { + builder.append("[").append(thread.getId()).append("] ").append(thread.getName()).append("\n"); } - return out.length() == 0 ? "None" : out; + return builder; } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/logsubmit/SubmitDebugLogRepository.java b/app/src/main/java/org/thoughtcrime/securesms/logsubmit/SubmitDebugLogRepository.java index e169612bc0..ad8501896c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/logsubmit/SubmitDebugLogRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/logsubmit/SubmitDebugLogRepository.java @@ -17,7 +17,6 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.logsubmit.util.Scrubber; import org.thoughtcrime.securesms.net.StandardUserAgentInterceptor; import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess; -import org.thoughtcrime.securesms.tracing.Tracer; import org.whispersystems.libsignal.util.guava.Optional; import java.io.IOException; @@ -64,6 +63,7 @@ public class SubmitDebugLogRepository { add(new LogSectionPermissions()); add(new LogSectionTrace()); add(new LogSectionThreads()); + add(new LogSectionBlockedThreads()); add(new LogSectionLogcat()); add(new LogSectionLogger()); }}; diff --git a/core-util/src/main/java/org/signal/core/util/logging/PersistentLogger.java b/core-util/src/main/java/org/signal/core/util/logging/PersistentLogger.java index ecc5897fdb..39c538f30c 100644 --- a/core-util/src/main/java/org/signal/core/util/logging/PersistentLogger.java +++ b/core-util/src/main/java/org/signal/core/util/logging/PersistentLogger.java @@ -2,6 +2,8 @@ package org.signal.core.util.logging; import android.annotation.SuppressLint; import android.content.Context; +import android.os.Looper; + import androidx.annotation.AnyThread; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -46,11 +48,14 @@ public final class PersistentLogger extends Log.Logger { private LogFile.Writer writer; + private ThreadLocal cachedThreadString; + public PersistentLogger(@NonNull Context context, @NonNull byte[] secret, @NonNull String logTag) { - this.context = context.getApplicationContext(); - this.secret = secret; - this.logTag = logTag; - this.executor = Executors.newSingleThreadExecutor(r -> { + this.context = context.getApplicationContext(); + this.secret = secret; + this.logTag = logTag; + this.cachedThreadString = new ThreadLocal<>(); + this.executor = Executors.newSingleThreadExecutor(r -> { Thread thread = new Thread(r, "signal-PersistentLogger"); thread.setPriority(Thread.MIN_PRIORITY); return thread; @@ -150,6 +155,20 @@ public final class PersistentLogger extends Log.Logger { @AnyThread private void write(String level, String tag, String message, Throwable t) { + String threadString = cachedThreadString.get(); + + if (cachedThreadString.get() == null) { + if (Looper.myLooper() == Looper.getMainLooper()) { + threadString = "main"; + } else { + threadString = String.format("%-4s", Thread.currentThread().getId()); + } + + cachedThreadString.set(threadString); + } + + final String finalThreadString = threadString; + executor.execute(() -> { try { if (writer == null) { @@ -162,7 +181,7 @@ public final class PersistentLogger extends Log.Logger { trimLogFilesOverMax(); } - for (String entry : buildLogEntries(level, tag, message, t)) { + for (String entry : buildLogEntries(level, tag, message, t, finalThreadString)) { writer.writeEntry(entry); } @@ -225,11 +244,11 @@ public final class PersistentLogger extends Log.Logger { return logDir; } - private List buildLogEntries(String level, String tag, String message, Throwable t) { + private List buildLogEntries(String level, String tag, String message, Throwable t, String threadString) { List entries = new LinkedList<>(); Date date = new Date(); - entries.add(buildEntry(level, tag, message, date)); + entries.add(buildEntry(level, tag, message, date, threadString)); if (t != null) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); @@ -239,14 +258,14 @@ public final class PersistentLogger extends Log.Logger { String[] lines = trace.split("\\n"); for (String line : lines) { - entries.add(buildEntry(level, tag, line, date)); + entries.add(buildEntry(level, tag, line, date, threadString)); } } return entries; } - private String buildEntry(String level, String tag, String message, Date date) { - return '[' + logTag + "] " + DATE_FORMAT.format(date) + ' ' + level + ' ' + tag + ": " + message; + private String buildEntry(String level, String tag, String message, Date date, String threadString) { + return '[' + logTag + "] [" + threadString + "] " + DATE_FORMAT.format(date) + ' ' + level + ' ' + tag + ": " + message; } }