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