@logbrew/react-native 0.1.10 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LogBrewReactNative.podspec +25 -3
- package/README.md +174 -4
- package/android/src/main/java/co/logbrew/reactnative/EventRecordStore.java +611 -0
- package/android/src/main/java/co/logbrew/reactnative/FatalStoreModuleImpl.java +129 -0
- package/android/src/newarch/java/co/logbrew/reactnative/FatalStoreModule.java +26 -0
- package/android/src/oldarch/java/co/logbrew/reactnative/FatalStoreModule.java +26 -0
- package/apple-native-diagnostics.d.ts +52 -0
- package/apple-native-diagnostics.js +286 -0
- package/expo.cjs +46 -0
- package/expo.d.ts +16 -0
- package/expo.js +5 -0
- package/fatal-replay.cjs +12 -1
- package/global-errors.cjs +3 -1
- package/index.cjs +86 -2
- package/index.d.cts +7 -0
- package/index.d.ts +7 -0
- package/index.js +86 -2
- package/index.native.d.ts +47 -1
- package/index.native.js +81 -1
- package/ios/AppleDiagnostics/LBRNAppleDiagnosticsModule.h +4 -0
- package/ios/AppleDiagnostics/LBRNAppleDiagnosticsModule.mm +56 -0
- package/ios/AppleDiagnostics/LBRNAppleNativeDiagnostics.swift +293 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/AutomaticTelemetryContext.swift +72 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/DeliveryEngine.swift +270 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/DeliveryEngineAutomatic.swift +331 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/DeliveryEngineDurable.swift +148 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/DeliveryEngineQueue.swift +343 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/DeliveryLifecycle.swift +70 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/DurableDeliveryStore.swift +258 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/DurableDeliveryStoreRecovery.swift +330 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/EventEncoding.swift +114 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/IssueDiagnostics.swift +385 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/LifecycleTrace.swift +138 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/LogBrewClient.swift +358 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/LogBrewLogger.swift +262 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/LogBrewTrace.swift +357 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/Metadata.swift +86 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/NativeStackFrame.swift +27 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/ProductTimeline.swift +228 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/PublicTypes.swift +334 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/TelemetryContext.swift +197 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/TelemetryContextValidation.swift +337 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/TraceEvidence.swift +79 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/Transport.swift +204 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/URLSessionTrace.swift +277 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/URLSessionTracer.swift +151 -0
- package/ios/GeneratedAppleDiagnostics/LogBrew/Validation.swift +165 -0
- package/ios/GeneratedAppleDiagnostics/LogBrewCrash/CrashEngine.swift +125 -0
- package/ios/GeneratedAppleDiagnostics/LogBrewCrash/CrashReportSanitizer.swift +139 -0
- package/ios/GeneratedAppleDiagnostics/LogBrewCrash/CrashStorageDirectory.swift +124 -0
- package/ios/GeneratedAppleDiagnostics/LogBrewCrash/NativeArtifactIdentity.swift +137 -0
- package/ios/GeneratedAppleDiagnostics/LogBrewCrash/NativeCrashCapture.swift +229 -0
- package/ios/GeneratedAppleDiagnostics/LogBrewCrash/NativeCrashPublic.swift +386 -0
- package/ios/GeneratedAppleDiagnostics/LogBrewCrash/NativeCrashReplay.swift +317 -0
- package/ios/GeneratedAppleDiagnostics/LogBrewCrash/NativeHangIncidentStore.swift +321 -0
- package/ios/GeneratedAppleDiagnostics/LogBrewCrash/NativeHangWatchdog.swift +386 -0
- package/ios/GeneratedAppleDiagnostics/LogBrewCrash/NativeHangWatchdogContracts.swift +84 -0
- package/ios/GeneratedAppleDiagnostics/LogBrewCrash/NativeHangWatchdogSystem.swift +139 -0
- package/ios/GeneratedAppleDiagnostics/LogBrewCrash/NativeMainThreadStackCapture.swift +84 -0
- package/ios/GeneratedAppleDiagnostics/LogBrewCrash/NativeStackFrameSanitizer.swift +170 -0
- package/ios/GeneratedAppleDiagnostics/SOURCE-MANIFEST.json +43 -0
- package/ios/LBRNEventRecordStore.h +29 -0
- package/ios/LBRNEventRecordStore.m +746 -0
- package/ios/LBRNFatalStoreModule.mm +159 -14
- package/ios/LBRNPrivateStorage.h +7 -0
- package/ios/LBRNPrivateStorage.m +38 -0
- package/package.json +47 -4
- package/persistent-delivery.native.js +282 -0
- package/promise-rejections.cjs +3 -1
- package/scripts/sync-apple-native-sources.mjs +93 -0
- package/src/NativeLogBrewAppleDiagnostics.ts +12 -0
- package/src/NativeLogBrewFatalStore.ts +9 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
// Generated by scripts/sync-apple-native-sources.mjs.
|
|
2
|
+
// Edit the canonical Swift source, then regenerate this package boundary.
|
|
3
|
+
import Darwin
|
|
4
|
+
import Foundation
|
|
5
|
+
|
|
6
|
+
extension DurableDeliveryStore {
|
|
7
|
+
static func loadRecovery(from directory: URL, sdk: SDKInfo, fileManager: FileManager) throws -> Recovery {
|
|
8
|
+
let children = try recoveryChildren(in: directory, fileManager: fileManager)
|
|
9
|
+
var events: [(UInt64, RecoveredEvent)] = []
|
|
10
|
+
var prefix: RecoveredPrefix?
|
|
11
|
+
|
|
12
|
+
for child in children where child.lastPathComponent != lockName {
|
|
13
|
+
let values = try resourceValues(for: child)
|
|
14
|
+
guard values.isSymbolicLink != true, values.isRegularFile == true else {
|
|
15
|
+
throw DurableStoreFailure.corrupt
|
|
16
|
+
}
|
|
17
|
+
try hardenOwnedFile(child, fileManager: fileManager)
|
|
18
|
+
if child.lastPathComponent == prefixName {
|
|
19
|
+
guard prefix == nil else {
|
|
20
|
+
throw DurableStoreFailure.corrupt
|
|
21
|
+
}
|
|
22
|
+
prefix = try recoverPrefix(from: child, values: values, sdk: sdk)
|
|
23
|
+
} else {
|
|
24
|
+
try events.append(recoverEvent(from: child, values: values, sdk: sdk))
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
events.sort { $0.0 < $1.0 }
|
|
29
|
+
let recovered = events.map(\.1)
|
|
30
|
+
try validateRecovery(events: recovered, prefix: prefix)
|
|
31
|
+
return Recovery(events: recovered, prefix: prefix)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static func validateParent(_ parent: URL, fileManager: FileManager) throws {
|
|
35
|
+
guard parent.isFileURL else {
|
|
36
|
+
throw DurableStoreFailure.invalidLocation
|
|
37
|
+
}
|
|
38
|
+
let values = try resourceValues(for: parent)
|
|
39
|
+
guard values.isSymbolicLink != true, values.isDirectory == true else {
|
|
40
|
+
throw DurableStoreFailure.invalidLocation
|
|
41
|
+
}
|
|
42
|
+
let permissions = try permissions(at: parent, fileManager: fileManager)
|
|
43
|
+
guard permissions & 0o022 == 0 else {
|
|
44
|
+
throw DurableStoreFailure.invalidLocation
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static func prepareOwnedDirectory(_ directory: URL, fileManager: FileManager) throws {
|
|
49
|
+
if fileManager.fileExists(atPath: directory.path) {
|
|
50
|
+
try validateDirectory(directory, fileManager: fileManager)
|
|
51
|
+
} else {
|
|
52
|
+
do {
|
|
53
|
+
try fileManager.createDirectory(
|
|
54
|
+
at: directory,
|
|
55
|
+
withIntermediateDirectories: false,
|
|
56
|
+
attributes: ownedDirectoryAttributes,
|
|
57
|
+
)
|
|
58
|
+
} catch {
|
|
59
|
+
throw DurableStoreFailure.inputOutput
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
do {
|
|
63
|
+
try fileManager.setAttributes(ownedDirectoryAttributes, ofItemAtPath: directory.path)
|
|
64
|
+
var values = URLResourceValues()
|
|
65
|
+
values.isExcludedFromBackup = true
|
|
66
|
+
var mutableDirectory = directory
|
|
67
|
+
try mutableDirectory.setResourceValues(values)
|
|
68
|
+
} catch {
|
|
69
|
+
throw DurableStoreFailure.inputOutput
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static func validateDirectory(_ directory: URL, fileManager: FileManager) throws {
|
|
74
|
+
let values = try resourceValues(for: directory)
|
|
75
|
+
guard values.isSymbolicLink != true, values.isDirectory == true else {
|
|
76
|
+
throw DurableStoreFailure.invalidLocation
|
|
77
|
+
}
|
|
78
|
+
let permissions = try permissions(at: directory, fileManager: fileManager)
|
|
79
|
+
guard permissions & 0o077 == 0 else {
|
|
80
|
+
throw DurableStoreFailure.invalidLocation
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
static func acquireLock(in directory: URL, fileManager: FileManager) throws -> FileHandle {
|
|
85
|
+
let lock = directory.appendingPathComponent(lockName, isDirectory: false)
|
|
86
|
+
if !fileManager.fileExists(atPath: lock.path) {
|
|
87
|
+
guard fileManager.createFile(atPath: lock.path, contents: Data(), attributes: ownedFileAttributes) else {
|
|
88
|
+
throw DurableStoreFailure.inputOutput
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
do {
|
|
92
|
+
let values = try resourceValues(for: lock)
|
|
93
|
+
guard values.isSymbolicLink != true, values.isRegularFile == true else {
|
|
94
|
+
throw DurableStoreFailure.invalidLocation
|
|
95
|
+
}
|
|
96
|
+
try hardenOwnedFile(lock, fileManager: fileManager)
|
|
97
|
+
let handle = try FileHandle(forUpdating: lock)
|
|
98
|
+
guard flock(handle.fileDescriptor, LOCK_EX | LOCK_NB) == 0 else {
|
|
99
|
+
try? handle.close()
|
|
100
|
+
throw DurableStoreFailure.owned
|
|
101
|
+
}
|
|
102
|
+
return handle
|
|
103
|
+
} catch let failure as DurableStoreFailure {
|
|
104
|
+
throw failure
|
|
105
|
+
} catch {
|
|
106
|
+
throw DurableStoreFailure.inputOutput
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
static func releaseLock(_ handle: FileHandle) {
|
|
111
|
+
_ = flock(handle.fileDescriptor, LOCK_UN)
|
|
112
|
+
try? handle.close()
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
static func resourceValues(for url: URL) throws -> URLResourceValues {
|
|
116
|
+
do {
|
|
117
|
+
return try url.resourceValues(forKeys: [
|
|
118
|
+
.fileSizeKey,
|
|
119
|
+
.isDirectoryKey,
|
|
120
|
+
.isRegularFileKey,
|
|
121
|
+
.isSymbolicLinkKey,
|
|
122
|
+
])
|
|
123
|
+
} catch {
|
|
124
|
+
throw DurableStoreFailure.inputOutput
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
static func permissions(at url: URL, fileManager: FileManager) throws -> Int {
|
|
129
|
+
do {
|
|
130
|
+
let attributes = try fileManager.attributesOfItem(atPath: url.path)
|
|
131
|
+
guard let permissions = attributes[.posixPermissions] as? NSNumber else {
|
|
132
|
+
throw DurableStoreFailure.invalidLocation
|
|
133
|
+
}
|
|
134
|
+
return permissions.intValue
|
|
135
|
+
} catch let failure as DurableStoreFailure {
|
|
136
|
+
throw failure
|
|
137
|
+
} catch {
|
|
138
|
+
throw DurableStoreFailure.inputOutput
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
static func hardenOwnedFile(_ file: URL, fileManager: FileManager) throws {
|
|
143
|
+
do {
|
|
144
|
+
try fileManager.setAttributes(ownedFileAttributes, ofItemAtPath: file.path)
|
|
145
|
+
} catch {
|
|
146
|
+
throw DurableStoreFailure.inputOutput
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
static var ownedDirectoryAttributes: [FileAttributeKey: Any] {
|
|
151
|
+
var attributes: [FileAttributeKey: Any] = [.posixPermissions: 0o700]
|
|
152
|
+
#if os(iOS) || os(tvOS) || os(watchOS)
|
|
153
|
+
attributes[.protectionKey] = FileProtectionType.completeUntilFirstUserAuthentication
|
|
154
|
+
#endif
|
|
155
|
+
return attributes
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
static var ownedFileAttributes: [FileAttributeKey: Any] {
|
|
159
|
+
var attributes: [FileAttributeKey: Any] = [.posixPermissions: 0o600]
|
|
160
|
+
#if os(iOS) || os(tvOS) || os(watchOS)
|
|
161
|
+
attributes[.protectionKey] = FileProtectionType.completeUntilFirstUserAuthentication
|
|
162
|
+
#endif
|
|
163
|
+
return attributes
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
static func eventName(sequence: UInt64) -> String {
|
|
167
|
+
String(format: "event-%020llu.json", sequence)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
static func sequence(from recovered: RecoveredEvent) throws -> UInt64 {
|
|
171
|
+
try sequence(from: recovered.recordName)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
static func sequence(from name: String) throws -> UInt64 {
|
|
175
|
+
let prefix = "event-"
|
|
176
|
+
let suffix = ".json"
|
|
177
|
+
guard name.hasPrefix(prefix), name.hasSuffix(suffix) else {
|
|
178
|
+
throw DurableStoreFailure.corrupt
|
|
179
|
+
}
|
|
180
|
+
let start = name.index(name.startIndex, offsetBy: prefix.count)
|
|
181
|
+
let end = name.index(name.endIndex, offsetBy: -suffix.count)
|
|
182
|
+
let digits = String(name[start ..< end])
|
|
183
|
+
guard digits.count == 20,
|
|
184
|
+
digits.allSatisfy(\.isNumber),
|
|
185
|
+
let sequence = UInt64(digits),
|
|
186
|
+
eventName(sequence: sequence) == name
|
|
187
|
+
else {
|
|
188
|
+
throw DurableStoreFailure.corrupt
|
|
189
|
+
}
|
|
190
|
+
return sequence
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
static func isOwnedName(_ name: String) -> Bool {
|
|
194
|
+
name == prefixName || (try? sequence(from: name)) != nil
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
static func encode(_ value: some Encodable) throws -> Data {
|
|
198
|
+
do {
|
|
199
|
+
let encoder = JSONEncoder()
|
|
200
|
+
encoder.outputFormatting = [.sortedKeys]
|
|
201
|
+
return try encoder.encode(value)
|
|
202
|
+
} catch {
|
|
203
|
+
throw DurableStoreFailure.inputOutput
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
static func encodeEvent(_ event: Event) throws -> Data {
|
|
208
|
+
try encode(event)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
static func checksum(_ data: Data) -> String {
|
|
212
|
+
var hash: UInt64 = 14_695_981_039_346_656_037
|
|
213
|
+
for byte in data {
|
|
214
|
+
hash ^= UInt64(byte)
|
|
215
|
+
hash &*= 1_099_511_628_211
|
|
216
|
+
}
|
|
217
|
+
return String(format: "%016llx", hash)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
private static func recoveryChildren(in directory: URL, fileManager: FileManager) throws -> [URL] {
|
|
221
|
+
do {
|
|
222
|
+
return try fileManager.contentsOfDirectory(
|
|
223
|
+
at: directory,
|
|
224
|
+
includingPropertiesForKeys: [.fileSizeKey, .isRegularFileKey, .isSymbolicLinkKey],
|
|
225
|
+
options: [],
|
|
226
|
+
)
|
|
227
|
+
} catch {
|
|
228
|
+
throw DurableStoreFailure.inputOutput
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
private static func recoverPrefix(
|
|
233
|
+
from file: URL,
|
|
234
|
+
values: URLResourceValues,
|
|
235
|
+
sdk: SDKInfo,
|
|
236
|
+
) throws -> RecoveredPrefix {
|
|
237
|
+
guard let size = values.fileSize, size <= maxPrefixRecordBytes else {
|
|
238
|
+
throw DurableStoreFailure.corrupt
|
|
239
|
+
}
|
|
240
|
+
let record = try decodePrefixRecord(from: file)
|
|
241
|
+
guard record.version == version, record.sdk == sdk else {
|
|
242
|
+
throw DurableStoreFailure.corrupt
|
|
243
|
+
}
|
|
244
|
+
return RecoveredPrefix(
|
|
245
|
+
body: record.body,
|
|
246
|
+
eventRecordNames: record.eventRecordNames,
|
|
247
|
+
encodedBytes: record.encodedBytes,
|
|
248
|
+
)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
private static func recoverEvent(
|
|
252
|
+
from file: URL,
|
|
253
|
+
values: URLResourceValues,
|
|
254
|
+
sdk: SDKInfo,
|
|
255
|
+
) throws -> (UInt64, RecoveredEvent) {
|
|
256
|
+
let name = file.lastPathComponent
|
|
257
|
+
let sequence = try sequence(from: name)
|
|
258
|
+
guard let size = values.fileSize, size <= maxEventRecordBytes else {
|
|
259
|
+
throw DurableStoreFailure.corrupt
|
|
260
|
+
}
|
|
261
|
+
let record = try decodeEventRecord(from: file)
|
|
262
|
+
let encodedEvent = try encodeEvent(record.event)
|
|
263
|
+
guard record.version == version,
|
|
264
|
+
record.sequence == sequence,
|
|
265
|
+
record.sdk == sdk,
|
|
266
|
+
record.encodedBytes == encodedEvent.count,
|
|
267
|
+
record.checksum == checksum(encodedEvent)
|
|
268
|
+
else {
|
|
269
|
+
throw DurableStoreFailure.corrupt
|
|
270
|
+
}
|
|
271
|
+
return (
|
|
272
|
+
sequence,
|
|
273
|
+
RecoveredEvent(event: record.event, encodedBytes: record.encodedBytes, recordName: name),
|
|
274
|
+
)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
private static func validateRecovery(events: [RecoveredEvent], prefix: RecoveredPrefix?) throws {
|
|
278
|
+
guard events.count <= DeliveryEngine.maxQueuedEvents,
|
|
279
|
+
events.reduce(0, { $0 + $1.encodedBytes }) <= DeliveryEngine.maxQueuedBytes
|
|
280
|
+
else {
|
|
281
|
+
throw DurableStoreFailure.corrupt
|
|
282
|
+
}
|
|
283
|
+
guard let prefix else {
|
|
284
|
+
return
|
|
285
|
+
}
|
|
286
|
+
let frozenEvents = events.prefix(prefix.eventRecordNames.count)
|
|
287
|
+
guard !prefix.eventRecordNames.isEmpty,
|
|
288
|
+
prefix.eventRecordNames.count <= DeliveryEngine.maxRequestEvents,
|
|
289
|
+
prefix.body.count <= DeliveryEngine.maxRequestBytes,
|
|
290
|
+
frozenEvents.map(\.recordName) == prefix.eventRecordNames,
|
|
291
|
+
frozenEvents.reduce(0, { $0 + $1.encodedBytes }) == prefix.encodedBytes
|
|
292
|
+
else {
|
|
293
|
+
throw DurableStoreFailure.corrupt
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
private static func decodeEventRecord(from file: URL) throws -> EventRecord {
|
|
298
|
+
do {
|
|
299
|
+
return try JSONDecoder().decode(EventRecord.self, from: read(file, maxBytes: maxEventRecordBytes))
|
|
300
|
+
} catch let failure as DurableStoreFailure {
|
|
301
|
+
throw failure
|
|
302
|
+
} catch {
|
|
303
|
+
throw DurableStoreFailure.corrupt
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
private static func decodePrefixRecord(from file: URL) throws -> PrefixRecord {
|
|
308
|
+
do {
|
|
309
|
+
return try JSONDecoder().decode(PrefixRecord.self, from: read(file, maxBytes: maxPrefixRecordBytes))
|
|
310
|
+
} catch let failure as DurableStoreFailure {
|
|
311
|
+
throw failure
|
|
312
|
+
} catch {
|
|
313
|
+
throw DurableStoreFailure.corrupt
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
private static func read(_ file: URL, maxBytes: Int) throws -> Data {
|
|
318
|
+
do {
|
|
319
|
+
let data = try Data(contentsOf: file, options: [.mappedIfSafe])
|
|
320
|
+
guard data.count <= maxBytes else {
|
|
321
|
+
throw DurableStoreFailure.corrupt
|
|
322
|
+
}
|
|
323
|
+
return data
|
|
324
|
+
} catch let failure as DurableStoreFailure {
|
|
325
|
+
throw failure
|
|
326
|
+
} catch {
|
|
327
|
+
throw DurableStoreFailure.corrupt
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// Generated by scripts/sync-apple-native-sources.mjs.
|
|
2
|
+
// Edit the canonical Swift source, then regenerate this package boundary.
|
|
3
|
+
struct SDKInfo: Codable, Equatable {
|
|
4
|
+
let name: String
|
|
5
|
+
let language: String
|
|
6
|
+
let version: String
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
struct EventBatch: Encodable {
|
|
10
|
+
let sdk: SDKInfo
|
|
11
|
+
let events: [Event]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
struct Event: Codable, Equatable {
|
|
15
|
+
let type: String
|
|
16
|
+
let timestamp: String
|
|
17
|
+
let id: String
|
|
18
|
+
let attributes: EventAttributes
|
|
19
|
+
|
|
20
|
+
private enum CodingKeys: String, CodingKey {
|
|
21
|
+
case type
|
|
22
|
+
case timestamp
|
|
23
|
+
case id
|
|
24
|
+
case attributes
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
init(type: String, timestamp: String, id: String, attributes: EventAttributes) {
|
|
28
|
+
self.type = type
|
|
29
|
+
self.timestamp = timestamp
|
|
30
|
+
self.id = id
|
|
31
|
+
self.attributes = attributes
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
func encode(to encoder: Encoder) throws {
|
|
35
|
+
var container = encoder.container(keyedBy: CodingKeys.self)
|
|
36
|
+
try container.encode(type, forKey: .type)
|
|
37
|
+
try container.encode(timestamp, forKey: .timestamp)
|
|
38
|
+
try container.encode(id, forKey: .id)
|
|
39
|
+
switch attributes {
|
|
40
|
+
case let .release(value):
|
|
41
|
+
try container.encode(value, forKey: .attributes)
|
|
42
|
+
case let .environment(value):
|
|
43
|
+
try container.encode(value, forKey: .attributes)
|
|
44
|
+
case let .issue(value):
|
|
45
|
+
try container.encode(value, forKey: .attributes)
|
|
46
|
+
case let .log(value):
|
|
47
|
+
try container.encode(value, forKey: .attributes)
|
|
48
|
+
case let .span(value):
|
|
49
|
+
try container.encode(value, forKey: .attributes)
|
|
50
|
+
case let .action(value):
|
|
51
|
+
try container.encode(value, forKey: .attributes)
|
|
52
|
+
case let .metric(value):
|
|
53
|
+
try container.encode(value, forKey: .attributes)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
init(from decoder: Decoder) throws {
|
|
58
|
+
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
59
|
+
type = try container.decode(String.self, forKey: .type)
|
|
60
|
+
timestamp = try container.decode(String.self, forKey: .timestamp)
|
|
61
|
+
id = try container.decode(String.self, forKey: .id)
|
|
62
|
+
switch type {
|
|
63
|
+
case "release":
|
|
64
|
+
attributes = try .release(container.decode(ReleaseAttributes.self, forKey: .attributes))
|
|
65
|
+
case "environment":
|
|
66
|
+
attributes = try .environment(container.decode(EnvironmentAttributes.self, forKey: .attributes))
|
|
67
|
+
case "issue":
|
|
68
|
+
attributes = try .issue(container.decode(IssueAttributes.self, forKey: .attributes))
|
|
69
|
+
case "log":
|
|
70
|
+
attributes = try .log(container.decode(LogAttributes.self, forKey: .attributes))
|
|
71
|
+
case "span":
|
|
72
|
+
attributes = try .span(container.decode(SpanAttributes.self, forKey: .attributes))
|
|
73
|
+
case "action":
|
|
74
|
+
attributes = try .action(container.decode(ActionAttributes.self, forKey: .attributes))
|
|
75
|
+
case "metric":
|
|
76
|
+
attributes = try .metric(container.decode(MetricAttributes.self, forKey: .attributes))
|
|
77
|
+
default:
|
|
78
|
+
throw DecodingError.dataCorruptedError(
|
|
79
|
+
forKey: .type,
|
|
80
|
+
in: container,
|
|
81
|
+
debugDescription: "unsupported event type",
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
enum EventAttributes: Equatable {
|
|
88
|
+
case release(ReleaseAttributes)
|
|
89
|
+
case environment(EnvironmentAttributes)
|
|
90
|
+
case issue(IssueAttributes)
|
|
91
|
+
case log(LogAttributes)
|
|
92
|
+
case span(SpanAttributes)
|
|
93
|
+
case action(ActionAttributes)
|
|
94
|
+
case metric(MetricAttributes)
|
|
95
|
+
|
|
96
|
+
var eventType: String {
|
|
97
|
+
switch self {
|
|
98
|
+
case .release:
|
|
99
|
+
"release"
|
|
100
|
+
case .environment:
|
|
101
|
+
"environment"
|
|
102
|
+
case .issue:
|
|
103
|
+
"issue"
|
|
104
|
+
case .log:
|
|
105
|
+
"log"
|
|
106
|
+
case .span:
|
|
107
|
+
"span"
|
|
108
|
+
case .action:
|
|
109
|
+
"action"
|
|
110
|
+
case .metric:
|
|
111
|
+
"metric"
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|