Skip to content

Commit 3b62bce

Browse files
DariaKunoichiRobert Bartoszewski
andauthored
Implement pre-loaded scenarios (#480)
* Test fixture uses saved startup configuration, added app start type tests * Fetching AppStartup overall span from AppStartupInstrumentation --------- Co-authored-by: Robert Bartoszewski <robert.smartbear@gmail.com>
1 parent 533a6e0 commit 3b62bce

File tree

18 files changed

+275
-21
lines changed

18 files changed

+275
-21
lines changed

BugsnagPerformance.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,10 @@
7878
09FFD4412BEE3DE2009B0E04 /* BugsnagPerformanceCrossTalkAPI.mm in Sources */ = {isa = PBXBuildFile; fileRef = 09FFD43F2BEE3DE2009B0E04 /* BugsnagPerformanceCrossTalkAPI.mm */; };
7979
1C3C0C612E2922080037B416 /* BugsnagPerformanceLoadingIndicatorView.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C3C0C602E2922000037B416 /* BugsnagPerformanceLoadingIndicatorView.h */; settings = {ATTRIBUTES = (Public, ); }; };
8080
1C60EB452E43F4BE00D46E88 /* BugsnagPerformanceLoadingIndicatorView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1C60EB442E43F4BE00D46E88 /* BugsnagPerformanceLoadingIndicatorView.mm */; };
81-
1C68DB932E535241002621D1 /* BugsnagPerformanceAppStartSpanControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C68DB922E535229002621D1 /* BugsnagPerformanceAppStartSpanControl.h */; };
81+
1C68DB932E535241002621D1 /* BugsnagPerformanceAppStartSpanControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C68DB922E535229002621D1 /* BugsnagPerformanceAppStartSpanControl.h */; settings = {ATTRIBUTES = (Public, ); }; };
8282
1C68DB952E535290002621D1 /* BugsnagPerformanceAppStartSpanControl+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C68DB942E53528D002621D1 /* BugsnagPerformanceAppStartSpanControl+Private.h */; };
8383
1C68DB992E535A88002621D1 /* BugsnagPerformanceAppStartSpanControl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1C68DB982E535A88002621D1 /* BugsnagPerformanceAppStartSpanControl.mm */; };
84-
1C68DB9D2E535C67002621D1 /* BugsnagPerformanceAppStartSpanQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C68DB9C2E535C64002621D1 /* BugsnagPerformanceAppStartSpanQuery.h */; };
84+
1C68DB9D2E535C67002621D1 /* BugsnagPerformanceAppStartSpanQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C68DB9C2E535C64002621D1 /* BugsnagPerformanceAppStartSpanQuery.h */; settings = {ATTRIBUTES = (Public, ); }; };
8585
1C68DBA12E535D06002621D1 /* BugsnagPerformanceAppStartSpanQuery.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1C68DBA02E535D01002621D1 /* BugsnagPerformanceAppStartSpanQuery.mm */; };
8686
1C68DBA32E535DF2002621D1 /* BugsnagPerformanceAppStartTypePlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C68DBA22E535DEE002621D1 /* BugsnagPerformanceAppStartTypePlugin.h */; };
8787
1C68DBA52E535E21002621D1 /* BugsnagPerformanceAppStartTypePlugin.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1C68DBA42E535E1E002621D1 /* BugsnagPerformanceAppStartTypePlugin.mm */; };

Sources/BugsnagPerformance/Private/BugsnagPerformanceAppStartTypePlugin.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@
99
#import "SpanStackingHandler.h"
1010
#import <BugsnagPerformance/BugsnagPerformancePlugin.h>
1111
#import <BugsnagPerformance/BugsnagPerformanceSpanControlProvider.h>
12+
#import "Instrumentation/Instrumentation.h"
1213

1314
NS_ASSUME_NONNULL_BEGIN
1415

