@raccoon.ninja/otel-react 0.0.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.

Potentially problematic release.


This version of @raccoon.ninja/otel-react might be problematic. Click here for more details.

@@ -0,0 +1,215 @@
1
+ 'use strict';
2
+
3
+ var api = require('@opentelemetry/api');
4
+ var sdkTraceBase = require('@opentelemetry/sdk-trace-base');
5
+ var exporterTraceOtlpHttp = require('@opentelemetry/exporter-trace-otlp-http');
6
+ var apiLogs = require('@opentelemetry/api-logs');
7
+ var resources = require('@opentelemetry/resources');
8
+ var semanticConventions = require('@opentelemetry/semantic-conventions');
9
+ var sdkLogs = require('@opentelemetry/sdk-logs');
10
+ var exporterLogsOtlpHttp = require('@opentelemetry/exporter-logs-otlp-http');
11
+ var sdkMetrics = require('@opentelemetry/sdk-metrics');
12
+ var exporterMetricsOtlpHttp = require('@opentelemetry/exporter-metrics-otlp-http');
13
+
14
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
15
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
16
+ }) : x)(function(x) {
17
+ if (typeof require !== "undefined") return require.apply(this, arguments);
18
+ throw Error('Dynamic require of "' + x + '" is not supported');
19
+ });
20
+
21
+ // src/core/options.ts
22
+ var DEFAULT_ENDPOINT = "http://localhost:4318";
23
+ var DEFAULT_EXPORT_TIMEOUT = 3e4;
24
+ function resolveEndpoint(options) {
25
+ return options.endpoint ?? DEFAULT_ENDPOINT;
26
+ }
27
+ function resolveExportTimeout(options) {
28
+ return options.exportTimeout ?? DEFAULT_EXPORT_TIMEOUT;
29
+ }
30
+ function validateOptions(options) {
31
+ if (!options.serviceName || typeof options.serviceName !== "string") {
32
+ throw new Error(
33
+ "[@raccoon.ninja/otel-react] serviceName is required and must be a non-empty string."
34
+ );
35
+ }
36
+ if (options.serviceName.trim() !== options.serviceName) {
37
+ throw new Error(
38
+ "[@raccoon.ninja/otel-react] serviceName must not have leading or trailing whitespace."
39
+ );
40
+ }
41
+ if (options.endpoint !== void 0) {
42
+ if (typeof options.endpoint !== "string" || options.endpoint.trim() === "") {
43
+ throw new Error(
44
+ "[@raccoon.ninja/otel-react] endpoint must be a non-empty string when provided."
45
+ );
46
+ }
47
+ }
48
+ if (options.exportTimeout !== void 0) {
49
+ if (typeof options.exportTimeout !== "number" || options.exportTimeout <= 0) {
50
+ throw new Error(
51
+ "[@raccoon.ninja/otel-react] exportTimeout must be a positive number when provided."
52
+ );
53
+ }
54
+ }
55
+ }
56
+ var SDK_NAME = "@raccoon.ninja/otel-react";
57
+ var SDK_VERSION = "0.0.1";
58
+ function buildResource(options) {
59
+ const attributes = {
60
+ [semanticConventions.ATTR_SERVICE_NAME]: options.serviceName,
61
+ "telemetry.sdk.name": SDK_NAME,
62
+ "telemetry.sdk.version": SDK_VERSION,
63
+ "telemetry.sdk.language": "webjs"
64
+ };
65
+ if (options.serviceVersion) {
66
+ attributes[semanticConventions.ATTR_SERVICE_VERSION] = options.serviceVersion;
67
+ }
68
+ if (options.environment) {
69
+ attributes[semanticConventions.SEMRESATTRS_DEPLOYMENT_ENVIRONMENT] = options.environment;
70
+ }
71
+ if (typeof navigator !== "undefined") {
72
+ if (navigator.language) {
73
+ attributes["browser.language"] = navigator.language;
74
+ }
75
+ if (navigator.userAgent) {
76
+ attributes["browser.user_agent"] = navigator.userAgent;
77
+ }
78
+ if (navigator.platform) {
79
+ attributes["browser.platform"] = navigator.platform;
80
+ }
81
+ }
82
+ if (options.resourceAttributes) {
83
+ Object.assign(attributes, options.resourceAttributes);
84
+ }
85
+ return resources.resourceFromAttributes(attributes);
86
+ }
87
+ function createLoggerProvider(options, resource) {
88
+ const endpoint = resolveEndpoint(options);
89
+ const timeout = resolveExportTimeout(options);
90
+ const exporter = new exporterLogsOtlpHttp.OTLPLogExporter({
91
+ url: `${endpoint}/v1/logs`,
92
+ headers: options.headers,
93
+ timeoutMillis: timeout
94
+ });
95
+ const provider = new sdkLogs.LoggerProvider({ resource });
96
+ provider.addLogRecordProcessor(new sdkLogs.BatchLogRecordProcessor(exporter));
97
+ apiLogs.logs.setGlobalLoggerProvider(provider);
98
+ return provider;
99
+ }
100
+ var METRIC_EXPORT_INTERVAL_MS = 3e4;
101
+ function createMeterProvider(options, resource) {
102
+ const endpoint = resolveEndpoint(options);
103
+ const timeout = resolveExportTimeout(options);
104
+ const exporter = new exporterMetricsOtlpHttp.OTLPMetricExporter({
105
+ url: `${endpoint}/v1/metrics`,
106
+ headers: options.headers,
107
+ timeoutMillis: timeout
108
+ });
109
+ const provider = new sdkMetrics.MeterProvider({
110
+ resource,
111
+ readers: [
112
+ new sdkMetrics.PeriodicExportingMetricReader({
113
+ exporter,
114
+ exportIntervalMillis: METRIC_EXPORT_INTERVAL_MS
115
+ })
116
+ ]
117
+ });
118
+ api.metrics.setGlobalMeterProvider(provider);
119
+ return provider;
120
+ }
121
+
122
+ // src/native/init.ts
123
+ var initialized = false;
124
+ async function initOtelNative(options) {
125
+ if (initialized) {
126
+ console.warn(
127
+ "[@raccoon.ninja/otel-react] initOtelNative() has already been called. Skipping."
128
+ );
129
+ return {
130
+ shutdown: async () => {
131
+ }
132
+ };
133
+ }
134
+ validateOptions(options);
135
+ const resource = buildResource(options);
136
+ const endpoint = resolveEndpoint(options);
137
+ const timeout = resolveExportTimeout(options);
138
+ const traceExporter = new exporterTraceOtlpHttp.OTLPTraceExporter({
139
+ url: `${endpoint}/v1/traces`,
140
+ headers: options.headers,
141
+ timeoutMillis: timeout
142
+ });
143
+ const tracerProvider = new sdkTraceBase.BasicTracerProvider({
144
+ resource,
145
+ spanProcessors: [new sdkTraceBase.BatchSpanProcessor(traceExporter)]
146
+ });
147
+ api.trace.setGlobalTracerProvider(tracerProvider);
148
+ const loggerProvider = createLoggerProvider(options, resource);
149
+ const meterProvider = createMeterProvider(options, resource);
150
+ let appStateSubscription = null;
151
+ try {
152
+ const { AppState } = __require("react-native");
153
+ appStateSubscription = AppState.addEventListener("change", (nextState) => {
154
+ if (nextState === "background" || nextState === "inactive") {
155
+ tracerProvider.forceFlush();
156
+ loggerProvider.forceFlush();
157
+ meterProvider.forceFlush();
158
+ }
159
+ });
160
+ } catch {
161
+ }
162
+ const logger = loggerProvider.getLogger("@raccoon.ninja/otel-react", "1.0.0");
163
+ logger.emit({
164
+ severityNumber: apiLogs.SeverityNumber.INFO,
165
+ severityText: "INFO",
166
+ body: `OpenTelemetry (RN) initialized for service "${options.serviceName}"`
167
+ });
168
+ initialized = true;
169
+ return {
170
+ shutdown: async () => {
171
+ appStateSubscription?.remove();
172
+ await Promise.all([
173
+ tracerProvider.forceFlush(),
174
+ loggerProvider.forceFlush(),
175
+ meterProvider.forceFlush()
176
+ ]);
177
+ await Promise.all([
178
+ tracerProvider.shutdown(),
179
+ loggerProvider.shutdown(),
180
+ meterProvider.shutdown()
181
+ ]);
182
+ initialized = false;
183
+ }
184
+ };
185
+ }
186
+ var TRACER_NAME = "@raccoon.ninja/otel-react/react-navigation";
187
+ function withReactNavigation() {
188
+ return () => {
189
+ api.trace.getTracer(TRACER_NAME, "1.0.0");
190
+ };
191
+ }
192
+ function createNavigationTracker() {
193
+ const tracer = api.trace.getTracer(TRACER_NAME, "1.0.0");
194
+ let previousRouteName;
195
+ return (state) => {
196
+ if (!state) return;
197
+ const currentRoute = state.routes[state.index];
198
+ if (!currentRoute) return;
199
+ const currentRouteName = currentRoute.name;
200
+ if (previousRouteName && previousRouteName !== currentRouteName) {
201
+ const span = tracer.startSpan("navigation.route_change");
202
+ span.setAttribute("navigation.from", previousRouteName);
203
+ span.setAttribute("navigation.to", currentRouteName);
204
+ span.setStatus({ code: api.SpanStatusCode.OK });
205
+ span.end();
206
+ }
207
+ previousRouteName = currentRouteName;
208
+ };
209
+ }
210
+
211
+ exports.createNavigationTracker = createNavigationTracker;
212
+ exports.initOtel = initOtelNative;
213
+ exports.withReactNavigation = withReactNavigation;
214
+ //# sourceMappingURL=index.cjs.map
215
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/options.ts","../../src/core/resource.ts","../../src/providers/logger.ts","../../src/providers/meter.ts","../../src/native/init.ts","../../src/native/navigation.ts"],"names":["ATTR_SERVICE_NAME","ATTR_SERVICE_VERSION","SEMRESATTRS_DEPLOYMENT_ENVIRONMENT","resourceFromAttributes","OTLPLogExporter","LoggerProvider","BatchLogRecordProcessor","logs","OTLPMetricExporter","MeterProvider","PeriodicExportingMetricReader","metrics","OTLPTraceExporter","BasicTracerProvider","BatchSpanProcessor","trace","SeverityNumber","SpanStatusCode"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { WebTracerProvider } from '@opentelemetry/sdk-trace-web';\nimport type { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';\n\n/** Configuration for enabling/disabling specific auto-instrumentations. */\nexport interface InstrumentationConfig {\n /** Auto-instrument fetch() calls. Default: true */\n fetch?: boolean;\n /** Auto-instrument XMLHttpRequest. Default: true */\n xhr?: boolean;\n /** Document load timing spans. Default: true */\n documentLoad?: boolean;\n /** Click/input interaction spans. Default: true */\n userInteraction?: boolean;\n /** LCP, CLS, INP, TTFB, FCP metrics. Default: true */\n webVitals?: boolean;\n}\n\n/** Extension function type for opt-in instrumentations (e.g., withReactRouter). */\nexport type OtelExtension = (context: ExtensionContext) => void;\n\n/** Context provided to extension functions during initialization. */\nexport interface ExtensionContext {\n tracerProvider: WebTracerProvider;\n}\n\n/** Configuration options for initOtel(). */\nexport interface OtelOptions {\n /** Required. Sets the service.name resource attribute. */\n serviceName: string;\n\n /** OTLP HTTP endpoint. Default: 'http://localhost:4318' */\n endpoint?: string;\n\n /** Additional OTel resource attributes. */\n resourceAttributes?: Record<string, string>;\n\n /** Service version. Sets service.version resource attribute. */\n serviceVersion?: string;\n\n /** Deployment environment. Sets deployment.environment resource attribute. */\n environment?: string;\n\n /** Enable/disable specific auto-instrumentations. All enabled by default. */\n instrumentations?: InstrumentationConfig;\n\n /** Escape hatch: configure the TracerProvider before it's registered. */\n configureTracing?: (provider: WebTracerProvider) => void;\n\n /** Escape hatch: configure the OTLP exporter. */\n configureExporter?: (exporter: OTLPTraceExporter) => void;\n\n /** Custom headers sent with OTLP export requests (e.g., auth tokens). */\n headers?: Record<string, string>;\n\n /** Export timeout in milliseconds. Default: 30000 */\n exportTimeout?: number;\n\n /**\n * URLs to exclude from fetch/XHR instrumentation.\n * Supports string patterns or RegExp.\n */\n ignoreUrls?: Array<string | RegExp>;\n\n /** Extension functions for opt-in instrumentations. */\n extensions?: OtelExtension[];\n}\n\n/** Handle returned from initOtel() for lifecycle management. */\nexport interface OtelHandle {\n /** Flush all pending telemetry and shut down providers. */\n shutdown: () => Promise<void>;\n}\n\nconst DEFAULT_ENDPOINT = 'http://localhost:4318';\nconst DEFAULT_EXPORT_TIMEOUT = 30000;\n\nexport function resolveEndpoint(options: OtelOptions): string {\n return options.endpoint ?? DEFAULT_ENDPOINT;\n}\n\nexport function resolveExportTimeout(options: OtelOptions): number {\n return options.exportTimeout ?? DEFAULT_EXPORT_TIMEOUT;\n}\n\nexport function resolveInstrumentations(options: OtelOptions): Required<InstrumentationConfig> {\n return {\n fetch: options.instrumentations?.fetch ?? true,\n xhr: options.instrumentations?.xhr ?? true,\n documentLoad: options.instrumentations?.documentLoad ?? true,\n userInteraction: options.instrumentations?.userInteraction ?? true,\n webVitals: options.instrumentations?.webVitals ?? true,\n };\n}\n\nexport function validateOptions(options: OtelOptions): void {\n if (!options.serviceName || typeof options.serviceName !== 'string') {\n throw new Error(\n '[@raccoon.ninja/otel-react] serviceName is required and must be a non-empty string.',\n );\n }\n\n if (options.serviceName.trim() !== options.serviceName) {\n throw new Error(\n '[@raccoon.ninja/otel-react] serviceName must not have leading or trailing whitespace.',\n );\n }\n\n if (options.endpoint !== undefined) {\n if (typeof options.endpoint !== 'string' || options.endpoint.trim() === '') {\n throw new Error(\n '[@raccoon.ninja/otel-react] endpoint must be a non-empty string when provided.',\n );\n }\n }\n\n if (options.exportTimeout !== undefined) {\n if (typeof options.exportTimeout !== 'number' || options.exportTimeout <= 0) {\n throw new Error(\n '[@raccoon.ninja/otel-react] exportTimeout must be a positive number when provided.',\n );\n }\n }\n}\n","import { resourceFromAttributes } from '@opentelemetry/resources';\nimport {\n ATTR_SERVICE_NAME,\n ATTR_SERVICE_VERSION,\n SEMRESATTRS_DEPLOYMENT_ENVIRONMENT,\n} from '@opentelemetry/semantic-conventions';\nimport type { OtelOptions } from './options';\n\nconst SDK_NAME = '@raccoon.ninja/otel-react';\nconst SDK_VERSION = '0.0.1';\n\nexport function buildResource(options: OtelOptions) {\n const attributes: Record<string, string> = {\n [ATTR_SERVICE_NAME]: options.serviceName,\n 'telemetry.sdk.name': SDK_NAME,\n 'telemetry.sdk.version': SDK_VERSION,\n 'telemetry.sdk.language': 'webjs',\n };\n\n if (options.serviceVersion) {\n attributes[ATTR_SERVICE_VERSION] = options.serviceVersion;\n }\n\n if (options.environment) {\n attributes[SEMRESATTRS_DEPLOYMENT_ENVIRONMENT] = options.environment;\n }\n\n if (typeof navigator !== 'undefined') {\n if (navigator.language) {\n attributes['browser.language'] = navigator.language;\n }\n if (navigator.userAgent) {\n attributes['browser.user_agent'] = navigator.userAgent;\n }\n if (navigator.platform) {\n attributes['browser.platform'] = navigator.platform;\n }\n }\n\n if (options.resourceAttributes) {\n Object.assign(attributes, options.resourceAttributes);\n }\n\n return resourceFromAttributes(attributes);\n}\n","import { LoggerProvider, BatchLogRecordProcessor } from '@opentelemetry/sdk-logs';\nimport { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';\nimport { logs } from '@opentelemetry/api-logs';\nimport type { Resource } from '@opentelemetry/resources';\nimport type { OtelOptions } from '../core/options';\nimport { resolveEndpoint, resolveExportTimeout } from '../core/options';\n\nexport function createLoggerProvider(options: OtelOptions, resource: Resource): LoggerProvider {\n const endpoint = resolveEndpoint(options);\n const timeout = resolveExportTimeout(options);\n\n const exporter = new OTLPLogExporter({\n url: `${endpoint}/v1/logs`,\n headers: options.headers,\n timeoutMillis: timeout,\n });\n\n const provider = new LoggerProvider({ resource });\n provider.addLogRecordProcessor(new BatchLogRecordProcessor(exporter));\n\n logs.setGlobalLoggerProvider(provider);\n\n return provider;\n}\n","import { MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';\nimport { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';\nimport { metrics } from '@opentelemetry/api';\nimport type { Resource } from '@opentelemetry/resources';\nimport type { OtelOptions } from '../core/options';\nimport { resolveEndpoint, resolveExportTimeout } from '../core/options';\n\nconst METRIC_EXPORT_INTERVAL_MS = 30_000;\n\nexport function createMeterProvider(options: OtelOptions, resource: Resource): MeterProvider {\n const endpoint = resolveEndpoint(options);\n const timeout = resolveExportTimeout(options);\n\n const exporter = new OTLPMetricExporter({\n url: `${endpoint}/v1/metrics`,\n headers: options.headers,\n timeoutMillis: timeout,\n });\n\n const provider = new MeterProvider({\n resource,\n readers: [\n new PeriodicExportingMetricReader({\n exporter,\n exportIntervalMillis: METRIC_EXPORT_INTERVAL_MS,\n }),\n ],\n });\n\n metrics.setGlobalMeterProvider(provider);\n\n return provider;\n}\n","import { trace } from '@opentelemetry/api';\nimport { BasicTracerProvider, BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';\nimport { SeverityNumber } from '@opentelemetry/api-logs';\nimport type { OtelOptions, OtelHandle } from '../core/options';\nimport {\n validateOptions,\n resolveEndpoint,\n resolveExportTimeout,\n} from '../core/options';\nimport { buildResource } from '../core/resource';\nimport { createLoggerProvider } from '../providers/logger';\nimport { createMeterProvider } from '../providers/meter';\n\nlet initialized = false;\n\n/**\n * Initialize OpenTelemetry for React Native.\n *\n * Key differences from browser init:\n * - Uses BasicTracerProvider (sdk-trace-base) instead of WebTracerProvider\n * - Only fetch instrumentation enabled (no document-load, no user-interaction, no Web Vitals)\n * - XHR disabled by default to avoid duplicate spans (RN's fetch polyfills over XHR)\n * - Uses AppState for flush instead of visibilitychange\n */\nexport async function initOtelNative(options: OtelOptions): Promise<OtelHandle> {\n if (initialized) {\n console.warn(\n '[@raccoon.ninja/otel-react] initOtelNative() has already been called. Skipping.',\n );\n return {\n shutdown: async () => {\n /* noop */\n },\n };\n }\n\n validateOptions(options);\n\n const resource = buildResource(options);\n const endpoint = resolveEndpoint(options);\n const timeout = resolveExportTimeout(options);\n\n const traceExporter = new OTLPTraceExporter({\n url: `${endpoint}/v1/traces`,\n headers: options.headers,\n timeoutMillis: timeout,\n });\n\n const tracerProvider = new BasicTracerProvider({\n resource,\n spanProcessors: [new BatchSpanProcessor(traceExporter)],\n });\n\n // BasicTracerProvider doesn't have register(), use the API directly\n trace.setGlobalTracerProvider(tracerProvider);\n\n const loggerProvider = createLoggerProvider(options, resource);\n const meterProvider = createMeterProvider(options, resource);\n\n // Listen for AppState changes for flush (React Native)\n let appStateSubscription: { remove: () => void } | null = null;\n try {\n // Dynamic import of AppState so this module doesn't crash in non-RN environments\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { AppState } = require('react-native') as {\n AppState: {\n addEventListener: (\n type: string,\n handler: (state: string) => void,\n ) => { remove: () => void };\n };\n };\n appStateSubscription = AppState.addEventListener('change', (nextState: string) => {\n if (nextState === 'background' || nextState === 'inactive') {\n tracerProvider.forceFlush();\n loggerProvider.forceFlush();\n meterProvider.forceFlush();\n }\n });\n } catch {\n // AppState not available — skip\n }\n\n const logger = loggerProvider.getLogger('@raccoon.ninja/otel-react', '1.0.0');\n logger.emit({\n severityNumber: SeverityNumber.INFO,\n severityText: 'INFO',\n body: `OpenTelemetry (RN) initialized for service \"${options.serviceName}\"`,\n });\n\n initialized = true;\n\n return {\n shutdown: async () => {\n appStateSubscription?.remove();\n await Promise.all([\n tracerProvider.forceFlush(),\n loggerProvider.forceFlush(),\n meterProvider.forceFlush(),\n ]);\n await Promise.all([\n tracerProvider.shutdown(),\n loggerProvider.shutdown(),\n meterProvider.shutdown(),\n ]);\n initialized = false;\n },\n };\n}\n","import { trace, SpanStatusCode } from '@opentelemetry/api';\nimport type { OtelExtension } from '../core/options';\n\nconst TRACER_NAME = '@raccoon.ninja/otel-react/react-navigation';\n\n/**\n * Extension for React Navigation route-change tracing.\n *\n * This extension pre-registers the tracer scope. Actual navigation\n * tracking requires hooking into React Navigation's onStateChange\n * in the consuming app.\n *\n * @example\n * ```tsx\n * import { withReactNavigation, createNavigationTracker } from '@raccoon.ninja/otel-react/native';\n *\n * const otel = await initOtelNative({\n * serviceName: 'my-rn-app',\n * extensions: [withReactNavigation()],\n * });\n * ```\n */\nexport function withReactNavigation(): OtelExtension {\n return () => {\n trace.getTracer(TRACER_NAME, '1.0.0');\n };\n}\n\n/**\n * Creates a navigation state change handler that records route changes as spans.\n *\n * @returns A function suitable for React Navigation's onStateChange prop.\n */\nexport function createNavigationTracker() {\n const tracer = trace.getTracer(TRACER_NAME, '1.0.0');\n let previousRouteName: string | undefined;\n\n return (state: { routes: Array<{ name: string }>; index: number } | undefined) => {\n if (!state) return;\n\n const currentRoute = state.routes[state.index];\n if (!currentRoute) return;\n\n const currentRouteName = currentRoute.name;\n\n if (previousRouteName && previousRouteName !== currentRouteName) {\n const span = tracer.startSpan('navigation.route_change');\n span.setAttribute('navigation.from', previousRouteName);\n span.setAttribute('navigation.to', currentRouteName);\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n }\n\n previousRouteName = currentRouteName;\n };\n}\n"]}
@@ -0,0 +1,100 @@
1
+ import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
2
+ import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
3
+
4
+ /** Configuration for enabling/disabling specific auto-instrumentations. */
5
+ interface InstrumentationConfig {
6
+ /** Auto-instrument fetch() calls. Default: true */
7
+ fetch?: boolean;
8
+ /** Auto-instrument XMLHttpRequest. Default: true */
9
+ xhr?: boolean;
10
+ /** Document load timing spans. Default: true */
11
+ documentLoad?: boolean;
12
+ /** Click/input interaction spans. Default: true */
13
+ userInteraction?: boolean;
14
+ /** LCP, CLS, INP, TTFB, FCP metrics. Default: true */
15
+ webVitals?: boolean;
16
+ }
17
+ /** Extension function type for opt-in instrumentations (e.g., withReactRouter). */
18
+ type OtelExtension = (context: ExtensionContext) => void;
19
+ /** Context provided to extension functions during initialization. */
20
+ interface ExtensionContext {
21
+ tracerProvider: WebTracerProvider;
22
+ }
23
+ /** Configuration options for initOtel(). */
24
+ interface OtelOptions {
25
+ /** Required. Sets the service.name resource attribute. */
26
+ serviceName: string;
27
+ /** OTLP HTTP endpoint. Default: 'http://localhost:4318' */
28
+ endpoint?: string;
29
+ /** Additional OTel resource attributes. */
30
+ resourceAttributes?: Record<string, string>;
31
+ /** Service version. Sets service.version resource attribute. */
32
+ serviceVersion?: string;
33
+ /** Deployment environment. Sets deployment.environment resource attribute. */
34
+ environment?: string;
35
+ /** Enable/disable specific auto-instrumentations. All enabled by default. */
36
+ instrumentations?: InstrumentationConfig;
37
+ /** Escape hatch: configure the TracerProvider before it's registered. */
38
+ configureTracing?: (provider: WebTracerProvider) => void;
39
+ /** Escape hatch: configure the OTLP exporter. */
40
+ configureExporter?: (exporter: OTLPTraceExporter) => void;
41
+ /** Custom headers sent with OTLP export requests (e.g., auth tokens). */
42
+ headers?: Record<string, string>;
43
+ /** Export timeout in milliseconds. Default: 30000 */
44
+ exportTimeout?: number;
45
+ /**
46
+ * URLs to exclude from fetch/XHR instrumentation.
47
+ * Supports string patterns or RegExp.
48
+ */
49
+ ignoreUrls?: Array<string | RegExp>;
50
+ /** Extension functions for opt-in instrumentations. */
51
+ extensions?: OtelExtension[];
52
+ }
53
+ /** Handle returned from initOtel() for lifecycle management. */
54
+ interface OtelHandle {
55
+ /** Flush all pending telemetry and shut down providers. */
56
+ shutdown: () => Promise<void>;
57
+ }
58
+
59
+ /**
60
+ * Initialize OpenTelemetry for React Native.
61
+ *
62
+ * Key differences from browser init:
63
+ * - Uses BasicTracerProvider (sdk-trace-base) instead of WebTracerProvider
64
+ * - Only fetch instrumentation enabled (no document-load, no user-interaction, no Web Vitals)
65
+ * - XHR disabled by default to avoid duplicate spans (RN's fetch polyfills over XHR)
66
+ * - Uses AppState for flush instead of visibilitychange
67
+ */
68
+ declare function initOtelNative(options: OtelOptions): Promise<OtelHandle>;
69
+
70
+ /**
71
+ * Extension for React Navigation route-change tracing.
72
+ *
73
+ * This extension pre-registers the tracer scope. Actual navigation
74
+ * tracking requires hooking into React Navigation's onStateChange
75
+ * in the consuming app.
76
+ *
77
+ * @example
78
+ * ```tsx
79
+ * import { withReactNavigation, createNavigationTracker } from '@raccoon.ninja/otel-react/native';
80
+ *
81
+ * const otel = await initOtelNative({
82
+ * serviceName: 'my-rn-app',
83
+ * extensions: [withReactNavigation()],
84
+ * });
85
+ * ```
86
+ */
87
+ declare function withReactNavigation(): OtelExtension;
88
+ /**
89
+ * Creates a navigation state change handler that records route changes as spans.
90
+ *
91
+ * @returns A function suitable for React Navigation's onStateChange prop.
92
+ */
93
+ declare function createNavigationTracker(): (state: {
94
+ routes: Array<{
95
+ name: string;
96
+ }>;
97
+ index: number;
98
+ } | undefined) => void;
99
+
100
+ export { type OtelExtension, type OtelHandle, type OtelOptions, createNavigationTracker, initOtelNative as initOtel, withReactNavigation };
@@ -0,0 +1,100 @@
1
+ import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
2
+ import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
3
+
4
+ /** Configuration for enabling/disabling specific auto-instrumentations. */
5
+ interface InstrumentationConfig {
6
+ /** Auto-instrument fetch() calls. Default: true */
7
+ fetch?: boolean;
8
+ /** Auto-instrument XMLHttpRequest. Default: true */
9
+ xhr?: boolean;
10
+ /** Document load timing spans. Default: true */
11
+ documentLoad?: boolean;
12
+ /** Click/input interaction spans. Default: true */
13
+ userInteraction?: boolean;
14
+ /** LCP, CLS, INP, TTFB, FCP metrics. Default: true */
15
+ webVitals?: boolean;
16
+ }
17
+ /** Extension function type for opt-in instrumentations (e.g., withReactRouter). */
18
+ type OtelExtension = (context: ExtensionContext) => void;
19
+ /** Context provided to extension functions during initialization. */
20
+ interface ExtensionContext {
21
+ tracerProvider: WebTracerProvider;
22
+ }
23
+ /** Configuration options for initOtel(). */
24
+ interface OtelOptions {
25
+ /** Required. Sets the service.name resource attribute. */
26
+ serviceName: string;
27
+ /** OTLP HTTP endpoint. Default: 'http://localhost:4318' */
28
+ endpoint?: string;
29
+ /** Additional OTel resource attributes. */
30
+ resourceAttributes?: Record<string, string>;
31
+ /** Service version. Sets service.version resource attribute. */
32
+ serviceVersion?: string;
33
+ /** Deployment environment. Sets deployment.environment resource attribute. */
34
+ environment?: string;
35
+ /** Enable/disable specific auto-instrumentations. All enabled by default. */
36
+ instrumentations?: InstrumentationConfig;
37
+ /** Escape hatch: configure the TracerProvider before it's registered. */
38
+ configureTracing?: (provider: WebTracerProvider) => void;
39
+ /** Escape hatch: configure the OTLP exporter. */
40
+ configureExporter?: (exporter: OTLPTraceExporter) => void;
41
+ /** Custom headers sent with OTLP export requests (e.g., auth tokens). */
42
+ headers?: Record<string, string>;
43
+ /** Export timeout in milliseconds. Default: 30000 */
44
+ exportTimeout?: number;
45
+ /**
46
+ * URLs to exclude from fetch/XHR instrumentation.
47
+ * Supports string patterns or RegExp.
48
+ */
49
+ ignoreUrls?: Array<string | RegExp>;
50
+ /** Extension functions for opt-in instrumentations. */
51
+ extensions?: OtelExtension[];
52
+ }
53
+ /** Handle returned from initOtel() for lifecycle management. */
54
+ interface OtelHandle {
55
+ /** Flush all pending telemetry and shut down providers. */
56
+ shutdown: () => Promise<void>;
57
+ }
58
+
59
+ /**
60
+ * Initialize OpenTelemetry for React Native.
61
+ *
62
+ * Key differences from browser init:
63
+ * - Uses BasicTracerProvider (sdk-trace-base) instead of WebTracerProvider
64
+ * - Only fetch instrumentation enabled (no document-load, no user-interaction, no Web Vitals)
65
+ * - XHR disabled by default to avoid duplicate spans (RN's fetch polyfills over XHR)
66
+ * - Uses AppState for flush instead of visibilitychange
67
+ */
68
+ declare function initOtelNative(options: OtelOptions): Promise<OtelHandle>;
69
+
70
+ /**
71
+ * Extension for React Navigation route-change tracing.
72
+ *
73
+ * This extension pre-registers the tracer scope. Actual navigation
74
+ * tracking requires hooking into React Navigation's onStateChange
75
+ * in the consuming app.
76
+ *
77
+ * @example
78
+ * ```tsx
79
+ * import { withReactNavigation, createNavigationTracker } from '@raccoon.ninja/otel-react/native';
80
+ *
81
+ * const otel = await initOtelNative({
82
+ * serviceName: 'my-rn-app',
83
+ * extensions: [withReactNavigation()],
84
+ * });
85
+ * ```
86
+ */
87
+ declare function withReactNavigation(): OtelExtension;
88
+ /**
89
+ * Creates a navigation state change handler that records route changes as spans.
90
+ *
91
+ * @returns A function suitable for React Navigation's onStateChange prop.
92
+ */
93
+ declare function createNavigationTracker(): (state: {
94
+ routes: Array<{
95
+ name: string;
96
+ }>;
97
+ index: number;
98
+ } | undefined) => void;
99
+
100
+ export { type OtelExtension, type OtelHandle, type OtelOptions, createNavigationTracker, initOtelNative as initOtel, withReactNavigation };
@@ -0,0 +1,211 @@
1
+ import { trace, SpanStatusCode, metrics } from '@opentelemetry/api';
2
+ import { BasicTracerProvider, BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
3
+ import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
4
+ import { SeverityNumber, logs } from '@opentelemetry/api-logs';
5
+ import { resourceFromAttributes } from '@opentelemetry/resources';
6
+ import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION, SEMRESATTRS_DEPLOYMENT_ENVIRONMENT } from '@opentelemetry/semantic-conventions';
7
+ import { LoggerProvider, BatchLogRecordProcessor } from '@opentelemetry/sdk-logs';
8
+ import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';
9
+ import { MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
10
+ import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
11
+
12
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
13
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
14
+ }) : x)(function(x) {
15
+ if (typeof require !== "undefined") return require.apply(this, arguments);
16
+ throw Error('Dynamic require of "' + x + '" is not supported');
17
+ });
18
+
19
+ // src/core/options.ts
20
+ var DEFAULT_ENDPOINT = "http://localhost:4318";
21
+ var DEFAULT_EXPORT_TIMEOUT = 3e4;
22
+ function resolveEndpoint(options) {
23
+ return options.endpoint ?? DEFAULT_ENDPOINT;
24
+ }
25
+ function resolveExportTimeout(options) {
26
+ return options.exportTimeout ?? DEFAULT_EXPORT_TIMEOUT;
27
+ }
28
+ function validateOptions(options) {
29
+ if (!options.serviceName || typeof options.serviceName !== "string") {
30
+ throw new Error(
31
+ "[@raccoon.ninja/otel-react] serviceName is required and must be a non-empty string."
32
+ );
33
+ }
34
+ if (options.serviceName.trim() !== options.serviceName) {
35
+ throw new Error(
36
+ "[@raccoon.ninja/otel-react] serviceName must not have leading or trailing whitespace."
37
+ );
38
+ }
39
+ if (options.endpoint !== void 0) {
40
+ if (typeof options.endpoint !== "string" || options.endpoint.trim() === "") {
41
+ throw new Error(
42
+ "[@raccoon.ninja/otel-react] endpoint must be a non-empty string when provided."
43
+ );
44
+ }
45
+ }
46
+ if (options.exportTimeout !== void 0) {
47
+ if (typeof options.exportTimeout !== "number" || options.exportTimeout <= 0) {
48
+ throw new Error(
49
+ "[@raccoon.ninja/otel-react] exportTimeout must be a positive number when provided."
50
+ );
51
+ }
52
+ }
53
+ }
54
+ var SDK_NAME = "@raccoon.ninja/otel-react";
55
+ var SDK_VERSION = "0.0.1";
56
+ function buildResource(options) {
57
+ const attributes = {
58
+ [ATTR_SERVICE_NAME]: options.serviceName,
59
+ "telemetry.sdk.name": SDK_NAME,
60
+ "telemetry.sdk.version": SDK_VERSION,
61
+ "telemetry.sdk.language": "webjs"
62
+ };
63
+ if (options.serviceVersion) {
64
+ attributes[ATTR_SERVICE_VERSION] = options.serviceVersion;
65
+ }
66
+ if (options.environment) {
67
+ attributes[SEMRESATTRS_DEPLOYMENT_ENVIRONMENT] = options.environment;
68
+ }
69
+ if (typeof navigator !== "undefined") {
70
+ if (navigator.language) {
71
+ attributes["browser.language"] = navigator.language;
72
+ }
73
+ if (navigator.userAgent) {
74
+ attributes["browser.user_agent"] = navigator.userAgent;
75
+ }
76
+ if (navigator.platform) {
77
+ attributes["browser.platform"] = navigator.platform;
78
+ }
79
+ }
80
+ if (options.resourceAttributes) {
81
+ Object.assign(attributes, options.resourceAttributes);
82
+ }
83
+ return resourceFromAttributes(attributes);
84
+ }
85
+ function createLoggerProvider(options, resource) {
86
+ const endpoint = resolveEndpoint(options);
87
+ const timeout = resolveExportTimeout(options);
88
+ const exporter = new OTLPLogExporter({
89
+ url: `${endpoint}/v1/logs`,
90
+ headers: options.headers,
91
+ timeoutMillis: timeout
92
+ });
93
+ const provider = new LoggerProvider({ resource });
94
+ provider.addLogRecordProcessor(new BatchLogRecordProcessor(exporter));
95
+ logs.setGlobalLoggerProvider(provider);
96
+ return provider;
97
+ }
98
+ var METRIC_EXPORT_INTERVAL_MS = 3e4;
99
+ function createMeterProvider(options, resource) {
100
+ const endpoint = resolveEndpoint(options);
101
+ const timeout = resolveExportTimeout(options);
102
+ const exporter = new OTLPMetricExporter({
103
+ url: `${endpoint}/v1/metrics`,
104
+ headers: options.headers,
105
+ timeoutMillis: timeout
106
+ });
107
+ const provider = new MeterProvider({
108
+ resource,
109
+ readers: [
110
+ new PeriodicExportingMetricReader({
111
+ exporter,
112
+ exportIntervalMillis: METRIC_EXPORT_INTERVAL_MS
113
+ })
114
+ ]
115
+ });
116
+ metrics.setGlobalMeterProvider(provider);
117
+ return provider;
118
+ }
119
+
120
+ // src/native/init.ts
121
+ var initialized = false;
122
+ async function initOtelNative(options) {
123
+ if (initialized) {
124
+ console.warn(
125
+ "[@raccoon.ninja/otel-react] initOtelNative() has already been called. Skipping."
126
+ );
127
+ return {
128
+ shutdown: async () => {
129
+ }
130
+ };
131
+ }
132
+ validateOptions(options);
133
+ const resource = buildResource(options);
134
+ const endpoint = resolveEndpoint(options);
135
+ const timeout = resolveExportTimeout(options);
136
+ const traceExporter = new OTLPTraceExporter({
137
+ url: `${endpoint}/v1/traces`,
138
+ headers: options.headers,
139
+ timeoutMillis: timeout
140
+ });
141
+ const tracerProvider = new BasicTracerProvider({
142
+ resource,
143
+ spanProcessors: [new BatchSpanProcessor(traceExporter)]
144
+ });
145
+ trace.setGlobalTracerProvider(tracerProvider);
146
+ const loggerProvider = createLoggerProvider(options, resource);
147
+ const meterProvider = createMeterProvider(options, resource);
148
+ let appStateSubscription = null;
149
+ try {
150
+ const { AppState } = __require("react-native");
151
+ appStateSubscription = AppState.addEventListener("change", (nextState) => {
152
+ if (nextState === "background" || nextState === "inactive") {
153
+ tracerProvider.forceFlush();
154
+ loggerProvider.forceFlush();
155
+ meterProvider.forceFlush();
156
+ }
157
+ });
158
+ } catch {
159
+ }
160
+ const logger = loggerProvider.getLogger("@raccoon.ninja/otel-react", "1.0.0");
161
+ logger.emit({
162
+ severityNumber: SeverityNumber.INFO,
163
+ severityText: "INFO",
164
+ body: `OpenTelemetry (RN) initialized for service "${options.serviceName}"`
165
+ });
166
+ initialized = true;
167
+ return {
168
+ shutdown: async () => {
169
+ appStateSubscription?.remove();
170
+ await Promise.all([
171
+ tracerProvider.forceFlush(),
172
+ loggerProvider.forceFlush(),
173
+ meterProvider.forceFlush()
174
+ ]);
175
+ await Promise.all([
176
+ tracerProvider.shutdown(),
177
+ loggerProvider.shutdown(),
178
+ meterProvider.shutdown()
179
+ ]);
180
+ initialized = false;
181
+ }
182
+ };
183
+ }
184
+ var TRACER_NAME = "@raccoon.ninja/otel-react/react-navigation";
185
+ function withReactNavigation() {
186
+ return () => {
187
+ trace.getTracer(TRACER_NAME, "1.0.0");
188
+ };
189
+ }
190
+ function createNavigationTracker() {
191
+ const tracer = trace.getTracer(TRACER_NAME, "1.0.0");
192
+ let previousRouteName;
193
+ return (state) => {
194
+ if (!state) return;
195
+ const currentRoute = state.routes[state.index];
196
+ if (!currentRoute) return;
197
+ const currentRouteName = currentRoute.name;
198
+ if (previousRouteName && previousRouteName !== currentRouteName) {
199
+ const span = tracer.startSpan("navigation.route_change");
200
+ span.setAttribute("navigation.from", previousRouteName);
201
+ span.setAttribute("navigation.to", currentRouteName);
202
+ span.setStatus({ code: SpanStatusCode.OK });
203
+ span.end();
204
+ }
205
+ previousRouteName = currentRouteName;
206
+ };
207
+ }
208
+
209
+ export { createNavigationTracker, initOtelNative as initOtel, withReactNavigation };
210
+ //# sourceMappingURL=index.mjs.map
211
+ //# sourceMappingURL=index.mjs.map