xref: /aosp_15_r20/external/pigweed/pw_web/log-viewer/src/custom/json-log-source.ts (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1// Copyright 2023 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14
15import { LogSource } from '../log-source';
16import { LogEntry, Field, Level } from '../shared/interfaces';
17import { timeFormat } from '../shared/time-format';
18
19import log_data from './log_data.json';
20
21interface LevelMap {
22  [level: number]: Level;
23}
24
25export class JsonLogSource extends LogSource {
26  private intervalId: NodeJS.Timeout | null = null;
27  private logIndex = 0;
28  private previousLogTime = 0;
29
30  private logLevelMap: LevelMap = {
31    10: Level.DEBUG,
32    20: Level.INFO,
33    21: Level.INFO,
34    30: Level.WARNING,
35    40: Level.ERROR,
36    50: Level.CRITICAL,
37    70: Level.CRITICAL,
38  };
39
40  private nonAdditionalDataFields = [
41    '_hosttime',
42    'levelname',
43    'levelno',
44    'args',
45    'fields',
46    'message',
47    'time',
48  ];
49
50  constructor(sourceName = 'JSON Log Source') {
51    super(sourceName);
52  }
53
54  start(): void {
55    this.updateLogTime();
56
57    const getInterval = () => {
58      // Get the current log time
59      const next_log_time = Number(log_data[this.logIndex].time);
60      const wait_ms = 1000 * (next_log_time - this.previousLogTime);
61
62      this.updateLogTime();
63      return Math.round(wait_ms);
64    };
65
66    const readLogEntry = () => {
67      const logEntry = this.readLogEntryFromJson();
68      this.publishLogEntry(logEntry);
69
70      const nextInterval = getInterval();
71      setTimeout(readLogEntry, nextInterval);
72    };
73
74    readLogEntry();
75  }
76
77  stop(): void {
78    if (this.intervalId) {
79      clearInterval(this.intervalId);
80      this.intervalId = null;
81    }
82  }
83
84  private updateLogTime(): void {
85    this.previousLogTime = Number(log_data[this.logIndex].time);
86  }
87
88  private updateLogIndex(): void {
89    this.logIndex += 1;
90    if (this.logIndex >= log_data.length) {
91      this.logIndex = 0;
92    }
93  }
94
95  readLogEntryFromJson(): LogEntry {
96    const data = log_data[this.logIndex];
97    const fields: Array<Field> = [
98      { key: 'level', value: this.logLevelMap[data.levelno] },
99      { key: 'time', value: timeFormat.format(new Date()) },
100    ];
101
102    Object.keys(data.fields).forEach((columnName) => {
103      if (this.nonAdditionalDataFields.indexOf(columnName) === -1) {
104        // @ts-ignore
105        fields.push({ key: columnName, value: data.fields[columnName] });
106      }
107    });
108
109    fields.push({ key: 'message', value: data.message });
110    fields.push({ key: 'py_file', value: data.py_file || '' });
111    fields.push({ key: 'py_logger', value: data.py_logger || '' });
112
113    const logEntry: LogEntry = {
114      level: this.logLevelMap[data.levelno],
115      timestamp: new Date(),
116      fields: fields,
117    };
118
119    this.updateLogIndex();
120
121    return logEntry;
122  }
123}
124