autotel 4.0.0 → 4.2.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.
Files changed (232) hide show
  1. package/README.md +26 -1
  2. package/dist/auto.cjs +2 -2
  3. package/dist/auto.js +1 -1
  4. package/dist/correlation-id.cjs +1 -1
  5. package/dist/correlation-id.js +1 -1
  6. package/dist/decorators.cjs +1 -1
  7. package/dist/decorators.js +1 -1
  8. package/dist/{event-Dlqr4ZNL.cjs → event-BhHREDJk.cjs} +3 -3
  9. package/dist/{event-Dlqr4ZNL.cjs.map → event-BhHREDJk.cjs.map} +1 -1
  10. package/dist/{event-_58ryBjh.js → event-ByBTV9M2.js} +3 -3
  11. package/dist/{event-_58ryBjh.js.map → event-ByBTV9M2.js.map} +1 -1
  12. package/dist/event.cjs +1 -1
  13. package/dist/event.js +1 -1
  14. package/dist/{functional-BGkT8J-h.js → functional-DtI0u4vx.js} +19 -19
  15. package/dist/functional-DtI0u4vx.js.map +1 -0
  16. package/dist/{functional-C4CzoVrX.cjs → functional-zpzNLhky.cjs} +4 -4
  17. package/dist/{functional-C4CzoVrX.cjs.map → functional-zpzNLhky.cjs.map} +1 -1
  18. package/dist/functional.cjs +1 -1
  19. package/dist/functional.js +1 -1
  20. package/dist/http.cjs +1 -1
  21. package/dist/http.js +1 -1
  22. package/dist/index.cjs +5 -5
  23. package/dist/index.d.cts +1 -1
  24. package/dist/index.d.ts +1 -1
  25. package/dist/index.js +5 -5
  26. package/dist/{init-DJQOdVlN.d.ts → init-B7u-DjxM.d.ts} +57 -2
  27. package/dist/init-B7u-DjxM.d.ts.map +1 -0
  28. package/dist/{init-DvapOXCc.cjs → init-BX7AmFRl.cjs} +40 -21
  29. package/dist/init-BX7AmFRl.cjs.map +1 -0
  30. package/dist/{init-Ch6t7MNI.js → init-D-jnNMix.js} +39 -20
  31. package/dist/init-D-jnNMix.js.map +1 -0
  32. package/dist/{init-CNp-ee80.d.cts → init-DSrRmVnz.d.cts} +57 -2
  33. package/dist/init-DSrRmVnz.d.cts.map +1 -0
  34. package/dist/instrumentation.cjs +1 -1
  35. package/dist/instrumentation.js +1 -1
  36. package/dist/logger-D3Ej3DII.js +446 -0
  37. package/dist/logger-D3Ej3DII.js.map +1 -0
  38. package/dist/logger-thMPLpOG.cjs +487 -0
  39. package/dist/logger-thMPLpOG.cjs.map +1 -0
  40. package/dist/logger.cjs +8 -236
  41. package/dist/logger.js +2 -204
  42. package/dist/messaging.cjs +1 -1
  43. package/dist/messaging.js +1 -1
  44. package/dist/semantic-helpers.cjs +1 -1
  45. package/dist/semantic-helpers.js +1 -1
  46. package/dist/{track-3HY4NGV-.cjs → track-D59FfpL0.cjs} +2 -2
  47. package/dist/{track-3HY4NGV-.cjs.map → track-D59FfpL0.cjs.map} +1 -1
  48. package/dist/{track-nsKVy-pj.js → track-wc0HafS_.js} +6 -6
  49. package/dist/track-wc0HafS_.js.map +1 -0
  50. package/dist/webhook.cjs +1 -1
  51. package/dist/webhook.js +1 -1
  52. package/dist/workflow-distributed.cjs +1 -1
  53. package/dist/workflow-distributed.js +1 -1
  54. package/dist/workflow.cjs +1 -1
  55. package/dist/workflow.js +1 -1
  56. package/dist/{yaml-config-B3dQ82GR.cjs → yaml-config-Ck2uB0Dp.cjs} +2 -1
  57. package/dist/yaml-config-Ck2uB0Dp.cjs.map +1 -0
  58. package/dist/yaml-config.cjs +1 -1
  59. package/dist/yaml-config.d.cts +7 -1
  60. package/dist/yaml-config.d.cts.map +1 -1
  61. package/dist/yaml-config.d.ts +7 -1
  62. package/dist/yaml-config.d.ts.map +1 -1
  63. package/dist/yaml-config.js +1 -0
  64. package/dist/yaml-config.js.map +1 -1
  65. package/package.json +1 -2
  66. package/skills/autotel-core/SKILL.md +2 -0
  67. package/skills/autotel-instrumentation/SKILL.md +25 -0
  68. package/skills/debug-missing-spans/SKILL.md +3 -1
  69. package/skills/migrate-to-autotel/SKILL.md +24 -23
  70. package/skills/review-otel-patterns/SKILL.md +5 -4
  71. package/dist/functional-BGkT8J-h.js.map +0 -1
  72. package/dist/init-CNp-ee80.d.cts.map +0 -1
  73. package/dist/init-Ch6t7MNI.js.map +0 -1
  74. package/dist/init-DJQOdVlN.d.ts.map +0 -1
  75. package/dist/init-DvapOXCc.cjs.map +0 -1
  76. package/dist/logger.cjs.map +0 -1
  77. package/dist/logger.js.map +0 -1
  78. package/dist/track-nsKVy-pj.js.map +0 -1
  79. package/dist/yaml-config-B3dQ82GR.cjs.map +0 -1
  80. package/src/attribute-redacting-processor.test.ts +0 -763
  81. package/src/attribute-redacting-processor.ts +0 -621
  82. package/src/attributes/attachers.ts +0 -161
  83. package/src/attributes/builders.ts +0 -529
  84. package/src/attributes/domains.ts +0 -42
  85. package/src/attributes/index.ts +0 -81
  86. package/src/attributes/registry.ts +0 -323
  87. package/src/attributes/types.ts +0 -211
  88. package/src/attributes/utils.ts +0 -64
  89. package/src/attributes/validators.ts +0 -266
  90. package/src/attributes.test.ts +0 -292
  91. package/src/auto.ts +0 -67
  92. package/src/autotel-logger.test.ts +0 -548
  93. package/src/autotel-logger.ts +0 -364
  94. package/src/baggage-span-processor.test.ts +0 -202
  95. package/src/baggage-span-processor.ts +0 -100
  96. package/src/business-baggage.test.ts +0 -500
  97. package/src/business-baggage.ts +0 -669
  98. package/src/circuit-breaker.test.ts +0 -341
  99. package/src/circuit-breaker.ts +0 -184
  100. package/src/config.test.ts +0 -94
  101. package/src/config.ts +0 -172
  102. package/src/correlated-events.test.ts +0 -151
  103. package/src/correlated-events.ts +0 -47
  104. package/src/correlation-id.test.ts +0 -163
  105. package/src/correlation-id.ts +0 -206
  106. package/src/db.test.ts +0 -252
  107. package/src/db.ts +0 -447
  108. package/src/decorators.test.ts +0 -153
  109. package/src/decorators.ts +0 -188
  110. package/src/define-event.test.ts +0 -41
  111. package/src/define-event.ts +0 -58
  112. package/src/devtools.ts +0 -60
  113. package/src/drain-pipeline.test.ts +0 -68
  114. package/src/drain-pipeline.ts +0 -199
  115. package/src/drain-toolkit.test.ts +0 -113
  116. package/src/drain-toolkit.ts +0 -129
  117. package/src/enricher-toolkit.test.ts +0 -67
  118. package/src/enricher-toolkit.ts +0 -79
  119. package/src/enrichers.test.ts +0 -150
  120. package/src/enrichers.ts +0 -145
  121. package/src/env-config.test.ts +0 -323
  122. package/src/env-config.ts +0 -309
  123. package/src/error-catalog.test.ts +0 -133
  124. package/src/error-catalog.ts +0 -262
  125. package/src/event-queue.test.ts +0 -864
  126. package/src/event-queue.ts +0 -699
  127. package/src/event-subscriber.ts +0 -262
  128. package/src/event-testing.ts +0 -197
  129. package/src/event.test.ts +0 -1104
  130. package/src/event.ts +0 -988
  131. package/src/events-config.ts +0 -235
  132. package/src/exporters.ts +0 -165
  133. package/src/filtering-span-processor.test.ts +0 -281
  134. package/src/filtering-span-processor.ts +0 -111
  135. package/src/flatten-attributes.test.ts +0 -76
  136. package/src/flatten-attributes.ts +0 -80
  137. package/src/functional.strict-types.typecheck.ts +0 -53
  138. package/src/functional.test.ts +0 -1464
  139. package/src/functional.ts +0 -2539
  140. package/src/functional.types.test.ts +0 -135
  141. package/src/hook.mjs +0 -15
  142. package/src/http.test.ts +0 -485
  143. package/src/http.ts +0 -424
  144. package/src/index.ts +0 -433
  145. package/src/init-auto-redactor.test.ts +0 -53
  146. package/src/init-redactor.test.ts +0 -8
  147. package/src/init.customization.test.ts +0 -594
  148. package/src/init.integrations.test.ts +0 -399
  149. package/src/init.openllmetry.test.ts +0 -194
  150. package/src/init.protocol.test.ts +0 -215
  151. package/src/init.ts +0 -2312
  152. package/src/instrumentation.test.ts +0 -108
  153. package/src/instrumentation.ts +0 -319
  154. package/src/logger.test.ts +0 -125
  155. package/src/logger.ts +0 -341
  156. package/src/messaging-adapters.test.ts +0 -595
  157. package/src/messaging-adapters.ts +0 -583
  158. package/src/messaging-testing.test.ts +0 -573
  159. package/src/messaging-testing.ts +0 -935
  160. package/src/messaging.test.ts +0 -1646
  161. package/src/messaging.ts +0 -2245
  162. package/src/metric-helpers.ts +0 -47
  163. package/src/metric-testing.ts +0 -197
  164. package/src/metric.ts +0 -446
  165. package/src/metrics.test.ts +0 -241
  166. package/src/node-require.ts +0 -123
  167. package/src/operation-context.ts +0 -93
  168. package/src/parse-error.test.ts +0 -73
  169. package/src/parse-error.ts +0 -112
  170. package/src/posthog-logs.test.ts +0 -115
  171. package/src/posthog-logs.ts +0 -77
  172. package/src/pretty-console-exporter.test.ts +0 -545
  173. package/src/pretty-console-exporter.ts +0 -413
  174. package/src/pretty-log-formatter.test.ts +0 -123
  175. package/src/pretty-log-formatter.ts +0 -210
  176. package/src/processors/canonical-log-line-processor.test.ts +0 -523
  177. package/src/processors/canonical-log-line-processor.ts +0 -396
  178. package/src/processors.ts +0 -152
  179. package/src/rate-limiter.test.ts +0 -199
  180. package/src/rate-limiter.ts +0 -98
  181. package/src/redact-values.test.ts +0 -90
  182. package/src/redact-values.ts +0 -34
  183. package/src/register.ts +0 -37
  184. package/src/request-logger.test.ts +0 -545
  185. package/src/request-logger.ts +0 -342
  186. package/src/sampling.test.ts +0 -1060
  187. package/src/sampling.ts +0 -737
  188. package/src/security-schema.test.ts +0 -45
  189. package/src/security-schema.ts +0 -107
  190. package/src/semantic-conventions.ts +0 -15
  191. package/src/semantic-helpers.test.ts +0 -226
  192. package/src/semantic-helpers.ts +0 -438
  193. package/src/shutdown.test.ts +0 -364
  194. package/src/shutdown.ts +0 -246
  195. package/src/span-name-normalizer.test.ts +0 -377
  196. package/src/span-name-normalizer.ts +0 -213
  197. package/src/stable-hash.ts +0 -27
  198. package/src/structured-error.test.ts +0 -191
  199. package/src/structured-error.ts +0 -157
  200. package/src/stub.integration.test.ts +0 -361
  201. package/src/tail-sampling-processor.test.ts +0 -230
  202. package/src/tail-sampling-processor.ts +0 -55
  203. package/src/test-span-collector.test.ts +0 -234
  204. package/src/test-span-collector.ts +0 -150
  205. package/src/testing.ts +0 -705
  206. package/src/trace-context.test.ts +0 -73
  207. package/src/trace-context.ts +0 -567
  208. package/src/trace-helpers.new.test.ts +0 -278
  209. package/src/trace-helpers.test.ts +0 -290
  210. package/src/trace-helpers.ts +0 -710
  211. package/src/trace-hybrid.test.ts +0 -42
  212. package/src/trace-hybrid.ts +0 -37
  213. package/src/tracer-provider.test.ts +0 -183
  214. package/src/tracer-provider.ts +0 -266
  215. package/src/track.test.ts +0 -154
  216. package/src/track.ts +0 -216
  217. package/src/validate.test.ts +0 -287
  218. package/src/validate.ts +0 -307
  219. package/src/validation-attributes.ts +0 -43
  220. package/src/validation.test.ts +0 -330
  221. package/src/validation.ts +0 -246
  222. package/src/variable-name-inference.test.ts +0 -178
  223. package/src/variable-name-inference.ts +0 -242
  224. package/src/webhook.test.ts +0 -649
  225. package/src/webhook.ts +0 -637
  226. package/src/workflow-distributed.test.ts +0 -786
  227. package/src/workflow-distributed.ts +0 -916
  228. package/src/workflow.async-safety.integration.test.ts +0 -345
  229. package/src/workflow.test.ts +0 -647
  230. package/src/workflow.ts +0 -810
  231. package/src/yaml-config.test.ts +0 -337
  232. package/src/yaml-config.ts +0 -342
