Skip to content

Commit 9df70d3

Browse files
authored
Merge e9d6a1e into 707c222
2 parents 707c222 + e9d6a1e commit 9df70d3

19 files changed

+928
-752
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
- Add SentryDistribution as Swift Package Manager target (#6149)
2626
- Add option `enablePropagateTraceparent` to support OTel/W3C trace propagation (#6356)
27+
- Structured Logs: Add `captureLog` to `Hub` and `Client` (#6518)
2728

2829
### Fixes
2930

Sentry.xcodeproj/project.pbxproj

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,6 @@
734734
92D957732E05A44600E20E66 /* SentryAsyncLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 92D957722E05A44600E20E66 /* SentryAsyncLog.m */; };
735735
92D957772E05A4F300E20E66 /* SentryAsyncLog.h in Headers */ = {isa = PBXBuildFile; fileRef = 92D957762E05A4F300E20E66 /* SentryAsyncLog.h */; };
736736
92E5F3D62CDBB3BF00B7AD98 /* SentrySampling.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8C57A525EEFC42001CEEFA /* SentrySampling.h */; };
737-
92EC54CE2E1EB54B00A10AC2 /* SentryClient+Logs.h in Headers */ = {isa = PBXBuildFile; fileRef = 92EC54CD2E1EB54B00A10AC2 /* SentryClient+Logs.h */; };
738737
92ECD7202E05A7DF0063EC10 /* SentryLogC.h in Headers */ = {isa = PBXBuildFile; fileRef = D8AE48B12C5786AA0092A2A6 /* SentryLogC.h */; settings = {ATTRIBUTES = (Private, ); }; };
739738
92ECD73C2E05ACE00063EC10 /* SentryLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92ECD73B2E05ACDE0063EC10 /* SentryLog.swift */; };
740739
92ECD73E2E05AD320063EC10 /* SentryLogLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92ECD73D2E05AD2B0063EC10 /* SentryLogLevel.swift */; };
@@ -2095,7 +2094,6 @@
20952094
92B6BDAC2E05B9F700D538B3 /* SentryLogTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogTests.swift; sourceTree = "<group>"; };
20962095
92D957722E05A44600E20E66 /* SentryAsyncLog.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryAsyncLog.m; sourceTree = "<group>"; };
20972096
92D957762E05A4F300E20E66 /* SentryAsyncLog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryAsyncLog.h; path = include/SentryAsyncLog.h; sourceTree = "<group>"; };
2098-
92EC54CD2E1EB54B00A10AC2 /* SentryClient+Logs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "SentryClient+Logs.h"; path = "include/SentryClient+Logs.h"; sourceTree = "<group>"; };
20992097
92ECD73B2E05ACDE0063EC10 /* SentryLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLog.swift; sourceTree = "<group>"; };
21002098
92ECD73D2E05AD2B0063EC10 /* SentryLogLevel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogLevel.swift; sourceTree = "<group>"; };
21012099
92ECD73F2E05AD500063EC10 /* SentryLogAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogAttribute.swift; sourceTree = "<group>"; };
@@ -3117,7 +3115,6 @@
31173115
63AA76941EB9C1C200D153DE /* SentryClient.h */,
31183116
63AA75ED1EB8B3C400D153DE /* SentryClient.m */,
31193117
7B85DC1C24EFAFCD007D01D2 /* SentryClient+Private.h */,
3120-
92EC54CD2E1EB54B00A10AC2 /* SentryClient+Logs.h */,
31213118
7B610D5E2512390E00B0B5D9 /* SentrySDK+Private.h */,
31223119
FA6555132E30181B009917BC /* SentrySDKInternal.h */,
31233120
FA6555152E30182B009917BC /* SentrySDKInternal.m */,
@@ -5153,7 +5150,6 @@
51535150
8E7C98312693E1CC00E6336C /* SentryTraceHeader.h in Headers */,
51545151
62C316812B1F2E93000D7031 /* SentryDelayedFramesTracker.h in Headers */,
51555152
92D957772E05A4F300E20E66 /* SentryAsyncLog.h in Headers */,
5156-
92EC54CE2E1EB54B00A10AC2 /* SentryClient+Logs.h in Headers */,
51575153
7B8713AE26415ADF006D6004 /* SentryAppStartTrackingIntegration.h in Headers */,
51585154
7B7D873224864BB900D2ECFF /* SentryCrashMachineContextWrapper.h in Headers */,
51595155
861265F92404EC1500C4AFDE /* SentryArray.h in Headers */,

SentryTestUtils/TestClient.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,8 @@ public class TestClient: SentryClient {
166166
flushInvocations.record(timeout)
167167
}
168168

