duron 0.3.0-beta.8 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/dist/action-job.d.ts +33 -2
  2. package/dist/action-job.d.ts.map +1 -1
  3. package/dist/action-job.js +93 -26
  4. package/dist/action-manager.d.ts +44 -2
  5. package/dist/action-manager.d.ts.map +1 -1
  6. package/dist/action-manager.js +64 -3
  7. package/dist/action.d.ts +388 -7
  8. package/dist/action.d.ts.map +1 -1
  9. package/dist/action.js +44 -23
  10. package/dist/adapters/adapter.d.ts +365 -8
  11. package/dist/adapters/adapter.d.ts.map +1 -1
  12. package/dist/adapters/adapter.js +221 -15
  13. package/dist/adapters/postgres/base.d.ts +184 -6
  14. package/dist/adapters/postgres/base.d.ts.map +1 -1
  15. package/dist/adapters/postgres/base.js +436 -75
  16. package/dist/adapters/postgres/pglite.d.ts +37 -0
  17. package/dist/adapters/postgres/pglite.d.ts.map +1 -1
  18. package/dist/adapters/postgres/pglite.js +38 -0
  19. package/dist/adapters/postgres/postgres.d.ts +35 -0
  20. package/dist/adapters/postgres/postgres.d.ts.map +1 -1
  21. package/dist/adapters/postgres/postgres.js +42 -0
  22. package/dist/adapters/postgres/schema.d.ts +150 -37
  23. package/dist/adapters/postgres/schema.d.ts.map +1 -1
  24. package/dist/adapters/postgres/schema.default.d.ts +151 -38
  25. package/dist/adapters/postgres/schema.default.d.ts.map +1 -1
  26. package/dist/adapters/postgres/schema.default.js +2 -2
  27. package/dist/adapters/postgres/schema.js +60 -23
  28. package/dist/adapters/schemas.d.ts +124 -80
  29. package/dist/adapters/schemas.d.ts.map +1 -1
  30. package/dist/adapters/schemas.js +139 -26
  31. package/dist/client.d.ts +426 -22
  32. package/dist/client.d.ts.map +1 -1
  33. package/dist/client.js +370 -20
  34. package/dist/constants.js +6 -0
  35. package/dist/errors.d.ts +166 -9
  36. package/dist/errors.d.ts.map +1 -1
  37. package/dist/errors.js +189 -19
  38. package/dist/index.d.ts +2 -1
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/server.d.ts +99 -37
  41. package/dist/server.d.ts.map +1 -1
  42. package/dist/server.js +84 -25
  43. package/dist/step-manager.d.ts +111 -4
  44. package/dist/step-manager.d.ts.map +1 -1
  45. package/dist/step-manager.js +411 -75
  46. package/dist/telemetry/index.d.ts +1 -4
  47. package/dist/telemetry/index.d.ts.map +1 -1
  48. package/dist/telemetry/index.js +2 -4
  49. package/dist/telemetry/local-span-exporter.d.ts +56 -0
  50. package/dist/telemetry/local-span-exporter.d.ts.map +1 -0
  51. package/dist/telemetry/local-span-exporter.js +118 -0
  52. package/dist/utils/p-retry.d.ts +5 -0
  53. package/dist/utils/p-retry.d.ts.map +1 -1
  54. package/dist/utils/p-retry.js +8 -0
  55. package/dist/utils/wait-for-abort.d.ts +1 -0
  56. package/dist/utils/wait-for-abort.d.ts.map +1 -1
  57. package/dist/utils/wait-for-abort.js +1 -0
  58. package/migrations/postgres/{20260119153838_flimsy_thor_girl → 20260121160012_normal_bloodstrike}/migration.sql +32 -20
  59. package/migrations/postgres/{20260119153838_flimsy_thor_girl → 20260121160012_normal_bloodstrike}/snapshot.json +241 -66
  60. package/package.json +42 -26
  61. package/src/action-job.ts +43 -32
  62. package/src/action-manager.ts +5 -5
  63. package/src/action.ts +317 -149
  64. package/src/adapters/adapter.ts +54 -54
  65. package/src/adapters/postgres/base.ts +266 -86
  66. package/src/adapters/postgres/schema.default.ts +2 -2
  67. package/src/adapters/postgres/schema.ts +52 -24
  68. package/src/adapters/schemas.ts +91 -36
  69. package/src/client.ts +322 -68
  70. package/src/errors.ts +141 -30
  71. package/src/index.ts +2 -0
  72. package/src/server.ts +39 -37
  73. package/src/step-manager.ts +254 -91
  74. package/src/telemetry/index.ts +2 -20
  75. package/src/telemetry/local-span-exporter.ts +148 -0
  76. package/dist/telemetry/adapter.d.ts +0 -107
  77. package/dist/telemetry/adapter.d.ts.map +0 -1
  78. package/dist/telemetry/adapter.js +0 -134
  79. package/dist/telemetry/local.d.ts +0 -22
  80. package/dist/telemetry/local.d.ts.map +0 -1
  81. package/dist/telemetry/local.js +0 -243
  82. package/dist/telemetry/noop.d.ts +0 -17
  83. package/dist/telemetry/noop.d.ts.map +0 -1
  84. package/dist/telemetry/noop.js +0 -66
  85. package/dist/telemetry/opentelemetry.d.ts +0 -25
  86. package/dist/telemetry/opentelemetry.d.ts.map +0 -1
  87. package/dist/telemetry/opentelemetry.js +0 -312
  88. package/src/telemetry/adapter.ts +0 -642
  89. package/src/telemetry/local.ts +0 -429
  90. package/src/telemetry/noop.ts +0 -141
  91. package/src/telemetry/opentelemetry.ts +0 -453
