@atrim/instrument-web 0.4.1 → 0.5.0-c05e3a1-20251119131241
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 +4 -4
- package/target/dist/index.d.ts +22 -12
- package/target/dist/index.js +104 -51
- package/target/dist/index.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atrim/instrument-web",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0-c05e3a1-20251119131241",
|
|
4
4
|
"description": "OpenTelemetry instrumentation for browsers with centralized YAML configuration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"tsup": "^8.0.1",
|
|
69
69
|
"typescript": "^5.7.2",
|
|
70
70
|
"vitest": "^4.0.8",
|
|
71
|
-
"@atrim/instrument-core": "0.
|
|
71
|
+
"@atrim/instrument-core": "0.5.0"
|
|
72
72
|
},
|
|
73
73
|
"scripts": {
|
|
74
74
|
"build": "tsup",
|
|
@@ -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": "
|
|
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",
|
|
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": "
|
|
88
|
+
"publish:dev:reset": "pnpm version 0.5.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
|
}
|
package/target/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { Effect, Layer } from 'effect';
|
|
1
2
|
import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
|
|
2
|
-
import { InstrumentationConfig, ConfigLoader } from '@atrim/instrument-core';
|
|
3
|
+
import { InstrumentationConfig, InitializationError, ConfigLoader } from '@atrim/instrument-core';
|
|
3
4
|
export { ConfigError, ConfigFileError, ConfigUrlError, ConfigValidationError, ExportError, InitializationError, InstrumentationConfig, PatternConfig, PatternMatcher, ShutdownError, clearPatternMatcher, getPatternMatcher, initializePatternMatcher, shouldInstrumentSpan } from '@atrim/instrument-core';
|
|
4
5
|
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,37 +103,47 @@ 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 WebTracerProvider instance
|
|
107
|
-
* @throws {Error} If initialization fails
|
|
106
|
+
* @returns Effect that yields WebTracerProvider instance
|
|
108
107
|
*
|
|
109
108
|
* @example
|
|
110
109
|
* ```typescript
|
|
110
|
+
* import { Effect } from 'effect'
|
|
111
111
|
* import { initializeInstrumentation } from '@atrim/instrument-web'
|
|
112
112
|
*
|
|
113
|
-
*
|
|
113
|
+
* const program = initializeInstrumentation({
|
|
114
114
|
* serviceName: 'my-app',
|
|
115
115
|
* otlpEndpoint: 'http://localhost:4318/v1/traces'
|
|
116
116
|
* })
|
|
117
|
+
*
|
|
118
|
+
* await Effect.runPromise(program)
|
|
117
119
|
* ```
|
|
118
120
|
*
|
|
119
121
|
* @example With pattern-based filtering
|
|
120
122
|
* ```typescript
|
|
121
|
-
*
|
|
123
|
+
* const program = initializeInstrumentation({
|
|
122
124
|
* serviceName: 'my-app',
|
|
123
125
|
* configUrl: 'https://config.company.com/instrumentation.yaml'
|
|
124
126
|
* })
|
|
127
|
+
*
|
|
128
|
+
* await Effect.runPromise(program)
|
|
125
129
|
* ```
|
|
126
130
|
*
|
|
127
|
-
* @example
|
|
131
|
+
* @example With error handling
|
|
128
132
|
* ```typescript
|
|
129
|
-
*
|
|
133
|
+
* const program = initializeInstrumentation({
|
|
130
134
|
* serviceName: 'my-app',
|
|
131
|
-
* enableUserInteraction: false
|
|
132
|
-
*
|
|
133
|
-
*
|
|
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)
|
|
134
144
|
* ```
|
|
135
145
|
*/
|
|
136
|
-
declare
|
|
146
|
+
declare const initializeInstrumentation: (options: SdkInitializationOptions) => Effect.Effect<WebTracerProvider, InitializationError>;
|
|
137
147
|
|
|
138
148
|
/**
|
|
139
149
|
* OTLP Exporter Factory for Browser
|
package/target/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { Data, Context, Effect, Layer, Deferred } from 'effect';
|
|
1
2
|
import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
|
|
2
3
|
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
|
|
3
4
|
import { registerInstrumentations } from '@opentelemetry/instrumentation';
|
|
4
5
|
import { getWebAutoInstrumentations } from '@opentelemetry/auto-instrumentations-web';
|
|
5
6
|
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,7 +4095,20 @@ 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()
|
|
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()
|
|
4099
4112
|
});
|
|
4100
4113
|
var InstrumentationConfigSchema = external_exports.object({
|
|
4101
4114
|
version: external_exports.string(),
|
|
@@ -4526,43 +4539,34 @@ var PatternSpanProcessor = class {
|
|
|
4526
4539
|
|
|
4527
4540
|
// src/core/sdk-initializer.ts
|
|
4528
4541
|
var sdkInstance = null;
|
|
4529
|
-
|
|
4542
|
+
var initializationDeferred = null;
|
|
4543
|
+
var initializeSdkEffect = (options) => Effect.gen(function* () {
|
|
4530
4544
|
if (sdkInstance) {
|
|
4531
4545
|
return sdkInstance;
|
|
4532
4546
|
}
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
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
|
-
}
|
|
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(() => {
|
|
4566
4570
|
const exporterOptions = {};
|
|
4567
4571
|
if (options.otlpEndpoint) {
|
|
4568
4572
|
exporterOptions.endpoint = options.otlpEndpoint;
|
|
@@ -4570,18 +4574,23 @@ async function initializeSdk(options) {
|
|
|
4570
4574
|
if (options.otlpHeaders) {
|
|
4571
4575
|
exporterOptions.headers = options.otlpHeaders;
|
|
4572
4576
|
}
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
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({
|
|
4580
4586
|
spanProcessors
|
|
4581
4587
|
});
|
|
4582
|
-
|
|
4588
|
+
p.register({
|
|
4583
4589
|
contextManager: new ZoneContextManager()
|
|
4584
4590
|
});
|
|
4591
|
+
return p;
|
|
4592
|
+
});
|
|
4593
|
+
yield* Effect.sync(() => {
|
|
4585
4594
|
registerInstrumentations({
|
|
4586
4595
|
instrumentations: [
|
|
4587
4596
|
getWebAutoInstrumentations({
|
|
@@ -4607,11 +4616,56 @@ async function initializeSdk(options) {
|
|
|
4607
4616
|
})
|
|
4608
4617
|
]
|
|
4609
4618
|
});
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
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
|
+
});
|
|
4614
4632
|
}
|
|
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;
|
|
4615
4669
|
}
|
|
4616
4670
|
function getSdkInstance() {
|
|
4617
4671
|
return sdkInstance;
|
|
@@ -4624,12 +4678,11 @@ async function shutdownSdk() {
|
|
|
4624
4678
|
}
|
|
4625
4679
|
function resetSdk() {
|
|
4626
4680
|
sdkInstance = null;
|
|
4681
|
+
initializationDeferred = null;
|
|
4627
4682
|
}
|
|
4628
4683
|
|
|
4629
4684
|
// src/api.ts
|
|
4630
|
-
|
|
4631
|
-
return await initializeSdk(options);
|
|
4632
|
-
}
|
|
4685
|
+
var initializeInstrumentation = (options) => initializeSdkEffect(options);
|
|
4633
4686
|
function setSpanAttributes(span, attributes) {
|
|
4634
4687
|
for (const [key, value] of Object.entries(attributes)) {
|
|
4635
4688
|
span.setAttribute(key, value);
|