autotel 4.1.0 → 4.2.1

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 (253) hide show
  1. package/dist/auto.cjs +5 -3
  2. package/dist/auto.cjs.map +1 -1
  3. package/dist/auto.js +3 -3
  4. package/dist/auto.js.map +1 -1
  5. package/dist/chunk-C_NdSu1c.cjs +34 -0
  6. package/dist/correlation-id.cjs +1 -1
  7. package/dist/correlation-id.d.cts.map +1 -1
  8. package/dist/correlation-id.d.ts.map +1 -1
  9. package/dist/correlation-id.js +1 -1
  10. package/dist/decorators.cjs +1 -1
  11. package/dist/decorators.js +1 -1
  12. package/dist/{event-ByBTV9M2.js → event-531asIM6.js} +4 -4
  13. package/dist/{event-ByBTV9M2.js.map → event-531asIM6.js.map} +1 -1
  14. package/dist/{event-BhHREDJk.cjs → event-CcZYwp50.cjs} +4 -4
  15. package/dist/{event-BhHREDJk.cjs.map → event-CcZYwp50.cjs.map} +1 -1
  16. package/dist/event.cjs +1 -1
  17. package/dist/event.js +1 -1
  18. package/dist/{functional-zpzNLhky.cjs → functional-C8B0Qa7o.cjs} +10 -7
  19. package/dist/functional-C8B0Qa7o.cjs.map +1 -0
  20. package/dist/{functional-DtI0u4vx.js → functional-r-AUIRy_.js} +9 -9
  21. package/dist/functional-r-AUIRy_.js.map +1 -0
  22. package/dist/functional.cjs +1 -1
  23. package/dist/functional.js +1 -1
  24. package/dist/http.cjs +1 -1
  25. package/dist/http.js +1 -1
  26. package/dist/index.cjs +15 -13
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts.map +1 -1
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +14 -14
  31. package/dist/index.js.map +1 -1
  32. package/dist/{init-D-jnNMix.js → init-BS2JVkrL.js} +2 -2
  33. package/dist/{init-D-jnNMix.js.map → init-BS2JVkrL.js.map} +1 -1
  34. package/dist/{init-BX7AmFRl.cjs → init-BXiuPK6j.cjs} +3 -3
  35. package/dist/{init-BX7AmFRl.cjs.map → init-BXiuPK6j.cjs.map} +1 -1
  36. package/dist/instrumentation.cjs +2 -2
  37. package/dist/instrumentation.js +2 -2
  38. package/dist/logger.cjs +236 -8
  39. package/dist/logger.cjs.map +1 -0
  40. package/dist/messaging.cjs +1 -1
  41. package/dist/messaging.js +1 -1
  42. package/dist/{node-require-DF5QBX6z.cjs → node-require-CZ_PU448.cjs} +6 -4
  43. package/dist/node-require-CZ_PU448.cjs.map +1 -0
  44. package/dist/{node-require-Db1oDpLj.js → node-require-vROmTeJ8.js} +5 -5
  45. package/dist/node-require-vROmTeJ8.js.map +1 -0
  46. package/dist/{operation-context-C-2hmmtP.js → operation-context-CKBoA4Qy.js} +3 -3
  47. package/dist/operation-context-CKBoA4Qy.js.map +1 -0
  48. package/dist/{operation-context-n4_obUwq.cjs → operation-context-D6LDf4W_.cjs} +3 -1
  49. package/dist/operation-context-D6LDf4W_.cjs.map +1 -0
  50. package/dist/register.cjs +3 -1
  51. package/dist/register.cjs.map +1 -1
  52. package/dist/register.js +2 -2
  53. package/dist/register.js.map +1 -1
  54. package/dist/semantic-helpers.cjs +1 -1
  55. package/dist/semantic-helpers.js +1 -1
  56. package/dist/{stable-hash-Cg5cT34Q.js → stable-hash-ChFBIhNt.js} +3 -3
  57. package/dist/stable-hash-ChFBIhNt.js.map +1 -0
  58. package/dist/{stable-hash-BNTMrmdB.cjs → stable-hash-brKISGf1.cjs} +4 -2
  59. package/dist/stable-hash-brKISGf1.cjs.map +1 -0
  60. package/dist/trace-context-Cijqoi6e.d.cts.map +1 -1
  61. package/dist/trace-context-Cijqoi6e.d.ts.map +1 -1
  62. package/dist/trace-helpers.cjs +1 -1
  63. package/dist/trace-helpers.js +1 -1
  64. package/dist/{track-wc0HafS_.js → track-COUuU48p.js} +5 -5
  65. package/dist/track-COUuU48p.js.map +1 -0
  66. package/dist/{track-D59FfpL0.cjs → track-Cb3Q4QmS.cjs} +4 -2
  67. package/dist/track-Cb3Q4QmS.cjs.map +1 -0
  68. package/dist/validate.cjs +1 -1
  69. package/dist/validate.js +1 -1
  70. package/dist/webhook.cjs +1 -1
  71. package/dist/webhook.js +1 -1
  72. package/dist/workflow-distributed.cjs +1 -1
  73. package/dist/workflow-distributed.js +1 -1
  74. package/dist/workflow.cjs +3 -1
  75. package/dist/workflow.cjs.map +1 -1
  76. package/dist/workflow.d.cts.map +1 -1
  77. package/dist/workflow.d.ts.map +1 -1
  78. package/dist/workflow.js +3 -3
  79. package/dist/workflow.js.map +1 -1
  80. package/dist/yaml-config.cjs +233 -4
  81. package/dist/yaml-config.cjs.map +1 -0
  82. package/dist/yaml-config.d.cts.map +1 -1
  83. package/dist/yaml-config.d.ts.map +1 -1
  84. package/dist/yaml-config.js +8 -7
  85. package/dist/yaml-config.js.map +1 -1
  86. package/package.json +1 -2
  87. package/dist/functional-DtI0u4vx.js.map +0 -1
  88. package/dist/functional-zpzNLhky.cjs.map +0 -1
  89. package/dist/logger-thMPLpOG.cjs +0 -487
  90. package/dist/logger-thMPLpOG.cjs.map +0 -1
  91. package/dist/node-require-DF5QBX6z.cjs.map +0 -1
  92. package/dist/node-require-Db1oDpLj.js.map +0 -1
  93. package/dist/operation-context-C-2hmmtP.js.map +0 -1
  94. package/dist/operation-context-n4_obUwq.cjs.map +0 -1
  95. package/dist/stable-hash-BNTMrmdB.cjs.map +0 -1
  96. package/dist/stable-hash-Cg5cT34Q.js.map +0 -1
  97. package/dist/track-D59FfpL0.cjs.map +0 -1
  98. package/dist/track-wc0HafS_.js.map +0 -1
  99. package/dist/yaml-config-Ck2uB0Dp.cjs +0 -273
  100. package/dist/yaml-config-Ck2uB0Dp.cjs.map +0 -1
  101. package/src/attribute-redacting-processor.test.ts +0 -763
  102. package/src/attribute-redacting-processor.ts +0 -621
  103. package/src/attributes/attachers.ts +0 -161
  104. package/src/attributes/builders.ts +0 -529
  105. package/src/attributes/domains.ts +0 -42
  106. package/src/attributes/index.ts +0 -81
  107. package/src/attributes/registry.ts +0 -323
  108. package/src/attributes/types.ts +0 -211
  109. package/src/attributes/utils.ts +0 -64
  110. package/src/attributes/validators.ts +0 -266
  111. package/src/attributes.test.ts +0 -292
  112. package/src/auto.ts +0 -67
  113. package/src/autotel-logger.test.ts +0 -548
  114. package/src/autotel-logger.ts +0 -364
  115. package/src/baggage-span-processor.test.ts +0 -202
  116. package/src/baggage-span-processor.ts +0 -100
  117. package/src/business-baggage.test.ts +0 -500
  118. package/src/business-baggage.ts +0 -669
  119. package/src/circuit-breaker.test.ts +0 -341
  120. package/src/circuit-breaker.ts +0 -184
  121. package/src/config.test.ts +0 -94
  122. package/src/config.ts +0 -172
  123. package/src/correlated-events.test.ts +0 -151
  124. package/src/correlated-events.ts +0 -47
  125. package/src/correlation-id.test.ts +0 -163
  126. package/src/correlation-id.ts +0 -206
  127. package/src/db.test.ts +0 -252
  128. package/src/db.ts +0 -447
  129. package/src/decorators.test.ts +0 -153
  130. package/src/decorators.ts +0 -188
  131. package/src/define-event.test.ts +0 -41
  132. package/src/define-event.ts +0 -58
  133. package/src/devtools.ts +0 -60
  134. package/src/drain-pipeline.test.ts +0 -68
  135. package/src/drain-pipeline.ts +0 -199
  136. package/src/drain-toolkit.test.ts +0 -113
  137. package/src/drain-toolkit.ts +0 -129
  138. package/src/enricher-toolkit.test.ts +0 -67
  139. package/src/enricher-toolkit.ts +0 -79
  140. package/src/enrichers.test.ts +0 -150
  141. package/src/enrichers.ts +0 -145
  142. package/src/env-config.test.ts +0 -323
  143. package/src/env-config.ts +0 -309
  144. package/src/error-catalog.test.ts +0 -133
  145. package/src/error-catalog.ts +0 -262
  146. package/src/event-queue.test.ts +0 -864
  147. package/src/event-queue.ts +0 -699
  148. package/src/event-subscriber.ts +0 -262
  149. package/src/event-testing.ts +0 -197
  150. package/src/event.test.ts +0 -1104
  151. package/src/event.ts +0 -988
  152. package/src/events-config.ts +0 -235
  153. package/src/exporters.ts +0 -165
  154. package/src/filtering-span-processor.test.ts +0 -281
  155. package/src/filtering-span-processor.ts +0 -111
  156. package/src/flatten-attributes.test.ts +0 -76
  157. package/src/flatten-attributes.ts +0 -80
  158. package/src/functional.strict-types.typecheck.ts +0 -53
  159. package/src/functional.test.ts +0 -1464
  160. package/src/functional.ts +0 -2539
  161. package/src/functional.types.test.ts +0 -135
  162. package/src/hook.mjs +0 -15
  163. package/src/http.test.ts +0 -485
  164. package/src/http.ts +0 -424
  165. package/src/index.ts +0 -433
  166. package/src/init-auto-redactor.test.ts +0 -53
  167. package/src/init-redactor.test.ts +0 -8
  168. package/src/init.customization.test.ts +0 -665
  169. package/src/init.integrations.test.ts +0 -399
  170. package/src/init.openllmetry.test.ts +0 -194
  171. package/src/init.protocol.test.ts +0 -215
  172. package/src/init.ts +0 -2439
  173. package/src/instrumentation.test.ts +0 -108
  174. package/src/instrumentation.ts +0 -319
  175. package/src/logger.test.ts +0 -125
  176. package/src/logger.ts +0 -341
  177. package/src/messaging-adapters.test.ts +0 -595
  178. package/src/messaging-adapters.ts +0 -583
  179. package/src/messaging-testing.test.ts +0 -573
  180. package/src/messaging-testing.ts +0 -935
  181. package/src/messaging.test.ts +0 -1646
  182. package/src/messaging.ts +0 -2245
  183. package/src/metric-helpers.ts +0 -47
  184. package/src/metric-testing.ts +0 -197
  185. package/src/metric.ts +0 -446
  186. package/src/metrics.test.ts +0 -241
  187. package/src/node-require.ts +0 -123
  188. package/src/operation-context.ts +0 -93
  189. package/src/parse-error.test.ts +0 -73
  190. package/src/parse-error.ts +0 -112
  191. package/src/posthog-logs.test.ts +0 -115
  192. package/src/posthog-logs.ts +0 -77
  193. package/src/pretty-console-exporter.test.ts +0 -545
  194. package/src/pretty-console-exporter.ts +0 -413
  195. package/src/pretty-log-formatter.test.ts +0 -123
  196. package/src/pretty-log-formatter.ts +0 -210
  197. package/src/processors/canonical-log-line-processor.test.ts +0 -523
  198. package/src/processors/canonical-log-line-processor.ts +0 -396
  199. package/src/processors.ts +0 -152
  200. package/src/rate-limiter.test.ts +0 -199
  201. package/src/rate-limiter.ts +0 -98
  202. package/src/redact-values.test.ts +0 -90
  203. package/src/redact-values.ts +0 -34
  204. package/src/register.ts +0 -37
  205. package/src/request-logger.test.ts +0 -545
  206. package/src/request-logger.ts +0 -342
  207. package/src/sampling.test.ts +0 -1060
  208. package/src/sampling.ts +0 -737
  209. package/src/security-schema.test.ts +0 -45
  210. package/src/security-schema.ts +0 -107
  211. package/src/semantic-conventions.ts +0 -15
  212. package/src/semantic-helpers.test.ts +0 -226
  213. package/src/semantic-helpers.ts +0 -438
  214. package/src/shutdown.test.ts +0 -364
  215. package/src/shutdown.ts +0 -246
  216. package/src/span-name-normalizer.test.ts +0 -377
  217. package/src/span-name-normalizer.ts +0 -213
  218. package/src/stable-hash.ts +0 -27
  219. package/src/structured-error.test.ts +0 -191
  220. package/src/structured-error.ts +0 -157
  221. package/src/stub.integration.test.ts +0 -361
  222. package/src/tail-sampling-processor.test.ts +0 -230
  223. package/src/tail-sampling-processor.ts +0 -55
  224. package/src/test-span-collector.test.ts +0 -234
  225. package/src/test-span-collector.ts +0 -150
  226. package/src/testing.ts +0 -705
  227. package/src/trace-context.test.ts +0 -73
  228. package/src/trace-context.ts +0 -567
  229. package/src/trace-helpers.new.test.ts +0 -278
  230. package/src/trace-helpers.test.ts +0 -290
  231. package/src/trace-helpers.ts +0 -710
  232. package/src/trace-hybrid.test.ts +0 -42
  233. package/src/trace-hybrid.ts +0 -37
  234. package/src/tracer-provider.test.ts +0 -183
  235. package/src/tracer-provider.ts +0 -266
  236. package/src/track.test.ts +0 -154
  237. package/src/track.ts +0 -216
  238. package/src/validate.test.ts +0 -287
  239. package/src/validate.ts +0 -307
  240. package/src/validation-attributes.ts +0 -43
  241. package/src/validation.test.ts +0 -330
  242. package/src/validation.ts +0 -246
  243. package/src/variable-name-inference.test.ts +0 -178
  244. package/src/variable-name-inference.ts +0 -242
  245. package/src/webhook.test.ts +0 -649
  246. package/src/webhook.ts +0 -637
  247. package/src/workflow-distributed.test.ts +0 -786
  248. package/src/workflow-distributed.ts +0 -916
  249. package/src/workflow.async-safety.integration.test.ts +0 -345
  250. package/src/workflow.test.ts +0 -647
  251. package/src/workflow.ts +0 -810
  252. package/src/yaml-config.test.ts +0 -373
  253. package/src/yaml-config.ts +0 -351
