Skip to content

Commit 826727e

Browse files
authored
Merge pull request #104 from danelson/include-data-template-body
Add option to set template as body
2 parents 3442e3a + 0a855b4 commit 826727e

File tree

8 files changed

+77
-21
lines changed

8 files changed

+77
-21
lines changed

src/Serilog.Sinks.OpenTelemetry/Serilog.Sinks.OpenTelemetry.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<PropertyGroup>
33
<Description>This Serilog sink transforms Serilog events into OpenTelemetry
44
logs and sends them to an OTLP (gRPC or HTTP) endpoint.</Description>
5-
<VersionPrefix>1.0.3</VersionPrefix>
5+
<VersionPrefix>1.1.0</VersionPrefix>
66
<Authors>Serilog Contributors</Authors>
77
<TargetFrameworks>net6.0;netstandard2.1;netstandard2.0;net462</TargetFrameworks>
88
<PackageTags>serilog;sink;opentelemetry</PackageTags>

src/Serilog.Sinks.OpenTelemetry/Sinks/OpenTelemetry/IncludedData.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,20 @@ public enum IncludedData
5656
/// means <c>service.name</c> if not supplied, along with the <c>telemetry.sdk.*</c> group of attributes.
5757
/// </summary>
5858
SpecRequiredResourceAttributes = 16,
59+
60+
/// <summary>
61+
/// Include the log event's message template in the OTLP <c>body</c> instead of the rendered messsage. For
62+
/// example, the string <c>Hello {Name}!</c>.
63+
/// </summary>
64+
/// <remarks>
65+
/// Note: It is often desirable to remove <see cref="IncludedData.MessageTemplateTextAttribute"/> when using
66+
/// <see cref="IncludedData.TemplateBody"/> but otherwise use defaults.
67+
/// <code>
68+
/// .WriteTo.OpenTelemetry(options =>
69+
/// {
70+
/// options.IncludedData = (options.IncludedData | IncludedData.TemplateBody) &amp; ~IncludedData.MessageTemplateTextAttribute;
71+
/// })
72+
/// </code>
73+
/// </remarks>
74+
TemplateBody = 32
5975
}

src/Serilog.Sinks.OpenTelemetry/Sinks/OpenTelemetry/LogRecordBuilder.cs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,33 @@ public static LogRecord ToLogRecord(LogEvent logEvent, IFormatProvider? formatPr
2828

2929
ProcessProperties(logRecord, logEvent);
3030
ProcessTimestamp(logRecord, logEvent);
31-
ProcessMessage(logRecord, logEvent, formatProvider);
31+
ProcessMessage(logRecord, logEvent, includedFields, formatProvider);
3232
ProcessLevel(logRecord, logEvent);
3333
ProcessException(logRecord, logEvent);
3434
ProcessIncludedFields(logRecord, logEvent, includedFields, activityContextCollector);
3535

3636
return logRecord;
3737
}
3838

39-
public static void ProcessMessage(LogRecord logRecord, LogEvent logEvent, IFormatProvider? formatProvider)
39+
public static void ProcessMessage(LogRecord logRecord, LogEvent logEvent, IncludedData includedFields, IFormatProvider? formatProvider)
4040
{
41-
var renderedMessage = CleanMessageTemplateFormatter.Format(logEvent.MessageTemplate, logEvent.Properties, formatProvider);
42-
if (renderedMessage.Trim() != "")
41+
if (!includedFields.HasFlag(IncludedData.TemplateBody))
42+
{
43+
var renderedMessage = CleanMessageTemplateFormatter.Format(logEvent.MessageTemplate, logEvent.Properties, formatProvider);
44+
45+
if (renderedMessage.Trim() != "")
46+
{
47+
logRecord.Body = new AnyValue
48+
{
49+
StringValue = renderedMessage
50+
};
51+
}
52+
}
53+
else if (includedFields.HasFlag(IncludedData.TemplateBody) && logEvent.MessageTemplate.Text.Trim() != "")
4354
{
4455
logRecord.Body = new AnyValue
4556
{
46-
StringValue = renderedMessage
57+
StringValue = logEvent.MessageTemplate.Text
4758
};
4859
}
4960
}

src/Serilog.Sinks.OpenTelemetry/Sinks/OpenTelemetry/OpenTelemetrySinkOptions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public class OpenTelemetrySinkOptions
2626
internal const string DefaultEndpoint = "http://localhost:4317";
2727
internal const OtlpProtocol DefaultProtocol = OtlpProtocol.Grpc;
2828

