@dudousxd/nestjs-durable-telescope 0.4.0 → 0.5.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.js CHANGED
@@ -1,21 +1,727 @@
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);
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+
4
+ // src/durable-telescope.watcher.ts
5
+ import { WorkflowEngine } from "@dudousxd/nestjs-durable-core";
6
+ import { SpanStatusCode, context, trace } from "@opentelemetry/api";
7
+ var DurableTelescopeWatcher = class {
8
+ static {
9
+ __name(this, "DurableTelescopeWatcher");
10
+ }
11
+ type = "durable";
12
+ /** Open root span per run, so step entries nest under it and share its traceId. */
13
+ roots = /* @__PURE__ */ new Map();
14
+ register(ctx) {
15
+ const engine = ctx.moduleRef.get(WorkflowEngine, {
16
+ strict: false
17
+ });
18
+ const tracer = trace.getTracer("@dudousxd/nestjs-durable-telescope");
19
+ engine.subscribe((event) => {
20
+ const record = /* @__PURE__ */ __name(() => ctx.record({
21
+ type: this.type,
22
+ content: {
23
+ event: event.type,
24
+ workflow: event.workflow,
25
+ runId: event.runId,
26
+ seq: event.seq,
27
+ name: event.name,
28
+ kind: event.kind,
29
+ output: event.output,
30
+ error: event.error,
31
+ durationMs: event.durationMs
32
+ },
33
+ tags: this.tags(event)
34
+ }), "record");
35
+ if (event.type === "run.started") {
36
+ this.roots.set(event.runId, tracer.startSpan(`workflow ${event.workflow ?? "?"}`, {
37
+ attributes: {
38
+ "durable.run_id": event.runId,
39
+ "durable.workflow": event.workflow
40
+ }
41
+ }));
42
+ }
43
+ const root = this.roots.get(event.runId);
44
+ const base = root ? trace.setSpan(context.active(), root) : context.active();
45
+ if (event.name != null && event.seq != null) {
46
+ const step = tracer.startSpan(`step ${event.name}`, {
47
+ attributes: {
48
+ "durable.run_id": event.runId,
49
+ "durable.step.seq": event.seq,
50
+ "durable.step.kind": event.kind
51
+ }
52
+ }, base);
53
+ context.with(trace.setSpan(base, step), record);
54
+ step.end();
55
+ } else {
56
+ context.with(base, record);
57
+ }
58
+ if (event.type === "run.completed" || event.type === "run.suspended") {
59
+ root?.end();
60
+ this.roots.delete(event.runId);
61
+ } else if (event.type === "run.failed") {
62
+ const message = event.error?.message;
63
+ root?.setStatus(message !== void 0 ? {
64
+ code: SpanStatusCode.ERROR,
65
+ message
66
+ } : {
67
+ code: SpanStatusCode.ERROR
68
+ });
69
+ root?.end();
70
+ this.roots.delete(event.runId);
71
+ }
72
+ });
73
+ }
74
+ tags(event) {
75
+ const tags = [
76
+ "durable",
77
+ event.type,
78
+ `run:${event.runId}`
79
+ ];
80
+ if (event.workflow) tags.push(`workflow:${event.workflow}`);
81
+ if (event.kind) tags.push(`kind:${event.kind}`);
82
+ if (event.type === "run.failed") tags.push("failed");
83
+ return tags;
84
+ }
85
+ };
86
+
87
+ // src/durable-telescope.extension.ts
88
+ import { defineTelescopeExtension } from "@dudousxd/nestjs-telescope";
89
+
90
+ // src/durable-dashboard.spec-data.ts
91
+ function durableDashboard(opts = {}) {
92
+ const runHref = opts.runHref ?? "/durable/runs/{runId}";
93
+ const windowMs = opts.recentFailuresWindowMs ?? 24 * 60 * 60 * 1e3;
94
+ return {
95
+ id: "durable.workflows",
96
+ label: "Workflows",
97
+ panels: [],
98
+ sections: [
99
+ {
100
+ title: "Health",
101
+ cols: 4,
102
+ panels: [
103
+ {
104
+ kind: "gauge",
105
+ title: "Success rate",
106
+ data: {
107
+ provider: "durable.successRate"
108
+ },
109
+ max: 1,
110
+ format: "percent",
111
+ thresholds: {
112
+ warn: 0.98,
113
+ bad: 0.95,
114
+ direction: "down-bad"
115
+ }
116
+ },
117
+ {
118
+ kind: "stat",
119
+ title: "Duration p95",
120
+ data: {
121
+ provider: "durable.duration",
122
+ query: {
123
+ metric: "p95"
124
+ }
125
+ },
126
+ format: "duration",
127
+ spark: false,
128
+ thresholds: {
129
+ warn: 2e3,
130
+ bad: 5e3,
131
+ direction: "up-bad"
132
+ }
133
+ },
134
+ {
135
+ kind: "stat",
136
+ title: "Backlog",
137
+ data: {
138
+ provider: "durable.state",
139
+ query: {
140
+ status: "pending"
141
+ }
142
+ },
143
+ spark: false,
144
+ thresholds: {
145
+ warn: 50,
146
+ bad: 200,
147
+ direction: "up-bad"
148
+ }
149
+ },
150
+ {
151
+ kind: "stat",
152
+ title: "Throughput",
153
+ data: {
154
+ provider: "durable.throughput"
155
+ },
156
+ format: "rate",
157
+ spark: true
158
+ }
159
+ ]
160
+ },
161
+ {
162
+ title: "Needs attention",
163
+ cols: 3,
164
+ panels: [
165
+ {
166
+ kind: "topN",
167
+ title: "Top failing workflows",
168
+ data: {
169
+ provider: "durable.timeseries",
170
+ query: {
171
+ metric: "topFailures"
172
+ }
173
+ },
174
+ limit: 8
175
+ },
176
+ {
177
+ kind: "table",
178
+ title: "Stuck runs",
179
+ data: {
180
+ provider: "durable.recentFailures",
181
+ query: {
182
+ windowMs
183
+ }
184
+ },
185
+ columns: [
186
+ {
187
+ key: "updatedAt",
188
+ label: "Updated"
189
+ },
190
+ {
191
+ key: "workflow",
192
+ label: "Workflow"
193
+ },
194
+ {
195
+ key: "runId",
196
+ label: "Run",
197
+ link: {
198
+ href: runHref
199
+ }
200
+ },
201
+ {
202
+ key: "error",
203
+ label: "Error"
204
+ }
205
+ ]
206
+ },
207
+ {
208
+ kind: "table",
209
+ title: "Starved worker groups",
210
+ data: {
211
+ provider: "durable.workerHealth"
212
+ },
213
+ columns: [
214
+ {
215
+ key: "group",
216
+ label: "Group"
217
+ },
218
+ {
219
+ key: "queued",
220
+ label: "Queued"
221
+ },
222
+ {
223
+ key: "liveWorkers",
224
+ label: "Workers"
225
+ },
226
+ {
227
+ key: "status",
228
+ label: "Status"
229
+ }
230
+ ]
231
+ }
232
+ ]
233
+ },
234
+ {
235
+ title: "Trends",
236
+ cols: 3,
237
+ panels: [
238
+ {
239
+ kind: "timeseries",
240
+ title: "Runs over time",
241
+ data: {
242
+ provider: "durable.runsOverTime"
243
+ },
244
+ series: [
245
+ "done",
246
+ "failed"
247
+ ],
248
+ style: "stacked"
249
+ },
250
+ {
251
+ kind: "distribution",
252
+ title: "Duration distribution",
253
+ data: {
254
+ provider: "durable.duration"
255
+ },
256
+ markers: [
257
+ "p50",
258
+ "p95",
259
+ "p99"
260
+ ],
261
+ format: "duration"
262
+ },
263
+ {
264
+ kind: "breakdown",
265
+ title: "Runs by state",
266
+ data: {
267
+ provider: "durable.stateBreakdown"
268
+ },
269
+ style: "donut"
270
+ }
271
+ ]
272
+ }
273
+ ]
274
+ };
275
+ }
276
+ __name(durableDashboard, "durableDashboard");
277
+
278
+ // src/durable-data-providers.ts
279
+ import { STATE_STORE, WorkflowEngine as WorkflowEngine2 } from "@dudousxd/nestjs-durable-core";
280
+ import { TELESCOPE_STORAGE } from "@dudousxd/nestjs-telescope";
281
+ function percentile(sorted, p) {
282
+ if (sorted.length === 0) return 0;
283
+ const idx = Math.min(sorted.length - 1, Math.ceil(p / 100 * sorted.length) - 1);
284
+ return sorted[Math.max(0, idx)] ?? 0;
285
+ }
286
+ __name(percentile, "percentile");
287
+ async function fetchEntries(ctx) {
288
+ const storage = ctx.moduleRef.get(TELESCOPE_STORAGE, {
289
+ strict: false
290
+ });
291
+ const page = await storage.get({
292
+ type: "durable",
293
+ limit: 5e3
294
+ });
295
+ return page.data;
296
+ }
297
+ __name(fetchEntries, "fetchEntries");
298
+ function splitWindows(entries, windowMs, now) {
299
+ const start = now - windowMs;
300
+ const prevStart = start - windowMs;
301
+ return {
302
+ current: entries.filter((e) => {
303
+ const t = e.createdAt ? +new Date(e.createdAt) : 0;
304
+ return t > start && t <= now;
305
+ }),
306
+ previous: entries.filter((e) => {
307
+ const t = e.createdAt ? +new Date(e.createdAt) : 0;
308
+ return t > prevStart && t <= start;
309
+ })
310
+ };
311
+ }
312
+ __name(splitWindows, "splitWindows");
313
+ function successRateOf(entries) {
314
+ let completed = 0;
315
+ let failed = 0;
316
+ for (const e of entries) {
317
+ const c = e.content ?? {};
318
+ if (c.event === "run.completed") completed += 1;
319
+ else if (c.event === "run.failed") failed += 1;
320
+ }
321
+ const total = completed + failed;
322
+ return total === 0 ? 1 : completed / total;
323
+ }
324
+ __name(successRateOf, "successRateOf");
325
+ var STATE_CAP = 1e4;
326
+ function durableStateProvider() {
327
+ return {
328
+ name: "durable.state",
329
+ async resolve(query, ctx) {
330
+ const store = ctx.moduleRef.get(STATE_STORE, {
331
+ strict: false
332
+ });
333
+ const status = query?.status ?? "dead";
334
+ const runs = await store.listRuns({
335
+ status,
336
+ limit: STATE_CAP
337
+ });
338
+ return {
339
+ value: runs.length
340
+ };
341
+ }
342
+ };
343
+ }
344
+ __name(durableStateProvider, "durableStateProvider");
345
+ function durableTimeseriesProvider() {
346
+ return {
347
+ name: "durable.timeseries",
348
+ async resolve(query, ctx) {
349
+ const storage = ctx.moduleRef.get(TELESCOPE_STORAGE, {
350
+ strict: false
351
+ });
352
+ const limit = Math.min(5e3, Math.max(100, Number(query?.limit ?? 2e3)));
353
+ const page = await storage.get({
354
+ type: "durable",
355
+ limit
356
+ });
357
+ let completed = 0;
358
+ let failed = 0;
359
+ const failByWorkflow = /* @__PURE__ */ new Map();
360
+ for (const e of page.data) {
361
+ const c = e.content ?? {};
362
+ if (c.event === "run.completed") completed += 1;
363
+ else if (c.event === "run.failed") {
364
+ failed += 1;
365
+ const wf = c.workflow ?? "unknown";
366
+ failByWorkflow.set(wf, (failByWorkflow.get(wf) ?? 0) + 1);
367
+ }
368
+ }
369
+ const total = completed + failed;
370
+ const metric = query?.metric ?? "successRate";
371
+ if (metric === "successRate") return {
372
+ value: total === 0 ? 1 : completed / total
373
+ };
374
+ if (metric === "failed") return {
375
+ value: failed
376
+ };
377
+ if (metric === "total") return {
378
+ value: total
379
+ };
380
+ if (metric === "topFailures") {
381
+ const items = [
382
+ ...failByWorkflow.entries()
383
+ ].map(([label, value]) => ({
384
+ label,
385
+ value
386
+ })).sort((a, b) => b.value - a.value);
387
+ return {
388
+ items
389
+ };
390
+ }
391
+ return {
392
+ value: total
393
+ };
394
+ }
395
+ };
396
+ }
397
+ __name(durableTimeseriesProvider, "durableTimeseriesProvider");
398
+ function durableRecentFailuresProvider() {
399
+ return {
400
+ name: "durable.recentFailures",
401
+ async resolve(query, ctx) {
402
+ const store = ctx.moduleRef.get(STATE_STORE, {
403
+ strict: false
404
+ });
405
+ const limit = Math.min(200, Math.max(10, Number(query?.limit ?? 50)));
406
+ const windowMs = query?.windowMs === void 0 ? 24 * 60 * 60 * 1e3 : Number(query.windowMs);
407
+ const cutoff = windowMs > 0 ? Date.now() - windowMs : 0;
408
+ const [failed, dead] = await Promise.all([
409
+ store.listRuns({
410
+ status: "failed",
411
+ limit
412
+ }),
413
+ store.listRuns({
414
+ status: "dead",
415
+ limit
416
+ })
417
+ ]);
418
+ const rows = [
419
+ ...failed,
420
+ ...dead
421
+ ].filter((r) => +new Date(r.updatedAt) >= cutoff).sort((a, b) => +new Date(b.updatedAt) - +new Date(a.updatedAt)).slice(0, limit).map((r) => ({
422
+ // Compact UTC stamp ("YYYY-MM-DD HH:mm Z"); the generic table renderer
423
+ // prints column values as-is, so we format here.
424
+ updatedAt: `${new Date(r.updatedAt).toISOString().replace("T", " ").slice(0, 16)}Z`,
425
+ workflow: r.workflow,
426
+ runId: r.id,
427
+ error: r.error?.message ?? ""
428
+ }));
429
+ return {
430
+ rows
431
+ };
432
+ }
433
+ };
434
+ }
435
+ __name(durableRecentFailuresProvider, "durableRecentFailuresProvider");
436
+ function durableWorkerHealthProvider() {
437
+ return {
438
+ name: "durable.workerHealth",
439
+ async resolve(query, ctx) {
440
+ const engine = ctx.moduleRef.get(WorkflowEngine2, {
441
+ strict: false
442
+ });
443
+ const health = await engine.workerHealth();
444
+ const isStarved = /* @__PURE__ */ __name((g) => g.depth > 0 && g.liveWorkers.length === 0, "isStarved");
445
+ if (query?.metric === "starvedCount") {
446
+ return {
447
+ value: health.filter(isStarved).length
448
+ };
449
+ }
450
+ const rows = health.slice().sort((a, b) => Number(isStarved(b)) - Number(isStarved(a)) || b.depth - a.depth).map((g) => ({
451
+ group: g.group,
452
+ queued: g.depth,
453
+ liveWorkers: g.liveWorkers.length,
454
+ status: isStarved(g) ? "STARVED" : "ok"
455
+ }));
456
+ return {
457
+ rows
458
+ };
459
+ }
460
+ };
461
+ }
462
+ __name(durableWorkerHealthProvider, "durableWorkerHealthProvider");
463
+ function durableDurationProvider() {
464
+ return {
465
+ name: "durable.duration",
466
+ async resolve(query, ctx) {
467
+ const entries = await fetchEntries(ctx);
468
+ const startedAt = /* @__PURE__ */ new Map();
469
+ for (const e of entries) {
470
+ const c = e.content ?? {};
471
+ if (c.event === "run.started" && c.runId && e.createdAt) {
472
+ startedAt.set(c.runId, +new Date(e.createdAt));
473
+ }
474
+ }
475
+ const durs = [];
476
+ for (const e of entries) {
477
+ const c = e.content ?? {};
478
+ if (c.event === "run.completed" || c.event === "run.failed") {
479
+ if (typeof c.durationMs === "number") {
480
+ durs.push(c.durationMs);
481
+ } else if (c.runId) {
482
+ const start = startedAt.get(c.runId);
483
+ const end = e.createdAt ? +new Date(e.createdAt) : void 0;
484
+ if (start !== void 0 && end !== void 0 && end >= start) {
485
+ durs.push(end - start);
486
+ }
487
+ }
488
+ }
489
+ }
490
+ durs.sort((a, b) => a - b);
491
+ const p50 = percentile(durs, 50);
492
+ const p95 = percentile(durs, 95);
493
+ const p99 = percentile(durs, 99);
494
+ const metric = query?.metric;
495
+ if (metric === "p50") return {
496
+ value: p50
497
+ };
498
+ if (metric === "p95") return {
499
+ value: p95
500
+ };
501
+ if (metric === "p99") return {
502
+ value: p99
503
+ };
504
+ const max = durs.at(-1) ?? 0;
505
+ const bucketCount = 8;
506
+ const size = Math.max(1, Math.ceil((max + 1) / bucketCount));
507
+ const buckets = Array.from({
508
+ length: bucketCount
509
+ }, (_, i) => ({
510
+ label: `${Math.round(i * size / 100) / 10}s`,
511
+ count: 0
512
+ }));
513
+ for (const d of durs) {
514
+ const bi = Math.min(bucketCount - 1, Math.floor(d / size));
515
+ const bucket = buckets[bi];
516
+ if (bucket) bucket.count += 1;
517
+ }
518
+ return {
519
+ buckets,
520
+ p50,
521
+ p95,
522
+ p99
523
+ };
524
+ }
525
+ };
526
+ }
527
+ __name(durableDurationProvider, "durableDurationProvider");
528
+ function durableRunsOverTimeProvider() {
529
+ return {
530
+ name: "durable.runsOverTime",
531
+ async resolve(query, ctx) {
532
+ const entries = await fetchEntries(ctx);
533
+ const n = Number(query?.buckets ?? 24);
534
+ const now = Date.now();
535
+ let minT = now;
536
+ for (const e of entries) {
537
+ if (e.createdAt) {
538
+ const t = +new Date(e.createdAt);
539
+ if (t < minT) minT = t;
540
+ }
541
+ }
542
+ const span = Math.max(now - minT, 1);
543
+ const bucketSize = span / n;
544
+ const rows = Array.from({
545
+ length: n
546
+ }, (_, i) => {
547
+ const bucketStart = new Date(minT + i * bucketSize);
548
+ const label = bucketStart.toISOString().slice(11, 16);
549
+ return {
550
+ label,
551
+ done: 0,
552
+ failed: 0
553
+ };
554
+ });
555
+ for (const e of entries) {
556
+ const c = e.content ?? {};
557
+ if (c.event !== "run.completed" && c.event !== "run.failed") continue;
558
+ const t = e.createdAt ? +new Date(e.createdAt) : 0;
559
+ const idx = Math.min(n - 1, Math.floor((t - minT) / bucketSize));
560
+ const row = rows[idx];
561
+ if (row) {
562
+ if (c.event === "run.completed") row.done += 1;
563
+ else row.failed += 1;
564
+ }
565
+ }
566
+ return {
567
+ rows
568
+ };
569
+ }
570
+ };
571
+ }
572
+ __name(durableRunsOverTimeProvider, "durableRunsOverTimeProvider");
573
+ function durableSuccessRateProvider() {
574
+ return {
575
+ name: "durable.successRate",
576
+ async resolve(query, ctx) {
577
+ const entries = await fetchEntries(ctx);
578
+ const windowMs = Number(query?.windowMs ?? 24 * 60 * 60 * 1e3);
579
+ const now = Date.now();
580
+ const { current, previous } = splitWindows(entries, windowMs, now);
581
+ const value = successRateOf(current);
582
+ const prevRate = successRateOf(previous);
583
+ const delta = previous.length > 0 ? value - prevRate : void 0;
584
+ const sparkBuckets = 8;
585
+ const bucketSize = windowMs / sparkBuckets;
586
+ const sparkStart = now - windowMs;
587
+ const spark = Array.from({
588
+ length: sparkBuckets
589
+ }, (_, i) => {
590
+ const bStart = sparkStart + i * bucketSize;
591
+ const bEnd = bStart + bucketSize;
592
+ const bEntries = current.filter((e) => {
593
+ const t = e.createdAt ? +new Date(e.createdAt) : 0;
594
+ return t > bStart && t <= bEnd;
595
+ });
596
+ return successRateOf(bEntries);
597
+ });
598
+ return {
599
+ value,
600
+ delta,
601
+ spark
602
+ };
603
+ }
604
+ };
605
+ }
606
+ __name(durableSuccessRateProvider, "durableSuccessRateProvider");
607
+ function durableThroughputProvider() {
608
+ return {
609
+ name: "durable.throughput",
610
+ async resolve(query, ctx) {
611
+ const entries = await fetchEntries(ctx);
612
+ const windowMs = Number(query?.windowMs ?? 24 * 60 * 60 * 1e3);
613
+ const now = Date.now();
614
+ const { current, previous } = splitWindows(entries, windowMs, now);
615
+ const countCompleted = /* @__PURE__ */ __name((es) => es.filter((e) => (e.content ?? {}).event === "run.completed").length, "countCompleted");
616
+ const windowHours = windowMs / (60 * 60 * 1e3);
617
+ const value = countCompleted(current) / windowHours;
618
+ const prevValue = countCompleted(previous) / windowHours;
619
+ const delta = previous.length > 0 ? value - prevValue : void 0;
620
+ const sparkBuckets = 8;
621
+ const bucketSize = windowMs / sparkBuckets;
622
+ const bucketHours = bucketSize / (60 * 60 * 1e3);
623
+ const sparkStart = now - windowMs;
624
+ const spark = Array.from({
625
+ length: sparkBuckets
626
+ }, (_, i) => {
627
+ const bStart = sparkStart + i * bucketSize;
628
+ const bEnd = bStart + bucketSize;
629
+ const bEntries = current.filter((e) => {
630
+ const t = e.createdAt ? +new Date(e.createdAt) : 0;
631
+ return t > bStart && t <= bEnd;
632
+ });
633
+ return countCompleted(bEntries) / bucketHours;
634
+ });
635
+ return {
636
+ value,
637
+ delta,
638
+ spark
639
+ };
640
+ }
641
+ };
642
+ }
643
+ __name(durableThroughputProvider, "durableThroughputProvider");
644
+ var STATE_BREAKDOWN_PALETTE = [
645
+ "#34d399",
646
+ "#fbbf24",
647
+ "#f87171",
648
+ "#38bdf8",
649
+ "#a78bfa"
650
+ ];
651
+ var STATE_BREAKDOWN_STATUSES = [
652
+ "running",
653
+ "pending",
654
+ "completed",
655
+ "failed",
656
+ "dead"
657
+ ];
658
+ function durableStateBreakdownProvider() {
659
+ return {
660
+ name: "durable.stateBreakdown",
661
+ async resolve(_query, ctx) {
662
+ const store = ctx.moduleRef.get(STATE_STORE, {
663
+ strict: false
664
+ });
665
+ const counts = await Promise.all(STATE_BREAKDOWN_STATUSES.map((status) => store.listRuns({
666
+ status,
667
+ limit: STATE_CAP
668
+ }).then((runs) => runs.length)));
669
+ const segments = STATE_BREAKDOWN_STATUSES.map((label, i) => ({
670
+ label,
671
+ value: counts[i],
672
+ color: STATE_BREAKDOWN_PALETTE[i]
673
+ }));
674
+ return {
675
+ segments
676
+ };
677
+ }
678
+ };
679
+ }
680
+ __name(durableStateBreakdownProvider, "durableStateBreakdownProvider");
681
+
682
+ // src/durable-telescope.extension.ts
683
+ function durableTelescopeExtension(opts = {}) {
684
+ return defineTelescopeExtension({
685
+ name: "durable",
686
+ watchers: /* @__PURE__ */ __name(() => [
687
+ new DurableTelescopeWatcher()
688
+ ], "watchers"),
689
+ entryTypes: /* @__PURE__ */ __name(() => [
690
+ {
691
+ id: "durable",
692
+ label: "Workflows",
693
+ dot: "bg-amber-400"
694
+ }
695
+ ], "entryTypes"),
696
+ dashboards: /* @__PURE__ */ __name(() => [
697
+ durableDashboard(opts)
698
+ ], "dashboards"),
699
+ dataProviders: /* @__PURE__ */ __name(() => [
700
+ durableStateProvider(),
701
+ durableTimeseriesProvider(),
702
+ durableRecentFailuresProvider(),
703
+ durableWorkerHealthProvider(),
704
+ durableDurationProvider(),
705
+ durableRunsOverTimeProvider(),
706
+ durableSuccessRateProvider(),
707
+ durableThroughputProvider(),
708
+ durableStateBreakdownProvider()
709
+ ], "dataProviders")
710
+ });
711
+ }
712
+ __name(durableTelescopeExtension, "durableTelescopeExtension");
713
+ export {
714
+ DurableTelescopeWatcher,
715
+ durableDashboard,
716
+ durableDurationProvider,
717
+ durableRecentFailuresProvider,
718
+ durableRunsOverTimeProvider,
719
+ durableStateBreakdownProvider,
720
+ durableStateProvider,
721
+ durableSuccessRateProvider,
722
+ durableTelescopeExtension,
723
+ durableThroughputProvider,
724
+ durableTimeseriesProvider,
725
+ durableWorkerHealthProvider
15
726
  };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./durable-telescope.watcher"), exports);
18
- __exportStar(require("./durable-telescope.extension"), exports);
19
- __exportStar(require("./durable-data-providers"), exports);
20
- __exportStar(require("./durable-dashboard.spec-data"), exports);
21
727
  //# sourceMappingURL=index.js.map