Skip to content
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

fix(launch profiling): set a new trace origin for app launch profiles #3636

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
6 changes: 3 additions & 3 deletions Samples/iOS-Swift/iOS-Swift/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

print("[iOS-Swift] launch arguments: \(ProcessInfo.processInfo.arguments)")
print("[iOS-Swift] environment: \(ProcessInfo.processInfo.environment)")
print("[iOS-Swift] [debug] launch arguments: \(ProcessInfo.processInfo.arguments)")
print("[iOS-Swift] [debug] environment: \(ProcessInfo.processInfo.environment)")

maybeWipeData()
AppDelegate.startSentry()
Expand Down Expand Up @@ -168,7 +168,7 @@ private extension AppDelegate {
// previously tried putting this in an AppDelegate.load override in ObjC, but it wouldn't run until after a launch profiler would have an opportunity to run, since SentryProfiler.load would always run first due to being dynamically linked in a framework module. it is sufficient to do it before calling SentrySDK.startWithOptions to clear state for testProfiledAppLaunches because we don't make any assertions on a launch profile the first launch of the app in that test
func maybeWipeData() {
if ProcessInfo.processInfo.arguments.contains("--io.sentry.wipe-data") {
print("[iOS-Swift] removing app data")
print("[iOS-Swift] [debug] removing app data")
let appSupport = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first!
let cache = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first!
for path in [appSupport, cache] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class ProfilingViewController: UIViewController, UITextFieldDelegate {
let value = SentryBenchmarking.stopBenchmark()!
valueTextField.isHidden = false
valueTextField.text = value
print("[iOS-Swift] [ProfilingViewController] benchmarking results:\n\(value)")
print("[iOS-Swift] [debug] [ProfilingViewController] benchmarking results:\n\(value)")
}

@IBAction func startCPUWork(_ sender: UIButton) {
Expand Down Expand Up @@ -130,7 +130,7 @@ extension ProfilingViewController {
let url = file as! URL
if url.absoluteString.contains(fileName) {
block(url)
print("[iOS-Swift] [ProfilingViewController] removing file at \(url)")
print("[iOS-Swift] [debug] [ProfilingViewController] removing file at \(url)")
try! FileManager.default.removeItem(at: url)
return
}
Expand All @@ -150,7 +150,7 @@ extension ProfilingViewController {
return
}
let contents = data.base64EncodedString()
print("[iOS-Swift] [ProfilingViewController] contents of file at \(file): \(String(describing: String(data: data, encoding: .utf8)))")
print("[iOS-Swift] [debug] [ProfilingViewController] contents of file at \(file): \(String(describing: String(data: data, encoding: .utf8)))")
profilingUITestDataMarshalingTextField.text = contents
profilingUITestDataMarshalingStatus.text = "✅"
}
Expand Down
49 changes: 34 additions & 15 deletions Sources/Sentry/Profiling/SentryLaunchProfiling.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
# import "SentrySamplerDecision.h"
# import "SentrySampling.h"
# import "SentrySamplingContext.h"
# import "SentryTraceOrigins.h"
# import "SentryTracer+Private.h"
# import "SentryTracerConfiguration.h"
# import "SentryTransactionContext.h"
# import "SentryTransactionContext+Private.h"

NS_ASSUME_NONNULL_BEGIN

Expand Down Expand Up @@ -90,6 +91,29 @@
}];
}

SentryTransactionContext *
context(NSNumber *tracesRate)
{
SentryTransactionContext *context =
[[SentryTransactionContext alloc] initWithName:@"launch"
nameSource:kSentryTransactionNameSourceCustom
operation:@"app.lifecycle"
origin:SentryTraceOriginAutoAppStartProfile
sampled:kSentrySampleDecisionYes];
context.sampleRate = tracesRate;
return context;
}

SentryTracerConfiguration *
config(NSNumber *profilesRate)
{
SentryTracerConfiguration *config = [SentryTracerConfiguration defaultConfiguration];
config.profilesSamplerDecision =
[[SentrySamplerDecision alloc] initWithDecision:kSentrySampleDecisionYes
forSampleRate:profilesRate];
return config;
}

Check warning on line 115 in Sources/Sentry/Profiling/SentryLaunchProfiling.m

View check run for this annotation

Codecov / codecov/patch

Sources/Sentry/Profiling/SentryLaunchProfiling.m#L110-L115

Added lines #L110 - L115 were not covered by tests

void
startLaunchProfile(void)
{
Expand All @@ -110,25 +134,19 @@
[SentryLog configure:YES diagnosticLevel:kSentryLevelDebug];
# endif // defined(DEBUG)

SENTRY_LOG_INFO(@"Starting app launch profile.");

SentryTransactionContext *context =
[[SentryTransactionContext alloc] initWithName:@"launch"
operation:@"app.lifecycle"
sampled:kSentrySampleDecisionYes];
SentryTracerConfiguration *config = [SentryTracerConfiguration defaultConfiguration];
NSDictionary<NSString *, NSNumber *> *rates = appLaunchProfileConfiguration();
NSNumber *profilesRate = rates[kSentryLaunchProfileConfigKeyProfilesSampleRate];
NSNumber *tracesRate = rates[kSentryLaunchProfileConfigKeyTracesSampleRate];
if (profilesRate != nil && tracesRate != nil) {
config.profilesSamplerDecision =
[[SentrySamplerDecision alloc] initWithDecision:kSentrySampleDecisionYes
forSampleRate:profilesRate];
context.sampleRate = tracesRate;
if (profilesRate == nil || tracesRate == nil) {
SENTRY_LOG_DEBUG(
@"Received a nil configured launch sample rate, will not trace or profile.");
return;

Check warning on line 143 in Sources/Sentry/Profiling/SentryLaunchProfiling.m

View check run for this annotation

Codecov / codecov/patch

Sources/Sentry/Profiling/SentryLaunchProfiling.m#L142-L143

Added lines #L142 - L143 were not covered by tests
}
launchTracer = [[SentryTracer alloc] initWithTransactionContext:context

SENTRY_LOG_INFO(@"Starting app launch profile.");
launchTracer = [[SentryTracer alloc] initWithTransactionContext:context(tracesRate)

Check warning on line 147 in Sources/Sentry/Profiling/SentryLaunchProfiling.m

View check run for this annotation

Codecov / codecov/patch

Sources/Sentry/Profiling/SentryLaunchProfiling.m#L147

Added line #L147 was not covered by tests
hub:nil
configuration:config];
configuration:config(profilesRate)];

Check warning on line 149 in Sources/Sentry/Profiling/SentryLaunchProfiling.m

View check run for this annotation

Codecov / codecov/patch

Sources/Sentry/Profiling/SentryLaunchProfiling.m#L149

Added line #L149 was not covered by tests
});
}

