@kronos-ts/opentelemetry 0.2.2 → 0.4.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.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export { createOpenTelemetrySpanFactory, type OpenTelemetrySpanFactoryOptions, } from "./opentelemetry-span-factory.js";
2
- export { openTelemetry } from "./opentelemetry.js";
2
+ export { openTelemetry, openTelemetryMetrics } from "./opentelemetry.js";
3
+ export { createOpenTelemetryMetricsRecorder, type OpenTelemetryMetricsRecorderOptions, } from "./opentelemetry-metrics-recorder.js";
3
4
  export { createOpenTelemetryDeadLetterListener } from "./opentelemetry-dead-letter-listener.js";
4
5
  export { createTracingCommandBus } from "@kronos-ts/messaging";
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,KAAK,+BAA+B,GACrC,MAAM,iCAAiC,CAAA;AAExC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAElD,OAAO,EAAE,qCAAqC,EAAE,MAAM,yCAAyC,CAAA;AAG/F,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,KAAK,+BAA+B,GACrC,MAAM,iCAAiC,CAAA;AAExC,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAExE,OAAO,EACL,kCAAkC,EAClC,KAAK,mCAAmC,GACzC,MAAM,qCAAqC,CAAA;AAE5C,OAAO,EAAE,qCAAqC,EAAE,MAAM,yCAAyC,CAAA;AAG/F,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA"}
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export { createOpenTelemetrySpanFactory, } from "./opentelemetry-span-factory.js";
2
- export { openTelemetry } from "./opentelemetry.js";
2
+ export { openTelemetry, openTelemetryMetrics } from "./opentelemetry.js";
3
+ export { createOpenTelemetryMetricsRecorder, } from "./opentelemetry-metrics-recorder.js";
3
4
  export { createOpenTelemetryDeadLetterListener } from "./opentelemetry-dead-letter-listener.js";
4
5
  // Re-export tracing command bus for convenience
5
6
  export { createTracingCommandBus } from "@kronos-ts/messaging";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,GAE/B,MAAM,iCAAiC,CAAA;AAExC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAElD,OAAO,EAAE,qCAAqC,EAAE,MAAM,yCAAyC,CAAA;AAE/F,gDAAgD;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,GAE/B,MAAM,iCAAiC,CAAA;AAExC,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAExE,OAAO,EACL,kCAAkC,GAEnC,MAAM,qCAAqC,CAAA;AAE5C,OAAO,EAAE,qCAAqC,EAAE,MAAM,yCAAyC,CAAA;AAE/F,gDAAgD;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA"}
