Skip to content
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
455e640
Support capturing logs in hub and client
denrase Oct 23, 2025
fe496c6
Merge branch 'main' into denrase/logs-in-hub-and-client
denrase Oct 23, 2025
79f488f
fix typo
denrase Oct 23, 2025
0a4031e
update tests
denrase Oct 24, 2025
7a38ee2
add documentation
denrase Oct 24, 2025
6f84e05
Merge branch 'main' into denrase/logs-in-hub-and-client
denrase Oct 24, 2025
010294f
add cl entry
denrase Oct 24, 2025
f376254
update public api
denrase Oct 24, 2025
f1e0dc3
relax flush accuracy
denrase Oct 24, 2025
e9d6a1e
fix SPM circular dependency issue
denrase Oct 24, 2025
b8be304
make new hub/scope selectors available in SPM
denrase Oct 24, 2025
e060a58
provide selector protocols outside of swift pkg if/else
denrase Oct 24, 2025
ca30a2d
use correct scope parameter, add test
denrase Oct 24, 2025
585893a
Merge branch 'main' into denrase/logs-in-hub-and-client
denrase Oct 27, 2025
4d72a5d
Merge branch 'main' into denrase/logs-in-hub-and-client
denrase Oct 28, 2025
4533b76
introduce captureLog dispatcher, handle case where it’ll not work and…
denrase Oct 28, 2025
4446d9f
Merge branch 'main' into denrase/logs-in-hub-and-client
denrase Oct 28, 2025
f913b46
Merge branch 'main' into denrase/logs-in-hub-and-client
denrase Nov 3, 2025
4bd9c2a
Merge branch 'main' into denrase/logs-in-hub-and-client
denrase Nov 3, 2025
5220b71
add test for replayid
denrase Nov 3, 2025
2eafc00
remove NS_SWIFT_NAME
denrase Nov 3, 2025
4197873
Merge branch 'main' into denrase/logs-in-hub-and-client
denrase Nov 3, 2025
b42d510
fix typo
denrase Nov 3, 2025
f00c069
add comment
denrase Nov 3, 2025
dee5276
rename
denrase Nov 3, 2025
11031c7
expose sentrylogger on Hub
denrase Nov 3, 2025
ebaac6b
Merge branch 'main' into denrase/logs-in-hub-and-client
denrase Nov 3, 2025
0239c61
use cast to exose logger
denrase Nov 4, 2025
130e34d
update test
denrase Nov 4, 2025
dd00bcb
update access to fw decalered log APIs
denrase Nov 4, 2025
ca58453
Merge branch 'main' into denrase/logs-in-hub-and-client
denrase Nov 4, 2025
df33907
cleanup
denrase Nov 4, 2025
11f2254
remove mention of logs in beta
denrase Nov 4, 2025
ddc8ad7
use _swiftLogger in hub swift
denrase Nov 4, 2025
1ee870f
cleanup
denrase Nov 4, 2025
1fe6bb7
remove redundant test
denrase Nov 4, 2025
d7e46ca
update public api
denrase Nov 4, 2025
33d4912
Merge branch 'main' into denrase/logs-in-hub-and-client
denrase Nov 4, 2025
0dd1af0
Merge branch 'main' into denrase/logs-in-hub-and-client
denrase Nov 4, 2025
0d24147
Merge branch 'main' into denrase/logs-in-hub-and-client
denrase Nov 4, 2025
75d3996
Add possibility to mutate log attributes from ObjC, Add heleper metho…
denrase Nov 4, 2025
c662522
Move log abtcher delegate to ctor and make it private
denrase Nov 4, 2025
a8766e9
make teh delegate non-nil
denrase Nov 4, 2025
c6c9bb6
add comment
denrase Nov 4, 2025
26d91ce
Merge branch 'main' into denrase/logs-in-hub-and-client
denrase Nov 4, 2025
d5e2104
Merge branch 'main' into denrase/logs-in-hub-and-client
denrase Nov 4, 2025
c811a52
update public api
denrase Nov 4, 2025
7510ff6
Merge branch 'denrase/logs-in-hub-and-client' of github.com:getsentry…
denrase Nov 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

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

