Skip to content

Commit

Permalink
feat: MetricKit TestVersion 1 (#2476)
Browse files Browse the repository at this point in the history
This PR adds a first iteration of sending MetricKitData of MXCrashDiagnostic, MXCPUExceptionDiagnostic, and MXDiskWriteExceptionDiagnostic to Sentry. This PRs aim is to have the code running in the iOS-Swift test app via TestFlight to get some real MetricKit data of MXCPUExceptionDiagnostic, and MXDiskWriteExceptionDiagnostic.

MXCrashDiagnostic exists solely for validating the stacktrace symbolication.
  • Loading branch information
philipphofmann authored Dec 6, 2022
1 parent 98fb18f commit 5ed4bee
Show file tree
Hide file tree
Showing 28 changed files with 1,817 additions and 22 deletions.
6 changes: 6 additions & 0 deletions Samples/iOS-Swift/iOS-Swift.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
637AFDB3243B02770034958B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 637AFDB2243B02770034958B /* Assets.xcassets */; };
637AFDB6243B02770034958B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 637AFDB4243B02770034958B /* LaunchScreen.storyboard */; };
7B3427F825876A5200056519 /* Tongariro.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 7B3427F725876A5200056519 /* Tongariro.jpg */; };
7B5525B32938B5B5006A2932 /* DiskWriteException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5525B22938B5B5006A2932 /* DiskWriteException.swift */; };
7B5525B62938B644006A2932 /* DiskWriteException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5525B22938B5B5006A2932 /* DiskWriteException.swift */; };
7B64386B26A6C544000D0F65 /* LaunchUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B64386A26A6C544000D0F65 /* LaunchUITests.swift */; };
7B79000429028C7300A7F467 /* MetricKitManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B79000329028C7300A7F467 /* MetricKitManager.swift */; };
7BFC8B0626D4D24B000D3504 /* LoremIpsum.txt in Resources */ = {isa = PBXBuildFile; fileRef = 7BFC8B0526D4D24B000D3504 /* LoremIpsum.txt */; };
Expand Down Expand Up @@ -245,6 +247,7 @@
7B3427F725876A5200056519 /* Tongariro.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = Tongariro.jpg; sourceTree = "<group>"; };
7B4F33F7271EBD2500C8591E /* SwiftUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUI.swift; sourceTree = "<group>"; };
7B4F33FA271EBE0C00C8591E /* SwiftUIViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIViewController.swift; sourceTree = "<group>"; };
7B5525B22938B5B5006A2932 /* DiskWriteException.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiskWriteException.swift; sourceTree = "<group>"; };
7B64386826A6C544000D0F65 /* iOS-SwiftUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "iOS-SwiftUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
7B64386A26A6C544000D0F65 /* LaunchUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchUITests.swift; sourceTree = "<group>"; };
7B64386C26A6C544000D0F65 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
Expand Down Expand Up @@ -511,6 +514,7 @@
D8D7BB492750067900044146 /* UIAssert.swift */,
D8D7BB4D27501B9400044146 /* SpanObserver.swift */,
84FB812C2840021B00F3A94A /* iOS-Swift-Bridging-Header.h */,
7B5525B22938B5B5006A2932 /* DiskWriteException.swift */,
);
path = Tools;
sourceTree = "<group>";
Expand Down Expand Up @@ -809,6 +813,7 @@
D8444E4C275E38090042F4DE /* UIViewControllerExtension.swift in Sources */,
637AFDAE243B02760034958B /* ViewController.swift in Sources */,
0AABE2EA28855FF80057ED69 /* PermissionsViewController.swift in Sources */,
7B5525B32938B5B5006A2932 /* DiskWriteException.swift in Sources */,
84FB8120283EEDB900F3A94A /* PerformanceViewController.swift in Sources */,
D8F3D062274EBD4800B56F8C /* SpanExtension.swift in Sources */,
637AFDAA243B02760034958B /* AppDelegate.swift in Sources */,
Expand Down Expand Up @@ -858,6 +863,7 @@
D8269A4F274C09A400BD5BD5 /* SwiftUI.swift in Sources */,
D8444E57275F795D0042F4DE /* UIViewControllerExtension.swift in Sources */,
D8F3D058274E57D600B56F8C /* TableViewController.swift in Sources */,
7B5525B62938B644006A2932 /* DiskWriteException.swift in Sources */,
D8269A58274C0FC700BD5BD5 /* ViewController.swift in Sources */,
844DA821282584C300E6B62E /* CoreDataViewController.swift in Sources */,
D8444E55275F79570042F4DE /* SpanExtension.swift in Sources */,
Expand Down
3 changes: 3 additions & 0 deletions Samples/iOS-Swift/iOS-Swift/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
return event
}
options.debug = true
if #available(iOS 14.0, *) {
options.enableMetricKit = true
}
// Sampling 100% - In Production you probably want to adjust this
options.tracesSampleRate = 1.0
options.sessionTrackingIntervalMillis = 5_000
Expand Down
32 changes: 23 additions & 9 deletions Samples/iOS-Swift/iOS-Swift/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleAspectFit" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="480-5y-FtF">
<rect key="frame" x="8" y="199.5" width="398" height="555.5"/>
<rect key="frame" x="8" y="169.5" width="398" height="615.5"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillProportionally" alignment="top" translatesAutoresizingMaskIntoConstraints="NO" id="VbH-LD-DBn">
<rect key="frame" x="0.0" y="0.0" width="398" height="390"/>
<rect key="frame" x="0.0" y="0.0" width="398" height="450"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" translatesAutoresizingMaskIntoConstraints="NO" id="hHG-as-TfH">
<rect key="frame" x="0.0" y="0.0" width="181.5" height="390"/>
<rect key="frame" x="0.0" y="0.0" width="181.5" height="450"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="QJW-l9-sD6">
<rect key="frame" x="0.0" y="0.0" width="181.5" height="30"/>
Expand Down Expand Up @@ -91,29 +91,43 @@
<action selector="oomCrash:" destination="BYZ-38-t0r" eventType="touchUpInside" id="Oju-om-O6e"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xur-X2-ih4">
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="2dB-TW-SJY" userLabel="DiskWriteException">
<rect key="frame" x="0.0" y="270" width="181.5" height="30"/>
<state key="normal" title="DiskWriteException"/>
<connections>
<action selector="diskWriteException:" destination="BYZ-38-t0r" eventType="touchUpInside" id="BG9-QM-rT0"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Nlv-4f-prb" userLabel="HighCpuLoad">
<rect key="frame" x="0.0" y="300" width="181.5" height="30"/>
<state key="normal" title="HighCpuLoad"/>
<connections>
<action selector="highCPULoad:" destination="BYZ-38-t0r" eventType="touchUpInside" id="hfR-s0-SRc"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xur-X2-ih4">
<rect key="frame" x="0.0" y="330" width="181.5" height="30"/>
<state key="normal" title="async crash"/>
<connections>
<action selector="asyncCrash:" destination="BYZ-38-t0r" eventType="touchUpInside" id="Mqi-sE-R7d"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="zmN-BT-tg3">
<rect key="frame" x="0.0" y="300" width="181.5" height="30"/>
<rect key="frame" x="0.0" y="360" width="181.5" height="30"/>
<state key="normal" title="permissions"/>
<connections>
<action selector="permissions:" destination="BYZ-38-t0r" eventType="touchUpInside" id="65U-z2-FjW"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="689-IN-jTP">
<rect key="frame" x="0.0" y="330" width="181.5" height="30"/>
<rect key="frame" x="0.0" y="390" width="181.5" height="30"/>
<state key="normal" title="Close"/>
<connections>
<action selector="close:" destination="BYZ-38-t0r" eventType="touchUpInside" id="P48-2Y-SKT"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="QIi-IM-YSk">
<rect key="frame" x="0.0" y="360" width="181.5" height="30"/>
<rect key="frame" x="0.0" y="420" width="181.5" height="30"/>
<state key="normal" title="Start SDK"/>
<connections>
<action selector="startSDK:" destination="BYZ-38-t0r" eventType="touchUpInside" id="UoF-Pv-fKg"/>
Expand Down Expand Up @@ -222,7 +236,7 @@
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="UrL-kT-AJU">
<rect key="frame" x="0.0" y="390" width="398" height="165.5"/>
<rect key="frame" x="0.0" y="450" width="398" height="165.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="DSN " textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="m3h-wb-Xfa">
<rect key="frame" x="8" y="32" width="382" height="20.5"/>
Expand Down Expand Up @@ -417,7 +431,7 @@
</items>
</navigationBar>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" fixedFrame="YES" preservesSuperviewLayoutMargins="YES" layoutMarginsFollowReadableWidth="YES" delaysContentTouches="NO" editable="NO" adjustsFontForContentSizeCategory="YES" translatesAutoresizingMaskIntoConstraints="NO" id="sla-j3-cfX">
<rect key="frame" x="19" y="69" width="373" height="825"/>
<rect key="frame" x="18" y="70" width="374" height="824"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<color key="textColor" systemColor="labelColor"/>
Expand Down
75 changes: 75 additions & 0 deletions Samples/iOS-Swift/iOS-Swift/Tools/DiskWriteException.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import Foundation
import Sentry

