Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v1.1.3 #219

Merged
merged 17 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
ed9b0df
feat: add privacy manifest
Nov 3, 2023
026a9d2
Merge pull request #212 from bugsnag/tom/privacy-manifest
tomlongridge Nov 13, 2023
19e6ad9
Automatically fetch mazerunner commands rather than waiting for a but…
kstenerud Nov 17, 2023
3a5d78b
Make sure administration network requests aren't captured by e2e tests
kstenerud Nov 17, 2023
17498ce
Fetch mazerunner address in the background to avoid OS shutdown for h…
kstenerud Nov 20, 2023
5401d66
Refactor e2e test URL handling code
kstenerud Nov 20, 2023
6ab90ef
Disable BackgroundForegroundScenario for now
kstenerud Nov 20, 2023
308b144
reflect URL doesn't require a different port anymore
kstenerud Nov 21, 2023
78a81a1
Merge pull request #215 from bugsnag/karl-automatic-mazerunner-fetch
kstenerud Nov 21, 2023
7346dde
Ensure span cancellation is done properly with concurrency protection
kstenerud Nov 21, 2023
cdca9ca
Merge pull request #217 from bugsnag/karl-span-cancellation-fix
kstenerud Nov 22, 2023
8161294
Discard view load spans started during pre-warm phases because we can…
kstenerud Nov 22, 2023
474002b
Merge pull request #211 from bugsnag/PLAT-10875-prewarm-view-span-2
kstenerud Nov 22, 2023
8677671
Fix faulty tests: Should be comparing objects, not pointers.
kstenerud Nov 23, 2023
063ea1f
Swizzle NSURLSession classes on a BG thread so that getting the class…
kstenerud Nov 23, 2023
f5b4e3d
Merge pull request #218 from bugsnag/karl-network-swizzle-timing
kstenerud Nov 23, 2023
3cef133
Release v1.1.3
kstenerud Nov 23, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,4 @@ logs/*

# Other
.DS_Store
features/fixtures/ios/Fixture/Info.plist
4 changes: 2 additions & 2 deletions .jazzy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ author_url: "https://www.bugsnag.com"
author: "Bugsnag Inc"
clean: false # avoid deleting docs/.git
framework_root: "BugsnagPerformance"
github_file_prefix: "https://github.com/bugsnag/bugsnag-cocoa-performance/tree/v1.1.2/Bugsnag"
github_file_prefix: "https://github.com/bugsnag/bugsnag-cocoa-performance/tree/v1.1.3/Bugsnag"
github_url: "https://github.com/bugsnag/bugsnag-cocoa-performance"
hide_documentation_coverage: true
module: "BugsnagPerformance"
module_version: "1.1.2"
module_version: "1.1.3"
objc: true
output: "docs"
readme: "README.md"
Expand Down
7 changes: 5 additions & 2 deletions BugsnagPerformance.podspec.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "BugsnagPerformance",
"version": "1.1.2",
"version": "1.1.3",
"summary": "The Bugsnag performance monitoring framework for iOS.",
"homepage": "https://github.com/bugsnag/bugsnag-cocoa-performance",
"license": {
Expand All @@ -12,13 +12,16 @@
},
"source": {
"git": "https://github.com/bugsnag/bugsnag-cocoa-performance.git",
"tag": "v1.1.2"
"tag": "v1.1.3"
},
"platforms": {
"ios": "11.0"
},
"requires_arc": true,
"source_files": "Sources/BugsnagPerformance/**/*",
"resources": [
"Sources/BugsnagPerformance/resources/PrivacyInfo.xcprivacy"
],
"public_header_files": "Sources/BugsnagPerformance/include/BugsnagPerformance/*.h",
"prefix_header_file": false,
"frameworks": [
Expand Down
8 changes: 7 additions & 1 deletion BugsnagPerformance.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
01EAF980291AAF19007AC627 /* Utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 01EAF97F291AAF19007AC627 /* Utils.h */; };
0921F02B2A67CBD600C764EB /* BugsnagPerformanceNetworkRequestInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0921F0292A67CBD600C764EB /* BugsnagPerformanceNetworkRequestInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
0921F02C2A67CBD600C764EB /* BugsnagPerformanceNetworkRequestInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0921F02A2A67CBD600C764EB /* BugsnagPerformanceNetworkRequestInfo.m */; };
09509B752ADFE9A900A358EC /* TracerTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 09509B742ADFE9A900A358EC /* TracerTests.mm */; };
8A80DA8B2966CE940035BDA9 /* BugsnagPerformance.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72E4BB63359EA30E80116E2A /* BugsnagPerformance.framework */; };
8A80DA912966CEB30035BDA9 /* ConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A80DA80296588840035BDA9 /* ConfigurationTests.swift */; };
962F80F229DB03A400BE82BC /* PerformanceMicrobenchmarkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 962F80F129DB03A400BE82BC /* PerformanceMicrobenchmarkTests.swift */; };
Expand Down Expand Up @@ -227,6 +228,7 @@
01EF4A3E29067786003CC5A5 /* BugsnagPerformance.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = BugsnagPerformance.xcconfig; sourceTree = "<group>"; };
0921F0292A67CBD600C764EB /* BugsnagPerformanceNetworkRequestInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BugsnagPerformanceNetworkRequestInfo.h; sourceTree = "<group>"; };
0921F02A2A67CBD600C764EB /* BugsnagPerformanceNetworkRequestInfo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BugsnagPerformanceNetworkRequestInfo.m; sourceTree = "<group>"; };
09509B742ADFE9A900A358EC /* TracerTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = TracerTests.mm; sourceTree = "<group>"; };
72E4BB63359EA30E80116E2A /* BugsnagPerformance.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BugsnagPerformance.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8A80DA80296588840035BDA9 /* ConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationTests.swift; sourceTree = "<group>"; };
8A80DA872966CE940035BDA9 /* BugsnagPerformance-SwiftTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "BugsnagPerformance-SwiftTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -315,6 +317,7 @@
CBF7C5DF297A8E9100D47719 /* Gzip.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Gzip.h; sourceTree = "<group>"; };
CBF7C5E0297A8E9100D47719 /* Gzip.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Gzip.m; sourceTree = "<group>"; };
CBF7C5E3297A963A00D47719 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
EDE8339F2AF550E20042A78F /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = Sources/BugsnagPerformance/resources/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -530,8 +533,8 @@
CBEC51C2296EC0AC009C0CE3 /* JSONTests.mm */,
CBEC51DE29782471009C0CE3 /* OtlpPackageTests.mm */,
0122C26029019C05002D243C /* OtlpTraceEncodingTests.mm */,
CB68FABB2A3C4208005B2CDB /* PersistentDeviceIDTest.mm */,
CBEC51CD296EEF52009C0CE3 /* PersistenceTests.mm */,
CB68FABB2A3C4208005B2CDB /* PersistentDeviceIDTest.mm */,
CBEC51C4296ED8BA009C0CE3 /* PersistentStateTests.mm */,
01A414C42912B93F003152A4 /* ResourceAttributesTests.mm */,
CBEC51E029793B1E009C0CE3 /* RetryQueueTests.mm */,
Expand All @@ -540,6 +543,7 @@
96D55C872A1EE26A006D1F29 /* SpanStackingHandlerTests.mm */,
CB2B8A9A2A0924A50054FBBE /* SpanTests.mm */,
CB747D20299E5458003CA1B4 /* TimeTests.mm */,
09509B742ADFE9A900A358EC /* TracerTests.mm */,
CB0AD75A295F27DD002A3FB6 /* WorkerTests.mm */,
);
path = BugsnagPerformanceTests;
Expand Down Expand Up @@ -583,6 +587,7 @@
isa = PBXGroup;
children = (
01EF4A3E29067786003CC5A5 /* BugsnagPerformance.xcconfig */,
EDE8339F2AF550E20042A78F /* PrivacyInfo.xcprivacy */,
0122C21329019770002D243C /* Sources */,
0122C25B29019C05002D243C /* Tests */,
96D415F129E6ADC500AEE435 /* BugsnagPerformanceTestsApp */,
Expand Down Expand Up @@ -849,6 +854,7 @@
CB68FABC2A3C4208005B2CDB /* PersistentDeviceIDTest.mm in Sources */,
CB747D21299E5458003CA1B4 /* TimeTests.mm in Sources */,
0122C27129019CEF002D243C /* OtlpTraceEncodingTests.mm in Sources */,
09509B752ADFE9A900A358EC /* TracerTests.mm in Sources */,
962F80F229DB03A400BE82BC /* PerformanceMicrobenchmarkTests.swift in Sources */,
CB747D1F299E4984003CA1B4 /* SpanOptionsTests.mm in Sources */,
CB0AD76C296578D9002A3FB6 /* BugsnagPerformanceConfigurationTests.mm in Sources */,
Expand Down
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
Changelog
=========

## 1.1.3 (2023-11-23)

### Enhancements

* Added [privacy manifest](https://developer.apple.com/documentation/bundleresources/privacy_manifest_files) to declare data use and required reasons for API usage
[212](https://github.com/bugsnag/bugsnag-cocoa-performance/pull/212)

* Detect app prewarming and discard any view load spans that would be distorted by it.
[211](https://github.com/bugsnag/bugsnag-cocoa-performance/pull/211)

### Bug fixes

* Fetching of network swizzle targets is now done on a BG queue in order to avoid a potential deadlock
[218](https://github.com/bugsnag/bugsnag-cocoa-performance/pull/218)

* Ensure span cancellation is done with concurrency protection
[217](https://github.com/bugsnag/bugsnag-cocoa-performance/pull/217)

## 1.1.2 (2023-10-19)

### Bug fixes
Expand Down
6 changes: 5 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.0
// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription
Expand All @@ -16,6 +16,10 @@ let package = Package(
targets: [
.target(
name: "BugsnagPerformance",
path: "Sources/BugsnagPerformance",
resources: [
.copy("resources/PrivacyInfo.xcprivacy")
],
linkerSettings: [
.linkedFramework("SystemConfiguration"),
.linkedFramework("UIKit"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,6 @@
return NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
}

void (^generateOnSpanStarted(BugsnagPerformanceImpl *impl))(void) {
__block auto blockImpl = impl;
return ^{
blockImpl->onSpanStarted();
};
}

BugsnagPerformanceImpl::BugsnagPerformanceImpl(std::shared_ptr<Reachability> reachability,
AppStateTracker *appStateTracker) noexcept
: persistence_(std::make_shared<Persistence>(getPersistenceDir()))
Expand All @@ -36,7 +29,7 @@
, reachability_(reachability)
, batch_(std::make_shared<Batch>())
, sampler_(std::make_shared<Sampler>())
, tracer_(std::make_shared<Tracer>(spanStackingHandler_, sampler_, batch_, generateOnSpanStarted(this)))
, tracer_(std::make_shared<Tracer>(spanStackingHandler_, sampler_, batch_, ^{this->onSpanStarted();}))
, retryQueue_(std::make_unique<RetryQueue>([persistence_->bugsnagPerformanceDir() stringByAppendingPathComponent:@"retry-queue"]))
, appStateTracker_(appStateTracker)
, viewControllersToSpans_([NSMapTable mapTableWithKeyOptions:NSMapTableWeakMemory | NSMapTableObjectPointerPersonality
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,17 @@
: appStateTracker_([[AppStateTracker alloc] init])
, reachability_(std::make_shared<Reachability>())
, bugsnagPerformanceImpl_(std::make_shared<BugsnagPerformanceImpl>(reachability_, appStateTracker_))
{
auto impl = bugsnagPerformanceImpl_;
bugsnagPerformanceImpl_->setOnViewLoadSpanStarted([=](NSString *className) {
impl->didStartViewLoadSpan(className);
});
}
{}

void BugsnagPerformanceLibrary::earlyConfigure(BSGEarlyConfiguration *config) noexcept {
bugsnagPerformanceImpl_->earlyConfigure(config);
}

void BugsnagPerformanceLibrary::earlySetup() noexcept {
auto impl = bugsnagPerformanceImpl_;
bugsnagPerformanceImpl_->setOnViewLoadSpanStarted([=](NSString *className) {
impl->didStartViewLoadSpan(className);
});
bugsnagPerformanceImpl_->earlySetup();
}

Expand Down
3 changes: 2 additions & 1 deletion Sources/BugsnagPerformance/Private/EarlyConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
* The early confguration happens duing the library early init phase (before main is called), and thus cannot be done
* using a configuration object passed in by the user (because control hasn't been passed to user code yet).
* Instead, we get the early configuration from the app's Info.plist file.
* Instead, we get the early configuration from the app's Info.plist file and environment variables.
*/
@interface BSGEarlyConfiguration : NSObject

Expand All @@ -30,6 +30,7 @@ NS_ASSUME_NONNULL_BEGIN

@property(nonatomic, readonly) BOOL enableSwizzling;
@property(nonatomic, readonly) BOOL swizzleViewLoadPreMain;
@property(nonatomic, readwrite) BOOL appWasLaunchedPreWarmed;

@end

Expand Down
1 change: 1 addition & 0 deletions Sources/BugsnagPerformance/Private/EarlyConfiguration.mm
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ - (instancetype) initWithBundleDictionary:(NSDictionary *)dict {
}
id swizzleViewLoadPreMain = [dict valueForKeyPath:@"bugsnag.performance.swizzleViewLoadPreMain"];
_swizzleViewLoadPreMain = swizzleViewLoadPreMain == nil || [swizzleViewLoadPreMain boolValue];
_appWasLaunchedPreWarmed = [NSProcessInfo.processInfo.environment[@"ActivePrewarm"] isEqualToString:@"1"];
}

return self;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class AppStartupInstrumentation: public PhasedStartup {
std::shared_ptr<SpanAttributesProvider> spanAttributesProvider) noexcept;

void earlyConfigure(BSGEarlyConfiguration *) noexcept {}
void earlySetup() noexcept {}
void earlySetup() noexcept;
void configure(BugsnagPerformanceConfiguration *config) noexcept;
void start() noexcept {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,10 @@ static inline bool isActivePrewarm(void) {
, tracer_(tracer)
, spanAttributesProvider_(spanAttributesProvider)
, didStartProcessAtTime_(getProcessStartTime())
, didCallMainFunctionAtTime_(CFAbsoluteTimeGetCurrent())
, isColdLaunch_(isColdLaunch())
{
{}

void AppStartupInstrumentation::earlySetup() noexcept {
if (!canInstallInstrumentation()) {
disable();
}
Expand All @@ -86,6 +87,7 @@ static inline bool isActivePrewarm(void) {

beginAppStartSpan();
beginPreMainSpan();
didCallMainFunctionAtTime_ = CFAbsoluteTimeGetCurrent();
[preMainSpan_ endWithAbsoluteTime:didCallMainFunctionAtTime_];
beginPostMainSpan();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ static void replace_NSURLSessionTask_resume(Class cls, BSGSessionTaskResumeCallb
}

void bsg_installNSURLSessionTaskPerformance(void (^onResume)(NSURLSessionTask *)) noexcept {
for (Class cls in getURLSessionTaskClassesWithResumeMethod()) {
replace_NSURLSessionTask_resume(cls, onResume);
}
// We must do this in a separate thread to avoid a potential mutex deadlock with
// Apple's com.apple.network.connections queue during early app startup.
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(void){
for (Class cls in getURLSessionTaskClassesWithResumeMethod()) {
replace_NSURLSessionTask_resume(cls, onResume);
}
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,10 @@ @implementation ViewLoadInstrumentationState
}

isEnabled_ &= config.autoInstrumentViewControllers;
callback_ = config.viewControllerInstrumentationCallback;
auto callback = config.viewControllerInstrumentationCallback;
if (callback != nullptr) {
callback_ = callback;
}

endEarlySpanPhase();
}
Expand Down
4 changes: 4 additions & 0 deletions Sources/BugsnagPerformance/Private/Span.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ class Span {
return isEnded_;
}

void abort() noexcept {
isEnded_ = true;
}

void end(CFAbsoluteTime time) noexcept {
bool expected = false;
if (!isEnded_.compare_exchange_strong(expected, true)) {
Expand Down
30 changes: 21 additions & 9 deletions Sources/BugsnagPerformance/Private/Tracer.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class Tracer: public PhasedStartup {
void (^onSpanStarted)()) noexcept;
~Tracer() {};

void earlyConfigure(BSGEarlyConfiguration *) noexcept {}
void earlyConfigure(BSGEarlyConfiguration *) noexcept;
void earlySetup() noexcept {}
void configure(BugsnagPerformanceConfiguration *configuration) noexcept;
void start() noexcept;
Expand All @@ -51,27 +51,39 @@ class Tracer: public PhasedStartup {
SpanOptions options) noexcept;

BugsnagPerformanceSpan *startNetworkSpan(NSURL *url, NSString *httpMethod, SpanOptions options) noexcept;

BugsnagPerformanceSpan *startViewLoadPhaseSpan(NSString *name, SpanOptions options) noexcept;

void cancelQueuedSpan(BugsnagPerformanceSpan *span) noexcept;

void onPrewarmPhaseEnded(void) noexcept;

private:
Tracer() = delete;
std::shared_ptr<Sampler> sampler_;
std::shared_ptr<SpanStackingHandler> spanStackingHandler_;

std::atomic<bool> isEarlySpansPhase_{true};
std::mutex earlySpansMutex_;
std::atomic<bool> isCapturingEarlyNetworkSpans_{true};
std::mutex earlyNetworkSpansMutex_;
NSMutableArray<BugsnagPerformanceSpan *> *earlyNetworkSpans_;

std::atomic<bool> willDiscardPrewarmSpans_{false};
std::mutex prewarmSpansMutex_;
NSMutableArray<BugsnagPerformanceSpan *> *prewarmSpans_;

std::shared_ptr<Batch> batch_;
void (^onSpanStarted_)(){nil};
std::function<void(NSString *)> onViewLoadSpanStarted_{};
BugsnagPerformanceNetworkRequestCallback networkRequestCallback_;
void (^onSpanStarted_)(){ ^(){} };
std::function<void(NSString *)> onViewLoadSpanStarted_{ [](NSString *){} };
BugsnagPerformanceNetworkRequestCallback networkRequestCallback_ {
^BugsnagPerformanceNetworkRequestInfo * _Nonnull(BugsnagPerformanceNetworkRequestInfo * _Nonnull info) {
return info;
}
};

BugsnagPerformanceSpan *startSpan(NSString *name, SpanOptions options, BSGFirstClass defaultFirstClass) noexcept;
void tryAddSpanToBatch(std::shared_ptr<SpanData> spanData);
void trySampleAndAddSpanToBatch(std::shared_ptr<SpanData> spanData);
void markEarlyNetworkSpan(BugsnagPerformanceSpan *span) noexcept;
void endEarlySpansPhase() noexcept;
void markPrewarmSpan(BugsnagPerformanceSpan *span) noexcept;
void endEarlyNetworkSpansPhase() noexcept;
};
}
Loading
Loading