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

Refine TracksDemo to help investigate crash logs from fatalError #292

Draft
wants to merge 8 commits into
base: trunk
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ Tracks for iOS is a client library used to help track events inside of an applic

## Installation


You can install the Tracks component in your app via Swift Package Manager:

```swift
Expand Down Expand Up @@ -57,7 +56,6 @@ Check out the **TracksDemo** project for more information on how to track events
1. Create an instance of `EventLogging` using `init(dataSource:delegate:)`.
2. Call `enqueueLogForUpload(log:)` to schedule log files for uploading.


### Logging

Tracks logs about some of its activity. By default, this logging will just go to the console. If you'd like to include this logging in your own logging solution, you can create and assign a logging delegate conforming to `TracksLoggingDelegate`:
Expand All @@ -66,6 +64,19 @@ Tracks logs about some of its activity. By default, this logging will just go to
TracksLogging.delegate = MyLoggingHandler()
```

## Development

You can open the TracksDemo project with:

```
open -a /Applications/Xcode.app TracksDemo/TracksDemo.xcodeproj
```

or by running:

```
bundle exec fastlane open_demo_project
```

## Contributing

Expand Down
13 changes: 10 additions & 3 deletions Sources/Remote Logging/Crash Logging/CrashLogging.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ public class CrashLogging {
#endif
}

TracksLogDebug("Successfully intialized SentrySDK.")
TracksLogDebug("- crashedLastRun: \(SentrySDK.crashedLastRun)")
TracksLogDebug("- detectedStartUpCrash: \(SentrySDK.detectedStartUpCrash)")

Internals.crashLogging = self

return self
Expand All @@ -106,7 +110,8 @@ public class CrashLogging {
}