### Fixes

Expand Down
12 changes: 8 additions & 4 deletions Sentry.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,8 @@
92235CAE2E15549C00865983 /* SentryLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92235CAD2E15549C00865983 /* SentryLogger.swift */; };
92235CB02E155B2600865983 /* SentryLoggerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92235CAF2E155B2600865983 /* SentryLoggerTests.swift */; };
925824C22CB5897700C9B20B /* SentrySessionReplayIntegration-Hybrid.h in Headers */ = {isa = PBXBuildFile; fileRef = D80382BE2C09C6FD0090E048 /* SentrySessionReplayIntegration-Hybrid.h */; settings = {ATTRIBUTES = (Private, ); }; };
92622E092EABB71000ABE7FF /* SentryLogSPMTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92622E082EABB71000ABE7FF /* SentryLogSPMTests.swift */; };
92622E142EABBDA900ABE7FF /* SentryLog+SPM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92622E132EABBDA900ABE7FF /* SentryLog+SPM.swift */; };
9264E1EB2E2E385E00B077CF /* SentryLogMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9264E1EA2E2E385B00B077CF /* SentryLogMessage.swift */; };
9264E1ED2E2E397C00B077CF /* SentryLogMessageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9264E1EC2E2E397400B077CF /* SentryLogMessageTests.swift */; };
92672BB629C9A2A9006B021C /* SentryBreadcrumb+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 92672BB529C9A2A9006B021C /* SentryBreadcrumb+Private.h */; settings = {ATTRIBUTES = (Private, ); }; };
Expand All @@ -734,7 +736,6 @@
92D957732E05A44600E20E66 /* SentryAsyncLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 92D957722E05A44600E20E66 /* SentryAsyncLog.m */; };
92D957772E05A4F300E20E66 /* SentryAsyncLog.h in Headers */ = {isa = PBXBuildFile; fileRef = 92D957762E05A4F300E20E66 /* SentryAsyncLog.h */; };
92E5F3D62CDBB3BF00B7AD98 /* SentrySampling.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8C57A525EEFC42001CEEFA /* SentrySampling.h */; };
92EC54CE2E1EB54B00A10AC2 /* SentryClient+Logs.h in Headers */ = {isa = PBXBuildFile; fileRef = 92EC54CD2E1EB54B00A10AC2 /* SentryClient+Logs.h */; };
92ECD7202E05A7DF0063EC10 /* SentryLogC.h in Headers */ = {isa = PBXBuildFile; fileRef = D8AE48B12C5786AA0092A2A6 /* SentryLogC.h */; settings = {ATTRIBUTES = (Private, ); }; };
92ECD73C2E05ACE00063EC10 /* SentryLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92ECD73B2E05ACDE0063EC10 /* SentryLog.swift */; };
92ECD73E2E05AD320063EC10 /* SentryLogLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92ECD73D2E05AD2B0063EC10 /* SentryLogLevel.swift */; };
Expand Down Expand Up @@ -2082,6 +2083,8 @@
92235CAB2E15369900865983 /* SentryLogBatcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogBatcher.swift; sourceTree = "<group>"; };
92235CAD2E15549C00865983 /* SentryLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogger.swift; sourceTree = "<group>"; };
92235CAF2E155B2600865983 /* SentryLoggerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLoggerTests.swift; sourceTree = "<group>"; };
92622E082EABB71000ABE7FF /* SentryLogSPMTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogSPMTests.swift; sourceTree = "<group>"; };
92622E132EABBDA900ABE7FF /* SentryLog+SPM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SentryLog+SPM.swift"; sourceTree = "<group>"; };
9264E1EA2E2E385B00B077CF /* SentryLogMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogMessage.swift; sourceTree = "<group>"; };
9264E1EC2E2E397400B077CF /* SentryLogMessageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogMessageTests.swift; sourceTree = "<group>"; };
92672BB529C9A2A9006B021C /* SentryBreadcrumb+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "SentryBreadcrumb+Private.h"; path = "include/HybridPublic/SentryBreadcrumb+Private.h"; sourceTree = "<group>"; };
Expand All @@ -2095,7 +2098,6 @@
92B6BDAC2E05B9F700D538B3 /* SentryLogTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogTests.swift; sourceTree = "<group>"; };
92D957722E05A44600E20E66 /* SentryAsyncLog.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryAsyncLog.m; sourceTree = "<group>"; };
92D957762E05A4F300E20E66 /* SentryAsyncLog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryAsyncLog.h; path = include/SentryAsyncLog.h; sourceTree = "<group>"; };
92EC54CD2E1EB54B00A10AC2 /* SentryClient+Logs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "SentryClient+Logs.h"; path = "include/SentryClient+Logs.h"; sourceTree = "<group>"; };
92ECD73B2E05ACDE0063EC10 /* SentryLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLog.swift; sourceTree = "<group>"; };
92ECD73D2E05AD2B0063EC10 /* SentryLogLevel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogLevel.swift; sourceTree = "<group>"; };
92ECD73F2E05AD500063EC10 /* SentryLogAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogAttribute.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2689,6 +2691,7 @@
84B0E0062CD963F9007FB332 /* SentryIconography.swift */,
621F61F02BEA073A005E654F /* SentryEnabledFeaturesBuilder.swift */,
F4FE9DFB2E622CD70014FED5 /* SentryDefaultObjCRuntimeWrapper.swift */,
92622E132EABBDA900ABE7FF /* SentryLog+SPM.swift */,
F4FE9DFC2E622CD70014FED5 /* SentryObjCRuntimeWrapper.swift */,
);
path = Helper;
Expand Down Expand Up @@ -3117,7 +3120,6 @@
63AA76941EB9C1C200D153DE /* SentryClient.h */,
63AA75ED1EB8B3C400D153DE /* SentryClient.m */,
7B85DC1C24EFAFCD007D01D2 /* SentryClient+Private.h */,
92EC54CD2E1EB54B00A10AC2 /* SentryClient+Logs.h */,
7B610D5E2512390E00B0B5D9 /* SentrySDK+Private.h */,
FA6555132E30181B009917BC /* SentrySDKInternal.h */,
FA6555152E30182B009917BC /* SentrySDKInternal.m */,
Expand Down Expand Up @@ -3612,6 +3614,7 @@
F4A930242E661856006DA6EF /* SentryMobileProvisionParserTests.swift */,
D4F7BD7C2E4373BB004A2D77 /* SentryLevelMapperTests.swift */,
D8AE48BE2C578D540092A2A6 /* SentrySDKLog.swift */,
92622E082EABB71000ABE7FF /* SentryLogSPMTests.swift */,
849AC3FF29E0C1FF00889C16 /* SentryFormatterTests.swift */,
7B88F30324BC8E6500ADF90A /* SentrySerializationTests.swift */,
62F4DDA02C04CB9700588890 /* SentryBaggageSerializationTests.swift */,
Expand Down Expand Up @@ -5153,7 +5156,6 @@
8E7C98312693E1CC00E6336C /* SentryTraceHeader.h in Headers */,
62C316812B1F2E93000D7031 /* SentryDelayedFramesTracker.h in Headers */,
92D957772E05A4F300E20E66 /* SentryAsyncLog.h in Headers */,
92EC54CE2E1EB54B00A10AC2 /* SentryClient+Logs.h in Headers */,
7B8713AE26415ADF006D6004 /* SentryAppStartTrackingIntegration.h in Headers */,
7B7D873224864BB900D2ECFF /* SentryCrashMachineContextWrapper.h in Headers */,
861265F92404EC1500C4AFDE /* SentryArray.h in Headers */,
Expand Down Expand Up @@ -6033,6 +6035,7 @@
7B14089824878F950035403D /* SentryCrashStackEntryMapper.m in Sources */,
D8BC28C82BFF5EBB0054DA4D /* SentryTouchTracker.swift in Sources */,
63FE711720DA4C1000CDBAE8 /* SentryCrashStackCursor_Backtrace.c in Sources */,
92622E142EABBDA900ABE7FF /* SentryLog+SPM.swift in Sources */,
FA3A42722E1C5F9B00A08C39 /* SentryNSNotificationCenterWrapper.swift in Sources */,
63FE70CB20DA4C1000CDBAE8 /* SentryCrashReportFixer.c in Sources */,
F4A930232E65FDBF006DA6EF /* SentryMobileProvisionParser.swift in Sources */,
Expand Down Expand Up @@ -6141,6 +6144,7 @@
7BE3C78724472E9800A38442 /* TestRequestManager.swift in Sources */,
63FE722220DA66EC00CDBAE8 /* SentryCrashJSONCodec_Tests.m in Sources */,
7B0A5452252311CE00A71716 /* SentryBreadcrumbTests.swift in Sources */,
92622E092EABB71000ABE7FF /* SentryLogSPMTests.swift in Sources */,
7BE3C7752445C82300A38442 /* SentryCurrentDateTests.swift in Sources */,
7B3398672459C4AE00BD9C96 /* SentryEnvelopeRateLimitTests.swift in Sources */,
8EA9AF492665AC48002771B4 /* SentryPerformanceTrackerTests.swift in Sources */,
Expand Down
6 changes: 3 additions & 3 deletions SentryTestUtils/TestClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ public class TestClient: SentryClient {
flushInvocations.record(timeout)
}

