Skip to content

Commit 5b10643

Browse files
committed
Let the batcher create it’s own serial default queue
1 parent 8c0be55 commit 5b10643

File tree

7 files changed

+51
-21
lines changed

7 files changed

+51
-21
lines changed

Sources/Sentry/SentryClient.m

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -116,17 +116,7 @@ - (instancetype)initWithOptions:(SentryOptions *)options
116116
self.timezone = timezone;
117117
self.attachmentProcessors = [[NSMutableArray alloc] init];
118118

119-
// Uses DEFAULT priority (not LOW) because captureLogs() is called synchronously during
120-
// app lifecycle events (willResignActive, willTerminate) and needs to complete quickly.
121-
dispatch_queue_attr_t attributes
122-
= dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0);
123-
SentryDispatchQueueWrapper *logBatcherQueue =
124-
[[SentryDispatchQueueWrapper alloc] initWithName:"io.sentry.log-batcher"
125-
attributes:attributes];
126-
127-
self.logBatcher = [[SentryLogBatcher alloc] initWithOptions:options
128-
dispatchQueue:logBatcherQueue
129-
delegate:self];
119+
self.logBatcher = [[SentryLogBatcher alloc] initWithOptions:options delegate:self];
130120

131121
// The SDK stores the installationID in a file. The first call requires file IO. To avoid
132122
// executing this on the main thread, we cache the installationID async here.

Sources/Sentry/_SentryDispatchQueueWrapperInternal.m

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,17 @@ @implementation _SentryDispatchQueueWrapperInternal
77

88
- (instancetype)init
99
{
10-
// DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL is requires iOS 10. Since we are targeting
11-
// iOS 9 we need to manually add the autoreleasepool.
12-
dispatch_queue_attr_t attributes = dispatch_queue_attr_make_with_qos_class(
13-
DISPATCH_QUEUE_SERIAL, DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
14-
self = [self initWithName:"io.sentry.default" attributes:attributes];
10+
self = [self initWithName:"io.sentry.default"];
11+
return self;
12+
}
13+
14+
- (instancetype)initWithName:(const char *)name
15+
{
16+
if (self = [super init]) {
17+
dispatch_queue_attr_t attributes
18+
= dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0);
19+
_queue = dispatch_queue_create(name, attributes);
20+
}
1521
return self;
1622
}
1723

Sources/Sentry/include/_SentryDispatchQueueWrapperInternal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ NS_ASSUME_NONNULL_BEGIN
1212

1313
@property (strong, nonatomic) dispatch_queue_t queue;
1414

15+
- (instancetype)initWithName:(const char *)name;
16+
1517
- (instancetype)initWithName:(const char *)name
1618
attributes:(nullable dispatch_queue_attr_t)attributes;
1719

Sources/Swift/Helper/SentryDispatchQueueWrapper.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
public override init() {
1111
internalWrapper = _SentryDispatchQueueWrapperInternal()
1212
}
13+
14+
public init(name: UnsafePointer<CChar>) {
15+
internalWrapper = _SentryDispatchQueueWrapperInternal(name: name)
16+
}
1317

