@juice-js/observability 1.0.1-alpha.15 → 1.0.1-alpha.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +2 -0
  2. package/fesm2022/{juice-js-observability-alert.page-TKwqJT2d.mjs → juice-js-observability-alert.page-nEy5Gc6j.mjs} +2 -2
  3. package/fesm2022/{juice-js-observability-alert.page-TKwqJT2d.mjs.map → juice-js-observability-alert.page-nEy5Gc6j.mjs.map} +1 -1
  4. package/fesm2022/{juice-js-observability-alerts.page-B-2uS9wr.mjs → juice-js-observability-alerts.page-DUXXBanH.mjs} +2 -2
  5. package/fesm2022/{juice-js-observability-alerts.page-B-2uS9wr.mjs.map → juice-js-observability-alerts.page-DUXXBanH.mjs.map} +1 -1
  6. package/fesm2022/{juice-js-observability-logs.page-CZNbTl2Q.mjs → juice-js-observability-logs.page-i76xbJLH.mjs} +2 -2
  7. package/fesm2022/{juice-js-observability-logs.page-CZNbTl2Q.mjs.map → juice-js-observability-logs.page-i76xbJLH.mjs.map} +1 -1
  8. package/fesm2022/{juice-js-observability-metrics.page-DoVED9MT.mjs → juice-js-observability-metrics.page-Cq5S0yGJ.mjs} +2 -2
  9. package/fesm2022/{juice-js-observability-metrics.page-DoVED9MT.mjs.map → juice-js-observability-metrics.page-Cq5S0yGJ.mjs.map} +1 -1
  10. package/fesm2022/{juice-js-observability-overview.page-Cod7-cIy.mjs → juice-js-observability-overview.page-DXZl_fUh.mjs} +2 -2
  11. package/fesm2022/{juice-js-observability-overview.page-Cod7-cIy.mjs.map → juice-js-observability-overview.page-DXZl_fUh.mjs.map} +1 -1
  12. package/fesm2022/{juice-js-observability-resource.page-C8RhUipF.mjs → juice-js-observability-resource.page-CauDE6kK.mjs} +2 -2
  13. package/fesm2022/{juice-js-observability-resource.page-C8RhUipF.mjs.map → juice-js-observability-resource.page-CauDE6kK.mjs.map} +1 -1
  14. package/fesm2022/{juice-js-observability-resources.page-KadGxEAh.mjs → juice-js-observability-resources.page-CukW8vVc.mjs} +2 -2
  15. package/fesm2022/{juice-js-observability-resources.page-KadGxEAh.mjs.map → juice-js-observability-resources.page-CukW8vVc.mjs.map} +1 -1
  16. package/fesm2022/{juice-js-observability-rules.page-DKWvNpu9.mjs → juice-js-observability-rules.page-Crb07uWm.mjs} +2 -2
  17. package/fesm2022/{juice-js-observability-rules.page-DKWvNpu9.mjs.map → juice-js-observability-rules.page-Crb07uWm.mjs.map} +1 -1
  18. package/fesm2022/{juice-js-observability-service.page-_yK0kVYS.mjs → juice-js-observability-service.page-Dt8bN2Ry.mjs} +2 -2
  19. package/fesm2022/{juice-js-observability-service.page-_yK0kVYS.mjs.map → juice-js-observability-service.page-Dt8bN2Ry.mjs.map} +1 -1
  20. package/fesm2022/{juice-js-observability-services.page-BtG8zyiI.mjs → juice-js-observability-services.page-B1huLe_a.mjs} +2 -2
  21. package/fesm2022/{juice-js-observability-services.page-BtG8zyiI.mjs.map → juice-js-observability-services.page-B1huLe_a.mjs.map} +1 -1
  22. package/fesm2022/{juice-js-observability-telemetry-B5jMJYfn.mjs → juice-js-observability-telemetry-BftWSOaQ.mjs} +235 -8
  23. package/fesm2022/juice-js-observability-telemetry-BftWSOaQ.mjs.map +1 -0
  24. package/fesm2022/{juice-js-observability-topology.page-B7aXWOYV.mjs → juice-js-observability-topology.page-aMWEXyMB.mjs} +2 -2
  25. package/fesm2022/{juice-js-observability-topology.page-B7aXWOYV.mjs.map → juice-js-observability-topology.page-aMWEXyMB.mjs.map} +1 -1
  26. package/fesm2022/{juice-js-observability-trace.page-CkLNNnKf.mjs → juice-js-observability-trace.page-DUCWnZL5.mjs} +126 -3
  27. package/fesm2022/juice-js-observability-trace.page-DUCWnZL5.mjs.map +1 -0
  28. package/fesm2022/{juice-js-observability-traces.page-DgvNixIc.mjs → juice-js-observability-traces.page-DXSDdeTH.mjs} +2 -2
  29. package/fesm2022/{juice-js-observability-traces.page-DgvNixIc.mjs.map → juice-js-observability-traces.page-DXSDdeTH.mjs.map} +1 -1
  30. package/fesm2022/juice-js-observability.mjs +13 -13
  31. package/package.json +1 -1
  32. package/styles/_observability.scss +2 -0
  33. package/types/juice-js-observability.d.ts +1 -0
  34. package/fesm2022/juice-js-observability-telemetry-B5jMJYfn.mjs.map +0 -1
  35. package/fesm2022/juice-js-observability-trace.page-CkLNNnKf.mjs.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import { ApiService, ContextService, LinkPipe } from "./juice-js-observability.mjs";
2
- import { _ as ReasonPipe, a as problemText, l as ContextBar, m as AgoPipe, s as screenPages, u as HealthBadge, x as apiResource } from "./juice-js-observability-telemetry-B5jMJYfn.mjs";
2
+ import { S as apiResource, c as screenPages, d as HealthBadge, h as AgoPipe, o as problemText, u as ContextBar, v as ReasonPipe } from "./juice-js-observability-telemetry-BftWSOaQ.mjs";
3
3
  import * as i0 from "@angular/core";
4
4
  import { ChangeDetectionStrategy, Component, computed, inject, input, signal } from "@angular/core";
5
5
  import { forkJoin, map } from "rxjs";
@@ -248,4 +248,4 @@ i0.ɵɵngDeclareClassMetadata({
248
248
  });
249
249
  export { ServicesPage };
250
250
 
