@adonis-agora/telescope 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/dist/configure.d.ts.map +1 -1
- package/dist/configure.js +6 -0
- package/dist/configure.js.map +1 -1
- package/dist/providers/telescope_ai_provider.d.ts +9 -1
- package/dist/providers/telescope_ai_provider.d.ts.map +1 -1
- package/dist/providers/telescope_ai_provider.js +22 -2
- package/dist/providers/telescope_ai_provider.js.map +1 -1
- package/dist/providers/telescope_alerts_provider.d.ts +1 -0
- package/dist/providers/telescope_alerts_provider.d.ts.map +1 -1
- package/dist/providers/telescope_alerts_provider.js +37 -1
- package/dist/providers/telescope_alerts_provider.js.map +1 -1
- package/dist/providers/telescope_mcp_provider.d.ts +26 -0
- package/dist/providers/telescope_mcp_provider.d.ts.map +1 -0
- package/dist/providers/telescope_mcp_provider.js +114 -0
- package/dist/providers/telescope_mcp_provider.js.map +1 -0
- package/dist/providers/telescope_provider.d.ts +8 -0
- package/dist/providers/telescope_provider.d.ts.map +1 -1
- package/dist/providers/telescope_provider.js +56 -1
- package/dist/providers/telescope_provider.js.map +1 -1
- package/dist/providers/telescope_ui_provider.d.ts +2 -0
- package/dist/providers/telescope_ui_provider.d.ts.map +1 -1
- package/dist/providers/telescope_ui_provider.js +106 -22
- package/dist/providers/telescope_ui_provider.js.map +1 -1
- package/dist/providers/telescope_watchers_provider.d.ts +13 -2
- package/dist/providers/telescope_watchers_provider.d.ts.map +1 -1
- package/dist/providers/telescope_watchers_provider.js +57 -7
- package/dist/providers/telescope_watchers_provider.js.map +1 -1
- package/dist/src/ai/define_config.d.ts +39 -7
- package/dist/src/ai/define_config.d.ts.map +1 -1
- package/dist/src/ai/define_config.js +14 -4
- package/dist/src/ai/define_config.js.map +1 -1
- package/dist/src/ai/diagnosis_coordinator.d.ts +106 -0
- package/dist/src/ai/diagnosis_coordinator.d.ts.map +1 -0
- package/dist/src/ai/diagnosis_coordinator.js +143 -0
- package/dist/src/ai/diagnosis_coordinator.js.map +1 -0
- package/dist/src/ai/factory.d.ts +8 -5
- package/dist/src/ai/factory.d.ts.map +1 -1
- package/dist/src/ai/factory.js +20 -8
- package/dist/src/ai/factory.js.map +1 -1
- package/dist/src/ai/index.d.ts +3 -1
- package/dist/src/ai/index.d.ts.map +1 -1
- package/dist/src/ai/index.js +3 -1
- package/dist/src/ai/index.js.map +1 -1
- package/dist/src/alerts/alert_rule.d.ts +79 -11
- package/dist/src/alerts/alert_rule.d.ts.map +1 -1
- package/dist/src/alerts/alerter.d.ts +11 -1
- package/dist/src/alerts/alerter.d.ts.map +1 -1
- package/dist/src/alerts/alerter.js +21 -1
- package/dist/src/alerts/alerter.js.map +1 -1
- package/dist/src/alerts/alerter_service.d.ts +103 -0
- package/dist/src/alerts/alerter_service.d.ts.map +1 -0
- package/dist/src/alerts/alerter_service.js +215 -0
- package/dist/src/alerts/alerter_service.js.map +1 -0
- package/dist/src/alerts/index.d.ts +4 -2
- package/dist/src/alerts/index.d.ts.map +1 -1
- package/dist/src/alerts/index.js +4 -2
- package/dist/src/alerts/index.js.map +1 -1
- package/dist/src/alerts/slack_format.d.ts.map +1 -1
- package/dist/src/alerts/slack_format.js +35 -2
- package/dist/src/alerts/slack_format.js.map +1 -1
- package/dist/src/client_errors/config.d.ts +66 -0
- package/dist/src/client_errors/config.d.ts.map +1 -0
- package/dist/src/client_errors/config.js +17 -0
- package/dist/src/client_errors/config.js.map +1 -0
- package/dist/src/client_errors/index.d.ts +5 -0
- package/dist/src/client_errors/index.d.ts.map +1 -0
- package/dist/src/client_errors/index.js +5 -0
- package/dist/src/client_errors/index.js.map +1 -0
- package/dist/src/client_errors/ingestor.d.ts +87 -0
- package/dist/src/client_errors/ingestor.d.ts.map +1 -0
- package/dist/src/client_errors/ingestor.js +135 -0
- package/dist/src/client_errors/ingestor.js.map +1 -0
- package/dist/src/client_errors/rate_limiter.d.ts +53 -0
- package/dist/src/client_errors/rate_limiter.d.ts.map +1 -0
- package/dist/src/client_errors/rate_limiter.js +83 -0
- package/dist/src/client_errors/rate_limiter.js.map +1 -0
- package/dist/src/client_errors/validation.d.ts +62 -0
- package/dist/src/client_errors/validation.d.ts.map +1 -0
- package/dist/src/client_errors/validation.js +109 -0
- package/dist/src/client_errors/validation.js.map +1 -0
- package/dist/src/define_config.d.ts +120 -0
- package/dist/src/define_config.d.ts.map +1 -1
- package/dist/src/define_config.js +41 -0
- package/dist/src/define_config.js.map +1 -1
- package/dist/src/entry.d.ts +20 -0
- package/dist/src/entry.d.ts.map +1 -1
- package/dist/src/entry.js +20 -0
- package/dist/src/entry.js.map +1 -1
- package/dist/src/index.d.ts +16 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +15 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/define_config.d.ts +57 -0
- package/dist/src/mcp/define_config.d.ts.map +1 -0
- package/dist/src/mcp/define_config.js +35 -0
- package/dist/src/mcp/define_config.js.map +1 -0
- package/dist/src/mcp/index.d.ts +7 -0
- package/dist/src/mcp/index.d.ts.map +1 -0
- package/dist/src/mcp/index.js +7 -0
- package/dist/src/mcp/index.js.map +1 -0
- package/dist/src/mcp/server.d.ts +89 -0
- package/dist/src/mcp/server.d.ts.map +1 -0
- package/dist/src/mcp/server.js +279 -0
- package/dist/src/mcp/server.js.map +1 -0
- package/dist/src/metrics/pulse.d.ts +158 -0
- package/dist/src/metrics/pulse.d.ts.map +1 -0
- package/dist/src/metrics/pulse.js +414 -0
- package/dist/src/metrics/pulse.js.map +1 -0
- package/dist/src/overload_guard.d.ts +77 -0
- package/dist/src/overload_guard.d.ts.map +1 -0
- package/dist/src/overload_guard.js +134 -0
- package/dist/src/overload_guard.js.map +1 -0
- package/dist/src/pruner.d.ts +93 -0
- package/dist/src/pruner.d.ts.map +1 -0
- package/dist/src/pruner.js +120 -0
- package/dist/src/pruner.js.map +1 -0
- package/dist/src/registry.d.ts +26 -0
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/registry.js +19 -0
- package/dist/src/registry.js.map +1 -1
- package/dist/src/service.d.ts +16 -1
- package/dist/src/service.d.ts.map +1 -1
- package/dist/src/service.js +19 -1
- package/dist/src/service.js.map +1 -1
- package/dist/src/telescope_middleware.d.ts.map +1 -1
- package/dist/src/telescope_middleware.js +3 -1
- package/dist/src/telescope_middleware.js.map +1 -1
- package/dist/src/ui/api.d.ts +9 -1
- package/dist/src/ui/api.d.ts.map +1 -1
- package/dist/src/ui/api.js +23 -1
- package/dist/src/ui/api.js.map +1 -1
- package/dist/src/ui/auth.d.ts +112 -0
- package/dist/src/ui/auth.d.ts.map +1 -0
- package/dist/src/ui/auth.js +130 -0
- package/dist/src/ui/auth.js.map +1 -0
- package/dist/src/ui/dashboard_auth.d.ts +34 -0
- package/dist/src/ui/dashboard_auth.d.ts.map +1 -0
- package/dist/src/ui/dashboard_auth.js +57 -0
- package/dist/src/ui/dashboard_auth.js.map +1 -0
- package/dist/src/ui/define_config.d.ts +15 -0
- package/dist/src/ui/define_config.d.ts.map +1 -1
- package/dist/src/ui/define_config.js +4 -0
- package/dist/src/ui/define_config.js.map +1 -1
- package/dist/src/ui/index.d.ts +7 -1
- package/dist/src/ui/index.d.ts.map +1 -1
- package/dist/src/ui/index.js +6 -1
- package/dist/src/ui/index.js.map +1 -1
- package/dist/src/ui/login_page.d.ts +23 -0
- package/dist/src/ui/login_page.d.ts.map +1 -0
- package/dist/src/ui/login_page.js +170 -0
- package/dist/src/ui/login_page.js.map +1 -0
- package/dist/src/ui/session_cookie.d.ts +42 -0
- package/dist/src/ui/session_cookie.d.ts.map +1 -0
- package/dist/src/ui/session_cookie.js +97 -0
- package/dist/src/ui/session_cookie.js.map +1 -0
- package/dist/src/watchers/define_config.d.ts +115 -12
- package/dist/src/watchers/define_config.d.ts.map +1 -1
- package/dist/src/watchers/define_config.js +48 -11
- package/dist/src/watchers/define_config.js.map +1 -1
- package/dist/src/watchers/http_client_watcher.d.ts +91 -31
- package/dist/src/watchers/http_client_watcher.d.ts.map +1 -1
- package/dist/src/watchers/http_client_watcher.js +161 -53
- package/dist/src/watchers/http_client_watcher.js.map +1 -1
- package/dist/src/watchers/index.d.ts +9 -5
- package/dist/src/watchers/index.d.ts.map +1 -1
- package/dist/src/watchers/index.js +6 -2
- package/dist/src/watchers/index.js.map +1 -1
- package/dist/src/watchers/lucid_query_watcher.d.ts +20 -2
- package/dist/src/watchers/lucid_query_watcher.d.ts.map +1 -1
- package/dist/src/watchers/lucid_query_watcher.js +44 -10
- package/dist/src/watchers/lucid_query_watcher.js.map +1 -1
- package/dist/src/watchers/profiling_watcher.d.ts +144 -0
- package/dist/src/watchers/profiling_watcher.d.ts.map +1 -0
- package/dist/src/watchers/profiling_watcher.js +231 -0
- package/dist/src/watchers/profiling_watcher.js.map +1 -0
- package/dist/src/watchers/query_family_hash.d.ts +7 -2
- package/dist/src/watchers/query_family_hash.d.ts.map +1 -1
- package/dist/src/watchers/query_family_hash.js +8 -3
- package/dist/src/watchers/query_family_hash.js.map +1 -1
- package/dist/src/watchers/record.d.ts.map +1 -1
- package/dist/src/watchers/record.js +4 -0
- package/dist/src/watchers/record.js.map +1 -1
- package/dist/src/watchers/schedule_watcher.d.ts +143 -0
- package/dist/src/watchers/schedule_watcher.d.ts.map +1 -0
- package/dist/src/watchers/schedule_watcher.js +195 -0
- package/dist/src/watchers/schedule_watcher.js.map +1 -0
- package/dist/stubs/config/telescope.stub +0 -65
- package/dist/stubs/config/telescope_ai.stub +0 -36
- package/dist/stubs/config/telescope_alerts.stub +0 -47
- package/dist/stubs/config/telescope_mcp.stub +0 -0
- package/dist/stubs/config/telescope_ui.stub +0 -53
- package/dist/stubs/config/telescope_watchers.stub +0 -41
- package/dist/stubs/database/migrations/create_telescope_entries_table.stub +2 -2
- package/package.json +12 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alerter.js","sourceRoot":"","sources":["../../../src/alerts/alerter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"alerter.js","sourceRoot":"","sources":["../../../src/alerts/alerter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { StatsResult } from '../metrics/stats.js';
|
|
2
|
+
import type { ResolvedAlerts } from './alert_rule.js';
|
|
3
|
+
/**
|
|
4
|
+
* The narrow read the {@link AlerterService} needs from the metrics layer:
|
|
5
|
+
* per-type windowed stats. `MetricsService` satisfies this structurally, so the
|
|
6
|
+
* service reuses the SAME `summarizeStats`/`percentile` aggregation the dashboard
|
|
7
|
+
* shows and NEVER re-implements windowed aggregation. A test can pass any object
|
|
8
|
+
* with a `getStats`.
|
|
9
|
+
*/
|
|
10
|
+
export interface MetricSource {
|
|
11
|
+
getStats(query: {
|
|
12
|
+
type: string;
|
|
13
|
+
windowMs: number;
|
|
14
|
+
buckets?: number;
|
|
15
|
+
}): Promise<StatsResult>;
|
|
16
|
+
}
|
|
17
|
+
export interface AlerterServiceDeps {
|
|
18
|
+
/** Boot-resolved alerting config (channels, cooldown, rules, instanceId). */
|
|
19
|
+
alerts: ResolvedAlerts;
|
|
20
|
+
/** Windowed metrics source (typically the core `MetricsService`). */
|
|
21
|
+
metrics: MetricSource;
|
|
22
|
+
/** Wall-clock seam (ms). Defaults to `Date.now`. */
|
|
23
|
+
now?: () => number;
|
|
24
|
+
/** Failure log sink. Defaults to `console.warn`. */
|
|
25
|
+
logger?: (message: string) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Returns `true` while the overload guard has shed load — evaluation is skipped
|
|
28
|
+
* so a struggling host isn't scanned for alerts. Defaults to the shared
|
|
29
|
+
* telescope runtime's `paused` flag.
|
|
30
|
+
*/
|
|
31
|
+
isPaused?: () => boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Interval-driven, stateful threshold alerting (the `metric-threshold` rule).
|
|
35
|
+
*
|
|
36
|
+
* A plain service in the shape of `MetricsService`/`PulseService`: on an unref'd
|
|
37
|
+
* timer it evaluates every configured `metric-threshold` rule over its trailing
|
|
38
|
+
* window by reading the injected {@link MetricSource} (reusing the dashboard's own
|
|
39
|
+
* `summarizeStats`/`percentile` aggregation — it computes NO aggregates itself),
|
|
40
|
+
* and it maintains a per-rule RAISE/RESOLVE state machine:
|
|
41
|
+
*
|
|
42
|
+
* - not active + metric crosses the threshold → RAISE (dispatch `status:'firing'`);
|
|
43
|
+
* - active + metric no longer crosses → RESOLVE (dispatch `status:'resolved'`);
|
|
44
|
+
* - active + still crossing → dedup (no duplicate raise);
|
|
45
|
+
* - a just-resolved rule is held down for `cooldownMs` before it can re-raise
|
|
46
|
+
* (flap control).
|
|
47
|
+
*
|
|
48
|
+
* Each dispatched alert fans out to ALL channels concurrently; one channel failing
|
|
49
|
+
* never blocks the others. NEVER throws into the caller/timer: an evaluation or
|
|
50
|
+
* channel failure is warn-logged (rate-limited per channel) and otherwise swallowed.
|
|
51
|
+
*/
|
|
52
|
+
export declare class AlerterService {
|
|
53
|
+
private readonly deps;
|
|
54
|
+
private readonly now;
|
|
55
|
+
private readonly logger;
|
|
56
|
+
private readonly isPaused;
|
|
57
|
+
private timer;
|
|
58
|
+
/** Rule indices currently in the FIRING state (the dedup + resolve keys). */
|
|
59
|
+
private readonly active;
|
|
60
|
+
/** Per-rule wall time of the last RESOLVE, for the post-resolve cooldown. */
|
|
61
|
+
private readonly lastResolvedAt;
|
|
62
|
+
/** Channels we've already warned about (rate-limit failure logs by name). */
|
|
63
|
+
private readonly warnedChannels;
|
|
64
|
+
constructor(deps: AlerterServiceDeps);
|
|
65
|
+
/** Start the unref'd evaluation interval. Idempotent. */
|
|
66
|
+
start(): void;
|
|
67
|
+
/** Stop the interval (shutdown). Idempotent. */
|
|
68
|
+
stop(): void;
|
|
69
|
+
/** Number of rules currently in the firing state (test/observability seam). */
|
|
70
|
+
get activeAlerts(): number;
|
|
71
|
+
/**
|
|
72
|
+
* Evaluate every `metric-threshold` rule once and raise/resolve accordingly.
|
|
73
|
+
* A no-op when alerting is disabled or the host is shedding load. Never throws:
|
|
74
|
+
* a single rule's evaluation error is logged and the others still run. Exposed
|
|
75
|
+
* for the timer and for deterministic tests.
|
|
76
|
+
*/
|
|
77
|
+
evaluateOnce(): Promise<void>;
|
|
78
|
+
private inCooldown;
|
|
79
|
+
/**
|
|
80
|
+
* Compute the rule's metric over its window and decide whether it crosses in the
|
|
81
|
+
* comparator direction. Returns `null` when the metric can't be evaluated (no
|
|
82
|
+
* samples, or below `minSamples` for a percentile/ratio rule) so the caller
|
|
83
|
+
* leaves the alert state unchanged.
|
|
84
|
+
*/
|
|
85
|
+
private measure;
|
|
86
|
+
/**
|
|
87
|
+
* Aggregate a single metric over `window` via the injected {@link MetricSource}
|
|
88
|
+
* — reusing the exact `summarizeStats`/`percentile` computation behind the
|
|
89
|
+
* dashboard. Returns `{ value, samples }`, or `null` when there is no data to
|
|
90
|
+
* compute a percentile/ratio from (`exception-count` never returns `null`; a
|
|
91
|
+
* count of 0 is valid).
|
|
92
|
+
*/
|
|
93
|
+
private computeMetric;
|
|
94
|
+
private buildPayload;
|
|
95
|
+
/**
|
|
96
|
+
* Fan the payload out to every channel concurrently. Each channel's failure is
|
|
97
|
+
* isolated (`Promise.allSettled`) and warn-logged ONCE per channel name so a
|
|
98
|
+
* persistently-down destination doesn't flood the logs. Never rejects.
|
|
99
|
+
*/
|
|
100
|
+
private dispatch;
|
|
101
|
+
private warnChannelFailure;
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=alerter_service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alerter_service.d.ts","sourceRoot":"","sources":["../../../src/alerts/alerter_service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGvD,OAAO,KAAK,EAAwC,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAM5F;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CAC7F;AAED,MAAM,WAAW,kBAAkB;IACjC,6EAA6E;IAC7E,MAAM,EAAE,cAAc,CAAC;IACvB,qEAAqE;IACrE,OAAO,EAAE,YAAY,CAAC;IACtB,oDAAoD;IACpD,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,oDAAoD;IACpD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,cAAc;IAYb,OAAO,CAAC,QAAQ,CAAC,IAAI;IAXjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4B;IACnD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IACzC,OAAO,CAAC,KAAK,CAA+C;IAC5D,6EAA6E;IAC7E,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,6EAA6E;IAC7E,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAC5D,6EAA6E;IAC7E,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;gBAEvB,IAAI,EAAE,kBAAkB;IAcrD,yDAAyD;IACzD,KAAK,IAAI,IAAI;IAUb,gDAAgD;IAChD,IAAI,IAAI,IAAI;IAOZ,+EAA+E;IAC/E,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED;;;;;OAKG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAgCnC,OAAO,CAAC,UAAU;IAMlB;;;;;OAKG;YACW,OAAO;IAiBrB;;;;;;OAMG;YACW,aAAa;IA0B3B,OAAO,CAAC,YAAY;IAoBpB;;;;OAIG;YACW,QAAQ;IAWtB,OAAO,CAAC,kBAAkB;CAM3B"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { EntryType } from '../entry.js';
|
|
2
|
+
import { getTelescopeRuntime } from '../registry.js';
|
|
3
|
+
import { durationToMs } from './parse_duration.js';
|
|
4
|
+
/**
|
|
5
|
+
* Interval-driven, stateful threshold alerting (the `metric-threshold` rule).
|
|
6
|
+
*
|
|
7
|
+
* A plain service in the shape of `MetricsService`/`PulseService`: on an unref'd
|
|
8
|
+
* timer it evaluates every configured `metric-threshold` rule over its trailing
|
|
9
|
+
* window by reading the injected {@link MetricSource} (reusing the dashboard's own
|
|
10
|
+
* `summarizeStats`/`percentile` aggregation — it computes NO aggregates itself),
|
|
11
|
+
* and it maintains a per-rule RAISE/RESOLVE state machine:
|
|
12
|
+
*
|
|
13
|
+
* - not active + metric crosses the threshold → RAISE (dispatch `status:'firing'`);
|
|
14
|
+
* - active + metric no longer crosses → RESOLVE (dispatch `status:'resolved'`);
|
|
15
|
+
* - active + still crossing → dedup (no duplicate raise);
|
|
16
|
+
* - a just-resolved rule is held down for `cooldownMs` before it can re-raise
|
|
17
|
+
* (flap control).
|
|
18
|
+
*
|
|
19
|
+
* Each dispatched alert fans out to ALL channels concurrently; one channel failing
|
|
20
|
+
* never blocks the others. NEVER throws into the caller/timer: an evaluation or
|
|
21
|
+
* channel failure is warn-logged (rate-limited per channel) and otherwise swallowed.
|
|
22
|
+
*/
|
|
23
|
+
export class AlerterService {
|
|
24
|
+
deps;
|
|
25
|
+
now;
|
|
26
|
+
logger;
|
|
27
|
+
isPaused;
|
|
28
|
+
timer = null;
|
|
29
|
+
/** Rule indices currently in the FIRING state (the dedup + resolve keys). */
|
|
30
|
+
active = new Set();
|
|
31
|
+
/** Per-rule wall time of the last RESOLVE, for the post-resolve cooldown. */
|
|
32
|
+
lastResolvedAt = new Map();
|
|
33
|
+
/** Channels we've already warned about (rate-limit failure logs by name). */
|
|
34
|
+
warnedChannels = new Set();
|
|
35
|
+
constructor(deps) {
|
|
36
|
+
this.deps = deps;
|
|
37
|
+
this.now = deps.now ?? Date.now;
|
|
38
|
+
this.logger = deps.logger ?? ((message) => console.warn(message));
|
|
39
|
+
this.isPaused =
|
|
40
|
+
deps.isPaused ??
|
|
41
|
+
(() => {
|
|
42
|
+
try {
|
|
43
|
+
return getTelescopeRuntime().paused;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/** Start the unref'd evaluation interval. Idempotent. */
|
|
51
|
+
start() {
|
|
52
|
+
if (this.timer !== null)
|
|
53
|
+
return;
|
|
54
|
+
this.timer = setInterval(() => {
|
|
55
|
+
this.evaluateOnce().catch((error) => {
|
|
56
|
+
this.logger(`Telescope alert evaluation failed: ${asMessage(error)}`);
|
|
57
|
+
});
|
|
58
|
+
}, this.deps.alerts.intervalMs);
|
|
59
|
+
this.timer.unref?.();
|
|
60
|
+
}
|
|
61
|
+
/** Stop the interval (shutdown). Idempotent. */
|
|
62
|
+
stop() {
|
|
63
|
+
if (this.timer !== null) {
|
|
64
|
+
clearInterval(this.timer);
|
|
65
|
+
this.timer = null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** Number of rules currently in the firing state (test/observability seam). */
|
|
69
|
+
get activeAlerts() {
|
|
70
|
+
return this.active.size;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Evaluate every `metric-threshold` rule once and raise/resolve accordingly.
|
|
74
|
+
* A no-op when alerting is disabled or the host is shedding load. Never throws:
|
|
75
|
+
* a single rule's evaluation error is logged and the others still run. Exposed
|
|
76
|
+
* for the timer and for deterministic tests.
|
|
77
|
+
*/
|
|
78
|
+
async evaluateOnce() {
|
|
79
|
+
if (!this.deps.alerts.enabled)
|
|
80
|
+
return;
|
|
81
|
+
if (this.isPaused())
|
|
82
|
+
return;
|
|
83
|
+
const nowMs = this.now();
|
|
84
|
+
for (let index = 0; index < this.deps.alerts.rules.length; index++) {
|
|
85
|
+
const rule = this.deps.alerts.rules[index];
|
|
86
|
+
if (rule === undefined || rule.type !== 'metric-threshold')
|
|
87
|
+
continue;
|
|
88
|
+
let outcome;
|
|
89
|
+
try {
|
|
90
|
+
outcome = await this.measure(rule);
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
this.logger(`Telescope alert rule '${rule.metric}' failed: ${asMessage(error)}`);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
// `null` ⇒ not enough data to decide — leave the current state untouched
|
|
97
|
+
// (a quiet window neither raises nor spuriously resolves a real alert).
|
|
98
|
+
if (outcome === null)
|
|
99
|
+
continue;
|
|
100
|
+
const isActive = this.active.has(index);
|
|
101
|
+
if (outcome.crosses) {
|
|
102
|
+
if (isActive)
|
|
103
|
+
continue; // dedup: already firing.
|
|
104
|
+
if (this.inCooldown(index, nowMs))
|
|
105
|
+
continue; // flap control after a resolve.
|
|
106
|
+
this.active.add(index);
|
|
107
|
+
await this.dispatch(this.buildPayload(rule, outcome.value, 'firing', nowMs));
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
if (!isActive)
|
|
111
|
+
continue; // nothing to resolve.
|
|
112
|
+
this.active.delete(index);
|
|
113
|
+
this.lastResolvedAt.set(index, nowMs);
|
|
114
|
+
await this.dispatch(this.buildPayload(rule, outcome.value, 'resolved', nowMs));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
inCooldown(index, nowMs) {
|
|
119
|
+
const last = this.lastResolvedAt.get(index);
|
|
120
|
+
if (last === undefined)
|
|
121
|
+
return false;
|
|
122
|
+
return nowMs - last < this.deps.alerts.cooldownMs;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Compute the rule's metric over its window and decide whether it crosses in the
|
|
126
|
+
* comparator direction. Returns `null` when the metric can't be evaluated (no
|
|
127
|
+
* samples, or below `minSamples` for a percentile/ratio rule) so the caller
|
|
128
|
+
* leaves the alert state unchanged.
|
|
129
|
+
*/
|
|
130
|
+
async measure(rule) {
|
|
131
|
+
const computed = await this.computeMetric(rule.metric, rule.window);
|
|
132
|
+
if (computed === null)
|
|
133
|
+
return null;
|
|
134
|
+
// `minSamples` guards noisy percentile/ratio pages; a raw count of 0 is a real
|
|
135
|
+
// value that must be able to auto-resolve a firing spike, so it bypasses it.
|
|
136
|
+
if (rule.metric !== 'exception-count' && computed.samples < (rule.minSamples ?? 1)) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
const crosses = rule.comparator === 'gte'
|
|
140
|
+
? computed.value >= rule.threshold
|
|
141
|
+
: computed.value <= rule.threshold;
|
|
142
|
+
return { crosses, value: computed.value };
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Aggregate a single metric over `window` via the injected {@link MetricSource}
|
|
146
|
+
* — reusing the exact `summarizeStats`/`percentile` computation behind the
|
|
147
|
+
* dashboard. Returns `{ value, samples }`, or `null` when there is no data to
|
|
148
|
+
* compute a percentile/ratio from (`exception-count` never returns `null`; a
|
|
149
|
+
* count of 0 is valid).
|
|
150
|
+
*/
|
|
151
|
+
async computeMetric(metric, window) {
|
|
152
|
+
const windowMs = durationToMs(window);
|
|
153
|
+
if (metric === 'cache-hit-rate') {
|
|
154
|
+
const stats = await this.deps.metrics.getStats({ type: EntryType.Cache, windowMs });
|
|
155
|
+
const cache = stats.cache;
|
|
156
|
+
if (cache === undefined)
|
|
157
|
+
return null;
|
|
158
|
+
const samples = cache.hits + cache.misses;
|
|
159
|
+
if (samples === 0)
|
|
160
|
+
return null;
|
|
161
|
+
return { value: cache.hitRatio, samples };
|
|
162
|
+
}
|
|
163
|
+
if (metric === 'exception-count') {
|
|
164
|
+
const stats = await this.deps.metrics.getStats({ type: EntryType.Exception, windowMs });
|
|
165
|
+
return { value: stats.total, samples: stats.total };
|
|
166
|
+
}
|
|
167
|
+
// Latency percentile metrics reuse `summarizeStats`' latency block.
|
|
168
|
+
const type = metric.startsWith('request') ? EntryType.Request : EntryType.Query;
|
|
169
|
+
const stats = await this.deps.metrics.getStats({ type, windowMs });
|
|
170
|
+
const latency = stats.latency;
|
|
171
|
+
if (latency === undefined)
|
|
172
|
+
return null;
|
|
173
|
+
const value = metric.endsWith('p99-ms') ? latency.p99 : latency.p95;
|
|
174
|
+
return { value, samples: latency.count };
|
|
175
|
+
}
|
|
176
|
+
buildPayload(rule, value, status, nowMs) {
|
|
177
|
+
return {
|
|
178
|
+
rule,
|
|
179
|
+
value,
|
|
180
|
+
threshold: rule.threshold,
|
|
181
|
+
firedAt: new Date(nowMs).toISOString(),
|
|
182
|
+
instanceId: this.deps.alerts.instanceId,
|
|
183
|
+
status,
|
|
184
|
+
metric: rule.metric,
|
|
185
|
+
...(this.deps.alerts.dashboardUrl !== null
|
|
186
|
+
? { dashboardUrl: this.deps.alerts.dashboardUrl }
|
|
187
|
+
: {}),
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Fan the payload out to every channel concurrently. Each channel's failure is
|
|
192
|
+
* isolated (`Promise.allSettled`) and warn-logged ONCE per channel name so a
|
|
193
|
+
* persistently-down destination doesn't flood the logs. Never rejects.
|
|
194
|
+
*/
|
|
195
|
+
async dispatch(payload) {
|
|
196
|
+
const results = await Promise.allSettled(this.deps.alerts.channels.map((channel) => channel.send(payload)));
|
|
197
|
+
results.forEach((result, index) => {
|
|
198
|
+
if (result.status === 'rejected') {
|
|
199
|
+
this.warnChannelFailure(this.deps.alerts.channels[index], result.reason);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
warnChannelFailure(channel, reason) {
|
|
204
|
+
if (channel === undefined)
|
|
205
|
+
return;
|
|
206
|
+
if (this.warnedChannels.has(channel.name))
|
|
207
|
+
return;
|
|
208
|
+
this.warnedChannels.add(channel.name);
|
|
209
|
+
this.logger(`Telescope alert channel '${channel.name}' failed: ${asMessage(reason)}`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
function asMessage(error) {
|
|
213
|
+
return error instanceof Error ? error.message : String(error);
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=alerter_service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alerter_service.js","sourceRoot":"","sources":["../../../src/alerts/alerter_service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
/** Keep in sync with this package's `version` in package.json. */
|
|
2
|
-
export declare const VERSION = "0.
|
|
2
|
+
export declare const VERSION = "0.5.0";
|
|
3
3
|
export { consoleChannel, customChannel, slackChannel, webhookChannel, } from './alert_channel.js';
|
|
4
4
|
export type { AlertChannel, ChannelFetch, ConsoleSink } from './alert_channel.js';
|
|
5
5
|
export { formatSlackMessage } from './slack_format.js';
|
|
6
6
|
export type { SlackChannelOptions, SlackMessage } from './slack_format.js';
|
|
7
|
-
export type { AlertPayload, AlertRule, ExceptionAlertContext, ResolvedAlerts, } from './alert_rule.js';
|
|
7
|
+
export type { AlertDiagnosis, AlertMetric, AlertPayload, AlertRule, ExceptionAlertContext, ResolvedAlerts, } from './alert_rule.js';
|
|
8
8
|
export { DEFAULT_MAX_FAMILIES, NewExceptionTracker } from './new_exception_tracker.js';
|
|
9
9
|
export { Alerter } from './alerter.js';
|
|
10
10
|
export type { AlerterDeps } from './alerter.js';
|
|
11
|
+
export { AlerterService } from './alerter_service.js';
|
|
12
|
+
export type { AlerterServiceDeps, MetricSource } from './alerter_service.js';
|
|
11
13
|
export { ExceptionPoller } from './exception_source.js';
|
|
12
14
|
export type { ExceptionPollerDeps } from './exception_source.js';
|
|
13
15
|
export { durationToMs } from './parse_duration.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/alerts/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,eAAO,MAAM,OAAO,UAAU,CAAC;AAG/B,OAAO,EACL,cAAc,EACd,aAAa,EACb,YAAY,EACZ,cAAc,GACf,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGlF,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,YAAY,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAG3E,YAAY,EACV,YAAY,EACZ,SAAS,EACT,qBAAqB,EACrB,cAAc,GACf,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAGvF,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,YAAY,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAGjE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAChF,YAAY,EACV,aAAa,EACb,WAAW,EACX,qBAAqB,GACtB,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/alerts/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,eAAO,MAAM,OAAO,UAAU,CAAC;AAG/B,OAAO,EACL,cAAc,EACd,aAAa,EACb,YAAY,EACZ,cAAc,GACf,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGlF,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,YAAY,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAG3E,YAAY,EACV,cAAc,EACd,WAAW,EACX,YAAY,EACZ,SAAS,EACT,qBAAqB,EACrB,cAAc,GACf,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAGvF,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAG7E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,YAAY,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAGjE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAChF,YAAY,EACV,aAAa,EACb,WAAW,EACX,qBAAqB,GACtB,MAAM,oBAAoB,CAAC"}
|
package/dist/src/alerts/index.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
/** Keep in sync with this package's `version` in package.json. */
|
|
2
|
-
export const VERSION = '0.
|
|
2
|
+
export const VERSION = '0.5.0';
|
|
3
3
|
// — channels —
|
|
4
4
|
export { consoleChannel, customChannel, slackChannel, webhookChannel, } from './alert_channel.js';
|
|
5
5
|
// — slack formatting —
|
|
6
6
|
export { formatSlackMessage } from './slack_format.js';
|
|
7
7
|
// — new-exception dedupe —
|
|
8
8
|
export { DEFAULT_MAX_FAMILIES, NewExceptionTracker } from './new_exception_tracker.js';
|
|
9
|
-
// — alerter (source → tracker → channels) —
|
|
9
|
+
// — alerter (exception source → tracker → channels) —
|
|
10
10
|
export { Alerter } from './alerter.js';
|
|
11
|
+
// — alerter service (interval metric-threshold rules with raise/resolve) —
|
|
12
|
+
export { AlerterService } from './alerter_service.js';
|
|
11
13
|
// — exception source (the polling hook) —
|
|
12
14
|
export { ExceptionPoller } from './exception_source.js';
|
|
13
15
|
// — duration helper —
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/alerts/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,eAAe;AACf,OAAO,EACL,cAAc,EACd,aAAa,EACb,YAAY,EACZ,cAAc,GACf,MAAM,oBAAoB,CAAC;AAG5B,uBAAuB;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/alerts/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,eAAe;AACf,OAAO,EACL,cAAc,EACd,aAAa,EACb,YAAY,EACZ,cAAc,GACf,MAAM,oBAAoB,CAAC;AAG5B,uBAAuB;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAavD,2BAA2B;AAC3B,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEvF,sDAAsD;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,2EAA2E;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,0CAA0C;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD,sBAAsB;AACtB,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,aAAa;AACb,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slack_format.d.ts","sourceRoot":"","sources":["../../../src/alerts/slack_format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAUD,UAAU,eAAe;IACvB,IAAI,EAAE,YAAY,GAAG,QAAQ,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AACD,UAAU,gBAAgB;IACxB,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,eAAe,CAAC;CACvB;AACD,UAAU,iBAAiB;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;CAC5B;AACD,UAAU,kBAAkB;IAC1B,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,eAAe,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACb;AACD,UAAU,iBAAiB;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,kBAAkB,EAAE,CAAC;CAChC;AACD,KAAK,UAAU,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,iBAAiB,CAAC;AAE3E,qFAAqF;AACrF,MAAM,WAAW,YAAY;IAC3B,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;
|
|
1
|
+
{"version":3,"file":"slack_format.d.ts","sourceRoot":"","sources":["../../../src/alerts/slack_format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAUD,UAAU,eAAe;IACvB,IAAI,EAAE,YAAY,GAAG,QAAQ,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AACD,UAAU,gBAAgB;IACxB,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,eAAe,CAAC;CACvB;AACD,UAAU,iBAAiB;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;CAC5B;AACD,UAAU,kBAAkB;IAC1B,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,eAAe,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACb;AACD,UAAU,iBAAiB;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,kBAAkB,EAAE,CAAC;CAChC;AACD,KAAK,UAAU,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,iBAAiB,CAAC;AAE3E,qFAAqF;AACrF,MAAM,WAAW,YAAY;IAC3B,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA0ED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,YAAY,EACrB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,YAAY,CAiEd"}
|
|
@@ -21,6 +21,8 @@ function ruleLabel(rule) {
|
|
|
21
21
|
return 'New exception family';
|
|
22
22
|
case 'exception-rate':
|
|
23
23
|
return 'Exception rate';
|
|
24
|
+
case 'metric-threshold':
|
|
25
|
+
return `Metric threshold (${rule.metric})`;
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
28
|
/** A Slack `mrkdwn` field pairing a bold label with a value. */
|
|
@@ -40,6 +42,30 @@ function clipStack(stack) {
|
|
|
40
42
|
return frames;
|
|
41
43
|
return `${frames.slice(0, STACK_CHAR_LIMIT)}…`;
|
|
42
44
|
}
|
|
45
|
+
/** A Slack section `text` field is capped at 3000 chars; keep the AI note under it. */
|
|
46
|
+
const DIAGNOSIS_CHAR_LIMIT = 2_800;
|
|
47
|
+
/**
|
|
48
|
+
* Render the optional AI probable-cause summary as a Slack `mrkdwn` block body:
|
|
49
|
+
* a bold "Probable cause (AI)" label with confidence, the cause, and — when
|
|
50
|
+
* present — the suggested fix. Returns `null` when no diagnosis is attached, so
|
|
51
|
+
* the caller omits the block entirely (an alert with AI off looks exactly as
|
|
52
|
+
* before).
|
|
53
|
+
*/
|
|
54
|
+
function formatDiagnosis(diagnosis) {
|
|
55
|
+
if (diagnosis === undefined)
|
|
56
|
+
return null;
|
|
57
|
+
const cause = diagnosis.cause.trim();
|
|
58
|
+
const fix = diagnosis.fix.trim();
|
|
59
|
+
if (cause === '' && fix === '')
|
|
60
|
+
return null;
|
|
61
|
+
const lines = [`*Probable cause (AI):* _${diagnosis.confidence} confidence_`];
|
|
62
|
+
if (cause !== '')
|
|
63
|
+
lines.push(cause);
|
|
64
|
+
if (fix !== '')
|
|
65
|
+
lines.push('', `*Suggested fix:* ${fix}`);
|
|
66
|
+
const text = lines.join('\n');
|
|
67
|
+
return text.length <= DIAGNOSIS_CHAR_LIMIT ? text : `${text.slice(0, DIAGNOSIS_CHAR_LIMIT)}…`;
|
|
68
|
+
}
|
|
43
69
|
/**
|
|
44
70
|
* Build the deep link to the offending exception entry in the host's external
|
|
45
71
|
* dashboard. Returns `null` when no `dashboardUrl` is configured or there is no
|
|
@@ -66,9 +92,12 @@ function dashboardLink(payload) {
|
|
|
66
92
|
* renders the header + context fields and skips the stack/button.
|
|
67
93
|
*/
|
|
68
94
|
export function formatSlackMessage(payload, options) {
|
|
69
|
-
|
|
95
|
+
// A stateful metric-threshold that has cleared renders as a green "Resolved"
|
|
96
|
+
// card so the on-call sees the all-clear without hunting for a follow-up.
|
|
97
|
+
const resolved = payload.status === 'resolved';
|
|
98
|
+
const emoji = resolved ? ':white_check_mark:' : severityEmoji(payload.rule);
|
|
70
99
|
const label = ruleLabel(payload.rule);
|
|
71
|
-
const headerText = `${emoji} ${label}`;
|
|
100
|
+
const headerText = `${emoji} ${resolved ? 'Resolved: ' : ''}${label}`;
|
|
72
101
|
const contextFields = [
|
|
73
102
|
field('Instance', payload.instanceId),
|
|
74
103
|
field('Observed', `${payload.value} (threshold ${payload.threshold})`),
|
|
@@ -95,6 +124,10 @@ export function formatSlackMessage(payload, options) {
|
|
|
95
124
|
{ type: 'header', text: { type: 'plain_text', text: headerText, emoji: true } },
|
|
96
125
|
{ type: 'section', fields: contextFields },
|
|
97
126
|
];
|
|
127
|
+
const diagnosisText = formatDiagnosis(payload.diagnosis);
|
|
128
|
+
if (diagnosisText !== null) {
|
|
129
|
+
blocks.push({ type: 'section', text: { type: 'mrkdwn', text: diagnosisText } });
|
|
130
|
+
}
|
|
98
131
|
const stack = exception ? clipStack(exception.stack) : null;
|
|
99
132
|
if (stack !== null) {
|
|
100
133
|
blocks.push({ type: 'section', text: { type: 'mrkdwn', text: `\`\`\`${stack}\`\`\`` } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slack_format.js","sourceRoot":"","sources":["../../../src/alerts/slack_format.ts"],"names":[],"mappings":"AAcA;;;;GAIG;AACH,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAC/B,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAoC7B;;;GAGG;AACH,SAAS,aAAa,CAAC,IAA0B;IAC/C,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe,IAAI,IAAI,CAAC,IAAI,KAAK,gBAAgB;QAAE,OAAO,kBAAkB,CAAC;IAC/F,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,8CAA8C;AAC9C,SAAS,SAAS,CAAC,IAA0B;IAC3C,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,eAAe;YAClB,OAAO,sBAAsB,CAAC;QAChC,KAAK,gBAAgB;YACnB,OAAO,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"slack_format.js","sourceRoot":"","sources":["../../../src/alerts/slack_format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { ClientErrorHttpContext } from './ingestor.js';
|
|
2
|
+
/** Default per-IP requests/minute when `rateLimit.perMinute` is omitted. */
|
|
3
|
+
export declare const DEFAULT_RATE_LIMIT_PER_MINUTE = 60;
|
|
4
|
+
/** Default accepted body size (32 KB) when `maxBodyBytes` is omitted. */
|
|
5
|
+
export declare const DEFAULT_MAX_BODY_BYTES = 32768;
|
|
6
|
+
/** Default route path the ingestion endpoint is mounted on. */
|
|
7
|
+
export declare const DEFAULT_CLIENT_ERRORS_PATH = "/telescope/client-errors";
|
|
8
|
+
/**
|
|
9
|
+
* Public front-end error ingestion (`POST <path>`). When enabled, browsers
|
|
10
|
+
* report errors directly to telescope, recorded as `client_exception` entries
|
|
11
|
+
* through the normal pipeline (family-hash, `failed`/`client`/`user:<id>` tags,
|
|
12
|
+
* sampling, prune, dashboard).
|
|
13
|
+
*
|
|
14
|
+
* DISABLED by default: a public, unauthenticated ingestion surface is opt-in.
|
|
15
|
+
* Unlike the NestJS port (which always mounts the controller and 404s while
|
|
16
|
+
* off), the AdonisJS provider only REGISTERS the route when `enabled` is `true`
|
|
17
|
+
* — so a disabled endpoint genuinely does not exist and a probe can't tell it is
|
|
18
|
+
* wired.
|
|
19
|
+
*
|
|
20
|
+
* Security knobs are all best-effort and PER-PROCESS: a byte cap
|
|
21
|
+
* (`maxBodyBytes`), an in-memory per-IP token bucket (`rateLimit`), and an
|
|
22
|
+
* `authorize` hook for session/header validation. Recording additionally honours
|
|
23
|
+
* the overload guard's `paused` flag (sheds while the event loop lags).
|
|
24
|
+
*/
|
|
25
|
+
export interface ClientErrorsConfig {
|
|
26
|
+
/** Master switch. Default `false` — no route is registered until enabled. */
|
|
27
|
+
enabled?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Route path the `POST` ingestion endpoint is mounted on via the AdonisJS
|
|
30
|
+
* router. Default `'/telescope/client-errors'`.
|
|
31
|
+
*/
|
|
32
|
+
path?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Hard cap on the accepted request body size in bytes. A larger body is
|
|
35
|
+
* rejected (413) BEFORE structural validation, so a hostile browser can't make
|
|
36
|
+
* telescope validate a huge payload. Default `32_768` (32 KB).
|
|
37
|
+
*/
|
|
38
|
+
maxBodyBytes?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Per-IP token-bucket rate limit. `perMinute` requests are allowed per IP per
|
|
41
|
+
* minute (default `60`); over the limit returns 429. The bucket map is bounded
|
|
42
|
+
* and per-process, so in a multi-instance deployment the EFFECTIVE limit is
|
|
43
|
+
* `perMinute × instances` — acceptable for abuse-dampening, not a hard quota.
|
|
44
|
+
*/
|
|
45
|
+
rateLimit?: {
|
|
46
|
+
perMinute?: number;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Optional gate that runs FIRST, before validation/rate-limiting. Return
|
|
50
|
+
* `false` to reject with 403 — lets a host require a session cookie or a shared
|
|
51
|
+
* header on the public endpoint. A throw is treated as a denial (fail closed)
|
|
52
|
+
* and never crashes the request.
|
|
53
|
+
*/
|
|
54
|
+
authorize?: (ctx: ClientErrorHttpContext) => boolean | Promise<boolean>;
|
|
55
|
+
}
|
|
56
|
+
/** The fully-resolved client-errors config the provider/ingestor act on. */
|
|
57
|
+
export interface ResolvedClientErrorsConfig {
|
|
58
|
+
enabled: boolean;
|
|
59
|
+
path: string;
|
|
60
|
+
maxBodyBytes: number;
|
|
61
|
+
rateLimitPerMinute: number;
|
|
62
|
+
authorize?: (ctx: ClientErrorHttpContext) => boolean | Promise<boolean>;
|
|
63
|
+
}
|
|
64
|
+
/** Apply defaults to a (possibly absent) client-errors config block. */
|
|
65
|
+
export declare function resolveClientErrors(config?: ClientErrorsConfig): ResolvedClientErrorsConfig;
|
|
66
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/client_errors/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAE5D,4EAA4E;AAC5E,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAChD,yEAAyE;AACzE,eAAO,MAAM,sBAAsB,QAAS,CAAC;AAC7C,+DAA+D;AAC/D,eAAO,MAAM,0BAA0B,6BAA6B,CAAC;AAErE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,kBAAkB;IACjC,6EAA6E;IAC7E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,SAAS,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,sBAAsB,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACzE;AAED,4EAA4E;AAC5E,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,sBAAsB,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACzE;AAED,wEAAwE;AACxE,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,0BAA0B,CAQ3F"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Default per-IP requests/minute when `rateLimit.perMinute` is omitted. */
|
|
2
|
+
export const DEFAULT_RATE_LIMIT_PER_MINUTE = 60;
|
|
3
|
+
/** Default accepted body size (32 KB) when `maxBodyBytes` is omitted. */
|
|
4
|
+
export const DEFAULT_MAX_BODY_BYTES = 32_768;
|
|
5
|
+
/** Default route path the ingestion endpoint is mounted on. */
|
|
6
|
+
export const DEFAULT_CLIENT_ERRORS_PATH = '/telescope/client-errors';
|
|
7
|
+
/** Apply defaults to a (possibly absent) client-errors config block. */
|
|
8
|
+
export function resolveClientErrors(config) {
|
|
9
|
+
return {
|
|
10
|
+
enabled: config?.enabled ?? false,
|
|
11
|
+
path: config?.path ?? DEFAULT_CLIENT_ERRORS_PATH,
|
|
12
|
+
maxBodyBytes: config?.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES,
|
|
13
|
+
rateLimitPerMinute: config?.rateLimit?.perMinute ?? DEFAULT_RATE_LIMIT_PER_MINUTE,
|
|
14
|
+
...(config?.authorize !== undefined ? { authorize: config.authorize } : {}),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/client_errors/config.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAC5E,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,CAAC;AAChD,yEAAyE;AACzE,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAC7C,+DAA+D;AAC/D,MAAM,CAAC,MAAM,0BAA0B,GAAG,0BAA0B,CAAC;AA0DrE,wEAAwE;AACxE,MAAM,UAAU,mBAAmB,CAAC,MAA2B;IAC7D,OAAO;QACL,OAAO,EAAE,MAAM,EAAE,OAAO,IAAI,KAAK;QACjC,IAAI,EAAE,MAAM,EAAE,IAAI,IAAI,0BAA0B;QAChD,YAAY,EAAE,MAAM,EAAE,YAAY,IAAI,sBAAsB;QAC5D,kBAAkB,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,IAAI,6BAA6B;QACjF,GAAG,CAAC,MAAM,EAAE,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5E,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { type ClientErrorsConfig, DEFAULT_CLIENT_ERRORS_PATH, DEFAULT_MAX_BODY_BYTES, DEFAULT_RATE_LIMIT_PER_MINUTE, resolveClientErrors, type ResolvedClientErrorsConfig, } from './config.js';
|
|
2
|
+
export { ClientErrorIngestor, type ClientErrorHttpContext, type ClientErrorIngestorDeps, type ClientErrorRequest, type ClientErrorResponse, storeRecorder, } from './ingestor.js';
|
|
3
|
+
export { ClientErrorRateLimiter, DEFAULT_MAX_TRACKED_IPS } from './rate_limiter.js';
|
|
4
|
+
export { type ClientErrorValidation, type ClientExceptionContent, userIdentityTag, validateClientErrorBody, } from './validation.js';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client_errors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EACvB,0BAA0B,EAC1B,sBAAsB,EACtB,6BAA6B,EAC7B,mBAAmB,EACnB,KAAK,0BAA0B,GAChC,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,mBAAmB,EACnB,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,aAAa,GACd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,eAAe,EACf,uBAAuB,GACxB,MAAM,iBAAiB,CAAC"}
|