@dudousxd/nestjs-durable-telescope 0.1.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/durable-telescope.watcher.d.ts +23 -0
- package/dist/durable-telescope.watcher.d.ts.map +1 -0
- package/dist/durable-telescope.watcher.js +91 -0
- package/dist/durable-telescope.watcher.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/package.json +35 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Watcher, WatcherContext } from '@dudousxd/nestjs-telescope';
|
|
2
|
+
/**
|
|
3
|
+
* A Telescope watcher that turns durable-workflow lifecycle events into Telescope entries, so
|
|
4
|
+
* runs and steps (including remote/Python steps) show up alongside the app's requests, queries
|
|
5
|
+
* and jobs in the Telescope UI — under the **Workflows** tab.
|
|
6
|
+
*
|
|
7
|
+
* It also **trace-groups** a run: a root span is opened per run and every entry is recorded inside
|
|
8
|
+
* that span's OTel context (step entries inside a child `step …` span). Telescope's trace-context
|
|
9
|
+
* provider stamps each entry with the active span, so a whole workflow shows up as a single trace
|
|
10
|
+
* on the Traces page — run → steps — with each entry carrying the run's `traceId`. When the host has
|
|
11
|
+
* no OTel SDK the spans are no-ops and entries simply carry no trace (the prior behaviour).
|
|
12
|
+
*
|
|
13
|
+
* Add it to `TelescopeModule.forRoot({ watchers: [new DurableTelescopeWatcher()] })`. It resolves
|
|
14
|
+
* the engine from the (global) durable providers and subscribes to its events.
|
|
15
|
+
*/
|
|
16
|
+
export declare class DurableTelescopeWatcher implements Watcher {
|
|
17
|
+
readonly type = "durable";
|
|
18
|
+
/** Open root span per run, so step entries nest under it and share its traceId. */
|
|
19
|
+
private readonly roots;
|
|
20
|
+
register(ctx: WatcherContext): void;
|
|
21
|
+
private tags;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=durable-telescope.watcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durable-telescope.watcher.d.ts","sourceRoot":"","sources":["../src/durable-telescope.watcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAG1E;;;;;;;;;;;;;GAaG;AACH,qBAAa,uBAAwB,YAAW,OAAO;IACrD,QAAQ,CAAC,IAAI,aAAa;IAC1B,mFAAmF;IACnF,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2B;IAEjD,QAAQ,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI;IAkEnC,OAAO,CAAC,IAAI;CAOb"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DurableTelescopeWatcher = void 0;
|
|
4
|
+
const nestjs_durable_core_1 = require("@dudousxd/nestjs-durable-core");
|
|
5
|
+
const api_1 = require("@opentelemetry/api");
|
|
6
|
+
/**
|
|
7
|
+
* A Telescope watcher that turns durable-workflow lifecycle events into Telescope entries, so
|
|
8
|
+
* runs and steps (including remote/Python steps) show up alongside the app's requests, queries
|
|
9
|
+
* and jobs in the Telescope UI — under the **Workflows** tab.
|
|
10
|
+
*
|
|
11
|
+
* It also **trace-groups** a run: a root span is opened per run and every entry is recorded inside
|
|
12
|
+
* that span's OTel context (step entries inside a child `step …` span). Telescope's trace-context
|
|
13
|
+
* provider stamps each entry with the active span, so a whole workflow shows up as a single trace
|
|
14
|
+
* on the Traces page — run → steps — with each entry carrying the run's `traceId`. When the host has
|
|
15
|
+
* no OTel SDK the spans are no-ops and entries simply carry no trace (the prior behaviour).
|
|
16
|
+
*
|
|
17
|
+
* Add it to `TelescopeModule.forRoot({ watchers: [new DurableTelescopeWatcher()] })`. It resolves
|
|
18
|
+
* the engine from the (global) durable providers and subscribes to its events.
|
|
19
|
+
*/
|
|
20
|
+
class DurableTelescopeWatcher {
|
|
21
|
+
type = 'durable';
|
|
22
|
+
/** Open root span per run, so step entries nest under it and share its traceId. */
|
|
23
|
+
roots = new Map();
|
|
24
|
+
register(ctx) {
|
|
25
|
+
const engine = ctx.moduleRef.get(nestjs_durable_core_1.WorkflowEngine, { strict: false });
|
|
26
|
+
const tracer = api_1.trace.getTracer('@dudousxd/nestjs-durable-telescope');
|
|
27
|
+
engine.subscribe((event) => {
|
|
28
|
+
const record = () => ctx.record({
|
|
29
|
+
type: this.type,
|
|
30
|
+
content: {
|
|
31
|
+
event: event.type,
|
|
32
|
+
workflow: event.workflow,
|
|
33
|
+
runId: event.runId,
|
|
34
|
+
seq: event.seq,
|
|
35
|
+
name: event.name,
|
|
36
|
+
kind: event.kind,
|
|
37
|
+
output: event.output,
|
|
38
|
+
error: event.error,
|
|
39
|
+
},
|
|
40
|
+
tags: this.tags(event),
|
|
41
|
+
});
|
|
42
|
+
// Open the run's root span on first sight; later events nest under it.
|
|
43
|
+
if (event.type === 'run.started') {
|
|
44
|
+
this.roots.set(event.runId, tracer.startSpan(`workflow ${event.workflow ?? '?'}`, {
|
|
45
|
+
attributes: { 'durable.run_id': event.runId, 'durable.workflow': event.workflow },
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
const root = this.roots.get(event.runId);
|
|
49
|
+
const base = root ? api_1.trace.setSpan(api_1.context.active(), root) : api_1.context.active();
|
|
50
|
+
// A step/signal/sleep event → give it its own child span so it's a distinct node in the
|
|
51
|
+
// trace; run-level events record directly on the root. Either way the active span at record
|
|
52
|
+
// time carries the run's traceId, so all entries group into one trace.
|
|
53
|
+
if (event.name != null && event.seq != null) {
|
|
54
|
+
const step = tracer.startSpan(`step ${event.name}`, {
|
|
55
|
+
attributes: {
|
|
56
|
+
'durable.run_id': event.runId,
|
|
57
|
+
'durable.step.seq': event.seq,
|
|
58
|
+
'durable.step.kind': event.kind,
|
|
59
|
+
},
|
|
60
|
+
}, base);
|
|
61
|
+
api_1.context.with(api_1.trace.setSpan(base, step), record);
|
|
62
|
+
step.end();
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
api_1.context.with(base, record);
|
|
66
|
+
}
|
|
67
|
+
// Close the run's root span when it leaves the running state.
|
|
68
|
+
if (event.type === 'run.completed' || event.type === 'run.suspended') {
|
|
69
|
+
root?.end();
|
|
70
|
+
this.roots.delete(event.runId);
|
|
71
|
+
}
|
|
72
|
+
else if (event.type === 'run.failed') {
|
|
73
|
+
root?.setStatus({ code: api_1.SpanStatusCode.ERROR, message: event.error?.message });
|
|
74
|
+
root?.end();
|
|
75
|
+
this.roots.delete(event.runId);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
tags(event) {
|
|
80
|
+
const tags = ['durable', event.type, `run:${event.runId}`];
|
|
81
|
+
if (event.workflow)
|
|
82
|
+
tags.push(`workflow:${event.workflow}`);
|
|
83
|
+
if (event.kind)
|
|
84
|
+
tags.push(`kind:${event.kind}`);
|
|
85
|
+
if (event.type === 'run.failed')
|
|
86
|
+
tags.push('failed');
|
|
87
|
+
return tags;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
exports.DurableTelescopeWatcher = DurableTelescopeWatcher;
|
|
91
|
+
//# sourceMappingURL=durable-telescope.watcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durable-telescope.watcher.js","sourceRoot":"","sources":["../src/durable-telescope.watcher.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./durable-telescope.watcher"), exports);
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8DAA4C"}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dudousxd/nestjs-durable-telescope",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Telescope watcher for nestjs-durable — workflow runs and steps as Telescope entries",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Davide Carvalho",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/DavideCarvalho/nestjs-durable.git",
|
|
10
|
+
"directory": "packages/telescope"
|
|
11
|
+
},
|
|
12
|
+
"type": "commonjs",
|
|
13
|
+
"main": "dist/index.js",
|
|
14
|
+
"types": "dist/index.d.ts",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"@dudousxd/nestjs-durable-core": ">=0.1.0 <1.0.0",
|
|
20
|
+
"@dudousxd/nestjs-telescope": ">=1.0.0 <2.0.0",
|
|
21
|
+
"@nestjs/core": "^10.0.0 || ^11.0.0",
|
|
22
|
+
"@opentelemetry/api": "^1.0.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@dudousxd/nestjs-telescope": "1.7.0",
|
|
26
|
+
"@nestjs/core": "11.1.26",
|
|
27
|
+
"@opentelemetry/api": "1.9.0",
|
|
28
|
+
"typescript": "5.9.3",
|
|
29
|
+
"@dudousxd/nestjs-durable-core": "^0.1.0"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsc -p tsconfig.json",
|
|
33
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
34
|
+
}
|
|
35
|
+
}
|