package/src/event.test.ts DELETED
@@ -1,1104 +0,0 @@
1
- import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
2
- import { Event, getEvents, resetEvents } from './event';
3
- import { type Logger } from './logger';
4
- import { init } from './init';
5
- import { shutdown } from './shutdown';
6
- import { trace } from './functional';
7
- import { context, propagation } from '@opentelemetry/api';
8
-
9
- describe('Events', () => {
10
- let mockLogger: Logger;
11
-
12
- beforeEach(() => {
13
- resetEvents();
14
- mockLogger = {
15
- info: vi.fn(),
16
- warn: vi.fn(),
17
- error: vi.fn(),
18
- debug: vi.fn(),
19
- };
20
- });
21
-
22
- describe('trackEvent', () => {
23
- it('should track business events', () => {
24
- const event = new Event('test-service', { logger: mockLogger });
25
-
26
- event.trackEvent('application.submitted', {
27
- jobId: '123',
28
- userId: '456',
29
- });
30
-
31
- // Pino-native: (extra, message)
32
- expect(mockLogger.info).toHaveBeenCalledWith(
33
- {
34
- event: 'application.submitted',
35
- attributes: { service: 'test-service', jobId: '123', userId: '456' },
36
- },
37
- 'Event tracked',
38
- );
39
- });
40
-
41
- it('should track events without attributes', () => {
42
- const event = new Event('test-service', { logger: mockLogger });
43
-
44
- event.trackEvent('user.login');
45
-
46
- // Pino-native: (extra, message)
47
- expect(mockLogger.info).toHaveBeenCalledWith(
48
- {
49
- event: 'user.login',
50
- attributes: { service: 'test-service' },
51
- },
52
- 'Event tracked',
53
- );
54
- });
55
- });
56
-
57
- describe('trackFunnelStep', () => {
58
- it('should track funnel progression', () => {
59
- const event = new Event('test-service', { logger: mockLogger });
60
-
61
- event.trackFunnelStep('checkout', 'started', { cartValue: 99.99 });
62
- event.trackFunnelStep('checkout', 'completed', { cartValue: 99.99 });
63
-
64
- expect(mockLogger.info).toHaveBeenCalledTimes(2);
65
- // Pino-native: (extra, message)
66
- expect(mockLogger.info).toHaveBeenCalledWith(
67
- {
68
- funnel: 'checkout',
69
- status: 'started',
70
- attributes: { service: 'test-service', cartValue: 99.99 },
71
- },
72
- 'Funnel step tracked',
73
- );
74
- });
75
-
76
- it('should track funnel abandonment', () => {
77
- const event = new Event('test-service', { logger: mockLogger });
78
-
79
- event.trackFunnelStep('checkout', 'abandoned', { reason: 'timeout' });
80
-
81
- // Pino-native: (extra, message)
82
- expect(mockLogger.info).toHaveBeenCalledWith(
83
- {
84
- funnel: 'checkout',
85
- status: 'abandoned',
86
- attributes: { service: 'test-service', reason: 'timeout' },
87
- },
88
- 'Funnel step tracked',
89
- );
90
- });
91
- });
92
-
93
- describe('trackOutcome', () => {
94
- it('should track successful outcomes', () => {
95
- const event = new Event('test-service', { logger: mockLogger });
96
-
97
- event.trackOutcome('email.delivery', 'success', {
98
- recipientType: 'school',
99
- });
100
-
101
- // Pino-native: (extra, message)
102
- expect(mockLogger.info).toHaveBeenCalledWith(
103
- {
104
- operation: 'email.delivery',
105
- status: 'success',
106
- attributes: { service: 'test-service', recipientType: 'school' },
107
- },
108
- 'Outcome tracked',
109
- );
110
- });
111
-
112
- it('should track failed outcomes', () => {
113
- const event = new Event('test-service', { logger: mockLogger });
114
-
115
- event.trackOutcome('email.delivery', 'failure', {
116
- error: 'invalid_email',
117
- });
118
-
119
- // Pino-native: (extra, message)
120
- expect(mockLogger.info).toHaveBeenCalledWith(
121
- {
122
- operation: 'email.delivery',
123
- status: 'failure',
124
- attributes: { service: 'test-service', error: 'invalid_email' },
125
- },
126
- 'Outcome tracked',
127
- );
128
- });
129
-
130
- it('should track partial outcomes', () => {
131
- const event = new Event('test-service', { logger: mockLogger });
132
-
133
- event.trackOutcome('batch.process', 'partial', {
134
- successCount: 8,
135
- failureCount: 2,
136
- });
137
-
138
- // Pino-native: (extra, message)
139
- expect(mockLogger.info).toHaveBeenCalledWith(
140
- {
141
- operation: 'batch.process',
142
- status: 'partial',
143
- attributes: {
144
- service: 'test-service',
145
- successCount: 8,
146
- failureCount: 2,
147
- },
148
- },
149
- 'Outcome tracked',
150
- );
151
- });
152
- });
153
-
154
- describe('trackValue', () => {
155
- it('should track revenue metrics', () => {
156
- const event = new Event('test-service', { logger: mockLogger });
157
-
158
- event.trackValue('order.revenue', 149.99, {
159
- currency: 'USD',
160
- productCategory: 'electronics',
161
- });
162
-
163
- // Pino-native: (extra, message)
164
- expect(mockLogger.debug).toHaveBeenCalledWith(
165
- {
166
- metric: 'order.revenue',
167
- value: 149.99,
168
- attributes: {
169
- service: 'test-service',
170
- metric: 'order.revenue',
171
- currency: 'USD',
172
- productCategory: 'electronics',
173
- },
174
- },
175
- 'Value tracked',
176
- );
177
- });
178
-
179
- it('should track processing time', () => {
180
- const event = new Event('test-service', { logger: mockLogger });
181
-
182
- event.trackValue('application.processing_time', 2500, {
183
- unit: 'ms',
184
- });
185
-
186
- // Pino-native: (extra, message)
187
- expect(mockLogger.debug).toHaveBeenCalledWith(
188
- {
189
- metric: 'application.processing_time',
190
- value: 2500,
191
- attributes: {
192
- service: 'test-service',
193
- metric: 'application.processing_time',
194
- unit: 'ms',
195
- },
196
- },
197
- 'Value tracked',
198
- );
199
- });
200
- });
201
-
202
- describe('getEvents', () => {
203
- it('should return singleton instance', () => {
204
- const events1 = getEvents('test-service');
205
- const events2 = getEvents('test-service');
206
-
207
- expect(events1).toBe(events2);
208
- });
209
-
210
- it('should return different instances for different services', () => {
211
- const events1 = getEvents('service-1');
212
- const events2 = getEvents('service-2');
213
-
214
- expect(events1).not.toBe(events2);
215
- });
216
-
217
- it('should reset instances', () => {
218
- const events1 = getEvents('test-service');
219
- resetEvents();
220
- const events2 = getEvents('test-service');
221
-
222
- expect(events1).not.toBe(events2);
223
- });
224
- });
225
-
226
- describe('real-world usage example', () => {
227
- it('should track job application flow', () => {
228
- const event = new Event('job-application', {
229
- logger: mockLogger,
230
- });
231
-
232
- // User starts application
233
- event.trackFunnelStep('application', 'started', { jobId: '123' });
234
-
235
- // User submits application
236
- event.trackEvent('application.submitted', {
237
- jobId: '123',
238
- userId: '456',
239
- });
240
- event.trackFunnelStep('application', 'completed', { jobId: '123' });
241
-
242
- // Email sent successfully
243
- event.trackOutcome('email.sent', 'success', {
244
- recipientType: 'school',
245
- jobId: '123',
246
- });
247
-
248
- expect(mockLogger.info).toHaveBeenCalledTimes(4);
249
- });
250
-
251
- it('should track email delivery failures', () => {
252
- const event = new Event('email-service', { logger: mockLogger });
253
-
254
- // Failed email delivery
255
- event.trackOutcome('email.delivery', 'failure', {
256
- error: 'invalid_email',
257
- recipientEmail: 'redacted',
258
- });
259
-
260
- // Track event for alerting
261
- event.trackEvent('email.bounce', {
262
- bounceType: 'permanent',
263
- });
264
-
265
- expect(mockLogger.info).toHaveBeenCalledTimes(2);
266
- });
267
- });
268
-
269
- describe('automatic telemetry context enrichment', () => {
270
- beforeEach(() => {
271
- resetEvents();
272
- });
273
-
274
- afterEach(async () => {
275
- await shutdown();
276
- });
277
-
278
- // Test without config first (before any init() is called)
279
- it('should still work without config (graceful degradation)', () => {
280
- // Don't initialize - no config available
281
- const event = new Event('test-service', { logger: mockLogger });
282
-
283
- event.trackEvent('user.login');
284
-
285
- // Pino-native: (extra, message)
286
- expect(mockLogger.info).toHaveBeenCalledWith(
287
- expect.objectContaining({
288
- attributes: {
289
- service: 'test-service',
290
- // No version/environment - gracefully omitted
291
- },
292
- }),
293
- 'Event tracked',
294
- );
295
- });
296
-
297
- it('should auto-capture resource attributes (service.version, deployment.environment)', () => {
298
- // Initialize with config
299
- init({
300
- service: 'test-service',
301
- version: '2.1.0',
302
- environment: 'production',
303
- });
304
-
305
- const event = new Event('test-service', { logger: mockLogger });
306
-
307
- event.trackEvent('user.signup', { userId: '123' });
308
-
309
- // Pino-native: (extra, message)
310
- expect(mockLogger.info).toHaveBeenCalledWith(
311
- expect.objectContaining({
312
- attributes: expect.objectContaining({
313
- service: 'test-service',
314
- 'service.version': '2.1.0',
315
- 'deployment.environment': 'production',
316
- userId: '123',
317
- }),
318
- }),
319
- 'Event tracked',
320
- );
321
- });
322
-
323
- it('should auto-capture trace context (traceId, spanId, correlationId) when inside a trace', async () => {
324
- init({ service: 'test-service' });
325
-
326
- const event = new Event('test-service', { logger: mockLogger });
327
-
328
- const tracedOperation = trace('test.operation', async () => {
329
- event.trackEvent('operation.started', { step: 1 });
330
- });
331
-
332
- await tracedOperation();
333
-
334
- // Pino-native: first arg is the extra object
335
- const capturedCall = (mockLogger.info as ReturnType<typeof vi.fn>).mock
336
- .calls[0];
337
- const attributes = capturedCall[0].attributes;
338
-
339
- expect(attributes).toHaveProperty('traceId');
340
- expect(attributes).toHaveProperty('spanId');
341
- expect(attributes).toHaveProperty('correlationId');
342
- expect(typeof attributes.traceId).toBe('string');
343
- expect(typeof attributes.spanId).toBe('string');
344
- expect(typeof attributes.correlationId).toBe('string');
345
- // Correlation ID should be first 16 chars of traceId
346
- expect(attributes.correlationId).toBe(attributes.traceId.slice(0, 16));
347
- });
348
-
349
- it('should enrich trackFunnelStep with telemetry context', async () => {
350
- init({
351
- service: 'test-service',
352
- version: '1.5.0',
353
- environment: 'staging',
354
- });
355
-
356
- const event = new Event('test-service', { logger: mockLogger });
357
-
358
- const tracedOperation = trace('checkout.flow', async () => {
359
- event.trackFunnelStep('checkout', 'started', { cartValue: 99.99 });
360
- });
361
-
362
- await tracedOperation();
363
-
364
- // Pino-native: (extra, message)
365
- expect(mockLogger.info).toHaveBeenCalledWith(
366
- expect.objectContaining({
367
- attributes: expect.objectContaining({
368
- service: 'test-service',
369
- 'service.version': '1.5.0',
370
- 'deployment.environment': 'staging',
371
- cartValue: 99.99,
372
- traceId: expect.any(String),
373
- spanId: expect.any(String),
374
- correlationId: expect.any(String),
375
- }),
376
- }),
377
- 'Funnel step tracked',
378
- );
379
- });
380
-
381
- it('should enrich trackOutcome with telemetry context', async () => {
382
- init({
383
- service: 'test-service',
384
- version: '3.0.0',
385
- environment: 'development',
386
- });
387
-
388
- const event = new Event('test-service', { logger: mockLogger });
389
-
390
- const tracedOperation = trace('email.send', async () => {
391
- event.trackOutcome('email.delivery', 'success', {
392
- recipientType: 'user',
393
- });
394
- });
395
-
396
- await tracedOperation();
397
-
398
- // Pino-native: (extra, message)
399
- expect(mockLogger.info).toHaveBeenCalledWith(
400
- expect.objectContaining({
401
- attributes: expect.objectContaining({
402
- service: 'test-service',
403
- 'service.version': '3.0.0',
404
- 'deployment.environment': 'development',
405
- recipientType: 'user',
406
- traceId: expect.any(String),
407
- spanId: expect.any(String),
408
- correlationId: expect.any(String),
409
- }),
410
- }),
411
- 'Outcome tracked',
412
- );
413
- });
414
-
415
- it('should enrich trackValue with telemetry context', async () => {
416
- init({
417
- service: 'test-service',
418
- version: '4.2.1',
419
- environment: 'production',
420
- });
421
-
422
- const event = new Event('test-service', { logger: mockLogger });
423
-
424
- const tracedOperation = trace('order.process', async () => {
425
- event.trackValue('order.revenue', 149.99, { currency: 'USD' });
426
- });
427
-
428
- await tracedOperation();
429
-
430
- // Pino-native: (extra, message)
431
- expect(mockLogger.debug).toHaveBeenCalledWith(
432
- expect.objectContaining({
433
- attributes: expect.objectContaining({
434
- service: 'test-service',
435
- metric: 'order.revenue',
436
- 'service.version': '4.2.1',
437
- 'deployment.environment': 'production',
438
- currency: 'USD',
439
- traceId: expect.any(String),
440
- spanId: expect.any(String),
441
- correlationId: expect.any(String),
442
- }),
443
- }),
444
- 'Value tracked',
445
- );
446
- });
447
-
448
- it('should still work outside a trace (no trace context)', () => {
449
- init({
450
- service: 'test-service',
451
- version: '1.0.0',
452
- environment: 'test',
453
- });
454
-
455
- const event = new Event('test-service', { logger: mockLogger });
456
-
457
- // Call outside a trace
458
- event.trackEvent('background.job.completed', { jobId: 'job-123' });
459
-
460
- // Pino-native: (extra, message)
461
- expect(mockLogger.info).toHaveBeenCalledWith(
462
- expect.objectContaining({
463
- attributes: {
464
- service: 'test-service',
465
- 'service.version': '1.0.0',
466
- 'deployment.environment': 'test',
467
- jobId: 'job-123',
468
- // No traceId/spanId/correlationId - gracefully omitted
469
- },
470
- }),
471
- 'Event tracked',
472
- );
473
- });
474
- });
475
-
476
- describe('automatic operation context enrichment', () => {
477
- beforeEach(() => {
478
- resetEvents();
479
- });
480
-
481
- afterEach(async () => {
482
- await shutdown();
483
- });
484
-
485
- it('should auto-capture operation.name when inside trace() with string name', async () => {
486
- init({ service: 'test-service' });
487
-
488
- const event = new Event('test-service', { logger: mockLogger });
489
-
490
- const operation = trace('user.create', async () => {
491
- event.trackEvent('user.created', { userId: '123' });
492
- });
493
-
494
- await operation();
495
-
496
- // Pino-native: (extra, message)
497
- expect(mockLogger.info).toHaveBeenCalledWith(
498
- expect.objectContaining({
499
- attributes: expect.objectContaining({
500
- 'operation.name': 'user.create',
501
- userId: '123',
502
- }),
503
- }),
504
- 'Event tracked',
505
- );
506
- });
507
-
508
- it('should auto-capture operation.name when inside trace() with named function', async () => {
509
- init({ service: 'test-service' });
510
-
511
- const event = new Event('test-service', { logger: mockLogger });
512
-
513
- const createUser = trace(async function createUser() {
514
- event.trackEvent('user.created', { userId: '456' });
515
- });
516
-
517
- await createUser();
518
-
519
- // Pino-native: (extra, message)
520
- expect(mockLogger.info).toHaveBeenCalledWith(
521
- expect.objectContaining({
522
- attributes: expect.objectContaining({
523
- // Function name might be inferred with slight variations (e.g., 'createUser2')
524
- // The important thing is that operation.name is auto-captured
525
- 'operation.name': expect.stringMatching(/createUser/),
526
- userId: '456',
527
- }),
528
- }),
529
- 'Event tracked',
530
- );
531
- });
532
-
533
- it('should reliably infer function names in both factory and non-factory patterns', async () => {
534
- init({ service: 'test-service' });
535
-
536
- const event = new Event('test-service', { logger: mockLogger });
537
-
538
- // Test 1: Named function declaration (non-factory pattern)
539
- // Should infer name from function declaration
540
- const updateUser = trace(async function updateUser(userId: string) {
541
- event.trackEvent('user.updated', { userId });
542
- });
543
- await updateUser('user-123');
544
-
545
- // Test 2: Named function with factory pattern (ctx parameter)
546
- // Explicit name should take precedence
547
- const deleteUser = trace(
548
- 'user.delete',
549
- (ctx) =>
550
- async function deleteUser(userId: string) {
551
- ctx.setAttribute('user.id', userId);
552
- event.trackEvent('user.deleted', { userId });
553
- },
554
- );
555
- await deleteUser('user-456');
556
-
557
- // Test 3: Named function in factory pattern (should infer inner function name)
558
- const createOrder = trace(
559
- (ctx) =>
560
- async function createOrder(orderId: string) {
561
- ctx.setAttribute('order.id', orderId);
562
- event.trackEvent('order.created', { orderId });
563
- },
564
- );
565
- await createOrder('order-789');
566
-
567
- // Verify all operations captured correct names
568
- // Pino-native: first arg is the extra object
569
- const calls = (mockLogger.info as ReturnType<typeof vi.fn>).mock.calls;
570
-
571
- // First call: updateUser - should infer from named function declaration
572
- expect(calls[0][0].attributes['operation.name']).toMatch(/updateUser/);
573
-
574
- // Second call: user.delete - explicit name takes precedence
575
- expect(calls[1][0].attributes['operation.name']).toBe('user.delete');
576
-
577
- // Third call: createOrder - should infer from inner named function in factory pattern
578
- expect(calls[2][0].attributes['operation.name']).toMatch(/createOrder/);
579
- });
580
-
581
- it('should auto-capture operation.name in nested spans', async () => {
582
- init({ service: 'test-service' });
583
-
584
- const event = new Event('test-service', { logger: mockLogger });
585
- const { span } = await import('./functional');
586
-
587
- const operation = trace('order.process', async () => {
588
- span({ name: 'order.validate' }, () => {
589
- // Should capture the innermost operation name
590
- event.trackEvent('order.validated', { orderId: 'ord_123' });
591
- });
592
- });
593
-
594
- await operation();
595
-
596
- // Pino-native: (extra, message)
597
- expect(mockLogger.info).toHaveBeenCalledWith(
598
- expect.objectContaining({
599
- attributes: expect.objectContaining({
600
- 'operation.name': 'order.validate',
601
- orderId: 'ord_123',
602
- }),
603
- }),
604
- 'Event tracked',
605
- );
606
- });
607
-
608
- it('should auto-capture operation.name in trackFunnelStep', async () => {
609
- init({ service: 'test-service' });
610
-
611
- const event = new Event('test-service', { logger: mockLogger });
612
-
613
- const checkout = trace('checkout.flow', async () => {
614
- event.trackFunnelStep('checkout', 'started', {
615
- cartValue: 99.99,
616
- });
617
- });
618
-
619
- await checkout();
620
-
621
- // Pino-native: (extra, message)
622
- expect(mockLogger.info).toHaveBeenCalledWith(
623
- expect.objectContaining({
624
- attributes: expect.objectContaining({
625
- 'operation.name': 'checkout.flow',
626
- cartValue: 99.99,
627
- }),
628
- }),
629
- 'Funnel step tracked',
630
- );
631
- });
632
-
633
- it('should auto-capture operation.name in trackOutcome', async () => {
634
- init({ service: 'test-service' });
635
-
636
- const event = new Event('test-service', { logger: mockLogger });
637
-
638
- const sendEmail = trace('email.send', async () => {
639
- event.trackOutcome('email.delivery', 'success', {
640
- recipientType: 'user',
641
- });
642
- });
643
-
644
- await sendEmail();
645
-
646
- // Pino-native: (extra, message)
647
- expect(mockLogger.info).toHaveBeenCalledWith(
648
- expect.objectContaining({
649
- attributes: expect.objectContaining({
650
- 'operation.name': 'email.send',
651
- recipientType: 'user',
652
- }),
653
- }),
654
- 'Outcome tracked',
655
- );
656
- });
657
-
658
- it('should auto-capture operation.name in trackValue', async () => {
659
- init({ service: 'test-service' });
660
-
661
- const event = new Event('test-service', { logger: mockLogger });
662
-
663
- const processOrder = trace('order.process', async () => {
664
- event.trackValue('order.revenue', 149.99, { currency: 'USD' });
665
- });
666
-
667
- await processOrder();
668
-
669
- // Pino-native: (extra, message)
670
- expect(mockLogger.debug).toHaveBeenCalledWith(
671
- expect.objectContaining({
672
- attributes: expect.objectContaining({
673
- 'operation.name': 'order.process',
674
- currency: 'USD',
675
- }),
676
- }),
677
- 'Value tracked',
678
- );
679
- });
680
-
681
- it('should handle missing operation.name gracefully (outside trace)', () => {
682
- init({ service: 'test-service' });
683
-
684
- const event = new Event('test-service', { logger: mockLogger });
685
-
686
- // Call outside any trace
687
- event.trackEvent('background.job', { jobId: 'job-123' });
688
-
689
- // Pino-native: (extra, message)
690
- expect(mockLogger.info).toHaveBeenCalledWith(
691
- expect.objectContaining({
692
- attributes: {
693
- service: 'test-service',
694
- 'service.version': undefined,
695
- 'deployment.environment': undefined,
696
- jobId: 'job-123',
697
- // No operation.name - gracefully omitted
698
- },
699
- }),
700
- 'Event tracked',
701
- );
702
- });
703
-
704
- it('should capture parent operation.name when not in nested span', async () => {
705
- init({ service: 'test-service' });
706
-
707
- const event = new Event('test-service', { logger: mockLogger });
708
-
709
- const parentOperation = trace('parent.operation', async () => {
710
- // Track event in parent context (not in a nested span)
711
- event.trackEvent('parent.event', { step: 1 });
712
-
713
- // Then create a nested span
714
- const { span } = await import('./functional');
715
- span({ name: 'child.operation' }, () => {
716
- event.trackEvent('child.event', { step: 2 });
717
- });
718
- });
719
-
720
- await parentOperation();
721
-
722
- // Check parent event has parent operation name
723
- // Pino-native: (extra, message)
724
- expect(mockLogger.info).toHaveBeenNthCalledWith(
725
- 1,
726
- expect.objectContaining({
727
- attributes: expect.objectContaining({
728
- 'operation.name': 'parent.operation',
729
- step: 1,
730
- }),
731
- }),
732
- 'Event tracked',
733
- );
734
-
735
- // Check child event has child operation name
736
- // Pino-native: (extra, message)
737
- expect(mockLogger.info).toHaveBeenNthCalledWith(
738
- 2,
739
- expect.objectContaining({
740
- attributes: expect.objectContaining({
741
- 'operation.name': 'child.operation',
742
- step: 2,
743
- }),
744
- }),
745
- 'Event tracked',
746
- );
747
- });
748
-
749
- it('should work with trace() factory pattern', async () => {
750
- init({ service: 'test-service' });
751
-
752
- const event = new Event('test-service', { logger: mockLogger });
753
-
754
- const operation = trace('factory.operation', (ctx) => async () => {
755
- ctx.setAttribute('custom', 'attribute');
756
- event.trackEvent('factory.event', { data: 'test' });
757
- });
758
-
759
- await operation();
760
-
761
- // Pino-native: (extra, message)
762
- expect(mockLogger.info).toHaveBeenCalledWith(
763
- expect.objectContaining({
764
- attributes: expect.objectContaining({
765
- 'operation.name': 'factory.operation',
766
- data: 'test',
767
- }),
768
- }),
769
- 'Event tracked',
770
- );
771
- });
772
- });
773
-
774
- describe('autotel trace context', () => {
775
- beforeEach(() => {
776
- resetEvents();
777
- });
778
-
779
- afterEach(async () => {
780
- await shutdown();
781
- });
782
-
783
- it('should always include correlation_id even without includeTraceContext', async () => {
784
- init({
785
- service: 'test-service',
786
- // events.includeTraceContext is false by default
787
- });
788
-
789
- const mockSubscriber = {
790
- name: 'MockSubscriber',
791
- trackEvent: vi.fn().mockResolvedValue(undefined),
792
- trackFunnelStep: vi.fn().mockResolvedValue(undefined),
793
- trackOutcome: vi.fn().mockResolvedValue(undefined),
794
- trackValue: vi.fn().mockResolvedValue(undefined),
795
- };
796
-
797
- const event = new Event('test-service', {
798
- subscribers: [mockSubscriber],
799
- });
800
-
801
- event.trackEvent('test.event', { userId: '123' });
802
-
803
- // Wait for async subscriber notification
804
- await new Promise((resolve) => setTimeout(resolve, 50));
805
-
806
- expect(mockSubscriber.trackEvent).toHaveBeenCalledWith(
807
- 'test.event',
808
- expect.any(Object),
809
- expect.objectContaining({
810
- autotel: expect.objectContaining({
811
- correlation_id: expect.any(String),
812
- }),
813
- }),
814
- );
815
-
816
- // Correlation ID should be 16 hex chars
817
- const call = mockSubscriber.trackEvent.mock.calls[0];
818
- const autotelContext = call[2].autotel;
819
- expect(autotelContext.correlation_id).toHaveLength(16);
820
- expect(/^[0-9a-f]{16}$/.test(autotelContext.correlation_id)).toBe(true);
821
- });
822
-
823
- it('should include full trace context when includeTraceContext is enabled', async () => {
824
- init({
825
- service: 'test-service',
826
- events: {
827
- includeTraceContext: true,
828
- },
829
- });
830
-
831
- const mockSubscriber = {
832
- name: 'MockSubscriber',
833
- trackEvent: vi.fn().mockResolvedValue(undefined),
834
- trackFunnelStep: vi.fn().mockResolvedValue(undefined),
835
- trackOutcome: vi.fn().mockResolvedValue(undefined),
836
- trackValue: vi.fn().mockResolvedValue(undefined),
837
- };
838
-
839
- const event = new Event('test-service', {
840
- subscribers: [mockSubscriber],
841
- });
842
-
843
- // Track event inside a trace
844
- const tracedOperation = trace('test.operation', async () => {
845
- event.trackEvent('traced.event', { data: 'test' });
846
- });
847
-
848
- await tracedOperation();
849
-
850
- // Wait for async subscriber notification
851
- await new Promise((resolve) => setTimeout(resolve, 50));
852
-
853
- expect(mockSubscriber.trackEvent).toHaveBeenCalledWith(
854
- 'traced.event',
855
- expect.any(Object),
856
- expect.objectContaining({
857
- autotel: expect.objectContaining({
858
- trace_id: expect.any(String),
859
- span_id: expect.any(String),
860
- trace_flags: expect.any(String),
861
- correlation_id: expect.any(String),
862
- }),
863
- }),
864
- );
865
-
866
- // Verify trace_id is 32 hex chars
867
- const call = mockSubscriber.trackEvent.mock.calls[0];
868
- const autotelContext = call[2].autotel;
869
- expect(autotelContext.trace_id).toHaveLength(32);
870
- expect(/^[0-9a-f]{32}$/.test(autotelContext.trace_id)).toBe(true);
871
-
872
- // Verify span_id is 16 hex chars
873
- expect(autotelContext.span_id).toHaveLength(16);
874
- expect(/^[0-9a-f]{16}$/.test(autotelContext.span_id)).toBe(true);
875
-
876
- // Verify trace_flags is 2 hex chars
877
- expect(autotelContext.trace_flags).toHaveLength(2);
878
- });
879
-
880
- it('should call traceUrl function when configured', async () => {
881
- const traceUrlFn = vi
882
- .fn()
883
- .mockReturnValue('https://traces.example.com/trace/abc123');
884
-
885
- init({
886
- service: 'test-service',
887
- events: {
888
- includeTraceContext: true,
889
- traceUrl: traceUrlFn,
890
- },
891
- });
892
-
893
- const mockSubscriber = {
894
- name: 'MockSubscriber',
895
- trackEvent: vi.fn().mockResolvedValue(undefined),
896
- trackFunnelStep: vi.fn().mockResolvedValue(undefined),
897
- trackOutcome: vi.fn().mockResolvedValue(undefined),
898
- trackValue: vi.fn().mockResolvedValue(undefined),
899
- };
900
-
901
- const event = new Event('test-service', {
902
- subscribers: [mockSubscriber],
903
- });
904
-
905
- // Track event inside a trace
906
- const tracedOperation = trace('test.operation', async () => {
907
- event.trackEvent('traced.event', {});
908
- });
909
-
910
- await tracedOperation();
911
- await new Promise((resolve) => setTimeout(resolve, 50));
912
-
913
- expect(traceUrlFn).toHaveBeenCalledWith(
914
- expect.objectContaining({
915
- traceId: expect.any(String),
916
- spanId: expect.any(String),
917
- correlationId: expect.any(String),
918
- serviceName: 'test-service',
919
- }),
920
- );
921
-
922
- expect(mockSubscriber.trackEvent).toHaveBeenCalledWith(
923
- 'traced.event',
924
- expect.any(Object),
925
- expect.objectContaining({
926
- autotel: expect.objectContaining({
927
- trace_url: 'https://traces.example.com/trace/abc123',
928
- }),
929
- }),
930
- );
931
- });
932
-
933
- it('should include autotel context in trackFunnelStep', async () => {
934
- init({
935
- service: 'test-service',
936
- events: {
937
- includeTraceContext: true,
938
- },
939
- });
940
-
941
- const mockSubscriber = {
942
- name: 'MockSubscriber',
943
- trackEvent: vi.fn().mockResolvedValue(undefined),
944
- trackFunnelStep: vi.fn().mockResolvedValue(undefined),
945
- trackOutcome: vi.fn().mockResolvedValue(undefined),
946
- trackValue: vi.fn().mockResolvedValue(undefined),
947
- };
948
-
949
- const event = new Event('test-service', {
950
- subscribers: [mockSubscriber],
951
- });
952
-
953
- const tracedOperation = trace('checkout.flow', async () => {
954
- event.trackFunnelStep('checkout', 'started', { cartValue: 99.99 });
955
- });
956
-
957
- await tracedOperation();
958
- await new Promise((resolve) => setTimeout(resolve, 50));
959
-
960
- expect(mockSubscriber.trackFunnelStep).toHaveBeenCalledWith(
961
- 'checkout',
962
- 'started',
963
- expect.any(Object),
964
- expect.objectContaining({
965
- autotel: expect.objectContaining({
966
- trace_id: expect.any(String),
967
- correlation_id: expect.any(String),
968
- }),
969
- }),
970
- );
971
- });
972
-
973
- it('should include autotel context in trackOutcome', async () => {
974
- init({
975
- service: 'test-service',
976
- events: {
977
- includeTraceContext: true,
978
- },
979
- });
980
-
981
- const mockSubscriber = {
982
- name: 'MockSubscriber',
983
- trackEvent: vi.fn().mockResolvedValue(undefined),
984
- trackFunnelStep: vi.fn().mockResolvedValue(undefined),
985
- trackOutcome: vi.fn().mockResolvedValue(undefined),
986
- trackValue: vi.fn().mockResolvedValue(undefined),
987
- };
988
-
989
- const event = new Event('test-service', {
990
- subscribers: [mockSubscriber],
991
- });
992
-
993
- const tracedOperation = trace('payment.process', async () => {
994
- event.trackOutcome('payment', 'success', { amount: 99.99 });
995
- });
996
-
997
- await tracedOperation();
998
- await new Promise((resolve) => setTimeout(resolve, 50));
999
-
1000
- expect(mockSubscriber.trackOutcome).toHaveBeenCalledWith(
1001
- 'payment',
1002
- 'success',
1003
- expect.any(Object),
1004
- expect.objectContaining({
1005
- autotel: expect.objectContaining({
1006
- trace_id: expect.any(String),
1007
- correlation_id: expect.any(String),
1008
- }),
1009
- }),
1010
- );
1011
- });
1012
-
1013
- it('should include autotel context in trackValue', async () => {
1014
- init({
1015
- service: 'test-service',
1016
- events: {
1017
- includeTraceContext: true,
1018
- },
1019
- });
1020
-
1021
- const mockSubscriber = {
1022
- name: 'MockSubscriber',
1023
- trackEvent: vi.fn().mockResolvedValue(undefined),
1024
- trackFunnelStep: vi.fn().mockResolvedValue(undefined),
1025
- trackOutcome: vi.fn().mockResolvedValue(undefined),
1026
- trackValue: vi.fn().mockResolvedValue(undefined),
1027
- };
1028
-
1029
- const event = new Event('test-service', {
1030
- subscribers: [mockSubscriber],
1031
- });
1032
-
1033
- const tracedOperation = trace('order.process', async () => {
1034
- event.trackValue('revenue', 149.99, { currency: 'USD' });
1035
- });
1036
-
1037
- await tracedOperation();
1038
- await new Promise((resolve) => setTimeout(resolve, 50));
1039
-
1040
- expect(mockSubscriber.trackValue).toHaveBeenCalledWith(
1041
- 'revenue',
1042
- 149.99,
1043
- expect.any(Object),
1044
- expect.objectContaining({
1045
- autotel: expect.objectContaining({
1046
- trace_id: expect.any(String),
1047
- correlation_id: expect.any(String),
1048
- }),
1049
- }),
1050
- );
1051
- });
1052
- });
1053
-
1054
- describe('baggage enrichment', () => {
1055
- afterEach(async () => {
1056
- await shutdown();
1057
- });
1058
-
1059
- it('should apply maxBytes after hashing baggage values', async () => {
1060
- init({
1061
- service: 'test-service',
1062
- events: {
1063
- enrichFromBaggage: {
1064
- allow: ['user.id'],
1065
- maxBytes: 16,
1066
- transform: {
1067
- 'user.id': 'hash',
1068
- },
1069
- },
1070
- },
1071
- });
1072
-
1073
- const mockSubscriber = {
1074
- name: 'MockSubscriber',
1075
- trackEvent: vi.fn().mockResolvedValue(undefined),
1076
- trackFunnelStep: vi.fn().mockResolvedValue(undefined),
1077
- trackOutcome: vi.fn().mockResolvedValue(undefined),
1078
- trackValue: vi.fn().mockResolvedValue(undefined),
1079
- };
1080
-
1081
- const event = new Event('test-service', {
1082
- subscribers: [mockSubscriber],
1083
- });
1084
-
1085
- const largeValue = 'x'.repeat(2048);
1086
- const baggage = propagation
1087
- .createBaggage()
1088
- .setEntry('user.id', { value: largeValue });
1089
- const ctx = propagation.setBaggage(context.active(), baggage);
1090
-
1091
- context.with(ctx, () => {
1092
- event.trackEvent('test.event', { foo: 'bar' });
1093
- });
1094
-
1095
- await new Promise((resolve) => setTimeout(resolve, 50));
1096
-
1097
- const call = mockSubscriber.trackEvent.mock.calls[0];
1098
- const attributes = call[1] as Record<string, unknown>;
1099
-
1100
- expect(attributes['user.id']).toBeDefined();
1101
- expect(String(attributes['user.id'])).toHaveLength(8);
1102
- });
1103
- });
1104
- });