public var captureLogsDataInvocations = Invocations<(data: Data, count: NSNumber)>()
public override func captureLogsData(_ data: Data, with count: NSNumber) {
captureLogsDataInvocations.record((data, count))
public var captureLogInvocations = Invocations<(log: SentryLog, scope: Scope)>()
public override func capture(log: SentryLog, scope: Scope) {
captureLogInvocations.record((log, scope))
}
}
9 changes: 9 additions & 0 deletions Sources/Sentry/Public/SentryClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
@class SentryOptions;
@class SentryScope;
@class SentryTransaction;
@class SentryLog;

NS_ASSUME_NONNULL_BEGIN

Expand Down Expand Up @@ -101,6 +102,14 @@ SENTRY_NO_INIT
- (void)captureFeedback:(SentryFeedback *)feedback
withScope:(SentryScope *)scope NS_SWIFT_NAME(capture(feedback:scope:));

/**
* Captures a log entry and sends it to Sentry.
* @param log The log entry to send to Sentry.
* @param scope The current scope from which to gather contextual information.
*/
- (void)captureLog:(SentryLog *)log
withScope:(SentryScope *)scope NS_SWIFT_NAME(capture(log:scope:));

/**
* Waits synchronously for the SDK to flush out all queued and cached items for up to the specified
* timeout in seconds. If there is no internet connection, the function returns immediately. The SDK
Expand Down
15 changes: 15 additions & 0 deletions Sources/Sentry/Public/SentryHub.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
@class SentryScope;
@class SentryTransactionContext;
@class SentryUser;
@class SentryLog;

NS_ASSUME_NONNULL_BEGIN
@interface SentryHub : NSObject
Expand Down Expand Up @@ -175,6 +176,20 @@ SENTRY_NO_INIT
*/
- (void)captureFeedback:(SentryFeedback *)feedback;

