Skip to content

Commit 50ac426

Browse files
authored
Merge pull request #40 from serilog/dev
4.1.0 Release (WIP)
2 parents 7645aa3 + 432895b commit 50ac426

File tree

8 files changed

+1164
-443
lines changed

8 files changed

+1164
-443
lines changed

src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/ColumnOptions.cs

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ namespace Serilog.Sinks.MSSqlServer
1010
/// </summary>
1111
public class ColumnOptions
1212
{
13-
private ICollection<StandardColumn> _store;
13+
ICollection<StandardColumn> _store;
1414

1515
/// <summary>
1616
/// Default constructor.
1717
/// </summary>
1818
public ColumnOptions()
1919
{
20+
Id = new IdColumnOptions();
21+
2022
Level = new LevelColumnOptions();
2123

2224
Properties = new PropertiesColumnOptions();
@@ -31,8 +33,10 @@ public ColumnOptions()
3133
StandardColumn.Properties
3234
};
3335

36+
Message = new MessageColumnOptions();
37+
MessageTemplate = new MessageTemplateColumnOptions();
3438
TimeStamp = new TimeStampColumnOptions();
35-
39+
Exception = new ExceptionColumnOptions();
3640
LogEvent = new LogEventColumnOptions();
3741
}
3842

@@ -47,7 +51,7 @@ public ICollection<StandardColumn> Store
4751
if (value == null)
4852
{
4953
_store = new Collection<StandardColumn>();
50-
foreach (StandardColumn column in Enum.GetValues(typeof (StandardColumn)))
54+
foreach (StandardColumn column in Enum.GetValues(typeof(StandardColumn)))
5155
{
5256
_store.Add(column);
5357
}
@@ -64,6 +68,11 @@ public ICollection<StandardColumn> Store
6468
/// </summary>
6569
public ICollection<DataColumn> AdditionalDataColumns { get; set; }
6670

71+
/// <summary>
72+
/// Options for the Id column.
73+
/// </summary>
74+
public IdColumnOptions Id { get; private set; }
75+
6776
/// <summary>
6877
/// Options for the Level column.
6978
/// </summary>
@@ -74,6 +83,21 @@ public ICollection<StandardColumn> Store
7483
/// </summary>
7584
public PropertiesColumnOptions Properties { get; private set; }
7685

86+
/// <summary>
87+
/// Options for the Exception column.
88+
/// </summary>
89+
public ExceptionColumnOptions Exception { get; set; }
90+
91+
/// <summary>
92+
/// Options for the MessageTemplate column.
93+
/// </summary>
94+
public MessageTemplateColumnOptions MessageTemplate { get; set; }
95+
96+
/// <summary>
97+
/// Options for the Message column.
98+
/// </summary>
99+
public MessageColumnOptions Message { get; set; }
100+
77101
/// <summary>
78102
/// Options for the TimeStamp column.
79103
/// </summary>
@@ -84,10 +108,15 @@ public ICollection<StandardColumn> Store
84108
/// </summary>
85109
public LogEventColumnOptions LogEvent { get; private set; }
86110

111+
/// <summary>
112+
/// Options for the Id column.
113+
/// </summary>
114+
public class IdColumnOptions : CommonColumnOptions { }
115+
87116
/// <summary>
88117
/// Options for the Level column.
89118
/// </summary>
90-
public class LevelColumnOptions
119+
public class LevelColumnOptions : CommonColumnOptions
91120
{
92121
/// <summary>
93122
/// If true will store Level as an enum in a tinyint column as opposed to a string.
@@ -98,7 +127,7 @@ public class LevelColumnOptions
98127
/// <summary>
99128
/// Options for the Properties column.
100129
/// </summary>
101-
public class PropertiesColumnOptions
130+
public class PropertiesColumnOptions : CommonColumnOptions
102131
{
103132
/// <summary>
104133
/// Default constructor.
@@ -175,10 +204,21 @@ public PropertiesColumnOptions()
175204
public bool UsePropertyKeyAsElementName { get; set; }
176205
}
177206

207+
/// <summary>
208+
/// Shared column customization options.
209+
/// </summary>
210+
public class CommonColumnOptions
211+
{
212+
/// <summary>
213+
/// The name of the column in the database.
214+
/// </summary>
215+
public string ColumnName { get; set; }
216+
}
217+
178218
/// <summary>
179219
/// Options for the TimeStamp column.
180220
/// </summary>
181-
public class TimeStampColumnOptions
221+
public class TimeStampColumnOptions : CommonColumnOptions
182222
{
183223
/// <summary>
184224
/// If true, the time is converted to universal time.
@@ -189,12 +229,27 @@ public class TimeStampColumnOptions
189229
/// <summary>
190230
/// Options for the LogEvent column.
191231
/// </summary>
192-
public class LogEventColumnOptions
232+
public class LogEventColumnOptions : CommonColumnOptions
193233
{
194234
/// <summary>
195235
/// Exclude properties from the LogEvent column if they are being saved to additional columns.
196236
/// </summary>
197237
public bool ExcludeAdditionalProperties { get; set; }
198238
}
239+
240+
/// <summary>
241+
/// Options for the message column
242+
/// </summary>
243+
public class MessageColumnOptions : CommonColumnOptions {}
244+
245+
/// <summary>
246+
/// Options for the Exception column.
247+
/// </summary>
248+
public class ExceptionColumnOptions : CommonColumnOptions {}
249+
250+
/// <summary>
251+
/// Options for the MessageTemplate column.
252+
/// </summary>
253+
public class MessageTemplateColumnOptions : CommonColumnOptions {}
199254
}
200-
}
255+
}

