@adonis-agora/telescope 0.13.0 → 0.15.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.
Files changed (91) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/dist/providers/telescope_provider.d.ts.map +1 -1
  3. package/dist/providers/telescope_provider.js +7 -2
  4. package/dist/providers/telescope_provider.js.map +1 -1
  5. package/dist/providers/telescope_ui_provider.d.ts.map +1 -1
  6. package/dist/providers/telescope_ui_provider.js +19 -3
  7. package/dist/providers/telescope_ui_provider.js.map +1 -1
  8. package/dist/providers/telescope_watchers_provider.d.ts +25 -0
  9. package/dist/providers/telescope_watchers_provider.d.ts.map +1 -1
  10. package/dist/providers/telescope_watchers_provider.js +67 -5
  11. package/dist/providers/telescope_watchers_provider.js.map +1 -1
  12. package/dist/src/ai/index.d.ts +1 -1
  13. package/dist/src/ai/index.js +1 -1
  14. package/dist/src/alerts/index.d.ts +1 -1
  15. package/dist/src/alerts/index.js +1 -1
  16. package/dist/src/extension/registry.d.ts +14 -1
  17. package/dist/src/extension/registry.d.ts.map +1 -1
  18. package/dist/src/extension/registry.js +38 -0
  19. package/dist/src/extension/registry.js.map +1 -1
  20. package/dist/src/extension/types.d.ts +22 -0
  21. package/dist/src/extension/types.d.ts.map +1 -1
  22. package/dist/src/extension/types.js.map +1 -1
  23. package/dist/src/index.d.ts +6 -4
  24. package/dist/src/index.d.ts.map +1 -1
  25. package/dist/src/index.js +3 -2
  26. package/dist/src/index.js.map +1 -1
  27. package/dist/src/mcp/index.d.ts +1 -1
  28. package/dist/src/mcp/index.js +1 -1
  29. package/dist/src/metrics/metrics_service.d.ts +36 -2
  30. package/dist/src/metrics/metrics_service.d.ts.map +1 -1
  31. package/dist/src/metrics/metrics_service.js +61 -6
  32. package/dist/src/metrics/metrics_service.js.map +1 -1
  33. package/dist/src/metrics/screens.d.ts +41 -0
  34. package/dist/src/metrics/screens.d.ts.map +1 -0
  35. package/dist/src/metrics/screens.js +70 -0
  36. package/dist/src/metrics/screens.js.map +1 -0
  37. package/dist/src/metrics/timeseries.d.ts +13 -0
  38. package/dist/src/metrics/timeseries.d.ts.map +1 -1
  39. package/dist/src/metrics/timeseries.js +38 -0
  40. package/dist/src/metrics/timeseries.js.map +1 -1
  41. package/dist/src/profiling/index.d.ts +1 -1
  42. package/dist/src/profiling/index.js +1 -1
  43. package/dist/src/registry.d.ts +30 -0
  44. package/dist/src/registry.d.ts.map +1 -1
  45. package/dist/src/registry.js +21 -0
  46. package/dist/src/registry.js.map +1 -1
  47. package/dist/src/request_watcher.d.ts +39 -0
  48. package/dist/src/request_watcher.d.ts.map +1 -1
  49. package/dist/src/request_watcher.js +45 -0
  50. package/dist/src/request_watcher.js.map +1 -1
  51. package/dist/src/store.d.ts +78 -0
  52. package/dist/src/store.d.ts.map +1 -1
  53. package/dist/src/stores/lucid.d.ts +37 -1
  54. package/dist/src/stores/lucid.d.ts.map +1 -1
  55. package/dist/src/stores/lucid.js +83 -0
  56. package/dist/src/stores/lucid.js.map +1 -1
  57. package/dist/src/stores/memory.d.ts +11 -1
  58. package/dist/src/stores/memory.d.ts.map +1 -1
  59. package/dist/src/stores/memory.js +61 -0
  60. package/dist/src/stores/memory.js.map +1 -1
  61. package/dist/src/telescope_middleware.d.ts +8 -0
  62. package/dist/src/telescope_middleware.d.ts.map +1 -1
  63. package/dist/src/telescope_middleware.js +19 -0
  64. package/dist/src/telescope_middleware.js.map +1 -1
  65. package/dist/src/ui/api.d.ts +16 -1
  66. package/dist/src/ui/api.d.ts.map +1 -1
  67. package/dist/src/ui/api.js +53 -5
  68. package/dist/src/ui/api.js.map +1 -1
  69. package/dist/src/ui/define_config.d.ts +12 -0
  70. package/dist/src/ui/define_config.d.ts.map +1 -1
  71. package/dist/src/ui/define_config.js +1 -0
  72. package/dist/src/ui/define_config.js.map +1 -1
  73. package/dist/src/ui/index.d.ts +1 -1
  74. package/dist/src/ui/index.js +1 -1
  75. package/dist/src/watchers/define_config.d.ts +28 -0
  76. package/dist/src/watchers/define_config.d.ts.map +1 -1
  77. package/dist/src/watchers/define_config.js +10 -0
  78. package/dist/src/watchers/define_config.js.map +1 -1
  79. package/dist/src/watchers/index.d.ts +4 -4
  80. package/dist/src/watchers/index.d.ts.map +1 -1
  81. package/dist/src/watchers/index.js +2 -3
  82. package/dist/src/watchers/index.js.map +1 -1
  83. package/dist/src/watchers/logs_watcher.d.ts +0 -19
  84. package/dist/src/watchers/logs_watcher.d.ts.map +1 -1
  85. package/dist/src/watchers/logs_watcher.js +22 -0
  86. package/dist/src/watchers/logs_watcher.js.map +1 -1
  87. package/dist/src/watchers/redis_watcher.d.ts +78 -1
  88. package/dist/src/watchers/redis_watcher.d.ts.map +1 -1
  89. package/dist/src/watchers/redis_watcher.js +124 -1
  90. package/dist/src/watchers/redis_watcher.js.map +1 -1
  91. package/package.json +1 -1
