Skip to content

Commit 58dce74

Browse files
committed
ref(logs): move Logger instances to Hubs
1 parent dcc0ec1 commit 58dce74

File tree

7 files changed

+99
-53
lines changed

7 files changed

+99
-53
lines changed

src/Sentry/Extensibility/DisabledHub.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using Sentry.Infrastructure;
12
using Sentry.Internal;
23
using Sentry.Protocol.Envelopes;
34
using Sentry.Protocol.Metrics;
@@ -21,6 +22,7 @@ public class DisabledHub : IHub, IDisposable
2122

2223
private DisabledHub()
2324
{
25+
Logger = new SentryStructuredLogger(this);
2426
}
2527

2628
/// <summary>
@@ -228,4 +230,11 @@ public void CaptureUserFeedback(UserFeedback userFeedback)
228230
/// No-Op.
229231
/// </summary>
230232
public SentryId LastEventId => SentryId.Empty;
233+
234+
/// <summary>
235+
/// Disabled Logger.
236+
/// <para>This API is experimental and it may change in the future.</para>
237+
/// </summary>
238+
[Experimental(DiagnosticId.ExperimentalFeature)]
239+
public SentryStructuredLogger Logger { get; }
231240
}

src/Sentry/Extensibility/HubAdapter.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ private HubAdapter() { }
3232
/// </summary>
3333
public SentryId LastEventId { [DebuggerStepThrough] get => SentrySdk.LastEventId; }
3434

35+
/// <summary>
36+
/// Forwards the call to <see cref="SentrySdk"/>.
37+
/// <para>This API is experimental and it may change in the future.</para>
38+
/// </summary>
39+
[Experimental(DiagnosticId.ExperimentalFeature)]
40+
public SentryStructuredLogger Logger { [DebuggerStepThrough] get => SentrySdk.Logger; }
41+
3542
/// <summary>
3643
/// Forwards the call to <see cref="SentrySdk"/>.
3744
/// </summary>

src/Sentry/IHub.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using Sentry.Infrastructure;
2+
13
namespace Sentry;
24

35
/// <summary>
@@ -17,6 +19,20 @@ public interface IHub : ISentryClient, ISentryScopeManager
1719
/// </summary>
1820
public SentryId LastEventId { get; }
1921

22+
/// <summary>
23+
/// Creates and sends logs to Sentry.
24+
/// <para>This API is experimental and it may change in the future.</para>
25+
/// </summary>
26+
/// <remarks>
27+
/// Available options:
28+
/// <list type="bullet">
29+
/// <item><see cref="Sentry.SentryOptions.EnableLogs"/></item>
30+
/// <item><see cref="Sentry.SentryOptions.SetBeforeSendLog(System.Func{Sentry.Protocol.SentryLog, Sentry.Protocol.SentryLog})"/></item>
31+
/// </list>
32+
/// </remarks>
33+
[Experimental(DiagnosticId.ExperimentalFeature)]
34+
public SentryStructuredLogger Logger { get; }
35+
2036
/// <summary>
2137
/// Starts a transaction.
2238
/// </summary>

src/Sentry/Internal/Hub.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ internal Hub(
5757
client ??= new SentryClient(options, randomValuesFactory: _randomValuesFactory, sessionManager: _sessionManager);
5858

5959
ScopeManager = scopeManager ?? new SentryScopeManager(options, client);
60+
Logger = new SentryStructuredLogger(this);
6061

6162
if (!options.IsGlobalModeEnabled)
6263
{
@@ -755,4 +756,7 @@ public void Dispose()
755756
}
756757

757758
public SentryId LastEventId => CurrentScope.LastEventId;
759+
760+
[Experimental(DiagnosticId.ExperimentalFeature)]
761+
public SentryStructuredLogger Logger { get; }
758762
}

src/Sentry/Protocol/SentryLog.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ public required SentryLogLevel Level
7777
[Experimental(DiagnosticId.ExperimentalFeature)]
7878
public ImmutableArray<object> Parameters { get; init; }
7979

80+
/// <summary>
81+
/// The span id of the span that was active when the log was collected.
82+
/// <para>This API is experimental and it may change in the future.</para>
83+
/// </summary>
84+
[Experimental(DiagnosticId.ExperimentalFeature)]
85+
public SpanId? ParentSpanId { get; init; }
86+
8087
/// <summary>
8188
/// Gets the attribute value associated with the specified key when of type <see cref="string"/>.
8289
/// <para>This API is experimental and it may change in the future.</para>
@@ -201,7 +208,7 @@ public void SetAttribute(string key, double value)
201208
_attributes[key] = new SentryAttribute(value, "double");
202209
}
203210

