blob: d23289164ebf226eadfcc21f63d8d43c7b5ebcf8 [file] [log] [blame]
// Copyright 2023 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
import { Detokenizer } from '../pw_tokenizer/ts';
import { LogSource } from '../pw_web/log-viewer/src/log-source';
import { Device } from './device';
import { LogEntry } from './logging';
export class PigweedRPCLogSource extends LogSource {
private detokenizer: Detokenizer | undefined;
private logs: LogEntry[] = [];
private call: any;
constructor(device: Device, tokenDB: string | undefined) {
super();
if (tokenDB && tokenDB.length > 0) {
this.detokenizer = new Detokenizer(tokenDB);
}
this.call = device.rpcs.pw.log.Logs.Listen((msg: any) => {
msg
.getEntriesList()
.forEach((entry: any) => this.processFrame(entry.getMessage()));
});
}
destroy() {
this.call.cancel();
}
private processFrame(frame: Uint8Array) {
let entry: LogEntry;
if (this.detokenizer) {
const detokenized = this.detokenizer.detokenizeUint8Array(frame);
entry = this.parseLogMsg(detokenized);
} else {
const decoded = new TextDecoder().decode(frame);
entry = this.parseLogMsg(decoded);
}
this.logs = [...this.logs, entry];
this.publishLogEntry(entry);
}
private parseLogMsg(msg: string): LogEntry {
const pairs = msg
.split('■')
.slice(1)
.map((pair) => pair.split('♦'));
// Not a valid message, print as-is.
const timestamp = new Date();
if (pairs.length === 0) {
return {
fields: [
{ key: 'timestamp', value: timestamp.toISOString() },
{ key: 'message', value: msg },
],
timestamp: timestamp,
};
}
const map: any = {};
pairs.forEach((pair) => (map[pair[0]] = pair[1]));
return {
fields: [
{ key: 'timestamp', value: timestamp },
{ key: 'message', value: map.msg },
{ key: 'module', value: map.module },
{ key: 'file', value: map.file },
],
timestamp: timestamp,
};
}
}