Skip to content
File

Blob: src/worker/util/logging.ts

typescript66 lines
1export type LogLevel = "debug" | "info" | "warn" | "error";
2 
3type Fields = Record<string, unknown>;
4 
5const LEVELS: Record<LogLevel, number> = { debug: 10, info: 20, warn: 30, error: 40 };
6 
7let minLevel: LogLevel = "info";
8 
9function parseLevel(input?: string | null): LogLevel {
10 const value = (input || "").toLowerCase();
11 if (value === "debug" || value === "info" || value === "warn" || value === "error") return value;
12 return "info";
13}
14 
15export function setLevel(input?: string): void {
16 minLevel = parseLevel(input);
17}
18 
19export interface Logger {
20 debug: (event: string, fields?: Fields) => void;
21 info: (event: string, fields?: Fields) => void;
22 warn: (event: string, fields?: Fields) => void;
23 error: (event: string, fields?: Fields) => void;
24 child: (fields: Fields) => Logger;
25}
26 
27function write(level: LogLevel, component: string, base: Fields, event: string, fields: Fields): void {
28 if (LEVELS[level] < LEVELS[minLevel]) return;
29 
30 const entry = JSON.stringify({
31 ts: new Date().toISOString(),
32 level,
33 component,
34 event,
35 eventType: event,
36 ...base,
37 ...fields,
38 });
39 if (level === "error") {
40 console.error(entry);
41 return;
42 }
43 if (level === "warn") {
44 console.warn(entry);
45 return;
46 }
47 console.log(entry);
48}
49 
50export function createLogger(component: string, baseFields: Fields = {}): Logger {
51 return {
52 debug: (event, fields = {}) => write("debug", component, baseFields, event, fields),
53 info: (event, fields = {}) => write("info", component, baseFields, event, fields),
54 warn: (event, fields = {}) => write("warn", component, baseFields, event, fields),
55 error: (event, fields = {}) => write("error", component, baseFields, event, fields),
56 child: (fields) => createLogger(component, { ...baseFields, ...fields }),
57 };
58}
59 
60export function errorContext(error: unknown): Fields {
61 if (error instanceof Error) {
62 return { errorName: error.name, errorMessage: error.message, errorStack: error.stack };
63 }
64 return { errorMessage: String(error) };
65}