abxbus 2.4.23 → 2.4.26
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/middleware_otel_tracing.d.ts +4 -9
- package/dist/cjs/middleware_otel_tracing.js +112 -190
- package/dist/cjs/middleware_otel_tracing.js.map +2 -2
- package/dist/esm/middleware_otel_tracing.js +113 -191
- package/dist/esm/middleware_otel_tracing.js.map +2 -2
- package/dist/types/middleware_otel_tracing.d.ts +4 -9
- package/package.json +1 -1
- package/src/middleware_otel_tracing.ts +141 -203
|
@@ -8,11 +8,12 @@ import {
|
|
|
8
8
|
type SpanAttributeValue,
|
|
9
9
|
type SpanAttributes,
|
|
10
10
|
type SpanContext,
|
|
11
|
+
type TimeInput,
|
|
11
12
|
type Tracer,
|
|
12
13
|
} from '@opentelemetry/api'
|
|
13
14
|
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'
|
|
14
15
|
import { resourceFromAttributes } from '@opentelemetry/resources'
|
|
15
|
-
import { BasicTracerProvider,
|
|
16
|
+
import { BasicTracerProvider, BatchSpanProcessor } from '@opentelemetry/sdk-trace-base'
|
|
16
17
|
import type { SpanLimits, SpanProcessor } from '@opentelemetry/sdk-trace-base'
|
|
17
18
|
import { SpanImpl } from '@opentelemetry/sdk-trace-base/build/src/Span.js'
|
|
18
19
|
|
|
@@ -29,7 +30,7 @@ export type OtelTracingSpanFactoryInput = {
|
|
|
29
30
|
span_context: SpanContext
|
|
30
31
|
parent_span_context?: SpanContext
|
|
31
32
|
attributes: SpanAttributes
|
|
32
|
-
start_time?:
|
|
33
|
+
start_time?: TimeInput
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
export type OtelTracingSpanFactory = (input: OtelTracingSpanFactoryInput) => Span
|
|
@@ -53,7 +54,6 @@ export type OtelTracingMiddlewareOptions = {
|
|
|
53
54
|
otlp_endpoint?: string
|
|
54
55
|
service_name?: string
|
|
55
56
|
instrumentation_name?: string
|
|
56
|
-
root_span_name?: string | ((eventbus: EventBus, event: BaseEvent) => string)
|
|
57
57
|
root_span_attributes?: SpanAttributes | ((eventbus: EventBus, event: BaseEvent) => SpanAttributes)
|
|
58
58
|
}
|
|
59
59
|
|
|
@@ -62,10 +62,7 @@ export class OtelTracingMiddleware implements EventBusMiddleware {
|
|
|
62
62
|
private readonly trace_api: OpenTelemetryTraceApi
|
|
63
63
|
private readonly span_factory?: OtelTracingSpanFactory
|
|
64
64
|
private readonly span_provider?: OtelTracingSpanProvider
|
|
65
|
-
private readonly root_span_name: OtelTracingMiddlewareOptions['root_span_name']
|
|
66
65
|
private readonly root_span_attributes: OtelTracingMiddlewareOptions['root_span_attributes']
|
|
67
|
-
private readonly root_spans = new Map<string, Span>()
|
|
68
|
-
private readonly root_contexts = new Map<string, Context>()
|
|
69
66
|
private readonly event_spans = new Map<string, Span>()
|
|
70
67
|
private readonly event_contexts = new Map<string, Context>()
|
|
71
68
|
private readonly handler_spans = new Map<string, Span>()
|
|
@@ -80,7 +77,6 @@ export class OtelTracingMiddleware implements EventBusMiddleware {
|
|
|
80
77
|
(this.span_provider
|
|
81
78
|
? createProviderSpanFactory(this.trace_api, this.span_provider, options.instrumentation_name ?? 'abxbus')
|
|
82
79
|
: undefined)
|
|
83
|
-
this.root_span_name = options.root_span_name
|
|
84
80
|
this.root_span_attributes = options.root_span_attributes
|
|
85
81
|
}
|
|
86
82
|
|
|
@@ -118,22 +114,14 @@ export class OtelTracingMiddleware implements EventBusMiddleware {
|
|
|
118
114
|
return existing
|
|
119
115
|
}
|
|
120
116
|
|
|
121
|
-
const parent_context = this.parentContextForEvent(event) ??
|
|
122
|
-
const start_time =
|
|
117
|
+
const parent_context = this.parentContextForEvent(event) ?? ROOT_CONTEXT
|
|
118
|
+
const start_time = timeInputFromIso(event.event_started_at)
|
|
123
119
|
const span = this.tracer.startSpan(
|
|
124
120
|
eventSpanName(eventbus, event),
|
|
125
121
|
{
|
|
126
|
-
attributes:
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
'abxbus.event.id': event.event_id,
|
|
130
|
-
'abxbus.event.type': event.event_type,
|
|
131
|
-
'abxbus.event.version': event.event_version,
|
|
132
|
-
'abxbus.event.session_id': stringValue((event as { session_id?: unknown }).session_id),
|
|
133
|
-
'abxbus.event.parent_id': event.event_parent_id,
|
|
134
|
-
'abxbus.event.emitted_by_handler_id': event.event_emitted_by_handler_id,
|
|
135
|
-
'abxbus.event.path': event.event_path.join(' '),
|
|
136
|
-
}),
|
|
122
|
+
attributes: event.event_parent_id
|
|
123
|
+
? eventStartedSpanAttributes(eventbus, event)
|
|
124
|
+
: topLevelEventStartedSpanAttributes(this.root_span_attributes, eventbus, event),
|
|
137
125
|
startTime: start_time,
|
|
138
126
|
},
|
|
139
127
|
parent_context
|
|
@@ -157,19 +145,13 @@ export class OtelTracingMiddleware implements EventBusMiddleware {
|
|
|
157
145
|
span.setStatus({ code: SpanStatusCode.OK })
|
|
158
146
|
}
|
|
159
147
|
span.setAttributes(
|
|
160
|
-
|
|
161
|
-
'abxbus.event.status': event.event_status,
|
|
162
|
-
'abxbus.event.result_count': event.event_results.size,
|
|
163
|
-
'abxbus.event.error_count': event.event_errors.length,
|
|
164
|
-
'abxbus.event.child_count': event.event_children.length,
|
|
165
|
-
})
|
|
148
|
+
event.event_parent_id ? eventSpanAttributes(eventbus, event) : topLevelEventSpanAttributes(this.root_span_attributes, eventbus, event)
|
|
166
149
|
)
|
|
167
|
-
const start_time =
|
|
168
|
-
const end_time = endTimeAfterStart(start_time,
|
|
150
|
+
const start_time = epochNsFromIso(event.event_started_at)
|
|
151
|
+
const end_time = endTimeAfterStart(start_time, epochNsFromIso(event.event_completed_at))
|
|
169
152
|
span.end(end_time)
|
|
170
153
|
this.event_spans.delete(event.event_id)
|
|
171
154
|
this.event_contexts.delete(event.event_id)
|
|
172
|
-
this.completeRootSpan(event.event_id, start_time, end_time)
|
|
173
155
|
}
|
|
174
156
|
|
|
175
157
|
private startHandlerSpan(eventbus: EventBus, event: BaseEvent, event_result: EventResult): Span {
|
|
@@ -183,18 +165,8 @@ export class OtelTracingMiddleware implements EventBusMiddleware {
|
|
|
183
165
|
const span = this.tracer.startSpan(
|
|
184
166
|
handlerSpanName(event, event_result),
|
|
185
167
|
{
|
|
186
|
-
attributes:
|
|
187
|
-
|
|
188
|
-
'abxbus.bus.name': eventbus.name,
|
|
189
|
-
'abxbus.event.id': event.event_id,
|
|
190
|
-
'abxbus.event.type': event.event_type,
|
|
191
|
-
'abxbus.handler.id': event_result.handler_id,
|
|
192
|
-
'abxbus.handler.name': event_result.handler_name,
|
|
193
|
-
'abxbus.handler.file_path': event_result.handler_file_path,
|
|
194
|
-
'abxbus.handler.event_pattern': event_result.handler.event_pattern,
|
|
195
|
-
'abxbus.event_result.id': event_result.id,
|
|
196
|
-
}),
|
|
197
|
-
startTime: dateFromIso(event_result.started_at),
|
|
168
|
+
attributes: handlerSpanAttributes(eventbus, event, event_result),
|
|
169
|
+
startTime: timeInputFromIso(event_result.started_at),
|
|
198
170
|
},
|
|
199
171
|
parent_context
|
|
200
172
|
)
|
|
@@ -206,7 +178,6 @@ export class OtelTracingMiddleware implements EventBusMiddleware {
|
|
|
206
178
|
|
|
207
179
|
private completeHandlerSpan(eventbus: EventBus, event: BaseEvent, event_result: EventResult): void {
|
|
208
180
|
if (this.span_factory) {
|
|
209
|
-
this.completeHandlerSpanWithFactory(eventbus, event, event_result)
|
|
210
181
|
return
|
|
211
182
|
}
|
|
212
183
|
|
|
@@ -220,59 +191,12 @@ export class OtelTracingMiddleware implements EventBusMiddleware {
|
|
|
220
191
|
} else {
|
|
221
192
|
span.setStatus({ code: SpanStatusCode.OK })
|
|
222
193
|
}
|
|
223
|
-
span.setAttributes(
|
|
224
|
-
|
|
225
|
-
'abxbus.event_result.status': event_result.status,
|
|
226
|
-
'abxbus.handler.child_count': event_result.event_children.length,
|
|
227
|
-
})
|
|
228
|
-
)
|
|
229
|
-
span.end(endTimeAfterStart(dateFromIso(event_result.started_at), dateFromIso(event_result.completed_at)))
|
|
194
|
+
span.setAttributes(handlerSpanAttributes(eventbus, event, event_result))
|
|
195
|
+
span.end(endTimeAfterStart(epochNsFromIso(event_result.started_at), epochNsFromIso(event_result.completed_at)))
|
|
230
196
|
this.handler_spans.delete(event_result.id)
|
|
231
197
|
this.handler_contexts.delete(handlerSpanKey(event_result.event_id, event_result.handler_id))
|
|
232
198
|
}
|
|
233
199
|
|
|
234
|
-
private startRootSpan(eventbus: EventBus, event: BaseEvent): Context {
|
|
235
|
-
const existing = this.root_contexts.get(event.event_id)
|
|
236
|
-
if (existing) {
|
|
237
|
-
return existing
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
const session_id = stringValue((event as { session_id?: unknown }).session_id)
|
|
241
|
-
const root_attributes = resolveAttributes(this.root_span_attributes, eventbus, event)
|
|
242
|
-
const root_span = this.tracer.startSpan(
|
|
243
|
-
resolveRootSpanName(this.root_span_name, eventbus, event),
|
|
244
|
-
{
|
|
245
|
-
attributes: compactAttributes({
|
|
246
|
-
...root_attributes,
|
|
247
|
-
'abxbus.trace.root': true,
|
|
248
|
-
'abxbus.bus.id': eventbus.id,
|
|
249
|
-
'abxbus.bus.name': eventbus.name,
|
|
250
|
-
'abxbus.root_event.id': event.event_id,
|
|
251
|
-
'abxbus.root_event.type': event.event_type,
|
|
252
|
-
'abxbus.root_event.session_id': session_id,
|
|
253
|
-
}),
|
|
254
|
-
startTime: dateFromIso(event.event_started_at),
|
|
255
|
-
},
|
|
256
|
-
ROOT_CONTEXT
|
|
257
|
-
)
|
|
258
|
-
const root_context = this.trace_api.setSpan(ROOT_CONTEXT, root_span)
|
|
259
|
-
this.root_spans.set(event.event_id, root_span)
|
|
260
|
-
this.root_contexts.set(event.event_id, root_context)
|
|
261
|
-
return root_context
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
private completeRootSpan(event_id: string, start_time: Date | undefined, end_time: Date | undefined): void {
|
|
265
|
-
const root_span = this.root_spans.get(event_id)
|
|
266
|
-
if (!root_span) {
|
|
267
|
-
return
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
root_span.setStatus({ code: SpanStatusCode.OK })
|
|
271
|
-
root_span.end(endTimeAfterStart(start_time, end_time))
|
|
272
|
-
this.root_spans.delete(event_id)
|
|
273
|
-
this.root_contexts.delete(event_id)
|
|
274
|
-
}
|
|
275
|
-
|
|
276
200
|
private parentContextForEvent(event: BaseEvent): Context | undefined {
|
|
277
201
|
if (event.event_parent_id && event.event_emitted_by_handler_id) {
|
|
278
202
|
const handler_context = this.handler_contexts.get(handlerSpanKey(event.event_parent_id, event.event_emitted_by_handler_id))
|
|
@@ -285,56 +209,77 @@ export class OtelTracingMiddleware implements EventBusMiddleware {
|
|
|
285
209
|
}
|
|
286
210
|
|
|
287
211
|
private completeEventSpanWithFactory(eventbus: EventBus, event: BaseEvent): void {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
const event_context = eventSpanContext(trace_id, event.event_id)
|
|
291
|
-
const start_time = dateFromIso(event.event_started_at)
|
|
292
|
-
const end_time = endTimeAfterStart(start_time, dateFromIso(event.event_completed_at))
|
|
293
|
-
|
|
294
|
-
if (!event.event_parent_id) {
|
|
295
|
-
const root_span = this.span_factory!({
|
|
296
|
-
name: resolveRootSpanName(this.root_span_name, eventbus, event),
|
|
297
|
-
span_context: rootSpanContext(trace_id, event.event_id),
|
|
298
|
-
attributes: rootSpanAttributes(this.root_span_attributes, eventbus, event),
|
|
299
|
-
start_time,
|
|
300
|
-
})
|
|
301
|
-
root_span.setStatus({ code: SpanStatusCode.OK })
|
|
302
|
-
root_span.end(end_time)
|
|
212
|
+
if (event.event_parent_id) {
|
|
213
|
+
return
|
|
303
214
|
}
|
|
304
215
|
|
|
216
|
+
const top_level_event = event._event_original ?? event
|
|
217
|
+
const trace_id = traceIdForRootEvent(top_level_event.event_id)
|
|
218
|
+
this.exportEventTreeWithFactory(eventbus, top_level_event, trace_id, undefined, new Set<string>())
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
private exportEventTreeWithFactory(
|
|
222
|
+
eventbus: EventBus,
|
|
223
|
+
event: BaseEvent,
|
|
224
|
+
trace_id: string,
|
|
225
|
+
parent_span_context: SpanContext | undefined,
|
|
226
|
+
visited_event_ids: Set<string>
|
|
227
|
+
): void {
|
|
228
|
+
const original_event = event._event_original ?? event
|
|
229
|
+
if (visited_event_ids.has(original_event.event_id)) {
|
|
230
|
+
return
|
|
231
|
+
}
|
|
232
|
+
visited_event_ids.add(original_event.event_id)
|
|
233
|
+
|
|
234
|
+
const start_time = epochNsFromIso(original_event.event_started_at)
|
|
235
|
+
const span_context = eventSpanContext(trace_id, original_event.event_id)
|
|
305
236
|
const span = this.span_factory!({
|
|
306
|
-
name: eventSpanName(eventbus,
|
|
307
|
-
span_context
|
|
308
|
-
parent_span_context
|
|
309
|
-
attributes:
|
|
310
|
-
|
|
237
|
+
name: eventSpanName(eventbus, original_event),
|
|
238
|
+
span_context,
|
|
239
|
+
parent_span_context,
|
|
240
|
+
attributes: original_event.event_parent_id
|
|
241
|
+
? eventSpanAttributes(eventbus, original_event)
|
|
242
|
+
: topLevelEventSpanAttributes(this.root_span_attributes, eventbus, original_event),
|
|
243
|
+
start_time: timeInputFromEpochNs(start_time),
|
|
311
244
|
})
|
|
312
|
-
if (
|
|
313
|
-
recordSpanError(span,
|
|
245
|
+
if (original_event.event_errors.length > 0) {
|
|
246
|
+
recordSpanError(span, original_event.event_errors[0])
|
|
314
247
|
} else {
|
|
315
248
|
span.setStatus({ code: SpanStatusCode.OK })
|
|
316
249
|
}
|
|
317
|
-
span.end(
|
|
250
|
+
span.end(endTimeAfterStart(start_time, epochNsFromIso(original_event.event_completed_at)))
|
|
251
|
+
|
|
252
|
+
for (const event_result of original_event.event_results.values()) {
|
|
253
|
+
const handler_context = this.exportHandlerSpanWithFactory(eventbus, original_event, event_result, trace_id, span_context)
|
|
254
|
+
for (const child of event_result.event_children) {
|
|
255
|
+
this.exportEventTreeWithFactory(eventbus, child, trace_id, handler_context, visited_event_ids)
|
|
256
|
+
}
|
|
257
|
+
}
|
|
318
258
|
}
|
|
319
259
|
|
|
320
|
-
private
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
260
|
+
private exportHandlerSpanWithFactory(
|
|
261
|
+
eventbus: EventBus,
|
|
262
|
+
event: BaseEvent,
|
|
263
|
+
event_result: EventResult,
|
|
264
|
+
trace_id: string,
|
|
265
|
+
parent_span_context: SpanContext
|
|
266
|
+
): SpanContext {
|
|
267
|
+
const start_time = epochNsFromIso(event_result.started_at)
|
|
268
|
+
const span_context = handlerSpanContext(trace_id, event_result.event_id, event_result.handler_id)
|
|
324
269
|
const span = this.span_factory!({
|
|
325
270
|
name: handlerSpanName(event, event_result),
|
|
326
|
-
span_context
|
|
327
|
-
parent_span_context
|
|
271
|
+
span_context,
|
|
272
|
+
parent_span_context,
|
|
328
273
|
attributes: handlerSpanAttributes(eventbus, event, event_result),
|
|
329
|
-
start_time,
|
|
274
|
+
start_time: timeInputFromEpochNs(start_time),
|
|
330
275
|
})
|
|
331
|
-
|
|
332
276
|
if (event_result.error !== undefined) {
|
|
333
277
|
recordSpanError(span, event_result.error)
|
|
334
278
|
} else {
|
|
335
279
|
span.setStatus({ code: SpanStatusCode.OK })
|
|
336
280
|
}
|
|
337
|
-
span.end(endTimeAfterStart(start_time,
|
|
281
|
+
span.end(endTimeAfterStart(start_time, epochNsFromIso(event_result.completed_at)))
|
|
282
|
+
return span_context
|
|
338
283
|
}
|
|
339
284
|
}
|
|
340
285
|
|
|
@@ -356,10 +301,13 @@ function createOtlpSpanProvider(options: OtelTracingMiddlewareOptions): OtelTrac
|
|
|
356
301
|
'service.name': options.service_name ?? 'abxbus',
|
|
357
302
|
}),
|
|
358
303
|
spanProcessors: [
|
|
359
|
-
new
|
|
304
|
+
new BatchSpanProcessor(
|
|
360
305
|
new OTLPTraceExporter({
|
|
361
306
|
url: normalizeOtlpTracesEndpoint(options.otlp_endpoint!),
|
|
362
|
-
})
|
|
307
|
+
}),
|
|
308
|
+
{
|
|
309
|
+
scheduledDelayMillis: 100,
|
|
310
|
+
}
|
|
363
311
|
),
|
|
364
312
|
],
|
|
365
313
|
})
|
|
@@ -403,92 +351,64 @@ function normalizeOtlpTracesEndpoint(endpoint: string): string {
|
|
|
403
351
|
return trimmed.endsWith('/v1/traces') ? trimmed : `${trimmed}/v1/traces`
|
|
404
352
|
}
|
|
405
353
|
|
|
354
|
+
function eventStartedSpanAttributes(eventbus: EventBus, event: BaseEvent): SpanAttributes {
|
|
355
|
+
return compactAttributes({
|
|
356
|
+
'abxbus.event_bus.id': eventbus.id,
|
|
357
|
+
'abxbus.event_bus.name': eventbus.name,
|
|
358
|
+
'abxbus.event_id': event.event_id,
|
|
359
|
+
'abxbus.event_type': event.event_type,
|
|
360
|
+
'abxbus.event_version': event.event_version,
|
|
361
|
+
'abxbus.session_id': stringValue((event as { session_id?: unknown }).session_id),
|
|
362
|
+
'abxbus.event_parent_id': event.event_parent_id,
|
|
363
|
+
'abxbus.event_emitted_by_handler_id': event.event_emitted_by_handler_id,
|
|
364
|
+
'abxbus.event_path': event.event_path.join(' '),
|
|
365
|
+
})
|
|
366
|
+
}
|
|
367
|
+
|
|
406
368
|
function eventSpanAttributes(eventbus: EventBus, event: BaseEvent): SpanAttributes {
|
|
407
369
|
return compactAttributes({
|
|
408
|
-
|
|
409
|
-
'abxbus.
|
|
410
|
-
'abxbus.event.id': event.event_id,
|
|
411
|
-
'abxbus.event.type': event.event_type,
|
|
412
|
-
'abxbus.event.version': event.event_version,
|
|
413
|
-
'abxbus.event.session_id': stringValue((event as { session_id?: unknown }).session_id),
|
|
414
|
-
'abxbus.event.parent_id': event.event_parent_id,
|
|
415
|
-
'abxbus.event.emitted_by_handler_id': event.event_emitted_by_handler_id,
|
|
416
|
-
'abxbus.event.path': event.event_path.join(' '),
|
|
417
|
-
'abxbus.event.status': event.event_status,
|
|
418
|
-
'abxbus.event.result_count': event.event_results.size,
|
|
419
|
-
'abxbus.event.error_count': event.event_errors.length,
|
|
420
|
-
'abxbus.event.child_count': event.event_children.length,
|
|
370
|
+
...eventStartedSpanAttributes(eventbus, event),
|
|
371
|
+
'abxbus.event_status': event.event_status,
|
|
421
372
|
})
|
|
422
373
|
}
|
|
423
374
|
|
|
424
375
|
function handlerSpanAttributes(eventbus: EventBus, event: BaseEvent, event_result: EventResult): SpanAttributes {
|
|
425
376
|
return compactAttributes({
|
|
426
|
-
'abxbus.
|
|
427
|
-
'abxbus.
|
|
428
|
-
'abxbus.
|
|
429
|
-
'abxbus.
|
|
430
|
-
'abxbus.
|
|
431
|
-
'abxbus.
|
|
432
|
-
'abxbus.
|
|
433
|
-
'abxbus.
|
|
434
|
-
'abxbus.
|
|
435
|
-
'abxbus.
|
|
436
|
-
'abxbus.handler.child_count': event_result.event_children.length,
|
|
377
|
+
'abxbus.event_bus.id': eventbus.id,
|
|
378
|
+
'abxbus.event_bus.name': eventbus.name,
|
|
379
|
+
'abxbus.event_id': event.event_id,
|
|
380
|
+
'abxbus.event_type': event.event_type,
|
|
381
|
+
'abxbus.handler_id': event_result.handler_id,
|
|
382
|
+
'abxbus.handler_name': event_result.handler_name,
|
|
383
|
+
'abxbus.handler_file_path': event_result.handler_file_path,
|
|
384
|
+
'abxbus.handler_event_pattern': event_result.handler.event_pattern,
|
|
385
|
+
'abxbus.event_result_id': event_result.id,
|
|
386
|
+
'abxbus.event_result_status': event_result.status,
|
|
437
387
|
})
|
|
438
388
|
}
|
|
439
389
|
|
|
440
|
-
function
|
|
390
|
+
function topLevelEventStartedSpanAttributes(
|
|
441
391
|
root_span_attributes: OtelTracingMiddlewareOptions['root_span_attributes'],
|
|
442
392
|
eventbus: EventBus,
|
|
443
393
|
event: BaseEvent
|
|
444
394
|
): SpanAttributes {
|
|
445
|
-
const session_id = stringValue((event as { session_id?: unknown }).session_id)
|
|
446
395
|
return compactAttributes({
|
|
396
|
+
...eventStartedSpanAttributes(eventbus, event),
|
|
447
397
|
...resolveAttributes(root_span_attributes, eventbus, event),
|
|
448
398
|
'abxbus.trace.root': true,
|
|
449
|
-
'abxbus.bus.id': eventbus.id,
|
|
450
|
-
'abxbus.bus.name': eventbus.name,
|
|
451
|
-
'abxbus.root_event.id': event.event_id,
|
|
452
|
-
'abxbus.root_event.type': event.event_type,
|
|
453
|
-
'abxbus.root_event.session_id': session_id,
|
|
454
|
-
'abxbus.root_event.status': event.event_status,
|
|
455
|
-
'abxbus.root_event.error_count': event.event_errors.length,
|
|
456
|
-
'abxbus.root_event.child_count': event.event_children.length,
|
|
457
399
|
})
|
|
458
400
|
}
|
|
459
401
|
|
|
460
|
-
function
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
}
|
|
471
|
-
return current
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
function parentSpanContextForEvent(event: BaseEvent, trace_id: string): SpanContext {
|
|
475
|
-
if (!event.event_parent_id) {
|
|
476
|
-
return rootSpanContext(trace_id, event.event_id)
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
if (event.event_emitted_by_handler_id) {
|
|
480
|
-
return handlerSpanContext(trace_id, event.event_parent_id, event.event_emitted_by_handler_id)
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
return eventSpanContext(trace_id, event.event_parent_id)
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
function rootSpanContext(trace_id: string, event_id: string): SpanContext {
|
|
487
|
-
return {
|
|
488
|
-
traceId: trace_id,
|
|
489
|
-
spanId: deterministicSpanId(`abxbus.root:${event_id}`),
|
|
490
|
-
traceFlags: 1,
|
|
491
|
-
}
|
|
402
|
+
function topLevelEventSpanAttributes(
|
|
403
|
+
root_span_attributes: OtelTracingMiddlewareOptions['root_span_attributes'],
|
|
404
|
+
eventbus: EventBus,
|
|
405
|
+
event: BaseEvent
|
|
406
|
+
): SpanAttributes {
|
|
407
|
+
return compactAttributes({
|
|
408
|
+
...eventSpanAttributes(eventbus, event),
|
|
409
|
+
...resolveAttributes(root_span_attributes, eventbus, event),
|
|
410
|
+
'abxbus.trace.root': true,
|
|
411
|
+
})
|
|
492
412
|
}
|
|
493
413
|
|
|
494
414
|
function eventSpanContext(trace_id: string, event_id: string): SpanContext {
|
|
@@ -529,27 +449,45 @@ function fnv1a64Hex(input: string): string {
|
|
|
529
449
|
return hash.toString(16).padStart(16, '0')
|
|
530
450
|
}
|
|
531
451
|
|
|
532
|
-
|
|
452
|
+
const ISO_EPOCH_NS_REGEX = /^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})(?:\.(\d{1,9}))?(Z|[+-]\d{2}:\d{2})$/
|
|
453
|
+
const NS_PER_SECOND = 1_000_000_000n
|
|
454
|
+
const NS_PER_MS = 1_000_000n
|
|
455
|
+
|
|
456
|
+
function epochNsFromIso(value: string | null | undefined): bigint | undefined {
|
|
533
457
|
if (value == null) {
|
|
534
458
|
return undefined
|
|
535
459
|
}
|
|
536
|
-
const
|
|
537
|
-
|
|
460
|
+
const match = ISO_EPOCH_NS_REGEX.exec(value)
|
|
461
|
+
if (!match) {
|
|
462
|
+
return undefined
|
|
463
|
+
}
|
|
464
|
+
const [, base, fraction = '', timezone] = match
|
|
465
|
+
const base_ms = Date.parse(`${base}.000${timezone}`)
|
|
466
|
+
if (Number.isNaN(base_ms)) {
|
|
467
|
+
return undefined
|
|
468
|
+
}
|
|
469
|
+
return BigInt(base_ms) * NS_PER_MS + BigInt(fraction.padEnd(9, '0'))
|
|
538
470
|
}
|
|
539
471
|
|
|
540
|
-
function
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
}
|
|
472
|
+
function timeInputFromIso(value: string | null | undefined): TimeInput | undefined {
|
|
473
|
+
return timeInputFromEpochNs(epochNsFromIso(value))
|
|
474
|
+
}
|
|
544
475
|
|
|
545
|
-
|
|
476
|
+
function timeInputFromEpochNs(epoch_ns: bigint | undefined): TimeInput | undefined {
|
|
477
|
+
if (epoch_ns === undefined) {
|
|
478
|
+
return undefined
|
|
479
|
+
}
|
|
480
|
+
const seconds = epoch_ns / NS_PER_SECOND
|
|
481
|
+
const nanos = epoch_ns % NS_PER_SECOND
|
|
482
|
+
return [Number(seconds), Number(nanos)]
|
|
546
483
|
}
|
|
547
484
|
|
|
548
|
-
function
|
|
549
|
-
if (
|
|
550
|
-
return
|
|
485
|
+
function endTimeAfterStart(start_time: bigint | undefined, end_time: bigint | undefined): TimeInput | undefined {
|
|
486
|
+
if (start_time === undefined || end_time === undefined) {
|
|
487
|
+
return timeInputFromEpochNs(end_time)
|
|
551
488
|
}
|
|
552
|
-
|
|
489
|
+
|
|
490
|
+
return timeInputFromEpochNs(end_time > start_time ? end_time : start_time + 1n)
|
|
553
491
|
}
|
|
554
492
|
|
|
555
493
|
function resolveAttributes(
|