forked from mozilla-mobile/focus-ios
-
Notifications
You must be signed in to change notification settings - Fork 1
/
SentryIntegration.swift
104 lines (83 loc) · 3.94 KB
/
SentryIntegration.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import Foundation
import Sentry
public class SentryIntegration {
public static let shared = SentryIntegration()
public static var crashedLastLaunch: Bool {
return Client.shared?.crashedLastLaunch() ?? false
}
private let SentryDSNKey = "SentryDSN"
private let SentryDeviceAppHashKey = "SentryDeviceAppHash"
private let DefaultDeviceAppHash = "0000000000000000000000000000000000000000"
private let DeviceAppHashLength = UInt(20)
private var enabled = false
private var attributes: [String : Any] = [:]
public func setup(sendUsageData: Bool) {
assert(!enabled, "SentryIntegration.setup() should only be called once")
if AppInfo.isSimulator() || !sendUsageData {
print("Sentry not enabled")
return
}
guard let dsn = Bundle.main.object(forInfoDictionaryKey: SentryDSNKey) as? String, !dsn.isEmpty else {
print("Could not obtain Sentry DSN")
return
}
do {
Client.shared = try Client(dsn: dsn)
try Client.shared?.startCrashHandler()
enabled = true
// If we have not already for this install, generate a completely random identifier
// for this device. It is stored in the app group so that the same value will
// be used for both the main application and the app extensions.
if let defaults = UserDefaults(suiteName: AppInfo.sharedContainerIdentifier), defaults.string(forKey: SentryDeviceAppHashKey) == nil {
defaults.set(Bytes.generateRandomBytes(DeviceAppHashLength).hexEncodedString, forKey: SentryDeviceAppHashKey)
defaults.synchronize()
}
// For all outgoing reports, override the default device identifier with our own random
// version. Default to a blank (zero) identifier in case of errors.
Client.shared?.beforeSerializeEvent = { event in
let deviceAppHash = UserDefaults(suiteName: AppInfo.sharedContainerIdentifier)?.string(forKey: self.SentryDeviceAppHashKey)
event.context?.appContext?["device_app_hash"] = deviceAppHash ?? self.DefaultDeviceAppHash
var attributes = event.extra ?? [:]
attributes.merge(with: self.attributes)
event.extra = attributes
}
} catch {}
}
public func crash() {
Client.shared?.crash()
}
public func send(message: String, tag: String = "general", severity: SentrySeverity = .info, completion: SentryRequestFinished? = nil) {
if !enabled {
if let completion = completion {
completion(nil)
}
return
}
let event = Event(level: severity)
event.message = message
event.tags = ["tag": tag]
Client.shared?.send(event: event, completion: completion)
}
public func sendWithStacktrace(message: String, tag: String = "general", severity: SentrySeverity = .info, completion: SentryRequestFinished? = nil) {
if !enabled {
if let completion = completion {
completion(nil)
}
return
}
Client.shared?.snapshotStacktrace {
let event = Event(level: severity)
event.message = message
event.tags = ["tag": tag]
Client.shared?.appendStacktrace(to: event)
event.debugMeta = nil
Client.shared?.send(event: event, completion: completion)
}
}
public func addAttributes(_ attributes: [String : Any]) {
self.attributes.merge(with: attributes)
}
}