Skip to content

Commit 01c2310

Browse files
authored
Merge pull request #239 from ckadluba/issue-187-datetimeoffset-exception-logevent-column
Fixed #187 considering LogEvent column.
2 parents c9f04a3 + 30c7a0e commit 01c2310

File tree

2 files changed

+185
-21
lines changed

2 files changed

+185
-21
lines changed

src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/Output/JsonLogEventFormatter.cs

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using Serilog.Parsing;
1919
using System;
2020
using System.Collections.Generic;
21+
using System.Data;
2122
using System.IO;
2223
using System.Linq;
2324

@@ -66,27 +67,7 @@ public void Format(LogEvent logEvent, TextWriter output)
6667
// whether Standard Columns are written (specifically, the subset of Standard
6768
// columns that were output by the external JsonFormatter class).
6869

69-
var store = _traits.ColumnOptions.Store;
70-
71-
WriteIfPresent(StandardColumn.TimeStamp);
72-
WriteIfPresent(StandardColumn.Level);
73-
WriteIfPresent(StandardColumn.Message);
74-
WriteIfPresent(StandardColumn.MessageTemplate);
75-
if(logEvent.Exception != null) WriteIfPresent(StandardColumn.Exception);
76-
77-
void WriteIfPresent(StandardColumn col)
78-
{
79-
if(store.Contains(col))
80-
{
81-
output.Write(precedingDelimiter);
82-
precedingDelimiter = COMMA_DELIMITER;
83-
var colData = _traits.GetStandardColumnNameAndValue(col, logEvent);
84-
JsonValueFormatter.WriteQuotedJsonString(colData.Key, output);
85-
output.Write(":");
86-
string value = (col != StandardColumn.TimeStamp) ? (colData.Value ?? string.Empty).ToString() : ((DateTime)colData.Value).ToString("o");
87-
JsonValueFormatter.WriteQuotedJsonString(value, output);
88-
}
89-
}
70+
WriteStandardColumns(logEvent, output, ref precedingDelimiter);
9071
}
9172

9273
if (logEvent.Properties.Count != 0)
@@ -111,6 +92,50 @@ void WriteIfPresent(StandardColumn col)
11192
output.Write("}");
11293
}
11394

