@raccoon.ninja/otel-react 0.0.1 → 0.0.2
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.
- package/README.md +71 -80
- package/dist/index.cjs +2 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +2 -5
- package/dist/index.mjs.map +1 -1
- package/dist/native/index.cjs +2 -4
- package/dist/native/index.cjs.map +1 -1
- package/dist/native/index.mjs +2 -4
- package/dist/native/index.mjs.map +1 -1
- package/dist/nextjs/index.cjs.map +1 -1
- package/dist/nextjs/index.mjs.map +1 -1
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -53,20 +53,20 @@ All telemetry is sent to `http://localhost:4318` by default (the standard OTLP H
|
|
|
53
53
|
|
|
54
54
|
### OtelProvider Props
|
|
55
55
|
|
|
56
|
-
| Prop
|
|
57
|
-
|
|
58
|
-
| `serviceName`
|
|
59
|
-
| `endpoint`
|
|
60
|
-
| `serviceVersion`
|
|
61
|
-
| `environment`
|
|
62
|
-
| `headers`
|
|
63
|
-
| `exportTimeout`
|
|
64
|
-
| `ignoreUrls`
|
|
65
|
-
| `instrumentations`
|
|
66
|
-
| `resourceAttributes` | `Record<string, string>` | --
|
|
67
|
-
| `extensions`
|
|
68
|
-
| `configureTracing`
|
|
69
|
-
| `configureExporter`
|
|
56
|
+
| Prop | Type | Default | Description |
|
|
57
|
+
| -------------------- | ------------------------ | ----------------------- | ---------------------------------------------------- |
|
|
58
|
+
| `serviceName` | `string` | **(required)** | Sets the `service.name` resource attribute |
|
|
59
|
+
| `endpoint` | `string` | `http://localhost:4318` | OTLP HTTP collector endpoint |
|
|
60
|
+
| `serviceVersion` | `string` | -- | Sets `service.version` resource attribute |
|
|
61
|
+
| `environment` | `string` | -- | Sets `deployment.environment` resource attribute |
|
|
62
|
+
| `headers` | `Record<string, string>` | -- | Custom headers for OTLP requests (e.g., auth tokens) |
|
|
63
|
+
| `exportTimeout` | `number` | `30000` | Export timeout in milliseconds |
|
|
64
|
+
| `ignoreUrls` | `(string \| RegExp)[]` | -- | URLs to exclude from fetch/XHR instrumentation |
|
|
65
|
+
| `instrumentations` | `InstrumentationConfig` | all enabled | Enable/disable specific auto-instrumentations |
|
|
66
|
+
| `resourceAttributes` | `Record<string, string>` | -- | Additional OTel resource attributes |
|
|
67
|
+
| `extensions` | `OtelExtension[]` | -- | Opt-in extensions (e.g., `withReactRouter()`) |
|
|
68
|
+
| `configureTracing` | `(provider) => void` | -- | Escape hatch to configure the TracerProvider |
|
|
69
|
+
| `configureExporter` | `(exporter) => void` | -- | Escape hatch to configure the OTLP exporter |
|
|
70
70
|
|
|
71
71
|
### Pointing to a Collector
|
|
72
72
|
|
|
@@ -86,11 +86,11 @@ All telemetry is sent to `http://localhost:4318` by default (the standard OTLP H
|
|
|
86
86
|
<OtelProvider
|
|
87
87
|
serviceName="my-app"
|
|
88
88
|
instrumentations={{
|
|
89
|
-
fetch: true,
|
|
90
|
-
xhr: false,
|
|
91
|
-
documentLoad: true,
|
|
89
|
+
fetch: true, // default: true
|
|
90
|
+
xhr: false, // disable XHR instrumentation
|
|
91
|
+
documentLoad: true, // default: true
|
|
92
92
|
userInteraction: false, // disable click tracking
|
|
93
|
-
webVitals: true,
|
|
93
|
+
webVitals: true, // default: true
|
|
94
94
|
}}
|
|
95
95
|
>
|
|
96
96
|
<App />
|
|
@@ -104,11 +104,7 @@ Useful for health checks, analytics endpoints, or any URL that shouldn't generat
|
|
|
104
104
|
```tsx
|
|
105
105
|
<OtelProvider
|
|
106
106
|
serviceName="my-app"
|
|
107
|
-
ignoreUrls={[
|
|
108
|
-
/\/health$/,
|
|
109
|
-
/\/analytics/,
|
|
110
|
-
'https://cdn.example.com',
|
|
111
|
-
]}
|
|
107
|
+
ignoreUrls={[/\/health$/, /\/analytics/, 'https://cdn.example.com']}
|
|
112
108
|
>
|
|
113
109
|
<App />
|
|
114
110
|
</OtelProvider>
|
|
@@ -170,6 +166,7 @@ The fallback can also be a render function that receives the error and a reset c
|
|
|
170
166
|
```
|
|
171
167
|
|
|
172
168
|
Each caught error generates:
|
|
169
|
+
|
|
173
170
|
- A span with `error.type`, `error.message`, `error.stack`, and `error.component_stack` attributes
|
|
174
171
|
- A log record at `ERROR` severity with the same details
|
|
175
172
|
|
|
@@ -220,10 +217,7 @@ import { OtelProvider, withReactRouter } from '@raccoon.ninja/otel-react';
|
|
|
220
217
|
|
|
221
218
|
function App() {
|
|
222
219
|
return (
|
|
223
|
-
<OtelProvider
|
|
224
|
-
serviceName="my-app"
|
|
225
|
-
extensions={[withReactRouter()]}
|
|
226
|
-
>
|
|
220
|
+
<OtelProvider serviceName="my-app" extensions={[withReactRouter()]}>
|
|
227
221
|
<RouterProvider router={router} />
|
|
228
222
|
</OtelProvider>
|
|
229
223
|
);
|
|
@@ -234,38 +228,38 @@ function App() {
|
|
|
234
228
|
|
|
235
229
|
### Traces (Automatic)
|
|
236
230
|
|
|
237
|
-
| Signal
|
|
238
|
-
|
|
239
|
-
| `fetch()` calls
|
|
240
|
-
| `XMLHttpRequest`
|
|
241
|
-
| Document load
|
|
242
|
-
| User interactions | `@opentelemetry/instrumentation-user-interaction` | Click events on DOM elements
|
|
243
|
-
| Error boundary
|
|
231
|
+
| Signal | Source | What It Captures |
|
|
232
|
+
| ----------------- | ------------------------------------------------- | ------------------------------------ |
|
|
233
|
+
| `fetch()` calls | `@opentelemetry/instrumentation-fetch` | URL, method, status, duration |
|
|
234
|
+
| `XMLHttpRequest` | `@opentelemetry/instrumentation-xml-http-request` | URL, method, status, duration |
|
|
235
|
+
| Document load | `@opentelemetry/instrumentation-document-load` | DNS, TCP, TLS, DOM processing |
|
|
236
|
+
| User interactions | `@opentelemetry/instrumentation-user-interaction` | Click events on DOM elements |
|
|
237
|
+
| Error boundary | `TracedErrorBoundary` | Uncaught errors with component stack |
|
|
244
238
|
|
|
245
239
|
### Metrics (Automatic)
|
|
246
240
|
|
|
247
|
-
| Metric
|
|
248
|
-
|
|
249
|
-
| `web_vitals.lcp`
|
|
250
|
-
| `web_vitals.cls`
|
|
251
|
-
| `web_vitals.inp`
|
|
252
|
-
| `web_vitals.ttfb` | Histogram | Time to First Byte (ms)
|
|
253
|
-
| `web_vitals.fcp`
|
|
241
|
+
| Metric | Type | Description |
|
|
242
|
+
| ----------------- | --------- | ------------------------------ |
|
|
243
|
+
| `web_vitals.lcp` | Histogram | Largest Contentful Paint (ms) |
|
|
244
|
+
| `web_vitals.cls` | Histogram | Cumulative Layout Shift |
|
|
245
|
+
| `web_vitals.inp` | Histogram | Interaction to Next Paint (ms) |
|
|
246
|
+
| `web_vitals.ttfb` | Histogram | Time to First Byte (ms) |
|
|
247
|
+
| `web_vitals.fcp` | Histogram | First Contentful Paint (ms) |
|
|
254
248
|
|
|
255
249
|
Each metric includes `web_vitals.rating` (`good`, `needs-improvement`, `poor`) and `page.url` attributes.
|
|
256
250
|
|
|
257
251
|
### Resource Attributes (Automatic)
|
|
258
252
|
|
|
259
|
-
| Attribute
|
|
260
|
-
|
|
261
|
-
| `service.name`
|
|
262
|
-
| `service.version`
|
|
263
|
-
| `deployment.environment` | Config (optional)
|
|
264
|
-
| `telemetry.sdk.name`
|
|
265
|
-
| `telemetry.sdk.version`
|
|
266
|
-
| `browser.language`
|
|
267
|
-
| `browser.user_agent`
|
|
268
|
-
| `browser.platform`
|
|
253
|
+
| Attribute | Source |
|
|
254
|
+
| ------------------------ | --------------------------- |
|
|
255
|
+
| `service.name` | Config (required) |
|
|
256
|
+
| `service.version` | Config (optional) |
|
|
257
|
+
| `deployment.environment` | Config (optional) |
|
|
258
|
+
| `telemetry.sdk.name` | `@raccoon.ninja/otel-react` |
|
|
259
|
+
| `telemetry.sdk.version` | Package version |
|
|
260
|
+
| `browser.language` | `navigator.language` |
|
|
261
|
+
| `browser.user_agent` | `navigator.userAgent` |
|
|
262
|
+
| `browser.platform` | `navigator.platform` |
|
|
269
263
|
|
|
270
264
|
Custom attributes can be added via the `resourceAttributes` prop.
|
|
271
265
|
|
|
@@ -283,6 +277,7 @@ const otel = await initOtel({
|
|
|
283
277
|
```
|
|
284
278
|
|
|
285
279
|
Key differences from the browser entry:
|
|
280
|
+
|
|
286
281
|
- Uses `BasicTracerProvider` instead of `WebTracerProvider` (no DOM APIs)
|
|
287
282
|
- Only `fetch` instrumentation is enabled (no document load, user interaction, or Web Vitals)
|
|
288
283
|
- XHR is disabled by default to avoid duplicate spans (React Native's `fetch` polyfills over XHR)
|
|
@@ -337,11 +332,7 @@ export async function register() {
|
|
|
337
332
|
import { OtelProvider } from '@raccoon.ninja/otel-react';
|
|
338
333
|
|
|
339
334
|
export function Providers({ children }: { children: React.ReactNode }) {
|
|
340
|
-
return
|
|
341
|
-
<OtelProvider serviceName="my-nextjs-app">
|
|
342
|
-
{children}
|
|
343
|
-
</OtelProvider>
|
|
344
|
-
);
|
|
335
|
+
return <OtelProvider serviceName="my-nextjs-app">{children}</OtelProvider>;
|
|
345
336
|
}
|
|
346
337
|
|
|
347
338
|
// app/layout.tsx
|
|
@@ -371,11 +362,11 @@ receivers:
|
|
|
371
362
|
endpoint: 0.0.0.0:4318
|
|
372
363
|
cors:
|
|
373
364
|
allowed_origins:
|
|
374
|
-
-
|
|
375
|
-
-
|
|
365
|
+
- 'https://your-app.com'
|
|
366
|
+
- 'http://localhost:3000'
|
|
376
367
|
allowed_headers:
|
|
377
|
-
-
|
|
378
|
-
-
|
|
368
|
+
- 'Content-Type'
|
|
369
|
+
- 'X-Requested-With'
|
|
379
370
|
max_age: 7200
|
|
380
371
|
```
|
|
381
372
|
|
|
@@ -394,32 +385,32 @@ This ensures telemetry is not lost during page navigation or tab close.
|
|
|
394
385
|
|
|
395
386
|
### Exports from `@raccoon.ninja/otel-react`
|
|
396
387
|
|
|
397
|
-
| Export
|
|
398
|
-
|
|
399
|
-
| `OtelProvider`
|
|
400
|
-
| `TracedErrorBoundary`
|
|
401
|
-
| `initOtel`
|
|
402
|
-
| `useTracer`
|
|
403
|
-
| `withReactRouter`
|
|
404
|
-
| `OtelOptions`
|
|
405
|
-
| `OtelHandle`
|
|
406
|
-
| `OtelExtension`
|
|
407
|
-
| `InstrumentationConfig`
|
|
408
|
-
| `OtelProviderProps`
|
|
409
|
-
| `TracedErrorBoundaryProps` | Type
|
|
388
|
+
| Export | Type | Description |
|
|
389
|
+
| -------------------------- | --------- | ------------------------------------------------ |
|
|
390
|
+
| `OtelProvider` | Component | React provider that initializes OTel on mount |
|
|
391
|
+
| `TracedErrorBoundary` | Component | Error boundary that records errors as spans/logs |
|
|
392
|
+
| `initOtel` | Function | Imperative initialization, returns `OtelHandle` |
|
|
393
|
+
| `useTracer` | Hook | Get an OTel `Tracer` for custom spans |
|
|
394
|
+
| `withReactRouter` | Function | Extension for React Router route tracing |
|
|
395
|
+
| `OtelOptions` | Type | Configuration interface |
|
|
396
|
+
| `OtelHandle` | Type | Handle with `shutdown()` method |
|
|
397
|
+
| `OtelExtension` | Type | Extension function signature |
|
|
398
|
+
| `InstrumentationConfig` | Type | Instrumentation toggle config |
|
|
399
|
+
| `OtelProviderProps` | Type | Props for `<OtelProvider>` |
|
|
400
|
+
| `TracedErrorBoundaryProps` | Type | Props for `<TracedErrorBoundary>` |
|
|
410
401
|
|
|
411
402
|
### Exports from `@raccoon.ninja/otel-react/native`
|
|
412
403
|
|
|
413
|
-
| Export
|
|
414
|
-
|
|
415
|
-
| `initOtel`
|
|
416
|
-
| `withReactNavigation`
|
|
417
|
-
| `createNavigationTracker` | Function | Creates `onStateChange` handler
|
|
404
|
+
| Export | Type | Description |
|
|
405
|
+
| ------------------------- | -------- | ---------------------------------- |
|
|
406
|
+
| `initOtel` | Function | RN-specific initialization (async) |
|
|
407
|
+
| `withReactNavigation` | Function | Extension for React Navigation |
|
|
408
|
+
| `createNavigationTracker` | Function | Creates `onStateChange` handler |
|
|
418
409
|
|
|
419
410
|
### Exports from `@raccoon.ninja/otel-react/nextjs`
|
|
420
411
|
|
|
421
|
-
| Export
|
|
422
|
-
|
|
412
|
+
| Export | Type | Description |
|
|
413
|
+
| ---------------- | -------- | --------------------------------------------------- |
|
|
423
414
|
| `initOtelServer` | Function | Server-side initialization for `instrumentation.ts` |
|
|
424
415
|
|
|
425
416
|
## Requirements
|
package/dist/index.cjs
CHANGED
|
@@ -66,7 +66,7 @@ function validateOptions(options) {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
var SDK_NAME = "@raccoon.ninja/otel-react";
|
|
69
|
-
var SDK_VERSION = "0.0.
|
|
69
|
+
var SDK_VERSION = "0.0.2";
|
|
70
70
|
function buildResource(options) {
|
|
71
71
|
const attributes = {
|
|
72
72
|
[semanticConventions.ATTR_SERVICE_NAME]: options.serviceName,
|
|
@@ -412,10 +412,7 @@ var TracedErrorBoundary = class extends react.Component {
|
|
|
412
412
|
};
|
|
413
413
|
var DEFAULT_TRACER_NAME = "@raccoon.ninja/otel-react/custom";
|
|
414
414
|
function useTracer(name, version) {
|
|
415
|
-
return react.useMemo(
|
|
416
|
-
() => api.trace.getTracer(name ?? DEFAULT_TRACER_NAME, version),
|
|
417
|
-
[name, version]
|
|
418
|
-
);
|
|
415
|
+
return react.useMemo(() => api.trace.getTracer(name ?? DEFAULT_TRACER_NAME, version), [name, version]);
|
|
419
416
|
}
|
|
420
417
|
var TRACER_NAME2 = "@raccoon.ninja/otel-react/router";
|
|
421
418
|
function withReactRouter() {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/options.ts","../src/core/resource.ts","../src/providers/tracer.ts","../src/providers/logger.ts","../src/providers/meter.ts","../src/instrumentations/auto.ts","../src/instrumentations/web-vitals.ts","../src/core/shutdown.ts","../src/core/init.ts","../src/components/OtelProvider.tsx","../src/components/TracedErrorBoundary.tsx","../src/hooks/useTracer.ts","../src/instrumentations/router.ts"],"names":["ATTR_SERVICE_NAME","ATTR_SERVICE_VERSION","SEMRESATTRS_DEPLOYMENT_ENVIRONMENT","resourceFromAttributes","OTLPTraceExporter","WebTracerProvider","BatchSpanProcessor","OTLPLogExporter","LoggerProvider","BatchLogRecordProcessor","logs","OTLPMetricExporter","MeterProvider","PeriodicExportingMetricReader","metrics","FetchInstrumentation","XMLHttpRequestInstrumentation","DocumentLoadInstrumentation","UserInteractionInstrumentation","registerInstrumentations","SeverityNumber","useRef","useEffect","Component","trace","SpanStatusCode","useMemo","TRACER_NAME"],"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 { WebTracerProvider } from '@opentelemetry/sdk-trace-web';\nimport { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';\nimport type { Resource } from '@opentelemetry/resources';\nimport type { OtelOptions } from '../core/options';\nimport { resolveEndpoint, resolveExportTimeout } from '../core/options';\n\nexport interface TracerSetupResult {\n provider: WebTracerProvider;\n exporter: OTLPTraceExporter;\n}\n\nexport function createTracerProvider(options: OtelOptions, resource: Resource): TracerSetupResult {\n const endpoint = resolveEndpoint(options);\n const timeout = resolveExportTimeout(options);\n\n const exporter = new OTLPTraceExporter({\n url: `${endpoint}/v1/traces`,\n headers: options.headers,\n timeoutMillis: timeout,\n });\n\n options.configureExporter?.(exporter);\n\n const provider = new WebTracerProvider({\n resource,\n spanProcessors: [new BatchSpanProcessor(exporter)],\n });\n\n options.configureTracing?.(provider);\n\n provider.register();\n\n return { provider, exporter };\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 { registerInstrumentations } from '@opentelemetry/instrumentation';\nimport { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch';\nimport { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request';\nimport { DocumentLoadInstrumentation } from '@opentelemetry/instrumentation-document-load';\nimport { UserInteractionInstrumentation } from '@opentelemetry/instrumentation-user-interaction';\nimport type { InstrumentationConfig, OtelOptions } from '../core/options';\nimport { resolveInstrumentations } from '../core/options';\n\nexport function registerAutoInstrumentations(options: OtelOptions): void {\n const config: Required<InstrumentationConfig> = resolveInstrumentations(options);\n const ignoreUrls = options.ignoreUrls ?? [];\n\n const instrumentations = [];\n\n if (config.fetch) {\n instrumentations.push(\n new FetchInstrumentation({\n ignoreUrls,\n }),\n );\n }\n\n if (config.xhr) {\n instrumentations.push(\n new XMLHttpRequestInstrumentation({\n ignoreUrls,\n }),\n );\n }\n\n if (config.documentLoad) {\n instrumentations.push(new DocumentLoadInstrumentation());\n }\n\n if (config.userInteraction) {\n instrumentations.push(new UserInteractionInstrumentation());\n }\n\n if (instrumentations.length > 0) {\n registerInstrumentations({ instrumentations });\n }\n}\n","import { metrics } from '@opentelemetry/api';\nimport type { Metric } from 'web-vitals';\n\nconst METER_NAME = '@raccoon.ninja/otel-react/web-vitals';\n\nexport function startWebVitalsCollection(): void {\n const meter = metrics.getMeter(METER_NAME, '1.0.0');\n\n const lcpHistogram = meter.createHistogram('web_vitals.lcp', {\n description: 'Largest Contentful Paint',\n unit: 'ms',\n });\n\n const clsHistogram = meter.createHistogram('web_vitals.cls', {\n description: 'Cumulative Layout Shift',\n unit: '',\n });\n\n const inpHistogram = meter.createHistogram('web_vitals.inp', {\n description: 'Interaction to Next Paint',\n unit: 'ms',\n });\n\n const ttfbHistogram = meter.createHistogram('web_vitals.ttfb', {\n description: 'Time to First Byte',\n unit: 'ms',\n });\n\n const fcpHistogram = meter.createHistogram('web_vitals.fcp', {\n description: 'First Contentful Paint',\n unit: 'ms',\n });\n\n const recordMetric = (histogram: ReturnType<typeof meter.createHistogram>) => {\n return (metric: Metric) => {\n const attrs: Record<string, string> = {\n 'web_vitals.rating': metric.rating,\n };\n\n if (typeof window !== 'undefined' && window.location) {\n attrs['page.url'] = window.location.pathname;\n }\n\n histogram.record(metric.value, attrs);\n };\n };\n\n // Dynamic import to enable tree-shaking when web-vitals is not used\n import('web-vitals').then(({ onLCP, onCLS, onINP, onTTFB, onFCP }) => {\n onLCP(recordMetric(lcpHistogram));\n onCLS(recordMetric(clsHistogram));\n onINP(recordMetric(inpHistogram));\n onTTFB(recordMetric(ttfbHistogram));\n onFCP(recordMetric(fcpHistogram));\n });\n}\n","import type { WebTracerProvider } from '@opentelemetry/sdk-trace-web';\nimport type { LoggerProvider } from '@opentelemetry/sdk-logs';\nimport type { MeterProvider } from '@opentelemetry/sdk-metrics';\n\nexport interface ShutdownTargets {\n tracerProvider: WebTracerProvider;\n loggerProvider: LoggerProvider;\n meterProvider: MeterProvider;\n}\n\nlet shutdownTargets: ShutdownTargets | null = null;\nlet visibilityHandler: (() => void) | null = null;\nlet beforeUnloadHandler: (() => void) | null = null;\n\nexport function registerShutdownTargets(targets: ShutdownTargets): void {\n shutdownTargets = targets;\n\n visibilityHandler = () => {\n if (document.visibilityState === 'hidden') {\n flushAll();\n }\n };\n\n beforeUnloadHandler = () => {\n flushAll();\n };\n\n if (typeof document !== 'undefined') {\n document.addEventListener('visibilitychange', visibilityHandler);\n }\n if (typeof window !== 'undefined') {\n window.addEventListener('beforeunload', beforeUnloadHandler);\n }\n}\n\nfunction flushAll(): void {\n if (!shutdownTargets) return;\n\n try {\n shutdownTargets.tracerProvider.forceFlush();\n shutdownTargets.loggerProvider.forceFlush();\n shutdownTargets.meterProvider.forceFlush();\n } catch {\n // Flush is best-effort during page unload\n }\n}\n\nexport async function shutdown(): Promise<void> {\n if (!shutdownTargets) return;\n\n if (typeof document !== 'undefined' && visibilityHandler) {\n document.removeEventListener('visibilitychange', visibilityHandler);\n }\n if (typeof window !== 'undefined' && beforeUnloadHandler) {\n window.removeEventListener('beforeunload', beforeUnloadHandler);\n }\n\n try {\n await Promise.all([\n shutdownTargets.tracerProvider.forceFlush(),\n shutdownTargets.loggerProvider.forceFlush(),\n shutdownTargets.meterProvider.forceFlush(),\n ]);\n\n await Promise.all([\n shutdownTargets.tracerProvider.shutdown(),\n shutdownTargets.loggerProvider.shutdown(),\n shutdownTargets.meterProvider.shutdown(),\n ]);\n } finally {\n shutdownTargets = null;\n visibilityHandler = null;\n beforeUnloadHandler = null;\n }\n}\n","import { SeverityNumber } from '@opentelemetry/api-logs';\nimport type { OtelOptions, OtelHandle } from './options';\nimport { validateOptions, resolveInstrumentations } from './options';\nimport { buildResource } from './resource';\nimport { createTracerProvider } from '../providers/tracer';\nimport { createLoggerProvider } from '../providers/logger';\nimport { createMeterProvider } from '../providers/meter';\nimport { registerAutoInstrumentations } from '../instrumentations/auto';\nimport { startWebVitalsCollection } from '../instrumentations/web-vitals';\nimport { registerShutdownTargets, shutdown } from './shutdown';\n\nlet initialized = false;\n\nexport function initOtel(options: OtelOptions): OtelHandle {\n if (initialized) {\n console.warn(\n '[@raccoon.ninja/otel-react] initOtel() has already been called. Skipping re-initialization.',\n );\n return { shutdown };\n }\n\n validateOptions(options);\n\n const resource = buildResource(options);\n const { provider: tracerProvider } = createTracerProvider(options, resource);\n const loggerProvider = createLoggerProvider(options, resource);\n const meterProvider = createMeterProvider(options, resource);\n\n registerAutoInstrumentations(options);\n\n const instrumentationConfig = resolveInstrumentations(options);\n if (instrumentationConfig.webVitals) {\n startWebVitalsCollection();\n }\n\n registerShutdownTargets({ tracerProvider, loggerProvider, meterProvider });\n\n // Run extensions\n if (options.extensions) {\n for (const ext of options.extensions) {\n ext({ tracerProvider });\n }\n }\n\n // Log initialization success\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 initialized for service \"${options.serviceName}\"`,\n attributes: {\n 'otel.service_name': options.serviceName,\n },\n });\n\n initialized = true;\n\n return {\n shutdown: async () => {\n await shutdown();\n initialized = false;\n },\n };\n}\n\n/** Reset initialization state (for testing). */\nexport function _resetInitState(): void {\n initialized = false;\n}\n","import { useEffect, useRef, type ReactNode } from 'react';\nimport { initOtel } from '../core/init';\nimport type { OtelOptions, OtelHandle, OtelExtension } from '../core/options';\n\n/** Props for the OtelProvider component. */\nexport interface OtelProviderProps {\n /** Required. Sets the service.name resource attribute. */\n serviceName: string;\n /** OTLP HTTP endpoint. Default: 'http://localhost:4318' */\n endpoint?: string;\n /** Additional OTel resource attributes. */\n resourceAttributes?: Record<string, string>;\n /** Service version. */\n serviceVersion?: string;\n /** Deployment environment. */\n environment?: string;\n /** Enable/disable specific auto-instrumentations. */\n instrumentations?: OtelOptions['instrumentations'];\n /** Custom headers sent with OTLP export requests. */\n headers?: Record<string, string>;\n /** Export timeout in milliseconds. */\n exportTimeout?: number;\n /** URLs to exclude from fetch/XHR instrumentation. */\n ignoreUrls?: Array<string | RegExp>;\n /** Escape hatch: configure the TracerProvider. */\n configureTracing?: OtelOptions['configureTracing'];\n /** Escape hatch: configure the OTLP exporter. */\n configureExporter?: OtelOptions['configureExporter'];\n /** Extension functions for opt-in instrumentations. */\n extensions?: OtelExtension[];\n /** React children to render. */\n children: ReactNode;\n}\n\n/**\n * React Provider component that initializes OpenTelemetry on mount\n * and flushes/shuts down on unmount.\n *\n * @example\n * ```tsx\n * import { OtelProvider } from '@raccoon.ninja/otel-react';\n *\n * function App() {\n * return (\n * <OtelProvider serviceName=\"my-app\">\n * <RestOfTheApp />\n * </OtelProvider>\n * );\n * }\n * ```\n */\nexport function OtelProvider({\n children,\n serviceName,\n endpoint,\n resourceAttributes,\n serviceVersion,\n environment,\n instrumentations,\n headers,\n exportTimeout,\n ignoreUrls,\n configureTracing,\n configureExporter,\n extensions,\n}: OtelProviderProps) {\n const handleRef = useRef<OtelHandle | null>(null);\n\n useEffect(() => {\n const handle = initOtel({\n serviceName,\n endpoint,\n resourceAttributes,\n serviceVersion,\n environment,\n instrumentations,\n headers,\n exportTimeout,\n ignoreUrls,\n configureTracing,\n configureExporter,\n extensions,\n });\n\n handleRef.current = handle;\n\n return () => {\n handleRef.current?.shutdown();\n handleRef.current = null;\n };\n // We intentionally only run this on mount/unmount.\n // Config changes require remounting the provider.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return <>{children}</>;\n}\n","import { Component, type ReactNode, type ErrorInfo } from 'react';\nimport { trace, SpanStatusCode } from '@opentelemetry/api';\nimport { SeverityNumber } from '@opentelemetry/api-logs';\nimport { logs } from '@opentelemetry/api-logs';\n\nconst TRACER_NAME = '@raccoon.ninja/otel-react/error-boundary';\nconst LOGGER_NAME = '@raccoon.ninja/otel-react/error-boundary';\n\n/** Props for the TracedErrorBoundary component. */\nexport interface TracedErrorBoundaryProps {\n /** Fallback UI to render when an error is caught. */\n fallback: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n /** Optional callback when an error is caught. */\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n /** Children to render. */\n children: ReactNode;\n}\n\ninterface TracedErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\n/**\n * Error boundary that records caught errors as OpenTelemetry spans and logs.\n *\n * @example\n * ```tsx\n * import { TracedErrorBoundary } from '@raccoon.ninja/otel-react';\n *\n * <TracedErrorBoundary fallback={<ErrorPage />}>\n * <RiskyComponent />\n * </TracedErrorBoundary>\n * ```\n */\nexport class TracedErrorBoundary extends Component<\n TracedErrorBoundaryProps,\n TracedErrorBoundaryState\n> {\n constructor(props: TracedErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): TracedErrorBoundaryState {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n const tracer = trace.getTracer(TRACER_NAME, '1.0.0');\n const span = tracer.startSpan('error-boundary.catch');\n\n span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });\n span.setAttribute('error.type', error.name);\n span.setAttribute('error.message', error.message);\n\n if (error.stack) {\n span.setAttribute('error.stack', error.stack);\n }\n if (errorInfo.componentStack) {\n span.setAttribute('error.component_stack', errorInfo.componentStack);\n }\n\n span.recordException(error);\n span.end();\n\n // Also emit as a log record\n try {\n const logger = logs.getLogger(LOGGER_NAME, '1.0.0');\n logger.emit({\n severityNumber: SeverityNumber.ERROR,\n severityText: 'ERROR',\n body: `Unhandled error: ${error.message}`,\n attributes: {\n 'error.type': error.name,\n 'error.message': error.message,\n ...(error.stack ? { 'error.stack': error.stack } : {}),\n ...(errorInfo.componentStack\n ? { 'error.component_stack': errorInfo.componentStack }\n : {}),\n },\n });\n } catch {\n // Logging is best-effort\n }\n\n this.props.onError?.(error, errorInfo);\n }\n\n private reset = () => {\n this.setState({ hasError: false, error: null });\n };\n\n render() {\n if (this.state.hasError && this.state.error) {\n const { fallback } = this.props;\n if (typeof fallback === 'function') {\n return fallback(this.state.error, this.reset);\n }\n return fallback;\n }\n\n return this.props.children;\n }\n}\n","import { useMemo } from 'react';\nimport { trace, type Tracer } from '@opentelemetry/api';\n\nconst DEFAULT_TRACER_NAME = '@raccoon.ninja/otel-react/custom';\n\n/**\n * Hook to get an OpenTelemetry Tracer for creating custom spans.\n *\n * @param name - Optional tracer name. Defaults to '@raccoon.ninja/otel-react/custom'.\n * @param version - Optional tracer version.\n * @returns An OTel Tracer instance.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const tracer = useTracer();\n *\n * const handleClick = () => {\n * const span = tracer.startSpan('button-click');\n * // ... do work ...\n * span.end();\n * };\n * }\n * ```\n */\nexport function useTracer(name?: string, version?: string): Tracer {\n return useMemo(\n () => trace.getTracer(name ?? DEFAULT_TRACER_NAME, version),\n [name, version],\n );\n}\n","import { trace } from '@opentelemetry/api';\nimport type { OtelExtension, ExtensionContext } from '../core/options';\n\nconst TRACER_NAME = '@raccoon.ninja/otel-react/router';\n\n/**\n * Extension for React Router v6/v7 route-change tracing.\n *\n * Usage:\n * ```tsx\n * import { OtelProvider, withReactRouter } from '@raccoon.ninja/otel-react';\n *\n * <OtelProvider serviceName=\"my-app\" extensions={[withReactRouter()]}>\n * <App />\n * </OtelProvider>\n * ```\n *\n * Note: The actual hook-based integration should be used inside\n * a component that has access to React Router's context. This extension\n * registers the tracer scope for route-change spans.\n */\nexport function withReactRouter(): OtelExtension {\n return (_context: ExtensionContext) => {\n // Pre-register the tracer scope so route spans are properly attributed\n trace.getTracer(TRACER_NAME, '1.0.0');\n };\n}\n\n/** Tracer name for route-change spans, exported for use in hooks. */\nexport const ROUTER_TRACER_NAME = TRACER_NAME;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/options.ts","../src/core/resource.ts","../src/providers/tracer.ts","../src/providers/logger.ts","../src/providers/meter.ts","../src/instrumentations/auto.ts","../src/instrumentations/web-vitals.ts","../src/core/shutdown.ts","../src/core/init.ts","../src/components/OtelProvider.tsx","../src/components/TracedErrorBoundary.tsx","../src/hooks/useTracer.ts","../src/instrumentations/router.ts"],"names":["ATTR_SERVICE_NAME","ATTR_SERVICE_VERSION","SEMRESATTRS_DEPLOYMENT_ENVIRONMENT","resourceFromAttributes","OTLPTraceExporter","WebTracerProvider","BatchSpanProcessor","OTLPLogExporter","LoggerProvider","BatchLogRecordProcessor","logs","OTLPMetricExporter","MeterProvider","PeriodicExportingMetricReader","metrics","FetchInstrumentation","XMLHttpRequestInstrumentation","DocumentLoadInstrumentation","UserInteractionInstrumentation","registerInstrumentations","SeverityNumber","useRef","useEffect","Component","trace","SpanStatusCode","useMemo","TRACER_NAME"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAyEA,IAAM,gBAAA,GAAmB,uBAAA;AACzB,IAAM,sBAAA,GAAyB,GAAA;AAExB,SAAS,gBAAgB,OAAA,EAA8B;AAC5D,EAAA,OAAO,QAAQ,QAAA,IAAY,gBAAA;AAC7B;AAEO,SAAS,qBAAqB,OAAA,EAA8B;AACjE,EAAA,OAAO,QAAQ,aAAA,IAAiB,sBAAA;AAClC;AAEO,SAAS,wBAAwB,OAAA,EAAuD;AAC7F,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,OAAA,CAAQ,gBAAA,EAAkB,KAAA,IAAS,IAAA;AAAA,IAC1C,GAAA,EAAK,OAAA,CAAQ,gBAAA,EAAkB,GAAA,IAAO,IAAA;AAAA,IACtC,YAAA,EAAc,OAAA,CAAQ,gBAAA,EAAkB,YAAA,IAAgB,IAAA;AAAA,IACxD,eAAA,EAAiB,OAAA,CAAQ,gBAAA,EAAkB,eAAA,IAAmB,IAAA;AAAA,IAC9D,SAAA,EAAW,OAAA,CAAQ,gBAAA,EAAkB,SAAA,IAAa;AAAA,GACpD;AACF;AAEO,SAAS,gBAAgB,OAAA,EAA4B;AAC1D,EAAA,IAAI,CAAC,OAAA,CAAQ,WAAA,IAAe,OAAO,OAAA,CAAQ,gBAAgB,QAAA,EAAU;AACnE,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,IAAI,OAAA,CAAQ,WAAA,CAAY,IAAA,EAAK,KAAM,QAAQ,WAAA,EAAa;AACtD,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,IAAI,OAAA,CAAQ,aAAa,MAAA,EAAW;AAClC,IAAA,IAAI,OAAO,QAAQ,QAAA,KAAa,QAAA,IAAY,QAAQ,QAAA,CAAS,IAAA,OAAW,EAAA,EAAI;AAC1E,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,IAAI,OAAA,CAAQ,kBAAkB,MAAA,EAAW;AACvC,IAAA,IAAI,OAAO,OAAA,CAAQ,aAAA,KAAkB,QAAA,IAAY,OAAA,CAAQ,iBAAiB,CAAA,EAAG;AAC3E,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AAAA,EACF;AACF;AClHA,IAAM,QAAA,GAAW,2BAAA;AACjB,IAAM,WAAA,GAAc,OAAA;AAEb,SAAS,cAAc,OAAA,EAAsB;AAClD,EAAA,MAAM,UAAA,GAAqC;AAAA,IACzC,CAACA,qCAAiB,GAAG,OAAA,CAAQ,WAAA;AAAA,IAC7B,oBAAA,EAAsB,QAAA;AAAA,IACtB,uBAAA,EAAyB,WAAA;AAAA,IACzB,wBAAA,EAA0B;AAAA,GAC5B;AAEA,EAAA,IAAI,QAAQ,cAAA,EAAgB;AAC1B,IAAA,UAAA,CAAWC,wCAAoB,IAAI,OAAA,CAAQ,cAAA;AAAA,EAC7C;AAEA,EAAA,IAAI,QAAQ,WAAA,EAAa;AACvB,IAAA,UAAA,CAAWC,sDAAkC,IAAI,OAAA,CAAQ,WAAA;AAAA,EAC3D;AAEA,EAAA,IAAI,OAAO,cAAc,WAAA,EAAa;AACpC,IAAA,IAAI,UAAU,QAAA,EAAU;AACtB,MAAA,UAAA,CAAW,kBAAkB,IAAI,SAAA,CAAU,QAAA;AAAA,IAC7C;AACA,IAAA,IAAI,UAAU,SAAA,EAAW;AACvB,MAAA,UAAA,CAAW,oBAAoB,IAAI,SAAA,CAAU,SAAA;AAAA,IAC/C;AACA,IAAA,IAAI,UAAU,QAAA,EAAU;AACtB,MAAA,UAAA,CAAW,kBAAkB,IAAI,SAAA,CAAU,QAAA;AAAA,IAC7C;AAAA,EACF;AAEA,EAAA,IAAI,QAAQ,kBAAA,EAAoB;AAC9B,IAAA,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,OAAA,CAAQ,kBAAkB,CAAA;AAAA,EACtD;AAEA,EAAA,OAAOC,iCAAuB,UAAU,CAAA;AAC1C;AChCO,SAAS,oBAAA,CAAqB,SAAsB,QAAA,EAAuC;AAChG,EAAA,MAAM,QAAA,GAAW,gBAAgB,OAAO,CAAA;AACxC,EAAA,MAAM,OAAA,GAAU,qBAAqB,OAAO,CAAA;AAE5C,EAAA,MAAM,QAAA,GAAW,IAAIC,uCAAA,CAAkB;AAAA,IACrC,GAAA,EAAK,GAAG,QAAQ,CAAA,UAAA,CAAA;AAAA,IAChB,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,aAAA,EAAe;AAAA,GAChB,CAAA;AAED,EAAA,OAAA,CAAQ,oBAAoB,QAAQ,CAAA;AAEpC,EAAA,MAAM,QAAA,GAAW,IAAIC,6BAAA,CAAkB;AAAA,IACrC,QAAA;AAAA,IACA,cAAA,EAAgB,CAAC,IAAIC,+BAAA,CAAmB,QAAQ,CAAC;AAAA,GAClD,CAAA;AAED,EAAA,OAAA,CAAQ,mBAAmB,QAAQ,CAAA;AAEnC,EAAA,QAAA,CAAS,QAAA,EAAS;AAElB,EAAA,OAAO,EAAE,UAAU,QAAA,EAAS;AAC9B;AC3BO,SAAS,oBAAA,CAAqB,SAAsB,QAAA,EAAoC;AAC7F,EAAA,MAAM,QAAA,GAAW,gBAAgB,OAAO,CAAA;AACxC,EAAA,MAAM,OAAA,GAAU,qBAAqB,OAAO,CAAA;AAE5C,EAAA,MAAM,QAAA,GAAW,IAAIC,oCAAA,CAAgB;AAAA,IACnC,GAAA,EAAK,GAAG,QAAQ,CAAA,QAAA,CAAA;AAAA,IAChB,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,aAAA,EAAe;AAAA,GAChB,CAAA;AAED,EAAA,MAAM,QAAA,GAAW,IAAIC,sBAAA,CAAe,EAAE,UAAU,CAAA;AAChD,EAAA,QAAA,CAAS,qBAAA,CAAsB,IAAIC,+BAAA,CAAwB,QAAQ,CAAC,CAAA;AAEpE,EAAAC,YAAA,CAAK,wBAAwB,QAAQ,CAAA;AAErC,EAAA,OAAO,QAAA;AACT;AChBA,IAAM,yBAAA,GAA4B,GAAA;AAE3B,SAAS,mBAAA,CAAoB,SAAsB,QAAA,EAAmC;AAC3F,EAAA,MAAM,QAAA,GAAW,gBAAgB,OAAO,CAAA;AACxC,EAAA,MAAM,OAAA,GAAU,qBAAqB,OAAO,CAAA;AAE5C,EAAA,MAAM,QAAA,GAAW,IAAIC,0CAAA,CAAmB;AAAA,IACtC,GAAA,EAAK,GAAG,QAAQ,CAAA,WAAA,CAAA;AAAA,IAChB,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,aAAA,EAAe;AAAA,GAChB,CAAA;AAED,EAAA,MAAM,QAAA,GAAW,IAAIC,wBAAA,CAAc;AAAA,IACjC,QAAA;AAAA,IACA,OAAA,EAAS;AAAA,MACP,IAAIC,wCAAA,CAA8B;AAAA,QAChC,QAAA;AAAA,QACA,oBAAA,EAAsB;AAAA,OACvB;AAAA;AACH,GACD,CAAA;AAED,EAAAC,WAAA,CAAQ,uBAAuB,QAAQ,CAAA;AAEvC,EAAA,OAAO,QAAA;AACT;ACxBO,SAAS,6BAA6B,OAAA,EAA4B;AACvE,EAAA,MAAM,MAAA,GAA0C,wBAAwB,OAAO,CAAA;AAC/E,EAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,UAAA,IAAc,EAAC;AAE1C,EAAA,MAAM,mBAAmB,EAAC;AAE1B,EAAA,IAAI,OAAO,KAAA,EAAO;AAChB,IAAA,gBAAA,CAAiB,IAAA;AAAA,MACf,IAAIC,yCAAA,CAAqB;AAAA,QACvB;AAAA,OACD;AAAA,KACH;AAAA,EACF;AAEA,EAAA,IAAI,OAAO,GAAA,EAAK;AACd,IAAA,gBAAA,CAAiB,IAAA;AAAA,MACf,IAAIC,2DAAA,CAA8B;AAAA,QAChC;AAAA,OACD;AAAA,KACH;AAAA,EACF;AAEA,EAAA,IAAI,OAAO,YAAA,EAAc;AACvB,IAAA,gBAAA,CAAiB,IAAA,CAAK,IAAIC,uDAAA,EAA6B,CAAA;AAAA,EACzD;AAEA,EAAA,IAAI,OAAO,eAAA,EAAiB;AAC1B,IAAA,gBAAA,CAAiB,IAAA,CAAK,IAAIC,6DAAA,EAAgC,CAAA;AAAA,EAC5D;AAEA,EAAA,IAAI,gBAAA,CAAiB,SAAS,CAAA,EAAG;AAC/B,IAAAC,wCAAA,CAAyB,EAAE,kBAAkB,CAAA;AAAA,EAC/C;AACF;ACtCA,IAAM,UAAA,GAAa,sCAAA;AAEZ,SAAS,wBAAA,GAAiC;AAC/C,EAAA,MAAM,KAAA,GAAQL,WAAAA,CAAQ,QAAA,CAAS,UAAA,EAAY,OAAO,CAAA;AAElD,EAAA,MAAM,YAAA,GAAe,KAAA,CAAM,eAAA,CAAgB,gBAAA,EAAkB;AAAA,IAC3D,WAAA,EAAa,0BAAA;AAAA,IACb,IAAA,EAAM;AAAA,GACP,CAAA;AAED,EAAA,MAAM,YAAA,GAAe,KAAA,CAAM,eAAA,CAAgB,gBAAA,EAAkB;AAAA,IAC3D,WAAA,EAAa,yBAAA;AAAA,IACb,IAAA,EAAM;AAAA,GACP,CAAA;AAED,EAAA,MAAM,YAAA,GAAe,KAAA,CAAM,eAAA,CAAgB,gBAAA,EAAkB;AAAA,IAC3D,WAAA,EAAa,2BAAA;AAAA,IACb,IAAA,EAAM;AAAA,GACP,CAAA;AAED,EAAA,MAAM,aAAA,GAAgB,KAAA,CAAM,eAAA,CAAgB,iBAAA,EAAmB;AAAA,IAC7D,WAAA,EAAa,oBAAA;AAAA,IACb,IAAA,EAAM;AAAA,GACP,CAAA;AAED,EAAA,MAAM,YAAA,GAAe,KAAA,CAAM,eAAA,CAAgB,gBAAA,EAAkB;AAAA,IAC3D,WAAA,EAAa,wBAAA;AAAA,IACb,IAAA,EAAM;AAAA,GACP,CAAA;AAED,EAAA,MAAM,YAAA,GAAe,CAAC,SAAA,KAAwD;AAC5E,IAAA,OAAO,CAAC,MAAA,KAAmB;AACzB,MAAA,MAAM,KAAA,GAAgC;AAAA,QACpC,qBAAqB,MAAA,CAAO;AAAA,OAC9B;AAEA,MAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,MAAA,CAAO,QAAA,EAAU;AACpD,QAAA,KAAA,CAAM,UAAU,CAAA,GAAI,MAAA,CAAO,QAAA,CAAS,QAAA;AAAA,MACtC;AAEA,MAAA,SAAA,CAAU,MAAA,CAAO,MAAA,CAAO,KAAA,EAAO,KAAK,CAAA;AAAA,IACtC,CAAA;AAAA,EACF,CAAA;AAGA,EAAA,OAAO,YAAY,CAAA,CAAE,IAAA,CAAK,CAAC,EAAE,OAAO,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAM,KAAM;AACpE,IAAA,KAAA,CAAM,YAAA,CAAa,YAAY,CAAC,CAAA;AAChC,IAAA,KAAA,CAAM,YAAA,CAAa,YAAY,CAAC,CAAA;AAChC,IAAA,KAAA,CAAM,YAAA,CAAa,YAAY,CAAC,CAAA;AAChC,IAAA,MAAA,CAAO,YAAA,CAAa,aAAa,CAAC,CAAA;AAClC,IAAA,KAAA,CAAM,YAAA,CAAa,YAAY,CAAC,CAAA;AAAA,EAClC,CAAC,CAAA;AACH;;;AC7CA,IAAI,eAAA,GAA0C,IAAA;AAC9C,IAAI,iBAAA,GAAyC,IAAA;AAC7C,IAAI,mBAAA,GAA2C,IAAA;AAExC,SAAS,wBAAwB,OAAA,EAAgC;AACtE,EAAA,eAAA,GAAkB,OAAA;AAElB,EAAA,iBAAA,GAAoB,MAAM;AACxB,IAAA,IAAI,QAAA,CAAS,oBAAoB,QAAA,EAAU;AACzC,MAAA,QAAA,EAAS;AAAA,IACX;AAAA,EACF,CAAA;AAEA,EAAA,mBAAA,GAAsB,MAAM;AAC1B,IAAA,QAAA,EAAS;AAAA,EACX,CAAA;AAEA,EAAA,IAAI,OAAO,aAAa,WAAA,EAAa;AACnC,IAAA,QAAA,CAAS,gBAAA,CAAiB,oBAAoB,iBAAiB,CAAA;AAAA,EACjE;AACA,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACjC,IAAA,MAAA,CAAO,gBAAA,CAAiB,gBAAgB,mBAAmB,CAAA;AAAA,EAC7D;AACF;AAEA,SAAS,QAAA,GAAiB;AACxB,EAAA,IAAI,CAAC,eAAA,EAAiB;AAEtB,EAAA,IAAI;AACF,IAAA,eAAA,CAAgB,eAAe,UAAA,EAAW;AAC1C,IAAA,eAAA,CAAgB,eAAe,UAAA,EAAW;AAC1C,IAAA,eAAA,CAAgB,cAAc,UAAA,EAAW;AAAA,EAC3C,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAEA,eAAsB,QAAA,GAA0B;AAC9C,EAAA,IAAI,CAAC,eAAA,EAAiB;AAEtB,EAAA,IAAI,OAAO,QAAA,KAAa,WAAA,IAAe,iBAAA,EAAmB;AACxD,IAAA,QAAA,CAAS,mBAAA,CAAoB,oBAAoB,iBAAiB,CAAA;AAAA,EACpE;AACA,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,mBAAA,EAAqB;AACxD,IAAA,MAAA,CAAO,mBAAA,CAAoB,gBAAgB,mBAAmB,CAAA;AAAA,EAChE;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,QAAQ,GAAA,CAAI;AAAA,MAChB,eAAA,CAAgB,eAAe,UAAA,EAAW;AAAA,MAC1C,eAAA,CAAgB,eAAe,UAAA,EAAW;AAAA,MAC1C,eAAA,CAAgB,cAAc,UAAA;AAAW,KAC1C,CAAA;AAED,IAAA,MAAM,QAAQ,GAAA,CAAI;AAAA,MAChB,eAAA,CAAgB,eAAe,QAAA,EAAS;AAAA,MACxC,eAAA,CAAgB,eAAe,QAAA,EAAS;AAAA,MACxC,eAAA,CAAgB,cAAc,QAAA;AAAS,KACxC,CAAA;AAAA,EACH,CAAA,SAAE;AACA,IAAA,eAAA,GAAkB,IAAA;AAClB,IAAA,iBAAA,GAAoB,IAAA;AACpB,IAAA,mBAAA,GAAsB,IAAA;AAAA,EACxB;AACF;;;AC/DA,IAAI,WAAA,GAAc,KAAA;AAEX,SAAS,SAAS,OAAA,EAAkC;AACzD,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN;AAAA,KACF;AACA,IAAA,OAAO,EAAE,QAAA,EAAS;AAAA,EACpB;AAEA,EAAA,eAAA,CAAgB,OAAO,CAAA;AAEvB,EAAA,MAAM,QAAA,GAAW,cAAc,OAAO,CAAA;AACtC,EAAA,MAAM,EAAE,QAAA,EAAU,cAAA,EAAe,GAAI,oBAAA,CAAqB,SAAS,QAAQ,CAAA;AAC3E,EAAA,MAAM,cAAA,GAAiB,oBAAA,CAAqB,OAAA,EAAS,QAAQ,CAAA;AAC7D,EAAA,MAAM,aAAA,GAAgB,mBAAA,CAAoB,OAAA,EAAS,QAAQ,CAAA;AAE3D,EAAA,4BAAA,CAA6B,OAAO,CAAA;AAEpC,EAAA,MAAM,qBAAA,GAAwB,wBAAwB,OAAO,CAAA;AAC7D,EAAA,IAAI,sBAAsB,SAAA,EAAW;AACnC,IAAA,wBAAA,EAAyB;AAAA,EAC3B;AAEA,EAAA,uBAAA,CAAwB,EAAE,cAAA,EAAgB,cAAA,EAAgB,aAAA,EAAe,CAAA;AAGzE,EAAA,IAAI,QAAQ,UAAA,EAAY;AACtB,IAAA,KAAA,MAAW,GAAA,IAAO,QAAQ,UAAA,EAAY;AACpC,MAAA,GAAA,CAAI,EAAE,gBAAgB,CAAA;AAAA,IACxB;AAAA,EACF;AAGA,EAAA,MAAM,MAAA,GAAS,cAAA,CAAe,SAAA,CAAU,2BAAA,EAA6B,OAAO,CAAA;AAC5E,EAAA,MAAA,CAAO,IAAA,CAAK;AAAA,IACV,gBAAgBM,sBAAA,CAAe,IAAA;AAAA,IAC/B,YAAA,EAAc,MAAA;AAAA,IACd,IAAA,EAAM,CAAA,uCAAA,EAA0C,OAAA,CAAQ,WAAW,CAAA,CAAA,CAAA;AAAA,IACnE,UAAA,EAAY;AAAA,MACV,qBAAqB,OAAA,CAAQ;AAAA;AAC/B,GACD,CAAA;AAED,EAAA,WAAA,GAAc,IAAA;AAEd,EAAA,OAAO;AAAA,IACL,UAAU,YAAY;AACpB,MAAA,MAAM,QAAA,EAAS;AACf,MAAA,WAAA,GAAc,KAAA;AAAA,IAChB;AAAA,GACF;AACF;ACZO,SAAS,YAAA,CAAa;AAAA,EAC3B,QAAA;AAAA,EACA,WAAA;AAAA,EACA,QAAA;AAAA,EACA,kBAAA;AAAA,EACA,cAAA;AAAA,EACA,WAAA;AAAA,EACA,gBAAA;AAAA,EACA,OAAA;AAAA,EACA,aAAA;AAAA,EACA,UAAA;AAAA,EACA,gBAAA;AAAA,EACA,iBAAA;AAAA,EACA;AACF,CAAA,EAAsB;AACpB,EAAA,MAAM,SAAA,GAAYC,aAA0B,IAAI,CAAA;AAEhD,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,MAAM,SAAS,QAAA,CAAS;AAAA,MACtB,WAAA;AAAA,MACA,QAAA;AAAA,MACA,kBAAA;AAAA,MACA,cAAA;AAAA,MACA,WAAA;AAAA,MACA,gBAAA;AAAA,MACA,OAAA;AAAA,MACA,aAAA;AAAA,MACA,UAAA;AAAA,MACA,gBAAA;AAAA,MACA,iBAAA;AAAA,MACA;AAAA,KACD,CAAA;AAED,IAAA,SAAA,CAAU,OAAA,GAAU,MAAA;AAEpB,IAAA,OAAO,MAAM;AACX,MAAA,SAAA,CAAU,SAAS,QAAA,EAAS;AAC5B,MAAA,SAAA,CAAU,OAAA,GAAU,IAAA;AAAA,IACtB,CAAA;AAAA,EAIF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,6DAAU,QAAA,EAAS,CAAA;AACrB;AC3FA,IAAM,WAAA,GAAc,0CAAA;AACpB,IAAM,WAAA,GAAc,0CAAA;AA6Bb,IAAM,mBAAA,GAAN,cAAkCC,eAAA,CAGvC;AAAA,EACA,YAAY,KAAA,EAAiC;AAC3C,IAAA,KAAA,CAAM,KAAK,CAAA;AACX,IAAA,IAAA,CAAK,KAAA,GAAQ,EAAE,QAAA,EAAU,KAAA,EAAO,OAAO,IAAA,EAAK;AAAA,EAC9C;AAAA,EAEA,OAAO,yBAAyB,KAAA,EAAwC;AACtE,IAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,KAAA,EAAM;AAAA,EACjC;AAAA,EAEA,iBAAA,CAAkB,OAAc,SAAA,EAA4B;AAC1D,IAAA,MAAM,MAAA,GAASC,SAAA,CAAM,SAAA,CAAU,WAAA,EAAa,OAAO,CAAA;AACnD,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,SAAA,CAAU,sBAAsB,CAAA;AAEpD,IAAA,IAAA,CAAK,SAAA,CAAU,EAAE,IAAA,EAAMC,kBAAA,CAAe,OAAO,OAAA,EAAS,KAAA,CAAM,SAAS,CAAA;AACrE,IAAA,IAAA,CAAK,YAAA,CAAa,YAAA,EAAc,KAAA,CAAM,IAAI,CAAA;AAC1C,IAAA,IAAA,CAAK,YAAA,CAAa,eAAA,EAAiB,KAAA,CAAM,OAAO,CAAA;AAEhD,IAAA,IAAI,MAAM,KAAA,EAAO;AACf,MAAA,IAAA,CAAK,YAAA,CAAa,aAAA,EAAe,KAAA,CAAM,KAAK,CAAA;AAAA,IAC9C;AACA,IAAA,IAAI,UAAU,cAAA,EAAgB;AAC5B,MAAA,IAAA,CAAK,YAAA,CAAa,uBAAA,EAAyB,SAAA,CAAU,cAAc,CAAA;AAAA,IACrE;AAEA,IAAA,IAAA,CAAK,gBAAgB,KAAK,CAAA;AAC1B,IAAA,IAAA,CAAK,GAAA,EAAI;AAGT,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAASf,YAAAA,CAAK,SAAA,CAAU,WAAA,EAAa,OAAO,CAAA;AAClD,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,gBAAgBU,sBAAAA,CAAe,KAAA;AAAA,QAC/B,YAAA,EAAc,OAAA;AAAA,QACd,IAAA,EAAM,CAAA,iBAAA,EAAoB,KAAA,CAAM,OAAO,CAAA,CAAA;AAAA,QACvC,UAAA,EAAY;AAAA,UACV,cAAc,KAAA,CAAM,IAAA;AAAA,UACpB,iBAAiB,KAAA,CAAM,OAAA;AAAA,UACvB,GAAI,MAAM,KAAA,GAAQ,EAAE,eAAe,KAAA,CAAM,KAAA,KAAU,EAAC;AAAA,UACpD,GAAI,UAAU,cAAA,GACV,EAAE,yBAAyB,SAAA,CAAU,cAAA,KACrC;AAAC;AACP,OACD,CAAA;AAAA,IACH,CAAA,CAAA,MAAQ;AAAA,IAER;AAEA,IAAA,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,KAAA,EAAO,SAAS,CAAA;AAAA,EACvC;AAAA,EAEQ,QAAQ,MAAM;AACpB,IAAA,IAAA,CAAK,SAAS,EAAE,QAAA,EAAU,KAAA,EAAO,KAAA,EAAO,MAAM,CAAA;AAAA,EAChD,CAAA;AAAA,EAEA,MAAA,GAAS;AACP,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,QAAA,IAAY,IAAA,CAAK,MAAM,KAAA,EAAO;AAC3C,MAAA,MAAM,EAAE,QAAA,EAAS,GAAI,IAAA,CAAK,KAAA;AAC1B,MAAA,IAAI,OAAO,aAAa,UAAA,EAAY;AAClC,QAAA,OAAO,QAAA,CAAS,IAAA,CAAK,KAAA,CAAM,KAAA,EAAO,KAAK,KAAK,CAAA;AAAA,MAC9C;AACA,MAAA,OAAO,QAAA;AAAA,IACT;AAEA,IAAA,OAAO,KAAK,KAAA,CAAM,QAAA;AAAA,EACpB;AACF;ACrGA,IAAM,mBAAA,GAAsB,kCAAA;AAsBrB,SAAS,SAAA,CAAU,MAAe,OAAA,EAA0B;AACjE,EAAA,OAAOM,aAAA,CAAQ,MAAMF,SAAAA,CAAM,SAAA,CAAU,IAAA,IAAQ,mBAAA,EAAqB,OAAO,CAAA,EAAG,CAAC,IAAA,EAAM,OAAO,CAAC,CAAA;AAC7F;ACxBA,IAAMG,YAAAA,GAAc,kCAAA;AAkBb,SAAS,eAAA,GAAiC;AAC/C,EAAA,OAAO,CAAC,QAAA,KAA+B;AAErC,IAAAH,SAAAA,CAAM,SAAA,CAAUG,YAAAA,EAAa,OAAO,CAAA;AAAA,EACtC,CAAA;AACF","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.2';\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 { WebTracerProvider } from '@opentelemetry/sdk-trace-web';\nimport { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';\nimport type { Resource } from '@opentelemetry/resources';\nimport type { OtelOptions } from '../core/options';\nimport { resolveEndpoint, resolveExportTimeout } from '../core/options';\n\nexport interface TracerSetupResult {\n provider: WebTracerProvider;\n exporter: OTLPTraceExporter;\n}\n\nexport function createTracerProvider(options: OtelOptions, resource: Resource): TracerSetupResult {\n const endpoint = resolveEndpoint(options);\n const timeout = resolveExportTimeout(options);\n\n const exporter = new OTLPTraceExporter({\n url: `${endpoint}/v1/traces`,\n headers: options.headers,\n timeoutMillis: timeout,\n });\n\n options.configureExporter?.(exporter);\n\n const provider = new WebTracerProvider({\n resource,\n spanProcessors: [new BatchSpanProcessor(exporter)],\n });\n\n options.configureTracing?.(provider);\n\n provider.register();\n\n return { provider, exporter };\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 { registerInstrumentations } from '@opentelemetry/instrumentation';\nimport { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch';\nimport { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request';\nimport { DocumentLoadInstrumentation } from '@opentelemetry/instrumentation-document-load';\nimport { UserInteractionInstrumentation } from '@opentelemetry/instrumentation-user-interaction';\nimport type { InstrumentationConfig, OtelOptions } from '../core/options';\nimport { resolveInstrumentations } from '../core/options';\n\nexport function registerAutoInstrumentations(options: OtelOptions): void {\n const config: Required<InstrumentationConfig> = resolveInstrumentations(options);\n const ignoreUrls = options.ignoreUrls ?? [];\n\n const instrumentations = [];\n\n if (config.fetch) {\n instrumentations.push(\n new FetchInstrumentation({\n ignoreUrls,\n }),\n );\n }\n\n if (config.xhr) {\n instrumentations.push(\n new XMLHttpRequestInstrumentation({\n ignoreUrls,\n }),\n );\n }\n\n if (config.documentLoad) {\n instrumentations.push(new DocumentLoadInstrumentation());\n }\n\n if (config.userInteraction) {\n instrumentations.push(new UserInteractionInstrumentation());\n }\n\n if (instrumentations.length > 0) {\n registerInstrumentations({ instrumentations });\n }\n}\n","import { metrics } from '@opentelemetry/api';\nimport type { Metric } from 'web-vitals';\n\nconst METER_NAME = '@raccoon.ninja/otel-react/web-vitals';\n\nexport function startWebVitalsCollection(): void {\n const meter = metrics.getMeter(METER_NAME, '1.0.0');\n\n const lcpHistogram = meter.createHistogram('web_vitals.lcp', {\n description: 'Largest Contentful Paint',\n unit: 'ms',\n });\n\n const clsHistogram = meter.createHistogram('web_vitals.cls', {\n description: 'Cumulative Layout Shift',\n unit: '',\n });\n\n const inpHistogram = meter.createHistogram('web_vitals.inp', {\n description: 'Interaction to Next Paint',\n unit: 'ms',\n });\n\n const ttfbHistogram = meter.createHistogram('web_vitals.ttfb', {\n description: 'Time to First Byte',\n unit: 'ms',\n });\n\n const fcpHistogram = meter.createHistogram('web_vitals.fcp', {\n description: 'First Contentful Paint',\n unit: 'ms',\n });\n\n const recordMetric = (histogram: ReturnType<typeof meter.createHistogram>) => {\n return (metric: Metric) => {\n const attrs: Record<string, string> = {\n 'web_vitals.rating': metric.rating,\n };\n\n if (typeof window !== 'undefined' && window.location) {\n attrs['page.url'] = window.location.pathname;\n }\n\n histogram.record(metric.value, attrs);\n };\n };\n\n // Dynamic import to enable tree-shaking when web-vitals is not used\n import('web-vitals').then(({ onLCP, onCLS, onINP, onTTFB, onFCP }) => {\n onLCP(recordMetric(lcpHistogram));\n onCLS(recordMetric(clsHistogram));\n onINP(recordMetric(inpHistogram));\n onTTFB(recordMetric(ttfbHistogram));\n onFCP(recordMetric(fcpHistogram));\n });\n}\n","import type { WebTracerProvider } from '@opentelemetry/sdk-trace-web';\nimport type { LoggerProvider } from '@opentelemetry/sdk-logs';\nimport type { MeterProvider } from '@opentelemetry/sdk-metrics';\n\nexport interface ShutdownTargets {\n tracerProvider: WebTracerProvider;\n loggerProvider: LoggerProvider;\n meterProvider: MeterProvider;\n}\n\nlet shutdownTargets: ShutdownTargets | null = null;\nlet visibilityHandler: (() => void) | null = null;\nlet beforeUnloadHandler: (() => void) | null = null;\n\nexport function registerShutdownTargets(targets: ShutdownTargets): void {\n shutdownTargets = targets;\n\n visibilityHandler = () => {\n if (document.visibilityState === 'hidden') {\n flushAll();\n }\n };\n\n beforeUnloadHandler = () => {\n flushAll();\n };\n\n if (typeof document !== 'undefined') {\n document.addEventListener('visibilitychange', visibilityHandler);\n }\n if (typeof window !== 'undefined') {\n window.addEventListener('beforeunload', beforeUnloadHandler);\n }\n}\n\nfunction flushAll(): void {\n if (!shutdownTargets) return;\n\n try {\n shutdownTargets.tracerProvider.forceFlush();\n shutdownTargets.loggerProvider.forceFlush();\n shutdownTargets.meterProvider.forceFlush();\n } catch {\n // Flush is best-effort during page unload\n }\n}\n\nexport async function shutdown(): Promise<void> {\n if (!shutdownTargets) return;\n\n if (typeof document !== 'undefined' && visibilityHandler) {\n document.removeEventListener('visibilitychange', visibilityHandler);\n }\n if (typeof window !== 'undefined' && beforeUnloadHandler) {\n window.removeEventListener('beforeunload', beforeUnloadHandler);\n }\n\n try {\n await Promise.all([\n shutdownTargets.tracerProvider.forceFlush(),\n shutdownTargets.loggerProvider.forceFlush(),\n shutdownTargets.meterProvider.forceFlush(),\n ]);\n\n await Promise.all([\n shutdownTargets.tracerProvider.shutdown(),\n shutdownTargets.loggerProvider.shutdown(),\n shutdownTargets.meterProvider.shutdown(),\n ]);\n } finally {\n shutdownTargets = null;\n visibilityHandler = null;\n beforeUnloadHandler = null;\n }\n}\n","import { SeverityNumber } from '@opentelemetry/api-logs';\nimport type { OtelOptions, OtelHandle } from './options';\nimport { validateOptions, resolveInstrumentations } from './options';\nimport { buildResource } from './resource';\nimport { createTracerProvider } from '../providers/tracer';\nimport { createLoggerProvider } from '../providers/logger';\nimport { createMeterProvider } from '../providers/meter';\nimport { registerAutoInstrumentations } from '../instrumentations/auto';\nimport { startWebVitalsCollection } from '../instrumentations/web-vitals';\nimport { registerShutdownTargets, shutdown } from './shutdown';\n\nlet initialized = false;\n\nexport function initOtel(options: OtelOptions): OtelHandle {\n if (initialized) {\n console.warn(\n '[@raccoon.ninja/otel-react] initOtel() has already been called. Skipping re-initialization.',\n );\n return { shutdown };\n }\n\n validateOptions(options);\n\n const resource = buildResource(options);\n const { provider: tracerProvider } = createTracerProvider(options, resource);\n const loggerProvider = createLoggerProvider(options, resource);\n const meterProvider = createMeterProvider(options, resource);\n\n registerAutoInstrumentations(options);\n\n const instrumentationConfig = resolveInstrumentations(options);\n if (instrumentationConfig.webVitals) {\n startWebVitalsCollection();\n }\n\n registerShutdownTargets({ tracerProvider, loggerProvider, meterProvider });\n\n // Run extensions\n if (options.extensions) {\n for (const ext of options.extensions) {\n ext({ tracerProvider });\n }\n }\n\n // Log initialization success\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 initialized for service \"${options.serviceName}\"`,\n attributes: {\n 'otel.service_name': options.serviceName,\n },\n });\n\n initialized = true;\n\n return {\n shutdown: async () => {\n await shutdown();\n initialized = false;\n },\n };\n}\n\n/** Reset initialization state (for testing). */\nexport function _resetInitState(): void {\n initialized = false;\n}\n","import { useEffect, useRef, type ReactNode } from 'react';\nimport { initOtel } from '../core/init';\nimport type { OtelOptions, OtelHandle, OtelExtension } from '../core/options';\n\n/** Props for the OtelProvider component. */\nexport interface OtelProviderProps {\n /** Required. Sets the service.name resource attribute. */\n serviceName: string;\n /** OTLP HTTP endpoint. Default: 'http://localhost:4318' */\n endpoint?: string;\n /** Additional OTel resource attributes. */\n resourceAttributes?: Record<string, string>;\n /** Service version. */\n serviceVersion?: string;\n /** Deployment environment. */\n environment?: string;\n /** Enable/disable specific auto-instrumentations. */\n instrumentations?: OtelOptions['instrumentations'];\n /** Custom headers sent with OTLP export requests. */\n headers?: Record<string, string>;\n /** Export timeout in milliseconds. */\n exportTimeout?: number;\n /** URLs to exclude from fetch/XHR instrumentation. */\n ignoreUrls?: Array<string | RegExp>;\n /** Escape hatch: configure the TracerProvider. */\n configureTracing?: OtelOptions['configureTracing'];\n /** Escape hatch: configure the OTLP exporter. */\n configureExporter?: OtelOptions['configureExporter'];\n /** Extension functions for opt-in instrumentations. */\n extensions?: OtelExtension[];\n /** React children to render. */\n children: ReactNode;\n}\n\n/**\n * React Provider component that initializes OpenTelemetry on mount\n * and flushes/shuts down on unmount.\n *\n * @example\n * ```tsx\n * import { OtelProvider } from '@raccoon.ninja/otel-react';\n *\n * function App() {\n * return (\n * <OtelProvider serviceName=\"my-app\">\n * <RestOfTheApp />\n * </OtelProvider>\n * );\n * }\n * ```\n */\nexport function OtelProvider({\n children,\n serviceName,\n endpoint,\n resourceAttributes,\n serviceVersion,\n environment,\n instrumentations,\n headers,\n exportTimeout,\n ignoreUrls,\n configureTracing,\n configureExporter,\n extensions,\n}: OtelProviderProps) {\n const handleRef = useRef<OtelHandle | null>(null);\n\n useEffect(() => {\n const handle = initOtel({\n serviceName,\n endpoint,\n resourceAttributes,\n serviceVersion,\n environment,\n instrumentations,\n headers,\n exportTimeout,\n ignoreUrls,\n configureTracing,\n configureExporter,\n extensions,\n });\n\n handleRef.current = handle;\n\n return () => {\n handleRef.current?.shutdown();\n handleRef.current = null;\n };\n // We intentionally only run this on mount/unmount.\n // Config changes require remounting the provider.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return <>{children}</>;\n}\n","import { Component, type ReactNode, type ErrorInfo } from 'react';\nimport { trace, SpanStatusCode } from '@opentelemetry/api';\nimport { SeverityNumber } from '@opentelemetry/api-logs';\nimport { logs } from '@opentelemetry/api-logs';\n\nconst TRACER_NAME = '@raccoon.ninja/otel-react/error-boundary';\nconst LOGGER_NAME = '@raccoon.ninja/otel-react/error-boundary';\n\n/** Props for the TracedErrorBoundary component. */\nexport interface TracedErrorBoundaryProps {\n /** Fallback UI to render when an error is caught. */\n fallback: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n /** Optional callback when an error is caught. */\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n /** Children to render. */\n children: ReactNode;\n}\n\ninterface TracedErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\n/**\n * Error boundary that records caught errors as OpenTelemetry spans and logs.\n *\n * @example\n * ```tsx\n * import { TracedErrorBoundary } from '@raccoon.ninja/otel-react';\n *\n * <TracedErrorBoundary fallback={<ErrorPage />}>\n * <RiskyComponent />\n * </TracedErrorBoundary>\n * ```\n */\nexport class TracedErrorBoundary extends Component<\n TracedErrorBoundaryProps,\n TracedErrorBoundaryState\n> {\n constructor(props: TracedErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): TracedErrorBoundaryState {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n const tracer = trace.getTracer(TRACER_NAME, '1.0.0');\n const span = tracer.startSpan('error-boundary.catch');\n\n span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });\n span.setAttribute('error.type', error.name);\n span.setAttribute('error.message', error.message);\n\n if (error.stack) {\n span.setAttribute('error.stack', error.stack);\n }\n if (errorInfo.componentStack) {\n span.setAttribute('error.component_stack', errorInfo.componentStack);\n }\n\n span.recordException(error);\n span.end();\n\n // Also emit as a log record\n try {\n const logger = logs.getLogger(LOGGER_NAME, '1.0.0');\n logger.emit({\n severityNumber: SeverityNumber.ERROR,\n severityText: 'ERROR',\n body: `Unhandled error: ${error.message}`,\n attributes: {\n 'error.type': error.name,\n 'error.message': error.message,\n ...(error.stack ? { 'error.stack': error.stack } : {}),\n ...(errorInfo.componentStack\n ? { 'error.component_stack': errorInfo.componentStack }\n : {}),\n },\n });\n } catch {\n // Logging is best-effort\n }\n\n this.props.onError?.(error, errorInfo);\n }\n\n private reset = () => {\n this.setState({ hasError: false, error: null });\n };\n\n render() {\n if (this.state.hasError && this.state.error) {\n const { fallback } = this.props;\n if (typeof fallback === 'function') {\n return fallback(this.state.error, this.reset);\n }\n return fallback;\n }\n\n return this.props.children;\n }\n}\n","import { useMemo } from 'react';\nimport { trace, type Tracer } from '@opentelemetry/api';\n\nconst DEFAULT_TRACER_NAME = '@raccoon.ninja/otel-react/custom';\n\n/**\n * Hook to get an OpenTelemetry Tracer for creating custom spans.\n *\n * @param name - Optional tracer name. Defaults to '@raccoon.ninja/otel-react/custom'.\n * @param version - Optional tracer version.\n * @returns An OTel Tracer instance.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const tracer = useTracer();\n *\n * const handleClick = () => {\n * const span = tracer.startSpan('button-click');\n * // ... do work ...\n * span.end();\n * };\n * }\n * ```\n */\nexport function useTracer(name?: string, version?: string): Tracer {\n return useMemo(() => trace.getTracer(name ?? DEFAULT_TRACER_NAME, version), [name, version]);\n}\n","import { trace } from '@opentelemetry/api';\nimport type { OtelExtension, ExtensionContext } from '../core/options';\n\nconst TRACER_NAME = '@raccoon.ninja/otel-react/router';\n\n/**\n * Extension for React Router v6/v7 route-change tracing.\n *\n * Usage:\n * ```tsx\n * import { OtelProvider, withReactRouter } from '@raccoon.ninja/otel-react';\n *\n * <OtelProvider serviceName=\"my-app\" extensions={[withReactRouter()]}>\n * <App />\n * </OtelProvider>\n * ```\n *\n * Note: The actual hook-based integration should be used inside\n * a component that has access to React Router's context. This extension\n * registers the tracer scope for route-change spans.\n */\nexport function withReactRouter(): OtelExtension {\n return (_context: ExtensionContext) => {\n // Pre-register the tracer scope so route spans are properly attributed\n trace.getTracer(TRACER_NAME, '1.0.0');\n };\n}\n\n/** Tracer name for route-change spans, exported for use in hooks. */\nexport const ROUTER_TRACER_NAME = TRACER_NAME;\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -64,7 +64,7 @@ function validateOptions(options) {
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
var SDK_NAME = "@raccoon.ninja/otel-react";
|
|
67
|
-
var SDK_VERSION = "0.0.
|
|
67
|
+
var SDK_VERSION = "0.0.2";
|
|
68
68
|
function buildResource(options) {
|
|
69
69
|
const attributes = {
|
|
70
70
|
[ATTR_SERVICE_NAME]: options.serviceName,
|
|
@@ -410,10 +410,7 @@ var TracedErrorBoundary = class extends Component {
|
|
|
410
410
|
};
|
|
411
411
|
var DEFAULT_TRACER_NAME = "@raccoon.ninja/otel-react/custom";
|
|
412
412
|
function useTracer(name, version) {
|
|
413
|
-
return useMemo(
|
|
414
|
-
() => trace.getTracer(name ?? DEFAULT_TRACER_NAME, version),
|
|
415
|
-
[name, version]
|
|
416
|
-
);
|
|
413
|
+
return useMemo(() => trace.getTracer(name ?? DEFAULT_TRACER_NAME, version), [name, version]);
|
|
417
414
|
}
|
|
418
415
|
var TRACER_NAME2 = "@raccoon.ninja/otel-react/router";
|
|
419
416
|
function withReactRouter() {
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/options.ts","../src/core/resource.ts","../src/providers/tracer.ts","../src/providers/logger.ts","../src/providers/meter.ts","../src/instrumentations/auto.ts","../src/instrumentations/web-vitals.ts","../src/core/shutdown.ts","../src/core/init.ts","../src/components/OtelProvider.tsx","../src/components/TracedErrorBoundary.tsx","../src/hooks/useTracer.ts","../src/instrumentations/router.ts"],"names":["metrics","logs","SeverityNumber","trace","TRACER_NAME"],"mappings":"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","file":"index.mjs","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 { WebTracerProvider } from '@opentelemetry/sdk-trace-web';\nimport { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';\nimport type { Resource } from '@opentelemetry/resources';\nimport type { OtelOptions } from '../core/options';\nimport { resolveEndpoint, resolveExportTimeout } from '../core/options';\n\nexport interface TracerSetupResult {\n provider: WebTracerProvider;\n exporter: OTLPTraceExporter;\n}\n\nexport function createTracerProvider(options: OtelOptions, resource: Resource): TracerSetupResult {\n const endpoint = resolveEndpoint(options);\n const timeout = resolveExportTimeout(options);\n\n const exporter = new OTLPTraceExporter({\n url: `${endpoint}/v1/traces`,\n headers: options.headers,\n timeoutMillis: timeout,\n });\n\n options.configureExporter?.(exporter);\n\n const provider = new WebTracerProvider({\n resource,\n spanProcessors: [new BatchSpanProcessor(exporter)],\n });\n\n options.configureTracing?.(provider);\n\n provider.register();\n\n return { provider, exporter };\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 { registerInstrumentations } from '@opentelemetry/instrumentation';\nimport { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch';\nimport { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request';\nimport { DocumentLoadInstrumentation } from '@opentelemetry/instrumentation-document-load';\nimport { UserInteractionInstrumentation } from '@opentelemetry/instrumentation-user-interaction';\nimport type { InstrumentationConfig, OtelOptions } from '../core/options';\nimport { resolveInstrumentations } from '../core/options';\n\nexport function registerAutoInstrumentations(options: OtelOptions): void {\n const config: Required<InstrumentationConfig> = resolveInstrumentations(options);\n const ignoreUrls = options.ignoreUrls ?? [];\n\n const instrumentations = [];\n\n if (config.fetch) {\n instrumentations.push(\n new FetchInstrumentation({\n ignoreUrls,\n }),\n );\n }\n\n if (config.xhr) {\n instrumentations.push(\n new XMLHttpRequestInstrumentation({\n ignoreUrls,\n }),\n );\n }\n\n if (config.documentLoad) {\n instrumentations.push(new DocumentLoadInstrumentation());\n }\n\n if (config.userInteraction) {\n instrumentations.push(new UserInteractionInstrumentation());\n }\n\n if (instrumentations.length > 0) {\n registerInstrumentations({ instrumentations });\n }\n}\n","import { metrics } from '@opentelemetry/api';\nimport type { Metric } from 'web-vitals';\n\nconst METER_NAME = '@raccoon.ninja/otel-react/web-vitals';\n\nexport function startWebVitalsCollection(): void {\n const meter = metrics.getMeter(METER_NAME, '1.0.0');\n\n const lcpHistogram = meter.createHistogram('web_vitals.lcp', {\n description: 'Largest Contentful Paint',\n unit: 'ms',\n });\n\n const clsHistogram = meter.createHistogram('web_vitals.cls', {\n description: 'Cumulative Layout Shift',\n unit: '',\n });\n\n const inpHistogram = meter.createHistogram('web_vitals.inp', {\n description: 'Interaction to Next Paint',\n unit: 'ms',\n });\n\n const ttfbHistogram = meter.createHistogram('web_vitals.ttfb', {\n description: 'Time to First Byte',\n unit: 'ms',\n });\n\n const fcpHistogram = meter.createHistogram('web_vitals.fcp', {\n description: 'First Contentful Paint',\n unit: 'ms',\n });\n\n const recordMetric = (histogram: ReturnType<typeof meter.createHistogram>) => {\n return (metric: Metric) => {\n const attrs: Record<string, string> = {\n 'web_vitals.rating': metric.rating,\n };\n\n if (typeof window !== 'undefined' && window.location) {\n attrs['page.url'] = window.location.pathname;\n }\n\n histogram.record(metric.value, attrs);\n };\n };\n\n // Dynamic import to enable tree-shaking when web-vitals is not used\n import('web-vitals').then(({ onLCP, onCLS, onINP, onTTFB, onFCP }) => {\n onLCP(recordMetric(lcpHistogram));\n onCLS(recordMetric(clsHistogram));\n onINP(recordMetric(inpHistogram));\n onTTFB(recordMetric(ttfbHistogram));\n onFCP(recordMetric(fcpHistogram));\n });\n}\n","import type { WebTracerProvider } from '@opentelemetry/sdk-trace-web';\nimport type { LoggerProvider } from '@opentelemetry/sdk-logs';\nimport type { MeterProvider } from '@opentelemetry/sdk-metrics';\n\nexport interface ShutdownTargets {\n tracerProvider: WebTracerProvider;\n loggerProvider: LoggerProvider;\n meterProvider: MeterProvider;\n}\n\nlet shutdownTargets: ShutdownTargets | null = null;\nlet visibilityHandler: (() => void) | null = null;\nlet beforeUnloadHandler: (() => void) | null = null;\n\nexport function registerShutdownTargets(targets: ShutdownTargets): void {\n shutdownTargets = targets;\n\n visibilityHandler = () => {\n if (document.visibilityState === 'hidden') {\n flushAll();\n }\n };\n\n beforeUnloadHandler = () => {\n flushAll();\n };\n\n if (typeof document !== 'undefined') {\n document.addEventListener('visibilitychange', visibilityHandler);\n }\n if (typeof window !== 'undefined') {\n window.addEventListener('beforeunload', beforeUnloadHandler);\n }\n}\n\nfunction flushAll(): void {\n if (!shutdownTargets) return;\n\n try {\n shutdownTargets.tracerProvider.forceFlush();\n shutdownTargets.loggerProvider.forceFlush();\n shutdownTargets.meterProvider.forceFlush();\n } catch {\n // Flush is best-effort during page unload\n }\n}\n\nexport async function shutdown(): Promise<void> {\n if (!shutdownTargets) return;\n\n if (typeof document !== 'undefined' && visibilityHandler) {\n document.removeEventListener('visibilitychange', visibilityHandler);\n }\n if (typeof window !== 'undefined' && beforeUnloadHandler) {\n window.removeEventListener('beforeunload', beforeUnloadHandler);\n }\n\n try {\n await Promise.all([\n shutdownTargets.tracerProvider.forceFlush(),\n shutdownTargets.loggerProvider.forceFlush(),\n shutdownTargets.meterProvider.forceFlush(),\n ]);\n\n await Promise.all([\n shutdownTargets.tracerProvider.shutdown(),\n shutdownTargets.loggerProvider.shutdown(),\n shutdownTargets.meterProvider.shutdown(),\n ]);\n } finally {\n shutdownTargets = null;\n visibilityHandler = null;\n beforeUnloadHandler = null;\n }\n}\n","import { SeverityNumber } from '@opentelemetry/api-logs';\nimport type { OtelOptions, OtelHandle } from './options';\nimport { validateOptions, resolveInstrumentations } from './options';\nimport { buildResource } from './resource';\nimport { createTracerProvider } from '../providers/tracer';\nimport { createLoggerProvider } from '../providers/logger';\nimport { createMeterProvider } from '../providers/meter';\nimport { registerAutoInstrumentations } from '../instrumentations/auto';\nimport { startWebVitalsCollection } from '../instrumentations/web-vitals';\nimport { registerShutdownTargets, shutdown } from './shutdown';\n\nlet initialized = false;\n\nexport function initOtel(options: OtelOptions): OtelHandle {\n if (initialized) {\n console.warn(\n '[@raccoon.ninja/otel-react] initOtel() has already been called. Skipping re-initialization.',\n );\n return { shutdown };\n }\n\n validateOptions(options);\n\n const resource = buildResource(options);\n const { provider: tracerProvider } = createTracerProvider(options, resource);\n const loggerProvider = createLoggerProvider(options, resource);\n const meterProvider = createMeterProvider(options, resource);\n\n registerAutoInstrumentations(options);\n\n const instrumentationConfig = resolveInstrumentations(options);\n if (instrumentationConfig.webVitals) {\n startWebVitalsCollection();\n }\n\n registerShutdownTargets({ tracerProvider, loggerProvider, meterProvider });\n\n // Run extensions\n if (options.extensions) {\n for (const ext of options.extensions) {\n ext({ tracerProvider });\n }\n }\n\n // Log initialization success\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 initialized for service \"${options.serviceName}\"`,\n attributes: {\n 'otel.service_name': options.serviceName,\n },\n });\n\n initialized = true;\n\n return {\n shutdown: async () => {\n await shutdown();\n initialized = false;\n },\n };\n}\n\n/** Reset initialization state (for testing). */\nexport function _resetInitState(): void {\n initialized = false;\n}\n","import { useEffect, useRef, type ReactNode } from 'react';\nimport { initOtel } from '../core/init';\nimport type { OtelOptions, OtelHandle, OtelExtension } from '../core/options';\n\n/** Props for the OtelProvider component. */\nexport interface OtelProviderProps {\n /** Required. Sets the service.name resource attribute. */\n serviceName: string;\n /** OTLP HTTP endpoint. Default: 'http://localhost:4318' */\n endpoint?: string;\n /** Additional OTel resource attributes. */\n resourceAttributes?: Record<string, string>;\n /** Service version. */\n serviceVersion?: string;\n /** Deployment environment. */\n environment?: string;\n /** Enable/disable specific auto-instrumentations. */\n instrumentations?: OtelOptions['instrumentations'];\n /** Custom headers sent with OTLP export requests. */\n headers?: Record<string, string>;\n /** Export timeout in milliseconds. */\n exportTimeout?: number;\n /** URLs to exclude from fetch/XHR instrumentation. */\n ignoreUrls?: Array<string | RegExp>;\n /** Escape hatch: configure the TracerProvider. */\n configureTracing?: OtelOptions['configureTracing'];\n /** Escape hatch: configure the OTLP exporter. */\n configureExporter?: OtelOptions['configureExporter'];\n /** Extension functions for opt-in instrumentations. */\n extensions?: OtelExtension[];\n /** React children to render. */\n children: ReactNode;\n}\n\n/**\n * React Provider component that initializes OpenTelemetry on mount\n * and flushes/shuts down on unmount.\n *\n * @example\n * ```tsx\n * import { OtelProvider } from '@raccoon.ninja/otel-react';\n *\n * function App() {\n * return (\n * <OtelProvider serviceName=\"my-app\">\n * <RestOfTheApp />\n * </OtelProvider>\n * );\n * }\n * ```\n */\nexport function OtelProvider({\n children,\n serviceName,\n endpoint,\n resourceAttributes,\n serviceVersion,\n environment,\n instrumentations,\n headers,\n exportTimeout,\n ignoreUrls,\n configureTracing,\n configureExporter,\n extensions,\n}: OtelProviderProps) {\n const handleRef = useRef<OtelHandle | null>(null);\n\n useEffect(() => {\n const handle = initOtel({\n serviceName,\n endpoint,\n resourceAttributes,\n serviceVersion,\n environment,\n instrumentations,\n headers,\n exportTimeout,\n ignoreUrls,\n configureTracing,\n configureExporter,\n extensions,\n });\n\n handleRef.current = handle;\n\n return () => {\n handleRef.current?.shutdown();\n handleRef.current = null;\n };\n // We intentionally only run this on mount/unmount.\n // Config changes require remounting the provider.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return <>{children}</>;\n}\n","import { Component, type ReactNode, type ErrorInfo } from 'react';\nimport { trace, SpanStatusCode } from '@opentelemetry/api';\nimport { SeverityNumber } from '@opentelemetry/api-logs';\nimport { logs } from '@opentelemetry/api-logs';\n\nconst TRACER_NAME = '@raccoon.ninja/otel-react/error-boundary';\nconst LOGGER_NAME = '@raccoon.ninja/otel-react/error-boundary';\n\n/** Props for the TracedErrorBoundary component. */\nexport interface TracedErrorBoundaryProps {\n /** Fallback UI to render when an error is caught. */\n fallback: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n /** Optional callback when an error is caught. */\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n /** Children to render. */\n children: ReactNode;\n}\n\ninterface TracedErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\n/**\n * Error boundary that records caught errors as OpenTelemetry spans and logs.\n *\n * @example\n * ```tsx\n * import { TracedErrorBoundary } from '@raccoon.ninja/otel-react';\n *\n * <TracedErrorBoundary fallback={<ErrorPage />}>\n * <RiskyComponent />\n * </TracedErrorBoundary>\n * ```\n */\nexport class TracedErrorBoundary extends Component<\n TracedErrorBoundaryProps,\n TracedErrorBoundaryState\n> {\n constructor(props: TracedErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): TracedErrorBoundaryState {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n const tracer = trace.getTracer(TRACER_NAME, '1.0.0');\n const span = tracer.startSpan('error-boundary.catch');\n\n span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });\n span.setAttribute('error.type', error.name);\n span.setAttribute('error.message', error.message);\n\n if (error.stack) {\n span.setAttribute('error.stack', error.stack);\n }\n if (errorInfo.componentStack) {\n span.setAttribute('error.component_stack', errorInfo.componentStack);\n }\n\n span.recordException(error);\n span.end();\n\n // Also emit as a log record\n try {\n const logger = logs.getLogger(LOGGER_NAME, '1.0.0');\n logger.emit({\n severityNumber: SeverityNumber.ERROR,\n severityText: 'ERROR',\n body: `Unhandled error: ${error.message}`,\n attributes: {\n 'error.type': error.name,\n 'error.message': error.message,\n ...(error.stack ? { 'error.stack': error.stack } : {}),\n ...(errorInfo.componentStack\n ? { 'error.component_stack': errorInfo.componentStack }\n : {}),\n },\n });\n } catch {\n // Logging is best-effort\n }\n\n this.props.onError?.(error, errorInfo);\n }\n\n private reset = () => {\n this.setState({ hasError: false, error: null });\n };\n\n render() {\n if (this.state.hasError && this.state.error) {\n const { fallback } = this.props;\n if (typeof fallback === 'function') {\n return fallback(this.state.error, this.reset);\n }\n return fallback;\n }\n\n return this.props.children;\n }\n}\n","import { useMemo } from 'react';\nimport { trace, type Tracer } from '@opentelemetry/api';\n\nconst DEFAULT_TRACER_NAME = '@raccoon.ninja/otel-react/custom';\n\n/**\n * Hook to get an OpenTelemetry Tracer for creating custom spans.\n *\n * @param name - Optional tracer name. Defaults to '@raccoon.ninja/otel-react/custom'.\n * @param version - Optional tracer version.\n * @returns An OTel Tracer instance.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const tracer = useTracer();\n *\n * const handleClick = () => {\n * const span = tracer.startSpan('button-click');\n * // ... do work ...\n * span.end();\n * };\n * }\n * ```\n */\nexport function useTracer(name?: string, version?: string): Tracer {\n return useMemo(\n () => trace.getTracer(name ?? DEFAULT_TRACER_NAME, version),\n [name, version],\n );\n}\n","import { trace } from '@opentelemetry/api';\nimport type { OtelExtension, ExtensionContext } from '../core/options';\n\nconst TRACER_NAME = '@raccoon.ninja/otel-react/router';\n\n/**\n * Extension for React Router v6/v7 route-change tracing.\n *\n * Usage:\n * ```tsx\n * import { OtelProvider, withReactRouter } from '@raccoon.ninja/otel-react';\n *\n * <OtelProvider serviceName=\"my-app\" extensions={[withReactRouter()]}>\n * <App />\n * </OtelProvider>\n * ```\n *\n * Note: The actual hook-based integration should be used inside\n * a component that has access to React Router's context. This extension\n * registers the tracer scope for route-change spans.\n */\nexport function withReactRouter(): OtelExtension {\n return (_context: ExtensionContext) => {\n // Pre-register the tracer scope so route spans are properly attributed\n trace.getTracer(TRACER_NAME, '1.0.0');\n };\n}\n\n/** Tracer name for route-change spans, exported for use in hooks. */\nexport const ROUTER_TRACER_NAME = TRACER_NAME;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/options.ts","../src/core/resource.ts","../src/providers/tracer.ts","../src/providers/logger.ts","../src/providers/meter.ts","../src/instrumentations/auto.ts","../src/instrumentations/web-vitals.ts","../src/core/shutdown.ts","../src/core/init.ts","../src/components/OtelProvider.tsx","../src/components/TracedErrorBoundary.tsx","../src/hooks/useTracer.ts","../src/instrumentations/router.ts"],"names":["metrics","logs","SeverityNumber","trace","TRACER_NAME"],"mappings":"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","file":"index.mjs","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.2';\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 { WebTracerProvider } from '@opentelemetry/sdk-trace-web';\nimport { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';\nimport type { Resource } from '@opentelemetry/resources';\nimport type { OtelOptions } from '../core/options';\nimport { resolveEndpoint, resolveExportTimeout } from '../core/options';\n\nexport interface TracerSetupResult {\n provider: WebTracerProvider;\n exporter: OTLPTraceExporter;\n}\n\nexport function createTracerProvider(options: OtelOptions, resource: Resource): TracerSetupResult {\n const endpoint = resolveEndpoint(options);\n const timeout = resolveExportTimeout(options);\n\n const exporter = new OTLPTraceExporter({\n url: `${endpoint}/v1/traces`,\n headers: options.headers,\n timeoutMillis: timeout,\n });\n\n options.configureExporter?.(exporter);\n\n const provider = new WebTracerProvider({\n resource,\n spanProcessors: [new BatchSpanProcessor(exporter)],\n });\n\n options.configureTracing?.(provider);\n\n provider.register();\n\n return { provider, exporter };\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 { registerInstrumentations } from '@opentelemetry/instrumentation';\nimport { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch';\nimport { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request';\nimport { DocumentLoadInstrumentation } from '@opentelemetry/instrumentation-document-load';\nimport { UserInteractionInstrumentation } from '@opentelemetry/instrumentation-user-interaction';\nimport type { InstrumentationConfig, OtelOptions } from '../core/options';\nimport { resolveInstrumentations } from '../core/options';\n\nexport function registerAutoInstrumentations(options: OtelOptions): void {\n const config: Required<InstrumentationConfig> = resolveInstrumentations(options);\n const ignoreUrls = options.ignoreUrls ?? [];\n\n const instrumentations = [];\n\n if (config.fetch) {\n instrumentations.push(\n new FetchInstrumentation({\n ignoreUrls,\n }),\n );\n }\n\n if (config.xhr) {\n instrumentations.push(\n new XMLHttpRequestInstrumentation({\n ignoreUrls,\n }),\n );\n }\n\n if (config.documentLoad) {\n instrumentations.push(new DocumentLoadInstrumentation());\n }\n\n if (config.userInteraction) {\n instrumentations.push(new UserInteractionInstrumentation());\n }\n\n if (instrumentations.length > 0) {\n registerInstrumentations({ instrumentations });\n }\n}\n","import { metrics } from '@opentelemetry/api';\nimport type { Metric } from 'web-vitals';\n\nconst METER_NAME = '@raccoon.ninja/otel-react/web-vitals';\n\nexport function startWebVitalsCollection(): void {\n const meter = metrics.getMeter(METER_NAME, '1.0.0');\n\n const lcpHistogram = meter.createHistogram('web_vitals.lcp', {\n description: 'Largest Contentful Paint',\n unit: 'ms',\n });\n\n const clsHistogram = meter.createHistogram('web_vitals.cls', {\n description: 'Cumulative Layout Shift',\n unit: '',\n });\n\n const inpHistogram = meter.createHistogram('web_vitals.inp', {\n description: 'Interaction to Next Paint',\n unit: 'ms',\n });\n\n const ttfbHistogram = meter.createHistogram('web_vitals.ttfb', {\n description: 'Time to First Byte',\n unit: 'ms',\n });\n\n const fcpHistogram = meter.createHistogram('web_vitals.fcp', {\n description: 'First Contentful Paint',\n unit: 'ms',\n });\n\n const recordMetric = (histogram: ReturnType<typeof meter.createHistogram>) => {\n return (metric: Metric) => {\n const attrs: Record<string, string> = {\n 'web_vitals.rating': metric.rating,\n };\n\n if (typeof window !== 'undefined' && window.location) {\n attrs['page.url'] = window.location.pathname;\n }\n\n histogram.record(metric.value, attrs);\n };\n };\n\n // Dynamic import to enable tree-shaking when web-vitals is not used\n import('web-vitals').then(({ onLCP, onCLS, onINP, onTTFB, onFCP }) => {\n onLCP(recordMetric(lcpHistogram));\n onCLS(recordMetric(clsHistogram));\n onINP(recordMetric(inpHistogram));\n onTTFB(recordMetric(ttfbHistogram));\n onFCP(recordMetric(fcpHistogram));\n });\n}\n","import type { WebTracerProvider } from '@opentelemetry/sdk-trace-web';\nimport type { LoggerProvider } from '@opentelemetry/sdk-logs';\nimport type { MeterProvider } from '@opentelemetry/sdk-metrics';\n\nexport interface ShutdownTargets {\n tracerProvider: WebTracerProvider;\n loggerProvider: LoggerProvider;\n meterProvider: MeterProvider;\n}\n\nlet shutdownTargets: ShutdownTargets | null = null;\nlet visibilityHandler: (() => void) | null = null;\nlet beforeUnloadHandler: (() => void) | null = null;\n\nexport function registerShutdownTargets(targets: ShutdownTargets): void {\n shutdownTargets = targets;\n\n visibilityHandler = () => {\n if (document.visibilityState === 'hidden') {\n flushAll();\n }\n };\n\n beforeUnloadHandler = () => {\n flushAll();\n };\n\n if (typeof document !== 'undefined') {\n document.addEventListener('visibilitychange', visibilityHandler);\n }\n if (typeof window !== 'undefined') {\n window.addEventListener('beforeunload', beforeUnloadHandler);\n }\n}\n\nfunction flushAll(): void {\n if (!shutdownTargets) return;\n\n try {\n shutdownTargets.tracerProvider.forceFlush();\n shutdownTargets.loggerProvider.forceFlush();\n shutdownTargets.meterProvider.forceFlush();\n } catch {\n // Flush is best-effort during page unload\n }\n}\n\nexport async function shutdown(): Promise<void> {\n if (!shutdownTargets) return;\n\n if (typeof document !== 'undefined' && visibilityHandler) {\n document.removeEventListener('visibilitychange', visibilityHandler);\n }\n if (typeof window !== 'undefined' && beforeUnloadHandler) {\n window.removeEventListener('beforeunload', beforeUnloadHandler);\n }\n\n try {\n await Promise.all([\n shutdownTargets.tracerProvider.forceFlush(),\n shutdownTargets.loggerProvider.forceFlush(),\n shutdownTargets.meterProvider.forceFlush(),\n ]);\n\n await Promise.all([\n shutdownTargets.tracerProvider.shutdown(),\n shutdownTargets.loggerProvider.shutdown(),\n shutdownTargets.meterProvider.shutdown(),\n ]);\n } finally {\n shutdownTargets = null;\n visibilityHandler = null;\n beforeUnloadHandler = null;\n }\n}\n","import { SeverityNumber } from '@opentelemetry/api-logs';\nimport type { OtelOptions, OtelHandle } from './options';\nimport { validateOptions, resolveInstrumentations } from './options';\nimport { buildResource } from './resource';\nimport { createTracerProvider } from '../providers/tracer';\nimport { createLoggerProvider } from '../providers/logger';\nimport { createMeterProvider } from '../providers/meter';\nimport { registerAutoInstrumentations } from '../instrumentations/auto';\nimport { startWebVitalsCollection } from '../instrumentations/web-vitals';\nimport { registerShutdownTargets, shutdown } from './shutdown';\n\nlet initialized = false;\n\nexport function initOtel(options: OtelOptions): OtelHandle {\n if (initialized) {\n console.warn(\n '[@raccoon.ninja/otel-react] initOtel() has already been called. Skipping re-initialization.',\n );\n return { shutdown };\n }\n\n validateOptions(options);\n\n const resource = buildResource(options);\n const { provider: tracerProvider } = createTracerProvider(options, resource);\n const loggerProvider = createLoggerProvider(options, resource);\n const meterProvider = createMeterProvider(options, resource);\n\n registerAutoInstrumentations(options);\n\n const instrumentationConfig = resolveInstrumentations(options);\n if (instrumentationConfig.webVitals) {\n startWebVitalsCollection();\n }\n\n registerShutdownTargets({ tracerProvider, loggerProvider, meterProvider });\n\n // Run extensions\n if (options.extensions) {\n for (const ext of options.extensions) {\n ext({ tracerProvider });\n }\n }\n\n // Log initialization success\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 initialized for service \"${options.serviceName}\"`,\n attributes: {\n 'otel.service_name': options.serviceName,\n },\n });\n\n initialized = true;\n\n return {\n shutdown: async () => {\n await shutdown();\n initialized = false;\n },\n };\n}\n\n/** Reset initialization state (for testing). */\nexport function _resetInitState(): void {\n initialized = false;\n}\n","import { useEffect, useRef, type ReactNode } from 'react';\nimport { initOtel } from '../core/init';\nimport type { OtelOptions, OtelHandle, OtelExtension } from '../core/options';\n\n/** Props for the OtelProvider component. */\nexport interface OtelProviderProps {\n /** Required. Sets the service.name resource attribute. */\n serviceName: string;\n /** OTLP HTTP endpoint. Default: 'http://localhost:4318' */\n endpoint?: string;\n /** Additional OTel resource attributes. */\n resourceAttributes?: Record<string, string>;\n /** Service version. */\n serviceVersion?: string;\n /** Deployment environment. */\n environment?: string;\n /** Enable/disable specific auto-instrumentations. */\n instrumentations?: OtelOptions['instrumentations'];\n /** Custom headers sent with OTLP export requests. */\n headers?: Record<string, string>;\n /** Export timeout in milliseconds. */\n exportTimeout?: number;\n /** URLs to exclude from fetch/XHR instrumentation. */\n ignoreUrls?: Array<string | RegExp>;\n /** Escape hatch: configure the TracerProvider. */\n configureTracing?: OtelOptions['configureTracing'];\n /** Escape hatch: configure the OTLP exporter. */\n configureExporter?: OtelOptions['configureExporter'];\n /** Extension functions for opt-in instrumentations. */\n extensions?: OtelExtension[];\n /** React children to render. */\n children: ReactNode;\n}\n\n/**\n * React Provider component that initializes OpenTelemetry on mount\n * and flushes/shuts down on unmount.\n *\n * @example\n * ```tsx\n * import { OtelProvider } from '@raccoon.ninja/otel-react';\n *\n * function App() {\n * return (\n * <OtelProvider serviceName=\"my-app\">\n * <RestOfTheApp />\n * </OtelProvider>\n * );\n * }\n * ```\n */\nexport function OtelProvider({\n children,\n serviceName,\n endpoint,\n resourceAttributes,\n serviceVersion,\n environment,\n instrumentations,\n headers,\n exportTimeout,\n ignoreUrls,\n configureTracing,\n configureExporter,\n extensions,\n}: OtelProviderProps) {\n const handleRef = useRef<OtelHandle | null>(null);\n\n useEffect(() => {\n const handle = initOtel({\n serviceName,\n endpoint,\n resourceAttributes,\n serviceVersion,\n environment,\n instrumentations,\n headers,\n exportTimeout,\n ignoreUrls,\n configureTracing,\n configureExporter,\n extensions,\n });\n\n handleRef.current = handle;\n\n return () => {\n handleRef.current?.shutdown();\n handleRef.current = null;\n };\n // We intentionally only run this on mount/unmount.\n // Config changes require remounting the provider.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return <>{children}</>;\n}\n","import { Component, type ReactNode, type ErrorInfo } from 'react';\nimport { trace, SpanStatusCode } from '@opentelemetry/api';\nimport { SeverityNumber } from '@opentelemetry/api-logs';\nimport { logs } from '@opentelemetry/api-logs';\n\nconst TRACER_NAME = '@raccoon.ninja/otel-react/error-boundary';\nconst LOGGER_NAME = '@raccoon.ninja/otel-react/error-boundary';\n\n/** Props for the TracedErrorBoundary component. */\nexport interface TracedErrorBoundaryProps {\n /** Fallback UI to render when an error is caught. */\n fallback: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n /** Optional callback when an error is caught. */\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n /** Children to render. */\n children: ReactNode;\n}\n\ninterface TracedErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\n/**\n * Error boundary that records caught errors as OpenTelemetry spans and logs.\n *\n * @example\n * ```tsx\n * import { TracedErrorBoundary } from '@raccoon.ninja/otel-react';\n *\n * <TracedErrorBoundary fallback={<ErrorPage />}>\n * <RiskyComponent />\n * </TracedErrorBoundary>\n * ```\n */\nexport class TracedErrorBoundary extends Component<\n TracedErrorBoundaryProps,\n TracedErrorBoundaryState\n> {\n constructor(props: TracedErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): TracedErrorBoundaryState {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n const tracer = trace.getTracer(TRACER_NAME, '1.0.0');\n const span = tracer.startSpan('error-boundary.catch');\n\n span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });\n span.setAttribute('error.type', error.name);\n span.setAttribute('error.message', error.message);\n\n if (error.stack) {\n span.setAttribute('error.stack', error.stack);\n }\n if (errorInfo.componentStack) {\n span.setAttribute('error.component_stack', errorInfo.componentStack);\n }\n\n span.recordException(error);\n span.end();\n\n // Also emit as a log record\n try {\n const logger = logs.getLogger(LOGGER_NAME, '1.0.0');\n logger.emit({\n severityNumber: SeverityNumber.ERROR,\n severityText: 'ERROR',\n body: `Unhandled error: ${error.message}`,\n attributes: {\n 'error.type': error.name,\n 'error.message': error.message,\n ...(error.stack ? { 'error.stack': error.stack } : {}),\n ...(errorInfo.componentStack\n ? { 'error.component_stack': errorInfo.componentStack }\n : {}),\n },\n });\n } catch {\n // Logging is best-effort\n }\n\n this.props.onError?.(error, errorInfo);\n }\n\n private reset = () => {\n this.setState({ hasError: false, error: null });\n };\n\n render() {\n if (this.state.hasError && this.state.error) {\n const { fallback } = this.props;\n if (typeof fallback === 'function') {\n return fallback(this.state.error, this.reset);\n }\n return fallback;\n }\n\n return this.props.children;\n }\n}\n","import { useMemo } from 'react';\nimport { trace, type Tracer } from '@opentelemetry/api';\n\nconst DEFAULT_TRACER_NAME = '@raccoon.ninja/otel-react/custom';\n\n/**\n * Hook to get an OpenTelemetry Tracer for creating custom spans.\n *\n * @param name - Optional tracer name. Defaults to '@raccoon.ninja/otel-react/custom'.\n * @param version - Optional tracer version.\n * @returns An OTel Tracer instance.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const tracer = useTracer();\n *\n * const handleClick = () => {\n * const span = tracer.startSpan('button-click');\n * // ... do work ...\n * span.end();\n * };\n * }\n * ```\n */\nexport function useTracer(name?: string, version?: string): Tracer {\n return useMemo(() => trace.getTracer(name ?? DEFAULT_TRACER_NAME, version), [name, version]);\n}\n","import { trace } from '@opentelemetry/api';\nimport type { OtelExtension, ExtensionContext } from '../core/options';\n\nconst TRACER_NAME = '@raccoon.ninja/otel-react/router';\n\n/**\n * Extension for React Router v6/v7 route-change tracing.\n *\n * Usage:\n * ```tsx\n * import { OtelProvider, withReactRouter } from '@raccoon.ninja/otel-react';\n *\n * <OtelProvider serviceName=\"my-app\" extensions={[withReactRouter()]}>\n * <App />\n * </OtelProvider>\n * ```\n *\n * Note: The actual hook-based integration should be used inside\n * a component that has access to React Router's context. This extension\n * registers the tracer scope for route-change spans.\n */\nexport function withReactRouter(): OtelExtension {\n return (_context: ExtensionContext) => {\n // Pre-register the tracer scope so route spans are properly attributed\n trace.getTracer(TRACER_NAME, '1.0.0');\n };\n}\n\n/** Tracer name for route-change spans, exported for use in hooks. */\nexport const ROUTER_TRACER_NAME = TRACER_NAME;\n"]}
|
package/dist/native/index.cjs
CHANGED
|
@@ -54,7 +54,7 @@ function validateOptions(options) {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
var SDK_NAME = "@raccoon.ninja/otel-react";
|
|
57
|
-
var SDK_VERSION = "0.0.
|
|
57
|
+
var SDK_VERSION = "0.0.2";
|
|
58
58
|
function buildResource(options) {
|
|
59
59
|
const attributes = {
|
|
60
60
|
[semanticConventions.ATTR_SERVICE_NAME]: options.serviceName,
|
|
@@ -123,9 +123,7 @@ function createMeterProvider(options, resource) {
|
|
|
123
123
|
var initialized = false;
|
|
124
124
|
async function initOtelNative(options) {
|
|
125
125
|
if (initialized) {
|
|
126
|
-
console.warn(
|
|
127
|
-
"[@raccoon.ninja/otel-react] initOtelNative() has already been called. Skipping."
|
|
128
|
-
);
|
|
126
|
+
console.warn("[@raccoon.ninja/otel-react] initOtelNative() has already been called. Skipping.");
|
|
129
127
|
return {
|
|
130
128
|
shutdown: async () => {
|
|
131
129
|
}
|
|
@@ -1 +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"]}
|
|
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.2';\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 { validateOptions, resolveEndpoint, resolveExportTimeout } 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('[@raccoon.ninja/otel-react] initOtelNative() has already been called. Skipping.');\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"]}
|
package/dist/native/index.mjs
CHANGED
|
@@ -52,7 +52,7 @@ function validateOptions(options) {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
var SDK_NAME = "@raccoon.ninja/otel-react";
|
|
55
|
-
var SDK_VERSION = "0.0.
|
|
55
|
+
var SDK_VERSION = "0.0.2";
|
|
56
56
|
function buildResource(options) {
|
|
57
57
|
const attributes = {
|
|
58
58
|
[ATTR_SERVICE_NAME]: options.serviceName,
|
|
@@ -121,9 +121,7 @@ function createMeterProvider(options, resource) {
|
|
|
121
121
|
var initialized = false;
|
|
122
122
|
async function initOtelNative(options) {
|
|
123
123
|
if (initialized) {
|
|
124
|
-
console.warn(
|
|
125
|
-
"[@raccoon.ninja/otel-react] initOtelNative() has already been called. Skipping."
|
|
126
|
-
);
|
|
124
|
+
console.warn("[@raccoon.ninja/otel-react] initOtelNative() has already been called. Skipping.");
|
|
127
125
|
return {
|
|
128
126
|
shutdown: async () => {
|
|
129
127
|
}
|
|
@@ -1 +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":["trace"],"mappings":";;;;;;;;;;;;;;;;;;;AAyEA,IAAM,gBAAA,GAAmB,uBAAA;AACzB,IAAM,sBAAA,GAAyB,GAAA;AAExB,SAAS,gBAAgB,OAAA,EAA8B;AAC5D,EAAA,OAAO,QAAQ,QAAA,IAAY,gBAAA;AAC7B;AAEO,SAAS,qBAAqB,OAAA,EAA8B;AACjE,EAAA,OAAO,QAAQ,aAAA,IAAiB,sBAAA;AAClC;AAYO,SAAS,gBAAgB,OAAA,EAA4B;AAC1D,EAAA,IAAI,CAAC,OAAA,CAAQ,WAAA,IAAe,OAAO,OAAA,CAAQ,gBAAgB,QAAA,EAAU;AACnE,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,IAAI,OAAA,CAAQ,WAAA,CAAY,IAAA,EAAK,KAAM,QAAQ,WAAA,EAAa;AACtD,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,IAAI,OAAA,CAAQ,aAAa,MAAA,EAAW;AAClC,IAAA,IAAI,OAAO,QAAQ,QAAA,KAAa,QAAA,IAAY,QAAQ,QAAA,CAAS,IAAA,OAAW,EAAA,EAAI;AAC1E,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,IAAI,OAAA,CAAQ,kBAAkB,MAAA,EAAW;AACvC,IAAA,IAAI,OAAO,OAAA,CAAQ,aAAA,KAAkB,QAAA,IAAY,OAAA,CAAQ,iBAAiB,CAAA,EAAG;AAC3E,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AAAA,EACF;AACF;AClHA,IAAM,QAAA,GAAW,2BAAA;AACjB,IAAM,WAAA,GAAc,OAAA;AAEb,SAAS,cAAc,OAAA,EAAsB;AAClD,EAAA,MAAM,UAAA,GAAqC;AAAA,IACzC,CAAC,iBAAiB,GAAG,OAAA,CAAQ,WAAA;AAAA,IAC7B,oBAAA,EAAsB,QAAA;AAAA,IACtB,uBAAA,EAAyB,WAAA;AAAA,IACzB,wBAAA,EAA0B;AAAA,GAC5B;AAEA,EAAA,IAAI,QAAQ,cAAA,EAAgB;AAC1B,IAAA,UAAA,CAAW,oBAAoB,IAAI,OAAA,CAAQ,cAAA;AAAA,EAC7C;AAEA,EAAA,IAAI,QAAQ,WAAA,EAAa;AACvB,IAAA,UAAA,CAAW,kCAAkC,IAAI,OAAA,CAAQ,WAAA;AAAA,EAC3D;AAEA,EAAA,IAAI,OAAO,cAAc,WAAA,EAAa;AACpC,IAAA,IAAI,UAAU,QAAA,EAAU;AACtB,MAAA,UAAA,CAAW,kBAAkB,IAAI,SAAA,CAAU,QAAA;AAAA,IAC7C;AACA,IAAA,IAAI,UAAU,SAAA,EAAW;AACvB,MAAA,UAAA,CAAW,oBAAoB,IAAI,SAAA,CAAU,SAAA;AAAA,IAC/C;AACA,IAAA,IAAI,UAAU,QAAA,EAAU;AACtB,MAAA,UAAA,CAAW,kBAAkB,IAAI,SAAA,CAAU,QAAA;AAAA,IAC7C;AAAA,EACF;AAEA,EAAA,IAAI,QAAQ,kBAAA,EAAoB;AAC9B,IAAA,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,OAAA,CAAQ,kBAAkB,CAAA;AAAA,EACtD;AAEA,EAAA,OAAO,uBAAuB,UAAU,CAAA;AAC1C;ACrCO,SAAS,oBAAA,CAAqB,SAAsB,QAAA,EAAoC;AAC7F,EAAA,MAAM,QAAA,GAAW,gBAAgB,OAAO,CAAA;AACxC,EAAA,MAAM,OAAA,GAAU,qBAAqB,OAAO,CAAA;AAE5C,EAAA,MAAM,QAAA,GAAW,IAAI,eAAA,CAAgB;AAAA,IACnC,GAAA,EAAK,GAAG,QAAQ,CAAA,QAAA,CAAA;AAAA,IAChB,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,aAAA,EAAe;AAAA,GAChB,CAAA;AAED,EAAA,MAAM,QAAA,GAAW,IAAI,cAAA,CAAe,EAAE,UAAU,CAAA;AAChD,EAAA,QAAA,CAAS,qBAAA,CAAsB,IAAI,uBAAA,CAAwB,QAAQ,CAAC,CAAA;AAEpE,EAAA,IAAA,CAAK,wBAAwB,QAAQ,CAAA;AAErC,EAAA,OAAO,QAAA;AACT;AChBA,IAAM,yBAAA,GAA4B,GAAA;AAE3B,SAAS,mBAAA,CAAoB,SAAsB,QAAA,EAAmC;AAC3F,EAAA,MAAM,QAAA,GAAW,gBAAgB,OAAO,CAAA;AACxC,EAAA,MAAM,OAAA,GAAU,qBAAqB,OAAO,CAAA;AAE5C,EAAA,MAAM,QAAA,GAAW,IAAI,kBAAA,CAAmB;AAAA,IACtC,GAAA,EAAK,GAAG,QAAQ,CAAA,WAAA,CAAA;AAAA,IAChB,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,aAAA,EAAe;AAAA,GAChB,CAAA;AAED,EAAA,MAAM,QAAA,GAAW,IAAI,aAAA,CAAc;AAAA,IACjC,QAAA;AAAA,IACA,OAAA,EAAS;AAAA,MACP,IAAI,6BAAA,CAA8B;AAAA,QAChC,QAAA;AAAA,QACA,oBAAA,EAAsB;AAAA,OACvB;AAAA;AACH,GACD,CAAA;AAED,EAAA,OAAA,CAAQ,uBAAuB,QAAQ,CAAA;AAEvC,EAAA,OAAO,QAAA;AACT;;;AClBA,IAAI,WAAA,GAAc,KAAA;AAWlB,eAAsB,eAAe,OAAA,EAA2C;AAC9E,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN;AAAA,KACF;AACA,IAAA,OAAO;AAAA,MACL,UAAU,YAAY;AAAA,MAEtB;AAAA,KACF;AAAA,EACF;AAEA,EAAA,eAAA,CAAgB,OAAO,CAAA;AAEvB,EAAA,MAAM,QAAA,GAAW,cAAc,OAAO,CAAA;AACtC,EAAA,MAAM,QAAA,GAAW,gBAAgB,OAAO,CAAA;AACxC,EAAA,MAAM,OAAA,GAAU,qBAAqB,OAAO,CAAA;AAE5C,EAAA,MAAM,aAAA,GAAgB,IAAI,iBAAA,CAAkB;AAAA,IAC1C,GAAA,EAAK,GAAG,QAAQ,CAAA,UAAA,CAAA;AAAA,IAChB,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,aAAA,EAAe;AAAA,GAChB,CAAA;AAED,EAAA,MAAM,cAAA,GAAiB,IAAI,mBAAA,CAAoB;AAAA,IAC7C,QAAA;AAAA,IACA,cAAA,EAAgB,CAAC,IAAI,kBAAA,CAAmB,aAAa,CAAC;AAAA,GACvD,CAAA;AAGD,EAAA,KAAA,CAAM,wBAAwB,cAAc,CAAA;AAE5C,EAAA,MAAM,cAAA,GAAiB,oBAAA,CAAqB,OAAA,EAAS,QAAQ,CAAA;AAC7D,EAAA,MAAM,aAAA,GAAgB,mBAAA,CAAoB,OAAA,EAAS,QAAQ,CAAA;AAG3D,EAAA,IAAI,oBAAA,GAAsD,IAAA;AAC1D,EAAA,IAAI;AAGF,IAAA,MAAM,EAAE,QAAA,EAAS,GAAI,SAAA,CAAQ,cAAc,CAAA;AAQ3C,IAAA,oBAAA,GAAuB,QAAA,CAAS,gBAAA,CAAiB,QAAA,EAAU,CAAC,SAAA,KAAsB;AAChF,MAAA,IAAI,SAAA,KAAc,YAAA,IAAgB,SAAA,KAAc,UAAA,EAAY;AAC1D,QAAA,cAAA,CAAe,UAAA,EAAW;AAC1B,QAAA,cAAA,CAAe,UAAA,EAAW;AAC1B,QAAA,aAAA,CAAc,UAAA,EAAW;AAAA,MAC3B;AAAA,IACF,CAAC,CAAA;AAAA,EACH,CAAA,CAAA,MAAQ;AAAA,EAER;AAEA,EAAA,MAAM,MAAA,GAAS,cAAA,CAAe,SAAA,CAAU,2BAAA,EAA6B,OAAO,CAAA;AAC5E,EAAA,MAAA,CAAO,IAAA,CAAK;AAAA,IACV,gBAAgB,cAAA,CAAe,IAAA;AAAA,IAC/B,YAAA,EAAc,MAAA;AAAA,IACd,IAAA,EAAM,CAAA,4CAAA,EAA+C,OAAA,CAAQ,WAAW,CAAA,CAAA;AAAA,GACzE,CAAA;AAED,EAAA,WAAA,GAAc,IAAA;AAEd,EAAA,OAAO;AAAA,IACL,UAAU,YAAY;AACpB,MAAA,oBAAA,EAAsB,MAAA,EAAO;AAC7B,MAAA,MAAM,QAAQ,GAAA,CAAI;AAAA,QAChB,eAAe,UAAA,EAAW;AAAA,QAC1B,eAAe,UAAA,EAAW;AAAA,QAC1B,cAAc,UAAA;AAAW,OAC1B,CAAA;AACD,MAAA,MAAM,QAAQ,GAAA,CAAI;AAAA,QAChB,eAAe,QAAA,EAAS;AAAA,QACxB,eAAe,QAAA,EAAS;AAAA,QACxB,cAAc,QAAA;AAAS,OACxB,CAAA;AACD,MAAA,WAAA,GAAc,KAAA;AAAA,IAChB;AAAA,GACF;AACF;AC1GA,IAAM,WAAA,GAAc,4CAAA;AAmBb,SAAS,mBAAA,GAAqC;AACnD,EAAA,OAAO,MAAM;AACX,IAAAA,KAAAA,CAAM,SAAA,CAAU,WAAA,EAAa,OAAO,CAAA;AAAA,EACtC,CAAA;AACF;AAOO,SAAS,uBAAA,GAA0B;AACxC,EAAA,MAAM,MAAA,GAASA,KAAAA,CAAM,SAAA,CAAU,WAAA,EAAa,OAAO,CAAA;AACnD,EAAA,IAAI,iBAAA;AAEJ,EAAA,OAAO,CAAC,KAAA,KAA0E;AAChF,IAAA,IAAI,CAAC,KAAA,EAAO;AAEZ,IAAA,MAAM,YAAA,GAAe,KAAA,CAAM,MAAA,CAAO,KAAA,CAAM,KAAK,CAAA;AAC7C,IAAA,IAAI,CAAC,YAAA,EAAc;AAEnB,IAAA,MAAM,mBAAmB,YAAA,CAAa,IAAA;AAEtC,IAAA,IAAI,iBAAA,IAAqB,sBAAsB,gBAAA,EAAkB;AAC/D,MAAA,MAAM,IAAA,GAAO,MAAA,CAAO,SAAA,CAAU,yBAAyB,CAAA;AACvD,MAAA,IAAA,CAAK,YAAA,CAAa,mBAAmB,iBAAiB,CAAA;AACtD,MAAA,IAAA,CAAK,YAAA,CAAa,iBAAiB,gBAAgB,CAAA;AACnD,MAAA,IAAA,CAAK,SAAA,CAAU,EAAE,IAAA,EAAM,cAAA,CAAe,IAAI,CAAA;AAC1C,MAAA,IAAA,CAAK,GAAA,EAAI;AAAA,IACX;AAEA,IAAA,iBAAA,GAAoB,gBAAA;AAAA,EACtB,CAAA;AACF","file":"index.mjs","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"]}
|
|
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":["trace"],"mappings":"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","file":"index.mjs","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.2';\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 { validateOptions, resolveEndpoint, resolveExportTimeout } 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('[@raccoon.ninja/otel-react] initOtelNative() has already been called. Skipping.');\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"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/options.ts","../../src/nextjs/server.ts"],"names":[],"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 type { OtelOptions, OtelHandle } from '../core/options';\nimport { validateOptions, resolveEndpoint, resolveExportTimeout } from '../core/options';\n\n/**\n * Initialize OpenTelemetry for Next.js server-side (instrumentation.ts).\n *\n * This function wraps the Node.js OTel SDK setup for use in Next.js's\n * `instrumentation.ts` file.\n *\n * @example\n * ```typescript\n * // instrumentation.ts\n * import { initOtelServer } from '@raccoon.ninja/otel-react/nextjs';\n *\n * export function register() {\n * initOtelServer({ serviceName: 'my-nextjs-app' });\n * }\n * ```\n */\nexport async function initOtelServer(options: OtelOptions): Promise<OtelHandle> {\n validateOptions(options);\n\n const runtime = process.env.NEXT_RUNTIME;\n if (runtime === 'edge') {\n console.warn(\n '[@raccoon.ninja/otel-react] Edge runtime detected. Server OTel is limited to Node.js runtime.',\n );\n return { shutdown: async () => {} };\n }\n\n const endpoint = resolveEndpoint(options);\n const timeout = resolveExportTimeout(options);\n\n // Dynamic imports to prevent bundling Node.js SDK in client builds.\n // These packages must be installed separately by the user as they are\n // Node.js-only and not included in this package's dependencies.\n const { BasicTracerProvider, BatchSpanProcessor } = await import(\n '@opentelemetry/sdk-trace-base'\n );\n const { OTLPTraceExporter } = await import('@opentelemetry/exporter-trace-otlp-http');\n const { OTLPLogExporter } = await import('@opentelemetry/exporter-logs-otlp-http');\n const { LoggerProvider, BatchLogRecordProcessor } = await import('@opentelemetry/sdk-logs');\n const { resourceFromAttributes } = await import('@opentelemetry/resources');\n const { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION, SEMRESATTRS_DEPLOYMENT_ENVIRONMENT } =\n await import('@opentelemetry/semantic-conventions');\n const { trace } = await import('@opentelemetry/api');\n const { logs } = await import('@opentelemetry/api-logs');\n\n const attributes: Record<string, string> = {\n [ATTR_SERVICE_NAME]: options.serviceName,\n 'telemetry.sdk.name': '@raccoon.ninja/otel-react',\n 'telemetry.sdk.version': '1.0.0',\n };\n\n if (options.serviceVersion) {\n attributes[ATTR_SERVICE_VERSION] = options.serviceVersion;\n }\n if (options.environment) {\n attributes[SEMRESATTRS_DEPLOYMENT_ENVIRONMENT] = options.environment;\n }\n if (options.resourceAttributes) {\n Object.assign(attributes, options.resourceAttributes);\n }\n\n const resource = resourceFromAttributes(attributes);\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 trace.setGlobalTracerProvider(tracerProvider);\n\n const logExporter = new OTLPLogExporter({\n url: `${endpoint}/v1/logs`,\n headers: options.headers,\n timeoutMillis: timeout,\n });\n\n const loggerProvider = new LoggerProvider({ resource });\n loggerProvider.addLogRecordProcessor(new BatchLogRecordProcessor(logExporter));\n logs.setGlobalLoggerProvider(loggerProvider);\n\n return {\n shutdown: async () => {\n await Promise.all([tracerProvider.forceFlush(), loggerProvider.forceFlush()]);\n await Promise.all([tracerProvider.shutdown(), loggerProvider.shutdown()]);\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/core/options.ts","../../src/nextjs/server.ts"],"names":[],"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 type { OtelOptions, OtelHandle } from '../core/options';\nimport { validateOptions, resolveEndpoint, resolveExportTimeout } from '../core/options';\n\n/**\n * Initialize OpenTelemetry for Next.js server-side (instrumentation.ts).\n *\n * This function wraps the Node.js OTel SDK setup for use in Next.js's\n * `instrumentation.ts` file.\n *\n * @example\n * ```typescript\n * // instrumentation.ts\n * import { initOtelServer } from '@raccoon.ninja/otel-react/nextjs';\n *\n * export function register() {\n * initOtelServer({ serviceName: 'my-nextjs-app' });\n * }\n * ```\n */\nexport async function initOtelServer(options: OtelOptions): Promise<OtelHandle> {\n validateOptions(options);\n\n const runtime = process.env.NEXT_RUNTIME;\n if (runtime === 'edge') {\n console.warn(\n '[@raccoon.ninja/otel-react] Edge runtime detected. Server OTel is limited to Node.js runtime.',\n );\n return { shutdown: async () => {} };\n }\n\n const endpoint = resolveEndpoint(options);\n const timeout = resolveExportTimeout(options);\n\n // Dynamic imports to prevent bundling Node.js SDK in client builds.\n // These packages must be installed separately by the user as they are\n // Node.js-only and not included in this package's dependencies.\n const { BasicTracerProvider, BatchSpanProcessor } = await import('@opentelemetry/sdk-trace-base');\n const { OTLPTraceExporter } = await import('@opentelemetry/exporter-trace-otlp-http');\n const { OTLPLogExporter } = await import('@opentelemetry/exporter-logs-otlp-http');\n const { LoggerProvider, BatchLogRecordProcessor } = await import('@opentelemetry/sdk-logs');\n const { resourceFromAttributes } = await import('@opentelemetry/resources');\n const { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION, SEMRESATTRS_DEPLOYMENT_ENVIRONMENT } =\n await import('@opentelemetry/semantic-conventions');\n const { trace } = await import('@opentelemetry/api');\n const { logs } = await import('@opentelemetry/api-logs');\n\n const attributes: Record<string, string> = {\n [ATTR_SERVICE_NAME]: options.serviceName,\n 'telemetry.sdk.name': '@raccoon.ninja/otel-react',\n 'telemetry.sdk.version': '1.0.0',\n };\n\n if (options.serviceVersion) {\n attributes[ATTR_SERVICE_VERSION] = options.serviceVersion;\n }\n if (options.environment) {\n attributes[SEMRESATTRS_DEPLOYMENT_ENVIRONMENT] = options.environment;\n }\n if (options.resourceAttributes) {\n Object.assign(attributes, options.resourceAttributes);\n }\n\n const resource = resourceFromAttributes(attributes);\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 trace.setGlobalTracerProvider(tracerProvider);\n\n const logExporter = new OTLPLogExporter({\n url: `${endpoint}/v1/logs`,\n headers: options.headers,\n timeoutMillis: timeout,\n });\n\n const loggerProvider = new LoggerProvider({ resource });\n loggerProvider.addLogRecordProcessor(new BatchLogRecordProcessor(logExporter));\n logs.setGlobalLoggerProvider(loggerProvider);\n\n return {\n shutdown: async () => {\n await Promise.all([tracerProvider.forceFlush(), loggerProvider.forceFlush()]);\n await Promise.all([tracerProvider.shutdown(), loggerProvider.shutdown()]);\n },\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/options.ts","../../src/nextjs/server.ts"],"names":[],"mappings":"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","file":"index.mjs","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 type { OtelOptions, OtelHandle } from '../core/options';\nimport { validateOptions, resolveEndpoint, resolveExportTimeout } from '../core/options';\n\n/**\n * Initialize OpenTelemetry for Next.js server-side (instrumentation.ts).\n *\n * This function wraps the Node.js OTel SDK setup for use in Next.js's\n * `instrumentation.ts` file.\n *\n * @example\n * ```typescript\n * // instrumentation.ts\n * import { initOtelServer } from '@raccoon.ninja/otel-react/nextjs';\n *\n * export function register() {\n * initOtelServer({ serviceName: 'my-nextjs-app' });\n * }\n * ```\n */\nexport async function initOtelServer(options: OtelOptions): Promise<OtelHandle> {\n validateOptions(options);\n\n const runtime = process.env.NEXT_RUNTIME;\n if (runtime === 'edge') {\n console.warn(\n '[@raccoon.ninja/otel-react] Edge runtime detected. Server OTel is limited to Node.js runtime.',\n );\n return { shutdown: async () => {} };\n }\n\n const endpoint = resolveEndpoint(options);\n const timeout = resolveExportTimeout(options);\n\n // Dynamic imports to prevent bundling Node.js SDK in client builds.\n // These packages must be installed separately by the user as they are\n // Node.js-only and not included in this package's dependencies.\n const { BasicTracerProvider, BatchSpanProcessor } = await import(\n '@opentelemetry/sdk-trace-base'\n );\n const { OTLPTraceExporter } = await import('@opentelemetry/exporter-trace-otlp-http');\n const { OTLPLogExporter } = await import('@opentelemetry/exporter-logs-otlp-http');\n const { LoggerProvider, BatchLogRecordProcessor } = await import('@opentelemetry/sdk-logs');\n const { resourceFromAttributes } = await import('@opentelemetry/resources');\n const { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION, SEMRESATTRS_DEPLOYMENT_ENVIRONMENT } =\n await import('@opentelemetry/semantic-conventions');\n const { trace } = await import('@opentelemetry/api');\n const { logs } = await import('@opentelemetry/api-logs');\n\n const attributes: Record<string, string> = {\n [ATTR_SERVICE_NAME]: options.serviceName,\n 'telemetry.sdk.name': '@raccoon.ninja/otel-react',\n 'telemetry.sdk.version': '1.0.0',\n };\n\n if (options.serviceVersion) {\n attributes[ATTR_SERVICE_VERSION] = options.serviceVersion;\n }\n if (options.environment) {\n attributes[SEMRESATTRS_DEPLOYMENT_ENVIRONMENT] = options.environment;\n }\n if (options.resourceAttributes) {\n Object.assign(attributes, options.resourceAttributes);\n }\n\n const resource = resourceFromAttributes(attributes);\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 trace.setGlobalTracerProvider(tracerProvider);\n\n const logExporter = new OTLPLogExporter({\n url: `${endpoint}/v1/logs`,\n headers: options.headers,\n timeoutMillis: timeout,\n });\n\n const loggerProvider = new LoggerProvider({ resource });\n loggerProvider.addLogRecordProcessor(new BatchLogRecordProcessor(logExporter));\n logs.setGlobalLoggerProvider(loggerProvider);\n\n return {\n shutdown: async () => {\n await Promise.all([tracerProvider.forceFlush(), loggerProvider.forceFlush()]);\n await Promise.all([tracerProvider.shutdown(), loggerProvider.shutdown()]);\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/core/options.ts","../../src/nextjs/server.ts"],"names":[],"mappings":"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","file":"index.mjs","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 type { OtelOptions, OtelHandle } from '../core/options';\nimport { validateOptions, resolveEndpoint, resolveExportTimeout } from '../core/options';\n\n/**\n * Initialize OpenTelemetry for Next.js server-side (instrumentation.ts).\n *\n * This function wraps the Node.js OTel SDK setup for use in Next.js's\n * `instrumentation.ts` file.\n *\n * @example\n * ```typescript\n * // instrumentation.ts\n * import { initOtelServer } from '@raccoon.ninja/otel-react/nextjs';\n *\n * export function register() {\n * initOtelServer({ serviceName: 'my-nextjs-app' });\n * }\n * ```\n */\nexport async function initOtelServer(options: OtelOptions): Promise<OtelHandle> {\n validateOptions(options);\n\n const runtime = process.env.NEXT_RUNTIME;\n if (runtime === 'edge') {\n console.warn(\n '[@raccoon.ninja/otel-react] Edge runtime detected. Server OTel is limited to Node.js runtime.',\n );\n return { shutdown: async () => {} };\n }\n\n const endpoint = resolveEndpoint(options);\n const timeout = resolveExportTimeout(options);\n\n // Dynamic imports to prevent bundling Node.js SDK in client builds.\n // These packages must be installed separately by the user as they are\n // Node.js-only and not included in this package's dependencies.\n const { BasicTracerProvider, BatchSpanProcessor } = await import('@opentelemetry/sdk-trace-base');\n const { OTLPTraceExporter } = await import('@opentelemetry/exporter-trace-otlp-http');\n const { OTLPLogExporter } = await import('@opentelemetry/exporter-logs-otlp-http');\n const { LoggerProvider, BatchLogRecordProcessor } = await import('@opentelemetry/sdk-logs');\n const { resourceFromAttributes } = await import('@opentelemetry/resources');\n const { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION, SEMRESATTRS_DEPLOYMENT_ENVIRONMENT } =\n await import('@opentelemetry/semantic-conventions');\n const { trace } = await import('@opentelemetry/api');\n const { logs } = await import('@opentelemetry/api-logs');\n\n const attributes: Record<string, string> = {\n [ATTR_SERVICE_NAME]: options.serviceName,\n 'telemetry.sdk.name': '@raccoon.ninja/otel-react',\n 'telemetry.sdk.version': '1.0.0',\n };\n\n if (options.serviceVersion) {\n attributes[ATTR_SERVICE_VERSION] = options.serviceVersion;\n }\n if (options.environment) {\n attributes[SEMRESATTRS_DEPLOYMENT_ENVIRONMENT] = options.environment;\n }\n if (options.resourceAttributes) {\n Object.assign(attributes, options.resourceAttributes);\n }\n\n const resource = resourceFromAttributes(attributes);\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 trace.setGlobalTracerProvider(tracerProvider);\n\n const logExporter = new OTLPLogExporter({\n url: `${endpoint}/v1/logs`,\n headers: options.headers,\n timeoutMillis: timeout,\n });\n\n const loggerProvider = new LoggerProvider({ resource });\n loggerProvider.addLogRecordProcessor(new BatchLogRecordProcessor(logExporter));\n logs.setGlobalLoggerProvider(loggerProvider);\n\n return {\n shutdown: async () => {\n await Promise.all([tracerProvider.forceFlush(), loggerProvider.forceFlush()]);\n await Promise.all([tracerProvider.shutdown(), loggerProvider.shutdown()]);\n },\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@raccoon.ninja/otel-react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "Drop-in OpenTelemetry instrumentation for React, React Native, and Next.js",
|
|
5
5
|
"author": "raccoon.ninja",
|
|
6
6
|
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/brenordv/npm-raccoon-otel.git"
|
|
10
|
+
},
|
|
7
11
|
"exports": {
|
|
8
12
|
".": {
|
|
9
13
|
"import": {
|
|
@@ -58,6 +62,7 @@
|
|
|
58
62
|
"test": "vitest run",
|
|
59
63
|
"test:watch": "vitest",
|
|
60
64
|
"test:coverage": "vitest run --coverage",
|
|
65
|
+
"check": "npm run lint && npm run format:check && npm run typecheck && npm run test && npm run build",
|
|
61
66
|
"prepublishOnly": "npm run build"
|
|
62
67
|
},
|
|
63
68
|
"peerDependencies": {
|