From ba8e843ebe1735dd2462fd0bd24b6ea5c1b7fc03 Mon Sep 17 00:00:00 2001 From: Robert Bartoszewski Date: Thu, 16 Oct 2025 00:16:55 +0200 Subject: [PATCH 01/14] Span Processing Pipeline abstract implementation --- BugsnagPerformance.xcodeproj/project.pbxproj | 32 +++++++ .../SpanProcessingPipeline.h | 21 +++++ .../SpanProcessingPipelineImpl.h | 53 +++++++++++ .../SpanProcessingPipelineImpl.mm | 89 +++++++++++++++++++ .../SpanProcessingPipelineStep.h | 19 ++++ 5 files changed, 214 insertions(+) create mode 100644 Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipeline.h create mode 100644 Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipelineImpl.h create mode 100644 Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipelineImpl.mm create mode 100644 Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipelineStep.h diff --git a/BugsnagPerformance.xcodeproj/project.pbxproj b/BugsnagPerformance.xcodeproj/project.pbxproj index 2699d4c6..98459cd0 100644 --- a/BugsnagPerformance.xcodeproj/project.pbxproj +++ b/BugsnagPerformance.xcodeproj/project.pbxproj @@ -190,6 +190,10 @@ 967949BD2E99373E005FD87F /* SpanStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 967949BC2E993735005FD87F /* SpanStore.h */; }; 967949BF2E993749005FD87F /* SpanStoreImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 967949BE2E993742005FD87F /* SpanStoreImpl.h */; }; 967949C12E993750005FD87F /* SpanStoreImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 967949C02E99374E005FD87F /* SpanStoreImpl.mm */; }; + 967949C82E9DC9B8005FD87F /* SpanProcessingPipeline.h in Headers */ = {isa = PBXBuildFile; fileRef = 967949C72E9DC9A1005FD87F /* SpanProcessingPipeline.h */; }; + 967949CA2E9DC9CE005FD87F /* SpanProcessingPipelineStep.h in Sources */ = {isa = PBXBuildFile; fileRef = 967949C92E9DC9C5005FD87F /* SpanProcessingPipelineStep.h */; }; + 967949CD2E9DCAEE005FD87F /* SpanProcessingPipelineImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 967949CC2E9DCAE0005FD87F /* SpanProcessingPipelineImpl.h */; }; + 967949CF2E9DCB06005FD87F /* SpanProcessingPipelineImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 967949CE2E9DCB02005FD87F /* SpanProcessingPipelineImpl.mm */; }; 967F6F1829C3783B0054EED8 /* BugsnagPerformanceConfiguration+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 967F6F1729C3782D0054EED8 /* BugsnagPerformanceConfiguration+Private.h */; }; 968AA5FB2CCA5A9200BA69CF /* BSGPerformanceSharedSessionProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 968AA5FA2CCA5A9200BA69CF /* BSGPerformanceSharedSessionProxy.h */; }; 968AA5FD2CCA5AB000BA69CF /* BSGPerformanceSharedSessionProxy.mm in Sources */ = {isa = PBXBuildFile; fileRef = 968AA5FC2CCA5AB000BA69CF /* BSGPerformanceSharedSessionProxy.mm */; }; @@ -550,6 +554,10 @@ 967949BC2E993735005FD87F /* SpanStore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SpanStore.h; sourceTree = ""; }; 967949BE2E993742005FD87F /* SpanStoreImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SpanStoreImpl.h; sourceTree = ""; }; 967949C02E99374E005FD87F /* SpanStoreImpl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SpanStoreImpl.mm; sourceTree = ""; }; + 967949C72E9DC9A1005FD87F /* SpanProcessingPipeline.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SpanProcessingPipeline.h; sourceTree = ""; }; + 967949C92E9DC9C5005FD87F /* SpanProcessingPipelineStep.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SpanProcessingPipelineStep.h; sourceTree = ""; }; + 967949CC2E9DCAE0005FD87F /* SpanProcessingPipelineImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SpanProcessingPipelineImpl.h; sourceTree = ""; }; + 967949CE2E9DCB02005FD87F /* SpanProcessingPipelineImpl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SpanProcessingPipelineImpl.mm; sourceTree = ""; }; 967F6F1729C3782D0054EED8 /* BugsnagPerformanceConfiguration+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BugsnagPerformanceConfiguration+Private.h"; sourceTree = ""; }; 968AA5FA2CCA5A9200BA69CF /* BSGPerformanceSharedSessionProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BSGPerformanceSharedSessionProxy.h; sourceTree = ""; }; 968AA5FC2CCA5AB000BA69CF /* BSGPerformanceSharedSessionProxy.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = BSGPerformanceSharedSessionProxy.mm; sourceTree = ""; }; @@ -869,6 +877,7 @@ 0122C22329019770002D243C /* SpanKind.h */, 967949B42E97CC7F005FD87F /* SpanLifecycle */, CB7FD935299D330500499E13 /* SpanOptions.h */, + 967949C62E9DC991005FD87F /* SpanProcessingPipeline */, 96D55C7D2A1EA5A8006D1F29 /* SpanStackingHandler.h */, 96D55C7F2A1EA5C6006D1F29 /* SpanStackingHandler.mm */, 967949BB2E99372C005FD87F /* SpanStore */, @@ -1211,6 +1220,25 @@ path = SpanStore; sourceTree = ""; }; + 967949C62E9DC991005FD87F /* SpanProcessingPipeline */ = { + isa = PBXGroup; + children = ( + 967949C72E9DC9A1005FD87F /* SpanProcessingPipeline.h */, + 967949CC2E9DCAE0005FD87F /* SpanProcessingPipelineImpl.h */, + 967949CE2E9DCB02005FD87F /* SpanProcessingPipelineImpl.mm */, + 967949C92E9DC9C5005FD87F /* SpanProcessingPipelineStep.h */, + 967949CB2E9DC9E9005FD87F /* Steps */, + ); + path = SpanProcessingPipeline; + sourceTree = ""; + }; + 967949CB2E9DC9E9005FD87F /* Steps */ = { + isa = PBXGroup; + children = ( + ); + path = Steps; + sourceTree = ""; + }; 969EE0EE2E7872A600600F63 /* SpanFactory */ = { isa = PBXGroup; children = ( @@ -1350,6 +1378,7 @@ 962CE7E82E6123E700380522 /* ViewLoadLoadingIndicatorsHandlerImpl.h in Headers */, 962CE7E92E6123E700380522 /* ViewLoadLoadingIndicatorsHandler.h in Headers */, CB7FD930299D2EF200499E13 /* BugsnagPerformanceSpanOptions.h in Headers */, + 967949C82E9DC9B8005FD87F /* SpanProcessingPipeline.h in Headers */, 965FBD152DF24D3300D6BACB /* Logging.h in Headers */, 9638292E2E56149100404F3A /* ViewLoadInstrumentationSystemUtils.h in Headers */, CB7881A129E698BF00A58906 /* PhasedStartup.h in Headers */, @@ -1440,6 +1469,7 @@ 962CE8082E651A0100380522 /* NetworkInstrumentationStateRepository.h in Headers */, 969EE0FE2E794A0700600F63 /* ViewLoadSpanFactoryCallbacks.h in Headers */, CBEC51BC296D9EEE009C0CE3 /* PersistentState.h in Headers */, + 967949CD2E9DCAEE005FD87F /* SpanProcessingPipelineImpl.h in Headers */, 0122C23829019770002D243C /* BugsnagPerformanceSpan.h in Headers */, 962CE8212E66D24200380522 /* NetworkInstrumentationSystemUtilsImpl.h in Headers */, 9638293C2E56284200404F3A /* ViewLoadSwizzlingCallbacks.h in Headers */, @@ -1815,6 +1845,7 @@ 963726CC2DEAB25600C739E6 /* BugsnagPerformancePriority+Private.m in Sources */, 962CE7D32E60768400380522 /* ViewLoadInstrumentationStateRepositoryImpl.mm in Sources */, CB7FD932299D2F7700499E13 /* BugsnagPerformanceSpanOptions.m in Sources */, + 967949CA2E9DC9CE005FD87F /* SpanProcessingPipelineStep.h in Sources */, CBEC51BD296D9EEE009C0CE3 /* PersistentState.mm in Sources */, CBEC51B9296D8386009C0CE3 /* Persistence.mm in Sources */, 963829232E5542B500404F3A /* AppStartupInstrumentationStateSnapshot.m in Sources */, @@ -1859,6 +1890,7 @@ 9638290F2E54881000404F3A /* AppStartupInstrumentationSystemUtilsImpl.mm in Sources */, CB68FABA2A3C27B9005B2CDB /* PersistentDeviceID.mm in Sources */, CBF7C5E2297A8E9100D47719 /* Gzip.m in Sources */, + 967949CF2E9DCB06005FD87F /* SpanProcessingPipelineImpl.mm in Sources */, 0122C24829019770002D243C /* NetworkInstrumentation.mm in Sources */, 962CE8062E6519E200380522 /* NetworkInstrumentationState.m in Sources */, 962CE82A2E67189F00380522 /* NetworkEarlyPhaseHandlerImpl.mm in Sources */, diff --git a/Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipeline.h b/Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipeline.h new file mode 100644 index 00000000..f16ef9dc --- /dev/null +++ b/Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipeline.h @@ -0,0 +1,21 @@ +// +// SpanProcessingPipeline.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 14/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#import "SpanProcessingPipelineStep.h" + +namespace bugsnag { + +class SpanProcessingPipeline { +public: + virtual void addSpanForProcessing(BugsnagPerformanceSpan *span) noexcept = 0; + virtual void removeSpan(BugsnagPerformanceSpan *span) noexcept = 0; + virtual void processPendingSpansIfNeeded() noexcept = 0; + + virtual ~SpanProcessingPipeline() {} +}; +} diff --git a/Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipelineImpl.h b/Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipelineImpl.h new file mode 100644 index 00000000..16d6a688 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipelineImpl.h @@ -0,0 +1,53 @@ +// +// SpanProcessingPipelineImpl.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 14/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#import "SpanProcessingPipeline.h" +#import "../Batch.h" +#import "../PhasedStartup.h" +#import "SpanProcessingPipelineStep.h" + +#import +#import +#import + +namespace bugsnag { + +class SpanProcessingPipelineImpl: public SpanProcessingPipeline, public PhasedStartup { +public: + SpanProcessingPipelineImpl() noexcept + : batch_(std::make_shared()) + , preStartSpans_([NSMutableArray new]) {} + + void earlyConfigure(BSGEarlyConfiguration *) noexcept {} + void earlySetup() noexcept {} + void configure(BugsnagPerformanceConfiguration *) noexcept {} + void preStartSetup() noexcept; + void start() noexcept {} + + void addSpanForProcessing(BugsnagPerformanceSpan *span) noexcept; + void removeSpan(BugsnagPerformanceSpan *span) noexcept; + void processPendingSpansIfNeeded() noexcept; + + void addPreprocessStep(std::shared_ptr step) noexcept; + void addPreStartStep(std::shared_ptr step) noexcept; + void addMainFlowStep(std::shared_ptr step) noexcept; + +private: + bool isStarted_{false}; + std::shared_ptr batch_; + NSMutableArray *preStartSpans_; + std::vector> *preprocessFlow_{}; + std::vector> *preStartFlow_{}; + std::vector> *mainFlow_{}; + + std::mutex mutex_; + + void executeFlow(std::vector> *flow, + NSArray *spans) noexcept; +}; +} diff --git a/Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipelineImpl.mm b/Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipelineImpl.mm new file mode 100644 index 00000000..9179572a --- /dev/null +++ b/Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipelineImpl.mm @@ -0,0 +1,89 @@ +// +// SpanProcessingPipelineImpl.mm +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 14/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#import "SpanProcessingPipelineImpl.h" + +using namespace bugsnag; + +void +SpanProcessingPipelineImpl::preStartSetup() noexcept { + std::lock_guard guard(mutex_); + executeFlow(preStartFlow_, preStartSpans_); + [preStartSpans_ removeAllObjects]; + isStarted_ = true; +} + +void +SpanProcessingPipelineImpl::addSpanForProcessing(BugsnagPerformanceSpan *span) noexcept { + std::lock_guard guard(mutex_); + executeFlow(preprocessFlow_, @[span]); + if (isStarted_) { + batch_->add(span); + } else { + [preStartSpans_ addObject:span]; + } +} + +void +SpanProcessingPipelineImpl::removeSpan(BugsnagPerformanceSpan *span) noexcept { + std::lock_guard guard(mutex_); + if (isStarted_) { + batch_->removeSpan(span.traceIdHi, span.traceIdLo, span.spanId); + } else { + [preStartSpans_ removeObject:span]; + } +} + +void +SpanProcessingPipelineImpl::processPendingSpansIfNeeded() noexcept { + std::lock_guard guard(mutex_); + auto spans = batch_->drain(false); + if (spans.count > 0) { + executeFlow(mainFlow_, spans); + } +} + +void +SpanProcessingPipelineImpl::addPreprocessStep(std::shared_ptr step) noexcept { + std::lock_guard guard(mutex_); + preprocessFlow_->push_back(step); +} + +void +SpanProcessingPipelineImpl::addPreStartStep(std::shared_ptr step) noexcept { + std::lock_guard guard(mutex_); + preStartFlow_->push_back(step); +} + +void +SpanProcessingPipelineImpl::addMainFlowStep(std::shared_ptr step) noexcept { + std::lock_guard guard(mutex_); + mainFlow_->push_back(step); +} + +#pragma mark Private + +void +SpanProcessingPipelineImpl::executeFlow(std::vector> *flow, + NSArray *spans) noexcept { + if (!flow || !spans) { + return; + } + NSMutableArray *spansToProcess = [spans mutableCopy]; + + for (const auto& step : *flow) { + NSMutableArray *spansToRemove = [NSMutableArray array]; + for (BugsnagPerformanceSpan *span in spansToProcess) { + bool shouldContinueWithCurrentSpan = step->run(span); + if (!shouldContinueWithCurrentSpan) { + [spansToRemove addObject:span]; + } + } + [spansToProcess removeObjectsInArray:spansToRemove]; + } +} diff --git a/Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipelineStep.h b/Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipelineStep.h new file mode 100644 index 00000000..2c31dd87 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipelineStep.h @@ -0,0 +1,19 @@ +// +// SpanProcessingPipelineStep.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 14/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#import + +namespace bugsnag { + +class SpanProcessingPipelineStep { +public: + virtual bool run(BugsnagPerformanceSpan *span) noexcept = 0; + + virtual ~SpanProcessingPipeline() {} +}; +} From 0ab8e4a77aab7306dbfc3bceed79136e8cedc74c Mon Sep 17 00:00:00 2001 From: Robert Bartoszewski Date: Thu, 16 Oct 2025 00:56:46 +0200 Subject: [PATCH 02/14] Grouped files into modules --- BugsnagPerformance.xcodeproj/project.pbxproj | 344 +++++++++++++----- .../Attributes}/ResourceAttributes.h | 4 +- .../Attributes}/ResourceAttributes.mm | 2 +- .../{ => Core/Attributes}/SpanAttributes.h | 0 .../{ => Core/Attributes}/SpanAttributes.mm | 4 +- .../Attributes}/SpanAttributesProvider.h | 4 +- .../Attributes}/SpanAttributesProvider.mm | 2 +- .../Private/{ => Core}/BSGPrioritizedStore.h | 0 .../Private/{ => Core}/BSGPrioritizedStore.mm | 2 +- .../BugsnagPerformancePriority+Private.h | 0 .../BugsnagPerformancePriority+Private.m | 0 .../BugsnagPerformanceViewType+Private.h | 0 .../{ => Core}/BugsnagPerformanceViewType.mm | 0 .../BugsnagPerformanceConfiguration+Private.h | 0 .../Configuration}/EarlyConfiguration.h | 0 .../Configuration}/EarlyConfiguration.mm | 2 +- .../{ => Core/Configuration}/Metrics.h | 0 .../Private/{ => Core}/PhasedStartup.h | 2 +- .../{ => Core/Sampler}/PersistentState.h | 4 +- .../{ => Core/Sampler}/PersistentState.mm | 6 +- .../Private/{ => Core/Sampler}/Sampler.h | 4 +- .../Span}/BugsnagPerformanceSpan+Private.h | 4 +- .../BugsnagPerformanceSpanContext+Private.h | 0 .../Private/{ => Core/Span}/SpanKind.h | 0 .../Private/{ => Core/Span}/SpanOptions.h | 4 +- .../BugsnagPerformanceSpanCondition+Private.h | 0 .../BugsnagPerformanceSpanCondition.mm | 0 .../ConditionTimeoutExecutor.h | 0 .../AppStartup/AppStartupSpanFactory.h | 2 +- .../AppStartup/AppStartupSpanFactoryImpl.h | 2 +- .../AppStartup/AppStartupSpanFactoryImpl.mm | 1 - .../SpanFactory/Network/NetworkSpanFactory.h | 2 +- .../Network/NetworkSpanFactoryImpl.h | 2 +- .../Network/NetworkSpanFactoryImpl.mm | 0 .../SpanFactory/Plain/PlainSpanFactory.h | 4 +- .../Plain/PlainSpanFactoryCallbacks.h | 2 +- .../Plain/PlainSpanFactoryCallbacks.mm | 0 .../SpanFactory/Plain/PlainSpanFactoryImpl.h | 6 +- .../SpanFactory/Plain/PlainSpanFactoryImpl.mm | 2 +- .../ViewLoad/ViewLoadSpanFactory.h | 2 +- .../ViewLoad/ViewLoadSpanFactoryCallbacks.h | 2 +- .../ViewLoad/ViewLoadSpanFactoryCallbacks.mm | 0 .../ViewLoad/ViewLoadSpanFactoryImpl.h | 2 +- .../ViewLoad/ViewLoadSpanFactoryImpl.mm | 3 +- .../SpanLifecycle/SpanLifecycleHandler.h | 2 +- .../SpanLifecycle/SpanLifecycleHandlerImpl.h | 13 +- .../SpanLifecycle/SpanLifecycleHandlerImpl.mm | 2 +- .../{ => Core/SpanProcessingPipeline}/Batch.h | 10 +- .../SpanProcessingPipeline.h | 0 .../SpanProcessingPipelineImpl.h | 2 +- .../SpanProcessingPipelineImpl.mm | 0 .../SpanProcessingPipelineStep.h | 2 +- .../{ => Core/SpanStack}/SpanActivityState.h | 2 +- .../SpanStack}/SpanStackingHandler.h | 2 +- .../SpanStack}/SpanStackingHandler.mm | 2 +- .../Private/{ => Core}/SpanStore/SpanStore.h | 0 .../{ => Core}/SpanStore/SpanStoreImpl.h | 4 +- .../{ => Core}/SpanStore/SpanStoreImpl.mm | 0 .../{ => Core/SpanStore}/WeakSpansList.h | 2 +- .../{ => Core/SpanStore}/WeakSpansList.mm | 0 .../Private/{ => Core/Worker}/Worker.h | 2 +- .../Private/{ => Core/Worker}/Worker.mm | 2 +- .../BugsnagPerformanceCrossTalkAPI.h | 2 +- .../BugsnagPerformanceCrossTalkAPI.mm | 6 +- .../AppStartupInstrumentation.h | 5 +- .../AppStartupInstrumentation.mm | 9 +- .../AppStartupLifecycleHandlerImpl.h | 6 +- .../AppStartupLifecycleHandlerImpl.mm | 6 +- .../State/AppStartupInstrumentationState.mm | 2 +- ...ppStartupInstrumentationSystemUtilsImpl.mm | 2 +- ...gPerformanceLoadingIndicatorView+Private.h | 0 .../Private/Instrumentation/Instrumentation.h | 16 +- .../Instrumentation/Instrumentation.mm | 4 +- .../Lifecycle/NetworkEarlyPhaseHandlerImpl.h | 2 +- .../Lifecycle/NetworkEarlyPhaseHandlerImpl.mm | 1 + .../Lifecycle/NetworkLifecycleHandlerImpl.h | 3 +- .../Lifecycle/NetworkLifecycleHandlerImpl.mm | 2 +- .../NetworkInstrumentation.h | 5 +- .../NetworkInstrumentation.mm | 4 +- .../System/BSGURLSessionPerformanceDelegate.h | 5 +- .../BSGURLSessionPerformanceDelegate.mm | 2 + .../System/NetworkHeaderInjector.h | 8 +- .../System/NetworkHeaderInjector.mm | 2 +- .../NetworkInstrumentationSystemUtilsImpl.mm | 4 +- .../System/NetworkSwizzlingHandlerImpl.mm | 2 +- .../Proxy/BSGURLSessionPerformanceProxy.mm | 2 +- .../Lifecycle/ViewLoadEarlyPhaseHandlerImpl.h | 3 +- .../ViewLoadEarlyPhaseHandlerImpl.mm | 3 + .../Lifecycle/ViewLoadLifecycleHandlerImpl.h | 6 +- .../Lifecycle/ViewLoadLifecycleHandlerImpl.mm | 3 +- .../ViewLoadLoadingIndicatorsHandlerImpl.mm | 2 +- .../System/ViewLoadSwizzlingHandlerImpl.mm | 2 +- .../ViewLoadInstrumentation.h | 5 +- .../ViewLoadInstrumentation.mm | 11 +- .../{ => Main}/BugsnagPerformanceImpl.h | 50 +-- .../{ => Main}/BugsnagPerformanceImpl.mm | 27 +- .../{ => Main}/BugsnagPerformanceLibrary.h | 6 +- .../{ => Main}/BugsnagPerformanceLibrary.mm | 2 +- .../FrameMetrics}/FrameMetricsCollector.h | 2 +- .../FrameMetrics}/FrameMetricsCollector.mm | 2 +- .../FrameMetrics}/FrameMetricsSnapshot.h | 2 +- .../FrameMetrics}/FrameMetricsSnapshot.mm | 0 .../FrameMetrics}/FrozenFrameData.h | 2 +- .../FrameMetrics}/FrozenFrameData.mm | 0 .../SystemMetrics}/BSGPSystemInfo.h | 2 +- .../SystemMetrics}/BSGPSystemInfo.mm | 2 +- .../SystemMetrics}/SystemInfoSampler.h | 4 +- .../SystemMetrics}/SystemInfoSampler.mm | 4 +- .../BugsnagPerformancePluginContext+Private.h | 0 .../BugsnagPerformancePluginSupport.h | 17 + ...agPerformanceSpanControlProvider+Private.h | 0 .../PluginManager}/BSGPluginManager.h | 4 +- .../PluginManager}/BSGPluginManager.m | 4 +- .../BSGCompositeSpanControlProvider.h | 2 +- .../BSGCompositeSpanControlProvider.m | 0 ...agPerformanceAppStartSpanControl+Private.h | 0 .../BugsnagPerformanceAppStartTypePlugin.h | 4 +- .../BugsnagPerformanceAppStartTypePlugin.mm | 4 +- Sources/BugsnagPerformance/Private/Tracer.h | 18 +- Sources/BugsnagPerformance/Private/Tracer.mm | 10 +- .../Private/{ => Upload/Otlp}/OtlpPackage.h | 0 .../Private/{ => Upload/Otlp}/OtlpPackage.mm | 0 .../{ => Upload/Otlp}/OtlpTraceEncoding.h | 4 +- .../{ => Upload/Otlp}/OtlpTraceEncoding.mm | 6 +- .../Private/{ => Upload/Otlp}/OtlpUploader.h | 0 .../Private/{ => Upload/Otlp}/OtlpUploader.mm | 2 +- .../Private/{ => Upload/Otlp}/Uploader.h | 0 .../Private/{ => Upload}/RetryQueue.h | 4 +- .../Private/{ => Upload}/RetryQueue.mm | 6 +- .../Private/{ => Utils}/AppStateTracker.h | 0 .../Private/{ => Utils}/AppStateTracker.m | 0 .../Private/{ => Utils}/BugsnagSwiftTools.h | 0 .../Private/{ => Utils}/BugsnagSwiftTools.m | 0 .../Private/{ => Utils}/Filesystem.h | 0 .../Private/{ => Utils}/Filesystem.mm | 0 .../Private/{ => Utils}/FixedLengthDequeue.h | 0 .../Private/{ => Utils}/Gzip.h | 0 .../Private/{ => Utils}/Gzip.m | 0 .../Private/{ => Utils}/IdGenerator.h | 0 .../Private/{ => Utils}/JSON.h | 0 .../Private/{ => Utils}/JSON.mm | 0 .../Private/{ => Utils}/Logging.h | 0 .../Private/{ => Utils}/ObjCUtils.h | 0 .../Private/{ => Utils}/ObjCUtils.mm | 0 .../Private/{ => Utils}/Persistence.h | 0 .../Private/{ => Utils}/Persistence.mm | 0 .../Private/{ => Utils}/PersistentDeviceID.h | 2 +- .../Private/{ => Utils}/PersistentDeviceID.mm | 2 +- .../Private/{ => Utils}/Reachability.h | 0 .../Private/{ => Utils}/Reachability.mm | 0 .../Private/{ => Utils}/Swizzle.h | 0 .../Private/{ => Utils}/Swizzle.mm | 0 .../Private/{ => Utils}/Targets.h | 0 .../Private/{ => Utils}/Utils.h | 0 .../Public/BugsnagPerformance.mm | 2 +- .../BugsnagPerformanceAppStartSpanControl.mm | 4 +- .../Public/BugsnagPerformanceConfiguration.mm | 6 +- .../BugsnagPerformanceLoadingIndicatorView.mm | 6 +- .../Public/BugsnagPerformancePluginContext.m | 4 +- .../BugsnagPerformanceRemoteSpanContext.mm | 2 +- .../Public/BugsnagPerformanceSpan.mm | 8 +- .../BugsnagPerformanceSpanCondition.h | 2 - .../BugsnagPerformanceSpanTests.mm | 2 +- .../OtlpTraceEncodingTests.mm | 2 +- .../ResourceAttributesTests.mm | 4 +- Tests/BugsnagPerformanceTests/SamplerTests.mm | 4 +- .../SpanAttributesTests.mm | 2 +- .../ios/Fixture.xcodeproj/project.pbxproj | 2 +- .../project.pbxproj | 2 +- 169 files changed, 506 insertions(+), 342 deletions(-) rename Sources/BugsnagPerformance/Private/{ => Core/Attributes}/ResourceAttributes.h (93%) rename Sources/BugsnagPerformance/Private/{ => Core/Attributes}/ResourceAttributes.mm (99%) rename Sources/BugsnagPerformance/Private/{ => Core/Attributes}/SpanAttributes.h (100%) rename Sources/BugsnagPerformance/Private/{ => Core/Attributes}/SpanAttributes.mm (91%) rename Sources/BugsnagPerformance/Private/{ => Core/Attributes}/SpanAttributesProvider.h (94%) rename Sources/BugsnagPerformance/Private/{ => Core/Attributes}/SpanAttributesProvider.mm (99%) rename Sources/BugsnagPerformance/Private/{ => Core}/BSGPrioritizedStore.h (100%) rename Sources/BugsnagPerformance/Private/{ => Core}/BSGPrioritizedStore.mm (99%) rename Sources/BugsnagPerformance/Private/{ => Core}/BugsnagPerformancePriority+Private.h (100%) rename Sources/BugsnagPerformance/Private/{ => Core}/BugsnagPerformancePriority+Private.m (100%) rename Sources/BugsnagPerformance/Private/{ => Core}/BugsnagPerformanceViewType+Private.h (100%) rename Sources/BugsnagPerformance/Private/{ => Core}/BugsnagPerformanceViewType.mm (100%) rename Sources/BugsnagPerformance/Private/{ => Core/Configuration}/BugsnagPerformanceConfiguration+Private.h (100%) rename Sources/BugsnagPerformance/Private/{ => Core/Configuration}/EarlyConfiguration.h (100%) rename Sources/BugsnagPerformance/Private/{ => Core/Configuration}/EarlyConfiguration.mm (97%) rename Sources/BugsnagPerformance/Private/{ => Core/Configuration}/Metrics.h (100%) rename Sources/BugsnagPerformance/Private/{ => Core}/PhasedStartup.h (98%) rename Sources/BugsnagPerformance/Private/{ => Core/Sampler}/PersistentState.h (93%) rename Sources/BugsnagPerformance/Private/{ => Core/Sampler}/PersistentState.mm (92%) rename Sources/BugsnagPerformance/Private/{ => Core/Sampler}/Sampler.h (94%) rename Sources/BugsnagPerformance/Private/{ => Core/Span}/BugsnagPerformanceSpan+Private.h (96%) rename Sources/BugsnagPerformance/Private/{ => Core/Span}/BugsnagPerformanceSpanContext+Private.h (100%) rename Sources/BugsnagPerformance/Private/{ => Core/Span}/SpanKind.h (100%) rename Sources/BugsnagPerformance/Private/{ => Core/Span}/SpanOptions.h (95%) rename Sources/BugsnagPerformance/Private/{ => Core/SpanConditions}/BugsnagPerformanceSpanCondition+Private.h (100%) rename Sources/BugsnagPerformance/Private/{ => Core/SpanConditions}/BugsnagPerformanceSpanCondition.mm (100%) rename Sources/BugsnagPerformance/Private/{ => Core/SpanConditions}/ConditionTimeoutExecutor.h (100%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanFactory/AppStartup/AppStartupSpanFactory.h (97%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.h (97%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.mm (99%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanFactory/Network/NetworkSpanFactory.h (96%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanFactory/Network/NetworkSpanFactoryImpl.h (96%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanFactory/Network/NetworkSpanFactoryImpl.mm (100%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanFactory/Plain/PlainSpanFactory.h (94%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanFactory/Plain/PlainSpanFactoryCallbacks.h (92%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanFactory/Plain/PlainSpanFactoryCallbacks.mm (100%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanFactory/Plain/PlainSpanFactoryImpl.h (93%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanFactory/Plain/PlainSpanFactoryImpl.mm (98%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanFactory/ViewLoad/ViewLoadSpanFactory.h (98%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanFactory/ViewLoad/ViewLoadSpanFactoryCallbacks.h (92%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanFactory/ViewLoad/ViewLoadSpanFactoryCallbacks.mm (100%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.h (98%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.mm (99%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanLifecycle/SpanLifecycleHandler.h (96%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanLifecycle/SpanLifecycleHandlerImpl.h (92%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanLifecycle/SpanLifecycleHandlerImpl.mm (99%) rename Sources/BugsnagPerformance/Private/{ => Core/SpanProcessingPipeline}/Batch.h (95%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanProcessingPipeline/SpanProcessingPipeline.h (100%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanProcessingPipeline/SpanProcessingPipelineImpl.h (98%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanProcessingPipeline/SpanProcessingPipelineImpl.mm (100%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanProcessingPipeline/SpanProcessingPipelineStep.h (88%) rename Sources/BugsnagPerformance/Private/{ => Core/SpanStack}/SpanActivityState.h (94%) rename Sources/BugsnagPerformance/Private/{ => Core/SpanStack}/SpanStackingHandler.h (95%) rename Sources/BugsnagPerformance/Private/{ => Core/SpanStack}/SpanStackingHandler.mm (99%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanStore/SpanStore.h (100%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanStore/SpanStoreImpl.h (94%) rename Sources/BugsnagPerformance/Private/{ => Core}/SpanStore/SpanStoreImpl.mm (100%) rename Sources/BugsnagPerformance/Private/{ => Core/SpanStore}/WeakSpansList.h (97%) rename Sources/BugsnagPerformance/Private/{ => Core/SpanStore}/WeakSpansList.mm (100%) rename Sources/BugsnagPerformance/Private/{ => Core/Worker}/Worker.h (96%) rename Sources/BugsnagPerformance/Private/{ => Core/Worker}/Worker.mm (97%) rename Sources/BugsnagPerformance/Private/{ => CrossTalkAPI}/BugsnagPerformanceCrossTalkAPI.h (98%) rename Sources/BugsnagPerformance/Private/{ => CrossTalkAPI}/BugsnagPerformanceCrossTalkAPI.mm (99%) rename Sources/BugsnagPerformance/Private/{ => Instrumentation}/BugsnagPerformanceLoadingIndicatorView+Private.h (100%) rename Sources/BugsnagPerformance/Private/{ => Main}/BugsnagPerformanceImpl.h (83%) rename Sources/BugsnagPerformance/Private/{ => Main}/BugsnagPerformanceImpl.mm (97%) rename Sources/BugsnagPerformance/Private/{ => Main}/BugsnagPerformanceLibrary.h (93%) rename Sources/BugsnagPerformance/Private/{ => Main}/BugsnagPerformanceLibrary.mm (99%) rename Sources/BugsnagPerformance/Private/{FrameRateMetrics => Metrics/FrameMetrics}/FrameMetricsCollector.h (91%) rename Sources/BugsnagPerformance/Private/{FrameRateMetrics => Metrics/FrameMetrics}/FrameMetricsCollector.mm (98%) rename Sources/BugsnagPerformance/Private/{FrameRateMetrics => Metrics/FrameMetrics}/FrameMetricsSnapshot.h (94%) rename Sources/BugsnagPerformance/Private/{FrameRateMetrics => Metrics/FrameMetrics}/FrameMetricsSnapshot.mm (100%) rename Sources/BugsnagPerformance/Private/{FrameRateMetrics => Metrics/FrameMetrics}/FrozenFrameData.h (93%) rename Sources/BugsnagPerformance/Private/{FrameRateMetrics => Metrics/FrameMetrics}/FrozenFrameData.mm (100%) rename Sources/BugsnagPerformance/Private/{ => Metrics/SystemMetrics}/BSGPSystemInfo.h (99%) rename Sources/BugsnagPerformance/Private/{ => Metrics/SystemMetrics}/BSGPSystemInfo.mm (99%) rename Sources/BugsnagPerformance/Private/{ => Metrics/SystemMetrics}/SystemInfoSampler.h (97%) rename Sources/BugsnagPerformance/Private/{ => Metrics/SystemMetrics}/SystemInfoSampler.mm (98%) rename Sources/BugsnagPerformance/Private/{ => PluginSupport}/BugsnagPerformancePluginContext+Private.h (100%) create mode 100644 Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformancePluginSupport.h rename Sources/BugsnagPerformance/Private/{ => PluginSupport}/BugsnagPerformanceSpanControlProvider+Private.h (100%) rename Sources/BugsnagPerformance/Private/{ => PluginSupport/PluginManager}/BSGPluginManager.h (89%) rename Sources/BugsnagPerformance/Private/{ => PluginSupport/PluginManager}/BSGPluginManager.m (97%) rename Sources/BugsnagPerformance/Private/{ => PluginSupport}/SpanControl/BSGCompositeSpanControlProvider.h (93%) rename Sources/BugsnagPerformance/Private/{ => PluginSupport}/SpanControl/BSGCompositeSpanControlProvider.m (100%) rename Sources/BugsnagPerformance/Private/{ => Plugins/AppStart}/BugsnagPerformanceAppStartSpanControl+Private.h (100%) rename Sources/BugsnagPerformance/Private/{ => Plugins/AppStart}/BugsnagPerformanceAppStartTypePlugin.h (84%) rename Sources/BugsnagPerformance/Private/{ => Plugins/AppStart}/BugsnagPerformanceAppStartTypePlugin.mm (94%) rename Sources/BugsnagPerformance/Private/{ => Upload/Otlp}/OtlpPackage.h (100%) rename Sources/BugsnagPerformance/Private/{ => Upload/Otlp}/OtlpPackage.mm (100%) rename Sources/BugsnagPerformance/Private/{ => Upload/Otlp}/OtlpTraceEncoding.h (94%) rename Sources/BugsnagPerformance/Private/{ => Upload/Otlp}/OtlpTraceEncoding.mm (99%) rename Sources/BugsnagPerformance/Private/{ => Upload/Otlp}/OtlpUploader.h (100%) rename Sources/BugsnagPerformance/Private/{ => Upload/Otlp}/OtlpUploader.mm (99%) rename Sources/BugsnagPerformance/Private/{ => Upload/Otlp}/Uploader.h (100%) rename Sources/BugsnagPerformance/Private/{ => Upload}/RetryQueue.h (96%) rename Sources/BugsnagPerformance/Private/{ => Upload}/RetryQueue.mm (97%) rename Sources/BugsnagPerformance/Private/{ => Utils}/AppStateTracker.h (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/AppStateTracker.m (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/BugsnagSwiftTools.h (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/BugsnagSwiftTools.m (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/Filesystem.h (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/Filesystem.mm (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/FixedLengthDequeue.h (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/Gzip.h (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/Gzip.m (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/IdGenerator.h (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/JSON.h (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/JSON.mm (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/Logging.h (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/ObjCUtils.h (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/ObjCUtils.mm (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/Persistence.h (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/Persistence.mm (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/PersistentDeviceID.h (97%) rename Sources/BugsnagPerformance/Private/{ => Utils}/PersistentDeviceID.mm (99%) rename Sources/BugsnagPerformance/Private/{ => Utils}/Reachability.h (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/Reachability.mm (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/Swizzle.h (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/Swizzle.mm (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/Targets.h (100%) rename Sources/BugsnagPerformance/Private/{ => Utils}/Utils.h (100%) diff --git a/BugsnagPerformance.xcodeproj/project.pbxproj b/BugsnagPerformance.xcodeproj/project.pbxproj index 98459cd0..d0ced058 100644 --- a/BugsnagPerformance.xcodeproj/project.pbxproj +++ b/BugsnagPerformance.xcodeproj/project.pbxproj @@ -194,6 +194,7 @@ 967949CA2E9DC9CE005FD87F /* SpanProcessingPipelineStep.h in Sources */ = {isa = PBXBuildFile; fileRef = 967949C92E9DC9C5005FD87F /* SpanProcessingPipelineStep.h */; }; 967949CD2E9DCAEE005FD87F /* SpanProcessingPipelineImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 967949CC2E9DCAE0005FD87F /* SpanProcessingPipelineImpl.h */; }; 967949CF2E9DCB06005FD87F /* SpanProcessingPipelineImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 967949CE2E9DCB02005FD87F /* SpanProcessingPipelineImpl.mm */; }; + 967949EC2EA06044005FD87F /* BugsnagPerformancePluginSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 967949EB2EA06038005FD87F /* BugsnagPerformancePluginSupport.h */; }; 967F6F1829C3783B0054EED8 /* BugsnagPerformanceConfiguration+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 967F6F1729C3782D0054EED8 /* BugsnagPerformanceConfiguration+Private.h */; }; 968AA5FB2CCA5A9200BA69CF /* BSGPerformanceSharedSessionProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 968AA5FA2CCA5A9200BA69CF /* BSGPerformanceSharedSessionProxy.h */; }; 968AA5FD2CCA5AB000BA69CF /* BSGPerformanceSharedSessionProxy.mm in Sources */ = {isa = PBXBuildFile; fileRef = 968AA5FC2CCA5AB000BA69CF /* BSGPerformanceSharedSessionProxy.mm */; }; @@ -558,6 +559,7 @@ 967949C92E9DC9C5005FD87F /* SpanProcessingPipelineStep.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SpanProcessingPipelineStep.h; sourceTree = ""; }; 967949CC2E9DCAE0005FD87F /* SpanProcessingPipelineImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SpanProcessingPipelineImpl.h; sourceTree = ""; }; 967949CE2E9DCB02005FD87F /* SpanProcessingPipelineImpl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SpanProcessingPipelineImpl.mm; sourceTree = ""; }; + 967949EB2EA06038005FD87F /* BugsnagPerformancePluginSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BugsnagPerformancePluginSupport.h; sourceTree = ""; }; 967F6F1729C3782D0054EED8 /* BugsnagPerformanceConfiguration+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BugsnagPerformanceConfiguration+Private.h"; sourceTree = ""; }; 968AA5FA2CCA5A9200BA69CF /* BSGPerformanceSharedSessionProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BSGPerformanceSharedSessionProxy.h; sourceTree = ""; }; 968AA5FC2CCA5AB000BA69CF /* BSGPerformanceSharedSessionProxy.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = BSGPerformanceSharedSessionProxy.mm; sourceTree = ""; }; @@ -798,103 +800,18 @@ 0122C21F29019770002D243C /* Private */ = { isa = PBXGroup; children = ( - CB572EA829BB783200FD7A2A /* AppStateTracker.h */, - CB572EA929BB783200FD7A2A /* AppStateTracker.m */, - CBE8EA1C294B5E1500702950 /* Batch.h */, - 963726E52DF1DFBA00C739E6 /* BSGPluginManager.h */, - 963726E72DF1DFCB00C739E6 /* BSGPluginManager.m */, - 963726CD2DEAB33D00C739E6 /* BSGPrioritizedStore.h */, - 963726CF2DEAB36600C739E6 /* BSGPrioritizedStore.mm */, - 098FC8452D2EB8E8001B627D /* BSGPSystemInfo.h */, - 098FC8442D2EB8E8001B627D /* BSGPSystemInfo.mm */, - 1C68DB942E53528D002621D1 /* BugsnagPerformanceAppStartSpanControl+Private.h */, - 1C68DBA22E535DEE002621D1 /* BugsnagPerformanceAppStartTypePlugin.h */, - 1C68DBA42E535E1E002621D1 /* BugsnagPerformanceAppStartTypePlugin.mm */, - 967F6F1729C3782D0054EED8 /* BugsnagPerformanceConfiguration+Private.h */, - 09FFD43E2BEE3DE2009B0E04 /* BugsnagPerformanceCrossTalkAPI.h */, - 09FFD43F2BEE3DE2009B0E04 /* BugsnagPerformanceCrossTalkAPI.mm */, - CBE8EA14294B528100702950 /* BugsnagPerformanceImpl.h */, - CBE8EA15294B528100702950 /* BugsnagPerformanceImpl.mm */, - CB78819B29E587CE00A58906 /* BugsnagPerformanceLibrary.h */, - CB78819A29E587CE00A58906 /* BugsnagPerformanceLibrary.mm */, - 962CE7D42E60967500380522 /* BugsnagPerformanceLoadingIndicatorView+Private.h */, - 963726E12DF101DF00C739E6 /* BugsnagPerformancePluginContext+Private.h */, - 963726C92DEAB23E00C739E6 /* BugsnagPerformancePriority+Private.h */, - 963726CB2DEAB25200C739E6 /* BugsnagPerformancePriority+Private.m */, - 0122C23229019770002D243C /* BugsnagPerformanceSpan+Private.h */, - 964B78552D4B924C00FF077D /* BugsnagPerformanceSpanCondition.mm */, - 964B785E2D504FD800FF077D /* BugsnagPerformanceSpanCondition+Private.h */, - 09DC62282C6A2EF6000AA8E1 /* BugsnagPerformanceSpanContext+Private.h */, - 963726E32DF19D7B00C739E6 /* BugsnagPerformanceSpanControlProvider+Private.h */, - CBE0873029FA984C007455F2 /* BugsnagPerformanceViewType.mm */, - CBE0873129FA984C007455F2 /* BugsnagPerformanceViewType+Private.h */, - 09F23A8A2CE351ED00F0D769 /* BugsnagSwiftTools.h */, - 09F23A8B2CE351ED00F0D769 /* BugsnagSwiftTools.m */, - 964B78512D47D26F00FF077D /* ConditionTimeoutExecutor.h */, - CBA22C942A0137230066A2C1 /* EarlyConfiguration.h */, - CBA22C952A0137230066A2C1 /* EarlyConfiguration.mm */, - CBEC51D42976BCAD009C0CE3 /* Filesystem.h */, - CBEC51D52976BCAD009C0CE3 /* Filesystem.mm */, - 098FC84D2D350E60001B627D /* FixedLengthDequeue.h */, - 966634D82C8A3939004A934D /* FrameRateMetrics */, - CBF7C5DF297A8E9100D47719 /* Gzip.h */, - CBF7C5E0297A8E9100D47719 /* Gzip.m */, - 0122C22229019770002D243C /* IdGenerator.h */, + 967949D22EA05615005FD87F /* Core */, + 967949DD2EA05A8F005FD87F /* CrossTalkAPI */, 0122C22929019770002D243C /* Instrumentation */, - CBEC51BE296DB311009C0CE3 /* JSON.h */, - CBEC51BF296DB311009C0CE3 /* JSON.mm */, - 965FBD142DF24D3100D6BACB /* Logging.h */, - 098FC8772D3E8D43001B627D /* Metrics.h */, - CBB48A3A295EE1E10044E9AC /* ObjCUtils.h */, - CBB48A3B295EE1E10044E9AC /* ObjCUtils.mm */, - CB04969529150D860097E526 /* OtlpPackage.h */, - CB04969629150D860097E526 /* OtlpPackage.mm */, - 0122C22029019770002D243C /* OtlpTraceEncoding.h */, - 0122C23029019770002D243C /* OtlpTraceEncoding.mm */, - CB0496992915194E0097E526 /* OtlpUploader.h */, - CB04969A2915194E0097E526 /* OtlpUploader.mm */, - CBEC51B6296D8386009C0CE3 /* Persistence.h */, - CBEC51B7296D8386009C0CE3 /* Persistence.mm */, - CB68FAB72A3C27B9005B2CDB /* PersistentDeviceID.h */, - CB68FAB82A3C27B9005B2CDB /* PersistentDeviceID.mm */, - CBEC51BA296D9EED009C0CE3 /* PersistentState.h */, - CBEC51BB296D9EED009C0CE3 /* PersistentState.mm */, - CB78819F29E698BF00A58906 /* PhasedStartup.h */, - 01A414CF2913C238003152A4 /* Reachability.h */, - 01A414D02913C238003152A4 /* Reachability.mm */, - 015836BF29125E7A002F54C8 /* ResourceAttributes.h */, - 015836C029125E7A002F54C8 /* ResourceAttributes.mm */, - CBEC51DA2976F1F9009C0CE3 /* RetryQueue.h */, - CBEC51DB2976F1F9009C0CE3 /* RetryQueue.mm */, - 01A58C0C29092D25006E4DF7 /* Sampler.h */, - 96D55C822A1EBA35006D1F29 /* SpanActivityState.h */, - 01A414CB2913C0F0003152A4 /* SpanAttributes.h */, - 01A414CC2913C0F0003152A4 /* SpanAttributes.mm */, - 96D4160D29F276FE00AEE435 /* SpanAttributesProvider.h */, - 96D4160B29F276E400AEE435 /* SpanAttributesProvider.mm */, - 963726C42DEAB14D00C739E6 /* SpanControl */, - 969EE0EE2E7872A600600F63 /* SpanFactory */, - 0122C22329019770002D243C /* SpanKind.h */, - 967949B42E97CC7F005FD87F /* SpanLifecycle */, - CB7FD935299D330500499E13 /* SpanOptions.h */, - 967949C62E9DC991005FD87F /* SpanProcessingPipeline */, - 96D55C7D2A1EA5A8006D1F29 /* SpanStackingHandler.h */, - 96D55C7F2A1EA5C6006D1F29 /* SpanStackingHandler.mm */, - 967949BB2E99372C005FD87F /* SpanStore */, - CBEBE59129F2783C00BF0B4F /* Swizzle.h */, - CBEBE59029F2783C00BF0B4F /* Swizzle.mm */, - 098FC8532D37A08D001B627D /* SystemInfoSampler.h */, - 098FC8522D37A08D001B627D /* SystemInfoSampler.mm */, - CBC90C4429C84DEB00280884 /* Targets.h */, + 967949D32EA05645005FD87F /* Main */, + 967949D12EA0560D005FD87F /* Metrics */, + 967949DC2EA05A0C005FD87F /* Plugins */, + 967949D82EA05897005FD87F /* PluginSupport */, 0122C23329019770002D243C /* Tracer.h */, 0122C22529019770002D243C /* Tracer.mm */, - CBF621052919418F004BEE0B /* Uploader.h */, - 01EAF97F291AAF19007AC627 /* Utils.h */, + 967949D62EA0578E005FD87F /* Upload */, + 967949D52EA056D6005FD87F /* Utils */, 015836C3291264E0002F54C8 /* Version.h */, - 09B473052B23087D0024CF11 /* WeakSpansList.h */, - 0986B7BF2B287C9D00BD2CA3 /* WeakSpansList.mm */, - CBE8EA18294B5AB800702950 /* Worker.h */, - CBE8EA19294B5AB800702950 /* Worker.mm */, ); path = Private; sourceTree = ""; @@ -903,6 +820,7 @@ isa = PBXGroup; children = ( 963829032E547BA400404F3A /* AppStartupInstrumentation */, + 962CE7D42E60967500380522 /* BugsnagPerformanceLoadingIndicatorView+Private.h */, CBEBE59829F671A800BF0B4F /* Instrumentation.h */, CBEBE59929F671A800BF0B4F /* Instrumentation.mm */, CB34771929068C350033759C /* NetworkInstrumentation */, @@ -1187,7 +1105,7 @@ path = Lifecycle; sourceTree = ""; }; - 966634D82C8A3939004A934D /* FrameRateMetrics */ = { + 966634D82C8A3939004A934D /* FrameMetrics */ = { isa = PBXGroup; children = ( 966634D02C8909BB004A934D /* FrameMetricsCollector.h */, @@ -1197,7 +1115,7 @@ 966634D92C8A39B1004A934D /* FrozenFrameData.h */, 966634DB2C8A39C1004A934D /* FrozenFrameData.mm */, ); - path = FrameRateMetrics; + path = FrameMetrics; sourceTree = ""; }; 967949B42E97CC7F005FD87F /* SpanLifecycle */ = { @@ -1216,6 +1134,8 @@ 967949BC2E993735005FD87F /* SpanStore.h */, 967949BE2E993742005FD87F /* SpanStoreImpl.h */, 967949C02E99374E005FD87F /* SpanStoreImpl.mm */, + 09B473052B23087D0024CF11 /* WeakSpansList.h */, + 0986B7BF2B287C9D00BD2CA3 /* WeakSpansList.mm */, ); path = SpanStore; sourceTree = ""; @@ -1223,20 +1143,247 @@ 967949C62E9DC991005FD87F /* SpanProcessingPipeline */ = { isa = PBXGroup; children = ( + CBE8EA1C294B5E1500702950 /* Batch.h */, 967949C72E9DC9A1005FD87F /* SpanProcessingPipeline.h */, 967949CC2E9DCAE0005FD87F /* SpanProcessingPipelineImpl.h */, 967949CE2E9DCB02005FD87F /* SpanProcessingPipelineImpl.mm */, 967949C92E9DC9C5005FD87F /* SpanProcessingPipelineStep.h */, - 967949CB2E9DC9E9005FD87F /* Steps */, ); path = SpanProcessingPipeline; sourceTree = ""; }; - 967949CB2E9DC9E9005FD87F /* Steps */ = { + 967949D12EA0560D005FD87F /* Metrics */ = { + isa = PBXGroup; + children = ( + 966634D82C8A3939004A934D /* FrameMetrics */, + 967949D42EA0567E005FD87F /* SystemMetrics */, + ); + path = Metrics; + sourceTree = ""; + }; + 967949D22EA05615005FD87F /* Core */ = { + isa = PBXGroup; + children = ( + 967949D72EA05844005FD87F /* Attributes */, + 963726CD2DEAB33D00C739E6 /* BSGPrioritizedStore.h */, + 963726CF2DEAB36600C739E6 /* BSGPrioritizedStore.mm */, + 963726C92DEAB23E00C739E6 /* BugsnagPerformancePriority+Private.h */, + 963726CB2DEAB25200C739E6 /* BugsnagPerformancePriority+Private.m */, + CBE0873029FA984C007455F2 /* BugsnagPerformanceViewType.mm */, + CBE0873129FA984C007455F2 /* BugsnagPerformanceViewType+Private.h */, + 967949DF2EA05B37005FD87F /* Configuration */, + CB78819F29E698BF00A58906 /* PhasedStartup.h */, + 967949E32EA05C85005FD87F /* Sampler */, + 967949E12EA05BE6005FD87F /* Span */, + 967949DE2EA05AF4005FD87F /* SpanConditions */, + 969EE0EE2E7872A600600F63 /* SpanFactory */, + 967949B42E97CC7F005FD87F /* SpanLifecycle */, + 967949C62E9DC991005FD87F /* SpanProcessingPipeline */, + 967949DB2EA059C0005FD87F /* SpanStack */, + 967949BB2E99372C005FD87F /* SpanStore */, + 967949E02EA05B58005FD87F /* Worker */, + ); + path = Core; + sourceTree = ""; + }; + 967949D32EA05645005FD87F /* Main */ = { + isa = PBXGroup; + children = ( + CBE8EA14294B528100702950 /* BugsnagPerformanceImpl.h */, + CBE8EA15294B528100702950 /* BugsnagPerformanceImpl.mm */, + CB78819B29E587CE00A58906 /* BugsnagPerformanceLibrary.h */, + CB78819A29E587CE00A58906 /* BugsnagPerformanceLibrary.mm */, + ); + path = Main; + sourceTree = ""; + }; + 967949D42EA0567E005FD87F /* SystemMetrics */ = { + isa = PBXGroup; + children = ( + 098FC8452D2EB8E8001B627D /* BSGPSystemInfo.h */, + 098FC8442D2EB8E8001B627D /* BSGPSystemInfo.mm */, + 098FC8532D37A08D001B627D /* SystemInfoSampler.h */, + 098FC8522D37A08D001B627D /* SystemInfoSampler.mm */, + ); + path = SystemMetrics; + sourceTree = ""; + }; + 967949D52EA056D6005FD87F /* Utils */ = { + isa = PBXGroup; + children = ( + CB572EA829BB783200FD7A2A /* AppStateTracker.h */, + CB572EA929BB783200FD7A2A /* AppStateTracker.m */, + 09F23A8A2CE351ED00F0D769 /* BugsnagSwiftTools.h */, + 09F23A8B2CE351ED00F0D769 /* BugsnagSwiftTools.m */, + CBEC51D42976BCAD009C0CE3 /* Filesystem.h */, + CBEC51D52976BCAD009C0CE3 /* Filesystem.mm */, + 098FC84D2D350E60001B627D /* FixedLengthDequeue.h */, + CBF7C5DF297A8E9100D47719 /* Gzip.h */, + CBF7C5E0297A8E9100D47719 /* Gzip.m */, + 0122C22229019770002D243C /* IdGenerator.h */, + CBEC51BE296DB311009C0CE3 /* JSON.h */, + CBEC51BF296DB311009C0CE3 /* JSON.mm */, + 965FBD142DF24D3100D6BACB /* Logging.h */, + CBB48A3A295EE1E10044E9AC /* ObjCUtils.h */, + CBB48A3B295EE1E10044E9AC /* ObjCUtils.mm */, + CBEC51B6296D8386009C0CE3 /* Persistence.h */, + CBEC51B7296D8386009C0CE3 /* Persistence.mm */, + CB68FAB72A3C27B9005B2CDB /* PersistentDeviceID.h */, + CB68FAB82A3C27B9005B2CDB /* PersistentDeviceID.mm */, + 01A414CF2913C238003152A4 /* Reachability.h */, + 01A414D02913C238003152A4 /* Reachability.mm */, + CBEBE59129F2783C00BF0B4F /* Swizzle.h */, + CBEBE59029F2783C00BF0B4F /* Swizzle.mm */, + CBC90C4429C84DEB00280884 /* Targets.h */, + 01EAF97F291AAF19007AC627 /* Utils.h */, + ); + path = Utils; + sourceTree = ""; + }; + 967949D62EA0578E005FD87F /* Upload */ = { + isa = PBXGroup; + children = ( + 967949DA2EA0592E005FD87F /* Otlp */, + CBEC51DA2976F1F9009C0CE3 /* RetryQueue.h */, + CBEC51DB2976F1F9009C0CE3 /* RetryQueue.mm */, + ); + path = Upload; + sourceTree = ""; + }; + 967949D72EA05844005FD87F /* Attributes */ = { isa = PBXGroup; children = ( + 015836BF29125E7A002F54C8 /* ResourceAttributes.h */, + 015836C029125E7A002F54C8 /* ResourceAttributes.mm */, + 01A414CB2913C0F0003152A4 /* SpanAttributes.h */, + 01A414CC2913C0F0003152A4 /* SpanAttributes.mm */, + 96D4160D29F276FE00AEE435 /* SpanAttributesProvider.h */, + 96D4160B29F276E400AEE435 /* SpanAttributesProvider.mm */, + ); + path = Attributes; + sourceTree = ""; + }; + 967949D82EA05897005FD87F /* PluginSupport */ = { + isa = PBXGroup; + children = ( + 963726E12DF101DF00C739E6 /* BugsnagPerformancePluginContext+Private.h */, + 967949EB2EA06038005FD87F /* BugsnagPerformancePluginSupport.h */, + 963726E32DF19D7B00C739E6 /* BugsnagPerformanceSpanControlProvider+Private.h */, + 967949D92EA05901005FD87F /* PluginManager */, + 963726C42DEAB14D00C739E6 /* SpanControl */, + ); + path = PluginSupport; + sourceTree = ""; + }; + 967949D92EA05901005FD87F /* PluginManager */ = { + isa = PBXGroup; + children = ( + 963726E52DF1DFBA00C739E6 /* BSGPluginManager.h */, + 963726E72DF1DFCB00C739E6 /* BSGPluginManager.m */, + ); + path = PluginManager; + sourceTree = ""; + }; + 967949DA2EA0592E005FD87F /* Otlp */ = { + isa = PBXGroup; + children = ( + CB04969529150D860097E526 /* OtlpPackage.h */, + CB04969629150D860097E526 /* OtlpPackage.mm */, + 0122C22029019770002D243C /* OtlpTraceEncoding.h */, + 0122C23029019770002D243C /* OtlpTraceEncoding.mm */, + CB0496992915194E0097E526 /* OtlpUploader.h */, + CB04969A2915194E0097E526 /* OtlpUploader.mm */, + CBF621052919418F004BEE0B /* Uploader.h */, + ); + path = Otlp; + sourceTree = ""; + }; + 967949DB2EA059C0005FD87F /* SpanStack */ = { + isa = PBXGroup; + children = ( + 96D55C822A1EBA35006D1F29 /* SpanActivityState.h */, + 96D55C7D2A1EA5A8006D1F29 /* SpanStackingHandler.h */, + 96D55C7F2A1EA5C6006D1F29 /* SpanStackingHandler.mm */, + ); + path = SpanStack; + sourceTree = ""; + }; + 967949DC2EA05A0C005FD87F /* Plugins */ = { + isa = PBXGroup; + children = ( + 967949E22EA05C3B005FD87F /* AppStart */, + ); + path = Plugins; + sourceTree = ""; + }; + 967949DD2EA05A8F005FD87F /* CrossTalkAPI */ = { + isa = PBXGroup; + children = ( + 09FFD43E2BEE3DE2009B0E04 /* BugsnagPerformanceCrossTalkAPI.h */, + 09FFD43F2BEE3DE2009B0E04 /* BugsnagPerformanceCrossTalkAPI.mm */, + ); + path = CrossTalkAPI; + sourceTree = ""; + }; + 967949DE2EA05AF4005FD87F /* SpanConditions */ = { + isa = PBXGroup; + children = ( + 964B78552D4B924C00FF077D /* BugsnagPerformanceSpanCondition.mm */, + 964B785E2D504FD800FF077D /* BugsnagPerformanceSpanCondition+Private.h */, + 964B78512D47D26F00FF077D /* ConditionTimeoutExecutor.h */, + ); + path = SpanConditions; + sourceTree = ""; + }; + 967949DF2EA05B37005FD87F /* Configuration */ = { + isa = PBXGroup; + children = ( + 967F6F1729C3782D0054EED8 /* BugsnagPerformanceConfiguration+Private.h */, + CBA22C942A0137230066A2C1 /* EarlyConfiguration.h */, + CBA22C952A0137230066A2C1 /* EarlyConfiguration.mm */, + 098FC8772D3E8D43001B627D /* Metrics.h */, + ); + path = Configuration; + sourceTree = ""; + }; + 967949E02EA05B58005FD87F /* Worker */ = { + isa = PBXGroup; + children = ( + CBE8EA18294B5AB800702950 /* Worker.h */, + CBE8EA19294B5AB800702950 /* Worker.mm */, + ); + path = Worker; + sourceTree = ""; + }; + 967949E12EA05BE6005FD87F /* Span */ = { + isa = PBXGroup; + children = ( + 0122C23229019770002D243C /* BugsnagPerformanceSpan+Private.h */, + 09DC62282C6A2EF6000AA8E1 /* BugsnagPerformanceSpanContext+Private.h */, + 0122C22329019770002D243C /* SpanKind.h */, + CB7FD935299D330500499E13 /* SpanOptions.h */, + ); + path = Span; + sourceTree = ""; + }; + 967949E22EA05C3B005FD87F /* AppStart */ = { + isa = PBXGroup; + children = ( + 1C68DB942E53528D002621D1 /* BugsnagPerformanceAppStartSpanControl+Private.h */, + 1C68DBA22E535DEE002621D1 /* BugsnagPerformanceAppStartTypePlugin.h */, + 1C68DBA42E535E1E002621D1 /* BugsnagPerformanceAppStartTypePlugin.mm */, + ); + path = AppStart; + sourceTree = ""; + }; + 967949E32EA05C85005FD87F /* Sampler */ = { + isa = PBXGroup; + children = ( + CBEC51BA296D9EED009C0CE3 /* PersistentState.h */, + CBEC51BB296D9EED009C0CE3 /* PersistentState.mm */, + 01A58C0C29092D25006E4DF7 /* Sampler.h */, ); - path = Steps; + path = Sampler; sourceTree = ""; }; 969EE0EE2E7872A600600F63 /* SpanFactory */ = { @@ -1420,6 +1567,7 @@ 0921F02B2A67CBD600C764EB /* BugsnagPerformanceNetworkRequestInfo.h in Headers */, 962CE7D52E60967A00380522 /* BugsnagPerformanceLoadingIndicatorView+Private.h in Headers */, 963726CA2DEAB24900C739E6 /* BugsnagPerformancePriority+Private.h in Headers */, + 967949EC2EA06044005FD87F /* BugsnagPerformancePluginSupport.h in Headers */, 962CE7DF2E60988100380522 /* ViewLoadEarlyPhaseHandlerImpl.h in Headers */, 964B785F2D504FD800FF077D /* BugsnagPerformanceSpanCondition+Private.h in Headers */, 963726C62DEAB14D00C739E6 /* BSGCompositeSpanControlProvider.h in Headers */, diff --git a/Sources/BugsnagPerformance/Private/ResourceAttributes.h b/Sources/BugsnagPerformance/Private/Core/Attributes/ResourceAttributes.h similarity index 93% rename from Sources/BugsnagPerformance/Private/ResourceAttributes.h rename to Sources/BugsnagPerformance/Private/Core/Attributes/ResourceAttributes.h index 084d6ac2..1180256a 100644 --- a/Sources/BugsnagPerformance/Private/ResourceAttributes.h +++ b/Sources/BugsnagPerformance/Private/Core/Attributes/ResourceAttributes.h @@ -8,8 +8,8 @@ #pragma once -#import "PhasedStartup.h" -#import "PersistentDeviceID.h" +#import "../PhasedStartup.h" +#import "../../Utils/PersistentDeviceID.h" #import NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/ResourceAttributes.mm b/Sources/BugsnagPerformance/Private/Core/Attributes/ResourceAttributes.mm similarity index 99% rename from Sources/BugsnagPerformance/Private/ResourceAttributes.mm rename to Sources/BugsnagPerformance/Private/Core/Attributes/ResourceAttributes.mm index 8a5389b9..477ab794 100644 --- a/Sources/BugsnagPerformance/Private/ResourceAttributes.mm +++ b/Sources/BugsnagPerformance/Private/Core/Attributes/ResourceAttributes.mm @@ -8,7 +8,7 @@ #import "ResourceAttributes.h" -#import "Version.h" +#import "../../Version.h" #import #import diff --git a/Sources/BugsnagPerformance/Private/SpanAttributes.h b/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributes.h similarity index 100% rename from Sources/BugsnagPerformance/Private/SpanAttributes.h rename to Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributes.h diff --git a/Sources/BugsnagPerformance/Private/SpanAttributes.mm b/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributes.mm similarity index 91% rename from Sources/BugsnagPerformance/Private/SpanAttributes.mm rename to Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributes.mm index 060cac6a..316a213e 100644 --- a/Sources/BugsnagPerformance/Private/SpanAttributes.mm +++ b/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributes.mm @@ -8,8 +8,8 @@ #import "SpanAttributes.h" -#import "BugsnagPerformanceLibrary.h" -#import "AppStateTracker.h" +#import "../../Main/BugsnagPerformanceLibrary.h" +#import "../../Utils/AppStateTracker.h" using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Private/SpanAttributesProvider.h b/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributesProvider.h similarity index 94% rename from Sources/BugsnagPerformance/Private/SpanAttributesProvider.h rename to Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributesProvider.h index e9e1b4f0..ac1250c7 100644 --- a/Sources/BugsnagPerformance/Private/SpanAttributesProvider.h +++ b/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributesProvider.h @@ -6,8 +6,8 @@ // Copyright © 2023 Bugsnag. All rights reserved. // #import -#import "BugsnagPerformanceViewType+Private.h" -#import "SystemInfoSampler.h" +#import "../BugsnagPerformanceViewType+Private.h" +#import "../../Metrics/SystemMetrics/SystemInfoSampler.h" namespace bugsnag { class SpanAttributesProvider { diff --git a/Sources/BugsnagPerformance/Private/SpanAttributesProvider.mm b/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributesProvider.mm similarity index 99% rename from Sources/BugsnagPerformance/Private/SpanAttributesProvider.mm rename to Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributesProvider.mm index d9bf155a..76164147 100644 --- a/Sources/BugsnagPerformance/Private/SpanAttributesProvider.mm +++ b/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributesProvider.mm @@ -8,7 +8,7 @@ #import "SpanAttributesProvider.h" #import -#import "Utils.h" +#import "../../Utils/Utils.h" #if TARGET_OS_IOS #import #endif diff --git a/Sources/BugsnagPerformance/Private/BSGPrioritizedStore.h b/Sources/BugsnagPerformance/Private/Core/BSGPrioritizedStore.h similarity index 100% rename from Sources/BugsnagPerformance/Private/BSGPrioritizedStore.h rename to Sources/BugsnagPerformance/Private/Core/BSGPrioritizedStore.h diff --git a/Sources/BugsnagPerformance/Private/BSGPrioritizedStore.mm b/Sources/BugsnagPerformance/Private/Core/BSGPrioritizedStore.mm similarity index 99% rename from Sources/BugsnagPerformance/Private/BSGPrioritizedStore.mm rename to Sources/BugsnagPerformance/Private/Core/BSGPrioritizedStore.mm index b61e2a63..6fa7efe7 100644 --- a/Sources/BugsnagPerformance/Private/BSGPrioritizedStore.mm +++ b/Sources/BugsnagPerformance/Private/Core/BSGPrioritizedStore.mm @@ -7,7 +7,7 @@ // #import "BSGPrioritizedStore.h" -#import "Utils.h" +#import "../Utils/Utils.h" @interface BSGPrioritizedStoreEntry: NSObject @property (nonatomic, strong) id object; diff --git a/Sources/BugsnagPerformance/Private/BugsnagPerformancePriority+Private.h b/Sources/BugsnagPerformance/Private/Core/BugsnagPerformancePriority+Private.h similarity index 100% rename from Sources/BugsnagPerformance/Private/BugsnagPerformancePriority+Private.h rename to Sources/BugsnagPerformance/Private/Core/BugsnagPerformancePriority+Private.h diff --git a/Sources/BugsnagPerformance/Private/BugsnagPerformancePriority+Private.m b/Sources/BugsnagPerformance/Private/Core/BugsnagPerformancePriority+Private.m similarity index 100% rename from Sources/BugsnagPerformance/Private/BugsnagPerformancePriority+Private.m rename to Sources/BugsnagPerformance/Private/Core/BugsnagPerformancePriority+Private.m diff --git a/Sources/BugsnagPerformance/Private/BugsnagPerformanceViewType+Private.h b/Sources/BugsnagPerformance/Private/Core/BugsnagPerformanceViewType+Private.h similarity index 100% rename from Sources/BugsnagPerformance/Private/BugsnagPerformanceViewType+Private.h rename to Sources/BugsnagPerformance/Private/Core/BugsnagPerformanceViewType+Private.h diff --git a/Sources/BugsnagPerformance/Private/BugsnagPerformanceViewType.mm b/Sources/BugsnagPerformance/Private/Core/BugsnagPerformanceViewType.mm similarity index 100% rename from Sources/BugsnagPerformance/Private/BugsnagPerformanceViewType.mm rename to Sources/BugsnagPerformance/Private/Core/BugsnagPerformanceViewType.mm diff --git a/Sources/BugsnagPerformance/Private/BugsnagPerformanceConfiguration+Private.h b/Sources/BugsnagPerformance/Private/Core/Configuration/BugsnagPerformanceConfiguration+Private.h similarity index 100% rename from Sources/BugsnagPerformance/Private/BugsnagPerformanceConfiguration+Private.h rename to Sources/BugsnagPerformance/Private/Core/Configuration/BugsnagPerformanceConfiguration+Private.h diff --git a/Sources/BugsnagPerformance/Private/EarlyConfiguration.h b/Sources/BugsnagPerformance/Private/Core/Configuration/EarlyConfiguration.h similarity index 100% rename from Sources/BugsnagPerformance/Private/EarlyConfiguration.h rename to Sources/BugsnagPerformance/Private/Core/Configuration/EarlyConfiguration.h diff --git a/Sources/BugsnagPerformance/Private/EarlyConfiguration.mm b/Sources/BugsnagPerformance/Private/Core/Configuration/EarlyConfiguration.mm similarity index 97% rename from Sources/BugsnagPerformance/Private/EarlyConfiguration.mm rename to Sources/BugsnagPerformance/Private/Core/Configuration/EarlyConfiguration.mm index 61f9f011..731e879a 100644 --- a/Sources/BugsnagPerformance/Private/EarlyConfiguration.mm +++ b/Sources/BugsnagPerformance/Private/Core/Configuration/EarlyConfiguration.mm @@ -7,7 +7,7 @@ // #import "EarlyConfiguration.h" -#import "Utils.h" +#import "../../Utils/Utils.h" @implementation BSGEarlyConfiguration diff --git a/Sources/BugsnagPerformance/Private/Metrics.h b/Sources/BugsnagPerformance/Private/Core/Configuration/Metrics.h similarity index 100% rename from Sources/BugsnagPerformance/Private/Metrics.h rename to Sources/BugsnagPerformance/Private/Core/Configuration/Metrics.h diff --git a/Sources/BugsnagPerformance/Private/PhasedStartup.h b/Sources/BugsnagPerformance/Private/Core/PhasedStartup.h similarity index 98% rename from Sources/BugsnagPerformance/Private/PhasedStartup.h rename to Sources/BugsnagPerformance/Private/Core/PhasedStartup.h index 63821efb..6ba3aa47 100644 --- a/Sources/BugsnagPerformance/Private/PhasedStartup.h +++ b/Sources/BugsnagPerformance/Private/Core/PhasedStartup.h @@ -9,7 +9,7 @@ #pragma once #import -#import "EarlyConfiguration.h" +#import "Configuration/EarlyConfiguration.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/PersistentState.h b/Sources/BugsnagPerformance/Private/Core/Sampler/PersistentState.h similarity index 93% rename from Sources/BugsnagPerformance/Private/PersistentState.h rename to Sources/BugsnagPerformance/Private/Core/Sampler/PersistentState.h index 89f0044b..fae22353 100644 --- a/Sources/BugsnagPerformance/Private/PersistentState.h +++ b/Sources/BugsnagPerformance/Private/Core/Sampler/PersistentState.h @@ -8,8 +8,8 @@ #pragma once -#import "PhasedStartup.h" -#import "Persistence.h" +#import "../PhasedStartup.h" +#import "../../Utils/Persistence.h" #import #import diff --git a/Sources/BugsnagPerformance/Private/PersistentState.mm b/Sources/BugsnagPerformance/Private/Core/Sampler/PersistentState.mm similarity index 92% rename from Sources/BugsnagPerformance/Private/PersistentState.mm rename to Sources/BugsnagPerformance/Private/Core/Sampler/PersistentState.mm index 83e1c060..8996c412 100644 --- a/Sources/BugsnagPerformance/Private/PersistentState.mm +++ b/Sources/BugsnagPerformance/Private/Core/Sampler/PersistentState.mm @@ -7,9 +7,9 @@ // #import "PersistentState.h" -#import "JSON.h" -#import "Filesystem.h" -#import "BugsnagPerformanceConfiguration+Private.h" +#import "../../Utils/JSON.h" +#import "../../Utils/Filesystem.h" +#import "../Configuration/BugsnagPerformanceConfiguration+Private.h" using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Private/Sampler.h b/Sources/BugsnagPerformance/Private/Core/Sampler/Sampler.h similarity index 94% rename from Sources/BugsnagPerformance/Private/Sampler.h rename to Sources/BugsnagPerformance/Private/Core/Sampler/Sampler.h index 4e6447cc..b323afe9 100644 --- a/Sources/BugsnagPerformance/Private/Sampler.h +++ b/Sources/BugsnagPerformance/Private/Core/Sampler/Sampler.h @@ -7,8 +7,8 @@ #pragma once -#import "IdGenerator.h" -#import "BugsnagPerformanceSpan+Private.h" +#import "../../Utils/IdGenerator.h" +#import "../Span/BugsnagPerformanceSpan+Private.h" #import #import diff --git a/Sources/BugsnagPerformance/Private/BugsnagPerformanceSpan+Private.h b/Sources/BugsnagPerformance/Private/Core/Span/BugsnagPerformanceSpan+Private.h similarity index 96% rename from Sources/BugsnagPerformance/Private/BugsnagPerformanceSpan+Private.h rename to Sources/BugsnagPerformance/Private/Core/Span/BugsnagPerformanceSpan+Private.h index 0d9c6ecd..2ee3e12d 100644 --- a/Sources/BugsnagPerformance/Private/BugsnagPerformanceSpan+Private.h +++ b/Sources/BugsnagPerformance/Private/Core/Span/BugsnagPerformanceSpan+Private.h @@ -10,9 +10,9 @@ #import #import "BugsnagPerformanceSpanContext+Private.h" #import "SpanKind.h" -#import "FrameRateMetrics/FrameMetricsSnapshot.h" +#import "../../Metrics/FrameMetrics/FrameMetricsSnapshot.h" #import "SpanOptions.h" -#import "BugsnagPerformanceSpanCondition+Private.h" +#import "../SpanConditions/BugsnagPerformanceSpanCondition+Private.h" #import diff --git a/Sources/BugsnagPerformance/Private/BugsnagPerformanceSpanContext+Private.h b/Sources/BugsnagPerformance/Private/Core/Span/BugsnagPerformanceSpanContext+Private.h similarity index 100% rename from Sources/BugsnagPerformance/Private/BugsnagPerformanceSpanContext+Private.h rename to Sources/BugsnagPerformance/Private/Core/Span/BugsnagPerformanceSpanContext+Private.h diff --git a/Sources/BugsnagPerformance/Private/SpanKind.h b/Sources/BugsnagPerformance/Private/Core/Span/SpanKind.h similarity index 100% rename from Sources/BugsnagPerformance/Private/SpanKind.h rename to Sources/BugsnagPerformance/Private/Core/Span/SpanKind.h diff --git a/Sources/BugsnagPerformance/Private/SpanOptions.h b/Sources/BugsnagPerformance/Private/Core/Span/SpanOptions.h similarity index 95% rename from Sources/BugsnagPerformance/Private/SpanOptions.h rename to Sources/BugsnagPerformance/Private/Core/Span/SpanOptions.h index fd6e37e8..64e0c092 100644 --- a/Sources/BugsnagPerformance/Private/SpanOptions.h +++ b/Sources/BugsnagPerformance/Private/Core/Span/SpanOptions.h @@ -8,8 +8,8 @@ #import #import -#import "Utils.h" -#import "Metrics.h" +#import "../../Utils/Utils.h" +#import "../Configuration/Metrics.h" namespace bugsnag { diff --git a/Sources/BugsnagPerformance/Private/BugsnagPerformanceSpanCondition+Private.h b/Sources/BugsnagPerformance/Private/Core/SpanConditions/BugsnagPerformanceSpanCondition+Private.h similarity index 100% rename from Sources/BugsnagPerformance/Private/BugsnagPerformanceSpanCondition+Private.h rename to Sources/BugsnagPerformance/Private/Core/SpanConditions/BugsnagPerformanceSpanCondition+Private.h diff --git a/Sources/BugsnagPerformance/Private/BugsnagPerformanceSpanCondition.mm b/Sources/BugsnagPerformance/Private/Core/SpanConditions/BugsnagPerformanceSpanCondition.mm similarity index 100% rename from Sources/BugsnagPerformance/Private/BugsnagPerformanceSpanCondition.mm rename to Sources/BugsnagPerformance/Private/Core/SpanConditions/BugsnagPerformanceSpanCondition.mm diff --git a/Sources/BugsnagPerformance/Private/ConditionTimeoutExecutor.h b/Sources/BugsnagPerformance/Private/Core/SpanConditions/ConditionTimeoutExecutor.h similarity index 100% rename from Sources/BugsnagPerformance/Private/ConditionTimeoutExecutor.h rename to Sources/BugsnagPerformance/Private/Core/SpanConditions/ConditionTimeoutExecutor.h diff --git a/Sources/BugsnagPerformance/Private/SpanFactory/AppStartup/AppStartupSpanFactory.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/AppStartup/AppStartupSpanFactory.h similarity index 97% rename from Sources/BugsnagPerformance/Private/SpanFactory/AppStartup/AppStartupSpanFactory.h rename to Sources/BugsnagPerformance/Private/Core/SpanFactory/AppStartup/AppStartupSpanFactory.h index e0b17192..482d0819 100644 --- a/Sources/BugsnagPerformance/Private/SpanFactory/AppStartup/AppStartupSpanFactory.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/AppStartup/AppStartupSpanFactory.h @@ -7,7 +7,7 @@ // #import -#import "../../SpanOptions.h" +#import "../../Span/SpanOptions.h" @class BugsnagPerformanceSpan; @class BugsnagPerformanceSpanContext; diff --git a/Sources/BugsnagPerformance/Private/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.h similarity index 97% rename from Sources/BugsnagPerformance/Private/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.h rename to Sources/BugsnagPerformance/Private/Core/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.h index a3e3501d..c351802f 100644 --- a/Sources/BugsnagPerformance/Private/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.h @@ -7,7 +7,7 @@ // #import "AppStartupSpanFactory.h" -#import "../../SpanAttributesProvider.h" +#import "../../Attributes/SpanAttributesProvider.h" #import "../Plain/PlainSpanFactory.h" namespace bugsnag { diff --git a/Sources/BugsnagPerformance/Private/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.mm b/Sources/BugsnagPerformance/Private/Core/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.mm similarity index 99% rename from Sources/BugsnagPerformance/Private/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.mm rename to Sources/BugsnagPerformance/Private/Core/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.mm index 80d9d1f4..5db35b51 100644 --- a/Sources/BugsnagPerformance/Private/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.mm +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.mm @@ -7,7 +7,6 @@ // #import "AppStartupSpanFactoryImpl.h" -#import "../../Tracer.h" static NSString *const PreMainPhaseName = @"App launching - pre main()"; static NSString *const PostMainPhaseName = @"App launching - post main()"; diff --git a/Sources/BugsnagPerformance/Private/SpanFactory/Network/NetworkSpanFactory.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Network/NetworkSpanFactory.h similarity index 96% rename from Sources/BugsnagPerformance/Private/SpanFactory/Network/NetworkSpanFactory.h rename to Sources/BugsnagPerformance/Private/Core/SpanFactory/Network/NetworkSpanFactory.h index 64dbdbd8..ed4efe8d 100644 --- a/Sources/BugsnagPerformance/Private/SpanFactory/Network/NetworkSpanFactory.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Network/NetworkSpanFactory.h @@ -7,7 +7,7 @@ // #import -#import "../../SpanOptions.h" +#import "../../Span/SpanOptions.h" @class BugsnagPerformanceSpan; diff --git a/Sources/BugsnagPerformance/Private/SpanFactory/Network/NetworkSpanFactoryImpl.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Network/NetworkSpanFactoryImpl.h similarity index 96% rename from Sources/BugsnagPerformance/Private/SpanFactory/Network/NetworkSpanFactoryImpl.h rename to Sources/BugsnagPerformance/Private/Core/SpanFactory/Network/NetworkSpanFactoryImpl.h index ca30d87e..c9889297 100644 --- a/Sources/BugsnagPerformance/Private/SpanFactory/Network/NetworkSpanFactoryImpl.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Network/NetworkSpanFactoryImpl.h @@ -7,7 +7,7 @@ // #import "NetworkSpanFactory.h" -#import "../../SpanAttributesProvider.h" +#import "../../Attributes/SpanAttributesProvider.h" #import "../Plain/PlainSpanFactory.h" namespace bugsnag { diff --git a/Sources/BugsnagPerformance/Private/SpanFactory/Network/NetworkSpanFactoryImpl.mm b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Network/NetworkSpanFactoryImpl.mm similarity index 100% rename from Sources/BugsnagPerformance/Private/SpanFactory/Network/NetworkSpanFactoryImpl.mm rename to Sources/BugsnagPerformance/Private/Core/SpanFactory/Network/NetworkSpanFactoryImpl.mm diff --git a/Sources/BugsnagPerformance/Private/SpanFactory/Plain/PlainSpanFactory.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactory.h similarity index 94% rename from Sources/BugsnagPerformance/Private/SpanFactory/Plain/PlainSpanFactory.h rename to Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactory.h index bd50e88b..ee953b87 100644 --- a/Sources/BugsnagPerformance/Private/SpanFactory/Plain/PlainSpanFactory.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactory.h @@ -8,8 +8,8 @@ #import #import -#import "../../SpanOptions.h" -#import "../../SpanKind.h" +#import "../../Span/SpanOptions.h" +#import "../../Span/SpanKind.h" @class BugsnagPerformanceSpanCondition; diff --git a/Sources/BugsnagPerformance/Private/SpanFactory/Plain/PlainSpanFactoryCallbacks.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryCallbacks.h similarity index 92% rename from Sources/BugsnagPerformance/Private/SpanFactory/Plain/PlainSpanFactoryCallbacks.h rename to Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryCallbacks.h index 6e751f30..adfd47cd 100644 --- a/Sources/BugsnagPerformance/Private/SpanFactory/Plain/PlainSpanFactoryCallbacks.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryCallbacks.h @@ -6,7 +6,7 @@ // Copyright © 2025 Bugsnag. All rights reserved. // -#import "../../BugsnagPerformanceSpan+Private.h" +#import "../../Span/BugsnagPerformanceSpan+Private.h" typedef void (^OnSpanStartCallback)(BugsnagPerformanceSpan * _Nonnull, const SpanOptions &options); diff --git a/Sources/BugsnagPerformance/Private/SpanFactory/Plain/PlainSpanFactoryCallbacks.mm b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryCallbacks.mm similarity index 100% rename from Sources/BugsnagPerformance/Private/SpanFactory/Plain/PlainSpanFactoryCallbacks.mm rename to Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryCallbacks.mm diff --git a/Sources/BugsnagPerformance/Private/SpanFactory/Plain/PlainSpanFactoryImpl.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryImpl.h similarity index 93% rename from Sources/BugsnagPerformance/Private/SpanFactory/Plain/PlainSpanFactoryImpl.h rename to Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryImpl.h index 480e04ac..3be9ac81 100644 --- a/Sources/BugsnagPerformance/Private/SpanFactory/Plain/PlainSpanFactoryImpl.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryImpl.h @@ -8,9 +8,9 @@ #import "PlainSpanFactory.h" #import "PlainSpanFactoryCallbacks.h" -#import "../../SpanAttributesProvider.h" -#import "../../Sampler.h" -#import "../../SpanStackingHandler.h" +#import "../../Attributes/SpanAttributesProvider.h" +#import "../../Sampler/Sampler.h" +#import "../../SpanStack/SpanStackingHandler.h" namespace bugsnag { diff --git a/Sources/BugsnagPerformance/Private/SpanFactory/Plain/PlainSpanFactoryImpl.mm b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryImpl.mm similarity index 98% rename from Sources/BugsnagPerformance/Private/SpanFactory/Plain/PlainSpanFactoryImpl.mm rename to Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryImpl.mm index 48bb5207..53870b88 100644 --- a/Sources/BugsnagPerformance/Private/SpanFactory/Plain/PlainSpanFactoryImpl.mm +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryImpl.mm @@ -7,7 +7,7 @@ // #import "PlainSpanFactoryImpl.h" -#import "../../SpanAttributes.h" +#import "../../Attributes/SpanAttributes.h" using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Private/SpanFactory/ViewLoad/ViewLoadSpanFactory.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactory.h similarity index 98% rename from Sources/BugsnagPerformance/Private/SpanFactory/ViewLoad/ViewLoadSpanFactory.h rename to Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactory.h index cd25713b..494eca68 100644 --- a/Sources/BugsnagPerformance/Private/SpanFactory/ViewLoad/ViewLoadSpanFactory.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactory.h @@ -10,7 +10,7 @@ #import #import -#import "../../SpanOptions.h" +#import "../../Span/SpanOptions.h" @class BugsnagPerformanceSpan; @class BugsnagPerformanceSpanContext; diff --git a/Sources/BugsnagPerformance/Private/SpanFactory/ViewLoad/ViewLoadSpanFactoryCallbacks.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryCallbacks.h similarity index 92% rename from Sources/BugsnagPerformance/Private/SpanFactory/ViewLoad/ViewLoadSpanFactoryCallbacks.h rename to Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryCallbacks.h index af11698f..f31db08c 100644 --- a/Sources/BugsnagPerformance/Private/SpanFactory/ViewLoad/ViewLoadSpanFactoryCallbacks.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryCallbacks.h @@ -7,7 +7,7 @@ // #import -#import "../../BugsnagPerformanceSpan+Private.h" +#import "../../Span/BugsnagPerformanceSpan+Private.h" typedef BugsnagPerformanceSpan *_Nullable(^GetViewLoadParentSpanCallback)(void); typedef BOOL (^IsViewLoadInProgressCallback)(void); diff --git a/Sources/BugsnagPerformance/Private/SpanFactory/ViewLoad/ViewLoadSpanFactoryCallbacks.mm b/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryCallbacks.mm similarity index 100% rename from Sources/BugsnagPerformance/Private/SpanFactory/ViewLoad/ViewLoadSpanFactoryCallbacks.mm rename to Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryCallbacks.mm diff --git a/Sources/BugsnagPerformance/Private/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.h similarity index 98% rename from Sources/BugsnagPerformance/Private/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.h rename to Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.h index 1466245a..6e8e0180 100644 --- a/Sources/BugsnagPerformance/Private/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.h @@ -7,7 +7,7 @@ // #import "ViewLoadSpanFactory.h" -#import "../../SpanAttributesProvider.h" +#import "../../Attributes/SpanAttributesProvider.h" #import "../Plain/PlainSpanFactory.h" #import "ViewLoadSpanFactoryCallbacks.h" diff --git a/Sources/BugsnagPerformance/Private/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.mm b/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.mm similarity index 99% rename from Sources/BugsnagPerformance/Private/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.mm rename to Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.mm index c87c70f4..c9a0449d 100644 --- a/Sources/BugsnagPerformance/Private/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.mm +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.mm @@ -7,8 +7,7 @@ // #import "ViewLoadSpanFactoryImpl.h" -#import "../../Tracer.h" -#import "../../BugsnagSwiftTools.h" +#import "../../../Utils/BugsnagSwiftTools.h" using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Private/SpanLifecycle/SpanLifecycleHandler.h b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandler.h similarity index 96% rename from Sources/BugsnagPerformance/Private/SpanLifecycle/SpanLifecycleHandler.h rename to Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandler.h index d5dc7b18..2eb52742 100644 --- a/Sources/BugsnagPerformance/Private/SpanLifecycle/SpanLifecycleHandler.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandler.h @@ -7,7 +7,7 @@ // #import -#import "../SpanOptions.h" +#import "../Span/SpanOptions.h" #import "../PhasedStartup.h" namespace bugsnag { diff --git a/Sources/BugsnagPerformance/Private/SpanLifecycle/SpanLifecycleHandlerImpl.h b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.h similarity index 92% rename from Sources/BugsnagPerformance/Private/SpanLifecycle/SpanLifecycleHandlerImpl.h rename to Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.h index cd46bf72..e85bcb23 100644 --- a/Sources/BugsnagPerformance/Private/SpanLifecycle/SpanLifecycleHandlerImpl.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.h @@ -8,15 +8,14 @@ #import "SpanLifecycleHandler.h" -#import "../Batch.h" -#import "../BugsnagPerformanceConfiguration+Private.h" -#import "../FrameRateMetrics/FrameMetricsCollector.h" -#import "../SpanStackingHandler.h" -#import "../Sampler.h" +#import "../SpanProcessingPipeline/Batch.h" +#import "../Configuration/BugsnagPerformanceConfiguration+Private.h" +#import "../../Metrics/FrameMetrics/FrameMetricsCollector.h" +#import "../SpanStack/SpanStackingHandler.h" +#import "../Sampler/Sampler.h" #import "../SpanFactory/Plain/PlainSpanFactoryImpl.h" -#import "../ConditionTimeoutExecutor.h" +#import "../SpanConditions/ConditionTimeoutExecutor.h" #import "../BSGPrioritizedStore.h" -#import "../WeakSpansList.h" #import "../SpanStore/SpanStore.h" #import diff --git a/Sources/BugsnagPerformance/Private/SpanLifecycle/SpanLifecycleHandlerImpl.mm b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.mm similarity index 99% rename from Sources/BugsnagPerformance/Private/SpanLifecycle/SpanLifecycleHandlerImpl.mm rename to Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.mm index 1a092675..f362ebd6 100644 --- a/Sources/BugsnagPerformance/Private/SpanLifecycle/SpanLifecycleHandlerImpl.mm +++ b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.mm @@ -7,7 +7,7 @@ // #import "SpanLifecycleHandlerImpl.h" -#import "../BugsnagPerformanceSpan+Private.h" +#import "../Span/BugsnagPerformanceSpan+Private.h" using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Private/Batch.h b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/Batch.h similarity index 95% rename from Sources/BugsnagPerformance/Private/Batch.h rename to Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/Batch.h index 8355a8d2..94901ebc 100644 --- a/Sources/BugsnagPerformance/Private/Batch.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/Batch.h @@ -8,11 +8,11 @@ #pragma once -#import "PhasedStartup.h" -#import "BugsnagPerformanceConfiguration+Private.h" -#import "BugsnagPerformanceSpan+Private.h" -#import "PhasedStartup.h" -#import "Utils.h" +#import "../PhasedStartup.h" +#import "../Configuration/BugsnagPerformanceConfiguration+Private.h" +#import "../Span/BugsnagPerformanceSpan+Private.h" +#import "../PhasedStartup.h" +#import "../../Utils/Utils.h" #import #import diff --git a/Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipeline.h b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipeline.h similarity index 100% rename from Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipeline.h rename to Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipeline.h diff --git a/Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipelineImpl.h b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.h similarity index 98% rename from Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipelineImpl.h rename to Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.h index 16d6a688..4eb56ed5 100644 --- a/Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipelineImpl.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.h @@ -7,7 +7,7 @@ // #import "SpanProcessingPipeline.h" -#import "../Batch.h" +#import "Batch.h" #import "../PhasedStartup.h" #import "SpanProcessingPipelineStep.h" diff --git a/Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipelineImpl.mm b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.mm similarity index 100% rename from Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipelineImpl.mm rename to Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.mm diff --git a/Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipelineStep.h b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineStep.h similarity index 88% rename from Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipelineStep.h rename to Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineStep.h index 2c31dd87..1b5b486a 100644 --- a/Sources/BugsnagPerformance/Private/SpanProcessingPipeline/SpanProcessingPipelineStep.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineStep.h @@ -14,6 +14,6 @@ class SpanProcessingPipelineStep { public: virtual bool run(BugsnagPerformanceSpan *span) noexcept = 0; - virtual ~SpanProcessingPipeline() {} + virtual ~SpanProcessingPipelineStep() {} }; } diff --git a/Sources/BugsnagPerformance/Private/SpanActivityState.h b/Sources/BugsnagPerformance/Private/Core/SpanStack/SpanActivityState.h similarity index 94% rename from Sources/BugsnagPerformance/Private/SpanActivityState.h rename to Sources/BugsnagPerformance/Private/Core/SpanStack/SpanActivityState.h index 5b5b1952..13c5dcbe 100644 --- a/Sources/BugsnagPerformance/Private/SpanActivityState.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanStack/SpanActivityState.h @@ -6,7 +6,7 @@ // Copyright © 2023 Bugsnag. All rights reserved. // -#import "BugsnagPerformanceSpan+Private.h" +#import "../Span/BugsnagPerformanceSpan+Private.h" #import namespace bugsnag { diff --git a/Sources/BugsnagPerformance/Private/SpanStackingHandler.h b/Sources/BugsnagPerformance/Private/Core/SpanStack/SpanStackingHandler.h similarity index 95% rename from Sources/BugsnagPerformance/Private/SpanStackingHandler.h rename to Sources/BugsnagPerformance/Private/Core/SpanStack/SpanStackingHandler.h index a5913e68..0330ab41 100644 --- a/Sources/BugsnagPerformance/Private/SpanStackingHandler.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanStack/SpanStackingHandler.h @@ -6,7 +6,7 @@ // Copyright © 2023 Bugsnag. All rights reserved. // -#import "BugsnagPerformanceSpan+Private.h" +#import "../Span/BugsnagPerformanceSpan+Private.h" #import "SpanActivityState.h" #import #import diff --git a/Sources/BugsnagPerformance/Private/SpanStackingHandler.mm b/Sources/BugsnagPerformance/Private/Core/SpanStack/SpanStackingHandler.mm similarity index 99% rename from Sources/BugsnagPerformance/Private/SpanStackingHandler.mm rename to Sources/BugsnagPerformance/Private/Core/SpanStack/SpanStackingHandler.mm index 9850888c..94e5989d 100644 --- a/Sources/BugsnagPerformance/Private/SpanStackingHandler.mm +++ b/Sources/BugsnagPerformance/Private/Core/SpanStack/SpanStackingHandler.mm @@ -8,7 +8,7 @@ #import #import "SpanStackingHandler.h" -#import "BugsnagPerformanceSpan+Private.h" +#import "../Span/BugsnagPerformanceSpan+Private.h" #import "SpanActivityState.h" #import #import diff --git a/Sources/BugsnagPerformance/Private/SpanStore/SpanStore.h b/Sources/BugsnagPerformance/Private/Core/SpanStore/SpanStore.h similarity index 100% rename from Sources/BugsnagPerformance/Private/SpanStore/SpanStore.h rename to Sources/BugsnagPerformance/Private/Core/SpanStore/SpanStore.h diff --git a/Sources/BugsnagPerformance/Private/SpanStore/SpanStoreImpl.h b/Sources/BugsnagPerformance/Private/Core/SpanStore/SpanStoreImpl.h similarity index 94% rename from Sources/BugsnagPerformance/Private/SpanStore/SpanStoreImpl.h rename to Sources/BugsnagPerformance/Private/Core/SpanStore/SpanStoreImpl.h index 20034826..0734eb92 100644 --- a/Sources/BugsnagPerformance/Private/SpanStore/SpanStoreImpl.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanStore/SpanStoreImpl.h @@ -7,8 +7,8 @@ // #import "SpanStore.h" -#import "../SpanStackingHandler.h" -#import "../WeakSpansList.h" +#import "../SpanStack/SpanStackingHandler.h" +#import "WeakSpansList.h" #import diff --git a/Sources/BugsnagPerformance/Private/SpanStore/SpanStoreImpl.mm b/Sources/BugsnagPerformance/Private/Core/SpanStore/SpanStoreImpl.mm similarity index 100% rename from Sources/BugsnagPerformance/Private/SpanStore/SpanStoreImpl.mm rename to Sources/BugsnagPerformance/Private/Core/SpanStore/SpanStoreImpl.mm diff --git a/Sources/BugsnagPerformance/Private/WeakSpansList.h b/Sources/BugsnagPerformance/Private/Core/SpanStore/WeakSpansList.h similarity index 97% rename from Sources/BugsnagPerformance/Private/WeakSpansList.h rename to Sources/BugsnagPerformance/Private/Core/SpanStore/WeakSpansList.h index cc12cd2d..0fb5416f 100644 --- a/Sources/BugsnagPerformance/Private/WeakSpansList.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanStore/WeakSpansList.h @@ -6,7 +6,7 @@ // Copyright © 2023 Bugsnag. All rights reserved. // -#import "BugsnagPerformanceSpan+Private.h" +#import "../Span/BugsnagPerformanceSpan+Private.h" #import @interface BSGWeakSpanPointer: NSObject diff --git a/Sources/BugsnagPerformance/Private/WeakSpansList.mm b/Sources/BugsnagPerformance/Private/Core/SpanStore/WeakSpansList.mm similarity index 100% rename from Sources/BugsnagPerformance/Private/WeakSpansList.mm rename to Sources/BugsnagPerformance/Private/Core/SpanStore/WeakSpansList.mm diff --git a/Sources/BugsnagPerformance/Private/Worker.h b/Sources/BugsnagPerformance/Private/Core/Worker/Worker.h similarity index 96% rename from Sources/BugsnagPerformance/Private/Worker.h rename to Sources/BugsnagPerformance/Private/Core/Worker/Worker.h index a11266f8..01a71f02 100644 --- a/Sources/BugsnagPerformance/Private/Worker.h +++ b/Sources/BugsnagPerformance/Private/Core/Worker/Worker.h @@ -9,7 +9,7 @@ #pragma once #import -#import "PhasedStartup.h" +#import "../PhasedStartup.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/Worker.mm b/Sources/BugsnagPerformance/Private/Core/Worker/Worker.mm similarity index 97% rename from Sources/BugsnagPerformance/Private/Worker.mm rename to Sources/BugsnagPerformance/Private/Core/Worker/Worker.mm index 30852a4d..0de03c39 100644 --- a/Sources/BugsnagPerformance/Private/Worker.mm +++ b/Sources/BugsnagPerformance/Private/Core/Worker/Worker.mm @@ -7,7 +7,7 @@ // #import "Worker.h" -#import "BugsnagPerformanceConfiguration+Private.h" +#import "../Configuration/BugsnagPerformanceConfiguration+Private.h" @interface Worker () diff --git a/Sources/BugsnagPerformance/Private/BugsnagPerformanceCrossTalkAPI.h b/Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h similarity index 98% rename from Sources/BugsnagPerformance/Private/BugsnagPerformanceCrossTalkAPI.h rename to Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h index c3c7abb6..5e187360 100644 --- a/Sources/BugsnagPerformance/Private/BugsnagPerformanceCrossTalkAPI.h +++ b/Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h @@ -23,7 +23,7 @@ #import #import -#import "PhasedStartup.h" +#import "../Core/PhasedStartup.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/BugsnagPerformanceCrossTalkAPI.mm b/Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.mm similarity index 99% rename from Sources/BugsnagPerformance/Private/BugsnagPerformanceCrossTalkAPI.mm rename to Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.mm index 79254663..a0d66753 100644 --- a/Sources/BugsnagPerformance/Private/BugsnagPerformanceCrossTalkAPI.mm +++ b/Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.mm @@ -7,9 +7,9 @@ // #import "BugsnagPerformanceCrossTalkAPI.h" -#import "SpanStackingHandler.h" -#import "Tracer.h" -#import "Utils.h" +#import "../Core/SpanStack/SpanStackingHandler.h" +#import "../Tracer.h" +#import "../Utils/Utils.h" #import using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/AppStartupInstrumentation.h b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/AppStartupInstrumentation.h index 768a5339..82f10b33 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/AppStartupInstrumentation.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/AppStartupInstrumentation.h @@ -7,9 +7,8 @@ #import #import -#import "../../PhasedStartup.h" -#import "../../SpanAttributesProvider.h" -#import "../../Tracer.h" +#import "../../Core/PhasedStartup.h" +#import "../../Core/Attributes/SpanAttributesProvider.h" #import "State/AppStartupInstrumentationState.h" #import "State/AppStartupInstrumentationStateSnapshot.h" #import "Lifecycle/AppStartupLifecycleHandler.h" diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/AppStartupInstrumentation.mm b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/AppStartupInstrumentation.mm index d5ebad02..8e5ef85a 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/AppStartupInstrumentation.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/AppStartupInstrumentation.mm @@ -7,11 +7,10 @@ #import "AppStartupInstrumentation.h" -#import "../../Tracer.h" -#import "../../Utils.h" -#import "../../BugsnagPerformanceSpan+Private.h" -#import "../../BugsnagPerformanceImpl.h" -#import "../../BugsnagPerformanceCrossTalkAPI.h" +#import "../../Utils/Utils.h" +#import "../../Core/Span/BugsnagPerformanceSpan+Private.h" +#import "../../Main/BugsnagPerformanceImpl.h" +#import "../../CrosstalkAPI/BugsnagPerformanceCrossTalkAPI.h" #import #import diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandlerImpl.h b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandlerImpl.h index f40b82a3..f2bc8073 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandlerImpl.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandlerImpl.h @@ -7,10 +7,10 @@ // #import "AppStartupLifecycleHandler.h" -#import "../../../SpanFactory/AppStartup/AppStartupSpanFactory.h" +#import "../../../Core/SpanFactory/AppStartup/AppStartupSpanFactory.h" #import "../System/AppStartupInstrumentationSystemUtils.h" -#import "../../../SpanAttributesProvider.h" -#import "../../../BugsnagPerformanceCrossTalkAPI.h" +#import "../../../Core/Attributes/SpanAttributesProvider.h" +#import "../../../CrosstalkAPI/BugsnagPerformanceCrossTalkAPI.h" #import diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandlerImpl.mm b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandlerImpl.mm index f97655da..913d995e 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandlerImpl.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandlerImpl.mm @@ -7,9 +7,9 @@ // #import "AppStartupLifecycleHandlerImpl.h" -#import "../../../SpanFactory/AppStartup/AppStartupSpanFactory.h" -#import "../../../SpanAttributesProvider.h" -#import "../../../BugsnagPerformanceSpan+Private.h" +#import "../../../Core/SpanFactory/AppStartup/AppStartupSpanFactory.h" +#import "../../../Core/Attributes/SpanAttributesProvider.h" +#import "../../../Core/Span/BugsnagPerformanceSpan+Private.h" using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/State/AppStartupInstrumentationState.mm b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/State/AppStartupInstrumentationState.mm index 32e60a47..b5bca636 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/State/AppStartupInstrumentationState.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/State/AppStartupInstrumentationState.mm @@ -6,7 +6,7 @@ // #import "AppStartupInstrumentationState.h" -#import "../../../BugsnagPerformanceSpan+Private.h" +#import "../../../Core/Span/BugsnagPerformanceSpan+Private.h" @implementation AppStartupInstrumentationState diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/System/AppStartupInstrumentationSystemUtilsImpl.mm b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/System/AppStartupInstrumentationSystemUtilsImpl.mm index ed6603dd..4646327c 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/System/AppStartupInstrumentationSystemUtilsImpl.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/System/AppStartupInstrumentationSystemUtilsImpl.mm @@ -7,7 +7,7 @@ // #import "AppStartupInstrumentationSystemUtilsImpl.h" -#import "../../../Utils.h" +#import "../../../Utils/Utils.h" #import diff --git a/Sources/BugsnagPerformance/Private/BugsnagPerformanceLoadingIndicatorView+Private.h b/Sources/BugsnagPerformance/Private/Instrumentation/BugsnagPerformanceLoadingIndicatorView+Private.h similarity index 100% rename from Sources/BugsnagPerformance/Private/BugsnagPerformanceLoadingIndicatorView+Private.h rename to Sources/BugsnagPerformance/Private/Instrumentation/BugsnagPerformanceLoadingIndicatorView+Private.h diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.h b/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.h index a29ff2f1..bde2a00a 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.h @@ -10,17 +10,17 @@ #import -#import "../PhasedStartup.h" +#import "../Core/PhasedStartup.h" #import "AppStartupInstrumentation/AppStartupInstrumentation.h" #import "NetworkInstrumentation/NetworkInstrumentation.h" #import "AppStartupInstrumentation/System/AppStartupInstrumentationSystemUtilsImpl.h" -#import "../SpanFactory/AppStartup/AppStartupSpanFactoryImpl.h" +#import "../Core/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.h" #import "AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandlerImpl.h" #import "ViewLoadInstrumentation/ViewLoadInstrumentation.h" #import "NetworkInstrumentation/System/NetworkHeaderInjector.h" -#import "../SpanFactory/AppStartup/AppStartupSpanFactory.h" -#import "../SpanFactory/ViewLoad/ViewLoadSpanFactory.h" -#import "../SpanFactory/Network/NetworkSpanFactory.h" +#import "../Core/SpanFactory/AppStartup/AppStartupSpanFactory.h" +#import "../Core/SpanFactory/ViewLoad/ViewLoadSpanFactory.h" +#import "../Core/SpanFactory/Network/NetworkSpanFactory.h" #import "AppStartupInstrumentation/State/AppStartupInstrumentationStateSnapshot.h" NS_ASSUME_NONNULL_BEGIN @@ -41,8 +41,7 @@ namespace bugsnag { class Instrumentation: public PhasedStartup { public: - Instrumentation(std::shared_ptr tracer, - std::shared_ptr appStartupSpanFactory, + Instrumentation(std::shared_ptr appStartupSpanFactory, std::shared_ptr viewLoadSpanFactory, std::shared_ptr networkSpanFactory, std::shared_ptr spanAttributesProvider, @@ -51,7 +50,8 @@ class Instrumentation: public PhasedStartup { , viewLoadInstrumentation_(createViewLoadInstrumentation(viewLoadSpanFactory, spanAttributesProvider)) , networkInstrumentation_(createNetworkInstrumentation(networkSpanFactory, spanAttributesProvider, networkHeaderInjector)) { - tracer->setGetAppStartInstrumentationState([=]{ return appStartupInstrumentation_->stateSnapshot(); }); + // TODO +// tracer->setGetAppStartInstrumentationState([=]{ return appStartupInstrumentation_->stateSnapshot(); }); } void earlyConfigure(BSGEarlyConfiguration *config) noexcept; diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.mm b/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.mm index 70b6f3a2..febe3be1 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.mm @@ -8,8 +8,8 @@ #import "Instrumentation.h" -#import "../SpanFactory/Network/NetworkSpanFactoryImpl.h" -#import "../SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.h" +#import "../Core/SpanFactory/Network/NetworkSpanFactoryImpl.h" +#import "../Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.h" #import "ViewLoadInstrumentation/System/ViewLoadInstrumentationSystemUtilsImpl.h" #import "ViewLoadInstrumentation/System/ViewLoadSwizzlingHandlerImpl.h" #import "ViewLoadInstrumentation/State/ViewLoadInstrumentationStateRepositoryImpl.h" diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkEarlyPhaseHandlerImpl.h b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkEarlyPhaseHandlerImpl.h index d3816403..730aec21 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkEarlyPhaseHandlerImpl.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkEarlyPhaseHandlerImpl.h @@ -7,7 +7,7 @@ // #import "NetworkEarlyPhaseHandler.h" -#import "../../../Tracer.h" +#import "../../../Core/Attributes/SpanAttributesProvider.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkEarlyPhaseHandlerImpl.mm b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkEarlyPhaseHandlerImpl.mm index 349ecf70..f7c7c8db 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkEarlyPhaseHandlerImpl.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkEarlyPhaseHandlerImpl.mm @@ -7,6 +7,7 @@ // #import "NetworkEarlyPhaseHandlerImpl.h" +#import "../../../Core/Span/BugsnagPerformanceSpan+Private.h" using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkLifecycleHandlerImpl.h b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkLifecycleHandlerImpl.h index baf39e76..f14710c8 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkLifecycleHandlerImpl.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkLifecycleHandlerImpl.h @@ -8,9 +8,8 @@ #import "NetworkLifecycleHandler.h" #import "NetworkEarlyPhaseHandler.h" -#import "../../../Tracer.h" #import "../State/NetworkInstrumentationStateRepository.h" -#import "../../../SpanFactory/Network/NetworkSpanFactory.h" +#import "../../../Core/SpanFactory/Network/NetworkSpanFactory.h" #import "../System/NetworkInstrumentationSystemUtils.h" #import "../System/NetworkHeaderInjector.h" diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkLifecycleHandlerImpl.mm b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkLifecycleHandlerImpl.mm index 952125eb..465b03cd 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkLifecycleHandlerImpl.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkLifecycleHandlerImpl.mm @@ -7,7 +7,7 @@ // #import "NetworkLifecycleHandlerImpl.h" -#import "../../../BugsnagPerformanceSpan+Private.h" +#import "../../../Core/Span/BugsnagPerformanceSpan+Private.h" using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/NetworkInstrumentation.h b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/NetworkInstrumentation.h index b6e6c543..f5d4f512 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/NetworkInstrumentation.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/NetworkInstrumentation.h @@ -6,9 +6,8 @@ // #import -#import "../../Tracer.h" -#import "../../PhasedStartup.h" -#import "../../Sampler.h" +#import "../../Core/PhasedStartup.h" +#import "../../Core/Sampler/Sampler.h" #import "State/NetworkInstrumentationStateRepository.h" #import "System/BSGURLSessionPerformanceDelegate.h" #import "System/NetworkInstrumentationSystemUtils.h" diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/NetworkInstrumentation.mm b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/NetworkInstrumentation.mm index 17cd75fc..a53a1ca0 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/NetworkInstrumentation.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/NetworkInstrumentation.mm @@ -7,8 +7,8 @@ #import "NetworkInstrumentation.h" -#import "../../BugsnagPerformanceSpan+Private.h" -#import "../../SpanAttributesProvider.h" +#import "../../Core/Span/BugsnagPerformanceSpan+Private.h" +#import "../../Core/Attributes/SpanAttributesProvider.h" using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/BSGURLSessionPerformanceDelegate.h b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/BSGURLSessionPerformanceDelegate.h index 6b7c19dc..ea9cf52b 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/BSGURLSessionPerformanceDelegate.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/BSGURLSessionPerformanceDelegate.h @@ -6,8 +6,11 @@ // Copyright © 2025 Bugsnag. All rights reserved. // -#import "../../../Tracer.h" #import "../Lifecycle/NetworkLifecycleHandler.h" +#import "../../../Core/PhasedStartup.h" +#import + +using namespace bugsnag; NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/BSGURLSessionPerformanceDelegate.mm b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/BSGURLSessionPerformanceDelegate.mm index 02eeef4b..d30c07d7 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/BSGURLSessionPerformanceDelegate.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/BSGURLSessionPerformanceDelegate.mm @@ -8,6 +8,8 @@ #import "BSGURLSessionPerformanceDelegate.h" +using namespace bugsnag; + @interface BSGURLSessionPerformanceDelegate () @property(readwrite,nonatomic) BOOL isEnabled; diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkHeaderInjector.h b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkHeaderInjector.h index 669d169e..8d51fcb6 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkHeaderInjector.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkHeaderInjector.h @@ -7,10 +7,10 @@ // #import -#import "../../../PhasedStartup.h" -#import "../../../SpanAttributesProvider.h" -#import "../../../SpanStackingHandler.h" -#import "../../../Sampler.h" +#import "../../../Core/PhasedStartup.h" +#import "../../../Core/Attributes/SpanAttributesProvider.h" +#import "../../../Core/SpanStack/SpanStackingHandler.h" +#import "../../../Core/Sampler/Sampler.h" #import diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkHeaderInjector.mm b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkHeaderInjector.mm index 694a4e6d..ea9b45ee 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkHeaderInjector.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkHeaderInjector.mm @@ -7,7 +7,7 @@ // #import "NetworkHeaderInjector.h" -#import "../../../Utils.h" +#import "../../../Utils/Utils.h" void NetworkHeaderInjector::configure(BugsnagPerformanceConfiguration *config) noexcept { propagateTraceParentToUrlsMatching_ = config.tracePropagationUrls; diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkInstrumentationSystemUtilsImpl.mm b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkInstrumentationSystemUtilsImpl.mm index d2dd6d57..ee7bf21f 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkInstrumentationSystemUtilsImpl.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkInstrumentationSystemUtilsImpl.mm @@ -8,8 +8,8 @@ #import "NetworkInstrumentationSystemUtilsImpl.h" -#import "../../../Swizzle.h" -#import "../../../Utils.h" +#import "../../../Utils/Swizzle.h" +#import "../../../Utils/Utils.h" #import using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkSwizzlingHandlerImpl.mm b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkSwizzlingHandlerImpl.mm index d1c75869..b8b19f1b 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkSwizzlingHandlerImpl.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkSwizzlingHandlerImpl.mm @@ -9,7 +9,7 @@ #import "NetworkSwizzlingHandlerImpl.h" #import "Proxy/BSGURLSessionPerformanceProxy.h" #import "Proxy/BSGPerformanceSharedSessionProxy.h" -#import "../../../Swizzle.h" +#import "../../../Utils/Swizzle.h" #import using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/Proxy/BSGURLSessionPerformanceProxy.mm b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/Proxy/BSGURLSessionPerformanceProxy.mm index 656fe11a..621dee70 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/Proxy/BSGURLSessionPerformanceProxy.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/Proxy/BSGURLSessionPerformanceProxy.mm @@ -7,7 +7,7 @@ #import "BSGURLSessionPerformanceProxy.h" #import -#import "../../../../Utils.h" +#import "../../../../Utils/Utils.h" @interface BSGURLSessionPerformanceProxy () diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadEarlyPhaseHandlerImpl.h b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadEarlyPhaseHandlerImpl.h index 09008223..a71bd5fd 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadEarlyPhaseHandlerImpl.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadEarlyPhaseHandlerImpl.h @@ -7,7 +7,8 @@ // #import "ViewLoadEarlyPhaseHandler.h" -#import "../../../Tracer.h" +#import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadEarlyPhaseHandlerImpl.mm b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadEarlyPhaseHandlerImpl.mm index 7d6552c6..9b223159 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadEarlyPhaseHandlerImpl.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadEarlyPhaseHandlerImpl.mm @@ -7,6 +7,9 @@ // #import "ViewLoadEarlyPhaseHandlerImpl.h" +#import "../../../Core/Span/BugsnagPerformanceSpan+Private.h" + +using namespace bugsnag; void ViewLoadEarlyPhaseHandlerImpl::onNewStateCreated(ViewLoadInstrumentationState *state) noexcept { diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandlerImpl.h b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandlerImpl.h index 8c9aa94d..7ba83813 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandlerImpl.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandlerImpl.h @@ -9,10 +9,10 @@ #import "ViewLoadLifecycleHandler.h" #import "ViewLoadEarlyPhaseHandler.h" #import "ViewLoadLoadingIndicatorsHandler.h" -#import "../../../SpanFactory/ViewLoad/ViewLoadSpanFactory.h" +#import "../../../Core/SpanFactory/ViewLoad/ViewLoadSpanFactory.h" +#import "../../../Core/Attributes/SpanAttributesProvider.h" #import "../State/ViewLoadInstrumentationStateRepository.h" -#import "../../../Tracer.h" -#import "../../../BugsnagPerformanceCrossTalkAPI.h" +#import "../../../CrosstalkAPI/BugsnagPerformanceCrossTalkAPI.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandlerImpl.mm b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandlerImpl.mm index 1989bbc6..1265949c 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandlerImpl.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandlerImpl.mm @@ -8,7 +8,8 @@ #import "ViewLoadLifecycleHandlerImpl.h" -#import "../../../BugsnagSwiftTools.h" +#import "../../../Utils/BugsnagSwiftTools.h" +#import "../../../Core/Span/BugsnagPerformanceSpan+Private.h" using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLoadingIndicatorsHandlerImpl.mm b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLoadingIndicatorsHandlerImpl.mm index 0af084c3..a731e837 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLoadingIndicatorsHandlerImpl.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLoadingIndicatorsHandlerImpl.mm @@ -7,7 +7,7 @@ // #import "ViewLoadLoadingIndicatorsHandlerImpl.h" -#import "../../../BugsnagPerformanceLoadingIndicatorView+Private.h" +#import "../../BugsnagPerformanceLoadingIndicatorView+Private.h" using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadSwizzlingHandlerImpl.mm b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadSwizzlingHandlerImpl.mm index 8c636517..6c662d50 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadSwizzlingHandlerImpl.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadSwizzlingHandlerImpl.mm @@ -9,7 +9,7 @@ #import #import "ViewLoadSwizzlingHandlerImpl.h" -#import "../../../Swizzle.h" +#import "../../../Utils/Swizzle.h" #import diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/ViewLoadInstrumentation.h b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/ViewLoadInstrumentation.h index ef250ed6..71184fa2 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/ViewLoadInstrumentation.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/ViewLoadInstrumentation.h @@ -6,10 +6,9 @@ // #import -#import "../../PhasedStartup.h" -#import "../../Tracer.h" +#import "../../Core/PhasedStartup.h" #import "State/ViewLoadInstrumentationState.h" -#import "../../SpanFactory/ViewLoad/ViewLoadSpanFactory.h" +#import "../../Core/SpanFactory/ViewLoad/ViewLoadSpanFactory.h" #import "System/ViewLoadInstrumentationSystemUtils.h" #import "System/ViewLoadSwizzlingHandler.h" #import "Lifecycle/ViewLoadLifecycleHandler.h" diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/ViewLoadInstrumentation.mm b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/ViewLoadInstrumentation.mm index 996f3927..c4561f26 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/ViewLoadInstrumentation.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/ViewLoadInstrumentation.mm @@ -8,12 +8,11 @@ #import "ViewLoadInstrumentation.h" #import -#import "../../BugsnagPerformanceSpan+Private.h" -#import "../../Tracer.h" -#import "../../Swizzle.h" -#import "../../Utils.h" -#import "../../BugsnagSwiftTools.h" -#import "../../BugsnagPerformanceCrossTalkAPI.h" +#import "../../Core/Span/BugsnagPerformanceSpan+Private.h" +#import "../../Utils/Swizzle.h" +#import "../../Utils/Utils.h" +#import "../../Utils/BugsnagSwiftTools.h" +#import "../../CrosstalkAPI/BugsnagPerformanceCrossTalkAPI.h" #if 0 #define Trace NSLog diff --git a/Sources/BugsnagPerformance/Private/BugsnagPerformanceImpl.h b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.h similarity index 83% rename from Sources/BugsnagPerformance/Private/BugsnagPerformanceImpl.h rename to Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.h index fb49f318..8a0264b5 100644 --- a/Sources/BugsnagPerformance/Private/BugsnagPerformanceImpl.h +++ b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.h @@ -12,31 +12,31 @@ #import #import -#import "BugsnagPerformanceSpan+Private.h" -#import "OtlpUploader.h" -#import "Sampler.h" -#import "Tracer.h" -#import "Worker.h" -#import "Persistence.h" -#import "PersistentState.h" -#import "Reachability.h" -#import "RetryQueue.h" -#import "AppStateTracker.h" -#import "PhasedStartup.h" -#import "Instrumentation/Instrumentation.h" -#import "ResourceAttributes.h" -#import "Instrumentation/NetworkInstrumentation/System/NetworkHeaderInjector.h" -#import "OtlpTraceEncoding.h" -#import "FrameRateMetrics/FrameMetricsCollector.h" -#import "ConditionTimeoutExecutor.h" -#import "SystemInfoSampler.h" -#import "SpanControl/BSGCompositeSpanControlProvider.h" -#import "BSGPluginManager.h" -#import "SpanFactory/AppStartup/AppStartupSpanFactoryImpl.h" -#import "SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.h" -#import "SpanFactory/Network/NetworkSpanFactoryImpl.h" -#import "SpanLifecycle/SpanLifecycleHandlerImpl.h" -#import "SpanStore/SpanStoreImpl.h" +#import "../Core/Span/BugsnagPerformanceSpan+Private.h" +#import "../Upload/Otlp/OtlpUploader.h" +#import "../Core/Sampler/Sampler.h" +#import "../Tracer.h" +#import "../Core/Worker/Worker.h" +#import "../Utils/Persistence.h" +#import "../Core/Sampler/PersistentState.h" +#import "../Utils/Reachability.h" +#import "../Upload/RetryQueue.h" +#import "../Utils/AppStateTracker.h" +#import "../Core/PhasedStartup.h" +#import "../Instrumentation/Instrumentation.h" +#import "../Core/Attributes/ResourceAttributes.h" +#import "../Instrumentation/NetworkInstrumentation/System/NetworkHeaderInjector.h" +#import "../Upload/Otlp/OtlpTraceEncoding.h" +#import "../Metrics/FrameMetrics/FrameMetricsCollector.h" +#import "../Core/SpanConditions/ConditionTimeoutExecutor.h" +#import "../Metrics/SystemMetrics/SystemInfoSampler.h" +#import "../PluginSupport/SpanControl/BSGCompositeSpanControlProvider.h" +#import "../PluginSupport/PluginManager/BSGPluginManager.h" +#import "../Core/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.h" +#import "../Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.h" +#import "../Core/SpanFactory/Network/NetworkSpanFactoryImpl.h" +#import "../Core/SpanLifecycle/SpanLifecycleHandlerImpl.h" +#import "../Core/SpanStore/SpanStoreImpl.h" #import diff --git a/Sources/BugsnagPerformance/Private/BugsnagPerformanceImpl.mm b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.mm similarity index 97% rename from Sources/BugsnagPerformance/Private/BugsnagPerformanceImpl.mm rename to Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.mm index f52eae08..d2943248 100644 --- a/Sources/BugsnagPerformance/Private/BugsnagPerformanceImpl.mm +++ b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.mm @@ -7,18 +7,18 @@ // #import "BugsnagPerformanceImpl.h" -#import "BugsnagPerformanceConfiguration+Private.h" - -#import "OtlpTraceEncoding.h" -#import "Utils.h" -#import "SpanAttributesProvider.h" -#import "SpanStackingHandler.h" -#import "BugsnagPerformanceCrossTalkAPI.h" -#import "Utils.h" -#import "FrameRateMetrics/FrameMetricsCollector.h" -#import "ConditionTimeoutExecutor.h" -#import "BugsnagPerformanceSpan+Private.h" -#import "BugsnagPerformanceAppStartTypePlugin.h" +#import "../Core/Configuration/BugsnagPerformanceConfiguration+Private.h" + +#import "../Upload/Otlp/OtlpTraceEncoding.h" +#import "../Utils/Utils.h" +#import "../Core/Attributes/SpanAttributesProvider.h" +#import "../Core/SpanStack/SpanStackingHandler.h" +#import "../CrosstalkAPI/BugsnagPerformanceCrossTalkAPI.h" +#import "../Utils/Utils.h" +#import "../Metrics/FrameMetrics/FrameMetricsCollector.h" +#import "../Core/SpanConditions/ConditionTimeoutExecutor.h" +#import "../Core/Span/BugsnagPerformanceSpan+Private.h" +#import "../Plugins/AppStart/BugsnagPerformanceAppStartTypePlugin.h" using namespace bugsnag; @@ -63,8 +63,7 @@ , appStateTracker_(appStateTracker) , viewControllersToSpans_([NSMapTable mapTableWithKeyOptions:NSMapTableWeakMemory | NSMapTableObjectPointerPersonality valueOptions:NSMapTableStrongMemory]) -, instrumentation_(std::make_shared(tracer_, - appStartupSpanFactory_, +, instrumentation_(std::make_shared(appStartupSpanFactory_, viewLoadSpanFactory_, networkSpanFactory_, spanAttributesProvider_, diff --git a/Sources/BugsnagPerformance/Private/BugsnagPerformanceLibrary.h b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.h similarity index 93% rename from Sources/BugsnagPerformance/Private/BugsnagPerformanceLibrary.h rename to Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.h index ac620842..b9ec4724 100644 --- a/Sources/BugsnagPerformance/Private/BugsnagPerformanceLibrary.h +++ b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.h @@ -8,9 +8,9 @@ #pragma once #import "BugsnagPerformanceImpl.h" -#import "AppStateTracker.h" -#import "Instrumentation/Instrumentation.h" -#import "PhasedStartup.h" +#import "../Utils/AppStateTracker.h" +#import "../Instrumentation/Instrumentation.h" +#import "../Core/PhasedStartup.h" namespace bugsnag { diff --git a/Sources/BugsnagPerformance/Private/BugsnagPerformanceLibrary.mm b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.mm similarity index 99% rename from Sources/BugsnagPerformance/Private/BugsnagPerformanceLibrary.mm rename to Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.mm index 11f2afb8..4d9e28ed 100644 --- a/Sources/BugsnagPerformance/Private/BugsnagPerformanceLibrary.mm +++ b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.mm @@ -6,7 +6,7 @@ // #import "BugsnagPerformanceLibrary.h" -#import "Reachability.h" +#import "../Utils/Reachability.h" using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Private/FrameRateMetrics/FrameMetricsCollector.h b/Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrameMetricsCollector.h similarity index 91% rename from Sources/BugsnagPerformance/Private/FrameRateMetrics/FrameMetricsCollector.h rename to Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrameMetricsCollector.h index 3227577f..186feca3 100644 --- a/Sources/BugsnagPerformance/Private/FrameRateMetrics/FrameMetricsCollector.h +++ b/Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrameMetricsCollector.h @@ -7,7 +7,7 @@ // #pragma once -#import "../PhasedStartup.h" +#import "../../Core/PhasedStartup.h" #import "FrameMetricsSnapshot.h" @interface FrameMetricsCollector: NSObject diff --git a/Sources/BugsnagPerformance/Private/FrameRateMetrics/FrameMetricsCollector.mm b/Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrameMetricsCollector.mm similarity index 98% rename from Sources/BugsnagPerformance/Private/FrameRateMetrics/FrameMetricsCollector.mm rename to Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrameMetricsCollector.mm index 7329b3db..36bed605 100644 --- a/Sources/BugsnagPerformance/Private/FrameRateMetrics/FrameMetricsCollector.mm +++ b/Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrameMetricsCollector.mm @@ -10,7 +10,7 @@ #import #import "BugsnagPerformance/BugsnagPerformanceConfiguration.h" -#import "../EarlyConfiguration.h" +#import "../../Core/Configuration/EarlyConfiguration.h" #import "FrameMetricsCollector.h" #import "FrozenFrameData.h" diff --git a/Sources/BugsnagPerformance/Private/FrameRateMetrics/FrameMetricsSnapshot.h b/Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrameMetricsSnapshot.h similarity index 94% rename from Sources/BugsnagPerformance/Private/FrameRateMetrics/FrameMetricsSnapshot.h rename to Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrameMetricsSnapshot.h index d3988515..1547b6bc 100644 --- a/Sources/BugsnagPerformance/Private/FrameRateMetrics/FrameMetricsSnapshot.h +++ b/Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrameMetricsSnapshot.h @@ -7,7 +7,7 @@ // #pragma once -#import "../PhasedStartup.h" +#import "../../Core/PhasedStartup.h" #import "FrozenFrameData.h" @interface FrameMetricsSnapshot: NSObject diff --git a/Sources/BugsnagPerformance/Private/FrameRateMetrics/FrameMetricsSnapshot.mm b/Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrameMetricsSnapshot.mm similarity index 100% rename from Sources/BugsnagPerformance/Private/FrameRateMetrics/FrameMetricsSnapshot.mm rename to Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrameMetricsSnapshot.mm diff --git a/Sources/BugsnagPerformance/Private/FrameRateMetrics/FrozenFrameData.h b/Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrozenFrameData.h similarity index 93% rename from Sources/BugsnagPerformance/Private/FrameRateMetrics/FrozenFrameData.h rename to Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrozenFrameData.h index cf99a293..32f88880 100644 --- a/Sources/BugsnagPerformance/Private/FrameRateMetrics/FrozenFrameData.h +++ b/Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrozenFrameData.h @@ -7,7 +7,7 @@ // #pragma once -#import "../PhasedStartup.h" +#import "../../Core/PhasedStartup.h" @interface FrozenFrameData: NSObject diff --git a/Sources/BugsnagPerformance/Private/FrameRateMetrics/FrozenFrameData.mm b/Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrozenFrameData.mm similarity index 100% rename from Sources/BugsnagPerformance/Private/FrameRateMetrics/FrozenFrameData.mm rename to Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrozenFrameData.mm diff --git a/Sources/BugsnagPerformance/Private/BSGPSystemInfo.h b/Sources/BugsnagPerformance/Private/Metrics/SystemMetrics/BSGPSystemInfo.h similarity index 99% rename from Sources/BugsnagPerformance/Private/BSGPSystemInfo.h rename to Sources/BugsnagPerformance/Private/Metrics/SystemMetrics/BSGPSystemInfo.h index 0a2a3e6e..e1be9b46 100644 --- a/Sources/BugsnagPerformance/Private/BSGPSystemInfo.h +++ b/Sources/BugsnagPerformance/Private/Metrics/SystemMetrics/BSGPSystemInfo.h @@ -10,7 +10,7 @@ #import #import #import -#import "FixedLengthDequeue.h" +#import "../../Utils/FixedLengthDequeue.h" // https://web.mit.edu/darwin/src/modules/xnu/osfmk/man/ diff --git a/Sources/BugsnagPerformance/Private/BSGPSystemInfo.mm b/Sources/BugsnagPerformance/Private/Metrics/SystemMetrics/BSGPSystemInfo.mm similarity index 99% rename from Sources/BugsnagPerformance/Private/BSGPSystemInfo.mm rename to Sources/BugsnagPerformance/Private/Metrics/SystemMetrics/BSGPSystemInfo.mm index bb3d4f9c..4cb54870 100644 --- a/Sources/BugsnagPerformance/Private/BSGPSystemInfo.mm +++ b/Sources/BugsnagPerformance/Private/Metrics/SystemMetrics/BSGPSystemInfo.mm @@ -8,7 +8,7 @@ #import "BSGPSystemInfo.h" #import -#import "Utils.h" +#import "../../Utils/Utils.h" using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Private/SystemInfoSampler.h b/Sources/BugsnagPerformance/Private/Metrics/SystemMetrics/SystemInfoSampler.h similarity index 97% rename from Sources/BugsnagPerformance/Private/SystemInfoSampler.h rename to Sources/BugsnagPerformance/Private/Metrics/SystemMetrics/SystemInfoSampler.h index 593376f4..dc73cfac 100644 --- a/Sources/BugsnagPerformance/Private/SystemInfoSampler.h +++ b/Sources/BugsnagPerformance/Private/Metrics/SystemMetrics/SystemInfoSampler.h @@ -13,8 +13,8 @@ #import #import #import "BSGPSystemInfo.h" -#import "FixedLengthDequeue.h" -#import "PhasedStartup.h" +#import "../../Utils/FixedLengthDequeue.h" +#import "../../Core/PhasedStartup.h" namespace bugsnag { diff --git a/Sources/BugsnagPerformance/Private/SystemInfoSampler.mm b/Sources/BugsnagPerformance/Private/Metrics/SystemMetrics/SystemInfoSampler.mm similarity index 98% rename from Sources/BugsnagPerformance/Private/SystemInfoSampler.mm rename to Sources/BugsnagPerformance/Private/Metrics/SystemMetrics/SystemInfoSampler.mm index 13fe631d..7265b6be 100644 --- a/Sources/BugsnagPerformance/Private/SystemInfoSampler.mm +++ b/Sources/BugsnagPerformance/Private/Metrics/SystemMetrics/SystemInfoSampler.mm @@ -8,8 +8,8 @@ #import "SystemInfoSampler.h" #import -#import "Utils.h" -#import "BugsnagPerformanceConfiguration+Private.h" +#import "../../Utils/Utils.h" +#import "../../Core/Configuration/BugsnagPerformanceConfiguration+Private.h" using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Private/BugsnagPerformancePluginContext+Private.h b/Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformancePluginContext+Private.h similarity index 100% rename from Sources/BugsnagPerformance/Private/BugsnagPerformancePluginContext+Private.h rename to Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformancePluginContext+Private.h diff --git a/Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformancePluginSupport.h b/Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformancePluginSupport.h new file mode 100644 index 00000000..41d397b6 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformancePluginSupport.h @@ -0,0 +1,17 @@ +// +// BugsnagPerformancePluginSupport.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 16/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +// Core Plugin Support +#import "BugsnagPerformancePluginContext+Private.h" +#import "BugsnagPerformanceSpanControlProvider+Private.h" + +// Plugin Manager +#import "PluginManager/BSGPluginManager.h" + +// Span Control +#import "SpanControl/BSGCompositeSpanControlProvider.h" diff --git a/Sources/BugsnagPerformance/Private/BugsnagPerformanceSpanControlProvider+Private.h b/Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformanceSpanControlProvider+Private.h similarity index 100% rename from Sources/BugsnagPerformance/Private/BugsnagPerformanceSpanControlProvider+Private.h rename to Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformanceSpanControlProvider+Private.h diff --git a/Sources/BugsnagPerformance/Private/BSGPluginManager.h b/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.h similarity index 89% rename from Sources/BugsnagPerformance/Private/BSGPluginManager.h rename to Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.h index c1b5f9b7..f7067276 100644 --- a/Sources/BugsnagPerformance/Private/BSGPluginManager.h +++ b/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.h @@ -9,8 +9,8 @@ #import #import #import -#import "BSGPrioritizedStore.h" -#import "SpanControl/BSGCompositeSpanControlProvider.h" +#import "../../Core/BSGPrioritizedStore.h" +#import "../SpanControl/BSGCompositeSpanControlProvider.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/BSGPluginManager.m b/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.m similarity index 97% rename from Sources/BugsnagPerformance/Private/BSGPluginManager.m rename to Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.m index 4a93f9d9..d1ae8497 100644 --- a/Sources/BugsnagPerformance/Private/BSGPluginManager.m +++ b/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.m @@ -7,8 +7,8 @@ // #import "BSGPluginManager.h" -#import "BugsnagPerformancePluginContext+Private.h" -#import "Logging.h" +#import "../BugsnagPerformancePluginContext+Private.h" +#import "../../Utils/Logging.h" @interface BSGPluginManager () diff --git a/Sources/BugsnagPerformance/Private/SpanControl/BSGCompositeSpanControlProvider.h b/Sources/BugsnagPerformance/Private/PluginSupport/SpanControl/BSGCompositeSpanControlProvider.h similarity index 93% rename from Sources/BugsnagPerformance/Private/SpanControl/BSGCompositeSpanControlProvider.h rename to Sources/BugsnagPerformance/Private/PluginSupport/SpanControl/BSGCompositeSpanControlProvider.h index c4f5d710..9694a2df 100644 --- a/Sources/BugsnagPerformance/Private/SpanControl/BSGCompositeSpanControlProvider.h +++ b/Sources/BugsnagPerformance/Private/PluginSupport/SpanControl/BSGCompositeSpanControlProvider.h @@ -8,7 +8,7 @@ #import #import -#import "../BSGPrioritizedStore.h" +#import "../../Core/BSGPrioritizedStore.h" #import "../BugsnagPerformanceSpanControlProvider+Private.h" typedef void (^ BSGCompositeSpanControlProviderBatchBlock)(AddSpanControlProviderBlock addBlock); diff --git a/Sources/BugsnagPerformance/Private/SpanControl/BSGCompositeSpanControlProvider.m b/Sources/BugsnagPerformance/Private/PluginSupport/SpanControl/BSGCompositeSpanControlProvider.m similarity index 100% rename from Sources/BugsnagPerformance/Private/SpanControl/BSGCompositeSpanControlProvider.m rename to Sources/BugsnagPerformance/Private/PluginSupport/SpanControl/BSGCompositeSpanControlProvider.m diff --git a/Sources/BugsnagPerformance/Private/BugsnagPerformanceAppStartSpanControl+Private.h b/Sources/BugsnagPerformance/Private/Plugins/AppStart/BugsnagPerformanceAppStartSpanControl+Private.h similarity index 100% rename from Sources/BugsnagPerformance/Private/BugsnagPerformanceAppStartSpanControl+Private.h rename to Sources/BugsnagPerformance/Private/Plugins/AppStart/BugsnagPerformanceAppStartSpanControl+Private.h diff --git a/Sources/BugsnagPerformance/Private/BugsnagPerformanceAppStartTypePlugin.h b/Sources/BugsnagPerformance/Private/Plugins/AppStart/BugsnagPerformanceAppStartTypePlugin.h similarity index 84% rename from Sources/BugsnagPerformance/Private/BugsnagPerformanceAppStartTypePlugin.h rename to Sources/BugsnagPerformance/Private/Plugins/AppStart/BugsnagPerformanceAppStartTypePlugin.h index 1655088a..efd94043 100644 --- a/Sources/BugsnagPerformance/Private/BugsnagPerformanceAppStartTypePlugin.h +++ b/Sources/BugsnagPerformance/Private/Plugins/AppStart/BugsnagPerformanceAppStartTypePlugin.h @@ -6,10 +6,10 @@ // Copyright © 2025 Bugsnag. All rights reserved. // -#import "SpanStackingHandler.h" +#import "../../Core/SpanStack/SpanStackingHandler.h" #import #import -#import "Instrumentation/Instrumentation.h" +#import "../../Instrumentation/Instrumentation.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/BugsnagPerformanceAppStartTypePlugin.mm b/Sources/BugsnagPerformance/Private/Plugins/AppStart/BugsnagPerformanceAppStartTypePlugin.mm similarity index 94% rename from Sources/BugsnagPerformance/Private/BugsnagPerformanceAppStartTypePlugin.mm rename to Sources/BugsnagPerformance/Private/Plugins/AppStart/BugsnagPerformanceAppStartTypePlugin.mm index f5f10de7..49e96b37 100644 --- a/Sources/BugsnagPerformance/Private/BugsnagPerformanceAppStartTypePlugin.mm +++ b/Sources/BugsnagPerformance/Private/Plugins/AppStart/BugsnagPerformanceAppStartTypePlugin.mm @@ -6,14 +6,14 @@ // Copyright © 2025 Bugsnag. All rights reserved. // -#import "SpanStackingHandler.h" +#import "../../Core/SpanStack/SpanStackingHandler.h" #import #import #import #import #import "BugsnagPerformanceAppStartSpanControl+Private.h" #import "BugsnagPerformanceAppStartTypePlugin.h" -#import "BugsnagPerformanceCrossTalkAPI.h" +#import "../../CrosstalkAPI/BugsnagPerformanceCrossTalkAPI.h" @interface BugsnagPerformanceAppStartTypePlugin() @property (nonatomic) GetAppStartInstrumentationStateSnapshot getAppStartInstrumentationState; diff --git a/Sources/BugsnagPerformance/Private/Tracer.h b/Sources/BugsnagPerformance/Private/Tracer.h index 41dfc637..ba0a5da9 100644 --- a/Sources/BugsnagPerformance/Private/Tracer.h +++ b/Sources/BugsnagPerformance/Private/Tracer.h @@ -9,16 +9,16 @@ #import #import -#import "PhasedStartup.h" -#import "SpanStackingHandler.h" +#import "Core/PhasedStartup.h" +#import "Core/SpanStack/SpanStackingHandler.h" #import "Instrumentation/AppStartupInstrumentation/State/AppStartupInstrumentationStateSnapshot.h" -#import "SpanFactory/Plain/PlainSpanFactoryImpl.h" -#import "SpanFactory/AppStartup/AppStartupSpanFactoryImpl.h" -#import "SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.h" -#import "SpanFactory/Network/NetworkSpanFactoryImpl.h" -#import "SpanFactory/ViewLoad/ViewLoadSpanFactoryCallbacks.h" -#import "SpanLifecycle/SpanLifecycleHandler.h" -#import "SpanStore/SpanStore.h" +#import "Core/SpanFactory/Plain/PlainSpanFactoryImpl.h" +#import "Core/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.h" +#import "Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.h" +#import "Core/SpanFactory/Network/NetworkSpanFactoryImpl.h" +#import "Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryCallbacks.h" +#import "Core/SpanLifecycle/SpanLifecycleHandler.h" +#import "Core/SpanStore/SpanStore.h" #import diff --git a/Sources/BugsnagPerformance/Private/Tracer.mm b/Sources/BugsnagPerformance/Private/Tracer.mm index f125a26a..fd8a990a 100644 --- a/Sources/BugsnagPerformance/Private/Tracer.mm +++ b/Sources/BugsnagPerformance/Private/Tracer.mm @@ -7,13 +7,13 @@ #import "Tracer.h" -#import "SpanAttributes.h" -#import "Utils.h" -#import "BugsnagPerformanceSpan+Private.h" +#import "Core/Attributes/SpanAttributes.h" +#import "Utils/Utils.h" +#import "Core/Span/BugsnagPerformanceSpan+Private.h" #import "Instrumentation/NetworkInstrumentation/NetworkInstrumentation.h" #import "Instrumentation/ViewLoadInstrumentation/ViewLoadInstrumentation.h" -#import "BugsnagPerformanceLibrary.h" -#import "FrameRateMetrics/FrameMetricsCollector.h" +#import "Main/BugsnagPerformanceLibrary.h" +#import "Metrics/FrameMetrics/FrameMetricsCollector.h" #import using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Private/OtlpPackage.h b/Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpPackage.h similarity index 100% rename from Sources/BugsnagPerformance/Private/OtlpPackage.h rename to Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpPackage.h diff --git a/Sources/BugsnagPerformance/Private/OtlpPackage.mm b/Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpPackage.mm similarity index 100% rename from Sources/BugsnagPerformance/Private/OtlpPackage.mm rename to Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpPackage.mm diff --git a/Sources/BugsnagPerformance/Private/OtlpTraceEncoding.h b/Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpTraceEncoding.h similarity index 94% rename from Sources/BugsnagPerformance/Private/OtlpTraceEncoding.h rename to Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpTraceEncoding.h index 1a65dd36..a9c3d71e 100644 --- a/Sources/BugsnagPerformance/Private/OtlpTraceEncoding.h +++ b/Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpTraceEncoding.h @@ -10,8 +10,8 @@ #import #import "OtlpPackage.h" -#import "BugsnagPerformanceSpan+Private.h" -#import "PhasedStartup.h" +#import "../../Core/Span/BugsnagPerformanceSpan+Private.h" +#import "../../Core/PhasedStartup.h" #import diff --git a/Sources/BugsnagPerformance/Private/OtlpTraceEncoding.mm b/Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpTraceEncoding.mm similarity index 99% rename from Sources/BugsnagPerformance/Private/OtlpTraceEncoding.mm rename to Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpTraceEncoding.mm index 00921715..89bdbbaa 100644 --- a/Sources/BugsnagPerformance/Private/OtlpTraceEncoding.mm +++ b/Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpTraceEncoding.mm @@ -5,11 +5,11 @@ // Created by Nick Dowell on 27/09/2022. // -#import "BugsnagPerformanceSpan+Private.h" +#import "../../Core/Span/BugsnagPerformanceSpan+Private.h" #import "OtlpTraceEncoding.h" #import -#import "Utils.h" -#import "Gzip.h" +#import "../../Utils/Utils.h" +#import "../../Utils/Gzip.h" using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Private/OtlpUploader.h b/Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpUploader.h similarity index 100% rename from Sources/BugsnagPerformance/Private/OtlpUploader.h rename to Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpUploader.h diff --git a/Sources/BugsnagPerformance/Private/OtlpUploader.mm b/Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpUploader.mm similarity index 99% rename from Sources/BugsnagPerformance/Private/OtlpUploader.mm rename to Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpUploader.mm index cc5b814a..e8fa5236 100644 --- a/Sources/BugsnagPerformance/Private/OtlpUploader.mm +++ b/Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpUploader.mm @@ -7,7 +7,7 @@ // #import "OtlpUploader.h" -#import "Utils.h" +#import "../../Utils/Utils.h" using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Private/Uploader.h b/Sources/BugsnagPerformance/Private/Upload/Otlp/Uploader.h similarity index 100% rename from Sources/BugsnagPerformance/Private/Uploader.h rename to Sources/BugsnagPerformance/Private/Upload/Otlp/Uploader.h diff --git a/Sources/BugsnagPerformance/Private/RetryQueue.h b/Sources/BugsnagPerformance/Private/Upload/RetryQueue.h similarity index 96% rename from Sources/BugsnagPerformance/Private/RetryQueue.h rename to Sources/BugsnagPerformance/Private/Upload/RetryQueue.h index 744336d5..a9bd7ce6 100644 --- a/Sources/BugsnagPerformance/Private/RetryQueue.h +++ b/Sources/BugsnagPerformance/Private/Upload/RetryQueue.h @@ -8,8 +8,8 @@ #pragma once -#import "OtlpPackage.h" -#import "PhasedStartup.h" +#import "Otlp/OtlpPackage.h" +#import "../Core/PhasedStartup.h" #import #import diff --git a/Sources/BugsnagPerformance/Private/RetryQueue.mm b/Sources/BugsnagPerformance/Private/Upload/RetryQueue.mm similarity index 97% rename from Sources/BugsnagPerformance/Private/RetryQueue.mm rename to Sources/BugsnagPerformance/Private/Upload/RetryQueue.mm index 9ecf9d81..475c8c48 100644 --- a/Sources/BugsnagPerformance/Private/RetryQueue.mm +++ b/Sources/BugsnagPerformance/Private/Upload/RetryQueue.mm @@ -7,9 +7,9 @@ // #import "RetryQueue.h" -#import "Filesystem.h" -#import "BugsnagPerformanceConfiguration+Private.h" -#import "Utils.h" +#import "../Utils/Filesystem.h" +#import "../Core/Configuration/BugsnagPerformanceConfiguration+Private.h" +#import "../Utils/Utils.h" #import // No valid file < 24h old will ever have a timestamp of 0. diff --git a/Sources/BugsnagPerformance/Private/AppStateTracker.h b/Sources/BugsnagPerformance/Private/Utils/AppStateTracker.h similarity index 100% rename from Sources/BugsnagPerformance/Private/AppStateTracker.h rename to Sources/BugsnagPerformance/Private/Utils/AppStateTracker.h diff --git a/Sources/BugsnagPerformance/Private/AppStateTracker.m b/Sources/BugsnagPerformance/Private/Utils/AppStateTracker.m similarity index 100% rename from Sources/BugsnagPerformance/Private/AppStateTracker.m rename to Sources/BugsnagPerformance/Private/Utils/AppStateTracker.m diff --git a/Sources/BugsnagPerformance/Private/BugsnagSwiftTools.h b/Sources/BugsnagPerformance/Private/Utils/BugsnagSwiftTools.h similarity index 100% rename from Sources/BugsnagPerformance/Private/BugsnagSwiftTools.h rename to Sources/BugsnagPerformance/Private/Utils/BugsnagSwiftTools.h diff --git a/Sources/BugsnagPerformance/Private/BugsnagSwiftTools.m b/Sources/BugsnagPerformance/Private/Utils/BugsnagSwiftTools.m similarity index 100% rename from Sources/BugsnagPerformance/Private/BugsnagSwiftTools.m rename to Sources/BugsnagPerformance/Private/Utils/BugsnagSwiftTools.m diff --git a/Sources/BugsnagPerformance/Private/Filesystem.h b/Sources/BugsnagPerformance/Private/Utils/Filesystem.h similarity index 100% rename from Sources/BugsnagPerformance/Private/Filesystem.h rename to Sources/BugsnagPerformance/Private/Utils/Filesystem.h diff --git a/Sources/BugsnagPerformance/Private/Filesystem.mm b/Sources/BugsnagPerformance/Private/Utils/Filesystem.mm similarity index 100% rename from Sources/BugsnagPerformance/Private/Filesystem.mm rename to Sources/BugsnagPerformance/Private/Utils/Filesystem.mm diff --git a/Sources/BugsnagPerformance/Private/FixedLengthDequeue.h b/Sources/BugsnagPerformance/Private/Utils/FixedLengthDequeue.h similarity index 100% rename from Sources/BugsnagPerformance/Private/FixedLengthDequeue.h rename to Sources/BugsnagPerformance/Private/Utils/FixedLengthDequeue.h diff --git a/Sources/BugsnagPerformance/Private/Gzip.h b/Sources/BugsnagPerformance/Private/Utils/Gzip.h similarity index 100% rename from Sources/BugsnagPerformance/Private/Gzip.h rename to Sources/BugsnagPerformance/Private/Utils/Gzip.h diff --git a/Sources/BugsnagPerformance/Private/Gzip.m b/Sources/BugsnagPerformance/Private/Utils/Gzip.m similarity index 100% rename from Sources/BugsnagPerformance/Private/Gzip.m rename to Sources/BugsnagPerformance/Private/Utils/Gzip.m diff --git a/Sources/BugsnagPerformance/Private/IdGenerator.h b/Sources/BugsnagPerformance/Private/Utils/IdGenerator.h similarity index 100% rename from Sources/BugsnagPerformance/Private/IdGenerator.h rename to Sources/BugsnagPerformance/Private/Utils/IdGenerator.h diff --git a/Sources/BugsnagPerformance/Private/JSON.h b/Sources/BugsnagPerformance/Private/Utils/JSON.h similarity index 100% rename from Sources/BugsnagPerformance/Private/JSON.h rename to Sources/BugsnagPerformance/Private/Utils/JSON.h diff --git a/Sources/BugsnagPerformance/Private/JSON.mm b/Sources/BugsnagPerformance/Private/Utils/JSON.mm similarity index 100% rename from Sources/BugsnagPerformance/Private/JSON.mm rename to Sources/BugsnagPerformance/Private/Utils/JSON.mm diff --git a/Sources/BugsnagPerformance/Private/Logging.h b/Sources/BugsnagPerformance/Private/Utils/Logging.h similarity index 100% rename from Sources/BugsnagPerformance/Private/Logging.h rename to Sources/BugsnagPerformance/Private/Utils/Logging.h diff --git a/Sources/BugsnagPerformance/Private/ObjCUtils.h b/Sources/BugsnagPerformance/Private/Utils/ObjCUtils.h similarity index 100% rename from Sources/BugsnagPerformance/Private/ObjCUtils.h rename to Sources/BugsnagPerformance/Private/Utils/ObjCUtils.h diff --git a/Sources/BugsnagPerformance/Private/ObjCUtils.mm b/Sources/BugsnagPerformance/Private/Utils/ObjCUtils.mm similarity index 100% rename from Sources/BugsnagPerformance/Private/ObjCUtils.mm rename to Sources/BugsnagPerformance/Private/Utils/ObjCUtils.mm diff --git a/Sources/BugsnagPerformance/Private/Persistence.h b/Sources/BugsnagPerformance/Private/Utils/Persistence.h similarity index 100% rename from Sources/BugsnagPerformance/Private/Persistence.h rename to Sources/BugsnagPerformance/Private/Utils/Persistence.h diff --git a/Sources/BugsnagPerformance/Private/Persistence.mm b/Sources/BugsnagPerformance/Private/Utils/Persistence.mm similarity index 100% rename from Sources/BugsnagPerformance/Private/Persistence.mm rename to Sources/BugsnagPerformance/Private/Utils/Persistence.mm diff --git a/Sources/BugsnagPerformance/Private/PersistentDeviceID.h b/Sources/BugsnagPerformance/Private/Utils/PersistentDeviceID.h similarity index 97% rename from Sources/BugsnagPerformance/Private/PersistentDeviceID.h rename to Sources/BugsnagPerformance/Private/Utils/PersistentDeviceID.h index 3f9bb352..5792dde3 100644 --- a/Sources/BugsnagPerformance/Private/PersistentDeviceID.h +++ b/Sources/BugsnagPerformance/Private/Utils/PersistentDeviceID.h @@ -8,7 +8,7 @@ #pragma once -#import "PhasedStartup.h" +#import "../Core/PhasedStartup.h" #import "Persistence.h" #import diff --git a/Sources/BugsnagPerformance/Private/PersistentDeviceID.mm b/Sources/BugsnagPerformance/Private/Utils/PersistentDeviceID.mm similarity index 99% rename from Sources/BugsnagPerformance/Private/PersistentDeviceID.mm rename to Sources/BugsnagPerformance/Private/Utils/PersistentDeviceID.mm index c00b66dc..8c15aecd 100644 --- a/Sources/BugsnagPerformance/Private/PersistentDeviceID.mm +++ b/Sources/BugsnagPerformance/Private/Utils/PersistentDeviceID.mm @@ -7,7 +7,7 @@ // #import "PersistentDeviceID.h" -#import "Version.h" +#import "../Version.h" #import "JSON.h" #import "Filesystem.h" diff --git a/Sources/BugsnagPerformance/Private/Reachability.h b/Sources/BugsnagPerformance/Private/Utils/Reachability.h similarity index 100% rename from Sources/BugsnagPerformance/Private/Reachability.h rename to Sources/BugsnagPerformance/Private/Utils/Reachability.h diff --git a/Sources/BugsnagPerformance/Private/Reachability.mm b/Sources/BugsnagPerformance/Private/Utils/Reachability.mm similarity index 100% rename from Sources/BugsnagPerformance/Private/Reachability.mm rename to Sources/BugsnagPerformance/Private/Utils/Reachability.mm diff --git a/Sources/BugsnagPerformance/Private/Swizzle.h b/Sources/BugsnagPerformance/Private/Utils/Swizzle.h similarity index 100% rename from Sources/BugsnagPerformance/Private/Swizzle.h rename to Sources/BugsnagPerformance/Private/Utils/Swizzle.h diff --git a/Sources/BugsnagPerformance/Private/Swizzle.mm b/Sources/BugsnagPerformance/Private/Utils/Swizzle.mm similarity index 100% rename from Sources/BugsnagPerformance/Private/Swizzle.mm rename to Sources/BugsnagPerformance/Private/Utils/Swizzle.mm diff --git a/Sources/BugsnagPerformance/Private/Targets.h b/Sources/BugsnagPerformance/Private/Utils/Targets.h similarity index 100% rename from Sources/BugsnagPerformance/Private/Targets.h rename to Sources/BugsnagPerformance/Private/Utils/Targets.h diff --git a/Sources/BugsnagPerformance/Private/Utils.h b/Sources/BugsnagPerformance/Private/Utils/Utils.h similarity index 100% rename from Sources/BugsnagPerformance/Private/Utils.h rename to Sources/BugsnagPerformance/Private/Utils/Utils.h diff --git a/Sources/BugsnagPerformance/Public/BugsnagPerformance.mm b/Sources/BugsnagPerformance/Public/BugsnagPerformance.mm index 24d2c4a9..a8445b8d 100644 --- a/Sources/BugsnagPerformance/Public/BugsnagPerformance.mm +++ b/Sources/BugsnagPerformance/Public/BugsnagPerformance.mm @@ -7,7 +7,7 @@ #import -#import "../Private/BugsnagPerformanceLibrary.h" +#import "../Private/Main/BugsnagPerformanceLibrary.h" using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Public/BugsnagPerformanceAppStartSpanControl.mm b/Sources/BugsnagPerformance/Public/BugsnagPerformanceAppStartSpanControl.mm index d6726a1c..4797fa83 100644 --- a/Sources/BugsnagPerformance/Public/BugsnagPerformanceAppStartSpanControl.mm +++ b/Sources/BugsnagPerformance/Public/BugsnagPerformanceAppStartSpanControl.mm @@ -7,9 +7,9 @@ // #import -#import "../Private/BugsnagPerformanceSpan+Private.h" +#import "../Private/Core/Span/BugsnagPerformanceSpan+Private.h" #import -#import "../Private/BugsnagPerformanceAppStartSpanControl+Private.h" +#import "../Private/Plugins/AppStart/BugsnagPerformanceAppStartSpanControl+Private.h" static NSString * const AppStartNameAttribute = @"bugsnag.app_start.name"; diff --git a/Sources/BugsnagPerformance/Public/BugsnagPerformanceConfiguration.mm b/Sources/BugsnagPerformance/Public/BugsnagPerformanceConfiguration.mm index ba28f0ff..8da554e9 100644 --- a/Sources/BugsnagPerformance/Public/BugsnagPerformanceConfiguration.mm +++ b/Sources/BugsnagPerformance/Public/BugsnagPerformanceConfiguration.mm @@ -5,10 +5,10 @@ // Created by Nick Dowell on 23/09/2022. // -#import "../Private/BugsnagPerformanceConfiguration+Private.h" +#import "../Private/Core/Configuration/BugsnagPerformanceConfiguration+Private.h" -#import "../Private/Utils.h" -#import "../Private/ObjCUtils.h" +#import "../Private/Utils/Utils.h" +#import "../Private/Utils/ObjCUtils.h" using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Public/BugsnagPerformanceLoadingIndicatorView.mm b/Sources/BugsnagPerformance/Public/BugsnagPerformanceLoadingIndicatorView.mm index 7717c6c6..f4bd0c19 100644 --- a/Sources/BugsnagPerformance/Public/BugsnagPerformanceLoadingIndicatorView.mm +++ b/Sources/BugsnagPerformance/Public/BugsnagPerformanceLoadingIndicatorView.mm @@ -7,9 +7,9 @@ // #import -#import "../Private/Logging.h" -#import "../Private/BugsnagPerformanceLibrary.h" -#import "../Private/BugsnagPerformanceSpanCondition+Private.h" +#import "../Private/Utils/Logging.h" +#import "../Private/Main/BugsnagPerformanceLibrary.h" +#import "../Private/Core/SpanConditions/BugsnagPerformanceSpanCondition+Private.h" @interface BugsnagPerformanceLoadingIndicatorView() @property (nonatomic, strong) NSMutableArray *conditions; diff --git a/Sources/BugsnagPerformance/Public/BugsnagPerformancePluginContext.m b/Sources/BugsnagPerformance/Public/BugsnagPerformancePluginContext.m index 9cec1a8a..9f51b9c0 100644 --- a/Sources/BugsnagPerformance/Public/BugsnagPerformancePluginContext.m +++ b/Sources/BugsnagPerformance/Public/BugsnagPerformancePluginContext.m @@ -6,8 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // -#import "../Private/BugsnagPerformancePluginContext+Private.h" -#import "../Private/BugsnagPerformanceSpanControlProvider+Private.h" +#import "../Private/PluginSupport/BugsnagPerformancePluginContext+Private.h" +#import "../Private/PluginSupport/BugsnagPerformanceSpanControlProvider+Private.h" @interface BugsnagPerformancePluginContext () @property (nonatomic, strong) BugsnagPerformanceConfiguration *configuration_; diff --git a/Sources/BugsnagPerformance/Public/BugsnagPerformanceRemoteSpanContext.mm b/Sources/BugsnagPerformance/Public/BugsnagPerformanceRemoteSpanContext.mm index 39da73dc..dbfd9f16 100644 --- a/Sources/BugsnagPerformance/Public/BugsnagPerformanceRemoteSpanContext.mm +++ b/Sources/BugsnagPerformance/Public/BugsnagPerformanceRemoteSpanContext.mm @@ -8,7 +8,7 @@ #import #import -#import "../Private/Utils.h" +#import "../Private/Utils/Utils.h" static const int kTraceParentComponentTraceId = 1; static const int kTraceParentComponentSpanId = 2; diff --git a/Sources/BugsnagPerformance/Public/BugsnagPerformanceSpan.mm b/Sources/BugsnagPerformance/Public/BugsnagPerformanceSpan.mm index 9301ba0d..789910ae 100644 --- a/Sources/BugsnagPerformance/Public/BugsnagPerformanceSpan.mm +++ b/Sources/BugsnagPerformance/Public/BugsnagPerformanceSpan.mm @@ -5,10 +5,10 @@ // Created by Nick Dowell on 23/09/2022. // -#import "../Private/BugsnagPerformanceSpan+Private.h" -#import "../Private/Utils.h" -#import "../Private/SpanOptions.h" -#import "../Private/Sampler.h" +#import "../Private/Core/Span/BugsnagPerformanceSpan+Private.h" +#import "../Private/Utils/Utils.h" +#import "../Private/Core/Span/SpanOptions.h" +#import "../Private/Core/Sampler/Sampler.h" using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/include/BugsnagPerformance/BugsnagPerformanceSpanCondition.h b/Sources/BugsnagPerformance/include/BugsnagPerformance/BugsnagPerformanceSpanCondition.h index e1915199..826a7ccb 100644 --- a/Sources/BugsnagPerformance/include/BugsnagPerformance/BugsnagPerformanceSpanCondition.h +++ b/Sources/BugsnagPerformance/include/BugsnagPerformance/BugsnagPerformanceSpanCondition.h @@ -7,7 +7,6 @@ // #import -#import #import OBJC_EXPORT @@ -20,4 +19,3 @@ OBJC_EXPORT - (void)cancel; @end - diff --git a/Tests/BugsnagPerformanceTests/BugsnagPerformanceSpanTests.mm b/Tests/BugsnagPerformanceTests/BugsnagPerformanceSpanTests.mm index 332f573e..31ecbb84 100644 --- a/Tests/BugsnagPerformanceTests/BugsnagPerformanceSpanTests.mm +++ b/Tests/BugsnagPerformanceTests/BugsnagPerformanceSpanTests.mm @@ -9,7 +9,7 @@ #import #import #import -#import "../../Sources/BugsnagPerformance/Private/BugsnagPerformanceConfiguration+Private.h" +#import "../../Sources/BugsnagPerformance/Private/Core/Configuration/BugsnagPerformanceConfiguration+Private.h" #import "BugsnagPerformanceSpan+Private.h" static BugsnagPerformanceSpan *createSpan(TraceId traceId, SpanId spanId, double samplingProbability) { diff --git a/Tests/BugsnagPerformanceTests/OtlpTraceEncodingTests.mm b/Tests/BugsnagPerformanceTests/OtlpTraceEncodingTests.mm index 9af401ca..6e15c062 100644 --- a/Tests/BugsnagPerformanceTests/OtlpTraceEncodingTests.mm +++ b/Tests/BugsnagPerformanceTests/OtlpTraceEncodingTests.mm @@ -7,7 +7,7 @@ #import -#import "../../Sources/BugsnagPerformance/Private/OtlpTraceEncoding.h" +#import "../../Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpTraceEncoding.h" #define XCTAssertIsKindOfClass(EXPR, CLASS) ({ \ id obj = EXPR; \ diff --git a/Tests/BugsnagPerformanceTests/ResourceAttributesTests.mm b/Tests/BugsnagPerformanceTests/ResourceAttributesTests.mm index ee55b7c8..4310b5ca 100644 --- a/Tests/BugsnagPerformanceTests/ResourceAttributesTests.mm +++ b/Tests/BugsnagPerformanceTests/ResourceAttributesTests.mm @@ -8,8 +8,8 @@ #import "FileBasedTest.h" -#import "../../Sources/BugsnagPerformance/Private/ResourceAttributes.h" -#import "../../Sources/BugsnagPerformance/Private/PersistentState.h" +#import "../../Sources/BugsnagPerformance/Private/Core/Attributes/ResourceAttributes.h" +#import "../../Sources/BugsnagPerformance/Private/Core/Sampler/PersistentState.h" #import using namespace bugsnag; diff --git a/Tests/BugsnagPerformanceTests/SamplerTests.mm b/Tests/BugsnagPerformanceTests/SamplerTests.mm index da7c00bf..e1981a76 100644 --- a/Tests/BugsnagPerformanceTests/SamplerTests.mm +++ b/Tests/BugsnagPerformanceTests/SamplerTests.mm @@ -8,8 +8,8 @@ #import -#import "../../Sources/BugsnagPerformance/Private/Sampler.h" -#import "../../Sources/BugsnagPerformance/Private/BugsnagPerformanceConfiguration+Private.h" +#import "../../Sources/BugsnagPerformance/Private/Core/Sampler/Sampler.h" +#import "../../Sources/BugsnagPerformance/Private/Core/Configuration/BugsnagPerformanceConfiguration+Private.h" #import "BugsnagPerformanceSpan+Private.h" #import diff --git a/Tests/BugsnagPerformanceTests/SpanAttributesTests.mm b/Tests/BugsnagPerformanceTests/SpanAttributesTests.mm index 58ad5b39..2e39dd77 100644 --- a/Tests/BugsnagPerformanceTests/SpanAttributesTests.mm +++ b/Tests/BugsnagPerformanceTests/SpanAttributesTests.mm @@ -7,7 +7,7 @@ // #import "TestHelpers.h" -#import "../../Sources/BugsnagPerformance/Private/SpanAttributesProvider.h" +#import "../../Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributesProvider.h" using namespace bugsnag; diff --git a/features/fixtures/ios/Fixture.xcodeproj/project.pbxproj b/features/fixtures/ios/Fixture.xcodeproj/project.pbxproj index b39cf540..4a6cbcc5 100644 --- a/features/fixtures/ios/Fixture.xcodeproj/project.pbxproj +++ b/features/fixtures/ios/Fixture.xcodeproj/project.pbxproj @@ -201,7 +201,7 @@ 96F5268B2C259E4E0095D600 /* ManualNetworkSpanCallbackSetToNilScenario.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManualNetworkSpanCallbackSetToNilScenario.swift; sourceTree = ""; }; CB0496932913CA300097E526 /* BatchingWithTimeoutScenario.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatchingWithTimeoutScenario.swift; sourceTree = ""; }; CB0AD76D2965BBDA002A3FB6 /* InitialPScenario.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InitialPScenario.swift; sourceTree = ""; }; - CB211D0629EEB615008F748D /* BugsnagPerformanceConfiguration+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "BugsnagPerformanceConfiguration+Private.h"; path = "../../../../Sources/BugsnagPerformance/Private/BugsnagPerformanceConfiguration+Private.h"; sourceTree = ""; }; + CB211D0629EEB615008F748D /* BugsnagPerformanceConfiguration+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "BugsnagPerformanceConfiguration+Private.h"; path = "../../../../Sources/BugsnagPerformance/Private/Core/Configuration/BugsnagPerformanceConfiguration+Private.h"; sourceTree = ""; }; CB2B8A9C2A0CCEF90054FBBE /* AutoInstrumentFileURLRequestScenario.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoInstrumentFileURLRequestScenario.swift; sourceTree = ""; }; CB2B8A9E2A0E80B80054FBBE /* AutoInstrumentNetworkBadAddressScenario.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoInstrumentNetworkBadAddressScenario.swift; sourceTree = ""; }; CB3477172901481F0033759C /* AutoInstrumentNetworkWithParentScenario.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoInstrumentNetworkWithParentScenario.swift; sourceTree = ""; }; diff --git a/features/fixtures/ios/FixtureXcFramework.xcodeproj/project.pbxproj b/features/fixtures/ios/FixtureXcFramework.xcodeproj/project.pbxproj index 4a2bc662..885160cc 100644 --- a/features/fixtures/ios/FixtureXcFramework.xcodeproj/project.pbxproj +++ b/features/fixtures/ios/FixtureXcFramework.xcodeproj/project.pbxproj @@ -214,7 +214,7 @@ 96F5268B2C259E4E0095D600 /* ManualNetworkSpanCallbackSetToNilScenario.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManualNetworkSpanCallbackSetToNilScenario.swift; sourceTree = ""; }; CB0496932913CA300097E526 /* BatchingWithTimeoutScenario.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatchingWithTimeoutScenario.swift; sourceTree = ""; }; CB0AD76D2965BBDA002A3FB6 /* InitialPScenario.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InitialPScenario.swift; sourceTree = ""; }; - CB211D0629EEB615008F748D /* BugsnagPerformanceConfiguration+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "BugsnagPerformanceConfiguration+Private.h"; path = "../../../../Sources/BugsnagPerformance/Private/BugsnagPerformanceConfiguration+Private.h"; sourceTree = ""; }; + CB211D0629EEB615008F748D /* BugsnagPerformanceConfiguration+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "BugsnagPerformanceConfiguration+Private.h"; path = "../../../../Sources/BugsnagPerformance/Private/Core/Configuration/BugsnagPerformanceConfiguration+Private.h"; sourceTree = ""; }; CB2B8A9C2A0CCEF90054FBBE /* AutoInstrumentFileURLRequestScenario.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoInstrumentFileURLRequestScenario.swift; sourceTree = ""; }; CB2B8A9E2A0E80B80054FBBE /* AutoInstrumentNetworkBadAddressScenario.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoInstrumentNetworkBadAddressScenario.swift; sourceTree = ""; }; CB3477172901481F0033759C /* AutoInstrumentNetworkWithParentScenario.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoInstrumentNetworkWithParentScenario.swift; sourceTree = ""; }; From c0b79114a9176f0709b0833b59f1277c5e8a874e Mon Sep 17 00:00:00 2001 From: Robert Bartoszewski Date: Thu, 16 Oct 2025 17:23:31 +0200 Subject: [PATCH 03/14] Added #pragma once to private headers --- .../Private/Core/Attributes/SpanAttributesProvider.h | 2 ++ Sources/BugsnagPerformance/Private/Core/BSGPrioritizedStore.h | 2 ++ .../Private/Core/BugsnagPerformancePriority+Private.h | 2 ++ .../Private/Core/BugsnagPerformanceViewType+Private.h | 2 ++ .../Private/Core/Configuration/EarlyConfiguration.h | 2 ++ Sources/BugsnagPerformance/Private/Core/Span/SpanOptions.h | 2 ++ .../SpanConditions/BugsnagPerformanceSpanCondition+Private.h | 2 ++ .../Private/Core/SpanFactory/AppStartup/AppStartupSpanFactory.h | 2 ++ .../Core/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.h | 2 ++ .../Private/Core/SpanFactory/Network/NetworkSpanFactory.h | 2 ++ .../Private/Core/SpanFactory/Network/NetworkSpanFactoryImpl.h | 2 ++ .../Private/Core/SpanFactory/Plain/PlainSpanFactory.h | 2 ++ .../Private/Core/SpanFactory/Plain/PlainSpanFactoryCallbacks.h | 2 ++ .../Private/Core/SpanFactory/Plain/PlainSpanFactoryImpl.h | 2 ++ .../Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactory.h | 2 ++ .../Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryCallbacks.h | 2 ++ .../Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.h | 2 ++ .../Private/Core/SpanLifecycle/SpanLifecycleHandler.h | 2 ++ .../Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.h | 2 ++ .../Core/SpanProcessingPipeline/SpanProcessingPipeline.h | 2 ++ .../Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.h | 2 ++ .../Core/SpanProcessingPipeline/SpanProcessingPipelineStep.h | 2 ++ .../Private/Core/SpanStack/SpanActivityState.h | 2 ++ .../Private/Core/SpanStack/SpanStackingHandler.h | 2 ++ Sources/BugsnagPerformance/Private/Core/SpanStore/SpanStore.h | 2 ++ .../BugsnagPerformance/Private/Core/SpanStore/SpanStoreImpl.h | 2 ++ .../BugsnagPerformance/Private/Core/SpanStore/WeakSpansList.h | 2 ++ .../Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h | 2 ++ .../Lifecycle/AppStartupLifecycleHandler.h | 2 ++ .../Lifecycle/AppStartupLifecycleHandlerImpl.h | 2 ++ .../State/AppStartupInstrumentationStateSnapshot.h | 2 ++ .../System/AppStartupInstrumentationSystemUtils.h | 2 ++ .../System/AppStartupInstrumentationSystemUtilsImpl.h | 2 ++ .../BugsnagPerformanceLoadingIndicatorView+Private.h | 2 ++ .../NetworkInstrumentation/Lifecycle/NetworkEarlyPhaseHandler.h | 2 ++ .../Lifecycle/NetworkEarlyPhaseHandlerImpl.h | 2 ++ .../NetworkInstrumentation/Lifecycle/NetworkLifecycleHandler.h | 2 ++ .../Lifecycle/NetworkLifecycleHandlerImpl.h | 2 ++ .../NetworkInstrumentation/State/NetworkInstrumentationState.h | 2 ++ .../State/NetworkInstrumentationStateRepository.h | 2 ++ .../State/NetworkInstrumentationStateRepositoryImpl.h | 2 ++ .../System/BSGURLSessionPerformanceDelegate.h | 2 ++ .../NetworkInstrumentation/System/NetworkHeaderInjector.h | 2 ++ .../System/NetworkInstrumentationSystemUtils.h | 2 ++ .../System/NetworkInstrumentationSystemUtilsImpl.h | 2 ++ .../NetworkInstrumentation/System/NetworkSwizzlingHandler.h | 2 ++ .../NetworkInstrumentation/System/NetworkSwizzlingHandlerImpl.h | 2 ++ .../System/Proxy/BSGPerformanceSharedSessionProxy.h | 2 ++ .../Lifecycle/ViewLoadEarlyPhaseHandler.h | 2 ++ .../Lifecycle/ViewLoadEarlyPhaseHandlerImpl.h | 2 ++ .../Lifecycle/ViewLoadLifecycleHandler.h | 2 ++ .../Lifecycle/ViewLoadLifecycleHandlerImpl.h | 2 ++ .../Lifecycle/ViewLoadLoadingIndicatorsHandler.h | 2 ++ .../Lifecycle/ViewLoadLoadingIndicatorsHandlerImpl.h | 2 ++ .../State/ViewLoadInstrumentationState.h | 2 ++ .../State/ViewLoadInstrumentationStateRepository.h | 2 ++ .../State/ViewLoadInstrumentationStateRepositoryImpl.h | 2 ++ .../System/ViewLoadInstrumentationSystemUtils.h | 2 ++ .../System/ViewLoadInstrumentationSystemUtilsImpl.h | 2 ++ .../ViewLoadInstrumentation/System/ViewLoadSwizzlingCallbacks.h | 2 ++ .../ViewLoadInstrumentation/System/ViewLoadSwizzlingHandler.h | 2 ++ .../System/ViewLoadSwizzlingHandlerImpl.h | 2 ++ .../Private/Metrics/SystemMetrics/BSGPSystemInfo.h | 2 ++ .../PluginSupport/BugsnagPerformancePluginContext+Private.h | 2 ++ .../Private/PluginSupport/BugsnagPerformancePluginSupport.h | 2 ++ .../BugsnagPerformanceSpanControlProvider+Private.h | 2 ++ .../Private/PluginSupport/PluginManager/BSGPluginManager.h | 2 ++ .../PluginSupport/SpanControl/BSGCompositeSpanControlProvider.h | 2 ++ .../AppStart/BugsnagPerformanceAppStartSpanControl+Private.h | 2 ++ .../Plugins/AppStart/BugsnagPerformanceAppStartTypePlugin.h | 2 ++ Sources/BugsnagPerformance/Private/Utils/AppStateTracker.h | 2 ++ Sources/BugsnagPerformance/Private/Utils/BugsnagSwiftTools.h | 2 ++ Sources/BugsnagPerformance/Private/Utils/Filesystem.h | 2 ++ Sources/BugsnagPerformance/Private/Utils/Gzip.h | 2 ++ Sources/BugsnagPerformance/Private/Utils/Logging.h | 2 ++ Sources/BugsnagPerformance/Private/Utils/Targets.h | 2 ++ 76 files changed, 152 insertions(+) diff --git a/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributesProvider.h b/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributesProvider.h index ac1250c7..ff43731f 100644 --- a/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributesProvider.h +++ b/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributesProvider.h @@ -5,6 +5,8 @@ // Created by Robert Bartoszewski on 21/04/2023. // Copyright © 2023 Bugsnag. All rights reserved. // + +#pragma once #import #import "../BugsnagPerformanceViewType+Private.h" #import "../../Metrics/SystemMetrics/SystemInfoSampler.h" diff --git a/Sources/BugsnagPerformance/Private/Core/BSGPrioritizedStore.h b/Sources/BugsnagPerformance/Private/Core/BSGPrioritizedStore.h index 4f4f4906..d11e8810 100644 --- a/Sources/BugsnagPerformance/Private/Core/BSGPrioritizedStore.h +++ b/Sources/BugsnagPerformance/Private/Core/BSGPrioritizedStore.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/Core/BugsnagPerformancePriority+Private.h b/Sources/BugsnagPerformance/Private/Core/BugsnagPerformancePriority+Private.h index f648cbfd..9adb4e20 100644 --- a/Sources/BugsnagPerformance/Private/Core/BugsnagPerformancePriority+Private.h +++ b/Sources/BugsnagPerformance/Private/Core/BugsnagPerformancePriority+Private.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import extern const BugsnagPerformancePriority BugsnagPerformancePriorityMax; diff --git a/Sources/BugsnagPerformance/Private/Core/BugsnagPerformanceViewType+Private.h b/Sources/BugsnagPerformance/Private/Core/BugsnagPerformanceViewType+Private.h index 2d3493cf..32e12128 100644 --- a/Sources/BugsnagPerformance/Private/Core/BugsnagPerformanceViewType+Private.h +++ b/Sources/BugsnagPerformance/Private/Core/BugsnagPerformanceViewType+Private.h @@ -6,6 +6,8 @@ // Copyright © 2023 Bugsnag. All rights reserved. // +#pragma once + #import namespace bugsnag { diff --git a/Sources/BugsnagPerformance/Private/Core/Configuration/EarlyConfiguration.h b/Sources/BugsnagPerformance/Private/Core/Configuration/EarlyConfiguration.h index 13ada9c9..9b085895 100644 --- a/Sources/BugsnagPerformance/Private/Core/Configuration/EarlyConfiguration.h +++ b/Sources/BugsnagPerformance/Private/Core/Configuration/EarlyConfiguration.h @@ -6,6 +6,8 @@ // Copyright © 2023 Bugsnag. All rights reserved. // +#pragma once + #import NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/Core/Span/SpanOptions.h b/Sources/BugsnagPerformance/Private/Core/Span/SpanOptions.h index 64e0c092..b53e394e 100644 --- a/Sources/BugsnagPerformance/Private/Core/Span/SpanOptions.h +++ b/Sources/BugsnagPerformance/Private/Core/Span/SpanOptions.h @@ -6,6 +6,8 @@ // Copyright © 2023 Bugsnag. All rights reserved. // +#pragma once + #import #import #import "../../Utils/Utils.h" diff --git a/Sources/BugsnagPerformance/Private/Core/SpanConditions/BugsnagPerformanceSpanCondition+Private.h b/Sources/BugsnagPerformance/Private/Core/SpanConditions/BugsnagPerformanceSpanCondition+Private.h index 24af2807..7786974f 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanConditions/BugsnagPerformanceSpanCondition+Private.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanConditions/BugsnagPerformanceSpanCondition+Private.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import @class BugsnagPerformanceSpan; diff --git a/Sources/BugsnagPerformance/Private/Core/SpanFactory/AppStartup/AppStartupSpanFactory.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/AppStartup/AppStartupSpanFactory.h index 482d0819..0cfbae4f 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanFactory/AppStartup/AppStartupSpanFactory.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/AppStartup/AppStartupSpanFactory.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import "../../Span/SpanOptions.h" diff --git a/Sources/BugsnagPerformance/Private/Core/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.h index c351802f..335058bd 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "AppStartupSpanFactory.h" #import "../../Attributes/SpanAttributesProvider.h" #import "../Plain/PlainSpanFactory.h" diff --git a/Sources/BugsnagPerformance/Private/Core/SpanFactory/Network/NetworkSpanFactory.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Network/NetworkSpanFactory.h index ed4efe8d..ace9586b 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanFactory/Network/NetworkSpanFactory.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Network/NetworkSpanFactory.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import "../../Span/SpanOptions.h" diff --git a/Sources/BugsnagPerformance/Private/Core/SpanFactory/Network/NetworkSpanFactoryImpl.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Network/NetworkSpanFactoryImpl.h index c9889297..4ddd9eca 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanFactory/Network/NetworkSpanFactoryImpl.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Network/NetworkSpanFactoryImpl.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "NetworkSpanFactory.h" #import "../../Attributes/SpanAttributesProvider.h" #import "../Plain/PlainSpanFactory.h" diff --git a/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactory.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactory.h index ee953b87..c9b2c070 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactory.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactory.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import #import "../../Span/SpanOptions.h" diff --git a/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryCallbacks.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryCallbacks.h index adfd47cd..6d2c18d4 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryCallbacks.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryCallbacks.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "../../Span/BugsnagPerformanceSpan+Private.h" typedef void (^OnSpanStartCallback)(BugsnagPerformanceSpan * _Nonnull, diff --git a/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryImpl.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryImpl.h index 3be9ac81..4e06c942 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryImpl.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryImpl.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "PlainSpanFactory.h" #import "PlainSpanFactoryCallbacks.h" #import "../../Attributes/SpanAttributesProvider.h" diff --git a/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactory.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactory.h index 494eca68..ef135575 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactory.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactory.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import #import diff --git a/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryCallbacks.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryCallbacks.h index f31db08c..c515649d 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryCallbacks.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryCallbacks.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import "../../Span/BugsnagPerformanceSpan+Private.h" diff --git a/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.h index 6e8e0180..2443df7f 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "ViewLoadSpanFactory.h" #import "../../Attributes/SpanAttributesProvider.h" #import "../Plain/PlainSpanFactory.h" diff --git a/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandler.h b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandler.h index 2eb52742..875d8f86 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandler.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandler.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import "../Span/SpanOptions.h" #import "../PhasedStartup.h" diff --git a/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.h b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.h index e85bcb23..8b640b9d 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "SpanLifecycleHandler.h" #import "../SpanProcessingPipeline/Batch.h" diff --git a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipeline.h b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipeline.h index f16ef9dc..bfc43506 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipeline.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipeline.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "SpanProcessingPipelineStep.h" namespace bugsnag { diff --git a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.h b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.h index 4eb56ed5..73b82f1e 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "SpanProcessingPipeline.h" #import "Batch.h" #import "../PhasedStartup.h" diff --git a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineStep.h b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineStep.h index 1b5b486a..7d59d324 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineStep.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineStep.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import namespace bugsnag { diff --git a/Sources/BugsnagPerformance/Private/Core/SpanStack/SpanActivityState.h b/Sources/BugsnagPerformance/Private/Core/SpanStack/SpanActivityState.h index 13c5dcbe..e85d57e5 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanStack/SpanActivityState.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanStack/SpanActivityState.h @@ -6,6 +6,8 @@ // Copyright © 2023 Bugsnag. All rights reserved. // +#pragma once + #import "../Span/BugsnagPerformanceSpan+Private.h" #import diff --git a/Sources/BugsnagPerformance/Private/Core/SpanStack/SpanStackingHandler.h b/Sources/BugsnagPerformance/Private/Core/SpanStack/SpanStackingHandler.h index 0330ab41..57621247 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanStack/SpanStackingHandler.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanStack/SpanStackingHandler.h @@ -6,6 +6,8 @@ // Copyright © 2023 Bugsnag. All rights reserved. // +#pragma once + #import "../Span/BugsnagPerformanceSpan+Private.h" #import "SpanActivityState.h" #import diff --git a/Sources/BugsnagPerformance/Private/Core/SpanStore/SpanStore.h b/Sources/BugsnagPerformance/Private/Core/SpanStore/SpanStore.h index 9e525ffe..96843457 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanStore/SpanStore.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanStore/SpanStore.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import namespace bugsnag { diff --git a/Sources/BugsnagPerformance/Private/Core/SpanStore/SpanStoreImpl.h b/Sources/BugsnagPerformance/Private/Core/SpanStore/SpanStoreImpl.h index 0734eb92..495a73e6 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanStore/SpanStoreImpl.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanStore/SpanStoreImpl.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "SpanStore.h" #import "../SpanStack/SpanStackingHandler.h" #import "WeakSpansList.h" diff --git a/Sources/BugsnagPerformance/Private/Core/SpanStore/WeakSpansList.h b/Sources/BugsnagPerformance/Private/Core/SpanStore/WeakSpansList.h index 0fb5416f..e2c2e613 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanStore/WeakSpansList.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanStore/WeakSpansList.h @@ -6,6 +6,8 @@ // Copyright © 2023 Bugsnag. All rights reserved. // +#pragma once + #import "../Span/BugsnagPerformanceSpan+Private.h" #import diff --git a/Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h b/Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h index 5e187360..8b7509ca 100644 --- a/Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h +++ b/Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h @@ -6,6 +6,8 @@ // Copyright © 2024 Bugsnag. All rights reserved. // +#pragma once + // Bugsnag CrossTalk API // // CrossTalk is an Objective-C layer for sharing private APIs between Bugsnag libraries. diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandler.h b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandler.h index 5e2488fb..9973db26 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandler.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandler.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import "../State/AppStartupInstrumentationState.h" diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandlerImpl.h b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandlerImpl.h index f2bc8073..9347e4e4 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandlerImpl.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandlerImpl.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "AppStartupLifecycleHandler.h" #import "../../../Core/SpanFactory/AppStartup/AppStartupSpanFactory.h" #import "../System/AppStartupInstrumentationSystemUtils.h" diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/State/AppStartupInstrumentationStateSnapshot.h b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/State/AppStartupInstrumentationStateSnapshot.h index e1d4b95e..39be2cba 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/State/AppStartupInstrumentationStateSnapshot.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/State/AppStartupInstrumentationStateSnapshot.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/System/AppStartupInstrumentationSystemUtils.h b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/System/AppStartupInstrumentationSystemUtils.h index b9cdd591..fc509cd3 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/System/AppStartupInstrumentationSystemUtils.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/System/AppStartupInstrumentationSystemUtils.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/System/AppStartupInstrumentationSystemUtilsImpl.h b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/System/AppStartupInstrumentationSystemUtilsImpl.h index e7a017df..6c9f3f25 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/System/AppStartupInstrumentationSystemUtilsImpl.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/System/AppStartupInstrumentationSystemUtilsImpl.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "AppStartupInstrumentationSystemUtils.h" namespace bugsnag { diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/BugsnagPerformanceLoadingIndicatorView+Private.h b/Sources/BugsnagPerformance/Private/Instrumentation/BugsnagPerformanceLoadingIndicatorView+Private.h index d16beed4..fd5f7625 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/BugsnagPerformanceLoadingIndicatorView+Private.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/BugsnagPerformanceLoadingIndicatorView+Private.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkEarlyPhaseHandler.h b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkEarlyPhaseHandler.h index ba240e4b..d5971282 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkEarlyPhaseHandler.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkEarlyPhaseHandler.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import "../State/NetworkInstrumentationState.h" diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkEarlyPhaseHandlerImpl.h b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkEarlyPhaseHandlerImpl.h index 730aec21..8d092334 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkEarlyPhaseHandlerImpl.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkEarlyPhaseHandlerImpl.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "NetworkEarlyPhaseHandler.h" #import "../../../Core/Attributes/SpanAttributesProvider.h" diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkLifecycleHandler.h b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkLifecycleHandler.h index a77e6453..7602f53d 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkLifecycleHandler.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkLifecycleHandler.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import "../State/NetworkInstrumentationState.h" diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkLifecycleHandlerImpl.h b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkLifecycleHandlerImpl.h index f14710c8..2b65b948 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkLifecycleHandlerImpl.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/Lifecycle/NetworkLifecycleHandlerImpl.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "NetworkLifecycleHandler.h" #import "NetworkEarlyPhaseHandler.h" #import "../State/NetworkInstrumentationStateRepository.h" diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/State/NetworkInstrumentationState.h b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/State/NetworkInstrumentationState.h index 8e5e178f..c3c41c0f 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/State/NetworkInstrumentationState.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/State/NetworkInstrumentationState.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/State/NetworkInstrumentationStateRepository.h b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/State/NetworkInstrumentationStateRepository.h index 7cbd9e02..cb5bd0cd 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/State/NetworkInstrumentationStateRepository.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/State/NetworkInstrumentationStateRepository.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import "NetworkInstrumentationState.h" diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/State/NetworkInstrumentationStateRepositoryImpl.h b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/State/NetworkInstrumentationStateRepositoryImpl.h index 7d4b3bbb..e8e4b70d 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/State/NetworkInstrumentationStateRepositoryImpl.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/State/NetworkInstrumentationStateRepositoryImpl.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "NetworkInstrumentationStateRepository.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/BSGURLSessionPerformanceDelegate.h b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/BSGURLSessionPerformanceDelegate.h index ea9cf52b..06922864 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/BSGURLSessionPerformanceDelegate.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/BSGURLSessionPerformanceDelegate.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "../Lifecycle/NetworkLifecycleHandler.h" #import "../../../Core/PhasedStartup.h" #import diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkHeaderInjector.h b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkHeaderInjector.h index 8d51fcb6..6ec53a9c 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkHeaderInjector.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkHeaderInjector.h @@ -6,6 +6,8 @@ // Copyright © 2024 Bugsnag. All rights reserved. // +#pragma once + #import #import "../../../Core/PhasedStartup.h" #import "../../../Core/Attributes/SpanAttributesProvider.h" diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkInstrumentationSystemUtils.h b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkInstrumentationSystemUtils.h index 1336ae15..bbb9e6da 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkInstrumentationSystemUtils.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkInstrumentationSystemUtils.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkInstrumentationSystemUtilsImpl.h b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkInstrumentationSystemUtilsImpl.h index c4c41ed9..a0c25ce6 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkInstrumentationSystemUtilsImpl.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkInstrumentationSystemUtilsImpl.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "NetworkInstrumentationSystemUtils.h" namespace bugsnag { diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkSwizzlingHandler.h b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkSwizzlingHandler.h index 2301ca57..40f38990 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkSwizzlingHandler.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkSwizzlingHandler.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import typedef void (^BSGSessionTaskResumeCallback)(NSURLSessionTask *); diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkSwizzlingHandlerImpl.h b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkSwizzlingHandlerImpl.h index 428be88d..6726b748 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkSwizzlingHandlerImpl.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkSwizzlingHandlerImpl.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "NetworkSwizzlingHandler.h" namespace bugsnag { diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/Proxy/BSGPerformanceSharedSessionProxy.h b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/Proxy/BSGPerformanceSharedSessionProxy.h index 5d00dde2..eb6e2690 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/Proxy/BSGPerformanceSharedSessionProxy.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/Proxy/BSGPerformanceSharedSessionProxy.h @@ -6,6 +6,8 @@ // Copyright © 2024 Bugsnag. All rights reserved. // +#pragma once + #import /** diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadEarlyPhaseHandler.h b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadEarlyPhaseHandler.h index 08651564..605732ba 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadEarlyPhaseHandler.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadEarlyPhaseHandler.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import "../State/ViewLoadInstrumentationState.h" diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadEarlyPhaseHandlerImpl.h b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadEarlyPhaseHandlerImpl.h index a71bd5fd..ba77f764 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadEarlyPhaseHandlerImpl.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadEarlyPhaseHandlerImpl.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "ViewLoadEarlyPhaseHandler.h" #import #import diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandler.h b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandler.h index 1338d368..ea4a3f19 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandler.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandler.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import #import diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandlerImpl.h b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandlerImpl.h index 7ba83813..8627a4be 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandlerImpl.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandlerImpl.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "ViewLoadLifecycleHandler.h" #import "ViewLoadEarlyPhaseHandler.h" #import "ViewLoadLoadingIndicatorsHandler.h" diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLoadingIndicatorsHandler.h b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLoadingIndicatorsHandler.h index ad66471b..402c8ea6 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLoadingIndicatorsHandler.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLoadingIndicatorsHandler.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import @class BugsnagPerformanceSpanCondition; diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLoadingIndicatorsHandlerImpl.h b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLoadingIndicatorsHandlerImpl.h index 3481012a..a58ff1e4 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLoadingIndicatorsHandlerImpl.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLoadingIndicatorsHandlerImpl.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "ViewLoadLoadingIndicatorsHandler.h" #import "../State/ViewLoadInstrumentationStateRepository.h" #import diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/State/ViewLoadInstrumentationState.h b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/State/ViewLoadInstrumentationState.h index 2fa4e0f5..a8288a9d 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/State/ViewLoadInstrumentationState.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/State/ViewLoadInstrumentationState.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + @class ViewLoadInstrumentationState; #import diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/State/ViewLoadInstrumentationStateRepository.h b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/State/ViewLoadInstrumentationStateRepository.h index 5a0d4695..fc0b8c79 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/State/ViewLoadInstrumentationStateRepository.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/State/ViewLoadInstrumentationStateRepository.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import "ViewLoadInstrumentationState.h" diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/State/ViewLoadInstrumentationStateRepositoryImpl.h b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/State/ViewLoadInstrumentationStateRepositoryImpl.h index c367add9..86d5aeea 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/State/ViewLoadInstrumentationStateRepositoryImpl.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/State/ViewLoadInstrumentationStateRepositoryImpl.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "ViewLoadInstrumentationStateRepository.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadInstrumentationSystemUtils.h b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadInstrumentationSystemUtils.h index 4774991e..fbf7cc40 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadInstrumentationSystemUtils.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadInstrumentationSystemUtils.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadInstrumentationSystemUtilsImpl.h b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadInstrumentationSystemUtilsImpl.h index fbac47fb..332b65d6 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadInstrumentationSystemUtilsImpl.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadInstrumentationSystemUtilsImpl.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "ViewLoadInstrumentationSystemUtils.h" namespace bugsnag { diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadSwizzlingCallbacks.h b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadSwizzlingCallbacks.h index c20a94d2..761f0b94 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadSwizzlingCallbacks.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadSwizzlingCallbacks.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import typedef void (^ ViewLoadSwizzlingOriginalImplementationCallback)(void); diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadSwizzlingHandler.h b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadSwizzlingHandler.h index bb4b9fd3..04a1dbd1 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadSwizzlingHandler.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadSwizzlingHandler.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "ViewLoadSwizzlingCallbacks.h" namespace bugsnag { diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadSwizzlingHandlerImpl.h b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadSwizzlingHandlerImpl.h index 7f902f96..33fd9954 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadSwizzlingHandlerImpl.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/System/ViewLoadSwizzlingHandlerImpl.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "ViewLoadSwizzlingHandler.h" #import #import diff --git a/Sources/BugsnagPerformance/Private/Metrics/SystemMetrics/BSGPSystemInfo.h b/Sources/BugsnagPerformance/Private/Metrics/SystemMetrics/BSGPSystemInfo.h index e1be9b46..3712fda8 100644 --- a/Sources/BugsnagPerformance/Private/Metrics/SystemMetrics/BSGPSystemInfo.h +++ b/Sources/BugsnagPerformance/Private/Metrics/SystemMetrics/BSGPSystemInfo.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import #import diff --git a/Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformancePluginContext+Private.h b/Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformancePluginContext+Private.h index 9d8bed63..2245abb8 100644 --- a/Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformancePluginContext+Private.h +++ b/Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformancePluginContext+Private.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import #import "SpanControl/BSGCompositeSpanControlProvider.h" diff --git a/Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformancePluginSupport.h b/Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformancePluginSupport.h index 41d397b6..a1d910c4 100644 --- a/Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformancePluginSupport.h +++ b/Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformancePluginSupport.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + // Core Plugin Support #import "BugsnagPerformancePluginContext+Private.h" #import "BugsnagPerformanceSpanControlProvider+Private.h" diff --git a/Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformanceSpanControlProvider+Private.h b/Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformanceSpanControlProvider+Private.h index b6034455..21cdfbd7 100644 --- a/Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformanceSpanControlProvider+Private.h +++ b/Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformanceSpanControlProvider+Private.h @@ -6,4 +6,6 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + typedef void (^ AddSpanControlProviderBlock)(id object, BugsnagPerformancePriority priority); diff --git a/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.h b/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.h index f7067276..5b1ab165 100644 --- a/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.h +++ b/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import #import diff --git a/Sources/BugsnagPerformance/Private/PluginSupport/SpanControl/BSGCompositeSpanControlProvider.h b/Sources/BugsnagPerformance/Private/PluginSupport/SpanControl/BSGCompositeSpanControlProvider.h index 9694a2df..6ba3c4da 100644 --- a/Sources/BugsnagPerformance/Private/PluginSupport/SpanControl/BSGCompositeSpanControlProvider.h +++ b/Sources/BugsnagPerformance/Private/PluginSupport/SpanControl/BSGCompositeSpanControlProvider.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import #import #import "../../Core/BSGPrioritizedStore.h" diff --git a/Sources/BugsnagPerformance/Private/Plugins/AppStart/BugsnagPerformanceAppStartSpanControl+Private.h b/Sources/BugsnagPerformance/Private/Plugins/AppStart/BugsnagPerformanceAppStartSpanControl+Private.h index cf677f55..43c8639d 100644 --- a/Sources/BugsnagPerformance/Private/Plugins/AppStart/BugsnagPerformanceAppStartSpanControl+Private.h +++ b/Sources/BugsnagPerformance/Private/Plugins/AppStart/BugsnagPerformanceAppStartSpanControl+Private.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/Plugins/AppStart/BugsnagPerformanceAppStartTypePlugin.h b/Sources/BugsnagPerformance/Private/Plugins/AppStart/BugsnagPerformanceAppStartTypePlugin.h index efd94043..aef85d89 100644 --- a/Sources/BugsnagPerformance/Private/Plugins/AppStart/BugsnagPerformanceAppStartTypePlugin.h +++ b/Sources/BugsnagPerformance/Private/Plugins/AppStart/BugsnagPerformanceAppStartTypePlugin.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "../../Core/SpanStack/SpanStackingHandler.h" #import #import diff --git a/Sources/BugsnagPerformance/Private/Utils/AppStateTracker.h b/Sources/BugsnagPerformance/Private/Utils/AppStateTracker.h index 2b74ed4e..9f7c8dfb 100644 --- a/Sources/BugsnagPerformance/Private/Utils/AppStateTracker.h +++ b/Sources/BugsnagPerformance/Private/Utils/AppStateTracker.h @@ -6,6 +6,8 @@ // Copyright © 2023 Bugsnag. All rights reserved. // +#pragma once + #import NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/Utils/BugsnagSwiftTools.h b/Sources/BugsnagPerformance/Private/Utils/BugsnagSwiftTools.h index 47822714..8c3380f6 100644 --- a/Sources/BugsnagPerformance/Private/Utils/BugsnagSwiftTools.h +++ b/Sources/BugsnagPerformance/Private/Utils/BugsnagSwiftTools.h @@ -6,6 +6,8 @@ // Copyright © 2024 Bugsnag. All rights reserved. // +#pragma once + #import NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/Utils/Filesystem.h b/Sources/BugsnagPerformance/Private/Utils/Filesystem.h index 6e41065b..e382c9e0 100644 --- a/Sources/BugsnagPerformance/Private/Utils/Filesystem.h +++ b/Sources/BugsnagPerformance/Private/Utils/Filesystem.h @@ -6,6 +6,8 @@ // Copyright © 2023 Bugsnag. All rights reserved. // +#pragma once + #import NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/Utils/Gzip.h b/Sources/BugsnagPerformance/Private/Utils/Gzip.h index 65da588f..a43d9576 100644 --- a/Sources/BugsnagPerformance/Private/Utils/Gzip.h +++ b/Sources/BugsnagPerformance/Private/Utils/Gzip.h @@ -6,6 +6,8 @@ // Copyright © 2023 Bugsnag. All rights reserved. // +#pragma once + #import NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/Utils/Logging.h b/Sources/BugsnagPerformance/Private/Utils/Logging.h index ec1925e1..9a58086f 100644 --- a/Sources/BugsnagPerformance/Private/Utils/Logging.h +++ b/Sources/BugsnagPerformance/Private/Utils/Logging.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #define BSG_LOGLEVEL_NONE 0 #define BSG_LOGLEVEL_ERR 10 #define BSG_LOGLEVEL_WARN 20 diff --git a/Sources/BugsnagPerformance/Private/Utils/Targets.h b/Sources/BugsnagPerformance/Private/Utils/Targets.h index c01f001a..ea940cb1 100644 --- a/Sources/BugsnagPerformance/Private/Utils/Targets.h +++ b/Sources/BugsnagPerformance/Private/Utils/Targets.h @@ -6,6 +6,8 @@ // Copyright © 2023 Bugsnag. All rights reserved. // +#pragma once + #import // Targets based on what technologis they use. From d0752e3bf839d65e33f79786428f1f963c3ee80e Mon Sep 17 00:00:00 2001 From: Robert Bartoszewski Date: Wed, 22 Oct 2025 11:11:05 +0200 Subject: [PATCH 04/14] WIP BugsnagPerformanceImpl refactor --- BugsnagPerformance.xcodeproj/project.pbxproj | 132 +++- .../Private/Core/AppLifecycleListener.h | 20 + .../Private/Core/Attributes/SpanAttributes.h | 18 - .../Private/Core/Attributes/SpanAttributes.mm | 33 - .../Core/Attributes/SpanAttributesProvider.h | 15 +- .../Core/Attributes/SpanAttributesProvider.mm | 22 +- .../Private/Core/CoreModule.h | 140 +++++ .../Private/Core/CoreModule.mm | 236 +++++++ .../BugsnagPerformance/Private/Core/Module.h | 19 + .../Private/Core/ModuleTaskTypes.h | 18 + .../NetworkSpanReporter/NetworkSpanReporter.h | 20 + .../NetworkSpanReporterImpl.h | 45 ++ .../NetworkSpanReporterImpl.mm | 38 ++ .../SpanFactory/Plain/PlainSpanFactoryImpl.h | 15 +- .../SpanFactory/Plain/PlainSpanFactoryImpl.mm | 3 +- .../ViewLoad/ViewLoadSpanFactory.h | 4 + .../SpanLifecycle/SpanLifecycleHandlerImpl.h | 17 +- .../SpanLifecycle/SpanLifecycleHandlerImpl.mm | 9 +- .../Private/Core/Worker/WorkerTask.h | 28 + .../Private/Core/Worker/WorkerTask.mm | 9 + .../BugsnagPerformanceCrossTalkAPI.h | 8 +- .../BugsnagPerformanceCrossTalkAPI.mm | 17 +- .../Private/CrossTalkAPI/CrossTalkAPIModule.h | 45 ++ .../CrossTalkAPI/CrossTalkAPIModule.mm | 46 ++ .../AppStartupInstrumentation.mm | 2 +- .../AppStartupLifecycleHandlerImpl.h | 2 +- .../AppStartupInstrumentationStateSnapshot.h | 2 + .../Private/Instrumentation/Instrumentation.h | 20 +- .../Instrumentation/Instrumentation.mm | 46 +- .../Instrumentation/InstrumentationModule.h | 82 +++ .../Instrumentation/InstrumentationModule.mm | 97 +++ .../Lifecycle/ViewLoadLifecycleHandlerImpl.h | 2 +- .../Private/Main/BugsnagPerformanceImpl.h | 65 +- .../Private/Main/BugsnagPerformanceImpl.mm | 581 +++--------------- .../Private/Main/BugsnagPerformanceLibrary.h | 5 +- .../Private/Main/BugsnagPerformanceLibrary.mm | 23 +- .../Private/Main/MainModule.h | 67 ++ .../Private/Main/MainModule.mm | 284 +++++++++ .../FrameMetrics/FrameMetricsSnapshot.h | 3 + .../Private/Metrics/MetricsModule.h | 53 ++ .../Private/Metrics/MetricsModule.mm | 78 +++ .../BugsnagPerformancePluginSupport.h | 19 - .../PluginManager/BSGPluginManager.h | 8 +- .../PluginManager/BSGPluginManager.m | 32 +- .../PluginSupport/PluginSupportModule.h | 41 ++ .../PluginSupport/PluginSupportModule.mm | 46 ++ .../BugsnagPerformanceAppStartTypePlugin.mm | 2 +- .../Private/Plugins/PluginsModule.h | 43 ++ .../Private/Plugins/PluginsModule.mm | 18 + Sources/BugsnagPerformance/Private/Tracer.h | 95 --- Sources/BugsnagPerformance/Private/Tracer.mm | 116 ---- .../Private/Upload/Otlp/OtlpUploader.h | 25 +- .../Private/Upload/Otlp/OtlpUploader.mm | 3 + .../Private/Upload/UploadModule.h | 54 ++ .../Private/Upload/UploadModule.mm | 57 ++ .../Private/Utils/Persistence.h | 20 +- .../Private/Utils/Persistence.mm | 22 +- .../Private/Utils/UtilsModule.h | 54 ++ .../Private/Utils/UtilsModule.mm | 71 +++ .../SpanAttributesTests.mm | 57 +- 60 files changed, 2187 insertions(+), 965 deletions(-) create mode 100644 Sources/BugsnagPerformance/Private/Core/AppLifecycleListener.h delete mode 100644 Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributes.h delete mode 100644 Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributes.mm create mode 100644 Sources/BugsnagPerformance/Private/Core/CoreModule.h create mode 100644 Sources/BugsnagPerformance/Private/Core/CoreModule.mm create mode 100644 Sources/BugsnagPerformance/Private/Core/Module.h create mode 100644 Sources/BugsnagPerformance/Private/Core/ModuleTaskTypes.h create mode 100644 Sources/BugsnagPerformance/Private/Core/NetworkSpanReporter/NetworkSpanReporter.h create mode 100644 Sources/BugsnagPerformance/Private/Core/NetworkSpanReporter/NetworkSpanReporterImpl.h create mode 100644 Sources/BugsnagPerformance/Private/Core/NetworkSpanReporter/NetworkSpanReporterImpl.mm create mode 100644 Sources/BugsnagPerformance/Private/Core/Worker/WorkerTask.h create mode 100644 Sources/BugsnagPerformance/Private/Core/Worker/WorkerTask.mm create mode 100644 Sources/BugsnagPerformance/Private/CrossTalkAPI/CrossTalkAPIModule.h create mode 100644 Sources/BugsnagPerformance/Private/CrossTalkAPI/CrossTalkAPIModule.mm create mode 100644 Sources/BugsnagPerformance/Private/Instrumentation/InstrumentationModule.h create mode 100644 Sources/BugsnagPerformance/Private/Instrumentation/InstrumentationModule.mm create mode 100644 Sources/BugsnagPerformance/Private/Main/MainModule.h create mode 100644 Sources/BugsnagPerformance/Private/Main/MainModule.mm create mode 100644 Sources/BugsnagPerformance/Private/Metrics/MetricsModule.h create mode 100644 Sources/BugsnagPerformance/Private/Metrics/MetricsModule.mm delete mode 100644 Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformancePluginSupport.h create mode 100644 Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.h create mode 100644 Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.mm create mode 100644 Sources/BugsnagPerformance/Private/Plugins/PluginsModule.h create mode 100644 Sources/BugsnagPerformance/Private/Plugins/PluginsModule.mm delete mode 100644 Sources/BugsnagPerformance/Private/Tracer.h delete mode 100644 Sources/BugsnagPerformance/Private/Tracer.mm create mode 100644 Sources/BugsnagPerformance/Private/Upload/UploadModule.h create mode 100644 Sources/BugsnagPerformance/Private/Upload/UploadModule.mm create mode 100644 Sources/BugsnagPerformance/Private/Utils/UtilsModule.h create mode 100644 Sources/BugsnagPerformance/Private/Utils/UtilsModule.mm diff --git a/BugsnagPerformance.xcodeproj/project.pbxproj b/BugsnagPerformance.xcodeproj/project.pbxproj index d0ced058..33429db5 100644 --- a/BugsnagPerformance.xcodeproj/project.pbxproj +++ b/BugsnagPerformance.xcodeproj/project.pbxproj @@ -17,7 +17,6 @@ 0122C23F29019770002D243C /* OtlpTraceEncoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 0122C22029019770002D243C /* OtlpTraceEncoding.h */; }; 0122C24129019770002D243C /* IdGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0122C22229019770002D243C /* IdGenerator.h */; }; 0122C24229019770002D243C /* SpanKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0122C22329019770002D243C /* SpanKind.h */; }; - 0122C24429019770002D243C /* Tracer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0122C22529019770002D243C /* Tracer.mm */; }; 0122C24829019770002D243C /* NetworkInstrumentation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0122C22A29019770002D243C /* NetworkInstrumentation.mm */; }; 0122C24929019770002D243C /* AppStartupInstrumentation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0122C22B29019770002D243C /* AppStartupInstrumentation.mm */; }; 0122C24A29019770002D243C /* AppStartupInstrumentation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0122C22C29019770002D243C /* AppStartupInstrumentation.h */; }; @@ -26,7 +25,6 @@ 0122C24D29019770002D243C /* ViewLoadInstrumentation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0122C22F29019770002D243C /* ViewLoadInstrumentation.mm */; }; 0122C24E29019770002D243C /* OtlpTraceEncoding.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0122C23029019770002D243C /* OtlpTraceEncoding.mm */; }; 0122C25029019770002D243C /* BugsnagPerformanceSpan+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 0122C23229019770002D243C /* BugsnagPerformanceSpan+Private.h */; }; - 0122C25129019770002D243C /* Tracer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0122C23329019770002D243C /* Tracer.h */; }; 0122C25829019904002D243C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0122C25729019904002D243C /* UIKit.framework */; }; 0122C26929019CE1002D243C /* BugsnagPerformance.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72E4BB63359EA30E80116E2A /* BugsnagPerformance.framework */; }; 0122C27129019CEF002D243C /* OtlpTraceEncodingTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0122C26029019C05002D243C /* OtlpTraceEncodingTests.mm */; }; @@ -34,8 +32,6 @@ 015836C229125E7A002F54C8 /* ResourceAttributes.mm in Sources */ = {isa = PBXBuildFile; fileRef = 015836C029125E7A002F54C8 /* ResourceAttributes.mm */; }; 015836C4291264E0002F54C8 /* Version.h in Headers */ = {isa = PBXBuildFile; fileRef = 015836C3291264E0002F54C8 /* Version.h */; }; 01A414C52912B93F003152A4 /* ResourceAttributesTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 01A414C42912B93F003152A4 /* ResourceAttributesTests.mm */; }; - 01A414CD2913C0F0003152A4 /* SpanAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 01A414CB2913C0F0003152A4 /* SpanAttributes.h */; }; - 01A414CE2913C0F0003152A4 /* SpanAttributes.mm in Sources */ = {isa = PBXBuildFile; fileRef = 01A414CC2913C0F0003152A4 /* SpanAttributes.mm */; }; 01A414D12913C238003152A4 /* Reachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 01A414CF2913C238003152A4 /* Reachability.h */; }; 01A414D22913C238003152A4 /* Reachability.mm in Sources */ = {isa = PBXBuildFile; fileRef = 01A414D02913C238003152A4 /* Reachability.mm */; }; 01A414D42913CAE7003152A4 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 01A414D32913CAE7003152A4 /* SystemConfiguration.framework */; }; @@ -194,7 +190,32 @@ 967949CA2E9DC9CE005FD87F /* SpanProcessingPipelineStep.h in Sources */ = {isa = PBXBuildFile; fileRef = 967949C92E9DC9C5005FD87F /* SpanProcessingPipelineStep.h */; }; 967949CD2E9DCAEE005FD87F /* SpanProcessingPipelineImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 967949CC2E9DCAE0005FD87F /* SpanProcessingPipelineImpl.h */; }; 967949CF2E9DCB06005FD87F /* SpanProcessingPipelineImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 967949CE2E9DCB02005FD87F /* SpanProcessingPipelineImpl.mm */; }; - 967949EC2EA06044005FD87F /* BugsnagPerformancePluginSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 967949EB2EA06038005FD87F /* BugsnagPerformancePluginSupport.h */; }; + 967949F62EA12E45005FD87F /* Module.h in Headers */ = {isa = PBXBuildFile; fileRef = 967949F52EA12E41005FD87F /* Module.h */; }; + 967949F82EA1507C005FD87F /* InstrumentationModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 967949F72EA15075005FD87F /* InstrumentationModule.h */; }; + 967949FA2EA15084005FD87F /* InstrumentationModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 967949F92EA15083005FD87F /* InstrumentationModule.mm */; }; + 967949FC2EA1645C005FD87F /* MainModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 967949FB2EA16458005FD87F /* MainModule.h */; }; + 967949FE2EA16465005FD87F /* MainModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 967949FD2EA16463005FD87F /* MainModule.mm */; }; + 96794A002EA165CB005FD87F /* CoreModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 967949FF2EA165C6005FD87F /* CoreModule.h */; }; + 96794A032EA165DA005FD87F /* CoreModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96794A022EA165D9005FD87F /* CoreModule.mm */; }; + 96794A052EA16655005FD87F /* UtilsModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A042EA1664E005FD87F /* UtilsModule.h */; }; + 96794A072EA16659005FD87F /* UtilsModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96794A062EA16658005FD87F /* UtilsModule.mm */; }; + 96794A0B2EA19AC5005FD87F /* MetricsModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A0A2EA19ABE005FD87F /* MetricsModule.h */; }; + 96794A0D2EA19ACB005FD87F /* MetricsModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96794A0C2EA19AC9005FD87F /* MetricsModule.mm */; }; + 96794A0F2EA19CE8005FD87F /* CrossTalkAPIModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A0E2EA19CD8005FD87F /* CrossTalkAPIModule.h */; }; + 96794A112EA19CEC005FD87F /* CrossTalkAPIModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96794A102EA19CEB005FD87F /* CrossTalkAPIModule.mm */; }; + 96794A132EA1A58A005FD87F /* PluginsModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A122EA1A581005FD87F /* PluginsModule.h */; }; + 96794A152EA1A593005FD87F /* PluginsModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96794A142EA1A590005FD87F /* PluginsModule.mm */; }; + 96794A172EA1A849005FD87F /* PluginSupportModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A162EA1A842005FD87F /* PluginSupportModule.h */; }; + 96794A192EA1A850005FD87F /* PluginSupportModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96794A182EA1A84E005FD87F /* PluginSupportModule.mm */; }; + 96794A1B2EA1B06A005FD87F /* UploadModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A1A2EA1B063005FD87F /* UploadModule.h */; }; + 96794A1D2EA1B074005FD87F /* UploadModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96794A1C2EA1B073005FD87F /* UploadModule.mm */; }; + 96794A1F2EA77AA6005FD87F /* WorkerTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A1E2EA77AA1005FD87F /* WorkerTask.h */; }; + 96794A212EA77AB8005FD87F /* WorkerTask.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96794A202EA77AB4005FD87F /* WorkerTask.mm */; }; + 96794A2A2EA7B103005FD87F /* AppLifecycleListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A292EA7B0F3005FD87F /* AppLifecycleListener.h */; }; + 96794A2C2EA81B84005FD87F /* ModuleTaskTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A2B2EA81B80005FD87F /* ModuleTaskTypes.h */; }; + 96794A312EA8450F005FD87F /* NetworkSpanReporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A302EA84508005FD87F /* NetworkSpanReporter.h */; }; + 96794A332EA8451A005FD87F /* NetworkSpanReporterImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A322EA84515005FD87F /* NetworkSpanReporterImpl.h */; }; + 96794A352EA84524005FD87F /* NetworkSpanReporterImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96794A342EA84520005FD87F /* NetworkSpanReporterImpl.mm */; }; 967F6F1829C3783B0054EED8 /* BugsnagPerformanceConfiguration+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 967F6F1729C3782D0054EED8 /* BugsnagPerformanceConfiguration+Private.h */; }; 968AA5FB2CCA5A9200BA69CF /* BSGPerformanceSharedSessionProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 968AA5FA2CCA5A9200BA69CF /* BSGPerformanceSharedSessionProxy.h */; }; 968AA5FD2CCA5AB000BA69CF /* BSGPerformanceSharedSessionProxy.mm in Sources */ = {isa = PBXBuildFile; fileRef = 968AA5FC2CCA5AB000BA69CF /* BSGPerformanceSharedSessionProxy.mm */; }; @@ -382,7 +403,6 @@ 0122C22029019770002D243C /* OtlpTraceEncoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OtlpTraceEncoding.h; sourceTree = ""; }; 0122C22229019770002D243C /* IdGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IdGenerator.h; sourceTree = ""; }; 0122C22329019770002D243C /* SpanKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpanKind.h; sourceTree = ""; }; - 0122C22529019770002D243C /* Tracer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Tracer.mm; sourceTree = ""; }; 0122C22A29019770002D243C /* NetworkInstrumentation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkInstrumentation.mm; sourceTree = ""; }; 0122C22B29019770002D243C /* AppStartupInstrumentation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AppStartupInstrumentation.mm; sourceTree = ""; }; 0122C22C29019770002D243C /* AppStartupInstrumentation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppStartupInstrumentation.h; sourceTree = ""; }; @@ -391,7 +411,6 @@ 0122C22F29019770002D243C /* ViewLoadInstrumentation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewLoadInstrumentation.mm; sourceTree = ""; }; 0122C23029019770002D243C /* OtlpTraceEncoding.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OtlpTraceEncoding.mm; sourceTree = ""; }; 0122C23229019770002D243C /* BugsnagPerformanceSpan+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "BugsnagPerformanceSpan+Private.h"; sourceTree = ""; }; - 0122C23329019770002D243C /* Tracer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Tracer.h; sourceTree = ""; }; 0122C25729019904002D243C /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/iOSSupport/System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 0122C26029019C05002D243C /* OtlpTraceEncodingTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = OtlpTraceEncodingTests.mm; sourceTree = ""; }; 0122C26529019CE1002D243C /* BugsnagPerformance-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "BugsnagPerformance-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -399,8 +418,6 @@ 015836C029125E7A002F54C8 /* ResourceAttributes.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ResourceAttributes.mm; sourceTree = ""; }; 015836C3291264E0002F54C8 /* Version.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Version.h; sourceTree = ""; }; 01A414C42912B93F003152A4 /* ResourceAttributesTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ResourceAttributesTests.mm; sourceTree = ""; }; - 01A414CB2913C0F0003152A4 /* SpanAttributes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SpanAttributes.h; sourceTree = ""; }; - 01A414CC2913C0F0003152A4 /* SpanAttributes.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SpanAttributes.mm; sourceTree = ""; }; 01A414CF2913C238003152A4 /* Reachability.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Reachability.h; sourceTree = ""; }; 01A414D02913C238003152A4 /* Reachability.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Reachability.mm; sourceTree = ""; }; 01A414D32913CAE7003152A4 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; @@ -559,7 +576,32 @@ 967949C92E9DC9C5005FD87F /* SpanProcessingPipelineStep.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SpanProcessingPipelineStep.h; sourceTree = ""; }; 967949CC2E9DCAE0005FD87F /* SpanProcessingPipelineImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SpanProcessingPipelineImpl.h; sourceTree = ""; }; 967949CE2E9DCB02005FD87F /* SpanProcessingPipelineImpl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SpanProcessingPipelineImpl.mm; sourceTree = ""; }; - 967949EB2EA06038005FD87F /* BugsnagPerformancePluginSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BugsnagPerformancePluginSupport.h; sourceTree = ""; }; + 967949F52EA12E41005FD87F /* Module.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Module.h; sourceTree = ""; }; + 967949F72EA15075005FD87F /* InstrumentationModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InstrumentationModule.h; sourceTree = ""; }; + 967949F92EA15083005FD87F /* InstrumentationModule.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = InstrumentationModule.mm; sourceTree = ""; }; + 967949FB2EA16458005FD87F /* MainModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MainModule.h; sourceTree = ""; }; + 967949FD2EA16463005FD87F /* MainModule.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MainModule.mm; sourceTree = ""; }; + 967949FF2EA165C6005FD87F /* CoreModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CoreModule.h; sourceTree = ""; }; + 96794A022EA165D9005FD87F /* CoreModule.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CoreModule.mm; sourceTree = ""; }; + 96794A042EA1664E005FD87F /* UtilsModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UtilsModule.h; sourceTree = ""; }; + 96794A062EA16658005FD87F /* UtilsModule.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = UtilsModule.mm; sourceTree = ""; }; + 96794A0A2EA19ABE005FD87F /* MetricsModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MetricsModule.h; sourceTree = ""; }; + 96794A0C2EA19AC9005FD87F /* MetricsModule.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MetricsModule.mm; sourceTree = ""; }; + 96794A0E2EA19CD8005FD87F /* CrossTalkAPIModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CrossTalkAPIModule.h; sourceTree = ""; }; + 96794A102EA19CEB005FD87F /* CrossTalkAPIModule.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CrossTalkAPIModule.mm; sourceTree = ""; }; + 96794A122EA1A581005FD87F /* PluginsModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PluginsModule.h; sourceTree = ""; }; + 96794A142EA1A590005FD87F /* PluginsModule.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PluginsModule.mm; sourceTree = ""; }; + 96794A162EA1A842005FD87F /* PluginSupportModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PluginSupportModule.h; sourceTree = ""; }; + 96794A182EA1A84E005FD87F /* PluginSupportModule.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PluginSupportModule.mm; sourceTree = ""; }; + 96794A1A2EA1B063005FD87F /* UploadModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UploadModule.h; sourceTree = ""; }; + 96794A1C2EA1B073005FD87F /* UploadModule.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = UploadModule.mm; sourceTree = ""; }; + 96794A1E2EA77AA1005FD87F /* WorkerTask.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WorkerTask.h; sourceTree = ""; }; + 96794A202EA77AB4005FD87F /* WorkerTask.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WorkerTask.mm; sourceTree = ""; }; + 96794A292EA7B0F3005FD87F /* AppLifecycleListener.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppLifecycleListener.h; sourceTree = ""; }; + 96794A2B2EA81B80005FD87F /* ModuleTaskTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ModuleTaskTypes.h; sourceTree = ""; }; + 96794A302EA84508005FD87F /* NetworkSpanReporter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NetworkSpanReporter.h; sourceTree = ""; }; + 96794A322EA84515005FD87F /* NetworkSpanReporterImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NetworkSpanReporterImpl.h; sourceTree = ""; }; + 96794A342EA84520005FD87F /* NetworkSpanReporterImpl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkSpanReporterImpl.mm; sourceTree = ""; }; 967F6F1729C3782D0054EED8 /* BugsnagPerformanceConfiguration+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BugsnagPerformanceConfiguration+Private.h"; sourceTree = ""; }; 968AA5FA2CCA5A9200BA69CF /* BSGPerformanceSharedSessionProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BSGPerformanceSharedSessionProxy.h; sourceTree = ""; }; 968AA5FC2CCA5AB000BA69CF /* BSGPerformanceSharedSessionProxy.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = BSGPerformanceSharedSessionProxy.mm; sourceTree = ""; }; @@ -807,8 +849,6 @@ 967949D12EA0560D005FD87F /* Metrics */, 967949DC2EA05A0C005FD87F /* Plugins */, 967949D82EA05897005FD87F /* PluginSupport */, - 0122C23329019770002D243C /* Tracer.h */, - 0122C22529019770002D243C /* Tracer.mm */, 967949D62EA0578E005FD87F /* Upload */, 967949D52EA056D6005FD87F /* Utils */, 015836C3291264E0002F54C8 /* Version.h */, @@ -823,6 +863,8 @@ 962CE7D42E60967500380522 /* BugsnagPerformanceLoadingIndicatorView+Private.h */, CBEBE59829F671A800BF0B4F /* Instrumentation.h */, CBEBE59929F671A800BF0B4F /* Instrumentation.mm */, + 967949F72EA15075005FD87F /* InstrumentationModule.h */, + 967949F92EA15083005FD87F /* InstrumentationModule.mm */, CB34771929068C350033759C /* NetworkInstrumentation */, 963829052E547C2900404F3A /* ViewLoadInstrumentation */, ); @@ -1156,6 +1198,8 @@ isa = PBXGroup; children = ( 966634D82C8A3939004A934D /* FrameMetrics */, + 96794A0A2EA19ABE005FD87F /* MetricsModule.h */, + 96794A0C2EA19AC9005FD87F /* MetricsModule.mm */, 967949D42EA0567E005FD87F /* SystemMetrics */, ); path = Metrics; @@ -1164,6 +1208,7 @@ 967949D22EA05615005FD87F /* Core */ = { isa = PBXGroup; children = ( + 96794A292EA7B0F3005FD87F /* AppLifecycleListener.h */, 967949D72EA05844005FD87F /* Attributes */, 963726CD2DEAB33D00C739E6 /* BSGPrioritizedStore.h */, 963726CF2DEAB36600C739E6 /* BSGPrioritizedStore.mm */, @@ -1172,6 +1217,11 @@ CBE0873029FA984C007455F2 /* BugsnagPerformanceViewType.mm */, CBE0873129FA984C007455F2 /* BugsnagPerformanceViewType+Private.h */, 967949DF2EA05B37005FD87F /* Configuration */, + 967949FF2EA165C6005FD87F /* CoreModule.h */, + 96794A022EA165D9005FD87F /* CoreModule.mm */, + 967949F52EA12E41005FD87F /* Module.h */, + 96794A2B2EA81B80005FD87F /* ModuleTaskTypes.h */, + 96794A2F2EA844E6005FD87F /* NetworkSpanReporter */, CB78819F29E698BF00A58906 /* PhasedStartup.h */, 967949E32EA05C85005FD87F /* Sampler */, 967949E12EA05BE6005FD87F /* Span */, @@ -1193,6 +1243,8 @@ CBE8EA15294B528100702950 /* BugsnagPerformanceImpl.mm */, CB78819B29E587CE00A58906 /* BugsnagPerformanceLibrary.h */, CB78819A29E587CE00A58906 /* BugsnagPerformanceLibrary.mm */, + 967949FB2EA16458005FD87F /* MainModule.h */, + 967949FD2EA16463005FD87F /* MainModule.mm */, ); path = Main; sourceTree = ""; @@ -1236,6 +1288,8 @@ CBEBE59029F2783C00BF0B4F /* Swizzle.mm */, CBC90C4429C84DEB00280884 /* Targets.h */, 01EAF97F291AAF19007AC627 /* Utils.h */, + 96794A042EA1664E005FD87F /* UtilsModule.h */, + 96794A062EA16658005FD87F /* UtilsModule.mm */, ); path = Utils; sourceTree = ""; @@ -1246,6 +1300,8 @@ 967949DA2EA0592E005FD87F /* Otlp */, CBEC51DA2976F1F9009C0CE3 /* RetryQueue.h */, CBEC51DB2976F1F9009C0CE3 /* RetryQueue.mm */, + 96794A1A2EA1B063005FD87F /* UploadModule.h */, + 96794A1C2EA1B073005FD87F /* UploadModule.mm */, ); path = Upload; sourceTree = ""; @@ -1255,8 +1311,6 @@ children = ( 015836BF29125E7A002F54C8 /* ResourceAttributes.h */, 015836C029125E7A002F54C8 /* ResourceAttributes.mm */, - 01A414CB2913C0F0003152A4 /* SpanAttributes.h */, - 01A414CC2913C0F0003152A4 /* SpanAttributes.mm */, 96D4160D29F276FE00AEE435 /* SpanAttributesProvider.h */, 96D4160B29F276E400AEE435 /* SpanAttributesProvider.mm */, ); @@ -1267,9 +1321,10 @@ isa = PBXGroup; children = ( 963726E12DF101DF00C739E6 /* BugsnagPerformancePluginContext+Private.h */, - 967949EB2EA06038005FD87F /* BugsnagPerformancePluginSupport.h */, 963726E32DF19D7B00C739E6 /* BugsnagPerformanceSpanControlProvider+Private.h */, 967949D92EA05901005FD87F /* PluginManager */, + 96794A162EA1A842005FD87F /* PluginSupportModule.h */, + 96794A182EA1A84E005FD87F /* PluginSupportModule.mm */, 963726C42DEAB14D00C739E6 /* SpanControl */, ); path = PluginSupport; @@ -1312,6 +1367,8 @@ isa = PBXGroup; children = ( 967949E22EA05C3B005FD87F /* AppStart */, + 96794A122EA1A581005FD87F /* PluginsModule.h */, + 96794A142EA1A590005FD87F /* PluginsModule.mm */, ); path = Plugins; sourceTree = ""; @@ -1321,6 +1378,8 @@ children = ( 09FFD43E2BEE3DE2009B0E04 /* BugsnagPerformanceCrossTalkAPI.h */, 09FFD43F2BEE3DE2009B0E04 /* BugsnagPerformanceCrossTalkAPI.mm */, + 96794A0E2EA19CD8005FD87F /* CrossTalkAPIModule.h */, + 96794A102EA19CEB005FD87F /* CrossTalkAPIModule.mm */, ); path = CrossTalkAPI; sourceTree = ""; @@ -1351,6 +1410,8 @@ children = ( CBE8EA18294B5AB800702950 /* Worker.h */, CBE8EA19294B5AB800702950 /* Worker.mm */, + 96794A1E2EA77AA1005FD87F /* WorkerTask.h */, + 96794A202EA77AB4005FD87F /* WorkerTask.mm */, ); path = Worker; sourceTree = ""; @@ -1386,6 +1447,16 @@ path = Sampler; sourceTree = ""; }; + 96794A2F2EA844E6005FD87F /* NetworkSpanReporter */ = { + isa = PBXGroup; + children = ( + 96794A302EA84508005FD87F /* NetworkSpanReporter.h */, + 96794A322EA84515005FD87F /* NetworkSpanReporterImpl.h */, + 96794A342EA84520005FD87F /* NetworkSpanReporterImpl.mm */, + ); + path = NetworkSpanReporter; + sourceTree = ""; + }; 969EE0EE2E7872A600600F63 /* SpanFactory */ = { isa = PBXGroup; children = ( @@ -1507,8 +1578,10 @@ buildActionMask = 2147483647; files = ( 967949B62E97CC9E005FD87F /* SpanLifecycleHandler.h in Headers */, + 96794A002EA165CB005FD87F /* CoreModule.h in Headers */, 9638291D2E54B4A200404F3A /* AppStartupLifecycleHandlerImpl.h in Headers */, CB04969729150D860097E526 /* OtlpPackage.h in Headers */, + 967949FC2EA1645C005FD87F /* MainModule.h in Headers */, 960EECF32B24CA24009FAA11 /* BugsnagPerformanceTrackedViewContainer.h in Headers */, 966634D52C8A3647004A934D /* FrameMetricsSnapshot.h in Headers */, CB34772029068C350033759C /* BSGURLSessionPerformanceProxy.h in Headers */, @@ -1522,6 +1595,8 @@ 962CE7CE2E60766000380522 /* ViewLoadInstrumentationStateRepository.h in Headers */, 967949BD2E99373E005FD87F /* SpanStore.h in Headers */, 963726C12DEA4E5700C739E6 /* BugsnagPerformancePriority.h in Headers */, + 96794A332EA8451A005FD87F /* NetworkSpanReporterImpl.h in Headers */, + 96794A312EA8450F005FD87F /* NetworkSpanReporter.h in Headers */, 962CE7E82E6123E700380522 /* ViewLoadLoadingIndicatorsHandlerImpl.h in Headers */, 962CE7E92E6123E700380522 /* ViewLoadLoadingIndicatorsHandler.h in Headers */, CB7FD930299D2EF200499E13 /* BugsnagPerformanceSpanOptions.h in Headers */, @@ -1539,12 +1614,14 @@ 0122C23929019770002D243C /* BugsnagPerformanceViewType.h in Headers */, 09FFD4402BEE3DE2009B0E04 /* BugsnagPerformanceCrossTalkAPI.h in Headers */, 0122C23A29019770002D243C /* BugsnagPerformanceConfiguration.h in Headers */, + 96794A132EA1A58A005FD87F /* PluginsModule.h in Headers */, CBA22C962A0137230066A2C1 /* EarlyConfiguration.h in Headers */, 963726BB2DE8D97000C739E6 /* BugsnagPerformanceSpanControlProvider.h in Headers */, 963726BC2DE8D97000C739E6 /* BugsnagPerformanceSpanControl.h in Headers */, 963726BD2DE8D97000C739E6 /* BugsnagPerformanceSpanQuery.h in Headers */, CB68FAB92A3C27B9005B2CDB /* PersistentDeviceID.h in Headers */, CBF7C5E1297A8E9100D47719 /* Gzip.h in Headers */, + 967949F82EA1507C005FD87F /* InstrumentationModule.h in Headers */, 96D55C832A1EBA35006D1F29 /* SpanActivityState.h in Headers */, CBE0873329FA984C007455F2 /* BugsnagPerformanceViewType+Private.h in Headers */, 1C68DB9D2E535C67002621D1 /* BugsnagPerformanceAppStartSpanQuery.h in Headers */, @@ -1567,18 +1644,22 @@ 0921F02B2A67CBD600C764EB /* BugsnagPerformanceNetworkRequestInfo.h in Headers */, 962CE7D52E60967A00380522 /* BugsnagPerformanceLoadingIndicatorView+Private.h in Headers */, 963726CA2DEAB24900C739E6 /* BugsnagPerformancePriority+Private.h in Headers */, - 967949EC2EA06044005FD87F /* BugsnagPerformancePluginSupport.h in Headers */, + 96794A052EA16655005FD87F /* UtilsModule.h in Headers */, 962CE7DF2E60988100380522 /* ViewLoadEarlyPhaseHandlerImpl.h in Headers */, 964B785F2D504FD800FF077D /* BugsnagPerformanceSpanCondition+Private.h in Headers */, 963726C62DEAB14D00C739E6 /* BSGCompositeSpanControlProvider.h in Headers */, 0122C24A29019770002D243C /* AppStartupInstrumentation.h in Headers */, + 96794A2C2EA81B84005FD87F /* ModuleTaskTypes.h in Headers */, CB04969B2915194E0097E526 /* OtlpUploader.h in Headers */, + 96794A1B2EA1B06A005FD87F /* UploadModule.h in Headers */, 962CE82C2E67376300380522 /* NetworkLifecycleHandler.h in Headers */, + 96794A0F2EA19CE8005FD87F /* CrossTalkAPIModule.h in Headers */, 962CE81F2E66D23600380522 /* NetworkInstrumentationSystemUtils.h in Headers */, 963829082E547D1A00404F3A /* ViewLoadInstrumentationState.h in Headers */, 966634D12C8909BB004A934D /* FrameMetricsCollector.h in Headers */, 0122C25029019770002D243C /* BugsnagPerformanceSpan+Private.h in Headers */, 09D59E1A2BDFE0D900199E1B /* NetworkHeaderInjector.h in Headers */, + 96794A2A2EA7B103005FD87F /* AppLifecycleListener.h in Headers */, 963829432E57537100404F3A /* ViewLoadLifecycleHandlerImpl.h in Headers */, 0122C23F29019770002D243C /* OtlpTraceEncoding.h in Headers */, 0122C24229019770002D243C /* SpanKind.h in Headers */, @@ -1589,9 +1670,7 @@ CB572EAA29BB783200FD7A2A /* AppStateTracker.h in Headers */, CBEC51DC2976F1F9009C0CE3 /* RetryQueue.h in Headers */, 963726CE2DEAB34B00C739E6 /* BSGPrioritizedStore.h in Headers */, - 01A414CD2913C0F0003152A4 /* SpanAttributes.h in Headers */, 963829162E54972600404F3A /* AppStartupSpanFactoryImpl.h in Headers */, - 0122C25129019770002D243C /* Tracer.h in Headers */, 963726E62DF1DFC300C739E6 /* BSGPluginManager.h in Headers */, CBB48A3C295EE1E10044E9AC /* ObjCUtils.h in Headers */, 96D55C812A1EB5F4006D1F29 /* SpanStackingHandler.h in Headers */, @@ -1599,6 +1678,7 @@ 962CE7DD2E60987600380522 /* ViewLoadEarlyPhaseHandler.h in Headers */, 962CE8042E6519D900380522 /* NetworkInstrumentationState.h in Headers */, CBE8EA1A294B5AB800702950 /* Worker.h in Headers */, + 96794A1F2EA77AA6005FD87F /* WorkerTask.h in Headers */, CBE8EA16294B528100702950 /* BugsnagPerformanceImpl.h in Headers */, 963726E22DF101E700C739E6 /* BugsnagPerformancePluginContext+Private.h in Headers */, 967F6F1829C3783B0054EED8 /* BugsnagPerformanceConfiguration+Private.h in Headers */, @@ -1609,12 +1689,14 @@ 963829142E54960F00404F3A /* AppStartupSpanFactory.h in Headers */, 962CE81A2E65FD4E00380522 /* NetworkSwizzlingHandlerImpl.h in Headers */, CBEBE59A29F671A800BF0B4F /* Instrumentation.h in Headers */, + 967949F62EA12E45005FD87F /* Module.h in Headers */, CBE8EA1E294B5E1500702950 /* Batch.h in Headers */, 962CE80A2E651A0C00380522 /* NetworkInstrumentationStateRepositoryImpl.h in Headers */, 1C68DB952E535290002621D1 /* BugsnagPerformanceAppStartSpanControl+Private.h in Headers */, 962CE8182E65FD4300380522 /* NetworkSwizzlingHandler.h in Headers */, CBEBE59329F2783C00BF0B4F /* Swizzle.h in Headers */, 962CE8082E651A0100380522 /* NetworkInstrumentationStateRepository.h in Headers */, + 96794A172EA1A849005FD87F /* PluginSupportModule.h in Headers */, 969EE0FE2E794A0700600F63 /* ViewLoadSpanFactoryCallbacks.h in Headers */, CBEC51BC296D9EEE009C0CE3 /* PersistentState.h in Headers */, 967949CD2E9DCAEE005FD87F /* SpanProcessingPipelineImpl.h in Headers */, @@ -1633,6 +1715,7 @@ CBEC51B8296D8386009C0CE3 /* Persistence.h in Headers */, 963829212E5542A700404F3A /* AppStartupInstrumentationStateSnapshot.h in Headers */, 9638291B2E54B48E00404F3A /* AppStartupLifecycleHandler.h in Headers */, + 96794A0B2EA19AC5005FD87F /* MetricsModule.h in Headers */, 963829112E548DBE00404F3A /* AppStartupInstrumentationSystemUtils.h in Headers */, 963829322E5614C000404F3A /* ViewLoadInstrumentationSystemUtilsImpl.h in Headers */, 962CE82E2E673A9400380522 /* NetworkLifecycleHandlerImpl.h in Headers */, @@ -1971,6 +2054,8 @@ buildActionMask = 2147483647; files = ( 96F1292D2DCD141700A6FB2B /* BugsnagPerformanceRemoteSpanContext.mm in Sources */, + 967949FA2EA15084005FD87F /* InstrumentationModule.mm in Sources */, + 96794A1D2EA1B074005FD87F /* UploadModule.mm in Sources */, 962CE8372E67972A00380522 /* NetworkSpanFactoryImpl.mm in Sources */, 1C68DB992E535A88002621D1 /* BugsnagPerformanceAppStartSpanControl.mm in Sources */, CB0AD7682965734F002A3FB6 /* BugsnagPerformanceErrors.m in Sources */, @@ -1979,8 +2064,8 @@ 0122C24929019770002D243C /* AppStartupInstrumentation.mm in Sources */, 9638290A2E547D2300404F3A /* ViewLoadInstrumentationState.m in Sources */, 969EE1002E794A1100600F63 /* ViewLoadSpanFactoryCallbacks.mm in Sources */, + 96794A352EA84524005FD87F /* NetworkSpanReporterImpl.mm in Sources */, 963829452E57537900404F3A /* ViewLoadLifecycleHandlerImpl.mm in Sources */, - 0122C24429019770002D243C /* Tracer.mm in Sources */, 962CE8112E65224300380522 /* BSGURLSessionPerformanceDelegate.mm in Sources */, 967949B82E97CCA9005FD87F /* SpanLifecycleHandlerImpl.mm in Sources */, CB04969829150D860097E526 /* OtlpPackage.mm in Sources */, @@ -2000,6 +2085,7 @@ CB572EAB29BB783200FD7A2A /* AppStateTracker.m in Sources */, CBE8EA17294B528100702950 /* BugsnagPerformanceImpl.mm in Sources */, 966634DC2C8A39C1004A934D /* FrozenFrameData.mm in Sources */, + 96794A032EA165DA005FD87F /* CoreModule.mm in Sources */, 9638293A2E56240900404F3A /* ViewLoadSwizzlingHandlerImpl.mm in Sources */, 0122C23E29019770002D243C /* BugsnagPerformanceSpan.mm in Sources */, 0987F27A2C32D4AD00777FD8 /* BugsnagPerformanceSpanContext.mm in Sources */, @@ -2009,9 +2095,9 @@ 967949C12E993750005FD87F /* SpanStoreImpl.mm in Sources */, 964B78562D4B924C00FF077D /* BugsnagPerformanceSpanCondition.mm in Sources */, CBEC51DD2976F1F9009C0CE3 /* RetryQueue.mm in Sources */, - 01A414CE2913C0F0003152A4 /* SpanAttributes.mm in Sources */, CBE8EA1B294B5AB800702950 /* Worker.mm in Sources */, CB78819C29E587CE00A58906 /* BugsnagPerformanceLibrary.mm in Sources */, + 96794A192EA1A850005FD87F /* PluginSupportModule.mm in Sources */, 963726E02DF0B4AD00C739E6 /* BugsnagPerformancePluginContext.m in Sources */, 098FC8552D37A08D001B627D /* SystemInfoSampler.mm in Sources */, 1C68DBA12E535D06002621D1 /* BugsnagPerformanceAppStartSpanQuery.mm in Sources */, @@ -2021,6 +2107,8 @@ 962CE7E72E6123E700380522 /* ViewLoadLoadingIndicatorsHandlerImpl.mm in Sources */, CBEBE59229F2783C00BF0B4F /* Swizzle.mm in Sources */, 963726E82DF1DFD100C739E6 /* BSGPluginManager.m in Sources */, + 96794A072EA16659005FD87F /* UtilsModule.mm in Sources */, + 96794A112EA19CEC005FD87F /* CrossTalkAPIModule.mm in Sources */, 962CE7E12E60988800380522 /* ViewLoadEarlyPhaseHandlerImpl.mm in Sources */, CBA22C972A0137230066A2C1 /* EarlyConfiguration.mm in Sources */, 963726C52DEAB14D00C739E6 /* BSGCompositeSpanControlProvider.m in Sources */, @@ -2033,12 +2121,15 @@ CBEBE59B29F671A800BF0B4F /* Instrumentation.mm in Sources */, 1C68DBA52E535E21002621D1 /* BugsnagPerformanceAppStartTypePlugin.mm in Sources */, 0986B7C02B287C9D00BD2CA3 /* WeakSpansList.mm in Sources */, + 96794A152EA1A593005FD87F /* PluginsModule.mm in Sources */, + 96794A0D2EA19ACB005FD87F /* MetricsModule.mm in Sources */, 962CE8232E66D25100380522 /* NetworkInstrumentationSystemUtilsImpl.mm in Sources */, 96D4160C29F276E400AEE435 /* SpanAttributesProvider.mm in Sources */, 9638290F2E54881000404F3A /* AppStartupInstrumentationSystemUtilsImpl.mm in Sources */, CB68FABA2A3C27B9005B2CDB /* PersistentDeviceID.mm in Sources */, CBF7C5E2297A8E9100D47719 /* Gzip.m in Sources */, 967949CF2E9DCB06005FD87F /* SpanProcessingPipelineImpl.mm in Sources */, + 96794A212EA77AB8005FD87F /* WorkerTask.mm in Sources */, 0122C24829019770002D243C /* NetworkInstrumentation.mm in Sources */, 962CE8062E6519E200380522 /* NetworkInstrumentationState.m in Sources */, 962CE82A2E67189F00380522 /* NetworkEarlyPhaseHandlerImpl.mm in Sources */, @@ -2057,6 +2148,7 @@ CBB48A3D295EE1E10044E9AC /* ObjCUtils.mm in Sources */, 0921F02C2A67CBD600C764EB /* BugsnagPerformanceNetworkRequestInfo.m in Sources */, 966634D72C8A365B004A934D /* FrameMetricsSnapshot.mm in Sources */, + 967949FE2EA16465005FD87F /* MainModule.mm in Sources */, 963829182E54972C00404F3A /* AppStartupSpanFactoryImpl.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Sources/BugsnagPerformance/Private/Core/AppLifecycleListener.h b/Sources/BugsnagPerformance/Private/Core/AppLifecycleListener.h new file mode 100644 index 00000000..05ab776f --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Core/AppLifecycleListener.h @@ -0,0 +1,20 @@ +// +// AppLifecycleListener.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 21/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#pragma once + +namespace bugsnag { + +class AppLifecycleListener { +public: + virtual void onAppFinishedLaunching() noexcept = 0; + virtual void onAppEnteredBackground() noexcept = 0; + virtual void onAppEnteredForeground() noexcept = 0; + virtual ~AppLifecycleListener() {} +}; +} diff --git a/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributes.h b/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributes.h deleted file mode 100644 index a12e0743..00000000 --- a/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributes.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// SpanAttributes.h -// BugsnagPerformance-iOS -// -// Created by Nick Dowell on 03/11/2022. -// Copyright © 2022 Bugsnag. All rights reserved. -// - -#pragma once - -#import - -namespace bugsnag { -class SpanAttributes { -public: - static NSMutableDictionary *get() noexcept; -}; -} diff --git a/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributes.mm b/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributes.mm deleted file mode 100644 index 316a213e..00000000 --- a/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributes.mm +++ /dev/null @@ -1,33 +0,0 @@ -// -// SpanAttributes.mm -// BugsnagPerformance -// -// Created by Nick Dowell on 03/11/2022. -// Copyright © 2022 Bugsnag. All rights reserved. -// - -#import "SpanAttributes.h" - -#import "../../Main/BugsnagPerformanceLibrary.h" -#import "../../Utils/AppStateTracker.h" - -using namespace bugsnag; - -static NSString *hostConnectionType() noexcept { - switch (BugsnagPerformanceLibrary::getReachability()->getConnectivity()) { - case bugsnag::Reachability::Unknown: return @"unknown"; - case bugsnag::Reachability::None: return @"unavailable"; - case bugsnag::Reachability::Cellular: return @"cell"; - case bugsnag::Reachability::Wifi: return @"wifi"; - } -} - -NSMutableDictionary * -SpanAttributes::get() noexcept { - return @{ - @"bugsnag.app.in_foreground": @(BugsnagPerformanceLibrary::getAppStateTracker().isInForeground), - - // https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/span-general/#network-transport-attributes - @"net.host.connection.type": hostConnectionType(), - }.mutableCopy; -} diff --git a/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributesProvider.h b/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributesProvider.h index ff43731f..c489d409 100644 --- a/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributesProvider.h +++ b/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributesProvider.h @@ -10,13 +10,20 @@ #import #import "../BugsnagPerformanceViewType+Private.h" #import "../../Metrics/SystemMetrics/SystemInfoSampler.h" +#import "../../Utils/AppStateTracker.h" +#import "../../Utils/Reachability.h" namespace bugsnag { class SpanAttributesProvider { public: - SpanAttributesProvider() noexcept; + SpanAttributesProvider(AppStateTracker *appStateTracker, + std::shared_ptr reachability) noexcept + : appStateTracker_(appStateTracker) + , reachability_(reachability) {}; + ~SpanAttributesProvider() {}; + NSMutableDictionary *initialAttributes() noexcept; NSMutableDictionary *initialNetworkSpanAttributes() noexcept; NSMutableDictionary *networkSpanUrlAttributes(NSURL *url, NSError *encounteredError) noexcept; NSMutableDictionary *networkSpanAttributes(NSURL *url, NSURLSessionTask *task, NSURLSessionTaskMetrics *metrics, @@ -35,5 +42,11 @@ class SpanAttributesProvider { NSMutableDictionary *cpuSampleAttributes(const std::vector &samples) noexcept; NSMutableDictionary *memorySampleAttributes(const std::vector &samples) noexcept; + +private: + AppStateTracker *appStateTracker_; + std::shared_ptr reachability_; + + NSString *hostConnectionType() noexcept; }; } diff --git a/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributesProvider.mm b/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributesProvider.mm index 76164147..50d65881 100644 --- a/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributesProvider.mm +++ b/Sources/BugsnagPerformance/Private/Core/Attributes/SpanAttributesProvider.mm @@ -21,7 +21,15 @@ static NSString * const networkSubtypeKey = @"0000000100000001"; static NSString * const connectionTypeCell = @"cell"; -SpanAttributesProvider::SpanAttributesProvider() noexcept {}; +NSMutableDictionary * +SpanAttributesProvider::initialAttributes() noexcept { + return @{ + @"bugsnag.app.in_foreground": @(appStateTracker_.isInForeground), + + // https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/span-general/#network-transport-attributes + @"net.host.connection.type": hostConnectionType(), + }.mutableCopy; +} static NSString *getHTTPFlavour(NSURLSessionTaskMetrics *metrics) { for (NSURLSessionTaskTransactionMetrics *transactionMetrics in metrics.transactionMetrics) { @@ -343,3 +351,15 @@ static uint64_t CFAbsoluteTimeToUTCNanos(CFAbsoluteTime time) { @"bugsnag.system.memory.spaces.device.mean": @(memoryUseTotal / memorySampleCount), }.mutableCopy; } + +#pragma mark Private + +NSString * +SpanAttributesProvider::hostConnectionType() noexcept { + switch (reachability_->getConnectivity()) { + case bugsnag::Reachability::Unknown: return @"unknown"; + case bugsnag::Reachability::None: return @"unavailable"; + case bugsnag::Reachability::Cellular: return @"cell"; + case bugsnag::Reachability::Wifi: return @"wifi"; + } +} diff --git a/Sources/BugsnagPerformance/Private/Core/CoreModule.h b/Sources/BugsnagPerformance/Private/Core/CoreModule.h new file mode 100644 index 00000000..87a10c50 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Core/CoreModule.h @@ -0,0 +1,140 @@ +// +// CoreModule.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 16/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#pragma once + +#import "Module.h" +#import "AppLifecycleListener.h" + +#import "Attributes/ResourceAttributes.h" +#import "Sampler/PersistentState.h" +#import "Sampler/Sampler.h" +#import "SpanFactory/AppStartup/AppStartupSpanFactoryImpl.h" +#import "SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.h" +#import "SpanFactory/Network/NetworkSpanFactoryImpl.h" +#import "SpanFactory/Plain/PlainSpanFactoryImpl.h" +#import "SpanStack/SpanStackingHandler.h" +#import "SpanStore/SpanStoreImpl.h" +#import "SpanLifecycle/SpanLifecycleHandlerImpl.h" +#import "NetworkSpanReporter/NetworkSpanReporterImpl.h" +#import "Worker/Worker.h" +#import "BSGPrioritizedStore.h" +#import "SpanConditions/ConditionTimeoutExecutor.h" +#import "SpanProcessingPipeline/Batch.h" + +#import "../Utils/Persistence.h" +#import "../Utils/PersistentDeviceID.h" +#import "../Metrics/FrameMetrics/FrameMetricsSnapshot.h" +#import "../Instrumentation/AppStartupInstrumentation/State/AppStartupInstrumentationStateSnapshot.h" + +namespace bugsnag { +class CoreModule: public Module, public AppLifecycleListener { +public: + CoreModule(AppStateTracker *appStateTracker, + std::shared_ptr reachability, + std::shared_ptr persistence, + std::shared_ptr deviceID) noexcept + : appStateTracker_(appStateTracker) + , reachability_(reachability) + , persistence_(persistence) + , deviceID_(deviceID) {}; + + ~CoreModule(); + + void earlyConfigure(BSGEarlyConfiguration *config) noexcept; + void earlySetup() noexcept; + void configure(BugsnagPerformanceConfiguration *config) noexcept; + void preStartSetup() noexcept; + void start() noexcept; + + void initialize(NSArray *initialTasks, + NSArray *recurringTasks) noexcept { + initialTasks_ = initialTasks; + recurringTasks_ = recurringTasks; + } + + void setUp() noexcept; + void onAppFinishedLaunching() noexcept {} + void onAppEnteredBackground() noexcept; + void onAppEnteredForeground() noexcept; + + void initializeComponentsCallbacks(GetCurrentFrameMetricsSnapshot getCurrentSnapshot, + GetAppStartupStateSnapshot getAppStartupStateSnapshot, + HandleStringTask onViewLoadSpanStarted) noexcept { + spanLifecycleHandler_->initialize(getCurrentSnapshot); + plainSpanFactory_->setup(createPlainSpanFactoryCallbacks()); + viewLoadSpanFactory_->setup(createViewLoadSpanFactoryCallbacks(onViewLoadSpanStarted, getAppStartupStateSnapshot)); + } + + // Tasks + + UpdateProbabilityTask getUpdateProbabilityTask() noexcept; + UpdateConnectivityTask getUpdateConnectivityTask() noexcept; + + // Components access + + std::shared_ptr getBatch() noexcept { return batch_; } + std::shared_ptr getPlainSpanFactory() noexcept { return plainSpanFactory_; } + std::shared_ptr getAppStartupSpanFactory() noexcept { return appStartupSpanFactory_; } + std::shared_ptr getViewLoadSpanFactory() noexcept { return viewLoadSpanFactory_; } + std::shared_ptr getNetworkSpanFactory() noexcept { return networkSpanFactory_; } + std::shared_ptr getSpanAttributesProvider() noexcept { return spanAttributesProvider_; } + std::shared_ptr getSpanStackingHandler() noexcept { return spanStackingHandler_; } + std::shared_ptr getSpanStore() noexcept { return spanStore_; } + std::shared_ptr getSampler() noexcept { return sampler_; } + std::shared_ptr getConditionTimeoutExecutor() noexcept { return conditionTimeoutExecutor_; } + std::shared_ptr getSpanLifecycleHandler() noexcept { return spanLifecycleHandler_; } + std::shared_ptr getResourceAttributes() noexcept { return resourceAttributes_; } + std::shared_ptr getNetworkSpanReporter() noexcept { return networkSpanReporter_; } + BSGPrioritizedStore *getSpanStartCallbacks() noexcept { return spanStartCallbacks_; } + BSGPrioritizedStore *getSpanEndCallbacks() noexcept { return spanEndCallbacks_; } + +private: + + bool isStarted_{false}; + BugsnagPerformanceConfiguration *configuration_; + CFAbsoluteTime probabilityExpiry_{0}; + + CFTimeInterval probabilityValueExpiresAfterSeconds_{0}; + CFTimeInterval probabilityRequestsPauseForSeconds_{0}; + + NSTimer *workerTimer_{nil}; + + // Dependencies + AppStateTracker *appStateTracker_; + std::shared_ptr reachability_; + std::shared_ptr persistence_; + std::shared_ptr deviceID_; + NSArray *initialTasks_; + NSArray *recurringTasks_; + std::function getAppStartupInstrumentationState_{ [](){ return nil; } }; + + // Components + std::shared_ptr batch_; + std::shared_ptr persistentState_; + std::shared_ptr plainSpanFactory_; + std::shared_ptr appStartupSpanFactory_; + std::shared_ptr viewLoadSpanFactory_; + std::shared_ptr networkSpanFactory_; + std::shared_ptr spanAttributesProvider_; + std::shared_ptr spanStackingHandler_; + std::shared_ptr spanStore_; + std::shared_ptr sampler_; + std::shared_ptr conditionTimeoutExecutor_; + std::shared_ptr spanLifecycleHandler_; + std::shared_ptr resourceAttributes_; + std::shared_ptr networkSpanReporter_; + BSGPrioritizedStore *spanStartCallbacks_; + BSGPrioritizedStore *spanEndCallbacks_; + Worker *worker_; + + PlainSpanFactoryCallbacks *createPlainSpanFactoryCallbacks() noexcept; + ViewLoadSpanFactoryCallbacks *createViewLoadSpanFactoryCallbacks(HandleStringTask onViewLoadSpanStartedTask, + GetAppStartupStateSnapshot getAppStartupStateSnapshot) noexcept; +}; +} diff --git a/Sources/BugsnagPerformance/Private/Core/CoreModule.mm b/Sources/BugsnagPerformance/Private/Core/CoreModule.mm new file mode 100644 index 00000000..7a33fffc --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Core/CoreModule.mm @@ -0,0 +1,236 @@ +// +// CoreModule.mm +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 16/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#import "CoreModule.h" + +using namespace bugsnag; + +CoreModule::~CoreModule() { + [workerTimer_ invalidate]; +} + +#pragma mark PhasedStartup + +void +CoreModule::earlyConfigure(BSGEarlyConfiguration *config) noexcept { + persistentState_->earlyConfigure(config); + plainSpanFactory_->earlyConfigure(config); + resourceAttributes_->earlyConfigure(config); + batch_->earlyConfigure(config); + spanLifecycleHandler_->earlyConfigure(config); + networkSpanReporter_->earlyConfigure(config); + [worker_ earlyConfigure:config]; +} + +void +CoreModule::earlySetup() noexcept { + persistentState_->earlySetup(); + plainSpanFactory_->earlySetup(); + resourceAttributes_->earlySetup(); + batch_->earlySetup(); + spanLifecycleHandler_->earlySetup(); + networkSpanReporter_->earlySetup(); + [worker_ earlySetup]; +} + +void +CoreModule::configure(BugsnagPerformanceConfiguration *config) noexcept { + configuration_ = config; + probabilityValueExpiresAfterSeconds_ = config.internal.probabilityValueExpiresAfterSeconds; + probabilityRequestsPauseForSeconds_ = config.internal.probabilityRequestsPauseForSeconds; + persistentState_->configure(config); + plainSpanFactory_->configure(config); + resourceAttributes_->configure(config); + batch_->configure(config); + spanLifecycleHandler_->configure(config); + networkSpanReporter_->configure(config); + [worker_ configure:config]; +} + +void +CoreModule::preStartSetup() noexcept { + persistentState_->preStartSetup(); + plainSpanFactory_->preStartSetup(); + resourceAttributes_->preStartSetup(); + batch_->preStartSetup(); + spanLifecycleHandler_->preStartSetup(); + networkSpanReporter_->preStartSetup(); + [worker_ preStartSetup]; +} + +void +CoreModule::start() noexcept { + isStarted_ = true; + persistentState_->start(); + + double samplingProbability = persistentState_->probability(); + if (configuration_.samplingProbability != nil) { + samplingProbability = [configuration_.samplingProbability doubleValue]; + } + sampler_->setProbability(samplingProbability); + + plainSpanFactory_->start(); + resourceAttributes_->start(); + batch_->start(); + spanLifecycleHandler_->start(); + networkSpanReporter_->start(); + [worker_ start]; + + __block auto blockThis = this; + auto initialWorkDelay = configuration_.internal.initialRecurringWorkDelay; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(initialWorkDelay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [blockThis->worker_ wake]; + blockThis->workerTimer_ = [NSTimer scheduledTimerWithTimeInterval:blockThis->configuration_.internal.performWorkInterval + repeats:YES + block:^(NSTimer *) { + blockThis->batch_->allowDrain(); + [blockThis->worker_ wake]; + }]; + }); + batch_->setBatchFullCallback(^{ + [blockThis->worker_ wake]; + }); +} + +#pragma mark Module + +void +CoreModule::setUp() noexcept { + batch_ = std::make_shared(); + persistentState_ = std::make_shared(persistence_); + spanAttributesProvider_ = std::make_shared(appStateTracker_, + reachability_); + spanStackingHandler_ = std::make_shared(); + sampler_ = std::make_shared(); + conditionTimeoutExecutor_ = std::make_shared(); + plainSpanFactory_ = std::make_shared(sampler_, spanStackingHandler_, spanAttributesProvider_); + appStartupSpanFactory_ = std::make_shared(plainSpanFactory_, spanAttributesProvider_); + viewLoadSpanFactory_ = std::make_shared(plainSpanFactory_, spanAttributesProvider_); + networkSpanFactory_ = std::make_shared(plainSpanFactory_, spanAttributesProvider_); + + spanStartCallbacks_ = [BSGPrioritizedStore new]; + spanEndCallbacks_ = [BSGPrioritizedStore new]; + spanStore_ = std::make_shared(spanStackingHandler_); + spanLifecycleHandler_ = std::make_shared(sampler_, + spanStore_, + conditionTimeoutExecutor_, + plainSpanFactory_, + batch_, + spanStartCallbacks_, + spanEndCallbacks_); + resourceAttributes_ = std::make_shared(deviceID_); + networkSpanReporter_ = std::make_shared(spanAttributesProvider_, + networkSpanFactory_); + worker_ = [[Worker alloc] initWithInitialTasks:initialTasks_ recurringTasks:recurringTasks_]; +} + +#pragma mark Tasks + +UpdateProbabilityTask +CoreModule::getUpdateProbabilityTask() noexcept { + __block auto blockThis = this; + return ^(double newProbability) { + if (blockThis->configuration_.samplingProbability != nil) { + BSGLogTrace(@"CoreModule::getUpdateProbabilityTask: configuration_.samplingProbability != nil"); + return; + } + blockThis->probabilityExpiry_ = CFAbsoluteTimeGetCurrent() + probabilityValueExpiresAfterSeconds_; + blockThis->sampler_->setProbability(newProbability); + blockThis->persistentState_->setProbability(newProbability); + }; +} + +UpdateConnectivityTask +CoreModule::getUpdateConnectivityTask() noexcept { + __block auto blockThis = this; + return ^(Reachability::Connectivity connectivity) { + switch (connectivity) { + case Reachability::Cellular: case Reachability::Wifi: + [blockThis->worker_ wake]; + break; + case Reachability::Unknown: case Reachability::None: + // Don't care + break; + } + }; +} + +#pragma mark AppLifecycleListener + +void +CoreModule::onAppEnteredBackground() noexcept { + spanLifecycleHandler_->onAppEnteredBackground(); +} + +void +CoreModule::onAppEnteredForeground() noexcept { + if (!isStarted_) { + return; + } + + batch_->allowDrain(); + [worker_ wake]; +} + +#pragma mark Private + +PlainSpanFactoryCallbacks * +CoreModule::createPlainSpanFactoryCallbacks() noexcept { + __block auto blockThis = this; + auto callbacks = [PlainSpanFactoryCallbacks new]; + callbacks.onSpanStarted = ^(BugsnagPerformanceSpan * _Nonnull span, const SpanOptions &options) { + blockThis->spanLifecycleHandler_->onSpanStarted(span, options); + }; + + callbacks.onSpanEndSet = ^(BugsnagPerformanceSpan * _Nonnull span) { + blockThis->spanLifecycleHandler_->onSpanEndSet(span); + }; + + callbacks.onSpanClosed = ^(BugsnagPerformanceSpan * _Nonnull span) { + blockThis->spanLifecycleHandler_->onSpanClosed(span); + }; + + callbacks.onSpanBlocked = ^BugsnagPerformanceSpanCondition * _Nullable(BugsnagPerformanceSpan * _Nonnull span, NSTimeInterval timeout) { + return blockThis->spanLifecycleHandler_->onSpanBlocked(span, timeout); + }; + + callbacks.onSpanCancelled = ^(BugsnagPerformanceSpan * _Nonnull span) { + blockThis->spanLifecycleHandler_->onSpanCancelled(span); + }; + + return callbacks; +} + +ViewLoadSpanFactoryCallbacks * +CoreModule::createViewLoadSpanFactoryCallbacks(HandleStringTask onViewLoadSpanStartedTask, + GetAppStartupStateSnapshot getAppStartupStateSnapshot) noexcept { + __block auto blockThis = this; + auto callbacks = [ViewLoadSpanFactoryCallbacks new]; + callbacks.getViewLoadParentSpan = ^BugsnagPerformanceSpan *() { + if (getAppStartupStateSnapshot != nil) { + AppStartupInstrumentationStateSnapshot *appStartupState = getAppStartupStateSnapshot(); + if (appStartupState.isInProgress && !appStartupState.hasFirstView) { + return appStartupState.uiInitSpan; + } + } + return nil; + }; + callbacks.isViewLoadInProgress = ^BOOL() { + return blockThis->spanStore_->hasSpanOnCurrentStack(@"bugsnag.span.category", @"view_load"); + }; + + auto onViewLoadSpanStarted = ^(NSString * _Nonnull className) { + if (onViewLoadSpanStartedTask != nil) { + onViewLoadSpanStartedTask(className); + } + }; + + callbacks.onViewLoadSpanStarted = onViewLoadSpanStarted; + + return callbacks; +} diff --git a/Sources/BugsnagPerformance/Private/Core/Module.h b/Sources/BugsnagPerformance/Private/Core/Module.h new file mode 100644 index 00000000..0a5182be --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Core/Module.h @@ -0,0 +1,19 @@ +// +// Module.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 16/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#import "PhasedStartup.h" +#import "ModuleTaskTypes.h" + +namespace bugsnag { +class Module: public PhasedStartup { +public: + virtual void setUp() noexcept = 0; + + virtual ~Module() {}; +}; +} diff --git a/Sources/BugsnagPerformance/Private/Core/ModuleTaskTypes.h b/Sources/BugsnagPerformance/Private/Core/ModuleTaskTypes.h new file mode 100644 index 00000000..a05a223c --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Core/ModuleTaskTypes.h @@ -0,0 +1,18 @@ +// +// ModuleTaskTypes.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 21/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#pragma once + +#import "../Utils/Reachability.h" + +using namespace bugsnag; + +typedef void (^ModuleTask)(); +typedef void (^UpdateProbabilityTask)(double); +typedef void (^UpdateConnectivityTask)(Reachability::Connectivity); +typedef void (^HandleStringTask)(NSString *); diff --git a/Sources/BugsnagPerformance/Private/Core/NetworkSpanReporter/NetworkSpanReporter.h b/Sources/BugsnagPerformance/Private/Core/NetworkSpanReporter/NetworkSpanReporter.h new file mode 100644 index 00000000..bf7b1ff3 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Core/NetworkSpanReporter/NetworkSpanReporter.h @@ -0,0 +1,20 @@ +// +// NetworkSpanReporter.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 22/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#pragma once + +#import +#import "../PhasedStartup.h" + +namespace bugsnag { + +class NetworkSpanReporter: public PhasedStartup { +public: + virtual void reportNetworkSpan(NSURLSessionTask *task, NSURLSessionTaskMetrics *metrics) noexcept = 0; +}; +} diff --git a/Sources/BugsnagPerformance/Private/Core/NetworkSpanReporter/NetworkSpanReporterImpl.h b/Sources/BugsnagPerformance/Private/Core/NetworkSpanReporter/NetworkSpanReporterImpl.h new file mode 100644 index 00000000..c5ce36a9 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Core/NetworkSpanReporter/NetworkSpanReporterImpl.h @@ -0,0 +1,45 @@ +// +// NetworkSpanReporterImpl.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 22/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#pragma once + +#import "NetworkSpanReporter.h" +#import "../Attributes/SpanAttributesProvider.h" +#import "../SpanFactory/Network/NetworkSpanFactory.h" + +namespace bugsnag { + +class NetworkSpanReporterImpl: public NetworkSpanReporter { +public: + NetworkSpanReporterImpl(std::shared_ptr spanAttributesProvider, + std::shared_ptr networkSpanFactory) noexcept + : spanAttributesProvider_(spanAttributesProvider) + , networkSpanFactory_(networkSpanFactory) {} + + void earlyConfigure(BSGEarlyConfiguration *) noexcept {} + void earlySetup() noexcept {} + void configure(BugsnagPerformanceConfiguration *config) noexcept { + auto networkRequestCallback = config.networkRequestCallback; + if (networkRequestCallback != nullptr) { + networkRequestCallback_ = (BugsnagPerformanceNetworkRequestCallback _Nonnull)networkRequestCallback; + } + } + void preStartSetup() noexcept {} + void start() noexcept {} + + void reportNetworkSpan(NSURLSessionTask *task, NSURLSessionTaskMetrics *metrics) noexcept; + +private: + std::shared_ptr spanAttributesProvider_; + std::shared_ptr networkSpanFactory_; + + BugsnagPerformanceNetworkRequestCallback networkRequestCallback_{nullptr}; + + NetworkSpanReporterImpl() = delete; +}; +} diff --git a/Sources/BugsnagPerformance/Private/Core/NetworkSpanReporter/NetworkSpanReporterImpl.mm b/Sources/BugsnagPerformance/Private/Core/NetworkSpanReporter/NetworkSpanReporterImpl.mm new file mode 100644 index 00000000..97927c34 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Core/NetworkSpanReporter/NetworkSpanReporterImpl.mm @@ -0,0 +1,38 @@ +// +// NetworkSpanReporterImpl.mm +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 22/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#import "../Span/BugsnagPerformanceSpan+Private.h" +#import "NetworkSpanReporterImpl.h" + +using namespace bugsnag; + +void +NetworkSpanReporterImpl::reportNetworkSpan(NSURLSessionTask *task, NSURLSessionTaskMetrics *metrics) noexcept { + BugsnagPerformanceSpan *span = nil; + + NSError *errorFromGetRequest = nil; + NSURLRequest *req = getTaskRequest(task, &errorFromGetRequest); + + auto info = [BugsnagPerformanceNetworkRequestInfo new]; + info.url = req.URL; + bool userVetoedTracing = false; + if (info.url != nil && networkRequestCallback_ != nullptr) { + info = networkRequestCallback_(info); + userVetoedTracing = info.url == nil; + } + if (!userVetoedTracing) { + auto interval = metrics.taskInterval; + auto name = req.HTTPMethod; + SpanOptions options; + options.makeCurrentContext = false; + options.startTime = dateToAbsoluteTime(interval.startDate); + auto attributes = spanAttributesProvider_->networkSpanAttributes(info.url, task, metrics, errorFromGetRequest); + span = networkSpanFactory_->startNetworkSpan(name, options, attributes); + [span endWithEndTime:interval.endDate]; + } +} diff --git a/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryImpl.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryImpl.h index 4e06c942..5ca46ebf 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryImpl.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryImpl.h @@ -10,13 +10,14 @@ #import "PlainSpanFactory.h" #import "PlainSpanFactoryCallbacks.h" +#import "../../PhasedStartup.h" #import "../../Attributes/SpanAttributesProvider.h" #import "../../Sampler/Sampler.h" #import "../../SpanStack/SpanStackingHandler.h" namespace bugsnag { -class PlainSpanFactoryImpl: public PlainSpanFactory { +class PlainSpanFactoryImpl: public PlainSpanFactory, public PhasedStartup { public: PlainSpanFactoryImpl(std::shared_ptr sampler, std::shared_ptr spanStackingHandler, @@ -25,6 +26,14 @@ class PlainSpanFactoryImpl: public PlainSpanFactory { , spanStackingHandler_(spanStackingHandler) , spanAttributesProvider_(spanAttributesProvider) {} + void earlyConfigure(BSGEarlyConfiguration *) noexcept {} + void earlySetup() noexcept {} + void configure(BugsnagPerformanceConfiguration *config) noexcept { + attributeCountLimit_ = config.attributeCountLimit; + } + void preStartSetup() noexcept {} + void start() noexcept {} + BugsnagPerformanceSpan *startSpan(NSString *name, const SpanOptions &options, BSGTriState defaultFirstClass, @@ -42,10 +51,6 @@ class PlainSpanFactoryImpl: public PlainSpanFactory { callbacks_ = callbacks; } - void setAttributeCountLimit(NSUInteger limit) noexcept { - attributeCountLimit_ = limit; - } - private: std::shared_ptr sampler_; std::shared_ptr spanStackingHandler_; diff --git a/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryImpl.mm b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryImpl.mm index 53870b88..9b0bf8a8 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryImpl.mm +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/Plain/PlainSpanFactoryImpl.mm @@ -7,7 +7,6 @@ // #import "PlainSpanFactoryImpl.h" -#import "../../Attributes/SpanAttributes.h" using namespace bugsnag; @@ -84,7 +83,7 @@ onSpanClosed:onSpanClosed onSpanBlocked:onSpanBlocked onSpanCancelled:onSpanCancelled]; - NSMutableDictionary *initialAttributes = SpanAttributes::get(); + NSMutableDictionary *initialAttributes = spanAttributesProvider_->initialAttributes(); [initialAttributes addEntriesFromDictionary:attributes]; [span internalSetMultipleAttributes:initialAttributes]; span.kind = kind; diff --git a/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactory.h b/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactory.h index ef135575..25f12f6d 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactory.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanFactory/ViewLoad/ViewLoadSpanFactory.h @@ -40,6 +40,10 @@ class ViewLoadSpanFactory { NSString *suffix, const SpanOptions &options, NSDictionary *attributes) noexcept = 0; + virtual BugsnagPerformanceSpan *startViewLoadPhaseSpan(NSString *className, + BugsnagPerformanceSpanContext *parentContext, + NSString *phase, + NSArray *conditionsToEndOnClose) noexcept = 0; virtual ~ViewLoadSpanFactory() {} }; } diff --git a/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.h b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.h index 8b640b9d..b9aadb07 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.h @@ -12,7 +12,7 @@ #import "SpanLifecycleHandler.h" #import "../SpanProcessingPipeline/Batch.h" #import "../Configuration/BugsnagPerformanceConfiguration+Private.h" -#import "../../Metrics/FrameMetrics/FrameMetricsCollector.h" +#import "../../Metrics/FrameMetrics/FrameMetricsSnapshot.h" #import "../SpanStack/SpanStackingHandler.h" #import "../Sampler/Sampler.h" #import "../SpanFactory/Plain/PlainSpanFactoryImpl.h" @@ -31,19 +31,15 @@ class SpanLifecycleHandlerImpl: public SpanLifecycleHandler { std::shared_ptr conditionTimeoutExecutor, std::shared_ptr plainSpanFactory, std::shared_ptr batch, - FrameMetricsCollector *frameMetricsCollector, BSGPrioritizedStore *onSpanStartCallbacks, - BSGPrioritizedStore *onSpanEndCallbacks, - void (^onSpanStarted)()) noexcept + BSGPrioritizedStore *onSpanEndCallbacks) noexcept : sampler_(sampler) , store_(store) , conditionTimeoutExecutor_(conditionTimeoutExecutor) , plainSpanFactory_(plainSpanFactory) , batch_(batch) - , frameMetricsCollector_(frameMetricsCollector) , onSpanStartCallbacks_(onSpanStartCallbacks) - , onSpanEndCallbacks_(onSpanEndCallbacks) - , onSpanStarted_(onSpanStarted) {} + , onSpanEndCallbacks_(onSpanEndCallbacks) {} void earlyConfigure(BSGEarlyConfiguration *) noexcept {} void earlySetup() noexcept {} @@ -55,6 +51,10 @@ class SpanLifecycleHandlerImpl: public SpanLifecycleHandler { isStarted_ = true; } + void initialize(GetCurrentFrameMetricsSnapshot getCurrentSnapshot) noexcept { + getCurrentSnapshot_ = getCurrentSnapshot; + } + void onAppEnteredBackground() noexcept; void onSpanStarted(BugsnagPerformanceSpan *span, const SpanOptions &options) noexcept; void onSpanEndSet(BugsnagPerformanceSpan *span) noexcept; @@ -68,14 +68,13 @@ class SpanLifecycleHandlerImpl: public SpanLifecycleHandler { std::shared_ptr conditionTimeoutExecutor_; std::shared_ptr plainSpanFactory_; std::shared_ptr store_; - FrameMetricsCollector *frameMetricsCollector_; bool isStarted_{false}; - void (^onSpanStarted_)(){ ^(){} }; std::shared_ptr batch_; BSGPrioritizedStore *onSpanStartCallbacks_; BSGPrioritizedStore *onSpanEndCallbacks_; BugsnagPerformanceEnabledMetrics *enabledMetrics_{[BugsnagPerformanceEnabledMetrics withAllEnabled]}; + GetCurrentFrameMetricsSnapshot getCurrentSnapshot_{nullptr}; void processClosedSpan(BugsnagPerformanceSpan *span) noexcept; bool shouldInstrumentRendering(BugsnagPerformanceSpan *span) noexcept; diff --git a/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.mm b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.mm index f362ebd6..d779e2e6 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.mm +++ b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.mm @@ -19,18 +19,17 @@ void SpanLifecycleHandlerImpl::onSpanStarted(BugsnagPerformanceSpan *span, const SpanOptions &options) noexcept { - if (shouldInstrumentRendering(span)) { - span.startFramerateSnapshot = [frameMetricsCollector_ currentSnapshot]; + if (shouldInstrumentRendering(span) && getCurrentSnapshot_) { + span.startFramerateSnapshot = getCurrentSnapshot_(); } store_->addNewSpan(span, options.makeCurrentContext); callOnSpanStartCallbacks(span); - onSpanStarted_(); } void SpanLifecycleHandlerImpl::onSpanEndSet(BugsnagPerformanceSpan *span) noexcept { - if (shouldInstrumentRendering(span)) { - span.endFramerateSnapshot = [frameMetricsCollector_ currentSnapshot]; + if (shouldInstrumentRendering(span) && getCurrentSnapshot_) { + span.endFramerateSnapshot = getCurrentSnapshot_(); } } diff --git a/Sources/BugsnagPerformance/Private/Core/Worker/WorkerTask.h b/Sources/BugsnagPerformance/Private/Core/Worker/WorkerTask.h new file mode 100644 index 00000000..ec981b2f --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Core/Worker/WorkerTask.h @@ -0,0 +1,28 @@ +// +// WorkerTask.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 20/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#pragma once + +typedef void (^TaskCompletion)(bool); +typedef void (^TaskWork)(TaskCompletion); + +namespace bugsnag { + +class WorkerTask { +public: + WorkerTask(TaskWork work) noexcept + : work_(work) {} + + bool executeSync(); + + ~WorkerTask() {} + +private: + TaskWork work_{nullptr}; +}; +} diff --git a/Sources/BugsnagPerformance/Private/Core/Worker/WorkerTask.mm b/Sources/BugsnagPerformance/Private/Core/Worker/WorkerTask.mm new file mode 100644 index 00000000..46697aa0 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Core/Worker/WorkerTask.mm @@ -0,0 +1,9 @@ +// +// WorkerTask.mm +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 20/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + + diff --git a/Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h b/Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h index 8b7509ca..d0d9462e 100644 --- a/Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h +++ b/Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h @@ -24,14 +24,15 @@ // It contains a full example for how to set up a client library to call this one. #import -#import #import "../Core/PhasedStartup.h" +#import + NS_ASSUME_NONNULL_BEGIN namespace bugsnag { class SpanStackingHandler; -class Tracer; +class PlainSpanFactory; } @interface BugsnagPerformanceCrossTalkAPI : NSObject @@ -41,7 +42,8 @@ class Tracer; /** * Use the initialize method to pass any information this CrossTalk API requires to function. */ -+ (void)initializeWithSpanStackingHandler:(std::shared_ptr) handler tracer:(std::shared_ptr) tracer; ++ (void)initializeWithSpanStackingHandler:(std::shared_ptr)handler + spanFactory:(std::shared_ptr)spanFactory; - (void)willEndUIInitSpan:(BugsnagPerformanceSpan *)span; - (void)willEndViewLoadSpan:(BugsnagPerformanceSpan *)span viewController:(UIViewController *)viewController; diff --git a/Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.mm b/Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.mm index a0d66753..d6934d67 100644 --- a/Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.mm +++ b/Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.mm @@ -7,9 +7,9 @@ // #import "BugsnagPerformanceCrossTalkAPI.h" -#import "../Core/SpanStack/SpanStackingHandler.h" -#import "../Tracer.h" #import "../Utils/Utils.h" +#import "../Core/SpanStack/SpanStackingHandler.h" +#import "../Core/SpanFactory/Plain/PlainSpanFactory.h" #import using namespace bugsnag; @@ -23,7 +23,7 @@ @interface BugsnagPerformanceCrossTalkAPI () // Declare the things your API class needs here @property(nonatomic) std::shared_ptr spanStackingHandler; -@property(nonatomic) std::shared_ptr tracer; +@property(nonatomic) std::shared_ptr spanFactory; @property(readwrite, nonatomic) BugsnagPerformanceConfiguration *configuration; @property(nonatomic, copy) NSArray *willEndUIInitSpanCallbacks; @property(nonatomic, copy) NSArray *willEndViewLoadSpanCallbacks; @@ -36,9 +36,10 @@ @implementation BugsnagPerformanceCrossTalkAPI /** * You'll call your initialize method during start up. */ -+ (void)initializeWithSpanStackingHandler:(std::shared_ptr) handler tracer:(std::shared_ptr)tracer { ++ (void)initializeWithSpanStackingHandler:(std::shared_ptr)handler + spanFactory:(std::shared_ptr)spanFactory { BugsnagPerformanceCrossTalkAPI.sharedInstance.spanStackingHandler = handler; - BugsnagPerformanceCrossTalkAPI.sharedInstance.tracer = tracer; + BugsnagPerformanceCrossTalkAPI.sharedInstance.spanFactory = spanFactory; } #pragma mark Exposed API @@ -82,13 +83,13 @@ - (BugsnagPerformanceConfiguration * _Nullable)getConfigurationV1 { } - (BugsnagPerformanceSpan * _Nullable)startSpanV1:(NSString * _Nonnull)name options:(BugsnagPerformanceSpanOptions *)optionsIn { - auto tracer = self.tracer; - if (tracer == nullptr) { + auto spanFactory = self.spanFactory; + if (spanFactory == nullptr) { return nil; } auto options = SpanOptions(optionsIn); - auto span = tracer->startSpan(name, options, BSGTriStateUnset, @[]); + auto span = spanFactory->startSpan(name, options, BSGTriStateUnset, @{}, @[]); return (BugsnagPerformanceSpan *)[BugsnagPerformanceCrossTalkProxiedObject proxied:span]; } diff --git a/Sources/BugsnagPerformance/Private/CrossTalkAPI/CrossTalkAPIModule.h b/Sources/BugsnagPerformance/Private/CrossTalkAPI/CrossTalkAPIModule.h new file mode 100644 index 00000000..18032b26 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/CrossTalkAPI/CrossTalkAPIModule.h @@ -0,0 +1,45 @@ +// +// CrossTalkAPIModule.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 16/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#pragma once + +#import "../Core/Module.h" +#import "../Core/PhasedStartup.h" +#import "../Core/SpanStack/SpanStackingHandler.h" +#import "../Core/SpanFactory/Plain/PlainSpanFactory.h" +#import "BugsnagPerformanceCrossTalkAPI.h" + +namespace bugsnag { +class CrossTalkAPIModule: public Module { +public: + CrossTalkAPIModule(std::shared_ptr spanFactory, + std::shared_ptr spanStackingHandler) + : spanFactory_(spanFactory) + , spanStackingHandler_(spanStackingHandler) {}; + + ~CrossTalkAPIModule() {}; + + void earlyConfigure(BSGEarlyConfiguration *config) noexcept; + void earlySetup() noexcept; + void configure(BugsnagPerformanceConfiguration *config) noexcept; + void preStartSetup() noexcept; + void start() noexcept; + + void setUp() noexcept; + + BugsnagPerformanceCrossTalkAPI *getCrossTalkAPI() noexcept { return [BugsnagPerformanceCrossTalkAPI sharedInstance]; } + +private: + + // Dependencies + std::shared_ptr spanFactory_; + std::shared_ptr spanStackingHandler_; + + CrossTalkAPIModule() = delete; +}; +} diff --git a/Sources/BugsnagPerformance/Private/CrossTalkAPI/CrossTalkAPIModule.mm b/Sources/BugsnagPerformance/Private/CrossTalkAPI/CrossTalkAPIModule.mm new file mode 100644 index 00000000..16e8278f --- /dev/null +++ b/Sources/BugsnagPerformance/Private/CrossTalkAPI/CrossTalkAPIModule.mm @@ -0,0 +1,46 @@ +// +// CrossTalkAPIModule.mm +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 16/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#import "CrossTalkAPIModule.h" + +using namespace bugsnag; + +#pragma mark PhasedStartup + +void +CrossTalkAPIModule::earlyConfigure(BSGEarlyConfiguration *config) noexcept { + [[BugsnagPerformanceCrossTalkAPI sharedInstance] earlyConfigure:config]; +} + +void +CrossTalkAPIModule::earlySetup() noexcept { + [[BugsnagPerformanceCrossTalkAPI sharedInstance] earlySetup]; +} + +void +CrossTalkAPIModule::configure(BugsnagPerformanceConfiguration *config) noexcept { + [[BugsnagPerformanceCrossTalkAPI sharedInstance] configure:config]; +} + +void +CrossTalkAPIModule::preStartSetup() noexcept { + [[BugsnagPerformanceCrossTalkAPI sharedInstance] preStartSetup]; +} + +void +CrossTalkAPIModule::start() noexcept { + [[BugsnagPerformanceCrossTalkAPI sharedInstance] start]; +} + +#pragma mark Module + +void +CrossTalkAPIModule::setUp() noexcept { + [BugsnagPerformanceCrossTalkAPI initializeWithSpanStackingHandler:spanStackingHandler_ + spanFactory:spanFactory_]; +} diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/AppStartupInstrumentation.mm b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/AppStartupInstrumentation.mm index 8e5ef85a..ab267d0c 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/AppStartupInstrumentation.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/AppStartupInstrumentation.mm @@ -10,7 +10,7 @@ #import "../../Utils/Utils.h" #import "../../Core/Span/BugsnagPerformanceSpan+Private.h" #import "../../Main/BugsnagPerformanceImpl.h" -#import "../../CrosstalkAPI/BugsnagPerformanceCrossTalkAPI.h" +#import "../../CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h" #import #import diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandlerImpl.h b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandlerImpl.h index 9347e4e4..00375915 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandlerImpl.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandlerImpl.h @@ -12,7 +12,7 @@ #import "../../../Core/SpanFactory/AppStartup/AppStartupSpanFactory.h" #import "../System/AppStartupInstrumentationSystemUtils.h" #import "../../../Core/Attributes/SpanAttributesProvider.h" -#import "../../../CrosstalkAPI/BugsnagPerformanceCrossTalkAPI.h" +#import "../../../CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h" #import diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/State/AppStartupInstrumentationStateSnapshot.h b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/State/AppStartupInstrumentationStateSnapshot.h index 39be2cba..175c8edd 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/State/AppStartupInstrumentationStateSnapshot.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/AppStartupInstrumentation/State/AppStartupInstrumentationStateSnapshot.h @@ -23,3 +23,5 @@ hasFirstView:(BOOL)hasFirstView; @end + +typedef AppStartupInstrumentationStateSnapshot *(^GetAppStartupStateSnapshot)(void); diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.h b/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.h index bde2a00a..15042c71 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.h @@ -11,6 +11,7 @@ #import #import "../Core/PhasedStartup.h" +#import "../Core/AppLifecycleListener.h" #import "AppStartupInstrumentation/AppStartupInstrumentation.h" #import "NetworkInstrumentation/NetworkInstrumentation.h" #import "AppStartupInstrumentation/System/AppStartupInstrumentationSystemUtilsImpl.h" @@ -39,7 +40,7 @@ std::shared_ptr createNetworkInstrumentation(std::shared namespace bugsnag { -class Instrumentation: public PhasedStartup { +class Instrumentation: public PhasedStartup, public AppLifecycleListener { public: Instrumentation(std::shared_ptr appStartupSpanFactory, std::shared_ptr viewLoadSpanFactory, @@ -49,22 +50,20 @@ class Instrumentation: public PhasedStartup { : appStartupInstrumentation_(createAppStartupInstrumentation(appStartupSpanFactory, spanAttributesProvider)) , viewLoadInstrumentation_(createViewLoadInstrumentation(viewLoadSpanFactory, spanAttributesProvider)) , networkInstrumentation_(createNetworkInstrumentation(networkSpanFactory, spanAttributesProvider, networkHeaderInjector)) - { - // TODO -// tracer->setGetAppStartInstrumentationState([=]{ return appStartupInstrumentation_->stateSnapshot(); }); - } + {} void earlyConfigure(BSGEarlyConfiguration *config) noexcept; void earlySetup() noexcept; void configure(BugsnagPerformanceConfiguration *config) noexcept; void preStartSetup() noexcept; void start() noexcept; - void abortAppStartupSpans() noexcept; + + void onAppFinishedLaunching() noexcept; + void onAppEnteredBackground() noexcept; + void onAppEnteredForeground() noexcept {} void didStartViewLoadSpan(NSString *name) noexcept { appStartupInstrumentation_->didStartViewLoadSpan(name); } void willCallMainFunction() noexcept { appStartupInstrumentation_->willCallMainFunction(); } - CFAbsoluteTime appStartDuration() noexcept { return appStartupInstrumentation_->appStartDuration(); } - CFAbsoluteTime timeSinceAppFirstBecameActive() noexcept { return appStartupInstrumentation_->timeSinceAppFirstBecameActive(); } AppStartupInstrumentationStateSnapshot *getAppStartInstrumentationStateSnapshot() { return appStartupInstrumentation_->stateSnapshot(); } @@ -73,10 +72,13 @@ class Instrumentation: public PhasedStartup { private: Instrumentation() = delete; - + + bool hasCheckedAppStartDuration_{false}; std::shared_ptr appStartupInstrumentation_; std::shared_ptr viewLoadInstrumentation_; std::shared_ptr networkInstrumentation_; + + void checkAppStartDuration() noexcept; }; } diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.mm b/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.mm index febe3be1..e1e4479b 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.mm @@ -23,8 +23,16 @@ #import "NetworkInstrumentation/Lifecycle/NetworkEarlyPhaseHandlerImpl.h" #import "NetworkInstrumentation/Lifecycle/NetworkLifecycleHandlerImpl.h" +// App start spans will be thrown out if the early app start duration exceeds this. +static constexpr CFTimeInterval maxAppStartDuration = 2.0; + +// App start spans will be thrown out if the app gets backgrounded within this timeframe after starting. +static constexpr CFTimeInterval minTimeToBackgrounding = 2.0; + using namespace bugsnag; +#pragma mark PhasedStartup + void Instrumentation::earlyConfigure(BSGEarlyConfiguration *config) noexcept { appStartupInstrumentation_->earlyConfigure(config); viewLoadInstrumentation_->earlyConfigure(config); @@ -50,15 +58,12 @@ } void Instrumentation::start() noexcept { + checkAppStartDuration(); appStartupInstrumentation_->start(); viewLoadInstrumentation_->start(); networkInstrumentation_->start(); } -void Instrumentation::abortAppStartupSpans() noexcept { - appStartupInstrumentation_->abortAllSpans(); -} - #pragma mark - Factory functions std::shared_ptr createAppStartupInstrumentation(std::shared_ptr spanFactory, @@ -108,3 +113,36 @@ lifecycleHandler, delegate); } + +#pragma mark AppLifecycleListener + +void +Instrumentation::onAppFinishedLaunching() noexcept { + checkAppStartDuration(); +} + +void +Instrumentation::onAppEnteredBackground() noexcept { + // We run this WITHOUT checking isStarted (in case there's notification + // timing jank and we get the notification before we've started). + if (appStartupInstrumentation_->timeSinceAppFirstBecameActive() < minTimeToBackgrounding) { + // If we get backgrounded too quickly after app start, throw out + // all app start spans even if they've completed. + // Sometimes the jank between backgrounding/foregrounding events + // can cause the spans to close very late, so we play it safe. + appStartupInstrumentation_->abortAllSpans(); + } +} + +#pragma mark Private + +// This is checked in two places: Bugsnag start, and NSApplicationDidFinishLaunchingNotification. +void +Instrumentation::checkAppStartDuration() noexcept { + if (!hasCheckedAppStartDuration_) { + hasCheckedAppStartDuration_ = true; + if (appStartupInstrumentation_->appStartDuration() > maxAppStartDuration) { + appStartupInstrumentation_->abortAllSpans(); + } + } +} diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/InstrumentationModule.h b/Sources/BugsnagPerformance/Private/Instrumentation/InstrumentationModule.h new file mode 100644 index 00000000..314c4391 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Instrumentation/InstrumentationModule.h @@ -0,0 +1,82 @@ +// +// InstrumentationModule.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 16/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#pragma once + +#import "Instrumentation.h" +#import "AppStartupInstrumentation/State/AppStartupInstrumentationStateSnapshot.h" +#import "../Core/Module.h" +#import "../Core/AppLifecycleListener.h" +#import "../Core/Attributes/SpanAttributesProvider.h" +#import "../Core/Sampler/Sampler.h" +#import "../Core/SpanFactory/AppStartup/AppStartupSpanFactory.h" +#import "../Core/SpanFactory/ViewLoad/ViewLoadSpanFactory.h" +#import "../Core/SpanFactory/Network/NetworkSpanFactory.h" +#import "../Core/SpanStack/SpanStackingHandler.h" + +namespace bugsnag { +class InstrumentationModule: public Module, AppLifecycleListener { +public: + InstrumentationModule(std::shared_ptr appStartupSpanFactory, + std::shared_ptr viewLoadSpanFactory, + std::shared_ptr networkSpanFactory, + std::shared_ptr spanAttributesProvider, + std::shared_ptr spanStackingHandler, + std::shared_ptr sampler) + : appStartupSpanFactory_(appStartupSpanFactory) + , viewLoadSpanFactory_(viewLoadSpanFactory) + , networkSpanFactory_(networkSpanFactory) + , spanAttributesProvider_(spanAttributesProvider) + , spanStackingHandler_(spanStackingHandler) + , sampler_(sampler) {}; + + ~InstrumentationModule() {}; + + void earlyConfigure(BSGEarlyConfiguration *) noexcept; + void earlySetup() noexcept; + void configure(BugsnagPerformanceConfiguration *config) noexcept; + void preStartSetup() noexcept; + void start() noexcept; + + void setUp() noexcept; + + void onAppFinishedLaunching() noexcept; + void onAppEnteredBackground() noexcept; + void onAppEnteredForeground() noexcept; + + void loadingIndicatorWasAdded(BugsnagPerformanceLoadingIndicatorView *loadingViewIndicator) noexcept { + instrumentation_->loadingIndicatorWasAdded(loadingViewIndicator); + } + + // Tasks + + GetAppStartupStateSnapshot getAppStartupStateSnapshotTask() noexcept; + HandleStringTask getHandleViewLoadSpanStartedTask() noexcept; + + // Component access + + std::shared_ptr getNetworkHeaderInjector() noexcept { return networkHeaderInjector_; } + std::shared_ptr getInstrumentation() noexcept { return instrumentation_; } + +private: + + // Dependencies + std::shared_ptr appStartupSpanFactory_; + std::shared_ptr viewLoadSpanFactory_; + std::shared_ptr networkSpanFactory_; + std::shared_ptr spanAttributesProvider_; + std::shared_ptr spanStackingHandler_; + std::shared_ptr sampler_; + + // Components + std::shared_ptr networkHeaderInjector_; + std::shared_ptr instrumentation_; + + InstrumentationModule() = delete; +}; +} diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/InstrumentationModule.mm b/Sources/BugsnagPerformance/Private/Instrumentation/InstrumentationModule.mm new file mode 100644 index 00000000..a5083b11 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Instrumentation/InstrumentationModule.mm @@ -0,0 +1,97 @@ +// +// InstrumentationModule.mm +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 16/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#import "InstrumentationModule.h" + +using namespace bugsnag; + +#pragma mark PhasedStartup + +void +InstrumentationModule::earlyConfigure(BSGEarlyConfiguration *config) noexcept { + networkHeaderInjector_->earlyConfigure(config); + instrumentation_->earlyConfigure(config); +} + +void +InstrumentationModule::earlySetup() noexcept { + networkHeaderInjector_->earlySetup(); + instrumentation_->earlySetup(); +} + +void +InstrumentationModule::configure(BugsnagPerformanceConfiguration *config) noexcept { + networkHeaderInjector_->configure(config); + instrumentation_->configure(config); +} + +void +InstrumentationModule::preStartSetup() noexcept { + networkHeaderInjector_->preStartSetup(); + instrumentation_->preStartSetup(); +} + +void +InstrumentationModule::start() noexcept { + networkHeaderInjector_->start(); + instrumentation_->start(); +} + +#pragma mark Module + +void +InstrumentationModule::setUp() noexcept { + networkHeaderInjector_ = std::make_shared(spanAttributesProvider_, spanStackingHandler_, sampler_); + + instrumentation_ = std::make_shared(appStartupSpanFactory_, + viewLoadSpanFactory_, + networkSpanFactory_, + spanAttributesProvider_, + networkHeaderInjector_); +} + +#pragma mark Tasks + +GetAppStartupStateSnapshot +InstrumentationModule::getAppStartupStateSnapshotTask() noexcept { + __block auto blockThis = this; + return ^AppStartupInstrumentationStateSnapshot *{ + if (blockThis->instrumentation_ == nullptr) { + return nil; + } + return blockThis->instrumentation_->getAppStartInstrumentationStateSnapshot(); + }; +} + +HandleStringTask +InstrumentationModule::getHandleViewLoadSpanStartedTask() noexcept { + __block auto blockThis = this; + return ^(NSString *viewName){ + if (blockThis->instrumentation_ == nullptr) { + return; + } + blockThis->instrumentation_->didStartViewLoadSpan(viewName); + }; +} + +#pragma mark AppLifecycleListener + +void +InstrumentationModule::onAppFinishedLaunching() noexcept { + instrumentation_->onAppFinishedLaunching(); +} + +void +InstrumentationModule::onAppEnteredBackground() noexcept { + instrumentation_->onAppEnteredBackground(); +} + +void +InstrumentationModule::onAppEnteredForeground() noexcept { + instrumentation_->onAppEnteredForeground(); +} diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandlerImpl.h b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandlerImpl.h index 8627a4be..23307d36 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandlerImpl.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/ViewLoadInstrumentation/Lifecycle/ViewLoadLifecycleHandlerImpl.h @@ -14,7 +14,7 @@ #import "../../../Core/SpanFactory/ViewLoad/ViewLoadSpanFactory.h" #import "../../../Core/Attributes/SpanAttributesProvider.h" #import "../State/ViewLoadInstrumentationStateRepository.h" -#import "../../../CrosstalkAPI/BugsnagPerformanceCrossTalkAPI.h" +#import "../../../CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.h b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.h index 8a0264b5..76872020 100644 --- a/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.h +++ b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.h @@ -12,10 +12,11 @@ #import #import +#import "MainModule.h" + #import "../Core/Span/BugsnagPerformanceSpan+Private.h" #import "../Upload/Otlp/OtlpUploader.h" #import "../Core/Sampler/Sampler.h" -#import "../Tracer.h" #import "../Core/Worker/Worker.h" #import "../Utils/Persistence.h" #import "../Core/Sampler/PersistentState.h" @@ -44,9 +45,14 @@ namespace bugsnag { class BugsnagPerformanceImpl: public PhasedStartup { public: - BugsnagPerformanceImpl(std::shared_ptr reachability, - AppStateTracker *appStateTracker) noexcept; + BugsnagPerformanceImpl(std::shared_ptr mainModule, + BugsnagPerformanceNetworkRequestCallback networkRequestCallback) noexcept + : mainModule_(mainModule) + , networkRequestCallback_(networkRequestCallback) {} + virtual ~BugsnagPerformanceImpl(); + + void initialize() noexcept; void earlyConfigure(BSGEarlyConfiguration *config) noexcept; void earlySetup() noexcept; @@ -76,56 +82,29 @@ class BugsnagPerformanceImpl: public PhasedStartup { void onSpanStarted() noexcept; BugsnagPerformanceSpanContext *currentContext() noexcept { - return spanStackingHandler_->currentSpan(); + return mainModule_->getCoreModule()->getSpanStackingHandler()->currentSpan(); } - void setOnViewLoadSpanStarted(std::function onViewLoadSpanStarted) noexcept { - tracer_->setOnViewLoadSpanStarted(onViewLoadSpanStarted); + void setOnViewLoadSpanStarted(std::function __unused onViewLoadSpanStarted) noexcept { + // TODO +// tracer_->setOnViewLoadSpanStarted(onViewLoadSpanStarted); } - void didStartViewLoadSpan(NSString *name) noexcept { instrumentation_->didStartViewLoadSpan(name); } - void willCallMainFunction() noexcept { instrumentation_->willCallMainFunction(); } + void didStartViewLoadSpan(NSString *name) noexcept { mainModule_->getInstrumentationModule()->getInstrumentation()->didStartViewLoadSpan(name); } + void willCallMainFunction() noexcept { mainModule_->getInstrumentationModule()->getInstrumentation()->willCallMainFunction(); } id getSpanControls(BugsnagPerformanceSpanQuery *query) noexcept { - return [spanControlProvider_ getSpanControlsWithQuery:query]; + return [mainModule_->getPluginSupportModule()->getSpanControlProvider() getSpanControlsWithQuery:query]; } void loadingIndicatorWasAdded(BugsnagPerformanceLoadingIndicatorView *loadingViewIndicator) noexcept; private: - std::shared_ptr persistence_; - std::shared_ptr persistentState_; - std::shared_ptr spanStackingHandler_; - std::shared_ptr reachability_; - std::shared_ptr batch_; - std::shared_ptr spanAttributesProvider_; - std::shared_ptr sampler_; - std::shared_ptr networkHeaderInjector_; - FrameMetricsCollector *frameMetricsCollector_; - std::shared_ptr conditionTimeoutExecutor_; - BSGCompositeSpanControlProvider *spanControlProvider_; - BSGPrioritizedStore *spanStartCallbacks_; - BSGPrioritizedStore *spanEndCallbacks_; - std::shared_ptr plainSpanFactory_; - std::shared_ptr appStartupSpanFactory_; - std::shared_ptr viewLoadSpanFactory_; - std::shared_ptr networkSpanFactory_; - std::shared_ptr spanStore_; - std::shared_ptr spanLifecycleHandler_; - std::shared_ptr tracer_; - std::unique_ptr retryQueue_; - AppStateTracker *appStateTracker_; + std::shared_ptr mainModule_; NSMapTable *viewControllersToSpans_; - std::shared_ptr instrumentation_; - Worker *worker_; - std::shared_ptr deviceID_; - std::shared_ptr resourceAttributes_; BugsnagPerformanceNetworkRequestCallback networkRequestCallback_; - OtlpTraceEncoding traceEncoding_; BugsnagPerformanceConfiguration *configuration_; - BSGPluginManager *pluginManager_; - std::shared_ptr uploader_; std::mutex viewControllersToSpansMutex_; CFAbsoluteTime probabilityExpiry_{0}; CFAbsoluteTime pausePValueRequestsUntil_{0}; @@ -135,7 +114,6 @@ class BugsnagPerformanceImpl: public PhasedStartup { CFTimeInterval probabilityRequestsPauseForSeconds_{0}; uint64_t maxPackageContentLength_{1000000}; std::atomic isStarted_{false}; - bool hasCheckedAppStartDuration_{false}; // Tasks NSArray *buildInitialTasks() noexcept; @@ -144,9 +122,6 @@ class BugsnagPerformanceImpl: public PhasedStartup { bool sendRetriesTask() noexcept; bool sweepTracerTask() noexcept; - // Periodic Measurements - SystemInfoSampler systemInfoSampler_; - // Event reactions void onBatchFull() noexcept; void onConnectivityChanged(Reachability::Connectivity connectivity) noexcept; @@ -158,8 +133,6 @@ class BugsnagPerformanceImpl: public PhasedStartup { void onAppFinishedLaunching() noexcept; // Utility - void checkAppStartDuration() noexcept; - void wakeWorker() noexcept; void uploadPValueRequest() noexcept; void uploadPackage(std::unique_ptr package, bool isRetry) noexcept; NSMutableArray * @@ -170,7 +143,9 @@ class BugsnagPerformanceImpl: public PhasedStartup { public: // For testing void testing_setProbability(double probability) { onProbabilityChanged(probability); }; NSUInteger testing_getViewControllersToSpansCount() { return viewControllersToSpans_.count; }; - NSUInteger testing_getBatchCount() { return batch_->count(); }; + NSUInteger testing_getBatchCount() { + return mainModule_->getCoreModule()->getBatch()->count(); + }; }; } diff --git a/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.mm b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.mm index d2943248..164bd505 100644 --- a/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.mm +++ b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.mm @@ -13,7 +13,7 @@ #import "../Utils/Utils.h" #import "../Core/Attributes/SpanAttributesProvider.h" #import "../Core/SpanStack/SpanStackingHandler.h" -#import "../CrosstalkAPI/BugsnagPerformanceCrossTalkAPI.h" +#import "../CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h" #import "../Utils/Utils.h" #import "../Metrics/FrameMetrics/FrameMetricsCollector.h" #import "../Core/SpanConditions/ConditionTimeoutExecutor.h" @@ -22,124 +22,22 @@ using namespace bugsnag; -static constexpr double SAMPLER_INTERVAL_SECONDS = 1.0; -static constexpr double SAMPLER_HISTORY_SECONDS = 10 * 60; - -// App start spans will be thrown out if the early app start duration exceeds this. -static constexpr CFTimeInterval maxAppStartDuration = 2.0; - -// App start spans will be thrown out if the app gets backgrounded within this timeframe after starting. -static constexpr CFTimeInterval minTimeToBackgrounding = 2.0; - - -static NSString *getPersistenceDir() { - // Persistent data in bugsnag-performance can handle files disappearing, so put it in the caches dir. - return NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject; -} - -BugsnagPerformanceImpl::BugsnagPerformanceImpl(std::shared_ptr reachability, - AppStateTracker *appStateTracker) noexcept -: persistence_(std::make_shared(getPersistenceDir())) -, persistentState_(std::make_shared(persistence_)) -, spanStackingHandler_(std::make_shared()) -, reachability_(reachability) -, batch_(std::make_shared()) -, sampler_(std::make_shared()) -, spanAttributesProvider_(std::make_shared()) -, networkHeaderInjector_(std::make_shared(spanAttributesProvider_, spanStackingHandler_, sampler_)) -, frameMetricsCollector_([FrameMetricsCollector new]) -, conditionTimeoutExecutor_(std::make_shared()) -, spanControlProvider_([BSGCompositeSpanControlProvider new]) -, spanStartCallbacks_([BSGPrioritizedStore new]) -, spanEndCallbacks_([BSGPrioritizedStore new]) -, plainSpanFactory_(std::make_shared(sampler_, spanStackingHandler_, spanAttributesProvider_)) -, appStartupSpanFactory_(std::make_shared(plainSpanFactory_, spanAttributesProvider_)) -, viewLoadSpanFactory_(std::make_shared(plainSpanFactory_, spanAttributesProvider_)) -, networkSpanFactory_(std::make_shared(plainSpanFactory_, spanAttributesProvider_)) -, spanStore_(std::make_shared(spanStackingHandler_)) -, spanLifecycleHandler_(std::make_shared(sampler_, spanStore_, conditionTimeoutExecutor_, plainSpanFactory_, batch_, frameMetricsCollector_, spanStartCallbacks_, spanEndCallbacks_, ^{this->onSpanStarted();})) -, tracer_(std::make_shared(plainSpanFactory_, viewLoadSpanFactory_, networkSpanFactory_, spanLifecycleHandler_, spanStore_)) -, retryQueue_(std::make_unique([persistence_->bugsnagPerformanceDir() stringByAppendingPathComponent:@"retry-queue"])) -, appStateTracker_(appStateTracker) -, viewControllersToSpans_([NSMapTable mapTableWithKeyOptions:NSMapTableWeakMemory | NSMapTableObjectPointerPersonality - valueOptions:NSMapTableStrongMemory]) -, instrumentation_(std::make_shared(appStartupSpanFactory_, - viewLoadSpanFactory_, - networkSpanFactory_, - spanAttributesProvider_, - networkHeaderInjector_)) -, worker_([[Worker alloc] initWithInitialTasks:buildInitialTasks() recurringTasks:buildRecurringTasks()]) -, deviceID_(std::make_shared(persistence_)) -, resourceAttributes_(std::make_shared(deviceID_)) -, systemInfoSampler_(SAMPLER_INTERVAL_SECONDS, SAMPLER_HISTORY_SECONDS) -, networkRequestCallback_( - ^BugsnagPerformanceNetworkRequestInfo * _Nonnull(BugsnagPerformanceNetworkRequestInfo * _Nonnull info) { - return info; - } -) -{} - -BugsnagPerformanceImpl::~BugsnagPerformanceImpl() { - [workerTimer_ invalidate]; +void BugsnagPerformanceImpl::initialize() noexcept { + viewControllersToSpans_ = [NSMapTable mapTableWithKeyOptions:NSMapTableWeakMemory | NSMapTableObjectPointerPersonality + valueOptions:NSMapTableStrongMemory]; + mainModule_->setUp(); } void BugsnagPerformanceImpl::earlyConfigure(BSGEarlyConfiguration *config) noexcept { - BSGLogDebug(@"BugsnagPerformanceImpl::earlyConfigure()"); - // Do systemInfoSampler first so that any early spans will always have a bounding sample - systemInfoSampler_.earlyConfigure(config); - persistentState_->earlyConfigure(config); - traceEncoding_.earlyConfigure(config); - tracer_->earlyConfigure(config); - deviceID_->earlyConfigure(config); - resourceAttributes_->earlyConfigure(config); - networkHeaderInjector_->earlyConfigure(config); - retryQueue_->earlyConfigure(config); - batch_->earlyConfigure(config); - spanLifecycleHandler_->earlyConfigure(config); - instrumentation_->earlyConfigure(config); - [worker_ earlyConfigure:config]; - [frameMetricsCollector_ earlyConfigure:config]; - - // Configure these here because notifications may arrive - // before Bugsnag is started. - __block auto blockThis = this; - appStateTracker_.onAppFinishedLaunching = ^{ - blockThis->onAppFinishedLaunching(); - }; - - appStateTracker_.onTransitionToBackground = ^{ - blockThis->onAppEnteredBackground(); - }; - - appStateTracker_.onTransitionToForeground = ^{ - blockThis->onAppEnteredForeground(); - }; + mainModule_->earlyConfigure(config); } void BugsnagPerformanceImpl::earlySetup() noexcept { - BSGLogDebug(@"BugsnagPerformanceImpl::earlySetup()"); - systemInfoSampler_.earlySetup(); - persistentState_->earlySetup(); - traceEncoding_.earlySetup(); - tracer_->earlySetup(); - deviceID_->earlySetup(); - resourceAttributes_->earlySetup(); - networkHeaderInjector_->earlySetup(); - retryQueue_->earlySetup(); - batch_->earlySetup(); - spanLifecycleHandler_->earlySetup(); - instrumentation_->earlySetup(); - [worker_ earlySetup]; - [frameMetricsCollector_ earlySetup]; - - [BugsnagPerformanceCrossTalkAPI initializeWithSpanStackingHandler:spanStackingHandler_ tracer:tracer_]; + mainModule_->earlySetup(); } void BugsnagPerformanceImpl::configure(BugsnagPerformanceConfiguration *config) noexcept { BSGLogDebug(@"BugsnagPerformanceImpl::configure()"); - performWorkInterval_ = config.internal.performWorkInterval; - probabilityValueExpiresAfterSeconds_ = config.internal.probabilityValueExpiresAfterSeconds; - probabilityRequestsPauseForSeconds_ = config.internal.probabilityRequestsPauseForSeconds; maxPackageContentLength_ = config.internal.maxPackageContentLength; for(BugsnagPerformanceSpanStartCallback callback in config.onSpanStartCallbacks) { [spanStartCallbacks_ addObject:callback priority:BugsnagPerformancePriorityMedium]; @@ -154,56 +52,21 @@ onSpanEndCallbacks:spanEndCallbacks_]; NSMutableArray> *defaultPlugins = [NSMutableArray array]; - BugsnagPerformanceAppStartTypePlugin *appStartTypePlugin = - [BugsnagPerformanceAppStartTypePlugin new]; - [appStartTypePlugin setGetAppStartInstrumentationStateCallback:^AppStartupInstrumentationStateSnapshot * _Nullable { - return instrumentation_->getAppStartInstrumentationStateSnapshot(); - }]; + [defaultPlugins addObject:appStartTypePlugin]; [pluginManager_ installPlugins:defaultPlugins]; [pluginManager_ installPlugins:config.plugins]; - - auto networkRequestCallback = config.networkRequestCallback; - if (networkRequestCallback != nullptr) { - networkRequestCallback_ = (BugsnagPerformanceNetworkRequestCallback _Nonnull)networkRequestCallback; - } configuration_ = config; - systemInfoSampler_.configure(config); - persistentState_->configure(config); - traceEncoding_.configure(config); - deviceID_->configure(config); - resourceAttributes_->configure(config); - tracer_->configure(config); - networkHeaderInjector_->configure(config); - retryQueue_->configure(config); - batch_->configure(config); - spanLifecycleHandler_->configure(config); - instrumentation_->configure(config); - [worker_ configure:config]; - [frameMetricsCollector_ configure:config]; - [BugsnagPerformanceCrossTalkAPI.sharedInstance configure:config]; + mainModule_->configure(config); } void BugsnagPerformanceImpl::preStartSetup() noexcept { - BSGLogDebug(@"BugsnagPerformanceImpl::preStartSetup()"); - systemInfoSampler_.preStartSetup(); - persistentState_->preStartSetup(); - traceEncoding_.preStartSetup(); - tracer_->preStartSetup(); - deviceID_->preStartSetup(); - resourceAttributes_->preStartSetup(); - networkHeaderInjector_->preStartSetup(); - retryQueue_->preStartSetup(); - batch_->preStartSetup(); - spanLifecycleHandler_->preStartSetup(); - instrumentation_->preStartSetup(); - [worker_ preStartSetup]; + mainModule_->preStartSetup(); } void BugsnagPerformanceImpl::start() noexcept { - BSGLogDebug(@"BugsnagPerformanceImpl::start()"); bool expected = false; if (!isStarted_.compare_exchange_strong(expected, true)) { // compare_exchange_strong() returns true only if isStarted_ was exchanged (from false to true). @@ -212,330 +75,45 @@ return; } - // This is checked in two places: Bugsnag start, and NSApplicationDidFinishLaunchingNotification. - checkAppStartDuration(); - - /* Note: Be careful about initialization order! - * - * - Everything depends on persistence at some level - * - uploader depends on resourceAttributes and sampler - * - persistentState depends on persistence and will call on worker later - * - worker depends on uploader and sampler - * - batch depends on worker - * - tracer depends on sampler and batch - * - Reachability depends on worker - * - Instrumentation depends on tracer - */ - - __block auto blockThis = this; - - persistence_->start(); - - if (configuration_.internal.clearPersistenceOnStart) { - persistence_->clearPerformanceData(); - } - - persistentState_->start(); - deviceID_->start(); - traceEncoding_.start(); - spanLifecycleHandler_->start(); - - retryQueue_->setOnFilesystemError(^{ - blockThis->onFilesystemError(); - }); - retryQueue_->start(); - - uploader_ = std::make_shared(configuration_.endpoint, - configuration_.apiKey, - ^(double newProbability) { - if (configuration_.samplingProbability != nil) { - BSGLogTrace(@"BugsnagPerformanceImpl::newProbabilityCallback: configuration_.samplingProbability != nil"); - return; - } - blockThis->onProbabilityChanged(newProbability); - }); - - double samplingProbability = persistentState_->probability(); - if (configuration_.samplingProbability != nil) { - samplingProbability = [configuration_.samplingProbability doubleValue]; - } - sampler_->setProbability(samplingProbability); - - resourceAttributes_->start(); - networkHeaderInjector_->start(); - - systemInfoSampler_.start(); - - [worker_ start]; - [frameMetricsCollector_ start]; - - workerTimer_ = [NSTimer scheduledTimerWithTimeInterval:performWorkInterval_ - repeats:YES - block:^(__unused NSTimer * _Nonnull timer) { - blockThis->onWorkInterval(); - }]; - - auto initialWorkDelay = configuration_.internal.initialRecurringWorkDelay; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(initialWorkDelay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - wakeWorker(); - }); - - batch_->setBatchFullCallback(^{ - blockThis->onBatchFull(); - }); - - tracer_->start(); - - reachability_->addCallback(^(Reachability::Connectivity connectivity) { - blockThis->onConnectivityChanged(connectivity); - }); - - instrumentation_->start(); - - // Send the initial P value request early on. - uploadPValueRequest(); + mainModule_->start(); if (!configuration_.shouldSendReports) { BSGLogInfo("Note: No reports will be sent because releaseStage '%@' is not in enabledReleaseStages", configuration_.releaseStage); } } -#pragma mark Tasks - -NSArray *BugsnagPerformanceImpl::buildInitialTasks() noexcept { - __block auto blockThis = this; - return @[ - ^bool() { - [blockThis->pluginManager_ startPlugins]; - return true; - }, - ]; -} - -NSArray *BugsnagPerformanceImpl::buildRecurringTasks() noexcept { - __block auto blockThis = this; - return @[ - ^bool() { return blockThis->sendCurrentBatchTask(); }, - ^bool() { return blockThis->sendRetriesTask(); }, - ^bool() { return blockThis->sweepTracerTask(); }, - ]; -} - -NSMutableArray * -BugsnagPerformanceImpl::sendableSpans(NSMutableArray *spans) noexcept { - NSMutableArray *sendableSpans = [NSMutableArray arrayWithCapacity:spans.count]; - for (BugsnagPerformanceSpan *span in spans) { - if (span.state != SpanStateAborted && sampler_->sampled(span)) { - [sendableSpans addObject:span]; - } - } - return sendableSpans; -} - -bool BugsnagPerformanceImpl::shouldSampleCPU(BugsnagPerformanceSpan *span) noexcept { - if (span.metricsOptions.cpu == BSGTriStateUnset) { - return span.firstClass == BSGTriStateYes; - } - return span.metricsOptions.cpu == BSGTriStateYes; -} - -bool BugsnagPerformanceImpl::shouldSampleMemory(BugsnagPerformanceSpan *span) noexcept { - if (span.metricsOptions.memory == BSGTriStateUnset) { - return span.firstClass == BSGTriStateYes; - } - return span.metricsOptions.memory == BSGTriStateYes; -} - -bool BugsnagPerformanceImpl::sendCurrentBatchTask() noexcept { - BSGLogDebug(@"BugsnagPerformanceImpl::sendCurrentBatchTask()"); - auto origSpans = batch_->drain(false); -#ifndef __clang_analyzer__ - #pragma clang diagnostic ignored "-Wunused-variable" - size_t origSpansSize = origSpans.count; -#endif - auto spans = sendableSpans(origSpans); - if (spans.count == 0) { -#ifndef __clang_analyzer__ - BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Nothing to send. origSpans size = %zu", origSpansSize); -#endif - return false; - } - bool includeSamplingHeader = configuration_ == nil || configuration_.samplingProbability == nil; - - // Delay so that the sampler has time to fetch one more sample. - BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Delaying %f seconds (%lld ns) before getting system info", SAMPLER_INTERVAL_SECONDS + 0.5, (int64_t)((SAMPLER_INTERVAL_SECONDS + 0.5) * NSEC_PER_SEC)); - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((SAMPLER_INTERVAL_SECONDS + 0.5) * NSEC_PER_SEC)), - dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{ - BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Delayed %f seconds, now getting system info", SAMPLER_INTERVAL_SECONDS + 0.5); - for(BugsnagPerformanceSpan *span: spans) { - auto samples = systemInfoSampler_.samplesAroundTimePeriod(span.actuallyStartedAt, span.actuallyEndedAt); - BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): System info sample size = %zu", samples.size()); - if (samples.size() >= 2) { - if (shouldSampleCPU(span)) { - BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Getting CPU sample attributes for span %@", span.name); - [span forceMutate:^() { - [span internalSetMultipleAttributes:spanAttributesProvider_->cpuSampleAttributes(samples)]; - }]; - } - if (shouldSampleMemory(span)) { - BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Getting memory sample attributes for span %@", span.name); - [span forceMutate:^() { - [span internalSetMultipleAttributes:spanAttributesProvider_->memorySampleAttributes(samples)]; - }]; - } - } - } - -#ifndef __clang_analyzer__ - BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Sending %zu sampled spans (out of %zu)", origSpansSize, spans.count); -#endif - uploadPackage(traceEncoding_.buildUploadPackage(spans, resourceAttributes_->get(), includeSamplingHeader), false); - }); - - return true; -} - -bool BugsnagPerformanceImpl::sendRetriesTask() noexcept { - BSGLogDebug(@"BugsnagPerformanceImpl::sendRetriesTask()"); - retryQueue_->sweep(); - - auto retries = retryQueue_->list(); - if (retries.size() == 0) { - BSGLogTrace(@"BugsnagPerformanceImpl::sendRetriesTask(): No retries to send"); - return false; - } - - for (auto &×tamp: retries) { - auto retry = retryQueue_->get(timestamp); - if (retry != nullptr) { - uploadPackage(std::move(retry), true); - } - } - - // Retries never count as work, otherwise we'd loop endlessly on a network outage. - return false; -} - -bool BugsnagPerformanceImpl::sweepTracerTask() noexcept { - BSGLogDebug(@"BugsnagPerformanceImpl::sweepTracerTask()"); - spanStore_->sweep(); - // Never auto-repeat this task, even if work was done; it can wait. - return false; -} - #pragma mark Event Reactions -void BugsnagPerformanceImpl::onFilesystemError() noexcept { - persistence_->clearPerformanceData(); -} - -void BugsnagPerformanceImpl::onBatchFull() noexcept { - BSGLogDebug(@"BugsnagPerformanceImpl::onBatchFull()"); - wakeWorker(); -} - -void BugsnagPerformanceImpl::onConnectivityChanged(Reachability::Connectivity connectivity) noexcept { - BSGLogDebug(@"BugsnagPerformanceImpl::onConnectivityChanged(): new reachability = %d", connectivity); - switch (connectivity) { - case Reachability::Cellular: case Reachability::Wifi: - wakeWorker(); - break; - case Reachability::Unknown: case Reachability::None: - // Don't care - break; - } -} - -void BugsnagPerformanceImpl::onProbabilityChanged(double newProbability) noexcept { - BSGLogDebug(@"BugsnagPerformanceImpl::onProbabilityChanged(): new probability = %f, expiring after %f seconds", newProbability, probabilityValueExpiresAfterSeconds_); - probabilityExpiry_ = CFAbsoluteTimeGetCurrent() + probabilityValueExpiresAfterSeconds_; - sampler_->setProbability(newProbability); - persistentState_->setProbability(newProbability); -} - -void BugsnagPerformanceImpl::onSpanStarted() noexcept { - // If a span starts before we've started Bugsnag, there won't be an uploader yet. - if (uploader_ != nullptr) { - if (CFAbsoluteTimeGetCurrent() > probabilityExpiry_) { - uploadPValueRequest(); - } - } -} - -void BugsnagPerformanceImpl::loadingIndicatorWasAdded(BugsnagPerformanceLoadingIndicatorView *loadingViewIndicator) noexcept { - this->instrumentation_->loadingIndicatorWasAdded(loadingViewIndicator); -} - -void BugsnagPerformanceImpl::onWorkInterval() noexcept { - BSGLogTrace(@"BugsnagPerformanceImpl::onWorkInterval()"); - batch_->allowDrain(); - wakeWorker(); -} +// TODO: Replace with worker task +//void BugsnagPerformanceImpl::onSpanStarted() noexcept { +// // If a span starts before we've started Bugsnag, there won't be an uploader yet. +// if (uploader_ != nullptr) { +// if (CFAbsoluteTimeGetCurrent() > probabilityExpiry_) { +// uploadPValueRequest(); +// } +// } +//} -void BugsnagPerformanceImpl::onAppFinishedLaunching() noexcept { - BSGLogDebug(@"BugsnagPerformanceImpl::onAppFinishedLaunching()"); - // We run this without checking isStarted (in case there's notification - // timing jank and we get the notification before we've started). - checkAppStartDuration(); -} - -void BugsnagPerformanceImpl::onAppEnteredBackground() noexcept { - BSGLogDebug(@"BugsnagPerformanceImpl::onAppEnteredBackground()"); - [frameMetricsCollector_ onAppEnteredBackground]; - - // We run this BEFORE checking isStarted (in case there's notification - // timing jank and we get the notification before we've started). - if (instrumentation_->timeSinceAppFirstBecameActive() < minTimeToBackgrounding) { - // If we get backgrounded too quickly after app start, throw out - // all app start spans even if they've completed. - // Sometimes the jank between backgrounding/foregrounding events - // can cause the spans to close very late, so we play it safe. - instrumentation_->abortAppStartupSpans(); - } - - spanLifecycleHandler_->onAppEnteredBackground(); -} - -void BugsnagPerformanceImpl::onAppEnteredForeground() noexcept { - [frameMetricsCollector_ onAppEnteredForeground]; - if (!isStarted_) { - BSGLogDebug(@"BugsnagPerformanceImpl::onAppEnteredForeground(), but not started yet"); - return; - } - BSGLogDebug(@"BugsnagPerformanceImpl::onAppEnteredForeground()"); - - batch_->allowDrain(); - wakeWorker(); +void +BugsnagPerformanceImpl::loadingIndicatorWasAdded(BugsnagPerformanceLoadingIndicatorView *loadingViewIndicator) noexcept { + mainModule_->getInstrumentationModule()->loadingIndicatorWasAdded(loadingViewIndicator); } #pragma mark Utility -void BugsnagPerformanceImpl::wakeWorker() noexcept { - BSGLogTrace(@"BugsnagPerformanceImpl::wakeWorker()"); - [worker_ wake]; -} - -void BugsnagPerformanceImpl::checkAppStartDuration() noexcept { - if (!hasCheckedAppStartDuration_) { - hasCheckedAppStartDuration_ = true; - if (instrumentation_->appStartDuration() > maxAppStartDuration) { - instrumentation_->abortAppStartupSpans(); - } - } -} - -void BugsnagPerformanceImpl::uploadPValueRequest() noexcept { - if (!configuration_.shouldSendReports || configuration_.samplingProbability != nil) { - return; - } - auto currentTime = CFAbsoluteTimeGetCurrent(); - if (currentTime > pausePValueRequestsUntil_) { - // Pause P-value requests so that we don't flood the server on every span start - pausePValueRequestsUntil_ = currentTime + probabilityRequestsPauseForSeconds_; - uploader_->upload(*traceEncoding_.buildPValueRequestPackage(), nil); - } -} +// TODO: Initial task +//void BugsnagPerformanceImpl::uploadPValueRequest() noexcept { +// if (!configuration_.shouldSendReports || configuration_.samplingProbability != nil) { +// return; +// } +// auto currentTime = CFAbsoluteTimeGetCurrent(); +// if (currentTime > pausePValueRequestsUntil_) { +// // Pause P-value requests so that we don't flood the server on every span start +// pausePValueRequestsUntil_ = currentTime + probabilityRequestsPauseForSeconds_; +// uploader_->upload(*traceEncoding_.buildPValueRequestPackage(), nil); +// } +//} void BugsnagPerformanceImpl::uploadPackage(std::unique_ptr package, bool isRetry) noexcept { BSGLogDebug(@"BugsnagPerformanceImpl::uploadPackage(package, isRetry:%s)", isRetry ? "yes" : "no"); @@ -586,53 +164,66 @@ #pragma mark Spans -BugsnagPerformanceSpan *BugsnagPerformanceImpl::startCustomSpan(NSString *name) noexcept { +BugsnagPerformanceSpan * +BugsnagPerformanceImpl::startCustomSpan(NSString *name) noexcept { SpanOptions options; - auto span = tracer_->startCustomSpan(name, options); - [span internalSetMultipleAttributes:spanAttributesProvider_->customSpanAttributes()]; - return span; + auto attributes = mainModule_->getCoreModule()->getSpanAttributesProvider()->customSpanAttributes(); + return mainModule_->getCoreModule()->getPlainSpanFactory()->startSpan(name, options, BSGTriStateYes, attributes, @[]); } -BugsnagPerformanceSpan *BugsnagPerformanceImpl::startCustomSpan(NSString *name, BugsnagPerformanceSpanOptions *optionsIn) noexcept { +BugsnagPerformanceSpan * +BugsnagPerformanceImpl::startCustomSpan(NSString *name, BugsnagPerformanceSpanOptions *optionsIn) noexcept { auto options = SpanOptions(optionsIn); - auto span = tracer_->startCustomSpan(name, options); - [span internalSetMultipleAttributes:spanAttributesProvider_->customSpanAttributes()]; - return span; + auto attributes = mainModule_->getCoreModule()->getSpanAttributesProvider()->customSpanAttributes(); + return mainModule_->getCoreModule()->getPlainSpanFactory()->startSpan(name, options, BSGTriStateYes, attributes, @[]); } -BugsnagPerformanceSpan *BugsnagPerformanceImpl::startViewLoadSpan(NSString *className, BugsnagPerformanceViewType viewType) noexcept { +BugsnagPerformanceSpan * +BugsnagPerformanceImpl::startViewLoadSpan(NSString *className, BugsnagPerformanceViewType viewType) noexcept { SpanOptions options; - auto span = tracer_->startViewLoadSpan(viewType, className, options); - [span internalSetMultipleAttributes:spanAttributesProvider_->viewLoadSpanAttributes(className, viewType)]; - return span; + return mainModule_->getCoreModule()->getViewLoadSpanFactory()->startViewLoadSpan(viewType, + className, + nil, + options, + @{}); } -BugsnagPerformanceSpan *BugsnagPerformanceImpl::startViewLoadSpan(NSString *className, BugsnagPerformanceViewType viewType, BugsnagPerformanceSpanOptions *optionsIn) noexcept { +BugsnagPerformanceSpan * +BugsnagPerformanceImpl::startViewLoadSpan(NSString *className, BugsnagPerformanceViewType viewType, BugsnagPerformanceSpanOptions *optionsIn) noexcept { auto options = SpanOptions(optionsIn); - auto span = tracer_->startViewLoadSpan(viewType, className, options); - [span internalSetMultipleAttributes:spanAttributesProvider_->viewLoadSpanAttributes(className, viewType)]; - return span; + return mainModule_->getCoreModule()->getViewLoadSpanFactory()->startViewLoadSpan(viewType, + className, + nil, + options, + @{}); } -void BugsnagPerformanceImpl::startViewLoadSpan(UIViewController *controller, BugsnagPerformanceSpanOptions *optionsIn) noexcept { +void +BugsnagPerformanceImpl::startViewLoadSpan(UIViewController *controller, BugsnagPerformanceSpanOptions *optionsIn) noexcept { auto options = SpanOptions(optionsIn); auto viewType = BugsnagPerformanceViewTypeUIKit; auto className = [NSString stringWithUTF8String:object_getClassName(controller)]; - auto span = tracer_->startViewLoadSpan(viewType, className, options); - [span internalSetMultipleAttributes:spanAttributesProvider_->viewLoadSpanAttributes(className, viewType)]; - + auto span = mainModule_->getCoreModule()->getViewLoadSpanFactory()->startViewLoadSpan(viewType, + className, + nil, + options, + @{}); std::lock_guard guard(viewControllersToSpansMutex_); [viewControllersToSpans_ setObject:span forKey:controller]; } -BugsnagPerformanceSpan *BugsnagPerformanceImpl::startViewLoadPhaseSpan(NSString *className, NSString *phase, - BugsnagPerformanceSpanContext *parentContext) noexcept { - auto span = tracer_->startViewLoadPhaseSpan(className, phase, parentContext, @[]); - [span internalSetMultipleAttributes:spanAttributesProvider_->viewLoadPhaseSpanAttributes(className, phase)]; - return span; +BugsnagPerformanceSpan * +BugsnagPerformanceImpl::startViewLoadPhaseSpan(NSString *className, + NSString *phase, + BugsnagPerformanceSpanContext *parentContext) noexcept { + return mainModule_->getCoreModule()->getViewLoadSpanFactory()->startViewLoadPhaseSpan(className, + parentContext, + phase, + @[]); } -void BugsnagPerformanceImpl::endViewLoadSpan(UIViewController *controller, NSDate *endTime) noexcept { +void +BugsnagPerformanceImpl::endViewLoadSpan(UIViewController *controller, NSDate *endTime) noexcept { /* Although NSMapTable supports weak keys, zeroed keys are not actually removed * until certain internal operations occur (such as the map resizing itself). * http://cocoamine.net/blog/2013/12/13/nsmaptable-and-zeroing-weak-references/ @@ -652,27 +243,5 @@ } void BugsnagPerformanceImpl::reportNetworkSpan(NSURLSessionTask *task, NSURLSessionTaskMetrics *metrics) noexcept { - BugsnagPerformanceSpan *span = nil; - - NSError *errorFromGetRequest = nil; - NSURLRequest *req = getTaskRequest(task, &errorFromGetRequest); - BSGLogDebug(@"BugsnagPerformanceImpl::reportNetworkSpan() for %@", req.URL); - - auto info = [BugsnagPerformanceNetworkRequestInfo new]; - info.url = req.URL; - bool userVetoedTracing = false; - if (info.url != nil) { - info = networkRequestCallback_(info); - userVetoedTracing = info.url == nil; - } - if (!userVetoedTracing) { - auto interval = metrics.taskInterval; - auto name = req.HTTPMethod; - SpanOptions options; - options.makeCurrentContext = false; - options.startTime = dateToAbsoluteTime(interval.startDate); - span = tracer_->startNetworkSpan(name, options); - [span internalSetMultipleAttributes:spanAttributesProvider_->networkSpanAttributes(info.url, task, metrics, errorFromGetRequest)]; - [span endWithEndTime:interval.endDate]; - } + mainModule_->getCoreModule()->getNetworkSpanReporter()->reportNetworkSpan(task, metrics); } diff --git a/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.h b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.h index b9ec4724..93983a8a 100644 --- a/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.h +++ b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.h @@ -23,8 +23,6 @@ class BugsnagPerformanceLibrary: private PhasedStartup { static void startLibrary() noexcept; static std::shared_ptr getBugsnagPerformanceImpl() noexcept; - static std::shared_ptr getReachability() noexcept; - static AppStateTracker *getAppStateTracker() noexcept; private: // Use GNU constructor attribute to auto-call functions before main() is called. // https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html @@ -43,10 +41,9 @@ class BugsnagPerformanceLibrary: private PhasedStartup { void configure(BugsnagPerformanceConfiguration *config) noexcept; void preStartSetup() noexcept; void start() noexcept; + void initialize() noexcept; BugsnagPerformanceLibrary(); - AppStateTracker *appStateTracker_; - std::shared_ptr reachability_; std::shared_ptr bugsnagPerformanceImpl_; }; diff --git a/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.mm b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.mm index 4d9e28ed..c1833300 100644 --- a/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.mm +++ b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.mm @@ -18,6 +18,7 @@ // (via calledAsEarlyAsPossible), which is a single-thread environment. if (!instance_do_not_access_directly) { instance_do_not_access_directly = std::shared_ptr(new BugsnagPerformanceLibrary); + instance_do_not_access_directly->initialize(); } return *instance_do_not_access_directly; @@ -78,11 +79,11 @@ } } -BugsnagPerformanceLibrary::BugsnagPerformanceLibrary() -: appStateTracker_([[AppStateTracker alloc] init]) -, reachability_(std::make_shared()) -, bugsnagPerformanceImpl_(std::make_shared(reachability_, appStateTracker_)) -{} +//BugsnagPerformanceLibrary::BugsnagPerformanceLibrary() +//: appStateTracker_([[AppStateTracker alloc] init]) +//, reachability_(std::make_shared()) +//, bugsnagPerformanceImpl_() +//{} void BugsnagPerformanceLibrary::earlyConfigure(BSGEarlyConfiguration *config) noexcept { BSGLogDebug(@"BugsnagPerformanceLibrary::configureLibrary"); @@ -117,10 +118,10 @@ return sharedInstance().bugsnagPerformanceImpl_; } -std::shared_ptr BugsnagPerformanceLibrary::getReachability() noexcept { - return sharedInstance().reachability_; -} - -AppStateTracker *BugsnagPerformanceLibrary::getAppStateTracker() noexcept { - return sharedInstance().appStateTracker_; +void BugsnagPerformanceLibrary::initialize() noexcept { + bugsnagPerformanceImpl_ = std::make_shared(std::make_shared(), + ^BugsnagPerformanceNetworkRequestInfo * _Nonnull(BugsnagPerformanceNetworkRequestInfo * _Nonnull info) { + return info; + }); + bugsnagPerformanceImpl_->initialize(); } diff --git a/Sources/BugsnagPerformance/Private/Main/MainModule.h b/Sources/BugsnagPerformance/Private/Main/MainModule.h new file mode 100644 index 00000000..bd995849 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Main/MainModule.h @@ -0,0 +1,67 @@ +// +// MainModule.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 16/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#pragma once + +#import "../Core/Module.h" +#import "../Core/AppLifecycleListener.h" +#import "../Core/CoreModule.h" +#import "../CrossTalkAPI/CrossTalkAPIModule.h" +#import "../Instrumentation/InstrumentationModule.h" +#import "../Utils/UtilsModule.h" +#import "../Metrics/MetricsModule.h" +#import "../Plugins/PluginsModule.h" +#import "../PluginSupport/PluginSupportModule.h" +#import "../Upload/UploadModule.h" + +#import + +namespace bugsnag { +class MainModule: public Module, public AppLifecycleListener { +public: + MainModule() {}; + + ~MainModule() {}; + + void earlyConfigure(BSGEarlyConfiguration *config) noexcept; + void earlySetup() noexcept; + void configure(BugsnagPerformanceConfiguration *config) noexcept; + void preStartSetup() noexcept; + void start() noexcept; + + void setUp() noexcept; + + void onAppFinishedLaunching() noexcept; + void onAppEnteredBackground() noexcept; + void onAppEnteredForeground() noexcept; + + std::shared_ptr getCoreModule() noexcept { return coreModule_; } + std::shared_ptr getCrossTalkAPIModule() noexcept { return crossTalkAPIModule_; } + std::shared_ptr getUtilsModule() noexcept { return utilsModule_; } + std::shared_ptr getInstrumentationModule() noexcept { return instrumentationModule_; } + std::shared_ptr getMetricsModule() noexcept { return metricsModule_; } + std::shared_ptr getPluginsModule() noexcept { return pluginsModule_; } + std::shared_ptr getPluginSupportModule() noexcept { return pluginSupportModule_; } + std::shared_ptr getUploadModule() noexcept { return uploadModule_; } + +private: + // Components + std::shared_ptr coreModule_; + std::shared_ptr crossTalkAPIModule_; + std::shared_ptr utilsModule_; + std::shared_ptr instrumentationModule_; + std::shared_ptr metricsModule_; + std::shared_ptr pluginsModule_; + std::shared_ptr pluginSupportModule_; + std::shared_ptr uploadModule_; + + void initializeModules() noexcept; + NSArray *buildInitialTasks() noexcept; + NSArray *buildRecurringTasks() noexcept; +}; +} diff --git a/Sources/BugsnagPerformance/Private/Main/MainModule.mm b/Sources/BugsnagPerformance/Private/Main/MainModule.mm new file mode 100644 index 00000000..e45b3cfb --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Main/MainModule.mm @@ -0,0 +1,284 @@ +// +// MainModule.mm +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 16/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#import "MainModule.h" + +using namespace bugsnag; + +#pragma mark PhasedStartup + +void +MainModule::earlyConfigure(BSGEarlyConfiguration *config) noexcept { + // Do MetricsModule first so that any early spans will always have a bounding sample + metricsModule_->earlyConfigure(config); + utilsModule_->earlyConfigure(config); + coreModule_->earlyConfigure(config); + instrumentationModule_->earlyConfigure(config); + uploadModule_->earlyConfigure(config); + pluginSupportModule_->earlyConfigure(config); + pluginsModule_->earlyConfigure(config); + crossTalkAPIModule_->earlyConfigure(config); + + // Configure these here because notifications may arrive + // before Bugsnag is started. + __block auto blockThis = this; + utilsModule_->getAppStateTracker().onAppFinishedLaunching = ^{ + blockThis->onAppFinishedLaunching(); + }; + + utilsModule_->getAppStateTracker().onTransitionToBackground = ^{ + blockThis->onAppEnteredBackground(); + }; + + utilsModule_->getAppStateTracker().onTransitionToForeground = ^{ + blockThis->onAppEnteredForeground(); + }; +} + +void +MainModule::earlySetup() noexcept { + metricsModule_->earlySetup(); + utilsModule_->earlySetup(); + coreModule_->earlySetup(); + instrumentationModule_->earlySetup(); + uploadModule_->earlySetup(); + pluginSupportModule_->earlySetup(); + pluginsModule_->earlySetup(); + crossTalkAPIModule_->earlySetup(); +} + +void +MainModule::configure(BugsnagPerformanceConfiguration *config) noexcept { + metricsModule_->configure(config); + utilsModule_->configure(config); + coreModule_->configure(config); + instrumentationModule_->configure(config); + uploadModule_->configure(config); + pluginSupportModule_->configure(config); + pluginsModule_->configure(config); + crossTalkAPIModule_->configure(config); +} + +void +MainModule::preStartSetup() noexcept { + metricsModule_->preStartSetup(); + utilsModule_->preStartSetup(); + coreModule_->preStartSetup(); + instrumentationModule_->preStartSetup(); + uploadModule_->preStartSetup(); + pluginSupportModule_->preStartSetup(); + pluginsModule_->preStartSetup(); + crossTalkAPIModule_->preStartSetup(); +} + +void +MainModule::start() noexcept { + metricsModule_->start(); + utilsModule_->start(); + coreModule_->start(); + instrumentationModule_->start(); + uploadModule_->start(); + pluginSupportModule_->start(); + pluginsModule_->start(); + crossTalkAPIModule_->start(); +} + +#pragma mark Module + +void +MainModule::setUp() noexcept { + initializeModules(); +} + +#pragma mark AppLifecycleListener + +void +MainModule::onAppFinishedLaunching() noexcept { + coreModule_->onAppFinishedLaunching(); + instrumentationModule_->onAppFinishedLaunching(); + metricsModule_->onAppFinishedLaunching(); +} + +void +MainModule::onAppEnteredBackground() noexcept { + coreModule_->onAppEnteredBackground(); + instrumentationModule_->onAppEnteredBackground(); + metricsModule_->onAppEnteredBackground(); +} + +void +MainModule::onAppEnteredForeground() noexcept { + coreModule_->onAppEnteredForeground(); + instrumentationModule_->onAppEnteredForeground(); + metricsModule_->onAppEnteredForeground(); +} + +#pragma mark Private + +void +MainModule::initializeModules() noexcept { + utilsModule_ = std::make_shared(); + utilsModule_->setUp(); + coreModule_ = std::make_shared(utilsModule_->getAppStateTracker(), + utilsModule_->getReachability(), + utilsModule_->getPersistence(), + utilsModule_->getDeviceID()); + coreModule_->initialize(buildInitialTasks(), buildRecurringTasks()); // TODO + coreModule_->setUp(); + instrumentationModule_ = std::make_shared(coreModule_->getAppStartupSpanFactory(), + coreModule_->getViewLoadSpanFactory(), + coreModule_->getNetworkSpanFactory(), + coreModule_->getSpanAttributesProvider(), + coreModule_->getSpanStackingHandler(), + coreModule_->getSampler()); + metricsModule_ = std::make_shared(); + metricsModule_->setUp(); + + crossTalkAPIModule_ = std::make_shared(coreModule_->getPlainSpanFactory(), + coreModule_->getSpanStackingHandler()); + crossTalkAPIModule_->setUp(); + + pluginsModule_ = std::make_shared(instrumentationModule_->getInstrumentation()); + pluginsModule_->setUp(); + + pluginSupportModule_ = std::make_shared(); + pluginSupportModule_->setUp(); + + uploadModule_ = std::make_shared(utilsModule_->getPersistence()); + uploadModule_->setUp(); + + utilsModule_->initializeComponentsCallbacks(coreModule_->getUpdateConnectivityTask()); + uploadModule_->initializeComponentsCallbacks(utilsModule_->getClearPersistentDataTask(), + coreModule_->getUpdateProbabilityTask()); + coreModule_->initializeComponentsCallbacks(metricsModule_->getCurrentFrameMetricsSnapshotTask(), + instrumentationModule_->getAppStartupStateSnapshotTask(), + instrumentationModule_->getHandleViewLoadSpanStartedTask()); +} + +NSArray * +MainModule::buildInitialTasks() noexcept { +// __block auto blockThis = this; + return @[ +// ^bool() { +// [blockThis->pluginSupportModule_->getPluginManager() startPlugins]; +// return true; +// }, + ]; +} + +NSArray * +MainModule::buildRecurringTasks() noexcept { +// __block auto blockThis = this; + return @[ +// ^bool() { return blockThis->sendCurrentBatchTask(); }, +// ^bool() { return blockThis->sendRetriesTask(); }, +// ^bool() { return blockThis->sweepTracerTask(); }, + ]; +} +// +//NSMutableArray * +//BugsnagPerformanceImpl::sendableSpans(NSMutableArray *spans) noexcept { +// NSMutableArray *sendableSpans = [NSMutableArray arrayWithCapacity:spans.count]; +// for (BugsnagPerformanceSpan *span in spans) { +// if (span.state != SpanStateAborted && sampler_->sampled(span)) { +// [sendableSpans addObject:span]; +// } +// } +// return sendableSpans; +//} +// +//bool BugsnagPerformanceImpl::shouldSampleCPU(BugsnagPerformanceSpan *span) noexcept { +// if (span.metricsOptions.cpu == BSGTriStateUnset) { +// return span.firstClass == BSGTriStateYes; +// } +// return span.metricsOptions.cpu == BSGTriStateYes; +//} +// +//bool BugsnagPerformanceImpl::shouldSampleMemory(BugsnagPerformanceSpan *span) noexcept { +// if (span.metricsOptions.memory == BSGTriStateUnset) { +// return span.firstClass == BSGTriStateYes; +// } +// return span.metricsOptions.memory == BSGTriStateYes; +//} +// +//bool BugsnagPerformanceImpl::sendCurrentBatchTask() noexcept { +// BSGLogDebug(@"BugsnagPerformanceImpl::sendCurrentBatchTask()"); +// auto origSpans = batch_->drain(false); +//#ifndef __clang_analyzer__ +// #pragma clang diagnostic ignored "-Wunused-variable" +// size_t origSpansSize = origSpans.count; +//#endif +// auto spans = sendableSpans(origSpans); +// if (spans.count == 0) { +//#ifndef __clang_analyzer__ +// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Nothing to send. origSpans size = %zu", origSpansSize); +//#endif +// return false; +// } +// bool includeSamplingHeader = configuration_ == nil || configuration_.samplingProbability == nil; +// +// // Delay so that the sampler has time to fetch one more sample. +// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Delaying %f seconds (%lld ns) before getting system info", SAMPLER_INTERVAL_SECONDS + 0.5, (int64_t)((SAMPLER_INTERVAL_SECONDS + 0.5) * NSEC_PER_SEC)); +// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((SAMPLER_INTERVAL_SECONDS + 0.5) * NSEC_PER_SEC)), +// dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{ +// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Delayed %f seconds, now getting system info", SAMPLER_INTERVAL_SECONDS + 0.5); +// for(BugsnagPerformanceSpan *span: spans) { +// auto samples = systemInfoSampler_.samplesAroundTimePeriod(span.actuallyStartedAt, span.actuallyEndedAt); +// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): System info sample size = %zu", samples.size()); +// if (samples.size() >= 2) { +// if (shouldSampleCPU(span)) { +// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Getting CPU sample attributes for span %@", span.name); +// [span forceMutate:^() { +// [span internalSetMultipleAttributes:spanAttributesProvider_->cpuSampleAttributes(samples)]; +// }]; +// } +// if (shouldSampleMemory(span)) { +// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Getting memory sample attributes for span %@", span.name); +// [span forceMutate:^() { +// [span internalSetMultipleAttributes:spanAttributesProvider_->memorySampleAttributes(samples)]; +// }]; +// } +// } +// } +// +//#ifndef __clang_analyzer__ +// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Sending %zu sampled spans (out of %zu)", origSpansSize, spans.count); +//#endif +// uploadPackage(traceEncoding_.buildUploadPackage(spans, resourceAttributes_->get(), includeSamplingHeader), false); +// }); +// +// return true; +//} +// +//bool BugsnagPerformanceImpl::sendRetriesTask() noexcept { +// BSGLogDebug(@"BugsnagPerformanceImpl::sendRetriesTask()"); +// retryQueue_->sweep(); +// +// auto retries = retryQueue_->list(); +// if (retries.size() == 0) { +// BSGLogTrace(@"BugsnagPerformanceImpl::sendRetriesTask(): No retries to send"); +// return false; +// } +// +// for (auto &×tamp: retries) { +// auto retry = retryQueue_->get(timestamp); +// if (retry != nullptr) { +// uploadPackage(std::move(retry), true); +// } +// } +// +// // Retries never count as work, otherwise we'd loop endlessly on a network outage. +// return false; +//} +// +//bool BugsnagPerformanceImpl::sweepTracerTask() noexcept { +// BSGLogDebug(@"BugsnagPerformanceImpl::sweepTracerTask()"); +// spanStore_->sweep(); +// // Never auto-repeat this task, even if work was done; it can wait. +// return false; +//} diff --git a/Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrameMetricsSnapshot.h b/Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrameMetricsSnapshot.h index 1547b6bc..bff3c75a 100644 --- a/Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrameMetricsSnapshot.h +++ b/Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrameMetricsSnapshot.h @@ -10,6 +10,7 @@ #import "../../Core/PhasedStartup.h" #import "FrozenFrameData.h" + @interface FrameMetricsSnapshot: NSObject @property(nonatomic, readwrite) uint64_t totalFrames; @@ -23,3 +24,5 @@ @end +typedef FrameMetricsSnapshot *(^GetCurrentFrameMetricsSnapshot)(); + diff --git a/Sources/BugsnagPerformance/Private/Metrics/MetricsModule.h b/Sources/BugsnagPerformance/Private/Metrics/MetricsModule.h new file mode 100644 index 00000000..9137789f --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Metrics/MetricsModule.h @@ -0,0 +1,53 @@ +// +// MetricsModule.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 16/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#pragma once + +#import "../Core/Module.h" +#import "../Core/AppLifecycleListener.h" +#import "FrameMetrics/FrameMetricsCollector.h" +#import "SystemMetrics/SystemInfoSampler.h" + +#import + +namespace bugsnag { +class MetricsModule: public Module, public AppLifecycleListener { +public: + MetricsModule() {}; + + ~MetricsModule() {}; + + void earlyConfigure(BSGEarlyConfiguration *config) noexcept; + void earlySetup() noexcept; + void configure(BugsnagPerformanceConfiguration *config) noexcept; + void preStartSetup() noexcept; + void start() noexcept; + + void setUp() noexcept; + + void onAppFinishedLaunching() noexcept {} + void onAppEnteredBackground() noexcept; + void onAppEnteredForeground() noexcept; + + // Tasks + + GetCurrentFrameMetricsSnapshot getCurrentFrameMetricsSnapshotTask() noexcept; + + + // Components access + + FrameMetricsCollector *getFrameMetricsCollector() noexcept { return frameMetricsCollector_; } + std::shared_ptr getSystemInfoSampler() noexcept { return systemInfoSampler_; } + +private: + + // Components + std::shared_ptr systemInfoSampler_; + FrameMetricsCollector *frameMetricsCollector_; +}; +} diff --git a/Sources/BugsnagPerformance/Private/Metrics/MetricsModule.mm b/Sources/BugsnagPerformance/Private/Metrics/MetricsModule.mm new file mode 100644 index 00000000..fd11cb34 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Metrics/MetricsModule.mm @@ -0,0 +1,78 @@ +// +// MetricsModule.mm +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 16/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#import "MetricsModule.h" + +using namespace bugsnag; + +static constexpr double SAMPLER_INTERVAL_SECONDS = 1.0; +static constexpr double SAMPLER_HISTORY_SECONDS = 10 * 60; + +#pragma mark PhasedStartup + +void +MetricsModule::earlyConfigure(BSGEarlyConfiguration *config) noexcept { + systemInfoSampler_->earlyConfigure(config); + [frameMetricsCollector_ earlyConfigure:config]; +} + +void +MetricsModule::earlySetup() noexcept { + systemInfoSampler_->earlySetup(); + [frameMetricsCollector_ earlySetup]; +} + +void +MetricsModule::configure(BugsnagPerformanceConfiguration *config) noexcept { + systemInfoSampler_->configure(config); + [frameMetricsCollector_ configure:config]; +} + +void +MetricsModule::preStartSetup() noexcept { + systemInfoSampler_->preStartSetup(); + [frameMetricsCollector_ preStartSetup]; +} + +void +MetricsModule::start() noexcept { + systemInfoSampler_->start(); + [frameMetricsCollector_ start]; +} + +#pragma mark Module + +void MetricsModule::setUp() noexcept { + frameMetricsCollector_ = [FrameMetricsCollector new]; + systemInfoSampler_ = std::make_shared(SAMPLER_INTERVAL_SECONDS, SAMPLER_HISTORY_SECONDS); +} + +#pragma mark Tasks + +GetCurrentFrameMetricsSnapshot +MetricsModule::getCurrentFrameMetricsSnapshotTask() noexcept { + __block auto blockThis = this; + return ^FrameMetricsSnapshot *{ + if (blockThis->frameMetricsCollector_ == nullptr) { + return nil; + } + return [blockThis->frameMetricsCollector_ currentSnapshot]; + }; +} + +#pragma mark AppLifecycleListener + +void +MetricsModule::onAppEnteredBackground() noexcept { + [frameMetricsCollector_ onAppEnteredBackground]; +} + +void +MetricsModule::onAppEnteredForeground() noexcept { + [frameMetricsCollector_ onAppEnteredForeground]; +} diff --git a/Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformancePluginSupport.h b/Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformancePluginSupport.h deleted file mode 100644 index a1d910c4..00000000 --- a/Sources/BugsnagPerformance/Private/PluginSupport/BugsnagPerformancePluginSupport.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// BugsnagPerformancePluginSupport.h -// BugsnagPerformance -// -// Created by Robert Bartoszewski on 16/10/2025. -// Copyright © 2025 Bugsnag. All rights reserved. -// - -#pragma once - -// Core Plugin Support -#import "BugsnagPerformancePluginContext+Private.h" -#import "BugsnagPerformanceSpanControlProvider+Private.h" - -// Plugin Manager -#import "PluginManager/BSGPluginManager.h" - -// Span Control -#import "SpanControl/BSGCompositeSpanControlProvider.h" diff --git a/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.h b/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.h index 5b1ab165..00f38fc9 100644 --- a/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.h +++ b/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.h @@ -12,16 +12,14 @@ #import #import #import "../../Core/BSGPrioritizedStore.h" +#import "../../Core/PhasedStartup.h" #import "../SpanControl/BSGCompositeSpanControlProvider.h" NS_ASSUME_NONNULL_BEGIN -@interface BSGPluginManager : NSObject +@interface BSGPluginManager : NSObject -- (instancetype)initWithConfiguration:(BugsnagPerformanceConfiguration *)configuration - compositeProvider:(BSGCompositeSpanControlProvider *)compositeProvider - onSpanStartCallbacks:(BSGPrioritizedStore *)onSpanStartCallbacks - onSpanEndCallbacks:(BSGPrioritizedStore *)onSpanEndCallbacks; +- (instancetype)initWithSpanControlProvider:(BSGCompositeSpanControlProvider *)compositeProvider; - (void)installPlugins:(NSArray> *)plugins; - (void)startPlugins; diff --git a/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.m b/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.m index d1ae8497..ff23873b 100644 --- a/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.m +++ b/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.m @@ -9,6 +9,7 @@ #import "BSGPluginManager.h" #import "../BugsnagPerformancePluginContext+Private.h" #import "../../Utils/Logging.h" +#import "../../Core/Configuration/BugsnagPerformanceConfiguration+Private.h" @interface BSGPluginManager () @@ -22,14 +23,10 @@ @interface BSGPluginManager () @implementation BSGPluginManager -- (instancetype)initWithConfiguration:(BugsnagPerformanceConfiguration *)configuration - compositeProvider:(BSGCompositeSpanControlProvider *)compositeProvider - onSpanStartCallbacks:(BSGPrioritizedStore *)onSpanStartCallbacks - onSpanEndCallbacks:(BSGPrioritizedStore *)onSpanEndCallbacks +- (instancetype)initWithSpanControlProvider:(BSGCompositeSpanControlProvider *)compositeProvider { self = [super init]; if (self) { - _configuration = configuration; _compositeProvider = compositeProvider; _onSpanStartCallbacks = onSpanStartCallbacks; _onSpanEndCallbacks = onSpanEndCallbacks; @@ -70,4 +67,29 @@ - (void)startPlugins { } } +#pragma mark BSGPhasedStartup + +- (void)earlyConfigure:(BSGEarlyConfiguration *)config { +} + +- (void)earlySetup { +} + +- (void)configure:(BugsnagPerformanceConfiguration *)config { + self.configuration = config; + for(BugsnagPerformanceSpanStartCallback callback in config.onSpanStartCallbacks) { + [self.onSpanStartCallbacks addObject:callback priority:BugsnagPerformancePriorityMedium]; + } + for(BugsnagPerformanceSpanEndCallback callback in config.onSpanEndCallbacks) { + [self.onSpanEndCallbacks addObject:callback priority:BugsnagPerformancePriorityMedium]; + } +} + +- (void)preStartSetup { + +} + +- (void) start { +} + @end diff --git a/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.h b/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.h new file mode 100644 index 00000000..64ceba1a --- /dev/null +++ b/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.h @@ -0,0 +1,41 @@ +// +// PluginSupportModule.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 16/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#pragma once + +#import "../Core/Module.h" +#import "SpanControl/BSGCompositeSpanControlProvider.h" +#import "PluginManager/BSGPluginManager.h" + +#import + +namespace bugsnag { +class PluginSupportModule: public Module { +public: + PluginSupportModule() {}; + + ~PluginSupportModule() {}; + + void earlyConfigure(BSGEarlyConfiguration *) noexcept; + void earlySetup() noexcept; + void configure(BugsnagPerformanceConfiguration *config) noexcept; + void preStartSetup() noexcept; + void start() noexcept; + + void setUp() noexcept; + + BSGCompositeSpanControlProvider *getSpanControlProvider() noexcept { return spanControlProvider_; } + +private: + + // Components + BSGCompositeSpanControlProvider *spanControlProvider_; + BSGPluginManager *pluginManager_; + +}; +} diff --git a/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.mm b/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.mm new file mode 100644 index 00000000..ac793ac6 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.mm @@ -0,0 +1,46 @@ +// +// PluginSupportModule.mm +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 16/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#import "PluginSupportModule.h" + +using namespace bugsnag; + +#pragma mark PhasedStartup + +void +PluginSupportModule::earlyConfigure(BSGEarlyConfiguration *config) noexcept { + [pluginManager_ earlyConfigure:config]; +} + +void +PluginSupportModule::earlySetup() noexcept { + [pluginManager_ earlySetup]; +} + +void +PluginSupportModule::configure(BugsnagPerformanceConfiguration *config) noexcept { + [pluginManager_ configure:config]; +} + +void +PluginSupportModule::preStartSetup() noexcept { + [pluginManager_ preStartSetup]; +} + +void +PluginSupportModule::start() noexcept { + [pluginManager_ start]; +} + +#pragma mark Module + +void +PluginSupportModule::setUp() noexcept { + spanControlProvider_ = [BSGCompositeSpanControlProvider new]; + pluginManager_ = [[BSGPluginManager alloc] initWithSpanControlProvider:spanControlProvider_]; +} diff --git a/Sources/BugsnagPerformance/Private/Plugins/AppStart/BugsnagPerformanceAppStartTypePlugin.mm b/Sources/BugsnagPerformance/Private/Plugins/AppStart/BugsnagPerformanceAppStartTypePlugin.mm index 49e96b37..37b1985b 100644 --- a/Sources/BugsnagPerformance/Private/Plugins/AppStart/BugsnagPerformanceAppStartTypePlugin.mm +++ b/Sources/BugsnagPerformance/Private/Plugins/AppStart/BugsnagPerformanceAppStartTypePlugin.mm @@ -13,7 +13,7 @@ #import #import "BugsnagPerformanceAppStartSpanControl+Private.h" #import "BugsnagPerformanceAppStartTypePlugin.h" -#import "../../CrosstalkAPI/BugsnagPerformanceCrossTalkAPI.h" +#import "../../CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h" @interface BugsnagPerformanceAppStartTypePlugin() @property (nonatomic) GetAppStartInstrumentationStateSnapshot getAppStartInstrumentationState; diff --git a/Sources/BugsnagPerformance/Private/Plugins/PluginsModule.h b/Sources/BugsnagPerformance/Private/Plugins/PluginsModule.h new file mode 100644 index 00000000..4323f949 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Plugins/PluginsModule.h @@ -0,0 +1,43 @@ +// +// PluginsModule.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 16/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#pragma once + +#import "../Core/Module.h" +#import "../Instrumentation/Instrumentation.h" +#import "AppStart/BugsnagPerformanceAppStartTypePlugin.h" + +#import + +namespace bugsnag { +class PluginsModule: public Module { +public: + PluginsModule(std::shared_ptr instrumentation) + : instrumentation_(instrumentation) {}; + + ~PluginsModule() {}; + + void earlyConfigure(BSGEarlyConfiguration *) noexcept {} + void earlySetup() noexcept {} + void configure(BugsnagPerformanceConfiguration *) noexcept {} + void preStartSetup() noexcept {} + void start() noexcept {} + + void setUp() noexcept; + + BugsnagPerformanceAppStartTypePlugin *getAppStartTypePlugin() noexcept { return appStartTypePlugin_; } + +private: + + // Dependencies + std::shared_ptr instrumentation_; + + // Components + BugsnagPerformanceAppStartTypePlugin *appStartTypePlugin_; +}; +} diff --git a/Sources/BugsnagPerformance/Private/Plugins/PluginsModule.mm b/Sources/BugsnagPerformance/Private/Plugins/PluginsModule.mm new file mode 100644 index 00000000..aa4edf37 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Plugins/PluginsModule.mm @@ -0,0 +1,18 @@ +// +// PluginsModule.mm +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 16/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#import "PluginsModule.h" + +using namespace bugsnag; + +void PluginsModule::setUp() noexcept { + appStartTypePlugin_ = [BugsnagPerformanceAppStartTypePlugin new]; + [appStartTypePlugin_ setGetAppStartInstrumentationStateCallback:^AppStartupInstrumentationStateSnapshot * _Nullable { + return instrumentation_->getAppStartInstrumentationStateSnapshot(); + }]; +} diff --git a/Sources/BugsnagPerformance/Private/Tracer.h b/Sources/BugsnagPerformance/Private/Tracer.h deleted file mode 100644 index ba0a5da9..00000000 --- a/Sources/BugsnagPerformance/Private/Tracer.h +++ /dev/null @@ -1,95 +0,0 @@ -// -// Tracer.h -// BugsnagPerformance -// -// Created by Nick Dowell on 23/09/2022. -// - -#pragma once - -#import -#import -#import "Core/PhasedStartup.h" -#import "Core/SpanStack/SpanStackingHandler.h" -#import "Instrumentation/AppStartupInstrumentation/State/AppStartupInstrumentationStateSnapshot.h" -#import "Core/SpanFactory/Plain/PlainSpanFactoryImpl.h" -#import "Core/SpanFactory/AppStartup/AppStartupSpanFactoryImpl.h" -#import "Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryImpl.h" -#import "Core/SpanFactory/Network/NetworkSpanFactoryImpl.h" -#import "Core/SpanFactory/ViewLoad/ViewLoadSpanFactoryCallbacks.h" -#import "Core/SpanLifecycle/SpanLifecycleHandler.h" -#import "Core/SpanStore/SpanStore.h" - -#import - -namespace bugsnag { -// https://opentelemetry.io/docs/reference/specification/trace/api/#tracer - -/** - * Tracer starts all spans, then samples them and routes them to the batch when they end. - */ -class Tracer: public PhasedStartup { -public: - Tracer(std::shared_ptr plainSpanFactory, - std::shared_ptr viewLoadSpanFactory, - std::shared_ptr networkSpanFactory, - std::shared_ptr spanLifecycleHandler, - std::shared_ptr spanStore) noexcept - : plainSpanFactory_(plainSpanFactory) - , viewLoadSpanFactory_(viewLoadSpanFactory) - , networkSpanFactory_(networkSpanFactory) - , spanLifecycleHandler_(spanLifecycleHandler) - , spanStore_(spanStore) - { - plainSpanFactory_->setup(createPlainSpanFactoryCallbacks()); - viewLoadSpanFactory_->setup(createViewLoadSpanFactoryCallbacks()); - } - - - ~Tracer() {}; - - void earlyConfigure(BSGEarlyConfiguration *) noexcept {} - void earlySetup() noexcept {} - void configure(BugsnagPerformanceConfiguration *config) noexcept { - plainSpanFactory_->setAttributeCountLimit(config.attributeCountLimit); - }; - void preStartSetup() noexcept {} - void start() noexcept {} - - void setOnViewLoadSpanStarted(std::function onViewLoadSpanStarted) noexcept { - onViewLoadSpanStarted_ = onViewLoadSpanStarted; - } - - void setGetAppStartInstrumentationState(std::function getAppStartupInstrumentationState) noexcept { - getAppStartupInstrumentationState_ = getAppStartupInstrumentationState; - } - - BugsnagPerformanceSpan *startSpan(NSString *name, const SpanOptions &options, BSGTriState defaultFirstClass, NSArray *conditionsToEndOnClose) noexcept; - - BugsnagPerformanceSpan *startCustomSpan(NSString *name, const SpanOptions &options) noexcept; - - BugsnagPerformanceSpan *startViewLoadSpan(BugsnagPerformanceViewType viewType, - NSString *className, - const SpanOptions &options) noexcept; - - BugsnagPerformanceSpan *startNetworkSpan(NSString *httpMethod, const SpanOptions &options) noexcept; - - BugsnagPerformanceSpan *startViewLoadPhaseSpan(NSString *className, - NSString *phase, - BugsnagPerformanceSpanContext *parentContext, - NSArray *conditionsToEndOnClose) noexcept; -private: - Tracer() = delete; - std::shared_ptr spanStore_; - std::shared_ptr plainSpanFactory_; - std::shared_ptr viewLoadSpanFactory_; - std::shared_ptr networkSpanFactory_; - std::shared_ptr spanLifecycleHandler_; - - std::function onViewLoadSpanStarted_{ [](NSString *){} }; - std::function getAppStartupInstrumentationState_{ [](){ return nil; } }; - - PlainSpanFactoryCallbacks *createPlainSpanFactoryCallbacks() noexcept; - ViewLoadSpanFactoryCallbacks *createViewLoadSpanFactoryCallbacks() noexcept; -}; -} diff --git a/Sources/BugsnagPerformance/Private/Tracer.mm b/Sources/BugsnagPerformance/Private/Tracer.mm deleted file mode 100644 index fd8a990a..00000000 --- a/Sources/BugsnagPerformance/Private/Tracer.mm +++ /dev/null @@ -1,116 +0,0 @@ -// -// Tracer.mm -// BugsnagPerformance -// -// Created by Nick Dowell on 23/09/2022. -// - -#import "Tracer.h" - -#import "Core/Attributes/SpanAttributes.h" -#import "Utils/Utils.h" -#import "Core/Span/BugsnagPerformanceSpan+Private.h" -#import "Instrumentation/NetworkInstrumentation/NetworkInstrumentation.h" -#import "Instrumentation/ViewLoadInstrumentation/ViewLoadInstrumentation.h" -#import "Main/BugsnagPerformanceLibrary.h" -#import "Metrics/FrameMetrics/FrameMetricsCollector.h" -#import - -using namespace bugsnag; - -BugsnagPerformanceSpan * -Tracer::startSpan(NSString *name, - const SpanOptions &options, - BSGTriState defaultFirstClass, - NSArray *conditionsToEndOnClose) noexcept { - return plainSpanFactory_->startSpan(name, options, defaultFirstClass, @{}, conditionsToEndOnClose); -} - -BugsnagPerformanceSpan * -Tracer::startCustomSpan(NSString *name, - const SpanOptions &options) noexcept { - return startSpan(name, options, BSGTriStateYes, @[]); -} - -BugsnagPerformanceSpan * -Tracer::startViewLoadSpan(BugsnagPerformanceViewType viewType, - NSString *className, - const SpanOptions &options) noexcept { - return viewLoadSpanFactory_->startViewLoadSpan(viewType, - className, - nil, - options, - @{}); -} - -BugsnagPerformanceSpan * -Tracer::startNetworkSpan(NSString *httpMethod, - const SpanOptions &options) noexcept { - return networkSpanFactory_->startNetworkSpan(httpMethod, options, @{}); -} - -BugsnagPerformanceSpan * -Tracer::startViewLoadPhaseSpan(NSString *className, - NSString *phase, - BugsnagPerformanceSpanContext *parentContext, - NSArray *conditionsToEndOnClose) noexcept { - return viewLoadSpanFactory_->startViewLoadPhaseSpan(className, - parentContext, - phase, - conditionsToEndOnClose); -} - -PlainSpanFactoryCallbacks * -Tracer::createPlainSpanFactoryCallbacks() noexcept { - __block auto blockThis = this; - auto callbacks = [PlainSpanFactoryCallbacks new]; - callbacks.onSpanStarted = ^(BugsnagPerformanceSpan * _Nonnull span, const SpanOptions &options) { - blockThis->spanLifecycleHandler_->onSpanStarted(span, options); - }; - - callbacks.onSpanEndSet = ^(BugsnagPerformanceSpan * _Nonnull span) { - blockThis->spanLifecycleHandler_->onSpanEndSet(span); - }; - - callbacks.onSpanClosed = ^(BugsnagPerformanceSpan * _Nonnull span) { - blockThis->spanLifecycleHandler_->onSpanClosed(span); - }; - - callbacks.onSpanBlocked = ^BugsnagPerformanceSpanCondition * _Nullable(BugsnagPerformanceSpan * _Nonnull span, NSTimeInterval timeout) { - return blockThis->spanLifecycleHandler_->onSpanBlocked(span, timeout); - }; - - callbacks.onSpanCancelled = ^(BugsnagPerformanceSpan * _Nonnull span) { - blockThis->spanLifecycleHandler_->onSpanCancelled(span); - }; - - return callbacks; -} - -ViewLoadSpanFactoryCallbacks * -Tracer::createViewLoadSpanFactoryCallbacks() noexcept { - __block auto blockThis = this; - auto callbacks = [ViewLoadSpanFactoryCallbacks new]; - callbacks.getViewLoadParentSpan = ^BugsnagPerformanceSpan *() { - if (blockThis->getAppStartupInstrumentationState_ != nil) { - AppStartupInstrumentationStateSnapshot *appStartupState = blockThis->getAppStartupInstrumentationState_(); - if (appStartupState.isInProgress && !appStartupState.hasFirstView) { - return appStartupState.uiInitSpan; - } - } - return nil; - }; - callbacks.isViewLoadInProgress = ^BOOL() { - return blockThis->spanStore_->hasSpanOnCurrentStack(@"bugsnag.span.category", @"view_load"); - }; - - auto onViewLoadSpanStarted = ^(NSString * _Nonnull className) { - if (onViewLoadSpanStarted_ != nil) { - onViewLoadSpanStarted_(className); - } - }; - - callbacks.onViewLoadSpanStarted = onViewLoadSpanStarted; - - return callbacks; -} diff --git a/Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpUploader.h b/Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpUploader.h index 6306f835..aed7c017 100644 --- a/Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpUploader.h +++ b/Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpUploader.h @@ -12,6 +12,7 @@ #import "Uploader.h" #import "OtlpPackage.h" +#import "../../Core/PhasedStartup.h" #import namespace bugsnag { @@ -20,17 +21,25 @@ namespace bugsnag { * Bugsnag backend uploader. * Also informs via callback any changes the backend makes to the probability value. */ -class OtlpUploader: public Uploader { +class OtlpUploader: public Uploader, public PhasedStartup { public: - OtlpUploader(NSURL *endpoint, NSString *apiKey, NewProbabilityCallback newProbabilityCallback) noexcept - : endpoint_(endpoint) - , apiKey_(apiKey) - , newProbabilityCallback_(newProbabilityCallback) - {} + OtlpUploader() noexcept {} virtual ~OtlpUploader() = default; - - void upload(OtlpPackage &package, UploadResultCallback callback) noexcept override; + + void earlyConfigure(BSGEarlyConfiguration *) noexcept {} + void earlySetup() noexcept {} + void configure(BugsnagPerformanceConfiguration *config) noexcept { + endpoint_ = config.endpoint; + apiKey_ = config.apiKey; + } + void preStartSetup() noexcept {} + void start() noexcept {} + + void upload(OtlpPackage &package, UploadResultCallback callback) noexcept; + void setNewProbabilityCallback(NewProbabilityCallback newProbabilityCallback) noexcept { + newProbabilityCallback_ = newProbabilityCallback; + } private: const NSURL *endpoint_{nil}; diff --git a/Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpUploader.mm b/Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpUploader.mm index e8fa5236..3cb00418 100644 --- a/Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpUploader.mm +++ b/Sources/BugsnagPerformance/Private/Upload/Otlp/OtlpUploader.mm @@ -29,6 +29,9 @@ typedef NS_ENUM(NSInteger, HTTPStatusCode) { }; void OtlpUploader::upload(OtlpPackage &package, UploadResultCallback callback) noexcept { + if (endpoint_ == nil) { + return; + } BSGLogDebug(@"OtlpUploader::upload(package, callback)"); auto urlRequest = [NSMutableURLRequest requestWithURL:(NSURL *)endpoint_]; [urlRequest setValue:apiKey_ forHTTPHeaderField:@"Bugsnag-Api-Key"]; diff --git a/Sources/BugsnagPerformance/Private/Upload/UploadModule.h b/Sources/BugsnagPerformance/Private/Upload/UploadModule.h new file mode 100644 index 00000000..8e4e8ada --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Upload/UploadModule.h @@ -0,0 +1,54 @@ +// +// UploadModule.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 17/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#pragma once + +#import "../Core/Module.h" +#import "../Utils/Persistence.h" +#import "RetryQueue.h" +#import "Otlp/OtlpTraceEncoding.h" +#import "Otlp/OtlpUploader.h" + +#import + +namespace bugsnag { +class UploadModule: public Module { +public: + UploadModule(std::shared_ptr persistence) + : persistence_(persistence) {}; + + ~UploadModule() {}; + + void earlyConfigure(BSGEarlyConfiguration *config) noexcept; + void earlySetup() noexcept; + void configure(BugsnagPerformanceConfiguration *config) noexcept; + void preStartSetup() noexcept; + void start() noexcept; + + void setUp() noexcept; + void initializeComponentsCallbacks(ModuleTask clearPersistentDataTask, + UpdateProbabilityTask updateProbabilityTask) noexcept { + retryQueue_->setOnFilesystemError(clearPersistentDataTask); + uploader_->setNewProbabilityCallback(updateProbabilityTask); + } + + std::shared_ptr getRetryQueue() noexcept { return retryQueue_; } + std::shared_ptr getTraceEncoding() noexcept { return traceEncoding_; } + std::shared_ptr getUploader() noexcept { return uploader_; } + +private: + + // Dependencies + std::shared_ptr persistence_; + + // Components + std::shared_ptr retryQueue_; + std::shared_ptr traceEncoding_; + std::shared_ptr uploader_; +}; +} diff --git a/Sources/BugsnagPerformance/Private/Upload/UploadModule.mm b/Sources/BugsnagPerformance/Private/Upload/UploadModule.mm new file mode 100644 index 00000000..3ea38a6d --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Upload/UploadModule.mm @@ -0,0 +1,57 @@ +// +// UploadModule.mm +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 17/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#import "UploadModule.h" + +using namespace bugsnag; + +#pragma mark PhasedStartup + +void +UploadModule::earlyConfigure(BSGEarlyConfiguration *config) noexcept { + traceEncoding_->earlyConfigure(config); + retryQueue_->earlyConfigure(config); + uploader_->earlyConfigure(config); +} + +void +UploadModule::earlySetup() noexcept { + traceEncoding_->earlySetup(); + retryQueue_->earlySetup(); + uploader_->earlySetup(); +} + +void +UploadModule::configure(BugsnagPerformanceConfiguration *config) noexcept { + traceEncoding_->configure(config); + retryQueue_->configure(config); + uploader_->configure(config); +} + +void +UploadModule::preStartSetup() noexcept { + traceEncoding_->preStartSetup(); + retryQueue_->preStartSetup(); + uploader_->preStartSetup(); +} + +void +UploadModule::start() noexcept { + traceEncoding_->start(); + retryQueue_->start(); + uploader_->start(); +} + +#pragma mark Module + +void +UploadModule::setUp() noexcept { + retryQueue_ = std::make_shared([persistence_->bugsnagPerformanceDir() stringByAppendingPathComponent:@"retry-queue"]); + traceEncoding_ = std::make_shared(); + uploader_ = std::make_shared(); +} diff --git a/Sources/BugsnagPerformance/Private/Utils/Persistence.h b/Sources/BugsnagPerformance/Private/Utils/Persistence.h index 66480c89..213fd2ea 100644 --- a/Sources/BugsnagPerformance/Private/Utils/Persistence.h +++ b/Sources/BugsnagPerformance/Private/Utils/Persistence.h @@ -9,14 +9,25 @@ #pragma once #import +#import "../Core/PhasedStartup.h" +#import "../Core/Configuration/BugsnagPerformanceConfiguration+Private.h" namespace bugsnag { +NSString *bugsnagPerformancePath(NSString *topLevelDir); +NSString *bugsnagSharedPath(NSString *topLevelDir); + class Persistence { public: - Persistence() = delete; - Persistence(NSString *topLevelDir) noexcept; - + Persistence(NSString *topLevelDir) noexcept + : bugsnagSharedDir_(bugsnagSharedPath(topLevelDir)) + , bugsnagPerformanceDir_(bugsnagPerformancePath(topLevelDir)) + {} + + void earlyConfigure(BSGEarlyConfiguration *) noexcept {} + void earlySetup() noexcept {} + void configure(BugsnagPerformanceConfiguration *config) noexcept; + void preStartSetup() noexcept {} void start() noexcept; // Clear all "performance" data. "shared" data is unaffected. @@ -31,6 +42,9 @@ class Persistence { private: NSString *bugsnagSharedDir_{nil}; NSString *bugsnagPerformanceDir_{nil}; + BugsnagPerformanceConfiguration *configuration_{nil}; + + Persistence() = delete; }; } diff --git a/Sources/BugsnagPerformance/Private/Utils/Persistence.mm b/Sources/BugsnagPerformance/Private/Utils/Persistence.mm index 172b6f1b..2fc37d83 100644 --- a/Sources/BugsnagPerformance/Private/Utils/Persistence.mm +++ b/Sources/BugsnagPerformance/Private/Utils/Persistence.mm @@ -14,21 +14,24 @@ using namespace bugsnag; -static NSString *bugsnagPerformancePath(NSString *topLevelDir) { +NSString *bugsnagPerformancePath(NSString *topLevelDir) { // Namespace it to the bundle identifier because all MacOS non-sandboxed apps share the same cache dir. return [topLevelDir stringByAppendingFormat:@"/bugsnag-performance-%@", [[NSBundle mainBundle] bundleIdentifier]]; } -static NSString *bugsnagSharedPath(NSString *topLevelDir) { +NSString *bugsnagSharedPath(NSString *topLevelDir) { return [topLevelDir stringByAppendingFormat:@"/bugsnag-shared-%@", [[NSBundle mainBundle] bundleIdentifier]]; } -Persistence::Persistence(NSString *topLevelDir) noexcept -: bugsnagSharedDir_(bugsnagSharedPath(topLevelDir)) -, bugsnagPerformanceDir_(bugsnagPerformancePath(topLevelDir)) -{} +#pragma mark PhasedStartup -void Persistence::start() noexcept { +void +Persistence::configure(BugsnagPerformanceConfiguration *config) noexcept { + configuration_ = config; +} + +void +Persistence::start() noexcept { NSError *error = nil; if ((error = [Filesystem ensurePathExists:bugsnagPerformanceDir_]) != nil) { BSGLogError(@"error while initializing bugsnag performance persistence dir: %@", error); @@ -36,8 +39,13 @@ if ((error = [Filesystem ensurePathExists:bugsnagSharedDir_]) != nil) { BSGLogError(@"error while initializing bugsnag shared persistence dir: %@", error); } + if (configuration_.internal.clearPersistenceOnStart) { + clearPerformanceData(); + } } +#pragma mark Public + NSString *Persistence::bugsnagSharedDir(void) noexcept { return bugsnagSharedDir_; } diff --git a/Sources/BugsnagPerformance/Private/Utils/UtilsModule.h b/Sources/BugsnagPerformance/Private/Utils/UtilsModule.h new file mode 100644 index 00000000..56639618 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Utils/UtilsModule.h @@ -0,0 +1,54 @@ +// +// UtilsModule.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 16/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#pragma once + +#import "../Core/Module.h" +#import "AppStateTracker.h" +#import "Reachability.h" +#import "Persistence.h" +#import "PersistentDeviceID.h" + +#import + +namespace bugsnag { +class UtilsModule: public Module { +public: + UtilsModule() {}; + + ~UtilsModule() {}; + + void earlyConfigure(BSGEarlyConfiguration *) noexcept; + void earlySetup() noexcept; + void configure(BugsnagPerformanceConfiguration *config) noexcept; + void preStartSetup() noexcept; + void start() noexcept; + + void setUp() noexcept; + void initializeComponentsCallbacks(UpdateConnectivityTask updateConnectivityTask) noexcept { + reachability_->addCallback(updateConnectivityTask); + } + + // Tasks + ModuleTask getClearPersistentDataTask() noexcept; + + // Components access + AppStateTracker *getAppStateTracker() noexcept { return appStateTracker_; } + std::shared_ptr getReachability() noexcept { return reachability_; } + std::shared_ptr getPersistence() noexcept { return persistence_; } + std::shared_ptr getDeviceID() noexcept { return deviceID_; } + +private: + + // Components + AppStateTracker *appStateTracker_; + std::shared_ptr reachability_; + std::shared_ptr persistence_; + std::shared_ptr deviceID_; +}; +} diff --git a/Sources/BugsnagPerformance/Private/Utils/UtilsModule.mm b/Sources/BugsnagPerformance/Private/Utils/UtilsModule.mm new file mode 100644 index 00000000..4cb440bb --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Utils/UtilsModule.mm @@ -0,0 +1,71 @@ +// +// UtilsModule.mm +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 16/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#import "UtilsModule.h" + +using namespace bugsnag; + +static NSString *getPersistenceDir() { + // Persistent data in bugsnag-performance can handle files disappearing, so put it in the caches dir. + return NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject; +} + +#pragma mark PhasedStartup + +void +UtilsModule::earlyConfigure(BSGEarlyConfiguration *config) noexcept { + persistence_->earlyConfigure(config); + deviceID_->earlyConfigure(config); +} + +void +UtilsModule::earlySetup() noexcept { + persistence_->earlySetup(); + deviceID_->earlySetup(); +} + +void +UtilsModule::configure(BugsnagPerformanceConfiguration *config) noexcept { + persistence_->configure(config); + deviceID_->configure(config); +} + +void +UtilsModule::preStartSetup() noexcept { + persistence_->preStartSetup(); + deviceID_->preStartSetup(); +} + +void +UtilsModule::start() noexcept { + persistence_->start(); + deviceID_->start(); +} + +#pragma mark Module + +void +UtilsModule::setUp() noexcept { + appStateTracker_ = [[AppStateTracker alloc] init]; + reachability_ = std::make_shared(); + persistence_ = std::make_shared(getPersistenceDir()); + deviceID_ = std::make_shared(persistence_); +} + +#pragma mark Tasks + +ModuleTask +UtilsModule::getClearPersistentDataTask() noexcept { + __block auto blockThis = this; + return ^{ + if (blockThis->persistence_ == nullptr) { + return; + } + blockThis->persistence_->clearPerformanceData(); + }; +} diff --git a/Tests/BugsnagPerformanceTests/SpanAttributesTests.mm b/Tests/BugsnagPerformanceTests/SpanAttributesTests.mm index 2e39dd77..cf224a32 100644 --- a/Tests/BugsnagPerformanceTests/SpanAttributesTests.mm +++ b/Tests/BugsnagPerformanceTests/SpanAttributesTests.mm @@ -18,7 +18,8 @@ @interface SpanAttributesTests : XCTestCase @implementation SpanAttributesTests - (void)testInitialNetworkSpanAttributes { - SpanAttributesProvider provider; + SpanAttributesProvider provider = SpanAttributesProvider([[AppStateTracker alloc] init], + std::make_shared()); auto attributes = provider.initialNetworkSpanAttributes(); XCTAssertEqual(2U, attributes.count); XCTAssertEqualObjects(attributes[@"bugsnag.span.category"], @"network"); @@ -26,7 +27,8 @@ - (void)testInitialNetworkSpanAttributes { } - (void)testNetworkSpanUrlAttributes { - SpanAttributesProvider provider; + SpanAttributesProvider provider = SpanAttributesProvider([[AppStateTracker alloc] init], + std::make_shared()); NSURL *url = [NSURL URLWithString:@"https://bugsnag.com"]; NSError *error = [NSError errorWithDomain:@"test" code:1 userInfo:nil]; @@ -50,7 +52,8 @@ - (void)testNetworkSpanUrlAttributes { } - (void)testInternalErrorAttributes { - SpanAttributesProvider provider; + SpanAttributesProvider provider = SpanAttributesProvider([[AppStateTracker alloc] init], + std::make_shared()); NSError *error = [NSError errorWithDomain:@"test" code:1 userInfo:nil]; auto attributes = provider.internalErrorAttributes(error); XCTAssertEqual(1U, attributes.count); @@ -58,7 +61,8 @@ - (void)testInternalErrorAttributes { } - (void)testAppStartPhaseSpanAttributes { - SpanAttributesProvider provider; + SpanAttributesProvider provider = SpanAttributesProvider([[AppStateTracker alloc] init], + std::make_shared()); auto attributes = provider.appStartPhaseSpanAttributes(@"phase1"); XCTAssertEqual(2U, attributes.count); @@ -67,7 +71,8 @@ - (void)testAppStartPhaseSpanAttributes { } - (void)testAppStartSpanAttributes { - SpanAttributesProvider provider; + SpanAttributesProvider provider = SpanAttributesProvider([[AppStateTracker alloc] init], + std::make_shared()); auto attributes = provider.appStartSpanAttributes(@"firstView", true); XCTAssertEqual(3U, attributes.count); @@ -89,7 +94,8 @@ - (void)testAppStartSpanAttributes { } - (void)testViewLoadSpanAttributes { - SpanAttributesProvider provider; + SpanAttributesProvider provider = SpanAttributesProvider([[AppStateTracker alloc] init], + std::make_shared()); auto attributes = provider.viewLoadSpanAttributes(@"myView", BugsnagPerformanceViewTypeUIKit); XCTAssertEqual(3U, attributes.count); @@ -111,7 +117,8 @@ - (void)testViewLoadSpanAttributes { } - (void)testPreloadViewLoadSpanAttributes { - SpanAttributesProvider provider; + SpanAttributesProvider provider = SpanAttributesProvider([[AppStateTracker alloc] init], + std::make_shared()); auto attributes = provider.preloadViewLoadSpanAttributes(@"myView", BugsnagPerformanceViewTypeUIKit); XCTAssertEqual(3U, attributes.count); @@ -133,7 +140,8 @@ - (void)testPreloadViewLoadSpanAttributes { } - (void)testPresentingViewLoadSpanAttributes { - SpanAttributesProvider provider; + SpanAttributesProvider provider = SpanAttributesProvider([[AppStateTracker alloc] init], + std::make_shared()); auto attributes = provider.presentingViewLoadSpanAttributes(@"myView", BugsnagPerformanceViewTypeUIKit); XCTAssertEqual(3U, attributes.count); @@ -155,7 +163,8 @@ - (void)testPresentingViewLoadSpanAttributes { } - (void)testViewLoadPhaseSpanAttributes { - SpanAttributesProvider provider; + SpanAttributesProvider provider = SpanAttributesProvider([[AppStateTracker alloc] init], + std::make_shared()); auto attributes = provider.viewLoadPhaseSpanAttributes(@"myView", @"myPhase"); XCTAssertEqual(3U, attributes.count); @@ -165,7 +174,8 @@ - (void)testViewLoadPhaseSpanAttributes { } - (void)testCustomSpanAttributes { - SpanAttributesProvider provider; + SpanAttributesProvider provider = SpanAttributesProvider([[AppStateTracker alloc] init], + std::make_shared()); auto attributes = provider.customSpanAttributes(); XCTAssertEqual(1U, attributes.count); @@ -173,7 +183,8 @@ - (void)testCustomSpanAttributes { } - (void)testCPUSampleAttributesInsufficient { - SpanAttributesProvider provider; + SpanAttributesProvider provider = SpanAttributesProvider([[AppStateTracker alloc] init], + std::make_shared()); // Not enough samples std::vector samples; @@ -197,7 +208,8 @@ - (void)testCPUSampleAttributesInsufficient { } - (void)testCPUAttributesNilIfInvalidCPUMeanTotal { - SpanAttributesProvider provider; + SpanAttributesProvider provider = SpanAttributesProvider([[AppStateTracker alloc] init], + std::make_shared()); std::vector samples = { SystemInfoSampleData(1), SystemInfoSampleData(2), @@ -217,7 +229,8 @@ - (void)testCPUAttributesNilIfInvalidCPUMeanTotal { } - (void)testCPUSampleAttributes { - SpanAttributesProvider provider; + SpanAttributesProvider provider = SpanAttributesProvider([[AppStateTracker alloc] init], + std::make_shared()); std::vector samples = { SystemInfoSampleData(1), SystemInfoSampleData(2), @@ -260,7 +273,8 @@ - (void)testCPUSampleAttributes { } - (void)testCPUSampleAttributesProcessOnly { - SpanAttributesProvider provider; + SpanAttributesProvider provider = SpanAttributesProvider([[AppStateTracker alloc] init], + std::make_shared()); std::vector samples = { SystemInfoSampleData(11), SystemInfoSampleData(12), @@ -285,7 +299,8 @@ - (void)testCPUSampleAttributesProcessOnly { } - (void)testCPUSampleAttributesMainThreadOnly { - SpanAttributesProvider provider; + SpanAttributesProvider provider = SpanAttributesProvider([[AppStateTracker alloc] init], + std::make_shared()); std::vector samples = { SystemInfoSampleData(1), SystemInfoSampleData(2), @@ -303,7 +318,8 @@ - (void)testCPUSampleAttributesMainThreadOnly { } - (void)testCPUSampleAttributesOverheadOnly { - SpanAttributesProvider provider; + SpanAttributesProvider provider = SpanAttributesProvider([[AppStateTracker alloc] init], + std::make_shared()); std::vector samples = { SystemInfoSampleData(1), SystemInfoSampleData(2), @@ -321,7 +337,8 @@ - (void)testCPUSampleAttributesOverheadOnly { } - (void)testCPUSampleAttributesComplex { - SpanAttributesProvider provider; + SpanAttributesProvider provider = SpanAttributesProvider([[AppStateTracker alloc] init], + std::make_shared()); std::vector samples = { SystemInfoSampleData(1), SystemInfoSampleData(2), @@ -387,7 +404,8 @@ - (void)testCPUSampleAttributesComplex { } - (void)testMemorySampleAttributesInsufficient { - SpanAttributesProvider provider; + SpanAttributesProvider provider = SpanAttributesProvider([[AppStateTracker alloc] init], + std::make_shared()); // Not enough samples std::vector samples; @@ -412,7 +430,8 @@ - (void)testMemorySampleAttributesInsufficient { } - (void)testMemorySampleAttributesProcessOnly { - SpanAttributesProvider provider; + SpanAttributesProvider provider = SpanAttributesProvider([[AppStateTracker alloc] init], + std::make_shared()); std::vector samples = { SystemInfoSampleData(11), SystemInfoSampleData(12), From 48acfe24f002a5d99c9174cbf1f934d50906b9ec Mon Sep 17 00:00:00 2001 From: Robert Bartoszewski Date: Wed, 22 Oct 2025 23:04:11 +0200 Subject: [PATCH 05/14] Moved plugins setup and fixed build issues --- BugsnagPerformance.xcodeproj/project.pbxproj | 4 + .../Private/Core/BSGPhasedStartup.h | 60 ++++++++++ .../Private/Core/ModuleTaskTypes.h | 3 + .../Private/Core/PhasedStartup.h | 44 ------- .../Private/Core/Worker/Worker.h | 2 +- .../BugsnagPerformanceCrossTalkAPI.h | 2 +- .../System/BSGURLSessionPerformanceDelegate.h | 2 +- .../System/NetworkHeaderInjector.h | 8 +- .../Private/Main/BugsnagPerformanceImpl.h | 42 +------ .../Private/Main/BugsnagPerformanceImpl.mm | 111 ++++++++---------- .../Private/Main/BugsnagPerformanceLibrary.mm | 9 +- .../Private/Main/MainModule.mm | 2 + .../FrameMetrics/FrameMetricsCollector.h | 2 +- .../PluginManager/BSGPluginManager.h | 2 +- .../PluginManager/BSGPluginManager.m | 7 +- .../PluginSupport/PluginSupportModule.h | 4 + .../Private/Plugins/PluginsModule.h | 5 + .../Private/Plugins/PluginsModule.mm | 16 +++ .../Private/Utils/Persistence.h | 4 +- 19 files changed, 160 insertions(+), 169 deletions(-) create mode 100644 Sources/BugsnagPerformance/Private/Core/BSGPhasedStartup.h diff --git a/BugsnagPerformance.xcodeproj/project.pbxproj b/BugsnagPerformance.xcodeproj/project.pbxproj index 33429db5..68079e32 100644 --- a/BugsnagPerformance.xcodeproj/project.pbxproj +++ b/BugsnagPerformance.xcodeproj/project.pbxproj @@ -216,6 +216,7 @@ 96794A312EA8450F005FD87F /* NetworkSpanReporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A302EA84508005FD87F /* NetworkSpanReporter.h */; }; 96794A332EA8451A005FD87F /* NetworkSpanReporterImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A322EA84515005FD87F /* NetworkSpanReporterImpl.h */; }; 96794A352EA84524005FD87F /* NetworkSpanReporterImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96794A342EA84520005FD87F /* NetworkSpanReporterImpl.mm */; }; + 96794A372EA97C76005FD87F /* BSGPhasedStartup.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A362EA97C73005FD87F /* BSGPhasedStartup.h */; }; 967F6F1829C3783B0054EED8 /* BugsnagPerformanceConfiguration+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 967F6F1729C3782D0054EED8 /* BugsnagPerformanceConfiguration+Private.h */; }; 968AA5FB2CCA5A9200BA69CF /* BSGPerformanceSharedSessionProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 968AA5FA2CCA5A9200BA69CF /* BSGPerformanceSharedSessionProxy.h */; }; 968AA5FD2CCA5AB000BA69CF /* BSGPerformanceSharedSessionProxy.mm in Sources */ = {isa = PBXBuildFile; fileRef = 968AA5FC2CCA5AB000BA69CF /* BSGPerformanceSharedSessionProxy.mm */; }; @@ -602,6 +603,7 @@ 96794A302EA84508005FD87F /* NetworkSpanReporter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NetworkSpanReporter.h; sourceTree = ""; }; 96794A322EA84515005FD87F /* NetworkSpanReporterImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NetworkSpanReporterImpl.h; sourceTree = ""; }; 96794A342EA84520005FD87F /* NetworkSpanReporterImpl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkSpanReporterImpl.mm; sourceTree = ""; }; + 96794A362EA97C73005FD87F /* BSGPhasedStartup.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BSGPhasedStartup.h; sourceTree = ""; }; 967F6F1729C3782D0054EED8 /* BugsnagPerformanceConfiguration+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BugsnagPerformanceConfiguration+Private.h"; sourceTree = ""; }; 968AA5FA2CCA5A9200BA69CF /* BSGPerformanceSharedSessionProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BSGPerformanceSharedSessionProxy.h; sourceTree = ""; }; 968AA5FC2CCA5AB000BA69CF /* BSGPerformanceSharedSessionProxy.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = BSGPerformanceSharedSessionProxy.mm; sourceTree = ""; }; @@ -1210,6 +1212,7 @@ children = ( 96794A292EA7B0F3005FD87F /* AppLifecycleListener.h */, 967949D72EA05844005FD87F /* Attributes */, + 96794A362EA97C73005FD87F /* BSGPhasedStartup.h */, 963726CD2DEAB33D00C739E6 /* BSGPrioritizedStore.h */, 963726CF2DEAB36600C739E6 /* BSGPrioritizedStore.mm */, 963726C92DEAB23E00C739E6 /* BugsnagPerformancePriority+Private.h */, @@ -1694,6 +1697,7 @@ 962CE80A2E651A0C00380522 /* NetworkInstrumentationStateRepositoryImpl.h in Headers */, 1C68DB952E535290002621D1 /* BugsnagPerformanceAppStartSpanControl+Private.h in Headers */, 962CE8182E65FD4300380522 /* NetworkSwizzlingHandler.h in Headers */, + 96794A372EA97C76005FD87F /* BSGPhasedStartup.h in Headers */, CBEBE59329F2783C00BF0B4F /* Swizzle.h in Headers */, 962CE8082E651A0100380522 /* NetworkInstrumentationStateRepository.h in Headers */, 96794A172EA1A849005FD87F /* PluginSupportModule.h in Headers */, diff --git a/Sources/BugsnagPerformance/Private/Core/BSGPhasedStartup.h b/Sources/BugsnagPerformance/Private/Core/BSGPhasedStartup.h new file mode 100644 index 00000000..8e2c0b67 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Core/BSGPhasedStartup.h @@ -0,0 +1,60 @@ +// +// BSGPhasedStartup.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 22/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#pragma once + +#import +#import "Configuration/EarlyConfiguration.h" + +NS_ASSUME_NONNULL_BEGIN + +@protocol BSGPhasedStartup + +/** + * Perform "early" configuration. This is called before main(), using configuration data + * pulled from the environment (Info.plist). + * + * It's called automatically by BugsnagPerformanceLibrary, and does not require any user runtime actions. + */ +- (void)earlyConfigure:(BSGEarlyConfiguration *)config; + +/** + * Perform "early" setup. This is called before main(), and gives each component an + * opportunity to perform any setup in response to the early configuration. + * + * It's split into a separate step so that any cross-component calls will always be + * made to an already-configured object. + */ +- (void)earlySetup; + +/** + * Perform user configuration. This is called as a consequence of the user calling [BugsnagPerformance start], + * and performs configuration according to what the user provided. + */ +- (void)configure:(BugsnagPerformanceConfiguration *)config; + +/** + * Perform pre-start setup. Like earlySetup(), this step gives each component an + * opportunity to perform any required setup in response to the configuration. + * + * It's split into a separate step so that any cross-component calls will always be + * made to an already-configured object. + */ +- (void)preStartSetup; + +/** + * Start this fully configured and set up component. + * + * This step is for actions that aren't part of the setup, but rather for "running" the object. + * This is typically for things such as starting threads and queues, patching into system callbacks, etc. + */ +- (void)start; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/BugsnagPerformance/Private/Core/ModuleTaskTypes.h b/Sources/BugsnagPerformance/Private/Core/ModuleTaskTypes.h index a05a223c..ddb59adb 100644 --- a/Sources/BugsnagPerformance/Private/Core/ModuleTaskTypes.h +++ b/Sources/BugsnagPerformance/Private/Core/ModuleTaskTypes.h @@ -10,9 +10,12 @@ #import "../Utils/Reachability.h" +@protocol BugsnagPerformancePlugin; + using namespace bugsnag; typedef void (^ModuleTask)(); typedef void (^UpdateProbabilityTask)(double); typedef void (^UpdateConnectivityTask)(Reachability::Connectivity); typedef void (^HandleStringTask)(NSString *); +typedef NSArray> *(^GetPluginsTask)(); diff --git a/Sources/BugsnagPerformance/Private/Core/PhasedStartup.h b/Sources/BugsnagPerformance/Private/Core/PhasedStartup.h index 6ba3aa47..8dd341f9 100644 --- a/Sources/BugsnagPerformance/Private/Core/PhasedStartup.h +++ b/Sources/BugsnagPerformance/Private/Core/PhasedStartup.h @@ -74,48 +74,4 @@ class PhasedStartup { } -@protocol BSGPhasedStartup - -/** - * Perform "early" configuration. This is called before main(), using configuration data - * pulled from the environment (Info.plist). - * - * It's called automatically by BugsnagPerformanceLibrary, and does not require any user runtime actions. - */ -- (void)earlyConfigure:(BSGEarlyConfiguration *)config; - -/** - * Perform "early" setup. This is called before main(), and gives each component an - * opportunity to perform any setup in response to the early configuration. - * - * It's split into a separate step so that any cross-component calls will always be - * made to an already-configured object. - */ -- (void)earlySetup; - -/** - * Perform user configuration. This is called as a consequence of the user calling [BugsnagPerformance start], - * and performs configuration according to what the user provided. - */ -- (void)configure:(BugsnagPerformanceConfiguration *)config; - -/** - * Perform pre-start setup. Like earlySetup(), this step gives each component an - * opportunity to perform any required setup in response to the configuration. - * - * It's split into a separate step so that any cross-component calls will always be - * made to an already-configured object. - */ -- (void)preStartSetup; - -/** - * Start this fully configured and set up component. - * - * This step is for actions that aren't part of the setup, but rather for "running" the object. - * This is typically for things such as starting threads and queues, patching into system callbacks, etc. - */ -- (void)start; - -@end - NS_ASSUME_NONNULL_END diff --git a/Sources/BugsnagPerformance/Private/Core/Worker/Worker.h b/Sources/BugsnagPerformance/Private/Core/Worker/Worker.h index 01a71f02..d9721755 100644 --- a/Sources/BugsnagPerformance/Private/Core/Worker/Worker.h +++ b/Sources/BugsnagPerformance/Private/Core/Worker/Worker.h @@ -9,7 +9,7 @@ #pragma once #import -#import "../PhasedStartup.h" +#import "../BSGPhasedStartup.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h b/Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h index d0d9462e..a543df6c 100644 --- a/Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h +++ b/Sources/BugsnagPerformance/Private/CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h @@ -24,7 +24,7 @@ // It contains a full example for how to set up a client library to call this one. #import -#import "../Core/PhasedStartup.h" +#import "../Core/BSGPhasedStartup.h" #import diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/BSGURLSessionPerformanceDelegate.h b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/BSGURLSessionPerformanceDelegate.h index 06922864..f2e17212 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/BSGURLSessionPerformanceDelegate.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/BSGURLSessionPerformanceDelegate.h @@ -9,7 +9,7 @@ #pragma once #import "../Lifecycle/NetworkLifecycleHandler.h" -#import "../../../Core/PhasedStartup.h" +#import "../../../Core/BSGPhasedStartup.h" #import using namespace bugsnag; diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkHeaderInjector.h b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkHeaderInjector.h index 6ec53a9c..c172cb11 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkHeaderInjector.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/NetworkInstrumentation/System/NetworkHeaderInjector.h @@ -31,11 +31,11 @@ class NetworkHeaderInjector: public PhasedStartup { {} virtual ~NetworkHeaderInjector() {} - void earlyConfigure(BSGEarlyConfiguration *) noexcept {}; - void earlySetup() noexcept {}; + void earlyConfigure(BSGEarlyConfiguration *) noexcept {} + void earlySetup() noexcept {} void configure(BugsnagPerformanceConfiguration *config) noexcept; - void preStartSetup() noexcept {}; - void start() noexcept {}; + void preStartSetup() noexcept {} + void start() noexcept {} void injectTraceParentIfMatches(NSURLSessionTask *task, BugsnagPerformanceSpan * _Nullable span); diff --git a/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.h b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.h index 76872020..6cda505c 100644 --- a/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.h +++ b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.h @@ -50,7 +50,7 @@ class BugsnagPerformanceImpl: public PhasedStartup { : mainModule_(mainModule) , networkRequestCallback_(networkRequestCallback) {} - virtual ~BugsnagPerformanceImpl(); + ~BugsnagPerformanceImpl() {}; void initialize() noexcept; @@ -78,18 +78,11 @@ class BugsnagPerformanceImpl: public PhasedStartup { void startViewLoadSpan(UIViewController *controller, BugsnagPerformanceSpanOptions *options) noexcept; void endViewLoadSpan(UIViewController *controller, NSDate *endTime) noexcept; - - void onSpanStarted() noexcept; BugsnagPerformanceSpanContext *currentContext() noexcept { return mainModule_->getCoreModule()->getSpanStackingHandler()->currentSpan(); } - void setOnViewLoadSpanStarted(std::function __unused onViewLoadSpanStarted) noexcept { - // TODO -// tracer_->setOnViewLoadSpanStarted(onViewLoadSpanStarted); - } - void didStartViewLoadSpan(NSString *name) noexcept { mainModule_->getInstrumentationModule()->getInstrumentation()->didStartViewLoadSpan(name); } void willCallMainFunction() noexcept { mainModule_->getInstrumentationModule()->getInstrumentation()->willCallMainFunction(); } @@ -106,42 +99,11 @@ class BugsnagPerformanceImpl: public PhasedStartup { BugsnagPerformanceConfiguration *configuration_; std::mutex viewControllersToSpansMutex_; - CFAbsoluteTime probabilityExpiry_{0}; - CFAbsoluteTime pausePValueRequestsUntil_{0}; - NSTimer *workerTimer_{nil}; - NSTimeInterval performWorkInterval_{0}; - CFTimeInterval probabilityValueExpiresAfterSeconds_{0}; - CFTimeInterval probabilityRequestsPauseForSeconds_{0}; uint64_t maxPackageContentLength_{1000000}; std::atomic isStarted_{false}; - // Tasks - NSArray *buildInitialTasks() noexcept; - NSArray *buildRecurringTasks() noexcept; - bool sendCurrentBatchTask() noexcept; - bool sendRetriesTask() noexcept; - bool sweepTracerTask() noexcept; - - // Event reactions - void onBatchFull() noexcept; - void onConnectivityChanged(Reachability::Connectivity connectivity) noexcept; - void onProbabilityChanged(double newProbability) noexcept; - void onFilesystemError() noexcept; - void onWorkInterval() noexcept; - void onAppEnteredForeground() noexcept; - void onAppEnteredBackground() noexcept; - void onAppFinishedLaunching() noexcept; - - // Utility - void uploadPValueRequest() noexcept; - void uploadPackage(std::unique_ptr package, bool isRetry) noexcept; - NSMutableArray * - sendableSpans(NSMutableArray *spans) noexcept; - bool shouldSampleCPU(BugsnagPerformanceSpan *span) noexcept; - bool shouldSampleMemory(BugsnagPerformanceSpan *span) noexcept; - public: // For testing - void testing_setProbability(double probability) { onProbabilityChanged(probability); }; +// void testing_setProbability(double probability) { onProbabilityChanged(probability); }; NSUInteger testing_getViewControllersToSpansCount() { return viewControllersToSpans_.count; }; NSUInteger testing_getBatchCount() { return mainModule_->getCoreModule()->getBatch()->count(); diff --git a/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.mm b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.mm index 164bd505..feb0c8a3 100644 --- a/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.mm +++ b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.mm @@ -39,24 +39,6 @@ void BugsnagPerformanceImpl::configure(BugsnagPerformanceConfiguration *config) noexcept { BSGLogDebug(@"BugsnagPerformanceImpl::configure()"); maxPackageContentLength_ = config.internal.maxPackageContentLength; - for(BugsnagPerformanceSpanStartCallback callback in config.onSpanStartCallbacks) { - [spanStartCallbacks_ addObject:callback priority:BugsnagPerformancePriorityMedium]; - } - for(BugsnagPerformanceSpanEndCallback callback in config.onSpanEndCallbacks) { - [spanEndCallbacks_ addObject:callback priority:BugsnagPerformancePriorityMedium]; - } - - pluginManager_ = [[BSGPluginManager alloc] initWithConfiguration:config - compositeProvider:spanControlProvider_ - onSpanStartCallbacks:spanStartCallbacks_ - onSpanEndCallbacks:spanEndCallbacks_]; - - NSMutableArray> *defaultPlugins = [NSMutableArray array]; - - [defaultPlugins addObject:appStartTypePlugin]; - [pluginManager_ installPlugins:defaultPlugins]; - - [pluginManager_ installPlugins:config.plugins]; configuration_ = config; mainModule_->configure(config); @@ -115,52 +97,53 @@ // } //} -void BugsnagPerformanceImpl::uploadPackage(std::unique_ptr package, bool isRetry) noexcept { - BSGLogDebug(@"BugsnagPerformanceImpl::uploadPackage(package, isRetry:%s)", isRetry ? "yes" : "no"); - if (!configuration_.shouldSendReports) { - BSGLogTrace(@"BugsnagPerformanceImpl::uploadPackage: !configuration_.shouldSendReports"); - return; - } - if (package == nullptr) { - BSGLogTrace(@"BugsnagPerformanceImpl::uploadPackage: package == nullptr"); - return; - } - - // Give up waiting for the upload after 20 seconds - NSTimeInterval maxWaitInterval = 20.0; - - __block auto blockThis = this; - __block std::unique_ptr blockPackage = std::move(package); - __block auto condition = [NSCondition new]; - - [condition lock]; - uploader_->upload(*blockPackage, ^(UploadResult result) { - switch (result) { - case UploadResult::SUCCESSFUL: - if (isRetry) { - blockThis->retryQueue_->remove(blockPackage->timestamp); - } - break; - case UploadResult::FAILED_CAN_RETRY: - if (!isRetry && blockPackage->uncompressedContentLength() <= maxPackageContentLength_) { - blockThis->retryQueue_->add(*blockPackage); - } - break; - case UploadResult::FAILED_CANNOT_RETRY: - // We can't do anything with it, so throw it out. - if (isRetry) { - blockThis->retryQueue_->remove(blockPackage->timestamp); - } - break; - } - [condition lock]; - [condition signal]; - [condition unlock]; - }); - NSDate *timeoutDate = [NSDate dateWithTimeIntervalSinceNow:maxWaitInterval]; - [condition waitUntilDate:timeoutDate]; - [condition unlock]; -} +// TODO: Move to worker task +//void BugsnagPerformanceImpl::uploadPackage(std::unique_ptr package, bool isRetry) noexcept { +// BSGLogDebug(@"BugsnagPerformanceImpl::uploadPackage(package, isRetry:%s)", isRetry ? "yes" : "no"); +// if (!configuration_.shouldSendReports) { +// BSGLogTrace(@"BugsnagPerformanceImpl::uploadPackage: !configuration_.shouldSendReports"); +// return; +// } +// if (package == nullptr) { +// BSGLogTrace(@"BugsnagPerformanceImpl::uploadPackage: package == nullptr"); +// return; +// } +// +// // Give up waiting for the upload after 20 seconds +// NSTimeInterval maxWaitInterval = 20.0; +// +// __block auto blockThis = this; +// __block std::unique_ptr blockPackage = std::move(package); +// __block auto condition = [NSCondition new]; +// +// [condition lock]; +// uploader_->upload(*blockPackage, ^(UploadResult result) { +// switch (result) { +// case UploadResult::SUCCESSFUL: +// if (isRetry) { +// blockThis->retryQueue_->remove(blockPackage->timestamp); +// } +// break; +// case UploadResult::FAILED_CAN_RETRY: +// if (!isRetry && blockPackage->uncompressedContentLength() <= maxPackageContentLength_) { +// blockThis->retryQueue_->add(*blockPackage); +// } +// break; +// case UploadResult::FAILED_CANNOT_RETRY: +// // We can't do anything with it, so throw it out. +// if (isRetry) { +// blockThis->retryQueue_->remove(blockPackage->timestamp); +// } +// break; +// } +// [condition lock]; +// [condition signal]; +// [condition unlock]; +// }); +// NSDate *timeoutDate = [NSDate dateWithTimeIntervalSinceNow:maxWaitInterval]; +// [condition waitUntilDate:timeoutDate]; +// [condition unlock]; +//} #pragma mark Spans diff --git a/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.mm b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.mm index c1833300..776e4e6d 100644 --- a/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.mm +++ b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.mm @@ -79,11 +79,7 @@ } } -//BugsnagPerformanceLibrary::BugsnagPerformanceLibrary() -//: appStateTracker_([[AppStateTracker alloc] init]) -//, reachability_(std::make_shared()) -//, bugsnagPerformanceImpl_() -//{} +BugsnagPerformanceLibrary::BugsnagPerformanceLibrary() {} void BugsnagPerformanceLibrary::earlyConfigure(BSGEarlyConfiguration *config) noexcept { BSGLogDebug(@"BugsnagPerformanceLibrary::configureLibrary"); @@ -93,9 +89,6 @@ void BugsnagPerformanceLibrary::earlySetup() noexcept { BSGLogDebug(@"BugsnagPerformanceLibrary::earlySetup"); auto impl = bugsnagPerformanceImpl_; - bugsnagPerformanceImpl_->setOnViewLoadSpanStarted([=](NSString *className) { - impl->didStartViewLoadSpan(className); - }); bugsnagPerformanceImpl_->earlySetup(); } diff --git a/Sources/BugsnagPerformance/Private/Main/MainModule.mm b/Sources/BugsnagPerformance/Private/Main/MainModule.mm index e45b3cfb..926ce838 100644 --- a/Sources/BugsnagPerformance/Private/Main/MainModule.mm +++ b/Sources/BugsnagPerformance/Private/Main/MainModule.mm @@ -136,6 +136,7 @@ coreModule_->getSpanAttributesProvider(), coreModule_->getSpanStackingHandler(), coreModule_->getSampler()); + instrumentationModule_->setUp(); metricsModule_ = std::make_shared(); metricsModule_->setUp(); @@ -158,6 +159,7 @@ coreModule_->initializeComponentsCallbacks(metricsModule_->getCurrentFrameMetricsSnapshotTask(), instrumentationModule_->getAppStartupStateSnapshotTask(), instrumentationModule_->getHandleViewLoadSpanStartedTask()); + pluginSupportModule_->installPlugins(pluginsModule_->getDefaultPluginsTask()()); } NSArray * diff --git a/Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrameMetricsCollector.h b/Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrameMetricsCollector.h index 186feca3..d8ee5cd5 100644 --- a/Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrameMetricsCollector.h +++ b/Sources/BugsnagPerformance/Private/Metrics/FrameMetrics/FrameMetricsCollector.h @@ -7,7 +7,7 @@ // #pragma once -#import "../../Core/PhasedStartup.h" +#import "../../Core/BSGPhasedStartup.h" #import "FrameMetricsSnapshot.h" @interface FrameMetricsCollector: NSObject diff --git a/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.h b/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.h index 00f38fc9..6311582f 100644 --- a/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.h +++ b/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.h @@ -12,7 +12,7 @@ #import #import #import "../../Core/BSGPrioritizedStore.h" -#import "../../Core/PhasedStartup.h" +#import "../../Core/BSGPhasedStartup.h" #import "../SpanControl/BSGCompositeSpanControlProvider.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.m b/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.m index ff23873b..0ecea5ea 100644 --- a/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.m +++ b/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.m @@ -28,8 +28,9 @@ - (instancetype)initWithSpanControlProvider:(BSGCompositeSpanControlProvider *)c self = [super init]; if (self) { _compositeProvider = compositeProvider; - _onSpanStartCallbacks = onSpanStartCallbacks; - _onSpanEndCallbacks = onSpanEndCallbacks; + + _onSpanStartCallbacks = [BSGPrioritizedStore new]; + _onSpanEndCallbacks = [BSGPrioritizedStore new]; _installedPlugins = [NSMutableArray array]; } return self; @@ -83,6 +84,8 @@ - (void)configure:(BugsnagPerformanceConfiguration *)config { for(BugsnagPerformanceSpanEndCallback callback in config.onSpanEndCallbacks) { [self.onSpanEndCallbacks addObject:callback priority:BugsnagPerformancePriorityMedium]; } + + [self installPlugins:config.plugins]; } - (void)preStartSetup { diff --git a/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.h b/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.h index 64ceba1a..4dfe0acc 100644 --- a/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.h +++ b/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.h @@ -29,6 +29,10 @@ class PluginSupportModule: public Module { void setUp() noexcept; + void installPlugins(NSArray> *plugins) noexcept { + [pluginManager_ installPlugins:plugins]; + } + BSGCompositeSpanControlProvider *getSpanControlProvider() noexcept { return spanControlProvider_; } private: diff --git a/Sources/BugsnagPerformance/Private/Plugins/PluginsModule.h b/Sources/BugsnagPerformance/Private/Plugins/PluginsModule.h index 4323f949..3479c7d4 100644 --- a/Sources/BugsnagPerformance/Private/Plugins/PluginsModule.h +++ b/Sources/BugsnagPerformance/Private/Plugins/PluginsModule.h @@ -30,6 +30,11 @@ class PluginsModule: public Module { void setUp() noexcept; + // Tasks + GetPluginsTask getDefaultPluginsTask(); + + // Component access + BugsnagPerformanceAppStartTypePlugin *getAppStartTypePlugin() noexcept { return appStartTypePlugin_; } private: diff --git a/Sources/BugsnagPerformance/Private/Plugins/PluginsModule.mm b/Sources/BugsnagPerformance/Private/Plugins/PluginsModule.mm index aa4edf37..758580cf 100644 --- a/Sources/BugsnagPerformance/Private/Plugins/PluginsModule.mm +++ b/Sources/BugsnagPerformance/Private/Plugins/PluginsModule.mm @@ -10,9 +10,25 @@ using namespace bugsnag; +#pragma mark Module + void PluginsModule::setUp() noexcept { appStartTypePlugin_ = [BugsnagPerformanceAppStartTypePlugin new]; [appStartTypePlugin_ setGetAppStartInstrumentationStateCallback:^AppStartupInstrumentationStateSnapshot * _Nullable { return instrumentation_->getAppStartInstrumentationStateSnapshot(); }]; } + +#pragma mark Tasks + +GetPluginsTask +PluginsModule::getDefaultPluginsTask() { + return ^NSArray> *(){ + NSMutableArray> *defaultPlugins = [NSMutableArray array]; + if (appStartTypePlugin_ != nil) { + [defaultPlugins addObject:appStartTypePlugin_]; + } + return defaultPlugins; + }; + +} diff --git a/Sources/BugsnagPerformance/Private/Utils/Persistence.h b/Sources/BugsnagPerformance/Private/Utils/Persistence.h index 213fd2ea..428e82a7 100644 --- a/Sources/BugsnagPerformance/Private/Utils/Persistence.h +++ b/Sources/BugsnagPerformance/Private/Utils/Persistence.h @@ -12,11 +12,11 @@ #import "../Core/PhasedStartup.h" #import "../Core/Configuration/BugsnagPerformanceConfiguration+Private.h" -namespace bugsnag { - NSString *bugsnagPerformancePath(NSString *topLevelDir); NSString *bugsnagSharedPath(NSString *topLevelDir); +namespace bugsnag { + class Persistence { public: Persistence(NSString *topLevelDir) noexcept From 0befe0cfceec9a0bc61a14ace753518ca90a6833 Mon Sep 17 00:00:00 2001 From: Robert Bartoszewski Date: Thu, 23 Oct 2025 16:39:36 +0200 Subject: [PATCH 06/14] Restored Worker tasks --- BugsnagPerformance.xcodeproj/project.pbxproj | 44 ++++- .../Private/Core/CoreModule.h | 24 +-- .../Private/Core/CoreModule.mm | 5 +- .../BugsnagPerformance/Private/Core/Module.h | 2 + .../{WorkerTask.h => AsyncToSyncTask.h} | 12 +- .../Private/Core/Worker/AsyncToSyncTask.mm | 48 +++++ .../Private/Core/Worker/Worker.h | 12 +- .../Private/Core/Worker/Worker.mm | 54 ++++-- .../Private/Core/Worker/WorkerTask.mm | 9 - .../Private/Main/BugsnagPerformanceImpl.h | 13 +- .../Private/Main/BugsnagPerformanceImpl.mm | 77 -------- .../Private/Main/BugsnagPerformanceLibrary.mm | 5 +- .../Private/Main/MainModule.h | 6 +- .../Private/Main/MainModule.mm | 133 +------------ .../Private/Main/WorkerTasksBuilder.h | 45 +++++ .../Private/Main/WorkerTasksBuilder.mm | 79 ++++++++ .../PluginSupport/PluginSupportModule.h | 1 + .../Upload/UploadHandler/UploadHandler.h | 26 +++ .../Upload/UploadHandler/UploadHandlerImpl.h | 59 ++++++ .../Upload/UploadHandler/UploadHandlerImpl.mm | 180 ++++++++++++++++++ .../Private/Upload/UploadModule.h | 11 +- .../Private/Upload/UploadModule.mm | 6 + Tests/BugsnagPerformanceTests/WorkerTests.mm | 34 ++-- 23 files changed, 596 insertions(+), 289 deletions(-) rename Sources/BugsnagPerformance/Private/Core/Worker/{WorkerTask.h => AsyncToSyncTask.h} (67%) create mode 100644 Sources/BugsnagPerformance/Private/Core/Worker/AsyncToSyncTask.mm delete mode 100644 Sources/BugsnagPerformance/Private/Core/Worker/WorkerTask.mm create mode 100644 Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.h create mode 100644 Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.mm create mode 100644 Sources/BugsnagPerformance/Private/Upload/UploadHandler/UploadHandler.h create mode 100644 Sources/BugsnagPerformance/Private/Upload/UploadHandler/UploadHandlerImpl.h create mode 100644 Sources/BugsnagPerformance/Private/Upload/UploadHandler/UploadHandlerImpl.mm diff --git a/BugsnagPerformance.xcodeproj/project.pbxproj b/BugsnagPerformance.xcodeproj/project.pbxproj index 68079e32..ab659b02 100644 --- a/BugsnagPerformance.xcodeproj/project.pbxproj +++ b/BugsnagPerformance.xcodeproj/project.pbxproj @@ -209,14 +209,19 @@ 96794A192EA1A850005FD87F /* PluginSupportModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96794A182EA1A84E005FD87F /* PluginSupportModule.mm */; }; 96794A1B2EA1B06A005FD87F /* UploadModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A1A2EA1B063005FD87F /* UploadModule.h */; }; 96794A1D2EA1B074005FD87F /* UploadModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96794A1C2EA1B073005FD87F /* UploadModule.mm */; }; - 96794A1F2EA77AA6005FD87F /* WorkerTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A1E2EA77AA1005FD87F /* WorkerTask.h */; }; - 96794A212EA77AB8005FD87F /* WorkerTask.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96794A202EA77AB4005FD87F /* WorkerTask.mm */; }; + 96794A1F2EA77AA6005FD87F /* AsyncToSyncTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A1E2EA77AA1005FD87F /* AsyncToSyncTask.h */; }; + 96794A212EA77AB8005FD87F /* AsyncToSyncTask.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96794A202EA77AB4005FD87F /* AsyncToSyncTask.mm */; }; 96794A2A2EA7B103005FD87F /* AppLifecycleListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A292EA7B0F3005FD87F /* AppLifecycleListener.h */; }; 96794A2C2EA81B84005FD87F /* ModuleTaskTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A2B2EA81B80005FD87F /* ModuleTaskTypes.h */; }; 96794A312EA8450F005FD87F /* NetworkSpanReporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A302EA84508005FD87F /* NetworkSpanReporter.h */; }; 96794A332EA8451A005FD87F /* NetworkSpanReporterImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A322EA84515005FD87F /* NetworkSpanReporterImpl.h */; }; 96794A352EA84524005FD87F /* NetworkSpanReporterImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96794A342EA84520005FD87F /* NetworkSpanReporterImpl.mm */; }; 96794A372EA97C76005FD87F /* BSGPhasedStartup.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A362EA97C73005FD87F /* BSGPhasedStartup.h */; }; + 96794A392EA99C9A005FD87F /* WorkerTasksBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A382EA99C91005FD87F /* WorkerTasksBuilder.h */; }; + 96794A3B2EA99CA2005FD87F /* WorkerTasksBuilder.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96794A3A2EA99CA0005FD87F /* WorkerTasksBuilder.mm */; }; + 96794A402EAA10A6005FD87F /* UploadHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A3F2EAA109F005FD87F /* UploadHandler.h */; }; + 96794A422EAA10F4005FD87F /* UploadHandlerImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A412EAA10EB005FD87F /* UploadHandlerImpl.h */; }; + 96794A442EAA10FB005FD87F /* UploadHandlerImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96794A432EAA10F9005FD87F /* UploadHandlerImpl.mm */; }; 967F6F1829C3783B0054EED8 /* BugsnagPerformanceConfiguration+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 967F6F1729C3782D0054EED8 /* BugsnagPerformanceConfiguration+Private.h */; }; 968AA5FB2CCA5A9200BA69CF /* BSGPerformanceSharedSessionProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 968AA5FA2CCA5A9200BA69CF /* BSGPerformanceSharedSessionProxy.h */; }; 968AA5FD2CCA5AB000BA69CF /* BSGPerformanceSharedSessionProxy.mm in Sources */ = {isa = PBXBuildFile; fileRef = 968AA5FC2CCA5AB000BA69CF /* BSGPerformanceSharedSessionProxy.mm */; }; @@ -596,14 +601,19 @@ 96794A182EA1A84E005FD87F /* PluginSupportModule.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PluginSupportModule.mm; sourceTree = ""; }; 96794A1A2EA1B063005FD87F /* UploadModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UploadModule.h; sourceTree = ""; }; 96794A1C2EA1B073005FD87F /* UploadModule.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = UploadModule.mm; sourceTree = ""; }; - 96794A1E2EA77AA1005FD87F /* WorkerTask.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WorkerTask.h; sourceTree = ""; }; - 96794A202EA77AB4005FD87F /* WorkerTask.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WorkerTask.mm; sourceTree = ""; }; + 96794A1E2EA77AA1005FD87F /* AsyncToSyncTask.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AsyncToSyncTask.h; sourceTree = ""; }; + 96794A202EA77AB4005FD87F /* AsyncToSyncTask.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AsyncToSyncTask.mm; sourceTree = ""; }; 96794A292EA7B0F3005FD87F /* AppLifecycleListener.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppLifecycleListener.h; sourceTree = ""; }; 96794A2B2EA81B80005FD87F /* ModuleTaskTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ModuleTaskTypes.h; sourceTree = ""; }; 96794A302EA84508005FD87F /* NetworkSpanReporter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NetworkSpanReporter.h; sourceTree = ""; }; 96794A322EA84515005FD87F /* NetworkSpanReporterImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NetworkSpanReporterImpl.h; sourceTree = ""; }; 96794A342EA84520005FD87F /* NetworkSpanReporterImpl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkSpanReporterImpl.mm; sourceTree = ""; }; 96794A362EA97C73005FD87F /* BSGPhasedStartup.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BSGPhasedStartup.h; sourceTree = ""; }; + 96794A382EA99C91005FD87F /* WorkerTasksBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WorkerTasksBuilder.h; sourceTree = ""; }; + 96794A3A2EA99CA0005FD87F /* WorkerTasksBuilder.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WorkerTasksBuilder.mm; sourceTree = ""; }; + 96794A3F2EAA109F005FD87F /* UploadHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UploadHandler.h; sourceTree = ""; }; + 96794A412EAA10EB005FD87F /* UploadHandlerImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UploadHandlerImpl.h; sourceTree = ""; }; + 96794A432EAA10F9005FD87F /* UploadHandlerImpl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = UploadHandlerImpl.mm; sourceTree = ""; }; 967F6F1729C3782D0054EED8 /* BugsnagPerformanceConfiguration+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BugsnagPerformanceConfiguration+Private.h"; sourceTree = ""; }; 968AA5FA2CCA5A9200BA69CF /* BSGPerformanceSharedSessionProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BSGPerformanceSharedSessionProxy.h; sourceTree = ""; }; 968AA5FC2CCA5AB000BA69CF /* BSGPerformanceSharedSessionProxy.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = BSGPerformanceSharedSessionProxy.mm; sourceTree = ""; }; @@ -1248,6 +1258,8 @@ CB78819A29E587CE00A58906 /* BugsnagPerformanceLibrary.mm */, 967949FB2EA16458005FD87F /* MainModule.h */, 967949FD2EA16463005FD87F /* MainModule.mm */, + 96794A382EA99C91005FD87F /* WorkerTasksBuilder.h */, + 96794A3A2EA99CA0005FD87F /* WorkerTasksBuilder.mm */, ); path = Main; sourceTree = ""; @@ -1303,6 +1315,7 @@ 967949DA2EA0592E005FD87F /* Otlp */, CBEC51DA2976F1F9009C0CE3 /* RetryQueue.h */, CBEC51DB2976F1F9009C0CE3 /* RetryQueue.mm */, + 96794A3C2EAA107C005FD87F /* UploadHandler */, 96794A1A2EA1B063005FD87F /* UploadModule.h */, 96794A1C2EA1B073005FD87F /* UploadModule.mm */, ); @@ -1413,8 +1426,8 @@ children = ( CBE8EA18294B5AB800702950 /* Worker.h */, CBE8EA19294B5AB800702950 /* Worker.mm */, - 96794A1E2EA77AA1005FD87F /* WorkerTask.h */, - 96794A202EA77AB4005FD87F /* WorkerTask.mm */, + 96794A1E2EA77AA1005FD87F /* AsyncToSyncTask.h */, + 96794A202EA77AB4005FD87F /* AsyncToSyncTask.mm */, ); path = Worker; sourceTree = ""; @@ -1460,6 +1473,16 @@ path = NetworkSpanReporter; sourceTree = ""; }; + 96794A3C2EAA107C005FD87F /* UploadHandler */ = { + isa = PBXGroup; + children = ( + 96794A3F2EAA109F005FD87F /* UploadHandler.h */, + 96794A412EAA10EB005FD87F /* UploadHandlerImpl.h */, + 96794A432EAA10F9005FD87F /* UploadHandlerImpl.mm */, + ); + path = UploadHandler; + sourceTree = ""; + }; 969EE0EE2E7872A600600F63 /* SpanFactory */ = { isa = PBXGroup; children = ( @@ -1645,6 +1668,7 @@ 967949BF2E993749005FD87F /* SpanStoreImpl.h in Headers */, 09F23A8C2CE351ED00F0D769 /* BugsnagSwiftTools.h in Headers */, 0921F02B2A67CBD600C764EB /* BugsnagPerformanceNetworkRequestInfo.h in Headers */, + 96794A392EA99C9A005FD87F /* WorkerTasksBuilder.h in Headers */, 962CE7D52E60967A00380522 /* BugsnagPerformanceLoadingIndicatorView+Private.h in Headers */, 963726CA2DEAB24900C739E6 /* BugsnagPerformancePriority+Private.h in Headers */, 96794A052EA16655005FD87F /* UtilsModule.h in Headers */, @@ -1669,6 +1693,7 @@ 098FC84E2D350E60001B627D /* FixedLengthDequeue.h in Headers */, CB78819D29E587CE00A58906 /* BugsnagPerformanceLibrary.h in Headers */, 967949BA2E97D5A5005FD87F /* SpanLifecycleHandlerImpl.h in Headers */, + 96794A422EAA10F4005FD87F /* UploadHandlerImpl.h in Headers */, 098FC8462D2EB8E8001B627D /* BSGPSystemInfo.h in Headers */, CB572EAA29BB783200FD7A2A /* AppStateTracker.h in Headers */, CBEC51DC2976F1F9009C0CE3 /* RetryQueue.h in Headers */, @@ -1681,7 +1706,7 @@ 962CE7DD2E60987600380522 /* ViewLoadEarlyPhaseHandler.h in Headers */, 962CE8042E6519D900380522 /* NetworkInstrumentationState.h in Headers */, CBE8EA1A294B5AB800702950 /* Worker.h in Headers */, - 96794A1F2EA77AA6005FD87F /* WorkerTask.h in Headers */, + 96794A1F2EA77AA6005FD87F /* AsyncToSyncTask.h in Headers */, CBE8EA16294B528100702950 /* BugsnagPerformanceImpl.h in Headers */, 963726E22DF101E700C739E6 /* BugsnagPerformancePluginContext+Private.h in Headers */, 967F6F1829C3783B0054EED8 /* BugsnagPerformanceConfiguration+Private.h in Headers */, @@ -1717,6 +1742,7 @@ 963829382E5623F100404F3A /* ViewLoadSwizzlingHandlerImpl.h in Headers */, 1C3C0C612E2922080037B416 /* BugsnagPerformanceLoadingIndicatorView.h in Headers */, CBEC51B8296D8386009C0CE3 /* Persistence.h in Headers */, + 96794A402EAA10A6005FD87F /* UploadHandler.h in Headers */, 963829212E5542A700404F3A /* AppStartupInstrumentationStateSnapshot.h in Headers */, 9638291B2E54B48E00404F3A /* AppStartupLifecycleHandler.h in Headers */, 96794A0B2EA19AC5005FD87F /* MetricsModule.h in Headers */, @@ -2065,6 +2091,7 @@ CB0AD7682965734F002A3FB6 /* BugsnagPerformanceErrors.m in Sources */, 0122C24E29019770002D243C /* OtlpTraceEncoding.mm in Sources */, 098FC8472D2EB8E8001B627D /* BSGPSystemInfo.mm in Sources */, + 96794A3B2EA99CA2005FD87F /* WorkerTasksBuilder.mm in Sources */, 0122C24929019770002D243C /* AppStartupInstrumentation.mm in Sources */, 9638290A2E547D2300404F3A /* ViewLoadInstrumentationState.m in Sources */, 969EE1002E794A1100600F63 /* ViewLoadSpanFactoryCallbacks.mm in Sources */, @@ -2091,6 +2118,7 @@ 966634DC2C8A39C1004A934D /* FrozenFrameData.mm in Sources */, 96794A032EA165DA005FD87F /* CoreModule.mm in Sources */, 9638293A2E56240900404F3A /* ViewLoadSwizzlingHandlerImpl.mm in Sources */, + 96794A442EAA10FB005FD87F /* UploadHandlerImpl.mm in Sources */, 0122C23E29019770002D243C /* BugsnagPerformanceSpan.mm in Sources */, 0987F27A2C32D4AD00777FD8 /* BugsnagPerformanceSpanContext.mm in Sources */, 09F23A8D2CE351ED00F0D769 /* BugsnagSwiftTools.m in Sources */, @@ -2133,7 +2161,7 @@ CB68FABA2A3C27B9005B2CDB /* PersistentDeviceID.mm in Sources */, CBF7C5E2297A8E9100D47719 /* Gzip.m in Sources */, 967949CF2E9DCB06005FD87F /* SpanProcessingPipelineImpl.mm in Sources */, - 96794A212EA77AB8005FD87F /* WorkerTask.mm in Sources */, + 96794A212EA77AB8005FD87F /* AsyncToSyncTask.mm in Sources */, 0122C24829019770002D243C /* NetworkInstrumentation.mm in Sources */, 962CE8062E6519E200380522 /* NetworkInstrumentationState.m in Sources */, 962CE82A2E67189F00380522 /* NetworkEarlyPhaseHandlerImpl.mm in Sources */, diff --git a/Sources/BugsnagPerformance/Private/Core/CoreModule.h b/Sources/BugsnagPerformance/Private/Core/CoreModule.h index 87a10c50..fadea189 100644 --- a/Sources/BugsnagPerformance/Private/Core/CoreModule.h +++ b/Sources/BugsnagPerformance/Private/Core/CoreModule.h @@ -32,6 +32,8 @@ #import "../Metrics/FrameMetrics/FrameMetricsSnapshot.h" #import "../Instrumentation/AppStartupInstrumentation/State/AppStartupInstrumentationStateSnapshot.h" +#import + namespace bugsnag { class CoreModule: public Module, public AppLifecycleListener { public: @@ -52,12 +54,6 @@ class CoreModule: public Module, public AppLifecycleListener { void preStartSetup() noexcept; void start() noexcept; - void initialize(NSArray *initialTasks, - NSArray *recurringTasks) noexcept { - initialTasks_ = initialTasks; - recurringTasks_ = recurringTasks; - } - void setUp() noexcept; void onAppFinishedLaunching() noexcept {} void onAppEnteredBackground() noexcept; @@ -71,6 +67,16 @@ class CoreModule: public Module, public AppLifecycleListener { viewLoadSpanFactory_->setup(createViewLoadSpanFactoryCallbacks(onViewLoadSpanStarted, getAppStartupStateSnapshot)); } + void initializeWorkerTasks(std::vector> initialTasks, + std::vector> recurringTasks) { + for (const auto &task : initialTasks) { + [worker_ addInitialTask:task]; + } + for (const auto &task : recurringTasks) { + [worker_ addRecurringTask:task]; + } + } + // Tasks UpdateProbabilityTask getUpdateProbabilityTask() noexcept; @@ -98,10 +104,6 @@ class CoreModule: public Module, public AppLifecycleListener { bool isStarted_{false}; BugsnagPerformanceConfiguration *configuration_; - CFAbsoluteTime probabilityExpiry_{0}; - - CFTimeInterval probabilityValueExpiresAfterSeconds_{0}; - CFTimeInterval probabilityRequestsPauseForSeconds_{0}; NSTimer *workerTimer_{nil}; @@ -110,8 +112,6 @@ class CoreModule: public Module, public AppLifecycleListener { std::shared_ptr reachability_; std::shared_ptr persistence_; std::shared_ptr deviceID_; - NSArray *initialTasks_; - NSArray *recurringTasks_; std::function getAppStartupInstrumentationState_{ [](){ return nil; } }; // Components diff --git a/Sources/BugsnagPerformance/Private/Core/CoreModule.mm b/Sources/BugsnagPerformance/Private/Core/CoreModule.mm index 7a33fffc..410d02d7 100644 --- a/Sources/BugsnagPerformance/Private/Core/CoreModule.mm +++ b/Sources/BugsnagPerformance/Private/Core/CoreModule.mm @@ -41,8 +41,6 @@ void CoreModule::configure(BugsnagPerformanceConfiguration *config) noexcept { configuration_ = config; - probabilityValueExpiresAfterSeconds_ = config.internal.probabilityValueExpiresAfterSeconds; - probabilityRequestsPauseForSeconds_ = config.internal.probabilityRequestsPauseForSeconds; persistentState_->configure(config); plainSpanFactory_->configure(config); resourceAttributes_->configure(config); @@ -126,7 +124,7 @@ resourceAttributes_ = std::make_shared(deviceID_); networkSpanReporter_ = std::make_shared(spanAttributesProvider_, networkSpanFactory_); - worker_ = [[Worker alloc] initWithInitialTasks:initialTasks_ recurringTasks:recurringTasks_]; + worker_ = [Worker worker]; } #pragma mark Tasks @@ -139,7 +137,6 @@ BSGLogTrace(@"CoreModule::getUpdateProbabilityTask: configuration_.samplingProbability != nil"); return; } - blockThis->probabilityExpiry_ = CFAbsoluteTimeGetCurrent() + probabilityValueExpiresAfterSeconds_; blockThis->sampler_->setProbability(newProbability); blockThis->persistentState_->setProbability(newProbability); }; diff --git a/Sources/BugsnagPerformance/Private/Core/Module.h b/Sources/BugsnagPerformance/Private/Core/Module.h index 0a5182be..d10817fd 100644 --- a/Sources/BugsnagPerformance/Private/Core/Module.h +++ b/Sources/BugsnagPerformance/Private/Core/Module.h @@ -6,6 +6,8 @@ // Copyright © 2025 Bugsnag. All rights reserved. // +#pragma once + #import "PhasedStartup.h" #import "ModuleTaskTypes.h" diff --git a/Sources/BugsnagPerformance/Private/Core/Worker/WorkerTask.h b/Sources/BugsnagPerformance/Private/Core/Worker/AsyncToSyncTask.h similarity index 67% rename from Sources/BugsnagPerformance/Private/Core/Worker/WorkerTask.h rename to Sources/BugsnagPerformance/Private/Core/Worker/AsyncToSyncTask.h index ec981b2f..e37858d2 100644 --- a/Sources/BugsnagPerformance/Private/Core/Worker/WorkerTask.h +++ b/Sources/BugsnagPerformance/Private/Core/Worker/AsyncToSyncTask.h @@ -1,5 +1,5 @@ // -// WorkerTask.h +// AsyncToSyncTask.h // BugsnagPerformance // // Created by Robert Bartoszewski on 20/10/2025. @@ -8,21 +8,25 @@ #pragma once +#import + typedef void (^TaskCompletion)(bool); typedef void (^TaskWork)(TaskCompletion); namespace bugsnag { -class WorkerTask { +class AsyncToSyncTask { public: - WorkerTask(TaskWork work) noexcept + AsyncToSyncTask(TaskWork work) noexcept : work_(work) {} bool executeSync(); - ~WorkerTask() {} + ~AsyncToSyncTask() {} private: TaskWork work_{nullptr}; + + std::recursive_mutex mutex_; }; } diff --git a/Sources/BugsnagPerformance/Private/Core/Worker/AsyncToSyncTask.mm b/Sources/BugsnagPerformance/Private/Core/Worker/AsyncToSyncTask.mm new file mode 100644 index 00000000..22433495 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Core/Worker/AsyncToSyncTask.mm @@ -0,0 +1,48 @@ +// +// AsyncToSyncTask.mm +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 20/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#import +#import "AsyncToSyncTask.h" + +const NSTimeInterval maxWaitInterval = 20.0; + +using namespace bugsnag; + +bool +AsyncToSyncTask::executeSync() { + __block auto blockThis = this; + __block BOOL result = NO; + __block BOOL didComplete = NO; + __block BOOL isWaiting = NO; + __block auto condition = [NSCondition new]; + + mutex_.lock(); + [condition lock]; + work_(^(bool workResult){ + result = workResult; + didComplete = YES; + blockThis->mutex_.lock(); + if (isWaiting) { + [condition lock]; + [condition signal]; + [condition unlock]; + } + blockThis->mutex_.unlock(); + }); + + isWaiting = YES; + mutex_.unlock(); + + NSDate *timeoutDate = [NSDate dateWithTimeIntervalSinceNow:maxWaitInterval]; + while (timeoutDate.timeIntervalSinceNow > 0 && !didComplete) { + [condition waitUntilDate:timeoutDate]; + } + [condition unlock]; + + return result; +} diff --git a/Sources/BugsnagPerformance/Private/Core/Worker/Worker.h b/Sources/BugsnagPerformance/Private/Core/Worker/Worker.h index d9721755..dabcd71e 100644 --- a/Sources/BugsnagPerformance/Private/Core/Worker/Worker.h +++ b/Sources/BugsnagPerformance/Private/Core/Worker/Worker.h @@ -9,18 +9,24 @@ #pragma once #import +#import "AsyncToSyncTask.h" #import "../BSGPhasedStartup.h" -NS_ASSUME_NONNULL_BEGIN +#import + +using namespace bugsnag; -typedef bool (^Task)(); +NS_ASSUME_NONNULL_BEGIN /** * The worker performs a set series of tasks on a background thread. */ @interface Worker : NSObject -- (instancetype) initWithInitialTasks:(NSArray *)initialTasks recurringTasks:(NSArray *)recurringTasks; ++ (instancetype)worker; + +- (void)addInitialTask:(std::shared_ptr)task; +- (void)addRecurringTask:(std::shared_ptr)task; /** * Wake the worker to run through the recurring tasks until none of them do any work. diff --git a/Sources/BugsnagPerformance/Private/Core/Worker/Worker.mm b/Sources/BugsnagPerformance/Private/Core/Worker/Worker.mm index 0de03c39..64aa48b5 100644 --- a/Sources/BugsnagPerformance/Private/Core/Worker/Worker.mm +++ b/Sources/BugsnagPerformance/Private/Core/Worker/Worker.mm @@ -8,6 +8,7 @@ #import "Worker.h" #import "../Configuration/BugsnagPerformanceConfiguration+Private.h" +#import @interface Worker () @@ -16,42 +17,71 @@ @interface Worker () @property(readwrite,atomic) BOOL shouldEnd; @property(readonly,nonatomic) NSCondition *condition; @property(readonly,nonatomic) NSThread *thread; -@property(readwrite,nonatomic) NSArray *initialTasks; -@property(readonly,nonatomic) NSArray *recurringTasks; +@property(nonatomic) std::vector> initialTasks; +@property(nonatomic) std::vector> recurringTasks; @end @implementation Worker -- (instancetype) initWithInitialTasks:(NSArray *)initialTasks - recurringTasks:(NSArray *)recurringTasks { ++ (instancetype)worker { + return [self new]; +} + +- (instancetype)init { if ((self = [super init])) { _condition = [[NSCondition alloc] init]; _thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil]; - _initialTasks = initialTasks; - _recurringTasks = recurringTasks; + _initialTasks = std::vector>(); + _recurringTasks = std::vector>(); _isStarted = false; _shouldEnd = false; } return self; } -- (void) performInitialWork { +- (void)addInitialTask:(std::shared_ptr)task { + @synchronized (self) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + _initialTasks.push_back(task); +#pragma clang diagnostic pop + } +} + +- (void)addRecurringTask:(std::shared_ptr)task { + @synchronized (self) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + _recurringTasks.push_back(task); +#pragma clang diagnostic pop + } +} + +- (void)performInitialWork { @autoreleasepool { - for (Task task in self.initialTasks) { - task(); + @synchronized (self) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + for (const auto &task : _initialTasks) { + task->executeSync(); + } + _initialTasks.clear(); +#pragma clang diagnostic pop } - self.initialTasks = nil; } } - (bool) performRecurringWork { bool performedWork = false; - for (Task task in self.recurringTasks) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + for (const auto &task : _recurringTasks) { @autoreleasepool { - performedWork |= task(); + performedWork |= task->executeSync(); } } +#pragma clang diagnostic pop return performedWork; } diff --git a/Sources/BugsnagPerformance/Private/Core/Worker/WorkerTask.mm b/Sources/BugsnagPerformance/Private/Core/Worker/WorkerTask.mm deleted file mode 100644 index 46697aa0..00000000 --- a/Sources/BugsnagPerformance/Private/Core/Worker/WorkerTask.mm +++ /dev/null @@ -1,9 +0,0 @@ -// -// WorkerTask.mm -// BugsnagPerformance -// -// Created by Robert Bartoszewski on 20/10/2025. -// Copyright © 2025 Bugsnag. All rights reserved. -// - - diff --git a/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.h b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.h index 6cda505c..be85500e 100644 --- a/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.h +++ b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.h @@ -45,10 +45,8 @@ namespace bugsnag { class BugsnagPerformanceImpl: public PhasedStartup { public: - BugsnagPerformanceImpl(std::shared_ptr mainModule, - BugsnagPerformanceNetworkRequestCallback networkRequestCallback) noexcept - : mainModule_(mainModule) - , networkRequestCallback_(networkRequestCallback) {} + BugsnagPerformanceImpl(std::shared_ptr mainModule) noexcept + : mainModule_(mainModule) {} ~BugsnagPerformanceImpl() {}; @@ -93,17 +91,14 @@ class BugsnagPerformanceImpl: public PhasedStartup { void loadingIndicatorWasAdded(BugsnagPerformanceLoadingIndicatorView *loadingViewIndicator) noexcept; private: + BugsnagPerformanceConfiguration *configuration_; + std::shared_ptr mainModule_; NSMapTable *viewControllersToSpans_; - BugsnagPerformanceNetworkRequestCallback networkRequestCallback_; - - BugsnagPerformanceConfiguration *configuration_; std::mutex viewControllersToSpansMutex_; - uint64_t maxPackageContentLength_{1000000}; std::atomic isStarted_{false}; public: // For testing -// void testing_setProbability(double probability) { onProbabilityChanged(probability); }; NSUInteger testing_getViewControllersToSpansCount() { return viewControllersToSpans_.count; }; NSUInteger testing_getBatchCount() { return mainModule_->getCoreModule()->getBatch()->count(); diff --git a/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.mm b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.mm index feb0c8a3..0f3b09cf 100644 --- a/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.mm +++ b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceImpl.mm @@ -37,9 +37,6 @@ } void BugsnagPerformanceImpl::configure(BugsnagPerformanceConfiguration *config) noexcept { - BSGLogDebug(@"BugsnagPerformanceImpl::configure()"); - maxPackageContentLength_ = config.internal.maxPackageContentLength; - configuration_ = config; mainModule_->configure(config); } @@ -66,85 +63,11 @@ #pragma mark Event Reactions - -// TODO: Replace with worker task -//void BugsnagPerformanceImpl::onSpanStarted() noexcept { -// // If a span starts before we've started Bugsnag, there won't be an uploader yet. -// if (uploader_ != nullptr) { -// if (CFAbsoluteTimeGetCurrent() > probabilityExpiry_) { -// uploadPValueRequest(); -// } -// } -//} - void BugsnagPerformanceImpl::loadingIndicatorWasAdded(BugsnagPerformanceLoadingIndicatorView *loadingViewIndicator) noexcept { mainModule_->getInstrumentationModule()->loadingIndicatorWasAdded(loadingViewIndicator); } -#pragma mark Utility - -// TODO: Initial task -//void BugsnagPerformanceImpl::uploadPValueRequest() noexcept { -// if (!configuration_.shouldSendReports || configuration_.samplingProbability != nil) { -// return; -// } -// auto currentTime = CFAbsoluteTimeGetCurrent(); -// if (currentTime > pausePValueRequestsUntil_) { -// // Pause P-value requests so that we don't flood the server on every span start -// pausePValueRequestsUntil_ = currentTime + probabilityRequestsPauseForSeconds_; -// uploader_->upload(*traceEncoding_.buildPValueRequestPackage(), nil); -// } -//} - -// TODO: Move to worker task -//void BugsnagPerformanceImpl::uploadPackage(std::unique_ptr package, bool isRetry) noexcept { -// BSGLogDebug(@"BugsnagPerformanceImpl::uploadPackage(package, isRetry:%s)", isRetry ? "yes" : "no"); -// if (!configuration_.shouldSendReports) { -// BSGLogTrace(@"BugsnagPerformanceImpl::uploadPackage: !configuration_.shouldSendReports"); -// return; -// } -// if (package == nullptr) { -// BSGLogTrace(@"BugsnagPerformanceImpl::uploadPackage: package == nullptr"); -// return; -// } -// -// // Give up waiting for the upload after 20 seconds -// NSTimeInterval maxWaitInterval = 20.0; -// -// __block auto blockThis = this; -// __block std::unique_ptr blockPackage = std::move(package); -// __block auto condition = [NSCondition new]; -// -// [condition lock]; -// uploader_->upload(*blockPackage, ^(UploadResult result) { -// switch (result) { -// case UploadResult::SUCCESSFUL: -// if (isRetry) { -// blockThis->retryQueue_->remove(blockPackage->timestamp); -// } -// break; -// case UploadResult::FAILED_CAN_RETRY: -// if (!isRetry && blockPackage->uncompressedContentLength() <= maxPackageContentLength_) { -// blockThis->retryQueue_->add(*blockPackage); -// } -// break; -// case UploadResult::FAILED_CANNOT_RETRY: -// // We can't do anything with it, so throw it out. -// if (isRetry) { -// blockThis->retryQueue_->remove(blockPackage->timestamp); -// } -// break; -// } -// [condition lock]; -// [condition signal]; -// [condition unlock]; -// }); -// NSDate *timeoutDate = [NSDate dateWithTimeIntervalSinceNow:maxWaitInterval]; -// [condition waitUntilDate:timeoutDate]; -// [condition unlock]; -//} - #pragma mark Spans BugsnagPerformanceSpan * diff --git a/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.mm b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.mm index 776e4e6d..8cc92700 100644 --- a/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.mm +++ b/Sources/BugsnagPerformance/Private/Main/BugsnagPerformanceLibrary.mm @@ -112,9 +112,6 @@ } void BugsnagPerformanceLibrary::initialize() noexcept { - bugsnagPerformanceImpl_ = std::make_shared(std::make_shared(), - ^BugsnagPerformanceNetworkRequestInfo * _Nonnull(BugsnagPerformanceNetworkRequestInfo * _Nonnull info) { - return info; - }); + bugsnagPerformanceImpl_ = std::make_shared(std::make_shared()); bugsnagPerformanceImpl_->initialize(); } diff --git a/Sources/BugsnagPerformance/Private/Main/MainModule.h b/Sources/BugsnagPerformance/Private/Main/MainModule.h index bd995849..3548f22f 100644 --- a/Sources/BugsnagPerformance/Private/Main/MainModule.h +++ b/Sources/BugsnagPerformance/Private/Main/MainModule.h @@ -8,6 +8,7 @@ #pragma once +#import "WorkerTasksBuilder.h" #import "../Core/Module.h" #import "../Core/AppLifecycleListener.h" #import "../Core/CoreModule.h" @@ -59,9 +60,10 @@ class MainModule: public Module, public AppLifecycleListener { std::shared_ptr pluginsModule_; std::shared_ptr pluginSupportModule_; std::shared_ptr uploadModule_; + std::shared_ptr workerTasksBuilder_; void initializeModules() noexcept; - NSArray *buildInitialTasks() noexcept; - NSArray *buildRecurringTasks() noexcept; + std::vector> buildInitialTasks() noexcept; + std::vector> buildRecurringTasks() noexcept; }; } diff --git a/Sources/BugsnagPerformance/Private/Main/MainModule.mm b/Sources/BugsnagPerformance/Private/Main/MainModule.mm index 926ce838..e8add2c1 100644 --- a/Sources/BugsnagPerformance/Private/Main/MainModule.mm +++ b/Sources/BugsnagPerformance/Private/Main/MainModule.mm @@ -128,7 +128,6 @@ utilsModule_->getReachability(), utilsModule_->getPersistence(), utilsModule_->getDeviceID()); - coreModule_->initialize(buildInitialTasks(), buildRecurringTasks()); // TODO coreModule_->setUp(); instrumentationModule_ = std::make_shared(coreModule_->getAppStartupSpanFactory(), coreModule_->getViewLoadSpanFactory(), @@ -150,7 +149,8 @@ pluginSupportModule_ = std::make_shared(); pluginSupportModule_->setUp(); - uploadModule_ = std::make_shared(utilsModule_->getPersistence()); + uploadModule_ = std::make_shared(utilsModule_->getPersistence(), + coreModule_->getResourceAttributes()); uploadModule_->setUp(); utilsModule_->initializeComponentsCallbacks(coreModule_->getUpdateConnectivityTask()); @@ -160,127 +160,10 @@ instrumentationModule_->getAppStartupStateSnapshotTask(), instrumentationModule_->getHandleViewLoadSpanStartedTask()); pluginSupportModule_->installPlugins(pluginsModule_->getDefaultPluginsTask()()); + + workerTasksBuilder_ = std::make_shared(coreModule_->getSpanStore(), + uploadModule_->getUploadHandler(), + pluginSupportModule_->getPluginManager()); + coreModule_->initializeWorkerTasks(workerTasksBuilder_->buildInitialTasks(), + workerTasksBuilder_->buildRecurringTasks()); } - -NSArray * -MainModule::buildInitialTasks() noexcept { -// __block auto blockThis = this; - return @[ -// ^bool() { -// [blockThis->pluginSupportModule_->getPluginManager() startPlugins]; -// return true; -// }, - ]; -} - -NSArray * -MainModule::buildRecurringTasks() noexcept { -// __block auto blockThis = this; - return @[ -// ^bool() { return blockThis->sendCurrentBatchTask(); }, -// ^bool() { return blockThis->sendRetriesTask(); }, -// ^bool() { return blockThis->sweepTracerTask(); }, - ]; -} -// -//NSMutableArray * -//BugsnagPerformanceImpl::sendableSpans(NSMutableArray *spans) noexcept { -// NSMutableArray *sendableSpans = [NSMutableArray arrayWithCapacity:spans.count]; -// for (BugsnagPerformanceSpan *span in spans) { -// if (span.state != SpanStateAborted && sampler_->sampled(span)) { -// [sendableSpans addObject:span]; -// } -// } -// return sendableSpans; -//} -// -//bool BugsnagPerformanceImpl::shouldSampleCPU(BugsnagPerformanceSpan *span) noexcept { -// if (span.metricsOptions.cpu == BSGTriStateUnset) { -// return span.firstClass == BSGTriStateYes; -// } -// return span.metricsOptions.cpu == BSGTriStateYes; -//} -// -//bool BugsnagPerformanceImpl::shouldSampleMemory(BugsnagPerformanceSpan *span) noexcept { -// if (span.metricsOptions.memory == BSGTriStateUnset) { -// return span.firstClass == BSGTriStateYes; -// } -// return span.metricsOptions.memory == BSGTriStateYes; -//} -// -//bool BugsnagPerformanceImpl::sendCurrentBatchTask() noexcept { -// BSGLogDebug(@"BugsnagPerformanceImpl::sendCurrentBatchTask()"); -// auto origSpans = batch_->drain(false); -//#ifndef __clang_analyzer__ -// #pragma clang diagnostic ignored "-Wunused-variable" -// size_t origSpansSize = origSpans.count; -//#endif -// auto spans = sendableSpans(origSpans); -// if (spans.count == 0) { -//#ifndef __clang_analyzer__ -// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Nothing to send. origSpans size = %zu", origSpansSize); -//#endif -// return false; -// } -// bool includeSamplingHeader = configuration_ == nil || configuration_.samplingProbability == nil; -// -// // Delay so that the sampler has time to fetch one more sample. -// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Delaying %f seconds (%lld ns) before getting system info", SAMPLER_INTERVAL_SECONDS + 0.5, (int64_t)((SAMPLER_INTERVAL_SECONDS + 0.5) * NSEC_PER_SEC)); -// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((SAMPLER_INTERVAL_SECONDS + 0.5) * NSEC_PER_SEC)), -// dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{ -// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Delayed %f seconds, now getting system info", SAMPLER_INTERVAL_SECONDS + 0.5); -// for(BugsnagPerformanceSpan *span: spans) { -// auto samples = systemInfoSampler_.samplesAroundTimePeriod(span.actuallyStartedAt, span.actuallyEndedAt); -// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): System info sample size = %zu", samples.size()); -// if (samples.size() >= 2) { -// if (shouldSampleCPU(span)) { -// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Getting CPU sample attributes for span %@", span.name); -// [span forceMutate:^() { -// [span internalSetMultipleAttributes:spanAttributesProvider_->cpuSampleAttributes(samples)]; -// }]; -// } -// if (shouldSampleMemory(span)) { -// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Getting memory sample attributes for span %@", span.name); -// [span forceMutate:^() { -// [span internalSetMultipleAttributes:spanAttributesProvider_->memorySampleAttributes(samples)]; -// }]; -// } -// } -// } -// -//#ifndef __clang_analyzer__ -// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Sending %zu sampled spans (out of %zu)", origSpansSize, spans.count); -//#endif -// uploadPackage(traceEncoding_.buildUploadPackage(spans, resourceAttributes_->get(), includeSamplingHeader), false); -// }); -// -// return true; -//} -// -//bool BugsnagPerformanceImpl::sendRetriesTask() noexcept { -// BSGLogDebug(@"BugsnagPerformanceImpl::sendRetriesTask()"); -// retryQueue_->sweep(); -// -// auto retries = retryQueue_->list(); -// if (retries.size() == 0) { -// BSGLogTrace(@"BugsnagPerformanceImpl::sendRetriesTask(): No retries to send"); -// return false; -// } -// -// for (auto &×tamp: retries) { -// auto retry = retryQueue_->get(timestamp); -// if (retry != nullptr) { -// uploadPackage(std::move(retry), true); -// } -// } -// -// // Retries never count as work, otherwise we'd loop endlessly on a network outage. -// return false; -//} -// -//bool BugsnagPerformanceImpl::sweepTracerTask() noexcept { -// BSGLogDebug(@"BugsnagPerformanceImpl::sweepTracerTask()"); -// spanStore_->sweep(); -// // Never auto-repeat this task, even if work was done; it can wait. -// return false; -//} diff --git a/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.h b/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.h new file mode 100644 index 00000000..7f1e5043 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.h @@ -0,0 +1,45 @@ +// +// WorkerTasksBuilder.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 23/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#pragma once + +#import "../Core/Worker/AsyncToSyncTask.h" +#import "../Core/SpanStore/SpanStore.h" +#import "../PluginSupport/PluginManager/BSGPluginManager.h" +#import "../Upload/UploadHandler/UploadHandler.h" + +#import +#import + +namespace bugsnag { +class WorkerTasksBuilder { +public: + WorkerTasksBuilder(std::shared_ptr spanStore, + std::shared_ptr uploadHandler, + BSGPluginManager *pluginManager) noexcept + : spanStore_(spanStore) + , uploadHandler_(uploadHandler) + , pluginManager_(pluginManager) {}; + + ~WorkerTasksBuilder() {}; + + std::vector> buildInitialTasks() noexcept; + std::vector> buildRecurringTasks() noexcept; +private: + + std::shared_ptr spanStore_; + std::shared_ptr uploadHandler_; + BSGPluginManager *pluginManager_; + + std::shared_ptr buildGetPValueTask() noexcept; + std::shared_ptr buildStartPluginsTask() noexcept; + std::shared_ptr buildSendCurrentBatchTask() noexcept; + std::shared_ptr buildSendRetriesTask() noexcept; + std::shared_ptr buildSweepStoreTask() noexcept; +}; +} diff --git a/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.mm b/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.mm new file mode 100644 index 00000000..e8dc8396 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.mm @@ -0,0 +1,79 @@ +// +// WorkerTasksBuilder.mm +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 23/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#import "WorkerTasksBuilder.h" + +using namespace bugsnag; + +std::vector> +WorkerTasksBuilder::buildInitialTasks() noexcept { + auto result = std::vector>(); + result.push_back(buildGetPValueTask()); + result.push_back(buildStartPluginsTask()); + return result; +} + +std::vector> +WorkerTasksBuilder::buildRecurringTasks() noexcept { + auto result = std::vector>(); + result.push_back(buildGetPValueTask()); + result.push_back(buildSendCurrentBatchTask()); + result.push_back(buildSendRetriesTask()); + result.push_back(buildSweepStoreTask()); + return result; +} + +#pragma mark Private + +std::shared_ptr +WorkerTasksBuilder::buildGetPValueTask() noexcept { + __block auto blockThis = this; + auto work = ^(TaskCompletion completion){ + blockThis->uploadHandler_->uploadPValueRequest(completion); + }; + return std::make_shared(work); +} + +std::shared_ptr +WorkerTasksBuilder::buildStartPluginsTask() noexcept { + __block auto blockThis = this; + auto work = ^(TaskCompletion completion){ + [blockThis->pluginManager_ startPlugins]; + completion(false); + }; + return std::make_shared(work); +} + +std::shared_ptr +WorkerTasksBuilder::buildSendCurrentBatchTask() noexcept { + __block auto blockThis = this; + auto work = ^(TaskCompletion completion){ + // TODO + blockThis->uploadHandler_->uploadSpans(@[], completion); + }; + return std::make_shared(work); +} + +std::shared_ptr +WorkerTasksBuilder::buildSendRetriesTask() noexcept { + __block auto blockThis = this; + auto work = ^(TaskCompletion completion){ + blockThis->uploadHandler_->sendRetries(completion); + }; + return std::make_shared(work); +} + +std::shared_ptr +WorkerTasksBuilder::buildSweepStoreTask() noexcept { + __block auto blockThis = this; + auto work = ^(TaskCompletion completion){ + blockThis->spanStore_->sweep(); + completion(false); + }; + return std::make_shared(work); +} diff --git a/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.h b/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.h index 4dfe0acc..c514be4d 100644 --- a/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.h +++ b/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.h @@ -34,6 +34,7 @@ class PluginSupportModule: public Module { } BSGCompositeSpanControlProvider *getSpanControlProvider() noexcept { return spanControlProvider_; } + BSGPluginManager *getPluginManager() noexcept { return pluginManager_; } private: diff --git a/Sources/BugsnagPerformance/Private/Upload/UploadHandler/UploadHandler.h b/Sources/BugsnagPerformance/Private/Upload/UploadHandler/UploadHandler.h new file mode 100644 index 00000000..73b980fb --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Upload/UploadHandler/UploadHandler.h @@ -0,0 +1,26 @@ +// +// UploadHandler.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 23/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#pragma once + +#import + +#import "../../Core/Worker/AsyncToSyncTask.h" + +@class BugsnagPerformanceSpan; + +namespace bugsnag { +class UploadHandler { +public: + virtual void uploadPValueRequest(TaskCompletion completion) noexcept = 0; + virtual void uploadSpans(NSArray *spans, TaskCompletion completion) noexcept = 0; + virtual void sendRetries(TaskCompletion completion) noexcept = 0; + + virtual ~UploadHandler() {}; +}; +} diff --git a/Sources/BugsnagPerformance/Private/Upload/UploadHandler/UploadHandlerImpl.h b/Sources/BugsnagPerformance/Private/Upload/UploadHandler/UploadHandlerImpl.h new file mode 100644 index 00000000..6a9f4783 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Upload/UploadHandler/UploadHandlerImpl.h @@ -0,0 +1,59 @@ +// +// UploadHandlerImpl.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 23/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#pragma once + +#import "UploadHandler.h" +#import "../../Core/PhasedStartup.h" +#import "../Otlp/OtlpTraceEncoding.h" +#import "../Otlp/Uploader.h" +#import "../RetryQueue.h" +#import "../../Core/Attributes/ResourceAttributes.h" +#import + +namespace bugsnag { +class UploadHandlerImpl: public UploadHandler, public PhasedStartup { +public: + UploadHandlerImpl(std::shared_ptr traceEncoding, + std::shared_ptr uploader, + std::shared_ptr retryQueue, + std::shared_ptr resourceAttributes) noexcept + : traceEncoding_(traceEncoding) + , uploader_(uploader) + , retryQueue_(retryQueue) + , resourceAttributes_(resourceAttributes) { + } + + ~UploadHandlerImpl() {}; + + void earlyConfigure(BSGEarlyConfiguration *) noexcept {} + void earlySetup() noexcept {} + void configure(BugsnagPerformanceConfiguration *config) noexcept; + void preStartSetup() noexcept {} + void start() noexcept {} + + void uploadPValueRequest(TaskCompletion completion) noexcept; + void uploadSpans(NSArray *spans, TaskCompletion completion) noexcept; + void sendRetries(TaskCompletion completion) noexcept; + +private: + BugsnagPerformanceConfiguration *configuration_; + std::shared_ptr traceEncoding_; + std::shared_ptr uploader_; + std::shared_ptr retryQueue_; + std::shared_ptr resourceAttributes_; + + CFAbsoluteTime probabilityExpiry_{0}; + CFAbsoluteTime pausePValueRequestsUntil_{0}; + CFTimeInterval probabilityValueExpiresAfterSeconds_{0}; + CFTimeInterval probabilityRequestsPauseForSeconds_{0}; + uint64_t maxPackageContentLength_{1000000}; + + void uploadPackage(std::unique_ptr package, bool isRetry, TaskCompletion completion) noexcept; +}; +} diff --git a/Sources/BugsnagPerformance/Private/Upload/UploadHandler/UploadHandlerImpl.mm b/Sources/BugsnagPerformance/Private/Upload/UploadHandler/UploadHandlerImpl.mm new file mode 100644 index 00000000..20e4edca --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Upload/UploadHandler/UploadHandlerImpl.mm @@ -0,0 +1,180 @@ +// +// UploadHandlerImpl.mm +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 23/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#import "UploadHandlerImpl.h" +#import "../../Core/Configuration/BugsnagPerformanceConfiguration+Private.h" +#import "../Otlp/Uploader.h" +#import "../Otlp/OtlpPackage.h" +#import "../RetryQueue.h" + +using namespace bugsnag; + +#pragma mark PhasedStartup + +void +UploadHandlerImpl::configure(BugsnagPerformanceConfiguration *config) noexcept { + configuration_ = config; + probabilityValueExpiresAfterSeconds_ = config.internal.probabilityValueExpiresAfterSeconds; + probabilityRequestsPauseForSeconds_ = config.internal.probabilityRequestsPauseForSeconds; + maxPackageContentLength_ = config.internal.maxPackageContentLength; +} + +#pragma mark Public + +void +UploadHandlerImpl::uploadPValueRequest(TaskCompletion completion) noexcept { + if (!configuration_.shouldSendReports || configuration_.samplingProbability != nil) { + return; + } + auto currentTime = CFAbsoluteTimeGetCurrent(); + if (currentTime > pausePValueRequestsUntil_ && currentTime > probabilityExpiry_) { + // Pause P-value requests so that we don't flood the server on every span start + pausePValueRequestsUntil_ = currentTime + probabilityRequestsPauseForSeconds_; + uploader_->upload(*traceEncoding_->buildPValueRequestPackage(), ^(UploadResult) { + completion(false); + }); + } else { + completion(false); + } +} + +void +UploadHandlerImpl::uploadSpans(NSArray *spans, TaskCompletion completion) noexcept { + if (spans.count == 0) { + completion(false); + } + bool includeSamplingHeader = configuration_ == nil || configuration_.samplingProbability == nil; + uploadPackage(traceEncoding_->buildUploadPackage(spans, resourceAttributes_->get(), includeSamplingHeader), false, completion); +} + + +// TODO: Move to pipeline +//bool NSArray::sendCurrentBatchTask() noexcept { +// BSGLogDebug(@"BugsnagPerformanceImpl::sendCurrentBatchTask()"); +// auto origSpans = batch_->drain(false); +//#ifndef __clang_analyzer__ +// #pragma clang diagnostic ignored "-Wunused-variable" +// size_t origSpansSize = origSpans.count; +//#endif +// auto spans = sendableSpans(origSpans); +// if (spans.count == 0) { +//#ifndef __clang_analyzer__ +// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Nothing to send. origSpans size = %zu", origSpansSize); +//#endif +// return false; +// } +// bool includeSamplingHeader = configuration_ == nil || configuration_.samplingProbability == nil; +// +// // Delay so that the sampler has time to fetch one more sample. +// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Delaying %f seconds (%lld ns) before getting system info", SAMPLER_INTERVAL_SECONDS + 0.5, (int64_t)((SAMPLER_INTERVAL_SECONDS + 0.5) * NSEC_PER_SEC)); +// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((SAMPLER_INTERVAL_SECONDS + 0.5) * NSEC_PER_SEC)), +// dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{ +// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Delayed %f seconds, now getting system info", SAMPLER_INTERVAL_SECONDS + 0.5); +// for(BugsnagPerformanceSpan *span: spans) { +// auto samples = systemInfoSampler_.samplesAroundTimePeriod(span.actuallyStartedAt, span.actuallyEndedAt); +// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): System info sample size = %zu", samples.size()); +// if (samples.size() >= 2) { +// if (shouldSampleCPU(span)) { +// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Getting CPU sample attributes for span %@", span.name); +// [span forceMutate:^() { +// [span internalSetMultipleAttributes:spanAttributesProvider_->cpuSampleAttributes(samples)]; +// }]; +// } +// if (shouldSampleMemory(span)) { +// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Getting memory sample attributes for span %@", span.name); +// [span forceMutate:^() { +// [span internalSetMultipleAttributes:spanAttributesProvider_->memorySampleAttributes(samples)]; +// }]; +// } +// } +// } +// +//#ifndef __clang_analyzer__ +// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Sending %zu sampled spans (out of %zu)", origSpansSize, spans.count); +//#endif +// uploadPackage(traceEncoding_.buildUploadPackage(spans, resourceAttributes_->get(), includeSamplingHeader), false); +// }); +// +// return true; +//} + +void +UploadHandlerImpl::sendRetries(TaskCompletion completion) noexcept { + retryQueue_->sweep(); + + auto retries = retryQueue_->list(); + if (retries.size() == 0) { + completion(false); + return; + } + + for (auto &×tamp: retries) { + __block auto retry = retryQueue_->get(timestamp); + if (retry != nullptr) { + auto work = ^(TaskCompletion retryCompletion) { + uploadPackage(std::move(retry), true, retryCompletion); + retryCompletion(false); + }; + auto task = std::make_shared(work); + task->executeSync(); + } + } + + // Retries never count as work, otherwise we'd loop endlessly on a network outage. + completion(false); +} + +#pragma mark Private + +void +UploadHandlerImpl::uploadPackage(std::unique_ptr package, + bool isRetry, + TaskCompletion completion) noexcept { + if (!configuration_.shouldSendReports || package == nullptr) { + completion(false); + return; + } + + __block auto blockThis = this; + __block std::unique_ptr blockPackage = std::move(package); + + uploader_->upload(*blockPackage, ^(UploadResult result) { + switch (result) { + case UploadResult::SUCCESSFUL: + if (isRetry) { + blockThis->retryQueue_->remove(blockPackage->timestamp); + } + break; + case UploadResult::FAILED_CAN_RETRY: + if (!isRetry && blockPackage->uncompressedContentLength() <= maxPackageContentLength_) { + blockThis->retryQueue_->add(*blockPackage); + } + break; + case UploadResult::FAILED_CANNOT_RETRY: + // We can't do anything with it, so throw it out. + if (isRetry) { + blockThis->retryQueue_->remove(blockPackage->timestamp); + } + break; + } + blockThis->probabilityExpiry_ = CFAbsoluteTimeGetCurrent() + probabilityValueExpiresAfterSeconds_; + completion(true); + }); +} + +// TODO: Move to pipeline +//NSArray * +//UploadHandlerImpl::sendableSpans(NSArray *spans) noexcept { +// NSMutableArray *sendableSpans = [NSMutableArray arrayWithCapacity:spans.count]; +// for (BugsnagPerformanceSpan *span in spans) { +// if (span.state != SpanStateAborted && sampler_->sampled(span)) { +// [sendableSpans addObject:span]; +// } +// } +// return sendableSpans; +//} diff --git a/Sources/BugsnagPerformance/Private/Upload/UploadModule.h b/Sources/BugsnagPerformance/Private/Upload/UploadModule.h index 8e4e8ada..ec57f277 100644 --- a/Sources/BugsnagPerformance/Private/Upload/UploadModule.h +++ b/Sources/BugsnagPerformance/Private/Upload/UploadModule.h @@ -9,18 +9,22 @@ #pragma once #import "../Core/Module.h" +#import "../Core/Attributes/ResourceAttributes.h" #import "../Utils/Persistence.h" #import "RetryQueue.h" #import "Otlp/OtlpTraceEncoding.h" #import "Otlp/OtlpUploader.h" +#import "UploadHandler/UploadHandlerImpl.h" #import namespace bugsnag { class UploadModule: public Module { public: - UploadModule(std::shared_ptr persistence) - : persistence_(persistence) {}; + UploadModule(std::shared_ptr persistence, + std::shared_ptr resourceAttributes) + : persistence_(persistence) + , resourceAttributes_(resourceAttributes) {}; ~UploadModule() {}; @@ -40,15 +44,18 @@ class UploadModule: public Module { std::shared_ptr getRetryQueue() noexcept { return retryQueue_; } std::shared_ptr getTraceEncoding() noexcept { return traceEncoding_; } std::shared_ptr getUploader() noexcept { return uploader_; } + std::shared_ptr getUploadHandler() noexcept { return uploadHandler_; } private: // Dependencies std::shared_ptr persistence_; + std::shared_ptr resourceAttributes_; // Components std::shared_ptr retryQueue_; std::shared_ptr traceEncoding_; std::shared_ptr uploader_; + std::shared_ptr uploadHandler_; }; } diff --git a/Sources/BugsnagPerformance/Private/Upload/UploadModule.mm b/Sources/BugsnagPerformance/Private/Upload/UploadModule.mm index 3ea38a6d..f23bc718 100644 --- a/Sources/BugsnagPerformance/Private/Upload/UploadModule.mm +++ b/Sources/BugsnagPerformance/Private/Upload/UploadModule.mm @@ -17,6 +17,7 @@ traceEncoding_->earlyConfigure(config); retryQueue_->earlyConfigure(config); uploader_->earlyConfigure(config); + uploadHandler_->earlyConfigure(config); } void @@ -24,6 +25,7 @@ traceEncoding_->earlySetup(); retryQueue_->earlySetup(); uploader_->earlySetup(); + uploadHandler_->earlySetup(); } void @@ -31,6 +33,7 @@ traceEncoding_->configure(config); retryQueue_->configure(config); uploader_->configure(config); + uploadHandler_->configure(config); } void @@ -38,6 +41,7 @@ traceEncoding_->preStartSetup(); retryQueue_->preStartSetup(); uploader_->preStartSetup(); + uploadHandler_->preStartSetup(); } void @@ -45,6 +49,7 @@ traceEncoding_->start(); retryQueue_->start(); uploader_->start(); + uploadHandler_->start(); } #pragma mark Module @@ -54,4 +59,5 @@ retryQueue_ = std::make_shared([persistence_->bugsnagPerformanceDir() stringByAppendingPathComponent:@"retry-queue"]); traceEncoding_ = std::make_shared(); uploader_ = std::make_shared(); + uploadHandler_ = std::make_shared(traceEncoding_, uploader_, retryQueue_, resourceAttributes_); } diff --git a/Tests/BugsnagPerformanceTests/WorkerTests.mm b/Tests/BugsnagPerformanceTests/WorkerTests.mm index c0873697..cc55a709 100644 --- a/Tests/BugsnagPerformanceTests/WorkerTests.mm +++ b/Tests/BugsnagPerformanceTests/WorkerTests.mm @@ -191,38 +191,36 @@ - (instancetype) initWithInitialTaskCount:(int)initialTaskCount recurringTaskCount:(int)recurringTaskCount { if ((self = [super init])) { _remainingRecurringRuns = 1; - auto initialTasks = [NSMutableArray array]; + _worker = [Worker worker]; for (int i = 0; i < initialTaskCount; i++) { - [initialTasks addObject:[self newInitialTask]]; + [_worker addInitialTask:[self newInitialTask]]; } - auto recurringTasks = [NSMutableArray array]; for (int i = 0; i < recurringTaskCount; i++) { - [recurringTasks addObject:[self newRecurringTask]]; + [_worker addRecurringTask:[self newRecurringTask]]; } - - _worker = [[Worker alloc] initWithInitialTasks:initialTasks - recurringTasks:recurringTasks]; } return self; } -- (Task) newInitialTask { +- (std::shared_ptr) newInitialTask { __block auto blockSelf = self; - return ^bool(){ - blockSelf.initialTaskCounter++; - return false; - }; + return std::make_shared( + ^(TaskCompletion completion){ + blockSelf.initialTaskCounter++; + completion(false); + }); } -- (Task) newRecurringTask { +- (std::shared_ptr) newRecurringTask { __block auto blockSelf = self; - return ^bool(){ - blockSelf.recurringTaskCounter++; - blockSelf.remainingRecurringRuns--; - return blockSelf.remainingRecurringRuns > 0; - }; + return std::make_shared( + ^(TaskCompletion completion){ + blockSelf.recurringTaskCounter++; + blockSelf.remainingRecurringRuns--; + completion(blockSelf.remainingRecurringRuns > 0); + }); } @end From d50440e251771774b497f292ae509e1fd3ce1c0a Mon Sep 17 00:00:00 2001 From: Robert Bartoszewski Date: Fri, 24 Oct 2025 01:08:45 +0200 Subject: [PATCH 07/14] Span processing pipeline --- BugsnagPerformance.xcodeproj/project.pbxproj | 8 + .../Private/Core/CoreModule.h | 28 ++- .../Private/Core/CoreModule.mm | 11 +- .../SpanLifecycle/SpanLifecycleHandlerImpl.h | 23 +- .../SpanLifecycle/SpanLifecycleHandlerImpl.mm | 152 ++---------- .../SpanProcessingPipeline.h | 3 + .../SpanProcessingPipelineImpl.h | 28 ++- .../SpanProcessingPipelineImpl.mm | 58 ++++- .../SpanProcessingPipelineStep.h | 14 +- .../Private/Main/MainModule.h | 4 + .../Private/Main/MainModule.mm | 25 +- .../Private/Main/PipelineStepsBuilder.h | 75 ++++++ .../Private/Main/PipelineStepsBuilder.mm | 226 ++++++++++++++++++ .../Private/Main/WorkerTasksBuilder.h | 8 +- .../Private/Main/WorkerTasksBuilder.mm | 58 +++-- .../Private/Metrics/MetricsModule.h | 2 + .../Private/Metrics/MetricsModule.mm | 5 + .../PluginManager/BSGPluginManager.h | 4 +- .../PluginManager/BSGPluginManager.m | 8 +- .../PluginSupport/PluginSupportModule.h | 8 +- .../PluginSupport/PluginSupportModule.mm | 4 +- .../Private/Plugins/PluginsModule.h | 1 - .../Upload/UploadHandler/UploadHandlerImpl.mm | 63 ----- 23 files changed, 524 insertions(+), 292 deletions(-) create mode 100644 Sources/BugsnagPerformance/Private/Main/PipelineStepsBuilder.h create mode 100644 Sources/BugsnagPerformance/Private/Main/PipelineStepsBuilder.mm diff --git a/BugsnagPerformance.xcodeproj/project.pbxproj b/BugsnagPerformance.xcodeproj/project.pbxproj index ab659b02..8f74fdfe 100644 --- a/BugsnagPerformance.xcodeproj/project.pbxproj +++ b/BugsnagPerformance.xcodeproj/project.pbxproj @@ -222,6 +222,8 @@ 96794A402EAA10A6005FD87F /* UploadHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A3F2EAA109F005FD87F /* UploadHandler.h */; }; 96794A422EAA10F4005FD87F /* UploadHandlerImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A412EAA10EB005FD87F /* UploadHandlerImpl.h */; }; 96794A442EAA10FB005FD87F /* UploadHandlerImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96794A432EAA10F9005FD87F /* UploadHandlerImpl.mm */; }; + 96794A462EAA8713005FD87F /* PipelineStepsBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 96794A452EAA8705005FD87F /* PipelineStepsBuilder.h */; }; + 96794A482EAA871C005FD87F /* PipelineStepsBuilder.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96794A472EAA871B005FD87F /* PipelineStepsBuilder.mm */; }; 967F6F1829C3783B0054EED8 /* BugsnagPerformanceConfiguration+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 967F6F1729C3782D0054EED8 /* BugsnagPerformanceConfiguration+Private.h */; }; 968AA5FB2CCA5A9200BA69CF /* BSGPerformanceSharedSessionProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 968AA5FA2CCA5A9200BA69CF /* BSGPerformanceSharedSessionProxy.h */; }; 968AA5FD2CCA5AB000BA69CF /* BSGPerformanceSharedSessionProxy.mm in Sources */ = {isa = PBXBuildFile; fileRef = 968AA5FC2CCA5AB000BA69CF /* BSGPerformanceSharedSessionProxy.mm */; }; @@ -614,6 +616,8 @@ 96794A3F2EAA109F005FD87F /* UploadHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UploadHandler.h; sourceTree = ""; }; 96794A412EAA10EB005FD87F /* UploadHandlerImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UploadHandlerImpl.h; sourceTree = ""; }; 96794A432EAA10F9005FD87F /* UploadHandlerImpl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = UploadHandlerImpl.mm; sourceTree = ""; }; + 96794A452EAA8705005FD87F /* PipelineStepsBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PipelineStepsBuilder.h; sourceTree = ""; }; + 96794A472EAA871B005FD87F /* PipelineStepsBuilder.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PipelineStepsBuilder.mm; sourceTree = ""; }; 967F6F1729C3782D0054EED8 /* BugsnagPerformanceConfiguration+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BugsnagPerformanceConfiguration+Private.h"; sourceTree = ""; }; 968AA5FA2CCA5A9200BA69CF /* BSGPerformanceSharedSessionProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BSGPerformanceSharedSessionProxy.h; sourceTree = ""; }; 968AA5FC2CCA5AB000BA69CF /* BSGPerformanceSharedSessionProxy.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = BSGPerformanceSharedSessionProxy.mm; sourceTree = ""; }; @@ -1258,6 +1262,8 @@ CB78819A29E587CE00A58906 /* BugsnagPerformanceLibrary.mm */, 967949FB2EA16458005FD87F /* MainModule.h */, 967949FD2EA16463005FD87F /* MainModule.mm */, + 96794A452EAA8705005FD87F /* PipelineStepsBuilder.h */, + 96794A472EAA871B005FD87F /* PipelineStepsBuilder.mm */, 96794A382EA99C91005FD87F /* WorkerTasksBuilder.h */, 96794A3A2EA99CA0005FD87F /* WorkerTasksBuilder.mm */, ); @@ -1618,6 +1624,7 @@ 963726DE2DF0B43500C739E6 /* BugsnagPerformancePlugin.h in Headers */, 0122C24C29019770002D243C /* NetworkInstrumentation.h in Headers */, 962CE8352E67972300380522 /* NetworkSpanFactoryImpl.h in Headers */, + 96794A462EAA8713005FD87F /* PipelineStepsBuilder.h in Headers */, 962CE7CE2E60766000380522 /* ViewLoadInstrumentationStateRepository.h in Headers */, 967949BD2E99373E005FD87F /* SpanStore.h in Headers */, 963726C12DEA4E5700C739E6 /* BugsnagPerformancePriority.h in Headers */, @@ -2109,6 +2116,7 @@ 963726CC2DEAB25600C739E6 /* BugsnagPerformancePriority+Private.m in Sources */, 962CE7D32E60768400380522 /* ViewLoadInstrumentationStateRepositoryImpl.mm in Sources */, CB7FD932299D2F7700499E13 /* BugsnagPerformanceSpanOptions.m in Sources */, + 96794A482EAA871C005FD87F /* PipelineStepsBuilder.mm in Sources */, 967949CA2E9DC9CE005FD87F /* SpanProcessingPipelineStep.h in Sources */, CBEC51BD296D9EEE009C0CE3 /* PersistentState.mm in Sources */, CBEC51B9296D8386009C0CE3 /* Persistence.mm in Sources */, diff --git a/Sources/BugsnagPerformance/Private/Core/CoreModule.h b/Sources/BugsnagPerformance/Private/Core/CoreModule.h index fadea189..e920ab91 100644 --- a/Sources/BugsnagPerformance/Private/Core/CoreModule.h +++ b/Sources/BugsnagPerformance/Private/Core/CoreModule.h @@ -26,6 +26,7 @@ #import "BSGPrioritizedStore.h" #import "SpanConditions/ConditionTimeoutExecutor.h" #import "SpanProcessingPipeline/Batch.h" +#import "SpanProcessingPipeline/SpanProcessingPipelineImpl.h" #import "../Utils/Persistence.h" #import "../Utils/PersistentDeviceID.h" @@ -40,11 +41,13 @@ class CoreModule: public Module, public AppLifecycleListener { CoreModule(AppStateTracker *appStateTracker, std::shared_ptr reachability, std::shared_ptr persistence, - std::shared_ptr deviceID) noexcept + std::shared_ptr deviceID, + BSGPrioritizedStore *spanStartCallbacks) noexcept : appStateTracker_(appStateTracker) , reachability_(reachability) , persistence_(persistence) - , deviceID_(deviceID) {}; + , deviceID_(deviceID) + , spanStartCallbacks_(spanStartCallbacks) {}; ~CoreModule(); @@ -61,10 +64,12 @@ class CoreModule: public Module, public AppLifecycleListener { void initializeComponentsCallbacks(GetCurrentFrameMetricsSnapshot getCurrentSnapshot, GetAppStartupStateSnapshot getAppStartupStateSnapshot, - HandleStringTask onViewLoadSpanStarted) noexcept { + HandleStringTask onViewLoadSpanStarted, + double spanProcessingDelay) noexcept { spanLifecycleHandler_->initialize(getCurrentSnapshot); plainSpanFactory_->setup(createPlainSpanFactoryCallbacks()); viewLoadSpanFactory_->setup(createViewLoadSpanFactoryCallbacks(onViewLoadSpanStarted, getAppStartupStateSnapshot)); + pipeline_->setMainFlowDelay(spanProcessingDelay); } void initializeWorkerTasks(std::vector> initialTasks, @@ -77,6 +82,16 @@ class CoreModule: public Module, public AppLifecycleListener { } } + void initializePipelineSteps(std::vector> preprocessSteps, + std::vector> mainFlowSteps) { + for (const auto &step : preprocessSteps) { + pipeline_->addPreprocessStep(step); + } + for (const auto &step : mainFlowSteps) { + pipeline_->addMainFlowStep(step); + } + } + // Tasks UpdateProbabilityTask getUpdateProbabilityTask() noexcept; @@ -97,8 +112,7 @@ class CoreModule: public Module, public AppLifecycleListener { std::shared_ptr getSpanLifecycleHandler() noexcept { return spanLifecycleHandler_; } std::shared_ptr getResourceAttributes() noexcept { return resourceAttributes_; } std::shared_ptr getNetworkSpanReporter() noexcept { return networkSpanReporter_; } - BSGPrioritizedStore *getSpanStartCallbacks() noexcept { return spanStartCallbacks_; } - BSGPrioritizedStore *getSpanEndCallbacks() noexcept { return spanEndCallbacks_; } + std::shared_ptr getSpanProcessingPipeline() noexcept { return pipeline_; } private: @@ -113,6 +127,7 @@ class CoreModule: public Module, public AppLifecycleListener { std::shared_ptr persistence_; std::shared_ptr deviceID_; std::function getAppStartupInstrumentationState_{ [](){ return nil; } }; + BSGPrioritizedStore *spanStartCallbacks_; // Components std::shared_ptr batch_; @@ -129,8 +144,7 @@ class CoreModule: public Module, public AppLifecycleListener { std::shared_ptr spanLifecycleHandler_; std::shared_ptr resourceAttributes_; std::shared_ptr networkSpanReporter_; - BSGPrioritizedStore *spanStartCallbacks_; - BSGPrioritizedStore *spanEndCallbacks_; + std::shared_ptr pipeline_; Worker *worker_; PlainSpanFactoryCallbacks *createPlainSpanFactoryCallbacks() noexcept; diff --git a/Sources/BugsnagPerformance/Private/Core/CoreModule.mm b/Sources/BugsnagPerformance/Private/Core/CoreModule.mm index 410d02d7..c984c43a 100644 --- a/Sources/BugsnagPerformance/Private/Core/CoreModule.mm +++ b/Sources/BugsnagPerformance/Private/Core/CoreModule.mm @@ -91,6 +91,9 @@ }]; }); batch_->setBatchFullCallback(^{ + blockThis->pipeline_->processPendingSpansIfNeeded(); + }); + pipeline_->setSendableSpansCallback(^{ [blockThis->worker_ wake]; }); } @@ -111,16 +114,14 @@ viewLoadSpanFactory_ = std::make_shared(plainSpanFactory_, spanAttributesProvider_); networkSpanFactory_ = std::make_shared(plainSpanFactory_, spanAttributesProvider_); - spanStartCallbacks_ = [BSGPrioritizedStore new]; - spanEndCallbacks_ = [BSGPrioritizedStore new]; spanStore_ = std::make_shared(spanStackingHandler_); + pipeline_ = std::make_shared(batch_); spanLifecycleHandler_ = std::make_shared(sampler_, spanStore_, conditionTimeoutExecutor_, plainSpanFactory_, - batch_, - spanStartCallbacks_, - spanEndCallbacks_); + pipeline_, + spanStartCallbacks_); resourceAttributes_ = std::make_shared(deviceID_); networkSpanReporter_ = std::make_shared(spanAttributesProvider_, networkSpanFactory_); diff --git a/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.h b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.h index b9aadb07..80b80bc7 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.h @@ -19,6 +19,7 @@ #import "../SpanConditions/ConditionTimeoutExecutor.h" #import "../BSGPrioritizedStore.h" #import "../SpanStore/SpanStore.h" +#import "../SpanProcessingPipeline/SpanProcessingPipeline.h" #import @@ -30,16 +31,14 @@ class SpanLifecycleHandlerImpl: public SpanLifecycleHandler { std::shared_ptr store, std::shared_ptr conditionTimeoutExecutor, std::shared_ptr plainSpanFactory, - std::shared_ptr batch, - BSGPrioritizedStore *onSpanStartCallbacks, - BSGPrioritizedStore *onSpanEndCallbacks) noexcept + std::shared_ptr pipeline, + BSGPrioritizedStore *onSpanStartCallbacks) noexcept : sampler_(sampler) , store_(store) , conditionTimeoutExecutor_(conditionTimeoutExecutor) , plainSpanFactory_(plainSpanFactory) - , batch_(batch) - , onSpanStartCallbacks_(onSpanStartCallbacks) - , onSpanEndCallbacks_(onSpanEndCallbacks) {} + , pipeline_(pipeline) + , onSpanStartCallbacks_(onSpanStartCallbacks) {} void earlyConfigure(BSGEarlyConfiguration *) noexcept {} void earlySetup() noexcept {} @@ -70,22 +69,14 @@ class SpanLifecycleHandlerImpl: public SpanLifecycleHandler { std::shared_ptr store_; bool isStarted_{false}; - std::shared_ptr batch_; + std::shared_ptr pipeline_; BSGPrioritizedStore *onSpanStartCallbacks_; - BSGPrioritizedStore *onSpanEndCallbacks_; BugsnagPerformanceEnabledMetrics *enabledMetrics_{[BugsnagPerformanceEnabledMetrics withAllEnabled]}; GetCurrentFrameMetricsSnapshot getCurrentSnapshot_{nullptr}; - void processClosedSpan(BugsnagPerformanceSpan *span) noexcept; - bool shouldInstrumentRendering(BugsnagPerformanceSpan *span) noexcept; - void processFrameMetrics(BugsnagPerformanceSpan *span) noexcept; void callOnSpanStartCallbacks(BugsnagPerformanceSpan *span) noexcept; - void callOnSpanEndCallbacks(BugsnagPerformanceSpan *span) noexcept; - void createFrozenFrameSpan(NSTimeInterval startTime, - NSTimeInterval endTime, - BugsnagPerformanceSpanContext *parentContext) noexcept; void abortAllOpenSpans() noexcept; - void reprocessEarlySpans() noexcept; + bool shouldInstrumentRendering(BugsnagPerformanceSpan *span) noexcept; SpanLifecycleHandlerImpl() = delete; }; diff --git a/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.mm b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.mm index d779e2e6..8d333635 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.mm +++ b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.mm @@ -14,7 +14,7 @@ void SpanLifecycleHandlerImpl::preStartSetup() noexcept { - reprocessEarlySpans(); + pipeline_->processPendingSpansIfNeeded(); } void @@ -36,7 +36,8 @@ void SpanLifecycleHandlerImpl::onSpanClosed(BugsnagPerformanceSpan *span) noexcept { if (!span.isBlocked) { - processClosedSpan(span); + store_->removeSpan(span); + pipeline_->addSpanForProcessing(span); } } @@ -82,7 +83,7 @@ if (!span) { return; } - batch_->removeSpan(span.traceIdHi, span.traceIdLo, span.spanId); + pipeline_->removeSpan(span); if (span.isBlocked) { store_->removeSpanFromBlocked(span); } @@ -97,45 +98,6 @@ #pragma mark Private -bool -SpanLifecycleHandlerImpl::shouldInstrumentRendering(BugsnagPerformanceSpan *span) noexcept { - switch (span.metricsOptions.rendering) { - case BSGTriStateYes: - return enabledMetrics_.rendering; - case BSGTriStateNo: - return false; - case BSGTriStateUnset: - return enabledMetrics_.rendering && - !span.wasStartOrEndTimeProvided && - span.firstClass == BSGTriStateYes; - } -} - -void -SpanLifecycleHandlerImpl::processFrameMetrics(BugsnagPerformanceSpan *span) noexcept { - auto startSnapshot = span.startFramerateSnapshot; - auto endSnapshot = span.endFramerateSnapshot; - if (!shouldInstrumentRendering(span) || - startSnapshot == nil || - endSnapshot == nil) { - return; - } - auto mergedSnapshot = [FrameMetricsSnapshot mergeWithStart:startSnapshot - end:endSnapshot]; - if (mergedSnapshot.totalFrames == 0) { - return; - } - [span setAttribute:@"bugsnag.rendering.total_frames" withValue:@(mergedSnapshot.totalFrames)]; - [span setAttribute:@"bugsnag.rendering.slow_frames" withValue:@(mergedSnapshot.totalSlowFrames)]; - [span setAttribute:@"bugsnag.rendering.frozen_frames" withValue:@(mergedSnapshot.totalFrozenFrames)]; - - auto frozenFrame = mergedSnapshot.firstFrozenFrame; - while (frozenFrame != nil) { - createFrozenFrameSpan(frozenFrame.startTime, frozenFrame.endTime, span); - frozenFrame = frozenFrame != mergedSnapshot.lastFrozenFrame ? frozenFrame.next : nil; - } -} - void SpanLifecycleHandlerImpl::callOnSpanStartCallbacks(BugsnagPerformanceSpan *span) noexcept { if(span == nil) { @@ -151,71 +113,6 @@ } } -void -SpanLifecycleHandlerImpl::callOnSpanEndCallbacks(BugsnagPerformanceSpan *span) noexcept { - if(span == nil) { - return; - } - if (span.state != SpanStateEnded) { - return; - } - - CFAbsoluteTime callbacksStartTime = CFAbsoluteTimeGetCurrent(); - for (BugsnagPerformanceSpanEndCallback callback: [onSpanEndCallbacks_ objects]) { - BOOL shouldDiscardSpan = false; - @try { - shouldDiscardSpan = !callback(span); - } @catch(NSException *e) { - BSGLogError(@"Tracer::callOnSpanEndCallbacks: span OnEnd callback threw exception: %@", e); - // We don't know whether they wanted to discard the span or not, so keep it. - shouldDiscardSpan = false; - } - if(shouldDiscardSpan) { - [span abortUnconditionally]; - return; - } - } - CFAbsoluteTime callbacksEndTime = CFAbsoluteTimeGetCurrent(); - [span internalSetAttribute:@"bugsnag.span.callbacks_duration" withValue:@(intervalToNanoseconds(callbacksEndTime - callbacksStartTime))]; -} - -void -SpanLifecycleHandlerImpl::createFrozenFrameSpan(NSTimeInterval startTime, - NSTimeInterval endTime, - BugsnagPerformanceSpanContext *parentContext) noexcept { - SpanOptions options; - options.startTime = startTime; - options.parentContext = parentContext; - options.makeCurrentContext = false; - auto span = plainSpanFactory_->startSpan(@"FrozenFrame", options, BSGTriStateNo, @{}, @[]); - [span endWithAbsoluteTime:endTime]; -} - -void -SpanLifecycleHandlerImpl::reprocessEarlySpans() noexcept { - // Up until now nothing was configured, so all early spans have been kept. - // Now that configuration is complete, force-drain all early spans and re-process them. - auto toReprocess = batch_->drain(true); - for (BugsnagPerformanceSpan *span in toReprocess) { - if (span.state != SpanStateEnded) { - continue; - } - if (!sampler_->sampled(span)) { - [span abortUnconditionally]; - continue; - } - [span forceMutate:^() { - callOnSpanEndCallbacks(span); - }]; - if (span.state == SpanStateAborted) { - [span abortUnconditionally]; - continue; - } - - batch_->add(span); - } -} - void SpanLifecycleHandlerImpl::abortAllOpenSpans() noexcept { store_->performActionAndClearOpenSpans(^(BugsnagPerformanceSpan *span) { @@ -223,35 +120,16 @@ }); } -void -SpanLifecycleHandlerImpl::processClosedSpan(BugsnagPerformanceSpan *span) noexcept { - @synchronized (span) { - for (BugsnagPerformanceSpanCondition *condition in span.conditionsToEndOnClose) { - [condition closeWithEndTime:span.endTime]; - } - } - - store_->removeSpan(span); - - if(span.state == SpanStateAborted) { - return; - } - - if (!sampler_->sampled(span)) { - [span abortUnconditionally]; - return; - } - - if (span != nil && span.state == SpanStateEnded) { - callOnSpanEndCallbacks(span); - if (span.state == SpanStateAborted) { - return; - } - } - - if (shouldInstrumentRendering(span)) { - processFrameMetrics(span); +bool +SpanLifecycleHandlerImpl::shouldInstrumentRendering(BugsnagPerformanceSpan *span) noexcept { + switch (span.metricsOptions.rendering) { + case BSGTriStateYes: + return enabledMetrics_.rendering; + case BSGTriStateNo: + return false; + case BSGTriStateUnset: + return enabledMetrics_.rendering && + !span.wasStartOrEndTimeProvided && + span.firstClass == BSGTriStateYes; } - - batch_->add(span); } diff --git a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipeline.h b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipeline.h index bfc43506..f01293ac 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipeline.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipeline.h @@ -8,6 +8,8 @@ #pragma once +#import + #import "SpanProcessingPipelineStep.h" namespace bugsnag { @@ -17,6 +19,7 @@ class SpanProcessingPipeline { virtual void addSpanForProcessing(BugsnagPerformanceSpan *span) noexcept = 0; virtual void removeSpan(BugsnagPerformanceSpan *span) noexcept = 0; virtual void processPendingSpansIfNeeded() noexcept = 0; + virtual NSArray *drainSendableSpans() noexcept = 0; virtual ~SpanProcessingPipeline() {} }; diff --git a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.h b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.h index 73b82f1e..46c8bc3e 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.h @@ -21,9 +21,10 @@ namespace bugsnag { class SpanProcessingPipelineImpl: public SpanProcessingPipeline, public PhasedStartup { public: - SpanProcessingPipelineImpl() noexcept - : batch_(std::make_shared()) - , preStartSpans_([NSMutableArray new]) {} + SpanProcessingPipelineImpl(std::shared_ptr batch) noexcept + : batch_(batch) + , preStartSpans_([NSMutableArray new]) + , sendableSpans_([NSMutableArray new]) {} void earlyConfigure(BSGEarlyConfiguration *) noexcept {} void earlySetup() noexcept {} @@ -31,25 +32,34 @@ class SpanProcessingPipelineImpl: public SpanProcessingPipeline, public PhasedSt void preStartSetup() noexcept; void start() noexcept {} + void setMainFlowDelay(double delay) noexcept { mainFlowDelay_ = delay; } + void addSpanForProcessing(BugsnagPerformanceSpan *span) noexcept; void removeSpan(BugsnagPerformanceSpan *span) noexcept; void processPendingSpansIfNeeded() noexcept; + NSArray *drainSendableSpans() noexcept; + + void setSendableSpansCallback(void (^sendableSpansCallback)()) { + onSendableSpans_ = sendableSpansCallback; + } void addPreprocessStep(std::shared_ptr step) noexcept; - void addPreStartStep(std::shared_ptr step) noexcept; void addMainFlowStep(std::shared_ptr step) noexcept; private: bool isStarted_{false}; + double mainFlowDelay_{0.0}; + void (^onSendableSpans_)(){nullptr}; std::shared_ptr batch_; NSMutableArray *preStartSpans_; - std::vector> *preprocessFlow_{}; - std::vector> *preStartFlow_{}; - std::vector> *mainFlow_{}; + NSMutableArray *sendableSpans_; + std::vector> preprocessFlow_{}; + std::vector> mainFlow_{}; std::mutex mutex_; - void executeFlow(std::vector> *flow, - NSArray *spans) noexcept; + NSArray *executeFlow(std::vector> *flow, + NSArray *spans) noexcept; + void processPendingSpans(NSArray *spans) noexcept; }; } diff --git a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.mm b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.mm index 9179572a..432a2708 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.mm +++ b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.mm @@ -10,18 +10,29 @@ using namespace bugsnag; +#pragma mark PhaseStartup + void SpanProcessingPipelineImpl::preStartSetup() noexcept { std::lock_guard guard(mutex_); - executeFlow(preStartFlow_, preStartSpans_); + auto spans = executeFlow(&preprocessFlow_, preStartSpans_); [preStartSpans_ removeAllObjects]; + for (BugsnagPerformanceSpan *span in spans) { + batch_->add(span); + } + processPendingSpansIfNeeded(); isStarted_ = true; } +#pragma mark Public + void SpanProcessingPipelineImpl::addSpanForProcessing(BugsnagPerformanceSpan *span) noexcept { std::lock_guard guard(mutex_); - executeFlow(preprocessFlow_, @[span]); + auto spans = executeFlow(&preprocessFlow_, @[span]); + if (spans.count == 0) { + return; + } if (isStarted_) { batch_->add(span); } else { @@ -42,37 +53,45 @@ void SpanProcessingPipelineImpl::processPendingSpansIfNeeded() noexcept { std::lock_guard guard(mutex_); - auto spans = batch_->drain(false); + __block auto spans = batch_->drain(false); + __block auto blockThis = this; if (spans.count > 0) { - executeFlow(mainFlow_, spans); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((mainFlowDelay_ + 0.5) * NSEC_PER_SEC)), + dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0),^{ + blockThis->processPendingSpans(spans); + }); } } -void -SpanProcessingPipelineImpl::addPreprocessStep(std::shared_ptr step) noexcept { - std::lock_guard guard(mutex_); - preprocessFlow_->push_back(step); +NSArray * +SpanProcessingPipelineImpl::drainSendableSpans() noexcept { + NSArray *result = [sendableSpans_ copy]; + [sendableSpans_ removeAllObjects]; + return result; } +#pragma mark Steps Management + void -SpanProcessingPipelineImpl::addPreStartStep(std::shared_ptr step) noexcept { +SpanProcessingPipelineImpl::addPreprocessStep(std::shared_ptr step) noexcept { std::lock_guard guard(mutex_); - preStartFlow_->push_back(step); + preprocessFlow_.push_back(step); } void SpanProcessingPipelineImpl::addMainFlowStep(std::shared_ptr step) noexcept { std::lock_guard guard(mutex_); - mainFlow_->push_back(step); + mainFlow_.push_back(step); } #pragma mark Private -void +NSArray * SpanProcessingPipelineImpl::executeFlow(std::vector> *flow, NSArray *spans) noexcept { + std::lock_guard guard(mutex_); if (!flow || !spans) { - return; + return @[]; } NSMutableArray *spansToProcess = [spans mutableCopy]; @@ -86,4 +105,17 @@ } [spansToProcess removeObjectsInArray:spansToRemove]; } + return spansToProcess; +} + +void +SpanProcessingPipelineImpl::processPendingSpans(NSArray *spans) noexcept { + std::lock_guard guard(mutex_); + auto spansToSend = executeFlow(&mainFlow_, spans); + if (spansToSend.count > 0) { + [sendableSpans_ addObjectsFromArray:spansToSend]; + if (onSendableSpans_) { + onSendableSpans_(); + } + } } diff --git a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineStep.h b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineStep.h index 7d59d324..ea157346 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineStep.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineStep.h @@ -10,12 +10,22 @@ #import +typedef bool (^StepWork)(BugsnagPerformanceSpan *span); + namespace bugsnag { class SpanProcessingPipelineStep { public: - virtual bool run(BugsnagPerformanceSpan *span) noexcept = 0; + SpanProcessingPipelineStep(StepWork work) noexcept + : work_(work) {}; + + ~SpanProcessingPipelineStep() {} + + bool run(BugsnagPerformanceSpan *span) noexcept { + return work_(span); + } - virtual ~SpanProcessingPipelineStep() {} +private: + StepWork work_{nullptr}; }; } diff --git a/Sources/BugsnagPerformance/Private/Main/MainModule.h b/Sources/BugsnagPerformance/Private/Main/MainModule.h index 3548f22f..48b4e94a 100644 --- a/Sources/BugsnagPerformance/Private/Main/MainModule.h +++ b/Sources/BugsnagPerformance/Private/Main/MainModule.h @@ -9,6 +9,7 @@ #pragma once #import "WorkerTasksBuilder.h" +#import "PipelineStepsBuilder.h" #import "../Core/Module.h" #import "../Core/AppLifecycleListener.h" #import "../Core/CoreModule.h" @@ -61,6 +62,9 @@ class MainModule: public Module, public AppLifecycleListener { std::shared_ptr pluginSupportModule_; std::shared_ptr uploadModule_; std::shared_ptr workerTasksBuilder_; + std::shared_ptr pipelineStepsBuilder_; + BSGPrioritizedStore *spanStartCallbacks_; + BSGPrioritizedStore *spanEndCallbacks_; void initializeModules() noexcept; std::vector> buildInitialTasks() noexcept; diff --git a/Sources/BugsnagPerformance/Private/Main/MainModule.mm b/Sources/BugsnagPerformance/Private/Main/MainModule.mm index e8add2c1..bb382682 100644 --- a/Sources/BugsnagPerformance/Private/Main/MainModule.mm +++ b/Sources/BugsnagPerformance/Private/Main/MainModule.mm @@ -53,7 +53,7 @@ } void -MainModule::configure(BugsnagPerformanceConfiguration *config) noexcept { +MainModule::configure(BugsnagPerformanceConfiguration *config) noexcept { metricsModule_->configure(config); utilsModule_->configure(config); coreModule_->configure(config); @@ -62,6 +62,8 @@ pluginSupportModule_->configure(config); pluginsModule_->configure(config); crossTalkAPIModule_->configure(config); + + pluginSupportModule_->installPlugins(pluginsModule_->getDefaultPluginsTask()()); } void @@ -122,12 +124,15 @@ void MainModule::initializeModules() noexcept { + spanStartCallbacks_ = [BSGPrioritizedStore new]; + spanEndCallbacks_ = [BSGPrioritizedStore new]; utilsModule_ = std::make_shared(); utilsModule_->setUp(); coreModule_ = std::make_shared(utilsModule_->getAppStateTracker(), utilsModule_->getReachability(), utilsModule_->getPersistence(), - utilsModule_->getDeviceID()); + utilsModule_->getDeviceID(), + spanStartCallbacks_); coreModule_->setUp(); instrumentationModule_ = std::make_shared(coreModule_->getAppStartupSpanFactory(), coreModule_->getViewLoadSpanFactory(), @@ -146,7 +151,8 @@ pluginsModule_ = std::make_shared(instrumentationModule_->getInstrumentation()); pluginsModule_->setUp(); - pluginSupportModule_ = std::make_shared(); + pluginSupportModule_ = std::make_shared(spanStartCallbacks_, + spanEndCallbacks_); pluginSupportModule_->setUp(); uploadModule_ = std::make_shared(utilsModule_->getPersistence(), @@ -158,11 +164,20 @@ coreModule_->getUpdateProbabilityTask()); coreModule_->initializeComponentsCallbacks(metricsModule_->getCurrentFrameMetricsSnapshotTask(), instrumentationModule_->getAppStartupStateSnapshotTask(), - instrumentationModule_->getHandleViewLoadSpanStartedTask()); - pluginSupportModule_->installPlugins(pluginsModule_->getDefaultPluginsTask()()); + instrumentationModule_->getHandleViewLoadSpanStartedTask(), + metricsModule_->getSamplerInterval()); + + pipelineStepsBuilder_ = std::make_shared(metricsModule_->getSystemInfoSampler(), + coreModule_->getSpanAttributesProvider(), + coreModule_->getPlainSpanFactory(), + coreModule_->getSampler(), + spanEndCallbacks_); + coreModule_->initializePipelineSteps(pipelineStepsBuilder_->buildPreprocessSteps(), + pipelineStepsBuilder_->buildMainFlowSteps()); workerTasksBuilder_ = std::make_shared(coreModule_->getSpanStore(), uploadModule_->getUploadHandler(), + coreModule_->getSpanProcessingPipeline(), pluginSupportModule_->getPluginManager()); coreModule_->initializeWorkerTasks(workerTasksBuilder_->buildInitialTasks(), workerTasksBuilder_->buildRecurringTasks()); diff --git a/Sources/BugsnagPerformance/Private/Main/PipelineStepsBuilder.h b/Sources/BugsnagPerformance/Private/Main/PipelineStepsBuilder.h new file mode 100644 index 00000000..6af68f30 --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Main/PipelineStepsBuilder.h @@ -0,0 +1,75 @@ +// +// PipelineStepsBuilder.h +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 23/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#pragma once + +#import "../Core/PhasedStartup.h" +#import "../Core/Attributes/SpanAttributesProvider.h" +#import "../Core/BSGPrioritizedStore.h" +#import "../Core/Configuration/BugsnagPerformanceConfiguration+Private.h" +#import "../Core/Sampler/Sampler.h" +#import "../Core/SpanProcessingPipeline/SpanProcessingPipelineStep.h" +#import "../Core/SpanFactory/Plain/PlainSpanFactory.h" +#import "../Metrics/SystemMetrics/SystemInfoSampler.h" + +#import +#import + +namespace bugsnag { +class PipelineStepsBuilder: public PhasedStartup { +public: + PipelineStepsBuilder(std::shared_ptr systemInfoSampler, + std::shared_ptr spanAttributesProvider, + std::shared_ptr plainSpanFactory, + std::shared_ptr sampler, + BSGPrioritizedStore *onSpanEndCallbacks) noexcept + : systemInfoSampler_(systemInfoSampler) + , spanAttributesProvider_(spanAttributesProvider) + , plainSpanFactory_(plainSpanFactory) + , sampler_(sampler) + , onSpanEndCallbacks_(onSpanEndCallbacks) {}; + + ~PipelineStepsBuilder() {}; + + void earlyConfigure(BSGEarlyConfiguration *) noexcept {} + void earlySetup() noexcept {} + void configure(BugsnagPerformanceConfiguration *config) noexcept; + void preStartSetup() noexcept {} + void start() noexcept {} + + std::vector> buildPreprocessSteps() noexcept; + std::vector> buildMainFlowSteps() noexcept; +private: + + BugsnagPerformanceConfiguration *configuration_; + BugsnagPerformanceEnabledMetrics *enabledMetrics_{[BugsnagPerformanceEnabledMetrics withAllEnabled]}; + + std::shared_ptr systemInfoSampler_; + std::shared_ptr spanAttributesProvider_; + std::shared_ptr plainSpanFactory_; + std::shared_ptr sampler_; + BSGPrioritizedStore *onSpanEndCallbacks_; + + std::shared_ptr buildAddSystemMetricsStep() noexcept; + std::shared_ptr buildAddFrameMetricsStep() noexcept; + std::shared_ptr buildProcessConditionsStep() noexcept; + std::shared_ptr buildFilterOutSpansStep() noexcept; + std::shared_ptr buildRunEndCallbacksStep() noexcept; + + bool shouldSampleCPU(BugsnagPerformanceSpan *span) noexcept; + bool shouldSampleMemory(BugsnagPerformanceSpan *span) noexcept; + bool shouldInstrumentRendering(BugsnagPerformanceSpan *span) noexcept; + + void processFrameMetrics(BugsnagPerformanceSpan *span) noexcept; + void createFrozenFrameSpan(NSTimeInterval startTime, + NSTimeInterval endTime, + BugsnagPerformanceSpanContext *parentContext) noexcept; + void callOnSpanEndCallbacks(BugsnagPerformanceSpan *span) noexcept; + void processSpanConditions(BugsnagPerformanceSpan *span) noexcept; +}; +} diff --git a/Sources/BugsnagPerformance/Private/Main/PipelineStepsBuilder.mm b/Sources/BugsnagPerformance/Private/Main/PipelineStepsBuilder.mm new file mode 100644 index 00000000..99214ffa --- /dev/null +++ b/Sources/BugsnagPerformance/Private/Main/PipelineStepsBuilder.mm @@ -0,0 +1,226 @@ +// +// PipelineStepsBuilder.mm +// BugsnagPerformance +// +// Created by Robert Bartoszewski on 23/10/2025. +// Copyright © 2025 Bugsnag. All rights reserved. +// + +#import "PipelineStepsBuilder.h" +#import "../Core/Span/BugsnagPerformanceSpan+Private.h" +#import "../Metrics/FrameMetrics/FrameMetricsSnapshot.h" + +#define buildSyncStep(workBlock) \ + __block auto blockThis = this; \ + auto work = ^bool (BugsnagPerformanceSpan *span) { \ + workBlock \ + }; \ + return std::make_shared(work) + +using namespace bugsnag; + +#pragma mark PhasedStartup + +void +PipelineStepsBuilder::configure(BugsnagPerformanceConfiguration *config) noexcept { + configuration_ = config; + enabledMetrics_ = config.enabledMetrics; +} + +#pragma mark Public + +std::vector> +PipelineStepsBuilder::buildPreprocessSteps() noexcept { + auto result = std::vector>(); + result.push_back(buildProcessConditionsStep()); + result.push_back(buildAddFrameMetricsStep()); + result.push_back(buildFilterOutSpansStep()); + result.push_back(buildRunEndCallbacksStep()); + return result; +} + +std::vector> +PipelineStepsBuilder::buildMainFlowSteps() noexcept { + auto result = std::vector>(); + result.push_back(buildAddSystemMetricsStep()); + result.push_back(buildFilterOutSpansStep()); + return result; +} + +#pragma mark Common Steps + +std::shared_ptr +PipelineStepsBuilder::buildFilterOutSpansStep() noexcept { + buildSyncStep( + if(span.state == SpanStateAborted) { + return false; + } + + if (!blockThis->sampler_->sampled(span)) { + [span abortUnconditionally]; + return false; + } + return true; + ); +} + +#pragma mark Preprocess Steps + +std::shared_ptr +PipelineStepsBuilder::buildProcessConditionsStep() noexcept { + buildSyncStep( + blockThis->processSpanConditions(span); + return true; + ); +} + +std::shared_ptr +PipelineStepsBuilder::buildAddFrameMetricsStep() noexcept { + buildSyncStep( + if (blockThis->shouldInstrumentRendering(span)) { + blockThis->processFrameMetrics(span); + } + return true; + ); +} + +std::shared_ptr +PipelineStepsBuilder::buildRunEndCallbacksStep() noexcept { + buildSyncStep( + if (span != nil && span.state == SpanStateEnded) { + blockThis->callOnSpanEndCallbacks(span); + if (span.state == SpanStateAborted) { + return false; + } + } + return true; + ); +} + +#pragma mark Main Flow Steps + +std::shared_ptr +PipelineStepsBuilder::buildAddSystemMetricsStep() noexcept { + buildSyncStep( + auto samples = blockThis->systemInfoSampler_->samplesAroundTimePeriod(span.actuallyStartedAt, span.actuallyEndedAt); + if (samples.size() >= 2) { + if (blockThis->shouldSampleCPU(span)) { + [span forceMutate:^() { + [span internalSetMultipleAttributes:blockThis->spanAttributesProvider_->cpuSampleAttributes(samples)]; + }]; + } + if (blockThis->shouldSampleMemory(span)) { + [span forceMutate:^() { + [span internalSetMultipleAttributes:blockThis->spanAttributesProvider_->memorySampleAttributes(samples)]; + }]; + } + } + return true; + ); +} + +#pragma mark Utility + +bool +PipelineStepsBuilder::shouldSampleCPU(BugsnagPerformanceSpan *span) noexcept { + if (span.metricsOptions.cpu == BSGTriStateUnset) { + return span.firstClass == BSGTriStateYes; + } + return span.metricsOptions.cpu == BSGTriStateYes; +} + +bool +PipelineStepsBuilder::shouldSampleMemory(BugsnagPerformanceSpan *span) noexcept { + if (span.metricsOptions.memory == BSGTriStateUnset) { + return span.firstClass == BSGTriStateYes; + } + return span.metricsOptions.memory == BSGTriStateYes; +} + +bool +PipelineStepsBuilder::shouldInstrumentRendering(BugsnagPerformanceSpan *span) noexcept { + switch (span.metricsOptions.rendering) { + case BSGTriStateYes: + return enabledMetrics_.rendering; + case BSGTriStateNo: + return false; + case BSGTriStateUnset: + return enabledMetrics_.rendering && + !span.wasStartOrEndTimeProvided && + span.firstClass == BSGTriStateYes; + } +} + +void +PipelineStepsBuilder::processFrameMetrics(BugsnagPerformanceSpan *span) noexcept { + auto startSnapshot = span.startFramerateSnapshot; + auto endSnapshot = span.endFramerateSnapshot; + if (!shouldInstrumentRendering(span) || + startSnapshot == nil || + endSnapshot == nil) { + return; + } + auto mergedSnapshot = [FrameMetricsSnapshot mergeWithStart:startSnapshot + end:endSnapshot]; + if (mergedSnapshot.totalFrames == 0) { + return; + } + [span setAttribute:@"bugsnag.rendering.total_frames" withValue:@(mergedSnapshot.totalFrames)]; + [span setAttribute:@"bugsnag.rendering.slow_frames" withValue:@(mergedSnapshot.totalSlowFrames)]; + [span setAttribute:@"bugsnag.rendering.frozen_frames" withValue:@(mergedSnapshot.totalFrozenFrames)]; + + auto frozenFrame = mergedSnapshot.firstFrozenFrame; + while (frozenFrame != nil) { + createFrozenFrameSpan(frozenFrame.startTime, frozenFrame.endTime, span); + frozenFrame = frozenFrame != mergedSnapshot.lastFrozenFrame ? frozenFrame.next : nil; + } +} + +void +PipelineStepsBuilder::createFrozenFrameSpan(NSTimeInterval startTime, + NSTimeInterval endTime, + BugsnagPerformanceSpanContext *parentContext) noexcept { + SpanOptions options; + options.startTime = startTime; + options.parentContext = parentContext; + options.makeCurrentContext = false; + auto span = plainSpanFactory_->startSpan(@"FrozenFrame", options, BSGTriStateNo, @{}, @[]); + [span endWithAbsoluteTime:endTime]; +} + +void +PipelineStepsBuilder::callOnSpanEndCallbacks(BugsnagPerformanceSpan *span) noexcept { + if (span == nil) { + return; + } + if (span.state != SpanStateEnded) { + return; + } + + CFAbsoluteTime callbacksStartTime = CFAbsoluteTimeGetCurrent(); + for (BugsnagPerformanceSpanEndCallback callback: [onSpanEndCallbacks_ objects]) { + BOOL shouldDiscardSpan = false; + @try { + shouldDiscardSpan = !callback(span); + } @catch(NSException *e) { + BSGLogError(@"Tracer::callOnSpanEndCallbacks: span OnEnd callback threw exception: %@", e); + // We don't know whether they wanted to discard the span or not, so keep it. + shouldDiscardSpan = false; + } + if(shouldDiscardSpan) { + [span abortUnconditionally]; + return; + } + } + CFAbsoluteTime callbacksEndTime = CFAbsoluteTimeGetCurrent(); + [span internalSetAttribute:@"bugsnag.span.callbacks_duration" withValue:@(intervalToNanoseconds(callbacksEndTime - callbacksStartTime))]; +} + +void +PipelineStepsBuilder::processSpanConditions(BugsnagPerformanceSpan *span) noexcept { + @synchronized (span) { + for (BugsnagPerformanceSpanCondition *condition in span.conditionsToEndOnClose) { + [condition closeWithEndTime:span.endTime]; + } + } +} diff --git a/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.h b/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.h index 7f1e5043..9470b90a 100644 --- a/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.h +++ b/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.h @@ -10,6 +10,7 @@ #import "../Core/Worker/AsyncToSyncTask.h" #import "../Core/SpanStore/SpanStore.h" +#import "../Core/SpanProcessingPipeline/SpanProcessingPipeline.h" #import "../PluginSupport/PluginManager/BSGPluginManager.h" #import "../Upload/UploadHandler/UploadHandler.h" @@ -21,9 +22,11 @@ class WorkerTasksBuilder { public: WorkerTasksBuilder(std::shared_ptr spanStore, std::shared_ptr uploadHandler, + std::shared_ptr pipeline, BSGPluginManager *pluginManager) noexcept : spanStore_(spanStore) , uploadHandler_(uploadHandler) + , pipeline_(pipeline) , pluginManager_(pluginManager) {}; ~WorkerTasksBuilder() {}; @@ -34,10 +37,13 @@ class WorkerTasksBuilder { std::shared_ptr spanStore_; std::shared_ptr uploadHandler_; + std::shared_ptr pipeline_; BSGPluginManager *pluginManager_; - std::shared_ptr buildGetPValueTask() noexcept; + std::shared_ptr buildGetInitialPValueTask() noexcept; std::shared_ptr buildStartPluginsTask() noexcept; + + std::shared_ptr buildGetPValueTask() noexcept; std::shared_ptr buildSendCurrentBatchTask() noexcept; std::shared_ptr buildSendRetriesTask() noexcept; std::shared_ptr buildSweepStoreTask() noexcept; diff --git a/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.mm b/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.mm index e8dc8396..8c0fed3c 100644 --- a/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.mm +++ b/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.mm @@ -8,12 +8,19 @@ #import "WorkerTasksBuilder.h" +#define buildTask(work) \ + __block auto blockThis = this; \ + auto workBlock = ^(TaskCompletion completion){ \ + work \ + }; \ + return std::make_shared(workBlock) + using namespace bugsnag; std::vector> WorkerTasksBuilder::buildInitialTasks() noexcept { auto result = std::vector>(); - result.push_back(buildGetPValueTask()); + result.push_back(buildGetInitialPValueTask()); result.push_back(buildStartPluginsTask()); return result; } @@ -28,52 +35,51 @@ return result; } -#pragma mark Private +#pragma mark Initial Tasks std::shared_ptr -WorkerTasksBuilder::buildGetPValueTask() noexcept { - __block auto blockThis = this; - auto work = ^(TaskCompletion completion){ - blockThis->uploadHandler_->uploadPValueRequest(completion); - }; - return std::make_shared(work); +WorkerTasksBuilder::buildGetInitialPValueTask() noexcept { + return buildGetPValueTask(); } std::shared_ptr WorkerTasksBuilder::buildStartPluginsTask() noexcept { - __block auto blockThis = this; - auto work = ^(TaskCompletion completion){ + buildTask( [blockThis->pluginManager_ startPlugins]; completion(false); - }; - return std::make_shared(work); + ); +} + +std::shared_ptr +WorkerTasksBuilder::buildGetPValueTask() noexcept { + buildTask( + blockThis->uploadHandler_->uploadPValueRequest(completion); + ); } std::shared_ptr WorkerTasksBuilder::buildSendCurrentBatchTask() noexcept { - __block auto blockThis = this; - auto work = ^(TaskCompletion completion){ - // TODO - blockThis->uploadHandler_->uploadSpans(@[], completion); - }; - return std::make_shared(work); + buildTask( + auto spans = blockThis->pipeline_->drainSendableSpans(); + if (spans.count == 0) { + completion(false); + return; + } + blockThis->uploadHandler_->uploadSpans(spans, completion); + ); } std::shared_ptr WorkerTasksBuilder::buildSendRetriesTask() noexcept { - __block auto blockThis = this; - auto work = ^(TaskCompletion completion){ + buildTask( blockThis->uploadHandler_->sendRetries(completion); - }; - return std::make_shared(work); + ); } std::shared_ptr WorkerTasksBuilder::buildSweepStoreTask() noexcept { - __block auto blockThis = this; - auto work = ^(TaskCompletion completion){ + buildTask( blockThis->spanStore_->sweep(); completion(false); - }; - return std::make_shared(work); + ); } diff --git a/Sources/BugsnagPerformance/Private/Metrics/MetricsModule.h b/Sources/BugsnagPerformance/Private/Metrics/MetricsModule.h index 9137789f..c8067103 100644 --- a/Sources/BugsnagPerformance/Private/Metrics/MetricsModule.h +++ b/Sources/BugsnagPerformance/Private/Metrics/MetricsModule.h @@ -34,6 +34,8 @@ class MetricsModule: public Module, public AppLifecycleListener { void onAppEnteredBackground() noexcept; void onAppEnteredForeground() noexcept; + double getSamplerInterval() noexcept; + // Tasks GetCurrentFrameMetricsSnapshot getCurrentFrameMetricsSnapshotTask() noexcept; diff --git a/Sources/BugsnagPerformance/Private/Metrics/MetricsModule.mm b/Sources/BugsnagPerformance/Private/Metrics/MetricsModule.mm index fd11cb34..c6529d38 100644 --- a/Sources/BugsnagPerformance/Private/Metrics/MetricsModule.mm +++ b/Sources/BugsnagPerformance/Private/Metrics/MetricsModule.mm @@ -52,6 +52,11 @@ systemInfoSampler_ = std::make_shared(SAMPLER_INTERVAL_SECONDS, SAMPLER_HISTORY_SECONDS); } +double +MetricsModule::getSamplerInterval() noexcept { + return SAMPLER_INTERVAL_SECONDS; +} + #pragma mark Tasks GetCurrentFrameMetricsSnapshot diff --git a/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.h b/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.h index 6311582f..27720616 100644 --- a/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.h +++ b/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.h @@ -19,7 +19,9 @@ NS_ASSUME_NONNULL_BEGIN @interface BSGPluginManager : NSObject -- (instancetype)initWithSpanControlProvider:(BSGCompositeSpanControlProvider *)compositeProvider; +- (instancetype)initWithSpanControlProvider:(BSGCompositeSpanControlProvider *)compositeProvider + onSpanStartCallbacks:(BSGPrioritizedStore *)onSpanStartCallbacks + onSpanEndCallbacks:(BSGPrioritizedStore *)onSpanEndCallbacks; - (void)installPlugins:(NSArray> *)plugins; - (void)startPlugins; diff --git a/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.m b/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.m index 0ecea5ea..108f5c04 100644 --- a/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.m +++ b/Sources/BugsnagPerformance/Private/PluginSupport/PluginManager/BSGPluginManager.m @@ -24,13 +24,13 @@ @interface BSGPluginManager () @implementation BSGPluginManager - (instancetype)initWithSpanControlProvider:(BSGCompositeSpanControlProvider *)compositeProvider -{ + onSpanStartCallbacks:(BSGPrioritizedStore *)onSpanStartCallbacks + onSpanEndCallbacks:(BSGPrioritizedStore *)onSpanEndCallbacks { self = [super init]; if (self) { _compositeProvider = compositeProvider; - - _onSpanStartCallbacks = [BSGPrioritizedStore new]; - _onSpanEndCallbacks = [BSGPrioritizedStore new]; + _onSpanStartCallbacks = onSpanStartCallbacks; + _onSpanEndCallbacks = onSpanEndCallbacks; _installedPlugins = [NSMutableArray array]; } return self; diff --git a/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.h b/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.h index c514be4d..946d0d07 100644 --- a/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.h +++ b/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.h @@ -17,7 +17,10 @@ namespace bugsnag { class PluginSupportModule: public Module { public: - PluginSupportModule() {}; + PluginSupportModule(BSGPrioritizedStore *spanStartCallbacks, + BSGPrioritizedStore *spanEndCallbacks) noexcept + : spanStartCallbacks_(spanStartCallbacks) + , spanEndCallbacks_(spanEndCallbacks) {}; ~PluginSupportModule() {}; @@ -37,6 +40,9 @@ class PluginSupportModule: public Module { BSGPluginManager *getPluginManager() noexcept { return pluginManager_; } private: + // Dependencies + BSGPrioritizedStore *spanStartCallbacks_; + BSGPrioritizedStore *spanEndCallbacks_; // Components BSGCompositeSpanControlProvider *spanControlProvider_; diff --git a/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.mm b/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.mm index ac793ac6..50e9c025 100644 --- a/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.mm +++ b/Sources/BugsnagPerformance/Private/PluginSupport/PluginSupportModule.mm @@ -42,5 +42,7 @@ void PluginSupportModule::setUp() noexcept { spanControlProvider_ = [BSGCompositeSpanControlProvider new]; - pluginManager_ = [[BSGPluginManager alloc] initWithSpanControlProvider:spanControlProvider_]; + pluginManager_ = [[BSGPluginManager alloc] initWithSpanControlProvider:spanControlProvider_ + onSpanStartCallbacks:spanStartCallbacks_ + onSpanEndCallbacks:spanEndCallbacks_]; } diff --git a/Sources/BugsnagPerformance/Private/Plugins/PluginsModule.h b/Sources/BugsnagPerformance/Private/Plugins/PluginsModule.h index 3479c7d4..f4f9fa97 100644 --- a/Sources/BugsnagPerformance/Private/Plugins/PluginsModule.h +++ b/Sources/BugsnagPerformance/Private/Plugins/PluginsModule.h @@ -34,7 +34,6 @@ class PluginsModule: public Module { GetPluginsTask getDefaultPluginsTask(); // Component access - BugsnagPerformanceAppStartTypePlugin *getAppStartTypePlugin() noexcept { return appStartTypePlugin_; } private: diff --git a/Sources/BugsnagPerformance/Private/Upload/UploadHandler/UploadHandlerImpl.mm b/Sources/BugsnagPerformance/Private/Upload/UploadHandler/UploadHandlerImpl.mm index 20e4edca..b58f3c6c 100644 --- a/Sources/BugsnagPerformance/Private/Upload/UploadHandler/UploadHandlerImpl.mm +++ b/Sources/BugsnagPerformance/Private/Upload/UploadHandler/UploadHandlerImpl.mm @@ -52,57 +52,6 @@ uploadPackage(traceEncoding_->buildUploadPackage(spans, resourceAttributes_->get(), includeSamplingHeader), false, completion); } - -// TODO: Move to pipeline -//bool NSArray::sendCurrentBatchTask() noexcept { -// BSGLogDebug(@"BugsnagPerformanceImpl::sendCurrentBatchTask()"); -// auto origSpans = batch_->drain(false); -//#ifndef __clang_analyzer__ -// #pragma clang diagnostic ignored "-Wunused-variable" -// size_t origSpansSize = origSpans.count; -//#endif -// auto spans = sendableSpans(origSpans); -// if (spans.count == 0) { -//#ifndef __clang_analyzer__ -// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Nothing to send. origSpans size = %zu", origSpansSize); -//#endif -// return false; -// } -// bool includeSamplingHeader = configuration_ == nil || configuration_.samplingProbability == nil; -// -// // Delay so that the sampler has time to fetch one more sample. -// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Delaying %f seconds (%lld ns) before getting system info", SAMPLER_INTERVAL_SECONDS + 0.5, (int64_t)((SAMPLER_INTERVAL_SECONDS + 0.5) * NSEC_PER_SEC)); -// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((SAMPLER_INTERVAL_SECONDS + 0.5) * NSEC_PER_SEC)), -// dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{ -// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Delayed %f seconds, now getting system info", SAMPLER_INTERVAL_SECONDS + 0.5); -// for(BugsnagPerformanceSpan *span: spans) { -// auto samples = systemInfoSampler_.samplesAroundTimePeriod(span.actuallyStartedAt, span.actuallyEndedAt); -// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): System info sample size = %zu", samples.size()); -// if (samples.size() >= 2) { -// if (shouldSampleCPU(span)) { -// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Getting CPU sample attributes for span %@", span.name); -// [span forceMutate:^() { -// [span internalSetMultipleAttributes:spanAttributesProvider_->cpuSampleAttributes(samples)]; -// }]; -// } -// if (shouldSampleMemory(span)) { -// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Getting memory sample attributes for span %@", span.name); -// [span forceMutate:^() { -// [span internalSetMultipleAttributes:spanAttributesProvider_->memorySampleAttributes(samples)]; -// }]; -// } -// } -// } -// -//#ifndef __clang_analyzer__ -// BSGLogTrace(@"BugsnagPerformanceImpl::sendCurrentBatchTask(): Sending %zu sampled spans (out of %zu)", origSpansSize, spans.count); -//#endif -// uploadPackage(traceEncoding_.buildUploadPackage(spans, resourceAttributes_->get(), includeSamplingHeader), false); -// }); -// -// return true; -//} - void UploadHandlerImpl::sendRetries(TaskCompletion completion) noexcept { retryQueue_->sweep(); @@ -166,15 +115,3 @@ completion(true); }); } - -// TODO: Move to pipeline -//NSArray * -//UploadHandlerImpl::sendableSpans(NSArray *spans) noexcept { -// NSMutableArray *sendableSpans = [NSMutableArray arrayWithCapacity:spans.count]; -// for (BugsnagPerformanceSpan *span in spans) { -// if (span.state != SpanStateAborted && sampler_->sampled(span)) { -// [sendableSpans addObject:span]; -// } -// } -// return sendableSpans; -//} From 5f5067bcb59faa7f39d932ffbe23435b49870e56 Mon Sep 17 00:00:00 2001 From: Robert Bartoszewski Date: Fri, 24 Oct 2025 09:55:41 +0200 Subject: [PATCH 08/14] Fixes --- .../Private/Core/CoreModule.mm | 5 +++++ .../SpanLifecycle/SpanLifecycleHandlerImpl.h | 2 +- .../SpanLifecycle/SpanLifecycleHandlerImpl.mm | 6 ------ .../SpanProcessingPipelineImpl.h | 2 +- .../SpanProcessingPipelineImpl.mm | 16 ++++++++-------- .../Private/Main/PipelineStepsBuilder.mm | 4 +++- .../Private/Main/WorkerTasksBuilder.mm | 1 + 7 files changed, 19 insertions(+), 17 deletions(-) diff --git a/Sources/BugsnagPerformance/Private/Core/CoreModule.mm b/Sources/BugsnagPerformance/Private/Core/CoreModule.mm index c984c43a..b200820c 100644 --- a/Sources/BugsnagPerformance/Private/Core/CoreModule.mm +++ b/Sources/BugsnagPerformance/Private/Core/CoreModule.mm @@ -22,6 +22,7 @@ plainSpanFactory_->earlyConfigure(config); resourceAttributes_->earlyConfigure(config); batch_->earlyConfigure(config); + pipeline_->earlyConfigure(config); spanLifecycleHandler_->earlyConfigure(config); networkSpanReporter_->earlyConfigure(config); [worker_ earlyConfigure:config]; @@ -33,6 +34,7 @@ plainSpanFactory_->earlySetup(); resourceAttributes_->earlySetup(); batch_->earlySetup(); + pipeline_->earlySetup(); spanLifecycleHandler_->earlySetup(); networkSpanReporter_->earlySetup(); [worker_ earlySetup]; @@ -45,6 +47,7 @@ plainSpanFactory_->configure(config); resourceAttributes_->configure(config); batch_->configure(config); + pipeline_->configure(config); spanLifecycleHandler_->configure(config); networkSpanReporter_->configure(config); [worker_ configure:config]; @@ -56,6 +59,7 @@ plainSpanFactory_->preStartSetup(); resourceAttributes_->preStartSetup(); batch_->preStartSetup(); + pipeline_->preStartSetup(); spanLifecycleHandler_->preStartSetup(); networkSpanReporter_->preStartSetup(); [worker_ preStartSetup]; @@ -75,6 +79,7 @@ plainSpanFactory_->start(); resourceAttributes_->start(); batch_->start(); + pipeline_->start(); spanLifecycleHandler_->start(); networkSpanReporter_->start(); [worker_ start]; diff --git a/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.h b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.h index 80b80bc7..a4435e5b 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.h @@ -45,7 +45,7 @@ class SpanLifecycleHandlerImpl: public SpanLifecycleHandler { void configure(BugsnagPerformanceConfiguration *config) noexcept { enabledMetrics_ = [config.enabledMetrics clone]; } - void preStartSetup() noexcept; + void preStartSetup() noexcept {} void start() noexcept { isStarted_ = true; } diff --git a/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.mm b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.mm index 8d333635..958f7495 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.mm +++ b/Sources/BugsnagPerformance/Private/Core/SpanLifecycle/SpanLifecycleHandlerImpl.mm @@ -11,12 +11,6 @@ using namespace bugsnag; - -void -SpanLifecycleHandlerImpl::preStartSetup() noexcept { - pipeline_->processPendingSpansIfNeeded(); -} - void SpanLifecycleHandlerImpl::onSpanStarted(BugsnagPerformanceSpan *span, const SpanOptions &options) noexcept { if (shouldInstrumentRendering(span) && getCurrentSnapshot_) { diff --git a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.h b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.h index 46c8bc3e..7392de43 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.h @@ -56,7 +56,7 @@ class SpanProcessingPipelineImpl: public SpanProcessingPipeline, public PhasedSt std::vector> preprocessFlow_{}; std::vector> mainFlow_{}; - std::mutex mutex_; + std::recursive_mutex mutex_; NSArray *executeFlow(std::vector> *flow, NSArray *spans) noexcept; diff --git a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.mm b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.mm index 432a2708..54da3dff 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.mm +++ b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.mm @@ -14,7 +14,7 @@ void SpanProcessingPipelineImpl::preStartSetup() noexcept { - std::lock_guard guard(mutex_); + std::lock_guard guard(mutex_); auto spans = executeFlow(&preprocessFlow_, preStartSpans_); [preStartSpans_ removeAllObjects]; for (BugsnagPerformanceSpan *span in spans) { @@ -28,7 +28,7 @@ void SpanProcessingPipelineImpl::addSpanForProcessing(BugsnagPerformanceSpan *span) noexcept { - std::lock_guard guard(mutex_); + std::lock_guard guard(mutex_); auto spans = executeFlow(&preprocessFlow_, @[span]); if (spans.count == 0) { return; @@ -42,7 +42,7 @@ void SpanProcessingPipelineImpl::removeSpan(BugsnagPerformanceSpan *span) noexcept { - std::lock_guard guard(mutex_); + std::lock_guard guard(mutex_); if (isStarted_) { batch_->removeSpan(span.traceIdHi, span.traceIdLo, span.spanId); } else { @@ -52,7 +52,7 @@ void SpanProcessingPipelineImpl::processPendingSpansIfNeeded() noexcept { - std::lock_guard guard(mutex_); + std::lock_guard guard(mutex_); __block auto spans = batch_->drain(false); __block auto blockThis = this; if (spans.count > 0) { @@ -74,13 +74,13 @@ void SpanProcessingPipelineImpl::addPreprocessStep(std::shared_ptr step) noexcept { - std::lock_guard guard(mutex_); + std::lock_guard guard(mutex_); preprocessFlow_.push_back(step); } void SpanProcessingPipelineImpl::addMainFlowStep(std::shared_ptr step) noexcept { - std::lock_guard guard(mutex_); + std::lock_guard guard(mutex_); mainFlow_.push_back(step); } @@ -89,7 +89,7 @@ NSArray * SpanProcessingPipelineImpl::executeFlow(std::vector> *flow, NSArray *spans) noexcept { - std::lock_guard guard(mutex_); + std::lock_guard guard(mutex_); if (!flow || !spans) { return @[]; } @@ -110,7 +110,7 @@ void SpanProcessingPipelineImpl::processPendingSpans(NSArray *spans) noexcept { - std::lock_guard guard(mutex_); + std::lock_guard guard(mutex_); auto spansToSend = executeFlow(&mainFlow_, spans); if (spansToSend.count > 0) { [sendableSpans_ addObjectsFromArray:spansToSend]; diff --git a/Sources/BugsnagPerformance/Private/Main/PipelineStepsBuilder.mm b/Sources/BugsnagPerformance/Private/Main/PipelineStepsBuilder.mm index 99214ffa..faa0eaec 100644 --- a/Sources/BugsnagPerformance/Private/Main/PipelineStepsBuilder.mm +++ b/Sources/BugsnagPerformance/Private/Main/PipelineStepsBuilder.mm @@ -88,7 +88,9 @@ PipelineStepsBuilder::buildRunEndCallbacksStep() noexcept { buildSyncStep( if (span != nil && span.state == SpanStateEnded) { - blockThis->callOnSpanEndCallbacks(span); + [span forceMutate:^{ + blockThis->callOnSpanEndCallbacks(span); + }]; if (span.state == SpanStateAborted) { return false; } diff --git a/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.mm b/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.mm index 8c0fed3c..ff7fd45c 100644 --- a/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.mm +++ b/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.mm @@ -60,6 +60,7 @@ std::shared_ptr WorkerTasksBuilder::buildSendCurrentBatchTask() noexcept { buildTask( + blockThis->pipeline_->processPendingSpansIfNeeded(); auto spans = blockThis->pipeline_->drainSendableSpans(); if (spans.count == 0) { completion(false); From c857f898d1fca799792665abd4408ab71cf36f9d Mon Sep 17 00:00:00 2001 From: Robert Bartoszewski Date: Fri, 24 Oct 2025 19:14:22 +0200 Subject: [PATCH 09/14] Fixed unit tests --- .../SpanProcessingPipelineImpl.h | 2 ++ .../SpanProcessingPipelineImpl.mm | 34 +++++++++++++------ .../Private/Main/PipelineStepsBuilder.mm | 2 +- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.h b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.h index 7392de43..9be6333a 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.h +++ b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.h @@ -60,6 +60,8 @@ class SpanProcessingPipelineImpl: public SpanProcessingPipeline, public PhasedSt NSArray *executeFlow(std::vector> *flow, NSArray *spans) noexcept; + bool executeFlow(std::vector> *flow, + BugsnagPerformanceSpan *span) noexcept; void processPendingSpans(NSArray *spans) noexcept; }; } diff --git a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.mm b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.mm index 54da3dff..8c8ad6a8 100644 --- a/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.mm +++ b/Sources/BugsnagPerformance/Private/Core/SpanProcessingPipeline/SpanProcessingPipelineImpl.mm @@ -29,8 +29,8 @@ void SpanProcessingPipelineImpl::addSpanForProcessing(BugsnagPerformanceSpan *span) noexcept { std::lock_guard guard(mutex_); - auto spans = executeFlow(&preprocessFlow_, @[span]); - if (spans.count == 0) { + bool shouldBeProcessed = executeFlow(&preprocessFlow_, span); + if (!shouldBeProcessed) { return; } if (isStarted_) { @@ -93,21 +93,33 @@ if (!flow || !spans) { return @[]; } - NSMutableArray *spansToProcess = [spans mutableCopy]; + NSMutableArray *spansToProcess = [NSMutableArray new]; - for (const auto& step : *flow) { - NSMutableArray *spansToRemove = [NSMutableArray array]; - for (BugsnagPerformanceSpan *span in spansToProcess) { - bool shouldContinueWithCurrentSpan = step->run(span); - if (!shouldContinueWithCurrentSpan) { - [spansToRemove addObject:span]; - } + for (BugsnagPerformanceSpan *span in spans) { + bool shouldProcessCurrentSpan = executeFlow(flow, span); + if (shouldProcessCurrentSpan) { + [spansToProcess addObject:span]; } - [spansToProcess removeObjectsInArray:spansToRemove]; } return spansToProcess; } +bool +SpanProcessingPipelineImpl::executeFlow(std::vector> *flow, + BugsnagPerformanceSpan *span) noexcept { + std::lock_guard guard(mutex_); + if (!flow || !span) { + return false; + } + bool didPassSteps = true; + for (const auto& step : *flow) { + if (didPassSteps) { + didPassSteps = step->run(span); + } + } + return didPassSteps; +} + void SpanProcessingPipelineImpl::processPendingSpans(NSArray *spans) noexcept { std::lock_guard guard(mutex_); diff --git a/Sources/BugsnagPerformance/Private/Main/PipelineStepsBuilder.mm b/Sources/BugsnagPerformance/Private/Main/PipelineStepsBuilder.mm index faa0eaec..94415326 100644 --- a/Sources/BugsnagPerformance/Private/Main/PipelineStepsBuilder.mm +++ b/Sources/BugsnagPerformance/Private/Main/PipelineStepsBuilder.mm @@ -33,8 +33,8 @@ PipelineStepsBuilder::buildPreprocessSteps() noexcept { auto result = std::vector>(); result.push_back(buildProcessConditionsStep()); - result.push_back(buildAddFrameMetricsStep()); result.push_back(buildFilterOutSpansStep()); + result.push_back(buildAddFrameMetricsStep()); result.push_back(buildRunEndCallbacksStep()); return result; } From e3c69b6e3d5530af9814e7aca70d8efebfa13eaf Mon Sep 17 00:00:00 2001 From: Robert Bartoszewski Date: Sat, 25 Oct 2025 13:22:58 +0200 Subject: [PATCH 10/14] Moved instrumentation setup to InstrumentationModule --- .../Private/Instrumentation/Instrumentation.h | 32 ++--- .../Instrumentation/Instrumentation.mm | 77 ------------ .../Instrumentation/InstrumentationModule.h | 12 ++ .../Instrumentation/InstrumentationModule.mm | 112 +++++++++++++++++- 4 files changed, 128 insertions(+), 105 deletions(-) diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.h b/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.h index 15042c71..67e362a4 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.h @@ -28,34 +28,22 @@ NS_ASSUME_NONNULL_BEGIN typedef AppStartupInstrumentationStateSnapshot * _Nullable (^GetAppStartInstrumentationStateSnapshot)(); -std::shared_ptr createAppStartupInstrumentation(std::shared_ptr spanFactory, - std::shared_ptr spanAttributesProvider); - -std::shared_ptr createViewLoadInstrumentation(std::shared_ptr spanFactory, - std::shared_ptr spanAttributesProvider); - -std::shared_ptr createNetworkInstrumentation(std::shared_ptr spanFactory, - std::shared_ptr spanAttributesProvider, - std::shared_ptr networkHeaderInjector); - namespace bugsnag { class Instrumentation: public PhasedStartup, public AppLifecycleListener { public: - Instrumentation(std::shared_ptr appStartupSpanFactory, - std::shared_ptr viewLoadSpanFactory, - std::shared_ptr networkSpanFactory, - std::shared_ptr spanAttributesProvider, - std::shared_ptr networkHeaderInjector) noexcept - : appStartupInstrumentation_(createAppStartupInstrumentation(appStartupSpanFactory, spanAttributesProvider)) - , viewLoadInstrumentation_(createViewLoadInstrumentation(viewLoadSpanFactory, spanAttributesProvider)) - , networkInstrumentation_(createNetworkInstrumentation(networkSpanFactory, spanAttributesProvider, networkHeaderInjector)) + Instrumentation(std::shared_ptr appStartupInstrumentation, + std::shared_ptr viewLoadInstrumentation, + std::shared_ptr networkInstrumentation) noexcept + : appStartupInstrumentation_(appStartupInstrumentation) + , viewLoadInstrumentation_(viewLoadInstrumentation) + , networkInstrumentation_(networkInstrumentation) {} - void earlyConfigure(BSGEarlyConfiguration *config) noexcept; - void earlySetup() noexcept; - void configure(BugsnagPerformanceConfiguration *config) noexcept; - void preStartSetup() noexcept; + void earlyConfigure(BSGEarlyConfiguration *) noexcept {} + void earlySetup() noexcept {} + void configure(BugsnagPerformanceConfiguration *) noexcept {} + void preStartSetup() noexcept {} void start() noexcept; void onAppFinishedLaunching() noexcept; diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.mm b/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.mm index e1e4479b..a370585e 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/Instrumentation.mm @@ -33,85 +33,8 @@ #pragma mark PhasedStartup -void Instrumentation::earlyConfigure(BSGEarlyConfiguration *config) noexcept { - appStartupInstrumentation_->earlyConfigure(config); - viewLoadInstrumentation_->earlyConfigure(config); - networkInstrumentation_->earlyConfigure(config); -} - -void Instrumentation::earlySetup() noexcept { - appStartupInstrumentation_->earlySetup(); - viewLoadInstrumentation_->earlySetup(); - networkInstrumentation_->earlySetup(); -} - -void Instrumentation::configure(BugsnagPerformanceConfiguration *config) noexcept { - appStartupInstrumentation_->configure(config); - viewLoadInstrumentation_->configure(config); - networkInstrumentation_->configure(config); -} - -void Instrumentation::preStartSetup() noexcept { - appStartupInstrumentation_->preStartSetup(); - viewLoadInstrumentation_->preStartSetup(); - networkInstrumentation_->preStartSetup(); -} - void Instrumentation::start() noexcept { checkAppStartDuration(); - appStartupInstrumentation_->start(); - viewLoadInstrumentation_->start(); - networkInstrumentation_->start(); -} - -#pragma mark - Factory functions - -std::shared_ptr createAppStartupInstrumentation(std::shared_ptr spanFactory, - std::shared_ptr spanAttributesProvider) { - auto systemUtils = std::make_shared(); - auto lifecycleHandler = std::make_shared(spanFactory, - spanAttributesProvider, - systemUtils, - [BugsnagPerformanceCrossTalkAPI sharedInstance]); - - return std::make_shared(lifecycleHandler, systemUtils); -} - -std::shared_ptr createViewLoadInstrumentation(std::shared_ptr spanFactory, - std::shared_ptr spanAttributesProvider) { - auto systemUtils = std::make_shared(); - auto swizzlingHandler = std::make_shared(); - auto repository = std::make_shared(); - auto earlyPhaseHandler = std::make_shared(); - auto loadingIndicatorsHandler = std::make_shared(repository); - auto lifecycleHandler = std::make_shared(earlyPhaseHandler, - spanAttributesProvider, - spanFactory, - repository, - loadingIndicatorsHandler, - [BugsnagPerformanceCrossTalkAPI sharedInstance]); - - return std::make_shared(systemUtils, swizzlingHandler, lifecycleHandler); -} - -std::shared_ptr createNetworkInstrumentation(std::shared_ptr spanFactory, - std::shared_ptr spanAttributesProvider, - std::shared_ptr networkHeaderInjector) { - auto repository = std::make_shared(); - auto systemUtils = std::make_shared(); - auto swizzlingHandler = std::make_shared(); - auto earlyPhaseHandler = std::make_shared(spanAttributesProvider); - auto lifecycleHandler = std::make_shared(spanAttributesProvider, - spanFactory, - earlyPhaseHandler, - systemUtils, - repository, - networkHeaderInjector); - auto delegate = [[BSGURLSessionPerformanceDelegate alloc] initWithLifecycleHandler:lifecycleHandler]; - return std::make_shared(systemUtils, - swizzlingHandler, - lifecycleHandler, - delegate); } #pragma mark AppLifecycleListener diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/InstrumentationModule.h b/Sources/BugsnagPerformance/Private/Instrumentation/InstrumentationModule.h index 314c4391..fc8e9dc9 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/InstrumentationModule.h +++ b/Sources/BugsnagPerformance/Private/Instrumentation/InstrumentationModule.h @@ -65,6 +65,14 @@ class InstrumentationModule: public Module, AppLifecycleListener { private: + std::shared_ptr createAppStartupInstrumentation(std::shared_ptr spanFactory, + std::shared_ptr spanAttributesProvider); + std::shared_ptr createViewLoadInstrumentation(std::shared_ptr spanFactory, + std::shared_ptr spanAttributesProvider); + std::shared_ptr createNetworkInstrumentation(std::shared_ptr spanFactory, + std::shared_ptr spanAttributesProvider, + std::shared_ptr networkHeaderInjector); + // Dependencies std::shared_ptr appStartupSpanFactory_; std::shared_ptr viewLoadSpanFactory_; @@ -74,7 +82,11 @@ class InstrumentationModule: public Module, AppLifecycleListener { std::shared_ptr sampler_; // Components + BSGURLSessionPerformanceDelegate *urlSessionDelegate_; std::shared_ptr networkHeaderInjector_; + std::shared_ptr appStartupInstrumentation_; + std::shared_ptr viewLoadInstrumentation_; + std::shared_ptr networkInstrumentation_; std::shared_ptr instrumentation_; InstrumentationModule() = delete; diff --git a/Sources/BugsnagPerformance/Private/Instrumentation/InstrumentationModule.mm b/Sources/BugsnagPerformance/Private/Instrumentation/InstrumentationModule.mm index a5083b11..80fb3fa0 100644 --- a/Sources/BugsnagPerformance/Private/Instrumentation/InstrumentationModule.mm +++ b/Sources/BugsnagPerformance/Private/Instrumentation/InstrumentationModule.mm @@ -8,6 +8,29 @@ #import "InstrumentationModule.h" +// App Startup Instrumentation +#import "AppStartupInstrumentation/System/AppStartupInstrumentationSystemUtilsImpl.h" +#import "AppStartupInstrumentation/Lifecycle/AppStartupLifecycleHandlerImpl.h" + +// 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/ViewLoadLifecycleHandlerImpl.h" + +// Network Instrumentation +#import "NetworkInstrumentation/State/NetworkInstrumentationStateRepositoryImpl.h" +#import "NetworkInstrumentation/System/NetworkInstrumentationSystemUtilsImpl.h" +#import "NetworkInstrumentation/System/NetworkSwizzlingHandlerImpl.h" +#import "NetworkInstrumentation/Lifecycle/NetworkEarlyPhaseHandlerImpl.h" +#import "NetworkInstrumentation/Lifecycle/NetworkLifecycleHandlerImpl.h" +#import "NetworkInstrumentation/System/BSGURLSessionPerformanceDelegate.h" + +// CrossTalk API +#import "../CrossTalkAPI/BugsnagPerformanceCrossTalkAPI.h" + using namespace bugsnag; #pragma mark PhasedStartup @@ -15,31 +38,51 @@ void InstrumentationModule::earlyConfigure(BSGEarlyConfiguration *config) noexcept { networkHeaderInjector_->earlyConfigure(config); + appStartupInstrumentation_->earlyConfigure(config); + viewLoadInstrumentation_->earlyConfigure(config); + networkInstrumentation_->earlyConfigure(config); instrumentation_->earlyConfigure(config); + [urlSessionDelegate_ earlyConfigure:config]; } void InstrumentationModule::earlySetup() noexcept { + [urlSessionDelegate_ earlySetup]; networkHeaderInjector_->earlySetup(); + appStartupInstrumentation_->earlySetup(); + viewLoadInstrumentation_->earlySetup(); + networkInstrumentation_->earlySetup(); instrumentation_->earlySetup(); } void InstrumentationModule::configure(BugsnagPerformanceConfiguration *config) noexcept { + [urlSessionDelegate_ configure:config]; networkHeaderInjector_->configure(config); + appStartupInstrumentation_->configure(config); + viewLoadInstrumentation_->configure(config); + networkInstrumentation_->configure(config); instrumentation_->configure(config); } void InstrumentationModule::preStartSetup() noexcept { + [urlSessionDelegate_ preStartSetup]; networkHeaderInjector_->preStartSetup(); + appStartupInstrumentation_->preStartSetup(); + viewLoadInstrumentation_->preStartSetup(); + networkInstrumentation_->preStartSetup(); instrumentation_->preStartSetup(); } void InstrumentationModule::start() noexcept { + [urlSessionDelegate_ start]; networkHeaderInjector_->start(); instrumentation_->start(); + appStartupInstrumentation_->start(); + viewLoadInstrumentation_->start(); + networkInstrumentation_->start(); } #pragma mark Module @@ -47,12 +90,16 @@ void InstrumentationModule::setUp() noexcept { networkHeaderInjector_ = std::make_shared(spanAttributesProvider_, spanStackingHandler_, sampler_); - - instrumentation_ = std::make_shared(appStartupSpanFactory_, - viewLoadSpanFactory_, - networkSpanFactory_, - spanAttributesProvider_, - networkHeaderInjector_); + appStartupInstrumentation_ = createAppStartupInstrumentation(appStartupSpanFactory_, + spanAttributesProvider_); + viewLoadInstrumentation_ = createViewLoadInstrumentation(viewLoadSpanFactory_, + spanAttributesProvider_); + networkInstrumentation_ = createNetworkInstrumentation(networkSpanFactory_, + spanAttributesProvider_, + networkHeaderInjector_); + instrumentation_ = std::make_shared(appStartupInstrumentation_, + viewLoadInstrumentation_, + networkInstrumentation_); } #pragma mark Tasks @@ -95,3 +142,56 @@ InstrumentationModule::onAppEnteredForeground() noexcept { instrumentation_->onAppEnteredForeground(); } + +#pragma mark Private + +std::shared_ptr +InstrumentationModule::createAppStartupInstrumentation(std::shared_ptr spanFactory, + std::shared_ptr spanAttributesProvider) { + auto systemUtils = std::make_shared(); + auto lifecycleHandler = std::make_shared(spanFactory, + spanAttributesProvider, + systemUtils, + [BugsnagPerformanceCrossTalkAPI sharedInstance]); + + return std::make_shared(lifecycleHandler, systemUtils); +} + +std::shared_ptr +InstrumentationModule::createViewLoadInstrumentation(std::shared_ptr spanFactory, + std::shared_ptr spanAttributesProvider) { + auto systemUtils = std::make_shared(); + auto swizzlingHandler = std::make_shared(); + auto repository = std::make_shared(); + auto earlyPhaseHandler = std::make_shared(); + auto loadingIndicatorsHandler = std::make_shared(repository); + auto lifecycleHandler = std::make_shared(earlyPhaseHandler, + spanAttributesProvider, + spanFactory, + repository, + loadingIndicatorsHandler, + [BugsnagPerformanceCrossTalkAPI sharedInstance]); + + return std::make_shared(systemUtils, swizzlingHandler, lifecycleHandler); +} + +std::shared_ptr +InstrumentationModule::createNetworkInstrumentation(std::shared_ptr spanFactory, + std::shared_ptr spanAttributesProvider, + std::shared_ptr networkHeaderInjector) { + auto repository = std::make_shared(); + auto systemUtils = std::make_shared(); + auto swizzlingHandler = std::make_shared(); + auto earlyPhaseHandler = std::make_shared(spanAttributesProvider); + auto lifecycleHandler = std::make_shared(spanAttributesProvider, + spanFactory, + earlyPhaseHandler, + systemUtils, + repository, + networkHeaderInjector); + urlSessionDelegate_ = [[BSGURLSessionPerformanceDelegate alloc] initWithLifecycleHandler:lifecycleHandler]; + return std::make_shared(systemUtils, + swizzlingHandler, + lifecycleHandler, + urlSessionDelegate_); +} From ba027a0f93476e17ed0bc768aa6b7663dd2a11be Mon Sep 17 00:00:00 2001 From: Robert Bartoszewski Date: Sat, 25 Oct 2025 15:17:39 +0200 Subject: [PATCH 11/14] Fixed a failing E2E test --- features/default/automatic_spans.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/default/automatic_spans.feature b/features/default/automatic_spans.feature index 5cc2cc2c..19cd2165 100644 --- a/features/default/automatic_spans.feature +++ b/features/default/automatic_spans.feature @@ -652,7 +652,7 @@ Feature: Automatic instrumentation spans Scenario: Automatically start a network span that has a null URL Given I run "AutoInstrumentNetworkNullURLScenario" - And I wait for 1 span + And I wait for 2 spans Then the trace "Content-Type" header equals "application/json" * 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$" * every span field "parentSpanId" does not exist From fa6fb1960ba0f9ff0fe81257d66b0844d9ab157d Mon Sep 17 00:00:00 2001 From: Robert Bartoszewski Date: Sun, 26 Oct 2025 01:22:00 +0200 Subject: [PATCH 12/14] Fixes --- .../Private/Core/Worker/AsyncToSyncTask.mm | 7 ++++++- .../BugsnagPerformance/Private/Main/WorkerTasksBuilder.h | 1 - .../BugsnagPerformance/Private/Main/WorkerTasksBuilder.mm | 6 ------ .../Private/Upload/UploadHandler/UploadHandlerImpl.mm | 2 +- Sources/BugsnagPerformance/Private/Upload/UploadModule.mm | 1 + features/default/plugins.feature | 4 ++-- .../ios/Scenarios/SamplingProbabilityZeroScenario.swift | 1 + 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Sources/BugsnagPerformance/Private/Core/Worker/AsyncToSyncTask.mm b/Sources/BugsnagPerformance/Private/Core/Worker/AsyncToSyncTask.mm index 22433495..409b2f73 100644 --- a/Sources/BugsnagPerformance/Private/Core/Worker/AsyncToSyncTask.mm +++ b/Sources/BugsnagPerformance/Private/Core/Worker/AsyncToSyncTask.mm @@ -20,12 +20,16 @@ __block BOOL didComplete = NO; __block BOOL isWaiting = NO; __block auto condition = [NSCondition new]; + __block BOOL didFinishWaiting = NO; mutex_.lock(); [condition lock]; - work_(^(bool workResult){ + work_(^(bool workResult) { result = workResult; didComplete = YES; + if (didFinishWaiting) { + return; + } blockThis->mutex_.lock(); if (isWaiting) { [condition lock]; @@ -42,6 +46,7 @@ while (timeoutDate.timeIntervalSinceNow > 0 && !didComplete) { [condition waitUntilDate:timeoutDate]; } + didFinishWaiting = YES; [condition unlock]; return result; diff --git a/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.h b/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.h index 9470b90a..a7a22267 100644 --- a/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.h +++ b/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.h @@ -40,7 +40,6 @@ class WorkerTasksBuilder { std::shared_ptr pipeline_; BSGPluginManager *pluginManager_; - std::shared_ptr buildGetInitialPValueTask() noexcept; std::shared_ptr buildStartPluginsTask() noexcept; std::shared_ptr buildGetPValueTask() noexcept; diff --git a/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.mm b/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.mm index ff7fd45c..6eae9275 100644 --- a/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.mm +++ b/Sources/BugsnagPerformance/Private/Main/WorkerTasksBuilder.mm @@ -20,7 +20,6 @@ std::vector> WorkerTasksBuilder::buildInitialTasks() noexcept { auto result = std::vector>(); - result.push_back(buildGetInitialPValueTask()); result.push_back(buildStartPluginsTask()); return result; } @@ -37,11 +36,6 @@ #pragma mark Initial Tasks -std::shared_ptr -WorkerTasksBuilder::buildGetInitialPValueTask() noexcept { - return buildGetPValueTask(); -} - std::shared_ptr WorkerTasksBuilder::buildStartPluginsTask() noexcept { buildTask( diff --git a/Sources/BugsnagPerformance/Private/Upload/UploadHandler/UploadHandlerImpl.mm b/Sources/BugsnagPerformance/Private/Upload/UploadHandler/UploadHandlerImpl.mm index b58f3c6c..2a3c50eb 100644 --- a/Sources/BugsnagPerformance/Private/Upload/UploadHandler/UploadHandlerImpl.mm +++ b/Sources/BugsnagPerformance/Private/Upload/UploadHandler/UploadHandlerImpl.mm @@ -29,6 +29,7 @@ void UploadHandlerImpl::uploadPValueRequest(TaskCompletion completion) noexcept { if (!configuration_.shouldSendReports || configuration_.samplingProbability != nil) { + completion(false); return; } auto currentTime = CFAbsoluteTimeGetCurrent(); @@ -67,7 +68,6 @@ if (retry != nullptr) { auto work = ^(TaskCompletion retryCompletion) { uploadPackage(std::move(retry), true, retryCompletion); - retryCompletion(false); }; auto task = std::make_shared(work); task->executeSync(); diff --git a/Sources/BugsnagPerformance/Private/Upload/UploadModule.mm b/Sources/BugsnagPerformance/Private/Upload/UploadModule.mm index f23bc718..fef31a38 100644 --- a/Sources/BugsnagPerformance/Private/Upload/UploadModule.mm +++ b/Sources/BugsnagPerformance/Private/Upload/UploadModule.mm @@ -50,6 +50,7 @@ retryQueue_->start(); uploader_->start(); uploadHandler_->start(); + uploadHandler_->uploadPValueRequest(^(bool) {}); } #pragma mark Module diff --git a/features/default/plugins.feature b/features/default/plugins.feature index 2c270d78..d454ce05 100644 --- a/features/default/plugins.feature +++ b/features/default/plugins.feature @@ -3,7 +3,7 @@ Feature: Plugins Scenario: Plugins can automatically update spans Given I run "PluginScenario" And I wait to receive a sampling request - And I wait to receive a trace + And I wait for 3 spans Then a span named "Span 1" contains the attributes: | attribute | type | value | @@ -24,7 +24,7 @@ Feature: Plugins Scenario: Error during plugin installation Given I run "PluginInstallErrorScenario" And I wait to receive a sampling request - And I wait to receive a trace + And I wait for 3 spans Then every span bool attribute "buggy_span_start" does not exist And every span bool attribute "buggy_span_end" does not exist diff --git a/features/fixtures/ios/Scenarios/SamplingProbabilityZeroScenario.swift b/features/fixtures/ios/Scenarios/SamplingProbabilityZeroScenario.swift index 7c16590e..8d18e14f 100644 --- a/features/fixtures/ios/Scenarios/SamplingProbabilityZeroScenario.swift +++ b/features/fixtures/ios/Scenarios/SamplingProbabilityZeroScenario.swift @@ -13,6 +13,7 @@ class SamplingProbabilityZeroScenario: Scenario { override func setInitialBugsnagConfiguration() { super.setInitialBugsnagConfiguration() bugsnagPerfConfig.internal.initialSamplingProbability = 0 + bugsnagPerfConfig.internal.autoTriggerExportOnBatchSize = 2 } override func postLoad() { From d8c5efcf408991c9472a5da229320025e17791b3 Mon Sep 17 00:00:00 2001 From: Robert Bartoszewski Date: Sun, 26 Oct 2025 14:46:47 +0100 Subject: [PATCH 13/14] Changed sampling header matching in E2E tests --- features/default/automatic_spans.feature | 6 +-- features/default/conditions.feature | 6 +-- features/default/configuration.feature | 2 +- features/default/initial-p-value.feature | 4 +- features/default/manual_spans.feature | 44 +++++++++---------- features/default/metrics.feature | 44 +++++++++---------- features/default/sampling.feature | 2 +- features/default/triggers.feature | 2 +- .../SamplingProbabilityZeroScenario.swift | 1 - 9 files changed, 55 insertions(+), 56 deletions(-) diff --git a/features/default/automatic_spans.feature b/features/default/automatic_spans.feature index 19cd2165..3b9d8645 100644 --- a/features/default/automatic_spans.feature +++ b/features/default/automatic_spans.feature @@ -5,7 +5,7 @@ Feature: Automatic instrumentation spans And I wait for 3 seconds And I wait for 4 spans Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:4" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "[AppStart/iOSCold]" * a span field "name" equals "[AppStartPhase/App launching - pre main()]" @@ -770,7 +770,7 @@ Feature: Automatic instrumentation spans Given I run "ComplexViewScenario" And I wait for 27 spans Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:27" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "[ViewLoadPhase/loadView]/Fixture.ViewController" * a span field "name" equals "[ViewLoadPhase/viewDidLoad]/Fixture.ViewController" @@ -821,7 +821,7 @@ Feature: Automatic instrumentation spans Given I run "ModifyEarlySpansScenario" And I wait for exactly 5 spans Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:5" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "[AppStart/iOSCold]" * a span field "name" equals "[AppStartPhase/App launching - pre main()]" diff --git a/features/default/conditions.feature b/features/default/conditions.feature index d24f8bd8..dc52712e 100644 --- a/features/default/conditions.feature +++ b/features/default/conditions.feature @@ -5,7 +5,7 @@ Feature: Conditions And I wait for 1 span Then the trace "Content-Type" header equals "application/json" * the trace "Bugsnag-Integrity" header matches the regex "^sha1 [A-Fa-f0-9]{40}$" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "ConditionsBasicScenario" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -22,7 +22,7 @@ Feature: Conditions And I wait for 1 span Then the trace "Content-Type" header equals "application/json" * the trace "Bugsnag-Integrity" header matches the regex "^sha1 [A-Fa-f0-9]{40}$" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "ConditionsBlockingBlockedEndedSpanScenario" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -39,7 +39,7 @@ Feature: Conditions And I wait for 1 span Then the trace "Content-Type" header equals "application/json" * the trace "Bugsnag-Integrity" header matches the regex "^sha1 [A-Fa-f0-9]{40}$" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "ConditionsOverrideEndTimeBackwardsScenario" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" diff --git a/features/default/configuration.feature b/features/default/configuration.feature index 3c7c65d7..4759162b 100644 --- a/features/default/configuration.feature +++ b/features/default/configuration.feature @@ -5,7 +5,7 @@ Feature: Configuration overrides And I wait for 1 span Then the trace "Content-Type" header equals "application/json" * the trace "Bugsnag-Integrity" header matches the regex "^sha1 [A-Fa-f0-9]{40}$" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "AppDataOverrideScenario" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" diff --git a/features/default/initial-p-value.feature b/features/default/initial-p-value.feature index 90f1b467..fcda477b 100644 --- a/features/default/initial-p-value.feature +++ b/features/default/initial-p-value.feature @@ -20,7 +20,7 @@ Feature: Initial P values * the sampling request "Bugsnag-Sent-At" header matches the regex "^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d\.\d\d\dZ$" Then I wait for 1 span - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "First" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -31,7 +31,7 @@ Feature: Initial P values Then I discard the oldest trace And I invoke "step2" And I wait for 1 span - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "Second" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" diff --git a/features/default/manual_spans.feature b/features/default/manual_spans.feature index c534759a..887bd126 100644 --- a/features/default/manual_spans.feature +++ b/features/default/manual_spans.feature @@ -6,7 +6,7 @@ Feature: Manual creation of spans Given I set the HTTP status code for the next requests to 200,500,200,200 And I run "RetryScenario" And I wait for 1 span - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "WillRetry" Then I discard the oldest trace @@ -24,7 +24,7 @@ Feature: Manual creation of spans And I wait for 1 span Then the trace "Content-Type" header equals "application/json" * the trace "Bugsnag-Integrity" header matches the regex "^sha1 [A-Fa-f0-9]{40}$" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "ManualSpanScenario" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -53,7 +53,7 @@ Feature: Manual creation of spans Scenario: Starting and ending a span before starting the SDK Given I run "ManualSpanBeforeStartScenario" And I wait for 1 span - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "BeforeStart" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -107,7 +107,7 @@ Feature: Manual creation of spans Scenario: Manually report a UIViewController load span Given I run "ManualUIViewLoadScenario" And I wait for 1 span - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "[ViewLoad/UIKit]/UIViewController" * every span string attribute "bugsnag.view.name" equals "UIViewController" @@ -122,7 +122,7 @@ Feature: Manual creation of spans Given I run "ManualNetworkSpanScenario" And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * the trace payload field "resourceSpans.0.resource" string attribute "service.name" matches the regex "com.bugsnag.fixtures.cocoaperformance(xcframework)?" * the trace payload field "resourceSpans.0.resource" string attribute "telemetry.sdk.name" equals "bugsnag.performance.cocoa" @@ -274,7 +274,7 @@ Feature: Manual creation of spans And I wait for exactly 1 span Then the trace "Content-Type" header equals "application/json" * the trace "Bugsnag-Integrity" header matches the regex "^sha1 [A-Fa-f0-9]{40}$" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * the trace "Bugsnag-Uncompressed-Content-Length" header matches the regex "^[0-9]+$" * every span field "name" equals "MaxPayloadSizeScenario" @@ -303,7 +303,7 @@ Feature: Manual creation of spans Scenario: Set attributes in a span Given I run "SetAttributesScenario" And I wait for 1 span - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "SetAttributesScenario" * a span string attribute "a" equals "xyz" @@ -320,7 +320,7 @@ Feature: Manual creation of spans Scenario: Set attributes in a span with limits set Given I run "SetAttributesWithLimitsScenario" And I wait for 1 span - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "SetAttributesWithLimitsScenario" * a span string attribute "a" equals "1234567890*** 1 CHARS TRUNCATED" @@ -332,7 +332,7 @@ Feature: Manual creation of spans Scenario: Set attributes in a span with an attribute count limit set Given I run "SetAttributeCountLimitScenario" And I wait for 1 span - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "SetAttributeCountLimitScenario" * every span string attribute "a" does not exist @@ -340,7 +340,7 @@ Feature: Manual creation of spans Scenario: Set OnStart Given I run "OnStartCallbackScenario" And I wait for exactly 1 span - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "OnStartCallbackScenario" * a span bool attribute "start_callback_1" is true @@ -349,7 +349,7 @@ Feature: Manual creation of spans Scenario: Set OnEnd Given I run "OnEndCallbackScenario" And I wait for exactly 1 span - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "OnEndCallbackScenario" @@ -357,7 +357,7 @@ Feature: Manual creation of spans Given I run "FrameMetricsNoSlowFramesScenario" And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "FrameMetricsNoSlowFramesScenario" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -374,7 +374,7 @@ Feature: Manual creation of spans Given I run "FrameMetricsSlowFramesScenario" And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "FrameMetricsSlowFramesScenario" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -391,7 +391,7 @@ Feature: Manual creation of spans Given I run "FrameMetricsFronzenFramesScenario" And I wait for 3 spans Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:3" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "FrameMetricsFronzenFramesScenario" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -409,7 +409,7 @@ Feature: Manual creation of spans Given I run "FrameMetricsAutoInstrumentRenderingOffScenario" And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "FrameMetricsAutoInstrumentRenderingOffScenario" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -426,7 +426,7 @@ Feature: Manual creation of spans Given I run "FrameMetricsSpanInstrumentRenderingOffScenario" And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "FrameMetricsSpanInstrumentRenderingOffScenario" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -443,7 +443,7 @@ Feature: Manual creation of spans Given I run "FrameMetricsNonFirstClassSpanInstrumentRenderingOnScenario" And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "FrameMetricsNonFirstClassSpanInstrumentRenderingOnScenario" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -460,7 +460,7 @@ Feature: Manual creation of spans Given I run "SpanConditionsSimpleConditionScenario" And I wait for 2 spans Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:2" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "SpanConditionsSimpleConditionScenarioSpan1" * a span field "name" equals "SpanConditionsSimpleConditionScenarioSpan2" @@ -476,7 +476,7 @@ Feature: Manual creation of spans Given I run "SpanConditionsConditionTimedOutScenario" And I wait for 2 spans Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:2" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "SpanConditionsConditionTimedOutScenarioSpan1" * a span field "name" equals "SpanConditionsConditionTimedOutScenarioSpan2" @@ -491,7 +491,7 @@ Feature: Manual creation of spans Given I run "SpanConditionsMultipleConditionsScenario" And I wait for 3 spans Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:3" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "SpanConditionsMultipleConditionsScenarioSpan1" * a span field "name" equals "SpanConditionsMultipleConditionsScenarioSpan2" @@ -508,7 +508,7 @@ Feature: Manual creation of spans Given I run "SpanConditionsBlockedSpanScenario" And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:2" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "SpanConditionsBlockedSpanScenarioSpan1" * a span field "name" equals "SpanConditionsBlockedSpanScenarioSpan2" @@ -524,7 +524,7 @@ Feature: Manual creation of spans And I wait for 1 span Then the trace "Content-Type" header equals "application/json" * the trace "Bugsnag-Integrity" header matches the regex "^sha1 [A-Fa-f0-9]{40}$" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "ManualSpanWithRemoteContextParentScenario" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" diff --git a/features/default/metrics.feature b/features/default/metrics.feature index c4e6a0e7..82c1d235 100644 --- a/features/default/metrics.feature +++ b/features/default/metrics.feature @@ -9,7 +9,7 @@ Feature: Spans with collected metrics And I run the loaded scenario And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "RenderingMetricsScenarioNoSlow" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -32,7 +32,7 @@ Feature: Spans with collected metrics And I run the loaded scenario And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "RenderingMetricsScenarioEarlyStart" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -49,7 +49,7 @@ Feature: Spans with collected metrics Given I run "FrameMetricsSlowFramesScenario" And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "FrameMetricsSlowFramesScenario" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -66,7 +66,7 @@ Feature: Spans with collected metrics Given I run "FrameMetricsFronzenFramesScenario" And I wait for 3 spans Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:3" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "FrameMetricsFronzenFramesScenario" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -84,7 +84,7 @@ Feature: Spans with collected metrics Given I run "FrameMetricsAutoInstrumentRenderingOffScenario" And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "FrameMetricsAutoInstrumentRenderingOffScenario" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -101,7 +101,7 @@ Feature: Spans with collected metrics Given I run "FrameMetricsSpanInstrumentRenderingOffScenario" And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "FrameMetricsSpanInstrumentRenderingOffScenario" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -118,7 +118,7 @@ Feature: Spans with collected metrics Given I run "FrameMetricsNonFirstClassSpanInstrumentRenderingOnScenario" And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "FrameMetricsNonFirstClassSpanInstrumentRenderingOnScenario" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -141,7 +141,7 @@ Feature: Spans with collected metrics And I run the loaded scenario And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "CPUMetricsScenarioDefaultSettingsCPUMetricsDisabled" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -172,7 +172,7 @@ Feature: Spans with collected metrics And I run the loaded scenario And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "CPUMetricsScenarioNoMetrics" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -203,7 +203,7 @@ Feature: Spans with collected metrics And I run the loaded scenario And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "CPUMetricsScenarioFirstClass" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -234,7 +234,7 @@ Feature: Spans with collected metrics And I run the loaded scenario And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "CPUMetricsScenarioNonFirstClass" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -266,7 +266,7 @@ Feature: Spans with collected metrics And I run the loaded scenario And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "CPUMetricsScenarioNonFirstClassWithMetrics" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -297,7 +297,7 @@ Feature: Spans with collected metrics And I run the loaded scenario And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "CPUMetricsScenarioLongerSpanDuration" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -328,7 +328,7 @@ Feature: Spans with collected metrics And I run the loaded scenario And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "CPUMetricsScenarioGenerateSpanLater" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -363,7 +363,7 @@ Feature: Spans with collected metrics And I run the loaded scenario And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "CPUMetricsScenarioMainThreadHeavyWork" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -396,7 +396,7 @@ Feature: Spans with collected metrics And I run the loaded scenario And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "CPUMetricsScenarioBgThreadHeavyWork" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -427,7 +427,7 @@ Feature: Spans with collected metrics And I run the loaded scenario And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "MemoryMetricsScenarioDefaultSettings" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -455,7 +455,7 @@ Feature: Spans with collected metrics And I run the loaded scenario And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "MemoryMetricsScenarioFirstClass" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -483,7 +483,7 @@ Feature: Spans with collected metrics And I run the loaded scenario And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "MemoryMetricsScenarioNonFirstClass" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -512,7 +512,7 @@ Feature: Spans with collected metrics And I run the loaded scenario And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "MemoryMetricsScenarioNonFirstClassEnabled" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -540,7 +540,7 @@ Feature: Spans with collected metrics And I run the loaded scenario And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "MemoryMetricsScenarioLongerDuration" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" @@ -568,7 +568,7 @@ Feature: Spans with collected metrics And I run the loaded scenario And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "MemoryMetricsScenarioGenerateLater" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" diff --git a/features/default/sampling.feature b/features/default/sampling.feature index 8d44c370..6e7a4b2f 100644 --- a/features/default/sampling.feature +++ b/features/default/sampling.feature @@ -9,7 +9,7 @@ Feature: Sampling Given I set the sampling probability to "1.0" And I run "SamplingProbabilityZeroScenario" And I wait for 2 spans - * the trace "Bugsnag-Span-Sampling" header equals "1:2" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * a span field "name" equals "Pre-start" * a span field "name" equals "Post-start" diff --git a/features/default/triggers.feature b/features/default/triggers.feature index 72ed3d0b..6794cac2 100644 --- a/features/default/triggers.feature +++ b/features/default/triggers.feature @@ -5,7 +5,7 @@ Scenario: BackgroundForegroundScenario And I switch to the web browser for 2 seconds And I wait for 1 span Then the trace "Content-Type" header equals "application/json" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$" * every span field "name" equals "BackgroundForegroundScenario" * every span field "spanId" matches the regex "^[A-Fa-f0-9]{16}$" diff --git a/features/fixtures/ios/Scenarios/SamplingProbabilityZeroScenario.swift b/features/fixtures/ios/Scenarios/SamplingProbabilityZeroScenario.swift index 8d18e14f..7c16590e 100644 --- a/features/fixtures/ios/Scenarios/SamplingProbabilityZeroScenario.swift +++ b/features/fixtures/ios/Scenarios/SamplingProbabilityZeroScenario.swift @@ -13,7 +13,6 @@ class SamplingProbabilityZeroScenario: Scenario { override func setInitialBugsnagConfiguration() { super.setInitialBugsnagConfiguration() bugsnagPerfConfig.internal.initialSamplingProbability = 0 - bugsnagPerfConfig.internal.autoTriggerExportOnBatchSize = 2 } override func postLoad() { From aedc0469bdd557cd5cde5b2d8660c58acc674c8c Mon Sep 17 00:00:00 2001 From: Robert Bartoszewski Date: Sun, 26 Oct 2025 17:17:37 +0100 Subject: [PATCH 14/14] Fixed a flaky E2E test --- features/default/manual_spans.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/default/manual_spans.feature b/features/default/manual_spans.feature index 887bd126..64a37bc9 100644 --- a/features/default/manual_spans.feature +++ b/features/default/manual_spans.feature @@ -506,7 +506,7 @@ Feature: Manual creation of spans Scenario: Span Conditions - blocking blocked ended span Given I run "SpanConditionsBlockedSpanScenario" - And I wait for 1 span + And I wait for 2 spans Then the trace "Content-Type" header equals "application/json" * the trace "Bugsnag-Span-Sampling" header matches the regex "^1:\d{1,2}$" * 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$"