mirror of
https://github.com/yume-chan/ya-webadb.git
synced 2025-10-05 19:42:15 +02:00
feat(bin/logcat): support more toString formats
This commit is contained in:
parent
82a6732e9e
commit
11011d1e85
1 changed files with 123 additions and 17 deletions
|
@ -68,7 +68,8 @@ export enum LogcatFormat {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LogcatFormatModifiers {
|
export interface LogcatFormatModifiers {
|
||||||
usec?: boolean;
|
microseconds?: boolean;
|
||||||
|
nanoseconds?: boolean;
|
||||||
printable?: boolean;
|
printable?: boolean;
|
||||||
year?: boolean;
|
year?: boolean;
|
||||||
zone?: boolean;
|
zone?: boolean;
|
||||||
|
@ -91,14 +92,14 @@ export const LoggerEntry = new Struct({ littleEndian: true })
|
||||||
.uint16("headerSize")
|
.uint16("headerSize")
|
||||||
.int32("pid")
|
.int32("pid")
|
||||||
.uint32("tid")
|
.uint32("tid")
|
||||||
.uint32("second")
|
.uint32("seconds")
|
||||||
.uint32("nanoseconds")
|
.uint32("nanoseconds")
|
||||||
.uint32("logId")
|
.uint32("logId")
|
||||||
.uint32("uid")
|
.uint32("uid")
|
||||||
.extra({
|
.extra({
|
||||||
get timestamp() {
|
get timestamp() {
|
||||||
return (
|
return (
|
||||||
BigInt(this.second) * NANOSECONDS_PER_SECOND +
|
BigInt(this.seconds) * NANOSECONDS_PER_SECOND +
|
||||||
BigInt(this.nanoseconds)
|
BigInt(this.nanoseconds)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -111,36 +112,139 @@ export interface AndroidLogEntry extends LoggerEntry {
|
||||||
priority: AndroidLogPriority;
|
priority: AndroidLogPriority;
|
||||||
tag: string;
|
tag: string;
|
||||||
message: string;
|
message: string;
|
||||||
|
|
||||||
|
toString(format?: LogcatFormat, modifiers?: LogcatFormatModifiers): string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://cs.android.com/android/platform/superproject/+/master:system/logging/liblog/logprint.cpp;l=1415;drc=8dbf3b2bb6b6d1652d9797e477b9abd03278bb79
|
function secondsToTimeString(
|
||||||
export function formatAndroidLogEntry(
|
seconds: number,
|
||||||
entry: AndroidLogEntry,
|
modifiers: LogcatFormatModifiers
|
||||||
format: LogcatFormat = LogcatFormat.Brief,
|
|
||||||
modifier?: LogcatFormatModifiers
|
|
||||||
) {
|
) {
|
||||||
const uid = modifier?.uid ? `${entry.uid.toString().padStart(5)}:` : "";
|
if (modifiers.monotonic) {
|
||||||
|
return seconds.toString().padStart(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modifiers.epoch) {
|
||||||
|
return seconds.toString().padStart(19);
|
||||||
|
}
|
||||||
|
|
||||||
|
const time = new Date(seconds * 1000);
|
||||||
|
|
||||||
|
if (modifiers.year) {
|
||||||
|
// prettier-ignore
|
||||||
|
return `${
|
||||||
|
time.getFullYear().toString().padStart(4, "0")
|
||||||
|
}-${
|
||||||
|
(time.getMonth() + 1).toString().padStart(2, "0")
|
||||||
|
}-${
|
||||||
|
time.getDate().toString().padStart(2, "0")
|
||||||
|
} ${
|
||||||
|
time.getHours().toString().padStart(2, "0")
|
||||||
|
}:${
|
||||||
|
time.getMinutes().toString().padStart(2, "0")
|
||||||
|
}:${
|
||||||
|
time.getSeconds().toString().padStart(2, "0")
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prettier-ignore
|
||||||
|
return `${
|
||||||
|
(time.getMonth() + 1).toString().padStart(2, "0")
|
||||||
|
}-${
|
||||||
|
time.getDate().toString().padStart(2, "0")
|
||||||
|
} ${
|
||||||
|
time.getHours().toString().padStart(2, "0")
|
||||||
|
}:${
|
||||||
|
time.getMinutes().toString().padStart(2, "0")
|
||||||
|
}:${
|
||||||
|
time.getSeconds().toString().padStart(2, "0")
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function timestampToTimeString(
|
||||||
|
seconds: number,
|
||||||
|
nanoseconds: number,
|
||||||
|
modifiers: LogcatFormatModifiers
|
||||||
|
) {
|
||||||
|
const wholePart = secondsToTimeString(seconds, modifiers);
|
||||||
|
|
||||||
|
if (modifiers.nanoseconds) {
|
||||||
|
// prettier-ignore
|
||||||
|
return `${
|
||||||
|
wholePart
|
||||||
|
}.${
|
||||||
|
nanoseconds.toString().padStart(9, "0")
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modifiers.microseconds) {
|
||||||
|
// prettier-ignore
|
||||||
|
return `${
|
||||||
|
wholePart
|
||||||
|
}.${
|
||||||
|
(nanoseconds / 1000 | 0).toString().padStart(6, "0")
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prettier-ignore
|
||||||
|
return `${
|
||||||
|
wholePart
|
||||||
|
}.${
|
||||||
|
(nanoseconds / 1000000 | 0).toString().padStart(3, "0")
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function entryToPrefix(
|
||||||
|
entry: AndroidLogEntry,
|
||||||
|
format: LogcatFormat,
|
||||||
|
modifiers: LogcatFormatModifiers
|
||||||
|
) {
|
||||||
|
// https://cs.android.com/android/platform/superproject/+/master:system/logging/liblog/logprint.cpp;l=1415;drc=8dbf3b2bb6b6d1652d9797e477b9abd03278bb79
|
||||||
|
const uid = modifiers?.uid ? `${entry.uid.toString().padStart(5)}` : "";
|
||||||
|
|
||||||
switch (format) {
|
switch (format) {
|
||||||
// TODO: implement other formats
|
// TODO: implement other formats
|
||||||
default: {
|
case LogcatFormat.Brief:
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const text = `${
|
return `${
|
||||||
AndroidLogPriorityToCharacter[entry.priority]
|
AndroidLogPriorityToCharacter[entry.priority]
|
||||||
}/${
|
}/${
|
||||||
entry.tag.padEnd(8)
|
entry.tag.padEnd(8)
|
||||||
}(${
|
}(${
|
||||||
uid
|
uid ? uid + ":" : ""
|
||||||
}${
|
}${
|
||||||
entry.pid.toString().padStart(5)
|
entry.pid.toString().padStart(5)
|
||||||
}): ${
|
}): `;
|
||||||
entry.message
|
case LogcatFormat.Raw:
|
||||||
}`;
|
return "";
|
||||||
return text;
|
case LogcatFormat.ThreadTime:
|
||||||
}
|
default:
|
||||||
|
// prettier-ignore
|
||||||
|
return `${
|
||||||
|
timestampToTimeString(entry.seconds, entry.nanoseconds, modifiers)
|
||||||
|
} ${
|
||||||
|
uid ? uid + " " : ""
|
||||||
|
}${
|
||||||
|
entry.pid.toString().padStart(5)
|
||||||
|
} ${
|
||||||
|
entry.tid.toString().padStart(5)
|
||||||
|
} ${
|
||||||
|
AndroidLogPriorityToCharacter[entry.priority]
|
||||||
|
} ${
|
||||||
|
entry.tag.toString().padEnd(8)
|
||||||
|
}: `;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function AndroidLogEntryToString(
|
||||||
|
this: AndroidLogEntry,
|
||||||
|
format: LogcatFormat = LogcatFormat.ThreadTime,
|
||||||
|
modifiers: LogcatFormatModifiers = {}
|
||||||
|
) {
|
||||||
|
const prefix = entryToPrefix(this, format, modifiers);
|
||||||
|
return prefix + this.message.replaceAll("\n", "\n" + prefix);
|
||||||
|
}
|
||||||
|
|
||||||
function findTagEnd(payload: Uint8Array) {
|
function findTagEnd(payload: Uint8Array) {
|
||||||
for (const separator of [0, " ".charCodeAt(0), ":".charCodeAt(0)]) {
|
for (const separator of [0, " ".charCodeAt(0), ":".charCodeAt(0)]) {
|
||||||
const index = payload.indexOf(separator);
|
const index = payload.indexOf(separator);
|
||||||
|
@ -179,6 +283,7 @@ export async function deserializeAndroidLogEntry(
|
||||||
tagEnd < payload.length - 1
|
tagEnd < payload.length - 1
|
||||||
? decodeUtf8(payload.subarray(tagEnd + 1))
|
? decodeUtf8(payload.subarray(tagEnd + 1))
|
||||||
: "";
|
: "";
|
||||||
|
entry.toString = AndroidLogEntryToString;
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,6 +358,7 @@ export class Logcat extends AdbCommandBase {
|
||||||
maxEntrySize: parseInt(match[8]!, 10),
|
maxEntrySize: parseInt(match[8]!, 10),
|
||||||
maxPayloadSize: parseInt(match[9]!, 10),
|
maxPayloadSize: parseInt(match[9]!, 10),
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match = chunk.match(Logcat.LOG_SIZE_REGEX_10);
|
match = chunk.match(Logcat.LOG_SIZE_REGEX_10);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue