Skip to content

Commit 2f0ff20

Browse files
Refactored to remove BackpressureMonitor from the SentryOptions
1 parent 4356d28 commit 2f0ff20

File tree

13 files changed

+109
-62
lines changed

13 files changed

+109
-62
lines changed

benchmarks/Sentry.Benchmarks/BackgroundWorkerFlushBenchmarks.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public Task SendEnvelopeAsync(Envelope envelope, CancellationToken cancellationT
2020
[IterationSetup]
2121
public void IterationSetup()
2222
{
23-
_backgroundWorker = new BackgroundWorker(new FakeTransport(), new SentryOptions { MaxQueueItems = 1000 });
23+
_backgroundWorker = new BackgroundWorker(new FakeTransport(), new SentryOptions { MaxQueueItems = 1000 }, null);
2424
_event = new SentryEvent();
2525
_envelope = Envelope.FromEvent(_event);
2626

src/Sentry/Http/HttpTransportBase.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public abstract class HttpTransportBase
1616
internal const string DefaultErrorMessage = "No message";
1717

1818
private readonly SentryOptions _options;
19+
private readonly BackpressureMonitor? _backpressureMonitor;
1920
private readonly ISystemClock _clock;
2021
private readonly Func<string, string?> _getEnvironmentVariable;
2122

@@ -42,6 +43,24 @@ protected HttpTransportBase(SentryOptions options,
4243
_typeName = GetType().Name;
4344
}
4445

46+
/// <summary>
47+
/// Constructor for this class.
48+
/// </summary>
49+
/// <param name="options">The Sentry options.</param>
50+
/// <param name="backpressureMonitor">The Sentry options.</param>
51+
/// <param name="getEnvironmentVariable">An optional method used to read environment variables.</param>
52+
/// <param name="clock">An optional system clock - used for testing.</param>
53+
internal HttpTransportBase(SentryOptions options, BackpressureMonitor? backpressureMonitor,
54+
Func<string, string?>? getEnvironmentVariable = default,
55+
ISystemClock? clock = default)
56+
{
57+
_options = options;
58+
_backpressureMonitor = backpressureMonitor;
59+
_clock = clock ?? SystemClock.Clock;
60+
_getEnvironmentVariable = getEnvironmentVariable ?? options.SettingLocator.GetEnvironmentVariable;
61+
_typeName = GetType().Name;
62+
}
63+
4564
// Keep track of rate limits and their expiry dates.
4665
// Internal for testing.
4766
internal ConcurrentDictionary<RateLimitCategory, DateTimeOffset> CategoryLimitResets { get; } = new();
@@ -256,7 +275,7 @@ private void ExtractRateLimits(HttpHeaders responseHeaders)
256275
}
257276

258277
var now = _clock.GetUtcNow();
259-
_options.BackpressureMonitor?.RecordRateLimitHit(now);
278+
_backpressureMonitor?.RecordRateLimitHit(now);
260279

261280
// Join to a string to handle both single-header and multi-header cases
262281
var rateLimitsEncoded = string.Join(",", rateLimitHeaderValues);

src/Sentry/Internal/BackgroundWorker.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ internal class BackgroundWorker : IBackgroundWorker, IDisposable
99
{
1010
private readonly ITransport _transport;
1111
private readonly SentryOptions _options;
12+
private readonly BackpressureMonitor? _backpressureMonitor;
1213
private readonly ConcurrentQueueLite<Envelope> _queue;
1314
private readonly int _maxItems;
1415
private readonly CancellationTokenSource _shutdownSource;
@@ -26,11 +27,13 @@ internal class BackgroundWorker : IBackgroundWorker, IDisposable
2627
public BackgroundWorker(
2728
ITransport transport,
2829
SentryOptions options,
30+
BackpressureMonitor? backpressureMonitor,
2931
CancellationTokenSource? shutdownSource = null,
3032
ConcurrentQueueLite<Envelope>? queue = null)
3133
{
3234
_transport = transport;
3335
_options = options;
36+
_backpressureMonitor = backpressureMonitor;
3437
_queue = queue ?? new ConcurrentQueueLite<Envelope>();
3538
_maxItems = options.MaxQueueItems;
3639
_shutdownSource = shutdownSource ?? new CancellationTokenSource();
@@ -66,7 +69,7 @@ public bool EnqueueEnvelope(Envelope envelope, bool process)
6669
var eventId = envelope.TryGetEventId(_options.DiagnosticLogger);
6770
if (Interlocked.Increment(ref _currentItems) > _maxItems)
6871
{
69-
_options.BackpressureMonitor?.RecordQueueOverflow();
72+
_backpressureMonitor?.RecordQueueOverflow();
7073
Interlocked.Decrement(ref _currentItems);
7174
_options.ClientReportRecorder.RecordDiscardedEvents(DiscardReason.QueueOverflow, envelope);
7275
_options.LogInfo("Discarding envelope {0} because the queue is full.", eventId);

src/Sentry/Internal/Http/HttpTransport.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ public HttpTransport(SentryOptions options, HttpClient httpClient)
1515
_httpClient = httpClient;
1616
}
1717

18-
internal HttpTransport(SentryOptions options, HttpClient httpClient,
18+
internal HttpTransport(SentryOptions options, HttpClient httpClient, BackpressureMonitor? backpressureMonitor,
1919
Func<string, string?>? getEnvironmentVariable = default,
2020
ISystemClock? clock = default)
21-
: base(options, getEnvironmentVariable, clock)
21+
: base(options, backpressureMonitor, getEnvironmentVariable, clock)
2222
{
2323
_httpClient = httpClient;
2424
}

src/Sentry/Internal/Http/LazyHttpTransport.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ internal class LazyHttpTransport : ITransport
77
{
88
private readonly Lazy<HttpTransport> _httpTransport;
99

10-
public LazyHttpTransport(SentryOptions options)
10+
public LazyHttpTransport(SentryOptions options, BackpressureMonitor? backpressureMonitor)
1111
{
12-
_httpTransport = new Lazy<HttpTransport>(() => new HttpTransport(options, options.GetHttpClient()));
12+
_httpTransport = new Lazy<HttpTransport>(() => new HttpTransport(options, options.GetHttpClient(), backpressureMonitor));
1313
}
1414

1515
public Task SendEnvelopeAsync(Envelope envelope, CancellationToken cancellationToken = default)

src/Sentry/Internal/Hub.cs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ internal class Hub : IHub, IDisposable
1818
private readonly RandomValuesFactory _randomValuesFactory;
1919
private readonly IReplaySession _replaySession;
2020
private readonly List<IDisposable> _integrationsToCleanup = new();
21+
private readonly BackpressureMonitor? _backpressureMonitor;
2122

2223
#if MEMORY_DUMP_SUPPORTED
2324
private readonly MemoryMonitor? _memoryMonitor;
@@ -46,7 +47,8 @@ internal Hub(
4647
IInternalScopeManager? scopeManager = null,
4748
RandomValuesFactory? randomValuesFactory = null,
4849
IReplaySession? replaySession = null,
49-
ISampleRandHelper? sampleRandHelper = null)
50+
ISampleRandHelper? sampleRandHelper = null,
51+
BackpressureMonitor? backpressureMonitor = null)
5052
{
5153
if (string.IsNullOrWhiteSpace(options.Dsn))
5254
{
@@ -61,9 +63,9 @@ internal Hub(
6163
_randomValuesFactory = randomValuesFactory ?? new SynchronizedRandomValuesFactory();
6264
_sessionManager = sessionManager ?? new GlobalSessionManager(options);
6365
_clock = clock ?? SystemClock.Clock;
64-
if (_options.EnableBackpressureHandling && _options.BackpressureMonitor is null)
66+
if (_options.EnableBackpressureHandling)
6567
{
66-
_options.BackpressureMonitor = new BackpressureMonitor(_options.DiagnosticLogger, clock);
68+
_backpressureMonitor = backpressureMonitor ?? new BackpressureMonitor(_options.DiagnosticLogger, clock);
6769
}
6870
client ??= new SentryClient(options, randomValuesFactory: _randomValuesFactory, sessionManager: _sessionManager);
6971
_replaySession = replaySession ?? ReplaySession.Instance;
@@ -197,7 +199,7 @@ internal ITransactionTracer StartTransaction(
197199
if (tracesSampler(samplingContext) is { } samplerSampleRate)
198200
{
199201
// The TracesSampler trumps all other sampling decisions (even the trace header)
200-
sampleRate = samplerSampleRate * _options.BackpressureMonitor.GetDownsampleFactor();
202+
sampleRate = samplerSampleRate * _backpressureMonitor.GetDownsampleFactor();
201203
isSampled = SampleRandHelper.IsSampled(sampleRand, sampleRate.Value);
202204
if (isSampled is false)
203205
{
@@ -216,7 +218,7 @@ internal ITransactionTracer StartTransaction(
216218
if (isSampled == null)
217219
{
218220
var optionsSampleRate = _options.TracesSampleRate ?? 0.0;
219-
sampleRate = optionsSampleRate * _options.BackpressureMonitor.GetDownsampleFactor();
221+
sampleRate = optionsSampleRate * _backpressureMonitor.GetDownsampleFactor();
220222
isSampled = context.IsSampled ?? SampleRandHelper.IsSampled(sampleRand, sampleRate.Value);
221223
if (isSampled is false)
222224
{
@@ -867,11 +869,7 @@ public void Dispose()
867869
}
868870
//Don't dispose of ScopeManager since we want dangling transactions to still be able to access tags.
869871

870-
if (_options.BackpressureMonitor is { } backpressureMonitor)
871-
{
872-
_options.BackpressureMonitor = null;
873-
backpressureMonitor.Dispose();
874-
}
872+
_backpressureMonitor?.Dispose();
875873

876874
#if __IOS__
877875
// TODO

src/Sentry/Internal/SdkComposer.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,24 @@ namespace Sentry.Internal;
88
internal class SdkComposer
99
{
1010
private readonly SentryOptions _options;
11+
private readonly BackpressureMonitor? _backpressureMonitor;
1112

12-
public SdkComposer(SentryOptions options)
13+
public SdkComposer(SentryOptions options, BackpressureMonitor? backpressureMonitor)
1314
{
1415
_options = options ?? throw new ArgumentNullException(nameof(options));
1516
if (options.Dsn is null)
1617
{
1718
throw new ArgumentException("No DSN defined in the SentryOptions");
1819
}
20+
_backpressureMonitor = backpressureMonitor;
1921
}
2022

2123
private ITransport CreateTransport()
2224
{
2325
_options.LogDebug("Creating transport.");
2426

2527
// Start from either the transport given on options, or create a new HTTP transport.
26-
var transport = _options.Transport ?? new LazyHttpTransport(_options);
28+
var transport = _options.Transport ?? new LazyHttpTransport(_options, _backpressureMonitor);
2729

2830
// When a cache directory path is given, wrap the transport in a caching transport.
2931
if (!string.IsNullOrWhiteSpace(_options.CacheDirectoryPath))
@@ -87,6 +89,6 @@ public IBackgroundWorker CreateBackgroundWorker()
8789

8890
var transport = CreateTransport();
8991

90-
return new BackgroundWorker(transport, _options);
92+
return new BackgroundWorker(transport, _options, _backpressureMonitor);
9193
}
9294
}

src/Sentry/SentryClient.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ namespace Sentry;
1616
public class SentryClient : ISentryClient, IDisposable
1717
{
1818
private readonly SentryOptions _options;
19+
private readonly BackpressureMonitor? _backpressureMonitor;
1920
private readonly ISessionManager _sessionManager;
2021
private readonly RandomValuesFactory _randomValuesFactory;
2122
private readonly Enricher _enricher;
@@ -41,9 +42,11 @@ internal SentryClient(
4142
SentryOptions options,
4243
IBackgroundWorker? worker = null,
4344
RandomValuesFactory? randomValuesFactory = null,
44-
ISessionManager? sessionManager = null)
45+
ISessionManager? sessionManager = null,
46+
BackpressureMonitor? backpressureMonitor = null)
4547
{
4648
_options = options ?? throw new ArgumentNullException(nameof(options));
49+
_backpressureMonitor = backpressureMonitor;
4750
_randomValuesFactory = randomValuesFactory ?? new SynchronizedRandomValuesFactory();
4851
_sessionManager = sessionManager ?? new GlobalSessionManager(options);
4952
_enricher = new Enricher(options);
@@ -52,7 +55,7 @@ internal SentryClient(
5255

5356
if (worker == null)
5457
{
55-
var composer = new SdkComposer(options);
58+
var composer = new SdkComposer(options, backpressureMonitor);
5659
Worker = composer.CreateBackgroundWorker();
5760
}
5861
else
@@ -375,7 +378,7 @@ private SentryId DoSendEvent(SentryEvent @event, SentryHint? hint, Scope? scope)
375378
if (_options.SampleRate != null)
376379
{
377380
var sampleRate = _options.SampleRate.Value;
378-
var downsampledRate = sampleRate * _options.BackpressureMonitor.GetDownsampleFactor();
381+
var downsampledRate = sampleRate * _backpressureMonitor.GetDownsampleFactor();
379382
var sampleRand = _randomValuesFactory.NextDouble();
380383
if (sampleRand >= downsampledRate)
381384
{

src/Sentry/SentryOptions.cs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,6 @@ public bool IsGlobalModeEnabled
100100
/// </summary>
101101
public bool EnableBackpressureHandling { get; set; } = false;
102102

103-
/// <summary>
104-
/// Stores a reference to the BackpressureMonitor for use by the rest of the SDK.
105-
/// </summary>
106-
/// <remarks>Note: this is necessary since the BackpressureMonitor is used by <see cref="HttpTransportBase"/>,
107-
/// which is a public abstract class. Adding parameters to the constructor of that class would be a breaking change.
108-
/// </remarks>
109-
internal BackpressureMonitor? BackpressureMonitor { get; set; }
110-
111103
/// <summary>
112104
/// This holds a reference to the current transport, when one is active.
113105
/// If set manually before initialization, the provided transport will be used instead of the default transport.

test/Sentry.Tests/HubTests.cs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55

66
namespace Sentry.Tests;
77

8-
public partial class HubTests
8+
public partial class HubTests : IDisposable
99
{
1010
private readonly ITestOutputHelper _output;
1111

12-
private class Fixture
12+
private class Fixture : IDisposable
1313
{
1414
public SentryOptions Options { get; }
1515
public ISentryClient Client { get; set; }
@@ -18,6 +18,7 @@ private class Fixture
1818
public ISystemClock Clock { get; set; }
1919
public IReplaySession ReplaySession { get; }
2020
public ISampleRandHelper SampleRandHelper { get; set; }
21+
public BackpressureMonitor BackpressureMonitor { get; set; }
2122

2223
public Fixture()
2324
{
@@ -27,14 +28,22 @@ public Fixture()
2728
TracesSampleRate = 1.0,
2829
AutoSessionTracking = false
2930
};
30-
3131
Client = Substitute.For<ISentryClient>();
32-
3332
ReplaySession = Substitute.For<IReplaySession>();
3433
}
3534

35+
public void Dispose()
36+
{
37+
BackpressureMonitor?.Dispose();
38+
}
39+
3640
public Hub GetSut() => new(Options, Client, SessionManager, Clock, ScopeManager, replaySession: ReplaySession,
37-
sampleRandHelper: SampleRandHelper);
41+
sampleRandHelper: SampleRandHelper, backpressureMonitor: BackpressureMonitor);
42+
}
43+
44+
public void Dispose()
45+
{
46+
_fixture.Dispose();
3847
}
3948

4049
private readonly Fixture _fixture = new();
@@ -725,11 +734,11 @@ public void StartTransaction_Backpressure_Downsamples(bool usesTracesSampler)
725734
var transactionContext = new TransactionContext("name", "operation");
726735

727736
var clock = new MockClock(DateTimeOffset.UtcNow);
728-
var backpressureMonitor = new BackpressureMonitor(null, clock, enablePeriodicHealthCheck: false);
729-
backpressureMonitor.SetDownsampleLevel(1);
730-
_fixture.Options.BackpressureMonitor = backpressureMonitor;
737+
_fixture.Options.EnableBackpressureHandling = true;
738+
_fixture.BackpressureMonitor = new BackpressureMonitor(null, clock, enablePeriodicHealthCheck: false);
739+
_fixture.BackpressureMonitor.SetDownsampleLevel(1);
731740
var sampleRate = 0.5f;
732-
var expectedDownsampledRate = sampleRate * backpressureMonitor.DownsampleFactor;
741+
var expectedDownsampledRate = sampleRate * _fixture.BackpressureMonitor.DownsampleFactor;
733742
if (usesTracesSampler)
734743
{
735744
_fixture.Options.TracesSampler = _ => sampleRate;
@@ -771,9 +780,9 @@ public void StartTransaction_Backpressure_SetsDiscardReason(bool usesTracesSampl
771780
var clock = new MockClock(DateTimeOffset.UtcNow);
772781
_fixture.SampleRandHelper = Substitute.For<ISampleRandHelper>();
773782
_fixture.SampleRandHelper.GenerateSampleRand(Arg.Any<string>()).Returns(sampleRand);
774-
var backpressureMonitor = new BackpressureMonitor(null, clock, enablePeriodicHealthCheck: false);
775-
backpressureMonitor.SetDownsampleLevel(1);
776-
_fixture.Options.BackpressureMonitor = backpressureMonitor;
783+
_fixture.Options.EnableBackpressureHandling = true;
784+
_fixture.BackpressureMonitor = new BackpressureMonitor(null, clock, enablePeriodicHealthCheck: false);
785+
_fixture.BackpressureMonitor.SetDownsampleLevel(1);
777786
var sampleRate = 0.5f;
778787
if (usesTracesSampler)
779788
{

0 commit comments

Comments
 (0)