diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index 8014fa5f642..e40b0ce161b 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -11,7 +11,6 @@ 03BCC38A27E1BF49003232C7 /* SentryTime.h in Headers */ = {isa = PBXBuildFile; fileRef = 03BCC38927E1BF49003232C7 /* SentryTime.h */; }; 03BCC38C27E1C01A003232C7 /* SentryTime.mm in Sources */ = {isa = PBXBuildFile; fileRef = 03BCC38B27E1C01A003232C7 /* SentryTime.mm */; }; 03BCC38E27E2A377003232C7 /* SentryProfilingConditionals.h in Headers */ = {isa = PBXBuildFile; fileRef = 03BCC38D27E2A377003232C7 /* SentryProfilingConditionals.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 03F84D1D27DD414C008FE43F /* SentryProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 03F84D1127DD414C008FE43F /* SentryProfiler.h */; }; 03F84D1E27DD414C008FE43F /* SentryBacktrace.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 03F84D1227DD414C008FE43F /* SentryBacktrace.hpp */; }; 03F84D1F27DD414C008FE43F /* SentryAsyncSafeLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = 03F84D1327DD414C008FE43F /* SentryAsyncSafeLogging.h */; }; 03F84D2027DD414C008FE43F /* SentryStackBounds.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 03F84D1427DD414C008FE43F /* SentryStackBounds.hpp */; }; @@ -672,7 +671,6 @@ 8489B8882A5F7905009A055A /* SentryThreadWrapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8489B8872A5F7905009A055A /* SentryThreadWrapperTests.swift */; }; 849AC40029E0C1FF00889C16 /* SentryFormatterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849AC3FF29E0C1FF00889C16 /* SentryFormatterTests.swift */; }; 84A5D75B29D5170700388BFA /* TimeInterval+Sentry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A5D75A29D5170700388BFA /* TimeInterval+Sentry.swift */; }; - 84A888FD28D9B11700C51DFD /* SentryProfiler+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 84A888FC28D9B11700C51DFD /* SentryProfiler+Private.h */; }; 84A8891C28DBD28900C51DFD /* SentryDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 84A8891A28DBD28900C51DFD /* SentryDevice.h */; }; 84A8891D28DBD28900C51DFD /* SentryDevice.mm in Sources */ = {isa = PBXBuildFile; fileRef = 84A8891B28DBD28900C51DFD /* SentryDevice.mm */; }; 84A8892128DBD8D600C51DFD /* SentryDeviceTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 84A8892028DBD8D600C51DFD /* SentryDeviceTests.mm */; }; @@ -926,7 +924,6 @@ 03BCC38927E1BF49003232C7 /* SentryTime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryTime.h; path = Sources/Sentry/include/SentryTime.h; sourceTree = SOURCE_ROOT; }; 03BCC38B27E1C01A003232C7 /* SentryTime.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = SentryTime.mm; path = Sources/Sentry/SentryTime.mm; sourceTree = SOURCE_ROOT; }; 03BCC38D27E2A377003232C7 /* SentryProfilingConditionals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryProfilingConditionals.h; path = ../Public/SentryProfilingConditionals.h; sourceTree = ""; }; - 03F84D1127DD414C008FE43F /* SentryProfiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryProfiler.h; path = Sources/Sentry/include/SentryProfiler.h; sourceTree = SOURCE_ROOT; }; 03F84D1227DD414C008FE43F /* SentryBacktrace.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SentryBacktrace.hpp; path = Sources/Sentry/include/SentryBacktrace.hpp; sourceTree = SOURCE_ROOT; }; 03F84D1327DD414C008FE43F /* SentryAsyncSafeLogging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryAsyncSafeLogging.h; path = Sources/Sentry/include/SentryAsyncSafeLogging.h; sourceTree = SOURCE_ROOT; }; 03F84D1427DD414C008FE43F /* SentryStackBounds.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SentryStackBounds.hpp; path = Sources/Sentry/include/SentryStackBounds.hpp; sourceTree = SOURCE_ROOT; }; @@ -1605,6 +1602,7 @@ 840B7EEE2BBF2B23008B8120 /* .ruby-version */ = {isa = PBXFileReference; lastKnownFileType = text; path = ".ruby-version"; sourceTree = ""; }; 840B7EEF2BBF2B2B008B8120 /* .spi.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .spi.yml; sourceTree = ""; }; 840B7EF02BBF2B5F008B8120 /* MIGRATION.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = MIGRATION.md; sourceTree = ""; }; + 840B7EF22BBF83DF008B8120 /* SentryProfiler+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "SentryProfiler+Private.h"; path = "Sources/Sentry/include/SentryProfiler+Private.h"; sourceTree = SOURCE_ROOT; }; 8419C0C328C1889D001C8259 /* SentryProfilerSwiftTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryProfilerSwiftTests.swift; sourceTree = ""; }; 84281C422A578E5600EE88F2 /* SentryProfilerState.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SentryProfilerState.mm; sourceTree = ""; }; 84281C442A57905700EE88F2 /* SentrySample.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentrySample.h; path = ../include/SentrySample.h; sourceTree = ""; }; @@ -1663,7 +1661,6 @@ 849472842971C41A002603DE /* SentryNSTimerFactoryTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryNSTimerFactoryTest.swift; sourceTree = ""; }; 849AC3FF29E0C1FF00889C16 /* SentryFormatterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SentryFormatterTests.swift; sourceTree = ""; }; 84A5D75A29D5170700388BFA /* TimeInterval+Sentry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TimeInterval+Sentry.swift"; sourceTree = ""; }; - 84A888FC28D9B11700C51DFD /* SentryProfiler+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "SentryProfiler+Private.h"; path = "Sources/Sentry/include/SentryProfiler+Private.h"; sourceTree = SOURCE_ROOT; }; 84A8891A28DBD28900C51DFD /* SentryDevice.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryDevice.h; path = include/SentryDevice.h; sourceTree = ""; }; 84A8891B28DBD28900C51DFD /* SentryDevice.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SentryDevice.mm; sourceTree = ""; }; 84A8892028DBD8D600C51DFD /* SentryDeviceTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SentryDeviceTests.mm; sourceTree = ""; }; @@ -3286,9 +3283,8 @@ 8454CF8B293EAF9A006AC140 /* SentryMetricProfiler.mm */, 84AF45A429A7FFA500FBB177 /* SentryProfiledTracerConcurrency.h */, 84AF45A529A7FFA500FBB177 /* SentryProfiledTracerConcurrency.mm */, - 03F84D1127DD414C008FE43F /* SentryProfiler.h */, + 840B7EF22BBF83DF008B8120 /* SentryProfiler+Private.h */, 03F84D2B27DD4191008FE43F /* SentryProfiler.mm */, - 84A888FC28D9B11700C51DFD /* SentryProfiler+Private.h */, 0354A22A2A134D9C003C3A04 /* SentryProfilerState.h */, 84281C422A578E5600EE88F2 /* SentryProfilerState.mm */, 84281C642A57D36100EE88F2 /* SentryProfilerState+ObjCpp.h */, @@ -3647,7 +3643,6 @@ 8E4E7C7425DAAB49006AB9E2 /* SentrySpanProtocol.h in Headers */, 8EC4CF4A25C38DAA0093DEE9 /* SentrySpanStatus.h in Headers */, 8ECC673D25C23996000E2BF6 /* SentrySpanId.h in Headers */, - 03F84D1D27DD414C008FE43F /* SentryProfiler.h in Headers */, 03F84D2227DD414C008FE43F /* SentryStackFrame.hpp in Headers */, 8ECC673E25C23996000E2BF6 /* SentrySpanContext.h in Headers */, 8ECC674025C23996000E2BF6 /* SentryTransactionContext.h in Headers */, @@ -3712,7 +3707,6 @@ 62862B1C2B1DDBC8009B16E3 /* SentryDelayedFrame.h in Headers */, 627E7589299F6FE40085504D /* SentryInternalDefines.h in Headers */, 7BE3C77B2446111500A38442 /* SentryRateLimitParser.h in Headers */, - 84A888FD28D9B11700C51DFD /* SentryProfiler+Private.h in Headers */, 7D0637032382B34300B30749 /* SentryScope.h in Headers */, 03F84D2727DD414C008FE43F /* SentryMachLogging.hpp in Headers */, 63295AF51EF3C7DB002D4490 /* SentryNSDictionarySanitize.h in Headers */, diff --git a/Sources/Sentry/PrivateSentrySDKOnly.mm b/Sources/Sentry/PrivateSentrySDKOnly.mm index f5a00f8707d..07d68dfdf70 100644 --- a/Sources/Sentry/PrivateSentrySDKOnly.mm +++ b/Sources/Sentry/PrivateSentrySDKOnly.mm @@ -10,7 +10,7 @@ #import "SentryMeta.h" #import "SentryOptions.h" #import "SentryProfiledTracerConcurrency.h" -#import "SentryProfiler.h" +#import "SentryProfiler+Private.h" #import "SentrySDK+Private.h" #import "SentrySerialization.h" #import "SentrySwift.h" diff --git a/Sources/Sentry/Profiling/SentryLaunchProfiling.m b/Sources/Sentry/Profiling/SentryLaunchProfiling.m index a526ab64ea2..8fbf006db56 100644 --- a/Sources/Sentry/Profiling/SentryLaunchProfiling.m +++ b/Sources/Sentry/Profiling/SentryLaunchProfiling.m @@ -8,7 +8,7 @@ # import "SentryInternalDefines.h" # import "SentryLog.h" # import "SentryOptions.h" -# import "SentryProfiler.h" +# import "SentryProfiler+Private.h" # import "SentryRandom.h" # import "SentrySamplerDecision.h" # import "SentrySampling.h" diff --git a/Sources/Sentry/SentryFramesTracker.m b/Sources/Sentry/SentryFramesTracker.m index be580efa019..ab68258d1ea 100644 --- a/Sources/Sentry/SentryFramesTracker.m +++ b/Sources/Sentry/SentryFramesTracker.m @@ -8,7 +8,7 @@ # import "SentryDispatchQueueWrapper.h" # import "SentryDisplayLinkWrapper.h" # import "SentryLog.h" -# import "SentryProfiler.h" +# import "SentryProfiler+Private.h" # import "SentryProfilingConditionals.h" # import "SentrySwift.h" # import "SentryTime.h" diff --git a/Sources/Sentry/SentryTracer.m b/Sources/Sentry/SentryTracer.m index b8714fb649b..1ee47db2095 100644 --- a/Sources/Sentry/SentryTracer.m +++ b/Sources/Sentry/SentryTracer.m @@ -36,7 +36,7 @@ #if SENTRY_TARGET_PROFILING_SUPPORTED # import "SentryLaunchProfiling.h" # import "SentryProfiledTracerConcurrency.h" -# import "SentryProfiler.h" +# import "SentryProfiler+Private.h" #endif // SENTRY_TARGET_PROFILING_SUPPORTED #if SENTRY_HAS_UIKIT diff --git a/Sources/Sentry/include/SentryProfiler+Private.h b/Sources/Sentry/include/SentryProfiler+Private.h index 5eaee6d21d0..41235225837 100644 --- a/Sources/Sentry/include/SentryProfiler+Private.h +++ b/Sources/Sentry/include/SentryProfiler+Private.h @@ -1,38 +1,106 @@ -#import "SentryProfiler.h" #import "SentryProfilingConditionals.h" #if SENTRY_TARGET_PROFILING_SUPPORTED -@class SentryDebugMeta; -@class SentryId; -@class SentryProfilerState; -@class SentrySample; +# import "SentryCompiler.h" +# import "SentrySpan.h" +# import + +@class SentryEnvelopeItem; @class SentryHub; +@class SentryProfilerState; +@class SentryTransaction; + # if SENTRY_HAS_UIKIT +@class SentryFramesTracker; @class SentryScreenFrames; # endif // SENTRY_HAS_UIKIT -@class SentryTransaction; + +typedef NS_ENUM(NSUInteger, SentryProfilerTruncationReason) { + SentryProfilerTruncationReasonNormal, + SentryProfilerTruncationReasonTimeout, + SentryProfilerTruncationReasonAppMovedToBackground, +}; NS_ASSUME_NONNULL_BEGIN -NSMutableDictionary *serializedProfileData( - NSDictionary *profileData, uint64_t startSystemTime, uint64_t endSystemTime, - NSString *truncationReason, NSDictionary *serializedMetrics, - NSArray *debugMeta, SentryHub *hub -# if SENTRY_HAS_UIKIT - , - SentryScreenFrames *gpuData -# endif // SENTRY_HAS_UIKIT -); +SENTRY_EXTERN const int kSentryProfilerFrequencyHz; + +SENTRY_EXTERN NSString *const kSentryProfilerSerializationKeySlowFrameRenders; +SENTRY_EXTERN NSString *const kSentryProfilerSerializationKeyFrozenFrameRenders; +SENTRY_EXTERN NSString *const kSentryProfilerSerializationKeyFrameRates; + +SENTRY_EXTERN_C_BEGIN -@interface -SentryProfiler () +/** + * Disable profiling when running with TSAN because it produces a TSAN false positive, similar to + * the situation described here: https://github.com/envoyproxy/envoy/issues/2561 + */ +BOOL threadSanitizerIsPresent(void); + +NSString *profilerTruncationReasonName(SentryProfilerTruncationReason reason); + +SENTRY_EXTERN_C_END + +/** + * A wrapper around the low-level components used to gather sampled backtrace profiles. + * @warning A main assumption is that profile start/stop must be contained within range of time of + * the first concurrent transaction's start time and last one's end time. + */ +@interface SentryProfiler : NSObject + +@property (strong, nonatomic) SentryId *profilerId; @property (strong, nonatomic) SentryProfilerState *_state; + # if SENTRY_HAS_UIKIT @property (strong, nonatomic) SentryScreenFrames *_screenFrameData; # endif // SENTRY_HAS_UIKIT +/** + * Start a profiler, if one isn't already running. + */ ++ (BOOL)startWithTracer:(SentryId *)traceId; + +/** + * Stop the profiler if it is running. + */ +- (void)stopForReason:(SentryProfilerTruncationReason)reason; + +/** + * Whether the profiler instance is currently running. If not, then it probably timed out or aborted + * due to app backgrounding and is being kept alive while its associated transactions finish so they + * can query for its profile data. */ +- (BOOL)isRunning; + +/** + * Whether there is any profiler that is currently running. A convenience method to query for this + * information from other SDK components that don't have access to specific @c SentryProfiler + * instances. + */ ++ (BOOL)isCurrentlyProfiling; + +/** + * Immediately record a sample of profiling metrics. Helps get full coverage of concurrent spans + * when they're ended. + */ ++ (void)recordMetrics; + +/** + * Given a transaction, return an envelope item containing any corresponding profile data to be + * attached to the transaction envelope. + * */ ++ (nullable SentryEnvelopeItem *)createProfilingEnvelopeItemForTransaction: + (SentryTransaction *)transaction + startTimestamp:startTimestamp; + +/** + * Collect profile data corresponding with the given traceId and time period. + * */ ++ (nullable NSMutableDictionary *)collectProfileBetween:(uint64_t)startSystemTime + and:(uint64_t)endSystemTime + forTrace:(SentryId *)traceId + onHub:(SentryHub *)hub; @end NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryProfiler.h b/Sources/Sentry/include/SentryProfiler.h deleted file mode 100644 index cfd976d02bc..00000000000 --- a/Sources/Sentry/include/SentryProfiler.h +++ /dev/null @@ -1,98 +0,0 @@ -#import "SentryCompiler.h" -#import "SentryProfilingConditionals.h" -#import "SentrySpan.h" -#import - -@class SentryEnvelopeItem; -#if SENTRY_HAS_UIKIT -@class SentryFramesTracker; -#endif // SENTRY_HAS_UIKIT -@class SentryTransaction; -@class SentryHub; - -#if SENTRY_TARGET_PROFILING_SUPPORTED - -typedef NS_ENUM(NSUInteger, SentryProfilerTruncationReason) { - SentryProfilerTruncationReasonNormal, - SentryProfilerTruncationReasonTimeout, - SentryProfilerTruncationReasonAppMovedToBackground, -}; - -NS_ASSUME_NONNULL_BEGIN - -SENTRY_EXTERN const int kSentryProfilerFrequencyHz; - -SENTRY_EXTERN NSString *const kSentryProfilerSerializationKeySlowFrameRenders; -SENTRY_EXTERN NSString *const kSentryProfilerSerializationKeyFrozenFrameRenders; -SENTRY_EXTERN NSString *const kSentryProfilerSerializationKeyFrameRates; - -SENTRY_EXTERN_C_BEGIN - -/** - * Disable profiling when running with TSAN because it produces a TSAN false positive, similar to - * the situation described here: https://github.com/envoyproxy/envoy/issues/2561 - */ -BOOL threadSanitizerIsPresent(void); - -NSString *profilerTruncationReasonName(SentryProfilerTruncationReason reason); - -SENTRY_EXTERN_C_END - -/** - * A wrapper around the low-level components used to gather sampled backtrace profiles. - * @warning A main assumption is that profile start/stop must be contained within range of time of - * the first concurrent transaction's start time and last one's end time. - */ -@interface SentryProfiler : NSObject - -@property (strong, nonatomic) SentryId *profilerId; - -/** - * Start a profiler, if one isn't already running. - */ -+ (BOOL)startWithTracer:(SentryId *)traceId; - -/** - * Stop the profiler if it is running. - */ -- (void)stopForReason:(SentryProfilerTruncationReason)reason; - -/** - * Whether the profiler instance is currently running. If not, then it probably timed out or aborted - * due to app backgrounding and is being kept alive while its associated transactions finish so they - * can query for its profile data. */ -- (BOOL)isRunning; - -/** - * Whether there is any profiler that is currently running. A convenience method to query for this - * information from other SDK components that don't have access to specific @c SentryProfiler - * instances. - */ -+ (BOOL)isCurrentlyProfiling; - -/** - * Immediately record a sample of profiling metrics. Helps get full coverage of concurrent spans - * when they're ended. - */ -+ (void)recordMetrics; - -/** - * Given a transaction, return an envelope item containing any corresponding profile data to be - * attached to the transaction envelope. - * */ -+ (nullable SentryEnvelopeItem *)createProfilingEnvelopeItemForTransaction: - (SentryTransaction *)transaction - startTimestamp:startTimestamp; - -/** - * Collect profile data corresponding with the given traceId and time period. - * */ -+ (nullable NSMutableDictionary *)collectProfileBetween:(uint64_t)startSystemTime - and:(uint64_t)endSystemTime - forTrace:(SentryId *)traceId - onHub:(SentryHub *)hub; -@end - -NS_ASSUME_NONNULL_END - -#endif // SENTRY_TARGET_PROFILING_SUPPORTED diff --git a/Tests/SentryProfilerTests/SentryProfilerTests.mm b/Tests/SentryProfilerTests/SentryProfilerTests.mm index 05d1fe53209..40ee42289eb 100644 --- a/Tests/SentryProfilerTests/SentryProfilerTests.mm +++ b/Tests/SentryProfilerTests/SentryProfilerTests.mm @@ -15,7 +15,7 @@ using namespace sentry::profiling; -# import "SentryProfiler.h" +# import "SentryProfiler+Private.h" # import # import diff --git a/Tests/SentryTests/SentryProfiler+Test.h b/Tests/SentryTests/SentryProfiler+Test.h index 1d94abfc7e1..6f57f368659 100644 --- a/Tests/SentryTests/SentryProfiler+Test.h +++ b/Tests/SentryTests/SentryProfiler+Test.h @@ -1,13 +1,26 @@ -#import "SentryProfiler.h" #import "SentryProfilingConditionals.h" #if SENTRY_TARGET_PROFILING_SUPPORTED +# import "SentryProfiler+Private.h" + +@class SentryDebugMeta; + NS_ASSUME_NONNULL_BEGIN @interface SentryProfiler () +NSMutableDictionary *serializedProfileData( + NSDictionary *profileData, uint64_t startSystemTime, uint64_t endSystemTime, + NSString *truncationReason, NSDictionary *serializedMetrics, + NSArray *debugMeta, SentryHub *hub +# if SENTRY_HAS_UIKIT + , + SentryScreenFrames *gpuData +# endif // SENTRY_HAS_UIKIT +); + + (SentryProfiler *)getCurrentProfiler; + (void)resetConcurrencyTracking; diff --git a/Tests/SentryTests/Transaction/SentryTracerObjCTests.m b/Tests/SentryTests/Transaction/SentryTracerObjCTests.m index 3ddf1741033..df979ff337c 100644 --- a/Tests/SentryTests/Transaction/SentryTracerObjCTests.m +++ b/Tests/SentryTests/Transaction/SentryTracerObjCTests.m @@ -9,7 +9,7 @@ #import #if SENTRY_TARGET_PROFILING_SUPPORTED -# import "SentryProfiler.h" +# import "SentryProfiler+Private.h" #endif // SENTRY_TARGET_PROFILING_SUPPORTED @interface SentryTracerObjCTests : XCTestCase