@@ -24,9 +24,14 @@ namespace Serilog.Sinks.Grafana.Loki
2424 /// <summary>
2525 /// Used to serialize a log event to a json format that loki 2.0 can parse using the json parser ( | json ), more information can be found here https://grafana.com/blog/2020/10/28/loki-2.0-released-transform-logs-as-youre-querying-them-and-set-up-alerts-within-loki/
2626 /// </summary>
27- [ SuppressMessage ( "ReSharper" , "PossibleMultipleEnumeration" , Justification = "Reviewed" ) ]
27+ [ SuppressMessage (
28+ "ReSharper" ,
29+ "PossibleMultipleEnumeration" ,
30+ Justification = "Reviewed" ) ]
2831 public class LokiJsonTextFormatter : ITextFormatter , ILabelAwareTextFormatter
2932 {
33+ private static readonly string [ ] ReservedKeywords = { "Message" , "MessageTemplate" , "Renderings" , "level" , "Exception" } ;
34+
3035 private readonly JsonValueFormatter _valueFormatter ;
3136
3237 /// <summary>
@@ -52,7 +57,10 @@ public LokiJsonTextFormatter()
5257 /// <param name="labels">
5358 /// List of labels that should not be written as json fields.
5459 /// </param>
55- public void Format ( LogEvent logEvent , TextWriter output , IEnumerable < string > labels )
60+ public void Format (
61+ LogEvent logEvent ,
62+ TextWriter output ,
63+ IEnumerable < string > labels )
5664 {
5765 if ( logEvent == null )
5866 {
@@ -98,12 +106,15 @@ public void Format(LogEvent logEvent, TextWriter output, IEnumerable<string> lab
98106 if ( logEvent . Exception != null )
99107 {
100108 output . Write ( ",\" Exception\" :" ) ;
101- SerializeException ( output , logEvent . Exception , 1 ) ;
109+ SerializeException (
110+ output ,
111+ logEvent . Exception ,
112+ 1 ) ;
102113 }
103114
104115 foreach ( var property in logEvent . Properties )
105116 {
106- var name = property . Key ;
117+ var name = GetSanitizedPropertyName ( property . Key ) ;
107118 if ( labels . Contains ( name ) )
108119 {
109120 continue ;
@@ -120,7 +131,20 @@ public void Format(LogEvent logEvent, TextWriter output, IEnumerable<string> lab
120131
121132 /// <inheritdoc/>
122133 [ Obsolete ( "Use \" Format(LogEvent logEvent, TextWriter output, IEnumerable<string> labels)\" instead!" ) ]
123- public void Format ( LogEvent logEvent , TextWriter output ) => Format ( logEvent , output , Enumerable . Empty < string > ( ) ) ;
134+ public void Format ( LogEvent logEvent , TextWriter output ) => Format (
135+ logEvent ,
136+ output ,
137+ Enumerable . Empty < string > ( ) ) ;
138+
139+ /// <summary>
140+ /// Used to sanitize property name to avoid conflict with reserved keywords.
141+ /// Appends _ to the property name if it matches with reserved keyword.
142+ /// </summary>
143+ /// <param name="propertyName">
144+ /// Name of property to sanitize
145+ /// </param>
146+ protected virtual string GetSanitizedPropertyName ( string propertyName ) =>
147+ ReservedKeywords . Contains ( propertyName ) ? $ "_{ propertyName } " : propertyName ;
124148
125149 /// <summary>
126150 /// Used to serialize exceptions, can be overridden when inheriting to change the format.
@@ -134,17 +158,23 @@ public void Format(LogEvent logEvent, TextWriter output, IEnumerable<string> lab
134158 /// <param name="level">
135159 /// The current nesting level of the exception.
136160 /// </param>
137- protected virtual void SerializeException ( TextWriter output , Exception exception , int level )
161+ protected virtual void SerializeException (
162+ TextWriter output ,
163+ Exception exception ,
164+ int level )
138165 {
139166 if ( level == 4 )
140167 {
141168 JsonValueFormatter . WriteQuotedJsonString ( exception . ToString ( ) , output ) ;
169+
142170 return ;
143171 }
144172
145173 output . Write ( "{\" Type\" :" ) ;
146174 var typeNamespace = exception . GetType ( ) . Namespace ;
147- var typeName = typeNamespace != null && typeNamespace . StartsWith ( "System." ) ? exception . GetType ( ) . Name : exception . GetType ( ) . ToString ( ) ;
175+ var typeName = typeNamespace != null && typeNamespace . StartsWith ( "System." )
176+ ? exception . GetType ( ) . Name
177+ : exception . GetType ( ) . ToString ( ) ;
148178 JsonValueFormatter . WriteQuotedJsonString ( typeName , output ) ;
149179
150180 if ( ! string . IsNullOrWhiteSpace ( exception . Message ) )
@@ -166,7 +196,10 @@ protected virtual void SerializeException(TextWriter output, Exception exception
166196 for ( var i = 0 ; i < count ; i ++ )
167197 {
168198 var isLast = i == count - 1 ;
169- SerializeException ( output , aggregateException . InnerExceptions [ i ] , level + 1 ) ;
199+ SerializeException (
200+ output ,
201+ aggregateException . InnerExceptions [ i ] ,
202+ level + 1 ) ;
170203 if ( ! isLast )
171204 {
172205 output . Write ( ',' ) ;
@@ -178,10 +211,13 @@ protected virtual void SerializeException(TextWriter output, Exception exception
178211 else if ( exception . InnerException != null )
179212 {
180213 output . Write ( ",\" InnerException\" :" ) ;
181- SerializeException ( output , exception . InnerException , level + 1 ) ;
214+ SerializeException (
215+ output ,
216+ exception . InnerException ,
217+ level + 1 ) ;
182218 }
183219
184220 output . Write ( '}' ) ;
185221 }
186222 }
187- }
223+ }
0 commit comments