WIP! A BB-style forum, on the ATmosphere!
We're still working... we'll be back soon when we have something to show off!
node
typescript
hono
htmx
atproto
1import type { Logger as IOTelLogger } from "@opentelemetry/api-logs";
2import { SeverityNumber } from "@opentelemetry/api-logs";
3import type { LoggerProvider } from "@opentelemetry/sdk-logs";
4import type { Attributes } from "@opentelemetry/api";
5import type { Logger, LogAttributes, LogLevel } from "./types.js";
6import { SEVERITY_MAP } from "./types.js";
7
8/**
9 * Structured logger wrapping the OpenTelemetry Logs API.
10 *
11 * Provides an ergonomic interface (info/warn/error/etc.) over the
12 * lower-level OTel LogRecord emit API, with child logger support
13 * for adding persistent context (request ID, component name, etc.).
14 */
15export class AppLogger implements Logger {
16 private otelLogger: IOTelLogger;
17 private provider: LoggerProvider;
18 private baseAttributes: LogAttributes;
19 private minSeverity: SeverityNumber;
20
21 constructor(
22 otelLogger: IOTelLogger,
23 provider: LoggerProvider,
24 baseAttributes: LogAttributes = {},
25 minSeverity: SeverityNumber = SeverityNumber.INFO
26 ) {
27 this.otelLogger = otelLogger;
28 this.provider = provider;
29 this.baseAttributes = baseAttributes;
30 this.minSeverity = minSeverity;
31 }
32
33 debug(message: string, attributes?: LogAttributes): void {
34 this.emit(SeverityNumber.DEBUG, "debug", message, attributes);
35 }
36
37 info(message: string, attributes?: LogAttributes): void {
38 this.emit(SeverityNumber.INFO, "info", message, attributes);
39 }
40
41 warn(message: string, attributes?: LogAttributes): void {
42 this.emit(SeverityNumber.WARN, "warn", message, attributes);
43 }
44
45 error(message: string, attributes?: LogAttributes): void {
46 this.emit(SeverityNumber.ERROR, "error", message, attributes);
47 }
48
49 fatal(message: string, attributes?: LogAttributes): void {
50 this.emit(SeverityNumber.FATAL, "fatal", message, attributes);
51 }
52
53 child(attributes: LogAttributes): Logger {
54 return new AppLogger(
55 this.otelLogger,
56 this.provider,
57 { ...this.baseAttributes, ...attributes },
58 this.minSeverity
59 );
60 }
61
62 async shutdown(): Promise<void> {
63 await this.provider.shutdown();
64 }
65
66 private emit(
67 severityNumber: SeverityNumber,
68 severityText: string,
69 message: string,
70 attributes?: LogAttributes
71 ): void {
72 if (severityNumber < this.minSeverity) {
73 return;
74 }
75
76 this.otelLogger.emit({
77 severityNumber,
78 severityText,
79 body: message,
80 attributes: {
81 ...this.baseAttributes,
82 ...attributes,
83 } as Attributes,
84 });
85 }
86}
87
88/** Resolve a LogLevel string to its OTel SeverityNumber. */
89export function resolveLogLevel(level: LogLevel): SeverityNumber {
90 return SEVERITY_MAP[level];
91}