1516
@interface BugsnagPerformanceAppStartTypePlugin: NSObject<BugsnagPerformancePlugin, BugsnagPerformanceSpanControlProvider>
16-
- (instancetype)initWithSpanStackingHandler:(std::shared_ptr<SpanStackingHandler>)spanStackingHandler;
17+
- (void)setGetAppStartInstrumentationStateCallback:(GetAppStartInstrumentationStateSnapshot)callback;
1718
@end
1819

1920
NS_ASSUME_NONNULL_END

Sources/BugsnagPerformance/Private/BugsnagPerformanceAppStartTypePlugin.mm

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,23 @@
88

99
#import "SpanStackingHandler.h"
1010
#import <BugsnagPerformance/BugsnagPerformanceSpanControl.h>
11-
#import <BugsnagPerformance/BugsnagPerformanceSpanQuery.h>
11+
#import <BugsnagPerformance/BugsnagPerformanceAppStartSpanQuery.h>
1212
#import <BugsnagPerformance/BugsnagPerformancePluginContext.h>
1313
#import <BugsnagPerformance/BugsnagPerformanceAppStartSpanControl.h>
1414
#import "BugsnagPerformanceAppStartSpanControl+Private.h"
1515
#import "BugsnagPerformanceAppStartTypePlugin.h"
1616
#import "BugsnagPerformanceCrossTalkAPI.h"
1717

1818
@interface BugsnagPerformanceAppStartTypePlugin()
19-
@property(nonatomic) std::shared_ptr<SpanStackingHandler> spanStackingHandler;
19+
@property (nonatomic) GetAppStartInstrumentationStateSnapshot getAppStartInstrumentationState;
2020
@end
2121

2222
@implementation BugsnagPerformanceAppStartTypePlugin
2323

