@juice-js/observability 0.0.0-stage → 1.0.0-alpha.11

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 (34) hide show
  1. package/README.md +63 -2
  2. package/fesm2022/juice-js-observability-alert.page-TKwqJT2d.mjs +404 -0
  3. package/fesm2022/juice-js-observability-alert.page-TKwqJT2d.mjs.map +1 -0
  4. package/fesm2022/juice-js-observability-alerts.page-B-2uS9wr.mjs +211 -0
  5. package/fesm2022/juice-js-observability-alerts.page-B-2uS9wr.mjs.map +1 -0
  6. package/fesm2022/juice-js-observability-logs.page-CZNbTl2Q.mjs +413 -0
  7. package/fesm2022/juice-js-observability-logs.page-CZNbTl2Q.mjs.map +1 -0
  8. package/fesm2022/juice-js-observability-metrics.page-DoVED9MT.mjs +267 -0
  9. package/fesm2022/juice-js-observability-metrics.page-DoVED9MT.mjs.map +1 -0
  10. package/fesm2022/juice-js-observability-overview.page-Cod7-cIy.mjs +249 -0
  11. package/fesm2022/juice-js-observability-overview.page-Cod7-cIy.mjs.map +1 -0
  12. package/fesm2022/juice-js-observability-resource.page-C8RhUipF.mjs +274 -0
  13. package/fesm2022/juice-js-observability-resource.page-C8RhUipF.mjs.map +1 -0
  14. package/fesm2022/juice-js-observability-resources.page-KadGxEAh.mjs +209 -0
  15. package/fesm2022/juice-js-observability-resources.page-KadGxEAh.mjs.map +1 -0
  16. package/fesm2022/juice-js-observability-rules.page-DKWvNpu9.mjs +175 -0
  17. package/fesm2022/juice-js-observability-rules.page-DKWvNpu9.mjs.map +1 -0
  18. package/fesm2022/juice-js-observability-service.page-_yK0kVYS.mjs +726 -0
  19. package/fesm2022/juice-js-observability-service.page-_yK0kVYS.mjs.map +1 -0
  20. package/fesm2022/juice-js-observability-services.page-BtG8zyiI.mjs +251 -0
  21. package/fesm2022/juice-js-observability-services.page-BtG8zyiI.mjs.map +1 -0
  22. package/fesm2022/juice-js-observability-telemetry-B5jMJYfn.mjs +1801 -0
  23. package/fesm2022/juice-js-observability-telemetry-B5jMJYfn.mjs.map +1 -0
  24. package/fesm2022/juice-js-observability-topology.page-B7aXWOYV.mjs +486 -0
  25. package/fesm2022/juice-js-observability-topology.page-B7aXWOYV.mjs.map +1 -0
  26. package/fesm2022/juice-js-observability-trace.page-CkLNNnKf.mjs +528 -0
  27. package/fesm2022/juice-js-observability-trace.page-CkLNNnKf.mjs.map +1 -0
  28. package/fesm2022/juice-js-observability-traces.page-DgvNixIc.mjs +520 -0
  29. package/fesm2022/juice-js-observability-traces.page-DgvNixIc.mjs.map +1 -0
  30. package/fesm2022/juice-js-observability.mjs +405 -0
  31. package/fesm2022/juice-js-observability.mjs.map +1 -0
  32. package/package.json +48 -4
  33. package/styles/_observability.scss +220 -0
  34. package/types/juice-js-observability.d.ts +400 -0