@@ -0,0 +1,17 @@
1
+ import { type Meter } from "@opentelemetry/api";
2
+ import type { MetricsRecorder } from "@kronos-ts/messaging";
3
+ export interface OpenTelemetryMetricsRecorderOptions {
4
+ /** Meter to create instruments from. Defaults to `metrics.getMeter("kronos-framework")`. */
5
+ meter?: Meter;
6
+ }
7
+ /**
8
+ * MetricsRecorder implementation backed by the OpenTelemetry Metrics API.
9
+ *
10
+ * Instruments are created lazily on the configured Meter; the OTel SDK
11
+ * deduplicates instruments by name, so repeated `counter`/`histogram` calls for
12
+ * the same name write to the same series. As with the span factory, you need an
13
+ * OpenTelemetry MeterProvider configured (e.g. via the OTel SDK or java agent)
14
+ * for measurements to be exported — otherwise this is effectively a no-op.
15
+ */
16
+ export declare function createOpenTelemetryMetricsRecorder(options?: OpenTelemetryMetricsRecorderOptions): MetricsRecorder;
17
+ //# sourceMappingURL=opentelemetry-metrics-recorder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opentelemetry-metrics-recorder.d.ts","sourceRoot":"","sources":["../src/opentelemetry-metrics-recorder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,KAAK,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,KAAK,EACV,eAAe,EAIhB,MAAM,sBAAsB,CAAA;AAE7B,MAAM,WAAW,mCAAmC;IAClD,4FAA4F;IAC5F,KAAK,CAAC,EAAE,KAAK,CAAA;CACd;AAED;;;;;;;;GAQG;AACH,wBAAgB,kCAAkC,CAChD,OAAO,GAAE,mCAAwC,GAChD,eAAe,CA2BjB"}
@@ -0,0 +1,38 @@
1
+ import { metrics } from "@opentelemetry/api";
2
+ /**
3
+ * MetricsRecorder implementation backed by the OpenTelemetry Metrics API.
4
+ *
5
+ * Instruments are created lazily on the configured Meter; the OTel SDK
6
+ * deduplicates instruments by name, so repeated `counter`/`histogram` calls for
7
+ * the same name write to the same series. As with the span factory, you need an
8
+ * OpenTelemetry MeterProvider configured (e.g. via the OTel SDK or java agent)
9
+ * for measurements to be exported — otherwise this is effectively a no-op.
10
+ */
11
+ export function createOpenTelemetryMetricsRecorder(options = {}) {
12
+ const meter = options.meter ?? metrics.getMeter("kronos-framework");
13
+ return {
14
+ counter(name, opts) {
15
+ const instrument = meter.createCounter(name, {
16
+ description: opts?.description,
17
+ unit: opts?.unit,
18
+ });
19
+ return {
20
+ add(value, attributes) {
21
+ instrument.add(value, attributes);
22
+ },
23
+ };
24
+ },
25
+ histogram(name, opts) {
26
+ const instrument = meter.createHistogram(name, {
27
+ description: opts?.description,
28
+ unit: opts?.unit,
29
+ });
30
+ return {
31
+ record(value, attributes) {
32
+ instrument.record(value, attributes);
33
+ },
34
+ };
35
+ },
36
+ };
37
+ }
38
+ //# sourceMappingURL=opentelemetry-metrics-recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opentelemetry-metrics-recorder.js","sourceRoot":"","sources":["../src/opentelemetry-metrics-recorder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAc,MAAM,oBAAoB,CAAA;AAaxD;;;;;;;;GAQG;AACH,MAAM,UAAU,kCAAkC,CAChD,UAA+C,EAAE;IAEjD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAA;IAEnE,OAAO;QACL,OAAO,CAAC,IAAY,EAAE,IAAwB;YAC5C,MAAM,UAAU,GAAG,KAAK,CAAC,aAAa,CAAC,IAAI,EAAE;gBAC3C,WAAW,EAAE,IAAI,EAAE,WAAW;gBAC9B,IAAI,EAAE,IAAI,EAAE,IAAI;aACjB,CAAC,CAAA;YACF,OAAO;gBACL,GAAG,CAAC,KAAK,EAAE,UAAU;oBACnB,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,CAAC,CAAA;gBACnC,CAAC;aACF,CAAA;QACH,CAAC;QACD,SAAS,CAAC,IAAY,EAAE,IAAwB;YAC9C,MAAM,UAAU,GAAG,KAAK,CAAC,eAAe,CAAC,IAAI,EAAE;gBAC7C,WAAW,EAAE,IAAI,EAAE,WAAW;gBAC9B,IAAI,EAAE,IAAI,EAAE,IAAI;aACjB,CAAC,CAAA;YACF,OAAO;gBACL,MAAM,CAAC,KAAK,EAAE,UAAU;oBACtB,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,CAAA;gBACtC,CAAC;aACF,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"opentelemetry-span-factory.d.ts","sourceRoot":"","sources":["../src/opentelemetry-span-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,MAAM,EAIZ,MAAM,oBAAoB,CAAA;AAG3B,OAAO,KAAK,EAAQ,WAAW,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAgDrF,MAAM,WAAW,+BAA+B;IAC9C,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,uCAAuC;IACvC,sBAAsB,CAAC,EAAE,sBAAsB,EAAE,CAAA;CAClD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,8BAA8B,CAC5C,OAAO,GAAE,+BAAoC,GAC5C,WAAW,CAgFb"}
1
+ {"version":3,"file":"opentelemetry-span-factory.d.ts","sourceRoot":"","sources":["../src/opentelemetry-span-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,MAAM,EAIZ,MAAM,oBAAoB,CAAA;AAG3B,OAAO,KAAK,EAAQ,WAAW,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAuDrF,MAAM,WAAW,+BAA+B;IAC9C,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,uCAAuC;IACvC,sBAAsB,CAAC,EAAE,sBAAsB,EAAE,CAAA;CAClD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,8BAA8B,CAC5C,OAAO,GAAE,+BAAoC,GAC5C,WAAW,CAyGb"}
@@ -19,7 +19,7 @@ const metadataSetter = {
19
19
  // ---------------------------------------------------------------------------
20
20
  // OpenTelemetry Span wrapper
21
21
  // ---------------------------------------------------------------------------
22
- function wrapOtelSpan(otelSpan, parentContext) {
22
+ function wrapOtelSpan(otelSpan, _parentContext) {
23
23
  return {
24
24
  start() {
25
25
  // OTel spans are started at creation — nothing to do
@@ -34,6 +34,13 @@ function wrapOtelSpan(otelSpan, parentContext) {
34
34
  otelSpan.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
35
35
  otelSpan.end();
36
36
  },
37
+ runActive(fn) {
38
+ // Make this span the active context for the duration of `fn`. With the
39
+ // AsyncLocalStorage context manager the span stays active across awaits in
40
+ // an async `fn`, so propagateContext / currentTraceContext and any child
41
+ // spans created during handling parent to it.
42
+ return context.with(trace.setSpan(context.active(), otelSpan), fn);
43
+ },
37
44
  };
38
45
  }
39
46
  /**
@@ -78,6 +85,20 @@ export function createOpenTelemetrySpanFactory(options = {}) {
78
85
  addMessageAttributes(otelSpan, parentMessage);
79
86
  return wrapOtelSpan(otelSpan, parentContext);
80
87
  },
88
+ createLinkedHandlerSpan(operationName, parentMessage) {
89
+ // New trace (root), linked to the parent message's span rather than
90
+ // parented to it — the originating trace may be long finished by the time
91
+ // an asynchronous processor handles the event.
92
+ const parentContext = extractContext(parentMessage);
93
+ const parentSpanContext = trace.getSpanContext(parentContext);
94
+ const otelSpan = tracer.startSpan(operationName, {
95
+ kind: SpanKind.CONSUMER,
96
+ root: true,
97
+ links: parentSpanContext ? [{ context: parentSpanContext }] : [],
98
+ });
99
+ addMessageAttributes(otelSpan, parentMessage);
100
+ return wrapOtelSpan(otelSpan, parentContext);
101
+ },
81
102
  createDispatchSpan(operationName, parentMessage) {
82
103
  const parentContext = extractContext(parentMessage);
83
104
  const otelSpan = tracer.startSpan(operationName, { kind: SpanKind.PRODUCER }, parentContext);
@@ -101,6 +122,11 @@ export function createOpenTelemetrySpanFactory(options = {}) {
101
122
  metadata: { ...message.metadata, ...additionalMetadata },
102
123
  };
103
124
  },
125
+ currentTraceContext() {
126
+ const carrier = {};
127
+ propagation.inject(context.active(), carrier, metadataSetter);
128
+ return carrier;
129
+ },
104
130
  registerSpanAttributeProvider(provider) {
105
131
  attributeProviders.push(provider);
106
132
  },
@@ -1 +1 @@
1
- {"version":3,"file":"opentelemetry-span-factory.js","sourceRoot":"","sources":["../src/opentelemetry-span-factory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"opentelemetry-span-factory.js","sourceRoot":"","sources":["../src/opentelemetry-span-factory.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,7 @@
1
1
  import type { App } from "@kronos-ts/app";
2
+ import { type MeteringOptions } from "@kronos-ts/messaging";
2
3
  import { type OpenTelemetrySpanFactoryOptions } from "./opentelemetry-span-factory.js";
4
+ import { type OpenTelemetryMetricsRecorderOptions } from "./opentelemetry-metrics-recorder.js";
3
5
  /**
4
6
  * OpenTelemetry tracing extension for Kronos.
5
7
  *
@@ -33,4 +35,25 @@ import { type OpenTelemetrySpanFactoryOptions } from "./opentelemetry-span-facto
33
35
  * ```
34
36
  */
35
37
  export declare function openTelemetry(options?: OpenTelemetrySpanFactoryOptions): (app: App) => void;
38
+ /**
39
+ * OpenTelemetry metrics extension for Kronos.
40
+ *
41
+ * Wires a metering handler enhancer (via `app.handlerEnhancer(...)`) that
42
+ * records throughput, latency, error rate, and event-processing lag for every
43
+ * command/query/event handler invocation, using the OpenTelemetry Metrics API.
44
+ *
45
+ * Compose independently of (and alongside) {@link openTelemetry}:
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * await kronos()
50
+ * .use(openTelemetry()) // tracing
51
+ * .use(openTelemetryMetrics()) // metrics
52
+ * .start()
53
+ * ```
54
+ *
55
+ * Requires an OpenTelemetry MeterProvider to be configured for measurements to
56
+ * be exported; without one this is effectively a no-op.
57
+ */
58
+ export declare function openTelemetryMetrics(options?: OpenTelemetryMetricsRecorderOptions & MeteringOptions): (app: App) => void;
36
59
  //# sourceMappingURL=opentelemetry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"opentelemetry.d.ts","sourceRoot":"","sources":["../src/opentelemetry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAA;AAKzC,OAAO,EAEL,KAAK,+BAA+B,EACrC,MAAM,iCAAiC,CAAA;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,aAAa,CAC3B,OAAO,GAAE,+BAAoC,GAC5C,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAQpB"}
1
+ {"version":3,"file":"opentelemetry.d.ts","sourceRoot":"","sources":["../src/opentelemetry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAEL,KAAK,+BAA+B,EACrC,MAAM,iCAAiC,CAAA;AACxC,OAAO,EAEL,KAAK,mCAAmC,EACzC,MAAM,qCAAqC,CAAA;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,aAAa,CAC3B,OAAO,GAAE,+BAAoC,GAC5C,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAQpB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,mCAAmC,GAAG,eAAoB,GAClE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAKpB"}
@@ -1,5 +1,6 @@
1
- import { createTracingCommandBus, tracingHandlerEnhancerDefinition, } from "@kronos-ts/messaging";
1
+ import { createTracingCommandBus, tracingHandlerEnhancerDefinition, meteringHandlerEnhancerDefinition, } from "@kronos-ts/messaging";
2
2
  import { createOpenTelemetrySpanFactory, } from "./opentelemetry-span-factory.js";
3
+ import { createOpenTelemetryMetricsRecorder, } from "./opentelemetry-metrics-recorder.js";
3
4
  /**
4
5
  * OpenTelemetry tracing extension for Kronos.
5
6
  *
@@ -39,4 +40,30 @@ export function openTelemetry(options = {}) {
39
40
  app.handlerEnhancer(tracingHandlerEnhancerDefinition(spanFactory));
40
41
  };
41
42
  }
43
+ /**
44
+ * OpenTelemetry metrics extension for Kronos.
45
+ *
46
+ * Wires a metering handler enhancer (via `app.handlerEnhancer(...)`) that
47
+ * records throughput, latency, error rate, and event-processing lag for every
48
+ * command/query/event handler invocation, using the OpenTelemetry Metrics API.
49
+ *
50
+ * Compose independently of (and alongside) {@link openTelemetry}:
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * await kronos()
55
+ * .use(openTelemetry()) // tracing
56
+ * .use(openTelemetryMetrics()) // metrics
57
+ * .start()
58
+ * ```
59
+ *
60
+ * Requires an OpenTelemetry MeterProvider to be configured for measurements to
61
+ * be exported; without one this is effectively a no-op.
62
+ */
63
+ export function openTelemetryMetrics(options = {}) {
64
+ return (app) => {
65
+ const recorder = createOpenTelemetryMetricsRecorder(options);
66
+ app.handlerEnhancer(meteringHandlerEnhancerDefinition(recorder, options));
67
+ };
68
+ }
42
69
  //# sourceMappingURL=opentelemetry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"opentelemetry.js","sourceRoot":"","sources":["../src/opentelemetry.ts"],"names":[],"mappings":"AACA,OAAO,EACL,uBAAuB,EACvB,gCAAgC,GACjC,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,8BAA8B,GAE/B,MAAM,iCAAiC,CAAA;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,UAAU,aAAa,CAC3B,UAA2C,EAAE;IAE7C,OAAO,CAAC,GAAG,EAAE,EAAE;QACb,MAAM,WAAW,GAAG,8BAA8B,CAAC,OAAO,CAAC,CAAA;QAC3D,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,QAAQ,EAAE,EAAE,CACtC,uBAAuB,CAAC,QAAQ,EAAE,WAAW,CAAC,CAC/C,CAAA;QACD,GAAG,CAAC,eAAe,CAAC,gCAAgC,CAAC,WAAW,CAAC,CAAC,CAAA;IACpE,CAAC,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"opentelemetry.js","sourceRoot":"","sources":["../src/opentelemetry.ts"],"names":[],"mappings":"AACA,OAAO,EACL,uBAAuB,EACvB,gCAAgC,EAChC,iCAAiC,GAElC,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,8BAA8B,GAE/B,MAAM,iCAAiC,CAAA;AACxC,OAAO,EACL,kCAAkC,GAEnC,MAAM,qCAAqC,CAAA;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,UAAU,aAAa,CAC3B,UAA2C,EAAE;IAE7C,OAAO,CAAC,GAAG,EAAE,EAAE;QACb,MAAM,WAAW,GAAG,8BAA8B,CAAC,OAAO,CAAC,CAAA;QAC3D,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,QAAQ,EAAE,EAAE,CACtC,uBAAuB,CAAC,QAAQ,EAAE,WAAW,CAAC,CAC/C,CAAA;QACD,GAAG,CAAC,eAAe,CAAC,gCAAgC,CAAC,WAAW,CAAC,CAAC,CAAA;IACpE,CAAC,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,oBAAoB,CAClC,UAAiE,EAAE;IAEnE,OAAO,CAAC,GAAG,EAAE,EAAE;QACb,MAAM,QAAQ,GAAG,kCAAkC,CAAC,OAAO,CAAC,CAAA;QAC5D,GAAG,CAAC,eAAe,CAAC,iCAAiC,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAA;IAC3E,CAAC,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kronos-ts/opentelemetry",
3
- "version": "0.2.2",
3
+ "version": "0.4.0",
4
4
  "description": "OpenTelemetry extension for Kronos — tracing for commands and events.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -50,13 +50,13 @@
50
50
  },
51
51
  "dependencies": {
52
52
  "@kronos-ts/common": "0.1.1",
53
- "@kronos-ts/app": "0.3.4",
54
- "@kronos-ts/messaging": "0.5.1",
53
+ "@kronos-ts/app": "0.4.1",
54
+ "@kronos-ts/messaging": "0.7.0",
55
55
  "@opentelemetry/api": "^1.9"
56
56
  },
57
57
  "devDependencies": {
58
- "@kronos-ts/eventsourcing": "0.2.1",
59
- "@kronos-ts/modelling": "0.2.4",
58
+ "@kronos-ts/eventsourcing": "0.2.3",
59
+ "@kronos-ts/modelling": "0.2.6",
60
60
  "@opentelemetry/sdk-trace-base": "^1.30.0",
61
61
  "@opentelemetry/sdk-trace-node": "^1.30.0",
62
62
  "zod": "^4.3.6"
package/src/index.ts CHANGED
@@ -3,7 +3,12 @@ export {
3
3
  type OpenTelemetrySpanFactoryOptions,
4
4
  } from "./opentelemetry-span-factory.js"
5
5
 
6
- export { openTelemetry } from "./opentelemetry.js"
6
+ export { openTelemetry, openTelemetryMetrics } from "./opentelemetry.js"
7
+
8
+ export {
9
+ createOpenTelemetryMetricsRecorder,
10
+ type OpenTelemetryMetricsRecorderOptions,
11
+ } from "./opentelemetry-metrics-recorder.js"
7
12
 
8
13
  export { createOpenTelemetryDeadLetterListener } from "./opentelemetry-dead-letter-listener.js"
9
14
 
@@ -0,0 +1,52 @@
1
+ import { metrics, type Meter } from "@opentelemetry/api"
2
+ import type {
3
+ MetricsRecorder,
4
+ Counter,
5
+ Histogram,
6
+ InstrumentOptions,
7
+ } from "@kronos-ts/messaging"
8
+
9
+ export interface OpenTelemetryMetricsRecorderOptions {
10
+ /** Meter to create instruments from. Defaults to `metrics.getMeter("kronos-framework")`. */
11
+ meter?: Meter
12
+ }
13
+
14
+ /**
15
+ * MetricsRecorder implementation backed by the OpenTelemetry Metrics API.
16
+ *
17
+ * Instruments are created lazily on the configured Meter; the OTel SDK
18
+ * deduplicates instruments by name, so repeated `counter`/`histogram` calls for
19
+ * the same name write to the same series. As with the span factory, you need an
20
+ * OpenTelemetry MeterProvider configured (e.g. via the OTel SDK or java agent)
21
+ * for measurements to be exported — otherwise this is effectively a no-op.
22
+ */
23
+ export function createOpenTelemetryMetricsRecorder(
24
+ options: OpenTelemetryMetricsRecorderOptions = {},
25
+ ): MetricsRecorder {
26
+ const meter = options.meter ?? metrics.getMeter("kronos-framework")
27
+
28
+ return {
29
+ counter(name: string, opts?: InstrumentOptions): Counter {
30
+ const instrument = meter.createCounter(name, {
31
+ description: opts?.description,
32
+ unit: opts?.unit,
33
+ })
34
+ return {
35
+ add(value, attributes) {
36
+ instrument.add(value, attributes)
37
+ },
38
+ }
39
+ },
40
+ histogram(name: string, opts?: InstrumentOptions): Histogram {
41
+ const instrument = meter.createHistogram(name, {
42
+ description: opts?.description,
43
+ unit: opts?.unit,
44
+ })
45
+ return {
46
+ record(value, attributes) {
47
+ instrument.record(value, attributes)
48
+ },
49
+ }
50
+ },
51
+ }
52
+ }
@@ -37,7 +37,7 @@ const metadataSetter: TextMapSetter<Record<string, unknown>> = {
37
37
  // OpenTelemetry Span wrapper
38
38
  // ---------------------------------------------------------------------------
39
39
 
40
- function wrapOtelSpan(otelSpan: import("@opentelemetry/api").Span, parentContext: OtelContext): Span {
40
+ function wrapOtelSpan(otelSpan: import("@opentelemetry/api").Span, _parentContext: OtelContext): Span {
41
41
  return {
42
42
  start() {
43
43
  // OTel spans are started at creation — nothing to do
@@ -52,6 +52,13 @@ function wrapOtelSpan(otelSpan: import("@opentelemetry/api").Span, parentContext
52
52
  otelSpan.setStatus({ code: SpanStatusCode.ERROR, message: error.message })
53
53
  otelSpan.end()
54
54
  },
55
+ runActive<T>(fn: () => T): T {
56
+ // Make this span the active context for the duration of `fn`. With the
57
+ // AsyncLocalStorage context manager the span stays active across awaits in
58
+ // an async `fn`, so propagateContext / currentTraceContext and any child
59
+ // spans created during handling parent to it.
60
+ return context.with(trace.setSpan(context.active(), otelSpan), fn)
61
+ },
55
62
  }
56
63
  }
57
64
 
@@ -123,6 +130,21 @@ export function createOpenTelemetrySpanFactory(
123
130
  return wrapOtelSpan(otelSpan, parentContext)
124
131
  },
125
132
 
133
+ createLinkedHandlerSpan(operationName: string, parentMessage: Message): Span {
134
+ // New trace (root), linked to the parent message's span rather than
135
+ // parented to it — the originating trace may be long finished by the time
136
+ // an asynchronous processor handles the event.
137
+ const parentContext = extractContext(parentMessage)
138
+ const parentSpanContext = trace.getSpanContext(parentContext)
139
+ const otelSpan = tracer.startSpan(operationName, {
140
+ kind: SpanKind.CONSUMER,
141
+ root: true,
142
+ links: parentSpanContext ? [{ context: parentSpanContext }] : [],
143
+ })
144
+ addMessageAttributes(otelSpan, parentMessage)
145
+ return wrapOtelSpan(otelSpan, parentContext)
146
+ },
147
+
126
148
  createDispatchSpan(operationName: string, parentMessage: Message): Span {
127
149
  const parentContext = extractContext(parentMessage)
128
150
  const otelSpan = tracer.startSpan(
@@ -155,6 +177,16 @@ export function createOpenTelemetrySpanFactory(
155
177
  }
156
178
  },
157
179
 
180
+ currentTraceContext(): Record<string, string> {
181
+ const carrier: Record<string, string> = {}
182
+ propagation.inject(
183
+ context.active(),
184
+ carrier,
185
+ metadataSetter as TextMapSetter<Record<string, string>>,
186
+ )
187
+ return carrier
188
+ },
189
+
158
190
  registerSpanAttributeProvider(provider: SpanAttributesProvider) {
159
191
  attributeProviders.push(provider)
160
192
  },
@@ -2,11 +2,17 @@ import type { App } from "@kronos-ts/app"
2
2
  import {
3
3
  createTracingCommandBus,
4
4
  tracingHandlerEnhancerDefinition,
5
+ meteringHandlerEnhancerDefinition,
6
+ type MeteringOptions,
5
7
  } from "@kronos-ts/messaging"
6
8
  import {
7
9
  createOpenTelemetrySpanFactory,
8
10
  type OpenTelemetrySpanFactoryOptions,
9
11
  } from "./opentelemetry-span-factory.js"
12
+ import {
13
+ createOpenTelemetryMetricsRecorder,
14
+ type OpenTelemetryMetricsRecorderOptions,
15
+ } from "./opentelemetry-metrics-recorder.js"
10
16
 
11
17
  /**
12
18
  * OpenTelemetry tracing extension for Kronos.
@@ -51,3 +57,32 @@ export function openTelemetry(
51
57
  app.handlerEnhancer(tracingHandlerEnhancerDefinition(spanFactory))
52
58
  }
53
59
  }
60
+
61
+ /**
62
+ * OpenTelemetry metrics extension for Kronos.
63
+ *
64
+ * Wires a metering handler enhancer (via `app.handlerEnhancer(...)`) that
65
+ * records throughput, latency, error rate, and event-processing lag for every
66
+ * command/query/event handler invocation, using the OpenTelemetry Metrics API.
67
+ *
68
+ * Compose independently of (and alongside) {@link openTelemetry}:
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * await kronos()
73
+ * .use(openTelemetry()) // tracing
74
+ * .use(openTelemetryMetrics()) // metrics
75
+ * .start()
76
+ * ```
77
+ *
78
+ * Requires an OpenTelemetry MeterProvider to be configured for measurements to
79
+ * be exported; without one this is effectively a no-op.
80
+ */
81
+ export function openTelemetryMetrics(
82
+ options: OpenTelemetryMetricsRecorderOptions & MeteringOptions = {},
83
+ ): (app: App) => void {
84
+ return (app) => {
85
+ const recorder = createOpenTelemetryMetricsRecorder(options)
86
+ app.handlerEnhancer(meteringHandlerEnhancerDefinition(recorder, options))
87
+ }
88
+ }