@atrim/instrument-node 0.5.0 → 0.5.1-3a86b84-20260105170223

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 CHANGED
@@ -1,42 +1,43 @@
1
1
  # @atrim/instrument-node
2
2
 
3
- **One-line OpenTelemetry for Node.js**
3
+ **Configuration layer for OpenTelemetry Node.js**
4
4
 
5
5
  [![npm version](https://badge.fury.io/js/%40atrim%2Finstrument-node.svg)](https://www.npmjs.com/package/@atrim/instrument-node)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
 
8
- OpenTelemetry instrumentation for Node.js with centralized YAML configuration. Works with any Node.js framework (Express, Fastify, Koa, Hono) and runtime (Node.js, Bun, Deno).
8
+ Built on [@opentelemetry/auto-instrumentations-node](https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-node), this package adds centralized YAML configuration, pattern-based span filtering, and first-class Effect-TS integration.
9
9
 
10
- ## Quick Start
11
-
12
- **1. Install**
10
+ ## What This Package Adds
13
11
 
14
- ```bash
15
- npm install @atrim/instrument-node
16
- ```
12
+ | Feature | Description |
13
+ |---------|-------------|
14
+ | **Pattern-based span filtering** | Control which spans are created via YAML config (unique to this package) |
15
+ | **Centralized configuration** | Load instrumentation config from file, URL, or environment variable |
16
+ | **Effect-TS integration** | Typed layers, annotation helpers for Effect users |
17
+ | **Smart defaults** | Auto-detects service name, configures graceful shutdown |
17
18
 
18
- **2. Initialize** (at the top of your app)
19
+ **Note:** Auto-instrumentation for Express, HTTP, Fastify, etc. comes from the underlying OpenTelemetry packages. This library configures and extends that functionality.
19
20
 
20
- ### Promise API (Traditional)
21
+ ## Installation
21
22
 
22
- ```typescript
23
- import { initializeInstrumentation } from '@atrim/instrument-node'
23
+ ```bash
24
+ # Required
25
+ npm install @atrim/instrument-node @opentelemetry/api
24
26
 
25
- await initializeInstrumentation()
27
+ # Optional: Effect-TS integration
28
+ npm install effect @effect/opentelemetry @effect/platform @effect/platform-node
26
29
  ```
27
30
 
28
- ### Effect API (Recommended)
31
+ ## Quick Start
29
32
 
30
33
  ```typescript
31
- import { Effect } from 'effect'
32
- import { initializeInstrumentationEffect } from '@atrim/instrument-node'
34
+ import { initializeInstrumentation } from '@atrim/instrument-node'
33
35
 
34
- await Effect.runPromise(initializeInstrumentationEffect())
36
+ await initializeInstrumentation()
37
+ // Done! Traces go to http://localhost:4318
35
38
  ```
36
39
 
37
- **3. Done!** Your app is now sending traces to OpenTelemetry.
38
-
39
- By default, traces go to `http://localhost:4318`. To send to a remote collector:
40
+ **Remote collector:**
40
41
 
41
42
  ```typescript
42
43
  await initializeInstrumentation({
@@ -44,308 +45,106 @@ await initializeInstrumentation({
44
45
  })
45
46
  ```
46
47
 
47
- ### What just happened?
48
-
49
- Auto-detected and configured:
50
- - ✅ Service name from `package.json`
51
- - ✅ OTLP endpoint (local or remote)
52
- - ✅ Auto-instrumentation for Express, HTTP, Fastify, etc.
53
- - ✅ Graceful shutdown on SIGTERM/SIGINT
54
-
55
- ## Optional: Control What Gets Traced
56
-
57
- Create `instrumentation.yaml` in your project root:
58
-
59
- ```yaml
60
- version: "1.0"
61
- instrumentation:
62
- enabled: true
63
- instrument_patterns:
64
- - pattern: "^app\\." # ✅ Trace application operations
65
- ignore_patterns:
66
- - pattern: "^health\\." # ❌ Skip health checks
67
- ```
68
-
69
- That's it!
70
-
71
- ## Features
72
-
73
- - **Zero-config** - Works out of the box with sensible defaults
74
- - **Universal** - Node.js 20+, Bun 1.0+, Deno 1.40+
75
- - **Framework-agnostic** - Express, Fastify, Koa, Hono, vanilla HTTP
76
- - **Effect-TS first** - Typed error handling with Effect (optional)
77
- - **Pattern-based filtering** - Control which spans are created via YAML
78
- - **HTTP filtering** - Prevent noisy health checks and metrics endpoints
79
- - **Centralized config** - YAML file, URL, or environment variable
80
- - **Production-ready** - Graceful shutdown, error handling, performance optimized
81
-
82
- ## Documentation
83
-
84
- Full documentation is available in the [main repository](https://github.com/atrim-ai/instrumentation):
85
-
86
- ### Core Docs
87
-
88
- - 📖 [Getting Started](../../docs/getting-started.md) - 5-minute setup guide
89
- - ⚙️ [Configuration](../../docs/configuration.md) - YAML configuration reference
90
- - 📋 [Examples](../../docs/EXAMPLES.md) - 8+ working examples
91
- - 🔧 [Troubleshooting](../../docs/TROUBLESHOOTING.md) - Common issues and solutions
92
- - 📚 [API Reference](../../docs/api-reference.md) - Complete API documentation
93
-
94
- ### Specialized Guides
95
-
96
- - 🌐 [HTTP Filtering](../../docs/HTTP_FILTERING_INVESTIGATION.md) - Prevent noisy traces
97
- - 🔄 [Effect Integration](../../examples/effect-ts/README.md) - Effect-TS patterns
98
- - 🧪 [Testing Guide](../../docs/TESTING.md) - How to test instrumented apps
99
-
100
- ## Installation
101
-
102
- ### npm
103
-
104
- ```bash
105
- npm install @atrim/instrument-node
106
- ```
107
-
108
- ### yarn
48
+ **What gets auto-configured:**
109
49
 
110
- ```bash
111
- yarn add @atrim/instrument-node
112
- ```
113
-
114
- ### pnpm
115
-
116
- ```bash
117
- pnpm add @atrim/instrument-node
118
- ```
119
-
120
- ### Bun
50
+ - Service name from `package.json`
51
+ - OTLP endpoint
52
+ - Auto-instrumentation (HTTP, Express, Fastify, etc.)
53
+ - Graceful shutdown
121
54
 
122
- ```bash
123
- bun add @atrim/instrument-node
124
- ```
125
-
126
- ## Usage Examples
127
-
128
- ### Express Application
129
-
130
- ```typescript
131
- import express from 'express'
132
- import { initializeInstrumentation } from '@atrim/instrument-node'
133
-
134
- // Initialize at startup
135
- await initializeInstrumentation()
136
-
137
- const app = express()
138
-
139
- app.get('/users', async (req, res) => {
140
- // Automatically traced!
141
- const users = await fetchUsers()
142
- res.json(users)
143
- })
144
-
145
- app.listen(3000)
146
- ```
147
-
148
- ### Effect-TS Application
55
+ ## Effect-TS Integration
149
56
 
150
57
  ```typescript
151
58
  import { Effect, Layer } from 'effect'
152
59
  import { EffectInstrumentationLive } from '@atrim/instrument-node/effect'
153
60
 
154
61
  const program = Effect.gen(function* () {
155
- // Automatically traced with Effect.withSpan()
156
62
  yield* myOperation.pipe(Effect.withSpan('app.operation'))
157
- }).pipe(
158
- Effect.provide(EffectInstrumentationLive)
159
- )
63
+ }).pipe(Effect.provide(EffectInstrumentationLive))
160
64
 
161
65
  await Effect.runPromise(program)
162
66
  ```
163
67
 
164
- ### Bun Runtime
165
-
166
- ```typescript
167
- import { initializeInstrumentation } from '@atrim/instrument-node'
168
-
169
- // Works exactly the same as Node.js
170
- await initializeInstrumentation()
171
-
172
- Bun.serve({
173
- port: 3000,
174
- fetch(req) {
175
- return new Response('Hello from Bun!')
176
- }
177
- })
178
- ```
179
-
180
- ### Remote Configuration
68
+ **Span annotation helpers:**
181
69
 
182
70
  ```typescript
183
- import { initializeInstrumentation } from '@atrim/instrument-node'
71
+ import { annotateUser, annotateBatch, annotateCache } from '@atrim/instrument-node/effect'
184
72
 
185
- await initializeInstrumentation({
186
- configUrl: 'https://config.company.com/instrumentation.yaml',
187
- cacheTimeout: 300_000 // 5 minutes
188
- })
73
+ const process = Effect.gen(function* () {
74
+ yield* annotateUser('user-123', 'user@example.com')
75
+ yield* annotateBatch(100, 10)
76
+ yield* annotateCache(true, 'user:123')
77
+ // ...
78
+ }).pipe(Effect.withSpan('batch.process'))
189
79
  ```
190
80
 
191
- ## Configuration
192
-
193
- ### Priority Order (Highest to Lowest)
81
+ Available: `annotateUser`, `annotateBatch`, `annotateDataSize`, `annotateLLM`, `annotateQuery`, `annotateHttpRequest`, `annotateError`, `annotatePriority`, `annotateCache`
194
82
 
195
- 1. **Explicit Config Object** - Passed programmatically
196
- 2. **Environment Variable** - `ATRIM_INSTRUMENTATION_CONFIG`
197
- 3. **Project Root File** - `./instrumentation.yaml`
198
- 4. **Default Config** - Built-in defaults
83
+ ## Configuration (Optional)
199
84
 
200
- ### instrumentation.yaml Example
85
+ Create `instrumentation.yaml` in your project root:
201
86
 
202
87
  ```yaml
203
88
  version: "1.0"
204
-
205
89
  instrumentation:
206
90
  enabled: true
207
- logging: "on"
208
-
209
- # Pattern-based span filtering
210
91
  instrument_patterns:
211
- - pattern: "^app\\."
212
- enabled: true
213
- description: "Application operations"
214
- - pattern: "^storage\\."
215
- enabled: true
216
- description: "Storage layer"
217
-
92
+ - pattern: "^app\\." # Trace app operations
218
93
  ignore_patterns:
219
- - pattern: "^health\\."
220
- description: "Health checks"
221
- - pattern: "^metrics\\."
222
- description: "Metrics endpoints"
223
-
224
- # Effect-TS specific (optional)
225
- effect:
226
- auto_extract_metadata: true
227
- ```
228
-
229
- See [Configuration Guide](../../docs/configuration.md) for complete reference.
230
-
231
- ## HTTP Request Filtering
232
-
233
- **IMPORTANT:** HTTP filtering requires explicit configuration to prevent noisy traces.
234
-
235
- ### Add HTTP Filtering Patterns
236
-
237
- ```yaml
238
- # instrumentation.yaml
239
- instrumentation:
94
+ - pattern: "^health\\." # Skip health checks
240
95
  http_filtering:
241
96
  enabled: true
242
97
  ignore_routes:
243
98
  - pattern: "^/health$"
244
99
  - pattern: "^/metrics$"
245
- - pattern: "^/api/internal/"
246
- - pattern: "http://.*:4318/v1/traces" # Prevent OTLP trace loops!
247
100
  ```
248
101
 
249
- See [HTTP Filtering Guide](../../docs/HTTP_FILTERING_INVESTIGATION.md) for details.
250
-
251
- ## API Reference
252
-
253
- ### Standard API (Promise-based)
102
+ **Priority order:** Explicit config > `ATRIM_INSTRUMENTATION_CONFIG` env var > `./instrumentation.yaml` > defaults
254
103
 
255
- ```typescript
256
- // Main initialization
257
- initializeInstrumentation(options?: SdkInitializationOptions): Promise<NodeSDK | null>
258
-
259
- // Pattern matching only (skip SDK)
260
- initializePatternMatchingOnly(options?: ConfigLoaderOptions): Promise<void>
104
+ ## Runtimes & Frameworks
261
105
 
262
- // Configuration
263
- loadConfig(options?: ConfigLoaderOptions): Promise<InstrumentationConfig>
106
+ | Runtime | Version |
107
+ |---------|---------|
108
+ | Node.js | 20+ |
109
+ | Bun | 1.0+ |
110
+ | Deno | 1.40+ |
264
111
 
265
- // Service detection
266
- detectServiceInfo(): Promise<ServiceInfo>
267
- getServiceName(): Promise<string>
268
- getServiceVersion(): Promise<string>
269
- ```
112
+ | Framework | Support |
113
+ |-----------|---------|
114
+ | Express | Auto-instrumented (via OTel) |
115
+ | Fastify | Auto-instrumented (via OTel) |
116
+ | Koa | Auto-instrumented (via OTel) |
117
+ | Hono | Manual spans |
118
+ | Effect-TS | First-class integration (unique) |
270
119
 
271
- ### Effect API
120
+ ## Version Compatibility
272
121
 
273
- ```typescript
274
- // Main initialization (Effect)
275
- initializeInstrumentationEffect(options?: SdkInitializationOptions): Effect.Effect<NodeSDK | null, InitializationError | ConfigError>
276
-
277
- // Effect-TS Layer
278
- EffectInstrumentationLive: Layer.Layer<Tracer.Tracer, ConfigError, never>
279
-
280
- // Service detection (Effect)
281
- detectServiceInfoEffect: Effect.Effect<ServiceInfo, ServiceDetectionError>
282
- getServiceNameEffect: Effect.Effect<string, ServiceDetectionError>
283
- getServiceVersionEffect: Effect.Effect<string, never>
284
- ```
122
+ | @atrim/instrument-node | @opentelemetry/api | effect |
123
+ |------------------------|--------------------| -------|
124
+ | 0.6.x | ^1.0.0 (1.0 - 1.9+) | ^3.0.0 (optional) |
285
125
 
286
- See [API Reference](../../docs/api-reference.md) for complete documentation.
126
+ **Notes:**
287
127
 
288
- ## Runtimes Supported
289
-
290
- - **Node.js** 20.0.0+
291
- - ✅ **Bun** 1.0.0+
292
- - ✅ **Deno** 1.40.0+ (via npm compatibility)
293
-
294
- ## Frameworks Supported
295
-
296
- - ✅ **Express** - Auto-instrumentation included
297
- - ✅ **Fastify** - Auto-instrumentation included
298
- - ✅ **Koa** - Auto-instrumentation included
299
- - ✅ **Hono** - Works with manual spans
300
- - ✅ **Vanilla HTTP** - Works with any Node.js HTTP server
301
- - ✅ **Effect-TS** - First-class integration with Effect.withSpan()
302
-
303
- ## Examples
304
-
305
- See the [examples directory](../../examples/) for complete working examples:
306
-
307
- - [Express](../../examples/express/) - Basic Express app
308
- - [Effect-TS](../../examples/effect-ts/) - Advanced Effect patterns
309
- - [Effect Platform](../../examples/effect-platform/) - Pure Effect HTTP server
310
- - [Vanilla TypeScript](../../examples/vanilla/) - Standard Node.js
311
- - [Bun Runtime](../../examples/bun/) - Bun-specific example
312
- - [Remote Config](../../examples/remote-config/) - Load config from URL
313
- - [Multi-Service](../../examples/multi-service/) - Distributed tracing
128
+ - `@opentelemetry/api` is the only required peer dependency
129
+ - Effect packages are optional - core features work without them
130
+ - The library is tested with @opentelemetry/api 1.9.x in CI
314
131
 
315
132
  ## Troubleshooting
316
133
 
317
- See [Troubleshooting Guide](../../docs/TROUBLESHOOTING.md) for common issues and solutions.
318
-
319
- ### Quick Fixes
134
+ **No traces?** Check collector: `docker run -p 4318:4318 otel/opentelemetry-collector`
320
135
 
321
- **No traces appearing?**
322
- - Check collector is running: `docker run -p 4318:4318 otel/opentelemetry-collector`
323
- - Check endpoint: `OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318`
136
+ **Too many traces?** Add HTTP filtering patterns for health checks, metrics, OTLP exports.
324
137
 
325
- **Too many traces?**
326
- - Add HTTP filtering patterns (health checks, metrics, OTLP exports)
327
- - See [HTTP Filtering Guide](../../docs/HTTP_FILTERING_INVESTIGATION.md)
138
+ **Effect spans missing?** Ensure you're using `Effect.withSpan()` and providing `EffectInstrumentationLive`.
328
139
 
329
- **Effect-TS spans not appearing?**
330
- - Make sure you're using `Effect.withSpan()`
331
- - Provide `EffectInstrumentationLive` layer
332
-
333
- ## Contributing
140
+ ## Documentation
334
141
 
335
- Contributions welcome! See [main repository](https://github.com/atrim-ai/instrumentation) for guidelines.
142
+ - [Getting Started](../../docs/getting-started.md)
143
+ - [Configuration Reference](../../docs/configuration.md)
144
+ - [API Reference](../../docs/api-reference.md)
145
+ - [Examples](../../examples/)
146
+ - [Troubleshooting](../../docs/TROUBLESHOOTING.md)
336
147
 
337
148
  ## License
338
149
 
339
- MIT © Atrim AI
340
-
341
- ## Related Packages
342
-
343
- - [@atrim/instrument-core](../core) - Internal shared logic (private)
344
- - @atrim/instrument-web - Browser/web support _(Phase 1)_
345
-
346
- ## Links
347
-
348
- - 📦 [npm package](https://www.npmjs.com/package/@atrim/instrument-node)
349
- - 🐙 [GitHub repository](https://github.com/atrim-ai/instrumentation)
350
- - 🐛 [Issue tracker](https://github.com/atrim-ai/instrumentation/issues)
351
- - 📖 [Documentation](https://github.com/atrim-ai/instrumentation#readme)
150
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atrim/instrument-node",
3
- "version": "0.5.0",
3
+ "version": "0.5.1-3a86b84-20260105170223",
4
4
  "description": "OpenTelemetry instrumentation for Node.js with centralized YAML configuration",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -54,50 +54,48 @@
54
54
  "LICENSE"
55
55
  ],
56
56
  "dependencies": {
57
- "@effect/opentelemetry": "^0.59.0",
58
- "@effect/platform": "^0.93.0",
59
- "@effect/platform-node": "latest",
60
57
  "@opentelemetry/auto-instrumentations-node": "^0.67.0",
61
58
  "@opentelemetry/exporter-trace-otlp-http": "^0.208.0",
62
59
  "@opentelemetry/instrumentation": "^0.208.0",
60
+ "@opentelemetry/resources": "^2.2.0",
63
61
  "@opentelemetry/sdk-node": "^0.208.0",
64
62
  "@opentelemetry/sdk-trace-base": "^2.2.0",
65
- "effect": "^3.19.0",
63
+ "@opentelemetry/sdk-trace-node": "^2.2.0",
64
+ "@opentelemetry/semantic-conventions": "^1.38.0",
66
65
  "yaml": "^2.3.0",
67
66
  "zod": "^3.22.0"
68
67
  },
69
68
  "devDependencies": {
69
+ "@effect/opentelemetry": "^0.59.1",
70
+ "@effect/platform": "^0.93.6",
71
+ "@effect/platform-node": "^0.103.0",
70
72
  "@opentelemetry/api": "^1.9.0",
71
- "@opentelemetry/resources": "^2.2.0",
72
73
  "@opentelemetry/sdk-logs": "^0.208.0",
73
74
  "@opentelemetry/sdk-metrics": "^2.2.0",
74
75
  "@opentelemetry/sdk-trace-node": "^2.2.0",
75
76
  "@opentelemetry/sdk-trace-web": "^2.2.0",
76
77
  "@opentelemetry/semantic-conventions": "^1.38.0",
77
- "@types/node": "^20.10.0",
78
- "@vitest/coverage-v8": "^4.0.8",
79
- "effect": "^3.19.0",
80
- "testcontainers": "^11.8.1",
78
+ "@types/node": "^25.0.3",
79
+ "@vitest/coverage-v8": "^4.0.16",
80
+ "effect": "^3.19.8",
81
+ "testcontainers": "^11.11.0",
81
82
  "tsup": "^8.0.1",
82
83
  "tsx": "^4.7.0",
83
84
  "typescript": "^5.7.2",
84
- "vitest": "^4.0.8",
85
+ "vitest": "^4.0.16",
85
86
  "@atrim/instrument-core": "0.5.0"
86
87
  },
87
88
  "peerDependencies": {
89
+ "@opentelemetry/api": "^1.0.0",
90
+ "effect": "^3.0.0",
88
91
  "@effect/opentelemetry": ">=0.40.0",
89
92
  "@effect/platform": ">=0.70.0",
90
- "@opentelemetry/api": "^1.0.0",
91
- "@opentelemetry/sdk-trace-base": "^1.0.0",
92
- "effect": "^3.0.0"
93
+ "@effect/platform-node": ">=0.60.0"
93
94
  },
94
95
  "peerDependenciesMeta": {
95
96
  "@opentelemetry/api": {
96
97
  "optional": false
97
98
  },
98
- "@opentelemetry/sdk-trace-base": {
99
- "optional": true
100
- },
101
99
  "effect": {
102
100
  "optional": true
103
101
  },
@@ -106,6 +104,9 @@
106
104
  },
107
105
  "@effect/platform": {
108
106
  "optional": true
107
+ },
108
+ "@effect/platform-node": {
109
+ "optional": true
109
110
  }
110
111
  },
111
112
  "scripts": {
@@ -122,10 +123,10 @@
122
123
  "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
123
124
  "format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\"",
124
125
  "clean": "rm -rf target",
125
- "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",
126
+ "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",
126
127
  "publish:dev:save": "node -p \"require('./package.json').version\" > .version",
127
128
  "publish:dev:publish": "pnpm build && pnpm publish --tag dev --access public --no-git-checks",
128
- "publish:dev:reset": "npm version 1.0.0 --no-git-tag-version",
129
+ "publish:dev:reset": "pnpm version 0.5.1 --no-git-tag-version",
129
130
  "publish:dev": "pnpm publish:dev:version && pnpm publish:dev:save && pnpm publish:dev:publish && pnpm publish:dev:reset"
130
131
  }
131
132
  }