kopia lustrzana https://github.com/ryukoposting/Signal-Android
Upload trace file as separate debuglogs item.
rodzic
39f1aea8e3
commit
7bb1262571
|
@ -29,4 +29,9 @@ public class CompleteLogLine implements LogLine {
|
|||
public @NonNull Style getStyle() {
|
||||
return line.getStyle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Placeholder getPlaceholderType() {
|
||||
return line.getPlaceholderType();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,15 +12,13 @@ public interface LogLine {
|
|||
long getId();
|
||||
@NonNull String getText();
|
||||
@NonNull Style getStyle();
|
||||
|
||||
static List<LogLine> fromText(@NonNull CharSequence text) {
|
||||
return Stream.of(Pattern.compile("\\n").split(text))
|
||||
.map(s -> new SimpleLogLine(s, Style.NONE))
|
||||
.map(line -> (LogLine) line)
|
||||
.toList();
|
||||
}
|
||||
@NonNull Placeholder getPlaceholderType();
|
||||
|
||||
enum Style {
|
||||
NONE, VERBOSE, DEBUG, INFO, WARNING, ERROR
|
||||
}
|
||||
|
||||
enum Placeholder {
|
||||
NONE, TRACE
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,19 +20,6 @@ public class LogSectionTrace implements LogSection {
|
|||
|
||||
@Override
|
||||
public @NonNull CharSequence getContent(@NonNull Context context) {
|
||||
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
GZIPOutputStream compressedStream = new GZIPOutputStream(outputStream))
|
||||
{
|
||||
compressedStream.write(Tracer.getInstance().serialize());
|
||||
compressedStream.flush();
|
||||
compressedStream.close();
|
||||
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
|
||||
return Base64.encodeBytes(outputStream.toByteArray());
|
||||
} catch (IOException e) {
|
||||
return "";
|
||||
}
|
||||
return LogStyleParser.TRACE_PLACEHOLDER;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ import java.util.Map;
|
|||
|
||||
public class LogStyleParser {
|
||||
|
||||
public static final String TRACE_PLACEHOLDER = "<binary trace data>";
|
||||
|
||||
private static final Map<String, LogLine.Style> STYLE_MARKERS = new HashMap<String, LogLine.Style>() {{
|
||||
put(" V ", LogLine.Style.VERBOSE);
|
||||
put(" D ", LogLine.Style.DEBUG);
|
||||
|
@ -15,7 +17,7 @@ public class LogStyleParser {
|
|||
put(" E ", LogLine.Style.ERROR);
|
||||
}};
|
||||
|
||||
public static LogLine.Style parseStyle(@NonNull String text) {
|
||||
public static @NonNull LogLine.Style parseStyle(@NonNull String text) {
|
||||
for (Map.Entry<String, LogLine.Style> entry : STYLE_MARKERS.entrySet()) {
|
||||
if (text.contains(entry.getKey())) {
|
||||
return entry.getValue();
|
||||
|
@ -23,4 +25,12 @@ public class LogStyleParser {
|
|||
}
|
||||
return LogLine.Style.NONE;
|
||||
}
|
||||
|
||||
public static @NonNull LogLine.Placeholder parsePlaceholderType(@NonNull String text) {
|
||||
if (text.equals(TRACE_PLACEHOLDER)) {
|
||||
return LogLine.Placeholder.TRACE;
|
||||
} else {
|
||||
return LogLine.Placeholder.NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,14 +7,16 @@ import androidx.annotation.NonNull;
|
|||
*/
|
||||
class SimpleLogLine implements LogLine {
|
||||
|
||||
static final SimpleLogLine EMPTY = new SimpleLogLine("", Style.NONE);
|
||||
static final SimpleLogLine EMPTY = new SimpleLogLine("", Style.NONE, Placeholder.NONE);
|
||||
|
||||
private final String text;
|
||||
private final Style style;
|
||||
private final String text;
|
||||
private final Style style;
|
||||
private final Placeholder placeholder;
|
||||
|
||||
SimpleLogLine(@NonNull String text, @NonNull Style style) {
|
||||
this.text = text;
|
||||
this.style = style;
|
||||
SimpleLogLine(@NonNull String text, @NonNull Style style, @NonNull Placeholder placeholder) {
|
||||
this.text = text;
|
||||
this.style = style;
|
||||
this.placeholder = placeholder;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -22,11 +24,18 @@ class SimpleLogLine implements LogLine {
|
|||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Style getStyle() {
|
||||
return style;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Placeholder getPlaceholderType() {
|
||||
return placeholder;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import android.content.Context;
|
|||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
|
@ -82,16 +83,48 @@ public class SubmitDebugLogRepository {
|
|||
}
|
||||
|
||||
public void submitLog(@NonNull List<LogLine> lines, Callback<Optional<String>> callback) {
|
||||
SignalExecutors.UNBOUNDED.execute(() -> callback.onResult(submitLogInternal(lines)));
|
||||
SignalExecutors.UNBOUNDED.execute(() -> callback.onResult(submitLogInternal(lines, null)));
|
||||
}
|
||||
|
||||
public void submitLog(@NonNull List<LogLine> lines, @Nullable byte[] trace, Callback<Optional<String>> callback) {
|
||||
SignalExecutors.UNBOUNDED.execute(() -> callback.onResult(submitLogInternal(lines, trace)));
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private @NonNull Optional<String> submitLogInternal(@NonNull List<LogLine> lines) {
|
||||
StringBuilder bodyBuilder = new StringBuilder();
|
||||
for (LogLine line : lines) {
|
||||
bodyBuilder.append(line.getText()).append('\n');
|
||||
private @NonNull Optional<String> submitLogInternal(@NonNull List<LogLine> lines, @Nullable byte[] trace) {
|
||||
String traceUrl = null;
|
||||
if (trace != null) {
|
||||
try {
|
||||
traceUrl = uploadContent("application/octet-stream", trace);
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, "Error during trace upload.", e);
|
||||
return Optional.absent();
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder bodyBuilder = new StringBuilder();
|
||||
for (LogLine line : lines) {
|
||||
switch (line.getPlaceholderType()) {
|
||||
case NONE:
|
||||
bodyBuilder.append(line.getText()).append('\n');
|
||||
break;
|
||||
case TRACE:
|
||||
bodyBuilder.append(traceUrl).append('\n');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
String logUrl = uploadContent("text/plain", bodyBuilder.toString().getBytes());
|
||||
return Optional.of(logUrl);
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, "Error during log upload.", e);
|
||||
return Optional.absent();
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private @NonNull String uploadContent(@NonNull String contentType, @NonNull byte[] content) throws IOException {
|
||||
try {
|
||||
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new StandardUserAgentInterceptor()).dns(SignalServiceNetworkAccess.DNS).build();
|
||||
Response response = client.newCall(new Request.Builder().url(API_ENDPOINT).get().build()).execute();
|
||||
|
@ -108,14 +141,14 @@ public class SubmitDebugLogRepository {
|
|||
MultipartBody.Builder post = new MultipartBody.Builder();
|
||||
Iterator<String> keys = fields.keys();
|
||||
|
||||
post.addFormDataPart("Content-Type", "text/plain");
|
||||
post.addFormDataPart("Content-Type", contentType);
|
||||
|
||||
while (keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
post.addFormDataPart(key, fields.getString(key));
|
||||
}
|
||||
|
||||
post.addFormDataPart("file", "file", RequestBody.create(MediaType.parse("text/plain"), bodyBuilder.toString()));
|
||||
post.addFormDataPart("file", "file", RequestBody.create(MediaType.parse(contentType), content));
|
||||
|
||||
Response postResponse = client.newCall(new Request.Builder().url(url).post(post.build()).build()).execute();
|
||||
|
||||
|
@ -123,10 +156,10 @@ public class SubmitDebugLogRepository {
|
|||
throw new IOException("Bad response: " + postResponse);
|
||||
}
|
||||
|
||||
return Optional.of(API_ENDPOINT + "/" + item);
|
||||
} catch (IOException | JSONException e) {
|
||||
return API_ENDPOINT + "/" + item;
|
||||
} catch (JSONException e) {
|
||||
Log.w(TAG, "Error during upload.", e);
|
||||
return Optional.absent();
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,12 +199,12 @@ public class SubmitDebugLogRepository {
|
|||
long startTime = System.currentTimeMillis();
|
||||
|
||||
List<LogLine> out = new ArrayList<>();
|
||||
out.add(new SimpleLogLine(formatTitle(section.getTitle(), maxTitleLength), LogLine.Style.NONE));
|
||||
out.add(new SimpleLogLine(formatTitle(section.getTitle(), maxTitleLength), LogLine.Style.NONE, LogLine.Placeholder.NONE));
|
||||
|
||||
CharSequence content = Scrubber.scrub(section.getContent(context));
|
||||
|
||||
List<LogLine> lines = Stream.of(Pattern.compile("\\n").split(content))
|
||||
.map(s -> new SimpleLogLine(s, LogStyleParser.parseStyle(s)))
|
||||
.map(s -> new SimpleLogLine(s, LogStyleParser.parseStyle(s), LogStyleParser.parsePlaceholderType(s)))
|
||||
.map(line -> (LogLine) line)
|
||||
.toList();
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import androidx.lifecycle.ViewModelProvider;
|
|||
|
||||
import com.annimon.stream.Stream;
|
||||
|
||||
import org.thoughtcrime.securesms.tracing.Tracer;
|
||||
import org.thoughtcrime.securesms.util.DefaultValueLiveData;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
|
@ -23,12 +24,17 @@ public class SubmitDebugLogViewModel extends ViewModel {
|
|||
private final MutableLiveData<Mode> mode;
|
||||
|
||||
private List<LogLine> sourceLines;
|
||||
private byte[] trace;
|
||||
|
||||
private SubmitDebugLogViewModel() {
|
||||
this.repo = new SubmitDebugLogRepository();
|
||||
this.lines = new DefaultValueLiveData<>(Collections.emptyList());
|
||||
this.mode = new MutableLiveData<>();
|
||||
|
||||
if (Tracer.getInstance().isEnabled()) {
|
||||
this.trace = Tracer.getInstance().serialize();
|
||||
}
|
||||
|
||||
repo.getLogLines(result -> {
|
||||
sourceLines = result;
|
||||
mode.postValue(Mode.NORMAL);
|
||||
|
@ -40,10 +46,6 @@ public class SubmitDebugLogViewModel extends ViewModel {
|
|||
return lines;
|
||||
}
|
||||
|
||||
boolean hasLines() {
|
||||
return lines.getValue().size() > 0;
|
||||
}
|
||||
|
||||
@NonNull LiveData<Mode> getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
@ -53,7 +55,7 @@ public class SubmitDebugLogViewModel extends ViewModel {
|
|||
|
||||
MutableLiveData<Optional<String>> result = new MutableLiveData<>();
|
||||
|
||||
repo.submitLog(lines.getValue(), value -> {
|
||||
repo.submitLog(lines.getValue(), trace, value -> {
|
||||
mode.postValue(Mode.NORMAL);
|
||||
result.postValue(value);
|
||||
});
|
||||
|
|
Ładowanie…
Reference in New Issue