src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/MSSqlServerSink.cs

Lines changed: 65 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ public class MSSqlServerSink : PeriodicBatchingSink
4848
readonly DataTable _eventsTable;
4949
readonly IFormatProvider _formatProvider;
5050
readonly string _tableName;
51-
readonly CancellationTokenSource _token = new CancellationTokenSource();
5251
private readonly ColumnOptions _columnOptions;
5352

5453
private readonly HashSet<string> _additionalDataColumnNames;
@@ -129,7 +128,7 @@ protected override async Task EmitBatchAsync(IEnumerable<LogEvent> events)
129128
{
130129
using (var cn = new SqlConnection(_connectionString))
131130
{
132-
await cn.OpenAsync(_token.Token).ConfigureAwait(false);
131+
await cn.OpenAsync().ConfigureAwait(false);
133132
using (var copy = new SqlBulkCopy(cn))
134133
{
135134
copy.DestinationTableName = _tableName;
@@ -140,9 +139,8 @@ protected override async Task EmitBatchAsync(IEnumerable<LogEvent> events)
140139
copy.ColumnMappings.Add(mapping);
141140
}
142141

143-
await copy.WriteToServerAsync(_eventsTable, _token.Token).ConfigureAwait(false);
142+
await copy.WriteToServerAsync(_eventsTable).ConfigureAwait(false);
144143
}
145-
146144
}
147145
}
148146
catch (Exception ex)
@@ -163,95 +161,71 @@ DataTable CreateDataTable()
163161
var id = new DataColumn
164162
{
165163
DataType = Type.GetType("System.Int32"),
166-
ColumnName = "Id",
164+
ColumnName = !string.IsNullOrWhiteSpace(_columnOptions.Id.ColumnName) ? _columnOptions.Id.ColumnName : "Id",
167165
AutoIncrement = true
168166
};
169167
eventsTable.Columns.Add(id);
170168

171-
if (_columnOptions.Store.Contains(StandardColumn.Message))
172-
{
173-
var message = new DataColumn
174-
{
175-
DataType = typeof (string),
176-
MaxLength = -1,
177-
ColumnName = "Message"
178-
};
179-
eventsTable.Columns.Add(message);
180-
}
181-
182-
if (_columnOptions.Store.Contains(StandardColumn.MessageTemplate))
169+
foreach (var standardColumn in _columnOptions.Store)
183170
{
184-
var messageTemplate = new DataColumn
185-
{
186-
DataType = typeof (string),
187-
MaxLength = -1,
188-
ColumnName = "MessageTemplate",
189-
190-
};
191-
eventsTable.Columns.Add(messageTemplate);
192-
}
193-
194-
if (_columnOptions.Store.Contains(StandardColumn.Level))
195-
{
196-
var level = new DataColumn
197-
{
198-
ColumnName = "Level"
199-
};
200-
201-
if (_columnOptions.Level.StoreAsEnum)
202-
{
203-
level.DataType = typeof (byte);
204-
}
205-
else
171+
switch (standardColumn)
206172
{
207-
level.DataType = typeof (string);
208-
level.MaxLength = 128;
173+
case StandardColumn.Level:
174+
eventsTable.Columns.Add(new DataColumn
175+
{
176+
DataType = _columnOptions.Level.StoreAsEnum ? typeof(byte) : typeof(string),
177+
MaxLength = _columnOptions.Level.StoreAsEnum ? 0 : 128,
178+
ColumnName = _columnOptions.Level.ColumnName ?? StandardColumn.Level.ToString()
179+
});
180+
break;
181+
case StandardColumn.TimeStamp:
182+
eventsTable.Columns.Add(new DataColumn
183+
{
184+
DataType = typeof(DateTime),
185+
ColumnName = _columnOptions.TimeStamp.ColumnName ?? StandardColumn.TimeStamp.ToString(),
186+
AllowDBNull = false
187+
});
188+
break;
189+
case StandardColumn.LogEvent:
190+
eventsTable.Columns.Add(new DataColumn
191+
{
192+
DataType = typeof(string),
193+
ColumnName = _columnOptions.LogEvent.ColumnName ?? StandardColumn.LogEvent.ToString()
194+
});
195+
break;
196+
case StandardColumn.Message:
197+
eventsTable.Columns.Add(new DataColumn
198+
{
199+
DataType = typeof(string),
200+
MaxLength = -1,
201+
ColumnName = _columnOptions.Message.ColumnName ?? StandardColumn.Message.ToString()
202+
});
203+
break;
204+
case StandardColumn.MessageTemplate:
205+
eventsTable.Columns.Add(new DataColumn
206+
{
207+
DataType = typeof(string),
208+
MaxLength = -1,
209+
ColumnName = _columnOptions.MessageTemplate.ColumnName ?? StandardColumn.MessageTemplate.ToString()
210+
});
211+
break;
212+
case StandardColumn.Exception:
213+
eventsTable.Columns.Add(new DataColumn
214+
{
215+
DataType = typeof(string),
216+
MaxLength = -1,
217+
ColumnName = _columnOptions.Exception.ColumnName ?? StandardColumn.Exception.ToString()
218+
});
219+
break;
220+
case StandardColumn.Properties:
221+
eventsTable.Columns.Add(new DataColumn
222+
{
223+
DataType = typeof(string),
224+
MaxLength = -1,
225+
ColumnName = _columnOptions.Properties.ColumnName ?? StandardColumn.Properties.ToString()
226+
});
227+
break;
209228
}
210-
211-
eventsTable.Columns.Add(level);
212-
}
213-
214-
if (_columnOptions.Store.Contains(StandardColumn.TimeStamp))
215-
{
216-
var timestamp = new DataColumn
217-
{
218-
DataType = Type.GetType("System.DateTime"),
219-
ColumnName = "TimeStamp",
220-
AllowDBNull = false
221-
};
222-
eventsTable.Columns.Add(timestamp);
223-
}
224-
225-
if (_columnOptions.Store.Contains(StandardColumn.Exception))
226-
{
227-
var exception = new DataColumn
228-
{
229-
DataType = typeof (string),
230-
MaxLength = -1,
231-
ColumnName = "Exception"
232-
};
233-
eventsTable.Columns.Add(exception);
234-
}
235-
236-
if (_columnOptions.Store.Contains(StandardColumn.Properties))
237-
{
238-
var props = new DataColumn
239-
{
240-
DataType = typeof (string),
241-
MaxLength = -1,
242-
ColumnName = "Properties",
243-
};
244-
eventsTable.Columns.Add(props);
245-
}
246-
247-
if (_columnOptions.Store.Contains(StandardColumn.LogEvent))
248-
{
249-
var eventData = new DataColumn
250-
{
251-
DataType = Type.GetType("System.String"),
252-
ColumnName = "LogEvent"
253-
};
254-
eventsTable.Columns.Add(eventData);
255229
}
256230

