Review log-level configuration

src/configured-logger.tsTypeScript
@@ -0,0 +1,49 @@
1+export type LogLevel = "trace" | "debug" | "info" | "warn" | "error" | "off";
2+
3+const RANK: Record<LogLevel, number> = {
4+ trace: 0,
5+ debug: 1,
6+ info: 2,
7+ warn: 3,
8+ error: 4,
9+ off: 5,
10+};
11+
12+export interface LogSink {
13+ write(record: { level: LogLevel; message: string }): void;
14+}
15+
16+export function parseLogLevel(raw: string | undefined): LogLevel {
17+ const candidate = (raw || "info").trim().toLowerCase();
18+ if (!(candidate in RANK)) {
19+ return "info";
20+ }
21+ return candidate as LogLevel;
22+}
23+
24+export class ConfiguredLogger {
25+ constructor(
26+ private readonly readLevel: () => string | undefined,
27+ private readonly sink: LogSink,
28+ ) {}
29+
30+ log(level: Exclude<LogLevel, "off">, message: string): void {
31+ const configured = parseLogLevel(this.readLevel());
32+
33+ if (!this.isEnabled(configured, level)) {
34+ return;
35+ }
36+
37+ this.sink.write({
38+ level: configured,
39+ message,
40+ });
41+ }
42+
43+ private isEnabled(
44+ configured: LogLevel,
45+ eventLevel: Exclude<LogLevel, "off">,
46+ ): boolean {
47+ return RANK[configured] >= RANK[eventLevel];
48+ }
49+}