24-
- (instancetype)initWithSpanStackingHandler:(std::shared_ptr<SpanStackingHandler>)spanStackingHandler {
25-
if ((self = [super init])) {
26-
_spanStackingHandler = spanStackingHandler;
24+
- (void)setGetAppStartInstrumentationStateCallback:(GetAppStartInstrumentationStateSnapshot)callback {
25+
@synchronized (self) {
26+
self.getAppStartInstrumentationState = callback;
2727
}
28-
return self;
2928
}
3029

3130
#pragma mark BugsnagPerformancePlugin
@@ -40,13 +39,17 @@ - (void)start {
4039
#pragma mark BugsnagPerformanceSpanControlProvider
4140

4241
- (__nullable id<BugsnagPerformanceSpanControl>)getSpanControlsWithQuery:(BugsnagPerformanceSpanQuery *)query {
43-
if ([query isKindOfClass:[BugsnagPerformanceAppStartSpanControl class]]) {
42+
if ([query isKindOfClass:[BugsnagPerformanceAppStartSpanQuery class]]) {
4443
@synchronized (self) {
45-
if (self.spanStackingHandler == nullptr) {
44+
if (self.getAppStartInstrumentationState == nullptr) {
4645
return nil;
4746
}
4847

49-
BugsnagPerformanceSpan *appStartSpan = self.spanStackingHandler->findSpanForCategory(@"app_start");
48+
BugsnagPerformanceSpan *appStartSpan;
49+
AppStartupInstrumentationStateSnapshot *snapshot = self.getAppStartInstrumentationState();
50+
if (snapshot.isInProgress) {
51+
appStartSpan = snapshot.appStartSpan;
52+
}
5053
if (appStartSpan == nil) {
5154
return nil;
5255
}

Sources/BugsnagPerformance/Private/BugsnagPerformanceImpl.mm

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,10 @@
152152

153153
NSMutableArray<id<BugsnagPerformancePlugin>> *defaultPlugins = [NSMutableArray array];
154154
BugsnagPerformanceAppStartTypePlugin *appStartTypePlugin =
155-
[[BugsnagPerformanceAppStartTypePlugin alloc] initWithSpanStackingHandler:spanStackingHandler_];
155+
[BugsnagPerformanceAppStartTypePlugin new];
156+
[appStartTypePlugin setGetAppStartInstrumentationStateCallback:^AppStartupInstrumentationStateSnapshot * _Nullable {
157+
return instrumentation_->getAppStartInstrumentationStateSnapshot();
158+
}];
156159
[defaultPlugins addObject:appStartTypePlugin];
157160
[pluginManager_ installPlugins:defaultPlugins];
158161

Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@
2121
#import "../SpanFactory/AppStartup/AppStartupSpanFactory.h"
2222
#import "../SpanFactory/ViewLoad/ViewLoadSpanFactory.h"
2323
#import "../SpanFactory/Network/NetworkSpanFactory.h"
24+
#import "AppStartupInstrumentation/State/AppStartupInstrumentationStateSnapshot.h"
25+
26+
NS_ASSUME_NONNULL_BEGIN
27+
28+
typedef AppStartupInstrumentationStateSnapshot * _Nullable (^GetAppStartInstrumentationStateSnapshot)();
2429

2530
std::shared_ptr<AppStartupInstrumentation> createAppStartupInstrumentation(std::shared_ptr<Tracer> tracer,
2631
std::shared_ptr<AppStartupSpanFactory> spanFactory,
@@ -63,6 +68,9 @@ class Instrumentation: public PhasedStartup {
6368
void willCallMainFunction() noexcept { appStartupInstrumentation_->willCallMainFunction(); }
6469
CFAbsoluteTime appStartDuration() noexcept { return appStartupInstrumentation_->appStartDuration(); }
6570
CFAbsoluteTime timeSinceAppFirstBecameActive() noexcept { return appStartupInstrumentation_->timeSinceAppFirstBecameActive(); }
71+
AppStartupInstrumentationStateSnapshot *getAppStartInstrumentationStateSnapshot() {
72+
return appStartupInstrumentation_->stateSnapshot();
73+
}
6674

6775
void loadingIndicatorWasAdded(BugsnagPerformanceLoadingIndicatorView *loadingViewIndicator) noexcept { viewLoadInstrumentation_->loadingIndicatorWasAdded(loadingViewIndicator); }
6876

@@ -75,3 +83,5 @@ class Instrumentation: public PhasedStartup {
7583
};
7684

7785
}
86+
87+
NS_ASSUME_NONNULL_END

Sources/BugsnagPerformance/include/BugsnagPerformance/BugsnagPerformance.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#import <BugsnagPerformance/BugsnagPerformancePlugin.h>
2222
#import <BugsnagPerformance/BugsnagPerformancePluginContext.h>
2323
#import <BugsnagPerformance/BugsnagPerformanceLoadingIndicatorView.h>
24+
#import <BugsnagPerformance/BugsnagPerformanceAppStartSpanQuery.h>
25+
#import <BugsnagPerformance/BugsnagPerformanceAppStartSpanControl.h>
2426

2527
NS_ASSUME_NONNULL_BEGIN
2628

features/default/plugins.feature

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,11 @@ Feature: Plugins
4242
| attribute | type | value |
4343
| span_count | intValue | 3 |
4444
| plugin_start | boolValue | true |
45+
46+
Scenario: App start type plugin correctly changes the span name
47+
Given I run "AppStartTypeScenario"
48+
Then I relaunch the app after shutdown
49+
And I wait for 5 spans
50+
Then the trace "Content-Type" header equals "application/json"
51+
* the trace "Bugsnag-Sent-At" header matches the regex "^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d\.\d\d\dZ$"
52+
* a span field "name" equals "[AppStart/iOSCold]customType"

features/fixtures/ios/Fixture.xcodeproj/project.pbxproj

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@
5959
09F23AC12CF0CBB500F0D769 /* AutoInstrumentGenericViewLoadScenario2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09F23AC02CF0CBB500F0D769 /* AutoInstrumentGenericViewLoadScenario2.swift */; };
6060
09F3F5282D6C728300BAA0A3 /* MemoryMetricsScenario.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09F3F5272D6C728300BAA0A3 /* MemoryMetricsScenario.swift */; };
6161
09F3F5302D6F17B300BAA0A3 /* RenderingMetricsScenario.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09F3F52F2D6F17B300BAA0A3 /* RenderingMetricsScenario.swift */; };
62+
1C377BA02E78BDFE002148B2 /* StartupConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C377B9F2E78BDF8002148B2 /* StartupConfiguration.swift */; };
63+
1CC791752E67838A0015FFBA /* AppStartTypeScenario.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CC791742E6783850015FFBA /* AppStartTypeScenario.swift */; };
6264
960EECE92B2316E1009FAA11 /* AutoInstrumentGenericViewLoadScenario.swift in Sources */ = {isa = PBXBuildFile; fileRef = 960EECE82B2316E1009FAA11 /* AutoInstrumentGenericViewLoadScenario.swift */; };
6365
96284DCE2B626B6F00025070 /* AutoInstrumentPreLoadedViewLoadScenario.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96284DCD2B626B6F00025070 /* AutoInstrumentPreLoadedViewLoadScenario.swift */; };
6466
962CE7EE2E62240E00380522 /* LoadingIndicatorViewSimpleStopScenario.swift in Sources */ = {isa = PBXBuildFile; fileRef = 962CE7ED2E62240E00380522 /* LoadingIndicatorViewSimpleStopScenario.swift */; };
@@ -167,6 +169,8 @@
167169
09F23AC02CF0CBB500F0D769 /* AutoInstrumentGenericViewLoadScenario2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoInstrumentGenericViewLoadScenario2.swift; sourceTree = "<group>"; };
168170
09F3F5272D6C728300BAA0A3 /* MemoryMetricsScenario.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryMetricsScenario.swift; sourceTree = "<group>"; };
169171
09F3F52F2D6F17B300BAA0A3 /* RenderingMetricsScenario.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RenderingMetricsScenario.swift; sourceTree = "<group>"; };
172+
1C377B9F2E78BDF8002148B2 /* StartupConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartupConfiguration.swift; sourceTree = "<group>"; };
173+
1CC791742E6783850015FFBA /* AppStartTypeScenario.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppStartTypeScenario.swift; sourceTree = "<group>"; };
170174
960EECE82B2316E1009FAA11 /* AutoInstrumentGenericViewLoadScenario.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoInstrumentGenericViewLoadScenario.swift; sourceTree = "<group>"; };
171175
96284DCD2B626B6F00025070 /* AutoInstrumentPreLoadedViewLoadScenario.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoInstrumentPreLoadedViewLoadScenario.swift; sourceTree = "<group>"; };
172176
962CE7EC2E62240E00380522 /* LoadingIndicatorViewSimpleRemoveScenario.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingIndicatorViewSimpleRemoveScenario.swift; sourceTree = "<group>"; };
@@ -259,6 +263,7 @@
259263
01FE4DA728E1AEBD00D1F239 /* Fixture */ = {
260264
isa = PBXGroup;
261265
children = (
266+
1C377B9F2E78BDF8002148B2 /* StartupConfiguration.swift */,
262267
01FE4DA828E1AEBD00D1F239 /* AppDelegate.swift */,
263268
01FE4DB128E1AEBF00D1F239 /* Assets.xcassets */,
264269
CB211D0629EEB615008F748D /* BugsnagPerformanceConfiguration+Private.h */,
@@ -297,6 +302,7 @@
297302
01FE4DC128E1AF0700D1F239 /* Scenarios */ = {
298303
isa = PBXGroup;
299304
children = (
305+
1CC791742E6783850015FFBA /* AppStartTypeScenario.swift */,
300306
96D528CB2C72B14300FEA2E2 /* AppDataOverrideScenario.swift */,
301307
01D3A7DF28F0290D0063D79E /* AutoInstrumentAppStartsScenario.swift */,
302308
96A25F3A2D6BC98100A18116 /* AutoInstrumentAppStartsWithViewLoadScenario.swift */,
@@ -567,13 +573,15 @@
567573
9691A9DD2CA5E61500707CDF /* FrameMetricsAutoInstrumentRenderingOffScenario.swift in Sources */,
568574
09637A452B0B883B00F4F776 /* FixtureConfig.swift in Sources */,
569575
CBC90CE429D1BDE400280884 /* AutoInstrumentSubViewLoadScenario.swift in Sources */,
576+
1CC791752E67838A0015FFBA /* AppStartTypeScenario.swift in Sources */,
570577
098C3B502C53CEC0006F9886 /* ErrorGenerator.m in Sources */,
571578
0921F02E2A69262300C764EB /* AutoInstrumentNetworkCallbackScenario.swift in Sources */,
572579
01E7918A28EC7B5E00855993 /* ManualSpanBeforeStartScenario.swift in Sources */,
573580
09DC622A2C6DE242000AA8E1 /* EarlySpanOnEndScenario.swift in Sources */,
574581
DADB14F92DE08A030006F44F /* OnStartCallbackScenario.swift in Sources */,
575582
DA85961E2DF718D100905922 /* PluginScenario.swift in Sources */,
576583
CBE615F729A4C1F0000E72D8 /* ParentSpanScenario.swift in Sources */,
584+
1C377BA02E78BDFE002148B2 /* StartupConfiguration.swift in Sources */,
577585
);
578586
runOnlyForDeploymentPostprocessing = 0;
579587
};
@@ -726,7 +734,6 @@
726734
INFOPLIST_FILE = Fixture/Info.plist;
727735
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
728736
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
729-
INFOPLIST_KEY_UIMainStoryboardFile = Main;
730737
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
731738
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
732739
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
@@ -758,7 +765,6 @@
758765
INFOPLIST_FILE = Fixture/Info.plist;
759766
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
760767
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
761-
INFOPLIST_KEY_UIMainStoryboardFile = Main;
762768
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
763769
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
764770
IPHONEOS_DEPLOYMENT_TARGET = 13.0;

features/fixtures/ios/Fixture/AppDelegate.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,19 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
1414

1515
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
1616
logInfo(">>>>>>>>>> Fixture app has launched <<<<<<<<<<")
17+
18+
if #unavailable(iOS 13.0) {
19+
let fixture = Fixture()
20+
let customViewController = fixture.processSavedStartupConfig()
21+
let defaultViewController = ViewController()
22+
if (customViewController == nil) {
23+
defaultViewController.setFixture(fixture: fixture)
24+
}
25+
window = UIWindow(frame: UIScreen.main.bounds)
26+
window?.rootViewController = customViewController != nil ? customViewController : defaultViewController
27+
window?.makeKeyAndVisible()
28+
}
29+
1730
return true
1831
}
1932
}

features/fixtures/ios/Fixture/Fixture.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,24 @@ class Fixture: NSObject, CommandReceiver {
7171
}
7272
}
7373

74+
func processSavedStartupConfig() -> UIViewController? {
75+
let startupConfig = StartupConfiguration(configFile: nil)
76+
if !startupConfig.loadStartupConfig() {
77+
return nil
78+
}
79+
80+
let scenarioClass: AnyClass = NSClassFromString("Fixture.\(startupConfig.scenarioName)")!
81+
let scenarioInstance = (scenarioClass as! Scenario.Type).init(fixtureConfig: fixtureConfig) as Scenario?
82+
if scenarioInstance == nil {
83+
return nil
84+
}
85+
scenarioInstance?.setInitialBugsnagConfiguration()
86+
scenarioInstance?.applyStartupConfig(startupConfig: startupConfig)
87+
scenarioInstance?.startBugsnag()
88+
89+
return scenarioInstance?.customViewController()
90+
}
91+
7492
func beginReceivingCommands(fixtureConfig: FixtureConfig) {
7593
readyToReceiveCommand = true
7694
commandReaderThread = CommandReaderThread(fixtureConfig: fixtureConfig, commandReceiver: self)

0 commit comments

Comments
 (0)