Skip to content
Closed
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
2 changes: 1 addition & 1 deletion .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ steps:
- "--farm=bb"
- "--no-tunnel"
- "--aws-public-ip"
- "features/default"
- "features/default/loading_indicator.feature"
test-collector#v1.10.2:
files: "reports/TEST-*.xml"
format: "junit"
Expand Down
44 changes: 38 additions & 6 deletions BugsnagPerformance.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,10 @@
969EE1002E794A1100600F63 /* ViewLoadSpanFactoryCallbacks.mm in Sources */ = {isa = PBXBuildFile; fileRef = 969EE0FF2E794A0D00600F63 /* ViewLoadSpanFactoryCallbacks.mm */; };
96A25F432D6BE42B00A18116 /* AppStartupInstrumentationState.h in Headers */ = {isa = PBXBuildFile; fileRef = 96A25F412D6BE42B00A18116 /* AppStartupInstrumentationState.h */; };
96A25F442D6BE42B00A18116 /* AppStartupInstrumentationState.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96A25F422D6BE42B00A18116 /* AppStartupInstrumentationState.mm */; };
96BB66C72EAEA78A00AB3C93 /* ViewLoadLoadingIndicatorsHandlerCallbacks.h in Headers */ = {isa = PBXBuildFile; fileRef = 96BB66C62EAEA78300AB3C93 /* ViewLoadLoadingIndicatorsHandlerCallbacks.h */; };
96BB66C92EAEA79200AB3C93 /* ViewLoadLoadingIndicatorsHandlerCallbacks.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96BB66C82EAEA79000AB3C93 /* ViewLoadLoadingIndicatorsHandlerCallbacks.mm */; };
96BB66CD2EAEB1A400AB3C93 /* ViewLoadLoadingIndicatorState.h in Headers */ = {isa = PBXBuildFile; fileRef = 96BB66CC2EAEB19D00AB3C93 /* ViewLoadLoadingIndicatorState.h */; };
96BB66CF2EAEB1AE00AB3C93 /* ViewLoadLoadingIndicatorState.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96BB66CE2EAEB1AC00AB3C93 /* ViewLoadLoadingIndicatorState.mm */; };
96D415F329E6ADC500AEE435 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96D415F229E6ADC500AEE435 /* AppDelegate.swift */; };
96D415F729E6ADC500AEE435 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96D415F629E6ADC500AEE435 /* ViewController.swift */; };
96D415FA29E6ADC500AEE435 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 96D415F829E6ADC500AEE435 /* Main.storyboard */; };
Expand Down Expand Up @@ -630,6 +634,10 @@
969EE0FF2E794A0D00600F63 /* ViewLoadSpanFactoryCallbacks.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewLoadSpanFactoryCallbacks.mm; sourceTree = "<group>"; };
96A25F412D6BE42B00A18116 /* AppStartupInstrumentationState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppStartupInstrumentationState.h; sourceTree = "<group>"; };
96A25F422D6BE42B00A18116 /* AppStartupInstrumentationState.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AppStartupInstrumentationState.mm; sourceTree = "<group>"; };
96BB66C62EAEA78300AB3C93 /* ViewLoadLoadingIndicatorsHandlerCallbacks.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewLoadLoadingIndicatorsHandlerCallbacks.h; sourceTree = "<group>"; };
96BB66C82EAEA79000AB3C93 /* ViewLoadLoadingIndicatorsHandlerCallbacks.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewLoadLoadingIndicatorsHandlerCallbacks.mm; sourceTree = "<group>"; };
96BB66CC2EAEB19D00AB3C93 /* ViewLoadLoadingIndicatorState.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewLoadLoadingIndicatorState.h; sourceTree = "<group>"; };
96BB66CE2EAEB1AC00AB3C93 /* ViewLoadLoadingIndicatorState.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewLoadLoadingIndicatorState.mm; sourceTree = "<group>"; };
96D415F029E6ADC500AEE435 /* BugsnagPerformanceTestsApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BugsnagPerformanceTestsApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
96D415F229E6ADC500AEE435 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
96D415F629E6ADC500AEE435 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1150,15 +1158,11 @@
9638293F2E5726C400404F3A /* Lifecycle */ = {
isa = PBXGroup;
children = (
962CE7DC2E60986300380522 /* ViewLoadEarlyPhaseHandler.h */,
962CE7DE2E60987A00380522 /* ViewLoadEarlyPhaseHandlerImpl.h */,
962CE7E02E60988500380522 /* ViewLoadEarlyPhaseHandlerImpl.mm */,
96BB66CB2EAEAA7600AB3C93 /* EarlyPhase */,
96BB66CA2EAEAA5C00AB3C93 /* LoadingIndicators */,
963829402E5726D400404F3A /* ViewLoadLifecycleHandler.h */,
963829422E57536B00404F3A /* ViewLoadLifecycleHandlerImpl.h */,
963829442E57537600404F3A /* ViewLoadLifecycleHandlerImpl.mm */,
962CE7E42E6123E700380522 /* ViewLoadLoadingIndicatorsHandler.h */,
962CE7E52E6123E700380522 /* ViewLoadLoadingIndicatorsHandlerImpl.h */,
962CE7E62E6123E700380522 /* ViewLoadLoadingIndicatorsHandlerImpl.mm */,
);
path = Lifecycle;
sourceTree = "<group>";
Expand Down Expand Up @@ -1544,6 +1548,30 @@
path = Network;
sourceTree = "<group>";
};
96BB66CA2EAEAA5C00AB3C93 /* LoadingIndicators */ = {
isa = PBXGroup;
children = (
962CE7E42E6123E700380522 /* ViewLoadLoadingIndicatorsHandler.h */,
96BB66C62EAEA78300AB3C93 /* ViewLoadLoadingIndicatorsHandlerCallbacks.h */,
96BB66C82EAEA79000AB3C93 /* ViewLoadLoadingIndicatorsHandlerCallbacks.mm */,
962CE7E52E6123E700380522 /* ViewLoadLoadingIndicatorsHandlerImpl.h */,
962CE7E62E6123E700380522 /* ViewLoadLoadingIndicatorsHandlerImpl.mm */,
96BB66CC2EAEB19D00AB3C93 /* ViewLoadLoadingIndicatorState.h */,
96BB66CE2EAEB1AC00AB3C93 /* ViewLoadLoadingIndicatorState.mm */,
);
path = LoadingIndicators;
sourceTree = "<group>";
};
96BB66CB2EAEAA7600AB3C93 /* EarlyPhase */ = {
isa = PBXGroup;
children = (
962CE7DC2E60986300380522 /* ViewLoadEarlyPhaseHandler.h */,
962CE7DE2E60987A00380522 /* ViewLoadEarlyPhaseHandlerImpl.h */,
962CE7E02E60988500380522 /* ViewLoadEarlyPhaseHandlerImpl.mm */,
);
path = EarlyPhase;
sourceTree = "<group>";
};
96D415F129E6ADC500AEE435 /* BugsnagPerformanceTestsApp */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -1621,6 +1649,7 @@
963726DD2DF0B43500C739E6 /* BugsnagPerformancePluginContext.h in Headers */,
963829412E5726DF00404F3A /* ViewLoadLifecycleHandler.h in Headers */,
962CE8332E67970600380522 /* NetworkSpanFactory.h in Headers */,
96BB66C72EAEA78A00AB3C93 /* ViewLoadLoadingIndicatorsHandlerCallbacks.h in Headers */,
963726DE2DF0B43500C739E6 /* BugsnagPerformancePlugin.h in Headers */,
0122C24C29019770002D243C /* NetworkInstrumentation.h in Headers */,
962CE8352E67972300380522 /* NetworkSpanFactoryImpl.h in Headers */,
Expand Down Expand Up @@ -1709,6 +1738,7 @@
963726E62DF1DFC300C739E6 /* BSGPluginManager.h in Headers */,
CBB48A3C295EE1E10044E9AC /* ObjCUtils.h in Headers */,
96D55C812A1EB5F4006D1F29 /* SpanStackingHandler.h in Headers */,
96BB66CD2EAEB1A400AB3C93 /* ViewLoadLoadingIndicatorState.h in Headers */,
015836C129125E7A002F54C8 /* ResourceAttributes.h in Headers */,
962CE7DD2E60987600380522 /* ViewLoadEarlyPhaseHandler.h in Headers */,
962CE8042E6519D900380522 /* NetworkInstrumentationState.h in Headers */,
Expand Down Expand Up @@ -2091,6 +2121,7 @@
buildActionMask = 2147483647;
files = (
96F1292D2DCD141700A6FB2B /* BugsnagPerformanceRemoteSpanContext.mm in Sources */,
96BB66C92EAEA79200AB3C93 /* ViewLoadLoadingIndicatorsHandlerCallbacks.mm in Sources */,
967949FA2EA15084005FD87F /* InstrumentationModule.mm in Sources */,
96794A1D2EA1B074005FD87F /* UploadModule.mm in Sources */,
962CE8372E67972A00380522 /* NetworkSpanFactoryImpl.mm in Sources */,
Expand Down Expand Up @@ -2175,6 +2206,7 @@
962CE82A2E67189F00380522 /* NetworkEarlyPhaseHandlerImpl.mm in Sources */,
0122C24D29019770002D243C /* ViewLoadInstrumentation.mm in Sources */,
015836C229125E7A002F54C8 /* ResourceAttributes.mm in Sources */,
96BB66CF2EAEB1AE00AB3C93 /* ViewLoadLoadingIndicatorState.mm in Sources */,
01A414D22913C238003152A4 /* Reachability.mm in Sources */,
962CE81C2E65FD5300380522 /* NetworkSwizzlingHandlerImpl.mm in Sources */,
969EE0F52E78731C00600F63 /* PlainSpanFactoryImpl.mm in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class ViewLoadSpanFactory {
BugsnagPerformanceSpanContext *parentContext,
NSString *phase,
NSArray<BugsnagPerformanceSpanCondition *> *conditionsToEndOnClose) noexcept = 0;
virtual BugsnagPerformanceSpan *startLoadingIndicatorSpan(NSString *name,
BugsnagPerformanceSpanContext *parentContext) noexcept = 0;
virtual ~ViewLoadSpanFactory() {}
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ class ViewLoadSpanFactoryImpl: public ViewLoadSpanFactory {
BugsnagPerformanceSpanContext *parentContext,
NSString *phase,
NSArray<BugsnagPerformanceSpanCondition *> *conditionsToEndOnClose) noexcept;
BugsnagPerformanceSpan *startLoadingIndicatorSpan(NSString *name,
BugsnagPerformanceSpanContext *parentContext) noexcept;

void setup(ViewLoadSpanFactoryCallbacks *callbacks) noexcept { callbacks_ = callbacks; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,19 @@
return span;
}

BugsnagPerformanceSpan *
ViewLoadSpanFactoryImpl::startLoadingIndicatorSpan(NSString *name,
BugsnagPerformanceSpanContext *parentContext) noexcept {
SpanOptions options;
options.parentContext = parentContext;
auto span = plainSpanFactory_->startSpan(name,
options,
BSGTriStateYes,
@{},
@[]);
return span;
}

#pragma mark Helpers

BugsnagPerformanceSpan *
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@

#import <BugsnagPerformance/BugsnagPerformanceSpanCondition.h>
#import <BugsnagPerformance/BugsnagPerformanceLoadingIndicatorView.h>
#import <BugsnagPerformance/BugsnagPerformanceSpan.h>

@interface BugsnagPerformanceLoadingIndicatorView()

- (void)addCondition:(BugsnagPerformanceSpanCondition *)condition;
@property (nonatomic, strong) BugsnagPerformanceSpan *loadingSpan;

- (void)addConditions:(NSArray<BugsnagPerformanceSpanCondition *> *)conditions;
- (void)closeAllConditions;
- (void)setLoadingSpan:(BugsnagPerformanceSpan *)loadingSpan;
- (void)endLoadingSpan;

@end
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
#import "ViewLoadInstrumentation/System/ViewLoadSwizzlingHandlerImpl.h"
#import "ViewLoadInstrumentation/State/ViewLoadInstrumentationStateRepositoryImpl.h"
#import "ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandlerImpl.h"
#import "ViewLoadInstrumentation/Lifecycle/ViewLoadEarlyPhaseHandlerImpl.h"
#import "ViewLoadInstrumentation/Lifecycle/ViewLoadLoadingIndicatorsHandlerImpl.h"
#import "ViewLoadInstrumentation/Lifecycle/EarlyPhase/ViewLoadEarlyPhaseHandlerImpl.h"
#import "ViewLoadInstrumentation/Lifecycle/LoadingIndicators/ViewLoadLoadingIndicatorsHandlerImpl.h"
#import "NetworkInstrumentation/State/NetworkInstrumentationStateRepositoryImpl.h"
#import "NetworkInstrumentation/System/BSGURLSessionPerformanceDelegate.h"
#import "NetworkInstrumentation/System/NetworkInstrumentationSystemUtilsImpl.h"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
#import "../Core/SpanFactory/ViewLoad/ViewLoadSpanFactory.h"
#import "../Core/SpanFactory/Network/NetworkSpanFactory.h"
#import "../Core/SpanStack/SpanStackingHandler.h"
#import "ViewLoadInstrumentation/Lifecycle/LoadingIndicators/ViewLoadLoadingIndicatorsHandlerImpl.h"
#import "ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandlerImpl.h"
#import "ViewLoadInstrumentation/State/ViewLoadInstrumentationStateRepositoryImpl.h"

namespace bugsnag {
class InstrumentationModule: public Module, AppLifecycleListener {
Expand Down Expand Up @@ -72,6 +75,7 @@ class InstrumentationModule: public Module, AppLifecycleListener {
std::shared_ptr<NetworkInstrumentation> createNetworkInstrumentation(std::shared_ptr<NetworkSpanFactory> spanFactory,
std::shared_ptr<SpanAttributesProvider> spanAttributesProvider,
std::shared_ptr<NetworkHeaderInjector> networkHeaderInjector);
ViewLoadLoadingIndicatorsHandlerCallbacks *createViewLoadLoadingIndicatorsHandlerCallbacks() noexcept;

// Dependencies
std::shared_ptr<AppStartupSpanFactory> appStartupSpanFactory_;
Expand All @@ -86,6 +90,8 @@ class InstrumentationModule: public Module, AppLifecycleListener {
std::shared_ptr<NetworkHeaderInjector> networkHeaderInjector_;
std::shared_ptr<AppStartupInstrumentation> appStartupInstrumentation_;
std::shared_ptr<ViewLoadInstrumentation> viewLoadInstrumentation_;
std::shared_ptr<ViewLoadLifecycleHandlerImpl> viewLoadLifecycleHandler_;
std::shared_ptr<ViewLoadInstrumentationStateRepositoryImpl> viewLoadRepository_;
std::shared_ptr<NetworkInstrumentation> networkInstrumentation_;
std::shared_ptr<Instrumentation> instrumentation_;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@
// View Load Instrumentation
#import "ViewLoadInstrumentation/System/ViewLoadInstrumentationSystemUtilsImpl.h"
#import "ViewLoadInstrumentation/System/ViewLoadSwizzlingHandlerImpl.h"
#import "ViewLoadInstrumentation/State/ViewLoadInstrumentationStateRepositoryImpl.h"
#import "ViewLoadInstrumentation/Lifecycle/ViewLoadEarlyPhaseHandlerImpl.h"
#import "ViewLoadInstrumentation/Lifecycle/ViewLoadLoadingIndicatorsHandlerImpl.h"
#import "ViewLoadInstrumentation/Lifecycle/EarlyPhase/ViewLoadEarlyPhaseHandlerImpl.h"
#import "ViewLoadInstrumentation/Lifecycle/LoadingIndicators/ViewLoadLoadingIndicatorsHandlerImpl.h"
#import "ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandlerImpl.h"

// Network Instrumentation
Expand Down Expand Up @@ -162,17 +161,20 @@
std::shared_ptr<SpanAttributesProvider> spanAttributesProvider) {
auto systemUtils = std::make_shared<ViewLoadInstrumentationSystemUtilsImpl>();
auto swizzlingHandler = std::make_shared<ViewLoadSwizzlingHandlerImpl>();
auto repository = std::make_shared<ViewLoadInstrumentationStateRepositoryImpl>();
viewLoadRepository_ = std::make_shared<ViewLoadInstrumentationStateRepositoryImpl>();
auto earlyPhaseHandler = std::make_shared<ViewLoadEarlyPhaseHandlerImpl>();
auto loadingIndicatorsHandler = std::make_shared<ViewLoadLoadingIndicatorsHandlerImpl>(repository);
auto lifecycleHandler = std::make_shared<ViewLoadLifecycleHandlerImpl>(earlyPhaseHandler,
spanAttributesProvider,
spanFactory,
repository,
loadingIndicatorsHandler,
[BugsnagPerformanceCrossTalkAPI sharedInstance]);
auto loadingIndicatorsHandler = std::make_shared<ViewLoadLoadingIndicatorsHandlerImpl>(viewLoadRepository_,
viewLoadSpanFactory_);
viewLoadLifecycleHandler_ = std::make_shared<ViewLoadLifecycleHandlerImpl>(earlyPhaseHandler,
spanAttributesProvider,
spanFactory,
viewLoadRepository_,
loadingIndicatorsHandler,
[BugsnagPerformanceCrossTalkAPI sharedInstance]);

return std::make_shared<ViewLoadInstrumentation>(systemUtils, swizzlingHandler, lifecycleHandler);
loadingIndicatorsHandler->setCallbacks(createViewLoadLoadingIndicatorsHandlerCallbacks());

return std::make_shared<ViewLoadInstrumentation>(systemUtils, swizzlingHandler, viewLoadLifecycleHandler_);
}

std::shared_ptr<NetworkInstrumentation>
Expand All @@ -195,3 +197,18 @@
lifecycleHandler,
urlSessionDelegate_);
}

ViewLoadLoadingIndicatorsHandlerCallbacks *
InstrumentationModule::createViewLoadLoadingIndicatorsHandlerCallbacks() noexcept {
__block auto blockThis = this;
auto callbacks = [ViewLoadLoadingIndicatorsHandlerCallbacks new];
callbacks.onLoading = ^BugsnagPerformanceSpanCondition * _Nullable(UIViewController * _Nonnull viewController) {
return blockThis->viewLoadLifecycleHandler_->onLoadingStarted(viewController);
};

callbacks.getParentContext = ^BugsnagPerformanceSpanContext * _Nullable(UIViewController * _Nonnull viewController) {
return blockThis->viewLoadRepository_->getInstrumentationState(viewController).overallSpan;
};

return callbacks;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#pragma once

#import <BugsnagPerformance/BugsnagPerformanceConfiguration.h>
#import "../State/ViewLoadInstrumentationState.h"
#import "../../State/ViewLoadInstrumentationState.h"

NS_ASSUME_NONNULL_BEGIN

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//

#import "ViewLoadEarlyPhaseHandlerImpl.h"
#import "../../../Core/Span/BugsnagPerformanceSpan+Private.h"
#import "../../../../Core/Span/BugsnagPerformanceSpan+Private.h"

using namespace bugsnag;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// ViewLoadLoadingIndicatorState.h
// BugsnagPerformance
//
// Created by Robert Bartoszewski on 26/10/2025.
// Copyright © 2025 Bugsnag. All rights reserved.
//

#import <BugsnagPerformance/BugsnagPerformanceSpan.h>
#import <BugsnagPerformance/BugsnagPerformanceSpanCondition.h>

@interface ViewLoadLoadingIndicatorState : NSObject

@property(nonatomic, strong) NSArray<BugsnagPerformanceSpanCondition *> *conditions;
@property(nonatomic, strong) BugsnagPerformanceSpan *loadingIndicatorSpan;
@property(nonatomic) BOOL needsSpanUpdate;

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// ViewLoadLoadingIndicatorState.mm
// BugsnagPerformance
//
// Created by Robert Bartoszewski on 26/10/2025.
// Copyright © 2025 Bugsnag. All rights reserved.
//

#import "ViewLoadLoadingIndicatorState.h"

@implementation ViewLoadLoadingIndicatorState
@end
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,19 @@
#pragma once

#import <BugsnagPerformance/BugsnagPerformanceLoadingIndicatorView.h>
#import "ViewLoadLoadingIndicatorsHandlerCallbacks.h"

@class BugsnagPerformanceSpanCondition;

NS_ASSUME_NONNULL_BEGIN

typedef BugsnagPerformanceSpanCondition *_Nullable(^ ViewLoadLoadingIndicatorsHandlerOnLoadingCallback)(UIViewController *_Nonnull viewController);

namespace bugsnag {

class ViewLoadLoadingIndicatorsHandler {
public:
virtual void onLoadingIndicatorWasAdded(BugsnagPerformanceLoadingIndicatorView *loadingIndicator) noexcept = 0;
virtual void onViewControllerUpdatedView(UIViewController *viewController) noexcept = 0;
virtual void setOnLoadingCallback(ViewLoadLoadingIndicatorsHandlerOnLoadingCallback callback) noexcept = 0;
virtual void setCallbacks(ViewLoadLoadingIndicatorsHandlerCallbacks *callbacks) noexcept = 0;
virtual ~ViewLoadLoadingIndicatorsHandler() {}
};
}
Expand Down
Loading