/**
* The system throws an exception and generates a report when the disk writes from your app exceed a certain threshold in a 24-hour period.
* See https://developer.apple.com/documentation/xcode/reducing-disk-write.
* Therefore we write plenty of data to disk on a background thread to hopefully trigger a DiskWriteException.
*/
class DiskWriteException {

private let dispatchQueue = DispatchQueue(label: "DiskWriteException", attributes: [.concurrent])
private let folder: URL
private var running = false

init() {
// swiftlint:disable force_unwrapping
let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
// swiftlint:enable force_unwrapping
folder = cachesDirectory.appendingPathComponent("DiskWriteException/")
}

func continuouslyWriteToDisk() {
if running {
return
}

running = true

dispatchQueue.async {
do {
let fileManager = FileManager.default
try fileManager.createDirectory(at: self.folder, withIntermediateDirectories: true)

let url = self.folder.appendingPathComponent("SomeBytes.txt")
fileManager.createFile(atPath: url.absoluteString, contents: nil)

// Keep writing random data to SomeBytes.txt
while true {
var data = Data()
for _ in 0..<100_000 {
let random = UInt8.random(in: 0...10)
data.append(Data(repeating: random, count: 50))
}

try data.write(to: url, options: .atomic)
self.delay()
}
} catch {
SentrySDK.capture(error: error)
}
}
}

private func delay(timeout: Double = 0.1) {
let group = DispatchGroup()
group.enter()

self.dispatchQueue.asyncAfter(deadline: .now() + timeout) {
group.leave()
}

group.wait()
}

func deleteFiles() {
let fileManager = FileManager.default
do {
if fileManager.fileExists(atPath: folder.path) {
try fileManager.removeItem(at: folder)
}
} catch {
SentrySDK.capture(error: error)
}
}
}
35 changes: 34 additions & 1 deletion Samples/iOS-Swift/iOS-Swift/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ class ViewController: UIViewController {
@IBOutlet weak var framesLabel: UILabel!
@IBOutlet weak var breadcrumbLabel: UILabel!

private let dispatchQueue = DispatchQueue(label: "ViewController")
private let dispatchQueue = DispatchQueue(label: "ViewController", attributes: .concurrent)
private let diskWriteException = DiskWriteException()

override func viewDidLoad() {
super.viewDidLoad()
Expand Down Expand Up @@ -200,6 +201,38 @@ class ViewController: UIViewController {
}
}
}

