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

feature/APMI-2820 iOS crash does not retain old screen name #2

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Changes from 4 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
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ let CrashReportingVersionString = "0.2.0"

var TheCrashReporter: PLCrashReporter?

let sessionIdKey = "SessionID"
let screenNameKey = "ScreenName"

func initializeCrashReporting() {
let startupSpan = buildTracer().spanBuilder(spanName: "SplunkRumCrashReporting").startSpan()
startupSpan.setAttribute(key: "component", value: "appstart")
Expand All @@ -49,6 +52,9 @@ func initializeCrashReporting() {
SplunkRum.addSessionIdChangeCallback {
updateCrashReportSessionId()
}
SplunkRum.addScreenNameChangeCallback { name in
updateCrashReportScreenName(screenname: name)
}
// Now for the pending report if there is one
if !crashReporter.hasPendingCrashReport() {
return
Expand All @@ -70,12 +76,54 @@ private func buildTracer() -> Tracer {

}

func dataToDictionary(data: Data) -> [String: String]? {
let dicFromData = try? PropertyListSerialization.propertyList(from: data, options: PropertyListSerialization.ReadOptions.mutableContainers, format: nil)
return dicFromData as? [String: String]
}

func dictionaryToData(dict: [String: String]) -> Data? {
let data = try? PropertyListSerialization.data(fromPropertyList: dict, format: PropertyListSerialization.PropertyListFormat.binary, options: 0)
return data
}

func updateCrashReportSessionId() {
DispatchQueue.main.async {
TheCrashReporter?.customData = SplunkRum.getSessionId().data(using: .utf8)
saveSessionIDIntoCustomData()
}
}

func saveSessionIDIntoCustomData() {
if let dict = fetchFromCustomData() {
let screenName = dict[screenNameKey] ?? ""
saveIntoCustomData(dict: [sessionIdKey: SplunkRum.getSessionId(), screenNameKey: screenName])
} else {
saveIntoCustomData(dict: [sessionIdKey: SplunkRum.getSessionId()])
}
}

func saveScreenNameIntoCustomData(screenname: String) {
if let dict = fetchFromCustomData() {
let oldsessionid = dict[sessionIdKey] ?? ""
saveIntoCustomData(dict: [sessionIdKey: oldsessionid, screenNameKey: screenname])
} else {
saveIntoCustomData(dict: [screenNameKey: screenname])
}
}

func saveIntoCustomData(dict: [String: String]) {
TheCrashReporter?.customData = dictionaryToData(dict: dict)
}

func fetchFromCustomData() -> [String: String]? {
guard let data = TheCrashReporter?.customData else { return nil}
let dicFromData = dataToDictionary(data: data)
return dicFromData
}
func updateCrashReportScreenName(screenname: String) {
DispatchQueue.main.async {
saveScreenNameIntoCustomData(screenname: screenname)
}
}
func loadPendingCrashReport(_ data: Data!) throws {
SplunkRum.debugLog("Loading crash report of size \(data?.count as Any)")
let report = try PLCrashReport(data: data)
Expand All @@ -84,7 +132,9 @@ func loadPendingCrashReport(_ data: Data!) throws {
exceptionType = report.exceptionInfo.exceptionName
}

let oldSessionId = String(decoding: report.customData, as: UTF8.self)
guard let dict = dataToDictionary(data: report.customData) else {return}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should make a best effort to report data, even if we are missing some fields. Missing the old session ID and/or the old screen name should not prevent us from reporting any crash reporting span.

let oldSessionId = dict[sessionIdKey] ?? ""
let screenName = dict[screenNameKey] ?? ""
// Turn the report into a span
let now = Date()
let span = buildTracer().spanBuilder(spanName: exceptionType ?? "unknown").setStartTime(time: now).setNoParent().startSpan()
Expand All @@ -96,6 +146,7 @@ func loadPendingCrashReport(_ data: Data!) throws {
span.addEvent(name: "crash.timestamp", timestamp: report.systemInfo.timestamp)
span.setAttribute(key: "exception.type", value: exceptionType ?? "unknown")
span.setAttribute(key: "crash.address", value: report.signalInfo.address.description)
span.setAttribute(key: "screen.name", value: screenName)
for case let thread as PLCrashReportThreadInfo in report.threads where thread.crashed {
span.setAttribute(key: "exception.stacktrace", value: crashedThreadToStack(report: report, thread: thread))
break
Expand Down