@@ -28,6 +28,28 @@ export interface TelescopeRuntime {
28
28
  * {@link RequestEnrichment}.
29
29
  */
30
30
  requestEnrichment: RequestEnrichment | null;
31
+ /**
32
+ * The dashboard's own URL prefix (e.g. `/telescope`), published by the UI provider.
33
+ *
34
+ * The request middleware skips it. Without that, the console competes with the
35
+ * application on the application's own list: telescope's aggregation endpoints are
36
+ * among the slowest the process serves — that is literally their job — so opening
37
+ * the Overview or Pulse recorded two more slow requests into the app's "slowest
38
+ * routes" ranking and its p99.
39
+ *
40
+ * `null` when the UI is not mounted, or when the host opted back in.
41
+ */
42
+ selfPath: string | null;
43
+ /**
44
+ * The watcher names actually running, published by both watcher providers.
45
+ *
46
+ * The console needs this to tell "nothing happened" apart from "nothing is being
47
+ * measured". A panel that renders "No N+1 loops detected 🎉" when the `query`
48
+ * watcher is off is not reporting health — it is reporting its own blindness, in
49
+ * the voice of good news. That is worse than showing nothing, because the reader
50
+ * walks away reassured.
51
+ */
52
+ enabledWatchers: Set<string>;
31
53
  /** The booted extension registry (entry types / dashboards / data providers), or `null`. */
32
54
  registry: ExtensionRegistry | null;
33
55
  /**
@@ -69,8 +91,16 @@ export interface TelescopeRuntime {
69
91
  export declare function getTelescopeRuntime(): TelescopeRuntime;
70
92
  /** Install the active store + flags (called by the provider at boot). */
71
93
  export declare function setTelescopeRuntime(store: TelescopeStore, requestWatcherEnabled: boolean, requestCapture?: RequestCaptureOptions | null, requestEnrichment?: RequestEnrichment | null): void;
94
+ /** Add watcher names to the set the console reads to distinguish "quiet" from "off". */
95
+ export declare function registerEnabledWatchers(names: Iterable<string>): void;
96
+ /** The watcher names currently running. */
97
+ export declare function getEnabledWatchers(): string[];
98
+ /** Publish (or clear) the dashboard's own path so the request middleware can skip it. */
99
+ export declare function setTelescopeSelfPath(path: string | null): void;
72
100
  /** Publish the booted extension registry so the UI can serve its dashboards + providers. */
73
101
  export declare function setTelescopeExtensionRegistry(registry: ExtensionRegistry | null): void;
102
+ /** The booted extension registry, or `null` when no extensions are configured. */
103
+ export declare function getTelescopeExtensionRegistry(): ExtensionRegistry | null;
74
104
  /** Publish the SSE entry-events bus so the UI stream route can subscribe to it. */
75
105
  export declare function setTelescopeEntryEvents(entryEvents: EntryEvents | null): void;
76
106
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,KAAK,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACrF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,2EAA2E;IAC3E,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IAC7B,iDAAiD;IACjD,qBAAqB,EAAE,OAAO,CAAC;IAC/B;;;;OAIG;IACH,cAAc,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAC7C;;;OAGG;IACH,iBAAiB,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC5C,4FAA4F;IAC5F,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACnC;;;;OAIG;IACH,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC;;;;;OAKG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB;;;;;OAKG;IACH,oBAAoB,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAClD;;;;;OAKG;IACH,WAAW,EAAE,eAAe,GAAG,IAAI,CAAC;IACpC;;;;;OAKG;IACH,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;CACnC;AAmBD,iCAAiC;AACjC,wBAAgB,mBAAmB,IAAI,gBAAgB,CAEtD;AAED,yEAAyE;AACzE,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,cAAc,EACrB,qBAAqB,EAAE,OAAO,EAC9B,cAAc,GAAE,qBAAqB,GAAG,IAAW,EACnD,iBAAiB,GAAE,iBAAiB,GAAG,IAAW,GACjD,IAAI,CAKN;AAED,4FAA4F;AAC5F,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,GAAG,IAAI,CAEtF;AAED,mFAAmF;AACnF,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI,CAE7E;AAED;;;;GAIG;AACH,wBAAgB,gCAAgC,CAAC,WAAW,EAAE,oBAAoB,GAAG,IAAI,GAAG,IAAI,CAE/F;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,GAAG,IAAI,CAE9E;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI,CAE3E;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAExD;AAED,kEAAkE;AAClE,wBAAgB,qBAAqB,IAAI,IAAI,CAW5C"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,KAAK,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACrF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,2EAA2E;IAC3E,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IAC7B,iDAAiD;IACjD,qBAAqB,EAAE,OAAO,CAAC;IAC/B;;;;OAIG;IACH,cAAc,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAC7C;;;OAGG;IACH,iBAAiB,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC5C;;;;;;;;;;OAUG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;;;;;;OAQG;IACH,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,4FAA4F;IAC5F,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACnC;;;;OAIG;IACH,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC;;;;;OAKG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB;;;;;OAKG;IACH,oBAAoB,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAClD;;;;;OAKG;IACH,WAAW,EAAE,eAAe,GAAG,IAAI,CAAC;IACpC;;;;;OAKG;IACH,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;CACnC;AAqBD,iCAAiC;AACjC,wBAAgB,mBAAmB,IAAI,gBAAgB,CAEtD;AAED,yEAAyE;AACzE,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,cAAc,EACrB,qBAAqB,EAAE,OAAO,EAC9B,cAAc,GAAE,qBAAqB,GAAG,IAAW,EACnD,iBAAiB,GAAE,iBAAiB,GAAG,IAAW,GACjD,IAAI,CAKN;AAED,wFAAwF;AACxF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,CAErE;AAED,2CAA2C;AAC3C,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAE7C;AAED,yFAAyF;AACzF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAE9D;AAED,4FAA4F;AAC5F,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,GAAG,IAAI,CAEtF;AAED,kFAAkF;AAClF,wBAAgB,6BAA6B,IAAI,iBAAiB,GAAG,IAAI,CAExE;AAED,mFAAmF;AACnF,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI,CAE7E;AAED;;;;GAIG;AACH,wBAAgB,gCAAgC,CAAC,WAAW,EAAE,oBAAoB,GAAG,IAAI,GAAG,IAAI,CAE/F;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,GAAG,IAAI,CAE9E;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI,CAE3E;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAExD;AAED,kEAAkE;AAClE,wBAAgB,qBAAqB,IAAI,IAAI,CAa5C"}
@@ -5,6 +5,8 @@ const runtime = globalStore[RUNTIME_KEY] ?? {
5
5
  requestWatcherEnabled: false,
6
6
  requestCapture: null,
7
7
  requestEnrichment: null,
8
+ selfPath: null,
9
+ enabledWatchers: new Set(),
8
10
  registry: null,
9
11
  entryEvents: null,
10
12
  paused: false,
@@ -24,10 +26,27 @@ export function setTelescopeRuntime(store, requestWatcherEnabled, requestCapture
24
26
  runtime.requestCapture = requestCapture;
25
27
  runtime.requestEnrichment = requestEnrichment;
26
28
  }
29
+ /** Add watcher names to the set the console reads to distinguish "quiet" from "off". */
30
+ export function registerEnabledWatchers(names) {
31
+ for (const name of names)
32
+ runtime.enabledWatchers.add(name);
33
+ }
34
+ /** The watcher names currently running. */
35
+ export function getEnabledWatchers() {
36
+ return [...runtime.enabledWatchers].sort();
37
+ }
38
+ /** Publish (or clear) the dashboard's own path so the request middleware can skip it. */
39
+ export function setTelescopeSelfPath(path) {
40
+ runtime.selfPath = path;
41
+ }
27
42
  /** Publish the booted extension registry so the UI can serve its dashboards + providers. */
28
43
  export function setTelescopeExtensionRegistry(registry) {
29
44
  runtime.registry = registry;
30
45
  }
46
+ /** The booted extension registry, or `null` when no extensions are configured. */
47
+ export function getTelescopeExtensionRegistry() {
48
+ return runtime.registry;
49
+ }
31
50
  /** Publish the SSE entry-events bus so the UI stream route can subscribe to it. */
32
51
  export function setTelescopeEntryEvents(entryEvents) {
33
52
  runtime.entryEvents = entryEvents;
@@ -70,6 +89,8 @@ export function resetTelescopeRuntime() {
70
89
  runtime.requestCapture = null;
71
90
  runtime.requestEnrichment = null;
72
91
  runtime.registry = null;
92
+ runtime.selfPath = null;
93
+ runtime.enabledWatchers.clear();
73
94
  runtime.entryEvents = null;
74
95
  runtime.paused = false;
75
96
  runtime.diagnosisCoordinator = null;
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/registry.ts"],"names":[],"mappings":"AAqEA,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,cAAc,EAAE,IAAI;IACpB,iBAAiB,EAAE,IAAI;IACvB,QAAQ,EAAE,IAAI;IACd,WAAW,EAAE,IAAI;IACjB,MAAM,EAAE,KAAK;IACb,oBAAoB,EAAE,IAAI;IAC1B,WAAW,EAAE,IAAI;IACjB,YAAY,EAAE,IAAI;CACnB,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,CACjC,KAAqB,EACrB,qBAA8B,EAC9B,cAAc,GAAiC,IAAI,EACnD,iBAAiB,GAA6B,IAAI;IAElD,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;IACtB,OAAO,CAAC,qBAAqB,GAAG,qBAAqB,CAAC;IACtD,OAAO,CAAC,cAAc,GAAG,cAAc,CAAC;IACxC,OAAO,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;AAChD,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,6BAA6B,CAAC,QAAkC;IAC9E,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;AAC9B,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,uBAAuB,CAAC,WAA+B;IACrE,OAAO,CAAC,WAAW,GAAG,WAAW,CAAC;AACpC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gCAAgC,CAAC,WAAwC;IACvF,OAAO,CAAC,oBAAoB,GAAG,WAAW,CAAC;AAC7C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,QAAgC;IACtE,OAAO,CAAC,WAAW,GAAG,QAAQ,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,OAA4B;IACnE,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC;AACjC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAe;IAChD,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;AAC1B,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,qBAAqB;IACnC,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IACrB,OAAO,CAAC,qBAAqB,GAAG,KAAK,CAAC;IACtC,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAC9B,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IACjC,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAC3B,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC;IACvB,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IACpC,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAC3B,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;AAC9B,CAAC"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/registry.ts"],"names":[],"mappings":"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"}
@@ -39,7 +39,43 @@ export interface RequestEntryContent {
39
39
  id: string;
40
40
  email?: string;
41
41
  } | null;
42
+ /**
43
+ * What KIND of request this was — see {@link classifyRequest}. `page` is a screen
44
+ * a person navigated to (Inertia visit or server-rendered HTML), `api` is data
45
+ * fetched by code, `asset` is a static file.
46
+ *
47
+ * Optional because entries recorded before this field existed do not have it, and
48
+ * the console has to keep rendering them.
49
+ */
50
+ kind?: RequestKind;
42
51
  }
