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)" },
};
}
}