-
-
Notifications
You must be signed in to change notification settings - Fork 372
Structured Logs: Add log APIs to Hub and Client
#6518
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 12 commits
455e640
fe496c6
79f488f
0a4031e
7a38ee2
6f84e05
010294f
f376254
f1e0dc3
e9d6a1e
b8be304
e060a58
ca30a2d
585893a
4d72a5d
4533b76
4446d9f
f913b46
4bd9c2a
5220b71
2eafc00
4197873
b42d510
f00c069
dee5276
11031c7
ebaac6b
0239c61
130e34d
dd00bcb
ca58453
df33907
11f2254
ddc8ad7
1ee870f
1fe6bb7
d7e46ca
33d4912
0dd1af0
0d24147
75d3996
c662522
a8766e9
c6c9bb6
26d91ce
d5e2104
c811a52
7510ff6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,13 +46,14 @@ | |
|
|
||
| NS_ASSUME_NONNULL_BEGIN | ||
|
|
||
| @interface SentryClient () | ||
| @interface SentryClient () <SentryLogBatcherDelegate> | ||
|
|
||
| @property (nonatomic, strong) SentryTransportAdapter *transportAdapter; | ||
| @property (nonatomic, strong) SentryDebugImageProvider *debugImageProvider; | ||
| @property (nonatomic, strong) id<SentryRandomProtocol> random; | ||
| @property (nonatomic, strong) NSLocale *locale; | ||
| @property (nonatomic, strong) NSTimeZone *timezone; | ||
| @property (nonatomic, strong) SentryLogBatcher *logBatcher; | ||
|
|
||
| @end | ||
|
|
||
|
|
@@ -149,6 +150,10 @@ - (instancetype)initWithOptions:(SentryOptions *)options | |
| self.locale = locale; | ||
| self.timezone = timezone; | ||
| self.attachmentProcessors = [[NSMutableArray alloc] init]; | ||
| self.logBatcher = [[SentryLogBatcher alloc] | ||
| initWithOptions:options | ||
| dispatchQueue:SentryDependencyContainer.sharedInstance.dispatchQueueWrapper]; | ||
| self.logBatcher.delegate = self; | ||
denrase marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| // The SDK stores the installationID in a file. The first call requires file IO. To avoid | ||
| // executing this on the main thread, we cache the installationID async here. | ||
|
|
@@ -654,7 +659,11 @@ - (SentryEvent *_Nullable)prepareEvent:(SentryEvent *)event | |
|
|
||
| - (void)flush:(NSTimeInterval)timeout | ||
| { | ||
| [self.transportAdapter flush:timeout]; | ||
| NSTimeInterval captureLogsDuration = [self.logBatcher captureLogs]; | ||
| // Capturing batched logs should never take long, but we need to fall back to a sane value. | ||
| // This is a workaround for experimental logs, until we'll write batched logs to disk, | ||
| // to avoid data loss due to crashes. This is a trade-off until then. | ||
|
||
| [self.transportAdapter flush:fmax(timeout / 2, timeout - captureLogsDuration)]; | ||
denrase marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| - (void)close | ||
|
|
@@ -1111,7 +1120,12 @@ - (void)removeAttachmentProcessor:(id<SentryClientAttachmentProcessor>)attachmen | |
| return processedAttachments; | ||
| } | ||
|
|
||
| - (void)captureLogsData:(NSData *)data with:(NSNumber *)itemCount; | ||
| - (void)captureLog:(SentryLog *)log withScope:(SentryScope *)scope | ||
| { | ||
| [self.logBatcher addLog:log scope:scope]; | ||
| } | ||
|
|
||
| - (void)captureLogsData:(NSData *)data with:(NSNumber *)itemCount | ||
| { | ||
| SentryEnvelopeItemHeader *header = | ||
| [[SentryEnvelopeItemHeader alloc] initWithType:SentryEnvelopeItemTypes.log | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -539,6 +539,20 @@ - (void)captureFeedback:(SentryFeedback *)feedback | |
| } | ||
| } | ||
|
|
||
| - (void)captureLog:(SentryLog *)log NS_SWIFT_NAME(capture(log:)) | ||
| { | ||
| [self captureLog:log withScope:self.scope]; | ||
| } | ||
|
|
||
| - (void)captureLog:(SentryLog *)log | ||
| withScope:(SentryScope *)scope NS_SWIFT_NAME(capture(log:scope:)) | ||
denrase marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| SentryClient *client = self.client; | ||
| if (client != nil) { | ||
| [client captureLog:log withScope:self.scope]; | ||
| } | ||
| } | ||
denrase marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
denrase marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| - (void)captureSerializedFeedback:(NSDictionary *)serializedFeedback | ||
| withEventId:(NSString *)feedbackEventId | ||
| attachments:(NSArray<SentryAttachment *> *)feedbackAttachments | ||
|
|
||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| @_implementationOnly import _SentryPrivate | ||
| import Foundation | ||
|
|
||
| // Swift extensions to provide properly typed log-related APIs for SPM builds. | ||
| // In SPM builds, SentryLog is only forward declared in the Objective-C headers, | ||
| // causing Swift-to-Objective-C bridging issues. These extensions work around that | ||
| // by providing Swift-native methods and properties that use dynamic dispatch internally. | ||
|
|
||
| @objc | ||
| protocol HubSelectors { | ||
| func captureLog(_ log: SentryLog) | ||
| func captureLog(_ log: SentryLog, withScope: Scope) | ||
| } | ||
|
|
||
| @objc | ||
| protocol ClientSelectors { | ||
| func captureLog(_ log: SentryLog, withScope: Scope) | ||
| } | ||
|
|
||
| #if SWIFT_PACKAGE | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @noahsmartin, can you please double-check if this approach works? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is existing code, I just moved it to its own file so it stays on our radar. Circular dependency issue when installing through SPM, before that, the SPM target on CI would not compile. |
||
|
|
||
| /** | ||
| * Use this callback to drop or modify a log before the SDK sends it to Sentry. Return `nil` to | ||
| * drop the log. | ||
| */ | ||
| public typealias SentryBeforeSendLogCallback = (SentryLog) -> SentryLog? | ||
|
|
||
| @objc | ||
| public extension Options { | ||
| /** | ||
| * Use this callback to drop or modify a log before the SDK sends it to Sentry. Return `nil` to | ||
| * drop the log. | ||
| */ | ||
| @objc | ||
| var beforeSendLog: SentryBeforeSendLogCallback? { | ||
| get { return value(forKey: "beforeSendLogDynamic") as? SentryBeforeSendLogCallback } | ||
| set { setValue(newValue, forKey: "beforeSendLogDynamic") } | ||
| } | ||
| } | ||
|
|
||
| @objc | ||
| public extension SentryHub { | ||
| /// Captures a log entry and sends it to Sentry. | ||
| /// - Parameter log: The log entry to send to Sentry. | ||
| /// | ||
| /// This method is provided for SPM builds where the Objective-C `captureLog:` method | ||
| /// may not be properly bridged due to `SentryLog` being defined in Swift. | ||
| func capture(log: SentryLog) { | ||
| // Use dynamic dispatch to work around bridging limitations | ||
| perform(#selector(HubSelectors.captureLog(_:)), with: log) | ||
denrase marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| /// Captures a log entry and sends it to Sentry with a specific scope. | ||
| /// - Parameters: | ||
| /// - log: The log entry to send to Sentry. | ||
| /// - scope: The scope containing event metadata. | ||
| /// | ||
| /// This method is provided for SPM builds where the Objective-C `captureLog:withScope:` method | ||
| /// may not be properly bridged due to `SentryLog` being defined in Swift. | ||
| func capture(log: SentryLog, scope: Scope) { | ||
| // Use dynamic dispatch to work around bridging limitations | ||
| perform(#selector(HubSelectors.captureLog(_:withScope:)), with: log, with: scope) | ||
| } | ||
| } | ||
|
|
||
| /// Extension to provide log capture methods for SPM builds. | ||
| @objc | ||
| public extension SentryClient { | ||
| /// Captures a log entry and sends it to Sentry. | ||
| /// - Parameters: | ||
| /// - log: The log entry to send to Sentry. | ||
| /// - scope: The scope containing event metadata. | ||
| func captureLog(_ log: SentryLog, withScope scope: Scope) { | ||
| // Use dynamic dispatch to work around bridging limitations | ||
| perform(#selector(ClientSelectors.captureLog(_:withScope:)), with: log, with: scope) | ||
| } | ||
| } | ||
|
|
||
| #endif // SWIFT_PACKAGE | ||
Uh oh!
There was an error while loading. Please reload this page.