@@ -21,7 +21,9 @@ class Logger {
2121 private currentLogLevel : LogLevel ;
2222 private serviceName : string ;
2323 private serviceVersion : string ;
24- private otelLogger : ReturnType < ReturnType < typeof logs . getLoggerProvider > [ "getLogger" ] > | null ;
24+ private otelLogger : ReturnType < ReturnType < typeof logs . getLoggerProvider > [ "getLogger" ] > | null =
25+ null ;
26+ private otelLoggerInitialized : boolean = false ;
2527
2628 constructor ( ) {
2729 this . environment = process . env . NODE_ENV || "development" ;
@@ -32,15 +34,28 @@ class Logger {
3234 const logLevelName =
3335 process . env . LOG_LEVEL || ( this . environment === "production" ? "info" : "debug" ) ;
3436 this . currentLogLevel = LOG_LEVELS [ logLevelName ] || LOG_LEVELS . info ;
37+ }
38+
39+ // Lazy-load OpenTelemetry logger on first use (after OTEL SDK is initialized)
40+ private getOtelLogger ( ) : ReturnType <
41+ ReturnType < typeof logs . getLoggerProvider > [ "getLogger" ]
42+ > | null {
43+ if ( this . otelLoggerInitialized ) {
44+ return this . otelLogger ;
45+ }
3546
36- // Get OpenTelemetry logger if available
3747 try {
3848 const loggerProvider = logs . getLoggerProvider ( ) ;
3949 this . otelLogger = loggerProvider . getLogger ( this . serviceName , this . serviceVersion ) ;
40- } catch ( error ) {
50+ this . otelLoggerInitialized = true ;
51+ console . log ( "✅ OpenTelemetry logger initialized for application logs" ) ;
52+ } catch {
4153 // OpenTelemetry not initialized, fall back to console logging
4254 this . otelLogger = null ;
55+ this . otelLoggerInitialized = true ;
4356 }
57+
58+ return this . otelLogger ;
4459 }
4560
4661 private shouldLog ( level : LogLevel ) : boolean {
@@ -78,7 +93,7 @@ class Logger {
7893 span_id : spanContext . spanId ,
7994 } ;
8095 }
81- } catch ( error ) {
96+ } catch {
8297 // OpenTelemetry not initialized or no active span
8398 }
8499 return { } ;
@@ -90,7 +105,7 @@ class Logger {
90105 const traceContext = this . getTraceContext ( ) ;
91106
92107 // Grafana/Loki standardized log structure
93- const logData : Record < string , any > = {
108+ const logData : Record < string , unknown > = {
94109 // Timestamps - ISO 8601 format
95110 timestamp : new Date ( ) . toISOString ( ) ,
96111 "@timestamp" : new Date ( ) . toISOString ( ) , // For Elasticsearch/Loki compatibility
@@ -130,9 +145,10 @@ class Logger {
130145 }
131146
132147 // Emit log via OpenTelemetry if available
133- if ( this . otelLogger ) {
148+ const otelLogger = this . getOtelLogger ( ) ;
149+ if ( otelLogger ) {
134150 try {
135- this . otelLogger . emit ( {
151+ otelLogger . emit ( {
136152 severityNumber : level . severity ,
137153 severityText : level . level . toUpperCase ( ) ,
138154 body : message ,
@@ -150,7 +166,7 @@ class Logger {
150166 } ) ,
151167 } ,
152168 } ) ;
153- } catch ( err ) {
169+ } catch {
154170 // If OTEL logging fails, fall back to console
155171 }
156172 }
0 commit comments