52
+ /**
53
+ * How a request reached the app.
54
+ *
55
+ * The distinction the console could not make before: `GET /pesquisador/escrita` as a
56
+ * page visit and the dozen XHRs that page then fires are all `request` entries with
57
+ * a url, so "most visited screens" and "busiest endpoints" were the same list — and
58
+ * neither answered either question.
59
+ */
60
+ export type RequestKind = 'page' | 'api' | 'asset';
61
+ /**
62
+ * Classify a request as a screen visit, an API call, or a static asset.
63
+ *
64
+ * Order matters and encodes what is most reliable:
65
+ *
66
+ * 1. Assets go by URL, before anything else — a `.css` fetched with `Accept: * / *`
67
+ * would otherwise land in `api` and drown the endpoint list.
68
+ * 2. `x-inertia` is decisive for `page`. An Inertia visit asks for JSON and IS a
69
+ * screen navigation; going by `Accept` alone would file every one of them as
70
+ * `api`, which is exactly backwards for an Inertia app.
71
+ * 3. Then the response content-type, which describes what was actually served
72
+ * rather than what the client hoped for.
73
+ * 4. Then `Accept: text/html` — a plain browser navigation to a server-rendered
74
+ * page (an Edge template, a redirect landing).
75
+ *
76
+ * Anything left is `api`.
77
+ */
78
+ export declare function classifyRequest(request: RequestLike, responseContentType?: string): RequestKind;
43
79
  /**
44
80
  * Default `requestCapture.maxBodyBytes`: bodies over 128 KiB are not captured.
45
81
  * ON by default — the safe-by-default guard so a synchronous redaction walk over
@@ -165,6 +201,9 @@ export interface ResponseLike {
165
201
  statusCode?: number;
166
202
  /** AdonisJS `Response.getStatus()` — the only status accessor Adonis exposes. */
