@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
|
@@ -12,11 +12,33 @@ Pod::Spec.new do |spec|
|
|
|
12
12
|
spec.platforms = { :ios => "13.0" }
|
|
13
13
|
spec.source = {
|
|
14
14
|
:git => "https://github.com/LogBrewCo/sdk.git",
|
|
15
|
-
:tag => "react-native
|
|
15
|
+
:tag => "js/logbrew-react-native/v#{spec.version}"
|
|
16
16
|
}
|
|
17
|
-
spec.
|
|
18
|
-
spec.
|
|
17
|
+
spec.default_subspecs = "Core"
|
|
18
|
+
spec.swift_versions = ["5.0"]
|
|
19
19
|
spec.dependency "React-Core"
|
|
20
20
|
|
|
21
|
+
spec.subspec "Core" do |core|
|
|
22
|
+
core.source_files = "ios/**/*.{h,m,mm}"
|
|
23
|
+
core.exclude_files = [
|
|
24
|
+
"ios/AppleDiagnostics/**/*",
|
|
25
|
+
"ios/Tests/**/*"
|
|
26
|
+
]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
spec.subspec "AppleNativeDiagnostics" do |diagnostics|
|
|
30
|
+
diagnostics.ios.deployment_target = "15.0"
|
|
31
|
+
diagnostics.source_files = [
|
|
32
|
+
"ios/AppleDiagnostics/**/*.{h,m,mm,swift}",
|
|
33
|
+
"ios/GeneratedAppleDiagnostics/**/*.swift"
|
|
34
|
+
]
|
|
35
|
+
diagnostics.dependency "#{spec.name}/Core"
|
|
36
|
+
diagnostics.dependency "KSCrash/Recording", "2.5.1"
|
|
37
|
+
diagnostics.pod_target_xcconfig = {
|
|
38
|
+
"DEFINES_MODULE" => "YES",
|
|
39
|
+
"SWIFT_VERSION" => "5.0"
|
|
40
|
+
}
|
|
41
|
+
end
|
|
42
|
+
|
|
21
43
|
install_modules_dependencies(spec) if respond_to?(:install_modules_dependencies, true)
|
|
22
44
|
end
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
React Native helpers for the public LogBrew JavaScript SDK.
|
|
8
8
|
|
|
9
|
-
This package
|
|
9
|
+
This package keeps event validation, retry, flush, and shutdown behavior in `@logbrew/sdk`. It adds mobile helpers for screen views, app-state changes, product actions, API milestones, bounded issue breadcrumbs, typed handled and unhandled JavaScript errors, Promise rejection tracking, provider and hook usage, W3C trace correlation and propagation, lifecycle spans, resource spans, reversible instrumentation, and opt-in Apple native crash and app-hang diagnostics.
|
|
10
10
|
|
|
11
11
|
## Install
|
|
12
12
|
|
|
@@ -118,6 +118,73 @@ client key before creating a new client. A `429` preserves the queue and
|
|
|
118
118
|
reports `pausedReason: "rate_limit"` plus the bounded retry signal exposed by
|
|
119
119
|
the failed flush.
|
|
120
120
|
|
|
121
|
+
## Offline And Restart Delivery
|
|
122
|
+
|
|
123
|
+
The React Native entry uses an app-private native queue by default when the
|
|
124
|
+
current app binary contains the linked LogBrew module. Each accepted event is
|
|
125
|
+
written before it enters memory. After a JavaScript runtime or app restart,
|
|
126
|
+
the client loads pending events oldest first with their original IDs. A
|
|
127
|
+
successful intake response commits which records were accepted before removing
|
|
128
|
+
them, so an interrupted removal can cause a duplicate but cannot silently lose
|
|
129
|
+
an unaccepted event. Replayed events keep their stable IDs. Delivery is at
|
|
130
|
+
least once, so apps must tolerate duplicates, including when retries regroup
|
|
131
|
+
events into different batches.
|
|
132
|
+
|
|
133
|
+
Inspect the delivery health snapshot to observe the active behavior:
|
|
134
|
+
|
|
135
|
+
```js
|
|
136
|
+
const health = client.deliveryHealth();
|
|
137
|
+
if (health.storage !== "persistent") {
|
|
138
|
+
// The app is running without the linked native queue.
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The default `persistentQueue: "auto"` mode uses memory when the native module
|
|
143
|
+
is absent, including Expo Go and an older app binary after a JavaScript-only
|
|
144
|
+
update. For a production build that must not start without restart recovery,
|
|
145
|
+
set `persistentQueue: "required"`. Use `persistentQueue: "disabled"` only
|
|
146
|
+
when the app intentionally accepts a memory-only queue.
|
|
147
|
+
|
|
148
|
+
```js
|
|
149
|
+
const client = createLogBrewReactNativeClient({
|
|
150
|
+
clientKey,
|
|
151
|
+
persistentQueue: "required",
|
|
152
|
+
transport: createReactNativeFetchTransport()
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
The native queue stores one compact event per atomic record, is limited to
|
|
157
|
+
1,000 events and 4 MiB of compact event data, and uses the same smaller limits
|
|
158
|
+
when you configure them on the client. Both platforms use app-private storage.
|
|
159
|
+
The client key is not written to disk; its SHA-256 digest separates queues
|
|
160
|
+
after key rotation. The queue does not provide mathematically exactly-once
|
|
161
|
+
delivery.
|
|
162
|
+
|
|
163
|
+
A successful `shutdown()` drains and closes the queue. A failed flush or
|
|
164
|
+
shutdown leaves the exact remainder available to the same client and the next
|
|
165
|
+
app start. Call `client.purgePendingEvents()` only when no flush or shutdown is
|
|
166
|
+
active. To retire an active key without sending its remainder, purge that
|
|
167
|
+
client first and then close it:
|
|
168
|
+
|
|
169
|
+
```js
|
|
170
|
+
client.purgePendingEvents();
|
|
171
|
+
await client.shutdown();
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
When no client owns the key, remove any remaining records explicitly with:
|
|
175
|
+
|
|
176
|
+
```js
|
|
177
|
+
import { purgeLogBrewReactNativePersistentQueue } from "@logbrew/react-native";
|
|
178
|
+
|
|
179
|
+
purgeLogBrewReactNativePersistentQueue({ clientKey: previousClientKey });
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Use only one active persistent client for a given key across an app process.
|
|
183
|
+
The SDK rejects duplicates within one JavaScript runtime; apps with multiple
|
|
184
|
+
React Native runtimes or platform processes must coordinate that ownership.
|
|
185
|
+
Different client keys use separate native queues. The Node ESM and CommonJS
|
|
186
|
+
entries remain platform-neutral and never load React Native.
|
|
187
|
+
|
|
121
188
|
## Product Actions And API Milestones
|
|
122
189
|
|
|
123
190
|
Use explicit action and network helpers for important mobile funnel steps your app already understands. These events are designed for timelines and agent analysis without enabling broad automatic replay:
|
|
@@ -160,7 +227,7 @@ withLogBrewTrace(trace, () => {
|
|
|
160
227
|
|
|
161
228
|
## Error Capture
|
|
162
229
|
|
|
163
|
-
Use `captureReactNativeError()` in app-owned error boundaries, route handlers, async catch blocks, or global handlers. It records
|
|
230
|
+
Use `captureReactNativeError()` in app-owned error boundaries, route handlers, async catch blocks, or global handlers. It records a typed exception with `react-native.error`, `handled: true`, prior screen/app-state/action/network breadcrumbs, and React Native context. Global errors and Promise rejections use their own mechanism with `handled: false`. Raw stack text stays omitted by default:
|
|
164
231
|
|
|
165
232
|
```js
|
|
166
233
|
import { captureReactNativeError } from "@logbrew/react-native";
|
|
@@ -202,7 +269,101 @@ Installation is idempotent for the active React Native `ErrorUtils` object. The
|
|
|
202
269
|
|
|
203
270
|
The React Native conditional export obtains LogBrew's synchronous native fatal store through the supported TurboModule or `NativeModules` seam. Before chaining a fatal report, it writes one bounded record to app-private storage that is excluded from operating-system archives. On a later installation it performs stable-ID at-least-once replay, and acknowledgement happens only after local queue admission is observable through the SDK queue counters. Filtered, dropped, unknown-admission, persistence-failed, and acknowledgement-failed records are retained. A failed acknowledgement is retried without admitting the same ID twice in one JavaScript runtime. Use `fatalHealth()` for frozen bounded counters and status, or `discardPendingFatalRecord()` for an explicit rollback discard. The Node ESM and CommonJS entries never import React Native; non-React-Native callers must inject `fatalStore` explicitly.
|
|
204
271
|
|
|
205
|
-
Automatic events exclude the original error message, raw stack, arbitrary metadata, full URLs, hosts, query strings, local absolute paths, payloads, and native error text. `onDiagnostic` receives only a fixed code. This integration does not claim mathematically exactly-once delivery,
|
|
272
|
+
Automatic events exclude the original error message, raw stack, arbitrary metadata, full URLs, hosts, query strings, local absolute paths, payloads, and native error text. `onDiagnostic` receives only a fixed code. This error-handler integration does not claim mathematically exactly-once delivery, native crash capture, ANR or hang detection, general offline queueing by the fatal-record slot, or symbolication. The client-level persistent queue above owns normal event restart delivery.
|
|
273
|
+
|
|
274
|
+
### Apple native crash and app-hang diagnostics
|
|
275
|
+
|
|
276
|
+
Apple native diagnostics are an iOS-only, opt-in build feature. They capture a
|
|
277
|
+
fatal native process crash and replay one privacy-bounded issue after the next
|
|
278
|
+
launch. Set `hangThresholdSeconds` to also capture recovered or ongoing UIKit
|
|
279
|
+
main-thread hangs. Android native crash and ANR capture are not included.
|
|
280
|
+
|
|
281
|
+
For Expo prebuild or development builds, add the config plugin:
|
|
282
|
+
|
|
283
|
+
```json
|
|
284
|
+
{
|
|
285
|
+
"expo": {
|
|
286
|
+
"plugins": ["@logbrew/react-native/expo"]
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Then run your normal Expo prebuild or EAS build. Expo Go cannot load this native
|
|
292
|
+
module. For a bare React Native app, add the optional subspec inside the app
|
|
293
|
+
target in `ios/Podfile`, then run `pod install`:
|
|
294
|
+
|
|
295
|
+
```ruby
|
|
296
|
+
logbrew_react_native_path = File.dirname(`node --print "require.resolve('@logbrew/react-native')"`)
|
|
297
|
+
pod 'LogBrewReactNative/AppleNativeDiagnostics', :path => logbrew_react_native_path
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
The default `LogBrewReactNative/Core` subspec remains unchanged and supports
|
|
301
|
+
iOS 13. `AppleNativeDiagnostics` requires iOS 15. Install it on the main thread
|
|
302
|
+
before root registration, then start replay:
|
|
303
|
+
|
|
304
|
+
```js
|
|
305
|
+
import {
|
|
306
|
+
installLogBrewAppleNativeDiagnostics,
|
|
307
|
+
replayLogBrewAppleNativeDiagnostics
|
|
308
|
+
} from "@logbrew/react-native/apple-native-diagnostics";
|
|
309
|
+
|
|
310
|
+
const nativeStatus = installLogBrewAppleNativeDiagnostics({
|
|
311
|
+
clientKey: process.env.EXPO_PUBLIC_LOGBREW_CLIENT_KEY,
|
|
312
|
+
projectId: "550e8400-e29b-41d4-a716-446655440000",
|
|
313
|
+
release: "com.example.app@1.2.3+45",
|
|
314
|
+
environment: "production",
|
|
315
|
+
service: "ios-app",
|
|
316
|
+
fatalHandlerOwnership: "logbrew",
|
|
317
|
+
hangThresholdSeconds: 2
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
void replayLogBrewAppleNativeDiagnostics().catch((error) => {
|
|
321
|
+
console.warn(error?.code ?? "native_diagnostics_failed");
|
|
322
|
+
});
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
`fatalHandlerOwnership: "logbrew"` is an explicit process-lifetime ownership
|
|
326
|
+
claim. Do not install these diagnostics while Sentry or another integration
|
|
327
|
+
owns the native fatal signal or Mach exception handlers. Linking both SDKs is
|
|
328
|
+
allowed, but only one integration may install native fatal capture in a given
|
|
329
|
+
process. LogBrew cannot transfer or remove that ownership before process
|
|
330
|
+
restart.
|
|
331
|
+
|
|
332
|
+
Installation creates app-private, data-protected storage that iOS excludes from
|
|
333
|
+
device data archives. Pending reports are partitioned by project, so changing
|
|
334
|
+
the configured project does not replay an earlier project's records with the
|
|
335
|
+
new project's key. The raw local KSCrash report can still contain sensitive
|
|
336
|
+
process details, so apply the app's consent and retention policy to it. Hosted
|
|
337
|
+
replay uploads only the bounded crash or hang issue described by the Swift
|
|
338
|
+
`LogBrewCrash` contract. Status and error results expose fixed codes and bounded
|
|
339
|
+
counters, not keys, paths, raw reports, or native error text. A custom endpoint
|
|
340
|
+
must be a plain HTTPS path without embedded authentication, a query, or a fragment.
|
|
341
|
+
|
|
342
|
+
Use the same project, release, environment, and service values for the runtime
|
|
343
|
+
and its Apple dSYM. After signing in with `logbrew login`, upload and inspect
|
|
344
|
+
the exact debug object with the released CLI:
|
|
345
|
+
|
|
346
|
+
```bash
|
|
347
|
+
logbrew debug-artifacts upload ios/build/MyApp.app.dSYM \
|
|
348
|
+
--project 550e8400-e29b-41d4-a716-446655440000 \
|
|
349
|
+
--release com.example.app@1.2.3+45 \
|
|
350
|
+
--environment production \
|
|
351
|
+
--service ios-app \
|
|
352
|
+
--json
|
|
353
|
+
|
|
354
|
+
logbrew debug-artifacts lookup \
|
|
355
|
+
--project 550e8400-e29b-41d4-a716-446655440000 \
|
|
356
|
+
--release com.example.app@1.2.3+45 \
|
|
357
|
+
--environment production \
|
|
358
|
+
--service ios-app \
|
|
359
|
+
--image-uuid <mach_o_uuid> \
|
|
360
|
+
--architecture arm64 \
|
|
361
|
+
--json
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
The SDK does not upload debug objects during a build or at runtime. Hosted
|
|
365
|
+
symbolication begins only after the exact Mach-O UUID and architecture lookup
|
|
366
|
+
succeeds.
|
|
206
367
|
|
|
207
368
|
### Opt-in Hermes Promise rejection tracking
|
|
208
369
|
|
|
@@ -387,6 +548,8 @@ export function App({ client }) {
|
|
|
387
548
|
}
|
|
388
549
|
```
|
|
389
550
|
|
|
551
|
+
Screen views carry the versioned `screen_view` analytics classification, and explicit product actions carry `interaction`. The SDK uses the app-owned screen name as a bounded surface and does not inspect view hierarchies, selectors, or input values. Caller metadata cannot replace the reserved classification. See the repository [product analytics capture contract](../../docs/product-analytics-contract.md).
|
|
552
|
+
|
|
390
553
|
The package ships a `react-native` entry that imports `AppState` and `Platform` for Metro, while the default Node entry accepts those dependencies explicitly. That keeps mobile setup explicit instead of pretending a Node process is a native runtime.
|
|
391
554
|
|
|
392
555
|
## Trace Propagation
|
|
@@ -714,7 +877,14 @@ uploadLogBrewReactNativeReleaseArtifacts({
|
|
|
714
877
|
|
|
715
878
|
The helper requires explicit `release`, `environment`, `service`, and `platform` metadata. Hosted uploads also require a UUID `projectId`; local preparation and loopback upload remain valid without it. It defaults minified bundle URLs to `app:///react-native/<platform>/...`, removes query strings and hashes from manifest URLs, and strips source paths under `root` or `stripSourcePrefix`. Hosted endpoints must use HTTPS and must not include embedded auth values, query strings, or fragments. The helper never uses normal SDK ingest keys or account/session API auth values. When `sourcemap` points at a final Hermes-composed map, the helper makes the bundle's `sourceMappingURL` point at that explicit map, so stale packager-map comments do not block manifest generation. The explicit Metro wrapper changes only app-owned serialization and one bounded runtime Debug-ID registry; neither helper patches Gradle, Xcode, global fetch/XHR, request payloads, or transport behavior.
|
|
716
879
|
|
|
717
|
-
React Native native symbols are
|
|
880
|
+
React Native native symbols are release artifacts, not runtime telemetry. Use
|
|
881
|
+
the repository release-artifact tooling for local dry-run checks of app-owned
|
|
882
|
+
outputs such as `ios/build/.../*.dSYM`, Android mapping files, and native shared
|
|
883
|
+
objects. Apple dSYM upload, storage, exact UUID and architecture lookup, and
|
|
884
|
+
hosted symbolication are available through `logbrew debug-artifacts`. The SDK
|
|
885
|
+
does not upload those artifacts automatically. Normal JavaScript error capture
|
|
886
|
+
does not produce native crash symbolication; use the opt-in Apple diagnostics
|
|
887
|
+
flow above with an exact uploaded dSYM.
|
|
718
888
|
|
|
719
889
|
## Example Source
|
|
720
890
|
|