@atrim/instrument-node 0.4.1 → 0.5.0-3a3dd2c-20251124202015

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
@@ -161,6 +161,72 @@ const program = Effect.gen(function* () {
161
161
  await Effect.runPromise(program)
162
162
  ```
163
163
 
164
+ ### Effect-TS Span Annotation Helpers
165
+
166
+ The library provides 9 production-tested annotation helpers for enriching spans with semantic attributes:
167
+
168
+ ```typescript
169
+ import { Effect } from 'effect'
170
+ import {
171
+ annotateUser,
172
+ annotateBatch,
173
+ annotateDataSize,
174
+ annotateLLM,
175
+ annotateQuery,
176
+ annotateHttpRequest,
177
+ annotateError,
178
+ annotatePriority,
179
+ annotateCache,
180
+ autoEnrichSpan,
181
+ withAutoEnrichedSpan
182
+ } from '@atrim/instrument-node/effect'
183
+
184
+ // Example: Batch processing with automatic enrichment
185
+ const processBatch = Effect.gen(function* () {
186
+ // Auto-enrich with Effect metadata (fiber ID, status, parent span info)
187
+ yield* autoEnrichSpan()
188
+
189
+ // Add user context
190
+ yield* annotateUser('user-123', 'user@example.com')
191
+
192
+ // Add batch metadata
193
+ yield* annotateBatch(100, 10) // 100 items in batches of 10
194
+
195
+ // Process items
196
+ const results = yield* processItems(items)
197
+
198
+ // Update with results
199
+ yield* annotateBatch(100, 10, results.success, results.failures)
200
+
201
+ return results
202
+ }).pipe(Effect.withSpan('batch.process'))
203
+
204
+ // Or use the convenience wrapper
205
+ const processWithAutoEnrich = withAutoEnrichedSpan('batch.process')(
206
+ Effect.gen(function* () {
207
+ yield* annotateBatch(100, 10)
208
+ return yield* processItems(items)
209
+ })
210
+ )
211
+ ```
212
+
213
+ **Available annotation helpers:**
214
+ - `annotateUser(userId, email?, username?)` - User context
215
+ - `annotateDataSize(bytes, items, compressionRatio?)` - Data size metrics
216
+ - `annotateBatch(totalItems, batchSize, successCount?, failureCount?)` - Batch operations
217
+ - `annotateLLM(model, provider, tokens?)` - LLM operations (GPT, Claude, etc.)
218
+ - `annotateQuery(query, duration?, rowCount?, database?)` - Database queries
219
+ - `annotateHttpRequest(method, url, statusCode?, contentLength?)` - HTTP requests
220
+ - `annotateError(error, recoverable, errorType?)` - Error context
221
+ - `annotatePriority(priority, reason?)` - Operation priority
222
+ - `annotateCache(hit, key, ttl?)` - Cache operations
223
+
224
+ **Auto-enrichment utilities:**
225
+ - `autoEnrichSpan()` - Automatically add Effect metadata (fiber ID, status, parent span info)
226
+ - `withAutoEnrichedSpan(name, options?)` - Wrapper combining `Effect.withSpan()` + auto-enrichment
227
+
228
+ All helpers return `Effect.Effect<void>` and use `Effect.annotateCurrentSpan()` under the hood.
229
+
164
230
  ### Bun Runtime
165
231
 
166
232
  ```typescript
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atrim/instrument-node",
3
- "version": "0.4.1",
3
+ "version": "0.5.0-3a3dd2c-20251124202015",
4
4
  "description": "OpenTelemetry instrumentation for Node.js with centralized YAML configuration",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -43,6 +43,11 @@
43
43
  "types": "./target/dist/integrations/effect/index.d.ts",
44
44
  "import": "./target/dist/integrations/effect/index.js",
45
45
  "require": "./target/dist/integrations/effect/index.cjs"
46
+ },
47
+ "./effect/auto": {
48
+ "types": "./target/dist/integrations/effect/auto/index.d.ts",
49
+ "import": "./target/dist/integrations/effect/auto/index.js",
50
+ "require": "./target/dist/integrations/effect/auto/index.cjs"
46
51
  }
47
52
  },
48
53
  "main": "./target/dist/index.js",
@@ -82,7 +87,7 @@
82
87
  "tsx": "^4.7.0",
83
88
  "typescript": "^5.7.2",
84
89
  "vitest": "^4.0.8",
85
- "@atrim/instrument-core": "0.4.1"
90
+ "@atrim/instrument-core": "0.5.0"
86
91
  },
