From 1bf3f910a3e524df1e8e63f3d9b0a3cf6674ce82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20P=C3=B6lz?= <38893694+Flash0ver@users.noreply.github.com> Date: Tue, 2 Dec 2025 19:09:23 +0100 Subject: [PATCH 1/2] feat(logs): when Debug is true then SDK-Logger also emits diagnostic logs --- .../Internal/DefaultSentryStructuredLogger.cs | 5 +++ src/Sentry/SentryLogLevel.cs | 12 +++++ test/Sentry.Tests/SentryLogLevelTests.cs | 44 +++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/src/Sentry/Internal/DefaultSentryStructuredLogger.cs b/src/Sentry/Internal/DefaultSentryStructuredLogger.cs index 90f6df853a..92a68be27c 100644 --- a/src/Sentry/Internal/DefaultSentryStructuredLogger.cs +++ b/src/Sentry/Internal/DefaultSentryStructuredLogger.cs @@ -72,6 +72,11 @@ private protected override void CaptureLog(SentryLogLevel level, string template log.SetDefaultAttributes(_options, scope?.Sdk ?? SdkVersion.Instance); CaptureLog(log); + + if (_options.Debug) + { + _options.DiagnosticLogger?.LogIfEnabled(level.ToSentryLevel(), null, message); + } } /// diff --git a/src/Sentry/SentryLogLevel.cs b/src/Sentry/SentryLogLevel.cs index f76a617571..94062a766c 100644 --- a/src/Sentry/SentryLogLevel.cs +++ b/src/Sentry/SentryLogLevel.cs @@ -128,4 +128,16 @@ static SentryLogLevel Overflow(int value, IDiagnosticLogger? logger) return SentryLogLevel.Fatal; } } + + internal static SentryLevel ToSentryLevel(this SentryLogLevel level) + { + return (int)level switch + { + <= 8 => SentryLevel.Debug, + >= 9 and <= 12 => SentryLevel.Info, + >= 13 and <= 16 => SentryLevel.Warning, + >= 17 and <= 20 => SentryLevel.Error, + >= 21 => SentryLevel.Fatal, + }; + } } diff --git a/test/Sentry.Tests/SentryLogLevelTests.cs b/test/Sentry.Tests/SentryLogLevelTests.cs index 36b557ea08..4a1751da03 100644 --- a/test/Sentry.Tests/SentryLogLevelTests.cs +++ b/test/Sentry.Tests/SentryLogLevelTests.cs @@ -149,4 +149,48 @@ public static TheoryData Create() { 24, SentryLogLevel.Fatal }, }; } + + [Theory] + [MemberData(nameof(Convert))] + public void Convert_FromSentryLogLevel_ToSentryLevel(int level, SentryLevel expected) + { + var @enum = (SentryLogLevel)level; + + var actual = @enum.ToSentryLevel(); + + Assert.Equal(expected, actual); + } + + public static TheoryData Convert() + { + return new TheoryData + { + { 0, SentryLevel.Debug }, + { 1, SentryLevel.Debug }, + { 2, SentryLevel.Debug }, + { 3, SentryLevel.Debug }, + { 4, SentryLevel.Debug }, + { 5, SentryLevel.Debug }, + { 6, SentryLevel.Debug }, + { 7, SentryLevel.Debug }, + { 8, SentryLevel.Debug }, + { 9, SentryLevel.Info }, + { 10, SentryLevel.Info }, + { 11, SentryLevel.Info }, + { 12, SentryLevel.Info }, + { 13, SentryLevel.Warning }, + { 14, SentryLevel.Warning }, + { 15, SentryLevel.Warning }, + { 16, SentryLevel.Warning }, + { 17, SentryLevel.Error }, + { 18, SentryLevel.Error }, + { 19, SentryLevel.Error }, + { 20, SentryLevel.Error }, + { 21, SentryLevel.Fatal }, + { 22, SentryLevel.Fatal }, + { 23, SentryLevel.Fatal }, + { 24, SentryLevel.Fatal }, + { 25, SentryLevel.Fatal }, + }; + } } From 5870b3911c8c1363e06a3b79084d9495cf0d8f02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20P=C3=B6lz?= <38893694+Flash0ver@users.noreply.github.com> Date: Wed, 3 Dec 2025 15:55:18 +0100 Subject: [PATCH 2/2] feat(logs): print to Console when it's going to be sent --- .../Internal/DefaultSentryStructuredLogger.cs | 21 ++++++- src/Sentry/SentryLogLevel.cs | 21 +++++-- test/Sentry.Tests/SentryLogLevelTests.cs | 60 +++++++++---------- 3 files changed, 63 insertions(+), 39 deletions(-) diff --git a/src/Sentry/Internal/DefaultSentryStructuredLogger.cs b/src/Sentry/Internal/DefaultSentryStructuredLogger.cs index 92a68be27c..17d1cfe99f 100644 --- a/src/Sentry/Internal/DefaultSentryStructuredLogger.cs +++ b/src/Sentry/Internal/DefaultSentryStructuredLogger.cs @@ -71,11 +71,11 @@ private protected override void CaptureLog(SentryLogLevel level, string template var scope = _hub.GetScope(); log.SetDefaultAttributes(_options, scope?.Sdk ?? SdkVersion.Instance); - CaptureLog(log); + var captured = CaptureLog(log); - if (_options.Debug) + if (captured && _options.Debug) { - _options.DiagnosticLogger?.LogIfEnabled(level.ToSentryLevel(), null, message); + WriteToConsole(log); } } @@ -114,4 +114,19 @@ public void Dispose() { _batchProcessor.Dispose(); } + + private static void WriteToConsole(SentryLog log) + { + Debug.Assert(!log.TryGetAttribute("sentry.origin", out string? origin), $"Logs should only be printed to the Console when captured via the Sentry Logger APIs and not through any integration: {origin}"); + + var capacity = 10 + 2 + log.Message.Length; + var text = new StringBuilder(capacity); + text.Append(log.Level.ToText().PadLeft(10)); + text.Append(": "); + text.Append(log.Message); + + Debug.Assert(text.Length == capacity, $"Wrong assumption of capacity: Expected: {capacity}; Actual: {text.Length}"); + + Console.WriteLine(text.ToString()); + } } diff --git a/src/Sentry/SentryLogLevel.cs b/src/Sentry/SentryLogLevel.cs index 94062a766c..9a55f72a9e 100644 --- a/src/Sentry/SentryLogLevel.cs +++ b/src/Sentry/SentryLogLevel.cs @@ -129,15 +129,24 @@ static SentryLogLevel Overflow(int value, IDiagnosticLogger? logger) } } - internal static SentryLevel ToSentryLevel(this SentryLogLevel level) + internal static string ToText(this SentryLogLevel level) { return (int)level switch { - <= 8 => SentryLevel.Debug, - >= 9 and <= 12 => SentryLevel.Info, - >= 13 and <= 16 => SentryLevel.Warning, - >= 17 and <= 20 => SentryLevel.Error, - >= 21 => SentryLevel.Fatal, + <= 0 => "trace(<1)", + 1 => "trace", + >= 2 and <= 4 => $"trace({(int)level})", + 5 => "debug", + >= 6 and <= 8 => $"debug({(int)level})", + 9 => "info", + >= 10 and <= 12 => $"info({(int)level})", + 13 => "warn", + >= 14 and <= 16 => $"warn({(int)level})", + 17 => "error", + >= 18 and <= 20 => $"error({(int)level})", + 21 => "fatal", + >= 22 and <= 24 => $"fatal({(int)level})", + >= 25 => "fatal(>24)", }; } } diff --git a/test/Sentry.Tests/SentryLogLevelTests.cs b/test/Sentry.Tests/SentryLogLevelTests.cs index 4a1751da03..471a0b0573 100644 --- a/test/Sentry.Tests/SentryLogLevelTests.cs +++ b/test/Sentry.Tests/SentryLogLevelTests.cs @@ -152,45 +152,45 @@ public static TheoryData Create() [Theory] [MemberData(nameof(Convert))] - public void Convert_FromSentryLogLevel_ToSentryLevel(int level, SentryLevel expected) + public void Convert_FromSentryLogLevel_ToString(int level, string expected) { var @enum = (SentryLogLevel)level; - var actual = @enum.ToSentryLevel(); + var actual = @enum.ToText(); Assert.Equal(expected, actual); } - public static TheoryData Convert() + public static TheoryData Convert() { - return new TheoryData + return new TheoryData { - { 0, SentryLevel.Debug }, - { 1, SentryLevel.Debug }, - { 2, SentryLevel.Debug }, - { 3, SentryLevel.Debug }, - { 4, SentryLevel.Debug }, - { 5, SentryLevel.Debug }, - { 6, SentryLevel.Debug }, - { 7, SentryLevel.Debug }, - { 8, SentryLevel.Debug }, - { 9, SentryLevel.Info }, - { 10, SentryLevel.Info }, - { 11, SentryLevel.Info }, - { 12, SentryLevel.Info }, - { 13, SentryLevel.Warning }, - { 14, SentryLevel.Warning }, - { 15, SentryLevel.Warning }, - { 16, SentryLevel.Warning }, - { 17, SentryLevel.Error }, - { 18, SentryLevel.Error }, - { 19, SentryLevel.Error }, - { 20, SentryLevel.Error }, - { 21, SentryLevel.Fatal }, - { 22, SentryLevel.Fatal }, - { 23, SentryLevel.Fatal }, - { 24, SentryLevel.Fatal }, - { 25, SentryLevel.Fatal }, + { 0, "trace(<1)" }, + { 1, "trace" }, + { 2, "trace(2)" }, + { 3, "trace(3)" }, + { 4, "trace(4)" }, + { 5, "debug" }, + { 6, "debug(6)" }, + { 7, "debug(7)" }, + { 8, "debug(8)" }, + { 9, "info" }, + { 10, "info(10)" }, + { 11, "info(11)" }, + { 12, "info(12)" }, + { 13, "warn" }, + { 14, "warn(14)" }, + { 15, "warn(15)" }, + { 16, "warn(16)" }, + { 17, "error" }, + { 18, "error(18)" }, + { 19, "error(19)" }, + { 20, "error(20)" }, + { 21, "fatal" }, + { 22, "fatal(22)" }, + { 23, "fatal(23)" }, + { 24, "fatal(24)" }, + { 25, "fatal(>24)" }, }; } }