@raccoon.ninja/otel-react 1.0.0 → 1.2.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -14
- package/dist/index.cjs +23 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +14 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.mjs +23 -12
- package/dist/index.mjs.map +1 -1
- package/dist/native/index.cjs +8 -7
- package/dist/native/index.cjs.map +1 -1
- package/dist/native/index.d.mts +11 -0
- package/dist/native/index.d.ts +11 -0
- package/dist/native/index.mjs +8 -7
- package/dist/native/index.mjs.map +1 -1
- package/dist/nextjs/index.cjs +5 -3
- package/dist/nextjs/index.cjs.map +1 -1
- package/dist/nextjs/index.d.mts +11 -0
- package/dist/nextjs/index.d.ts +11 -0
- package/dist/nextjs/index.mjs +5 -3
- package/dist/nextjs/index.mjs.map +1 -1
- package/package.json +33 -33
package/README.md
CHANGED
|
@@ -53,20 +53,21 @@ 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
|
-
| `
|
|
66
|
-
| `
|
|
67
|
-
| `
|
|
68
|
-
| `
|
|
69
|
-
| `
|
|
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
|
+
| `propagateTraceHeaderCorsUrls` | `(string \| RegExp)[]` | `[]` | Cross-origin URLs that should receive W3C Trace Context headers |
|
|
66
|
+
| `instrumentations` | `InstrumentationConfig` | all enabled | Enable/disable specific auto-instrumentations |
|
|
67
|
+
| `resourceAttributes` | `Record<string, string>` | -- | Additional OTel resource attributes |
|
|
68
|
+
| `extensions` | `OtelExtension[]` | -- | Opt-in extensions (e.g., `withReactRouter()`) |
|
|
69
|
+
| `configureTracing` | `(provider) => void` | -- | Escape hatch to configure the TracerProvider |
|
|
70
|
+
| `configureExporter` | `(exporter) => void` | -- | Escape hatch to configure the OTLP exporter |
|
|
70
71
|
|
|
71
72
|
### Pointing to a Collector
|
|
72
73
|
|
package/dist/index.cjs
CHANGED
|
@@ -66,12 +66,11 @@ function validateOptions(options) {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
var SDK_NAME = "@raccoon.ninja/otel-react";
|
|
69
|
-
var SDK_VERSION = "1.0.0";
|
|
70
69
|
function buildResource(options) {
|
|
71
70
|
const attributes = {
|
|
72
71
|
[semanticConventions.ATTR_SERVICE_NAME]: options.serviceName,
|
|
73
72
|
"telemetry.sdk.name": SDK_NAME,
|
|
74
|
-
"telemetry.sdk.version":
|
|
73
|
+
"telemetry.sdk.version": "1.2.0-rc.1",
|
|
75
74
|
"telemetry.sdk.language": "webjs"
|
|
76
75
|
};
|
|
77
76
|
if (options.serviceVersion) {
|
|
@@ -121,8 +120,10 @@ function createLoggerProvider(options, resource) {
|
|
|
121
120
|
headers: options.headers,
|
|
122
121
|
timeoutMillis: timeout
|
|
123
122
|
});
|
|
124
|
-
const provider = new sdkLogs.LoggerProvider({
|
|
125
|
-
|
|
123
|
+
const provider = new sdkLogs.LoggerProvider({
|
|
124
|
+
resource,
|
|
125
|
+
processors: [new sdkLogs.BatchLogRecordProcessor(exporter)]
|
|
126
|
+
});
|
|
126
127
|
apiLogs.logs.setGlobalLoggerProvider(provider);
|
|
127
128
|
return provider;
|
|
128
129
|
}
|
|
@@ -149,19 +150,27 @@ function createMeterProvider(options, resource) {
|
|
|
149
150
|
}
|
|
150
151
|
function registerAutoInstrumentations(options) {
|
|
151
152
|
const config = resolveInstrumentations(options);
|
|
152
|
-
const
|
|
153
|
+
const endpoint = resolveEndpoint(options);
|
|
154
|
+
const escapedEndpoint = endpoint.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
155
|
+
const ignoreUrls = [
|
|
156
|
+
...options.ignoreUrls ?? [],
|
|
157
|
+
new RegExp(escapedEndpoint)
|
|
158
|
+
];
|
|
153
159
|
const instrumentations = [];
|
|
160
|
+
const propagateTraceHeaderCorsUrls = options.propagateTraceHeaderCorsUrls ?? [];
|
|
154
161
|
if (config.fetch) {
|
|
155
162
|
instrumentations.push(
|
|
156
163
|
new instrumentationFetch.FetchInstrumentation({
|
|
157
|
-
ignoreUrls
|
|
164
|
+
ignoreUrls,
|
|
165
|
+
propagateTraceHeaderCorsUrls
|
|
158
166
|
})
|
|
159
167
|
);
|
|
160
168
|
}
|
|
161
169
|
if (config.xhr) {
|
|
162
170
|
instrumentations.push(
|
|
163
171
|
new instrumentationXmlHttpRequest.XMLHttpRequestInstrumentation({
|
|
164
|
-
ignoreUrls
|
|
172
|
+
ignoreUrls,
|
|
173
|
+
propagateTraceHeaderCorsUrls
|
|
165
174
|
})
|
|
166
175
|
);
|
|
167
176
|
}
|
|
@@ -177,7 +186,7 @@ function registerAutoInstrumentations(options) {
|
|
|
177
186
|
}
|
|
178
187
|
var METER_NAME = "@raccoon.ninja/otel-react/web-vitals";
|
|
179
188
|
function startWebVitalsCollection() {
|
|
180
|
-
const meter = api.metrics.getMeter(METER_NAME, "1.0.
|
|
189
|
+
const meter = api.metrics.getMeter(METER_NAME, "1.2.0-rc.1");
|
|
181
190
|
const lcpHistogram = meter.createHistogram("web_vitals.lcp", {
|
|
182
191
|
description: "Largest Contentful Paint",
|
|
183
192
|
unit: "ms"
|
|
@@ -299,7 +308,7 @@ function initOtel(options) {
|
|
|
299
308
|
ext({ tracerProvider });
|
|
300
309
|
}
|
|
301
310
|
}
|
|
302
|
-
const logger = loggerProvider.getLogger("@raccoon.ninja/otel-react", "1.0.
|
|
311
|
+
const logger = loggerProvider.getLogger("@raccoon.ninja/otel-react", "1.2.0-rc.1");
|
|
303
312
|
logger.emit({
|
|
304
313
|
severityNumber: apiLogs.SeverityNumber.INFO,
|
|
305
314
|
severityText: "INFO",
|
|
@@ -327,6 +336,7 @@ function OtelProvider({
|
|
|
327
336
|
headers,
|
|
328
337
|
exportTimeout,
|
|
329
338
|
ignoreUrls,
|
|
339
|
+
propagateTraceHeaderCorsUrls,
|
|
330
340
|
configureTracing,
|
|
331
341
|
configureExporter,
|
|
332
342
|
extensions
|
|
@@ -343,6 +353,7 @@ function OtelProvider({
|
|
|
343
353
|
headers,
|
|
344
354
|
exportTimeout,
|
|
345
355
|
ignoreUrls,
|
|
356
|
+
propagateTraceHeaderCorsUrls,
|
|
346
357
|
configureTracing,
|
|
347
358
|
configureExporter,
|
|
348
359
|
extensions
|
|
@@ -366,7 +377,7 @@ var TracedErrorBoundary = class extends react.Component {
|
|
|
366
377
|
return { hasError: true, error };
|
|
367
378
|
}
|
|
368
379
|
componentDidCatch(error, errorInfo) {
|
|
369
|
-
const tracer = api.trace.getTracer(TRACER_NAME, "1.0.
|
|
380
|
+
const tracer = api.trace.getTracer(TRACER_NAME, "1.2.0-rc.1");
|
|
370
381
|
const span = tracer.startSpan("error-boundary.catch");
|
|
371
382
|
span.setStatus({ code: api.SpanStatusCode.ERROR, message: error.message });
|
|
372
383
|
span.setAttribute("error.type", error.name);
|
|
@@ -380,7 +391,7 @@ var TracedErrorBoundary = class extends react.Component {
|
|
|
380
391
|
span.recordException(error);
|
|
381
392
|
span.end();
|
|
382
393
|
try {
|
|
383
|
-
const logger = apiLogs.logs.getLogger(LOGGER_NAME, "1.0.
|
|
394
|
+
const logger = apiLogs.logs.getLogger(LOGGER_NAME, "1.2.0-rc.1");
|
|
384
395
|
logger.emit({
|
|
385
396
|
severityNumber: apiLogs.SeverityNumber.ERROR,
|
|
386
397
|
severityText: "ERROR",
|
|
@@ -417,7 +428,7 @@ function useTracer(name, version) {
|
|
|
417
428
|
var TRACER_NAME2 = "@raccoon.ninja/otel-react/router";
|
|
418
429
|
function withReactRouter() {
|
|
419
430
|
return (_context) => {
|
|
420
|
-
api.trace.getTracer(TRACER_NAME2, "1.0.
|
|
431
|
+
api.trace.getTracer(TRACER_NAME2, "1.2.0-rc.1");
|
|
421
432
|
};
|
|
422
433
|
}
|
|
423
434
|
|
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 = '1.0.0';\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"]}
|
|
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 /**\n * Cross-origin URLs that should receive W3C Trace Context headers\n * (traceparent / tracestate). Required when the frontend calls APIs\n * on a different origin and you want end-to-end distributed traces.\n *\n * @example\n * ```ts\n * propagateTraceHeaderCorsUrls: [/api\\.example\\.com/, 'https://my-backend.local']\n * ```\n */\n propagateTraceHeaderCorsUrls?: 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';\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({\n resource,\n processors: [new BatchLogRecordProcessor(exporter)],\n });\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, resolveEndpoint } from '@/core/options';\n\nexport function registerAutoInstrumentations(options: OtelOptions): void {\n const config: Required<InstrumentationConfig> = resolveInstrumentations(options);\n\n // Automatically exclude the OTLP collector endpoint from instrumentation\n // to prevent the SDK from tracing its own export requests.\n const endpoint = resolveEndpoint(options);\n const escapedEndpoint = endpoint.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const ignoreUrls: Array<string | RegExp> = [\n ...(options.ignoreUrls ?? []),\n new RegExp(escapedEndpoint),\n ];\n\n const instrumentations = [];\n\n const propagateTraceHeaderCorsUrls = options.propagateTraceHeaderCorsUrls ?? [];\n\n if (config.fetch) {\n instrumentations.push(\n new FetchInstrumentation({\n ignoreUrls,\n propagateTraceHeaderCorsUrls,\n }),\n );\n }\n\n if (config.xhr) {\n instrumentations.push(\n new XMLHttpRequestInstrumentation({\n ignoreUrls,\n propagateTraceHeaderCorsUrls,\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, __SDK_VERSION__);\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', __SDK_VERSION__);\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 /** Cross-origin URLs that should receive W3C Trace Context headers. */\n propagateTraceHeaderCorsUrls?: 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 propagateTraceHeaderCorsUrls,\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 propagateTraceHeaderCorsUrls,\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, __SDK_VERSION__);\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, __SDK_VERSION__);\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, __SDK_VERSION__);\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.d.mts
CHANGED
|
@@ -50,6 +50,17 @@ interface OtelOptions {
|
|
|
50
50
|
* Supports string patterns or RegExp.
|
|
51
51
|
*/
|
|
52
52
|
ignoreUrls?: Array<string | RegExp>;
|
|
53
|
+
/**
|
|
54
|
+
* Cross-origin URLs that should receive W3C Trace Context headers
|
|
55
|
+
* (traceparent / tracestate). Required when the frontend calls APIs
|
|
56
|
+
* on a different origin and you want end-to-end distributed traces.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* propagateTraceHeaderCorsUrls: [/api\.example\.com/, 'https://my-backend.local']
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
propagateTraceHeaderCorsUrls?: Array<string | RegExp>;
|
|
53
64
|
/** Extension functions for opt-in instrumentations. */
|
|
54
65
|
extensions?: OtelExtension[];
|
|
55
66
|
}
|
|
@@ -81,6 +92,8 @@ interface OtelProviderProps {
|
|
|
81
92
|
exportTimeout?: number;
|
|
82
93
|
/** URLs to exclude from fetch/XHR instrumentation. */
|
|
83
94
|
ignoreUrls?: Array<string | RegExp>;
|
|
95
|
+
/** Cross-origin URLs that should receive W3C Trace Context headers. */
|
|
96
|
+
propagateTraceHeaderCorsUrls?: Array<string | RegExp>;
|
|
84
97
|
/** Escape hatch: configure the TracerProvider. */
|
|
85
98
|
configureTracing?: OtelOptions['configureTracing'];
|
|
86
99
|
/** Escape hatch: configure the OTLP exporter. */
|
|
@@ -107,7 +120,7 @@ interface OtelProviderProps {
|
|
|
107
120
|
* }
|
|
108
121
|
* ```
|
|
109
122
|
*/
|
|
110
|
-
declare function OtelProvider({ children, serviceName, endpoint, resourceAttributes, serviceVersion, environment, instrumentations, headers, exportTimeout, ignoreUrls, configureTracing, configureExporter, extensions, }: OtelProviderProps): react_jsx_runtime.JSX.Element;
|
|
123
|
+
declare function OtelProvider({ children, serviceName, endpoint, resourceAttributes, serviceVersion, environment, instrumentations, headers, exportTimeout, ignoreUrls, propagateTraceHeaderCorsUrls, configureTracing, configureExporter, extensions, }: OtelProviderProps): react_jsx_runtime.JSX.Element;
|
|
111
124
|
|
|
112
125
|
/** Props for the TracedErrorBoundary component. */
|
|
113
126
|
interface TracedErrorBoundaryProps {
|
package/dist/index.d.ts
CHANGED
|
@@ -50,6 +50,17 @@ interface OtelOptions {
|
|
|
50
50
|
* Supports string patterns or RegExp.
|
|
51
51
|
*/
|
|
52
52
|
ignoreUrls?: Array<string | RegExp>;
|
|
53
|
+
/**
|
|
54
|
+
* Cross-origin URLs that should receive W3C Trace Context headers
|
|
55
|
+
* (traceparent / tracestate). Required when the frontend calls APIs
|
|
56
|
+
* on a different origin and you want end-to-end distributed traces.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* propagateTraceHeaderCorsUrls: [/api\.example\.com/, 'https://my-backend.local']
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
propagateTraceHeaderCorsUrls?: Array<string | RegExp>;
|
|
53
64
|
/** Extension functions for opt-in instrumentations. */
|
|
54
65
|
extensions?: OtelExtension[];
|
|
55
66
|
}
|
|
@@ -81,6 +92,8 @@ interface OtelProviderProps {
|
|
|
81
92
|
exportTimeout?: number;
|
|
82
93
|
/** URLs to exclude from fetch/XHR instrumentation. */
|
|
83
94
|
ignoreUrls?: Array<string | RegExp>;
|
|
95
|
+
/** Cross-origin URLs that should receive W3C Trace Context headers. */
|
|
96
|
+
propagateTraceHeaderCorsUrls?: Array<string | RegExp>;
|
|
84
97
|
/** Escape hatch: configure the TracerProvider. */
|
|
85
98
|
configureTracing?: OtelOptions['configureTracing'];
|
|
86
99
|
/** Escape hatch: configure the OTLP exporter. */
|
|
@@ -107,7 +120,7 @@ interface OtelProviderProps {
|
|
|
107
120
|
* }
|
|
108
121
|
* ```
|
|
109
122
|
*/
|
|
110
|
-
declare function OtelProvider({ children, serviceName, endpoint, resourceAttributes, serviceVersion, environment, instrumentations, headers, exportTimeout, ignoreUrls, configureTracing, configureExporter, extensions, }: OtelProviderProps): react_jsx_runtime.JSX.Element;
|
|
123
|
+
declare function OtelProvider({ children, serviceName, endpoint, resourceAttributes, serviceVersion, environment, instrumentations, headers, exportTimeout, ignoreUrls, propagateTraceHeaderCorsUrls, configureTracing, configureExporter, extensions, }: OtelProviderProps): react_jsx_runtime.JSX.Element;
|
|
111
124
|
|
|
112
125
|
/** Props for the TracedErrorBoundary component. */
|
|
113
126
|
interface TracedErrorBoundaryProps {
|
package/dist/index.mjs
CHANGED
|
@@ -64,12 +64,11 @@ function validateOptions(options) {
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
var SDK_NAME = "@raccoon.ninja/otel-react";
|
|
67
|
-
var SDK_VERSION = "1.0.0";
|
|
68
67
|
function buildResource(options) {
|
|
69
68
|
const attributes = {
|
|
70
69
|
[ATTR_SERVICE_NAME]: options.serviceName,
|
|
71
70
|
"telemetry.sdk.name": SDK_NAME,
|
|
72
|
-
"telemetry.sdk.version":
|
|
71
|
+
"telemetry.sdk.version": "1.2.0-rc.1",
|
|
73
72
|
"telemetry.sdk.language": "webjs"
|
|
74
73
|
};
|
|
75
74
|
if (options.serviceVersion) {
|
|
@@ -119,8 +118,10 @@ function createLoggerProvider(options, resource) {
|
|
|
119
118
|
headers: options.headers,
|
|
120
119
|
timeoutMillis: timeout
|
|
121
120
|
});
|
|
122
|
-
const provider = new LoggerProvider({
|
|
123
|
-
|
|
121
|
+
const provider = new LoggerProvider({
|
|
122
|
+
resource,
|
|
123
|
+
processors: [new BatchLogRecordProcessor(exporter)]
|
|
124
|
+
});
|
|
124
125
|
logs.setGlobalLoggerProvider(provider);
|
|
125
126
|
return provider;
|
|
126
127
|
}
|
|
@@ -147,19 +148,27 @@ function createMeterProvider(options, resource) {
|
|
|
147
148
|
}
|
|
148
149
|
function registerAutoInstrumentations(options) {
|
|
149
150
|
const config = resolveInstrumentations(options);
|
|
150
|
-
const
|
|
151
|
+
const endpoint = resolveEndpoint(options);
|
|
152
|
+
const escapedEndpoint = endpoint.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
153
|
+
const ignoreUrls = [
|
|
154
|
+
...options.ignoreUrls ?? [],
|
|
155
|
+
new RegExp(escapedEndpoint)
|
|
156
|
+
];
|
|
151
157
|
const instrumentations = [];
|
|
158
|
+
const propagateTraceHeaderCorsUrls = options.propagateTraceHeaderCorsUrls ?? [];
|
|
152
159
|
if (config.fetch) {
|
|
153
160
|
instrumentations.push(
|
|
154
161
|
new FetchInstrumentation({
|
|
155
|
-
ignoreUrls
|
|
162
|
+
ignoreUrls,
|
|
163
|
+
propagateTraceHeaderCorsUrls
|
|
156
164
|
})
|
|
157
165
|
);
|
|
158
166
|
}
|
|
159
167
|
if (config.xhr) {
|
|
160
168
|
instrumentations.push(
|
|
161
169
|
new XMLHttpRequestInstrumentation({
|
|
162
|
-
ignoreUrls
|
|
170
|
+
ignoreUrls,
|
|
171
|
+
propagateTraceHeaderCorsUrls
|
|
163
172
|
})
|
|
164
173
|
);
|
|
165
174
|
}
|
|
@@ -175,7 +184,7 @@ function registerAutoInstrumentations(options) {
|
|
|
175
184
|
}
|
|
176
185
|
var METER_NAME = "@raccoon.ninja/otel-react/web-vitals";
|
|
177
186
|
function startWebVitalsCollection() {
|
|
178
|
-
const meter = metrics.getMeter(METER_NAME, "1.0.
|
|
187
|
+
const meter = metrics.getMeter(METER_NAME, "1.2.0-rc.1");
|
|
179
188
|
const lcpHistogram = meter.createHistogram("web_vitals.lcp", {
|
|
180
189
|
description: "Largest Contentful Paint",
|
|
181
190
|
unit: "ms"
|
|
@@ -297,7 +306,7 @@ function initOtel(options) {
|
|
|
297
306
|
ext({ tracerProvider });
|
|
298
307
|
}
|
|
299
308
|
}
|
|
300
|
-
const logger = loggerProvider.getLogger("@raccoon.ninja/otel-react", "1.0.
|
|
309
|
+
const logger = loggerProvider.getLogger("@raccoon.ninja/otel-react", "1.2.0-rc.1");
|
|
301
310
|
logger.emit({
|
|
302
311
|
severityNumber: SeverityNumber.INFO,
|
|
303
312
|
severityText: "INFO",
|
|
@@ -325,6 +334,7 @@ function OtelProvider({
|
|
|
325
334
|
headers,
|
|
326
335
|
exportTimeout,
|
|
327
336
|
ignoreUrls,
|
|
337
|
+
propagateTraceHeaderCorsUrls,
|
|
328
338
|
configureTracing,
|
|
329
339
|
configureExporter,
|
|
330
340
|
extensions
|
|
@@ -341,6 +351,7 @@ function OtelProvider({
|
|
|
341
351
|
headers,
|
|
342
352
|
exportTimeout,
|
|
343
353
|
ignoreUrls,
|
|
354
|
+
propagateTraceHeaderCorsUrls,
|
|
344
355
|
configureTracing,
|
|
345
356
|
configureExporter,
|
|
346
357
|
extensions
|
|
@@ -364,7 +375,7 @@ var TracedErrorBoundary = class extends Component {
|
|
|
364
375
|
return { hasError: true, error };
|
|
365
376
|
}
|
|
366
377
|
componentDidCatch(error, errorInfo) {
|
|
367
|
-
const tracer = trace.getTracer(TRACER_NAME, "1.0.
|
|
378
|
+
const tracer = trace.getTracer(TRACER_NAME, "1.2.0-rc.1");
|
|
368
379
|
const span = tracer.startSpan("error-boundary.catch");
|
|
369
380
|
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
|
|
370
381
|
span.setAttribute("error.type", error.name);
|
|
@@ -378,7 +389,7 @@ var TracedErrorBoundary = class extends Component {
|
|
|
378
389
|
span.recordException(error);
|
|
379
390
|
span.end();
|
|
380
391
|
try {
|
|
381
|
-
const logger = logs.getLogger(LOGGER_NAME, "1.0.
|
|
392
|
+
const logger = logs.getLogger(LOGGER_NAME, "1.2.0-rc.1");
|
|
382
393
|
logger.emit({
|
|
383
394
|
severityNumber: SeverityNumber.ERROR,
|
|
384
395
|
severityText: "ERROR",
|
|
@@ -415,7 +426,7 @@ function useTracer(name, version) {
|
|
|
415
426
|
var TRACER_NAME2 = "@raccoon.ninja/otel-react/router";
|
|
416
427
|
function withReactRouter() {
|
|
417
428
|
return (_context) => {
|
|
418
|
-
trace.getTracer(TRACER_NAME2, "1.0.
|
|
429
|
+
trace.getTracer(TRACER_NAME2, "1.2.0-rc.1");
|
|
419
430
|
};
|
|
420
431
|
}
|
|
421
432
|
|