@logbrew/react-native 0.1.0 → 0.1.1
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/README.md +407 -18
- package/apollo.cjs +301 -0
- package/apollo.d.cts +70 -0
- package/apollo.d.ts +70 -0
- package/apollo.js +294 -0
- package/examples/apollo-link-spans.mjs +149 -0
- package/examples/index.mjs +29 -1
- package/examples/instrumentation-kit.mjs +304 -0
- package/examples/lifecycle-spans.mjs +131 -0
- package/examples/native-bridge-scope.mjs +107 -0
- package/examples/navigation-resource-spans.mjs +156 -0
- package/examples/package.json +8 -1
- package/examples/real-user-smoke.mjs +106 -9
- package/examples/resource-fetch-spans.mjs +133 -0
- package/examples/trace-correlation.mjs +135 -0
- package/index.cjs +625 -111
- package/index.d.cts +236 -0
- package/index.d.ts +236 -0
- package/index.js +613 -95
- package/index.native.js +18 -0
- package/instrumentation.cjs +639 -0
- package/instrumentation.d.cts +84 -0
- package/instrumentation.d.ts +84 -0
- package/instrumentation.js +634 -0
- package/lifecycle.cjs +129 -0
- package/lifecycle.d.cts +50 -0
- package/lifecycle.d.ts +50 -0
- package/lifecycle.js +121 -0
- package/metadata.cjs +175 -0
- package/metadata.js +165 -0
- package/metro.cjs +310 -0
- package/metro.d.cts +37 -0
- package/metro.d.ts +37 -0
- package/metro.js +6 -0
- package/native-bridge.cjs +127 -0
- package/native-bridge.d.cts +60 -0
- package/native-bridge.d.ts +60 -0
- package/native-bridge.js +125 -0
- package/package.json +113 -4
- package/release-artifacts.cjs +344 -0
- package/release-artifacts.d.cts +55 -0
- package/release-artifacts.d.ts +53 -0
- package/release-artifacts.js +8 -0
- package/resource-fetch.cjs +469 -0
- package/resource-fetch.d.cts +60 -0
- package/resource-fetch.d.ts +60 -0
- package/resource-fetch.js +464 -0
package/index.cjs
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
const React = require("react");
|
|
2
2
|
const {
|
|
3
|
+
createIssueAttributesFromError,
|
|
3
4
|
createTraceparent,
|
|
4
5
|
LogBrewClient,
|
|
5
6
|
parseTraceparent,
|
|
6
7
|
SdkError
|
|
7
8
|
} = require("@logbrew/sdk");
|
|
9
|
+
const {
|
|
10
|
+
runtimeReactNativeDebugIdMap,
|
|
11
|
+
sanitizeReactNativeIssueMetadata,
|
|
12
|
+
sanitizeReactNativeIssueStackFrames
|
|
13
|
+
} = require("./metadata.cjs");
|
|
8
14
|
|
|
9
15
|
const DEFAULT_SDK_NAME = "logbrew-react-native";
|
|
10
16
|
const DEFAULT_SDK_VERSION = "0.1.0";
|
|
11
17
|
const LogBrewNativeContext = React.createContext(null);
|
|
18
|
+
const activeTraceScopes = [];
|
|
19
|
+
let nextTraceScopeId = 0;
|
|
12
20
|
|
|
13
21
|
function createLogBrewReactNativeClient({
|
|
14
22
|
apiKey,
|
|
@@ -24,12 +32,7 @@ function createLogBrewReactNativeClient({
|
|
|
24
32
|
return LogBrewClient.create({ apiKey: authKey, sdkName, sdkVersion, maxRetries });
|
|
25
33
|
}
|
|
26
34
|
|
|
27
|
-
function createReactNativeTraceparent({
|
|
28
|
-
randomValues = defaultRandomValues,
|
|
29
|
-
spanId,
|
|
30
|
-
traceFlags = "01",
|
|
31
|
-
traceId
|
|
32
|
-
} = {}) {
|
|
35
|
+
function createReactNativeTraceparent({ randomValues = defaultRandomValues, spanId, traceFlags = "01", traceId } = {}) {
|
|
33
36
|
return createTraceparent({
|
|
34
37
|
spanId: spanId ?? randomHex(8, randomValues),
|
|
35
38
|
traceFlags,
|
|
@@ -37,9 +40,123 @@ function createReactNativeTraceparent({
|
|
|
37
40
|
});
|
|
38
41
|
}
|
|
39
42
|
|
|
43
|
+
function createReactNativeTraceContext({
|
|
44
|
+
parentSpanId, randomValues = defaultRandomValues, spanId, traceFlags = "01", traceId, traceparent
|
|
45
|
+
} = {}) {
|
|
46
|
+
if (traceparent !== undefined && traceparent !== null && String(traceparent).trim() !== "") {
|
|
47
|
+
try {
|
|
48
|
+
const parsed = parseTraceparent(traceparent);
|
|
49
|
+
const localSpanId = spanId ?? randomHex(8, randomValues);
|
|
50
|
+
createTraceparent({ traceId: parsed.traceId, spanId: localSpanId, traceFlags: parsed.traceFlags });
|
|
51
|
+
return freezeTraceContext({
|
|
52
|
+
parentSpanId: parsed.parentSpanId,
|
|
53
|
+
sampled: parsed.sampled,
|
|
54
|
+
spanId: localSpanId,
|
|
55
|
+
traceFlags: parsed.traceFlags,
|
|
56
|
+
traceId: parsed.traceId
|
|
57
|
+
});
|
|
58
|
+
} catch {
|
|
59
|
+
// Bad upstream propagation should not break mobile app flows.
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const localTraceId = traceId ?? randomHex(16, randomValues);
|
|
64
|
+
const localSpanId = spanId ?? randomHex(8, randomValues);
|
|
65
|
+
createTraceparent({ traceId: localTraceId, spanId: localSpanId, traceFlags });
|
|
66
|
+
if (parentSpanId !== undefined) {
|
|
67
|
+
createTraceparent({ traceId: localTraceId, spanId: parentSpanId, traceFlags });
|
|
68
|
+
}
|
|
69
|
+
return freezeTraceContext({
|
|
70
|
+
parentSpanId,
|
|
71
|
+
sampled: sampledFromTraceFlags(traceFlags),
|
|
72
|
+
spanId: localSpanId,
|
|
73
|
+
traceFlags,
|
|
74
|
+
traceId: localTraceId
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function getActiveLogBrewTrace() {
|
|
79
|
+
return activeTraceScopes.length === 0 ? undefined : activeTraceScopes[activeTraceScopes.length - 1].trace;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function withLogBrewTrace(trace, callback) {
|
|
83
|
+
if (typeof callback !== "function") {
|
|
84
|
+
throw new SdkError("configuration_error", "withLogBrewTrace requires a callback");
|
|
85
|
+
}
|
|
86
|
+
const context = resolveTraceContext(trace) ?? createReactNativeTraceContext();
|
|
87
|
+
const scope = {
|
|
88
|
+
id: ++nextTraceScopeId,
|
|
89
|
+
trace: context
|
|
90
|
+
};
|
|
91
|
+
activeTraceScopes.push(scope);
|
|
92
|
+
try {
|
|
93
|
+
return callback(context);
|
|
94
|
+
} finally {
|
|
95
|
+
removeActiveTraceScope(scope.id);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function bindLogBrewTrace(trace, callback) {
|
|
100
|
+
if (typeof callback !== "function") {
|
|
101
|
+
throw new SdkError("configuration_error", "bindLogBrewTrace requires a callback");
|
|
102
|
+
}
|
|
103
|
+
const context = resolveTraceContext(trace) ?? createReactNativeTraceContext();
|
|
104
|
+
return function logBrewTracedCallback(...args) {
|
|
105
|
+
return withLogBrewTrace(context, () => callback(...args));
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function getReactNativeTraceMetadata(trace = getActiveLogBrewTrace()) {
|
|
110
|
+
const context = resolveTraceContext(trace);
|
|
111
|
+
if (!context) {
|
|
112
|
+
return {};
|
|
113
|
+
}
|
|
114
|
+
return compactMetadata({
|
|
115
|
+
parentSpanId: context.parentSpanId,
|
|
116
|
+
spanId: context.spanId,
|
|
117
|
+
traceFlags: context.traceFlags,
|
|
118
|
+
traceId: context.traceId,
|
|
119
|
+
traceSampled: context.sampled
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function createReactNativeSpanAttributes({
|
|
124
|
+
durationMs,
|
|
125
|
+
metadata = {},
|
|
126
|
+
name,
|
|
127
|
+
spanId,
|
|
128
|
+
status = "ok",
|
|
129
|
+
trace = getActiveLogBrewTrace()
|
|
130
|
+
} = {}) {
|
|
131
|
+
const context = resolveTraceContext(trace) ?? createReactNativeTraceContext();
|
|
132
|
+
return {
|
|
133
|
+
name,
|
|
134
|
+
traceId: context.traceId,
|
|
135
|
+
spanId: spanId ?? context.spanId,
|
|
136
|
+
status,
|
|
137
|
+
durationMs,
|
|
138
|
+
metadata: compactMetadata({
|
|
139
|
+
...metadata,
|
|
140
|
+
...getReactNativeTraceMetadata(context)
|
|
141
|
+
})
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function createReactNativeTraceHeaders(trace = getActiveLogBrewTrace()) {
|
|
146
|
+
const context = resolveTraceContext(trace) ?? createReactNativeTraceContext();
|
|
147
|
+
return {
|
|
148
|
+
traceparent: createTraceparent({
|
|
149
|
+
traceFlags: context.traceFlags,
|
|
150
|
+
traceId: context.traceId,
|
|
151
|
+
spanId: context.spanId
|
|
152
|
+
})
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
40
156
|
function createTraceparentFetch({
|
|
41
157
|
fetchImpl = defaultFetch(),
|
|
42
158
|
randomValues = defaultRandomValues,
|
|
159
|
+
trace,
|
|
43
160
|
traceFlags = "01",
|
|
44
161
|
traceparent,
|
|
45
162
|
traceparentFactory,
|
|
@@ -62,15 +179,7 @@ function createTraceparentFetch({
|
|
|
62
179
|
}
|
|
63
180
|
|
|
64
181
|
const requestInit = init ?? {};
|
|
65
|
-
const nextTraceparent = traceparentForRequest({
|
|
66
|
-
init,
|
|
67
|
-
input,
|
|
68
|
-
randomValues,
|
|
69
|
-
traceFlags,
|
|
70
|
-
traceparent,
|
|
71
|
-
traceparentFactory,
|
|
72
|
-
url
|
|
73
|
-
});
|
|
182
|
+
const nextTraceparent = traceparentForRequest({ init, input, randomValues, trace, traceFlags, traceparent, traceparentFactory, url });
|
|
74
183
|
const nextInit = {
|
|
75
184
|
...requestInit,
|
|
76
185
|
headers: headersWithTraceparent(requestHeaders(input, requestInit), nextTraceparent)
|
|
@@ -85,7 +194,7 @@ function shouldPropagateTraceparent(url, tracePropagationTargets = []) {
|
|
|
85
194
|
}
|
|
86
195
|
return tracePropagationTargets.some((target) => {
|
|
87
196
|
if (typeof target === "string") {
|
|
88
|
-
return url
|
|
197
|
+
return shouldPropagateToStringTarget(url, target);
|
|
89
198
|
}
|
|
90
199
|
if (target instanceof RegExp) {
|
|
91
200
|
target.lastIndex = 0;
|
|
@@ -117,6 +226,7 @@ function captureScreenView(client, screenName, {
|
|
|
117
226
|
status = "success",
|
|
118
227
|
platform,
|
|
119
228
|
appState,
|
|
229
|
+
trace,
|
|
120
230
|
metadata = {}
|
|
121
231
|
} = {}) {
|
|
122
232
|
requireClient(client);
|
|
@@ -127,7 +237,8 @@ function captureScreenView(client, screenName, {
|
|
|
127
237
|
metadata: {
|
|
128
238
|
...getReactNativeContext({ platform, appState }),
|
|
129
239
|
screen: screenName,
|
|
130
|
-
...metadata
|
|
240
|
+
...metadata,
|
|
241
|
+
...getReactNativeTraceMetadata(trace ?? getActiveLogBrewTrace())
|
|
131
242
|
}
|
|
132
243
|
});
|
|
133
244
|
}
|
|
@@ -137,6 +248,7 @@ function captureAppStateChange(client, state, {
|
|
|
137
248
|
timestamp = new Date().toISOString(),
|
|
138
249
|
platform,
|
|
139
250
|
appState,
|
|
251
|
+
trace,
|
|
140
252
|
metadata = {}
|
|
141
253
|
} = {}) {
|
|
142
254
|
requireClient(client);
|
|
@@ -147,12 +259,260 @@ function captureAppStateChange(client, state, {
|
|
|
147
259
|
metadata: {
|
|
148
260
|
...getReactNativeContext({ platform, appState }),
|
|
149
261
|
appState: state,
|
|
150
|
-
...metadata
|
|
262
|
+
...metadata,
|
|
263
|
+
...getReactNativeTraceMetadata(trace ?? getActiveLogBrewTrace())
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function createReactNativeActionEvent({
|
|
269
|
+
id,
|
|
270
|
+
idFactory = defaultActionEventId,
|
|
271
|
+
metadata = {},
|
|
272
|
+
name,
|
|
273
|
+
now = () => new Date().toISOString(),
|
|
274
|
+
platform,
|
|
275
|
+
appState,
|
|
276
|
+
screen,
|
|
277
|
+
sessionId,
|
|
278
|
+
status = "success",
|
|
279
|
+
timestamp,
|
|
280
|
+
trace,
|
|
281
|
+
traceId
|
|
282
|
+
} = {}) {
|
|
283
|
+
return {
|
|
284
|
+
id: id ?? idFactory({ name, screen }),
|
|
285
|
+
timestamp: timestamp ?? now(),
|
|
286
|
+
attributes: {
|
|
287
|
+
name,
|
|
288
|
+
status,
|
|
289
|
+
metadata: compactMetadata({
|
|
290
|
+
...getReactNativeContext({ platform, appState }),
|
|
291
|
+
source: "react-native.action",
|
|
292
|
+
screen,
|
|
293
|
+
sessionId,
|
|
294
|
+
traceId,
|
|
295
|
+
...metadata,
|
|
296
|
+
...getReactNativeTraceMetadata(trace ?? getActiveLogBrewTrace())
|
|
297
|
+
})
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function captureReactNativeAction(client, input = {}) {
|
|
303
|
+
requireClient(client);
|
|
304
|
+
const event = createReactNativeActionEvent(input);
|
|
305
|
+
client.action(event.id, event.timestamp, event.attributes);
|
|
306
|
+
return event;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function createReactNativeNetworkEvent({
|
|
310
|
+
durationMs,
|
|
311
|
+
id,
|
|
312
|
+
idFactory = defaultNetworkEventId,
|
|
313
|
+
metadata = {},
|
|
314
|
+
method,
|
|
315
|
+
name,
|
|
316
|
+
now = () => new Date().toISOString(),
|
|
317
|
+
platform,
|
|
318
|
+
appState,
|
|
319
|
+
routeTemplate,
|
|
320
|
+
screen,
|
|
321
|
+
sessionId,
|
|
322
|
+
status,
|
|
323
|
+
statusCode,
|
|
324
|
+
timestamp,
|
|
325
|
+
trace,
|
|
326
|
+
traceId
|
|
327
|
+
} = {}) {
|
|
328
|
+
const safeRouteTemplate = stripQueryAndHash(routeTemplate);
|
|
329
|
+
const safeMethod = method === undefined ? undefined : String(method).toUpperCase();
|
|
330
|
+
const actionName = name ?? [safeMethod, safeRouteTemplate].filter(Boolean).join(" ");
|
|
331
|
+
return {
|
|
332
|
+
id: id ?? idFactory({ method: safeMethod, routeTemplate: safeRouteTemplate, screen }),
|
|
333
|
+
timestamp: timestamp ?? now(),
|
|
334
|
+
attributes: {
|
|
335
|
+
name: actionName,
|
|
336
|
+
status: status ?? statusFromStatusCode(statusCode),
|
|
337
|
+
metadata: compactMetadata({
|
|
338
|
+
...getReactNativeContext({ platform, appState }),
|
|
339
|
+
source: "react-native.network",
|
|
340
|
+
durationMs,
|
|
341
|
+
method: safeMethod,
|
|
342
|
+
routeTemplate: safeRouteTemplate,
|
|
343
|
+
screen,
|
|
344
|
+
sessionId,
|
|
345
|
+
statusCode,
|
|
346
|
+
traceId,
|
|
347
|
+
...metadata,
|
|
348
|
+
...getReactNativeTraceMetadata(trace ?? getActiveLogBrewTrace())
|
|
349
|
+
})
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function captureReactNativeNetwork(client, input = {}) {
|
|
355
|
+
requireClient(client);
|
|
356
|
+
const event = createReactNativeNetworkEvent(input);
|
|
357
|
+
client.action(event.id, event.timestamp, event.attributes);
|
|
358
|
+
return event;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function createReactNativeNavigationSpanEvent({
|
|
362
|
+
actionType, durationMs, id, idFactory = defaultNavigationSpanEventId, includeRouteKey = false, metadata = {},
|
|
363
|
+
name, now = () => new Date().toISOString(), platform, appState, previousRouteKey, previousRouteName,
|
|
364
|
+
routeKey, routeName, routePath, screen, status = "ok", timestamp, trace
|
|
365
|
+
} = {}) {
|
|
366
|
+
const safeRoutePath = stripQueryAndHash(routePath);
|
|
367
|
+
const spanName = name ?? `navigation:${routeName ?? safeRoutePath ?? screen ?? "route"}`;
|
|
368
|
+
const context = resolveTraceContext(trace) ?? getActiveLogBrewTrace() ?? createReactNativeTraceContext();
|
|
369
|
+
return {
|
|
370
|
+
id: id ?? idFactory({ routeName, routePath: safeRoutePath, screen }),
|
|
371
|
+
timestamp: timestamp ?? now(),
|
|
372
|
+
attributes: createReactNativeSpanAttributes({
|
|
373
|
+
name: spanName,
|
|
374
|
+
status,
|
|
375
|
+
durationMs,
|
|
376
|
+
trace: context,
|
|
377
|
+
metadata: {
|
|
378
|
+
...getReactNativeContext({ platform, appState }),
|
|
379
|
+
source: "react-native.navigation",
|
|
380
|
+
actionType,
|
|
381
|
+
previousRouteName,
|
|
382
|
+
routeName,
|
|
383
|
+
routePath: safeRoutePath,
|
|
384
|
+
screen: screen ?? routeName,
|
|
385
|
+
...(includeRouteKey ? { previousRouteKey, routeKey } : {}),
|
|
386
|
+
...metadata
|
|
387
|
+
}
|
|
388
|
+
})
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function captureReactNativeNavigationSpan(client, input = {}) {
|
|
393
|
+
requireClient(client);
|
|
394
|
+
const event = createReactNativeNavigationSpanEvent(input);
|
|
395
|
+
client.span(event.id, event.timestamp, event.attributes);
|
|
396
|
+
return event;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function createReactNativeResourceSpanEvent({
|
|
400
|
+
durationMs, id, idFactory = defaultResourceSpanEventId, kind = "fetch", metadata = {}, method, name,
|
|
401
|
+
now = () => new Date().toISOString(), platform, appState, responseSizeBytes, routeTemplate, screen,
|
|
402
|
+
sessionId, status, statusCode, timestamp, trace
|
|
403
|
+
} = {}) {
|
|
404
|
+
const safeRouteTemplate = stripQueryAndHash(routeTemplate);
|
|
405
|
+
const safeMethod = method === undefined ? undefined : String(method).toUpperCase();
|
|
406
|
+
const defaultName = [safeMethod, safeRouteTemplate].filter(Boolean).join(" ");
|
|
407
|
+
const spanName = name ?? (defaultName || "mobile.resource");
|
|
408
|
+
const context = resolveTraceContext(trace) ?? getActiveLogBrewTrace() ?? createReactNativeTraceContext();
|
|
409
|
+
return {
|
|
410
|
+
id: id ?? idFactory({ method: safeMethod, routeTemplate: safeRouteTemplate, screen }),
|
|
411
|
+
timestamp: timestamp ?? now(),
|
|
412
|
+
attributes: createReactNativeSpanAttributes({
|
|
413
|
+
name: spanName,
|
|
414
|
+
status: status ?? spanStatusFromStatusCode(statusCode),
|
|
415
|
+
durationMs,
|
|
416
|
+
trace: context,
|
|
417
|
+
metadata: {
|
|
418
|
+
...getReactNativeContext({ platform, appState }),
|
|
419
|
+
source: "react-native.resource",
|
|
420
|
+
durationMs,
|
|
421
|
+
method: safeMethod,
|
|
422
|
+
resourceKind: kind,
|
|
423
|
+
responseSizeBytes,
|
|
424
|
+
routeTemplate: safeRouteTemplate,
|
|
425
|
+
screen,
|
|
426
|
+
sessionId,
|
|
427
|
+
statusCode,
|
|
428
|
+
...metadata
|
|
429
|
+
}
|
|
430
|
+
})
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
function captureReactNativeResourceSpan(client, input = {}) {
|
|
435
|
+
requireClient(client);
|
|
436
|
+
const event = createReactNativeResourceSpanEvent(input);
|
|
437
|
+
client.span(event.id, event.timestamp, event.attributes);
|
|
438
|
+
return event;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
function createReactNavigationSpanListener(client, navigationContainer, {
|
|
442
|
+
captureInitialRoute = false, includeRouteKey = false, metadata = {}, now = () => new Date().toISOString(),
|
|
443
|
+
nowMs = () => Date.now(), onError, platform, appState, trace
|
|
444
|
+
} = {}) {
|
|
445
|
+
requireClient(client);
|
|
446
|
+
const container = resolveNavigationContainer(navigationContainer);
|
|
447
|
+
if (!container || typeof container.addListener !== "function" || typeof container.getCurrentRoute !== "function") {
|
|
448
|
+
throw new SdkError("configuration_error", "createReactNavigationSpanListener requires a React Navigation container ref with addListener and getCurrentRoute");
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
let previousRoute = captureInitialRoute ? {} : routeSnapshot(container.getCurrentRoute());
|
|
452
|
+
let pendingNavigation;
|
|
453
|
+
const removers = [];
|
|
454
|
+
const captureCurrentRoute = () => {
|
|
455
|
+
try {
|
|
456
|
+
const route = routeSnapshot(container.getCurrentRoute());
|
|
457
|
+
if (!route.name && !route.path) {
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
const startedAtMs = pendingNavigation?.startedAtMs;
|
|
461
|
+
const durationMs = startedAtMs === undefined ? undefined : Math.max(0, nowMs() - startedAtMs);
|
|
462
|
+
captureReactNativeNavigationSpan(client, {
|
|
463
|
+
actionType: pendingNavigation?.actionType,
|
|
464
|
+
durationMs,
|
|
465
|
+
includeRouteKey,
|
|
466
|
+
metadata,
|
|
467
|
+
now,
|
|
468
|
+
platform,
|
|
469
|
+
appState,
|
|
470
|
+
previousRouteKey: previousRoute.key,
|
|
471
|
+
previousRouteName: previousRoute.name,
|
|
472
|
+
routeKey: route.key,
|
|
473
|
+
routeName: route.name,
|
|
474
|
+
routePath: route.path,
|
|
475
|
+
timestamp: pendingNavigation?.timestamp,
|
|
476
|
+
trace
|
|
477
|
+
});
|
|
478
|
+
previousRoute = route;
|
|
479
|
+
pendingNavigation = undefined;
|
|
480
|
+
} catch (error) {
|
|
481
|
+
if (typeof onError === "function") {
|
|
482
|
+
onError(error);
|
|
483
|
+
} else {
|
|
484
|
+
throw error;
|
|
485
|
+
}
|
|
151
486
|
}
|
|
487
|
+
};
|
|
488
|
+
|
|
489
|
+
const actionSubscription = safeNavigationListener(container, "__unsafe_action__", (event) => {
|
|
490
|
+
pendingNavigation = {
|
|
491
|
+
actionType: navigationActionType(event),
|
|
492
|
+
startedAtMs: nowMs(),
|
|
493
|
+
timestamp: now()
|
|
494
|
+
};
|
|
152
495
|
});
|
|
496
|
+
if (actionSubscription) {
|
|
497
|
+
removers.push(actionSubscription);
|
|
498
|
+
}
|
|
499
|
+
removers.push(addNavigationListener(container, "state", captureCurrentRoute));
|
|
500
|
+
|
|
501
|
+
if (captureInitialRoute) {
|
|
502
|
+
captureCurrentRoute();
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
return () => {
|
|
506
|
+
for (const remove of removers.splice(0).reverse()) {
|
|
507
|
+
remove();
|
|
508
|
+
}
|
|
509
|
+
};
|
|
153
510
|
}
|
|
154
511
|
|
|
155
512
|
function createReactNativeErrorEvent(error, {
|
|
513
|
+
debugIdMap,
|
|
514
|
+
environment,
|
|
515
|
+
fingerprint,
|
|
156
516
|
id,
|
|
157
517
|
idFactory = defaultErrorEventId,
|
|
158
518
|
includeStack = false,
|
|
@@ -161,27 +521,43 @@ function createReactNativeErrorEvent(error, {
|
|
|
161
521
|
now = () => new Date().toISOString(),
|
|
162
522
|
platform,
|
|
163
523
|
appState,
|
|
524
|
+
release,
|
|
525
|
+
runtime,
|
|
164
526
|
screen,
|
|
165
|
-
|
|
527
|
+
service,
|
|
528
|
+
timestamp,
|
|
529
|
+
trace
|
|
166
530
|
} = {}) {
|
|
167
|
-
const details = errorDetails(error
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
531
|
+
const details = errorDetails(error);
|
|
532
|
+
const traceContext = resolveTraceContext(trace ?? getActiveLogBrewTrace());
|
|
533
|
+
const attributes = createIssueAttributesFromError(error?.reason ?? error?.error ?? error, {
|
|
534
|
+
debugIdMap: debugIdMap === undefined ? runtimeReactNativeDebugIdMap() : debugIdMap,
|
|
535
|
+
environment,
|
|
536
|
+
fingerprint,
|
|
537
|
+
includeErrorStack: includeStack,
|
|
538
|
+
level,
|
|
539
|
+
metadata: {
|
|
540
|
+
...getReactNativeContext({ platform, appState }),
|
|
541
|
+
errorValueType: details.valueType,
|
|
542
|
+
screen,
|
|
543
|
+
...metadata
|
|
544
|
+
},
|
|
545
|
+
release,
|
|
546
|
+
runtime,
|
|
547
|
+
service,
|
|
172
548
|
source: "react-native.error",
|
|
173
|
-
|
|
174
|
-
...(includeStack ? { errorStack: details.stack } : {}),
|
|
175
|
-
...metadata
|
|
549
|
+
trace: traceContext
|
|
176
550
|
});
|
|
551
|
+
const stackFrames = sanitizeReactNativeIssueStackFrames(attributes.stackFrames);
|
|
177
552
|
return {
|
|
178
553
|
id: id ?? idFactory({ error, message: details.message, screen }),
|
|
179
554
|
timestamp: timestamp ?? now(),
|
|
180
555
|
attributes: {
|
|
556
|
+
...attributes,
|
|
557
|
+
...(stackFrames ? { stackFrames } : {}),
|
|
181
558
|
title: `React Native error: ${details.message}`,
|
|
182
|
-
level,
|
|
183
559
|
message: details.message,
|
|
184
|
-
metadata:
|
|
560
|
+
metadata: sanitizeReactNativeIssueMetadata(attributes.metadata, compactMetadata)
|
|
185
561
|
}
|
|
186
562
|
};
|
|
187
563
|
}
|
|
@@ -206,22 +582,17 @@ function createAppStateListener(client, appState, options = {}) {
|
|
|
206
582
|
});
|
|
207
583
|
});
|
|
208
584
|
|
|
209
|
-
|
|
210
|
-
return subscription;
|
|
211
|
-
}
|
|
212
|
-
if (subscription && typeof subscription.remove === "function") {
|
|
213
|
-
return () => subscription.remove();
|
|
214
|
-
}
|
|
215
|
-
return () => {};
|
|
585
|
+
return subscriptionRemover(subscription);
|
|
216
586
|
}
|
|
217
587
|
|
|
218
|
-
function LogBrewNativeProvider({ client, platform, appState, children }) {
|
|
588
|
+
function LogBrewNativeProvider({ client, platform, appState, trace, children }) {
|
|
219
589
|
requireClient(client);
|
|
220
590
|
const value = React.useMemo(() => ({
|
|
221
591
|
client,
|
|
222
592
|
platform,
|
|
223
|
-
appState
|
|
224
|
-
|
|
593
|
+
appState,
|
|
594
|
+
trace: resolveTraceContext(trace)
|
|
595
|
+
}), [appState, client, platform, trace]);
|
|
225
596
|
return React.createElement(LogBrewNativeContext.Provider, { value }, children);
|
|
226
597
|
}
|
|
227
598
|
|
|
@@ -234,33 +605,27 @@ function useLogBrewNative() {
|
|
|
234
605
|
}
|
|
235
606
|
|
|
236
607
|
function useLogBrewNativeActions() {
|
|
237
|
-
const { client, platform, appState } = useLogBrewNative();
|
|
608
|
+
const { client, platform, appState, trace } = useLogBrewNative();
|
|
609
|
+
const scoped = (options = {}) => ({ platform, appState, trace, ...options });
|
|
238
610
|
return {
|
|
239
611
|
release: client.release.bind(client),
|
|
240
612
|
environment: client.environment.bind(client),
|
|
241
|
-
issue: client.issue
|
|
242
|
-
log: client.log
|
|
613
|
+
issue: (id, timestamp, attributes) => client.issue(id, timestamp, attributesWithTrace(attributes, trace)),
|
|
614
|
+
log: (id, timestamp, attributes) => client.log(id, timestamp, attributesWithTrace(attributes, trace)),
|
|
243
615
|
span: client.span.bind(client),
|
|
244
|
-
action: client.action
|
|
616
|
+
action: (id, timestamp, attributes) => client.action(id, timestamp, attributesWithTrace(attributes, trace)),
|
|
245
617
|
flush: client.flush.bind(client),
|
|
246
618
|
shutdown: client.shutdown.bind(client),
|
|
247
619
|
previewJson: client.previewJson.bind(client),
|
|
248
620
|
pendingEvents: client.pendingEvents.bind(client),
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
}),
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
...options
|
|
258
|
-
}),
|
|
259
|
-
captureReactNativeError: (error, options = {}) => captureReactNativeError(client, error, {
|
|
260
|
-
platform,
|
|
261
|
-
appState,
|
|
262
|
-
...options
|
|
263
|
-
})
|
|
621
|
+
trace,
|
|
622
|
+
captureScreenView: (screenName, options = {}) => captureScreenView(client, screenName, scoped(options)),
|
|
623
|
+
captureAppStateChange: (state, options = {}) => captureAppStateChange(client, state, scoped(options)),
|
|
624
|
+
captureReactNativeAction: (input = {}) => captureReactNativeAction(client, scoped(input)),
|
|
625
|
+
captureReactNativeNetwork: (input = {}) => captureReactNativeNetwork(client, scoped(input)),
|
|
626
|
+
captureReactNativeNavigationSpan: (input = {}) => captureReactNativeNavigationSpan(client, scoped(input)),
|
|
627
|
+
captureReactNativeResourceSpan: (input = {}) => captureReactNativeResourceSpan(client, scoped(input)),
|
|
628
|
+
captureReactNativeError: (error, options = {}) => captureReactNativeError(client, error, scoped(options))
|
|
264
629
|
};
|
|
265
630
|
}
|
|
266
631
|
|
|
@@ -299,25 +664,26 @@ function compactMetadata(metadata) {
|
|
|
299
664
|
return compacted;
|
|
300
665
|
}
|
|
301
666
|
|
|
302
|
-
function
|
|
303
|
-
const
|
|
304
|
-
|
|
667
|
+
function attributesWithTrace(attributes, trace) {
|
|
668
|
+
const context = resolveTraceContext(trace) ?? getActiveLogBrewTrace();
|
|
669
|
+
if (!context) {
|
|
670
|
+
return attributes;
|
|
671
|
+
}
|
|
305
672
|
return {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
673
|
+
...attributes,
|
|
674
|
+
metadata: compactMetadata({
|
|
675
|
+
...(attributes?.metadata ?? {}),
|
|
676
|
+
...getReactNativeTraceMetadata(context)
|
|
677
|
+
})
|
|
310
678
|
};
|
|
311
679
|
}
|
|
312
680
|
|
|
313
|
-
function
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
}
|
|
320
|
-
return undefined;
|
|
681
|
+
function errorDetails(error) {
|
|
682
|
+
const candidate = error?.reason ?? error?.error ?? error;
|
|
683
|
+
return {
|
|
684
|
+
message: errorMessage(candidate),
|
|
685
|
+
valueType: candidate === null ? "null" : typeof candidate
|
|
686
|
+
};
|
|
321
687
|
}
|
|
322
688
|
|
|
323
689
|
function errorMessage(error) {
|
|
@@ -337,6 +703,22 @@ function defaultErrorEventId({ message, screen }) {
|
|
|
337
703
|
return `evt_native_error_${slugify(`${screen ?? "app"}_${message}`)}`;
|
|
338
704
|
}
|
|
339
705
|
|
|
706
|
+
function defaultActionEventId({ name, screen }) {
|
|
707
|
+
return `evt_native_action_${slugify(`${screen ?? "app"}_${name ?? "event"}`)}`;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
function defaultNetworkEventId({ method, routeTemplate, screen }) {
|
|
711
|
+
return `evt_native_network_${slugify([screen, method, routeTemplate].filter(Boolean).join("_") || "request")}`;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
function defaultNavigationSpanEventId({ routeName, routePath, screen }) {
|
|
715
|
+
return `evt_native_navigation_${slugify([screen, routeName, routePath].filter(Boolean).join("_") || "route")}`;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
function defaultResourceSpanEventId({ method, routeTemplate, screen }) {
|
|
719
|
+
return `evt_native_resource_${slugify([screen, method, routeTemplate].filter(Boolean).join("_") || "request")}`;
|
|
720
|
+
}
|
|
721
|
+
|
|
340
722
|
function defaultFetch() {
|
|
341
723
|
return typeof globalThis.fetch === "function" ? globalThis.fetch.bind(globalThis) : undefined;
|
|
342
724
|
}
|
|
@@ -395,6 +777,99 @@ function randomHex(length, randomValues) {
|
|
|
395
777
|
return bytes.map((value) => value.toString(16).padStart(2, "0")).join("");
|
|
396
778
|
}
|
|
397
779
|
|
|
780
|
+
function resolveTraceContext(trace) {
|
|
781
|
+
if (trace === undefined || trace === null) {
|
|
782
|
+
return undefined;
|
|
783
|
+
}
|
|
784
|
+
if (typeof trace === "string") {
|
|
785
|
+
return createReactNativeTraceContext({ traceparent: trace });
|
|
786
|
+
}
|
|
787
|
+
if (typeof trace === "object") {
|
|
788
|
+
const {
|
|
789
|
+
parentSpanId,
|
|
790
|
+
sampled,
|
|
791
|
+
spanId,
|
|
792
|
+
traceFlags = "01",
|
|
793
|
+
traceId
|
|
794
|
+
} = trace;
|
|
795
|
+
if (typeof traceId !== "string" || typeof spanId !== "string") {
|
|
796
|
+
throw new SdkError("validation_error", "trace context requires traceId and spanId");
|
|
797
|
+
}
|
|
798
|
+
createTraceparent({ traceId, spanId, traceFlags });
|
|
799
|
+
if (parentSpanId !== undefined) {
|
|
800
|
+
createTraceparent({ traceId, spanId: parentSpanId, traceFlags });
|
|
801
|
+
}
|
|
802
|
+
return freezeTraceContext({
|
|
803
|
+
parentSpanId,
|
|
804
|
+
sampled: sampled ?? sampledFromTraceFlags(traceFlags),
|
|
805
|
+
spanId,
|
|
806
|
+
traceFlags,
|
|
807
|
+
traceId
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
throw new SdkError("validation_error", "trace must be a trace context or traceparent string");
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
function freezeTraceContext({ parentSpanId, sampled, spanId, traceFlags, traceId }) {
|
|
814
|
+
const normalized = {
|
|
815
|
+
traceId: String(traceId).toLowerCase(),
|
|
816
|
+
spanId: String(spanId).toLowerCase(),
|
|
817
|
+
parentSpanId: parentSpanId === undefined ? undefined : String(parentSpanId).toLowerCase(),
|
|
818
|
+
traceFlags: String(traceFlags).toLowerCase(),
|
|
819
|
+
sampled: Boolean(sampled)
|
|
820
|
+
};
|
|
821
|
+
return Object.freeze(normalized);
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
function sampledFromTraceFlags(traceFlags) {
|
|
825
|
+
return (Number.parseInt(traceFlags, 16) & 1) === 1;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
function removeActiveTraceScope(scopeId) {
|
|
829
|
+
const index = activeTraceScopes.findIndex((scope) => scope.id === scopeId);
|
|
830
|
+
if (index >= 0) {
|
|
831
|
+
activeTraceScopes.splice(index, 1);
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
function shouldPropagateToStringTarget(url, target) {
|
|
836
|
+
const targetText = target.trim();
|
|
837
|
+
if (targetText === "") {
|
|
838
|
+
return false;
|
|
839
|
+
}
|
|
840
|
+
if (targetText.startsWith("/")) {
|
|
841
|
+
return url.startsWith(targetText);
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
const URLConstructor = globalThis.URL;
|
|
845
|
+
if (typeof URLConstructor === "function") {
|
|
846
|
+
try {
|
|
847
|
+
const targetUrl = new URLConstructor(targetText);
|
|
848
|
+
if (!hasUrlScheme(url)) {
|
|
849
|
+
return false;
|
|
850
|
+
}
|
|
851
|
+
const requestUrl = new URLConstructor(url, targetUrl.origin);
|
|
852
|
+
if (requestUrl.origin !== targetUrl.origin) {
|
|
853
|
+
return false;
|
|
854
|
+
}
|
|
855
|
+
const targetPath = targetUrl.pathname || "/";
|
|
856
|
+
return requestUrl.pathname === targetPath || requestUrl.pathname.startsWith(pathPrefix(targetPath));
|
|
857
|
+
} catch {
|
|
858
|
+
return url.startsWith(targetText);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
return url.startsWith(targetText);
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
function pathPrefix(pathname) {
|
|
866
|
+
return pathname.endsWith("/") ? pathname : `${pathname}/`;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
function hasUrlScheme(url) {
|
|
870
|
+
return /^[a-z][a-z0-9+.-]*:/iu.test(url);
|
|
871
|
+
}
|
|
872
|
+
|
|
398
873
|
function requestHeaders(input, init) {
|
|
399
874
|
if (init && init.headers !== undefined) {
|
|
400
875
|
return init.headers;
|
|
@@ -417,57 +892,96 @@ function requestUrl(input) {
|
|
|
417
892
|
}
|
|
418
893
|
|
|
419
894
|
function slugify(value) {
|
|
420
|
-
return value
|
|
895
|
+
return String(value)
|
|
421
896
|
.toLowerCase()
|
|
422
897
|
.replace(/[^a-z0-9]+/g, "_")
|
|
423
898
|
.replace(/^_+|_+$/g, "") || "event";
|
|
424
899
|
}
|
|
425
900
|
|
|
901
|
+
function statusFromStatusCode(statusCode) {
|
|
902
|
+
if (typeof statusCode === "number" && Number.isFinite(statusCode) && statusCode >= 400) {
|
|
903
|
+
return "failure";
|
|
904
|
+
}
|
|
905
|
+
return "success";
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
function spanStatusFromStatusCode(statusCode) {
|
|
909
|
+
if (typeof statusCode === "number" && Number.isFinite(statusCode) && statusCode >= 400) {
|
|
910
|
+
return "error";
|
|
911
|
+
}
|
|
912
|
+
return "ok";
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
function stripQueryAndHash(value) {
|
|
916
|
+
if (value === undefined || value === null) {
|
|
917
|
+
return undefined;
|
|
918
|
+
}
|
|
919
|
+
return String(value).split(/[?#]/u, 1)[0];
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
function resolveNavigationContainer(navigationContainer) {
|
|
923
|
+
if (navigationContainer && typeof navigationContainer === "object" && "current" in navigationContainer) {
|
|
924
|
+
return navigationContainer.current;
|
|
925
|
+
}
|
|
926
|
+
return navigationContainer;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
function addNavigationListener(container, eventName, listener) {
|
|
930
|
+
const subscription = container.addListener(eventName, listener);
|
|
931
|
+
return subscriptionRemover(subscription);
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
function subscriptionRemover(subscription) {
|
|
935
|
+
if (typeof subscription === "function") {
|
|
936
|
+
return subscription;
|
|
937
|
+
}
|
|
938
|
+
if (subscription && typeof subscription.remove === "function") {
|
|
939
|
+
return () => subscription.remove();
|
|
940
|
+
}
|
|
941
|
+
return () => {};
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
function safeNavigationListener(container, eventName, listener) {
|
|
945
|
+
try {
|
|
946
|
+
return addNavigationListener(container, eventName, listener);
|
|
947
|
+
} catch {
|
|
948
|
+
return undefined;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
function routeSnapshot(route) {
|
|
953
|
+
return {
|
|
954
|
+
key: normalizeMetadataValue(route?.key),
|
|
955
|
+
name: typeof route?.name === "string" && route.name.trim() !== "" ? route.name : undefined,
|
|
956
|
+
path: stripQueryAndHash(route?.path)
|
|
957
|
+
};
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
function navigationActionType(event) {
|
|
961
|
+
const action = event?.data?.action ?? event?.action ?? event;
|
|
962
|
+
return typeof action?.type === "string" && action.type.trim() !== "" ? action.type : undefined;
|
|
963
|
+
}
|
|
964
|
+
|
|
426
965
|
function traceparentForRequest({
|
|
427
|
-
init,
|
|
428
|
-
input,
|
|
429
|
-
randomValues,
|
|
430
|
-
traceFlags,
|
|
431
|
-
traceparent,
|
|
432
|
-
traceparentFactory,
|
|
433
|
-
url
|
|
966
|
+
init, input, randomValues, trace, traceFlags, traceparent, traceparentFactory, url
|
|
434
967
|
}) {
|
|
968
|
+
const context = resolveTraceContext(trace) ?? getActiveLogBrewTrace();
|
|
435
969
|
const nextTraceparent = typeof traceparentFactory === "function"
|
|
436
970
|
? traceparentFactory({ init, input, url })
|
|
437
|
-
: traceparent ?? createReactNativeTraceparent({ randomValues, traceFlags });
|
|
971
|
+
: traceparent ?? (context ? createReactNativeTraceHeaders(context).traceparent : createReactNativeTraceparent({ randomValues, traceFlags }));
|
|
438
972
|
parseTraceparent(nextTraceparent);
|
|
439
973
|
return nextTraceparent;
|
|
440
974
|
}
|
|
441
975
|
|
|
442
976
|
const defaultExport = {
|
|
443
|
-
LogBrewNativeProvider,
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
createTraceparentFetch,
|
|
452
|
-
getReactNativeContext,
|
|
453
|
-
shouldPropagateTraceparent,
|
|
454
|
-
useLogBrewNative,
|
|
455
|
-
useLogBrewNativeActions
|
|
977
|
+
LogBrewNativeProvider, captureAppStateChange, captureReactNativeAction, captureReactNativeError,
|
|
978
|
+
captureReactNativeNetwork, captureReactNativeNavigationSpan, captureReactNativeResourceSpan, captureScreenView,
|
|
979
|
+
bindLogBrewTrace, createAppStateListener, createLogBrewReactNativeClient, createReactNavigationSpanListener,
|
|
980
|
+
createReactNativeSpanAttributes, createReactNativeTraceContext, createReactNativeTraceHeaders, createReactNativeActionEvent,
|
|
981
|
+
createReactNativeErrorEvent, createReactNativeNetworkEvent, createReactNativeNavigationSpanEvent,
|
|
982
|
+
createReactNativeResourceSpanEvent, createReactNativeTraceparent, createTraceparentFetch, getActiveLogBrewTrace,
|
|
983
|
+
getReactNativeContext, getReactNativeTraceMetadata, shouldPropagateTraceparent, useLogBrewNative,
|
|
984
|
+
useLogBrewNativeActions, withLogBrewTrace
|
|
456
985
|
};
|
|
457
986
|
|
|
458
|
-
module.exports = {
|
|
459
|
-
LogBrewNativeProvider,
|
|
460
|
-
captureAppStateChange,
|
|
461
|
-
captureReactNativeError,
|
|
462
|
-
captureScreenView,
|
|
463
|
-
createAppStateListener,
|
|
464
|
-
createLogBrewReactNativeClient,
|
|
465
|
-
createReactNativeErrorEvent,
|
|
466
|
-
createReactNativeTraceparent,
|
|
467
|
-
createTraceparentFetch,
|
|
468
|
-
default: defaultExport,
|
|
469
|
-
getReactNativeContext,
|
|
470
|
-
shouldPropagateTraceparent,
|
|
471
|
-
useLogBrewNative,
|
|
472
|
-
useLogBrewNativeActions
|
|
473
|
-
};
|
|
987
|
+
module.exports = { ...defaultExport, default: defaultExport };
|