95+
private void WriteStandardColumns(LogEvent logEvent, TextWriter output, ref string precedingDelimiter)
96+
{
97+
WriteTimeStampIfPresent(logEvent, output, ref precedingDelimiter);
98+
WriteIfPresent(StandardColumn.Level, logEvent, output, ref precedingDelimiter);
99+
WriteIfPresent(StandardColumn.Message, logEvent, output, ref precedingDelimiter);
100+
WriteIfPresent(StandardColumn.MessageTemplate, logEvent, output, ref precedingDelimiter);
101+
if (logEvent.Exception != null) WriteIfPresent(StandardColumn.Exception, logEvent, output, ref precedingDelimiter);
102+
}
103+
104+
private void WriteIfPresent(StandardColumn col, LogEvent logEvent, TextWriter output, ref string precedingDelimiter)
105+
{
106+
if (!_traits.ColumnOptions.Store.Contains(col))
107+
return;
108+
109+
output.Write(precedingDelimiter);
110+
precedingDelimiter = COMMA_DELIMITER;
111+
var colData = WritePropertyName(logEvent, output, col);
112+
string value = (colData.Value ?? string.Empty).ToString();
113+
JsonValueFormatter.WriteQuotedJsonString(value, output);
114+
}
115+
116+
private void WriteTimeStampIfPresent(LogEvent logEvent, TextWriter output, ref string precedingDelimiter)
117+
{
118+
if (!_traits.ColumnOptions.Store.Contains(StandardColumn.TimeStamp))
119+
return;
120+
121+
output.Write(precedingDelimiter);
122+
precedingDelimiter = COMMA_DELIMITER;
123+
var colData = WritePropertyName(logEvent, output, StandardColumn.TimeStamp);
124+
string value = _traits.ColumnOptions.TimeStamp.DataType == SqlDbType.DateTime
125+
? ((DateTime)colData.Value).ToString("o")
126+
: ((DateTimeOffset)colData.Value).ToString("o");
127+
JsonValueFormatter.WriteQuotedJsonString(value, output);
128+
}
129+
130+
private KeyValuePair<string, object> WritePropertyName(LogEvent le, TextWriter writer, StandardColumn col)
131+
{
132+
var colData = _traits.GetStandardColumnNameAndValue(col, le);
133+
JsonValueFormatter.WriteQuotedJsonString(colData.Key, writer);
134+
writer.Write(":");
135+
136+
return colData;
137+
}
138+
114139
static void WriteProperties(IReadOnlyDictionary<string, LogEventPropertyValue> properties, TextWriter output)
115140
{
116141
output.Write("\"Properties\":{");
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
using Serilog.Events;
2+
using Serilog.Parsing;
3+
using Serilog.Sinks.MSSqlServer.Output;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Data;
7+
using System.IO;
8+
using Xunit;
9+
10+
namespace Serilog.Sinks.MSSqlServer.Tests.Sinks.MSSqlServer.Output
11+
{
12+
public class TestJsonLogEventFormatter
13+
{
14+
private Serilog.Sinks.MSSqlServer.ColumnOptions _testColumnOptions;
15+
private MSSqlServerSinkTraits _testTraits;
16+
private JsonLogEventFormatter _sut;
17+
18+
public TestJsonLogEventFormatter()
19+
{
20+
SetupTest();
21+
}
22+
23+
[Fact]
24+
[Trait("Bugfix", "#187")]
25+
public void FormatTimeStampColumnTypeDateTimeOffsetUtcRendersCorrectTimeStamp()
26+
{
27+
// arrange
28+
const string expectedResult = "{\"TimeStamp\":\"2020-03-27T14:17:00.0000000+00:00\",\"Level\":\"Information\",\"Message\":\"\",\"MessageTemplate\":\"Test message template\"}";
29+
_testTraits.ColumnOptions.TimeStamp.DataType = SqlDbType.DateTimeOffset;
30+
var testLogEvent = CreateTestLogEvent(new DateTimeOffset(2020, 3, 27, 14, 17, 0, TimeSpan.Zero));
31+
var outputWriter = new StringWriter();
32+
33+
// act
34+
_sut.Format(testLogEvent, outputWriter);
35+
36+
// assert
37+
var renderResult = outputWriter.ToString();
38+
Assert.Equal(expectedResult, renderResult);
39+
}
40+
41+
[Fact]
42+
[Trait("Bugfix", "#187")]
43+
public void FormatTimeStampColumnTypeDateTimeOffsetLocalRendersCorrectTimeStamp()
44+
{
45+
// arrange
46+
const string expectedResult = "{\"TimeStamp\":\"2020-03-27T13:17:00.0000000+01:00\",\"Level\":\"Information\",\"Message\":\"\",\"MessageTemplate\":\"Test message template\"}";
47+
_testTraits.ColumnOptions.TimeStamp.DataType = SqlDbType.DateTimeOffset;
48+
var testLogEvent = CreateTestLogEvent(new DateTimeOffset(2020, 3, 27, 13, 17, 0, new TimeSpan(1, 0, 0)));
49+
var outputWriter = new StringWriter();
50+
51+
// act
52+
_sut.Format(testLogEvent, outputWriter);
53+
54+
// assert
55+
var renderResult = outputWriter.ToString();
56+
Assert.Equal(expectedResult, renderResult);
57+
}
58+
59+
[Fact]
60+
[Trait("Bugfix", "#187")]
61+
public void FormatTimeStampColumnTypeDateTimeRendersCorrectTimeStamp()
62+
{
63+
// arrange
64+
const string expectedResult = "{\"TimeStamp\":\"2020-03-27T14:17:00.0000000\",\"Level\":\"Information\",\"Message\":\"\",\"MessageTemplate\":\"Test message template\"}";
65+
var testLogEvent = CreateTestLogEvent(new DateTimeOffset(2020, 3, 27, 14, 17, 0, TimeSpan.Zero));
66+
var outputWriter = new StringWriter();
67+
68+
// act
69+
_sut.Format(testLogEvent, outputWriter);
70+
71+
// assert
72+
var renderResult = outputWriter.ToString();
73+
Assert.Equal(expectedResult, renderResult);
74+
}
75+
76+
[Fact]
77+
public void FormatWithPropertiesRendersCorrectProperties()
78+
{
79+
// arrange
80+
const string expectedResult = "{\"TimeStamp\":\"2020-03-27T14:17:00.0000000\",\"Level\":\"Information\",\"Message\":\"\",\"MessageTemplate\":\"Test message template\",\"Properties\":{\"TestProperty1\":\"TestValue1\",\"TestProperty2\":2}}";
81+
var properties = new List<LogEventProperty>
82+
{
83+
new LogEventProperty("TestProperty1", new ScalarValue("TestValue1")),
84+
new LogEventProperty("TestProperty2", new ScalarValue(2))
85+
};
86+
var testLogEvent = CreateTestLogEvent(new DateTimeOffset(2020, 3, 27, 14, 17, 0, TimeSpan.Zero), properties);
87+
var outputWriter = new StringWriter();
88+
89+
// act
90+
_sut.Format(testLogEvent, outputWriter);
91+
92+
// assert
93+
var renderResult = outputWriter.ToString();
94+
Assert.Equal(expectedResult, renderResult);
95+
}
96+
97+
[Fact]
98+
public void FormatWithExcludeStandardColumnsWithPropertiesRendersCorrectProperties()
99+
{
100+
// arrange
101+
const string expectedResult = "{\"Properties\":{\"TestProperty1\":\"TestValue1\",\"TestProperty2\":2}}";
102+
_testTraits.ColumnOptions.LogEvent.ExcludeStandardColumns = true;
103+
var properties = new List<LogEventProperty>
104+
{
105+
new LogEventProperty("TestProperty1", new ScalarValue("TestValue1")),
106+
new LogEventProperty("TestProperty2", new ScalarValue(2))
107+
};
108+
var testLogEvent = CreateTestLogEvent(new DateTimeOffset(2020, 3, 27, 14, 17, 0, TimeSpan.Zero), properties);
109+
var outputWriter = new StringWriter();
110+
111+
// act
112+
_sut.Format(testLogEvent, outputWriter);
113+
114+
// assert
115+
var renderResult = outputWriter.ToString();
116+
Assert.Equal(expectedResult, renderResult);
117+
}
118+
119+
private void SetupTest()
120+
{
121+
_testColumnOptions = new Serilog.Sinks.MSSqlServer.ColumnOptions();
122+
_testColumnOptions.Store.Add(StandardColumn.LogEvent);
123+
_testTraits = new MSSqlServerSinkTraits("ConnectionString", "TableName", "SchemaName", _testColumnOptions,
124+
formatProvider: null, autoCreateSqlTable: false, logEventFormatter: null);
125+
_sut = new JsonLogEventFormatter(_testTraits);
126+
}
127+
128+
private static LogEvent CreateTestLogEvent(DateTimeOffset testTimeStamp, List<LogEventProperty> properties = null)
129+
{
130+
if (properties == null)
131+
{
132+
properties = new List<LogEventProperty>();
133+
}
134+
135+
var testMessageTemplate = new MessageTemplate("Test message template", new List<MessageTemplateToken>());
136+
return new LogEvent(testTimeStamp, LogEventLevel.Information, null, testMessageTemplate, properties);
137+
}
138+
}
139+
}

0 commit comments

Comments
 (0)