@adonis-agora/telescope 0.1.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/LICENSE +21 -0
- package/README.md +26 -0
- package/dist/configure.d.ts +16 -0
- package/dist/configure.d.ts.map +1 -0
- package/dist/configure.js +75 -0
- package/dist/configure.js.map +1 -0
- package/dist/providers/telescope_ai_provider.d.ts +20 -0
- package/dist/providers/telescope_ai_provider.d.ts.map +1 -0
- package/dist/providers/telescope_ai_provider.js +45 -0
- package/dist/providers/telescope_ai_provider.js.map +1 -0
- package/dist/providers/telescope_alerts_provider.d.ts +23 -0
- package/dist/providers/telescope_alerts_provider.d.ts.map +1 -0
- package/dist/providers/telescope_alerts_provider.js +72 -0
- package/dist/providers/telescope_alerts_provider.js.map +1 -0
- package/dist/providers/telescope_provider.d.ts +43 -0
- package/dist/providers/telescope_provider.d.ts.map +1 -0
- package/dist/providers/telescope_provider.js +103 -0
- package/dist/providers/telescope_provider.js.map +1 -0
- package/dist/providers/telescope_ui_provider.d.ts +21 -0
- package/dist/providers/telescope_ui_provider.d.ts.map +1 -0
- package/dist/providers/telescope_ui_provider.js +119 -0
- package/dist/providers/telescope_ui_provider.js.map +1 -0
- package/dist/providers/telescope_watchers_provider.d.ts +31 -0
- package/dist/providers/telescope_watchers_provider.d.ts.map +1 -0
- package/dist/providers/telescope_watchers_provider.js +116 -0
- package/dist/providers/telescope_watchers_provider.js.map +1 -0
- package/dist/src/ai/define_config.d.ts +56 -0
- package/dist/src/ai/define_config.d.ts.map +1 -0
- package/dist/src/ai/define_config.js +39 -0
- package/dist/src/ai/define_config.js.map +1 -0
- package/dist/src/ai/diagnoser.d.ts +34 -0
- package/dist/src/ai/diagnoser.d.ts.map +1 -0
- package/dist/src/ai/diagnoser.js +74 -0
- package/dist/src/ai/diagnoser.js.map +1 -0
- package/dist/src/ai/diagnosis_cache.d.ts +43 -0
- package/dist/src/ai/diagnosis_cache.d.ts.map +1 -0
- package/dist/src/ai/diagnosis_cache.js +56 -0
- package/dist/src/ai/diagnosis_cache.js.map +1 -0
- package/dist/src/ai/factory.d.ts +15 -0
- package/dist/src/ai/factory.d.ts.map +1 -0
- package/dist/src/ai/factory.js +24 -0
- package/dist/src/ai/factory.js.map +1 -0
- package/dist/src/ai/index.d.ts +14 -0
- package/dist/src/ai/index.d.ts.map +1 -0
- package/dist/src/ai/index.js +15 -0
- package/dist/src/ai/index.js.map +1 -0
- package/dist/src/ai/prompt.d.ts +31 -0
- package/dist/src/ai/prompt.d.ts.map +1 -0
- package/dist/src/ai/prompt.js +66 -0
- package/dist/src/ai/prompt.js.map +1 -0
- package/dist/src/ai/telescope_ai_diagnoser.d.ts +79 -0
- package/dist/src/ai/telescope_ai_diagnoser.d.ts.map +1 -0
- package/dist/src/ai/telescope_ai_diagnoser.js +111 -0
- package/dist/src/ai/telescope_ai_diagnoser.js.map +1 -0
- package/dist/src/alerts/alert_channel.d.ts +69 -0
- package/dist/src/alerts/alert_channel.d.ts.map +1 -0
- package/dist/src/alerts/alert_channel.js +114 -0
- package/dist/src/alerts/alert_channel.js.map +1 -0
- package/dist/src/alerts/alert_rule.d.ts +86 -0
- package/dist/src/alerts/alert_rule.d.ts.map +1 -0
- package/dist/src/alerts/alert_rule.js +2 -0
- package/dist/src/alerts/alert_rule.js.map +1 -0
- package/dist/src/alerts/alerter.d.ts +72 -0
- package/dist/src/alerts/alerter.d.ts.map +1 -0
- package/dist/src/alerts/alerter.js +248 -0
- package/dist/src/alerts/alerter.js.map +1 -0
- package/dist/src/alerts/define_config.d.ts +68 -0
- package/dist/src/alerts/define_config.d.ts.map +1 -0
- package/dist/src/alerts/define_config.js +57 -0
- package/dist/src/alerts/define_config.js.map +1 -0
- package/dist/src/alerts/exception_source.d.ts +44 -0
- package/dist/src/alerts/exception_source.d.ts.map +1 -0
- package/dist/src/alerts/exception_source.js +79 -0
- package/dist/src/alerts/exception_source.js.map +1 -0
- package/dist/src/alerts/index.d.ts +16 -0
- package/dist/src/alerts/index.d.ts.map +1 -0
- package/dist/src/alerts/index.js +17 -0
- package/dist/src/alerts/index.js.map +1 -0
- package/dist/src/alerts/new_exception_tracker.d.ts +50 -0
- package/dist/src/alerts/new_exception_tracker.d.ts.map +1 -0
- package/dist/src/alerts/new_exception_tracker.js +74 -0
- package/dist/src/alerts/new_exception_tracker.js.map +1 -0
- package/dist/src/alerts/parse_duration.d.ts +10 -0
- package/dist/src/alerts/parse_duration.d.ts.map +1 -0
- package/dist/src/alerts/parse_duration.js +27 -0
- package/dist/src/alerts/parse_duration.js.map +1 -0
- package/dist/src/alerts/slack_format.d.ts +60 -0
- package/dist/src/alerts/slack_format.d.ts.map +1 -0
- package/dist/src/alerts/slack_format.js +122 -0
- package/dist/src/alerts/slack_format.js.map +1 -0
- package/dist/src/context_accessor.d.ts +30 -0
- package/dist/src/context_accessor.d.ts.map +1 -0
- package/dist/src/context_accessor.js +20 -0
- package/dist/src/context_accessor.js.map +1 -0
- package/dist/src/define_config.d.ts +109 -0
- package/dist/src/define_config.d.ts.map +1 -0
- package/dist/src/define_config.js +38 -0
- package/dist/src/define_config.js.map +1 -0
- package/dist/src/diagnostics_registry.d.ts +46 -0
- package/dist/src/diagnostics_registry.d.ts.map +1 -0
- package/dist/src/diagnostics_registry.js +34 -0
- package/dist/src/diagnostics_registry.js.map +1 -0
- package/dist/src/diagnostics_watcher.d.ts +72 -0
- package/dist/src/diagnostics_watcher.d.ts.map +1 -0
- package/dist/src/diagnostics_watcher.js +119 -0
- package/dist/src/diagnostics_watcher.js.map +1 -0
- package/dist/src/entry.d.ts +81 -0
- package/dist/src/entry.d.ts.map +1 -0
- package/dist/src/entry.js +34 -0
- package/dist/src/entry.js.map +1 -0
- package/dist/src/exception_family_hash.d.ts +29 -0
- package/dist/src/exception_family_hash.d.ts.map +1 -0
- package/dist/src/exception_family_hash.js +30 -0
- package/dist/src/exception_family_hash.js.map +1 -0
- package/dist/src/exception_watcher.d.ts +66 -0
- package/dist/src/exception_watcher.d.ts.map +1 -0
- package/dist/src/exception_watcher.js +94 -0
- package/dist/src/exception_watcher.js.map +1 -0
- package/dist/src/extension/registry.d.ts +17 -0
- package/dist/src/extension/registry.d.ts.map +1 -0
- package/dist/src/extension/registry.js +56 -0
- package/dist/src/extension/registry.js.map +1 -0
- package/dist/src/extension/types.d.ts +158 -0
- package/dist/src/extension/types.d.ts.map +1 -0
- package/dist/src/extension/types.js +5 -0
- package/dist/src/extension/types.js.map +1 -0
- package/dist/src/index.d.ts +36 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +28 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/redaction/redact.d.ts +93 -0
- package/dist/src/redaction/redact.d.ts.map +1 -0
- package/dist/src/redaction/redact.js +184 -0
- package/dist/src/redaction/redact.js.map +1 -0
- package/dist/src/redaction/redacting_store.d.ts +28 -0
- package/dist/src/redaction/redacting_store.d.ts.map +1 -0
- package/dist/src/redaction/redacting_store.js +49 -0
- package/dist/src/redaction/redacting_store.js.map +1 -0
- package/dist/src/registry.d.ts +26 -0
- package/dist/src/registry.d.ts.map +1 -0
- package/dist/src/registry.js +28 -0
- package/dist/src/registry.js.map +1 -0
- package/dist/src/request_watcher.d.ts +44 -0
- package/dist/src/request_watcher.d.ts.map +1 -0
- package/dist/src/request_watcher.js +37 -0
- package/dist/src/request_watcher.js.map +1 -0
- package/dist/src/service.d.ts +36 -0
- package/dist/src/service.d.ts.map +1 -0
- package/dist/src/service.js +65 -0
- package/dist/src/service.js.map +1 -0
- package/dist/src/store.d.ts +56 -0
- package/dist/src/store.d.ts.map +1 -0
- package/dist/src/store.js +2 -0
- package/dist/src/store.js.map +1 -0
- package/dist/src/stores/factory.d.ts +61 -0
- package/dist/src/stores/factory.d.ts.map +1 -0
- package/dist/src/stores/factory.js +42 -0
- package/dist/src/stores/factory.js.map +1 -0
- package/dist/src/stores/lucid.d.ts +138 -0
- package/dist/src/stores/lucid.d.ts.map +1 -0
- package/dist/src/stores/lucid.js +257 -0
- package/dist/src/stores/lucid.js.map +1 -0
- package/dist/src/stores/memory.d.ts +31 -0
- package/dist/src/stores/memory.d.ts.map +1 -0
- package/dist/src/stores/memory.js +117 -0
- package/dist/src/stores/memory.js.map +1 -0
- package/dist/src/telescope_middleware.d.ts +19 -0
- package/dist/src/telescope_middleware.d.ts.map +1 -0
- package/dist/src/telescope_middleware.js +56 -0
- package/dist/src/telescope_middleware.js.map +1 -0
- package/dist/src/ui/api.d.ts +49 -0
- package/dist/src/ui/api.d.ts.map +1 -0
- package/dist/src/ui/api.js +155 -0
- package/dist/src/ui/api.js.map +1 -0
- package/dist/src/ui/dashboard.d.ts +8 -0
- package/dist/src/ui/dashboard.d.ts.map +1 -0
- package/dist/src/ui/dashboard.html +626 -0
- package/dist/src/ui/dashboard.js +29 -0
- package/dist/src/ui/dashboard.js.map +1 -0
- package/dist/src/ui/define_config.d.ts +87 -0
- package/dist/src/ui/define_config.d.ts.map +1 -0
- package/dist/src/ui/define_config.js +104 -0
- package/dist/src/ui/define_config.js.map +1 -0
- package/dist/src/ui/extension_api.d.ts +23 -0
- package/dist/src/ui/extension_api.d.ts.map +1 -0
- package/dist/src/ui/extension_api.js +50 -0
- package/dist/src/ui/extension_api.js.map +1 -0
- package/dist/src/ui/guard.d.ts +33 -0
- package/dist/src/ui/guard.d.ts.map +1 -0
- package/dist/src/ui/guard.js +47 -0
- package/dist/src/ui/guard.js.map +1 -0
- package/dist/src/ui/http.d.ts +47 -0
- package/dist/src/ui/http.d.ts.map +1 -0
- package/dist/src/ui/http.js +43 -0
- package/dist/src/ui/http.js.map +1 -0
- package/dist/src/ui/index.d.ts +12 -0
- package/dist/src/ui/index.d.ts.map +1 -0
- package/dist/src/ui/index.js +13 -0
- package/dist/src/ui/index.js.map +1 -0
- package/dist/src/watchers/cache_watcher.d.ts +60 -0
- package/dist/src/watchers/cache_watcher.d.ts.map +1 -0
- package/dist/src/watchers/cache_watcher.js +72 -0
- package/dist/src/watchers/cache_watcher.js.map +1 -0
- package/dist/src/watchers/define_config.d.ts +38 -0
- package/dist/src/watchers/define_config.d.ts.map +1 -0
- package/dist/src/watchers/define_config.js +17 -0
- package/dist/src/watchers/define_config.js.map +1 -0
- package/dist/src/watchers/emitter.d.ts +32 -0
- package/dist/src/watchers/emitter.d.ts.map +1 -0
- package/dist/src/watchers/emitter.js +2 -0
- package/dist/src/watchers/emitter.js.map +1 -0
- package/dist/src/watchers/http_client_watcher.d.ts +74 -0
- package/dist/src/watchers/http_client_watcher.d.ts.map +1 -0
- package/dist/src/watchers/http_client_watcher.js +168 -0
- package/dist/src/watchers/http_client_watcher.js.map +1 -0
- package/dist/src/watchers/index.d.ts +19 -0
- package/dist/src/watchers/index.d.ts.map +1 -0
- package/dist/src/watchers/index.js +19 -0
- package/dist/src/watchers/index.js.map +1 -0
- package/dist/src/watchers/logs_watcher.d.ts +82 -0
- package/dist/src/watchers/logs_watcher.d.ts.map +1 -0
- package/dist/src/watchers/logs_watcher.js +145 -0
- package/dist/src/watchers/logs_watcher.js.map +1 -0
- package/dist/src/watchers/lucid_query_watcher.d.ts +64 -0
- package/dist/src/watchers/lucid_query_watcher.d.ts.map +1 -0
- package/dist/src/watchers/lucid_query_watcher.js +84 -0
- package/dist/src/watchers/lucid_query_watcher.js.map +1 -0
- package/dist/src/watchers/mail_watcher.d.ts +51 -0
- package/dist/src/watchers/mail_watcher.d.ts.map +1 -0
- package/dist/src/watchers/mail_watcher.js +93 -0
- package/dist/src/watchers/mail_watcher.js.map +1 -0
- package/dist/src/watchers/normalize_http_target.d.ts +17 -0
- package/dist/src/watchers/normalize_http_target.d.ts.map +1 -0
- package/dist/src/watchers/normalize_http_target.js +41 -0
- package/dist/src/watchers/normalize_http_target.js.map +1 -0
- package/dist/src/watchers/query_family_hash.d.ts +8 -0
- package/dist/src/watchers/query_family_hash.d.ts.map +1 -0
- package/dist/src/watchers/query_family_hash.js +31 -0
- package/dist/src/watchers/query_family_hash.js.map +1 -0
- package/dist/src/watchers/record.d.ts +22 -0
- package/dist/src/watchers/record.d.ts.map +1 -0
- package/dist/src/watchers/record.js +48 -0
- package/dist/src/watchers/record.js.map +1 -0
- package/dist/stubs/config/telescope.stub +56 -0
- package/dist/stubs/config/telescope_ai.stub +36 -0
- package/dist/stubs/config/telescope_alerts.stub +47 -0
- package/dist/stubs/config/telescope_ui.stub +40 -0
- package/dist/stubs/config/telescope_watchers.stub +30 -0
- package/dist/stubs/database/migrations/create_telescope_entries_table.stub +39 -0
- package/dist/stubs/main.d.ts +6 -0
- package/dist/stubs/main.d.ts.map +1 -0
- package/dist/stubs/main.js +7 -0
- package/dist/stubs/main.js.map +1 -0
- package/package.json +140 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ExtensionRegistry } from './extension/registry.js';
|
|
2
|
+
import type { TelescopeStore } from './store.js';
|
|
3
|
+
/**
|
|
4
|
+
* The live runtime telescope handles, published on a cross-copy-stable global slot
|
|
5
|
+
* so the request middleware can reach the active store WITHOUT constructor wiring
|
|
6
|
+
* — mirroring the "singleton lives outside the container" stance the Agora
|
|
7
|
+
* ecosystem uses for context/diagnostics. The provider sets this at boot and
|
|
8
|
+
* clears it at shutdown.
|
|
9
|
+
*/
|
|
10
|
+
export interface TelescopeRuntime {
|
|
11
|
+
/** The active store, or `null` when telescope is disabled / not booted. */
|
|
12
|
+
store: TelescopeStore | null;
|
|
13
|
+
/** Whether the request watcher should record. */
|
|
14
|
+
requestWatcherEnabled: boolean;
|
|
15
|
+
/** The booted extension registry (entry types / dashboards / data providers), or `null`. */
|
|
16
|
+
registry: ExtensionRegistry | null;
|
|
17
|
+
}
|
|
18
|
+
/** The shared runtime handle. */
|
|
19
|
+
export declare function getTelescopeRuntime(): TelescopeRuntime;
|
|
20
|
+
/** Install the active store + flags (called by the provider at boot). */
|
|
21
|
+
export declare function setTelescopeRuntime(store: TelescopeStore, requestWatcherEnabled: boolean): void;
|
|
22
|
+
/** Publish the booted extension registry so the UI can serve its dashboards + providers. */
|
|
23
|
+
export declare function setTelescopeExtensionRegistry(registry: ExtensionRegistry | null): void;
|
|
24
|
+
/** Tear down the runtime (called by the provider at shutdown). */
|
|
25
|
+
export declare function resetTelescopeRuntime(): void;
|
|
26
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,2EAA2E;IAC3E,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IAC7B,iDAAiD;IACjD,qBAAqB,EAAE,OAAO,CAAC;IAC/B,4FAA4F;IAC5F,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;CACpC;AAYD,iCAAiC;AACjC,wBAAgB,mBAAmB,IAAI,gBAAgB,CAEtD;AAED,yEAAyE;AACzE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAE,OAAO,GAAG,IAAI,CAG/F;AAED,4FAA4F;AAC5F,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,GAAG,IAAI,CAEtF;AAED,kEAAkE;AAClE,wBAAgB,qBAAqB,IAAI,IAAI,CAI5C"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const RUNTIME_KEY = Symbol.for('@agora/telescope:runtime');
|
|
2
|
+
const globalStore = globalThis;
|
|
3
|
+
const runtime = globalStore[RUNTIME_KEY] ?? {
|
|
4
|
+
store: null,
|
|
5
|
+
requestWatcherEnabled: false,
|
|
6
|
+
registry: null,
|
|
7
|
+
};
|
|
8
|
+
globalStore[RUNTIME_KEY] = runtime;
|
|
9
|
+
/** The shared runtime handle. */
|
|
10
|
+
export function getTelescopeRuntime() {
|
|
11
|
+
return runtime;
|
|
12
|
+
}
|
|
13
|
+
/** Install the active store + flags (called by the provider at boot). */
|
|
14
|
+
export function setTelescopeRuntime(store, requestWatcherEnabled) {
|
|
15
|
+
runtime.store = store;
|
|
16
|
+
runtime.requestWatcherEnabled = requestWatcherEnabled;
|
|
17
|
+
}
|
|
18
|
+
/** Publish the booted extension registry so the UI can serve its dashboards + providers. */
|
|
19
|
+
export function setTelescopeExtensionRegistry(registry) {
|
|
20
|
+
runtime.registry = registry;
|
|
21
|
+
}
|
|
22
|
+
/** Tear down the runtime (called by the provider at shutdown). */
|
|
23
|
+
export function resetTelescopeRuntime() {
|
|
24
|
+
runtime.store = null;
|
|
25
|
+
runtime.requestWatcherEnabled = false;
|
|
26
|
+
runtime.registry = null;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/registry.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;AAC3D,MAAM,WAAW,GAAG,UAAsE,CAAC;AAE3F,MAAM,OAAO,GAAqB,WAAW,CAAC,WAAW,CAAC,IAAI;IAC5D,KAAK,EAAE,IAAI;IACX,qBAAqB,EAAE,KAAK;IAC5B,QAAQ,EAAE,IAAI;CACf,CAAC;AACF,WAAW,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC;AAEnC,iCAAiC;AACjC,MAAM,UAAU,mBAAmB;IACjC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,mBAAmB,CAAC,KAAqB,EAAE,qBAA8B;IACvF,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;IACtB,OAAO,CAAC,qBAAqB,GAAG,qBAAqB,CAAC;AACxD,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,6BAA6B,CAAC,QAAkC;IAC9E,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;AAC9B,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,qBAAqB;IACnC,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IACrB,OAAO,CAAC,qBAAqB,GAAG,KAAK,CAAC;IACtC,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type Entry } from './entry.js';
|
|
2
|
+
import type { TelescopeStore } from './store.js';
|
|
3
|
+
/** The recorded body of a `request` entry. */
|
|
4
|
+
export interface RequestEntryContent {
|
|
5
|
+
/** HTTP method, upper-cased (`GET`, `POST`, …). */
|
|
6
|
+
method: string;
|
|
7
|
+
/** Request path (no query string), e.g. `/users/42`. */
|
|
8
|
+
url: string;
|
|
9
|
+
/** Response status code, or `null` if it could not be determined. */
|
|
10
|
+
status: number | null;
|
|
11
|
+
/** Request duration in milliseconds. */
|
|
12
|
+
durationMs: number;
|
|
13
|
+
/** The active trace id at request time, or `null`. */
|
|
14
|
+
traceId: string | null;
|
|
15
|
+
}
|
|
16
|
+
/** The minimal slice of an Adonis HttpContext the watcher reads. */
|
|
17
|
+
export interface RequestLike {
|
|
18
|
+
method(): string;
|
|
19
|
+
url(): string;
|
|
20
|
+
}
|
|
21
|
+
export interface ResponseLike {
|
|
22
|
+
response: {
|
|
23
|
+
statusCode?: number;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export interface HttpContextLike {
|
|
27
|
+
request: RequestLike;
|
|
28
|
+
response: ResponseLike['response'];
|
|
29
|
+
}
|
|
30
|
+
/** Options for {@link recordRequest}. */
|
|
31
|
+
export interface RecordRequestOptions {
|
|
32
|
+
/** Override the duration; defaults to `Date.now() - startedAt`. */
|
|
33
|
+
durationMs?: number;
|
|
34
|
+
/** The trace id; defaults to the one the store resolves from context. */
|
|
35
|
+
traceId?: string | null;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The pure, framework-agnostic core of the HTTP request watcher: build a
|
|
39
|
+
* `request` {@link RecordInput} from a (stubbable) HttpContext-like value and a
|
|
40
|
+
* start timestamp, and record it. Kept out of the middleware so it is trivially
|
|
41
|
+
* unit-testable with a plain object. Resolves to the recorded {@link Entry}.
|
|
42
|
+
*/
|
|
43
|
+
export declare function recordRequest(store: TelescopeStore, ctx: HttpContextLike, startedAt: number, options?: RecordRequestOptions): Promise<Entry<RequestEntryContent>>;
|
|
44
|
+
//# sourceMappingURL=request_watcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request_watcher.d.ts","sourceRoot":"","sources":["../../src/request_watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAA+B,MAAM,YAAY,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,8CAA8C;AAC9C,MAAM,WAAW,mBAAmB;IAClC,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,GAAG,EAAE,MAAM,CAAC;IACZ,qEAAqE;IACrE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,oEAAoE;AACpE,MAAM,WAAW,WAAW;IAC1B,MAAM,IAAI,MAAM,CAAC;IACjB,GAAG,IAAI,MAAM,CAAC;CACf;AACD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACnC;AACD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC;CACpC;AAED,yCAAyC;AACzC,MAAM,WAAW,oBAAoB;IACnC,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,cAAc,EACrB,GAAG,EAAE,eAAe,EACpB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAyBrC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { EntryType } from './entry.js';
|
|
2
|
+
/**
|
|
3
|
+
* The pure, framework-agnostic core of the HTTP request watcher: build a
|
|
4
|
+
* `request` {@link RecordInput} from a (stubbable) HttpContext-like value and a
|
|
5
|
+
* start timestamp, and record it. Kept out of the middleware so it is trivially
|
|
6
|
+
* unit-testable with a plain object. Resolves to the recorded {@link Entry}.
|
|
7
|
+
*/
|
|
8
|
+
export async function recordRequest(store, ctx, startedAt, options = {}) {
|
|
9
|
+
const method = String(ctx.request.method()).toUpperCase();
|
|
10
|
+
const url = stripQuery(ctx.request.url());
|
|
11
|
+
const status = typeof ctx.response.statusCode === 'number' ? ctx.response.statusCode : null;
|
|
12
|
+
const durationMs = options.durationMs ?? Math.max(0, Date.now() - startedAt);
|
|
13
|
+
const input = {
|
|
14
|
+
type: EntryType.Request,
|
|
15
|
+
content: {
|
|
16
|
+
method,
|
|
17
|
+
url,
|
|
18
|
+
status,
|
|
19
|
+
durationMs,
|
|
20
|
+
traceId: options.traceId ?? null,
|
|
21
|
+
},
|
|
22
|
+
durationMs,
|
|
23
|
+
origin: 'http',
|
|
24
|
+
tags: [`method:${method}`, ...(status !== null ? [`status:${status}`] : [])],
|
|
25
|
+
...(options.traceId !== undefined ? { traceId: options.traceId } : {}),
|
|
26
|
+
};
|
|
27
|
+
const recorded = await store.record(input);
|
|
28
|
+
// Backfill the content trace id from whatever the store resolved (context).
|
|
29
|
+
recorded.content.traceId = recorded.traceId;
|
|
30
|
+
return recorded;
|
|
31
|
+
}
|
|
32
|
+
/** Drop a `?query=string` suffix from a url. */
|
|
33
|
+
function stripQuery(url) {
|
|
34
|
+
const q = url.indexOf('?');
|
|
35
|
+
return q === -1 ? url : url.slice(0, q);
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=request_watcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request_watcher.js","sourceRoot":"","sources":["../../src/request_watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,SAAS,EAAoB,MAAM,YAAY,CAAC;AAsCrE;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAAqB,EACrB,GAAoB,EACpB,SAAiB,EACjB,UAAgC,EAAE;IAElC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1D,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,OAAO,GAAG,CAAC,QAAQ,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5F,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;IAE7E,MAAM,KAAK,GAAqC;QAC9C,IAAI,EAAE,SAAS,CAAC,OAAO;QACvB,OAAO,EAAE;YACP,MAAM;YACN,GAAG;YACH,MAAM;YACN,UAAU;YACV,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,IAAI;SACjC;QACD,UAAU;QACV,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,CAAC,UAAU,MAAM,EAAE,EAAE,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC5E,GAAG,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACvE,CAAC;IAEF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3C,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;IAC5C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,gDAAgD;AAChD,SAAS,UAAU,CAAC,GAAW;IAC7B,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3B,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Entry } from './entry.js';
|
|
2
|
+
import type { EntryQuery, TelescopeStore } from './store.js';
|
|
3
|
+
/** A `{ familyHash | tag, count }` aggregate for top-N style summaries. */
|
|
4
|
+
export interface CountBucket {
|
|
5
|
+
key: string;
|
|
6
|
+
count: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The headless query API over recorded entries — what a future dashboard, an
|
|
10
|
+
* `inspector` endpoint, or your own controller reads. Thin facade over a
|
|
11
|
+
* {@link TelescopeStore} with a couple of convenience aggregates the recorded
|
|
12
|
+
* `tags`/`familyHash` make cheap.
|
|
13
|
+
*/
|
|
14
|
+
export declare class TelescopeService {
|
|
15
|
+
private readonly store;
|
|
16
|
+
constructor(store: TelescopeStore);
|
|
17
|
+
/** The underlying store, for advanced callers (and the provider's shutdown). */
|
|
18
|
+
get telescopeStore(): TelescopeStore;
|
|
19
|
+
/** List entries matching `query`, newest-first. */
|
|
20
|
+
list(query?: EntryQuery): Promise<Entry[]>;
|
|
21
|
+
/** Fetch one entry by id, or `null`. */
|
|
22
|
+
find(id: string): Promise<Entry | null>;
|
|
23
|
+
/** Every entry recorded under a given trace id, newest-first. */
|
|
24
|
+
byTrace(traceId: string): Promise<Entry[]>;
|
|
25
|
+
/** Total number of stored entries. */
|
|
26
|
+
count(): Promise<number>;
|
|
27
|
+
/**
|
|
28
|
+
* Top-N busiest groups by `familyHash` (e.g. the busiest `lib:event` pairs, or
|
|
29
|
+
* grouped exceptions), optionally scoped to a `type`. Newest data wins ties via
|
|
30
|
+
* the store's newest-first ordering.
|
|
31
|
+
*/
|
|
32
|
+
topFamilies(limit?: number, type?: string): Promise<CountBucket[]>;
|
|
33
|
+
/** Top-N most common tags across stored entries, optionally by prefix. */
|
|
34
|
+
topTags(limit?: number, prefix?: string): Promise<CountBucket[]>;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE7D,2EAA2E;AAC3E,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,qBAAa,gBAAgB;IACf,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,cAAc;IAElD,gFAAgF;IAChF,IAAI,cAAc,IAAI,cAAc,CAEnC;IAED,mDAAmD;IACnD,IAAI,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAI1C,wCAAwC;IACxC,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAIvC,iEAAiE;IACjE,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAI1C,sCAAsC;IACtC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAIxB;;;;OAIG;IACG,WAAW,CAAC,KAAK,SAAK,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IASpE,0EAA0E;IACpE,OAAO,CAAC,KAAK,SAAK,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;CAUnE"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The headless query API over recorded entries — what a future dashboard, an
|
|
3
|
+
* `inspector` endpoint, or your own controller reads. Thin facade over a
|
|
4
|
+
* {@link TelescopeStore} with a couple of convenience aggregates the recorded
|
|
5
|
+
* `tags`/`familyHash` make cheap.
|
|
6
|
+
*/
|
|
7
|
+
export class TelescopeService {
|
|
8
|
+
store;
|
|
9
|
+
constructor(store) {
|
|
10
|
+
this.store = store;
|
|
11
|
+
}
|
|
12
|
+
/** The underlying store, for advanced callers (and the provider's shutdown). */
|
|
13
|
+
get telescopeStore() {
|
|
14
|
+
return this.store;
|
|
15
|
+
}
|
|
16
|
+
/** List entries matching `query`, newest-first. */
|
|
17
|
+
list(query) {
|
|
18
|
+
return this.store.list(query);
|
|
19
|
+
}
|
|
20
|
+
/** Fetch one entry by id, or `null`. */
|
|
21
|
+
find(id) {
|
|
22
|
+
return this.store.get(id);
|
|
23
|
+
}
|
|
24
|
+
/** Every entry recorded under a given trace id, newest-first. */
|
|
25
|
+
byTrace(traceId) {
|
|
26
|
+
return this.store.list({ traceId });
|
|
27
|
+
}
|
|
28
|
+
/** Total number of stored entries. */
|
|
29
|
+
count() {
|
|
30
|
+
return this.store.count();
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Top-N busiest groups by `familyHash` (e.g. the busiest `lib:event` pairs, or
|
|
34
|
+
* grouped exceptions), optionally scoped to a `type`. Newest data wins ties via
|
|
35
|
+
* the store's newest-first ordering.
|
|
36
|
+
*/
|
|
37
|
+
async topFamilies(limit = 10, type) {
|
|
38
|
+
const counts = new Map();
|
|
39
|
+
for (const entry of await this.store.list(type !== undefined ? { type } : {})) {
|
|
40
|
+
if (!entry.familyHash)
|
|
41
|
+
continue;
|
|
42
|
+
counts.set(entry.familyHash, (counts.get(entry.familyHash) ?? 0) + 1);
|
|
43
|
+
}
|
|
44
|
+
return toSortedBuckets(counts, limit);
|
|
45
|
+
}
|
|
46
|
+
/** Top-N most common tags across stored entries, optionally by prefix. */
|
|
47
|
+
async topTags(limit = 10, prefix) {
|
|
48
|
+
const counts = new Map();
|
|
49
|
+
for (const entry of await this.store.list()) {
|
|
50
|
+
for (const tag of entry.tags) {
|
|
51
|
+
if (prefix !== undefined && !tag.startsWith(prefix))
|
|
52
|
+
continue;
|
|
53
|
+
counts.set(tag, (counts.get(tag) ?? 0) + 1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return toSortedBuckets(counts, limit);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function toSortedBuckets(counts, limit) {
|
|
60
|
+
return [...counts.entries()]
|
|
61
|
+
.map(([key, count]) => ({ key, count }))
|
|
62
|
+
.sort((a, b) => b.count - a.count)
|
|
63
|
+
.slice(0, limit);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/service.ts"],"names":[],"mappings":"AASA;;;;;GAKG;AACH,MAAM,OAAO,gBAAgB;IACE;IAA7B,YAA6B,KAAqB;QAArB,UAAK,GAAL,KAAK,CAAgB;IAAG,CAAC;IAEtD,gFAAgF;IAChF,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,mDAAmD;IACnD,IAAI,CAAC,KAAkB;QACrB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;IAED,wCAAwC;IACxC,IAAI,CAAC,EAAU;QACb,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC;IAED,iEAAiE;IACjE,OAAO,CAAC,OAAe;QACrB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IACtC,CAAC;IAED,sCAAsC;IACtC,KAAK;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IAC5B,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,WAAW,CAAC,KAAK,GAAG,EAAE,EAAE,IAAa;QACzC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzC,KAAK,MAAM,KAAK,IAAI,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;YAC9E,IAAI,CAAC,KAAK,CAAC,UAAU;gBAAE,SAAS;YAChC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACxE,CAAC;QACD,OAAO,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,0EAA0E;IAC1E,KAAK,CAAC,OAAO,CAAC,KAAK,GAAG,EAAE,EAAE,MAAe;QACvC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzC,KAAK,MAAM,KAAK,IAAI,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;YAC5C,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;gBAC7B,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC;oBAAE,SAAS;gBAC9D,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;QACD,OAAO,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACxC,CAAC;CACF;AAED,SAAS,eAAe,CAAC,MAA2B,EAAE,KAAa;IACjE,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;SACzB,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;SACvC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;SACjC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { Entry, RecordInput } from './entry.js';
|
|
2
|
+
/**
|
|
3
|
+
* A filter for {@link TelescopeStore.list}. Every set field is an AND predicate,
|
|
4
|
+
* so they compose. Results are always returned newest-first.
|
|
5
|
+
*/
|
|
6
|
+
export interface EntryQuery {
|
|
7
|
+
/** Only entries of this type (e.g. `request`, `diagnostic`). */
|
|
8
|
+
type?: string;
|
|
9
|
+
/** Only entries carrying this exact tag (e.g. `lib:billing`). */
|
|
10
|
+
tag?: string;
|
|
11
|
+
/** Only entries with this grouping key. */
|
|
12
|
+
familyHash?: string;
|
|
13
|
+
/** Only entries recorded under this trace id. */
|
|
14
|
+
traceId?: string;
|
|
15
|
+
/** Only entries strictly older than this instant (keyset-ish pagination). */
|
|
16
|
+
before?: Date;
|
|
17
|
+
/** Only entries newer than this instant. */
|
|
18
|
+
after?: Date;
|
|
19
|
+
/**
|
|
20
|
+
* Case-insensitive substring matched against the entry's JSON-serialized
|
|
21
|
+
* `content` and its `tags` — a request matches by url, a diagnostic by event,
|
|
22
|
+
* etc. Composes with every other filter.
|
|
23
|
+
*/
|
|
24
|
+
search?: string;
|
|
25
|
+
/** Cap the number of returned entries. */
|
|
26
|
+
limit?: number;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The storage abstraction Telescope records through and the headless query API
|
|
30
|
+
* reads from. Adapted from `nestjs-telescope`'s `StorageProvider`, trimmed to the
|
|
31
|
+
* headless slice (no rollups, keyset cursors, or family-seen alerting — those are
|
|
32
|
+
* deferred, see DESIGN.md). A future `@adonis-agora/telescope-lucid` / SQLite store
|
|
33
|
+
* implements this same contract.
|
|
34
|
+
*/
|
|
35
|
+
export interface TelescopeStore {
|
|
36
|
+
/**
|
|
37
|
+
* Record one entry from a watcher's {@link RecordInput}, filling in `id`,
|
|
38
|
+
* `sequence`, `createdAt` and resolving `traceId`/`origin` from context when the
|
|
39
|
+
* caller omits them. Resolves to the persisted {@link Entry}.
|
|
40
|
+
*/
|
|
41
|
+
record<TContent>(input: RecordInput<TContent>): Promise<Entry<TContent>>;
|
|
42
|
+
/** Fetch a single entry by id, or `null` when absent. */
|
|
43
|
+
get(id: string): Promise<Entry | null>;
|
|
44
|
+
/** List entries matching `query`, newest-first. */
|
|
45
|
+
list(query?: EntryQuery): Promise<Entry[]>;
|
|
46
|
+
/** Total number of stored entries. */
|
|
47
|
+
count(): Promise<number>;
|
|
48
|
+
/**
|
|
49
|
+
* Delete entries older than `olderThan`. When `keepLast` is set, the newest N of
|
|
50
|
+
* the matched-and-doomed entries are retained. Resolves to the number deleted.
|
|
51
|
+
*/
|
|
52
|
+
prune(olderThan: Date, keepLast?: number): Promise<number>;
|
|
53
|
+
/** Delete every stored entry. */
|
|
54
|
+
clear(): Promise<void>;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAErD;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,IAAI,CAAC;IACd,4CAA4C;IAC5C,KAAK,CAAC,EAAE,IAAI,CAAC;IACb;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEzE,yDAAyD;IACzD,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IAEvC,mDAAmD;IACnD,IAAI,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;IAE3C,sCAAsC;IACtC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAEzB;;;OAGG;IACH,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE3D,iCAAiC;IACjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/store.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { ApplicationService } from '@adonisjs/core/types';
|
|
2
|
+
import type { TelescopeStore } from '../store.js';
|
|
3
|
+
import type { LucidStoreOptions } from './lucid.js';
|
|
4
|
+
import type { InMemoryStoreOptions } from './memory.js';
|
|
5
|
+
/**
|
|
6
|
+
* Runtime context a {@link StoreProvider} receives when the telescope provider builds the
|
|
7
|
+
* configured store at boot.
|
|
8
|
+
*/
|
|
9
|
+
export interface StoreContext {
|
|
10
|
+
/** The booted application — used to resolve connections, services, etc. */
|
|
11
|
+
app: ApplicationService;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A configured store: a thunk the telescope provider calls at boot to build the active
|
|
15
|
+
* {@link TelescopeStore}. Each factory lazily imports its peer dependency (`@adonisjs/lucid`)
|
|
16
|
+
* inside the thunk, so a driver is only loaded when it is actually selected — keeping those
|
|
17
|
+
* packages optional.
|
|
18
|
+
*/
|
|
19
|
+
export type StoreProvider = (ctx: StoreContext) => Promise<TelescopeStore>;
|
|
20
|
+
/** Options for the `memory` store driver. */
|
|
21
|
+
export interface MemoryStoreConfig extends InMemoryStoreOptions {
|
|
22
|
+
/**
|
|
23
|
+
* Hard cap on retained entries. Past it, the oldest entries are evicted (ring-buffer
|
|
24
|
+
* semantics). Alias of {@link InMemoryStoreOptions.maxEntries}. Default 1000.
|
|
25
|
+
*/
|
|
26
|
+
limit?: number;
|
|
27
|
+
}
|
|
28
|
+
/** Options for the `lucid` store driver. */
|
|
29
|
+
export interface LucidStoreConfig extends LucidStoreOptions {
|
|
30
|
+
/**
|
|
31
|
+
* `@adonisjs/lucid` connection name to use. Omit to use the default connection. When set,
|
|
32
|
+
* the store binds to that single connection client instead of the `Database` facade.
|
|
33
|
+
*/
|
|
34
|
+
connection?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The store factory namespace used in `config/telescope.ts`:
|
|
38
|
+
*
|
|
39
|
+
* ```ts
|
|
40
|
+
* import { defineConfig, storage } from '@adonis-agora/telescope'
|
|
41
|
+
*
|
|
42
|
+
* export default defineConfig({
|
|
43
|
+
* store: 'memory',
|
|
44
|
+
* stores: {
|
|
45
|
+
* memory: storage.memory({ limit: 1000 }),
|
|
46
|
+
* lucid: storage.lucid({ connection: 'pg' }),
|
|
47
|
+
* },
|
|
48
|
+
* })
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* Each factory returns a {@link StoreProvider} — a lazy thunk. Calling it in the config file
|
|
52
|
+
* costs nothing; the peer dependency is only imported when the provider builds the selected
|
|
53
|
+
* store at boot.
|
|
54
|
+
*/
|
|
55
|
+
export declare const storage: {
|
|
56
|
+
/** The built-in, dependency-free bounded ring buffer (great for dev/tests). */
|
|
57
|
+
memory(config?: MemoryStoreConfig): StoreProvider;
|
|
58
|
+
/** A persistent, SQL-backed store on `@adonisjs/lucid` (sqlite / Postgres / MySQL). */
|
|
59
|
+
lucid(config?: LucidStoreConfig): StoreProvider;
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/stores/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAqB,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,2EAA2E;IAC3E,GAAG,EAAE,kBAAkB,CAAC;CACzB;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,YAAY,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;AAE3E,6CAA6C;AAC7C,MAAM,WAAW,iBAAkB,SAAQ,oBAAoB;IAC7D;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,4CAA4C;AAC5C,MAAM,WAAW,gBAAiB,SAAQ,iBAAiB;IACzD;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,OAAO;IAClB,+EAA+E;oBAChE,iBAAiB,GAAQ,aAAa;IAQrD,uFAAuF;mBACzE,gBAAgB,GAAQ,aAAa;CAYpD,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The store factory namespace used in `config/telescope.ts`:
|
|
3
|
+
*
|
|
4
|
+
* ```ts
|
|
5
|
+
* import { defineConfig, storage } from '@adonis-agora/telescope'
|
|
6
|
+
*
|
|
7
|
+
* export default defineConfig({
|
|
8
|
+
* store: 'memory',
|
|
9
|
+
* stores: {
|
|
10
|
+
* memory: storage.memory({ limit: 1000 }),
|
|
11
|
+
* lucid: storage.lucid({ connection: 'pg' }),
|
|
12
|
+
* },
|
|
13
|
+
* })
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Each factory returns a {@link StoreProvider} — a lazy thunk. Calling it in the config file
|
|
17
|
+
* costs nothing; the peer dependency is only imported when the provider builds the selected
|
|
18
|
+
* store at boot.
|
|
19
|
+
*/
|
|
20
|
+
export const storage = {
|
|
21
|
+
/** The built-in, dependency-free bounded ring buffer (great for dev/tests). */
|
|
22
|
+
memory(config = {}) {
|
|
23
|
+
return async () => {
|
|
24
|
+
const { InMemoryTelescopeStore } = await import('./memory.js');
|
|
25
|
+
const maxEntries = config.limit ?? config.maxEntries;
|
|
26
|
+
return new InMemoryTelescopeStore(maxEntries !== undefined ? { maxEntries } : {});
|
|
27
|
+
};
|
|
28
|
+
},
|
|
29
|
+
/** A persistent, SQL-backed store on `@adonisjs/lucid` (sqlite / Postgres / MySQL). */
|
|
30
|
+
lucid(config = {}) {
|
|
31
|
+
return async () => {
|
|
32
|
+
const db = (await import('@adonisjs/lucid/services/db')).default;
|
|
33
|
+
const { LucidTelescopeStore } = await import('./lucid.js');
|
|
34
|
+
// Bind to a single connection client when named, else the Database facade. Both
|
|
35
|
+
// satisfy the structural LucidDatabaseLike surface the store consumes.
|
|
36
|
+
const client = config.connection ? db.connection(config.connection) : db;
|
|
37
|
+
const { connection: _connection, ...storeOptions } = config;
|
|
38
|
+
return new LucidTelescopeStore(client, storeOptions);
|
|
39
|
+
};
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../../../src/stores/factory.ts"],"names":[],"mappings":"AAwCA;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,+EAA+E;IAC/E,MAAM,CAAC,SAA4B,EAAE;QACnC,OAAO,KAAK,IAAI,EAAE;YAChB,MAAM,EAAE,sBAAsB,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;YAC/D,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,UAAU,CAAC;YACrD,OAAO,IAAI,sBAAsB,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpF,CAAC,CAAC;IACJ,CAAC;IAED,uFAAuF;IACvF,KAAK,CAAC,SAA2B,EAAE;QACjC,OAAO,KAAK,IAAI,EAAE;YAChB,MAAM,EAAE,GAAG,CAAC,MAAM,MAAM,CAAC,6BAA6B,CAAC,CAAC,CAAC,OAAO,CAAC;YACjE,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;YAE3D,gFAAgF;YAChF,uEAAuE;YACvE,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACzE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,YAAY,EAAE,GAAG,MAAM,CAAC;YAC5D,OAAO,IAAI,mBAAmB,CAAC,MAAsC,EAAE,YAAY,CAAC,CAAC;QACvF,CAAC,CAAC;IACJ,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { type Entry, type RecordInput } from '../entry.js';
|
|
2
|
+
import type { EntryQuery, TelescopeStore } from '../store.js';
|
|
3
|
+
/**
|
|
4
|
+
* The table {@link LucidTelescopeStore} reads and writes. Override via
|
|
5
|
+
* {@link LucidStoreOptions.tableName} when `telescope_entries` collides with an
|
|
6
|
+
* existing table.
|
|
7
|
+
*/
|
|
8
|
+
export declare const DEFAULT_TABLE_NAME = "telescope_entries";
|
|
9
|
+
/**
|
|
10
|
+
* The column layout, kept in one place so the DDL helper, the migration stub and
|
|
11
|
+
* the store's queries can never drift apart.
|
|
12
|
+
*
|
|
13
|
+
* - `content` / `tags` are JSON text columns (portable across every Lucid dialect).
|
|
14
|
+
* - `family_hash` is the grouping key used by `topFamilies`; `trace_id` powers
|
|
15
|
+
* trace correlation; `created_at` is stored as epoch milliseconds so newest-first
|
|
16
|
+
* ordering and age-based pruning are a plain integer comparison (no timezone or
|
|
17
|
+
* string-format ambiguity across drivers).
|
|
18
|
+
*/
|
|
19
|
+
export interface TelescopeColumns {
|
|
20
|
+
id: string;
|
|
21
|
+
type: string;
|
|
22
|
+
family_hash: string | null;
|
|
23
|
+
content: string;
|
|
24
|
+
tags: string;
|
|
25
|
+
sequence: number;
|
|
26
|
+
duration_ms: number | null;
|
|
27
|
+
origin: string;
|
|
28
|
+
trace_id: string | null;
|
|
29
|
+
created_at: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* `CREATE TABLE IF NOT EXISTS` DDL for the telescope entries table, plus the
|
|
33
|
+
* indexes `list` / `prune` / `topFamilies` lean on, as one statement per array
|
|
34
|
+
* element so each can be issued through Lucid's `rawQuery`.
|
|
35
|
+
*
|
|
36
|
+
* Portable across sqlite / Postgres / MySQL (quoted identifiers, no dialect-only
|
|
37
|
+
* column types). A real deployment should still prefer the bundled migration stub
|
|
38
|
+
* so the schema is versioned, but this lets a store stand itself up in tests and
|
|
39
|
+
* scripts without a migration runner.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createTableStatements(tableName?: string): string[];
|
|
42
|
+
/**
|
|
43
|
+
* The slice of an AdonisJS Lucid `Database` (or `QueryClientContract`) this store
|
|
44
|
+
* uses. Typed structurally so `@adonisjs/lucid` stays an *optional peer* dependency
|
|
45
|
+
* and the store works against either the `Database` facade or a single connection /
|
|
46
|
+
* transaction client.
|
|
47
|
+
*/
|
|
48
|
+
export interface LucidDatabaseLike {
|
|
49
|
+
/** Start a SELECT/DELETE query builder on a table. */
|
|
50
|
+
from(table: string): LucidQueryBuilderLike;
|
|
51
|
+
/** Start an INSERT query builder on a table. */
|
|
52
|
+
table(table: string): LucidInsertBuilderLike;
|
|
53
|
+
/** Run a raw SQL statement (DDL, `MAX(sequence)` seed). */
|
|
54
|
+
rawQuery(sql: string, bindings?: unknown[]): Promise<unknown>;
|
|
55
|
+
}
|
|
56
|
+
/** The structural query-builder surface the store leans on (Knex-shaped). */
|
|
57
|
+
export interface LucidQueryBuilderLike {
|
|
58
|
+
where(column: string, value: unknown): this;
|
|
59
|
+
where(column: string, operator: string, value: unknown): this;
|
|
60
|
+
whereRaw(sql: string, bindings?: unknown[]): this;
|
|
61
|
+
orderBy(column: string, direction: 'asc' | 'desc'): this;
|
|
62
|
+
limit(value: number): this;
|
|
63
|
+
select(...columns: string[]): Promise<Record<string, unknown>[]>;
|
|
64
|
+
count(column: string, alias: string): Promise<Record<string, unknown>[]>;
|
|
65
|
+
delete(): Promise<number>;
|
|
66
|
+
first(): Promise<Record<string, unknown> | null>;
|
|
67
|
+
}
|
|
68
|
+
export interface LucidInsertBuilderLike {
|
|
69
|
+
insert(row: Record<string, unknown>): Promise<unknown>;
|
|
70
|
+
}
|
|
71
|
+
/** Options for {@link LucidTelescopeStore} (and the `storage.lucid` factory). */
|
|
72
|
+
export interface LucidStoreOptions {
|
|
73
|
+
/** Table name. Defaults to `telescope_entries`. */
|
|
74
|
+
tableName?: string;
|
|
75
|
+
/**
|
|
76
|
+
* Hard cap on retained entries enforced on each {@link LucidTelescopeStore.prune}
|
|
77
|
+
* by `keepLast`-style trimming when set. The store never auto-evicts on `record`
|
|
78
|
+
* (that would add a query per write); prune on a schedule instead. Default unset.
|
|
79
|
+
*/
|
|
80
|
+
maxEntries?: number;
|
|
81
|
+
/**
|
|
82
|
+
* Run {@link createTableStatements} on first use so the table exists without a
|
|
83
|
+
* migration. Convenient for tests/scripts; production should run the migration.
|
|
84
|
+
* Default `false`.
|
|
85
|
+
*/
|
|
86
|
+
autoCreateTable?: boolean;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* A persistent, SQL-backed {@link TelescopeStore} on AdonisJS Lucid. Uses Lucid's
|
|
90
|
+
* **async** query builder directly, so it works on every dialect Lucid supports
|
|
91
|
+
* (sqlite / Postgres / MySQL) — no synchronous driver handle, no dialect lock-in.
|
|
92
|
+
*
|
|
93
|
+
* `content` and `tags` are stored as JSON text and round-tripped on read;
|
|
94
|
+
* `created_at` is epoch-ms so ordering and age-pruning are integer comparisons.
|
|
95
|
+
* `sequence` is seeded from `MAX(sequence)` on first use so it keeps climbing
|
|
96
|
+
* across process restarts.
|
|
97
|
+
*
|
|
98
|
+
* Usually you don't construct this directly: `config/telescope.ts` selects it via
|
|
99
|
+
* `storage.lucid({ ... })` and the provider builds it for you, lazily importing
|
|
100
|
+
* `@adonisjs/lucid` only when the `lucid` driver is the active one.
|
|
101
|
+
*/
|
|
102
|
+
export declare class LucidTelescopeStore implements TelescopeStore {
|
|
103
|
+
private readonly db;
|
|
104
|
+
private readonly tableName;
|
|
105
|
+
private readonly maxEntries;
|
|
106
|
+
private readonly autoCreateTable;
|
|
107
|
+
/** Lazily-resolved init (table creation + sequence seed), run at most once. */
|
|
108
|
+
private ready;
|
|
109
|
+
private sequence;
|
|
110
|
+
constructor(db: LucidDatabaseLike, options?: LucidStoreOptions);
|
|
111
|
+
record<TContent>(input: RecordInput<TContent>): Promise<Entry<TContent>>;
|
|
112
|
+
get(id: string): Promise<Entry | null>;
|
|
113
|
+
list(query?: EntryQuery): Promise<Entry[]>;
|
|
114
|
+
count(): Promise<number>;
|
|
115
|
+
prune(olderThan: Date, keepLast?: number): Promise<number>;
|
|
116
|
+
clear(): Promise<void>;
|
|
117
|
+
/** Cap enforcement helper for callers running a scheduled trim. */
|
|
118
|
+
get capacity(): number | null;
|
|
119
|
+
/** Run table creation (optional) + sequence seeding exactly once. */
|
|
120
|
+
private init;
|
|
121
|
+
private doInit;
|
|
122
|
+
}
|
|
123
|
+
/** Options for {@link createTelescopeTable}. */
|
|
124
|
+
export interface CreateTableOptions {
|
|
125
|
+
/** Table to create. Defaults to `telescope_entries`. */
|
|
126
|
+
tableName?: string;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Stand up the telescope entries table (and its indexes) through Lucid's async
|
|
130
|
+
* query runner, idempotently (`CREATE TABLE IF NOT EXISTS`). Works on every Lucid
|
|
131
|
+
* dialect. Handy for tests, scripts and quick-starts where running a full
|
|
132
|
+
* migration is overkill.
|
|
133
|
+
*
|
|
134
|
+
* Production apps should prefer the bundled migration stub so the schema is
|
|
135
|
+
* versioned and runs through `node ace migration:run`.
|
|
136
|
+
*/
|
|
137
|
+
export declare function createTelescopeTable(db: LucidDatabaseLike, options?: CreateTableOptions): Promise<void>;
|
|
138
|
+
//# sourceMappingURL=lucid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lucid.d.ts","sourceRoot":"","sources":["../../../src/stores/lucid.ts"],"names":[],"mappings":"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"}
|