1
- // Copyright 2013 Serilog Contributors
1
+ // Copyright 2013 Serilog Contributors
2
2
//
3
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
4
// you may not use this file except in compliance with the License.
@@ -49,6 +49,8 @@ public class MSSqlServerSink : PeriodicBatchingSink
49
49
readonly CancellationTokenSource _token = new CancellationTokenSource ( ) ;
50
50
readonly bool _storeTimestampInUtc ;
51
51
52
+ private DataColumn [ ] _additionalDataColumns ;
53
+
52
54
/// <summary>
53
55
/// Construct a sink posting to the specified database.
54
56
/// </summary>
@@ -59,8 +61,9 @@ public class MSSqlServerSink : PeriodicBatchingSink
59
61
/// <param name="period">The time to wait between checking for event batches.</param>
60
62
/// <param name="formatProvider">Supplies culture-specific formatting information, or null.</param>
61
63
/// <param name="storeTimestampInUtc">Store Timestamp In UTC</param>
64
+ /// <param name="additionalDataColumns">Additional columns for data storage.</param>
62
65
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 )
64
67
: base ( batchPostingLimit , period )
65
68
{
66
69
if ( string . IsNullOrWhiteSpace ( connectionString ) )
@@ -75,6 +78,7 @@ public MSSqlServerSink(string connectionString, string tableName, bool includePr
75
78
_includeProperties = includeProperties ;
76
79
_formatProvider = formatProvider ;
77
80
_storeTimestampInUtc = storeTimestampInUtc ;
81
+ _additionalDataColumns = additionalDataColumns ;
78
82
79
83
// Prepare the data table
80
84
_eventsTable = CreateDataTable ( ) ;
@@ -162,6 +166,10 @@ DataTable CreateDataTable()
162
166
} ;
163
167
eventsTable . Columns . Add ( props ) ;
164
168
169
+ if ( _additionalDataColumns != null )
170
+ {
171
+ eventsTable . Columns . AddRange ( _additionalDataColumns ) ;
172
+ }
165
173
166
174
// Create an array for DataColumn objects.
167
175
var keys = new DataColumn [ 1 ] ;
@@ -171,7 +179,7 @@ DataTable CreateDataTable()
171
179
return eventsTable ;
172
180
}
173
181
174
- void FillDataTable ( IEnumerable < LogEvent > events )
182
+ void FillDataTable ( IEnumerable < LogEvent > events )
175
183
{
176
184
// Add the new rows to the collection.
177
185
foreach ( var logEvent in events )
@@ -188,6 +196,10 @@ void FillDataTable(IEnumerable<LogEvent> events)
188
196
{
189
197
row [ "Properties" ] = ConvertPropertiesToXmlStructure ( logEvent . Properties ) ;
190
198
}
199
+ if ( _additionalDataColumns != null )
200
+ {
201
+ ConvertPropertiesToColumn ( row , logEvent . Properties ) ;
202
+ }
191
203
192
204
_eventsTable . Rows . Add ( row ) ;
193
205
}
@@ -213,6 +225,23 @@ static string ConvertPropertiesToXmlStructure(
213
225
return sb . ToString ( ) ;
214
226
}
215
227
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
+ }
216
245
217
246
/// <summary>
218
247
/// Disposes the connection
@@ -223,7 +252,7 @@ protected override void Dispose(bool disposing)
223
252
_token . Cancel ( ) ;
224
253
225
254
if ( _eventsTable != null )
226
- _eventsTable . Dispose ( ) ;
255
+ _eventsTable . Dispose ( ) ;
227
256
228
257
base . Dispose ( disposing ) ;
229
258
}
0 commit comments