abxbus 2.4.18 → 2.4.20
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/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/middleware_otel_tracing.d.ts +21 -1
- package/dist/cjs/middleware_otel_tracing.js +246 -6
- package/dist/cjs/middleware_otel_tracing.js.map +2 -2
- package/dist/esm/index.js.map +2 -2
- package/dist/esm/middleware_otel_tracing.js +251 -7
- package/dist/esm/middleware_otel_tracing.js.map +2 -2
- package/dist/types/index.d.ts +1 -0
- package/dist/types/middleware_otel_tracing.d.ts +21 -1
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/middleware_otel_tracing.ts +309 -11
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ROOT_CONTEXT,
|
|
3
|
+
SpanStatusCode,
|
|
4
|
+
trace,
|
|
5
|
+
type Context,
|
|
6
|
+
type Span,
|
|
7
|
+
type SpanAttributeValue,
|
|
8
|
+
type SpanAttributes,
|
|
9
|
+
type SpanContext,
|
|
10
|
+
type Tracer,
|
|
11
|
+
} from '@opentelemetry/api'
|
|
2
12
|
|
|
3
13
|
import type { BaseEvent } from './base_event.js'
|
|
4
14
|
import type { EventBus } from './event_bus.js'
|
|
@@ -8,14 +18,32 @@ import type { EventStatus } from './types.js'
|
|
|
8
18
|
|
|
9
19
|
type OpenTelemetryTraceApi = Pick<typeof trace, 'getTracer' | 'setSpan'>
|
|
10
20
|
|
|
21
|
+
export type OtelTracingSpanFactoryInput = {
|
|
22
|
+
name: string
|
|
23
|
+
span_context: SpanContext
|
|
24
|
+
parent_span_context?: SpanContext
|
|
25
|
+
attributes: SpanAttributes
|
|
26
|
+
start_time?: Date
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type OtelTracingSpanFactory = (input: OtelTracingSpanFactoryInput) => Span
|
|
30
|
+
|
|
11
31
|
export type OtelTracingMiddlewareOptions = {
|
|
12
32
|
tracer?: Tracer
|
|
13
33
|
trace_api?: OpenTelemetryTraceApi
|
|
34
|
+
span_factory?: OtelTracingSpanFactory
|
|
35
|
+
root_span_name?: string | ((eventbus: EventBus, event: BaseEvent) => string)
|
|
36
|
+
root_span_attributes?: SpanAttributes | ((eventbus: EventBus, event: BaseEvent) => SpanAttributes)
|
|
14
37
|
}
|
|
15
38
|
|
|
16
39
|
export class OtelTracingMiddleware implements EventBusMiddleware {
|
|
17
40
|
private readonly tracer: Tracer
|
|
18
41
|
private readonly trace_api: OpenTelemetryTraceApi
|
|
42
|
+
private readonly span_factory?: OtelTracingSpanFactory
|
|
43
|
+
private readonly root_span_name: OtelTracingMiddlewareOptions['root_span_name']
|
|
44
|
+
private readonly root_span_attributes: OtelTracingMiddlewareOptions['root_span_attributes']
|
|
45
|
+
private readonly root_spans = new Map<string, Span>()
|
|
46
|
+
private readonly root_contexts = new Map<string, Context>()
|
|
19
47
|
private readonly event_spans = new Map<string, Span>()
|
|
20
48
|
private readonly event_contexts = new Map<string, Context>()
|
|
21
49
|
private readonly handler_spans = new Map<string, Span>()
|
|
@@ -24,10 +52,16 @@ export class OtelTracingMiddleware implements EventBusMiddleware {
|
|
|
24
52
|
constructor(options: OtelTracingMiddlewareOptions = {}) {
|
|
25
53
|
this.trace_api = options.trace_api ?? trace
|
|
26
54
|
this.tracer = options.tracer ?? this.trace_api.getTracer('abxbus')
|
|
55
|
+
this.span_factory = options.span_factory
|
|
56
|
+
this.root_span_name = options.root_span_name
|
|
57
|
+
this.root_span_attributes = options.root_span_attributes
|
|
27
58
|
}
|
|
28
59
|
|
|
29
60
|
onEventChange(eventbus: EventBus, event: BaseEvent, status: EventStatus): void {
|
|
30
61
|
if (status === 'started') {
|
|
62
|
+
if (this.span_factory) {
|
|
63
|
+
return
|
|
64
|
+
}
|
|
31
65
|
this.startEventSpan(eventbus, event)
|
|
32
66
|
return
|
|
33
67
|
}
|
|
@@ -39,12 +73,15 @@ export class OtelTracingMiddleware implements EventBusMiddleware {
|
|
|
39
73
|
|
|
40
74
|
onEventResultChange(eventbus: EventBus, event: BaseEvent, event_result: EventResult, status: EventStatus): void {
|
|
41
75
|
if (status === 'started') {
|
|
76
|
+
if (this.span_factory) {
|
|
77
|
+
return
|
|
78
|
+
}
|
|
42
79
|
this.startHandlerSpan(eventbus, event, event_result)
|
|
43
80
|
return
|
|
44
81
|
}
|
|
45
82
|
|
|
46
83
|
if (status === 'completed') {
|
|
47
|
-
this.completeHandlerSpan(event_result)
|
|
84
|
+
this.completeHandlerSpan(eventbus, event, event_result)
|
|
48
85
|
}
|
|
49
86
|
}
|
|
50
87
|
|
|
@@ -54,7 +91,8 @@ export class OtelTracingMiddleware implements EventBusMiddleware {
|
|
|
54
91
|
return existing
|
|
55
92
|
}
|
|
56
93
|
|
|
57
|
-
const parent_context = this.parentContextForEvent(event) ??
|
|
94
|
+
const parent_context = this.parentContextForEvent(event) ?? this.startRootSpan(eventbus, event)
|
|
95
|
+
const start_time = dateFromIso(event.event_started_at)
|
|
58
96
|
const span = this.tracer.startSpan(
|
|
59
97
|
`abxbus.event ${event.event_type}`,
|
|
60
98
|
{
|
|
@@ -64,11 +102,12 @@ export class OtelTracingMiddleware implements EventBusMiddleware {
|
|
|
64
102
|
'abxbus.event.id': event.event_id,
|
|
65
103
|
'abxbus.event.type': event.event_type,
|
|
66
104
|
'abxbus.event.version': event.event_version,
|
|
105
|
+
'abxbus.event.session_id': stringValue((event as { session_id?: unknown }).session_id),
|
|
67
106
|
'abxbus.event.parent_id': event.event_parent_id,
|
|
68
107
|
'abxbus.event.emitted_by_handler_id': event.event_emitted_by_handler_id,
|
|
69
108
|
'abxbus.event.path': event.event_path.join(' '),
|
|
70
109
|
}),
|
|
71
|
-
startTime:
|
|
110
|
+
startTime: start_time,
|
|
72
111
|
},
|
|
73
112
|
parent_context
|
|
74
113
|
)
|
|
@@ -79,6 +118,11 @@ export class OtelTracingMiddleware implements EventBusMiddleware {
|
|
|
79
118
|
}
|
|
80
119
|
|
|
81
120
|
private completeEventSpan(eventbus: EventBus, event: BaseEvent): void {
|
|
121
|
+
if (this.span_factory) {
|
|
122
|
+
this.completeEventSpanWithFactory(eventbus, event)
|
|
123
|
+
return
|
|
124
|
+
}
|
|
125
|
+
|
|
82
126
|
const span = this.event_spans.get(event.event_id) ?? this.startEventSpan(eventbus, event)
|
|
83
127
|
if (event.event_errors.length > 0) {
|
|
84
128
|
recordSpanError(span, event.event_errors[0])
|
|
@@ -93,9 +137,12 @@ export class OtelTracingMiddleware implements EventBusMiddleware {
|
|
|
93
137
|
'abxbus.event.child_count': event.event_children.length,
|
|
94
138
|
})
|
|
95
139
|
)
|
|
96
|
-
|
|
140
|
+
const start_time = dateFromIso(event.event_started_at)
|
|
141
|
+
const end_time = endTimeAfterStart(start_time, dateFromIso(event.event_completed_at))
|
|
142
|
+
span.end(end_time)
|
|
97
143
|
this.event_spans.delete(event.event_id)
|
|
98
144
|
this.event_contexts.delete(event.event_id)
|
|
145
|
+
this.completeRootSpan(event.event_id, start_time, end_time)
|
|
99
146
|
}
|
|
100
147
|
|
|
101
148
|
private startHandlerSpan(eventbus: EventBus, event: BaseEvent, event_result: EventResult): Span {
|
|
@@ -130,7 +177,12 @@ export class OtelTracingMiddleware implements EventBusMiddleware {
|
|
|
130
177
|
return span
|
|
131
178
|
}
|
|
132
179
|
|
|
133
|
-
private completeHandlerSpan(event_result: EventResult): void {
|
|
180
|
+
private completeHandlerSpan(eventbus: EventBus, event: BaseEvent, event_result: EventResult): void {
|
|
181
|
+
if (this.span_factory) {
|
|
182
|
+
this.completeHandlerSpanWithFactory(eventbus, event, event_result)
|
|
183
|
+
return
|
|
184
|
+
}
|
|
185
|
+
|
|
134
186
|
const span = this.handler_spans.get(event_result.id)
|
|
135
187
|
if (!span) {
|
|
136
188
|
return
|
|
@@ -147,11 +199,53 @@ export class OtelTracingMiddleware implements EventBusMiddleware {
|
|
|
147
199
|
'abxbus.handler.child_count': event_result.event_children.length,
|
|
148
200
|
})
|
|
149
201
|
)
|
|
150
|
-
span.end(dateFromIso(event_result.completed_at))
|
|
202
|
+
span.end(endTimeAfterStart(dateFromIso(event_result.started_at), dateFromIso(event_result.completed_at)))
|
|
151
203
|
this.handler_spans.delete(event_result.id)
|
|
152
204
|
this.handler_contexts.delete(handlerSpanKey(event_result.event_id, event_result.handler_id))
|
|
153
205
|
}
|
|
154
206
|
|
|
207
|
+
private startRootSpan(eventbus: EventBus, event: BaseEvent): Context {
|
|
208
|
+
const existing = this.root_contexts.get(event.event_id)
|
|
209
|
+
if (existing) {
|
|
210
|
+
return existing
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const session_id = stringValue((event as { session_id?: unknown }).session_id)
|
|
214
|
+
const root_attributes = resolveAttributes(this.root_span_attributes, eventbus, event)
|
|
215
|
+
const root_span = this.tracer.startSpan(
|
|
216
|
+
resolveRootSpanName(this.root_span_name, eventbus, event),
|
|
217
|
+
{
|
|
218
|
+
attributes: compactAttributes({
|
|
219
|
+
...root_attributes,
|
|
220
|
+
'abxbus.trace.root': true,
|
|
221
|
+
'abxbus.bus.id': eventbus.id,
|
|
222
|
+
'abxbus.bus.name': eventbus.name,
|
|
223
|
+
'abxbus.root_event.id': event.event_id,
|
|
224
|
+
'abxbus.root_event.type': event.event_type,
|
|
225
|
+
'abxbus.root_event.session_id': session_id,
|
|
226
|
+
}),
|
|
227
|
+
startTime: dateFromIso(event.event_started_at),
|
|
228
|
+
},
|
|
229
|
+
ROOT_CONTEXT
|
|
230
|
+
)
|
|
231
|
+
const root_context = this.trace_api.setSpan(ROOT_CONTEXT, root_span)
|
|
232
|
+
this.root_spans.set(event.event_id, root_span)
|
|
233
|
+
this.root_contexts.set(event.event_id, root_context)
|
|
234
|
+
return root_context
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
private completeRootSpan(event_id: string, start_time: Date | undefined, end_time: Date | undefined): void {
|
|
238
|
+
const root_span = this.root_spans.get(event_id)
|
|
239
|
+
if (!root_span) {
|
|
240
|
+
return
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
root_span.setStatus({ code: SpanStatusCode.OK })
|
|
244
|
+
root_span.end(endTimeAfterStart(start_time, end_time))
|
|
245
|
+
this.root_spans.delete(event_id)
|
|
246
|
+
this.root_contexts.delete(event_id)
|
|
247
|
+
}
|
|
248
|
+
|
|
155
249
|
private parentContextForEvent(event: BaseEvent): Context | undefined {
|
|
156
250
|
if (event.event_parent_id && event.event_emitted_by_handler_id) {
|
|
157
251
|
const handler_context = this.handler_contexts.get(handlerSpanKey(event.event_parent_id, event.event_emitted_by_handler_id))
|
|
@@ -162,12 +256,191 @@ export class OtelTracingMiddleware implements EventBusMiddleware {
|
|
|
162
256
|
|
|
163
257
|
return event.event_parent_id ? this.event_contexts.get(event.event_parent_id) : undefined
|
|
164
258
|
}
|
|
259
|
+
|
|
260
|
+
private completeEventSpanWithFactory(eventbus: EventBus, event: BaseEvent): void {
|
|
261
|
+
const root_event = rootEventForEvent(eventbus, event)
|
|
262
|
+
const trace_id = traceIdForRootEvent(root_event.event_id)
|
|
263
|
+
const event_context = eventSpanContext(trace_id, event.event_id)
|
|
264
|
+
const start_time = dateFromIso(event.event_started_at)
|
|
265
|
+
const end_time = endTimeAfterStart(start_time, dateFromIso(event.event_completed_at))
|
|
266
|
+
|
|
267
|
+
if (!event.event_parent_id) {
|
|
268
|
+
const root_span = this.span_factory!({
|
|
269
|
+
name: resolveRootSpanName(this.root_span_name, eventbus, event),
|
|
270
|
+
span_context: rootSpanContext(trace_id, event.event_id),
|
|
271
|
+
attributes: rootSpanAttributes(this.root_span_attributes, eventbus, event),
|
|
272
|
+
start_time,
|
|
273
|
+
})
|
|
274
|
+
root_span.setStatus({ code: SpanStatusCode.OK })
|
|
275
|
+
root_span.end(end_time)
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const span = this.span_factory!({
|
|
279
|
+
name: `abxbus.event ${event.event_type}`,
|
|
280
|
+
span_context: event_context,
|
|
281
|
+
parent_span_context: parentSpanContextForEvent(event, trace_id),
|
|
282
|
+
attributes: eventSpanAttributes(eventbus, event),
|
|
283
|
+
start_time,
|
|
284
|
+
})
|
|
285
|
+
if (event.event_errors.length > 0) {
|
|
286
|
+
recordSpanError(span, event.event_errors[0])
|
|
287
|
+
} else {
|
|
288
|
+
span.setStatus({ code: SpanStatusCode.OK })
|
|
289
|
+
}
|
|
290
|
+
span.end(end_time)
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
private completeHandlerSpanWithFactory(eventbus: EventBus, event: BaseEvent, event_result: EventResult): void {
|
|
294
|
+
const root_event = rootEventForEvent(eventbus, event)
|
|
295
|
+
const trace_id = traceIdForRootEvent(root_event.event_id)
|
|
296
|
+
const start_time = dateFromIso(event_result.started_at)
|
|
297
|
+
const span = this.span_factory!({
|
|
298
|
+
name: `abxbus.handler ${event.event_type} ${event_result.handler_name}`,
|
|
299
|
+
span_context: handlerSpanContext(trace_id, event_result.event_id, event_result.handler_id),
|
|
300
|
+
parent_span_context: eventSpanContext(trace_id, event.event_id),
|
|
301
|
+
attributes: handlerSpanAttributes(eventbus, event, event_result),
|
|
302
|
+
start_time,
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
if (event_result.error !== undefined) {
|
|
306
|
+
recordSpanError(span, event_result.error)
|
|
307
|
+
} else {
|
|
308
|
+
span.setStatus({ code: SpanStatusCode.OK })
|
|
309
|
+
}
|
|
310
|
+
span.end(endTimeAfterStart(start_time, dateFromIso(event_result.completed_at)))
|
|
311
|
+
}
|
|
165
312
|
}
|
|
166
313
|
|
|
167
314
|
function handlerSpanKey(event_id: string, handler_id: string): string {
|
|
168
315
|
return `${event_id}:${handler_id}`
|
|
169
316
|
}
|
|
170
317
|
|
|
318
|
+
function eventSpanAttributes(eventbus: EventBus, event: BaseEvent): SpanAttributes {
|
|
319
|
+
return compactAttributes({
|
|
320
|
+
'abxbus.bus.id': eventbus.id,
|
|
321
|
+
'abxbus.bus.name': eventbus.name,
|
|
322
|
+
'abxbus.event.id': event.event_id,
|
|
323
|
+
'abxbus.event.type': event.event_type,
|
|
324
|
+
'abxbus.event.version': event.event_version,
|
|
325
|
+
'abxbus.event.session_id': stringValue((event as { session_id?: unknown }).session_id),
|
|
326
|
+
'abxbus.event.parent_id': event.event_parent_id,
|
|
327
|
+
'abxbus.event.emitted_by_handler_id': event.event_emitted_by_handler_id,
|
|
328
|
+
'abxbus.event.path': event.event_path.join(' '),
|
|
329
|
+
'abxbus.event.status': event.event_status,
|
|
330
|
+
'abxbus.event.result_count': event.event_results.size,
|
|
331
|
+
'abxbus.event.error_count': event.event_errors.length,
|
|
332
|
+
'abxbus.event.child_count': event.event_children.length,
|
|
333
|
+
})
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function handlerSpanAttributes(eventbus: EventBus, event: BaseEvent, event_result: EventResult): SpanAttributes {
|
|
337
|
+
return compactAttributes({
|
|
338
|
+
'abxbus.bus.id': eventbus.id,
|
|
339
|
+
'abxbus.bus.name': eventbus.name,
|
|
340
|
+
'abxbus.event.id': event.event_id,
|
|
341
|
+
'abxbus.event.type': event.event_type,
|
|
342
|
+
'abxbus.handler.id': event_result.handler_id,
|
|
343
|
+
'abxbus.handler.name': event_result.handler_name,
|
|
344
|
+
'abxbus.handler.file_path': event_result.handler_file_path,
|
|
345
|
+
'abxbus.handler.event_pattern': event_result.handler.event_pattern,
|
|
346
|
+
'abxbus.event_result.id': event_result.id,
|
|
347
|
+
'abxbus.event_result.status': event_result.status,
|
|
348
|
+
'abxbus.handler.child_count': event_result.event_children.length,
|
|
349
|
+
})
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function rootSpanAttributes(
|
|
353
|
+
root_span_attributes: OtelTracingMiddlewareOptions['root_span_attributes'],
|
|
354
|
+
eventbus: EventBus,
|
|
355
|
+
event: BaseEvent
|
|
356
|
+
): SpanAttributes {
|
|
357
|
+
const session_id = stringValue((event as { session_id?: unknown }).session_id)
|
|
358
|
+
return compactAttributes({
|
|
359
|
+
...resolveAttributes(root_span_attributes, eventbus, event),
|
|
360
|
+
'abxbus.trace.root': true,
|
|
361
|
+
'abxbus.bus.id': eventbus.id,
|
|
362
|
+
'abxbus.bus.name': eventbus.name,
|
|
363
|
+
'abxbus.root_event.id': event.event_id,
|
|
364
|
+
'abxbus.root_event.type': event.event_type,
|
|
365
|
+
'abxbus.root_event.session_id': session_id,
|
|
366
|
+
'abxbus.root_event.status': event.event_status,
|
|
367
|
+
'abxbus.root_event.error_count': event.event_errors.length,
|
|
368
|
+
'abxbus.root_event.child_count': event.event_children.length,
|
|
369
|
+
})
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function rootEventForEvent(eventbus: EventBus, event: BaseEvent): BaseEvent {
|
|
373
|
+
let current = event._event_original ?? event
|
|
374
|
+
const seen = new Set<string>()
|
|
375
|
+
while (current.event_parent_id && !seen.has(current.event_id)) {
|
|
376
|
+
seen.add(current.event_id)
|
|
377
|
+
const parent = eventbus.findEventById(current.event_parent_id)
|
|
378
|
+
if (!parent) {
|
|
379
|
+
break
|
|
380
|
+
}
|
|
381
|
+
current = parent._event_original ?? parent
|
|
382
|
+
}
|
|
383
|
+
return current
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function parentSpanContextForEvent(event: BaseEvent, trace_id: string): SpanContext {
|
|
387
|
+
if (!event.event_parent_id) {
|
|
388
|
+
return rootSpanContext(trace_id, event.event_id)
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
if (event.event_emitted_by_handler_id) {
|
|
392
|
+
return handlerSpanContext(trace_id, event.event_parent_id, event.event_emitted_by_handler_id)
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
return eventSpanContext(trace_id, event.event_parent_id)
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
function rootSpanContext(trace_id: string, event_id: string): SpanContext {
|
|
399
|
+
return {
|
|
400
|
+
traceId: trace_id,
|
|
401
|
+
spanId: deterministicSpanId(`abxbus.root:${event_id}`),
|
|
402
|
+
traceFlags: 1,
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
function eventSpanContext(trace_id: string, event_id: string): SpanContext {
|
|
407
|
+
return {
|
|
408
|
+
traceId: trace_id,
|
|
409
|
+
spanId: deterministicSpanId(`abxbus.event:${event_id}`),
|
|
410
|
+
traceFlags: 1,
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function handlerSpanContext(trace_id: string, event_id: string, handler_id: string): SpanContext {
|
|
415
|
+
return {
|
|
416
|
+
traceId: trace_id,
|
|
417
|
+
spanId: deterministicSpanId(`abxbus.handler:${event_id}:${handler_id}`),
|
|
418
|
+
traceFlags: 1,
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
function traceIdForRootEvent(event_id: string): string {
|
|
423
|
+
return `${fnv1a64Hex(`abxbus.trace.a:${event_id}`)}${fnv1a64Hex(`abxbus.trace.b:${event_id}`)}`
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
function deterministicSpanId(input: string): string {
|
|
427
|
+
return fnv1a64Hex(input)
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
function fnv1a64Hex(input: string): string {
|
|
431
|
+
let hash = 0xcbf29ce484222325n
|
|
432
|
+
const prime = 0x100000001b3n
|
|
433
|
+
const mask = 0xffffffffffffffffn
|
|
434
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
435
|
+
hash ^= BigInt(input.charCodeAt(index))
|
|
436
|
+
hash = (hash * prime) & mask
|
|
437
|
+
}
|
|
438
|
+
if (hash === 0n) {
|
|
439
|
+
hash = 1n
|
|
440
|
+
}
|
|
441
|
+
return hash.toString(16).padStart(16, '0')
|
|
442
|
+
}
|
|
443
|
+
|
|
171
444
|
function dateFromIso(value: string | null | undefined): Date | undefined {
|
|
172
445
|
if (value == null) {
|
|
173
446
|
return undefined
|
|
@@ -176,10 +449,35 @@ function dateFromIso(value: string | null | undefined): Date | undefined {
|
|
|
176
449
|
return Number.isNaN(date.getTime()) ? undefined : date
|
|
177
450
|
}
|
|
178
451
|
|
|
179
|
-
function
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
452
|
+
function endTimeAfterStart(start_time: Date | undefined, end_time: Date | undefined): Date | undefined {
|
|
453
|
+
if (!start_time || !end_time) {
|
|
454
|
+
return end_time
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
return end_time.getTime() > start_time.getTime() ? end_time : new Date(start_time.getTime() + 1)
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
function resolveRootSpanName(root_span_name: OtelTracingMiddlewareOptions['root_span_name'], eventbus: EventBus, event: BaseEvent): string {
|
|
461
|
+
if (typeof root_span_name === 'function') {
|
|
462
|
+
return root_span_name(eventbus, event)
|
|
463
|
+
}
|
|
464
|
+
return root_span_name ?? `abxbus.trace ${eventbus.name}`
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
function resolveAttributes(
|
|
468
|
+
attributes: OtelTracingMiddlewareOptions['root_span_attributes'],
|
|
469
|
+
eventbus: EventBus,
|
|
470
|
+
event: BaseEvent
|
|
471
|
+
): SpanAttributes {
|
|
472
|
+
return typeof attributes === 'function' ? attributes(eventbus, event) : (attributes ?? {})
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
function stringValue(value: unknown): string | undefined {
|
|
476
|
+
return typeof value === 'string' && value.length > 0 ? value : undefined
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
function compactAttributes(attributes: Record<string, SpanAttributeValue | null | undefined>): SpanAttributes {
|
|
480
|
+
const compacted: SpanAttributes = {}
|
|
183
481
|
for (const [key, value] of Object.entries(attributes)) {
|
|
184
482
|
if (value !== null && value !== undefined) {
|
|
185
483
|
compacted[key] = value
|