169-
public var captureLogsDataInvocations = Invocations<(data: Data, count: NSNumber)>()
170-
public override func captureLogsData(_ data: Data, with count: NSNumber) {
171-
captureLogsDataInvocations.record((data, count))
169+
public var captureLogInvocations = Invocations<(log: SentryLog, scope: Scope)>()
170+
public override func capture(log: SentryLog, scope: Scope) {
171+
captureLogInvocations.record((log, scope))
172172
}
173173
}

Sources/Sentry/Public/SentryClient.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
@class SentryOptions;
1313
@class SentryScope;
1414
@class SentryTransaction;
15+
@class SentryLog;
1516

1617
NS_ASSUME_NONNULL_BEGIN
1718

@@ -101,6 +102,14 @@ SENTRY_NO_INIT
101102
- (void)captureFeedback:(SentryFeedback *)feedback
102103
withScope:(SentryScope *)scope NS_SWIFT_NAME(capture(feedback:scope:));
103104

105+
/**
106+
* Captures a log entry and sends it to Sentry.
107+
* @param log The log entry to send to Sentry.
108+
* @param scope The current scope from which to gather contextual information.
109+
*/
110+
- (void)captureLog:(SentryLog *)log
111+
withScope:(SentryScope *)scope NS_SWIFT_NAME(capture(log:scope:));
112+
104113
/**
105114
* Waits synchronously for the SDK to flush out all queued and cached items for up to the specified
106115
* timeout in seconds. If there is no internet connection, the function returns immediately. The SDK

Sources/Sentry/Public/SentryHub.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
@class SentryScope;
1616
@class SentryTransactionContext;
1717
@class SentryUser;
18+
@class SentryLog;
1819

1920
NS_ASSUME_NONNULL_BEGIN
2021
@interface SentryHub : NSObject
@@ -175,6 +176,20 @@ SENTRY_NO_INIT
175176
*/
176177
- (void)captureFeedback:(SentryFeedback *)feedback;
177178

