55 lines
2.2 KiB
TypeScript
55 lines
2.2 KiB
TypeScript
|
|
import { describe, it, expect } from 'vitest';
|
||
|
|
import { ErrorLogBuffer } from '../src/services/error-log-buffer.js';
|
||
|
|
|
||
|
|
const line = (o: Record<string, unknown>): string => JSON.stringify(o) + '\n';
|
||
|
|
|
||
|
|
describe('ErrorLogBuffer', () => {
|
||
|
|
it('keeps error/fatal records and drops info/warn', () => {
|
||
|
|
const b = new ErrorLogBuffer();
|
||
|
|
b.recordLine(line({ level: 30, time: 1, msg: 'info' }));
|
||
|
|
b.recordLine(line({ level: 40, time: 2, msg: 'warn' }));
|
||
|
|
b.recordLine(line({ level: 50, time: 3, msg: 'an error' }));
|
||
|
|
b.recordLine(line({ level: 60, time: 4, msg: 'fatal', kind: 'BACKEND_TOKEN_DEAD' }));
|
||
|
|
const recent = b.recent();
|
||
|
|
expect(recent.map((e) => e.msg)).toEqual(['fatal', 'an error']); // most-recent first
|
||
|
|
expect(recent[0]?.kind).toBe('BACKEND_TOKEN_DEAD');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('flattens an err object to its message', () => {
|
||
|
|
const b = new ErrorLogBuffer();
|
||
|
|
b.recordLine(line({ level: 50, time: 1, msg: 'boom', err: { type: 'Error', message: 'OpenBao write … 403' } }));
|
||
|
|
expect(b.recent()[0]?.err).toBe('OpenBao write … 403');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('ignores blank and non-JSON lines', () => {
|
||
|
|
const b = new ErrorLogBuffer();
|
||
|
|
b.recordLine('');
|
||
|
|
b.recordLine('not json at all');
|
||
|
|
b.recordLine(' ');
|
||
|
|
expect(b.recent()).toHaveLength(0);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('caps at capacity (ring buffer)', () => {
|
||
|
|
const b = new ErrorLogBuffer(3);
|
||
|
|
for (let i = 1; i <= 5; i++) b.recordLine(line({ level: 50, time: i, msg: `e${i}` }));
|
||
|
|
const recent = b.recent(10);
|
||
|
|
expect(recent.map((e) => e.msg)).toEqual(['e5', 'e4', 'e3']); // oldest two evicted
|
||
|
|
});
|
||
|
|
|
||
|
|
it('respects the limit argument', () => {
|
||
|
|
const b = new ErrorLogBuffer();
|
||
|
|
for (let i = 1; i <= 10; i++) b.recordLine(line({ level: 50, time: i }));
|
||
|
|
expect(b.recent(2)).toHaveLength(2);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('handles multiple records in one chunk via the stream', (ctx) => new Promise<void>((resolve) => {
|
||
|
|
const b = new ErrorLogBuffer();
|
||
|
|
const s = b.stream();
|
||
|
|
s.write(line({ level: 50, time: 1, msg: 'a' }) + line({ level: 30, time: 2 }) + line({ level: 60, time: 3, msg: 'b' }));
|
||
|
|
s.end(() => {
|
||
|
|
expect(b.recent().map((e) => e.msg)).toEqual(['b', 'a']);
|
||
|
|
resolve();
|
||
|
|
});
|
||
|
|
}));
|
||
|
|
});
|