@nwire/telemetry-otel 0.7.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/LICENSE +21 -0
- package/README.md +67 -0
- package/dist/exporter.d.ts +66 -0
- package/dist/exporter.d.ts.map +1 -0
- package/dist/exporter.js +352 -0
- package/dist/exporter.js.map +1 -0
- package/dist/otel-types.d.ts +35 -0
- package/dist/otel-types.d.ts.map +1 -0
- package/dist/otel-types.js +11 -0
- package/dist/otel-types.js.map +1 -0
- package/dist/telemetry-otel.d.ts +18 -0
- package/dist/telemetry-otel.d.ts.map +1 -0
- package/dist/telemetry-otel.js +17 -0
- package/dist/telemetry-otel.js.map +1 -0
- package/package.json +33 -0
- package/src/__tests__/exporter.test.ts +256 -0
- package/src/exporter.ts +416 -0
- package/src/otel-types.ts +42 -0
- package/src/telemetry-otel.ts +18 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alex Gefter / 200apps Ltd.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# @nwire/telemetry-otel
|
|
2
|
+
|
|
3
|
+
> OpenTelemetry bridge — subscribes to `runtime.onTelemetry` and emits OTLP spans + events.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
Translates every canonical telemetry record into OTel spans (with causation-id-keyed parent lookup) and events. `@opentelemetry/api` is duck-typed, so the only runtime dep on Nwire side is `@nwire/forge`'s telemetry types. Pairs cleanly with Vector → GreptimeDB and any OTLP backend (Datadog, Honeycomb, Tempo, Jaeger).
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm add @nwire/telemetry-otel @opentelemetry/api
|
|
13
|
+
# plus the SDK + exporter you choose, e.g.:
|
|
14
|
+
pnpm add @opentelemetry/sdk-node @opentelemetry/exporter-trace-otlp-http
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { trace } from "@opentelemetry/api";
|
|
21
|
+
import { attachOtelExporter } from "@nwire/telemetry-otel";
|
|
22
|
+
import { app } from "./app";
|
|
23
|
+
|
|
24
|
+
const detach = attachOtelExporter(app.runtime, {
|
|
25
|
+
tracer: trace.getTracer("learnflow"),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// later, during shutdown:
|
|
29
|
+
detach();
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## API surface
|
|
33
|
+
|
|
34
|
+
- `attachOtelExporter(runtime, { tracer })` — returns an unsubscribe function.
|
|
35
|
+
- `OtelTracer` / `OtelSpan` / `SpanContext` / `SpanKind` / `SpanStatusCode` — duck-typed OTel shapes.
|
|
36
|
+
|
|
37
|
+
## When to use
|
|
38
|
+
|
|
39
|
+
When you want production traces in your APM. Fits L4 and up.
|
|
40
|
+
|
|
41
|
+
## Standalone use
|
|
42
|
+
|
|
43
|
+
For developers using `@nwire/telemetry-otel` **without the rest of Nwire** — pair it with any TypeScript project, any container, any HTTP framework.
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
// See the package's main entry (src/) for the standalone surface.
|
|
47
|
+
// The exports below work without @nwire/app or @nwire/forge.
|
|
48
|
+
import {} from /* ...standalone exports... */ "@nwire/telemetry-otel";
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Within nwire-app
|
|
52
|
+
|
|
53
|
+
For developers using this package as part of the Nwire stack — register it via `app.use(...)` or it auto-wires when you compose `createApp({ modules })`.
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { createApp } from "@nwire/forge";
|
|
57
|
+
|
|
58
|
+
const app = createApp({
|
|
59
|
+
/* ...config... */
|
|
60
|
+
});
|
|
61
|
+
// Adapter/plugin wiring happens here when applicable.
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## See also
|
|
65
|
+
|
|
66
|
+
- [Architecture sketch §05 — Adapters tier](../../architecture-sketch.html#packages)
|
|
67
|
+
- Sibling packages: [@nwire/observability](../nwire-observability), [@nwire/logger-pino](../nwire-logger-pino)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `attachOtelExporter(runtime, options)` — translates the canonical
|
|
3
|
+
* Nwire telemetry stream into OpenTelemetry spans + events.
|
|
4
|
+
*
|
|
5
|
+
* import { trace } from "@opentelemetry/api";
|
|
6
|
+
* import { attachOtelExporter } from "@nwire/telemetry-otel";
|
|
7
|
+
*
|
|
8
|
+
* const tracer = trace.getTracer("amit");
|
|
9
|
+
* const detach = attachOtelExporter(app.runtime, { tracer });
|
|
10
|
+
*
|
|
11
|
+
* Every Telemetry kind gets a sensible OTel mapping:
|
|
12
|
+
*
|
|
13
|
+
* action.dispatched → open span "action {name}" (parent for the dispatch)
|
|
14
|
+
* action.completed → close that span with ok status
|
|
15
|
+
* action.failed → addEvent "action.failed" (attempt + error)
|
|
16
|
+
* dlq.recorded → close span with error status + dlq event
|
|
17
|
+
* event.published → addEvent "event.published" on the open action span
|
|
18
|
+
* OR ad-hoc span if no open parent
|
|
19
|
+
* actor.transitioned → addEvent "actor.transitioned"
|
|
20
|
+
* projection.folded → addEvent "projection.folded"
|
|
21
|
+
* reaction.fired → child span "reaction {sourceEvent}"
|
|
22
|
+
* reaction.failed → addEvent on the parent + recordException
|
|
23
|
+
* query.executed → ad-hoc span "query {name}"
|
|
24
|
+
* timer.scheduled / .fired → addEvent
|
|
25
|
+
* external.call.started → open child span "external {call}"
|
|
26
|
+
* external.call.completed → close it with ok
|
|
27
|
+
* external.call.failed → close it with error + addEvent per attempt
|
|
28
|
+
* inbound.webhook.received → ad-hoc span "webhook {name}"
|
|
29
|
+
* outbox.flushed → addEvent (could become a metric later)
|
|
30
|
+
* inbox.dedup.hit → addEvent
|
|
31
|
+
* queue.job.{enqueued,started,completed} → ad-hoc span "queue {queue}/{jobId}"
|
|
32
|
+
* cron.fired → ad-hoc span "cron {name}"
|
|
33
|
+
*
|
|
34
|
+
* Spans are correlated by `envelope.messageId` (when present) — open spans
|
|
35
|
+
* are tracked in a Map so completion records can look them up. If a
|
|
36
|
+
* close-record arrives with no matching open span (e.g. listener attached
|
|
37
|
+
* mid-flight), we emit an orphan span with `{ status: ERROR, orphan: true }`.
|
|
38
|
+
*
|
|
39
|
+
* Returns a detach function — calling it unsubscribes and closes any
|
|
40
|
+
* still-open spans with an `unsubscribed` event.
|
|
41
|
+
*/
|
|
42
|
+
import type { Runtime, Telemetry } from "@nwire/forge";
|
|
43
|
+
import type { OtelTracer } from "./otel-types";
|
|
44
|
+
export interface AttachOtelExporterOptions {
|
|
45
|
+
/** OTel Tracer instance from `trace.getTracer(name, version?)`. */
|
|
46
|
+
readonly tracer: OtelTracer;
|
|
47
|
+
/**
|
|
48
|
+
* Prefix to apply to span names. Default `'nwire.'` so traces in OTLP
|
|
49
|
+
* backends stand out. Pass empty string to disable.
|
|
50
|
+
*/
|
|
51
|
+
readonly spanNamePrefix?: string;
|
|
52
|
+
/**
|
|
53
|
+
* Custom event-published handling. By default, we attach published
|
|
54
|
+
* events as span events on the open action span. If you prefer each
|
|
55
|
+
* event as its own span, set `eventsAsSpans: true`.
|
|
56
|
+
*/
|
|
57
|
+
readonly eventsAsSpans?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Filter which telemetry kinds to forward. Default: all. Pass an array
|
|
60
|
+
* to opt in to specific kinds (e.g. for high-volume production traffic
|
|
61
|
+
* you might keep only action.* + external.call.*).
|
|
62
|
+
*/
|
|
63
|
+
readonly kinds?: readonly Telemetry["kind"][];
|
|
64
|
+
}
|
|
65
|
+
export declare function attachOtelExporter(runtime: Runtime, options: AttachOtelExporterOptions): () => void;
|
|
66
|
+
//# sourceMappingURL=exporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exporter.d.ts","sourceRoot":"","sources":["../src/exporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAmB,MAAM,cAAc,CAAC;AACxE,OAAO,KAAK,EAAE,UAAU,EAA4B,MAAM,cAAc,CAAC;AAEzE,MAAM,WAAW,yBAAyB;IACxC,mEAAmE;IACnE,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;CAC/C;AAUD,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,yBAAyB,GACjC,MAAM,IAAI,CAwTZ"}
|
package/dist/exporter.js
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `attachOtelExporter(runtime, options)` — translates the canonical
|
|
3
|
+
* Nwire telemetry stream into OpenTelemetry spans + events.
|
|
4
|
+
*
|
|
5
|
+
* import { trace } from "@opentelemetry/api";
|
|
6
|
+
* import { attachOtelExporter } from "@nwire/telemetry-otel";
|
|
7
|
+
*
|
|
8
|
+
* const tracer = trace.getTracer("amit");
|
|
9
|
+
* const detach = attachOtelExporter(app.runtime, { tracer });
|
|
10
|
+
*
|
|
11
|
+
* Every Telemetry kind gets a sensible OTel mapping:
|
|
12
|
+
*
|
|
13
|
+
* action.dispatched → open span "action {name}" (parent for the dispatch)
|
|
14
|
+
* action.completed → close that span with ok status
|
|
15
|
+
* action.failed → addEvent "action.failed" (attempt + error)
|
|
16
|
+
* dlq.recorded → close span with error status + dlq event
|
|
17
|
+
* event.published → addEvent "event.published" on the open action span
|
|
18
|
+
* OR ad-hoc span if no open parent
|
|
19
|
+
* actor.transitioned → addEvent "actor.transitioned"
|
|
20
|
+
* projection.folded → addEvent "projection.folded"
|
|
21
|
+
* reaction.fired → child span "reaction {sourceEvent}"
|
|
22
|
+
* reaction.failed → addEvent on the parent + recordException
|
|
23
|
+
* query.executed → ad-hoc span "query {name}"
|
|
24
|
+
* timer.scheduled / .fired → addEvent
|
|
25
|
+
* external.call.started → open child span "external {call}"
|
|
26
|
+
* external.call.completed → close it with ok
|
|
27
|
+
* external.call.failed → close it with error + addEvent per attempt
|
|
28
|
+
* inbound.webhook.received → ad-hoc span "webhook {name}"
|
|
29
|
+
* outbox.flushed → addEvent (could become a metric later)
|
|
30
|
+
* inbox.dedup.hit → addEvent
|
|
31
|
+
* queue.job.{enqueued,started,completed} → ad-hoc span "queue {queue}/{jobId}"
|
|
32
|
+
* cron.fired → ad-hoc span "cron {name}"
|
|
33
|
+
*
|
|
34
|
+
* Spans are correlated by `envelope.messageId` (when present) — open spans
|
|
35
|
+
* are tracked in a Map so completion records can look them up. If a
|
|
36
|
+
* close-record arrives with no matching open span (e.g. listener attached
|
|
37
|
+
* mid-flight), we emit an orphan span with `{ status: ERROR, orphan: true }`.
|
|
38
|
+
*
|
|
39
|
+
* Returns a detach function — calling it unsubscribes and closes any
|
|
40
|
+
* still-open spans with an `unsubscribed` event.
|
|
41
|
+
*/
|
|
42
|
+
const OK = 1;
|
|
43
|
+
const ERROR = 2;
|
|
44
|
+
export function attachOtelExporter(runtime, options) {
|
|
45
|
+
const tracer = options.tracer;
|
|
46
|
+
const prefix = options.spanNamePrefix ?? "nwire.";
|
|
47
|
+
const eventsAsSpans = options.eventsAsSpans ?? false;
|
|
48
|
+
const allowed = options.kinds
|
|
49
|
+
? new Set(options.kinds)
|
|
50
|
+
: null;
|
|
51
|
+
// Open spans, keyed by envelope.messageId (action) or call+messageId
|
|
52
|
+
// pair (external call). When the matching completion arrives we close.
|
|
53
|
+
const actionSpans = new Map();
|
|
54
|
+
const externalCallSpans = new Map();
|
|
55
|
+
const unsubscribe = runtime.onTelemetry((rec) => {
|
|
56
|
+
if (allowed && !allowed.has(rec.kind))
|
|
57
|
+
return;
|
|
58
|
+
try {
|
|
59
|
+
route(rec);
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
// Don't let exporter errors break the runtime — the framework's
|
|
63
|
+
// emit() already guards listener throws, but we add explicit
|
|
64
|
+
// logging here too.
|
|
65
|
+
// eslint-disable-next-line no-console
|
|
66
|
+
console.error("[telemetry-otel] export failed:", err);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
function route(rec) {
|
|
70
|
+
switch (rec.kind) {
|
|
71
|
+
case "action.dispatched":
|
|
72
|
+
openActionSpan(rec);
|
|
73
|
+
return;
|
|
74
|
+
case "action.completed":
|
|
75
|
+
closeActionSpan(rec, OK, undefined, {
|
|
76
|
+
"nwire.action.duration_ms": rec.durationMs,
|
|
77
|
+
"nwire.action.emitted_events": rec.emittedEvents.join(","),
|
|
78
|
+
});
|
|
79
|
+
return;
|
|
80
|
+
case "action.failed":
|
|
81
|
+
addEventToActionSpan(rec.envelope.messageId, "action.failed", {
|
|
82
|
+
"nwire.action.attempt": rec.attempt,
|
|
83
|
+
"nwire.action.max_attempts": rec.maxAttempts,
|
|
84
|
+
"nwire.action.will_retry": rec.willRetry,
|
|
85
|
+
...errorAttrs(rec.error),
|
|
86
|
+
});
|
|
87
|
+
return;
|
|
88
|
+
case "dlq.recorded":
|
|
89
|
+
closeActionSpan(rec, ERROR, rec.error.message, {
|
|
90
|
+
"nwire.dlq.attempts": rec.attempts,
|
|
91
|
+
...errorAttrs(rec.error),
|
|
92
|
+
});
|
|
93
|
+
return;
|
|
94
|
+
case "event.published":
|
|
95
|
+
if (eventsAsSpans) {
|
|
96
|
+
adhocSpan(`event ${rec.event.eventName}`, rec.ts, {
|
|
97
|
+
"nwire.event.name": rec.event.eventName,
|
|
98
|
+
"nwire.event.source": rec.source,
|
|
99
|
+
...envelopeAttrs(rec.envelope),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
// Event records carry a DERIVED envelope: messageId is the
|
|
104
|
+
// event's own, causationId is the action that emitted it. So
|
|
105
|
+
// we look up the action span by causationId.
|
|
106
|
+
addEventToActionSpan(rec.envelope.causationId, "event.published", {
|
|
107
|
+
"nwire.event.name": rec.event.eventName,
|
|
108
|
+
"nwire.event.source": rec.source,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
return;
|
|
112
|
+
case "actor.transitioned":
|
|
113
|
+
addEventToActionSpan(rec.envelope.causationId, "actor.transitioned", {
|
|
114
|
+
"nwire.actor": rec.actor,
|
|
115
|
+
"nwire.actor.key": rec.key,
|
|
116
|
+
"nwire.actor.from": rec.from,
|
|
117
|
+
"nwire.actor.to": rec.to,
|
|
118
|
+
"nwire.actor.event": rec.triggeringEvent,
|
|
119
|
+
});
|
|
120
|
+
return;
|
|
121
|
+
case "projection.folded":
|
|
122
|
+
addEventToActionSpan(rec.envelope.causationId, "projection.folded", {
|
|
123
|
+
"nwire.projection": rec.projection,
|
|
124
|
+
"nwire.event.name": rec.event,
|
|
125
|
+
"nwire.projection.duration_ms": rec.durationMs,
|
|
126
|
+
});
|
|
127
|
+
return;
|
|
128
|
+
case "reaction.fired":
|
|
129
|
+
adhocSpan(`reaction ${rec.sourceEvent}`, rec.ts, {
|
|
130
|
+
"nwire.reaction.source_event": rec.sourceEvent,
|
|
131
|
+
"nwire.reaction.duration_ms": rec.durationMs,
|
|
132
|
+
...envelopeAttrs(rec.envelope),
|
|
133
|
+
});
|
|
134
|
+
return;
|
|
135
|
+
case "reaction.failed":
|
|
136
|
+
addEventToActionSpan(rec.envelope.causationId, "reaction.failed", {
|
|
137
|
+
"nwire.reaction.source_event": rec.sourceEvent,
|
|
138
|
+
...errorAttrs(rec.error),
|
|
139
|
+
});
|
|
140
|
+
return;
|
|
141
|
+
case "query.executed":
|
|
142
|
+
adhocSpan(`query ${rec.query}`, rec.ts, {
|
|
143
|
+
"nwire.query.name": rec.query,
|
|
144
|
+
"nwire.query.duration_ms": rec.durationMs,
|
|
145
|
+
"nwire.tenant": rec.tenant,
|
|
146
|
+
});
|
|
147
|
+
return;
|
|
148
|
+
case "timer.scheduled":
|
|
149
|
+
case "timer.fired":
|
|
150
|
+
adhocSpan(rec.kind, rec.ts, {
|
|
151
|
+
"nwire.actor": rec.actor,
|
|
152
|
+
"nwire.actor.key": rec.key,
|
|
153
|
+
"nwire.timer.name": rec.timer,
|
|
154
|
+
"nwire.timer.action": rec.action,
|
|
155
|
+
"nwire.tenant": rec.tenant,
|
|
156
|
+
...(rec.kind === "timer.fired"
|
|
157
|
+
? { "nwire.timer.late_by_ms": rec.lateByMs }
|
|
158
|
+
: { "nwire.timer.fire_at": rec.fireAt }),
|
|
159
|
+
});
|
|
160
|
+
return;
|
|
161
|
+
case "external.call.started":
|
|
162
|
+
openExternalCallSpan(rec);
|
|
163
|
+
return;
|
|
164
|
+
case "external.call.completed":
|
|
165
|
+
closeExternalCallSpan(rec, OK, undefined, {
|
|
166
|
+
"nwire.external.duration_ms": rec.durationMs,
|
|
167
|
+
...(rec.status !== undefined ? { "nwire.external.status": rec.status } : {}),
|
|
168
|
+
});
|
|
169
|
+
return;
|
|
170
|
+
case "external.call.failed":
|
|
171
|
+
closeExternalCallSpan(rec, ERROR, rec.error.message, {
|
|
172
|
+
"nwire.external.attempt": rec.attempt,
|
|
173
|
+
"nwire.external.will_retry": rec.willRetry,
|
|
174
|
+
...errorAttrs(rec.error),
|
|
175
|
+
});
|
|
176
|
+
return;
|
|
177
|
+
case "inbound.webhook.received":
|
|
178
|
+
adhocSpan(`webhook ${rec.webhook}`, rec.ts, {
|
|
179
|
+
"nwire.webhook.name": rec.webhook,
|
|
180
|
+
"nwire.webhook.source": rec.source,
|
|
181
|
+
"nwire.webhook.signature_valid": rec.signatureValid,
|
|
182
|
+
"nwire.webhook.dedup_hit": rec.dedupHit,
|
|
183
|
+
...(rec.routedTo ? { "nwire.webhook.routed_to": rec.routedTo } : {}),
|
|
184
|
+
});
|
|
185
|
+
return;
|
|
186
|
+
case "outbox.flushed":
|
|
187
|
+
adhocSpan(`outbox ${rec.outbox} flush`, rec.ts, {
|
|
188
|
+
"nwire.outbox.name": rec.outbox,
|
|
189
|
+
"nwire.outbox.events": rec.events,
|
|
190
|
+
"nwire.outbox.failed": rec.failed,
|
|
191
|
+
"nwire.outbox.duration_ms": rec.durationMs,
|
|
192
|
+
});
|
|
193
|
+
return;
|
|
194
|
+
case "inbox.dedup.hit":
|
|
195
|
+
adhocSpan(`inbox ${rec.inbox} dedup`, rec.ts, {
|
|
196
|
+
"nwire.inbox.name": rec.inbox,
|
|
197
|
+
"nwire.inbox.message_id": rec.messageId,
|
|
198
|
+
"nwire.inbox.first_seen_at": rec.firstSeenAt,
|
|
199
|
+
});
|
|
200
|
+
return;
|
|
201
|
+
case "queue.job.enqueued":
|
|
202
|
+
case "queue.job.started":
|
|
203
|
+
case "queue.job.completed":
|
|
204
|
+
adhocSpan(`queue ${rec.queue}/${rec.kind.replace("queue.job.", "")}`, rec.ts, {
|
|
205
|
+
"nwire.queue.name": rec.queue,
|
|
206
|
+
"nwire.queue.job_id": rec.jobId,
|
|
207
|
+
...(rec.kind === "queue.job.enqueued" && rec.delay !== undefined
|
|
208
|
+
? { "nwire.queue.delay": rec.delay }
|
|
209
|
+
: {}),
|
|
210
|
+
...(rec.kind === "queue.job.started" ? { "nwire.queue.waited_ms": rec.waitedMs } : {}),
|
|
211
|
+
...(rec.kind === "queue.job.completed"
|
|
212
|
+
? { "nwire.queue.duration_ms": rec.durationMs, "nwire.queue.ok": rec.ok }
|
|
213
|
+
: {}),
|
|
214
|
+
});
|
|
215
|
+
return;
|
|
216
|
+
case "cron.fired":
|
|
217
|
+
adhocSpan(`cron ${rec.cronName}`, rec.ts, {
|
|
218
|
+
"nwire.cron.name": rec.cronName,
|
|
219
|
+
"nwire.cron.schedule": rec.schedule,
|
|
220
|
+
"nwire.cron.expected": rec.expected,
|
|
221
|
+
"nwire.cron.actual": rec.actual,
|
|
222
|
+
"nwire.cron.late_by_ms": rec.lateByMs,
|
|
223
|
+
});
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
function openActionSpan(rec) {
|
|
228
|
+
const span = tracer.startSpan(`${prefix}action ${rec.action}`, {
|
|
229
|
+
startTime: new Date(rec.ts),
|
|
230
|
+
attributes: {
|
|
231
|
+
"nwire.action": rec.action,
|
|
232
|
+
...envelopeAttrs(rec.envelope),
|
|
233
|
+
"nwire.app": rec.appName,
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
actionSpans.set(rec.envelope.messageId, { span, startedAt: Date.now() });
|
|
237
|
+
}
|
|
238
|
+
function closeActionSpan(rec, status, msg, attrs) {
|
|
239
|
+
const open = actionSpans.get(rec.envelope.messageId);
|
|
240
|
+
if (!open) {
|
|
241
|
+
// Orphan — close-record without an open span. Emit an ad-hoc record
|
|
242
|
+
// so we don't silently drop data.
|
|
243
|
+
adhocSpan(`${prefix}action.orphan`, rec.ts, {
|
|
244
|
+
"nwire.orphan": true,
|
|
245
|
+
"nwire.app": rec.appName,
|
|
246
|
+
...attrs,
|
|
247
|
+
});
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
actionSpans.delete(rec.envelope.messageId);
|
|
251
|
+
setAttrs(open.span, attrs);
|
|
252
|
+
open.span.setStatus({ code: status, message: msg });
|
|
253
|
+
open.span.end(new Date(rec.ts));
|
|
254
|
+
}
|
|
255
|
+
function addEventToActionSpan(messageId, name, attrs) {
|
|
256
|
+
const open = actionSpans.get(messageId);
|
|
257
|
+
if (open) {
|
|
258
|
+
open.span.addEvent(name, attrs);
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
// No parent — emit standalone ad-hoc.
|
|
262
|
+
adhocSpan(name, new Date().toISOString(), attrs);
|
|
263
|
+
}
|
|
264
|
+
function openExternalCallSpan(rec) {
|
|
265
|
+
const span = tracer.startSpan(`${prefix}external ${rec.call}`, {
|
|
266
|
+
startTime: new Date(rec.ts),
|
|
267
|
+
attributes: {
|
|
268
|
+
"nwire.external.call": rec.call,
|
|
269
|
+
"nwire.external.target": rec.target,
|
|
270
|
+
...(rec.idempotencyKey
|
|
271
|
+
? { "nwire.external.idempotency_key": rec.idempotencyKey }
|
|
272
|
+
: {}),
|
|
273
|
+
...(rec.envelope ? envelopeAttrs(rec.envelope) : {}),
|
|
274
|
+
"nwire.app": rec.appName,
|
|
275
|
+
},
|
|
276
|
+
});
|
|
277
|
+
// Key by call + correlation; multiple concurrent calls with same name
|
|
278
|
+
// would collide, so include messageId if available.
|
|
279
|
+
const key = externalCallKey(rec.call, rec.envelope?.messageId);
|
|
280
|
+
externalCallSpans.set(key, { span, startedAt: Date.now() });
|
|
281
|
+
}
|
|
282
|
+
function closeExternalCallSpan(rec, status, msg, attrs) {
|
|
283
|
+
const key = externalCallKey(rec.call, rec.envelope?.messageId);
|
|
284
|
+
const open = externalCallSpans.get(key);
|
|
285
|
+
if (!open) {
|
|
286
|
+
adhocSpan(`${prefix}external.orphan ${rec.call}`, rec.ts, {
|
|
287
|
+
"nwire.orphan": true,
|
|
288
|
+
"nwire.external.call": rec.call,
|
|
289
|
+
"nwire.external.target": rec.target,
|
|
290
|
+
...attrs,
|
|
291
|
+
});
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
externalCallSpans.delete(key);
|
|
295
|
+
setAttrs(open.span, attrs);
|
|
296
|
+
open.span.setStatus({ code: status, message: msg });
|
|
297
|
+
open.span.end(new Date(rec.ts));
|
|
298
|
+
}
|
|
299
|
+
function externalCallKey(call, messageId) {
|
|
300
|
+
return `${call}::${messageId ?? "no-envelope"}`;
|
|
301
|
+
}
|
|
302
|
+
function adhocSpan(name, ts, attrs) {
|
|
303
|
+
const startTime = new Date(ts);
|
|
304
|
+
const span = tracer.startSpan(name.startsWith(prefix) ? name : `${prefix}${name}`, {
|
|
305
|
+
startTime,
|
|
306
|
+
attributes: attrs,
|
|
307
|
+
});
|
|
308
|
+
span.end(startTime);
|
|
309
|
+
}
|
|
310
|
+
return () => {
|
|
311
|
+
unsubscribe();
|
|
312
|
+
// Close any still-open spans so the exporter flushes them.
|
|
313
|
+
for (const { span } of actionSpans.values()) {
|
|
314
|
+
span.addEvent("nwire.unsubscribed");
|
|
315
|
+
span.end();
|
|
316
|
+
}
|
|
317
|
+
for (const { span } of externalCallSpans.values()) {
|
|
318
|
+
span.addEvent("nwire.unsubscribed");
|
|
319
|
+
span.end();
|
|
320
|
+
}
|
|
321
|
+
actionSpans.clear();
|
|
322
|
+
externalCallSpans.clear();
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
function envelopeAttrs(envelope) {
|
|
326
|
+
return {
|
|
327
|
+
"nwire.message_id": envelope.messageId,
|
|
328
|
+
"nwire.correlation_id": envelope.correlationId,
|
|
329
|
+
"nwire.causation_id": envelope.causationId,
|
|
330
|
+
...(envelope.tenant ? { "nwire.tenant": envelope.tenant } : {}),
|
|
331
|
+
...(envelope.userId ? { "nwire.user_id": envelope.userId } : {}),
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
function errorAttrs(err) {
|
|
335
|
+
return {
|
|
336
|
+
"nwire.error.name": err.name,
|
|
337
|
+
"nwire.error.message": err.message,
|
|
338
|
+
...(err.stack ? { "nwire.error.stack": err.stack } : {}),
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
function setAttrs(span, attrs) {
|
|
342
|
+
if (span.setAttributes) {
|
|
343
|
+
span.setAttributes(attrs);
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
for (const [k, v] of Object.entries(attrs)) {
|
|
347
|
+
if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") {
|
|
348
|
+
span.setAttribute(k, v);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
//# sourceMappingURL=exporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exporter.js","sourceRoot":"","sources":["../src/exporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AA2BH,MAAM,EAAE,GAAmB,CAAC,CAAC;AAC7B,MAAM,KAAK,GAAmB,CAAC,CAAC;AAOhC,MAAM,UAAU,kBAAkB,CAChC,OAAgB,EAChB,OAAkC;IAElC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC9B,MAAM,MAAM,GAAG,OAAO,CAAC,cAAc,IAAI,QAAQ,CAAC;IAClD,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,KAAK,CAAC;IACrD,MAAM,OAAO,GAA+B,OAAO,CAAC,KAAK;QACvD,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC;QACxB,CAAC,CAAC,IAAI,CAAC;IAET,qEAAqE;IACrE,uEAAuE;IACvE,MAAM,WAAW,GAAG,IAAI,GAAG,EAAoB,CAAC;IAChD,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAoB,CAAC;IAEtD,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,EAAE,EAAE;QAC9C,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO;QAC9C,IAAI,CAAC;YACH,KAAK,CAAC,GAAG,CAAC,CAAC;QACb,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,gEAAgE;YAChE,6DAA6D;YAC7D,oBAAoB;YACpB,sCAAsC;YACtC,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,GAAG,CAAC,CAAC;QACxD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,SAAS,KAAK,CAAC,GAAc;QAC3B,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;YACjB,KAAK,mBAAmB;gBACtB,cAAc,CAAC,GAAG,CAAC,CAAC;gBACpB,OAAO;YACT,KAAK,kBAAkB;gBACrB,eAAe,CAAC,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE;oBAClC,0BAA0B,EAAE,GAAG,CAAC,UAAU;oBAC1C,6BAA6B,EAAE,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC;iBAC3D,CAAC,CAAC;gBACH,OAAO;YACT,KAAK,eAAe;gBAClB,oBAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,EAAE,eAAe,EAAE;oBAC5D,sBAAsB,EAAE,GAAG,CAAC,OAAO;oBACnC,2BAA2B,EAAE,GAAG,CAAC,WAAW;oBAC5C,yBAAyB,EAAE,GAAG,CAAC,SAAS;oBACxC,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;iBACzB,CAAC,CAAC;gBACH,OAAO;YACT,KAAK,cAAc;gBACjB,eAAe,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE;oBAC7C,oBAAoB,EAAE,GAAG,CAAC,QAAQ;oBAClC,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;iBACzB,CAAC,CAAC;gBACH,OAAO;YACT,KAAK,iBAAiB;gBACpB,IAAI,aAAa,EAAE,CAAC;oBAClB,SAAS,CAAC,SAAS,GAAG,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE;wBAChD,kBAAkB,EAAE,GAAG,CAAC,KAAK,CAAC,SAAS;wBACvC,oBAAoB,EAAE,GAAG,CAAC,MAAM;wBAChC,GAAG,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC;qBAC/B,CAAC,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACN,2DAA2D;oBAC3D,6DAA6D;oBAC7D,6CAA6C;oBAC7C,oBAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,iBAAiB,EAAE;wBAChE,kBAAkB,EAAE,GAAG,CAAC,KAAK,CAAC,SAAS;wBACvC,oBAAoB,EAAE,GAAG,CAAC,MAAM;qBACjC,CAAC,CAAC;gBACL,CAAC;gBACD,OAAO;YACT,KAAK,oBAAoB;gBACvB,oBAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,oBAAoB,EAAE;oBACnE,aAAa,EAAE,GAAG,CAAC,KAAK;oBACxB,iBAAiB,EAAE,GAAG,CAAC,GAAG;oBAC1B,kBAAkB,EAAE,GAAG,CAAC,IAAI;oBAC5B,gBAAgB,EAAE,GAAG,CAAC,EAAE;oBACxB,mBAAmB,EAAE,GAAG,CAAC,eAAe;iBACzC,CAAC,CAAC;gBACH,OAAO;YACT,KAAK,mBAAmB;gBACtB,oBAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,mBAAmB,EAAE;oBAClE,kBAAkB,EAAE,GAAG,CAAC,UAAU;oBAClC,kBAAkB,EAAE,GAAG,CAAC,KAAK;oBAC7B,8BAA8B,EAAE,GAAG,CAAC,UAAU;iBAC/C,CAAC,CAAC;gBACH,OAAO;YACT,KAAK,gBAAgB;gBACnB,SAAS,CAAC,YAAY,GAAG,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE;oBAC/C,6BAA6B,EAAE,GAAG,CAAC,WAAW;oBAC9C,4BAA4B,EAAE,GAAG,CAAC,UAAU;oBAC5C,GAAG,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC;iBAC/B,CAAC,CAAC;gBACH,OAAO;YACT,KAAK,iBAAiB;gBACpB,oBAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,iBAAiB,EAAE;oBAChE,6BAA6B,EAAE,GAAG,CAAC,WAAW;oBAC9C,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;iBACzB,CAAC,CAAC;gBACH,OAAO;YACT,KAAK,gBAAgB;gBACnB,SAAS,CAAC,SAAS,GAAG,CAAC,KAAK,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE;oBACtC,kBAAkB,EAAE,GAAG,CAAC,KAAK;oBAC7B,yBAAyB,EAAE,GAAG,CAAC,UAAU;oBACzC,cAAc,EAAE,GAAG,CAAC,MAAM;iBAC3B,CAAC,CAAC;gBACH,OAAO;YACT,KAAK,iBAAiB,CAAC;YACvB,KAAK,aAAa;gBAChB,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE;oBAC1B,aAAa,EAAE,GAAG,CAAC,KAAK;oBACxB,iBAAiB,EAAE,GAAG,CAAC,GAAG;oBAC1B,kBAAkB,EAAE,GAAG,CAAC,KAAK;oBAC7B,oBAAoB,EAAE,GAAG,CAAC,MAAM;oBAChC,cAAc,EAAE,GAAG,CAAC,MAAM;oBAC1B,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,aAAa;wBAC5B,CAAC,CAAC,EAAE,wBAAwB,EAAE,GAAG,CAAC,QAAQ,EAAE;wBAC5C,CAAC,CAAC,EAAE,qBAAqB,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;iBAC3C,CAAC,CAAC;gBACH,OAAO;YACT,KAAK,uBAAuB;gBAC1B,oBAAoB,CAAC,GAAG,CAAC,CAAC;gBAC1B,OAAO;YACT,KAAK,yBAAyB;gBAC5B,qBAAqB,CAAC,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE;oBACxC,4BAA4B,EAAE,GAAG,CAAC,UAAU;oBAC5C,GAAG,CAAC,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,uBAAuB,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAC7E,CAAC,CAAC;gBACH,OAAO;YACT,KAAK,sBAAsB;gBACzB,qBAAqB,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE;oBACnD,wBAAwB,EAAE,GAAG,CAAC,OAAO;oBACrC,2BAA2B,EAAE,GAAG,CAAC,SAAS;oBAC1C,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;iBACzB,CAAC,CAAC;gBACH,OAAO;YACT,KAAK,0BAA0B;gBAC7B,SAAS,CAAC,WAAW,GAAG,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE;oBAC1C,oBAAoB,EAAE,GAAG,CAAC,OAAO;oBACjC,sBAAsB,EAAE,GAAG,CAAC,MAAM;oBAClC,+BAA+B,EAAE,GAAG,CAAC,cAAc;oBACnD,yBAAyB,EAAE,GAAG,CAAC,QAAQ;oBACvC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,yBAAyB,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACrE,CAAC,CAAC;gBACH,OAAO;YACT,KAAK,gBAAgB;gBACnB,SAAS,CAAC,UAAU,GAAG,CAAC,MAAM,QAAQ,EAAE,GAAG,CAAC,EAAE,EAAE;oBAC9C,mBAAmB,EAAE,GAAG,CAAC,MAAM;oBAC/B,qBAAqB,EAAE,GAAG,CAAC,MAAM;oBACjC,qBAAqB,EAAE,GAAG,CAAC,MAAM;oBACjC,0BAA0B,EAAE,GAAG,CAAC,UAAU;iBAC3C,CAAC,CAAC;gBACH,OAAO;YACT,KAAK,iBAAiB;gBACpB,SAAS,CAAC,SAAS,GAAG,CAAC,KAAK,QAAQ,EAAE,GAAG,CAAC,EAAE,EAAE;oBAC5C,kBAAkB,EAAE,GAAG,CAAC,KAAK;oBAC7B,wBAAwB,EAAE,GAAG,CAAC,SAAS;oBACvC,2BAA2B,EAAE,GAAG,CAAC,WAAW;iBAC7C,CAAC,CAAC;gBACH,OAAO;YACT,KAAK,oBAAoB,CAAC;YAC1B,KAAK,mBAAmB,CAAC;YACzB,KAAK,qBAAqB;gBACxB,SAAS,CAAC,SAAS,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE;oBAC5E,kBAAkB,EAAE,GAAG,CAAC,KAAK;oBAC7B,oBAAoB,EAAE,GAAG,CAAC,KAAK;oBAC/B,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,oBAAoB,IAAI,GAAG,CAAC,KAAK,KAAK,SAAS;wBAC9D,CAAC,CAAC,EAAE,mBAAmB,EAAE,GAAG,CAAC,KAAK,EAAE;wBACpC,CAAC,CAAC,EAAE,CAAC;oBACP,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,mBAAmB,CAAC,CAAC,CAAC,EAAE,uBAAuB,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACtF,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,qBAAqB;wBACpC,CAAC,CAAC,EAAE,yBAAyB,EAAE,GAAG,CAAC,UAAU,EAAE,gBAAgB,EAAE,GAAG,CAAC,EAAE,EAAE;wBACzE,CAAC,CAAC,EAAE,CAAC;iBACR,CAAC,CAAC;gBACH,OAAO;YACT,KAAK,YAAY;gBACf,SAAS,CAAC,QAAQ,GAAG,CAAC,QAAQ,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE;oBACxC,iBAAiB,EAAE,GAAG,CAAC,QAAQ;oBAC/B,qBAAqB,EAAE,GAAG,CAAC,QAAQ;oBACnC,qBAAqB,EAAE,GAAG,CAAC,QAAQ;oBACnC,mBAAmB,EAAE,GAAG,CAAC,MAAM;oBAC/B,uBAAuB,EAAE,GAAG,CAAC,QAAQ;iBACtC,CAAC,CAAC;gBACH,OAAO;QACX,CAAC;IACH,CAAC;IAED,SAAS,cAAc,CACrB,GAAsD;QAEtD,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,EAAE;YAC7D,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B,UAAU,EAAE;gBACV,cAAc,EAAE,GAAG,CAAC,MAAM;gBAC1B,GAAG,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAC9B,WAAW,EAAE,GAAG,CAAC,OAAO;aACzB;SACF,CAAC,CAAC;QACH,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED,SAAS,eAAe,CACtB,GAAqE,EACrE,MAAsB,EACtB,GAAuB,EACvB,KAA8B;QAE9B,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QACrD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,oEAAoE;YACpE,kCAAkC;YAClC,SAAS,CAAC,GAAG,MAAM,eAAe,EAAE,GAAG,CAAC,EAAE,EAAE;gBAC1C,cAAc,EAAE,IAAI;gBACpB,WAAW,EAAE,GAAG,CAAC,OAAO;gBACxB,GAAG,KAAK;aACT,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC3C,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC3B,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAClC,CAAC;IAED,SAAS,oBAAoB,CAC3B,SAAiB,EACjB,IAAY,EACZ,KAA8B;QAE9B,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACxC,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAChC,OAAO;QACT,CAAC;QACD,sCAAsC;QACtC,SAAS,CAAC,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,KAAK,CAAC,CAAC;IACnD,CAAC;IAED,SAAS,oBAAoB,CAC3B,GAA0D;QAE1D,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,EAAE;YAC7D,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B,UAAU,EAAE;gBACV,qBAAqB,EAAE,GAAG,CAAC,IAAI;gBAC/B,uBAAuB,EAAE,GAAG,CAAC,MAAM;gBACnC,GAAG,CAAC,GAAG,CAAC,cAAc;oBACpB,CAAC,CAAC,EAAE,gCAAgC,EAAE,GAAG,CAAC,cAAc,EAAE;oBAC1D,CAAC,CAAC,EAAE,CAAC;gBACP,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpD,WAAW,EAAE,GAAG,CAAC,OAAO;aACzB;SACF,CAAC,CAAC;QACH,sEAAsE;QACtE,oDAAoD;QACpD,MAAM,GAAG,GAAG,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAC/D,iBAAiB,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,SAAS,qBAAqB,CAC5B,GAEwD,EACxD,MAAsB,EACtB,GAAuB,EACvB,KAA8B;QAE9B,MAAM,GAAG,GAAG,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAC/D,MAAM,IAAI,GAAG,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,SAAS,CAAC,GAAG,MAAM,mBAAmB,GAAG,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE;gBACxD,cAAc,EAAE,IAAI;gBACpB,qBAAqB,EAAE,GAAG,CAAC,IAAI;gBAC/B,uBAAuB,EAAE,GAAG,CAAC,MAAM;gBACnC,GAAG,KAAK;aACT,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,iBAAiB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9B,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC3B,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAClC,CAAC;IAED,SAAS,eAAe,CAAC,IAAY,EAAE,SAA6B;QAClE,OAAO,GAAG,IAAI,KAAK,SAAS,IAAI,aAAa,EAAE,CAAC;IAClD,CAAC;IAED,SAAS,SAAS,CAChB,IAAY,EACZ,EAAU,EACV,KAA8B;QAE9B,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC;QAC/B,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,IAAI,EAAE,EAAE;YACjF,SAAS;YACT,UAAU,EAAE,KAAK;SAClB,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACtB,CAAC;IAED,OAAO,GAAG,EAAE;QACV,WAAW,EAAE,CAAC;QACd,2DAA2D;QAC3D,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC;YAC5C,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;YACpC,IAAI,CAAC,GAAG,EAAE,CAAC;QACb,CAAC;QACD,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,iBAAiB,CAAC,MAAM,EAAE,EAAE,CAAC;YAClD,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;YACpC,IAAI,CAAC,GAAG,EAAE,CAAC;QACb,CAAC;QACD,WAAW,CAAC,KAAK,EAAE,CAAC;QACpB,iBAAiB,CAAC,KAAK,EAAE,CAAC;IAC5B,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,QAOtB;IACC,OAAO;QACL,kBAAkB,EAAE,QAAQ,CAAC,SAAS;QACtC,sBAAsB,EAAE,QAAQ,CAAC,aAAa;QAC9C,oBAAoB,EAAE,QAAQ,CAAC,WAAW;QAC1C,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACjE,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,GAAoB;IACtC,OAAO;QACL,kBAAkB,EAAE,GAAG,CAAC,IAAI;QAC5B,qBAAqB,EAAE,GAAG,CAAC,OAAO;QAClC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,mBAAmB,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACzD,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,IAAc,EAAE,KAA8B;IAC9D,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACvB,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC1B,OAAO;IACT,CAAC;IACD,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3C,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,SAAS,EAAE,CAAC;YAC7E,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal duck-typed surface of `@opentelemetry/api`'s Tracer + Span. We
|
|
3
|
+
* never import the package — consumers bring their own version and pass a
|
|
4
|
+
* `Tracer` in. This keeps `@nwire/telemetry-otel` zero-dep at runtime
|
|
5
|
+
* (only `@nwire/forge` for the Telemetry type).
|
|
6
|
+
*
|
|
7
|
+
* The fields are the subset we actually use. If a consumer passes a real
|
|
8
|
+
* `@opentelemetry/api` Tracer, structural typing makes it compatible.
|
|
9
|
+
*/
|
|
10
|
+
export type SpanKind = 0 | 1 | 2 | 3 | 4 | 5;
|
|
11
|
+
export type SpanStatusCode = 0 | 1 | 2;
|
|
12
|
+
export interface SpanContext {
|
|
13
|
+
traceId: string;
|
|
14
|
+
spanId: string;
|
|
15
|
+
}
|
|
16
|
+
export interface OtelSpan {
|
|
17
|
+
spanContext?(): SpanContext;
|
|
18
|
+
setAttribute(key: string, value: string | number | boolean): OtelSpan | void;
|
|
19
|
+
setAttributes?(attrs: Record<string, unknown>): OtelSpan | void;
|
|
20
|
+
addEvent(name: string, attrs?: Record<string, unknown>, timestamp?: number | Date): OtelSpan | void;
|
|
21
|
+
recordException(err: unknown): OtelSpan | void;
|
|
22
|
+
setStatus(status: {
|
|
23
|
+
code: SpanStatusCode;
|
|
24
|
+
message?: string;
|
|
25
|
+
}): OtelSpan | void;
|
|
26
|
+
end(endTime?: number | Date): void;
|
|
27
|
+
}
|
|
28
|
+
export interface OtelTracer {
|
|
29
|
+
startSpan(name: string, options?: {
|
|
30
|
+
attributes?: Record<string, unknown>;
|
|
31
|
+
kind?: SpanKind;
|
|
32
|
+
startTime?: number | Date;
|
|
33
|
+
}): OtelSpan;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=otel-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otel-types.d.ts","sourceRoot":"","sources":["../src/otel-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC7C,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAEvC,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,QAAQ;IACvB,WAAW,CAAC,IAAI,WAAW,CAAC;IAC5B,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC7E,aAAa,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,QAAQ,GAAG,IAAI,CAAC;IAChE,QAAQ,CACN,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GACxB,QAAQ,GAAG,IAAI,CAAC;IACnB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC/C,SAAS,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,cAAc,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC/E,GAAG,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,CACP,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QACR,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACrC,IAAI,CAAC,EAAE,QAAQ,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC3B,GACA,QAAQ,CAAC;CACb"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal duck-typed surface of `@opentelemetry/api`'s Tracer + Span. We
|
|
3
|
+
* never import the package — consumers bring their own version and pass a
|
|
4
|
+
* `Tracer` in. This keeps `@nwire/telemetry-otel` zero-dep at runtime
|
|
5
|
+
* (only `@nwire/forge` for the Telemetry type).
|
|
6
|
+
*
|
|
7
|
+
* The fields are the subset we actually use. If a consumer passes a real
|
|
8
|
+
* `@opentelemetry/api` Tracer, structural typing makes it compatible.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=otel-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otel-types.js","sourceRoot":"","sources":["../src/otel-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@nwire/telemetry-otel` — OpenTelemetry bridge for the canonical Nwire
|
|
3
|
+
* telemetry stream. Subscribes to `runtime.onTelemetry` and translates
|
|
4
|
+
* every record into OTel spans + events.
|
|
5
|
+
*
|
|
6
|
+
* import { trace } from "@opentelemetry/api";
|
|
7
|
+
* import { attachOtelExporter } from "@nwire/telemetry-otel";
|
|
8
|
+
*
|
|
9
|
+
* const detach = attachOtelExporter(app.runtime, {
|
|
10
|
+
* tracer: trace.getTracer("amit"),
|
|
11
|
+
* });
|
|
12
|
+
*
|
|
13
|
+
* Pairs cleanly with Vector → GreptimeDB (and any other OTLP backend —
|
|
14
|
+
* Datadog, Honeycomb, Tempo, Jaeger).
|
|
15
|
+
*/
|
|
16
|
+
export { attachOtelExporter, type AttachOtelExporterOptions } from "./exporter";
|
|
17
|
+
export type { OtelTracer, OtelSpan, SpanContext, SpanKind, SpanStatusCode } from "./otel-types";
|
|
18
|
+
//# sourceMappingURL=telemetry-otel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-otel.d.ts","sourceRoot":"","sources":["../src/telemetry-otel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAChF,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@nwire/telemetry-otel` — OpenTelemetry bridge for the canonical Nwire
|
|
3
|
+
* telemetry stream. Subscribes to `runtime.onTelemetry` and translates
|
|
4
|
+
* every record into OTel spans + events.
|
|
5
|
+
*
|
|
6
|
+
* import { trace } from "@opentelemetry/api";
|
|
7
|
+
* import { attachOtelExporter } from "@nwire/telemetry-otel";
|
|
8
|
+
*
|
|
9
|
+
* const detach = attachOtelExporter(app.runtime, {
|
|
10
|
+
* tracer: trace.getTracer("amit"),
|
|
11
|
+
* });
|
|
12
|
+
*
|
|
13
|
+
* Pairs cleanly with Vector → GreptimeDB (and any other OTLP backend —
|
|
14
|
+
* Datadog, Honeycomb, Tempo, Jaeger).
|
|
15
|
+
*/
|
|
16
|
+
export { attachOtelExporter } from "./exporter";
|
|
17
|
+
//# sourceMappingURL=telemetry-otel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-otel.js","sourceRoot":"","sources":["../src/telemetry-otel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,kBAAkB,EAAkC,MAAM,YAAY,CAAC"}
|