Skip to content

Commit 43d4334

Browse files
authored
Support custom LogEventPropertyValue values in direct log submission (#8034)
## Summary of changes Handle the case where a customer is using a custom `LogEventPropertyValue` implementation and direct log submission ## Reason for change #8010 handled a case where we were generating invalid JSON by dropping the offending value. This PR adds support for serializing the value as a string instead. ## Implementation details Ducktyped `LogEventPropertyValue` and called its `Render` method with a cached `StringBuilder` to get the value, then use the same mechanisms ## Test coverage Should be covered by the tests added in #8010 ## Other details
1 parent 8b26eb2 commit 43d4334

File tree

3 files changed

+42
-1
lines changed

3 files changed

+42
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// <copyright file="ILogEventPropertyValue.cs" company="Datadog">
2+
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
3+
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
4+
// </copyright>
5+
6+
#nullable enable
7+
using System;
8+
using System.IO;
9+
10+
namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.DirectSubmission.Formatting;
11+
12+
/// <summary>
13+
/// Duck type for LogEventPropertyValue
14+
/// https://github.com/serilog/serilog/blob/5e93d5045585095ebcb71ef340d6accd61f01670/src/Serilog/Events/LogEventPropertyValue.cs
15+
/// </summary>
16+
internal interface ILogEventPropertyValue
17+
{
18+
void Render(TextWriter output, string? format, IFormatProvider? formatProvider);
19+
}

tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Logging/Serilog/DirectSubmission/Formatting/SerilogLogFormatter.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
#nullable enable
66

77
using System.Collections;
8+
using System.IO;
89
using System.Text;
910
using Datadog.Trace.DuckTyping;
1011
using Datadog.Trace.Logging;
1112
using Datadog.Trace.Logging.DirectSubmission;
1213
using Datadog.Trace.Logging.DirectSubmission.Formatting;
14+
using Datadog.Trace.Util;
1315
using Datadog.Trace.Vendors.Newtonsoft.Json;
1416
using Datadog.Trace.Vendors.Serilog.Events;
1517

@@ -107,6 +109,18 @@ private static void FormatLogEventPropertyValue(JsonTextWriter writer, object va
107109
return;
108110
}
109111

112+
if (value.TryDuckCast<ILogEventPropertyValue>(out var propertyValue))
113+
{
114+
// This is likely an edge case, so we just write the value as a string and then embed that in the JSON
115+
var sb = StringBuilderCache.Acquire();
116+
var stringWriter = new StringWriter(sb);
117+
propertyValue.Render(stringWriter, null, null);
118+
var stringValue = stringWriter.ToString();
119+
StringBuilderCache.Release(sb);
120+
LogFormatter.WriteValue(writer, stringValue);
121+
return;
122+
}
123+
110124
// Always write null for unknown types to maintain valid JSON
111125
LogFormatter.WriteValue(writer, value: null);
112126

tracer/src/Datadog.Trace/Logging/DirectSubmission/Sink/DirectSubmissionLogSink.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,15 @@ protected override async Task<bool> EmitBatch(Queue<DirectSubmissionLogEvent> ev
100100
_logStringBuilder.Capacity = InitialBuilderSizeBytes;
101101
}
102102

103-
log.Format(_logStringBuilder, _formatter);
103+
try
104+
{
105+
log.Format(_logStringBuilder, _formatter);
106+
}
107+
catch (Exception ex)
108+
{
109+
_logger.Error(ex, "Log dropped due to an error during serialization");
110+
continue;
111+
}
104112

105113
// would be nice to avoid this, but can't see a way without direct UTF8 serialization (System.Text.Json)
106114
// Currently a rogue giant message still pays the serialization cost but is then thrown away

0 commit comments

Comments
 (0)