@atrim/instrument-web 0.5.0-c05e3a1-20251119131241 → 0.5.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atrim/instrument-web",
3
- "version": "0.5.0-c05e3a1-20251119131241",
3
+ "version": "0.5.0",
4
4
  "description": "OpenTelemetry instrumentation for browsers with centralized YAML configuration",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -82,10 +82,10 @@
82
82
  "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
83
83
  "format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\"",
84
84
  "clean": "rm -rf target",
85
- "publish:dev:version": "pnpm version $(node -p \"require('./package.json').version\")-$(git rev-parse --short HEAD)-$(date -u +%Y%m%d%H%M%S) --no-git-tag-version",
85
+ "publish:dev:version": "npm version $(git describe --tags --abbrev=0 | sed 's/^.*@//' | sed 's/^v//')-$(git rev-parse --short HEAD)-$(date -u +%Y%m%d%H%M%S) --no-git-tag-version",
86
86
  "publish:dev:save": "node -p \"require('./package.json').version\" > .version",
87
87
  "publish:dev:publish": "pnpm build && pnpm publish --tag dev --access public --no-git-checks",
88
- "publish:dev:reset": "pnpm version 0.5.0 --no-git-tag-version",
88
+ "publish:dev:reset": "npm version 0.1.0 --no-git-tag-version",
89
89
  "publish:dev": "pnpm publish:dev:version && pnpm publish:dev:save && pnpm publish:dev:publish && pnpm publish:dev:reset"
90
90
  }
91
91
  }
@@ -1,8 +1,8 @@
1
- import { Effect, Layer } from 'effect';
2
1
  import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
3
- import { InstrumentationConfig, InitializationError, ConfigLoader } from '@atrim/instrument-core';
2
+ import { InstrumentationConfig, ConfigLoader } from '@atrim/instrument-core';
4
3
  export { ConfigError, ConfigFileError, ConfigUrlError, ConfigValidationError, ExportError, InitializationError, InstrumentationConfig, PatternConfig, PatternMatcher, ShutdownError, clearPatternMatcher, getPatternMatcher, initializePatternMatcher, shouldInstrumentSpan } from '@atrim/instrument-core';
5
4
  import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
5
+ import { Layer } from 'effect';
6
6
  import { SpanProcessor, ReadableSpan } from '@opentelemetry/sdk-trace-base';
7
7
  import { Context, Span } from '@opentelemetry/api';
8
8
 
@@ -103,47 +103,37 @@ declare function resetSdk(): void;
103
103
  * Call this function once at application startup, before any other code runs.
104
104
  *
105
105
  * @param options - Initialization options
106
- * @returns Effect that yields WebTracerProvider instance
106
+ * @returns WebTracerProvider instance
107
+ * @throws {Error} If initialization fails
107
108
  *
108
109
  * @example
109
110
  * ```typescript
110
- * import { Effect } from 'effect'
111
111
  * import { initializeInstrumentation } from '@atrim/instrument-web'
112
112
  *
113
- * const program = initializeInstrumentation({
113
+ * await initializeInstrumentation({
114
114
  * serviceName: 'my-app',
115
115
  * otlpEndpoint: 'http://localhost:4318/v1/traces'
116
116
  * })
117
- *
118
- * await Effect.runPromise(program)
119
117
  * ```
120
118
  *
121
119
  * @example With pattern-based filtering
122
120
  * ```typescript
123
- * const program = initializeInstrumentation({
121
+ * await initializeInstrumentation({
124
122
  * serviceName: 'my-app',
125
123
  * configUrl: 'https://config.company.com/instrumentation.yaml'
126
124
  * })
127
- *
128
- * await Effect.runPromise(program)
129
125
  * ```
130
126
  *
131
- * @example With error handling
127
+ * @example Disable specific instrumentations
132
128
  * ```typescript
133
- * const program = initializeInstrumentation({
129
+ * await initializeInstrumentation({
134
130
  * serviceName: 'my-app',
135
- * enableUserInteraction: false
136
- * }).pipe(
137
- * Effect.catchTag('InitializationError', (error) => {
138
- * console.error('Failed to initialize:', error.reason)
139
- * return Effect.die(error) // Re-throw or handle
140
- * })
141
- * )
142
- *
143
- * await Effect.runPromise(program)
131
+ * enableUserInteraction: false, // Disable click tracking
132
+ * enableXhr: false // Disable XMLHttpRequest tracking
133
+ * })
144
134
  * ```
145
135
  */
146
- declare const initializeInstrumentation: (options: SdkInitializationOptions) => Effect.Effect<WebTracerProvider, InitializationError>;
136
+ declare function initializeInstrumentation(options: SdkInitializationOptions): Promise<WebTracerProvider>;
147
137
 