/// If we shouldn't send the event we have nothing else to do here
guard let event = event, shouldSendEvent else {
guard let event, shouldSendEvent else {
TracksLogVerbose("No event to send or user opted-out. Moving on...")
return nil
}

Expand All @@ -122,9 +127,11 @@ public class CrashLogging {
/// Read the current user from the Data Provider (though the Data Provider can decide not to provide it for functional or privacy reasons)
event.user = dataProvider.currentUser?.sentryUser

TracksLogDebug("🐷 \(dataProvider.currentUser.debugDescription)")

/// Everything below this line is related to event logging, so if it's not set up we can exit
guard let eventLogging = self.eventLogging else {
TracksLogDebug("📜 Cancelling log file attachment – Event Logging is not initialized")
guard let eventLogging else {
TracksLogDebug("📜 Will not attach log file because `EventLogging` is not initialized")
return event
}

Expand Down
26 changes: 15 additions & 11 deletions Sources/Remote Logging/EventLogging+Sentry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,27 @@ public extension EventLoggingDelegate {

extension EventLogging {
func attachLogToEventIfNeeded(event: Event) {

/// Don't enqueue logs for non-fatal events unless directed to by the delegate
if event.level != .fatal && !delegate.shouldUploadLogFilesForNonFatalEvents {
TracksLogDebug("📜 Cancelling event log attachment – level is \(String(describing: event.level))")
/// Only enqueue logs for fatal events unless directed to by the delegate
guard event.level == .fatal || delegate.shouldUploadLogFilesForNonFatalEvents else {
TracksLogDebug("""
📜 Will not attempt to attach log file because event level is \(String(describing: event.level)).
Bypass this check by setting shouldUploadLogFilesForNonFatalEvents to true via EventLoggingDelegate
"""
)
return
}

guard let timestamp = event.timestamp else {
TracksLogDebug("📜 Unable to locate event timestamp")
TracksLogDebug("📜 Will not attempt to attach log file because unable to locate event timestamp")
return
}

/// Allow the hosting app to determine the most appropriate log file to send for the error type. For example, in an application using
/// session-based file logging, the newest log file would be the current session, which is appropriate for debugging logs. However,
/// the previous session's log file is the correct one for a crash, because when the crash is sent there will already be a new log
/// file for the current session. Other apps may use time-based logs, in which case the same log would be the correct one.
/// Allow the hosting app to determine the most appropriate log file to send for the error type.
///
/// For example, in an application using session-based file logging, the newest log file would be the current session, which is
/// appropriate for debugging logs. However, the previous session's log file is the correct one for a crash, because when the
/// crash is sent there will already be a new log file for the current session. Other apps may use time-based logs, in which
/// case the same log would be the correct one.
///
/// We also pass the timestamp for the event, as that can be useful for determining the correct log file.
guard let logFilePath = dataSource.logFilePath(forErrorLevel: event.errorType, at: timestamp) else {
Expand All @@ -43,8 +48,7 @@ extension EventLogging {
let logFile = LogFile(url: logFilePath)
try enqueueLogForUpload(log: logFile)
event.logID = logFile.uuid
}
catch let err {
} catch let err {
CrashLogging.Internals.crashLogging?.logError(err)
}
}
Expand Down
44 changes: 44 additions & 0 deletions Sources/UI/Crash Logging/CrashLoggingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ public struct CrashLoggingView: View {
}
}
}
CrashButton("Crash with fatalError()") {
fatalError("Manually triggered fatalError()")
}
}

/// Push the form to the top of the screen
Expand Down Expand Up @@ -101,3 +104,44 @@ extension CrashLoggingView {
}
}
}

struct CrashButton: View {
let titleKey: LocalizedStringKey
let onCrashTapped: () -> Void

let message = """
For crashes to be reported, make sure no debbuger is attached.
If running from Xcode, go to Debug > Detach from <app name>.
Alternatively, stop the app from Xcode, then open it directly from the Simulator.
After the crash, open the app directly from the Simulator.
"""

@State var crashAlertPresented = false

public init(_ titleKey: LocalizedStringKey, onCrashTapped: @escaping () -> Void) {
self.titleKey = titleKey
self.onCrashTapped = onCrashTapped
}

public var body: some View {
if #available(iOS 15.0, *) {
Button(titleKey) {
crashAlertPresented = true
}
.alert(
"Before you continue...",
isPresented: $crashAlertPresented,
actions: {
Button("Cancel", role: .cancel) {}
Button("Crash", role: .destructive, action: onCrashTapped)
},
message: {
Text(message)
}
)
} else {
// TODO: It's really about time we update Tracks to a later iOS deployment target
preconditionFailure("Please run the demo app on iOS 15 or above...")
}
}
}
18 changes: 15 additions & 3 deletions TracksDemo/TracksDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 52;
objectVersion = 54;
objects = {

/* Begin PBXBuildFile section */
Expand All @@ -13,6 +13,7 @@
24FB4D3D25B2AF02006E4031 /* CrashLoggingDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24FB4D3C25B2AF02006E4031 /* CrashLoggingDataSource.swift */; };
24FB4D8425B2B304006E4031 /* CrashLoggingRootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24FB4D8325B2B304006E4031 /* CrashLoggingRootViewController.swift */; };
24FB4D8E25B2B332006E4031 /* CrashLoggingDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24FB4D3C25B2AF02006E4031 /* CrashLoggingDataSource.swift */; };
3F9FFE712C2442C600E68A22 /* Base.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 3F9FFE6F2C2442C600E68A22 /* Base.xcconfig */; };
937632941AC2026900086BC6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 937632931AC2026900086BC6 /* main.m */; };
937632971AC2026900086BC6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 937632961AC2026900086BC6 /* AppDelegate.m */; };
9376329A1AC2026900086BC6 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 937632991AC2026900086BC6 /* ViewController.m */; };
Expand Down Expand Up @@ -46,6 +47,7 @@
24FB4D3C25B2AF02006E4031 /* CrashLoggingDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashLoggingDataSource.swift; sourceTree = "<group>"; };
24FB4D4125B2AF0C006E4031 /* Secrets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Secrets.swift; sourceTree = "<group>"; };
24FB4D8325B2B304006E4031 /* CrashLoggingRootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashLoggingRootViewController.swift; sourceTree = "<group>"; };
3F9FFE6F2C2442C600E68A22 /* Base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Base.xcconfig; sourceTree = "<group>"; };
937539871AFA8A9000B94B2A /* TracksDemo_Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TracksDemo_Prefix.pch; sourceTree = "<group>"; };
9376328E1AC2026900086BC6 /* TracksDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TracksDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
937632921AC2026900086BC6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
Expand Down Expand Up @@ -107,6 +109,14 @@
path = Shared;
sourceTree = "<group>";
};
3F9FFE702C2442C600E68A22 /* Config */ = {
isa = PBXGroup;
children = (
3F9FFE6F2C2442C600E68A22 /* Base.xcconfig */,
);
path = Config;
sourceTree = "<group>";
};
937632851AC2026900086BC6 = {
isa = PBXGroup;
children = (
Expand All @@ -133,6 +143,7 @@
937632901AC2026900086BC6 /* TracksDemo */ = {
isa = PBXGroup;
children = (
3F9FFE702C2442C600E68A22 /* Config */,
937632951AC2026900086BC6 /* AppDelegate.h */,
937632961AC2026900086BC6 /* AppDelegate.m */,
937632981AC2026900086BC6 /* ViewController.h */,
Expand Down Expand Up @@ -324,6 +335,7 @@
9376329D1AC2026900086BC6 /* Main.storyboard in Resources */,
937632A21AC2026900086BC6 /* LaunchScreen.xib in Resources */,
9376329F1AC2026900086BC6 /* Images.xcassets in Resources */,
3F9FFE712C2442C600E68A22 /* Base.xcconfig in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -462,6 +474,7 @@
/* Begin XCBuildConfiguration section */
937632AF1AC2026900086BC6 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 3F9FFE6F2C2442C600E68A22 /* Base.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
Expand Down Expand Up @@ -507,7 +520,6 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
Expand All @@ -517,6 +529,7 @@
};
937632B01AC2026900086BC6 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 3F9FFE6F2C2442C600E68A22 /* Base.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
Expand Down Expand Up @@ -555,7 +568,6 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
"repositoryURL": "https://github.com/getsentry/sentry-cocoa",
"state": {
"branch": null,
"revision": "2479b6f7ff69b66bcdea82184d097667e63828ed",
"version": "8.5.0"
"revision": "08862789e1cbba7a9561bed69832a9306f339cd3",
"version": "8.29.1"
}
},
{
Expand Down
2 changes: 2 additions & 0 deletions TracksDemo/TracksDemo/Config/Base.xcconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// See the value set in Package.swift and Automattic-Tracks-iOS.podspec
IPHONEOS_DEPLOYMENT_TARGET = 13.0
4 changes: 4 additions & 0 deletions fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ PROJECT_PATH = File.join(__dir__, 'TracksDemo', 'TracksDemo.xcodeproj')

default_platform(:ios)

lane :open_demo_project do
sh 'open -a /Applications/Xcode.app ../TracksDemo/TracksDemo.xcodeproj'
end

platform :ios do
desc 'Builds the project and runs tests'
lane :test do
Expand Down