@@ -206,20 +206,43 @@ public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Except
206
206
if ( ! IsEnabled ( logLevel ) )
207
207
return ;
208
208
209
- var message = new Dictionary < string , object > ( StringComparer . Ordinal ) ;
209
+ var timestamp = DateTime . UtcNow ;
210
+ var message = CustomFormatter ( state , exception , out var customMessage ) && customMessage is not null
211
+ ? customMessage
212
+ : formatter ( state , exception ) ;
213
+
214
+ var logFormatter = Logger . GetFormatter ( ) ;
215
+ var logEntry = logFormatter is null ?
216
+ GetLogEntry ( logLevel , timestamp , message , exception ) :
217
+ GetFormattedLogEntry ( logLevel , timestamp , message , exception , logFormatter ) ;
218
+
219
+ _systemWrapper . LogLine ( JsonSerializer . Serialize ( logEntry , JsonSerializerOptions ) ) ;
220
+ }
221
+
222
+ /// <summary>
223
+ /// Gets a log entry.
224
+ /// </summary>
225
+ /// <param name="logLevel">Entry will be written on this level.</param>
226
+ /// <param name="timestamp">Entry timestamp.</param>
227
+ /// <param name="message">The message to be written. Can be also an object.</param>
228
+ /// <param name="exception">The exception related to this entry.</param>
229
+ private Dictionary < string , object > GetLogEntry ( LogLevel logLevel , DateTime timestamp , object message ,
230
+ Exception exception )
231
+ {
232
+ var logEntry = new Dictionary < string , object > ( StringComparer . Ordinal ) ;
210
233
211
234
// Add Custom Keys
212
235
foreach ( var ( key , value ) in Logger . GetAllKeys ( ) )
213
- message . TryAdd ( key , value ) ;
236
+ logEntry . TryAdd ( key , value ) ;
214
237
215
238
// Add Lambda Context Keys
216
239
if ( PowertoolsLambdaContext . Instance is not null )
217
240
{
218
- message . TryAdd ( LoggingConstants . KeyFunctionName , PowertoolsLambdaContext . Instance . FunctionName ) ;
219
- message . TryAdd ( LoggingConstants . KeyFunctionVersion , PowertoolsLambdaContext . Instance . FunctionVersion ) ;
220
- message . TryAdd ( LoggingConstants . KeyFunctionMemorySize , PowertoolsLambdaContext . Instance . MemoryLimitInMB ) ;
221
- message . TryAdd ( LoggingConstants . KeyFunctionArn , PowertoolsLambdaContext . Instance . InvokedFunctionArn ) ;
222
- message . TryAdd ( LoggingConstants . KeyFunctionRequestId , PowertoolsLambdaContext . Instance . AwsRequestId ) ;
241
+ logEntry . TryAdd ( LoggingConstants . KeyFunctionName , PowertoolsLambdaContext . Instance . FunctionName ) ;
242
+ logEntry . TryAdd ( LoggingConstants . KeyFunctionVersion , PowertoolsLambdaContext . Instance . FunctionVersion ) ;
243
+ logEntry . TryAdd ( LoggingConstants . KeyFunctionMemorySize , PowertoolsLambdaContext . Instance . MemoryLimitInMB ) ;
244
+ logEntry . TryAdd ( LoggingConstants . KeyFunctionArn , PowertoolsLambdaContext . Instance . InvokedFunctionArn ) ;
245
+ logEntry . TryAdd ( LoggingConstants . KeyFunctionRequestId , PowertoolsLambdaContext . Instance . AwsRequestId ) ;
223
246
}
224
247
225
248
// Add Extra Fields
@@ -228,24 +251,109 @@ public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Except
228
251
foreach ( var ( key , value ) in CurrentScope . ExtraKeys )
229
252
{
230
253
if ( ! string . IsNullOrWhiteSpace ( key ) )
231
- message . TryAdd ( key , value ) ;
254
+ logEntry . TryAdd ( key , value ) ;
232
255
}
233
256
}
234
257
235
- message . TryAdd ( LoggingConstants . KeyTimestamp , DateTime . UtcNow . ToString ( "o" ) ) ;
236
- message . TryAdd ( LoggingConstants . KeyLogLevel , logLevel . ToString ( ) ) ;
237
- message . TryAdd ( LoggingConstants . KeyService , Service ) ;
238
- message . TryAdd ( LoggingConstants . KeyLoggerName , _name ) ;
239
- message . TryAdd ( LoggingConstants . KeyMessage ,
240
- CustomFormatter ( state , exception , out var customMessage ) && customMessage is not null
241
- ? customMessage
242
- : formatter ( state , exception ) ) ;
258
+ logEntry . TryAdd ( LoggingConstants . KeyTimestamp , timestamp . ToString ( "o" ) ) ;
259
+ logEntry . TryAdd ( LoggingConstants . KeyLogLevel , logLevel . ToString ( ) ) ;
260
+ logEntry . TryAdd ( LoggingConstants . KeyService , Service ) ;
261
+ logEntry . TryAdd ( LoggingConstants . KeyLoggerName , _name ) ;
262
+ logEntry . TryAdd ( LoggingConstants . KeyMessage , message ) ;
263
+
243
264
if ( CurrentConfig . SamplingRate . HasValue )
244
- message . TryAdd ( LoggingConstants . KeySamplingRate , CurrentConfig . SamplingRate . Value ) ;
265
+ logEntry . TryAdd ( LoggingConstants . KeySamplingRate , CurrentConfig . SamplingRate . Value ) ;
245
266
if ( exception != null )
246
- message . TryAdd ( LoggingConstants . KeyException , exception ) ;
267
+ logEntry . TryAdd ( LoggingConstants . KeyException , exception ) ;
247
268
248
- _systemWrapper . LogLine ( JsonSerializer . Serialize ( message , JsonSerializerOptions ) ) ;
269
+ return logEntry ;
270
+ }
271
+
272
+ /// <summary>
273
+ /// Gets a formatted log entry.
274
+ /// </summary>
275
+ /// <param name="logLevel">Entry will be written on this level.</param>
276
+ /// <param name="timestamp">Entry timestamp.</param>
277
+ /// <param name="message">The message to be written. Can be also an object.</param>
278
+ /// <param name="exception">The exception related to this entry.</param>
279
+ /// <param name="logFormatter">The custom log entry formatter.</param>
280
+ private object GetFormattedLogEntry ( LogLevel logLevel , DateTime timestamp , object message ,
281
+ Exception exception , ILogFormatter logFormatter )
282
+ {
283
+ if ( logFormatter is null )
284
+ return null ;
285
+
286
+ var logEntry = new LogEntry
287
+ {
288
+ Timestamp = timestamp ,
289
+ Level = logLevel ,
290
+ Service = Service ,
291
+ Name = _name ,
292
+ Message = message ,
293
+ Exception = exception ,
294
+ SamplingRate = CurrentConfig . SamplingRate ,
295
+ } ;
296
+
297
+ var extraKeys = new Dictionary < string , object > ( ) ;
298
+
299
+ // Add Custom Keys
300
+ foreach ( var ( key , value ) in Logger . GetAllKeys ( ) )
301
+ {
302
+ switch ( key )
303
+ {
304
+ case LoggingConstants . KeyColdStart :
305
+ logEntry . ColdStart = ( bool ) value ;
306
+ break ;
307
+ case LoggingConstants . KeyXRayTraceId :
308
+ logEntry . XRayTraceId = value as string ;
309
+ break ;
310
+ case LoggingConstants . KeyCorrelationId :
311
+ logEntry . CorrelationId = value as string ;
312
+ break ;
313
+ default :
314
+ extraKeys . TryAdd ( key , value ) ;
315
+ break ;
316
+ }
317
+ }
318
+
319
+ // Add Extra Fields
320
+ if ( CurrentScope ? . ExtraKeys is not null )
321
+ {
322
+ foreach ( var ( key , value ) in CurrentScope . ExtraKeys )
323
+ {
324
+ if ( ! string . IsNullOrWhiteSpace ( key ) )
325
+ extraKeys . TryAdd ( key , value ) ;
326
+ }
327
+ }
328
+
329
+ if ( extraKeys . Any ( ) )
330
+ logEntry . ExtraKeys = extraKeys ;
331
+
332
+ // Add Lambda Context Keys
333
+ if ( PowertoolsLambdaContext . Instance is not null )
334
+ {
335
+ logEntry . LambdaContext = new LogEntryLambdaContext
336
+ {
337
+ FunctionName = PowertoolsLambdaContext . Instance . FunctionName ,
338
+ FunctionVersion = PowertoolsLambdaContext . Instance . FunctionVersion ,
339
+ MemoryLimitInMB = PowertoolsLambdaContext . Instance . MemoryLimitInMB ,
340
+ InvokedFunctionArn = PowertoolsLambdaContext . Instance . InvokedFunctionArn ,
341
+ AwsRequestId = PowertoolsLambdaContext . Instance . AwsRequestId ,
342
+ } ;
343
+ }
344
+
345
+ try
346
+ {
347
+ var logObject = logFormatter . FormatLogEntry ( logEntry ) ;
348
+ if ( logObject is null )
349
+ throw new LogFormatException ( $ "{ logFormatter . GetType ( ) . FullName } returned Null value.") ;
350
+ return logObject ;
351
+ }
352
+ catch ( Exception e )
353
+ {
354
+ throw new LogFormatException (
355
+ $ "{ logFormatter . GetType ( ) . FullName } raised an exception: { e . Message } .", e ) ;
356
+ }
249
357
}
250
358
251
359
/// <summary>
0 commit comments