@@ -0,0 +1,148 @@
1
+ import type { SpanKind as OTelSpanKind, SpanStatusCode as OTelSpanStatusCode } from '@opentelemetry/api'
2
+ import { type ExportResult, ExportResultCode } from '@opentelemetry/core'
3
+ import type { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base'
4
+
5
+ import type { Adapter, InsertSpanOptions } from '../adapters/adapter.js'
6
+
7
+ /**
8
+ * Configuration options for the LocalSpanExporter.
9
+ */
10
+ export interface LocalSpanExporterOptions {
11
+ /**
12
+ * The database adapter to use for storing spans.
13
+ * This is the same adapter used by the Duron Client.
14
+ */
15
+ adapter: Adapter
16
+ }
17
+
18
+ /**
19
+ * A custom OpenTelemetry SpanExporter that stores spans locally in the database.
20
+ *
21
+ * This exporter converts OpenTelemetry ReadableSpan objects into database records
22
+ * and inserts them via the Duron Adapter interface.
23
+ *
24
+ * It extracts `duron.job.id` and `duron.step.id` from span attributes to link
25
+ * spans to Duron jobs and steps.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * import { LocalSpanExporter } from 'duron/telemetry'
30
+ * import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base'
31
+ *
32
+ * const exporter = new LocalSpanExporter({ adapter })
33
+ * const processor = new BatchSpanProcessor(exporter)
34
+ * ```
35
+ */
36
+ export class LocalSpanExporter implements SpanExporter {
37
+ #adapter: Adapter
38
+ #shutdown = false
39
+
40
+ constructor(options: LocalSpanExporterOptions) {
41
+ this.#adapter = options.adapter
42
+ }
43
+
44
+ /**
45
+ * Export spans to the local database.
46
+ *
47
+ * Converts ReadableSpan objects to database records and inserts them.
48
+ * Follows OpenTelemetry exporter rules:
49
+ * - Does not throw exceptions
50
+ * - Does not modify received spans
51
+ * - Does not implement queuing/batching (handled by SpanProcessor)
52
+ */
53
+ export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void): void {
54
+ if (this.#shutdown) {
55
+ resultCallback({ code: ExportResultCode.FAILED, error: new Error('Exporter has been shutdown') })
56
+ return
57
+ }
58
+
59
+ this.#exportSpans(spans)
60
+ .then(() => {
61
+ resultCallback({ code: ExportResultCode.SUCCESS })
62
+ })
63
+ .catch((error) => {
64
+ resultCallback({ code: ExportResultCode.FAILED, error })
65
+ })
66
+ }
67
+
68
+ /**
69
+ * Shutdown the exporter.
70
+ * After shutdown, no more spans will be exported.
71
+ */
72
+ async shutdown(): Promise<void> {
73
+ this.#shutdown = true
74
+ }
75
+
76
+ /**
77
+ * Force flush any pending exports.
78
+ * Since we export synchronously to the database, this is a no-op.
79
+ */
80
+ async forceFlush(): Promise<void> {
81
+ // No-op: we don't buffer spans, they're exported immediately
82
+ }
83
+
84
+ /**
85
+ * Internal method to export spans to the database.
86
+ */
87
+ async #exportSpans(spans: ReadableSpan[]): Promise<void> {
88
+ if (spans.length === 0) {
89
+ return
90
+ }
91
+
92
+ const records = spans.map((span) => this.#readableSpanToRecord(span))
93
+ await this.#adapter.insertSpans(records)
94
+ }
95
+
96
+ /**
97
+ * Convert a ReadableSpan to an InsertSpanOptions record.
98
+ */
99
+ #readableSpanToRecord(span: ReadableSpan): InsertSpanOptions {
100
+ const spanContext = span.spanContext()
101
+
102
+ // Extract Duron-specific attributes
103
+ const jobId = span.attributes['duron.job.id'] as string | undefined
104
+ const stepId = span.attributes['duron.step.id'] as string | undefined
105
+
106
+ // Convert attributes to plain object, excluding only job.id and step.id
107
+ // (those are stored in separate columns)
108
+ const attributes: Record<string, any> = {}
109
+ for (const [key, value] of Object.entries(span.attributes)) {
110
+ if (key !== 'duron.job.id' && key !== 'duron.step.id') {
111
+ attributes[key] = value
112
+ }
113
+ }
114
+
115
+ // Convert events
116
+ const events = span.events.map((event) => ({
117
+ name: event.name,
118
+ timeUnixNano: this.#hrTimeToNanos(event.time).toString(),
119
+ attributes: event.attributes as Record<string, any> | undefined,
120
+ }))
121
+
122
+ // Get parent span ID from parentSpanContext if available
123
+ const parentSpanId = span.parentSpanContext?.spanId || null
124
+
125
+ return {
126
+ traceId: spanContext.traceId,
127
+ spanId: spanContext.spanId,
128
+ parentSpanId,
129
+ jobId: jobId || null,
130
+ stepId: stepId || null,
131
+ name: span.name,
132
+ kind: span.kind as OTelSpanKind,
133
+ startTimeUnixNano: this.#hrTimeToNanos(span.startTime),
134
+ endTimeUnixNano: span.endTime ? this.#hrTimeToNanos(span.endTime) : null,
135
+ statusCode: span.status.code as OTelSpanStatusCode,
136
+ statusMessage: span.status.message || null,
137
+ attributes,
138
+ events,
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Convert HrTime [seconds, nanoseconds] to bigint nanoseconds.
144
+ */
145
+ #hrTimeToNanos(hrTime: [number, number]): bigint {
146
+ return BigInt(hrTime[0]) * BigInt(1_000_000_000) + BigInt(hrTime[1])
147
+ }
148
+ }
@@ -1,107 +0,0 @@
1
- import type { Logger } from 'pino';
2
- import type { Adapter } from '../adapters/adapter.js';
3
- export interface TelemetryClient {
4
- database: Adapter;
5
- }
6
- export interface Span {
7
- id: string;
8
- jobId: string;
9
- stepId: string | null;
10
- parentSpanId: string | null;
11
- }
12
- export interface StartJobSpanOptions {
13
- jobId: string;
14
- actionName: string;
15
- groupKey: string;
16
- input?: any;
17
- }
18
- export interface StartStepSpanOptions {
19
- jobId: string;
20
- stepId: string;
21
- stepName: string;
22
- parentSpan?: Span;
23
- parentStepId: string | null;
24
- }
25
- export interface EndSpanOptions {
26
- status: 'ok' | 'error' | 'cancelled';
27
- error?: any;
28
- }
29
- export interface StartDatabaseSpanOptions {
30
- operation: string;
31
- query?: string;
32
- }
33
- export interface RecordMetricOptions {
34
- jobId: string;
35
- stepId?: string;
36
- name: string;
37
- value: number;
38
- attributes?: Record<string, any>;
39
- }
40
- export interface AddSpanEventOptions {
41
- span: Span;
42
- name: string;
43
- attributes?: Record<string, any>;
44
- }
45
- export interface AddSpanAttributeOptions {
46
- span: Span;
47
- key: string;
48
- value: string | number | boolean;
49
- }
50
- export interface StartSpanOptions {
51
- kind?: 'internal' | 'client' | 'server' | 'producer' | 'consumer';
52
- attributes?: Record<string, string | number | boolean>;
53
- parentSpan?: TracerSpan;
54
- }
55
- export interface TracerSpan {
56
- setAttribute(key: string, value: string | number | boolean): void;
57
- setAttributes(attributes: Record<string, string | number | boolean>): void;
58
- addEvent(name: string, attributes?: Record<string, string | number | boolean>): void;
59
- recordException(error: Error): void;
60
- setStatusOk(): void;
61
- setStatusError(message?: string): void;
62
- end(): void;
63
- isRecording(): boolean;
64
- }
65
- export interface Tracer {
66
- readonly name: string;
67
- startSpan(name: string, options?: StartSpanOptions): TracerSpan;
68
- }
69
- export interface ObserveContext {
70
- recordMetric(name: string, value: number, attributes?: Record<string, any>): void;
71
- addSpanAttribute(key: string, value: string | number | boolean): void;
72
- addSpanEvent(name: string, attributes?: Record<string, any>): void;
73
- getTracer(name: string): Tracer;
74
- }
75
- export declare abstract class TelemetryAdapter {
76
- #private;
77
- start(): Promise<boolean>;
78
- stop(): Promise<boolean>;
79
- setLogger(logger: Logger): void;
80
- get logger(): Logger | null;
81
- setClient(client: TelemetryClient): void;
82
- protected get client(): TelemetryClient | null;
83
- startJobSpan(options: StartJobSpanOptions): Promise<Span>;
84
- endJobSpan(span: Span, options: EndSpanOptions): Promise<void>;
85
- startStepSpan(options: StartStepSpanOptions): Promise<Span>;
86
- endStepSpan(span: Span, options: EndSpanOptions): Promise<void>;
87
- startDatabaseSpan(options: StartDatabaseSpanOptions): Promise<Span | null>;
88
- endDatabaseSpan(span: Span | null, options: EndSpanOptions): Promise<void>;
89
- recordMetric(options: RecordMetricOptions): Promise<void>;
90
- addSpanEvent(options: AddSpanEventOptions): Promise<void>;
91
- addSpanAttribute(options: AddSpanAttributeOptions): Promise<void>;
92
- getTracer(name: string): Tracer;
93
- createObserveContext(jobId: string, stepId: string | null, span: Span): ObserveContext;
94
- protected abstract _start(): Promise<void>;
95
- protected abstract _stop(): Promise<void>;
96
- protected abstract _startJobSpan(options: StartJobSpanOptions): Promise<Span>;
97
- protected abstract _endJobSpan(span: Span, options: EndSpanOptions): Promise<void>;
98
- protected abstract _startStepSpan(options: StartStepSpanOptions): Promise<Span>;
99
- protected abstract _endStepSpan(span: Span, options: EndSpanOptions): Promise<void>;
100
- protected abstract _startDatabaseSpan(options: StartDatabaseSpanOptions): Promise<Span | null>;
101
- protected abstract _endDatabaseSpan(span: Span, options: EndSpanOptions): Promise<void>;
102
- protected abstract _recordMetric(options: RecordMetricOptions): Promise<void>;
103
- protected abstract _addSpanEvent(options: AddSpanEventOptions): Promise<void>;
104
- protected abstract _addSpanAttribute(options: AddSpanAttributeOptions): Promise<void>;
105
- protected abstract _getTracer(name: string): Tracer;
106
- }
107
- //# sourceMappingURL=adapter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/telemetry/adapter.ts"],"names":[],"mappings":"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"}
@@ -1,134 +0,0 @@
1
- export class TelemetryAdapter {
2
- #logger = null;
3
- #client = null;
4
- #started = false;
5
- #stopped = false;
6
- #starting = null;
7
- #stopping = null;
8
- async start() {
9
- try {
10
- if (this.#stopping || this.#stopped) {
11
- return false;
12
- }
13
- if (this.#started) {
14
- return true;
15
- }
16
- if (this.#starting) {
17
- return this.#starting;
18
- }
19
- this.#starting = (async () => {
20
- await this._start();
21
- this.#started = true;
22
- this.#starting = null;
23
- return true;
24
- })();
25
- return this.#starting;
26
- }
27
- catch (error) {
28
- this.#logger?.error(error, 'Error in TelemetryAdapter.start()');
29
- throw error;
30
- }
31
- }
32
- async stop() {
33
- try {
34
- if (this.#stopped) {
35
- return true;
36
- }
37
- if (this.#stopping) {
38
- return this.#stopping;
39
- }
40
- this.#stopping = (async () => {
41
- await this._stop();
42
- this.#stopped = true;
43
- this.#stopping = null;
44
- return true;
45
- })();
46
- return this.#stopping;
47
- }
48
- catch (error) {
49
- this.#logger?.error(error, 'Error in TelemetryAdapter.stop()');
50
- throw error;
51
- }
52
- }
53
- setLogger(logger) {
54
- this.#logger = logger;
55
- }
56
- get logger() {
57
- return this.#logger;
58
- }
59
- setClient(client) {
60
- this.#client = client;
61
- }
62
- get client() {
63
- return this.#client;
64
- }
65
- async startJobSpan(options) {
66
- await this.start();
67
- return this._startJobSpan(options);
68
- }
69
- async endJobSpan(span, options) {
70
- await this.start();
71
- return this._endJobSpan(span, options);
72
- }
73
- async startStepSpan(options) {
74
- await this.start();
75
- return this._startStepSpan(options);
76
- }
77
- async endStepSpan(span, options) {
78
- await this.start();
79
- return this._endStepSpan(span, options);
80
- }
81
- async startDatabaseSpan(options) {
82
- await this.start();
83
- return this._startDatabaseSpan(options);
84
- }
85
- async endDatabaseSpan(span, options) {
86
- if (!span)
87
- return;
88
- await this.start();
89
- return this._endDatabaseSpan(span, options);
90
- }
91
- async recordMetric(options) {
92
- await this.start();
93
- return this._recordMetric(options);
94
- }
95
- async addSpanEvent(options) {
96
- await this.start();
97
- return this._addSpanEvent(options);
98
- }
99
- async addSpanAttribute(options) {
100
- await this.start();
101
- return this._addSpanAttribute(options);
102
- }
103
- getTracer(name) {
104
- return this._getTracer(name);
105
- }
106
- createObserveContext(jobId, stepId, span) {
107
- return {
108
- recordMetric: (name, value, attributes) => {
109
- this.recordMetric({
110
- jobId,
111
- stepId: stepId ?? undefined,
112
- name,
113
- value,
114
- attributes,
115
- }).catch((err) => {
116
- this.#logger?.error(err, 'Error recording metric');
117
- });
118
- },
119
- addSpanAttribute: (key, value) => {
120
- this.addSpanAttribute({ span, key, value }).catch((err) => {
121
- this.#logger?.error(err, 'Error adding span attribute');
122
- });
123
- },
124
- addSpanEvent: (name, attributes) => {
125
- this.addSpanEvent({ span, name, attributes }).catch((err) => {
126
- this.#logger?.error(err, 'Error adding span event');
127
- });
128
- },
129
- getTracer: (name) => {
130
- return this.getTracer(name);
131
- },
132
- };
133
- }
134
- }
@@ -1,22 +0,0 @@
1
- import { type AddSpanAttributeOptions, type AddSpanEventOptions, type EndSpanOptions, type RecordMetricOptions, type Span, type StartDatabaseSpanOptions, type StartJobSpanOptions, type StartStepSpanOptions, TelemetryAdapter, type Tracer } from './adapter.js';
2
- export interface LocalTelemetryAdapterOptions {
3
- flushDelayMs?: number;
4
- }
5
- export declare class LocalTelemetryAdapter extends TelemetryAdapter {
6
- #private;
7
- constructor(options?: LocalTelemetryAdapterOptions);
8
- protected _start(): Promise<void>;
9
- protected _stop(): Promise<void>;
10
- protected _startJobSpan(options: StartJobSpanOptions): Promise<Span>;
11
- protected _endJobSpan(span: Span, options: EndSpanOptions): Promise<void>;
12
- protected _startStepSpan(options: StartStepSpanOptions): Promise<Span>;
13
- protected _endStepSpan(span: Span, options: EndSpanOptions): Promise<void>;
14
- protected _startDatabaseSpan(_options: StartDatabaseSpanOptions): Promise<Span | null>;
15
- protected _endDatabaseSpan(_span: Span, _options: EndSpanOptions): Promise<void>;
16
- protected _recordMetric(options: RecordMetricOptions): Promise<void>;
17
- protected _addSpanEvent(options: AddSpanEventOptions): Promise<void>;
18
- protected _addSpanAttribute(options: AddSpanAttributeOptions): Promise<void>;
19
- protected _getTracer(name: string): Tracer;
20
- }
21
- export declare const localTelemetryAdapter: (options?: LocalTelemetryAdapterOptions) => LocalTelemetryAdapter;
22
- //# sourceMappingURL=local.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../src/telemetry/local.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,IAAI,EACT,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,EAExB,KAAK,oBAAoB,EACzB,gBAAgB,EAChB,KAAK,MAAM,EAEZ,MAAM,cAAc,CAAA;AAMrB,MAAM,WAAW,4BAA4B;IAM3C,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AA4BD,qBAAa,qBAAsB,SAAQ,gBAAgB;;gBAO7C,OAAO,CAAC,EAAE,4BAA4B;cAwFlC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;cAIvB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;cAUtB,aAAa,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;cAyB1D,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;cAoB/D,cAAc,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;cA2B5D,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;cAqBhE,kBAAkB,CAAC,QAAQ,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;cAK5E,gBAAgB,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;cAQtE,aAAa,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;cAW1D,aAAa,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;cAc1D,iBAAiB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBlF,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAqF3C;AA6BD,eAAO,MAAM,qBAAqB,GAAI,UAAU,4BAA4B,0BAAuC,CAAA"}
@@ -1,243 +0,0 @@
1
- import { TelemetryAdapter, } from './adapter.js';
2
- const DEFAULT_FLUSH_DELAY_MS = 1000;
3
- export class LocalTelemetryAdapter extends TelemetryAdapter {
4
- #spanStartTimes = new Map();
5
- #metricsQueue = [];
6
- #flushTimer = null;
7
- #flushPromise = null;
8
- #flushDelayMs;
9
- constructor(options) {
10
- super();
11
- this.#flushDelayMs = options?.flushDelayMs ?? DEFAULT_FLUSH_DELAY_MS;
12
- }
13
- get #database() {
14
- const client = this.client;
15
- if (!client) {
16
- throw new Error('LocalTelemetryAdapter requires the Duron client to be set. This is done automatically by the Duron client.');
17
- }
18
- return client.database;
19
- }
20
- #queueMetric(options) {
21
- this.#metricsQueue.push(options);
22
- this.#scheduleFlush();
23
- }
24
- #scheduleFlush() {
25
- if (this.#flushTimer) {
26
- clearTimeout(this.#flushTimer);
27
- }
28
- this.#flushTimer = setTimeout(() => {
29
- this.#flushTimer = null;
30
- this.#flushPromise = this.#flushQueue().finally(() => {
31
- this.#flushPromise = null;
32
- });
33
- }, this.#flushDelayMs);
34
- }
35
- async #flushQueue() {
36
- if (this.#metricsQueue.length === 0) {
37
- return;
38
- }
39
- const metrics = this.#metricsQueue.splice(0, this.#metricsQueue.length);
40
- await this.#database.insertMetrics(metrics);
41
- }
42
- async #forceFlush() {
43
- if (this.#flushTimer) {
44
- clearTimeout(this.#flushTimer);
45
- this.#flushTimer = null;
46
- }
47
- if (this.#flushPromise) {
48
- await this.#flushPromise;
49
- }
50
- await this.#flushQueue();
51
- }
52
- async _start() {
53
- }
54
- async _stop() {
55
- await this.#forceFlush();
56
- this.#spanStartTimes.clear();
57
- }
58
- async _startJobSpan(options) {
59
- const spanId = `job:${options.jobId}`;
60
- this.#spanStartTimes.set(spanId, Date.now());
61
- this.#queueMetric({
62
- jobId: options.jobId,
63
- name: 'duron.job.span.start',
64
- value: Date.now(),
65
- type: 'span_event',
66
- attributes: {
67
- actionName: options.actionName,
68
- groupKey: options.groupKey,
69
- spanId,
70
- },
71
- });
72
- return {
73
- id: spanId,
74
- jobId: options.jobId,
75
- stepId: null,
76
- parentSpanId: null,
77
- };
78
- }
79
- async _endJobSpan(span, options) {
80
- const startTime = this.#spanStartTimes.get(span.id);
81
- const duration = startTime ? Date.now() - startTime : 0;
82
- this.#spanStartTimes.delete(span.id);
83
- this.#queueMetric({
84
- jobId: span.jobId,
85
- name: 'duron.job.span.end',
86
- value: duration,
87
- type: 'span_event',
88
- attributes: {
89
- spanId: span.id,
90
- status: options.status,
91
- error: options.error?.message ?? null,
92
- durationMs: duration,
93
- },
94
- });
95
- }
96
- async _startStepSpan(options) {
97
- const spanId = `step:${options.stepId}`;
98
- this.#spanStartTimes.set(spanId, Date.now());
99
- this.#queueMetric({
100
- jobId: options.jobId,
101
- stepId: options.stepId,
102
- name: 'duron.step.span.start',
103
- value: Date.now(),
104
- type: 'span_event',
105
- attributes: {
106
- stepName: options.stepName,
107
- parentStepId: options.parentStepId,
108
- parentSpanId: options.parentSpan?.id ?? null,
109
- spanId,
110
- },
111
- });
112
- return {
113
- id: spanId,
114
- jobId: options.jobId,
115
- stepId: options.stepId,
116
- parentSpanId: options.parentSpan?.id ?? null,
117
- };
118
- }
119
- async _endStepSpan(span, options) {
120
- const startTime = this.#spanStartTimes.get(span.id);
121
- const duration = startTime ? Date.now() - startTime : 0;
122
- this.#spanStartTimes.delete(span.id);
123
- this.#queueMetric({
124
- jobId: span.jobId,
125
- stepId: span.stepId ?? undefined,
126
- name: 'duron.step.span.end',
127
- value: duration,
128
- type: 'span_event',
129
- attributes: {
130
- spanId: span.id,
131
- status: options.status,
132
- error: options.error?.message ?? null,
133
- durationMs: duration,
134
- },
135
- });
136
- }
137
- async _startDatabaseSpan(_options) {
138
- return null;
139
- }
140
- async _endDatabaseSpan(_span, _options) {
141
- }
142
- async _recordMetric(options) {
143
- this.#queueMetric({
144
- jobId: options.jobId,
145
- stepId: options.stepId,
146
- name: options.name,
147
- value: options.value,
148
- type: 'metric',
149
- attributes: options.attributes,
150
- });
151
- }
152
- async _addSpanEvent(options) {
153
- this.#queueMetric({
154
- jobId: options.span.jobId,
155
- stepId: options.span.stepId ?? undefined,
156
- name: options.name,
157
- value: Date.now(),
158
- type: 'span_event',
159
- attributes: {
160
- spanId: options.span.id,
161
- ...options.attributes,
162
- },
163
- });
164
- }
165
- async _addSpanAttribute(options) {
166
- this.#queueMetric({
167
- jobId: options.span.jobId,
168
- stepId: options.span.stepId ?? undefined,
169
- name: `attribute:${options.key}`,
170
- value: typeof options.value === 'number' ? options.value : 0,
171
- type: 'span_attribute',
172
- attributes: {
173
- spanId: options.span.id,
174
- key: options.key,
175
- value: String(options.value),
176
- },
177
- });
178
- }
179
- _getTracer(name) {
180
- const adapter = this;
181
- return {
182
- name,
183
- startSpan(spanName, options) {
184
- const spanId = `tracer:${name}:${globalThis.crypto.randomUUID()}`;
185
- const startTime = Date.now();
186
- let ended = false;
187
- const attributes = {
188
- ...options?.attributes,
189
- };
190
- const tracerSpan = {
191
- setAttribute(key, value) {
192
- if (!ended) {
193
- attributes[key] = value;
194
- }
195
- },
196
- setAttributes(attrs) {
197
- if (!ended) {
198
- Object.assign(attributes, attrs);
199
- }
200
- },
201
- addEvent(eventName, eventAttrs) {
202
- if (!ended) {
203
- adapter.logger?.debug({ spanId, event: eventName, attributes: eventAttrs }, 'Tracer span event');
204
- }
205
- },
206
- recordException(error) {
207
- if (!ended) {
208
- attributes['error.message'] = error.message;
209
- attributes['error.name'] = error.name;
210
- adapter.logger?.debug({ spanId, error: error.message }, 'Tracer span exception');
211
- }
212
- },
213
- setStatusOk() {
214
- if (!ended) {
215
- attributes['status'] = 'ok';
216
- }
217
- },
218
- setStatusError(message) {
219
- if (!ended) {
220
- attributes['status'] = 'error';
221
- if (message) {
222
- attributes['status.message'] = message;
223
- }
224
- }
225
- },
226
- end() {
227
- if (!ended) {
228
- ended = true;
229
- const duration = Date.now() - startTime;
230
- adapter.logger?.debug({ spanId, spanName, tracerName: name, durationMs: duration, attributes }, 'Tracer span ended');
231
- }
232
- },
233
- isRecording() {
234
- return !ended;
235
- },
236
- };
237
- adapter.logger?.debug({ spanId, spanName, tracerName: name }, 'Tracer span started');
238
- return tracerSpan;
239
- },
240
- };
241
- }
242
- }
243
- export const localTelemetryAdapter = (options) => new LocalTelemetryAdapter(options);
@@ -1,17 +0,0 @@
1
- import { type AddSpanAttributeOptions, type AddSpanEventOptions, type EndSpanOptions, type RecordMetricOptions, type Span, type StartDatabaseSpanOptions, type StartJobSpanOptions, type StartStepSpanOptions, TelemetryAdapter, type Tracer } from './adapter.js';
2
- export declare class NoopTelemetryAdapter extends TelemetryAdapter {
3
- protected _start(): Promise<void>;
4
- protected _stop(): Promise<void>;
5
- protected _startJobSpan(options: StartJobSpanOptions): Promise<Span>;
6
- protected _endJobSpan(_span: Span, _options: EndSpanOptions): Promise<void>;
7
- protected _startStepSpan(options: StartStepSpanOptions): Promise<Span>;
8
- protected _endStepSpan(_span: Span, _options: EndSpanOptions): Promise<void>;
9
- protected _startDatabaseSpan(_options: StartDatabaseSpanOptions): Promise<Span | null>;
10
- protected _endDatabaseSpan(_span: Span, _options: EndSpanOptions): Promise<void>;
11
- protected _recordMetric(_options: RecordMetricOptions): Promise<void>;
12
- protected _addSpanEvent(_options: AddSpanEventOptions): Promise<void>;
13
- protected _addSpanAttribute(_options: AddSpanAttributeOptions): Promise<void>;
14
- protected _getTracer(name: string): Tracer;
15
- }
16
- export declare const noopTelemetryAdapter: () => NoopTelemetryAdapter;
17
- //# sourceMappingURL=noop.d.ts.map