Expand All @@ -137,6 +155,7 @@
{
if (launchTracer == nil) {
SENTRY_LOG_DEBUG(@"No launch tracer present to stop.");
return;
}

SENTRY_LOG_DEBUG(@"Finishing launch tracer.");
Expand Down
2 changes: 1 addition & 1 deletion Sources/Sentry/include/SentryLaunchProfiling.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ NS_ASSUME_NONNULL_BEGIN
SENTRY_EXTERN BOOL isTracingAppLaunch;

/** Try to start a profiled trace for this app launch, if the configuration allows. */
void startLaunchProfile(void);
SENTRY_EXTERN void startLaunchProfile(void);

/** Stop any profiled trace that may be in flight from the start of the app launch. */
void stopLaunchProfile(SentryHub *hub);
Expand Down
1 change: 1 addition & 0 deletions Sources/Sentry/include/SentryTraceOrigins.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ static NSString *const SentryTraceOriginManual = @"manual";
static NSString *const SentryTraceOriginUIEventTracker = @"auto.ui.event_tracker";

static NSString *const SentryTraceOriginAutoAppStart = @"auto.app.start";
static NSString *const SentryTraceOriginAutoAppStartProfile = @"auto.app.start.profile";
static NSString *const SentryTraceOriginAutoNSData = @"auto.file.ns_data";
static NSString *const SentryTraceOriginAutoDBCoreData = @"auto.db.core_data";
static NSString *const SentryTraceOriginAutoHttpNSURLSession = @"auto.http.ns_url_session";
Expand Down
12 changes: 12 additions & 0 deletions Tests/SentryProfilerTests/SentryAppLaunchProfilingTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#import "SentryOptions+Private.h"
#import "SentryProfilingConditionals.h"
#import "SentrySDK+Tests.h"
#import "SentryTraceOrigins.h"
#import "SentryTransactionContext.h"
#import <XCTest/XCTest.h>

#if SENTRY_TARGET_PROFILING_SUPPORTED
Expand All @@ -12,6 +14,14 @@ @interface SentryAppLaunchProfilingTests : XCTestCase

@implementation SentryAppLaunchProfilingTests

- (void)testLaunchProfileTransactionContext
{
SentryTransactionContext *actualContext = context(@1);
XCTAssertEqual(actualContext.nameSource, kSentryTransactionNameSourceCustom);
XCTAssert([actualContext.origin isEqualToString:SentryTraceOriginAutoAppStartProfile]);
XCTAssert(actualContext.sampled);
}

# define SENTRY_OPTION(name, value) \
NSStringFromSelector(@selector(name)) \
: value
Expand Down Expand Up @@ -107,6 +117,8 @@ - (void)testSettingProfilesSampleRateTo0DisablesAppLaunchProfiling
@"but profiles sample rate of 0 should not enable launch profiling");
}

# pragma mark - Private

- (SentryOptions *)defaultLaunchProfilingOptionsWithOverrides:
(NSDictionary<NSString *, id> *)overrides
{
Expand Down
7 changes: 7 additions & 0 deletions Tests/SentryTests/SentryLaunchProfiling+Tests.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#import "SentryDefines.h"
#import "SentryLaunchProfiling.h"

#if SENTRY_TARGET_PROFILING_SUPPORTED

@class SentrySamplerDecision;
@class SentryOptions;

Expand All @@ -17,4 +19,9 @@ SENTRY_EXTERN SentryLaunchProfileConfig shouldProfileNextLaunch(SentryOptions *o
SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyTracesSampleRate;
SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyProfilesSampleRate;

SENTRY_EXTERN SentryTransactionContext *context(NSNumber *tracesRate);
SENTRY_EXTERN SentryTracerConfiguration *config(NSNumber *profilesRate);

NS_ASSUME_NONNULL_END

#endif // SENTRY_TARGET_PROFILING_SUPPORTED
Loading