Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 0 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@
- 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 `SentrySwiftLog` Integration (#6286)
- Structured Logs: Add log APIs to `Hub` and `Client` (#6518)

## 8.57.2

Expand Down
11 changes: 3 additions & 8 deletions Sentry.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -725,8 +725,6 @@
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 @@ -741,6 +739,7 @@
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 @@ -2129,8 +2128,6 @@
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 @@ -2148,6 +2145,7 @@
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 @@ -2766,7 +2764,6 @@
84B0E0062CD963F9007FB332 /* SentryIconography.swift */,
621F61F02BEA073A005E654F /* SentryEnabledFeaturesBuilder.swift */,
F4FE9DFB2E622CD70014FED5 /* SentryDefaultObjCRuntimeWrapper.swift */,
92622E132EABBDA900ABE7FF /* SentryLog+SPM.swift */,
F4FE9DFC2E622CD70014FED5 /* SentryObjCRuntimeWrapper.swift */,
);
path = Helper;
Expand Down Expand Up @@ -3692,7 +3689,6 @@
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 @@ -5321,6 +5317,7 @@
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 @@ -6272,7 +6269,6 @@
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 @@ -6382,7 +6378,6 @@
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: 3 additions & 5 deletions SentryTestUtils/Sources/TestClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,8 @@ public class TestClient: SentryClientInternal {
flushInvocations.record(timeout)
}

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))
}
public var captureLogsDataInvocations = Invocations<(data: Data, count: NSNumber)>()
public override func captureLogsData(_ data: Data, with count: NSNumber) {
captureLogsDataInvocations.record((data, count))
}
}
22 changes: 3 additions & 19 deletions Sources/Sentry/SentryClient.m
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,13 @@

NS_ASSUME_NONNULL_BEGIN

@interface SentryClientInternal () <SentryLogBatcherDelegate>
@interface SentryClientInternal ()

@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 @@ -115,10 +114,6 @@ - (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 @@ -624,11 +619,7 @@ - (SentryEvent *_Nullable)prepareEvent:(SentryEvent *)event

- (void)flush:(NSTimeInterval)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)];
[self.transportAdapter flush:timeout];
}

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

- (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
- (void)captureLogsData:(NSData *)data with:(NSNumber *)itemCount;
{
SentryEnvelopeItemHeader *header =
[[SentryEnvelopeItemHeader alloc] initWithType:SentryEnvelopeItemTypes.log
Expand Down
35 changes: 1 addition & 34 deletions 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 () <SentryLoggerDelegate>
@interface SentryHubInternal ()

@property (nullable, atomic, strong) SentryClientInternal *client;
@property (nullable, nonatomic, strong) SentryScope *scope;
Expand Down Expand Up @@ -73,10 +73,6 @@ - (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 @@ -837,35 +833,6 @@ - (void)unregisterSessionListener:(id<SentrySessionListener>)listener
}
}

// SentryLoggerDelegate

- (void)captureLog:(SentryLog *)log
{
SentryClientInternal *client = self.client;
if (client == nil) {
SENTRY_LOG_WARN(@"No client configured. Dropping log.");
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: 2 additions & 0 deletions Sources/Sentry/SentrySDKInternal.m
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,8 @@ + (void)close

[SentrySDKInternal setCurrentHub:nil];

[SentrySDK clearLogger];

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

Expand Down
2 changes: 0 additions & 2 deletions Sources/Sentry/include/SentryClient+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,6 @@ 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: 0 additions & 2 deletions Sources/Sentry/include/SentryHub+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ 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: 1 addition & 0 deletions Sources/Sentry/include/SentryPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#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: 0 additions & 31 deletions Sources/Swift/Helper/SentryLog+SPM.swift

This file was deleted.

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

/// API to access Sentry logs
@objc public static var logger: SentryLogger {
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 _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
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 @@ -347,12 +360,18 @@ 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) {
SentrySDKInternal.flush(timeout: timeout)
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))
}

/// 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 @@ -393,6 +412,32 @@ 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