204-
internal void SetAttributes(SentryOptions options, SpanId? parentSpanId)
211+
internal void SetAttributes(SentryOptions options)
205212
{
206213
var environment = options.SettingLocator.GetEnvironment();
207214
SetAttribute("sentry.environment", environment);
@@ -212,9 +219,9 @@ internal void SetAttributes(SentryOptions options, SpanId? parentSpanId)
212219
SetAttribute("sentry.release", release);
213220
}
214221

215-
if (parentSpanId.HasValue)
222+
if (ParentSpanId.HasValue)
216223
{
217-
SetAttribute("sentry.trace.parent_span_id", parentSpanId.Value.ToString());
224+
SetAttribute("sentry.trace.parent_span_id", ParentSpanId.Value.ToString());
218225
}
219226

220227
SetAttribute("sentry.sdk.name", Constants.SdkName);

src/Sentry/SentrySdk.cs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -280,19 +280,9 @@ public void Dispose()
280280
/// </summary>
281281
public static bool IsEnabled { [DebuggerStepThrough] get => CurrentHub.IsEnabled; }
282282

283-
/// <summary>
284-
/// Creates and sends logs to Sentry.
285-
/// <para>This API is experimental and it may change in the future.</para>
286-
/// </summary>
287-
/// <remarks>
288-
/// Available options:
289-
/// <list type="bullet">
290-
/// <item><see cref="Sentry.SentryOptions.EnableLogs"/></item>
291-
/// <item><see cref="Sentry.SentryOptions.SetBeforeSendLog(System.Func{Sentry.Protocol.SentryLog, Sentry.Protocol.SentryLog})"/></item>
292-
/// </list>
293-
/// </remarks>
283+
/// <inheritdoc cref="IHub.Logger" />
294284
[Experimental(DiagnosticId.ExperimentalFeature)]
295-
public static SentryStructuredLogger Logger { get; } = new SentryStructuredLogger();
285+
public static SentryStructuredLogger Logger { [DebuggerStepThrough] get => CurrentHub.Logger; }
296286

297287
/// <summary>
298288
/// Creates a new scope that will terminate when disposed.

src/Sentry/SentryStructuredLogger.cs