257231
if (_columnOptions.AdditionalDataColumns != null)
@@ -288,9 +262,7 @@ void FillDataTable(IEnumerable<LogEvent> events)
288262
row["Level"] = logEvent.Level;
289263
break;
290264
case StandardColumn.TimeStamp:
291-
row["TimeStamp"] = _columnOptions.TimeStamp.ConvertToUtc
292-
? logEvent.Timestamp.DateTime.ToUniversalTime()
293-
: logEvent.Timestamp.DateTime;
265+
row["TimeStamp"] = _columnOptions.TimeStamp.ConvertToUtc ? logEvent.Timestamp.DateTime.ToUniversalTime() : logEvent.Timestamp.DateTime;
294266
break;
295267
case StandardColumn.Exception:
296268
row["Exception"] = logEvent.Exception != null ? logEvent.Exception.ToString() : null;
@@ -338,15 +310,11 @@ private string ConvertPropertiesToXmlStructure(IEnumerable<KeyValuePair<string,
338310

339311
if (options.UsePropertyKeyAsElementName)
340312
{
341-
sb.AppendFormat("<{0}>{1}</{0}>", XmlPropertyFormatter.GetValidElementName(property.Key),
342-
value);
313+
sb.AppendFormat("<{0}>{1}</{0}>", XmlPropertyFormatter.GetValidElementName(property.Key), value);
343314
}
344315
else
345316
{
346-
sb.AppendFormat("<{0} key='{1}'>{2}</{0}>",
347-
options.PropertyElementName,
348-
property.Key,
349-
value);
317+
sb.AppendFormat("<{0} key='{1}'>{2}</{0}>", options.PropertyElementName, property.Key, value);
350318
}
351319
}
352320

@@ -390,15 +358,15 @@ private void ConvertPropertiesToColumn(DataRow row, IReadOnlyDictionary<string,
390358
if (scalarValue == null)
391359
{
392360
row[columnName] = property.Value.ToString();
393-
continue;
361+
continue;
394362
}
395363

396364
if (scalarValue.Value == null && row.Table.Columns[columnName].AllowDBNull)
397365
{
398366
row[columnName] = DBNull.Value;
399367
continue;
400368
}
401-
369+
402370
if (TryChangeType(scalarValue.Value, columnType, out conversion))
403371
{
404372
row[columnName] = conversion;
@@ -436,8 +404,6 @@ private static bool TryChangeType(object obj, Type type, out object conversion)
436404
/// <param name="disposing"></param>
437405
protected override void Dispose(bool disposing)
438406
{
439-
_token.Cancel();
440-
441407
if (_eventsTable != null)
442408
_eventsTable.Dispose();
443409

0 commit comments

Comments
 (0)