1418
public init(name: UnsafePointer<CChar>, relativePriority: Int32) {
1519
internalWrapper = _SentryDispatchQueueWrapperInternal(name: name, relativePriority: relativePriority)

Sources/Swift/Tools/SentryLogBatcher.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,19 @@ import Foundation
2626
private weak var delegate: SentryLogBatcherDelegate?
2727

2828
/// Convenience initializer with default flush timeout, max log count (100), and buffer size.
29+
/// Creates its own serial dispatch queue with DEFAULT QoS for thread-safe access to mutable state.
2930
/// - Parameters:
3031
/// - options: The Sentry configuration options
31-
/// - dispatchQueue: A **serial** dispatch queue wrapper for thread-safe access to mutable state
3232
/// - delegate: The delegate to handle captured log batches
3333
///
34-
/// - Important: The `dispatchQueue` parameter MUST be a serial queue to ensure thread safety.
35-
/// Passing a concurrent queue will result in undefined behavior and potential data races.
36-
///
34+
/// - Note: Uses DEFAULT priority (not LOW) because captureLogs() is called synchronously during
35+
/// app lifecycle events (willResignActive, willTerminate) and needs to complete quickly.
3736
/// - Note: Setting `maxLogCount` to 100. While Replay hard limit is 1000, we keep this lower, as it's hard to lower once released.
3837
@_spi(Private) public convenience init(
3938
options: Options,
40-
dispatchQueue: SentryDispatchQueueWrapper,
4139
delegate: SentryLogBatcherDelegate
4240
) {
41+
let dispatchQueue = SentryDispatchQueueWrapper(name: "io.sentry.log-batcher")
4342
self.init(
4443
options: options,
4544
flushTimeout: 5,

Tests/SentryTests/Networking/SentryDispatchQueueWrapperTests.m

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,26 @@ - (void)testInitWithNameAndAttributes_customAttributes_shouldCreateQueueWithGive
7777
XCTAssertEqual(actualQoSClass, QOS_CLASS_UNSPECIFIED);
7878
XCTAssertEqual(actualRelativePriority, 0);
7979
}
80+
81+
- (void)testInitWithName_shouldCreateQueueWithDefaultQoS
82+
{
83+
// -- Arrange --
84+
const char *queueName = "sentry-dispatch-factory.test-default-qos";
85+
86+
// -- Act --
87+
SentryDispatchQueueWrapper *wrappedQueue =
88+
[[SentryDispatchQueueWrapper alloc] initWithName:queueName];
89+
90+
// -- Assert --
91+
const char *actualName = dispatch_queue_get_label(wrappedQueue.queue);
92+
XCTAssertEqual(strcmp(actualName, queueName), 0);
93+
94+
int actualRelativePriority;
95+
dispatch_qos_class_t actualQoSClass
96+
= dispatch_queue_get_qos_class(wrappedQueue.queue, &actualRelativePriority);
97+
XCTAssertEqual(actualQoSClass, QOS_CLASS_DEFAULT);
98+
XCTAssertEqual(actualRelativePriority, 0);
99+
}
80100
@end
81101

82102
NS_ASSUME_NONNULL_END

Tests/SentryTests/SentryClientTests.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2398,6 +2398,9 @@ class SentryClientTests: XCTestCase {
23982398
let testDelegate = TestLogBatcherDelegateForClient()
23992399
let testBatcher = TestLogBatcherForClient(
24002400
options: sut.options,
2401+
flushTimeout: 5,
2402+
maxLogCount: 100,
2403+
maxBufferSizeBytes: 1_024 * 1_024,
24012404
dispatchQueue: TestSentryDispatchQueueWrapper(),
24022405
delegate: testDelegate
24032406
)
@@ -2426,6 +2429,9 @@ class SentryClientTests: XCTestCase {
24262429
let testDelegate = TestLogBatcherDelegateForClient()
24272430
let testBatcher = TestLogBatcherForClient(
24282431
options: sut.options,
2432+
flushTimeout: 5,
2433+
maxLogCount: 100,
2434+
maxBufferSizeBytes: 1_024 * 1_024,
24292435
dispatchQueue: TestSentryDispatchQueueWrapper(),
24302436
delegate: testDelegate
24312437
)
@@ -2444,6 +2450,9 @@ class SentryClientTests: XCTestCase {
24442450
let testDelegate = TestLogBatcherDelegateForClient()
24452451
let testBatcher = TestLogBatcherForClient(
24462452
options: sut.options,
2453+
flushTimeout: 5,
2454+
maxLogCount: 100,
2455+
maxBufferSizeBytes: 1_024 * 1_024,
24472456
dispatchQueue: TestSentryDispatchQueueWrapper(),
24482457
delegate: testDelegate
24492458
)

0 commit comments

Comments
 (0)