@adonis-agora/telescope 0.5.2 → 0.6.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 +6 -0
- package/dist/providers/telescope_alerts_provider.d.ts.map +1 -1
- package/dist/providers/telescope_alerts_provider.js +1 -1
- package/dist/providers/telescope_alerts_provider.js.map +1 -1
- package/dist/providers/telescope_mcp_provider.d.ts.map +1 -1
- package/dist/providers/telescope_mcp_provider.js +1 -1
- package/dist/providers/telescope_mcp_provider.js.map +1 -1
- package/dist/providers/telescope_provider.d.ts.map +1 -1
- package/dist/providers/telescope_provider.js +9 -3
- package/dist/providers/telescope_provider.js.map +1 -1
- package/dist/src/ai/index.d.ts +1 -1
- package/dist/src/ai/index.js +1 -1
- package/dist/src/alerts/alert_rule.d.ts +84 -3
- package/dist/src/alerts/alert_rule.d.ts.map +1 -1
- package/dist/src/alerts/alerter.d.ts +24 -2
- package/dist/src/alerts/alerter.d.ts.map +1 -1
- package/dist/src/alerts/alerter.js +122 -11
- package/dist/src/alerts/alerter.js.map +1 -1
- package/dist/src/alerts/define_config.d.ts +9 -1
- package/dist/src/alerts/define_config.d.ts.map +1 -1
- package/dist/src/alerts/define_config.js +8 -0
- package/dist/src/alerts/define_config.js.map +1 -1
- package/dist/src/alerts/exception_source.d.ts +16 -7
- package/dist/src/alerts/exception_source.d.ts.map +1 -1
- package/dist/src/alerts/exception_source.js +29 -17
- package/dist/src/alerts/exception_source.js.map +1 -1
- package/dist/src/alerts/index.d.ts +2 -2
- package/dist/src/alerts/index.d.ts.map +1 -1
- package/dist/src/alerts/index.js +1 -1
- package/dist/src/alerts/index.js.map +1 -1
- package/dist/src/alerts/slack_format.d.ts +8 -0
- package/dist/src/alerts/slack_format.d.ts.map +1 -1
- package/dist/src/alerts/slack_format.js +128 -3
- package/dist/src/alerts/slack_format.js.map +1 -1
- package/dist/src/client_errors/ingestor.d.ts.map +1 -1
- package/dist/src/client_errors/ingestor.js +20 -1
- package/dist/src/client_errors/ingestor.js.map +1 -1
- package/dist/src/client_errors/validation.d.ts.map +1 -1
- package/dist/src/client_errors/validation.js +7 -2
- package/dist/src/client_errors/validation.js.map +1 -1
- package/dist/src/define_config.d.ts +51 -0
- package/dist/src/define_config.d.ts.map +1 -1
- package/dist/src/define_config.js +6 -0
- package/dist/src/define_config.js.map +1 -1
- package/dist/src/diagnostics_registry.d.ts +15 -0
- package/dist/src/diagnostics_registry.d.ts.map +1 -1
- package/dist/src/diagnostics_registry.js +19 -0
- package/dist/src/diagnostics_registry.js.map +1 -1
- package/dist/src/diagnostics_watcher.d.ts +28 -1
- package/dist/src/diagnostics_watcher.d.ts.map +1 -1
- package/dist/src/diagnostics_watcher.js +17 -2
- package/dist/src/diagnostics_watcher.js.map +1 -1
- package/dist/src/extension/types.d.ts +35 -2
- package/dist/src/extension/types.d.ts.map +1 -1
- package/dist/src/extension/types.js.map +1 -1
- package/dist/src/index.d.ts +7 -7
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/index.d.ts +1 -1
- package/dist/src/mcp/index.js +1 -1
- package/dist/src/mcp/server.d.ts.map +1 -1
- package/dist/src/mcp/server.js +7 -2
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/metrics/waterfall.d.ts.map +1 -1
- package/dist/src/metrics/waterfall.js +6 -0
- package/dist/src/metrics/waterfall.js.map +1 -1
- package/dist/src/redaction/redact.d.ts +21 -0
- package/dist/src/redaction/redact.d.ts.map +1 -1
- package/dist/src/redaction/redact.js +18 -0
- package/dist/src/redaction/redact.js.map +1 -1
- package/dist/src/redaction/redacting_store.d.ts.map +1 -1
- package/dist/src/redaction/redacting_store.js +10 -1
- package/dist/src/redaction/redacting_store.js.map +1 -1
- package/dist/src/registry.d.ts +8 -1
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/registry.js +4 -1
- package/dist/src/registry.js.map +1 -1
- package/dist/src/request_watcher.d.ts +68 -0
- package/dist/src/request_watcher.d.ts.map +1 -1
- package/dist/src/request_watcher.js +101 -0
- package/dist/src/request_watcher.js.map +1 -1
- package/dist/src/service.d.ts.map +1 -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 +5 -1
- package/dist/src/telescope_middleware.js.map +1 -1
- package/dist/src/ui/dashboard.html +58 -10
- package/dist/src/ui/ext_table.d.ts +50 -0
- package/dist/src/ui/ext_table.d.ts.map +1 -0
- package/dist/src/ui/ext_table.js +42 -0
- package/dist/src/ui/ext_table.js.map +1 -0
- package/dist/src/ui/index.d.ts +3 -1
- package/dist/src/ui/index.d.ts.map +1 -1
- package/dist/src/ui/index.js +3 -1
- package/dist/src/ui/index.js.map +1 -1
- package/dist/src/watchers/index.d.ts +1 -1
- package/dist/src/watchers/index.js +1 -1
- package/dist/src/watchers/schedule_watcher.d.ts.map +1 -1
- package/dist/src/watchers/schedule_watcher.js +6 -1
- package/dist/src/watchers/schedule_watcher.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type AlertChannel } from './alert_channel.js';
|
|
2
|
-
import type { AlertRule, ResolvedAlerts } from './alert_rule.js';
|
|
2
|
+
import type { AlertRule, GeoLookup, ResolvedAlerts } from './alert_rule.js';
|
|
3
3
|
import type { SlackChannelOptions } from './slack_format.js';
|
|
4
4
|
/**
|
|
5
5
|
* A declarative channel descriptor — the JSON-friendly form usable directly in
|
|
@@ -50,6 +50,14 @@ export interface TelescopeAlertsConfig {
|
|
|
50
50
|
cooldown?: string;
|
|
51
51
|
/** Reporting instance identifier carried on every payload. Default `'telescope'`. */
|
|
52
52
|
instanceId?: string;
|
|
53
|
+
/**
|
|
54
|
+
* Optional IP→geo resolver. When set, a firing exception alert that carries a
|
|
55
|
+
* `clientIp` is enriched with a coarse {@link AlertGeoLocation} (rendered as a
|
|
56
|
+
* "Location" field by channels that support it). Kept out of the lib core so
|
|
57
|
+
* telescope ships no geo dependency — see {@link GeoLookup}. May be sync or
|
|
58
|
+
* async; a `null`/throw simply omits the Location field.
|
|
59
|
+
*/
|
|
60
|
+
geoLookup?: GeoLookup;
|
|
53
61
|
}
|
|
54
62
|
/** The default rule set — page on a brand-new exception family within the hour. */
|
|
55
63
|
export declare const DEFAULT_RULES: AlertRule[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define_config.d.ts","sourceRoot":"","sources":["../../../src/alerts/define_config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EAIlB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"define_config.d.ts","sourceRoot":"","sources":["../../../src/alerts/define_config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EAIlB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAM7D;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,mBAAmB,CAAA;CAAE,GAC7D;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAExB,gEAAgE;AAChE,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,YAAY,CAAC;AAEvD;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,qEAAqE;IACrE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;IAC3B;;OAEG;IACH,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;IACpB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oFAAoF;IACpF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,mFAAmF;AACnF,eAAO,MAAM,aAAa,EAAE,SAAS,EAA8C,CAAC;AAEpF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,qBAAqB,GAAG,qBAAqB,CAEjF;AAoBD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,GAAE,qBAA0B,GAAG,cAAc,CA6BhF"}
|
|
@@ -40,6 +40,13 @@ export function resolveConfig(config = {}) {
|
|
|
40
40
|
const rules = config.rules !== undefined && config.rules.length > 0 ? config.rules : DEFAULT_RULES;
|
|
41
41
|
// Validate every rule window at boot — a typo surfaces here, not silently never.
|
|
42
42
|
for (const rule of rules) {
|
|
43
|
+
// `every-exception`'s window is OPTIONAL (occurrence-count only); validate it
|
|
44
|
+
// when present so a typo fails at boot rather than silently mis-counting.
|
|
45
|
+
if (rule.type === 'every-exception') {
|
|
46
|
+
if (rule.window !== undefined)
|
|
47
|
+
durationToMs(rule.window);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
43
50
|
durationToMs(rule.window);
|
|
44
51
|
}
|
|
45
52
|
return {
|
|
@@ -52,6 +59,7 @@ export function resolveConfig(config = {}) {
|
|
|
52
59
|
cooldownMs: durationToMs(config.cooldown ?? DEFAULT_COOLDOWN),
|
|
53
60
|
instanceId: config.instanceId ?? DEFAULT_INSTANCE_ID,
|
|
54
61
|
rules,
|
|
62
|
+
geoLookup: typeof config.geoLookup === 'function' ? config.geoLookup : null,
|
|
55
63
|
};
|
|
56
64
|
}
|
|
57
65
|
//# sourceMappingURL=define_config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define_config.js","sourceRoot":"","sources":["../../../src/alerts/define_config.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,cAAc,EACd,YAAY,EACZ,cAAc,GACf,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAC/B,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAC/B,MAAM,mBAAmB,GAAG,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"define_config.js","sourceRoot":"","sources":["../../../src/alerts/define_config.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,cAAc,EACd,YAAY,EACZ,cAAc,GACf,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAC/B,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAC/B,MAAM,mBAAmB,GAAG,WAAW,CAAC;AAyDxC,mFAAmF;AACnF,MAAM,CAAC,MAAM,aAAa,GAAgB,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AAEpF;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,MAA6B;IACxD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,2EAA2E;AAC3E,SAAS,SAAS,CAAC,MAAqB;IACtC,OAAO,OAAQ,MAAuB,CAAC,IAAI,KAAK,UAAU,CAAC;AAC7D,CAAC;AAED,wFAAwF;AACxF,SAAS,cAAc,CAAC,MAAqB;IAC3C,IAAI,SAAS,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IACrC,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,OAAO;YACV,OAAO,YAAY,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QAClD,KAAK,SAAS;YACZ,OAAO,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACpC,KAAK,SAAS;YACZ,OAAO,cAAc,EAAE,CAAC;IAC5B,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,SAAgC,EAAE;IAC9D,MAAM,QAAQ,GAAmB,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChG,MAAM,KAAK,GACT,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC;IAEvF,iFAAiF;IACjF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,8EAA8E;QAC9E,0EAA0E;QAC1E,IAAI,IAAI,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;YACpC,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;gBAAE,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACzD,SAAS;QACX,CAAC;QACD,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,IAAI;QAC/B,QAAQ;QACR,YAAY,EACV,OAAO,MAAM,CAAC,YAAY,KAAK,QAAQ,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE;YAC1E,CAAC,CAAC,MAAM,CAAC,YAAY;YACrB,CAAC,CAAC,IAAI;QACV,UAAU,EAAE,YAAY,CAAC,MAAM,CAAC,KAAK,IAAI,gBAAgB,CAAC;QAC1D,UAAU,EAAE,YAAY,CAAC,MAAM,CAAC,QAAQ,IAAI,gBAAgB,CAAC;QAC7D,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,mBAAmB;QACpD,KAAK;QACL,SAAS,EAAE,OAAO,MAAM,CAAC,SAAS,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;KAC5E,CAAC;AACJ,CAAC"}
|
|
@@ -13,10 +13,12 @@ export interface ExceptionPollerDeps {
|
|
|
13
13
|
/**
|
|
14
14
|
* The hook point. Telescope's headless `@adonis-agora/telescope` core does not expose a
|
|
15
15
|
* "new entry" event, so — by design, to avoid modifying core — this poller reads
|
|
16
|
-
* the {@link TelescopeStore} on an interval for
|
|
16
|
+
* the {@link TelescopeStore} on an interval for exception entries recorded since
|
|
17
17
|
* the previous poll (a high-water-mark on `createdAt`) and feeds them to the
|
|
18
|
-
* {@link Alerter}.
|
|
19
|
-
*
|
|
18
|
+
* {@link Alerter}. It polls BOTH server `exception` entries AND browser-reported
|
|
19
|
+
* `client_exception` entries, so a front-end error family pages exactly like a
|
|
20
|
+
* server one (and feeds the `every-exception` rule). Polling keeps the hook fully
|
|
21
|
+
* testable (drive {@link pollOnce} directly) and decoupled from any specific watcher.
|
|
20
22
|
*
|
|
21
23
|
* The unref'd timer means the poller never keeps the process alive on its own.
|
|
22
24
|
* Every poll is wrapped so a store failure is logged, not thrown.
|
|
@@ -34,10 +36,17 @@ export declare class ExceptionPoller {
|
|
|
34
36
|
/** Stop the poll interval. Idempotent. */
|
|
35
37
|
stop(): void;
|
|
36
38
|
/**
|
|
37
|
-
* Read exception entries
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* next poll retries the
|
|
39
|
+
* Read exception entries (server `exception` + browser `client_exception`)
|
|
40
|
+
* recorded since the last poll, advance the high-water mark, and hand them to
|
|
41
|
+
* the alerter. Exposed for deterministic tests. Never throws — a store failure
|
|
42
|
+
* is logged and the watermark is left untouched so the next poll retries the
|
|
43
|
+
* same window.
|
|
44
|
+
*
|
|
45
|
+
* `list` filters a single `type`, so the two families are queried separately
|
|
46
|
+
* with the shared watermark, then merged and sorted oldest-first (by
|
|
47
|
+
* `createdAt`, then `sequence`) so occurrence ordering / first-seen detection is
|
|
48
|
+
* natural across both. The watermark advances to the newest entry seen across
|
|
49
|
+
* BOTH types, so neither starves the other.
|
|
41
50
|
*/
|
|
42
51
|
pollOnce(): Promise<void>;
|
|
43
52
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exception_source.d.ts","sourceRoot":"","sources":["../../../src/alerts/exception_source.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAK5C,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,cAAc,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,0BAA0B;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,oDAAoD;IACpD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;
|
|
1
|
+
{"version":3,"file":"exception_source.d.ts","sourceRoot":"","sources":["../../../src/alerts/exception_source.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAK5C,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,cAAc,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,0BAA0B;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,oDAAoD;IACpD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAKD;;;;;;;;;;;;GAYG;AACH,qBAAa,eAAe;IAOd,OAAO,CAAC,QAAQ,CAAC,IAAI;IANjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4B;IACnD,OAAO,CAAC,KAAK,CAA+C;IAC5D,4EAA4E;IAC5E,OAAO,CAAC,KAAK,CAAO;gBAES,IAAI,EAAE,mBAAmB;IAOtD,mDAAmD;IACnD,KAAK,IAAI,IAAI;IAUb,0CAA0C;IAC1C,IAAI,IAAI,IAAI;IAOZ;;;;;;;;;;;;OAYG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CA4BhC"}
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { EntryType } from '../entry.js';
|
|
2
2
|
/** Cap on entries pulled per poll — a coarse alert check never needs more. */
|
|
3
3
|
const POLL_SCAN_CAP = 1_000;
|
|
4
|
+
/** The entry types the poller feeds to the alerter: server + browser-reported exceptions. */
|
|
5
|
+
const EXCEPTION_TYPES = [EntryType.Exception, EntryType.ClientException];
|
|
4
6
|
/**
|
|
5
7
|
* The hook point. Telescope's headless `@adonis-agora/telescope` core does not expose a
|
|
6
8
|
* "new entry" event, so — by design, to avoid modifying core — this poller reads
|
|
7
|
-
* the {@link TelescopeStore} on an interval for
|
|
9
|
+
* the {@link TelescopeStore} on an interval for exception entries recorded since
|
|
8
10
|
* the previous poll (a high-water-mark on `createdAt`) and feeds them to the
|
|
9
|
-
* {@link Alerter}.
|
|
10
|
-
*
|
|
11
|
+
* {@link Alerter}. It polls BOTH server `exception` entries AND browser-reported
|
|
12
|
+
* `client_exception` entries, so a front-end error family pages exactly like a
|
|
13
|
+
* server one (and feeds the `every-exception` rule). Polling keeps the hook fully
|
|
14
|
+
* testable (drive {@link pollOnce} directly) and decoupled from any specific watcher.
|
|
11
15
|
*
|
|
12
16
|
* The unref'd timer means the poller never keeps the process alive on its own.
|
|
13
17
|
* Every poll is wrapped so a store failure is logged, not thrown.
|
|
@@ -45,32 +49,40 @@ export class ExceptionPoller {
|
|
|
45
49
|
}
|
|
46
50
|
}
|
|
47
51
|
/**
|
|
48
|
-
* Read exception entries
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* next poll retries the
|
|
52
|
+
* Read exception entries (server `exception` + browser `client_exception`)
|
|
53
|
+
* recorded since the last poll, advance the high-water mark, and hand them to
|
|
54
|
+
* the alerter. Exposed for deterministic tests. Never throws — a store failure
|
|
55
|
+
* is logged and the watermark is left untouched so the next poll retries the
|
|
56
|
+
* same window.
|
|
57
|
+
*
|
|
58
|
+
* `list` filters a single `type`, so the two families are queried separately
|
|
59
|
+
* with the shared watermark, then merged and sorted oldest-first (by
|
|
60
|
+
* `createdAt`, then `sequence`) so occurrence ordering / first-seen detection is
|
|
61
|
+
* natural across both. The watermark advances to the newest entry seen across
|
|
62
|
+
* BOTH types, so neither starves the other.
|
|
52
63
|
*/
|
|
53
64
|
async pollOnce() {
|
|
54
|
-
let
|
|
65
|
+
let batches;
|
|
55
66
|
try {
|
|
56
|
-
|
|
57
|
-
type: EntryType.Exception,
|
|
58
|
-
after: this.since,
|
|
59
|
-
limit: POLL_SCAN_CAP,
|
|
60
|
-
});
|
|
67
|
+
batches = await Promise.all(EXCEPTION_TYPES.map((type) => this.deps.store.list({ type, after: this.since, limit: POLL_SCAN_CAP })));
|
|
61
68
|
}
|
|
62
69
|
catch (error) {
|
|
63
70
|
this.logger(`Telescope alert poll failed: ${asMessage(error)}`);
|
|
64
71
|
return;
|
|
65
72
|
}
|
|
73
|
+
// Merge and order oldest-first (createdAt asc, then sequence asc for a stable
|
|
74
|
+
// order within the same instant).
|
|
75
|
+
const entries = batches.flat().sort((a, b) => {
|
|
76
|
+
const byTime = a.createdAt.getTime() - b.createdAt.getTime();
|
|
77
|
+
return byTime !== 0 ? byTime : a.sequence - b.sequence;
|
|
78
|
+
});
|
|
66
79
|
if (entries.length > 0) {
|
|
67
|
-
//
|
|
68
|
-
const newest = entries[
|
|
80
|
+
// Advance the mark to the newest (last, after the asc sort) across both types.
|
|
81
|
+
const newest = entries[entries.length - 1];
|
|
69
82
|
if (newest !== undefined)
|
|
70
83
|
this.since = newest.createdAt;
|
|
71
84
|
}
|
|
72
|
-
|
|
73
|
-
await this.deps.alerter.evaluate([...entries].reverse());
|
|
85
|
+
await this.deps.alerter.evaluate(entries);
|
|
74
86
|
}
|
|
75
87
|
}
|
|
76
88
|
function asMessage(error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exception_source.js","sourceRoot":"","sources":["../../../src/alerts/exception_source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,SAAS,EAAE,MAAM,aAAa,CAAC;AAIpD,8EAA8E;AAC9E,MAAM,aAAa,GAAG,KAAK,CAAC;AAa5B
|
|
1
|
+
{"version":3,"file":"exception_source.js","sourceRoot":"","sources":["../../../src/alerts/exception_source.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
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.6.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 { AlertDiagnosis, AlertMetric, AlertPayload, AlertRule, ExceptionAlertContext, ResolvedAlerts, } from './alert_rule.js';
|
|
7
|
+
export type { AlertDiagnosis, AlertGeoLocation, AlertMetric, AlertPayload, AlertRule, ExceptionAlertContext, GeoLookup, 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';
|
|
@@ -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,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"}
|
|
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,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,SAAS,EACT,qBAAqB,EACrB,SAAS,EACT,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,5 +1,5 @@
|
|
|
1
1
|
/** Keep in sync with this package's `version` in package.json. */
|
|
2
|
-
export const VERSION = '0.
|
|
2
|
+
export const VERSION = '0.6.0';
|
|
3
3
|
// — channels —
|
|
4
4
|
export { consoleChannel, customChannel, slackChannel, webhookChannel, } from './alert_channel.js';
|
|
5
5
|
// — slack formatting —
|
|
@@ -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;AAevD,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"}
|
|
@@ -10,6 +10,14 @@ export interface SlackChannelOptions {
|
|
|
10
10
|
/** Override the message icon (a Slack emoji shortcode, e.g. `:rotating_light:`). */
|
|
11
11
|
iconEmoji?: string;
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Chunk a flat list of Slack section fields into groups of at most
|
|
15
|
+
* {@link MAX_SECTION_FIELDS}, so each becomes its own `section` block. Slack
|
|
16
|
+
* rejects the WHOLE message with `400 invalid_blocks` if any single section
|
|
17
|
+
* carries more than 10 fields, so this is what keeps a fully-enriched exception
|
|
18
|
+
* alert deliverable. Exported for direct testing of the field-cap invariant.
|
|
19
|
+
*/
|
|
20
|
+
export declare function chunkContextFields<T>(fields: readonly T[]): T[][];
|
|
13
21
|
interface SlackTextObject {
|
|
14
22
|
type: 'plain_text' | 'mrkdwn';
|
|
15
23
|
text: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slack_format.d.ts","sourceRoot":"","sources":["../../../src/alerts/slack_format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"slack_format.d.ts","sourceRoot":"","sources":["../../../src/alerts/slack_format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEtE;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAmBD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,CAMjE;AAED,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;AAkID;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,YAAY,EACrB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,YAAY,CAkHd"}
|
|
@@ -5,13 +5,38 @@
|
|
|
5
5
|
*/
|
|
6
6
|
const STACK_CHAR_LIMIT = 2_800;
|
|
7
7
|
const STACK_FRAME_LIMIT = 10;
|
|
8
|
+
/**
|
|
9
|
+
* Slack caps a `section` block's `fields` array at 10 items — an 11th makes Slack
|
|
10
|
+
* reject the WHOLE message with `400 invalid_blocks`. A fully-enriched exception
|
|
11
|
+
* (instance + observed + error + route + UA + referer + duration + user + client
|
|
12
|
+
* IP + location + occurrences) exceeds that, so we spread the fields across as
|
|
13
|
+
* many section blocks as needed rather than overflowing one.
|
|
14
|
+
*/
|
|
15
|
+
const MAX_SECTION_FIELDS = 10;
|
|
16
|
+
/**
|
|
17
|
+
* Chunk a flat list of Slack section fields into groups of at most
|
|
18
|
+
* {@link MAX_SECTION_FIELDS}, so each becomes its own `section` block. Slack
|
|
19
|
+
* rejects the WHOLE message with `400 invalid_blocks` if any single section
|
|
20
|
+
* carries more than 10 fields, so this is what keeps a fully-enriched exception
|
|
21
|
+
* alert deliverable. Exported for direct testing of the field-cap invariant.
|
|
22
|
+
*/
|
|
23
|
+
export function chunkContextFields(fields) {
|
|
24
|
+
const chunks = [];
|
|
25
|
+
for (let i = 0; i < fields.length; i += MAX_SECTION_FIELDS) {
|
|
26
|
+
chunks.push(fields.slice(i, i + MAX_SECTION_FIELDS));
|
|
27
|
+
}
|
|
28
|
+
return chunks;
|
|
29
|
+
}
|
|
8
30
|
/**
|
|
9
31
|
* Severity → leading emoji, derived from the rule kind: a brand-new error family
|
|
10
32
|
* or an exception spike is the loudest signal an operator can get.
|
|
11
33
|
*/
|
|
12
34
|
function severityEmoji(rule) {
|
|
13
|
-
if (rule.type === 'new-exception' ||
|
|
35
|
+
if (rule.type === 'new-exception' ||
|
|
36
|
+
rule.type === 'every-exception' ||
|
|
37
|
+
rule.type === 'exception-rate') {
|
|
14
38
|
return ':rotating_light:';
|
|
39
|
+
}
|
|
15
40
|
return ':warning:';
|
|
16
41
|
}
|
|
17
42
|
/** Short, human rule label for the header. */
|
|
@@ -19,12 +44,67 @@ function ruleLabel(rule) {
|
|
|
19
44
|
switch (rule.type) {
|
|
20
45
|
case 'new-exception':
|
|
21
46
|
return 'New exception family';
|
|
47
|
+
case 'every-exception':
|
|
48
|
+
return 'Exception';
|
|
22
49
|
case 'exception-rate':
|
|
23
50
|
return 'Exception rate';
|
|
24
51
|
case 'metric-threshold':
|
|
25
52
|
return `Metric threshold (${rule.metric})`;
|
|
26
53
|
}
|
|
27
54
|
}
|
|
55
|
+
/** Regional-indicator flag emoji for an ISO 3166-1 alpha-2 code, or `''`. */
|
|
56
|
+
function flagEmoji(countryCode) {
|
|
57
|
+
if (countryCode === undefined || !/^[A-Za-z]{2}$/.test(countryCode))
|
|
58
|
+
return '';
|
|
59
|
+
const cc = countryCode.toUpperCase();
|
|
60
|
+
const base = 0x1f1e6 - 65; // 'A' → 🇦
|
|
61
|
+
return String.fromCodePoint(base + cc.charCodeAt(0), base + cc.charCodeAt(1));
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Render a coarse geo location as `🇺🇸 City, Region, Country`, skipping absent or
|
|
65
|
+
* duplicate parts (a city equal to its region isn't repeated). Returns `null` when
|
|
66
|
+
* there's nothing to show, so the caller omits the field entirely.
|
|
67
|
+
*/
|
|
68
|
+
function formatGeo(geo) {
|
|
69
|
+
if (!geo)
|
|
70
|
+
return null;
|
|
71
|
+
const parts = [];
|
|
72
|
+
if (geo.city)
|
|
73
|
+
parts.push(geo.city);
|
|
74
|
+
if (geo.region && geo.region !== geo.city)
|
|
75
|
+
parts.push(geo.region);
|
|
76
|
+
if (geo.country && geo.country !== geo.region)
|
|
77
|
+
parts.push(geo.country);
|
|
78
|
+
if (parts.length === 0)
|
|
79
|
+
return null;
|
|
80
|
+
const flag = flagEmoji(geo.countryCode);
|
|
81
|
+
return flag ? `${flag} ${parts.join(', ')}` : parts.join(', ');
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Clip an auxiliary code block (React component stack / serialized `extra`) to
|
|
85
|
+
* Slack's per-section budget. Returns `null` for absent/empty input so the caller
|
|
86
|
+
* omits the block rather than rendering an empty fence.
|
|
87
|
+
*/
|
|
88
|
+
function clipBlock(text) {
|
|
89
|
+
if (text === null || text === undefined || text.trim() === '')
|
|
90
|
+
return null;
|
|
91
|
+
if (text.length <= STACK_CHAR_LIMIT)
|
|
92
|
+
return text;
|
|
93
|
+
return `${text.slice(0, STACK_CHAR_LIMIT)}…`;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Best-effort pretty JSON for the `extra` bag. The Recorder already redacted +
|
|
97
|
+
* depth-bounded it, but a circular ref could still slip through a host-built
|
|
98
|
+
* object, so we fall back to a placeholder rather than throwing into formatting.
|
|
99
|
+
*/
|
|
100
|
+
function safeJson(value) {
|
|
101
|
+
try {
|
|
102
|
+
return JSON.stringify(value, null, 2);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return '[unserializable]';
|
|
106
|
+
}
|
|
107
|
+
}
|
|
28
108
|
/** A Slack `mrkdwn` field pairing a bold label with a value. */
|
|
29
109
|
function field(label, value) {
|
|
30
110
|
return { type: 'mrkdwn', text: `*${label}:*\n${value}` };
|
|
@@ -97,7 +177,14 @@ export function formatSlackMessage(payload, options) {
|
|
|
97
177
|
const resolved = payload.status === 'resolved';
|
|
98
178
|
const emoji = resolved ? ':white_check_mark:' : severityEmoji(payload.rule);
|
|
99
179
|
const label = ruleLabel(payload.rule);
|
|
100
|
-
|
|
180
|
+
// Badge a brand-new error family distinctly from a recurrence so on-call can
|
|
181
|
+
// triage urgency at a glance. Only exceptions carry this; rate rules don't.
|
|
182
|
+
const badge = payload.exception === undefined
|
|
183
|
+
? ''
|
|
184
|
+
: payload.exception.isNew
|
|
185
|
+
? ' · 🆕 New'
|
|
186
|
+
: ' · 🔁 Recurring';
|
|
187
|
+
const headerText = `${emoji} ${resolved ? 'Resolved: ' : ''}${label}${badge}`;
|
|
101
188
|
const contextFields = [
|
|
102
189
|
field('Instance', payload.instanceId),
|
|
103
190
|
field('Observed', `${payload.value} (threshold ${payload.threshold})`),
|
|
@@ -110,9 +197,25 @@ export function formatSlackMessage(payload, options) {
|
|
|
110
197
|
const status = exception.statusCode === null ? '' : ` → ${exception.statusCode}`;
|
|
111
198
|
contextFields.push(field('Route', `${method} ${exception.route}${status}`.trim()));
|
|
112
199
|
}
|
|
200
|
+
if (exception.userAgent !== null) {
|
|
201
|
+
contextFields.push(field('User agent', exception.userAgent));
|
|
202
|
+
}
|
|
203
|
+
if (exception.referer !== null) {
|
|
204
|
+
contextFields.push(field('Referer', exception.referer));
|
|
205
|
+
}
|
|
206
|
+
if (exception.durationMs !== null) {
|
|
207
|
+
contextFields.push(field('Duration', `${exception.durationMs} ms`));
|
|
208
|
+
}
|
|
113
209
|
if (exception.user !== null) {
|
|
114
210
|
contextFields.push(field('User', exception.user));
|
|
115
211
|
}
|
|
212
|
+
if (exception.clientIp !== null) {
|
|
213
|
+
contextFields.push(field('Client IP', exception.clientIp));
|
|
214
|
+
}
|
|
215
|
+
const geoText = formatGeo(exception.geo);
|
|
216
|
+
if (geoText !== null) {
|
|
217
|
+
contextFields.push(field('Location', geoText));
|
|
218
|
+
}
|
|
116
219
|
contextFields.push(field('Occurrences', `${exception.occurrences} in window`));
|
|
117
220
|
}
|
|
118
221
|
else {
|
|
@@ -122,8 +225,12 @@ export function formatSlackMessage(payload, options) {
|
|
|
122
225
|
}
|
|
123
226
|
const blocks = [
|
|
124
227
|
{ type: 'header', text: { type: 'plain_text', text: headerText, emoji: true } },
|
|
125
|
-
{ type: 'section', fields: contextFields },
|
|
126
228
|
];
|
|
229
|
+
// Spread the context fields across section blocks of at most MAX_SECTION_FIELDS —
|
|
230
|
+
// one overflowing section makes Slack reject the entire message (invalid_blocks).
|
|
231
|
+
for (const chunk of chunkContextFields(contextFields)) {
|
|
232
|
+
blocks.push({ type: 'section', fields: chunk });
|
|
233
|
+
}
|
|
127
234
|
const diagnosisText = formatDiagnosis(payload.diagnosis);
|
|
128
235
|
if (diagnosisText !== null) {
|
|
129
236
|
blocks.push({ type: 'section', text: { type: 'mrkdwn', text: diagnosisText } });
|
|
@@ -132,6 +239,24 @@ export function formatSlackMessage(payload, options) {
|
|
|
132
239
|
if (stack !== null) {
|
|
133
240
|
blocks.push({ type: 'section', text: { type: 'mrkdwn', text: `\`\`\`${stack}\`\`\`` } });
|
|
134
241
|
}
|
|
242
|
+
// React component stack (client_exception from an error boundary), when present.
|
|
243
|
+
const componentStack = exception ? clipBlock(exception.componentStack) : null;
|
|
244
|
+
if (componentStack !== null) {
|
|
245
|
+
blocks.push({
|
|
246
|
+
type: 'section',
|
|
247
|
+
text: { type: 'mrkdwn', text: `*Component stack:*\n\`\`\`${componentStack}\`\`\`` },
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
// Host-defined free-form `extra` bag (client_exception), serialized as JSON.
|
|
251
|
+
const extra = exception?.extra && Object.keys(exception.extra).length > 0
|
|
252
|
+
? clipBlock(safeJson(exception.extra))
|
|
253
|
+
: null;
|
|
254
|
+
if (extra !== null) {
|
|
255
|
+
blocks.push({
|
|
256
|
+
type: 'section',
|
|
257
|
+
text: { type: 'mrkdwn', text: `*Extra:*\n\`\`\`${extra}\`\`\`` },
|
|
258
|
+
});
|
|
259
|
+
}
|
|
135
260
|
const link = dashboardLink(payload);
|
|
136
261
|
if (link !== null) {
|
|
137
262
|
blocks.push({
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"slack_format.js","sourceRoot":"","sources":["../../../src/alerts/slack_format.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingestor.d.ts","sourceRoot":"","sources":["../../../src/client_errors/ingestor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,EACL,KAAK,sBAAsB,EAG5B,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,yDAAyD;IACzD,IAAI,IAAI,OAAO,CAAC;IAChB,0EAA0E;IAC1E,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACzC,kFAAkF;IAClF,EAAE,IAAI,MAAM,GAAG,SAAS,CAAC;CAC1B;AAED,6DAA6D;AAC7D,MAAM,WAAW,mBAAmB;IAClC,iFAAiF;IACjF,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,CAAC;IAC1C,6DAA6D;IAC7D,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;CAC9B;AAED,gFAAgF;AAChF,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,QAAQ,EAAE,mBAAmB,CAAC;CAC/B;AAED,+EAA+E;AAC/E,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,0BAA0B,CAAC;IACnC;;;;OAIG;IACH,MAAM,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,sBAAsB,CAAC,KAAK,IAAI,CAAC;IAC7D,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC;IACzB,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,cAAc,GACpB,CAAC,KAAK,EAAE,WAAW,CAAC,sBAAsB,CAAC,KAAK,IAAI,CAQtD;AAOD;;;;;;;;GAQG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;IACpD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuD;IAC9E,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,6EAA6E;IAC7E,OAAO,CAAC,eAAe,CAAS;gBAEpB,IAAI,EAAE,uBAAuB;IAUnC,MAAM,CAAC,GAAG,EAAE,sBAAsB,GAAG,OAAO,CAAC,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"ingestor.d.ts","sourceRoot":"","sources":["../../../src/client_errors/ingestor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,EACL,KAAK,sBAAsB,EAG5B,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,yDAAyD;IACzD,IAAI,IAAI,OAAO,CAAC;IAChB,0EAA0E;IAC1E,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACzC,kFAAkF;IAClF,EAAE,IAAI,MAAM,GAAG,SAAS,CAAC;CAC1B;AAED,6DAA6D;AAC7D,MAAM,WAAW,mBAAmB;IAClC,iFAAiF;IACjF,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,CAAC;IAC1C,6DAA6D;IAC7D,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;CAC9B;AAED,gFAAgF;AAChF,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,QAAQ,EAAE,mBAAmB,CAAC;CAC/B;AAED,+EAA+E;AAC/E,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,0BAA0B,CAAC;IACnC;;;;OAIG;IACH,MAAM,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,sBAAsB,CAAC,KAAK,IAAI,CAAC;IAC7D,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC;IACzB,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,cAAc,GACpB,CAAC,KAAK,EAAE,WAAW,CAAC,sBAAsB,CAAC,KAAK,IAAI,CAQtD;AAOD;;;;;;;;GAQG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;IACpD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuD;IAC9E,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,6EAA6E;IAC7E,OAAO,CAAC,eAAe,CAAS;gBAEpB,IAAI,EAAE,uBAAuB;IAUnC,MAAM,CAAC,GAAG,EAAE,sBAAsB,GAAG,OAAO,CAAC,OAAO,CAAC;IA2E3D;;;;OAIG;YACW,YAAY;IAmB1B;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IAQpB,2EAA2E;IAC3E,OAAO,CAAC,QAAQ;CAIjB"}
|
|
@@ -83,6 +83,14 @@ export class ClientErrorIngestor {
|
|
|
83
83
|
const userTag = userIdentityTag(content.user);
|
|
84
84
|
if (userTag !== null)
|
|
85
85
|
tags.push(userTag);
|
|
86
|
+
// Content field ORDER is load-bearing. The Recorder's content-byte budget
|
|
87
|
+
// (redact.maxContentBytes) walks keys in insertion order and drops every key
|
|
88
|
+
// after the budget is exhausted. A deep React error boundary yields a
|
|
89
|
+
// componentStack of many KB, so the short enrichment fields the alert renders
|
|
90
|
+
// (clientIp/url/userAgent) MUST precede `stack`/`componentStack` — otherwise a
|
|
91
|
+
// big stack starves them out and the Slack card silently loses its Client IP
|
|
92
|
+
// (hence geo), URL and user-agent. `clientIp` is server-derived (never from
|
|
93
|
+
// the body) and leads, so it survives even the tightest budget.
|
|
86
94
|
this.record({
|
|
87
95
|
type: EntryType.ClientException,
|
|
88
96
|
familyHash: exceptionFamilyHash({
|
|
@@ -91,7 +99,18 @@ export class ClientErrorIngestor {
|
|
|
91
99
|
stack: content.stack,
|
|
92
100
|
}),
|
|
93
101
|
tags,
|
|
94
|
-
content: {
|
|
102
|
+
content: {
|
|
103
|
+
clientIp: ip === 'unknown' ? null : ip,
|
|
104
|
+
message: content.message,
|
|
105
|
+
name: content.name,
|
|
106
|
+
url: content.url,
|
|
107
|
+
userAgent: content.userAgent,
|
|
108
|
+
user: content.user,
|
|
109
|
+
release: content.release,
|
|
110
|
+
extra: content.extra,
|
|
111
|
+
stack: content.stack,
|
|
112
|
+
componentStack: content.componentStack,
|
|
113
|
+
},
|
|
95
114
|
});
|
|
96
115
|
return ctx.response.status(204).send(null);
|
|
97
116
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingestor.js","sourceRoot":"","sources":["../../../src/client_errors/ingestor.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ingestor.js","sourceRoot":"","sources":["../../../src/client_errors/ingestor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/client_errors/validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACtC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAgBD;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAC7B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,IAAI,CAAC,sBAAsB,EAAE,UAAU,CAAC,CAAA;CAAE,GAC7D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAqBlC;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG,qBAAqB,
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/client_errors/validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACtC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAgBD;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAC7B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,IAAI,CAAC,sBAAsB,EAAE,UAAU,CAAC,CAAA;CAAE,GAC7D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAqBlC;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG,qBAAqB,CAoD5E;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAK5D"}
|
|
@@ -71,11 +71,14 @@ export function validateClientErrorBody(body) {
|
|
|
71
71
|
}
|
|
72
72
|
return {
|
|
73
73
|
ok: true,
|
|
74
|
+
// Field ORDER is load-bearing: the Recorder's content-byte budget drops keys
|
|
75
|
+
// in insertion order, so the short enrichment fields (url/userAgent) lead and
|
|
76
|
+
// the multi-KB `stack`/`componentStack` come LAST — otherwise a deep error
|
|
77
|
+
// boundary's stack starves the short fields the alert renders. The ingestor
|
|
78
|
+
// re-asserts this order (with server-derived clientIp first) at record time.
|
|
74
79
|
value: {
|
|
75
80
|
message: cappedMessage,
|
|
76
81
|
name: name.value,
|
|
77
|
-
stack: stack.value,
|
|
78
|
-
componentStack: componentStack.value,
|
|
79
82
|
url: url.value,
|
|
80
83
|
userAgent: userAgent.value,
|
|
81
84
|
// `user` is intentionally untyped passthrough: redacted at record time and
|
|
@@ -83,6 +86,8 @@ export function validateClientErrorBody(body) {
|
|
|
83
86
|
user: 'user' in body ? body.user : null,
|
|
84
87
|
release: release.value,
|
|
85
88
|
extra,
|
|
89
|
+
stack: stack.value,
|
|
90
|
+
componentStack: componentStack.value,
|
|
86
91
|
},
|
|
87
92
|
};
|
|
88
93
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../src/client_errors/validation.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../src/client_errors/validation.ts"],"names":[],"mappings":"AAiCA;;;;;;GAMG;AACH,MAAM,SAAS,GAAG,EAAE,GAAG,IAAI,CAAC;AAC5B,MAAM,mBAAmB,GAAG,EAAE,GAAG,IAAI,CAAC;AACtC,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,CAAC;AAC7B,MAAM,eAAe,GAAG,CAAC,GAAG,IAAI,CAAC;AACjC,MAAM,QAAQ,GAAG,GAAG,CAAC;AACrB,MAAM,WAAW,GAAG,GAAG,CAAC;AAWxB,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc,CACrB,KAAc,EACd,KAAa,EACb,GAAW;IAEX,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAC5E,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,KAAK,qBAAqB,EAAE,CAAC;IAC7F,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;AAC/E,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAa;IACnD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACpB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,4BAA4B,EAAE,CAAC;IAC7D,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IAC7B,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,sDAAsD,EAAE,CAAC;IACvF,CAAC;IACD,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAE7F,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IACzD,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IAC7D,IAAI,CAAC,KAAK,CAAC,EAAE;QAAE,OAAO,KAAK,CAAC;IAC5B,MAAM,cAAc,GAAG,cAAc,CAAC,IAAI,CAAC,cAAc,EAAE,gBAAgB,EAAE,mBAAmB,CAAC,CAAC;IAClG,IAAI,CAAC,cAAc,CAAC,EAAE;QAAE,OAAO,cAAc,CAAC;IAC9C,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC;IAC7D,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,OAAO,GAAG,CAAC;IACxB,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC;IAC/E,IAAI,CAAC,SAAS,CAAC,EAAE;QAAE,OAAO,SAAS,CAAC;IACpC,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IACrE,IAAI,CAAC,OAAO,CAAC,EAAE;QAAE,OAAO,OAAO,CAAC;IAEhC,IAAI,KAAK,GAAmC,IAAI,CAAC;IACjD,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;QACpD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,2BAA2B,EAAE,CAAC;QAC5D,CAAC;QACD,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACrB,CAAC;IAED,OAAO;QACL,EAAE,EAAE,IAAI;QACR,6EAA6E;QAC7E,8EAA8E;QAC9E,2EAA2E;QAC3E,4EAA4E;QAC5E,6EAA6E;QAC7E,KAAK,EAAE;YACL,OAAO,EAAE,aAAa;YACtB,IAAI,EAAE,IAAI,CAAC,KAAK;YAChB,GAAG,EAAE,GAAG,CAAC,KAAK;YACd,SAAS,EAAE,SAAS,CAAC,KAAK;YAC1B,2EAA2E;YAC3E,sDAAsD;YACtD,IAAI,EAAE,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;YACvC,OAAO,EAAE,OAAO,CAAC,KAAK;YACtB,KAAK;YACL,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,cAAc,EAAE,cAAc,CAAC,KAAK;SACrC;KACF,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,IAAa;IAC3C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC3D,MAAM,MAAM,GAAG,IAA+B,CAAC;IAC/C,MAAM,EAAE,GAAG,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAChG,OAAO,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC;AAC3C,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IACtE,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACpF,OAAO,IAAI,CAAC;AACd,CAAC"}
|