1/* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17import {AbstractParser} from 'parsers/perfetto/abstract_parser'; 18import {LogMessage} from 'parsers/protolog/log_message'; 19import {ParserProtologUtils} from 'parsers/protolog/parser_protolog_utils'; 20import {TraceType} from 'trace/trace_type'; 21import {PropertyTreeNode} from 'trace/tree_node/property_tree_node'; 22 23class PerfettoLogMessageTableRow { 24 message = '<NO_MESSAGE>'; 25 tag = '<NO_TAG>'; 26 level = '<NO_LEVEL>'; 27 location = '<NO_LOC>'; 28 timestamp: bigint = 0n; 29 30 constructor(timestamp: bigint, tag: string, level: string, message: string) { 31 this.timestamp = timestamp ?? this.timestamp; 32 this.tag = tag ?? this.tag; 33 this.level = level ?? this.level; 34 this.message = message ?? this.message; 35 } 36} 37 38export class ParserProtolog extends AbstractParser<PropertyTreeNode> { 39 override getTraceType(): TraceType { 40 return TraceType.PROTO_LOG; 41 } 42 43 override async getEntry(index: number): Promise<PropertyTreeNode> { 44 const protologEntry = await this.queryEntry(index); 45 const logMessage: LogMessage = { 46 text: protologEntry.message, 47 tag: protologEntry.tag, 48 level: protologEntry.level, 49 at: protologEntry.location, 50 timestamp: protologEntry.timestamp, 51 }; 52 53 return ParserProtologUtils.makeMessagePropertiesTree( 54 logMessage, 55 this.timestampConverter, 56 this.getRealToMonotonicTimeOffsetNs() !== undefined, 57 ); 58 } 59 60 protected override getTableName(): string { 61 return 'protolog'; 62 } 63 64 private async queryEntry(index: number): Promise<PerfettoLogMessageTableRow> { 65 const sql = ` 66 SELECT 67 ts, tag, level, message 68 FROM 69 protolog 70 WHERE protolog.id = ${this.entryIndexToRowIdMap[index]}; 71 `; 72 const result = await this.traceProcessor.query(sql).waitAllRows(); 73 74 if (result.numRows() !== 1) { 75 throw new Error( 76 `Expected exactly 1 protolog message with id ${index} but got ${result.numRows()}`, 77 ); 78 } 79 80 const entry = result.iter({}); 81 82 return new PerfettoLogMessageTableRow( 83 entry.get('ts') as bigint, 84 entry.get('tag') as string, 85 entry.get('level') as string, 86 entry.get('message') as string, 87 ); 88 } 89} 90