@IBAction func diskWriteException(_ sender: Any) {
diskWriteException.continuouslyWriteToDisk()

// As we are writing to disk continuously we would keep adding spans to this UIEventTransaction.
SentrySDK.span?.finish()
}

@IBAction func highCPULoad(_ sender: Any) {
dispatchQueue.async {
while true {
_ = self.calcPi()
}
}
}

private func calcPi() -> Double {
var denominator = 1.0
var pi = 0.0

for i in 0..<10_000_000 {
if i % 2 == 0 {
pi += 4 / denominator
} else {
pi -= 4 / denominator
}

denominator += 2
}

return pi
}

@IBAction func anrFullyBlocking(_ sender: Any) {
let buttonTitle = self.anrFullyBlockingButton.currentTitle
Expand Down
15 changes: 15 additions & 0 deletions Samples/macOS-Swift/macOS-Swift.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@
remoteGlobalIDString = 63AA759A1EB8AEF500D153DE;
remoteInfo = Sentry;
};
7B0AC1772939FBC700EFD958 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 6308533E2440C45A00DDE4CE /* Sentry.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = D81A3488291D0AC0005A27A9;
remoteInfo = SentryPrivate;
};
/* End PBXContainerItemProxy section */

/* Begin PBXCopyFilesBuildPhase section */
Expand Down Expand Up @@ -91,6 +98,7 @@
children = (
630853442440C45A00DDE4CE /* Sentry.framework */,
630853462440C45A00DDE4CE /* SentryTests.xctest */,
7B0AC1782939FBC700EFD958 /* SentryPrivate.framework */,
);
name = Products;
sourceTree = "<group>";
Expand Down Expand Up @@ -217,6 +225,13 @@
remoteRef = 630853452440C45A00DDE4CE /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
7B0AC1782939FBC700EFD958 /* SentryPrivate.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = SentryPrivate.framework;
remoteRef = 7B0AC1772939FBC700EFD958 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */

/* Begin PBXResourcesBuildPhase section */
Expand Down
Loading

0 comments on commit 5ed4bee

Please sign in to comment.