179+
/**
180+
* Captures a log entry and sends it to Sentry.
181+
* @param log The log entry to send to Sentry.
182+
*/
183+
- (void)captureLog:(SentryLog *)log NS_SWIFT_NAME(capture(log:));
184+
185+
/**
186+
* Captures a log entry and sends it to Sentry.
187+
* @param log The log entry to send to Sentry.
188+
* @param scope The scope containing event metadata.
189+
*/
190+
- (void)captureLog:(SentryLog *)log
191+
withScope:(SentryScope *)scope NS_SWIFT_NAME(capture(log:scope:));
192+
178193
/**
179194
* Use this method to modify the Scope of the Hub. The SDK uses the Scope to attach
180195
* contextual data to events.

Sources/Sentry/SentryClient.m

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,14 @@
4646

4747
NS_ASSUME_NONNULL_BEGIN
4848

49-
@interface SentryClient ()
49+
@interface SentryClient () <SentryLogBatcherDelegate>
5050

5151
@property (nonatomic, strong) SentryTransportAdapter *transportAdapter;
5252
@property (nonatomic, strong) SentryDebugImageProvider *debugImageProvider;
5353
@property (nonatomic, strong) id<SentryRandomProtocol> random;
5454
@property (nonatomic, strong) NSLocale *locale;
5555
@property (nonatomic, strong) NSTimeZone *timezone;
56+
@property (nonatomic, strong) SentryLogBatcher *logBatcher;
5657

5758
@end
5859

@@ -149,6 +150,10 @@ - (instancetype)initWithOptions:(SentryOptions *)options
149150
self.locale = locale;
150151
self.timezone = timezone;
151152
self.attachmentProcessors = [[NSMutableArray alloc] init];
153+
self.logBatcher = [[SentryLogBatcher alloc]
154+
initWithOptions:options
155+
dispatchQueue:SentryDependencyContainer.sharedInstance.dispatchQueueWrapper];
156+
self.logBatcher.delegate = self;
152157

153158
// The SDK stores the installationID in a file. The first call requires file IO. To avoid
154159
// executing this on the main thread, we cache the installationID async here.
@@ -654,7 +659,11 @@ - (SentryEvent *_Nullable)prepareEvent:(SentryEvent *)event
654659

655660
- (void)flush:(NSTimeInterval)timeout
656661
{
657-
[self.transportAdapter flush:timeout];
662+
NSTimeInterval captureLogsDuration = [self.logBatcher captureLogs];
663+
// Capturing batched logs should never take long, but we need to fall back to a sane value.
664+
// This is a workaround for experimental logs, until we'll write batched logs to disk,
665+
// to avoid data loss due to crashes. This is a trade-off until then.
666+
[self.transportAdapter flush:fmax(timeout / 2, timeout - captureLogsDuration)];
658667
}
659668

660669
- (void)close
@@ -1111,7 +1120,12 @@ - (void)removeAttachmentProcessor:(id<SentryClientAttachmentProcessor>)attachmen
11111120
return processedAttachments;
11121121
}
11131122

1114-
- (void)captureLogsData:(NSData *)data with:(NSNumber *)itemCount;
1123+
- (void)captureLog:(SentryLog *)log withScope:(SentryScope *)scope
1124+
{
1125+
[self.logBatcher addLog:log scope:scope];
1126+
}
1127+
1128+
- (void)captureLogsData:(NSData *)data with:(NSNumber *)itemCount
11151129
{
11161130
SentryEnvelopeItemHeader *header =
11171131
[[SentryEnvelopeItemHeader alloc] initWithType:SentryEnvelopeItemTypes.log

Sources/Sentry/SentryHub.m

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,20 @@ - (void)captureFeedback:(SentryFeedback *)feedback
539539
}
540540
}
541541

542+
- (void)captureLog:(SentryLog *)log NS_SWIFT_NAME(capture(log:))
543+
{
544+
[self captureLog:log withScope:self.scope];
545+
}
546+
547+
- (void)captureLog:(SentryLog *)log
548+
withScope:(SentryScope *)scope NS_SWIFT_NAME(capture(log:scope:))
549+
{
550+
SentryClient *client = self.client;
551+
if (client != nil) {
552+
[client captureLog:log withScope:self.scope];
553+
}
554+
}
555+
542556
- (void)captureSerializedFeedback:(NSDictionary *)serializedFeedback
543557
withEventId:(NSString *)feedbackEventId
544558
attachments:(NSArray<SentryAttachment *> *)feedbackAttachments

Sources/Sentry/include/SentryClient+Logs.h

Lines changed: 0 additions & 14 deletions
This file was deleted.

Sources/Sentry/include/SentryPrivate.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
#import "SentryANRTrackerV1.h"
2828
#import "SentryANRTrackerV2.h"
2929
#import "SentryAsyncLog.h"
30-
#import "SentryClient+Logs.h"
3130
#import "SentryContinuousProfiler.h"
3231
#import "SentryCrash.h"
3332
#import "SentryCrashDebug.h"

Sources/Swift/Helper/SentrySDK.swift

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,9 @@ import Foundation
3535
if let _logger, _loggerConfigured {
3636
return _logger
3737
}
38-
let hub = SentryDependencyContainerSwiftHelper.currentHub()
39-
var batcher: SentryLogBatcher?
40-
if let client = hub.getClient(), client.options.enableLogs {
41-
batcher = SentryLogBatcher(client: client, dispatchQueue: Dependencies.dispatchQueueWrapper)
42-
}
4338
let logger = SentryLogger(
44-
hub: hub,
45-
dateProvider: Dependencies.dateProvider,
46-
batcher: batcher
39+
hub: SentryDependencyContainerSwiftHelper.currentHub(),
40+
dateProvider: Dependencies.dateProvider
4741
)
4842
_logger = logger
4943
_loggerConfigured = sdkEnabled
@@ -360,18 +354,12 @@ import Foundation
360354
/// - note: This might take slightly longer than the specified timeout if there are many batched logs to capture.
361355
@objc(flush:)
362356
public static func flush(timeout: TimeInterval) {
363-
let captureLogsDuration = captureLogs()
364-
// Capturing batched logs should never take long, but we need to fall back to a sane value.
365-
// This is a workaround for experimental logs, until we'll write batched logs to disk,
366-
// to avoid data loss due to crashes. This is a trade-off until then.
367-
SentrySDKInternal.flush(timeout: max(timeout / 2, timeout - captureLogsDuration))
357+
SentrySDKInternal.flush(timeout: timeout)
368358
}
369359

370360
/// Closes the SDK, uninstalls all the integrations, and calls `flush` with
371361
/// `SentryOptions.shutdownTimeInterval`.
372362
@objc public static func close() {
373-
// Capturing batched logs should never take long, ignore the duration here.
374-
_ = captureLogs()
375363
SentrySDKInternal.close()
376364
}
377365

@@ -430,15 +418,6 @@ import Foundation
430418
private static var _logger: SentryLogger?
431419
// Flag to re-create instance if accessed before SDK init.
432420
private static var _loggerConfigured = false
433-
434-
@discardableResult
435-
private static func captureLogs() -> TimeInterval {
436-
var duration: TimeInterval = 0.0
437-
_loggerLock.synchronized {
438-
duration = _logger?.captureLogs() ?? 0.0
439-
}
440-
return duration
441-
}
442421
}
443422

444423
extension SentryIdWrapper {

0 commit comments

Comments
 (0)