@atrim/instrument-node 0.1.0-7603d70-20251119002755

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,351 @@
1
+ # @atrim/instrument-node
2
+
3
+ **One-line OpenTelemetry for Node.js**
4
+
5
+ [![npm version](https://badge.fury.io/js/%40atrim%2Finstrument-node.svg)](https://www.npmjs.com/package/@atrim/instrument-node)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
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).
9
+
10
+ ## Quick Start
11
+
12
+ **1. Install**
13
+
14
+ ```bash
15
+ npm install @atrim/instrument-node
16
+ ```
17
+
18
+ **2. Initialize** (at the top of your app)
19
+
20
+ ### Promise API (Traditional)
21
+
22
+ ```typescript
23
+ import { initializeInstrumentation } from '@atrim/instrument-node'
24
+
25
+ await initializeInstrumentation()
26
+ ```
27
+
28
+ ### Effect API (Recommended)
29
+
30
+ ```typescript
31
+ import { Effect } from 'effect'
32
+ import { initializeInstrumentationEffect } from '@atrim/instrument-node'
33
+
34
+ await Effect.runPromise(initializeInstrumentationEffect())
35
+ ```
36
+
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
+
41
+ ```typescript
42
+ await initializeInstrumentation({
43
+ otlp: { endpoint: 'https://otel-collector.company.com:4318' }
44
+ })
45
+ ```
46
+
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
109
+
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
121
+
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
149
+
150
+ ```typescript
151
+ import { Effect, Layer } from 'effect'
152
+ import { EffectInstrumentationLive } from '@atrim/instrument-node/effect'
153
+
154
+ const program = Effect.gen(function* () {
155
+ // Automatically traced with Effect.withSpan()
156
+ yield* myOperation.pipe(Effect.withSpan('app.operation'))
157
+ }).pipe(
158
+ Effect.provide(EffectInstrumentationLive)
159
+ )
160
+
161
+ await Effect.runPromise(program)
162
+ ```
163
+
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
181
+
182
+ ```typescript
183
+ import { initializeInstrumentation } from '@atrim/instrument-node'
184
+
185
+ await initializeInstrumentation({
186
+ configUrl: 'https://config.company.com/instrumentation.yaml',
187
+ cacheTimeout: 300_000 // 5 minutes
188
+ })
189
+ ```
190
+
191
+ ## Configuration
192
+
193
+ ### Priority Order (Highest to Lowest)
194
+
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
199
+
200
+ ### instrumentation.yaml Example
201
+
202
+ ```yaml
203
+ version: "1.0"
204
+
205
+ instrumentation:
206
+ enabled: true
207
+ logging: "on"
208
+
209
+ # Pattern-based span filtering
210
+ instrument_patterns:
211
+ - pattern: "^app\\."
212
+ enabled: true
213
+ description: "Application operations"
214
+ - pattern: "^storage\\."
215
+ enabled: true
216
+ description: "Storage layer"
217
+
218
+ 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:
240
+ http_filtering:
241
+ enabled: true
242
+ ignore_routes:
243
+ - pattern: "^/health$"
244
+ - pattern: "^/metrics$"
245
+ - pattern: "^/api/internal/"
246
+ - pattern: "http://.*:4318/v1/traces" # Prevent OTLP trace loops!
247
+ ```
248
+
249
+ See [HTTP Filtering Guide](../../docs/HTTP_FILTERING_INVESTIGATION.md) for details.
250
+
251
+ ## API Reference
252
+
253
+ ### Standard API (Promise-based)
254
+
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>
261
+
262
+ // Configuration
263
+ loadConfig(options?: ConfigLoaderOptions): Promise<InstrumentationConfig>
264
+
265
+ // Service detection
266
+ detectServiceInfo(): Promise<ServiceInfo>
267
+ getServiceName(): Promise<string>
268
+ getServiceVersion(): Promise<string>
269
+ ```
270
+
271
+ ### Effect API
272
+
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
+ ```
285
+
286
+ See [API Reference](../../docs/api-reference.md) for complete documentation.
287
+
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
314
+
315
+ ## Troubleshooting
316
+
317
+ See [Troubleshooting Guide](../../docs/TROUBLESHOOTING.md) for common issues and solutions.
318
+
319
+ ### Quick Fixes
320
+
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`
324
+
325
+ **Too many traces?**
326
+ - Add HTTP filtering patterns (health checks, metrics, OTLP exports)
327
+ - See [HTTP Filtering Guide](../../docs/HTTP_FILTERING_INVESTIGATION.md)
328
+
329
+ **Effect-TS spans not appearing?**
330
+ - Make sure you're using `Effect.withSpan()`
331
+ - Provide `EffectInstrumentationLive` layer
332
+
333
+ ## Contributing
334
+
335
+ Contributions welcome! See [main repository](https://github.com/atrim-ai/instrumentation) for guidelines.
336
+
337
+ ## License
338
+
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)
package/package.json ADDED
@@ -0,0 +1,131 @@
1
+ {
2
+ "name": "@atrim/instrument-node",
3
+ "version": "0.1.0-7603d70-20251119002755",
4
+ "description": "OpenTelemetry instrumentation for Node.js 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/node"
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
+ "nodejs",
26
+ "bun",
27
+ "deno",
28
+ "effect",
29
+ "express",
30
+ "fastify"
31
+ ],
32
+ "engines": {
33
+ "node": ">=20.0.0",
34
+ "bun": ">=1.0.0"
35
+ },
36
+ "exports": {
37
+ ".": {
38
+ "types": "./target/dist/index.d.ts",
39
+ "import": "./target/dist/index.js",
40
+ "require": "./target/dist/index.cjs"
41
+ },
42
+ "./effect": {
43
+ "types": "./target/dist/integrations/effect/index.d.ts",
44
+ "import": "./target/dist/integrations/effect/index.js",
45
+ "require": "./target/dist/integrations/effect/index.cjs"
46
+ }
47
+ },
48
+ "main": "./target/dist/index.js",
49
+ "module": "./target/dist/index.js",
50
+ "types": "./target/dist/index.d.ts",
51
+ "files": [
52
+ "target/dist",
53
+ "README.md",
54
+ "LICENSE"
55
+ ],
56
+ "dependencies": {
57
+ "@effect/opentelemetry": "^0.59.0",
58
+ "@effect/platform": "^0.93.0",
59
+ "@effect/platform-node": "latest",
60
+ "@opentelemetry/auto-instrumentations-node": "^0.67.0",
61
+ "@opentelemetry/exporter-trace-otlp-http": "^0.208.0",
62
+ "@opentelemetry/instrumentation": "^0.208.0",
63
+ "@opentelemetry/sdk-node": "^0.208.0",
64
+ "@opentelemetry/sdk-trace-base": "^2.2.0",
65
+ "effect": "^3.19.0",
66
+ "yaml": "^2.3.0",
67
+ "zod": "^3.22.0"
68
+ },
69
+ "devDependencies": {
70
+ "@opentelemetry/api": "^1.9.0",
71
+ "@opentelemetry/resources": "^2.2.0",
72
+ "@opentelemetry/sdk-logs": "^0.208.0",
73
+ "@opentelemetry/sdk-metrics": "^2.2.0",
74
+ "@opentelemetry/sdk-trace-node": "^2.2.0",
75
+ "@opentelemetry/sdk-trace-web": "^2.2.0",
76
+ "@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",
81
+ "tsup": "^8.0.1",
82
+ "tsx": "^4.7.0",
83
+ "typescript": "^5.7.2",
84
+ "vitest": "^4.0.8",
85
+ "@atrim/instrument-core": "0.4.0"
86
+ },
87
+ "peerDependencies": {
88
+ "@effect/opentelemetry": ">=0.40.0",
89
+ "@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
+ },
94
+ "peerDependenciesMeta": {
95
+ "@opentelemetry/api": {
96
+ "optional": false
97
+ },
98
+ "@opentelemetry/sdk-trace-base": {
99
+ "optional": true
100
+ },
101
+ "effect": {
102
+ "optional": true
103
+ },
104
+ "@effect/opentelemetry": {
105
+ "optional": true
106
+ },
107
+ "@effect/platform": {
108
+ "optional": true
109
+ }
110
+ },
111
+ "scripts": {
112
+ "build": "tsup",
113
+ "dev": "tsup --watch",
114
+ "test": "vitest run",
115
+ "test:watch": "vitest",
116
+ "test:coverage": "vitest run --coverage",
117
+ "test:integration": "OTEL_BSP_SCHEDULE_DELAY=500 vitest run --config vitest.integration.config.ts",
118
+ "test:all": "pnpm test && pnpm test:integration",
119
+ "typecheck": "tsc --noEmit",
120
+ "lint": "eslint src",
121
+ "lint:fix": "eslint src --fix",
122
+ "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
123
+ "format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\"",
124
+ "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:save": "node -p \"require('./package.json').version\" > .version",
127
+ "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": "pnpm publish:dev:version && pnpm publish:dev:save && pnpm publish:dev:publish && pnpm publish:dev:reset"
130
+ }
131
+ }