29-
const IncludedData DefaultIncludedData = IncludedData.MessageTemplateTextAttribute |
29+
internal const IncludedData DefaultIncludedData = IncludedData.MessageTemplateTextAttribute |
3030
IncludedData.TraceIdField | IncludedData.SpanIdField |
3131
IncludedData.SpecRequiredResourceAttributes;
3232

test/Serilog.Sinks.OpenTelemetry.Tests/LogRecordBuilderTests.cs

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ public void TestProcessMessage()
2929
{
3030
var logRecord = new LogRecord();
3131

32-
LogRecordBuilder.ProcessMessage(logRecord, Some.SerilogEvent(messageTemplate: ""), null);
32+
LogRecordBuilder.ProcessMessage(logRecord, Some.SerilogEvent(messageTemplate: ""), OpenTelemetrySinkOptions.DefaultIncludedData, null);
3333
Assert.Null(logRecord.Body);
3434

35-
LogRecordBuilder.ProcessMessage(logRecord, Some.SerilogEvent(messageTemplate: "\t\f "), null);
35+
LogRecordBuilder.ProcessMessage(logRecord, Some.SerilogEvent(messageTemplate: "\t\f "), OpenTelemetrySinkOptions.DefaultIncludedData, null);
3636
Assert.Null(logRecord.Body);
3737

3838
const string message = "log message";
39-
LogRecordBuilder.ProcessMessage(logRecord, Some.SerilogEvent(messageTemplate: message), null);
39+
LogRecordBuilder.ProcessMessage(logRecord, Some.SerilogEvent(messageTemplate: message), OpenTelemetrySinkOptions.DefaultIncludedData, null);
4040
Assert.NotNull(logRecord.Body);
4141
Assert.Equal(message, logRecord.Body.StringValue);
4242
}
@@ -45,7 +45,7 @@ public void TestProcessMessage()
4545
public void TestProcessLevel()
4646
{
4747
var logRecord = new LogRecord();
48-
var logEvent = Some.SerilogEvent();
48+
var logEvent = Some.DefaultSerilogEvent();
4949

5050
LogRecordBuilder.ProcessLevel(logRecord, logEvent);
5151

@@ -57,7 +57,7 @@ public void TestProcessLevel()
5757
public void TestProcessProperties()
5858
{
5959
var logRecord = new LogRecord();
60-
var logEvent = Some.SerilogEvent();
60+
var logEvent = Some.DefaultSerilogEvent();
6161

6262
var prop = new LogEventProperty("property_name", new ScalarValue("ok"));
6363
var propertyKeyValue = PrimitiveConversions.NewStringAttribute("property_name", "ok");
@@ -76,7 +76,7 @@ public void TestTimestamp()
7676
var nowNano = PrimitiveConversions.ToUnixNano(now);
7777

7878
var logRecord = new LogRecord();
79-
var logEvent = Some.SerilogEvent(timestamp: now);
79+
var logEvent = Some.SerilogEvent(Some.TestMessageTemplate, timestamp: now);
8080

8181
LogRecordBuilder.ProcessTimestamp(logRecord, logEvent);
8282

@@ -96,7 +96,7 @@ public void TestException()
9696
catch (Exception ex)
9797
{
9898
var logRecord = new LogRecord();
99-
var logEvent = Some.SerilogEvent(ex: ex);
99+
var logEvent = Some.SerilogEvent(Some.TestMessageTemplate, ex: ex);
100100

101101
LogRecordBuilder.ProcessException(logRecord, logEvent);
102102

@@ -131,11 +131,14 @@ public void IncludeMessageTemplateMD5Hash()
131131
[Fact]
132132
public void IncludeMessageTemplateText()
133133
{
134-
var logEvent = Some.SerilogEvent(messageTemplate: Some.TestMessageTemplate);
134+
var messageTemplate = "Hello, {Name}";
135+
var properties = new List<LogEventProperty> { new("Name", new ScalarValue("World")) };
136+
137+
var logEvent = Some.SerilogEvent(messageTemplate, properties);
135138

136139
var logRecord = LogRecordBuilder.ToLogRecord(logEvent, null, IncludedData.MessageTemplateTextAttribute, new());
137140

138-
var expectedAttribute = new KeyValue { Key = SemanticConventions.AttributeMessageTemplateText, Value = new() { StringValue = Some.TestMessageTemplate }};
141+
var expectedAttribute = new KeyValue { Key = SemanticConventions.AttributeMessageTemplateText, Value = new() { StringValue = messageTemplate } };
139142
Assert.Contains(expectedAttribute, logRecord.Attributes);
140143
}
141144

@@ -146,7 +149,7 @@ public void IncludeTraceIdWhenActivityIsNull()
146149

147150
var collector = new ActivityContextCollector();
148151

149-
var logEvent = Some.SerilogEvent();
152+
var logEvent = Some.DefaultSerilogEvent();
150153
collector.CollectFor(logEvent);
151154

152155
var logRecord = LogRecordBuilder.ToLogRecord(logEvent, null, IncludedData.TraceIdField | IncludedData.SpanIdField, collector);
@@ -172,12 +175,23 @@ public void IncludeTraceIdAndSpanId()
172175

173176
var collector = new ActivityContextCollector();
174177

175-
var logEvent = Some.SerilogEvent();
178+
var logEvent = Some.DefaultSerilogEvent();
176179
collector.CollectFor(logEvent);
177180

178181
var logRecord = LogRecordBuilder.ToLogRecord(logEvent, null, IncludedData.TraceIdField | IncludedData.SpanIdField, collector);
179182

180183
Assert.Equal(logRecord.TraceId, PrimitiveConversions.ToOpenTelemetryTraceId(Activity.Current.TraceId.ToHexString()));
181184
Assert.Equal(logRecord.SpanId, PrimitiveConversions.ToOpenTelemetrySpanId(Activity.Current.SpanId.ToHexString()));
182185
}
186+
187+
[Fact]
188+
public void TemplateBodyIncludesMessageTemplateInBody()
189+
{
190+
var messageTemplate = "Hello, {Name}";
191+
var properties = new List<LogEventProperty> { new("Name", new ScalarValue("World")) };
192+
193+
var logRecord = LogRecordBuilder.ToLogRecord(Some.SerilogEvent(messageTemplate, properties), null, IncludedData.TemplateBody, new());
194+
Assert.NotNull(logRecord.Body);
195+
Assert.Equal(messageTemplate, logRecord.Body.StringValue);
196+
}
183197
}

test/Serilog.Sinks.OpenTelemetry.Tests/OpenTelemetryUtilsTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public class RequestTemplateFactoryTests
2424
// request template to another.
2525
public void TestNoDuplicateLogs()
2626
{
27-
var logEvent = Some.SerilogEvent();
27+
var logEvent = Some.DefaultSerilogEvent();
2828
var logRecord = LogRecordBuilder.ToLogRecord(logEvent, null, IncludedData.None, new());
2929

3030
var requestTemplate = RequestTemplateFactory.CreateRequestTemplate(new Dictionary<string, object>());

test/Serilog.Sinks.OpenTelemetry.Tests/PublicApiVisibilityTests.approved.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ namespace Serilog.Sinks.OpenTelemetry
2424
TraceIdField = 4,
2525
SpanIdField = 8,
2626
SpecRequiredResourceAttributes = 16,
27+
TemplateBody = 32,
2728
}
2829
public class OpenTelemetrySinkOptions
2930
{

test/Serilog.Sinks.OpenTelemetry.Tests/Some.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,21 @@ static class Some
2323

2424
public const string TestMessageTemplate = "Message template {Variable}";
2525

26-
internal static LogEvent SerilogEvent(DateTimeOffset? timestamp = null, Exception? ex = null, string messageTemplate = TestMessageTemplate)
26+
internal static LogEvent DefaultSerilogEvent()
27+
{
28+
return SerilogEvent(
29+
TestMessageTemplate,
30+
new List<LogEventProperty> { new("Variable", new ScalarValue(42)) },
31+
DateTimeOffset.UtcNow,
32+
null);
33+
}
34+
35+
internal static LogEvent SerilogEvent(string messageTemplate, DateTimeOffset? timestamp = null, Exception? ex = null)
36+
{
37+
return SerilogEvent(messageTemplate, new List<LogEventProperty>(), timestamp, ex);
38+
}
39+
40+
internal static LogEvent SerilogEvent(string messageTemplate, IEnumerable<LogEventProperty> properties, DateTimeOffset? timestamp = null, Exception? ex = null)
2741
{
2842
var ts = timestamp ?? DateTimeOffset.UtcNow;
2943
var parser = new MessageTemplateParser();
@@ -33,7 +47,7 @@ internal static LogEvent SerilogEvent(DateTimeOffset? timestamp = null, Exceptio
3347
LogEventLevel.Warning,
3448
ex,
3549
template,
36-
new List<LogEventProperty>{ new("Variable", new ScalarValue(42)) });
50+
properties);
3751

3852
return logEvent;
3953
}

0 commit comments

Comments
 (0)