148
138
  /**
149
139
  * OTLP Exporter Factory for Browser
@@ -1,9 +1,9 @@
1
- import { Data, Context, Effect, Layer, Deferred } from 'effect';
2
1
  import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
3
2
  import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
4
3
  import { registerInstrumentations } from '@opentelemetry/instrumentation';
5
4
  import { getWebAutoInstrumentations } from '@opentelemetry/auto-instrumentations-web';
6
5
  import { ZoneContextManager } from '@opentelemetry/context-zone';
6
+ import { Data, Context, Effect, Layer } from 'effect';
7
7
  import { FileSystem } from '@effect/platform/FileSystem';
8
8
  import * as HttpClient from '@effect/platform/HttpClient';
9
9
  import * as HttpClientRequest from '@effect/platform/HttpClientRequest';
@@ -4095,20 +4095,7 @@ var HttpFilteringConfigSchema = external_exports.object({
4095
4095
  // Patterns to ignore for incoming HTTP requests (string patterns only in YAML)
4096
4096
  ignore_incoming_paths: external_exports.array(external_exports.string()).optional(),
4097
4097
  // Require parent span for outgoing requests (prevents root spans for HTTP calls)
4098
- require_parent_for_outgoing_spans: external_exports.boolean().optional(),
4099
- // Trace context propagation configuration
4100
- // Controls which cross-origin requests receive W3C Trace Context headers (traceparent, tracestate)
4101
- propagate_trace_context: external_exports.object({
4102
- // Strategy for trace propagation
4103
- // - "all": Propagate to all cross-origin requests (may cause CORS errors)
4104
- // - "none": Never propagate trace headers
4105
- // - "same-origin": Only propagate to same-origin requests (default, safe)
4106
- // - "patterns": Propagate based on include_urls patterns
4107
- strategy: external_exports.enum(["all", "none", "same-origin", "patterns"]).default("same-origin"),
4108
- // URL patterns to include when strategy is "patterns"
4109
- // Supports regex patterns (e.g., "^https://api\\.myapp\\.com")
4110
- include_urls: external_exports.array(external_exports.string()).optional()
4111
- }).optional()
4098
+ require_parent_for_outgoing_spans: external_exports.boolean().optional()
4112
4099
  });
4113
4100
  var InstrumentationConfigSchema = external_exports.object({
4114
4101
  version: external_exports.string(),
@@ -4539,34 +4526,43 @@ var PatternSpanProcessor = class {
4539
4526
 
4540
4527
  // src/core/sdk-initializer.ts
4541
4528
  var sdkInstance = null;
4542
- var initializationDeferred = null;
4543
- var initializeSdkEffect = (options) => Effect.gen(function* () {
4529
+ async function initializeSdk(options) {
4544
4530
  if (sdkInstance) {
4545
4531
  return sdkInstance;
4546
4532
  }
4547
- if (initializationDeferred) {
4548
- return yield* Deferred.await(initializationDeferred);
4549
- }
4550
- const deferred = yield* Deferred.make();
4551
- initializationDeferred = deferred;
4552
- const result = yield* performInitializationEffect(options).pipe(
4553
- Effect.tap((provider) => Deferred.succeed(deferred, provider)),
4554
- Effect.tapError((error) => Deferred.fail(deferred, error)),
4555
- Effect.ensuring(
4556
- Effect.sync(() => {
4557
- initializationDeferred = null;
4558
- })
4559
- )
4560
- );
4561
- return result;
4562
- });
4563
- var performInitializationEffect = (options) => Effect.gen(function* () {
4564
- const config = yield* loadConfigEffect(options);
4565
- if (config) {
4566
- initializePatternMatcher(config);
4567
- }
4568
- const ignoreUrls = buildIgnoreUrls(config);
4569
- const exporter = yield* Effect.sync(() => {
4533
+ try {
4534
+ let config = null;
4535
+ if (options.config) {
4536
+ config = await loadConfigFromInline(options.config);
4537
+ } else if (options.configPath || options.configUrl) {
4538
+ const url = options.configUrl || options.configPath;
4539
+ config = await loadConfig(url);
4540
+ }
4541
+ if (config) {
4542
+ initializePatternMatcher(config);
4543
+ }
4544
+ const ignoreUrls = [
4545
+ // Always ignore standard OTLP endpoints (prevents infinite loops)
4546
+ /\/v1\/traces$/,
4547
+ /\/v1\/metrics$/,
4548
+ /\/v1\/logs$/
4549
+ ];
4550
+ if (config?.http?.ignore_outgoing_urls) {
4551
+ for (const pattern of config.http.ignore_outgoing_urls) {
4552
+ try {
4553
+ ignoreUrls.push(new RegExp(pattern));
4554
+ } catch (error) {
4555
+ console.warn(
4556
+ `[@atrim/instrument-web] Invalid ignore_outgoing_urls pattern: "${pattern}"`,
4557
+ error
4558
+ );
4559
+ }
4560
+ }
4561
+ } else {
4562
+ console.warn(
4563
+ "[@atrim/instrument-web] Missing http.ignore_outgoing_urls in instrumentation.yaml. Using default OTLP endpoint patterns only. Consider adding http filtering to your config for better control."
4564
+ );
4565
+ }
4570
4566
  const exporterOptions = {};
4571
4567
  if (options.otlpEndpoint) {
4572
4568
  exporterOptions.endpoint = options.otlpEndpoint;
@@ -4574,23 +4570,18 @@ var performInitializationEffect = (options) => Effect.gen(function* () {
4574
4570
  if (options.otlpHeaders) {
4575
4571
  exporterOptions.headers = options.otlpHeaders;
4576
4572
  }
4577
- return createOtlpExporter(exporterOptions);
4578
- });
4579
- const spanProcessors = [];
4580
- if (config) {
4581
- spanProcessors.push(new PatternSpanProcessor());
4582
- }
4583
- spanProcessors.push(new SimpleSpanProcessor(exporter));
4584
- const provider = yield* Effect.sync(() => {
4585
- const p = new WebTracerProvider({
4573
+ const exporter = createOtlpExporter(exporterOptions);
4574
+ const spanProcessors = [];
4575
+ if (config) {
4576
+ spanProcessors.push(new PatternSpanProcessor());
4577
+ }
4578
+ spanProcessors.push(new SimpleSpanProcessor(exporter));
4579
+ const provider = new WebTracerProvider({
4586
4580
  spanProcessors
4587
4581
  });
4588
- p.register({
4582
+ provider.register({
4589
4583
  contextManager: new ZoneContextManager()
4590
4584
  });
4591
- return p;
4592
- });
4593
- yield* Effect.sync(() => {
4594
4585
  registerInstrumentations({
4595
4586
  instrumentations: [
4596
4587
  getWebAutoInstrumentations({
@@ -4616,56 +4607,11 @@ var performInitializationEffect = (options) => Effect.gen(function* () {
4616
4607
  })
4617
4608
  ]
4618
4609
  });
4619
- });
4620
- sdkInstance = provider;
4621
- return provider;
4622
- });
4623
- var loadConfigEffect = (options) => Effect.gen(function* () {
4624
- if (options.config) {
4625
- return yield* Effect.tryPromise({
4626
- try: () => loadConfigFromInline(options.config),
4627
- catch: (error) => new InitializationError({
4628
- reason: "Failed to load inline config",
4629
- cause: error
4630
- })
4631
- });
4610
+ sdkInstance = provider;
4611
+ return provider;
4612
+ } catch (error) {
4613
+ throw new Error(`Failed to initialize OpenTelemetry SDK: ${error}`);
4632
4614
  }
4633
- if (options.configPath || options.configUrl) {
4634
- const url = options.configUrl || options.configPath;
4635
- return yield* Effect.tryPromise({
4636
- try: () => loadConfig(url),
4637
- catch: (error) => new InitializationError({
4638
- reason: `Failed to load config from ${url}`,
4639
- cause: error
4640
- })
4641
- });
4642
- }
4643
- return null;
4644
- });
4645
- function buildIgnoreUrls(config) {
4646
- const ignoreUrls = [
4647
- // Always ignore standard OTLP endpoints (prevents infinite loops)
4648
- /\/v1\/traces$/,
4649
- /\/v1\/metrics$/,
4650
- /\/v1\/logs$/
4651
- ];
4652
- if (config?.http?.ignore_outgoing_urls) {
4653
- for (const pattern of config.http.ignore_outgoing_urls) {
4654
- try {
4655
- ignoreUrls.push(new RegExp(pattern));
4656
- } catch (error) {
4657
- console.warn(
4658
- `[@atrim/instrument-web] Invalid ignore_outgoing_urls pattern: "${pattern}"`,
4659
- error
4660
- );
4661
- }
4662
- }
4663
- } else {
4664
- console.warn(
4665
- "[@atrim/instrument-web] Missing http.ignore_outgoing_urls in instrumentation.yaml. Using default OTLP endpoint patterns only. Consider adding http filtering to your config for better control."
4666
- );
4667
- }
4668
- return ignoreUrls;
4669
4615
  }
4670
4616
  function getSdkInstance() {
4671
4617
  return sdkInstance;
@@ -4678,11 +4624,12 @@ async function shutdownSdk() {
4678
4624
  }
4679
4625
  function resetSdk() {
4680
4626
  sdkInstance = null;
4681
- initializationDeferred = null;
4682
4627
  }
4683
4628
 
4684
4629
  // src/api.ts
4685
- var initializeInstrumentation = (options) => initializeSdkEffect(options);
4630
+ async function initializeInstrumentation(options) {
4631
+ return await initializeSdk(options);
4632
+ }
4686
4633
  function setSpanAttributes(span, attributes) {
4687
4634
  for (const [key, value] of Object.entries(attributes)) {
4688
4635
  span.setAttribute(key, value);