251
- //# sourceMappingURL=juice-js-observability-services.page-BtG8zyiI.mjs.map
251
+ //# sourceMappingURL=juice-js-observability-services.page-B1huLe_a.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"juice-js-observability-services.page-BtG8zyiI.mjs","names":[],"sources":["../../../../projects/juice-js/observability/src/lib/pages/services.page.ts"],"sourcesContent":["import { LinkPipe } from '../core/options';\nimport { ChangeDetectionStrategy, Component, computed, inject, input, signal } from '@angular/core';\nimport { apiResource } from '../shared/resource';\nimport { MatPaginatorModule } from '@angular/material/paginator';\nimport { MatProgressBarModule } from '@angular/material/progress-bar';\nimport { RouterLink } from '@angular/router';\nimport { SearchablePage } from '@juice-js/layout';\nimport { forkJoin, map } from 'rxjs';\nimport { ApiService } from '../core/api.service';\nimport { ContextService } from '../core/context.service';\nimport { Health, HealthState } from '../core/models';\nimport { AgoPipe, ReasonPipe } from '../shared/format';\nimport { ContextBar, HealthBadge } from '../shared/ui';\nimport { problemText } from '../shared/telemetry';\nimport { screenPages } from '../shared/paging';\n\nconst SEVERITY: HealthState[] = ['Critical', 'Unhealthy', 'Degraded', 'Offline', 'Unknown', 'Healthy'];\n\n/**\n * The service catalog (Console requirements §8): one row per service, environment-independent, with its health in\n * each environment. The toolbar search box filters it.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [LinkPipe, RouterLink, MatPaginatorModule, MatProgressBarModule, ContextBar, HealthBadge, AgoPipe],\n template: `\n <jc-context-bar><h1>Services</h1>\n @if (state()) { <span class=\"jc-chip\">{{ state() }} <a [routerLink]=\"['services'] | jcLink\" [queryParams]=\"ctx.keep()\">×</a></span> }\n </jc-context-bar>\n @if (data.isLoading()) { <mat-progress-bar mode=\"indeterminate\" /> }\n @if (data.error()) { <p class=\"jc-error\">{{ error() }}</p> }\n @if (capped()) { <p class=\"jc-notice\">Showing the first 5,000 only. Narrow the list with the search box or a filter.</p> }\n <table class=\"jc-table\">\n <thead><tr><th>Service</th><th>Health by environment</th><th>Why</th><th>Last seen</th></tr></thead>\n <tbody>\n @for (s of pages.visible(); track s.id) {\n <tr>\n <td><a [routerLink]=\"['services', s.id] | jcLink\" [queryParams]=\"ctx.keep()\">{{ s.key }}</a></td>\n <td class=\"jc-envs\">\n @for (h of s.health; track h.environment) {\n <span><span class=\"jc-muted jc-small\">{{ h.environment ?? '—' }}</span> <jc-health [state]=\"h.state\" [stale]=\"h.stale\" /></span>\n } @empty { <jc-health [state]=\"null\" /> }\n </td>\n <td class=\"jc-small\">{{ s.worst?.reasons?.slice(0, 2)?.map(reason)?.join(' · ') }}</td>\n <td>{{ s.lastSeen | ago }}</td>\n </tr>\n } @empty { <tr><td colspan=\"4\" class=\"jc-muted\">No services{{ filter() ? ' match \"' + filter() + '\"' : '' }}.</td></tr> }\n </tbody>\n </table>\n @if (pages.needed()) {\n <mat-paginator [length]=\"rows().length\" [pageSize]=\"pages.size()\" [pageIndex]=\"pages.index()\" [pageSizeOptions]=\"pages.sizes\"\n (page)=\"pages.change($event)\" aria-label=\"Pages\" />\n }`,\n})\nexport class ServicesPage implements SearchablePage {\n protected readonly ctx = inject(ContextService);\n private readonly api = inject(ApiService);\n readonly state = input<string>();\n protected readonly filter = signal('');\n private readonly reasonPipe = new ReasonPipe();\n protected readonly reason = (r: string) => this.reasonPipe.transform(r);\n\n protected readonly data = apiResource({\n stream: () => forkJoin({\n services: this.api.resources('service'),\n health: this.api.health({ subjectType: 'service' }),\n }).pipe(map(({ services, health }) => ({\n services: services.items, health: health.items, capped: services.nextCursor !== null || health.nextCursor !== null,\n }))),\n });\n protected readonly capped = computed(() => this.data.value()?.capped ?? false);\n protected readonly error = computed(() => problemText(this.data.error()));\n\n protected readonly rows = computed(() => {\n const data = this.data.value();\n if (!data) return [];\n const env = this.ctx.environment();\n const byService = new Map<string, Health[]>();\n for (const h of data.health) byService.set(h.subjectId, [...(byService.get(h.subjectId) ?? []), h]);\n const q = this.filter().toLowerCase();\n return data.services\n .map(s => {\n const health = (byService.get(s.id) ?? []).filter(h => !env || h.environment === env);\n const worst = [...health].sort((a, b) => SEVERITY.indexOf(a.state) - SEVERITY.indexOf(b.state))[0];\n return { ...s, health, worst };\n })\n // With an environment chosen, only the services seen in it.\n .filter(s => !env || s.health.length > 0)\n .filter(s => !q || s.key.toLowerCase().includes(q))\n .filter(s => !this.state() || s.health.some(h => h.state === this.state()))\n .sort((a, b) => SEVERITY.indexOf(a.worst?.state ?? 'Unknown') - SEVERITY.indexOf(b.worst?.state ?? 'Unknown') || a.key.localeCompare(b.key));\n });\n\n protected readonly pages = screenPages(this.rows);\n\n onSearch(query: string) { this.filter.set(query); }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"juice-js-observability-services.page-B1huLe_a.mjs","names":[],"sources":["../../../../projects/juice-js/observability/src/lib/pages/services.page.ts"],"sourcesContent":["import { LinkPipe } from '../core/options';\nimport { ChangeDetectionStrategy, Component, computed, inject, input, signal } from '@angular/core';\nimport { apiResource } from '../shared/resource';\nimport { MatPaginatorModule } from '@angular/material/paginator';\nimport { MatProgressBarModule } from '@angular/material/progress-bar';\nimport { RouterLink } from '@angular/router';\nimport { SearchablePage } from '@juice-js/layout';\nimport { forkJoin, map } from 'rxjs';\nimport { ApiService } from '../core/api.service';\nimport { ContextService } from '../core/context.service';\nimport { Health, HealthState } from '../core/models';\nimport { AgoPipe, ReasonPipe } from '../shared/format';\nimport { ContextBar, HealthBadge } from '../shared/ui';\nimport { problemText } from '../shared/telemetry';\nimport { screenPages } from '../shared/paging';\n\nconst SEVERITY: HealthState[] = ['Critical', 'Unhealthy', 'Degraded', 'Offline', 'Unknown', 'Healthy'];\n\n/**\n * The service catalog (Console requirements §8): one row per service, environment-independent, with its health in\n * each environment. The toolbar search box filters it.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [LinkPipe, RouterLink, MatPaginatorModule, MatProgressBarModule, ContextBar, HealthBadge, AgoPipe],\n template: `\n <jc-context-bar><h1>Services</h1>\n @if (state()) { <span class=\"jc-chip\">{{ state() }} <a [routerLink]=\"['services'] | jcLink\" [queryParams]=\"ctx.keep()\">×</a></span> }\n </jc-context-bar>\n @if (data.isLoading()) { <mat-progress-bar mode=\"indeterminate\" /> }\n @if (data.error()) { <p class=\"jc-error\">{{ error() }}</p> }\n @if (capped()) { <p class=\"jc-notice\">Showing the first 5,000 only. Narrow the list with the search box or a filter.</p> }\n <table class=\"jc-table\">\n <thead><tr><th>Service</th><th>Health by environment</th><th>Why</th><th>Last seen</th></tr></thead>\n <tbody>\n @for (s of pages.visible(); track s.id) {\n <tr>\n <td><a [routerLink]=\"['services', s.id] | jcLink\" [queryParams]=\"ctx.keep()\">{{ s.key }}</a></td>\n <td class=\"jc-envs\">\n @for (h of s.health; track h.environment) {\n <span><span class=\"jc-muted jc-small\">{{ h.environment ?? '—' }}</span> <jc-health [state]=\"h.state\" [stale]=\"h.stale\" /></span>\n } @empty { <jc-health [state]=\"null\" /> }\n </td>\n <td class=\"jc-small\">{{ s.worst?.reasons?.slice(0, 2)?.map(reason)?.join(' · ') }}</td>\n <td>{{ s.lastSeen | ago }}</td>\n </tr>\n } @empty { <tr><td colspan=\"4\" class=\"jc-muted\">No services{{ filter() ? ' match \"' + filter() + '\"' : '' }}.</td></tr> }\n </tbody>\n </table>\n @if (pages.needed()) {\n <mat-paginator [length]=\"rows().length\" [pageSize]=\"pages.size()\" [pageIndex]=\"pages.index()\" [pageSizeOptions]=\"pages.sizes\"\n (page)=\"pages.change($event)\" aria-label=\"Pages\" />\n }`,\n})\nexport class ServicesPage implements SearchablePage {\n protected readonly ctx = inject(ContextService);\n private readonly api = inject(ApiService);\n readonly state = input<string>();\n protected readonly filter = signal('');\n private readonly reasonPipe = new ReasonPipe();\n protected readonly reason = (r: string) => this.reasonPipe.transform(r);\n\n protected readonly data = apiResource({\n stream: () => forkJoin({\n services: this.api.resources('service'),\n health: this.api.health({ subjectType: 'service' }),\n }).pipe(map(({ services, health }) => ({\n services: services.items, health: health.items, capped: services.nextCursor !== null || health.nextCursor !== null,\n }))),\n });\n protected readonly capped = computed(() => this.data.value()?.capped ?? false);\n protected readonly error = computed(() => problemText(this.data.error()));\n\n protected readonly rows = computed(() => {\n const data = this.data.value();\n if (!data) return [];\n const env = this.ctx.environment();\n const byService = new Map<string, Health[]>();\n for (const h of data.health) byService.set(h.subjectId, [...(byService.get(h.subjectId) ?? []), h]);\n const q = this.filter().toLowerCase();\n return data.services\n .map(s => {\n const health = (byService.get(s.id) ?? []).filter(h => !env || h.environment === env);\n const worst = [...health].sort((a, b) => SEVERITY.indexOf(a.state) - SEVERITY.indexOf(b.state))[0];\n return { ...s, health, worst };\n })\n // With an environment chosen, only the services seen in it.\n .filter(s => !env || s.health.length > 0)\n .filter(s => !q || s.key.toLowerCase().includes(q))\n .filter(s => !this.state() || s.health.some(h => h.state === this.state()))\n .sort((a, b) => SEVERITY.indexOf(a.worst?.state ?? 'Unknown') - SEVERITY.indexOf(b.worst?.state ?? 'Unknown') || a.key.localeCompare(b.key));\n });\n\n protected readonly pages = screenPages(this.rows);\n\n onSearch(query: string) { this.filter.set(query); }\n}\n"],"mappings":"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"}
@@ -674,6 +674,7 @@ var Chart = class Chart {
674
674
  title = input("", ...ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []);
675
675
  series = input([], ...ngDevMode ? [{ debugName: "series" }] : /* istanbul ignore next */ []);
676
676
  format = input((v) => String(Math.round(v * 100) / 100), ...ngDevMode ? [{ debugName: "format" }] : /* istanbul ignore next */ []);
677
+ marks = input([], ...ngDevMode ? [{ debugName: "marks" }] : /* istanbul ignore next */ []);
677
678
  host = viewChild.required("host", ...ngDevMode ? [{ debugName: "host" }] : /* istanbul ignore next */ []);
678
679
  empty = computed(() => this.series().every((s) => s.points.every((p) => p.value === null)), ...ngDevMode ? [{ debugName: "empty" }] : /* istanbul ignore next */ []);
679
680
  chart;
@@ -692,6 +693,7 @@ var Chart = class Chart {
692
693
  components.GridComponent,
693
694
  components.TooltipComponent,
694
695
  components.LegendComponent,
696
+ components.MarkLineComponent,
695
697
  renderers.SVGRenderer
696
698
  ]);