/**
* Captures a log entry and sends it to Sentry.
* @param log The log entry to send to Sentry.
*/
- (void)captureLog:(SentryLog *)log NS_SWIFT_NAME(capture(log:));

/**
* Captures a log entry and sends it to Sentry.
* @param log The log entry to send to Sentry.
* @param scope The scope containing event metadata.
*/
- (void)captureLog:(SentryLog *)log
withScope:(SentryScope *)scope NS_SWIFT_NAME(capture(log:scope:));

/**
* Use this method to modify the Scope of the Hub. The SDK uses the Scope to attach
* contextual data to events.
Expand Down
20 changes: 17 additions & 3 deletions Sources/Sentry/SentryClient.m
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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;

// 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.
Expand Down Expand Up @@ -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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

l: Logs aren't experimental anymore with V9. We're close to merging the develop docs PR for logs for crashes getsentry/sentry-docs#15274. Maybe we could link this PR already or create an issue for logs for crashes and link it here.

[self.transportAdapter flush:fmax(timeout / 2, timeout - captureLogsDuration)];
}

- (void)close
Expand Down Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions Sources/Sentry/SentryHub.m
Original file line number Diff line number Diff line change
Expand Up @@ -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:))
{
SentryClient *client = self.client;
if (client != nil) {
[client captureLog:log withScope:self.scope];
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Replay ID Handling Causes Duplicate Log Attributes

It looks like the captureLog:withScope: method has a couple of issues. It uses self.scope.replayId instead of the scope parameter for replay IDs, and it directly modifies the input log object's attributes. This modification, which adds replay information, then gets processed a second time by SentryLogBatcher.addLog, potentially leading to duplicate or conflicting replay attributes.

Fix in Cursor Fix in Web


- (void)captureSerializedFeedback:(NSDictionary *)serializedFeedback
withEventId:(NSString *)feedbackEventId
attachments:(NSArray<SentryAttachment *> *)feedbackAttachments
Expand Down
14 changes: 0 additions & 14 deletions Sources/Sentry/include/SentryClient+Logs.h

This file was deleted.

1 change: 0 additions & 1 deletion Sources/Sentry/include/SentryPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
#import "SentryANRTrackerV1.h"
#import "SentryANRTrackerV2.h"
#import "SentryAsyncLog.h"
#import "SentryClient+Logs.h"
#import "SentryContinuousProfiler.h"
#import "SentryCrash.h"
#import "SentryCrashDebug.h"
Expand Down
79 changes: 79 additions & 0 deletions Sources/Swift/Helper/SentryLog+SPM.swift
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@noahsmartin, can you please double-check if this approach works?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The 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)
}

/// 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
27 changes: 3 additions & 24 deletions Sources/Swift/Helper/SentrySDK.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,9 @@ import Foundation
if let _logger, _loggerConfigured {
return _logger
}
let hub = SentryDependencyContainerSwiftHelper.currentHub()
var batcher: SentryLogBatcher?
if let client = hub.getClient(), client.options.enableLogs {
batcher = SentryLogBatcher(client: client, dispatchQueue: Dependencies.dispatchQueueWrapper)
}
let logger = SentryLogger(
hub: hub,
dateProvider: Dependencies.dateProvider,
batcher: batcher
hub: SentryDependencyContainerSwiftHelper.currentHub(),
dateProvider: Dependencies.dateProvider
)
_logger = logger
_loggerConfigured = sdkEnabled
Expand Down Expand Up @@ -360,18 +354,12 @@ import Foundation
/// - note: This might take slightly longer than the specified timeout if there are many batched logs to capture.
@objc(flush:)
public static func flush(timeout: TimeInterval) {
let captureLogsDuration = 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.
SentrySDKInternal.flush(timeout: max(timeout / 2, timeout - captureLogsDuration))
SentrySDKInternal.flush(timeout: timeout)
}

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

Expand Down Expand Up @@ -430,15 +418,6 @@ import Foundation
private static var _logger: SentryLogger?
// Flag to re-create instance if accessed before SDK init.
private static var _loggerConfigured = false

@discardableResult
private static func captureLogs() -> TimeInterval {
var duration: TimeInterval = 0.0
_loggerLock.synchronized {
duration = _logger?.captureLogs() ?? 0.0
}
return duration
}
}

extension SentryIdWrapper {
Expand Down
Loading
Loading