duron 0.3.0-beta.6 → 0.3.0-beta.8
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/action-job.js +1 -1
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js +2 -2
- package/dist/adapters/postgres/schema.d.ts.map +1 -1
- package/dist/adapters/postgres/schema.js +3 -1
- package/dist/step-manager.d.ts.map +1 -1
- package/dist/step-manager.js +39 -0
- package/dist/telemetry/adapter.d.ts +22 -0
- package/dist/telemetry/adapter.d.ts.map +1 -1
- package/dist/telemetry/adapter.js +6 -0
- package/dist/telemetry/index.d.ts +1 -1
- package/dist/telemetry/index.d.ts.map +1 -1
- package/dist/telemetry/local.d.ts +2 -1
- package/dist/telemetry/local.d.ts.map +1 -1
- package/dist/telemetry/local.js +63 -0
- package/dist/telemetry/noop.d.ts +2 -1
- package/dist/telemetry/noop.d.ts.map +1 -1
- package/dist/telemetry/noop.js +27 -0
- package/dist/telemetry/opentelemetry.d.ts +2 -1
- package/dist/telemetry/opentelemetry.d.ts.map +1 -1
- package/dist/telemetry/opentelemetry.js +110 -0
- package/migrations/postgres/20260119153838_flimsy_thor_girl/snapshot.json +12 -36
- package/package.json +1 -1
- package/src/action-job.ts +1 -1
- package/src/action.ts +8 -14
- package/src/adapters/postgres/schema.ts +3 -1
- package/src/step-manager.ts +58 -1
- package/src/telemetry/adapter.ts +174 -0
- package/src/telemetry/index.ts +3 -0
- package/src/telemetry/local.ts +93 -0
- package/src/telemetry/noop.ts +46 -0
- package/src/telemetry/opentelemetry.ts +145 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Span as OTelSpan, Tracer, TracerProvider } from '@opentelemetry/api'
|
|
1
|
+
import type { Span as OTelSpan, Tracer as OTelTracer, TracerProvider } from '@opentelemetry/api'
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
type AddSpanAttributeOptions,
|
|
@@ -8,8 +8,11 @@ import {
|
|
|
8
8
|
type Span,
|
|
9
9
|
type StartDatabaseSpanOptions,
|
|
10
10
|
type StartJobSpanOptions,
|
|
11
|
+
type StartSpanOptions,
|
|
11
12
|
type StartStepSpanOptions,
|
|
12
13
|
TelemetryAdapter,
|
|
14
|
+
type Tracer,
|
|
15
|
+
type TracerSpan,
|
|
13
16
|
} from './adapter.js'
|
|
14
17
|
|
|
15
18
|
// ============================================================================
|
|
@@ -52,8 +55,9 @@ export class OpenTelemetryAdapter extends TelemetryAdapter {
|
|
|
52
55
|
#serviceName: string
|
|
53
56
|
#tracerProvider: TracerProvider | null
|
|
54
57
|
#traceDatabaseQueries: boolean
|
|
55
|
-
#tracer:
|
|
58
|
+
#tracer: OTelTracer | null = null
|
|
56
59
|
#spanMap = new Map<string, OTelSpan>()
|
|
60
|
+
#tracerCache = new Map<string, Tracer>()
|
|
57
61
|
|
|
58
62
|
constructor(options: OpenTelemetryAdapterOptions = {}) {
|
|
59
63
|
super()
|
|
@@ -298,6 +302,145 @@ export class OpenTelemetryAdapter extends TelemetryAdapter {
|
|
|
298
302
|
extSpan.otelSpan.setAttribute(options.key, options.value)
|
|
299
303
|
}
|
|
300
304
|
}
|
|
305
|
+
|
|
306
|
+
// ============================================================================
|
|
307
|
+
// Tracer Methods
|
|
308
|
+
// ============================================================================
|
|
309
|
+
|
|
310
|
+
protected _getTracer(name: string): Tracer {
|
|
311
|
+
// Return cached tracer if available
|
|
312
|
+
const cached = this.#tracerCache.get(name)
|
|
313
|
+
if (cached) {
|
|
314
|
+
return cached
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const adapter = this
|
|
318
|
+
|
|
319
|
+
const tracer: Tracer = {
|
|
320
|
+
name,
|
|
321
|
+
|
|
322
|
+
startSpan(spanName: string, options?: StartSpanOptions): TracerSpan {
|
|
323
|
+
// We need to dynamically get the OpenTelemetry API
|
|
324
|
+
// Since _getTracer is synchronous, we need to handle this carefully
|
|
325
|
+
let otelSpan: OTelSpan | null = null
|
|
326
|
+
let api: typeof import('@opentelemetry/api') | null = null
|
|
327
|
+
let ended = false
|
|
328
|
+
|
|
329
|
+
// Initialize the span asynchronously but return synchronously
|
|
330
|
+
const initPromise = (async () => {
|
|
331
|
+
api = await import('@opentelemetry/api')
|
|
332
|
+
|
|
333
|
+
// Get the tracer
|
|
334
|
+
let otelTracer: OTelTracer
|
|
335
|
+
if (adapter.#tracerProvider) {
|
|
336
|
+
otelTracer = adapter.#tracerProvider.getTracer(name)
|
|
337
|
+
} else {
|
|
338
|
+
otelTracer = api.trace.getTracer(name)
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Map kind
|
|
342
|
+
let spanKind = api.SpanKind.INTERNAL
|
|
343
|
+
if (options?.kind === 'client') spanKind = api.SpanKind.CLIENT
|
|
344
|
+
else if (options?.kind === 'server') spanKind = api.SpanKind.SERVER
|
|
345
|
+
else if (options?.kind === 'producer') spanKind = api.SpanKind.PRODUCER
|
|
346
|
+
else if (options?.kind === 'consumer') spanKind = api.SpanKind.CONSUMER
|
|
347
|
+
|
|
348
|
+
// Get parent context
|
|
349
|
+
let parentContext = api.context.active()
|
|
350
|
+
if (options?.parentSpan) {
|
|
351
|
+
const parentOtelSpan = (options.parentSpan as any)._otelSpan as OTelSpan | undefined
|
|
352
|
+
if (parentOtelSpan) {
|
|
353
|
+
parentContext = api.trace.setSpan(api.context.active(), parentOtelSpan)
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
otelSpan = otelTracer.startSpan(
|
|
358
|
+
spanName,
|
|
359
|
+
{
|
|
360
|
+
kind: spanKind,
|
|
361
|
+
attributes: options?.attributes,
|
|
362
|
+
},
|
|
363
|
+
parentContext,
|
|
364
|
+
)
|
|
365
|
+
})()
|
|
366
|
+
|
|
367
|
+
const tracerSpan: TracerSpan & { _otelSpan?: OTelSpan } = {
|
|
368
|
+
setAttribute(key: string, value: string | number | boolean): void {
|
|
369
|
+
initPromise.then(() => {
|
|
370
|
+
if (otelSpan && !ended) {
|
|
371
|
+
otelSpan.setAttribute(key, value)
|
|
372
|
+
}
|
|
373
|
+
})
|
|
374
|
+
},
|
|
375
|
+
|
|
376
|
+
setAttributes(attributes: Record<string, string | number | boolean>): void {
|
|
377
|
+
initPromise.then(() => {
|
|
378
|
+
if (otelSpan && !ended) {
|
|
379
|
+
otelSpan.setAttributes(attributes)
|
|
380
|
+
}
|
|
381
|
+
})
|
|
382
|
+
},
|
|
383
|
+
|
|
384
|
+
addEvent(eventName: string, attributes?: Record<string, string | number | boolean>): void {
|
|
385
|
+
initPromise.then(() => {
|
|
386
|
+
if (otelSpan && !ended) {
|
|
387
|
+
otelSpan.addEvent(eventName, attributes)
|
|
388
|
+
}
|
|
389
|
+
})
|
|
390
|
+
},
|
|
391
|
+
|
|
392
|
+
recordException(error: Error): void {
|
|
393
|
+
initPromise.then(() => {
|
|
394
|
+
if (otelSpan && !ended) {
|
|
395
|
+
otelSpan.recordException(error)
|
|
396
|
+
}
|
|
397
|
+
})
|
|
398
|
+
},
|
|
399
|
+
|
|
400
|
+
setStatusOk(): void {
|
|
401
|
+
initPromise.then(() => {
|
|
402
|
+
if (otelSpan && api && !ended) {
|
|
403
|
+
otelSpan.setStatus({ code: api.SpanStatusCode.OK })
|
|
404
|
+
}
|
|
405
|
+
})
|
|
406
|
+
},
|
|
407
|
+
|
|
408
|
+
setStatusError(message?: string): void {
|
|
409
|
+
initPromise.then(() => {
|
|
410
|
+
if (otelSpan && api && !ended) {
|
|
411
|
+
otelSpan.setStatus({ code: api.SpanStatusCode.ERROR, message })
|
|
412
|
+
}
|
|
413
|
+
})
|
|
414
|
+
},
|
|
415
|
+
|
|
416
|
+
end(): void {
|
|
417
|
+
initPromise.then(() => {
|
|
418
|
+
if (otelSpan && !ended) {
|
|
419
|
+
ended = true
|
|
420
|
+
otelSpan.end()
|
|
421
|
+
}
|
|
422
|
+
})
|
|
423
|
+
},
|
|
424
|
+
|
|
425
|
+
isRecording(): boolean {
|
|
426
|
+
return otelSpan?.isRecording() ?? false
|
|
427
|
+
},
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Store reference for parent context propagation
|
|
431
|
+
initPromise.then(() => {
|
|
432
|
+
if (otelSpan) {
|
|
433
|
+
;(tracerSpan as any)._otelSpan = otelSpan
|
|
434
|
+
}
|
|
435
|
+
})
|
|
436
|
+
|
|
437
|
+
return tracerSpan
|
|
438
|
+
},
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
this.#tracerCache.set(name, tracer)
|
|
442
|
+
return tracer
|
|
443
|
+
}
|
|
301
444
|
}
|
|
302
445
|
|
|
303
446
|
/**
|