697
699
  this.chart = echarts.init(this.host().nativeElement, void 0, { renderer: "svg" });
@@ -702,6 +704,7 @@ var Chart = class Chart {
702
704
  });
703
705
  effect(() => {
704
706
  this.series();
707
+ this.marks();
705
708
  this.render();
706
709
  });
707
710
  }
@@ -734,7 +737,10 @@ var Chart = class Chart {
734
737
  } : void 0,
735
738
  xAxis: {
736
739
  type: "time",
737
- axisLabel: { color: muted },
740
+ axisLabel: {
741
+ color: muted,
742
+ hideOverlap: true
743
+ },
738
744
  axisLine: { lineStyle: { color: border } }
739
745
  },
740
746
  yAxis: {
@@ -745,12 +751,22 @@ var Chart = class Chart {
745
751
  },
746
752
  splitLine: { lineStyle: { color: border } }
747
753
  },
748
- series: this.series().map((s) => ({
754
+ series: this.series().map((s, i) => ({
749
755
  name: s.name,
750
756
  type: "line",
751
757
  showSymbol: false,
752
758
  connectNulls: false,
753
- data: s.points.map((p) => [p.at, p.value])
759
+ data: s.points.map((p) => [p.at, p.value]),
760
+ ...i === 0 && this.marks().length ? { markLine: {
761
+ silent: true,
762
+ symbol: "none",
763
+ label: { show: false },
764
+ lineStyle: {
765
+ color: muted,
766
+ type: "dashed"
767
+ },
768
+ data: this.marks().map((at) => ({ xAxis: at }))
769
+ } } : {}
754
770
  }))
755
771
  };
756
772
  this.chart.setOption(option, true);
@@ -795,6 +811,13 @@ var Chart = class Chart {
795
811
  isSignal: true,
796
812
  isRequired: false,
797
813
  transformFunction: null
814
+ },
815
+ marks: {
816
+ classPropertyName: "marks",
817
+ publicName: "marks",
818
+ isSignal: true,
819
+ isRequired: false,
820
+ transformFunction: null
798
821
  }
799
822
  },
800
823
  viewQueries: [{
@@ -853,6 +876,14 @@ i0.ɵɵngDeclareClassMetadata({
853
876
  required: false
854
877
  }]
855
878
  }],
879
+ marks: [{
880
+ type: i0.Input,
881
+ args: [{
882
+ isSignal: true,
883
+ alias: "marks",
884
+ required: false
885
+ }]
886
+ }],
856
887
  host: [{
857
888
  type: i0.ViewChild,
858
889
  args: ["host", { isSignal: true }]
@@ -1409,7 +1440,7 @@ var MetricExplorer = class MetricExplorer {
1409
1440
  names = computed(() => this.metrics.value()?.items ?? [], ...ngDevMode ? [{ debugName: "names" }] : /* istanbul ignore next */ []);
1410
1441
  selected = linkedSignal(() => {
1411
1442
  const names = this.names();
1412
- return names.find((m) => m.name === this.initial())?.name ?? names[0]?.name ?? null;
1443
+ return names.find((m) => m.name === this.initial())?.name ?? names.find((m) => !/^(dotnet|process|system)./.test(m.name))?.name ?? names[0]?.name ?? null;
1413
1444
  }, ...ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []);
1414
1445
  series = apiResource({
1415
1446
  params: () => this.selected() ? {
@@ -1592,7 +1623,8 @@ var MetricExplorer = class MetricExplorer {
1592
1623
  inputs: [
1593
1624
  "title",
1594
1625
  "series",
1595
- "format"
1626
+ "format",
1627
+ "marks"
1596
1628
  ]
1597
1629
  }
1598
1630
  ],
@@ -1653,6 +1685,200 @@ i0.ɵɵngDeclareClassMetadata({
1653
1685
  }]
1654
1686
  }
1655
1687
  });
1688
+ var InstanceMetric = class InstanceMetric {
1689
+ api = inject(ApiService);
1690
+ title = input.required(...ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []);
1691
+ name = input.required(...ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []);
1692
+ instanceId = input.required(...ngDevMode ? [{ debugName: "instanceId" }] : /* istanbul ignore next */ []);
1693
+ from = input.required(...ngDevMode ? [{ debugName: "from" }] : /* istanbul ignore next */ []);
1694
+ to = input.required(...ngDevMode ? [{ debugName: "to" }] : /* istanbul ignore next */ []);
1695
+ marks = input([], ...ngDevMode ? [{ debugName: "marks" }] : /* istanbul ignore next */ []);
1696
+ format = input((v) => String(Math.round(v * 100) / 100), ...ngDevMode ? [{ debugName: "format" }] : /* istanbul ignore next */ []);
1697
+ level = input(false, ...ngDevMode ? [{ debugName: "level" }] : /* istanbul ignore next */ []);
1698
+ series = apiResource({
1699
+ params: () => ({
1700
+ name: this.name(),
1701
+ instanceId: this.instanceId(),
1702
+ from: this.from(),
1703
+ to: this.to(),
1704
+ ...this.level() ? { level: true } : {}
1705
+ }),
1706
+ stream: ({ params }) => this.api.series(params)
1707
+ });
1708
+ points = computed(() => {
1709
+ const s = this.series.value();
1710
+ return s ? withGaps(s.points, this.from(), this.to(), s.stepSeconds) : [];
1711
+ }, ...ngDevMode ? [{ debugName: "points" }] : /* istanbul ignore next */ []);
1712
+ static ɵfac = i0.ɵɵngDeclareFactory({
1713
+ minVersion: "12.0.0",
1714
+ version: "22.2.4",
1715
+ ngImport: i0,
1716
+ type: InstanceMetric,
1717
+ deps: [],
1718
+ target: i0.ɵɵFactoryTarget.Component
1719
+ });
1720
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1721
+ minVersion: "17.1.0",
1722
+ version: "22.2.4",
1723
+ type: InstanceMetric,
1724
+ isStandalone: true,
1725
+ selector: "jc-instance-metric",
1726
+ inputs: {
1727
+ title: {
1728
+ classPropertyName: "title",
1729
+ publicName: "title",
1730
+ isSignal: true,
1731
+ isRequired: true,
1732
+ transformFunction: null
1733
+ },
1734
+ name: {
1735
+ classPropertyName: "name",
1736
+ publicName: "name",
1737
+ isSignal: true,
1738
+ isRequired: true,
1739
+ transformFunction: null
1740
+ },
1741
+ instanceId: {
1742
+ classPropertyName: "instanceId",
1743
+ publicName: "instanceId",
1744
+ isSignal: true,
1745
+ isRequired: true,
1746
+ transformFunction: null
1747
+ },
1748
+ from: {
1749
+ classPropertyName: "from",
1750
+ publicName: "from",
1751
+ isSignal: true,
1752
+ isRequired: true,
1753
+ transformFunction: null
1754
+ },
1755
+ to: {
1756
+ classPropertyName: "to",
1757
+ publicName: "to",
1758
+ isSignal: true,
1759
+ isRequired: true,
1760
+ transformFunction: null
1761
+ },
1762
+ marks: {
1763
+ classPropertyName: "marks",
1764
+ publicName: "marks",
1765
+ isSignal: true,
1766
+ isRequired: false,
1767
+ transformFunction: null
1768
+ },
1769
+ format: {
1770
+ classPropertyName: "format",
1771
+ publicName: "format",
1772
+ isSignal: true,
1773
+ isRequired: false,
1774
+ transformFunction: null
1775
+ },
1776
+ level: {
1777
+ classPropertyName: "level",
1778
+ publicName: "level",
1779
+ isSignal: true,
1780
+ isRequired: false,
1781
+ transformFunction: null
1782
+ }
1783
+ },
1784
+ ngImport: i0,
1785
+ template: `<jc-chart [title]="title()" [series]="[{ name: name(), points: points() }]" [format]="format()" [marks]="marks()" />`,
1786
+ isInline: true,
1787
+ dependencies: [{
1788
+ kind: "component",
1789
+ type: Chart,
1790
+ selector: "jc-chart",
1791
+ inputs: [
1792
+ "title",
1793
+ "series",
1794
+ "format",
1795
+ "marks"
1796
+ ]
1797
+ }],
1798
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
1799
+ });
1800
+ };
1801
+ i0.ɵɵngDeclareClassMetadata({
1802
+ minVersion: "12.0.0",
1803
+ version: "22.2.4",
1804
+ ngImport: i0,
1805
+ type: InstanceMetric,
1806
+ decorators: [{
1807
+ type: Component,
1808
+ args: [{
1809
+ selector: "jc-instance-metric",
1810
+ changeDetection: ChangeDetectionStrategy.OnPush,
1811
+ imports: [Chart],
1812
+ template: `<jc-chart [title]="title()" [series]="[{ name: name(), points: points() }]" [format]="format()" [marks]="marks()" />`
1813
+ }]
1814
+ }],
1815
+ propDecorators: {
1816
+ title: [{
1817
+ type: i0.Input,
1818
+ args: [{
1819
+ isSignal: true,
1820
+ alias: "title",
1821
+ required: true
1822
+ }]
1823
+ }],
1824
+ name: [{
1825
+ type: i0.Input,
1826
+ args: [{
1827
+ isSignal: true,
1828
+ alias: "name",
1829
+ required: true
1830
+ }]
1831
+ }],
1832
+ instanceId: [{
1833
+ type: i0.Input,
1834
+ args: [{
1835
+ isSignal: true,
1836
+ alias: "instanceId",
1837
+ required: true
1838
+ }]
1839
+ }],
1840
+ from: [{
1841
+ type: i0.Input,
1842
+ args: [{
1843
+ isSignal: true,
1844
+ alias: "from",
1845
+ required: true
1846
+ }]
1847
+ }],
1848
+ to: [{
1849
+ type: i0.Input,
1850
+ args: [{
1851
+ isSignal: true,
1852
+ alias: "to",
1853
+ required: true
1854
+ }]
1855
+ }],
1856
+ marks: [{
1857
+ type: i0.Input,
1858
+ args: [{
1859
+ isSignal: true,
1860
+ alias: "marks",
1861
+ required: false
1862
+ }]
1863
+ }],
1864
+ format: [{
1865
+ type: i0.Input,
1866
+ args: [{
1867
+ isSignal: true,
1868
+ alias: "format",
1869
+ required: false
1870
+ }]
1871
+ }],
1872
+ level: [{
1873
+ type: i0.Input,
1874
+ args: [{
1875
+ isSignal: true,
1876
+ alias: "level",
1877
+ required: false
1878
+ }]
1879
+ }]
1880
+ }
1881
+ });
1656
1882
  var ServiceStatsCharts = class ServiceStatsCharts {
1657
1883
  ctx = inject(ContextService);
1658
1884
  api = inject(ApiService);
@@ -1741,7 +1967,8 @@ var ServiceStatsCharts = class ServiceStatsCharts {
1741
1967
  inputs: [
1742
1968
  "title",
1743
1969
  "series",
1744
- "format"
1970
+ "format",
1971
+ "marks"
1745
1972
  ]
1746
1973
  },
1747
1974
  {
@@ -1796,6 +2023,6 @@ i0.ɵɵngDeclareClassMetadata({
1796
2023
  }]
1797
2024
  }] }