@@ -0,0 +1,211 @@
1
+ import { ApiService, ContextService, LinkPipe } from "./juice-js-observability.mjs";
2
+ import { a as problemText, l as ContextBar, m as AgoPipe, o as cursorList } from "./juice-js-observability-telemetry-B5jMJYfn.mjs";
3
+ import * as i0 from "@angular/core";
4
+ import { ChangeDetectionStrategy, Component, computed, inject, input } from "@angular/core";
5
+ import { RouterLink } from "@angular/router";
6
+ import * as i1 from "@angular/material/button";
7
+ import { MatButtonModule } from "@angular/material/button";
8
+ import * as i2 from "@angular/material/progress-bar";
9
+ import { MatProgressBarModule } from "@angular/material/progress-bar";
10
+ var AlertsPage = class AlertsPage {
11
+ ctx = inject(ContextService);
12
+ api = inject(ApiService);
13
+ states = [
14
+ "firing",
15
+ "pending",
16
+ "resolved"
17
+ ];
18
+ state = input(...ngDevMode ? [void 0, { debugName: "state" }] : /* istanbul ignore next */ []);
19
+ alerts = cursorList(() => ({
20
+ state: this.state() ?? "firing",
21
+ environment: this.ctx.environment()
22
+ }), (params) => params, (q) => this.api.alerts(q));
23
+ error = computed(() => problemText(this.alerts.first.error()), ...ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []);
24
+ moreError = computed(() => problemText(this.alerts.moreError()), ...ngDevMode ? [{ debugName: "moreError" }] : /* istanbul ignore next */ []);
25
+ static ɵfac = i0.ɵɵngDeclareFactory({
26
+ minVersion: "12.0.0",
27
+ version: "22.2.4",
28
+ ngImport: i0,
29
+ type: AlertsPage,
30
+ deps: [],
31
+ target: i0.ɵɵFactoryTarget.Component
32
+ });
33
+ static ɵcmp = i0.ɵɵngDeclareComponent({
34
+ minVersion: "17.0.0",
35
+ version: "22.2.4",
36
+ type: AlertsPage,
37
+ isStandalone: true,
38
+ selector: "ng-component",
39
+ inputs: { state: {
40
+ classPropertyName: "state",
41
+ publicName: "state",
42
+ isSignal: true,
43
+ isRequired: false,
44
+ transformFunction: null
45
+ } },
46
+ ngImport: i0,
47
+ template: `
48
+ <jc-context-bar><h1>Alerts</h1>
49
+ @for (s of states; track s) {
50
+ <a class="jc-chip" [class.jc-selected]="s === (state() ?? 'firing')" [routerLink]="['alerts'] | jcLink" [queryParams]="ctx.keep({ state: s })">{{ s }}</a>
51
+ }
52
+ </jc-context-bar>
53
+ @if (alerts.first.isLoading()) { <mat-progress-bar mode="indeterminate" /> }
54
+ @if (alerts.first.error()) { <p class="jc-error">{{ error() }}</p> }
55
+ <table class="jc-table">
56
+ <thead><tr><th>Severity</th><th>Rule</th><th>Subject</th><th>State</th><th>Value</th><th>Fired</th><th>Acknowledged</th></tr></thead>
57
+ <tbody>
58
+ @for (a of alerts.items(); track a.id) {
59
+ <tr>
60
+ <td><span class="jc-badge" [class.jc-health-unhealthy]="a.severity === 'Critical'" [class.jc-health-degraded]="a.severity === 'Warning'">{{ a.severity }}</span></td>
61
+ <td><a [routerLink]="['alerts', a.id] | jcLink" [queryParams]="ctx.keep()">{{ a.rule }}</a></td>
62
+ <td>{{ a.subjectKey }}</td>
63
+ <td>{{ a.state }}@if (a.noData) { <span class="jc-muted" title="The last evaluation had too few samples; the state is kept"> · no data</span> }</td>
64
+ <td>{{ a.lastValue ?? '—' }}</td>
65
+ <td>{{ a.firedAt | ago }}</td>
66
+ <td>{{ a.acknowledgedBy ?? '—' }}</td>
67
+ </tr>
68
+ } @empty { @if (alerts.first.hasValue()) { <tr><td colspan="7" class="jc-muted">No {{ state() ?? 'firing' }} alerts.</td></tr> } }
69
+ </tbody>
70
+ </table>
71
+ @if (alerts.items().length > 0) {
72
+ <div class="jc-more">
73
+ <span class="jc-muted">{{ alerts.items().length }} {{ state() ?? 'firing' }} alert{{ alerts.items().length === 1 ? '' : 's' }}{{ alerts.hasMore() ? ', newest first' : '' }}</span>
74
+ @if (alerts.hasMore()) {
75
+ <button mat-button (click)="alerts.more()" [disabled]="alerts.loadingMore()">{{ alerts.loadingMore() ? 'Loading…' : 'Load more' }}</button>
76
+ }
77
+ @if (alerts.moreError()) { <span class="jc-error">{{ moreError() }}</span> }
78
+ </div>
79
+ }`,
80
+ isInline: true,
81
+ dependencies: [
82
+ {
83
+ kind: "directive",
84
+ type: RouterLink,
85
+ selector: "[routerLink]",
86
+ inputs: [
87
+ "target",
88
+ "queryParams",
89
+ "fragment",
90
+ "queryParamsHandling",
91
+ "state",
92
+ "info",
93
+ "relativeTo",
94
+ "preserveFragment",
95
+ "skipLocationChange",
96
+ "replaceUrl",
97
+ "browserUrl",
98
+ "routerLink"
99
+ ]
100
+ },
101
+ {
102
+ kind: "ngmodule",
103
+ type: MatButtonModule
104
+ },
105
+ {
106
+ kind: "component",
107
+ type: i1.MatButton,
108
+ selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ",
109
+ inputs: ["matButton"],
110
+ exportAs: ["matButton", "matAnchor"]
111
+ },
112
+ {
113
+ kind: "ngmodule",
114
+ type: MatProgressBarModule
115
+ },
116
+ {
117
+ kind: "component",
118
+ type: i2.MatProgressBar,
119
+ selector: "mat-progress-bar",
120
+ inputs: [
121
+ "color",
122
+ "value",
123
+ "bufferValue",
124
+ "mode"
125
+ ],
126
+ outputs: ["animationEnd"],
127
+ exportAs: ["matProgressBar"]
128
+ },
129
+ {
130
+ kind: "component",
131
+ type: ContextBar,
132
+ selector: "jc-context-bar"
133
+ },
134
+ {
135
+ kind: "pipe",
136
+ type: LinkPipe,
137
+ name: "jcLink"
138
+ },
139
+ {
140
+ kind: "pipe",
141
+ type: AgoPipe,
142
+ name: "ago"
143
+ }
144
+ ],
145
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
146
+ });
147
+ };
148
+ i0.ɵɵngDeclareClassMetadata({
149
+ minVersion: "12.0.0",
150
+ version: "22.2.4",
151
+ ngImport: i0,
152
+ type: AlertsPage,
153
+ decorators: [{
154
+ type: Component,
155
+ args: [{
156
+ changeDetection: ChangeDetectionStrategy.OnPush,
157
+ imports: [
158
+ LinkPipe,
159
+ RouterLink,
160
+ MatButtonModule,
161
+ MatProgressBarModule,
162
+ ContextBar,
163
+ AgoPipe
164
+ ],
165
+ template: `
166
+ <jc-context-bar><h1>Alerts</h1>
167
+ @for (s of states; track s) {
168
+ <a class="jc-chip" [class.jc-selected]="s === (state() ?? 'firing')" [routerLink]="['alerts'] | jcLink" [queryParams]="ctx.keep({ state: s })">{{ s }}</a>
169
+ }
170
+ </jc-context-bar>
171
+ @if (alerts.first.isLoading()) { <mat-progress-bar mode="indeterminate" /> }
172
+ @if (alerts.first.error()) { <p class="jc-error">{{ error() }}</p> }
173
+ <table class="jc-table">
174
+ <thead><tr><th>Severity</th><th>Rule</th><th>Subject</th><th>State</th><th>Value</th><th>Fired</th><th>Acknowledged</th></tr></thead>
175
+ <tbody>
176
+ @for (a of alerts.items(); track a.id) {
177
+ <tr>
178
+ <td><span class="jc-badge" [class.jc-health-unhealthy]="a.severity === 'Critical'" [class.jc-health-degraded]="a.severity === 'Warning'">{{ a.severity }}</span></td>
179
+ <td><a [routerLink]="['alerts', a.id] | jcLink" [queryParams]="ctx.keep()">{{ a.rule }}</a></td>
180
+ <td>{{ a.subjectKey }}</td>
181
+ <td>{{ a.state }}@if (a.noData) { <span class="jc-muted" title="The last evaluation had too few samples; the state is kept"> · no data</span> }</td>
182
+ <td>{{ a.lastValue ?? '—' }}</td>
183
+ <td>{{ a.firedAt | ago }}</td>
184
+ <td>{{ a.acknowledgedBy ?? '—' }}</td>
185
+ </tr>
186
+ } @empty { @if (alerts.first.hasValue()) { <tr><td colspan="7" class="jc-muted">No {{ state() ?? 'firing' }} alerts.</td></tr> } }
187
+ </tbody>
188
+ </table>
189
+ @if (alerts.items().length > 0) {
190
+ <div class="jc-more">
191
+ <span class="jc-muted">{{ alerts.items().length }} {{ state() ?? 'firing' }} alert{{ alerts.items().length === 1 ? '' : 's' }}{{ alerts.hasMore() ? ', newest first' : '' }}</span>
192
+ @if (alerts.hasMore()) {
193
+ <button mat-button (click)="alerts.more()" [disabled]="alerts.loadingMore()">{{ alerts.loadingMore() ? 'Loading…' : 'Load more' }}</button>
194
+ }
195
+ @if (alerts.moreError()) { <span class="jc-error">{{ moreError() }}</span> }
196
+ </div>
197
+ }`
198
+ }]
199
+ }],
200
+ propDecorators: { state: [{
201
+ type: i0.Input,
202
+ args: [{
203
+ isSignal: true,
204
+ alias: "state",
205
+ required: false
206
+ }]
207
+ }] }
208
+ });
209
+ export { AlertsPage };
210
+
211
+ //# sourceMappingURL=juice-js-observability-alerts.page-B-2uS9wr.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"juice-js-observability-alerts.page-B-2uS9wr.mjs","names":[],"sources":["../../../../projects/juice-js/observability/src/lib/pages/alerts.page.ts"],"sourcesContent":["import { LinkPipe } from '../core/options';\nimport { ChangeDetectionStrategy, Component, computed, inject, input } from '@angular/core';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatProgressBarModule } from '@angular/material/progress-bar';\nimport { RouterLink } from '@angular/router';\nimport { ApiService } from '../core/api.service';\nimport { ContextService } from '../core/context.service';\nimport { AgoPipe } from '../shared/format';\nimport { ContextBar } from '../shared/ui';\nimport { cursorList } from '../shared/paging';\nimport { problemText } from '../shared/telemetry';\n\n/** Alerts, newest first (Console requirements §14), filtered by state; 100 at a time, with the next on request. */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [LinkPipe, RouterLink, MatButtonModule, MatProgressBarModule, ContextBar, AgoPipe],\n template: `\n <jc-context-bar><h1>Alerts</h1>\n @for (s of states; track s) {\n <a class=\"jc-chip\" [class.jc-selected]=\"s === (state() ?? 'firing')\" [routerLink]=\"['alerts'] | jcLink\" [queryParams]=\"ctx.keep({ state: s })\">{{ s }}</a>\n }\n </jc-context-bar>\n @if (alerts.first.isLoading()) { <mat-progress-bar mode=\"indeterminate\" /> }\n @if (alerts.first.error()) { <p class=\"jc-error\">{{ error() }}</p> }\n <table class=\"jc-table\">\n <thead><tr><th>Severity</th><th>Rule</th><th>Subject</th><th>State</th><th>Value</th><th>Fired</th><th>Acknowledged</th></tr></thead>\n <tbody>\n @for (a of alerts.items(); track a.id) {\n <tr>\n <td><span class=\"jc-badge\" [class.jc-health-unhealthy]=\"a.severity === 'Critical'\" [class.jc-health-degraded]=\"a.severity === 'Warning'\">{{ a.severity }}</span></td>\n <td><a [routerLink]=\"['alerts', a.id] | jcLink\" [queryParams]=\"ctx.keep()\">{{ a.rule }}</a></td>\n <td>{{ a.subjectKey }}</td>\n <td>{{ a.state }}@if (a.noData) { <span class=\"jc-muted\" title=\"The last evaluation had too few samples; the state is kept\"> · no data</span> }</td>\n <td>{{ a.lastValue ?? '—' }}</td>\n <td>{{ a.firedAt | ago }}</td>\n <td>{{ a.acknowledgedBy ?? '—' }}</td>\n </tr>\n } @empty { @if (alerts.first.hasValue()) { <tr><td colspan=\"7\" class=\"jc-muted\">No {{ state() ?? 'firing' }} alerts.</td></tr> } }\n </tbody>\n </table>\n @if (alerts.items().length > 0) {\n <div class=\"jc-more\">\n <span class=\"jc-muted\">{{ alerts.items().length }} {{ state() ?? 'firing' }} alert{{ alerts.items().length === 1 ? '' : 's' }}{{ alerts.hasMore() ? ', newest first' : '' }}</span>\n @if (alerts.hasMore()) {\n <button mat-button (click)=\"alerts.more()\" [disabled]=\"alerts.loadingMore()\">{{ alerts.loadingMore() ? 'Loading…' : 'Load more' }}</button>\n }\n @if (alerts.moreError()) { <span class=\"jc-error\">{{ moreError() }}</span> }\n </div>\n }`,\n})\nexport class AlertsPage {\n protected readonly ctx = inject(ContextService);\n private readonly api = inject(ApiService);\n protected readonly states = ['firing', 'pending', 'resolved'];\n readonly state = input<string>();\n protected readonly alerts = cursorList(\n () => ({ state: this.state() ?? 'firing', environment: this.ctx.environment() }), params => params, q => this.api.alerts(q));\n protected readonly error = computed(() => problemText(this.alerts.first.error()));\n protected readonly moreError = computed(() => problemText(this.alerts.moreError()));\n}\n"],"mappings":";;;;;;;;;AAkDA,IAAa,aAAb,MAAa,WAAU;CACF,MAAM,OAAO,cAAc;CAC7B,MAAM,OAAO,UAAU;CACrB,SAAS;EAAC;EAAU;EAAW;CAAU;CACnD,QAAQ,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CACb,SAAS,kBACnB;EAAE,OAAO,KAAK,MAAK,KAAM;EAAU,aAAa,KAAK,IAAI,YAAW;CAAE,KAAK,WAAU,SAAQ,MAAK,KAAK,IAAI,OAAO,CAAC,CAAC;CAC1G,QAAQ,eAAe,YAAY,KAAK,OAAO,MAAM,MAAK,CAAE,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAC9D,YAAY,eAAe,YAAY,KAAK,OAAO,UAAS,CAAE,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CARxE,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAU,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAV,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAU,cAAA;EAAA,UAAA;EAAA,QAAA,EAAA,OAAA;GAAA,mBAAA;GAAA,YAAA;GAAA,UAAA;GAAA,YAAA;GAAA,mBAAA;EAAA,EAAA;EAAA,UAAA;EAAA,UAlCX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgCN,UAAA;EAAA,cAAA;GAAA;IAAA,MAAA;IAAA,MAjCgB;IAAU,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;GAAe;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;IAAA,QAAA,CAAA,WAAA;IAAA,UAAA,CAAA,aAAA,WAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;GAAoB;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA,CAAA,cAAA;IAAA,UAAA,CAAA,gBAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAU,UAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAvE;IAAQ,MAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAiE;IAAO,MAAA;GAAA;EAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AAmC/E,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAU,YAAA,CAAA;EArCtB,MAAA;EAAU,MAAA,CAAA;GACT,iBAAiB,wBAAwB;GACzC,SAAS;IAAC;IAAU;IAAY;IAAiB;IAAsB;IAAY;GAAO;GAC1F,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiCX,CAAA"}
@@ -0,0 +1,413 @@
1
+ import { ApiService, ContextService } from "./juice-js-observability.mjs";
2
+ import { l as ContextBar, t as LogTable, x as apiResource } from "./juice-js-observability-telemetry-B5jMJYfn.mjs";
3
+ import * as i0 from "@angular/core";
4
+ import { ChangeDetectionStrategy, Component, computed, inject, input } from "@angular/core";
5
+ import { map } from "rxjs";
6
+ import { Router } from "@angular/router";
7
+ import * as i1 from "@angular/forms";
8
+ import { FormsModule } from "@angular/forms";
9
+ import * as i2 from "@angular/material/button";
10
+ import { MatButtonModule } from "@angular/material/button";
11
+ import { MatFormFieldModule } from "@angular/material/form-field";
12
+ import * as i4 from "@angular/material/input";
13
+ import { MatInputModule } from "@angular/material/input";
14
+ import * as i3 from "@angular/material/select";
15
+ import { MatSelectModule } from "@angular/material/select";
16
+ var LogsPage = class LogsPage {
17
+ ctx = inject(ContextService);
18
+ api = inject(ApiService);
19
+ router = inject(Router);
20
+ service = input(...ngDevMode ? [void 0, { debugName: "service" }] : /* istanbul ignore next */ []);
21
+ severity = input(...ngDevMode ? [void 0, { debugName: "severity" }] : /* istanbul ignore next */ []);
22
+ q = input(...ngDevMode ? [void 0, { debugName: "q" }] : /* istanbul ignore next */ []);
23
+ trace = input(...ngDevMode ? [void 0, { debugName: "trace" }] : /* istanbul ignore next */ []);
24
+ spanId = input(...ngDevMode ? [void 0, { debugName: "spanId" }] : /* istanbul ignore next */ []);
25
+ instance = input(...ngDevMode ? [void 0, { debugName: "instance" }] : /* istanbul ignore next */ []);
26
+ resource = input(...ngDevMode ? [void 0, { debugName: "resource" }] : /* istanbul ignore next */ []);
27
+ services = apiResource({ stream: () => this.api.resources("service").pipe(map((p) => p.items)) });
28
+ query = computed(() => ({
29
+ serviceId: this.service(),
30
+ minSeverity: this.severity(),
31
+ q: this.q(),
32
+ traceId: this.trace(),
33
+ spanId: this.spanId(),
34
+ instanceId: this.instance(),
35
+ resourceId: this.resource()
36
+ }), ...ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []);
37
+ apply(value) {
38
+ const queryParams = {};
39
+ for (const [key, v] of Object.entries(value)) queryParams[key] = v === "" || v === void 0 ? null : v;
40
+ this.router.navigate([], {
41
+ queryParams,
42
+ queryParamsHandling: "merge"
43
+ });
44
+ }
45
+ clear() {
46
+ this.router.navigate([], { queryParams: this.ctx.keep() });
47
+ }
48
+ static ɵfac = i0.ɵɵngDeclareFactory({
49
+ minVersion: "12.0.0",
50
+ version: "22.2.4",
51
+ ngImport: i0,
52
+ type: LogsPage,
53
+ deps: [],
54
+ target: i0.ɵɵFactoryTarget.Component
55
+ });
56
+ static ɵcmp = i0.ɵɵngDeclareComponent({
57
+ minVersion: "17.0.0",
58
+ version: "22.2.4",
59
+ type: LogsPage,
60
+ isStandalone: true,
61
+ selector: "ng-component",
62
+ inputs: {
63
+ service: {
64
+ classPropertyName: "service",
65
+ publicName: "service",
66
+ isSignal: true,
67
+ isRequired: false,
68
+ transformFunction: null
69
+ },
70
+ severity: {
71
+ classPropertyName: "severity",
72
+ publicName: "severity",
73
+ isSignal: true,
74
+ isRequired: false,
75
+ transformFunction: null
76
+ },
77
+ q: {
78
+ classPropertyName: "q",
79
+ publicName: "q",
80
+ isSignal: true,
81
+ isRequired: false,
82
+ transformFunction: null
83
+ },
84
+ trace: {
85
+ classPropertyName: "trace",
86
+ publicName: "trace",
87
+ isSignal: true,
88
+ isRequired: false,
89
+ transformFunction: null
90
+ },
91
+ spanId: {
92
+ classPropertyName: "spanId",
93
+ publicName: "spanId",
94
+ isSignal: true,
95
+ isRequired: false,
96
+ transformFunction: null
97
+ },
98
+ instance: {
99
+ classPropertyName: "instance",
100
+ publicName: "instance",
101
+ isSignal: true,
102
+ isRequired: false,
103
+ transformFunction: null
104
+ },
105
+ resource: {
106
+ classPropertyName: "resource",
107
+ publicName: "resource",
108
+ isSignal: true,
109
+ isRequired: false,
110
+ transformFunction: null
111
+ }
112
+ },
113
+ ngImport: i0,
114
+ template: `
115
+ <jc-context-bar><h1>Logs</h1></jc-context-bar>
116
+ <form class="jc-filter-form" (ngSubmit)="apply(f.value)" #f="ngForm">
117
+ <mat-form-field subscriptSizing="dynamic">
118
+ <mat-label>Service</mat-label>
119
+ <mat-select name="service" [ngModel]="service() ?? ''">
120
+ <mat-option value="">Any</mat-option>
121
+ @for (s of services.value() ?? []; track s.id) { <mat-option [value]="s.id">{{ s.key }}</mat-option> }
122
+ </mat-select>
123
+ </mat-form-field>
124
+ <mat-form-field subscriptSizing="dynamic" class="jc-field-sm">
125
+ <mat-label>Severity at least</mat-label>
126
+ <mat-select name="severity" [ngModel]="severity() ?? ''">
127
+ <mat-option value="">Any</mat-option><mat-option value="5">Debug</mat-option><mat-option value="9">Info</mat-option>
128
+ <mat-option value="13">Warn</mat-option><mat-option value="17">Error</mat-option><mat-option value="21">Fatal</mat-option>
129
+ </mat-select>
130
+ </mat-form-field>
131
+ <mat-form-field subscriptSizing="dynamic" class="jc-field-wide"><mat-label>Message contains</mat-label><input matInput name="q" [ngModel]="q() ?? ''"></mat-form-field>
132
+ <mat-form-field subscriptSizing="dynamic"><mat-label>Trace ID</mat-label><input matInput name="trace" [ngModel]="trace() ?? ''"></mat-form-field>
133
+ <mat-form-field subscriptSizing="dynamic"><mat-label>Span ID</mat-label><input matInput name="spanId" [ngModel]="spanId() ?? ''"></mat-form-field>
134
+ <button mat-flat-button type="submit">Search</button>
135
+ <button mat-button type="button" (click)="clear()">Clear</button>
136
+ </form>
137
+ <jc-log-table [query]="query()" />`,
138
+ isInline: true,
139
+ dependencies: [
140
+ {
141
+ kind: "ngmodule",
142
+ type: FormsModule
143
+ },
144
+ {
145
+ kind: "directive",
146
+ type: i1.ɵNgNoValidate,
147
+ selector: "form:not([ngNoForm]):not([ngNativeValidate])"
148
+ },
149
+ {
150
+ kind: "directive",
151
+ type: i1.DefaultValueAccessor,
152
+ selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]"
153
+ },
154
+ {
155
+ kind: "directive",
156
+ type: i1.NgControlStatus,
157
+ selector: "[formControlName],[ngModel],[formControl]"
158
+ },
159
+ {
160
+ kind: "directive",
161
+ type: i1.NgControlStatusGroup,
162
+ selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]"
163
+ },
164
+ {
165
+ kind: "directive",
166
+ type: i1.NgModel,
167
+ selector: "[ngModel]:not([formControlName]):not([formControl])",
168
+ inputs: [
169
+ "name",
170
+ "disabled",
171
+ "ngModel",
172
+ "ngModelOptions"
173
+ ],
174
+ outputs: ["ngModelChange"],
175
+ exportAs: ["ngModel"]
176
+ },
177
+ {
178
+ kind: "directive",
179
+ type: i1.NgForm,
180
+ selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]",
181
+ inputs: ["ngFormOptions"],
182
+ outputs: ["ngSubmit"],
183
+ exportAs: ["ngForm"]
184
+ },
185
+ {
186
+ kind: "ngmodule",
187
+ type: MatButtonModule
188
+ },
189
+ {
190
+ kind: "component",
191
+ type: i2.MatButton,
192
+ selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ",
193
+ inputs: ["matButton"],
194
+ exportAs: ["matButton", "matAnchor"]
195
+ },
196
+ {
197
+ kind: "ngmodule",
198
+ type: MatFormFieldModule
199
+ },
200
+ {
201
+ kind: "component",
202
+ type: i3.MatFormField,
203
+ selector: "mat-form-field",
204
+ inputs: [
205
+ "hideRequiredMarker",
206
+ "color",
207
+ "floatLabel",
208
+ "appearance",
209
+ "subscriptSizing",
210
+ "hintLabel"
211
+ ],
212
+ exportAs: ["matFormField"]
213
+ },
214
+ {
215
+ kind: "directive",
216
+ type: i3.MatLabel,
217
+ selector: "mat-label"
218
+ },
219
+ {
220
+ kind: "ngmodule",
221
+ type: MatInputModule
222
+ },
223
+ {
224
+ kind: "directive",
225
+ type: i4.MatInput,
226
+ selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",
227
+ inputs: [
228
+ "disabled",
229
+ "id",
230
+ "placeholder",
231
+ "name",
232
+ "required",
233
+ "type",
234
+ "errorStateMatcher",
235
+ "aria-describedby",
236
+ "value",
237
+ "readonly",
238
+ "disabledInteractive"
239
+ ],
240
+ exportAs: ["matInput"]
241
+ },
242
+ {
243
+ kind: "ngmodule",
244
+ type: MatSelectModule
245
+ },
246
+ {
247
+ kind: "component",
248
+ type: i3.MatSelect,
249
+ selector: "mat-select",
250
+ inputs: [
251
+ "aria-describedby",
252
+ "panelClass",
253
+ "disabled",
254
+ "disableRipple",
255
+ "tabIndex",
256
+ "hideSingleSelectionIndicator",
257
+ "placeholder",
258
+ "required",
259
+ "multiple",
260
+ "disableOptionCentering",
261
+ "compareWith",
262
+ "value",
263
+ "aria-label",
264
+ "aria-labelledby",
265
+ "errorStateMatcher",
266
+ "typeaheadDebounceInterval",
267
+ "sortComparator",
268
+ "id",
269
+ "panelWidth",
270
+ "canSelectNullableOptions"
271
+ ],
272
+ outputs: [
273
+ "openedChange",
274
+ "opened",
275
+ "closed",
276
+ "selectionChange",
277
+ "valueChange"
278
+ ],
279
+ exportAs: ["matSelect"]
280
+ },
281
+ {
282
+ kind: "component",
283
+ type: i3.MatOption,
284
+ selector: "mat-option",
285
+ inputs: [
286
+ "value",
287
+ "id",
288
+ "disabled"
289
+ ],
290
+ outputs: ["onSelectionChange"],
291
+ exportAs: ["matOption"]
292
+ },
293
+ {
294
+ kind: "component",
295
+ type: ContextBar,
296
+ selector: "jc-context-bar"
297
+ },
298
+ {
299
+ kind: "component",
300
+ type: LogTable,
301
+ selector: "jc-log-table",
302
+ inputs: ["query", "compact"]
303
+ }
304
+ ],
305
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
306
+ });
307
+ };
308
+ i0.ɵɵngDeclareClassMetadata({
309
+ minVersion: "12.0.0",
310
+ version: "22.2.4",
311
+ ngImport: i0,
312
+ type: LogsPage,
313
+ decorators: [{
314
+ type: Component,
315
+ args: [{
316
+ changeDetection: ChangeDetectionStrategy.OnPush,
317
+ imports: [
318
+ FormsModule,
319
+ MatButtonModule,
320
+ MatFormFieldModule,
321
+ MatInputModule,
322
+ MatSelectModule,
323
+ ContextBar,
324
+ LogTable
325
+ ],
326
+ template: `
327
+ <jc-context-bar><h1>Logs</h1></jc-context-bar>
328
+ <form class="jc-filter-form" (ngSubmit)="apply(f.value)" #f="ngForm">
329
+ <mat-form-field subscriptSizing="dynamic">
330
+ <mat-label>Service</mat-label>
331
+ <mat-select name="service" [ngModel]="service() ?? ''">
332
+ <mat-option value="">Any</mat-option>
333
+ @for (s of services.value() ?? []; track s.id) { <mat-option [value]="s.id">{{ s.key }}</mat-option> }
334
+ </mat-select>
335
+ </mat-form-field>
336
+ <mat-form-field subscriptSizing="dynamic" class="jc-field-sm">
337
+ <mat-label>Severity at least</mat-label>
338
+ <mat-select name="severity" [ngModel]="severity() ?? ''">
339
+ <mat-option value="">Any</mat-option><mat-option value="5">Debug</mat-option><mat-option value="9">Info</mat-option>
340
+ <mat-option value="13">Warn</mat-option><mat-option value="17">Error</mat-option><mat-option value="21">Fatal</mat-option>
341
+ </mat-select>
342
+ </mat-form-field>
343
+ <mat-form-field subscriptSizing="dynamic" class="jc-field-wide"><mat-label>Message contains</mat-label><input matInput name="q" [ngModel]="q() ?? ''"></mat-form-field>
344
+ <mat-form-field subscriptSizing="dynamic"><mat-label>Trace ID</mat-label><input matInput name="trace" [ngModel]="trace() ?? ''"></mat-form-field>
345
+ <mat-form-field subscriptSizing="dynamic"><mat-label>Span ID</mat-label><input matInput name="spanId" [ngModel]="spanId() ?? ''"></mat-form-field>
346
+ <button mat-flat-button type="submit">Search</button>
347
+ <button mat-button type="button" (click)="clear()">Clear</button>
348
+ </form>
349
+ <jc-log-table [query]="query()" />`
350
+ }]
351
+ }],
352
+ propDecorators: {
353
+ service: [{
354
+ type: i0.Input,
355
+ args: [{
356
+ isSignal: true,
357
+ alias: "service",
358
+ required: false
359
+ }]
360
+ }],
361
+ severity: [{
362
+ type: i0.Input,
363
+ args: [{
364
+ isSignal: true,
365
+ alias: "severity",
366
+ required: false
367
+ }]
368
+ }],
369
+ q: [{
370
+ type: i0.Input,
371
+ args: [{
372
+ isSignal: true,
373
+ alias: "q",
374
+ required: false
375
+ }]
376
+ }],
377
+ trace: [{
378
+ type: i0.Input,
379
+ args: [{
380
+ isSignal: true,
381
+ alias: "trace",
382
+ required: false
383
+ }]
384
+ }],
385
+ spanId: [{
386
+ type: i0.Input,
387
+ args: [{
388
+ isSignal: true,
389
+ alias: "spanId",
390
+ required: false
391
+ }]
392
+ }],
393
+ instance: [{
394
+ type: i0.Input,
395
+ args: [{
396
+ isSignal: true,
397
+ alias: "instance",
398
+ required: false
399
+ }]
400
+ }],
401
+ resource: [{
402
+ type: i0.Input,
403
+ args: [{
404
+ isSignal: true,
405
+ alias: "resource",
406
+ required: false
407
+ }]
408
+ }]
409
+ }
410
+ });
411
+ export { LogsPage };
412
+
413
+ //# sourceMappingURL=juice-js-observability-logs.page-CZNbTl2Q.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"juice-js-observability-logs.page-CZNbTl2Q.mjs","names":[],"sources":["../../../../projects/juice-js/observability/src/lib/pages/logs.page.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, inject, input } from '@angular/core';\nimport { apiResource } from '../shared/resource';\nimport { FormsModule } from '@angular/forms';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatFormFieldModule } from '@angular/material/form-field';\nimport { MatInputModule } from '@angular/material/input';\nimport { MatSelectModule } from '@angular/material/select';\nimport { Router } from '@angular/router';\nimport { map } from 'rxjs';\nimport { ApiService } from '../core/api.service';\nimport { ContextService } from '../core/context.service';\nimport { ContextBar } from '../shared/ui';\nimport { LogTable } from '../shared/telemetry';\n\n/** Log search (Console requirements §7): by service, severity, text, trace or span; each record links to its trace. */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [FormsModule, MatButtonModule, MatFormFieldModule, MatInputModule, MatSelectModule, ContextBar, LogTable],\n template: `\n <jc-context-bar><h1>Logs</h1></jc-context-bar>\n <form class=\"jc-filter-form\" (ngSubmit)=\"apply(f.value)\" #f=\"ngForm\">\n <mat-form-field subscriptSizing=\"dynamic\">\n <mat-label>Service</mat-label>\n <mat-select name=\"service\" [ngModel]=\"service() ?? ''\">\n <mat-option value=\"\">Any</mat-option>\n @for (s of services.value() ?? []; track s.id) { <mat-option [value]=\"s.id\">{{ s.key }}</mat-option> }\n </mat-select>\n </mat-form-field>\n <mat-form-field subscriptSizing=\"dynamic\" class=\"jc-field-sm\">\n <mat-label>Severity at least</mat-label>\n <mat-select name=\"severity\" [ngModel]=\"severity() ?? ''\">\n <mat-option value=\"\">Any</mat-option><mat-option value=\"5\">Debug</mat-option><mat-option value=\"9\">Info</mat-option>\n <mat-option value=\"13\">Warn</mat-option><mat-option value=\"17\">Error</mat-option><mat-option value=\"21\">Fatal</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field subscriptSizing=\"dynamic\" class=\"jc-field-wide\"><mat-label>Message contains</mat-label><input matInput name=\"q\" [ngModel]=\"q() ?? ''\"></mat-form-field>\n <mat-form-field subscriptSizing=\"dynamic\"><mat-label>Trace ID</mat-label><input matInput name=\"trace\" [ngModel]=\"trace() ?? ''\"></mat-form-field>\n <mat-form-field subscriptSizing=\"dynamic\"><mat-label>Span ID</mat-label><input matInput name=\"spanId\" [ngModel]=\"spanId() ?? ''\"></mat-form-field>\n <button mat-flat-button type=\"submit\">Search</button>\n <button mat-button type=\"button\" (click)=\"clear()\">Clear</button>\n </form>\n <jc-log-table [query]=\"query()\" />`,\n})\nexport class LogsPage {\n protected readonly ctx = inject(ContextService);\n private readonly api = inject(ApiService);\n private readonly router = inject(Router);\n\n readonly service = input<string>();\n readonly severity = input<string>();\n readonly q = input<string>();\n readonly trace = input<string>();\n readonly spanId = input<string>();\n readonly instance = input<string>();\n readonly resource = input<string>();\n\n protected readonly services = apiResource({ stream: () => this.api.resources('service').pipe(map(p => p.items)) });\n protected readonly query = computed(() => ({\n serviceId: this.service(), minSeverity: this.severity(), q: this.q(), traceId: this.trace(), spanId: this.spanId(),\n instanceId: this.instance(), resourceId: this.resource(),\n }));\n\n apply(value: Record<string, unknown>) {\n const queryParams: Record<string, unknown> = {};\n for (const [key, v] of Object.entries(value)) queryParams[key] = v === '' || v === undefined ? null : v;\n void this.router.navigate([], { queryParams, queryParamsHandling: 'merge' });\n }\n\n clear() { void this.router.navigate([], { queryParams: this.ctx.keep() }); }\n}\n"],"mappings":"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"}