Lines changed: 51 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,42 @@ namespace Sentry;
1313
[Experimental(DiagnosticId.ExperimentalFeature)]
1414
public sealed class SentryStructuredLogger
1515
{
16+
private readonly IHub _hub;
1617
private readonly ISystemClock _clock;
1718

18-
internal SentryStructuredLogger()
19-
: this(SystemClock.Clock)
19+
private readonly SentryOptions? _options;
20+
private readonly IInternalScopeManager? _scopeManager;
21+
22+
internal SentryStructuredLogger(IHub hub)
23+
: this(hub, SystemClock.Clock)
24+
{
25+
}
26+
27+
internal SentryStructuredLogger(IHub hub, ISystemClock clock)
28+
: this(hub, (hub as Hub)?.ScopeManager, hub.GetSentryOptions(), clock)
2029
{
2130
}
2231

23-
internal SentryStructuredLogger(ISystemClock clock)
32+
internal SentryStructuredLogger(IHub hub, IInternalScopeManager? scopeManager, SentryOptions? options, ISystemClock clock)
2433
{
34+
_hub = hub;
2535
_clock = clock;
36+
37+
_options = options;
38+
_scopeManager = scopeManager;
39+
IsEnabled = options is { EnableLogs: true };
2640
}
2741

42+
[MemberNotNullWhen(true, nameof(_options))]
43+
private bool IsEnabled { get; }
44+
2845
/// <summary>
2946
/// Creates and sends a structured log to Sentry, with severity <see cref="SentryLogLevel.Trace"/>, when enabled and sampled.
3047
/// <para>This API is experimental and it may change in the future.</para>
3148
/// </summary>
3249
public void LogTrace(string template, object[]? parameters = null, Action<SentryLog>? configureLog = null)
3350
{
34-
if (IsEnabled())
51+
if (IsEnabled)
3552
{
3653
CaptureLog(SentryLogLevel.Trace, template, parameters, configureLog);
3754
}
@@ -44,7 +61,7 @@ public void LogTrace(string template, object[]? parameters = null, Action<Sentry
4461
[Experimental(DiagnosticId.ExperimentalFeature)]
4562
public void LogDebug(string template, object[]? parameters = null, Action<SentryLog>? configureLog = null)
4663
{
47-
if (IsEnabled())
64+
if (IsEnabled)
4865
{
4966
CaptureLog(SentryLogLevel.Debug, template, parameters, configureLog);
5067
}
@@ -57,7 +74,7 @@ public void LogDebug(string template, object[]? parameters = null, Action<Sentry
5774
[Experimental(DiagnosticId.ExperimentalFeature)]
5875
public void LogInfo(string template, object[]? parameters = null, Action<SentryLog>? configureLog = null)
5976
{
60-
if (IsEnabled())
77+
if (IsEnabled)
6178
{
6279
CaptureLog(SentryLogLevel.Info, template, parameters, configureLog);
6380
}
@@ -70,7 +87,7 @@ public void LogInfo(string template, object[]? parameters = null, Action<SentryL
7087
[Experimental(DiagnosticId.ExperimentalFeature)]
7188
public void LogWarning(string template, object[]? parameters = null, Action<SentryLog>? configureLog = null)
7289
{
73-
if (IsEnabled())
90+
if (IsEnabled)
7491
{
7592
CaptureLog(SentryLogLevel.Warning, template, parameters, configureLog);
7693
}
@@ -83,7 +100,7 @@ public void LogWarning(string template, object[]? parameters = null, Action<Sent
83100
[Experimental(DiagnosticId.ExperimentalFeature)]
84101
public void LogError(string template, object[]? parameters = null, Action<SentryLog>? configureLog = null)
85102
{
86-
if (IsEnabled())
103+
if (IsEnabled)
87104
{
88105
CaptureLog(SentryLogLevel.Error, template, parameters, configureLog);
89106
}
@@ -96,57 +113,37 @@ public void LogError(string template, object[]? parameters = null, Action<Sentry
96113
[Experimental(DiagnosticId.ExperimentalFeature)]
97114
public void LogFatal(string template, object[]? parameters = null, Action<SentryLog>? configureLog = null)
98115
{
99-
if (IsEnabled())
116+
if (IsEnabled)
100117
{
101118
CaptureLog(SentryLogLevel.Fatal, template, parameters, configureLog);
102119
}
103120
}
104121

105-
private bool IsEnabled()
106-
{
107-
var hub = SentrySdk.CurrentHub;
108-
109-
if (hub.GetSentryOptions() is { } options)
110-
{
111-
return options.EnableLogs;
112-
}
113-
114-
return false;
115-
}
116-
117122
private void CaptureLog(SentryLogLevel level, string template, object[]? parameters, Action<SentryLog>? configureLog)
118123
{
119-
var timestamp = _clock.GetUtcNow();
120-
121-
var hub = SentrySdk.CurrentHub;
122-
123-
if (hub.GetSentryOptions() is not { EnableLogs: true } options)
124-
{
125-
return;
126-
}
124+
Debug.Assert(_options is not null);
127125

128-
var scopeManager = (hub as Hub)?.ScopeManager;
126+
var timestamp = _clock.GetUtcNow();
129127

130-
if (!TryGetTraceId(hub, scopeManager, out var traceId))
128+
if (!TryGetTraceId(_hub, _scopeManager, out var traceId))
131129
{
132-
options.DiagnosticLogger?.LogWarning("TraceId not found");
130+
_options.DiagnosticLogger?.LogWarning("TraceId not found");
133131
}
134132

135-
_ = TryGetParentSpanId(hub, scopeManager, out var parentSpanId);
133+
_ = TryGetParentSpanId(_hub, _scopeManager, out var parentSpanId);
136134

137-
var message = string.Format(template, parameters ?? []);
135+
var message = string.Format(CultureInfo.InvariantCulture, template, parameters ?? []);
138136
SentryLog log = new(timestamp, traceId, level, message)
139137
{
140138
Template = template,
141139
Parameters = ImmutableArray.Create(parameters),
140+
ParentSpanId = parentSpanId,
142141
};
143-
log.SetAttributes(options, parentSpanId);
142+
log.SetAttributes(_options);
144143

145-
SentryLog? configuredLog;
146144
try
147145
{
148146
configureLog?.Invoke(log);
149-
configuredLog = options.BeforeSendLogInternal?.Invoke(log);
150147
}
151148
catch (Exception e)
152149
{
@@ -156,11 +153,27 @@ private void CaptureLog(SentryLogLevel level, string template, object[]? paramet
156153
return;
157154
}
158155

156+
var configuredLog = log;
157+
if (_options.BeforeSendLogInternal is { } beforeSendLog)
158+
{
159+
try
160+
{
161+
configuredLog = beforeSendLog.Invoke(log);
162+
}
163+
catch (Exception e)
164+
{
165+
//TODO: change to Diagnostic Logger (if enabled)
166+
// see https://github.com/getsentry/sentry-dotnet/issues/4132
167+
Console.WriteLine(e);
168+
return;
169+
}
170+
}
171+
159172
if (configuredLog is not null)
160173
{
161174
//TODO: enqueue in Batch-Processor / Background-Worker
162175
// see https://github.com/getsentry/sentry-dotnet/issues/4132
163-
_ = hub.CaptureEnvelope(Envelope.FromLog(configuredLog));
176+
_ = _hub.CaptureEnvelope(Envelope.FromLog(configuredLog));
164177
}
165178
}
166179

0 commit comments

Comments
 (0)