Skip to content
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
57 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
d9513b1
Merge branch 'main' into denrase/logs-in-hub-and-client
denrase Nov 6, 2025
1031ebc
pe review feedback
denrase Nov 6, 2025
232820f
update pub api
denrase Nov 6, 2025
e8e1d88
Merge branch 'main' into denrase/logs-in-hub-and-client
denrase Nov 7, 2025
b86e969
wanr if no client
denrase Nov 7, 2025
04e1373
use noop delegate instead of internal init
denrase Nov 7, 2025
f48cef0
update cl
denrase Nov 7, 2025
47d0d41
revert to no-op init
denrase Nov 7, 2025
75e78bc
Merge branch 'main' into denrase/logs-in-hub-and-client
denrase Nov 7, 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 @@ -49,6 +49,7 @@
This option is still disabled by default and will be enabled in a future major release.
- Move `enableDataSwizzling` from experimental options to top-level options (#6592). This option remains enabled by default.
- Add `sentry.replay_id` attribute to logs ([#6515](https://github.com/getsentry/sentry-cocoa/pull/6515))
- Structured Logs: Add log APIs to `Hub` and `Client` (#6518)
- Structured Logs: Add `SentrySwiftLog` Integration (#6286)

### Fixes
Expand Down
11 changes: 8 additions & 3 deletions Sentry.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,8 @@
9241AC442EBA39A500E611ED /* SentrySwiftLog.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9241AC132EBA38CB00E611ED /* SentrySwiftLog.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
9241AC4F2EBA3A0C00E611ED /* SentryLogHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9241AC4D2EBA3A0C00E611ED /* SentryLogHandlerTests.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 @@ -739,7 +741,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 @@ -2128,6 +2129,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>"; };
9241AC132EBA38CB00E611ED /* SentrySwiftLog.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SentrySwiftLog.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9241AC1B2EBA38CC00E611ED /* SentrySwiftLogTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SentrySwiftLogTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
9241AC4A2EBA39EE00E611ED /* SentryLogHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogHandler.swift; sourceTree = "<group>"; };
Expand All @@ -2145,7 +2148,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 @@ -2764,6 +2766,7 @@
84B0E0062CD963F9007FB332 /* SentryIconography.swift */,
621F61F02BEA073A005E654F /* SentryEnabledFeaturesBuilder.swift */,
F4FE9DFB2E622CD70014FED5 /* SentryDefaultObjCRuntimeWrapper.swift */,
92622E132EABBDA900ABE7FF /* SentryLog+SPM.swift */,
F4FE9DFC2E622CD70014FED5 /* SentryObjCRuntimeWrapper.swift */,
);
path = Helper;
Expand Down Expand Up @@ -3689,6 +3692,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 @@ -5317,7 +5321,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 @@ -6269,6 +6272,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 @@ -6378,6 +6382,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
8 changes: 5 additions & 3 deletions SentryTestUtils/Sources/TestClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,10 @@ public class TestClient: SentryClientInternal {
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 _swiftCaptureLog(_ log: NSObject, with scope: Scope) {
if let castLog = log as? SentryLog {
captureLogInvocations.record((castLog, scope))
}
}
}
22 changes: 19 additions & 3 deletions Sources/Sentry/SentryClient.m
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,14 @@

NS_ASSUME_NONNULL_BEGIN

@interface SentryClientInternal ()
@interface SentryClientInternal () <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 @@ -114,6 +115,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
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 @@ -619,7 +624,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 in-memory 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)];
}

- (void)close
Expand Down Expand Up @@ -1089,7 +1098,14 @@ - (void)removeAttachmentProcessor:(id<SentryClientAttachmentProcessor>)attachmen
return processedAttachments;
}

- (void)captureLogsData:(NSData *)data with:(NSNumber *)itemCount;
- (void)_swiftCaptureLog:(NSObject *)log withScope:(SentryScope *)scope
{
if ([log isKindOfClass:[SentryLog class]]) {
[self.logBatcher addLog:(SentryLog *)log scope:scope];
}
}

- (void)captureLogsData:(NSData *)data with:(NSNumber *)itemCount
{
SentryEnvelopeItemHeader *header =
[[SentryEnvelopeItemHeader alloc] initWithType:SentryEnvelopeItemTypes.log
Expand Down
34 changes: 33 additions & 1 deletion Sources/Sentry/SentryHub.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

NS_ASSUME_NONNULL_BEGIN

@interface SentryHubInternal ()
@interface SentryHubInternal () <SentryLoggerDelegate>

@property (nullable, atomic, strong) SentryClientInternal *client;
@property (nullable, nonatomic, strong) SentryScope *scope;
Expand Down Expand Up @@ -73,6 +73,10 @@ - (instancetype)initWithClient:(nullable SentryClientInternal *)client
if (_scope) {
[_crashWrapper enrichScope:SENTRY_UNWRAP_NULLABLE(SentryScope, _scope)];
}

__swiftLogger = [[SentryLogger alloc]
initWithDelegate:self
dateProvider:SentryDependencyContainer.sharedInstance.dateProvider];
}

return self;
Expand Down Expand Up @@ -833,6 +837,34 @@ - (void)unregisterSessionListener:(id<SentrySessionListener>)listener
}
}