@@ -1,206 +0,0 @@
1
- /**
2
- * Correlation ID utilities for event-driven observability
3
- *
4
- * Provides a stable join key across events, logs, and spans even when traces fragment.
5
- * Format: 16 hex chars (64 bits), crypto-random, URL-safe.
6
- *
7
- * Lifecycle:
8
- * 1. Generated at boundary root (HTTP server span, message process span, cron job span)
9
- * 2. Reused within context (nested work shares it via AsyncLocalStorage)
10
- * 3. Propagated via baggage (optional, default OFF to avoid header bloat)
11
- *
12
- * @example Basic usage
13
- * ```typescript
14
- * import { generateCorrelationId, getCorrelationId } from 'autotel/correlation-id';
15
- *
16
- * // Generate a new correlation ID
17
- * const id = generateCorrelationId();
18
- * // Returns: 'a1b2c3d4e5f67890'
19
- *
20
- * // Get current correlation ID from context
21
- * const currentId = getCorrelationId();
22
- * ```
23
- */
24
-
25
- import { trace, propagation, context } from '@opentelemetry/api';
26
- import { AsyncLocalStorage } from 'node:async_hooks';
27
- import { enterOrRun } from './trace-context';
28
-
29
- type CorrelationStore = {
30
- value: string;
31
- };
32
-
33
- /**
34
- * AsyncLocalStorage for storing correlation ID
35
- * This allows correlation IDs to persist across async boundaries
36
- */
37
- const correlationStorage = new AsyncLocalStorage<CorrelationStore>();
38
-
39
- /**
40
- * Baggage key for correlation ID propagation
41
- */
42
- export const CORRELATION_ID_BAGGAGE_KEY = 'autotel.correlation_id';
43
-
44
- /**
45
- * Generate a new correlation ID
46
- *
47
- * Format: 16 hex chars (64 bits), crypto-random, URL-safe
48
- *
49
- * @returns A new correlation ID
50
- *
51
- * @example
52
- * ```typescript
53
- * const id = generateCorrelationId();
54
- * // Returns: 'a1b2c3d4e5f67890'
55
- * ```
56
- */
57
- export function generateCorrelationId(): string {
58
- // Use crypto.getRandomValues for secure random bytes
59
- const bytes = new Uint8Array(8); // 64 bits
60
- crypto.getRandomValues(bytes);
61
-
62
- // Convert to hex string
63
- return [...bytes].map((b) => b.toString(16).padStart(2, '0')).join('');
64
- }
65
-
66
- /**
67
- * Get the current correlation ID from context
68
- *
69
- * Resolution order:
70
- * 1. AsyncLocalStorage (from explicit setCorrelationId or runWithCorrelationId)
71
- * 2. Baggage (if propagated from upstream)
72
- * 3. Active span's trace ID (first 16 chars as fallback)
73
- * 4. undefined (if not in any context)
74
- *
75
- * @returns Current correlation ID or undefined
76
- *
77
- * @example
78
- * ```typescript
79
- * const id = getCorrelationId();
80
- * if (id) {
81
- * console.log('Correlation ID:', id);
82
- * }
83
- * ```
84
- */
85
- export function getCorrelationId(): string | undefined {
86
- // 1. Check AsyncLocalStorage first (explicit correlation ID)
87
- const storedId = correlationStorage.getStore()?.value;
88
- if (storedId) {
89
- return storedId;
90
- }
91
-
92
- // 2. Check baggage (propagated from upstream)
93
- const activeContext = context.active();
94
- const baggage = propagation.getBaggage(activeContext);
95
- const baggageEntry = baggage?.getEntry(CORRELATION_ID_BAGGAGE_KEY);
96
- if (baggageEntry?.value) {
97
- return baggageEntry.value;
98
- }
99
-
100
- // 3. Fall back to active span's trace ID (first 16 chars)
101
- const span = trace.getActiveSpan();
102
- if (span) {
103
- const spanContext = span.spanContext();
104
- return spanContext.traceId.slice(0, 16);
105
- }
106
-
107
- // 4. No context available
108
- return undefined;
109
- }
110
-
111
- /**
112
- * Get or create a correlation ID
113
- *
114
- * If a correlation ID exists in the current context, returns it.
115
- * Otherwise, generates a new one.
116
- *
117
- * @returns Existing or new correlation ID
118
- *
119
- * @example
120
- * ```typescript
121
- * const id = getOrCreateCorrelationId();
122
- * // Always returns a valid correlation ID
123
- * ```
124
- */
125
- export function getOrCreateCorrelationId(): string {
126
- return getCorrelationId() ?? generateCorrelationId();
127
- }
128
-
129
- /**
130
- * Run a function with a specific correlation ID in context
131
- *
132
- * The correlation ID will be available via getCorrelationId() throughout
133
- * the execution of the function and any async operations it spawns.
134
- *
135
- * @param correlationId - Correlation ID to use
136
- * @param fn - Function to execute
137
- * @returns The return value of the function
138
- *
139
- * @example
140
- * ```typescript
141
- * await runWithCorrelationId('abc123', async () => {
142
- * // getCorrelationId() returns 'abc123' here
143
- * await processRequest();
144
- * });
145
- * ```
146
- */
147
- export function runWithCorrelationId<T>(correlationId: string, fn: () => T): T {
148
- return correlationStorage.run({ value: correlationId }, fn);
149
- }
150
-
151
- /**
152
- * Set correlation ID in the current context (mutates context)
153
- *
154
- * Note: This updates the AsyncLocalStorage context. For proper scoping
155
- * across async boundaries, prefer runWithCorrelationId() instead.
156
- *
157
- * @param correlationId - Correlation ID to set
158
- *
159
- * @example
160
- * ```typescript
161
- * setCorrelationId('abc123');
162
- * // Now getCorrelationId() returns 'abc123'
163
- * ```
164
- */
165
- export function setCorrelationId(correlationId: string): void {
166
- enterOrRun(correlationStorage, correlationId);
167
- }
168
-
169
- /**
170
- * Set correlation ID in baggage for propagation
171
- *
172
- * This adds the correlation ID to the W3C baggage header, allowing it
173
- * to be propagated to downstream services.
174
- *
175
- * Note: Only use this when you explicitly want cross-service propagation.
176
- * Default is OFF to avoid header bloat.
177
- *
178
- * @param correlationId - Correlation ID to propagate
179
- * @returns New context with baggage set
180
- *
181
- * @example
182
- * ```typescript
183
- * const newContext = setCorrelationIdInBaggage('abc123');
184
- * context.with(newContext, () => {
185
- * // Baggage will be propagated in outgoing requests
186
- * });
187
- * ```
188
- */
189
- export function setCorrelationIdInBaggage(
190
- correlationId: string,
191
- ): import('@opentelemetry/api').Context {
192
- const activeContext = context.active();
193
- let baggage =
194
- propagation.getBaggage(activeContext) ?? propagation.createBaggage();
195
- baggage = baggage.setEntry(CORRELATION_ID_BAGGAGE_KEY, {
196
- value: correlationId,
197
- });
198
- return propagation.setBaggage(activeContext, baggage);
199
- }
200
-
201
- /**
202
- * Get the correlation storage instance (for internal use in init/shutdown)
203
- */
204
- export function getCorrelationStorage(): AsyncLocalStorage<CorrelationStore> {
205
- return correlationStorage;
206
- }
package/src/db.test.ts DELETED
@@ -1,252 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import {
3
- instrumentDatabase,
4
- tracebQuery,
5
- DB_SYSTEMS,
6
- DB_OPERATIONS,
7
- } from './db';
8
- import { configure, resetConfig } from './config';
9
-
10
- describe('instrumentDatabase', () => {
11
- beforeEach(() => {
12
- resetConfig();
13
- });
14
-
15
- it('should instrument database methods', async () => {
16
- const mockSpan = {
17
- setStatus: vi.fn(),
18
- setAttributes: vi.fn(),
19
- setAttribute: vi.fn(),
20
- end: vi.fn(),
21
- };
22
-
23
- const mockTracer = {
24
- startActiveSpan: vi.fn((name, fn) => fn(mockSpan)),
25
- };
26
-
27
- configure({
28
- tracer: mockTracer as any,
29
- });
30
-
31
- const repo = {
32
- async findUser(id: string) {
33
- return { id, name: 'Test' };
34
- },
35
- };
36
-
37
- instrumentDatabase(repo, {
38
- dbSystem: DB_SYSTEMS.POSTGRESQL,
39
- dbName: 'testdb',
40
- });
41
-
42
- const result = await repo.findUser('123');
43
-
44
- expect(result).toEqual({ id: '123', name: 'Test' });
45
- expect(mockTracer.startActiveSpan).toHaveBeenCalledWith(
46
- 'postgresql.SELECT user',
47
- expect.any(Function),
48
- );
49
- expect(mockSpan.setAttributes).toHaveBeenCalledWith(
50
- expect.objectContaining({
51
- 'db.system': 'postgresql',
52
- 'db.operation': 'SELECT',
53
- }),
54
- );
55
- expect(mockSpan.setAttribute).toHaveBeenCalledWith('db.name', 'testdb');
56
- expect(mockSpan.setAttribute).toHaveBeenCalledWith('db.sql.table', 'user');
57
- expect(mockSpan.end).toHaveBeenCalled();
58
- });
59
-
60
- it('should infer table names from method names', async () => {
61
- const mockSpan = {
62
- setStatus: vi.fn(),
63
- setAttributes: vi.fn(),
64
- setAttribute: vi.fn(),
65
- end: vi.fn(),
66
- };
67
-
68
- const mockTracer = {
69
- startActiveSpan: vi.fn((name, fn) => fn(mockSpan)),
70
- };
71
-
72
- configure({
73
- tracer: mockTracer as any,
74
- });
75
-
76
- const repo = {
77
- async createOrder() {
78
- return {};
79
- },
80
- async listUsers() {
81
- return [];
82
- },
83
- async deletePost() {
84
- return true;
85
- },
86
- };
87
-
88
- instrumentDatabase(repo, { dbSystem: 'postgresql' });
89
-
90
- await repo.createOrder();
91
- expect(mockTracer.startActiveSpan).toHaveBeenCalledWith(
92
- 'postgresql.INSERT order',
93
- expect.any(Function),
94
- );
95
-
96
- await repo.listUsers();
97
- expect(mockTracer.startActiveSpan).toHaveBeenCalledWith(
98
- 'postgresql.SELECT users',
99
- expect.any(Function),
100
- );
101
-
102
- await repo.deletePost();
103
- expect(mockTracer.startActiveSpan).toHaveBeenCalledWith(
104
- 'postgresql.DELETE post',
105
- expect.any(Function),
106
- );
107
- });
108
-
109
- it('should mark slow queries', async () => {
110
- const mockSpan = {
111
- setStatus: vi.fn(),
112
- setAttributes: vi.fn(),
113
- setAttribute: vi.fn(),
114
- end: vi.fn(),
115
- };
116
-
117
- const mockTracer = {
118
- startActiveSpan: vi.fn((name, fn) => fn(mockSpan)),
119
- };
120
-
121
- configure({
122
- tracer: mockTracer as any,
123
- });
124
-
125
- const repo = {
126
- async slowQuery() {
127
- await new Promise((resolve) => setTimeout(resolve, 50));
128
- return [];
129
- },
130
- };
131
-
132
- instrumentDatabase(repo, {
133
- dbSystem: 'postgresql',
134
- slowQueryThresholdMs: 10, // Very low threshold for testing
135
- });
136
- await repo.slowQuery();
137
-
138
- expect(mockSpan.setAttribute).toHaveBeenCalledWith('db.slow_query', true);
139
- expect(mockSpan.setAttribute).toHaveBeenCalledWith(
140
- 'db.slow_query_threshold_ms',
141
- 10,
142
- );
143
- });
144
-
145
- it('should track result counts for arrays', async () => {
146
- const mockSpan = {
147
- setStatus: vi.fn(),
148
- setAttributes: vi.fn(),
149
- setAttribute: vi.fn(),
150
- end: vi.fn(),
151
- };
152
-
153
- const mockTracer = {
154
- startActiveSpan: vi.fn((name, fn) => fn(mockSpan)),
155
- };
156
-
157
- configure({
158
- tracer: mockTracer as any,
159
- });
160
-
161
- const repo = {
162
- async listItems() {
163
- return [1, 2, 3, 4, 5];
164
- },
165
- };
166
-
167
- instrumentDatabase(repo, { dbSystem: 'postgresql' });
168
- await repo.listItems();
169
-
170
- expect(mockSpan.setAttribute).toHaveBeenCalledWith('db.result_count', 5);
171
- });
172
-
173
- it('should handle errors correctly', async () => {
174
- const mockSpan = {
175
- setStatus: vi.fn(),
176
- setAttributes: vi.fn(),
177
- setAttribute: vi.fn(),
178
- recordException: vi.fn(),
179
- end: vi.fn(),
180
- };
181
-
182
- const mockTracer = {
183
- startActiveSpan: vi.fn((name, fn) => fn(mockSpan)),
184
- };
185
-
186
- configure({
187
- tracer: mockTracer as any,
188
- });
189
-
190
- const repo = {
191
- async failingQuery() {
192
- throw new Error('Connection timeout');
193
- },
194
- };
195
-
196
- instrumentDatabase(repo, { dbSystem: 'postgresql' });
197
-
198
- await expect(repo.failingQuery()).rejects.toThrow('Connection timeout');
199
-
200
- expect(mockSpan.setStatus).toHaveBeenCalledWith({
201
- code: 2, // SpanStatusCode.ERROR
202
- message: 'Connection timeout',
203
- });
204
- expect(mockSpan.end).toHaveBeenCalled();
205
- });
206
- });
207
-
208
- describe('tracebQuery', () => {
209
- beforeEach(() => {
210
- resetConfig();
211
- });
212
-
213
- it('should trace database queries', async () => {
214
- const mockSpan = {
215
- setStatus: vi.fn(),
216
- setAttributes: vi.fn(),
217
- setAttribute: vi.fn(),
218
- end: vi.fn(),
219
- };
220
-
221
- const mockTracer = {
222
- startActiveSpan: vi.fn((name, fn) => fn(mockSpan)),
223
- };
224
-
225
- configure({
226
- tracer: mockTracer as any,
227
- });
228
-
229
- const result = await tracebQuery(
230
- DB_SYSTEMS.POSTGRESQL,
231
- DB_OPERATIONS.SELECT,
232
- async () => [{ id: 1 }],
233
- {
234
- 'db.statement': 'SELECT * FROM users',
235
- },
236
- );
237
-
238
- expect(result).toEqual([{ id: 1 }]);
239
- expect(mockTracer.startActiveSpan).toHaveBeenCalledWith(
240
- 'postgresql.SELECT',
241
- expect.any(Function),
242
- );
243
- expect(mockSpan.setAttributes).toHaveBeenCalledWith(
244
- expect.objectContaining({
245
- 'db.system': 'postgresql',
246
- 'db.operation': 'SELECT',
247
- 'db.statement': 'SELECT * FROM users',
248
- }),
249
- );
250
- expect(mockSpan.end).toHaveBeenCalled();
251
- });
252
- });