@dreamhorizonorg/pulse-react-native 0.0.2 → 0.0.4
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/android/build.gradle +1 -1
- package/android/src/main/java/com/pulsereactnativeotel/Pulse.kt +6 -0
- package/android/src/main/java/com/pulsereactnativeotel/PulseReactNativeOtelModule.kt +45 -24
- package/ios/PulseReactNativeOtel.mm +124 -63
- package/lib/module/NativePulseReactNativeOtel.js.map +1 -1
- package/lib/module/config.js +79 -19
- package/lib/module/config.js.map +1 -1
- package/lib/module/errorBoundary.js +4 -1
- package/lib/module/errorBoundary.js.map +1 -1
- package/lib/module/errorHandler.js +5 -1
- package/lib/module/errorHandler.js.map +1 -1
- package/lib/module/events.js +2 -2
- package/lib/module/events.js.map +1 -1
- package/lib/module/index.js +2 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/navigation/index.js +21 -3
- package/lib/module/navigation/index.js.map +1 -1
- package/lib/module/navigation/navigation.interface.js +6 -0
- package/lib/module/navigation/navigation.interface.js.map +1 -1
- package/lib/module/navigation/screen-interactive.js +4 -0
- package/lib/module/navigation/screen-interactive.js.map +1 -1
- package/lib/module/navigation/screen-load.js +1 -2
- package/lib/module/navigation/screen-load.js.map +1 -1
- package/lib/module/navigation/useNavigationTracking.js +4 -3
- package/lib/module/navigation/useNavigationTracking.js.map +1 -1
- package/lib/module/network-interceptor/header-helper.js +24 -0
- package/lib/module/network-interceptor/header-helper.js.map +1 -0
- package/lib/module/network-interceptor/initialization.js +31 -2
- package/lib/module/network-interceptor/initialization.js.map +1 -1
- package/lib/module/network-interceptor/request-tracker-xhr.js +74 -5
- package/lib/module/network-interceptor/request-tracker-xhr.js.map +1 -1
- package/lib/module/network-interceptor/span-helpers.js +15 -3
- package/lib/module/network-interceptor/span-helpers.js.map +1 -1
- package/lib/module/pulse.constants.js +11 -6
- package/lib/module/pulse.constants.js.map +1 -1
- package/lib/module/trace.js +16 -10
- package/lib/module/trace.js.map +1 -1
- package/lib/module/user.js +4 -3
- package/lib/module/user.js.map +1 -1
- package/lib/typescript/plugin/src/types.d.ts +6 -0
- package/lib/typescript/plugin/src/types.d.ts.map +1 -1
- package/lib/typescript/plugin/src/utils.d.ts +2 -0
- package/lib/typescript/plugin/src/utils.d.ts.map +1 -1
- package/lib/typescript/plugin/src/withAndroidPulse.d.ts.map +1 -1
- package/lib/typescript/src/NativePulseReactNativeOtel.d.ts +10 -1
- package/lib/typescript/src/NativePulseReactNativeOtel.d.ts.map +1 -1
- package/lib/typescript/src/config.d.ts +11 -7
- package/lib/typescript/src/config.d.ts.map +1 -1
- package/lib/typescript/src/errorBoundary.d.ts.map +1 -1
- package/lib/typescript/src/errorHandler.d.ts +1 -0
- package/lib/typescript/src/errorHandler.d.ts.map +1 -1
- package/lib/typescript/src/events.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +3 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/navigation/index.d.ts +2 -0
- package/lib/typescript/src/navigation/index.d.ts.map +1 -1
- package/lib/typescript/src/navigation/navigation.interface.d.ts +1 -0
- package/lib/typescript/src/navigation/navigation.interface.d.ts.map +1 -1
- package/lib/typescript/src/navigation/screen-interactive.d.ts.map +1 -1
- package/lib/typescript/src/navigation/screen-load.d.ts.map +1 -1
- package/lib/typescript/src/navigation/useNavigationTracking.d.ts +1 -1
- package/lib/typescript/src/navigation/useNavigationTracking.d.ts.map +1 -1
- package/lib/typescript/src/network-interceptor/header-helper.d.ts +15 -0
- package/lib/typescript/src/network-interceptor/header-helper.d.ts.map +1 -0
- package/lib/typescript/src/network-interceptor/initialization.d.ts +5 -1
- package/lib/typescript/src/network-interceptor/initialization.d.ts.map +1 -1
- package/lib/typescript/src/network-interceptor/network.interface.d.ts +3 -0
- package/lib/typescript/src/network-interceptor/network.interface.d.ts.map +1 -1
- package/lib/typescript/src/network-interceptor/request-tracker-xhr.d.ts +5 -1
- package/lib/typescript/src/network-interceptor/request-tracker-xhr.d.ts.map +1 -1
- package/lib/typescript/src/network-interceptor/span-helpers.d.ts.map +1 -1
- package/lib/typescript/src/pulse.constants.d.ts +13 -5
- package/lib/typescript/src/pulse.constants.d.ts.map +1 -1
- package/lib/typescript/src/pulse.interface.d.ts +1 -1
- package/lib/typescript/src/pulse.interface.d.ts.map +1 -1
- package/lib/typescript/src/trace.d.ts.map +1 -1
- package/lib/typescript/src/user.d.ts.map +1 -1
- package/package.json +1 -1
- package/plugin/build/types.d.ts +6 -0
- package/plugin/build/utils.d.ts +2 -0
- package/plugin/build/utils.js +6 -2
- package/plugin/build/withAndroidPulse.js +3 -1
- package/src/NativePulseReactNativeOtel.ts +11 -1
- package/src/config.ts +120 -28
- package/src/errorBoundary.tsx +4 -1
- package/src/errorHandler.ts +6 -1
- package/src/events.ts +6 -2
- package/src/index.tsx +3 -2
- package/src/navigation/index.ts +49 -7
- package/src/navigation/navigation.interface.ts +7 -0
- package/src/navigation/screen-interactive.ts +4 -0
- package/src/navigation/screen-load.ts +1 -7
- package/src/navigation/useNavigationTracking.ts +13 -4
- package/src/network-interceptor/header-helper.ts +26 -0
- package/src/network-interceptor/initialization.ts +36 -2
- package/src/network-interceptor/network.interface.ts +3 -0
- package/src/network-interceptor/request-tracker-xhr.ts +106 -5
- package/src/network-interceptor/span-helpers.ts +23 -3
- package/src/pulse.constants.ts +19 -5
- package/src/pulse.interface.ts +1 -1
- package/src/trace.ts +17 -10
- package/src/user.ts +4 -3
|
@@ -6,6 +6,8 @@ import { RequestTracker } from './request-tracker';
|
|
|
6
6
|
import { getAbsoluteUrl } from '../utility';
|
|
7
7
|
import type { Span } from '../index';
|
|
8
8
|
import { createNetworkSpan, completeNetworkSpan } from './span-helpers';
|
|
9
|
+
import { getHeaderConfig } from './initialization';
|
|
10
|
+
import { shouldCaptureHeader } from './header-helper';
|
|
9
11
|
|
|
10
12
|
interface RequestData {
|
|
11
13
|
method: string;
|
|
@@ -16,12 +18,17 @@ type ReadyStateChangeHandler = (this: XMLHttpRequest, ev: Event) => any;
|
|
|
16
18
|
|
|
17
19
|
let isXHRIntercepted = false;
|
|
18
20
|
|
|
21
|
+
export interface XmlHttpRequestTrackerResult {
|
|
22
|
+
requestTracker: RequestTracker;
|
|
23
|
+
uninstall: () => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
19
26
|
function createXmlHttpRequestTracker(
|
|
20
27
|
xhr: typeof XMLHttpRequest
|
|
21
|
-
):
|
|
28
|
+
): XmlHttpRequestTrackerResult {
|
|
22
29
|
if (isXHRIntercepted) {
|
|
23
30
|
console.warn('[Pulse] XMLHttpRequest already intercepted');
|
|
24
|
-
return new RequestTracker();
|
|
31
|
+
return { requestTracker: new RequestTracker(), uninstall: () => {} };
|
|
25
32
|
}
|
|
26
33
|
|
|
27
34
|
const requestTracker = new RequestTracker();
|
|
@@ -48,6 +55,28 @@ function createXmlHttpRequestTracker(
|
|
|
48
55
|
};
|
|
49
56
|
isXHRIntercepted = true;
|
|
50
57
|
|
|
58
|
+
// Store request headers before send
|
|
59
|
+
const requestHeadersMap = new WeakMap<
|
|
60
|
+
XMLHttpRequest,
|
|
61
|
+
Record<string, string>
|
|
62
|
+
>();
|
|
63
|
+
const originalSetRequestHeader = xhr.prototype.setRequestHeader;
|
|
64
|
+
xhr.prototype.setRequestHeader = function setRequestHeader(
|
|
65
|
+
name: string,
|
|
66
|
+
value: string
|
|
67
|
+
): void {
|
|
68
|
+
const headerConfig = getHeaderConfig();
|
|
69
|
+
const requestHeadersList = headerConfig.requestHeaders ?? [];
|
|
70
|
+
if (
|
|
71
|
+
requestHeadersList.length > 0 &&
|
|
72
|
+
shouldCaptureHeader(name, requestHeadersList)
|
|
73
|
+
) {
|
|
74
|
+
const existing = requestHeadersMap.get(this) || {};
|
|
75
|
+
requestHeadersMap.set(this, { ...existing, [name]: value });
|
|
76
|
+
}
|
|
77
|
+
originalSetRequestHeader.call(this, name, value);
|
|
78
|
+
};
|
|
79
|
+
|
|
51
80
|
const originalSend = xhr.prototype.send;
|
|
52
81
|
xhr.prototype.send = function send(
|
|
53
82
|
body?: Document | XMLHttpRequestBodyInit | null
|
|
@@ -58,10 +87,28 @@ function createXmlHttpRequestTracker(
|
|
|
58
87
|
if (existingHandler)
|
|
59
88
|
this.removeEventListener('readystatechange', existingHandler);
|
|
60
89
|
|
|
90
|
+
// Capture request headers
|
|
91
|
+
const headerConfig = getHeaderConfig();
|
|
92
|
+
const capturedRequestHeaders = requestHeadersMap.get(this);
|
|
93
|
+
const requestHeadersList = headerConfig.requestHeaders ?? [];
|
|
94
|
+
const filteredRequestHeaders: Record<string, string> | undefined =
|
|
95
|
+
capturedRequestHeaders && requestHeadersList.length > 0
|
|
96
|
+
? Object.fromEntries(
|
|
97
|
+
Object.entries(capturedRequestHeaders).filter(([name]) =>
|
|
98
|
+
shouldCaptureHeader(name, requestHeadersList)
|
|
99
|
+
)
|
|
100
|
+
)
|
|
101
|
+
: undefined;
|
|
102
|
+
|
|
61
103
|
const startContext: RequestStartContext = {
|
|
62
104
|
type: 'xmlhttprequest',
|
|
63
105
|
method: requestData.method,
|
|
64
106
|
url: requestData.url,
|
|
107
|
+
requestHeaders:
|
|
108
|
+
filteredRequestHeaders &&
|
|
109
|
+
Object.keys(filteredRequestHeaders).length > 0
|
|
110
|
+
? filteredRequestHeaders
|
|
111
|
+
: undefined,
|
|
65
112
|
};
|
|
66
113
|
|
|
67
114
|
this.setRequestHeader('X-Pulse-RN-Tracked', 'true');
|
|
@@ -74,13 +121,56 @@ function createXmlHttpRequestTracker(
|
|
|
74
121
|
if (this.readyState === xhr.DONE && onRequestEnd) {
|
|
75
122
|
const activeSpan = trackedSpans.get(this);
|
|
76
123
|
|
|
124
|
+
// Capture response headers
|
|
125
|
+
const responseHeaderConfig = getHeaderConfig();
|
|
126
|
+
const capturedResponseHeaders: Record<string, string> = {};
|
|
127
|
+
const responseHeadersList =
|
|
128
|
+
responseHeaderConfig.responseHeaders ?? [];
|
|
129
|
+
if (responseHeadersList.length > 0) {
|
|
130
|
+
try {
|
|
131
|
+
const allHeaders = this.getAllResponseHeaders();
|
|
132
|
+
if (allHeaders) {
|
|
133
|
+
const headerLines = allHeaders.trim().split(/[\r\n]+/);
|
|
134
|
+
for (const line of headerLines) {
|
|
135
|
+
const parts = line.split(': ');
|
|
136
|
+
if (parts.length === 2) {
|
|
137
|
+
const [name, value] = parts;
|
|
138
|
+
if (
|
|
139
|
+
name &&
|
|
140
|
+
value &&
|
|
141
|
+
shouldCaptureHeader(name, responseHeadersList)
|
|
142
|
+
) {
|
|
143
|
+
capturedResponseHeaders[name] = value;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
} catch (e) {
|
|
149
|
+
// Headers may not be available in some cases (CORS, etc.)
|
|
150
|
+
console.debug('[Pulse] Could not read response headers:', e);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
77
154
|
// Determine request outcome based on status code
|
|
78
155
|
let endContext: RequestEndContext;
|
|
79
156
|
|
|
157
|
+
const responseHeaders =
|
|
158
|
+
Object.keys(capturedResponseHeaders).length > 0
|
|
159
|
+
? capturedResponseHeaders
|
|
160
|
+
: undefined;
|
|
161
|
+
|
|
80
162
|
if (this.status <= 0 || this.status >= 400) {
|
|
81
|
-
endContext = {
|
|
163
|
+
endContext = {
|
|
164
|
+
state: 'error',
|
|
165
|
+
status: this.status,
|
|
166
|
+
responseHeaders,
|
|
167
|
+
};
|
|
82
168
|
} else {
|
|
83
|
-
endContext = {
|
|
169
|
+
endContext = {
|
|
170
|
+
state: 'success',
|
|
171
|
+
status: this.status,
|
|
172
|
+
responseHeaders,
|
|
173
|
+
};
|
|
84
174
|
}
|
|
85
175
|
|
|
86
176
|
if (activeSpan) {
|
|
@@ -93,6 +183,9 @@ function createXmlHttpRequestTracker(
|
|
|
93
183
|
trackedSpans.delete(this);
|
|
94
184
|
}
|
|
95
185
|
|
|
186
|
+
// Clean up
|
|
187
|
+
requestHeadersMap.delete(this);
|
|
188
|
+
|
|
96
189
|
onRequestEnd(endContext);
|
|
97
190
|
}
|
|
98
191
|
};
|
|
@@ -104,7 +197,15 @@ function createXmlHttpRequestTracker(
|
|
|
104
197
|
originalSend.call(this, body);
|
|
105
198
|
};
|
|
106
199
|
|
|
107
|
-
|
|
200
|
+
const uninstall = (): void => {
|
|
201
|
+
if (!isXHRIntercepted) return;
|
|
202
|
+
xhr.prototype.open = originalOpen;
|
|
203
|
+
xhr.prototype.setRequestHeader = originalSetRequestHeader;
|
|
204
|
+
xhr.prototype.send = originalSend;
|
|
205
|
+
isXHRIntercepted = false;
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
return { requestTracker, uninstall };
|
|
108
209
|
}
|
|
109
210
|
|
|
110
211
|
export default createXmlHttpRequestTracker;
|
|
@@ -8,7 +8,8 @@ import { Pulse, SpanStatusCode } from '../index';
|
|
|
8
8
|
import type { PulseAttributes } from '../pulse.interface';
|
|
9
9
|
import { extractHttpAttributes } from './url-helper';
|
|
10
10
|
import { updateAttributesWithGraphQLData } from './graphql-helper';
|
|
11
|
-
import { ATTRIBUTE_KEYS,
|
|
11
|
+
import { ATTRIBUTE_KEYS, PULSE_TYPES } from '../pulse.constants';
|
|
12
|
+
import { normalizeHeaderName } from './header-helper';
|
|
12
13
|
|
|
13
14
|
export function setNetworkSpanAttributes(
|
|
14
15
|
span: Span,
|
|
@@ -19,7 +20,7 @@ export function setNetworkSpanAttributes(
|
|
|
19
20
|
let attributes: PulseAttributes = {
|
|
20
21
|
[ATTRIBUTE_KEYS.HTTP_METHOD]: method,
|
|
21
22
|
[ATTRIBUTE_KEYS.HTTP_URL]: startContext.url,
|
|
22
|
-
[ATTRIBUTE_KEYS.PULSE_TYPE]:
|
|
23
|
+
[ATTRIBUTE_KEYS.PULSE_TYPE]: `${PULSE_TYPES.NETWORK}.${endContext.status ?? 0}`,
|
|
23
24
|
[ATTRIBUTE_KEYS.HTTP_REQUEST_TYPE]: startContext.type,
|
|
24
25
|
[ATTRIBUTE_KEYS.PLATFORM]: Platform.OS,
|
|
25
26
|
};
|
|
@@ -43,6 +44,26 @@ export function setNetworkSpanAttributes(
|
|
|
43
44
|
span.recordException(endContext.error, attributes);
|
|
44
45
|
}
|
|
45
46
|
|
|
47
|
+
if (startContext.requestHeaders) {
|
|
48
|
+
for (const [headerName, headerValue] of Object.entries(
|
|
49
|
+
startContext.requestHeaders
|
|
50
|
+
)) {
|
|
51
|
+
const normalizedName = normalizeHeaderName(headerName);
|
|
52
|
+
attributes[`${ATTRIBUTE_KEYS.HTTP_REQUEST_HEADER}.${normalizedName}`] =
|
|
53
|
+
headerValue;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (endContext.responseHeaders) {
|
|
58
|
+
for (const [headerName, headerValue] of Object.entries(
|
|
59
|
+
endContext.responseHeaders
|
|
60
|
+
)) {
|
|
61
|
+
const normalizedName = normalizeHeaderName(headerName);
|
|
62
|
+
attributes[`${ATTRIBUTE_KEYS.HTTP_RESPONSE_HEADER}.${normalizedName}`] =
|
|
63
|
+
headerValue;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
46
67
|
span.setAttributes(attributes);
|
|
47
68
|
return attributes;
|
|
48
69
|
}
|
|
@@ -58,7 +79,6 @@ export function createNetworkSpan(
|
|
|
58
79
|
let baseAttributes: PulseAttributes = {
|
|
59
80
|
[ATTRIBUTE_KEYS.HTTP_METHOD]: method,
|
|
60
81
|
[ATTRIBUTE_KEYS.HTTP_URL]: startContext.url,
|
|
61
|
-
[ATTRIBUTE_KEYS.PULSE_TYPE]: PHASE_VALUES.NETWORK,
|
|
62
82
|
[ATTRIBUTE_KEYS.HTTP_REQUEST_TYPE]: interceptorType,
|
|
63
83
|
};
|
|
64
84
|
|
package/src/pulse.constants.ts
CHANGED
|
@@ -12,7 +12,6 @@ export enum ATTRIBUTE_KEYS {
|
|
|
12
12
|
PULSE_TYPE = 'pulse.type',
|
|
13
13
|
SCREEN_NAME = 'screen.name',
|
|
14
14
|
ROUTE_KEY = 'routeKey',
|
|
15
|
-
PHASE = 'phase',
|
|
16
15
|
LAST_SCREEN_NAME = 'last.screen.name',
|
|
17
16
|
ROUTE_HAS_BEEN_SEEN = 'routeHasBeenSeen',
|
|
18
17
|
PLATFORM = 'platform',
|
|
@@ -22,6 +21,8 @@ export enum ATTRIBUTE_KEYS {
|
|
|
22
21
|
HTTP_URL = 'http.url',
|
|
23
22
|
HTTP_STATUS_CODE = 'http.status_code',
|
|
24
23
|
HTTP_REQUEST_TYPE = 'http.request.type',
|
|
24
|
+
HTTP_REQUEST_HEADER = 'http.request.header',
|
|
25
|
+
HTTP_RESPONSE_HEADER = 'http.response.header',
|
|
25
26
|
ERROR_MESSAGE = 'error.message',
|
|
26
27
|
ERROR_STACK = 'error.stack',
|
|
27
28
|
}
|
|
@@ -30,9 +31,22 @@ export enum PULSE_TYPES {
|
|
|
30
31
|
SCREEN_SESSION = 'screen_session',
|
|
31
32
|
SCREEN_LOAD = 'screen_load',
|
|
32
33
|
SCREEN_INTERACTIVE = 'screen_interactive',
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export enum PHASE_VALUES {
|
|
36
|
-
START = 'start',
|
|
37
34
|
NETWORK = 'network',
|
|
38
35
|
}
|
|
36
|
+
|
|
37
|
+
export const PULSE_FEATURE_NAMES = {
|
|
38
|
+
RN_SCREEN_LOAD: 'rn_screen_load',
|
|
39
|
+
SCREEN_SESSION: 'screen_session',
|
|
40
|
+
RN_SCREEN_INTERACTIVE: 'rn_screen_interactive',
|
|
41
|
+
NETWORK_INSTRUMENTATION: 'network_instrumentation',
|
|
42
|
+
CUSTOM_EVENTS: 'custom_events',
|
|
43
|
+
JS_CRASH: 'js_crash',
|
|
44
|
+
} as const;
|
|
45
|
+
|
|
46
|
+
export type PulseFeatureName =
|
|
47
|
+
(typeof PULSE_FEATURE_NAMES)[keyof typeof PULSE_FEATURE_NAMES];
|
|
48
|
+
|
|
49
|
+
export type NavigationFeatureName =
|
|
50
|
+
| typeof PULSE_FEATURE_NAMES.SCREEN_SESSION
|
|
51
|
+
| typeof PULSE_FEATURE_NAMES.RN_SCREEN_LOAD
|
|
52
|
+
| typeof PULSE_FEATURE_NAMES.RN_SCREEN_INTERACTIVE;
|
package/src/pulse.interface.ts
CHANGED
package/src/trace.ts
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import PulseReactNativeOtel from './NativePulseReactNativeOtel';
|
|
2
|
+
import { getIsShutdown, getIsStarted } from './config';
|
|
2
3
|
import { isSupportedPlatform } from './initialization';
|
|
3
4
|
import { mergeWithGlobalAttributes } from './globalAttributes';
|
|
4
5
|
import { extractErrorDetails } from './utility';
|
|
5
6
|
import type { PulseAttributes } from './pulse.interface';
|
|
6
7
|
|
|
8
|
+
const noopSpan: Span = {
|
|
9
|
+
end: (_statusCode?: SpanStatusCode) => {},
|
|
10
|
+
addEvent: (_eventName: string, _eventAttributes?: PulseAttributes) => {},
|
|
11
|
+
setAttributes: (_attributes?: PulseAttributes) => {},
|
|
12
|
+
recordException: (_error: Error, _attributes?: PulseAttributes) => {},
|
|
13
|
+
spanId: undefined,
|
|
14
|
+
};
|
|
15
|
+
|
|
7
16
|
/**
|
|
8
17
|
* Options for starting a span.
|
|
9
18
|
* @param attributes - Attributes to set on the span.
|
|
@@ -30,14 +39,8 @@ export type Span = {
|
|
|
30
39
|
};
|
|
31
40
|
|
|
32
41
|
export function startSpan(name: string, options?: SpanOptions): Span {
|
|
33
|
-
if (!isSupportedPlatform()) {
|
|
34
|
-
return
|
|
35
|
-
end: (_statusCode?: SpanStatusCode) => {},
|
|
36
|
-
addEvent: (_eventName: string, _eventAttributes?: PulseAttributes) => {},
|
|
37
|
-
setAttributes: (_attributes?: PulseAttributes) => {},
|
|
38
|
-
recordException: (_error: Error, _attributes?: PulseAttributes) => {},
|
|
39
|
-
spanId: undefined,
|
|
40
|
-
};
|
|
42
|
+
if (!isSupportedPlatform() || !getIsStarted() || getIsShutdown()) {
|
|
43
|
+
return noopSpan;
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
const mergedAttributes = mergeWithGlobalAttributes(options?.attributes || {});
|
|
@@ -69,7 +72,7 @@ export function trackSpan<T>(
|
|
|
69
72
|
options: SpanOptions,
|
|
70
73
|
fn: () => T | Promise<T>
|
|
71
74
|
): T | Promise<T> {
|
|
72
|
-
if (!isSupportedPlatform()) {
|
|
75
|
+
if (!isSupportedPlatform() || !getIsStarted() || getIsShutdown()) {
|
|
73
76
|
return fn();
|
|
74
77
|
}
|
|
75
78
|
|
|
@@ -94,11 +97,12 @@ export function trackSpan<T>(
|
|
|
94
97
|
}
|
|
95
98
|
|
|
96
99
|
function endSpan(spanId: string, statusCode?: SpanStatusCode): void {
|
|
100
|
+
if (getIsShutdown()) return;
|
|
97
101
|
PulseReactNativeOtel.endSpan(spanId, statusCode);
|
|
98
102
|
}
|
|
99
103
|
|
|
100
104
|
export function discardSpan(spanId: string): void {
|
|
101
|
-
if (!isSupportedPlatform()) {
|
|
105
|
+
if (!isSupportedPlatform() || !getIsStarted() || getIsShutdown()) {
|
|
102
106
|
return;
|
|
103
107
|
}
|
|
104
108
|
PulseReactNativeOtel.discardSpan(spanId);
|
|
@@ -109,14 +113,17 @@ function addSpanEvent(
|
|
|
109
113
|
name: string,
|
|
110
114
|
attributes?: PulseAttributes
|
|
111
115
|
): void {
|
|
116
|
+
if (getIsShutdown()) return;
|
|
112
117
|
PulseReactNativeOtel.addSpanEvent(spanId, name, attributes || undefined);
|
|
113
118
|
}
|
|
114
119
|
|
|
115
120
|
function setSpanAttributes(spanId: string, attributes?: PulseAttributes): void {
|
|
121
|
+
if (getIsShutdown()) return;
|
|
116
122
|
PulseReactNativeOtel.setSpanAttributes(spanId, attributes || undefined);
|
|
117
123
|
}
|
|
118
124
|
|
|
119
125
|
function recordSpanException(error: Error, attributes?: PulseAttributes): void {
|
|
126
|
+
if (getIsShutdown()) return;
|
|
120
127
|
const { message, stackTrace, errorType } = extractErrorDetails(error);
|
|
121
128
|
const observedTimeMs = Date.now();
|
|
122
129
|
const mergedAttributes = mergeWithGlobalAttributes(attributes || {});
|
package/src/user.ts
CHANGED
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
import PulseReactNativeOtel from './NativePulseReactNativeOtel';
|
|
2
|
+
import { getIsShutdown } from './config';
|
|
2
3
|
import { isSupportedPlatform } from './initialization';
|
|
3
4
|
import type { PulseAttributes } from './pulse.interface';
|
|
4
5
|
|
|
5
6
|
export function setUserId(id: string | null): void {
|
|
6
|
-
if (!isSupportedPlatform()) {
|
|
7
|
+
if (!isSupportedPlatform() || getIsShutdown()) {
|
|
7
8
|
return;
|
|
8
9
|
}
|
|
9
10
|
PulseReactNativeOtel.setUserId(id);
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
export function setUserProperty(name: string, value: string | null): void {
|
|
13
|
-
if (!isSupportedPlatform()) {
|
|
14
|
+
if (!isSupportedPlatform() || getIsShutdown()) {
|
|
14
15
|
return;
|
|
15
16
|
}
|
|
16
17
|
PulseReactNativeOtel.setUserProperty(name, value);
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
export function setUserProperties(properties: PulseAttributes): void {
|
|
20
|
-
if (!isSupportedPlatform()) {
|
|
21
|
+
if (!isSupportedPlatform() || getIsShutdown()) {
|
|
21
22
|
return;
|
|
22
23
|
}
|
|
23
24
|
PulseReactNativeOtel.setUserProperties(properties);
|