167
203
  getStatus?(): number;
204
+ /** Adonis's `response.getHeader(name)`. Optional so a plain stub still satisfies
205
+ * this shape — classification just falls back to the request headers. */
206
+ getHeader?(name: string): unknown;
168
207
  };
169
208
  }
170
209
  export interface HttpContextLike {
@@ -1 +1 @@
1
- {"version":3,"file":"request_watcher.d.ts","sourceRoot":"","sources":["../../src/request_watcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"request_watcher.d.ts","sourceRoot":"","sources":["../../src/request_watcher.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,40 @@
1
1
  import { currentUserRef } from './context_accessor.js';
2
2
  import { EntryType } from './entry.js';
3
+ /** File extensions treated as static assets. */
4
+ const ASSET_EXTENSIONS = /\.(?:js|mjs|cjs|css|map|png|jpe?g|gif|svg|webp|avif|ico|woff2?|ttf|eot|mp4|webm|txt|xml|wasm)$/i;
5
+ /**
6
+ * Classify a request as a screen visit, an API call, or a static asset.
7
+ *
8
+ * Order matters and encodes what is most reliable:
9
+ *
10
+ * 1. Assets go by URL, before anything else — a `.css` fetched with `Accept: * / *`
11
+ * would otherwise land in `api` and drown the endpoint list.
12
+ * 2. `x-inertia` is decisive for `page`. An Inertia visit asks for JSON and IS a
13
+ * screen navigation; going by `Accept` alone would file every one of them as
14
+ * `api`, which is exactly backwards for an Inertia app.
15
+ * 3. Then the response content-type, which describes what was actually served
16
+ * rather than what the client hoped for.
17
+ * 4. Then `Accept: text/html` — a plain browser navigation to a server-rendered
18
+ * page (an Edge template, a redirect landing).
19
+ *
20
+ * Anything left is `api`.
21
+ */
22
+ export function classifyRequest(request, responseContentType) {
23
+ const url = stripQuery(String(request.url()));
24
+ if (ASSET_EXTENSIONS.test(url))
25
+ return 'asset';
26
+ // An Inertia visit sets this and asks for JSON, but it is a screen navigation.
27
+ if (headerString(request, 'x-inertia') !== undefined)
28
+ return 'page';
29
+ if (responseContentType !== undefined && responseContentType.includes('text/html'))
30
+ return 'page';
31
+ const accept = headerString(request, 'accept') ?? '';
32
+ // `text/html` before any `application/json` in the list: browsers send both, and
33
+ // the FIRST one is what they actually prefer.
34
+ if (accept.includes('text/html'))
35
+ return 'page';
36
+ return 'api';
37
+ }
3
38
  /**
4
39
  * Default `requestCapture.maxBodyBytes`: bodies over 128 KiB are not captured.
5
40
  * ON by default — the safe-by-default guard so a synchronous redaction walk over
@@ -222,6 +257,7 @@ export async function recordRequest(store, ctx, startedAt, options = {}) {
222
257
  : enrichment.user !== undefined
223
258
  ? enrichment.user
224
259
  : resolveRequestUser(ctx);
260
+ const kind = classifyRequest(ctx.request, responseContentType(ctx));
225
261
  // Body capture (gated). Only when the caller opted in AND the request exposes a
226
262
  // body accessor. The gate runs HERE — before the store's synchronous redaction
227
263
  // walk — so a huge/binary body is replaced by a marker and never walked; a body
@@ -237,6 +273,7 @@ export async function recordRequest(store, ctx, startedAt, options = {}) {
237
273
  status,
238
274
  durationMs,
239
275
  traceId: options.traceId ?? null,
276
+ kind,
240
277
  user,
241
278
  ...(enrichment.context !== undefined ? { context: enrichment.context } : {}),
242
279
  ...(captureBody !== undefined ? { body: captureBody } : {}),
@@ -245,6 +282,7 @@ export async function recordRequest(store, ctx, startedAt, options = {}) {
245
282
  origin: 'http',
246
283
  tags: [
247
284
  `method:${method}`,
285
+ `kind:${kind}`,
248
286
  ...(status !== null ? [`status:${status}`] : []),
249
287
  ...(user?.id ? [`user:${user.id}`] : []),
250
288
  ...enrichment.tags,
@@ -256,6 +294,13 @@ export async function recordRequest(store, ctx, startedAt, options = {}) {
256
294
  recorded.content.traceId = recorded.traceId;
257
295
  return recorded;
258
296
  }
297
+ /** The response's content-type, when the host exposes a header accessor. */
298
+ function responseContentType(ctx) {
299
+ const value = ctx.response.getHeader?.('content-type');
300
+ if (typeof value === 'string')
301
+ return value;
302
+ return Array.isArray(value) && typeof value[0] === 'string' ? value[0] : undefined;
303
+ }
259
304
  /** Drop a `?query=string` suffix from a url. */
260
305
  function stripQuery(url) {
261
306
  const q = url.indexOf('?');
@@ -1 +1 @@
1
- {"version":3,"file":"request_watcher.js","sourceRoot":"","sources":["../../src/request_watcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"request_watcher.js","sourceRoot":"","sources":["../../src/request_watcher.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,13 @@ export interface EntryQuery {
12
12
  familyHash?: string;
13
13
  /** Only entries recorded under this trace id. */
14
14
  traceId?: string;
15
+ /**
16
+ * Only entries recorded under ANY of these trace ids. Exists so a page of traces
17
+ * can be hydrated with ONE query instead of one per trace: the traces screen picks
18
+ * its page of ids first (see {@link TelescopeStore.listTraceIds}) and then fetches
19
+ * exactly those entries. Composes with `traceId` as an additional constraint.
20
+ */
21
+ traceIds?: string[];
15
22
  /** Only entries strictly older than this instant (keyset-ish pagination). */
16
23
  before?: Date;
17
24
  /** Only entries newer than this instant. */
@@ -24,6 +31,46 @@ export interface EntryQuery {
24
31
  search?: string;
25
32
  /** Cap the number of returned entries. */
26
33
  limit?: number;
34
+ /**
35
+ * Skip this many entries before returning, for offset pagination. Applied AFTER
36
+ * ordering (newest-first), so `{ limit: 25, offset: 25 }` is the second page.
37
+ */
38
+ offset?: number;
39
+ }
40
+ /** One row of {@link TelescopeStore.listTraceIds} — a trace and when it was last seen. */
41
+ export interface TraceIdRow {
42
+ traceId: string;
43
+ /** The newest `createdAt` among the trace's entries. */
44
+ lastAt: Date;
45
+ }
46
+ /** One `(bucket, type)` tally from {@link TelescopeStore.countByBucket}. */
47
+ export interface BucketCountRow {
48
+ /** Zero-based bucket index, counted from `after` in `bucketMs` steps. */
49
+ index: number;
50
+ type: string;
51
+ count: number;
52
+ }
53
+ /** The window and bucket size for {@link TelescopeStore.countByBucket}. */
54
+ export interface BucketCountQuery {
55
+ /** Window start (exclusive), the origin bucket indices are counted from. */
56
+ after: Date;
57
+ /** Window end (inclusive). */
58
+ before: Date;
59
+ /** Bucket width in ms. */
60
+ bucketMs: number;
61
+ /** Only entries of this type. */
62
+ type?: string;
63
+ }
64
+ /** The window + page for {@link TelescopeStore.listTraceIds}. */
65
+ export interface TraceIdQuery {
66
+ /** How many trace ids to return. */
67
+ limit: number;
68
+ /** How many to skip, for offset pagination. */
69
+ offset?: number;
70
+ /** Only traces with an entry strictly older than this instant. */
71
+ before?: Date;
72
+ /** Only traces with an entry newer than this instant. */
73
+ after?: Date;
27
74
  }
28
75
  /**
29
76
  * The storage abstraction Telescope records through and the headless query API
@@ -52,5 +99,36 @@ export interface TelescopeStore {
52
99
  prune(olderThan: Date, keepLast?: number): Promise<number>;
53
100
  /** Delete every stored entry. */
54
101
  clear(): Promise<void>;
102
+ /**
103
+ * OPTIONAL fast path for the traces screen: the page of distinct trace ids,
104
+ * ordered by most-recently-seen, WITHOUT loading their entries.
105
+ *
106
+ * Why it exists: summarizing traces means grouping entries by `traceId`, and doing
107
+ * that in JS requires loading every candidate entry first. On a real table (500k+
108
+ * rows, dominated by whichever watcher is chattiest) asking for 80 traces meant
109
+ * reading 50k rows and discarding 99% of them. A store backed by SQL can answer
110
+ * this with `GROUP BY trace_id ORDER BY MAX(created_at) DESC LIMIT/OFFSET`, which
111
+ * is an index walk instead of a scan.
112
+ *
113
+ * OPTIONAL, and that is deliberate: it is a capability, not a requirement. A store
114
+ * that does not implement it (including any third-party one written before this
115
+ * existed) keeps working — the metrics service falls back to scan-and-group, which
116
+ * is correct, just slower.
117
+ */
118
+ listTraceIds?(query: TraceIdQuery): Promise<TraceIdRow[]>;
119
+ /**
120
+ * OPTIONAL fast path for the throughput chart: per-bucket, per-type COUNTS,
121
+ * without loading the entries.
122
+ *
123
+ * The chart needs exactly two fields — `createdAt` and `type` — but the only way
124
+ * to get them was `list()`, which selects whole rows including the `content` JSON
125
+ * blob. Drawing sixty bars meant shipping every entry in the window out of the
126
+ * database and parsing each one, to then throw all of it away except a timestamp
127
+ * and a string.
128
+ *
129
+ * OPTIONAL, like {@link listTraceIds}: a store without it falls back to
130
+ * scan-and-bucket, which is what this always used to do.
131
+ */
132
+ countByBucket?(query: BucketCountQuery): Promise<BucketCountRow[]>;
55
133
  }
56
134
  //# sourceMappingURL=store.d.ts.map
@@ -1 +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"}
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;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,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;IACf;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,0FAA0F;AAC1F,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,MAAM,EAAE,IAAI,CAAC;CACd;AAED,4EAA4E;AAC5E,MAAM,WAAW,cAAc;IAC7B,yEAAyE;IACzE,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB;IAC/B,4EAA4E;IAC5E,KAAK,EAAE,IAAI,CAAC;IACZ,8BAA8B;IAC9B,MAAM,EAAE,IAAI,CAAC;IACb,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,iEAAiE;AACjE,MAAM,WAAW,YAAY;IAC3B,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,MAAM,CAAC,EAAE,IAAI,CAAC;IACd,yDAAyD;IACzD,KAAK,CAAC,EAAE,IAAI,CAAC;CACd;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;IAEvB;;;;;;;;;;;;;;;OAeG;IACH,YAAY,CAAC,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAE1D;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;CACpE"}
@@ -1,5 +1,5 @@
1
1
  import { type Entry, type RecordInput } from '../entry.js';
2
- import type { EntryQuery, TelescopeStore } from '../store.js';
2
+ import type { BucketCountQuery, BucketCountRow, EntryQuery, TelescopeStore, TraceIdQuery, TraceIdRow } from '../store.js';
3
3
  /**
4
4
  * The table {@link LucidTelescopeStore} reads and writes. Override via
5
5
  * {@link LucidStoreOptions.tableName} when `telescope_entries` collides with an
@@ -66,8 +66,15 @@ export interface LucidQueryBuilderLike {
66
66
  where(column: string, value: unknown): this;
67
67
  where(column: string, operator: string, value: unknown): this;
68
68
  whereRaw(sql: string, bindings?: unknown[]): this;
69
+ whereIn(column: string, values: readonly unknown[]): this;
70
+ whereNotNull(column: string): this;
69
71
  orderBy(column: string, direction: 'asc' | 'desc'): this;
72
+ groupBy(...columns: string[]): this;
70
73
  limit(value: number): this;
74
+ offset(value: number): this;
75
+ /** Aggregate MAX with an alias, e.g. `max('created_at as last_at')`. Chainable so it
76
+ * composes with `select()` in a grouped query. */
77
+ max(expression: string): this;
71
78
  select(...columns: string[]): Promise<Record<string, unknown>[]>;
72
79
  count(column: string, alias: string): Promise<Record<string, unknown>[]>;
73
80
  delete(): Promise<number>;
@@ -127,6 +134,35 @@ export declare class LucidTelescopeStore implements TelescopeStore {
127
134
  record<TContent>(input: RecordInput<TContent>): Promise<Entry<TContent>>;
128
135
  get(id: string): Promise<Entry | null>;
129
136
  list(query?: EntryQuery): Promise<Entry[]>;
137
+ /**
138
+ * The page of distinct trace ids, most-recently-seen first — the SQL fast path
139
+ * described on {@link TelescopeStore.listTraceIds}.
140
+ *
141
+ * `GROUP BY trace_id` with `MAX(created_at)` lets the database do the grouping and
142
+ * the paging, so the traces screen reads ~`limit` rows instead of every entry in
143
+ * the window. Entries with a NULL `trace_id` are excluded: they belong to no trace
144
+ * and would collapse into one meaningless bucket.
145
+ */
146
+ listTraceIds(query: TraceIdQuery): Promise<TraceIdRow[]>;
147
+ /**
148
+ * Per-bucket, per-type counts for the throughput chart.
149
+ *
150
+ * The win here is the PROJECTION, not the grouping: the chart needs `created_at`
151
+ * and `type` and nothing else, but the only way to get them was `list()`, which
152
+ * does `select('*')` — shipping every row's `content` JSON blob out of the database
153
+ * and running it through `hydrate()`, to then discard all of it except a timestamp
154
+ * and a string. Two scalar columns instead of a blob is orders of magnitude less
155
+ * bytes on the wire and no per-row JSON parse.
156
+ *
157
+ * The bucketing itself stays in JS, deliberately. Doing it in SQL needs a raw
158
+ * select expression (`(created_at - ?) / ?`), and Lucid exposes `groupByRaw` but no
159
+ * `selectRaw` — the alternative is `rawQuery`, whose result shape differs per driver
160
+ * (`{ rows }` on Postgres, an array on SQLite). Trading a portability bug for the
161
+ * second-order win is a bad deal; the row count is what would justify it, and after
162
+ * the redis-watcher filter that count drops by roughly an order of magnitude. If
163
+ * this is still hot with a clean table, THAT is when it earns the raw query.
164
+ */
165
+ countByBucket(query: BucketCountQuery): Promise<BucketCountRow[]>;
130
166
  count(): Promise<number>;
131
167
  prune(olderThan: Date, keepLast?: number): Promise<number>;
132
168
  clear(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"lucid.d.ts","sourceRoot":"","sources":["../../../src/stores/lucid.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lucid.d.ts","sourceRoot":"","sources":["../../../src/stores/lucid.ts"],"names":[],"mappings":"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"}
@@ -181,6 +181,13 @@ export class LucidTelescopeStore {
181
181
  builder = builder.where('family_hash', query.familyHash);
182
182
  if (query.traceId !== undefined)
183
183
  builder = builder.where('trace_id', query.traceId);
184
+ if (query.traceIds !== undefined) {
185
+ // An empty list means "no traces", not "no filter" — whereIn([]) already yields
186
+ // zero rows, but being explicit keeps a caller's empty page from becoming a scan.
187
+ if (query.traceIds.length === 0)
188
+ return [];
189
+ builder = builder.whereIn('trace_id', query.traceIds);
190
+ }
184
191
  if (query.before !== undefined)
185
192
  builder = builder.where('created_at', '<', query.before.getTime());
186
193
  if (query.after !== undefined)
@@ -200,9 +207,85 @@ export class LucidTelescopeStore {
200
207
  builder = builder.orderBy('created_at', 'desc').orderBy('sequence', 'desc');
201
208
  if (query.limit !== undefined)
202
209
  builder = builder.limit(query.limit);
210
+ if (query.offset !== undefined && query.offset > 0)
211
+ builder = builder.offset(query.offset);
203
212
  const rows = await builder.select('*');
204
213
  return rows.map((r) => hydrate(r));
205
214
  }
215
+ /**
216
+ * The page of distinct trace ids, most-recently-seen first — the SQL fast path
217
+ * described on {@link TelescopeStore.listTraceIds}.
218
+ *
219
+ * `GROUP BY trace_id` with `MAX(created_at)` lets the database do the grouping and
220
+ * the paging, so the traces screen reads ~`limit` rows instead of every entry in
221
+ * the window. Entries with a NULL `trace_id` are excluded: they belong to no trace
222
+ * and would collapse into one meaningless bucket.
223
+ */
224
+ async listTraceIds(query) {
225
+ await this.init();
226
+ let builder = this.db.from(this.tableName);
227
+ if (query.before !== undefined)
228
+ builder = builder.where('created_at', '<', query.before.getTime());
229
+ if (query.after !== undefined)
230
+ builder = builder.where('created_at', '>', query.after.getTime());
231
+ // `select()` resolves the query, so it goes LAST — every chainable clause
232
+ // (including the MAX aggregate) has to be applied before it.
233
+ const rows = await builder
234
+ .whereNotNull('trace_id')
235
+ .groupBy('trace_id')
236
+ .max('created_at as last_at')
237
+ .orderBy('last_at', 'desc')
238
+ .limit(query.limit)
239
+ .offset(query.offset ?? 0)
240
+ .select('trace_id');
241
+ return rows.map((row) => ({
242
+ traceId: row.trace_id,
243
+ lastAt: new Date(toInt(row.last_at)),
244
+ }));
245
+ }
246
+ /**
247
+ * Per-bucket, per-type counts for the throughput chart.
248
+ *
249
+ * The win here is the PROJECTION, not the grouping: the chart needs `created_at`
250
+ * and `type` and nothing else, but the only way to get them was `list()`, which
251
+ * does `select('*')` — shipping every row's `content` JSON blob out of the database
252
+ * and running it through `hydrate()`, to then discard all of it except a timestamp
253
+ * and a string. Two scalar columns instead of a blob is orders of magnitude less
254
+ * bytes on the wire and no per-row JSON parse.
255
+ *
256
+ * The bucketing itself stays in JS, deliberately. Doing it in SQL needs a raw
257
+ * select expression (`(created_at - ?) / ?`), and Lucid exposes `groupByRaw` but no
258
+ * `selectRaw` — the alternative is `rawQuery`, whose result shape differs per driver
259
+ * (`{ rows }` on Postgres, an array on SQLite). Trading a portability bug for the
260
+ * second-order win is a bad deal; the row count is what would justify it, and after
261
+ * the redis-watcher filter that count drops by roughly an order of magnitude. If
262
+ * this is still hot with a clean table, THAT is when it earns the raw query.
263
+ */
264
+ async countByBucket(query) {
265
+ await this.init();
266
+ const startMs = query.after.getTime();
267
+ const bucketMs = Math.max(1, Math.floor(query.bucketMs));
268
+ let builder = this.db
269
+ .from(this.tableName)
270
+ .where('created_at', '>', startMs)
271
+ .where('created_at', '<=', query.before.getTime());
272
+ if (query.type !== undefined)
273
+ builder = builder.where('type', query.type);
274
+ const rows = (await builder.select('created_at', 'type'));
275
+ const tally = new Map();
276
+ for (const row of rows) {
277
+ const index = Math.floor((toInt(row.created_at) - startMs) / bucketMs);
278
+ const key = `${index}\u0000${row.type}`;
279
+ const seen = tally.get(key);
280
+ if (seen === undefined) {
281
+ tally.set(key, { index, type: row.type, count: 1 });
282
+ }
283
+ else {
284
+ seen.count += 1;
285
+ }
286
+ }
287
+ return [...tally.values()];
288
+ }
206
289
  async count() {
207
290
  await this.init();
208
291
  const rows = await this.db.from(this.tableName).count('*', 'total');