// SentryLoggerDelegate

- (void)captureLog:(SentryLog *)log
{
SentryClientInternal *client = self.client;
if (client == nil) {
return;
}
#if SENTRY_TARGET_REPLAY_SUPPORTED
NSString *scopeReplayId = self.scope.replayId;
if (scopeReplayId != nil) {
// Session mode: use scope replay ID
[log setAttribute:[[SentryLogAttribute alloc] initWithString:scopeReplayId]
forKey:@"sentry.replay_id"];
} else {
// Buffer mode: check if hub has a session replay ID
NSString *sessionReplayId = [self getSessionReplayId];
if (sessionReplayId != nil) {
[log setAttribute:[[SentryLogAttribute alloc] initWithString:sessionReplayId]
forKey:@"sentry.replay_id"];
[log setAttribute:[[SentryLogAttribute alloc] initWithBoolean:YES]
forKey:@"sentry._internal.replay_is_buffering"];
}
}
#endif
[client _swiftCaptureLog:log withScope:self.scope];
}

#pragma mark - Protected

- (NSArray<NSString *> *)trimmedInstalledIntegrationNames
Expand Down
2 changes: 0 additions & 2 deletions Sources/Sentry/SentrySDKInternal.m
Original file line number Diff line number Diff line change
Expand Up @@ -667,8 +667,6 @@ + (void)close

[SentrySDKInternal setCurrentHub:nil];

[SentrySDK clearLogger];

[SentryDependencyContainer.sharedInstance.crashWrapper stopBinaryImageCache];
[SentryDependencyContainer.sharedInstance.binaryImageCache stop];

Expand Down
2 changes: 2 additions & 0 deletions Sources/Sentry/include/SentryClient+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ NS_ASSUME_NONNULL_BEGIN
- (void)addAttachmentProcessor:(id<SentryClientAttachmentProcessor>)attachmentProcessor;
- (void)removeAttachmentProcessor:(id<SentryClientAttachmentProcessor>)attachmentProcessor;

- (void)_swiftCaptureLog:(NSObject *)log withScope:(SentryScope *)scope;

@end

NS_ASSUME_NONNULL_END
2 changes: 2 additions & 0 deletions Sources/Sentry/include/SentryHub+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ NS_ASSUME_NONNULL_BEGIN

@property (nonatomic, strong) NSMutableArray<id<SentryIntegrationProtocol>> *installedIntegrations;

@property (nonatomic, readonly, strong) NSObject *_swiftLogger;

/**
* Every integration starts with "Sentry" and ends with "Integration". To keep the payload of the
* event small we remove both.
Expand Down
1 change: 0 additions & 1 deletion Sources/Sentry/include/SentryPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,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
31 changes: 31 additions & 0 deletions Sources/Swift/Helper/SentryLog+SPM.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
@_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,
// which causes Swift-to-Objective-C bridging issues. These extensions work around
// that limitation by providing Swift-native methods and properties that use dynamic
// dispatch internally.

#if SWIFT_PACKAGE

/**
* 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") }
}
}

#endif // SWIFT_PACKAGE
61 changes: 8 additions & 53 deletions Sources/Swift/Helper/SentrySDK.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,14 @@ import Foundation

/// API to access Sentry logs
@objc public static var logger: SentryLogger {
return _loggerLock.synchronized {
let sdkEnabled = SentrySDKInternal.isEnabled
if !sdkEnabled {
SentrySDKLog.fatal("Logs called before SentrySDK.start() will be dropped.")
}
if let _logger, _loggerConfigured {
return _logger
}
let hub = SentrySDKInternal.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
)
_logger = logger
_loggerConfigured = sdkEnabled
if !SentrySDKInternal.isEnabled {
SentrySDKLog.fatal("Logs called before SentrySDK.start() will not be sent to Sentry.")
}
if let logger = SentrySDKInternal.currentHub()._swiftLogger as? SentryLogger {
return logger
} else {
SentrySDKLog.fatal("Unable to access configured logger. Logs will not be sent to Sentry.")
return SentryLogger(dateProvider: SentryDependencyContainer.sharedInstance().dateProvider)
}
}

Expand Down Expand Up @@ -360,18 +347,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 @@ -412,32 +393,6 @@ import Foundation
SentrySDKInternal.stopProfiler()
}
#endif

// MARK: Internal

/// - note: Conceptually internal but needs to be marked public with SPI for ObjC visibility
@objc @_spi(Private) public static func clearLogger() {
_loggerLock.synchronized {
_logger = nil
_loggerConfigured = false
}
}

// MARK: Private

private static var _loggerLock = NSLock()
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
}
}

// swiftlint:enable file_length
Loading
Loading