import { LoggerProvider, SimpleLogRecordProcessor, } from "@opentelemetry/sdk-logs"; import { resourceFromAttributes } from "@opentelemetry/resources"; import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION, } from "@opentelemetry/semantic-conventions"; import { StructuredLogExporter } from "./exporter.js"; import { AppLogger, resolveLogLevel } from "./logger.js"; import type { CreateLoggerOptions, Logger } from "./types.js"; /** * Create a structured logger backed by the OpenTelemetry Logs SDK. * * Sets up a LoggerProvider with a Resource describing the service, * and a StructuredLogExporter that writes NDJSON to stdout. * * When traces and metrics are added later, the same Resource * can be shared across all signal providers. * * @example * ```ts * const logger = createLogger({ * service: "atbb-appview", * version: "0.1.0", * environment: "development", * level: "debug", * }); * * logger.info("Server started", { port: 3000 }); * logger.error("Query failed", { error: err.message, table: "posts" }); * * const reqLog = logger.child({ requestId: "abc-123" }); * reqLog.info("Handling request"); * ``` */ export function createLogger(options: CreateLoggerOptions): Logger { const resourceAttrs: Record = { [ATTR_SERVICE_NAME]: options.service, }; if (options.version) { resourceAttrs[ATTR_SERVICE_VERSION] = options.version; } if (options.environment) { resourceAttrs["deployment.environment.name"] = options.environment; } const resource = resourceFromAttributes(resourceAttrs); const exporter = new StructuredLogExporter(); const processor = new SimpleLogRecordProcessor(exporter); const provider = new LoggerProvider({ resource }); provider.addLogRecordProcessor(processor); const otelLogger = provider.getLogger(options.service); const minSeverity = resolveLogLevel(options.level ?? "info"); return new AppLogger(otelLogger, provider, {}, minSeverity); }