@@ -32,6 +32,8 @@ public class ElasticSearchTarget : TargetWithLayout, IElasticSearchTarget
3232 private JsonSerializer JsonSerializer => _jsonSerializer ?? ( _jsonSerializer = JsonSerializer . CreateDefault ( _jsonSerializerSettings . Value ) ) ;
3333 private JsonSerializer JsonSerializerFlat => _flatJsonSerializer ?? ( _flatJsonSerializer = JsonSerializer . CreateDefault ( _flatSerializerSettings . Value ) ) ;
3434
35+ private JsonLayout _documentInfoJsonLayout ;
36+
3537 /// <summary>
3638 /// Gets or sets a connection string name to retrieve the Uri from.
3739 ///
@@ -177,6 +179,11 @@ public string CloudId
177179 /// </summary>
178180 public int MaxRecursionLimit { get ; set ; } = - 1 ;
179181
182+ /// <summary>
183+ /// Take the raw output from configured JsonLayout and send as document (Instead of creating expando-object for document serialization)
184+ /// </summary>
185+ public bool EnableJsonLayout { get ; set ; }
186+
180187 /// <summary>
181188 /// Initializes a new instance of the <see cref="ElasticSearchTarget"/> class.
182189 /// </summary>
@@ -265,6 +272,28 @@ protected override void InitializeTarget()
265272
266273 if ( ! string . IsNullOrEmpty ( ExcludedProperties ) )
267274 _excludedProperties = new HashSet < string > ( ExcludedProperties . Split ( new [ ] { ',' } , StringSplitOptions . RemoveEmptyEntries ) ) ;
275+
276+ if ( EnableJsonLayout )
277+ {
278+ if ( Layout is SimpleLayout )
279+ {
280+ InternalLogger . Info ( "ElasticSearch: Layout-property has type SimpleLayout, instead of the expected JsonLayout" ) ;
281+ }
282+
283+ _documentInfoJsonLayout = new JsonLayout ( )
284+ {
285+ Attributes = {
286+ new JsonAttribute ( "index" , new JsonLayout ( )
287+ {
288+ Attributes = {
289+ new JsonAttribute ( "_index" , Index ) { EscapeForwardSlash = false } ,
290+ new JsonAttribute ( "_type" , DocumentType ) { EscapeForwardSlash = false } ,
291+ new JsonAttribute ( "pipeline" , Pipeline ) { EscapeForwardSlash = false } ,
292+ }
293+ } , encode : false )
294+ }
295+ } ;
296+ }
268297 }
269298
270299 /// <inheritdoc />
@@ -283,7 +312,7 @@ private void SendBatch(ICollection<AsyncLogEventInfo> logEvents)
283312 {
284313 try
285314 {
286- var payload = FormPayload ( logEvents ) ;
315+ var payload = EnableJsonLayout ? FromPayloadWithJsonLayout ( logEvents ) : FormPayload ( logEvents ) ;
287316
288317 var result = _client . Bulk < BytesResponse > ( payload ) ;
289318
@@ -321,6 +350,24 @@ private void SendBatch(ICollection<AsyncLogEventInfo> logEvents)
321350 }
322351 }
323352
353+ private PostData FromPayloadWithJsonLayout ( ICollection < AsyncLogEventInfo > logEvents )
354+ {
355+ var payload = new List < string > ( logEvents . Count * 2 ) ; // documentInfo + document
356+
357+ foreach ( var ev in logEvents )
358+ {
359+ var logEvent = ev . LogEvent ;
360+
361+ var documentInfo = RenderLogEvent ( _documentInfoJsonLayout , logEvent ) ;
362+ var document = RenderLogEvent ( Layout , logEvent ) ;
363+
364+ payload . Add ( documentInfo ) ;
365+ payload . Add ( document ) ;
366+ }
367+
368+ return PostData . MultiJson ( payload ) ;
369+ }
370+
324371 private PostData FormPayload ( ICollection < AsyncLogEventInfo > logEvents )
325372 {
326373 var payload = new List < object > ( logEvents . Count * 2 ) ; // documentInfo + document
@@ -329,65 +376,72 @@ private PostData FormPayload(ICollection<AsyncLogEventInfo> logEvents)
329376 {
330377 var logEvent = ev . LogEvent ;
331378
332- var document = new Dictionary < string , object >
379+ var index = RenderLogEvent ( Index , logEvent ) . ToLowerInvariant ( ) ;
380+ var type = RenderLogEvent ( DocumentType , logEvent ) ;
381+ var pipeLine = RenderLogEvent ( Pipeline , logEvent ) ;
382+
383+ var documentInfo = GenerateDocumentInfo ( index , type , pipeLine ) ;
384+ var document = GenerateDocumentProperties ( logEvent ) ;
385+
386+ payload . Add ( documentInfo ) ;
387+ payload . Add ( document ) ;
388+ }
389+
390+ return PostData . MultiJson ( payload ) ;
391+ }
392+
393+ private Dictionary < string , object > GenerateDocumentProperties ( LogEventInfo logEvent )
394+ {
395+ var document = new Dictionary < string , object >
333396 {
334397 { "@timestamp" , logEvent . TimeStamp } ,
335398 { "level" , logEvent . Level . Name } ,
336399 { "message" , RenderLogEvent ( Layout , logEvent ) }
337400 } ;
338401
339- foreach ( var field in Fields )
340- {
341- var renderedField = RenderLogEvent ( field . Layout , logEvent ) ;
402+ foreach ( var field in Fields )
403+ {
404+ var renderedField = RenderLogEvent ( field . Layout , logEvent ) ;
342405
343- if ( string . IsNullOrWhiteSpace ( renderedField ) )
344- continue ;
406+ if ( string . IsNullOrWhiteSpace ( renderedField ) )
407+ continue ;
345408
346- try
347- {
348- document [ field . Name ] = renderedField . ToSystemType ( field . LayoutType , logEvent . FormatProvider , JsonSerializer ) ;
349- }
350- catch ( Exception ex )
351- {
352- _jsonSerializer = null ; // Reset as it might now be in bad state
353- InternalLogger . Error ( ex , "ElasticSearch: Error while formatting field: {0}" , field . Name ) ;
354- }
409+ try
410+ {
411+ document [ field . Name ] = renderedField . ToSystemType ( field . LayoutType , logEvent . FormatProvider , JsonSerializer ) ;
355412 }
356-
357- if ( logEvent . Exception != null && ! document . ContainsKey ( "exception" ) )
413+ catch ( Exception ex )
358414 {
359- document . Add ( "exception" , FormatValueSafe ( logEvent . Exception , "exception" ) ) ;
415+ _jsonSerializer = null ; // Reset as it might now be in bad state
416+ InternalLogger . Error ( ex , "ElasticSearch: Error while formatting field: {0}" , field . Name ) ;
360417 }
418+ }
419+
420+ if ( logEvent . Exception != null && ! document . ContainsKey ( "exception" ) )
421+ {
422+ document . Add ( "exception" , FormatValueSafe ( logEvent . Exception , "exception" ) ) ;
423+ }
361424
362- if ( IncludeAllProperties && logEvent . HasProperties )
425+ if ( IncludeAllProperties && logEvent . HasProperties )
426+ {
427+ foreach ( var p in logEvent . Properties )
363428 {
364- foreach ( var p in logEvent . Properties )
365- {
366- var propertyKey = p . Key . ToString ( ) ;
367- if ( _excludedProperties . Contains ( propertyKey ) )
368- continue ;
429+ var propertyKey = p . Key . ToString ( ) ;
430+ if ( _excludedProperties . Contains ( propertyKey ) )
431+ continue ;
369432
433+ if ( document . ContainsKey ( propertyKey ) )
434+ {
435+ propertyKey += "_1" ;
370436 if ( document . ContainsKey ( propertyKey ) )
371- {
372- propertyKey += "_1" ;
373- if ( document . ContainsKey ( propertyKey ) )
374- continue ;
375- }
376-
377- document [ propertyKey ] = FormatValueSafe ( p . Value , propertyKey ) ;
437+ continue ;
378438 }
379- }
380439
381- var index = RenderLogEvent ( Index , logEvent ) . ToLowerInvariant ( ) ;
382- var type = RenderLogEvent ( DocumentType , logEvent ) ;
383- var pipeLine = RenderLogEvent ( Pipeline , logEvent ) ;
384-
385- var documentInfo = GenerateDocumentInfo ( index , type , pipeLine ) ;
386- payload . Add ( documentInfo ) ;
387- payload . Add ( document ) ;
440+ document [ propertyKey ] = FormatValueSafe ( p . Value , propertyKey ) ;
441+ }
388442 }
389443
390- return PostData . MultiJson ( payload ) ;
444+ return document ;
391445 }
392446
393447 private static object GenerateDocumentInfo ( string index , string type , string pipeLine )
0 commit comments