Skip to content

Commit db5eba2

Browse files
committed
New log model.
1 parent 209ed62 commit db5eba2

12 files changed

Lines changed: 142 additions & 79 deletions

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "berlin-lea-performance-monitor",
3-
"version": "1.14.0",
3+
"version": "1.15.0",
44
"author": "David Leclerc",
55
"main": "./src/index.ts",
66
"scripts": {

src/Log.ts

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import Release from './models/Release';
2+
3+
type Args = {
4+
line: number,
5+
level: number,
6+
time: Date,
7+
version: Release,
8+
processId: number,
9+
hostname: string,
10+
message: string,
11+
error?: string,
12+
}
13+
14+
class Log {
15+
private line: number;
16+
private level: number;
17+
private time: Date;
18+
private version: Release;
19+
private processId: number;
20+
private hostname: string;
21+
private message: string;
22+
private error?: string;
23+
24+
constructor(args: Args) {
25+
const { line, level, time, version, processId, hostname, message, error } = args;
26+
27+
this.line = line;
28+
this.level = level;
29+
this.time = time;
30+
this.version = version;
31+
this.processId = processId;
32+
this.hostname = hostname;
33+
this.message = message;
34+
this.error = error;
35+
}
36+
37+
public static fromText(line: string, index: number) {
38+
const { level, time, version, pid, hostname, msg, err } = JSON.parse(line);
39+
40+
return new Log({
41+
line: index + 1,
42+
level,
43+
time: new Date(time),
44+
version: Release.fromString(version),
45+
processId: pid,
46+
hostname,
47+
message: msg,
48+
error: err,
49+
});
50+
}
51+
52+
public static isLineValid(line: string) {
53+
return line.startsWith('{') && line.endsWith('}');
54+
}
55+
56+
public toString() {
57+
return (`{` +
58+
`"level":${this.level},` +
59+
`"time":"${this.time}",` +
60+
`"pid":${this.processId},` +
61+
`"hostname":"${this.hostname}",` +
62+
`"version":"${this.version.toString()}",` +
63+
(this.error ? `"err":"${this.error}",` : '') +
64+
`"msg":"${this.message}"` +
65+
`}`);
66+
}
67+
68+
public getLine() {
69+
return this.line;
70+
}
71+
72+
public getLevel() {
73+
return this.level;
74+
}
75+
76+
public getTime() {
77+
return this.time;
78+
}
79+
80+
public getVersion() {
81+
return this.version;
82+
}
83+
84+
public hasMessage() {
85+
return !!this.message;
86+
}
87+
88+
public getMessage() {
89+
return this.message;
90+
}
91+
92+
public hasError() {
93+
return !!this.error;
94+
}
95+
96+
public getError() {
97+
return this.error;
98+
}
99+
}
100+
101+
export default Log;

src/models/jobs/AnalysisJob.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ class AnalysisJob extends Job {
3737
public async execute() {
3838
const logs = await this.getLogsToAnalyze();
3939

40+
if (logs.length === 0) {
41+
logger.info(`No logs to analyze.`);
42+
return;
43+
}
44+
4045
const hourlyHistory = SessionHistoryBuilder.build(logs, ONE_HOUR);
4146
const biHourlyHistory = SessionHistoryBuilder.rebuildWithDifferentBucketSize(hourlyHistory, new TimeDuration(2, TimeUnit.Hours));
4247

src/models/logs/LogRotater.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { writeFileSync } from 'fs';
22
import { LOGS_DIR, LOGS_FILEPATH } from '../../config/file';
3-
import { Log } from '../../types';
43
import { formatDateForFilename } from '../../utils/locale';
5-
import { logToText, parseLogs } from '../../utils/parsing';
4+
import { parseLogs } from '../../utils/parsing';
65
import { getMidnightInUTC } from '../../utils/time';
76
import logger from '../../logger';
87
import { NEW_LINE } from '../../constants';
8+
import Log from '../../Log';
99

1010
type LogFiles = Record<string, Log[]>;
1111

@@ -36,7 +36,7 @@ class LogRotater {
3636

3737
// Differentiate between logs in the past, and logs today
3838
logs.forEach((log: Log) => {
39-
const date = new Date(log.time);
39+
const date = log.getTime();
4040
const filepath = this.getFilepathForDate(date);
4141

4242
// Ignore today's logs: they stay in the default 'app.log'
@@ -54,7 +54,9 @@ class LogRotater {
5454

5555
// Store previous days in individual log files
5656
for (const [filepath, logs] of Object.entries(prevFiles)) {
57-
const data = logs.map(logToText).join(NEW_LINE) + NEW_LINE;
57+
const data = logs
58+
.map(log => log.toString())
59+
.join(NEW_LINE) + NEW_LINE;
5860

5961
// Write synchronously to avoid other parts of the code
6062
// logging to the default output file during rotation
@@ -63,7 +65,9 @@ class LogRotater {
6365

6466
// Overwrite default output log file 'app.log' with only
6567
// logs from current day
66-
const dataFromToday = nextFiles[this.getFilepathForDate(now)].map(logToText).join(NEW_LINE) + NEW_LINE;
68+
const dataFromToday = nextFiles[this.getFilepathForDate(now)]
69+
.map(log => log.toString())
70+
.join(NEW_LINE) + NEW_LINE;
6771

6872
writeFileSync(LOGS_FILEPATH, dataFromToday);
6973

src/models/sessions/CompleteSession.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class CompleteSession extends Session implements Comparable {
5959
// The session was completed, no error was detected, and the success
6060
// message was logged: there seems to be an appointment available!
6161
public wasSuccess() {
62-
const logMessages = this.logs.map(log => log.msg);
62+
const logMessages = this.logs.map(log => log.getMessage());
6363

6464
return (
6565
!this.error &&

src/models/sessions/IncompleteSession.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { Log } from '../../types';
21
import os from 'os';
32
import process from 'process';
43
import crypto from 'crypto';
54
import Session from './Session';
5+
import Log from '../../Log';
66

77
class IncompleteSession extends Session {
88
protected errors: string[] = [];
@@ -43,12 +43,10 @@ class IncompleteSession extends Session {
4343
}
4444

4545
public push(log: Log) {
46-
const { err } = log;
47-
4846
this.logs.push(log);
4947

50-
if (err) {
51-
this.errors.push(err);
48+
if (log.hasError()) {
49+
this.errors.push(log.getError()!);
5250
}
5351
}
5452
}

src/models/sessions/Session.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Log } from '../../types';
1+
import Log from '../../Log';
22

33
export interface SessionArgs {
44
id: string,

src/models/sessions/SessionHistoryBuilder.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import logger from '../../logger';
2-
import { Log, TimeUnit, Weekday } from '../../types';
2+
import { TimeUnit, Weekday } from '../../types';
33
import IncompleteSession from './IncompleteSession';
44
import SessionHistory from './SessionHistory';
55
import CompleteSession from './CompleteSession';
@@ -8,6 +8,7 @@ import TimeDuration from '../units/TimeDuration';
88
import { getRange } from '../../utils/math';
99
import SessionBucket from '../buckets/SessionBucket';
1010
import { formatDateForFilename } from '../../utils/locale';
11+
import Log from '../../Log';
1112

1213
const TEXTS = {
1314
SessionStart: '[START]',
@@ -40,11 +41,11 @@ class SessionHistoryBuilder {
4041
logs.forEach(log => {
4142

4243
// Session started
43-
if (log.msg.includes(TEXTS.SessionStart)) {
44+
if (log.getMessage().includes(TEXTS.SessionStart)) {
4445
session = IncompleteSession.create();
4546

46-
logger.trace(`Starting session: ${session.getId()} [${log.version.toJSON()}]`);
47-
session.start(new Date(log.time));
47+
logger.trace(`Starting session: ${session.getId()} [${log.getVersion().toJSON()}]`);
48+
session.start(log.getTime());
4849
}
4950

5051
// Session exists and is open: store log
@@ -53,9 +54,9 @@ class SessionHistoryBuilder {
5354
}
5455

5556
// Session ended
56-
if (log.msg.includes(TEXTS.SessionEnd)) {
57-
logger.trace(`Finishing session: ${session.getId()} [${log.version.toJSON()}]`);
58-
session.end(new Date(log.time));
57+
if (log.getMessage().includes(TEXTS.SessionEnd)) {
58+
logger.trace(`Finishing session: ${session.getId()} [${log.getVersion().toJSON()}]`);
59+
session.end(log.getTime());
5960

6061
// Sessions should have a start and an end
6162
if (!session.isComplete()) {
@@ -65,15 +66,15 @@ class SessionHistoryBuilder {
6566
// Has session more than one error: it is invalid!
6667
const errorCount = session.getErrors().length;
6768
if (errorCount > 1) {
68-
const sessionStartLine = session.getLogs()[0].line;
69-
logger.warn(`Invalid session [${formatDateForFilename(session.getStartTime()!)} @${sessionStartLine}] with ${errorCount} > 1 errors found`);
69+
const sessionStartLine = session.getLogs()[0].getLine();
70+
logger.warn(`Invalid session [${formatDateForFilename(session.getStartTime()!)} @${sessionStartLine}] with (${errorCount} > 1) errors found`);
7071
return;
7172
}
7273

7374
// Store complete session in history
7475
history.addSession(new CompleteSession({
7576
id: session.getId(),
76-
release: log.version,
77+
release: log.getVersion(),
7778
startTime: session.getStartTime()!,
7879
endTime: session.getEndTime()!,
7980
logs: session.getLogs(),

src/models/sessions/SessionHistoryExporter.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import logger from '../../logger';
33
import { getLastValue } from '../../utils/array';
44
import { writeFile } from '../../utils/file';
55
import { sum } from '../../utils/math';
6-
import { logToText } from '../../utils/parsing';
76
import CompleteSession from './CompleteSession';
87
import SessionHistory from './SessionHistory';
98

@@ -35,7 +34,7 @@ class SessionHistoryExporter {
3534

3635
const lines = history.getSessions()
3736
.reduce((prevLogs: string[], session: CompleteSession) => {
38-
const newLogs = [...prevLogs, ...session.getLogs().map(logToText)];
37+
const newLogs = [...prevLogs, ...session.getLogs().map(log => log.toString())];
3938

4039
logger.debug(`Converted ${newLogs.length} logs to string.`);
4140

0 commit comments

Comments
 (0)