1798
2025
  });
1799
- export { ReasonPipe as _, problemText as a, preciseTime as b, ConfidenceBadge as c, KeyValueTable as d, onThemeChange as f, PercentPipe as g, DurationPipe as h, TraceTable as i, ContextBar as l, AgoPipe as m, MetricExplorer as n, cursorList as o, themeColor as p, ServiceStatsCharts as r, screenPages as s, LogTable as t, HealthBadge as u, formatDuration as v, apiResource as x, plainTraceId as y };
2026
+ export { apiResource as S, PercentPipe as _, TraceTable as a, plainTraceId as b, screenPages as c, HealthBadge as d, KeyValueTable as f, DurationPipe as g, AgoPipe as h, ServiceStatsCharts as i, ConfidenceBadge as l, themeColor as m, LogTable as n, problemText as o, onThemeChange as p, MetricExplorer as r, cursorList as s, InstanceMetric as t, ContextBar as u, ReasonPipe as v, preciseTime as x, formatDuration as y };
1800
2027
 
1801
- //# sourceMappingURL=juice-js-observability-telemetry-B5jMJYfn.mjs.map
2028
+ //# sourceMappingURL=juice-js-observability-telemetry-BftWSOaQ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"juice-js-observability-telemetry-BftWSOaQ.mjs","names":["i1","i2","i3"],"sources":["../../../../projects/juice-js/observability/src/lib/shared/resource.ts","../../../../projects/juice-js/observability/src/lib/shared/format.ts","../../../../projects/juice-js/observability/src/lib/shared/theme.ts","../../../../projects/juice-js/observability/src/lib/shared/ui.ts","../../../../projects/juice-js/observability/src/lib/shared/paging.ts","../../../../projects/juice-js/observability/src/lib/shared/telemetry.ts"],"sourcesContent":["import { ResourceRef, Signal, computed, isSignal } from '@angular/core';\nimport { RxResourceOptions, rxResource } from '@angular/core/rxjs-interop';\n\n/** A resource whose `value()` is `undefined` while its request failed, instead of throwing. */\nexport type ApiResource<T> = Omit<ResourceRef<T | undefined>, 'value'> & { readonly value: Signal<T | undefined> };\n\n/**\n * An `rxResource` for an API read. Angular's `value()` throws while the resource is in error, so a failed request (a\n * trace not found, a 500, the API unreachable) would break the page's rendering, and with it every overlay such as a\n * select's options. Here `value()` reads `undefined` then, and `error()` says why.\n */\nexport function apiResource<T, P>(options: RxResourceOptions<T, P>): ApiResource<T> {\n const ref = rxResource<T, P>(options);\n const value = computed(() => (ref.hasValue() ? ref.value() : undefined));\n return new Proxy(ref, {\n get(target, prop) {\n if (prop === 'value') return value;\n const member = Reflect.get(target, prop, target);\n return typeof member === 'function' && !isSignal(member) ? member.bind(target) : member;\n },\n }) as unknown as ApiResource<T>;\n}\n","import { Pipe, PipeTransform } from '@angular/core';\n\n/** Milliseconds since the epoch of an ISO 8601 time, keeping the sub-millisecond digits that Date.parse drops. */\nexport function preciseTime(iso: string): number {\n const fraction = /\\.\\d{3}(\\d+)/.exec(iso)?.[1];\n return Date.parse(iso) + (fraction ? Number(`0.${fraction}`) : 0);\n}\n\n/** The 32-hex trace id of a W3C traceparent (\"00-<trace id>-<span id>-01\"); any other text unchanged but trimmed and lower-cased. */\nexport function plainTraceId(text: string): string {\n const lower = text.trim().toLowerCase();\n return /^[0-9a-f]{2}-([0-9a-f]{32})-[0-9a-f]{16}-[0-9a-f]{2}$/.exec(lower)?.[1] ?? lower;\n}\n\n/** 0.8 ms, 120 ms, 1.42 s, 2 m 05 s. */\nexport function formatDuration(ms: number | null | undefined): string {\n if (ms === null || ms === undefined || Number.isNaN(ms)) return '—';\n if (ms < 1) return `${ms.toFixed(2)} ms`;\n if (ms < 1000) return `${Math.round(ms * 10) / 10} ms`;\n if (ms < 60_000) return `${(ms / 1000).toFixed(2)} s`;\n const s = Math.round(ms / 1000);\n return `${Math.floor(s / 60)} m ${String(s % 60).padStart(2, '0')} s`;\n}\n\nexport function formatPercent(rate: number | null | undefined): string {\n if (rate === null || rate === undefined) return '—';\n const p = rate * 100;\n return `${p === 0 ? '0' : p < 0.1 ? '<0.1' : p.toFixed(p < 10 ? 1 : 0)} %`;\n}\n\nexport function formatAgo(iso: string | null | undefined): string {\n if (!iso) return '—';\n const s = Math.round((Date.now() - new Date(iso).getTime()) / 1000);\n if (s < 60) return `${Math.max(s, 0)} s ago`;\n if (s < 3600) return `${Math.round(s / 60)} min ago`;\n if (s < 86_400) return `${Math.round(s / 3600)} h ago`;\n return `${Math.round(s / 86_400)} d ago`;\n}\n\n@Pipe({ name: 'duration' })\nexport class DurationPipe implements PipeTransform {\n transform(ms: number | null | undefined) { return formatDuration(ms); }\n}\n\n@Pipe({ name: 'percent2' })\nexport class PercentPipe implements PipeTransform {\n transform(rate: number | null | undefined) { return formatPercent(rate); }\n}\n\n@Pipe({ name: 'ago' })\nexport class AgoPipe implements PipeTransform {\n transform(iso: string | null | undefined) { return formatAgo(iso); }\n}\n\n/** A reason code such as `dependency_failed:shop/payments` as words. */\n@Pipe({ name: 'reason' })\nexport class ReasonPipe implements PipeTransform {\n transform(code: string) {\n const [what, subject] = code.split(/:(.*)/s);\n const text = what.replace(/_/g, ' ');\n return subject ? `${text}: ${subject}` : text;\n }\n}\n","/**\n * The app's colours, as `observability.colors($theme)` wrote them in `--jc-*` custom properties, for what CSS cannot\n * colour itself: the charts (ECharts) and the dependency graph (Cytoscape) draw on their own.\n */\nexport function themeColor(name: string, element: Element = document.body): string {\n return getComputedStyle(element).getPropertyValue(`--jc-${name}`).trim();\n}\n\n/** The categorical colours (`$series`): services in a trace, lines in a chart. */\nexport function seriesColors(element: Element = document.body): string[] {\n const count = Number(themeColor('series-count', element)) || 0;\n return Array.from({ length: count }, (_, i) => themeColor(`series-${i + 1}`, element)).filter(Boolean);\n}\n\n/**\n * Calls back when the app switches theme: a class change on `<html>` or `<body>`, as juice-layout's dark-mode toggle\n * makes. Returns the function that stops listening.\n */\nexport function onThemeChange(callback: () => void): () => void {\n const observer = new MutationObserver(callback);\n for (const element of [document.documentElement, document.body]) {\n observer.observe(element, { attributes: true, attributeFilter: ['class'] });\n }\n return () => observer.disconnect();\n}\n","import { ObservabilityLinks } from '../core/options';\nimport {\n ChangeDetectionStrategy, Component, ElementRef, OnDestroy, afterNextRender, computed, effect, inject, input, signal, viewChild,\n} from '@angular/core';\nimport { toSignal } from '@angular/core/rxjs-interop';\nimport { FormsModule } from '@angular/forms';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatSelectModule } from '@angular/material/select';\nimport { Router } from '@angular/router';\nimport { catchError, map, of } from 'rxjs';\nimport type { ECharts, EChartsOption } from 'echarts';\nimport { ApiService } from '../core/api.service';\nimport { ContextService, RANGES } from '../core/context.service';\nimport { HealthState } from '../core/models';\nimport { onThemeChange, seriesColors, themeColor } from './theme';\n\n/** A health state, with \"no data\" for a missing one (Console requirements §10: missing data is not zero). */\n@Component({\n selector: 'jc-health',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `<span class=\"jc-badge\" [class]=\"'jc-health-' + (state() ?? 'none').toLowerCase()\"\n [attr.title]=\"stale() ? 'Evaluation has stopped: this state may be out of date' : null\">\n {{ state() ?? 'No data' }}@if (stale()) {<span class=\"jc-stale\"> · stale</span>}</span>`,\n})\nexport class HealthBadge {\n readonly state = input<HealthState | null | undefined>();\n readonly stale = input(false);\n}\n\n/** Observed or inferred dependency evidence (Console requirements §9): inferred is never shown as confirmed. */\n@Component({\n selector: 'jc-confidence',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `<span class=\"jc-badge\" [class.jc-observed]=\"observed()\" [class.jc-inferred]=\"!observed()\"\n [attr.title]=\"observed() ? 'Seen in traces: a call from one service to the other' : 'Inferred from span attributes, not a confirmed call'\">\n {{ observed() ? 'observed' : 'inferred' }}</span>`,\n})\nexport class ConfidenceBadge {\n readonly confidence = input.required<string>();\n protected readonly observed = computed(() => this.confidence().toLowerCase() === 'observed');\n}\n\n/** Attributes as a key/value table, sorted, values wrapped. */\n@Component({\n selector: 'jc-kv',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n @if (entries().length === 0) { <p class=\"jc-muted\">{{ empty() }}</p> }\n @else {\n <table class=\"jc-kv\"><tbody>\n @for (e of entries(); track e[0]) { <tr><th>{{ e[0] }}</th><td>{{ e[1] }}</td></tr> }\n </tbody></table>\n }`,\n})\nexport class KeyValueTable {\n readonly values = input<Record<string, string | null | undefined>>({});\n readonly empty = input('None');\n protected readonly entries = computed(() =>\n Object.entries(this.values()).filter((e): e is [string, string] => e[1] !== null && e[1] !== undefined && e[1] !== '')\n .sort((a, b) => a[0].localeCompare(b[0])));\n}\n\n/**\n * The context bar on every page (Console requirements §13, §17): environment, time range, and a global lookup for a\n * trace id, a span id or a service name.\n */\n@Component({\n selector: 'jc-context-bar',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [FormsModule, MatSelectModule, MatIconModule, MatButtonModule],\n template: `\n <div class=\"jc-context\">\n <ng-content />\n <span class=\"jc-spacer\"></span>\n <mat-form-field subscriptSizing=\"dynamic\" class=\"jc-field-sm\">\n <mat-label>Environment</mat-label>\n <mat-select [value]=\"ctx.environment()\" (valueChange)=\"ctx.set({ env: $event || null })\">\n <mat-option value=\"\">All</mat-option>\n @for (e of environments(); track e.id) { <mat-option [value]=\"e.key\">{{ e.key }}</mat-option> }\n </mat-select>\n </mat-form-field>\n <mat-form-field subscriptSizing=\"dynamic\" class=\"jc-field-sm\">\n <mat-label>Time range</mat-label>\n <mat-select [value]=\"ctx.range()\" (valueChange)=\"ctx.set({ range: $event })\">\n @for (r of ranges; track r) { <mat-option [value]=\"r\">Last {{ r }}</mat-option> }\n @if (ctx.range() === 'custom') { <mat-option value=\"custom\" disabled>Custom window</mat-option> }\n </mat-select>\n </mat-form-field>\n <form class=\"jc-lookup\" (ngSubmit)=\"lookup()\">\n <mat-icon>search</mat-icon>\n <input name=\"q\" [(ngModel)]=\"query\" placeholder=\"Trace ID, span ID or service\" aria-label=\"Go to trace, span or service\">\n </form>\n </div>\n @if (message()) { <p class=\"jc-muted jc-lookup-message\">{{ message() }}</p> }`,\n})\nexport class ContextBar {\n protected readonly ctx = inject(ContextService);\n private readonly api = inject(ApiService);\n private readonly router = inject(Router);\n private readonly links = inject(ObservabilityLinks);\n protected readonly ranges = Object.keys(RANGES);\n protected readonly environments = toSignal(this.api.environments().pipe(map(p => p.items), catchError(() => of([]))), { initialValue: [] });\n protected query = '';\n protected readonly message = signal('');\n\n lookup() {\n const q = this.query.trim();\n if (!q) return;\n this.message.set('Searching…');\n this.api.search(q).subscribe({\n next: page => {\n const hit = page.items[0];\n if (!hit) { this.message.set(`Nothing found for \"${q}\".`); return; }\n this.message.set(page.items.length > 1 ? `${page.items.length} matches; showing the first.` : '');\n const extra = hit.kind === 'span' ? { span: hit.id } : {};\n void (hit.kind === 'service'\n ? this.router.navigate(this.links.to('services', hit.id), { queryParams: this.ctx.keep() })\n : this.router.navigate(this.links.to('traces', hit.traceId), { queryParams: this.ctx.keep(extra) }));\n },\n error: () => this.message.set('Search failed.'),\n });\n }\n}\n\nexport interface ChartSeries { name: string; points: { at: string; value: number | null }[]; unit?: string; }\n\n/**\n * The API returns no point for a bucket without data; give each missing bucket a null so the chart shows a gap\n * instead of drawing a line across it (no data is not zero).\n */\nexport function withGaps(points: { at: string; value: number | null }[], from: string, to: string, stepSeconds: number) {\n const step = stepSeconds * 1000;\n const byTime = new Map(points.map(p => [new Date(p.at).getTime(), p.value]));\n const out: { at: string; value: number | null }[] = [];\n for (let t = Math.floor(new Date(from).getTime() / step) * step; t < new Date(to).getTime(); t += step) {\n out.push({ at: new Date(t).toISOString(), value: byTime.get(t) ?? null });\n }\n return out;\n}\n\n/**\n * A time series chart (Apache ECharts, loaded on first use). A missing bucket is a gap in the line, never zero.\n */\n@Component({\n selector: 'jc-chart',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `<div class=\"jc-chart-title\">{{ title() }}</div>\n @if (empty()) { <div class=\"jc-chart jc-chart-empty\">No data in this window</div> }\n <div #host class=\"jc-chart\" [hidden]=\"empty()\"></div>`,\n})\nexport class Chart implements OnDestroy {\n readonly title = input('');\n readonly series = input<ChartSeries[]>([]);\n readonly format = input<(v: number) => string>(v => String(Math.round(v * 100) / 100));\n /** Moments to mark with a vertical line. */\n readonly marks = input<string[]>([]);\n private readonly host = viewChild.required<ElementRef<HTMLDivElement>>('host');\n protected readonly empty = computed(() => this.series().every(s => s.points.every(p => p.value === null)));\n private chart?: ECharts;\n private observer?: ResizeObserver;\n private stopThemeWatch?: () => void;\n\n constructor() {\n afterNextRender(async () => {\n // Only what a line chart needs: the full library is three times the size.\n const [echarts, charts, components, renderers] = await Promise.all([\n import('echarts/core'), import('echarts/charts'), import('echarts/components'), import('echarts/renderers')]);\n echarts.use([charts.LineChart, components.GridComponent, components.TooltipComponent, components.LegendComponent, components.MarkLineComponent, renderers.SVGRenderer]);\n this.chart = echarts.init(this.host().nativeElement, undefined, { renderer: 'svg' });\n this.observer = new ResizeObserver(() => this.chart?.resize());\n this.observer.observe(this.host().nativeElement);\n this.stopThemeWatch = onThemeChange(() => this.render());\n this.render();\n });\n effect(() => { this.series(); this.marks(); this.render(); });\n }\n\n private render() {\n if (!this.chart) return;\n const format = this.format();\n // The app's theme colours (observability.colors), read at each render so a theme switch repaints.\n const host = this.host().nativeElement;\n const [text, muted, border, colors] = [themeColor('text', host), themeColor('muted', host), themeColor('border', host), seriesColors(host)];\n const option: EChartsOption = {\n animation: false,\n color: colors.length ? colors : undefined,\n grid: { left: 56, right: 16, top: 16, bottom: 28 },\n tooltip: { trigger: 'axis', valueFormatter: v => (typeof v === 'number' ? format(v) : '—') },\n legend: this.series().length > 1 ? { top: 0, textStyle: { color: text } } : undefined,\n xAxis: { type: 'time', axisLabel: { color: muted, hideOverlap: true }, axisLine: { lineStyle: { color: border } } },\n yAxis: { type: 'value', axisLabel: { color: muted, formatter: (v: number) => format(v) },\n splitLine: { lineStyle: { color: border } } },\n series: this.series().map((s, i) => ({\n name: s.name, type: 'line', showSymbol: false, connectNulls: false,\n data: s.points.map(p => [p.at, p.value]),\n ...(i === 0 && this.marks().length ? { markLine: {\n silent: true, symbol: 'none', label: { show: false }, lineStyle: { color: muted, type: 'dashed' as const },\n data: this.marks().map(at => ({ xAxis: at })),\n } } : {}),\n })),\n };\n this.chart.setOption(option, true);\n }\n\n ngOnDestroy() {\n this.observer?.disconnect();\n this.stopThemeWatch?.();\n this.chart?.dispose();\n }\n}\n","import { DestroyRef, Signal, computed, inject, linkedSignal, signal } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { apiResource } from './resource';\nimport { PageEvent } from '@angular/material/paginator';\nimport { Observable, map } from 'rxjs';\nimport { Query } from '../core/api.service';\n\n/** A page from an API list that pages with a cursor: alerts, traces, logs. */\nexport interface CursorPage<T> { items: T[]; nextCursor?: string | null; }\n\n/**\n * A newest-first list read page by page with the API's cursor. The first page loads whenever `params` change; `more()`\n * appends the next page, asked with exactly the query of the first one (its time window included), so the list grows\n * without shifting, skipping or repeating rows. Call it in an injection context, such as a field initializer.\n */\nexport function cursorList<P, T>(params: () => P, query: (params: P) => Query, fetch: (query: Query) => Observable<CursorPage<T>>) {\n const destroyRef = inject(DestroyRef);\n const first = apiResource({\n params,\n stream: ({ params }) => {\n const q = query(params);\n return fetch(q).pipe(map(page => ({ page, query: q })));\n },\n });\n // Pages after the first; reset whenever the first page reloads.\n const rest = linkedSignal({ source: first.value, computation: () => ({ items: [] as T[], cursor: undefined as string | null | undefined }) });\n const loadingMore = signal(false);\n const moreError = signal<unknown>(null);\n const items = computed(() => [...(first.value()?.page.items ?? []), ...rest().items]);\n const cursor = computed(() => rest().cursor !== undefined ? rest().cursor! : first.value()?.page.nextCursor ?? null);\n\n function more() {\n const current = first.value();\n const next = cursor();\n if (!current || !next || loadingMore()) return;\n loadingMore.set(true);\n moreError.set(null);\n fetch({ ...current.query, cursor: next }).pipe(takeUntilDestroyed(destroyRef)).subscribe({\n next: page => rest.update(r => ({ items: [...r.items, ...page.items], cursor: page.nextCursor ?? null })),\n error: e => { moreError.set(e); loadingMore.set(false); },\n complete: () => loadingMore.set(false),\n });\n }\n\n return { first, items, hasMore: computed(() => cursor() !== null), loadingMore, moreError: moreError.asReadonly(), more };\n}\n\n/**\n * Pages a list already in memory for display (the inventory lists, which the Console sorts and filters itself). Goes\n * back to the first page whenever the rows change, for example when a filter narrows them.\n */\nexport function screenPages<T>(rows: Signal<T[]>, sizes = [50, 100, 200]) {\n const size = signal(sizes[0]);\n const index = linkedSignal({ source: rows, computation: () => 0 });\n return {\n sizes,\n size: size.asReadonly(),\n index: index.asReadonly(),\n visible: computed(() => rows().slice(index() * size(), (index() + 1) * size())),\n /** More rows than one page: show the paginator. */\n needed: computed(() => rows().length > sizes[0]),\n change(event: PageEvent) { size.set(event.pageSize); index.set(event.pageIndex); },\n };\n}\n","import { LinkPipe } from '../core/options';\nimport { ChangeDetectionStrategy, Component, computed, inject, input, linkedSignal } from '@angular/core';\nimport { apiResource } from './resource';\nimport { DatePipe } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatProgressBarModule } from '@angular/material/progress-bar';\nimport { MatSelectModule } from '@angular/material/select';\nimport { RouterLink } from '@angular/router';\nimport { ApiService, Query } from '../core/api.service';\nimport { ContextService, MAX_SEARCH_MS } from '../core/context.service';\nimport { DurationPipe } from './format';\nimport { cursorList } from './paging';\nimport { Chart, withGaps } from './ui';\n\n/** Shows a request's failure as a short line instead of a broken page. */\nexport function problemText(error: unknown): string {\n const e = error as { status?: number; error?: { title?: string; detail?: string } } | undefined;\n if (!e) return '';\n if (e.status === 0) return 'The Juice API cannot be reached.';\n return [e.error?.title, e.error?.detail].filter(Boolean).join(': ') || `Request failed (${e.status}).`;\n}\n\n/**\n * Traces matching a query in the current context, newest first (Console requirements §5): enough per row to pick a\n * useful one, and one click to its waterfall.\n */\n@Component({\n selector: 'jc-trace-table',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [LinkPipe, RouterLink, DatePipe, DurationPipe, MatProgressBarModule, MatButtonModule],\n template: `\n @if (traces.first.isLoading()) { <mat-progress-bar mode=\"indeterminate\" /> }\n @if (traces.first.error()) { <p class=\"jc-error\">{{ error() }}</p> }\n @if (traces.first.hasValue()) {\n @if (rows().length === 0) { <p class=\"jc-muted\">No traces match in this window.</p> }\n @else {\n <table class=\"jc-table\">\n <thead><tr><th>Start</th><th>Root operation</th><th>Duration</th><th>Spans</th><th>Status</th><th>Instance</th></tr></thead>\n <tbody>\n @for (t of rows(); track t.traceId) {\n <tr>\n <td class=\"jc-nowrap\">{{ t.startedAt | date: 'MMM d, HH:mm:ss.SSS' }}</td>\n <td><a [routerLink]=\"['traces', t.traceId] | jcLink\" [queryParams]=\"ctx.keep()\">{{ t.rootService }} · {{ t.rootOperation }}</a>\n @if (t.services.length > 1) { <div class=\"jc-muted jc-small\">{{ t.services.join(' → ') }}</div> }</td>\n <td class=\"jc-nowrap\"><span class=\"jc-bar\" [style.width.px]=\"barWidth(t.durationMs)\"></span>{{ t.durationMs | duration }}</td>\n <td>{{ t.spanCount }}</td>\n <td>@if (t.errorCount > 0) { <span class=\"jc-badge jc-health-unhealthy\">{{ t.errorCount }} error{{ t.errorCount > 1 ? 's' : '' }}</span> }\n @else { <span class=\"jc-badge jc-health-healthy\">ok</span> }</td>\n <td class=\"jc-muted jc-small\">{{ t.rootInstance ?? t.rootHost ?? '—' }}</td>\n </tr>\n }\n </tbody>\n </table>\n <div class=\"jc-more\">\n <span class=\"jc-muted\">{{ rows().length }} trace{{ rows().length === 1 ? '' : 's' }}{{ traces.hasMore() ? ', newest first' : '' }}</span>\n @if (traces.hasMore()) {\n <button mat-button (click)=\"traces.more()\" [disabled]=\"traces.loadingMore()\">{{ traces.loadingMore() ? 'Loading…' : 'Older traces' }}</button>\n }\n @if (traces.moreError()) { <span class=\"jc-error\">{{ moreError() }}</span> }\n </div>\n }\n }`,\n})\nexport class TraceTable {\n protected readonly ctx = inject(ContextService);\n private readonly api = inject(ApiService);\n readonly query = input<Query>({});\n readonly limit = input(50);\n\n /** \"Older traces\" appends the next page of the same search, over the same window. */\n protected readonly traces = cursorList(\n () => ({ query: this.query(), env: this.ctx.environment(), range: this.ctx.range(), abs: this.ctx.absolute(), limit: this.limit() }),\n p => ({ environment: p.env, ...this.ctx.window(MAX_SEARCH_MS), limit: p.limit, ...p.query }),\n q => this.api.traces(q));\n protected readonly rows = this.traces.items;\n protected readonly longest = computed(() => Math.max(1, ...this.rows().map(t => t.durationMs)));\n /** Pixels, not a percentage: an auto-sized cell ignores a percentage width, so a full bar pushed the time into the next column. */\n protected barWidth(ms: number) { return Math.max(2, 80 * ms / this.longest()); }\n protected readonly error = computed(() => problemText(this.traces.first.error()));\n protected readonly moreError = computed(() => problemText(this.traces.moreError()));\n}\n\n/**\n * Log records for a query in the current context (Console requirements §7): each with its trace and span, when the\n * record carries them.\n */\n@Component({\n selector: 'jc-log-table',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [LinkPipe, RouterLink, DatePipe, MatProgressBarModule, MatButtonModule],\n template: `\n @if (logs.first.isLoading()) { <mat-progress-bar mode=\"indeterminate\" /> }\n @if (logs.first.error()) { <p class=\"jc-error\">{{ error() }}</p> }\n @if (logs.first.hasValue()) {\n @if (rows().length === 0) { <p class=\"jc-muted\">No log records match in this window.</p> }\n @else {\n <table class=\"jc-table jc-logs\">\n <thead><tr><th>Time</th><th>Severity</th>@if (!compact()) { <th>Service</th> }<th>Message</th>@if (!compact()) { <th>Trace</th> }</tr></thead>\n <tbody>\n @for (l of rows(); track $index) {\n <tr>\n <td class=\"jc-nowrap\">{{ l.timestamp | date: 'MMM d, HH:mm:ss.SSS' }}</td>\n <td><span class=\"jc-badge\" [class]=\"severityClass(l.severityNumber)\">{{ l.severity || l.severityNumber }}</span></td>\n @if (!compact()) { <td class=\"jc-nowrap\">{{ l.service }}@if (l.instance) {<div class=\"jc-muted jc-small\">{{ l.instance }}</div>}</td> }\n <td><pre class=\"jc-body\">{{ l.body }}@if (l.bodyTruncated) {…}</pre></td>\n @if (!compact()) { <td class=\"jc-nowrap\">\n @if (l.traceId) {\n <a [routerLink]=\"['traces', l.traceId] | jcLink\" [queryParams]=\"ctx.keep(l.spanId ? { span: l.spanId } : {})\">{{ l.spanId ? 'span' : 'trace' }} ↗</a>\n } @else { <span class=\"jc-muted\">—</span> }\n </td> }\n </tr>\n }\n </tbody>\n </table>\n <div class=\"jc-more\">\n <span class=\"jc-muted\">{{ rows().length }} record{{ rows().length === 1 ? '' : 's' }}{{ logs.hasMore() ? ', newest first' : '' }}</span>\n @if (logs.hasMore()) {\n <button mat-button (click)=\"logs.more()\" [disabled]=\"logs.loadingMore()\">{{ logs.loadingMore() ? 'Loading…' : 'Older logs' }}</button>\n }\n @if (logs.moreError()) { <span class=\"jc-error\">{{ moreError() }}</span> }\n </div>\n }\n }`,\n})\nexport class LogTable {\n protected readonly ctx = inject(ContextService);\n private readonly api = inject(ApiService);\n readonly query = input<Query>({});\n /** Inside a span: its service and trace are already on screen, so only time, severity and message. */\n readonly compact = input(false);\n\n /** \"Older logs\" appends the next page of the same search, over the same window. */\n protected readonly logs = cursorList(\n () => ({ query: this.query(), env: this.ctx.environment(), range: this.ctx.range(), abs: this.ctx.absolute() }),\n p => ({ environment: p.env, ...this.ctx.window(MAX_SEARCH_MS), limit: 200, ...p.query }),\n q => this.api.logs(q));\n protected readonly rows = this.logs.items;\n protected readonly error = computed(() => problemText(this.logs.first.error()));\n protected readonly moreError = computed(() => problemText(this.logs.moreError()));\n\n severityClass(n: number) {\n return n >= 17 ? 'jc-health-unhealthy' : n >= 13 ? 'jc-health-degraded' : n >= 9 ? 'jc-health-healthy' : 'jc-health-none';\n }\n}\n\n/**\n * The metrics reported for a scope (service, instance or host) and a chart of the one selected (Console requirements\n * §7): a counter as a rate, a gauge or histogram as an average.\n */\n@Component({\n selector: 'jc-metric-explorer',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [FormsModule, MatSelectModule, MatProgressBarModule, Chart],\n template: `\n @if (metrics.isLoading()) { <mat-progress-bar mode=\"indeterminate\" /> }\n @if (metrics.error()) { <p class=\"jc-error\">{{ metricsError() }}</p> }\n @if (metrics.hasValue()) {\n @if (names().length === 0) { <p class=\"jc-muted\">No metrics reported in this window.</p> }\n @else {\n <mat-form-field subscriptSizing=\"dynamic\" class=\"jc-field-wide\">\n <mat-label>Metric</mat-label>\n <mat-select [value]=\"selected()\" (valueChange)=\"selected.set($event)\">\n @for (m of names(); track m.name) { <mat-option [value]=\"m.name\">{{ m.name }} <span class=\"jc-muted\">({{ m.type }}{{ m.unit ? ', ' + m.unit : '' }})</span></mat-option> }\n </mat-select>\n </mat-form-field>\n @if (series.value(); as s) {\n <jc-chart [title]=\"title()\" [series]=\"[{ name: s.name, points: points() }]\" />\n }\n }\n }`,\n})\nexport class MetricExplorer {\n private readonly ctx = inject(ContextService);\n private readonly api = inject(ApiService);\n readonly scope = input<Query>({});\n readonly initial = input<string | null>(null);\n\n protected readonly metrics = apiResource({\n params: () => ({ scope: this.scope(), env: this.ctx.environment(), range: this.ctx.range(), abs: this.ctx.absolute() }),\n stream: ({ params }) => this.api.metrics({ environment: params.env, ...this.ctx.window(), ...params.scope }),\n });\n protected readonly names = computed(() => this.metrics.value()?.items ?? []);\n protected readonly selected = linkedSignal(() => {\n const names = this.names();\n // The app's own metrics first: host and runtime metrics say less about a service, and sort before most names.\n return names.find(m => m.name === this.initial())?.name\n ?? names.find(m => !/^(dotnet|process|system)./.test(m.name))?.name ?? names[0]?.name ?? null;\n });\n protected readonly series = apiResource({\n // Idle until a metric is chosen.\n params: () => this.selected() ? { name: this.selected()!, scope: this.scope(), env: this.ctx.environment(), range: this.ctx.range(), abs: this.ctx.absolute() } : undefined,\n stream: ({ params }) => {\n this.window = this.ctx.window();\n return this.api.series({ name: params.name, environment: params.env, ...this.window, ...params.scope });\n },\n });\n private window = { from: '', to: '' };\n protected readonly points = computed(() => {\n const s = this.series.value();\n return s ? withGaps(s.points, this.window.from, this.window.to, s.stepSeconds) : [];\n });\n protected readonly title = computed(() => {\n const s = this.series.value();\n if (!s) return '';\n const what = s.aggregation === 'rate' ? 'rate per second' : 'average';\n return `${s.name} — ${what}${s.unit ? ` (${s.unit}${s.aggregation === 'rate' ? '/s' : ''})` : ''}`;\n });\n protected readonly metricsError = computed(() => problemText(this.metrics.error()));\n}\n\n/**\n * One resource metric of one instance around a moment, for the trace page. A counter reads as a rate. The window is\n * fixed by the trace, not the context bar's range.\n */\n@Component({\n selector: 'jc-instance-metric',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [Chart],\n template: `<jc-chart [title]=\"title()\" [series]=\"[{ name: name(), points: points() }]\" [format]=\"format()\" [marks]=\"marks()\" />`,\n})\nexport class InstanceMetric {\n private readonly api = inject(ApiService);\n readonly title = input.required<string>();\n readonly name = input.required<string>();\n readonly instanceId = input.required<string>();\n readonly from = input.required<string>();\n readonly to = input.required<string>();\n readonly marks = input<string[]>([]);\n readonly format = input<(v: number) => string>(v => String(Math.round(v * 100) / 100));\n /** Reads the metric as a level, even if the host reports it as a counter. */\n readonly level = input(false);\n\n private readonly series = apiResource({\n params: () => ({ name: this.name(), instanceId: this.instanceId(), from: this.from(), to: this.to(), ...(this.level() ? { level: true } : {}) }),\n stream: ({ params }) => this.api.series(params),\n });\n protected readonly points = computed(() => {\n const s = this.series.value();\n return s ? withGaps(s.points, this.from(), this.to(), s.stepSeconds) : [];\n });\n}\n\n/** Requests, error rate and p95 of a service (or one operation) over the window. */\n@Component({\n selector: 'jc-service-stats',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [Chart, MatProgressBarModule],\n template: `\n @if (stats.isLoading()) { <mat-progress-bar mode=\"indeterminate\" /> }\n @if (stats.hasValue()) {\n <div class=\"jc-grid-3\">\n <jc-chart [title]=\"rates().length > 1 ? 'Requests and messages per second' : rates()[0].title\" [series]=\"rates()\" />\n <jc-chart title=\"Error rate\" [series]=\"[{ name: 'errors', points: pick('errorRate') }]\" [format]=\"percent\" />\n <jc-chart title=\"p95 latency\" [series]=\"[{ name: 'p95', points: pick('p95Ms') }]\" [format]=\"ms\" />\n </div>\n }`,\n})\nexport class ServiceStatsCharts {\n private readonly ctx = inject(ContextService);\n private readonly api = inject(ApiService);\n readonly query = input.required<Query>();\n private window = { from: '', to: '' };\n protected readonly percent = (v: number) => `${Math.round(v * 1000) / 10} %`;\n protected readonly ms = (v: number) => `${Math.round(v)} ms`;\n\n protected readonly stats = apiResource({\n params: () => ({ query: this.query(), env: this.ctx.environment(), range: this.ctx.range(), abs: this.ctx.absolute() }),\n stream: ({ params }) => {\n this.window = this.ctx.window();\n return this.api.serviceStats({ environment: params.env, ...this.window, ...params.query });\n },\n });\n\n /** Requests and messages are separate lines; a service with only one of them shows only that one. */\n rates() {\n const points = this.stats.value()?.points ?? [];\n const requests = { title: 'Requests per second', name: 'requests/s', points: this.pick('requestsPerSecond') };\n const messages = { title: 'Messages per second', name: 'messages/s', points: this.pick('messagesPerSecond') };\n if (!points.some(p => p.messagesPerSecond > 0)) return [requests];\n return points.some(p => p.requestsPerSecond > 0) ? [requests, messages] : [messages];\n }\n\n pick(field: 'requestsPerSecond' | 'messagesPerSecond' | 'errorRate' | 'p95Ms') {\n const s = this.stats.value();\n return s ? withGaps(s.points.map(p => ({ at: p.at, value: p[field] })), this.window.from, this.window.to, s.stepSeconds) : [];\n }\n}\n\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { ApiService, ContextService, LinkPipe, ObservabilityLinks } from "./juice-js-observability.mjs";
2
- import { a as problemText, c as ConfidenceBadge, f as onThemeChange, g as PercentPipe, h as DurationPipe, l as ContextBar, m as AgoPipe, p as themeColor, u as HealthBadge, x as apiResource } from "./juice-js-observability-telemetry-B5jMJYfn.mjs";
2
+ import { S as apiResource, _ as PercentPipe, d as HealthBadge, g as DurationPipe, h as AgoPipe, l as ConfidenceBadge, m as themeColor, o as problemText, p as onThemeChange, u as ContextBar } from "./juice-js-observability-telemetry-BftWSOaQ.mjs";
3
3
  import * as i0 from "@angular/core";
4
4
  import { ChangeDetectionStrategy, Component, afterNextRender, computed, effect, inject, input, viewChild } from "@angular/core";
5
5
  import { Router, RouterLink } from "@angular/router";
@@ -483,4 +483,4 @@ i0.ɵɵngDeclareClassMetadata({
483
483
  });
484
484
  export { TopologyPage };
485
485
 
486
- //# sourceMappingURL=juice-js-observability-topology.page-B7aXWOYV.mjs.map
486
+ //# sourceMappingURL=juice-js-observability-topology.page-aMWEXyMB.mjs.map