87
92
  "peerDependencies": {
88
93
  "@effect/opentelemetry": ">=0.40.0",
@@ -122,10 +127,10 @@
122
127
  "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
123
128
  "format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\"",
124
129
  "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",
130
+ "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
131
  "publish:dev:save": "node -p \"require('./package.json').version\" > .version",
127
132
  "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",
133
+ "publish:dev:reset": "pnpm version 0.5.0 --no-git-tag-version",
129
134
  "publish:dev": "pnpm publish:dev:version && pnpm publish:dev:save && pnpm publish:dev:publish && pnpm publish:dev:reset"
130
135
  }
131
136
  }
@@ -76,13 +76,69 @@ var AutoIsolationConfigSchema = zod.z.object({
76
76
  add_metadata: zod.z.boolean().default(true)
77
77
  }).default({})
78
78
  });
79
+ var SpanNamingRuleSchema = zod.z.object({
80
+ // Match conditions (all specified conditions must match)
81
+ match: zod.z.object({
82
+ // Match by file path pattern (regex)
83
+ file: zod.z.string().optional(),
84
+ // Match by function name pattern (regex)
85
+ function: zod.z.string().optional(),
86
+ // Match by operator type (gen, all, forEach, etc.)
87
+ operator: zod.z.string().optional(),
88
+ // Match by call stack pattern (regex)
89
+ stack: zod.z.string().optional(),
90
+ // Match by fiber annotation key
91
+ annotation: zod.z.string().optional()
92
+ }),
93
+ // Name template with substitution variables
94
+ // Available: {operator}, {function}, {module}, {file}, {line}, {class}, {match:N}
95
+ name: zod.z.string()
96
+ });
97
+ var AutoTracingConfigSchema = zod.z.object({
98
+ // Global enable/disable for auto-tracing
99
+ enabled: zod.z.boolean().default(true),
100
+ // Span naming configuration
101
+ span_naming: zod.z.object({
102
+ // Default name template when no rules match
103
+ default: zod.z.string().default("effect.{operator}"),
104
+ // Custom naming rules (applied in order, first match wins)
105
+ rules: zod.z.array(SpanNamingRuleSchema).default([])
106
+ }).default({}),
107
+ // Pattern filtering
108
+ filter_patterns: zod.z.object({
109
+ // Only trace spans matching these patterns
110
+ include: zod.z.array(zod.z.string()).default([]),
111
+ // Exclude spans matching these patterns (takes precedence)
112
+ exclude: zod.z.array(zod.z.string()).default([])
113
+ }).default({}),
114
+ // Sampling configuration
115
+ sampling: zod.z.object({
116
+ // Sampling rate (0.0 to 1.0)
117
+ rate: zod.z.number().min(0).max(1).default(1),
118
+ // Only trace effects with duration > this value
119
+ min_duration: zod.z.string().default("0 millis")
120
+ }).default({})
121
+ });
79
122
  var HttpFilteringConfigSchema = zod.z.object({
80
123
  // Patterns to ignore for outgoing HTTP requests (string patterns only in YAML)
81
124
  ignore_outgoing_urls: zod.z.array(zod.z.string()).optional(),
82
125
  // Patterns to ignore for incoming HTTP requests (string patterns only in YAML)
83
126
  ignore_incoming_paths: zod.z.array(zod.z.string()).optional(),
84
127
  // Require parent span for outgoing requests (prevents root spans for HTTP calls)
85
- require_parent_for_outgoing_spans: zod.z.boolean().optional()
128
+ require_parent_for_outgoing_spans: zod.z.boolean().optional(),
129
+ // Trace context propagation configuration
130
+ // Controls which cross-origin requests receive W3C Trace Context headers (traceparent, tracestate)
131
+ propagate_trace_context: zod.z.object({
132
+ // Strategy for trace propagation
133
+ // - "all": Propagate to all cross-origin requests (may cause CORS errors)
134
+ // - "none": Never propagate trace headers
135
+ // - "same-origin": Only propagate to same-origin requests (default, safe)
136
+ // - "patterns": Propagate based on include_urls patterns
137
+ strategy: zod.z.enum(["all", "none", "same-origin", "patterns"]).default("same-origin"),
138
+ // URL patterns to include when strategy is "patterns"
139
+ // Supports regex patterns (e.g., "^https://api\\.myapp\\.com")
140
+ include_urls: zod.z.array(zod.z.string()).optional()
141
+ }).optional()
86
142
  });
87
143
  var InstrumentationConfigSchema = zod.z.object({
88
144
  version: zod.z.string(),
@@ -95,7 +151,8 @@ var InstrumentationConfigSchema = zod.z.object({
95
151
  }),
96
152
  effect: zod.z.object({
97
153
  auto_extract_metadata: zod.z.boolean(),
98
- auto_isolation: AutoIsolationConfigSchema.optional()
154
+ auto_isolation: AutoIsolationConfigSchema.optional(),
155
+ auto_tracing: AutoTracingConfigSchema.optional()
99
156
  }).optional(),
100
157
  http: HttpFilteringConfigSchema.optional()
101
158
  });