1- // Copyright 2013 Serilog Contributors
1+ // Copyright 2013 Serilog Contributors
22//
33// Licensed under the Apache License, Version 2.0 (the "License");
44// you may not use this file except in compliance with the License.
@@ -49,6 +49,8 @@ public class MSSqlServerSink : PeriodicBatchingSink
4949 readonly CancellationTokenSource _token = new CancellationTokenSource ( ) ;
5050 readonly bool _storeTimestampInUtc ;
5151
52+ private DataColumn [ ] _additionalDataColumns ;
53+
5254 /// <summary>
5355 /// Construct a sink posting to the specified database.
5456 /// </summary>
@@ -59,8 +61,9 @@ public class MSSqlServerSink : PeriodicBatchingSink
5961 /// <param name="period">The time to wait between checking for event batches.</param>
6062 /// <param name="formatProvider">Supplies culture-specific formatting information, or null.</param>
6163 /// <param name="storeTimestampInUtc">Store Timestamp In UTC</param>
64+ /// <param name="additionalDataColumns">Additional columns for data storage.</param>
6265 public MSSqlServerSink ( string connectionString , string tableName , bool includeProperties , int batchPostingLimit ,
63- TimeSpan period , IFormatProvider formatProvider , bool storeTimestampInUtc )
66+ TimeSpan period , IFormatProvider formatProvider , bool storeTimestampInUtc , DataColumn [ ] additionalDataColumns = null )
6467 : base ( batchPostingLimit , period )
6568 {
6669 if ( string . IsNullOrWhiteSpace ( connectionString ) )
@@ -75,6 +78,7 @@ public MSSqlServerSink(string connectionString, string tableName, bool includePr
7578 _includeProperties = includeProperties ;
7679 _formatProvider = formatProvider ;
7780 _storeTimestampInUtc = storeTimestampInUtc ;
81+ _additionalDataColumns = additionalDataColumns ;
7882
7983 // Prepare the data table
8084 _eventsTable = CreateDataTable ( ) ;
@@ -162,6 +166,10 @@ DataTable CreateDataTable()
162166 } ;
163167 eventsTable . Columns . Add ( props ) ;
164168
169+ if ( _additionalDataColumns != null )
170+ {
171+ eventsTable . Columns . AddRange ( _additionalDataColumns ) ;
172+ }
165173
166174 // Create an array for DataColumn objects.
167175 var keys = new DataColumn [ 1 ] ;
@@ -171,7 +179,7 @@ DataTable CreateDataTable()
171179 return eventsTable ;
172180 }
173181
174- void FillDataTable ( IEnumerable < LogEvent > events )
182+ void FillDataTable ( IEnumerable < LogEvent > events )
175183 {
176184 // Add the new rows to the collection.
177185 foreach ( var logEvent in events )
@@ -188,6 +196,10 @@ void FillDataTable(IEnumerable<LogEvent> events)
188196 {
189197 row [ "Properties" ] = ConvertPropertiesToXmlStructure ( logEvent . Properties ) ;
190198 }
199+ if ( _additionalDataColumns != null )
200+ {
201+ ConvertPropertiesToColumn ( row , logEvent . Properties ) ;
202+ }
191203
192204 _eventsTable . Rows . Add ( row ) ;
193205 }
@@ -213,6 +225,23 @@ static string ConvertPropertiesToXmlStructure(
213225 return sb . ToString ( ) ;
214226 }
215227
228+ /// <summary>
229+ /// Mapping values from properties which have a corresponding data row.
230+ /// Matching is done based on Column name and property key
231+ /// </summary>
232+ /// <param name="row"></param>
233+ /// <param name="properties"></param>
234+ private void ConvertPropertiesToColumn (
235+ DataRow row , IReadOnlyDictionary < string , LogEventPropertyValue > properties )
236+ {
237+ foreach ( var property in properties )
238+ {
239+ if ( row . Table . Columns . Contains ( property . Key ) )
240+ {
241+ row [ property . Key ] = property . Value . ToString ( ) ;
242+ }
243+ }
244+ }
216245
217246 /// <summary>
218247 /// Disposes the connection
@@ -223,7 +252,7 @@ protected override void Dispose(bool disposing)
223252 _token . Cancel ( ) ;
224253
225254 if ( _eventsTable != null )
226- _eventsTable . Dispose ( ) ;
255+ _eventsTable . Dispose ( ) ;
227256
228257 base . Dispose ( disposing ) ;
229258 }
0 commit comments