-
-
Notifications
You must be signed in to change notification settings - Fork 215
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Sync Serilog scope properties to Sentry events (#3976)
- Loading branch information
1 parent
e0ed84c
commit 2a798a8
Showing
8 changed files
with
134 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
namespace Sentry.Serilog; | ||
|
||
/// <summary> | ||
/// Extensions for <see cref="SentryOptions"/> to add Serilog specific configuration. | ||
/// </summary> | ||
public static class SentryOptionExtensions | ||
{ | ||
/// <summary> | ||
/// Ensures Serilog scope properties get applied to Sentry events. If you are not initialising Sentry when | ||
/// configuring the Sentry sink for Serilog then you should call this method in the options callback for whichever | ||
/// Sentry integration you are using to initialise Sentry. | ||
/// </summary> | ||
/// <param name="options"></param> | ||
/// <typeparam name="T"></typeparam> | ||
/// <returns></returns> | ||
public static T ApplySerilogScopeToEvents<T>(this T options) where T : SentryOptions | ||
{ | ||
options.AddEventProcessor(new SerilogScopeEventProcessor(options)); | ||
return options; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
using Serilog.Context; | ||
|
||
namespace Sentry.Serilog; | ||
|
||
/// <summary> | ||
/// Sentry event processor that applies properties from the Serilog scope to Sentry events. | ||
/// </summary> | ||
internal class SerilogScopeEventProcessor : ISentryEventProcessor | ||
{ | ||
private readonly SentryOptions _options; | ||
|
||
/// <summary> | ||
/// This processor extracts properties from the Serilog context and applies these to Sentry events. | ||
/// </summary> | ||
public SerilogScopeEventProcessor(SentryOptions options) | ||
{ | ||
_options = options; | ||
_options.LogDebug("Initializing Serilog scope event processor."); | ||
} | ||
|
||
/// <inheritdoc cref="ISentryEventProcessor"/> | ||
public SentryEvent Process(SentryEvent @event) | ||
{ | ||
_options.LogDebug("Running Serilog scope event processor on: Event {0}", @event.EventId); | ||
|
||
// This is a bit of a hack. Serilog doesn't have any hooks that let us inspect the context. We can, however, | ||
// apply the context to a dummy log event and then copy across the properties from that log event to our Sentry | ||
// event. | ||
// See: https://github.com/getsentry/sentry-dotnet/issues/3544#issuecomment-2307884977 | ||
var enricher = LogContext.Clone(); | ||
var logEvent = new LogEvent(DateTimeOffset.Now, LogEventLevel.Error, null, MessageTemplate.Empty, []); | ||
enricher.Enrich(logEvent, new LogEventPropertyFactory()); | ||
foreach (var (key, value) in logEvent.Properties) | ||
{ | ||
if (!@event.Tags.ContainsKey(key)) | ||
{ | ||
// Potentially we could be doing SetData here instead of SetTag. See DefaultSentryScopeStateProcessor. | ||
@event.SetTag( | ||
key, | ||
value is ScalarValue { Value: string stringValue } | ||
? stringValue | ||
: value.ToString() | ||
); | ||
} | ||
} | ||
return @event; | ||
} | ||
|
||
private class LogEventPropertyFactory : ILogEventPropertyFactory | ||
{ | ||
public LogEventProperty CreateProperty(string name, object? value, bool destructureObjects = false) | ||
{ | ||
var scalarValue = new ScalarValue(value); | ||
return new LogEventProperty(name, scalarValue); | ||
} | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
test/Sentry.Serilog.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 5 additions & 0 deletions
5
test/Sentry.Serilog.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 5 additions & 0 deletions
5
test/Sentry.Serilog.Tests/ApiApprovalTests.Run.Net4_8.verified.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
test/Sentry.Serilog.Tests/SerilogScopeEventProcessorTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace Sentry.Serilog.Tests; | ||
|
||
public class SerilogScopeEventProcessorTests | ||
{ | ||
[Theory] | ||
[InlineData("42", "42")] | ||
[InlineData(42, "42")] | ||
public void Emit_WithException_CreatesEventWithException(object value, string expected) | ||
{ | ||
// Arrange | ||
var options = new SentryOptions(); | ||
var sut = new SerilogScopeEventProcessor(options); | ||
|
||
using var log = new LoggerConfiguration().CreateLogger(); | ||
var factory = new LoggerFactory().AddSerilog(log); | ||
var logger = factory.CreateLogger<SerilogScopeEventProcessorTests>(); | ||
|
||
// Act | ||
SentryEvent evt; | ||
using (logger.BeginScope(new Dictionary<string, object> { ["Answer"] = value })) | ||
{ | ||
evt = new SentryEvent(); | ||
sut.Process(evt); | ||
} | ||
|
||
// Assert | ||
evt.Tags.Should().ContainKey("Answer"); | ||
evt.Tags["Answer"].Should().Be(expected); | ||
} | ||
} |