@atrim/instrument-web 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Atrim AI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,360 @@
1
+ # @atrim/instrument-web
2
+
3
+ OpenTelemetry instrumentation for browsers with centralized YAML configuration.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@atrim/instrument-web.svg)](https://www.npmjs.com/package/@atrim/instrument-web)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ## Features
9
+
10
+ - ✅ **Zero-config OpenTelemetry setup** for browser applications
11
+ - ✅ **Auto-instrumentation** (fetch, XHR, document load, user interactions)
12
+ - ✅ **Pattern-based span filtering** via `instrumentation.yaml`
13
+ - ✅ **OTLP export over HTTP** (browser-compatible)
14
+ - ✅ **TypeScript support** with full type definitions
15
+ - ✅ **<50KB bundle size** (gzipped) - optimized for web
16
+ - ✅ **Modern browsers** (Chrome 90+, Firefox 88+, Safari 14+, Edge 90+)
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install @atrim/instrument-web
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ ```typescript
27
+ import { initializeInstrumentation } from '@atrim/instrument-web'
28
+
29
+ // Initialize once at application startup
30
+ await initializeInstrumentation({
31
+ serviceName: 'my-app',
32
+ otlpEndpoint: 'http://localhost:4318/v1/traces'
33
+ })
34
+
35
+ // That's it! Auto-instrumentation is now active.
36
+ ```
37
+
38
+ ## Auto-Instrumentations
39
+
40
+ The following are automatically instrumented when you initialize:
41
+
42
+ ### 1. Document Load
43
+ Captures page load timing metrics (LCP, FCP, TTFB).
44
+
45
+ ### 2. Fetch API
46
+ All `fetch()` calls are automatically traced with:
47
+ - HTTP method, URL, status code
48
+ - Request/response headers (configurable)
49
+ - Request/response timing
50
+
51
+ ### 3. XMLHttpRequest (XHR)
52
+ Legacy AJAX requests are traced automatically.
53
+
54
+ ### 4. User Interactions
55
+ Click events and form submissions are captured.
56
+
57
+ ## Manual Instrumentation
58
+
59
+ You can also create custom spans:
60
+
61
+ ```typescript
62
+ import { trace } from '@opentelemetry/api'
63
+
64
+ const tracer = trace.getTracer('my-app')
65
+
66
+ tracer.startActiveSpan('my-operation', (span) => {
67
+ try {
68
+ // Your code here
69
+ span.setAttribute('user.id', '123')
70
+ span.setAttribute('operation.type', 'checkout')
71
+
72
+ // ... do work ...
73
+
74
+ span.setStatus({ code: 1 }) // OK
75
+ } catch (error) {
76
+ span.recordException(error)
77
+ span.setStatus({ code: 2 }) // ERROR
78
+ throw error
79
+ } finally {
80
+ span.end()
81
+ }
82
+ })
83
+ ```
84
+
85
+ ## Span Helpers
86
+
87
+ We provide convenient helpers for common annotations:
88
+
89
+ ```typescript
90
+ import {
91
+ annotateHttpRequest,
92
+ annotateCacheOperation,
93
+ annotateUserInteraction,
94
+ annotateNavigation
95
+ } from '@atrim/instrument-web'
96
+
97
+ // HTTP request
98
+ annotateHttpRequest(span, {
99
+ method: 'GET',
100
+ url: 'https://api.example.com/users',
101
+ statusCode: 200,
102
+ responseTime: 150
103
+ })
104
+
105
+ // Cache operation
106
+ annotateCacheOperation(span, {
107
+ operation: 'get',
108
+ key: 'user:123',
109
+ hit: true
110
+ })
111
+
112
+ // User interaction
113
+ annotateUserInteraction(span, {
114
+ type: 'click',
115
+ target: 'button#submit',
116
+ page: '/checkout'
117
+ })
118
+
119
+ // Navigation
120
+ annotateNavigation(span, {
121
+ from: '/home',
122
+ to: '/profile',
123
+ type: 'client-side'
124
+ })
125
+ ```
126
+
127
+ ## Configuration
128
+
129
+ ### Basic Configuration
130
+
131
+ ```typescript
132
+ await initializeInstrumentation({
133
+ serviceName: 'my-app', // Required
134
+ serviceVersion: '1.0.0', // Optional
135
+ otlpEndpoint: 'http://localhost:4318/v1/traces', // Optional
136
+ otlpHeaders: { // Optional
137
+ 'Authorization': 'Bearer token'
138
+ }
139
+ })
140
+ ```
141
+
142
+ ### Pattern-Based Filtering
143
+
144
+ Create an `instrumentation.yaml` file:
145
+
146
+ ```yaml
147
+ version: "1.0"
148
+
149
+ instrumentation:
150
+ enabled: true
151
+
152
+ # Only instrument these patterns
153
+ instrument_patterns:
154
+ - pattern: "^documentLoad"
155
+ description: "Page load metrics"
156
+ - pattern: "^HTTP (GET|POST)"
157
+ description: "API requests"
158
+ - pattern: "^click"
159
+ description: "User clicks"
160
+
161
+ # Ignore these patterns
162
+ ignore_patterns:
163
+ - pattern: "^HTTP GET /health"
164
+ description: "Health check endpoints"
165
+ - pattern: "^HTTP.*analytics"
166
+ description: "Analytics requests"
167
+ ```
168
+
169
+ Then load it:
170
+
171
+ ```typescript
172
+ await initializeInstrumentation({
173
+ serviceName: 'my-app',
174
+ configPath: '/instrumentation.yaml' // Path relative to your app
175
+ })
176
+ ```
177
+
178
+ ### Remote Configuration
179
+
180
+ Load configuration from a remote URL:
181
+
182
+ ```typescript
183
+ await initializeInstrumentation({
184
+ serviceName: 'my-app',
185
+ configUrl: 'https://config.company.com/instrumentation.yaml'
186
+ })
187
+ ```
188
+
189
+ ### Disable Specific Instrumentations
190
+
191
+ ```typescript
192
+ await initializeInstrumentation({
193
+ serviceName: 'my-app',
194
+ enableDocumentLoad: true, // Page load metrics
195
+ enableUserInteraction: false, // Disable click tracking
196
+ enableFetch: true, // HTTP requests via fetch()
197
+ enableXhr: false // Disable XMLHttpRequest
198
+ })
199
+ ```
200
+
201
+ ## Environment Variables
202
+
203
+ Configure via Vite/Webpack environment variables:
204
+
205
+ ```bash
206
+ # .env
207
+ VITE_OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318/v1/traces
208
+ ```
209
+
210
+ Or set at runtime via window object:
211
+
212
+ ```typescript
213
+ window.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://custom:4318/v1/traces'
214
+ ```
215
+
216
+ ## Browser Considerations
217
+
218
+ ### CORS
219
+
220
+ Your OpenTelemetry collector must have CORS enabled:
221
+
222
+ ```yaml
223
+ # otel-collector-config.yaml
224
+ receivers:
225
+ otlp:
226
+ protocols:
227
+ http:
228
+ cors:
229
+ allowed_origins:
230
+ - "http://localhost:3000"
231
+ - "https://your-app.com"
232
+ allowed_headers:
233
+ - "*"
234
+ ```
235
+
236
+ ### Content Security Policy (CSP)
237
+
238
+ Add your OTLP endpoint to CSP:
239
+
240
+ ```html
241
+ <meta http-equiv="Content-Security-Policy"
242
+ content="connect-src 'self' http://localhost:4318">
243
+ ```
244
+
245
+ ### Bundle Size
246
+
247
+ The package is optimized for web with:
248
+ - ESM-only (no CJS overhead)
249
+ - Tree-shakeable exports
250
+ - Code splitting support
251
+ - Minification-friendly
252
+
253
+ **Estimated sizes:**
254
+ - Core SDK: ~15KB (gzipped)
255
+ - Auto-instrumentations: ~20KB (gzipped)
256
+ - OTLP exporter: ~10KB (gzipped)
257
+ - **Total: ~45KB (gzipped)**
258
+
259
+ ## Examples
260
+
261
+ See the [examples/web-vanilla](../../examples/web-vanilla) directory for a complete working example.
262
+
263
+ ## API Reference
264
+
265
+ ### `initializeInstrumentation(options)`
266
+
267
+ Initialize OpenTelemetry for the browser.
268
+
269
+ **Options:**
270
+ - `serviceName` (string, required) - Service name for telemetry
271
+ - `serviceVersion` (string, optional) - Service version
272
+ - `otlpEndpoint` (string, optional) - OTLP HTTP endpoint (default: `http://localhost:4318/v1/traces`)
273
+ - `otlpHeaders` (object, optional) - Custom HTTP headers for OTLP export
274
+ - `configPath` (string, optional) - Path to `instrumentation.yaml` file
275
+ - `configUrl` (string, optional) - URL to remote `instrumentation.yaml`
276
+ - `config` (object, optional) - Inline configuration object
277
+ - `enableDocumentLoad` (boolean, optional) - Enable document load instrumentation (default: true)
278
+ - `enableUserInteraction` (boolean, optional) - Enable user interaction instrumentation (default: true)
279
+ - `enableFetch` (boolean, optional) - Enable fetch instrumentation (default: true)
280
+ - `enableXhr` (boolean, optional) - Enable XMLHttpRequest instrumentation (default: true)
281
+
282
+ **Returns:** `Promise<WebTracerProvider>`
283
+
284
+ ### `getSdkInstance()`
285
+
286
+ Get the current SDK instance.
287
+
288
+ **Returns:** `WebTracerProvider | null`
289
+
290
+ ### `shutdownSdk()`
291
+
292
+ Shutdown the SDK gracefully.
293
+
294
+ **Returns:** `Promise<void>`
295
+
296
+ ## Comparison with Node.js Package
297
+
298
+ | Feature | @atrim/instrument-web | @atrim/instrument-node |
299
+ |---------|----------------------|------------------------|
300
+ | Platform | Browser | Node.js, Bun, Deno |
301
+ | Export Protocol | HTTP only | HTTP + gRPC |
302
+ | Auto-instrumentations | Fetch, XHR, DOM events | HTTP, gRPC, DB, etc. |
303
+ | Effect-TS | ❌ No | ✅ Yes |
304
+ | Bundle Size | <50KB | N/A |
305
+ | Service Detection | Manual | Automatic |
306
+
307
+ ## Requirements
308
+
309
+ - **Modern browsers:** Chrome 90+, Firefox 88+, Safari 14+, Edge 90+
310
+ - **Build tool:** Vite, Webpack, or similar (for bundling)
311
+ - **OpenTelemetry Collector:** Running with HTTP endpoint
312
+
313
+ ## Troubleshooting
314
+
315
+ ### Traces not appearing
316
+
317
+ 1. **Check collector is running:**
318
+ ```bash
319
+ docker run -p 4318:4318 otel/opentelemetry-collector
320
+ ```
321
+
322
+ 2. **Check CORS configuration** on your collector
323
+
324
+ 3. **Check browser console** for errors
325
+
326
+ 4. **Verify endpoint:**
327
+ ```typescript
328
+ import { getOtlpEndpoint } from '@atrim/instrument-web'
329
+ console.log('OTLP endpoint:', getOtlpEndpoint())
330
+ ```
331
+
332
+ ### Performance issues
333
+
334
+ 1. **Disable unused instrumentations:**
335
+ ```typescript
336
+ await initializeInstrumentation({
337
+ serviceName: 'my-app',
338
+ enableUserInteraction: false, // Reduce overhead
339
+ enableDocumentLoad: false
340
+ })
341
+ ```
342
+
343
+ 2. **Use pattern filtering** to reduce span volume
344
+
345
+ 3. **Sample traces** at the collector level
346
+
347
+ ## Contributing
348
+
349
+ See [CONTRIBUTING.md](../../CONTRIBUTING.md) for development setup.
350
+
351
+ ## License
352
+
353
+ MIT License - see [LICENSE](../../LICENSE) for details.
354
+
355
+ ## Links
356
+
357
+ - [GitHub Repository](https://github.com/atrim-ai/instrumentation)
358
+ - [Issue Tracker](https://github.com/atrim-ai/instrumentation/issues)
359
+ - [OpenTelemetry JavaScript](https://opentelemetry.io/docs/languages/js/)
360
+ - [Atrim Platform](https://atrim.ai)
package/package.json ADDED
@@ -0,0 +1,91 @@
1
+ {
2
+ "name": "@atrim/instrument-web",
3
+ "version": "0.1.0",
4
+ "description": "OpenTelemetry instrumentation for browsers with centralized YAML configuration",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "Atrim AI",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/atrim-ai/instrumentation.git",
11
+ "directory": "packages/web"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/atrim-ai/instrumentation/issues"
15
+ },
16
+ "homepage": "https://github.com/atrim-ai/instrumentation#readme",
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "keywords": [
21
+ "opentelemetry",
22
+ "instrumentation",
23
+ "tracing",
24
+ "observability",
25
+ "browser",
26
+ "web",
27
+ "frontend",
28
+ "spa",
29
+ "react",
30
+ "fetch",
31
+ "xhr"
32
+ ],
33
+ "engines": {
34
+ "node": ">=20.0.0"
35
+ },
36
+ "exports": {
37
+ ".": {
38
+ "types": "./target/dist/index.d.ts",
39
+ "import": "./target/dist/index.js"
40
+ }
41
+ },
42
+ "main": "./target/dist/index.js",
43
+ "module": "./target/dist/index.js",
44
+ "types": "./target/dist/index.d.ts",
45
+ "files": [
46
+ "target/dist",
47
+ "README.md",
48
+ "LICENSE"
49
+ ],
50
+ "dependencies": {
51
+ "@effect/platform": "^0.93.0",
52
+ "effect": "^3.19.0",
53
+ "@opentelemetry/api": "^1.9.0",
54
+ "@opentelemetry/auto-instrumentations-web": "^0.54.0",
55
+ "@opentelemetry/context-zone": "^2.2.0",
56
+ "@opentelemetry/exporter-trace-otlp-http": "^0.208.0",
57
+ "@opentelemetry/instrumentation": "^0.208.0",
58
+ "@opentelemetry/resources": "^2.2.0",
59
+ "@opentelemetry/sdk-trace-base": "^2.2.0",
60
+ "@opentelemetry/sdk-trace-web": "^2.2.0",
61
+ "yaml": "^2.8.1"
62
+ },
63
+ "devDependencies": {
64
+ "@opentelemetry/semantic-conventions": "^1.38.0",
65
+ "@types/node": "^20.10.0",
66
+ "@vitest/coverage-v8": "^4.0.8",
67
+ "jsdom": "^24.0.0",
68
+ "tsup": "^8.0.1",
69
+ "typescript": "^5.7.2",
70
+ "vitest": "^4.0.8",
71
+ "@atrim/instrument-core": "0.4.0"
72
+ },
73
+ "scripts": {
74
+ "build": "tsup",
75
+ "dev": "tsup --watch",
76
+ "test": "vitest run",
77
+ "test:watch": "vitest",
78
+ "test:coverage": "vitest run --coverage",
79
+ "typecheck": "tsc --noEmit",
80
+ "lint": "eslint src",
81
+ "lint:fix": "eslint src --fix",
82
+ "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
83
+ "format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\"",
84
+ "clean": "rm -rf target",
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
+ "publish:dev:save": "node -p \"require('./package.json').version\" > .version",
87
+ "publish:dev:publish": "pnpm build && pnpm publish --tag dev --access public --no-git-checks",
88
+ "publish:dev:reset": "npm version 0.1.0 --no-git-tag-version",
89
+ "publish:dev": "pnpm publish:dev:version && pnpm publish:dev:save && pnpm publish:dev:publish && pnpm publish:dev:reset"
90
+ }
91
+ }