@adonis-agora/telescope 0.3.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/configure.d.ts.map +1 -1
  3. package/dist/configure.js +6 -0
  4. package/dist/configure.js.map +1 -1
  5. package/dist/providers/telescope_ai_provider.d.ts +9 -1
  6. package/dist/providers/telescope_ai_provider.d.ts.map +1 -1
  7. package/dist/providers/telescope_ai_provider.js +22 -2
  8. package/dist/providers/telescope_ai_provider.js.map +1 -1
  9. package/dist/providers/telescope_alerts_provider.d.ts +1 -0
  10. package/dist/providers/telescope_alerts_provider.d.ts.map +1 -1
  11. package/dist/providers/telescope_alerts_provider.js +37 -1
  12. package/dist/providers/telescope_alerts_provider.js.map +1 -1
  13. package/dist/providers/telescope_mcp_provider.d.ts +26 -0
  14. package/dist/providers/telescope_mcp_provider.d.ts.map +1 -0
  15. package/dist/providers/telescope_mcp_provider.js +114 -0
  16. package/dist/providers/telescope_mcp_provider.js.map +1 -0
  17. package/dist/providers/telescope_provider.d.ts +8 -0
  18. package/dist/providers/telescope_provider.d.ts.map +1 -1
  19. package/dist/providers/telescope_provider.js +56 -1
  20. package/dist/providers/telescope_provider.js.map +1 -1
  21. package/dist/providers/telescope_ui_provider.d.ts +2 -0
  22. package/dist/providers/telescope_ui_provider.d.ts.map +1 -1
  23. package/dist/providers/telescope_ui_provider.js +106 -22
  24. package/dist/providers/telescope_ui_provider.js.map +1 -1
  25. package/dist/providers/telescope_watchers_provider.d.ts +13 -2
  26. package/dist/providers/telescope_watchers_provider.d.ts.map +1 -1
  27. package/dist/providers/telescope_watchers_provider.js +57 -7
  28. package/dist/providers/telescope_watchers_provider.js.map +1 -1
  29. package/dist/src/ai/define_config.d.ts +39 -7
  30. package/dist/src/ai/define_config.d.ts.map +1 -1
  31. package/dist/src/ai/define_config.js +14 -4
  32. package/dist/src/ai/define_config.js.map +1 -1
  33. package/dist/src/ai/diagnosis_coordinator.d.ts +106 -0
  34. package/dist/src/ai/diagnosis_coordinator.d.ts.map +1 -0
  35. package/dist/src/ai/diagnosis_coordinator.js +143 -0
  36. package/dist/src/ai/diagnosis_coordinator.js.map +1 -0
  37. package/dist/src/ai/factory.d.ts +8 -5
  38. package/dist/src/ai/factory.d.ts.map +1 -1
  39. package/dist/src/ai/factory.js +20 -8
  40. package/dist/src/ai/factory.js.map +1 -1
  41. package/dist/src/ai/index.d.ts +3 -1
  42. package/dist/src/ai/index.d.ts.map +1 -1
  43. package/dist/src/ai/index.js +3 -1
  44. package/dist/src/ai/index.js.map +1 -1
  45. package/dist/src/alerts/alert_rule.d.ts +79 -11
  46. package/dist/src/alerts/alert_rule.d.ts.map +1 -1
  47. package/dist/src/alerts/alerter.d.ts +11 -1
  48. package/dist/src/alerts/alerter.d.ts.map +1 -1
  49. package/dist/src/alerts/alerter.js +21 -1
  50. package/dist/src/alerts/alerter.js.map +1 -1
  51. package/dist/src/alerts/alerter_service.d.ts +103 -0
  52. package/dist/src/alerts/alerter_service.d.ts.map +1 -0
  53. package/dist/src/alerts/alerter_service.js +215 -0
  54. package/dist/src/alerts/alerter_service.js.map +1 -0
  55. package/dist/src/alerts/index.d.ts +4 -2
  56. package/dist/src/alerts/index.d.ts.map +1 -1
  57. package/dist/src/alerts/index.js +4 -2
  58. package/dist/src/alerts/index.js.map +1 -1
  59. package/dist/src/alerts/slack_format.d.ts.map +1 -1
  60. package/dist/src/alerts/slack_format.js +35 -2
  61. package/dist/src/alerts/slack_format.js.map +1 -1
  62. package/dist/src/client_errors/config.d.ts +66 -0
  63. package/dist/src/client_errors/config.d.ts.map +1 -0
  64. package/dist/src/client_errors/config.js +17 -0
  65. package/dist/src/client_errors/config.js.map +1 -0
  66. package/dist/src/client_errors/index.d.ts +5 -0
  67. package/dist/src/client_errors/index.d.ts.map +1 -0
  68. package/dist/src/client_errors/index.js +5 -0
  69. package/dist/src/client_errors/index.js.map +1 -0
  70. package/dist/src/client_errors/ingestor.d.ts +87 -0
  71. package/dist/src/client_errors/ingestor.d.ts.map +1 -0
  72. package/dist/src/client_errors/ingestor.js +135 -0
  73. package/dist/src/client_errors/ingestor.js.map +1 -0
  74. package/dist/src/client_errors/rate_limiter.d.ts +53 -0
  75. package/dist/src/client_errors/rate_limiter.d.ts.map +1 -0
  76. package/dist/src/client_errors/rate_limiter.js +83 -0
  77. package/dist/src/client_errors/rate_limiter.js.map +1 -0
  78. package/dist/src/client_errors/validation.d.ts +62 -0
  79. package/dist/src/client_errors/validation.d.ts.map +1 -0
  80. package/dist/src/client_errors/validation.js +109 -0
  81. package/dist/src/client_errors/validation.js.map +1 -0
  82. package/dist/src/define_config.d.ts +120 -0
  83. package/dist/src/define_config.d.ts.map +1 -1
  84. package/dist/src/define_config.js +41 -0
  85. package/dist/src/define_config.js.map +1 -1
  86. package/dist/src/entry.d.ts +20 -0
  87. package/dist/src/entry.d.ts.map +1 -1
  88. package/dist/src/entry.js +20 -0
  89. package/dist/src/entry.js.map +1 -1
  90. package/dist/src/index.d.ts +17 -4
  91. package/dist/src/index.d.ts.map +1 -1
  92. package/dist/src/index.js +16 -3
  93. package/dist/src/index.js.map +1 -1
  94. package/dist/src/mcp/define_config.d.ts +57 -0
  95. package/dist/src/mcp/define_config.d.ts.map +1 -0
  96. package/dist/src/mcp/define_config.js +35 -0
  97. package/dist/src/mcp/define_config.js.map +1 -0
  98. package/dist/src/mcp/index.d.ts +7 -0
  99. package/dist/src/mcp/index.d.ts.map +1 -0
  100. package/dist/src/mcp/index.js +7 -0
  101. package/dist/src/mcp/index.js.map +1 -0
  102. package/dist/src/mcp/server.d.ts +89 -0
  103. package/dist/src/mcp/server.d.ts.map +1 -0
  104. package/dist/src/mcp/server.js +279 -0
  105. package/dist/src/mcp/server.js.map +1 -0
  106. package/dist/src/metrics/pulse.d.ts +158 -0
  107. package/dist/src/metrics/pulse.d.ts.map +1 -0
  108. package/dist/src/metrics/pulse.js +414 -0
  109. package/dist/src/metrics/pulse.js.map +1 -0
  110. package/dist/src/overload_guard.d.ts +77 -0
  111. package/dist/src/overload_guard.d.ts.map +1 -0
  112. package/dist/src/overload_guard.js +134 -0
  113. package/dist/src/overload_guard.js.map +1 -0
  114. package/dist/src/pruner.d.ts +93 -0
  115. package/dist/src/pruner.d.ts.map +1 -0
  116. package/dist/src/pruner.js +120 -0
  117. package/dist/src/pruner.js.map +1 -0
  118. package/dist/src/registry.d.ts +26 -0
  119. package/dist/src/registry.d.ts.map +1 -1
  120. package/dist/src/registry.js +19 -0
  121. package/dist/src/registry.js.map +1 -1
  122. package/dist/src/service.d.ts +16 -1
  123. package/dist/src/service.d.ts.map +1 -1
  124. package/dist/src/service.js +19 -1
  125. package/dist/src/service.js.map +1 -1
  126. package/dist/src/stores/lucid.d.ts +20 -0
  127. package/dist/src/stores/lucid.d.ts.map +1 -1
  128. package/dist/src/stores/lucid.js +89 -4
  129. package/dist/src/stores/lucid.js.map +1 -1
  130. package/dist/src/telescope_middleware.d.ts.map +1 -1
  131. package/dist/src/telescope_middleware.js +3 -1
  132. package/dist/src/telescope_middleware.js.map +1 -1
  133. package/dist/src/ui/api.d.ts +9 -1
  134. package/dist/src/ui/api.d.ts.map +1 -1
  135. package/dist/src/ui/api.js +23 -1
  136. package/dist/src/ui/api.js.map +1 -1
  137. package/dist/src/ui/auth.d.ts +112 -0
  138. package/dist/src/ui/auth.d.ts.map +1 -0
  139. package/dist/src/ui/auth.js +130 -0
  140. package/dist/src/ui/auth.js.map +1 -0
  141. package/dist/src/ui/dashboard_auth.d.ts +34 -0
  142. package/dist/src/ui/dashboard_auth.d.ts.map +1 -0
  143. package/dist/src/ui/dashboard_auth.js +57 -0
  144. package/dist/src/ui/dashboard_auth.js.map +1 -0
  145. package/dist/src/ui/define_config.d.ts +15 -0
  146. package/dist/src/ui/define_config.d.ts.map +1 -1
  147. package/dist/src/ui/define_config.js +4 -0
  148. package/dist/src/ui/define_config.js.map +1 -1
  149. package/dist/src/ui/index.d.ts +7 -1
  150. package/dist/src/ui/index.d.ts.map +1 -1
  151. package/dist/src/ui/index.js +6 -1
  152. package/dist/src/ui/index.js.map +1 -1
  153. package/dist/src/ui/login_page.d.ts +23 -0
  154. package/dist/src/ui/login_page.d.ts.map +1 -0
  155. package/dist/src/ui/login_page.js +170 -0
  156. package/dist/src/ui/login_page.js.map +1 -0
  157. package/dist/src/ui/session_cookie.d.ts +42 -0
  158. package/dist/src/ui/session_cookie.d.ts.map +1 -0
  159. package/dist/src/ui/session_cookie.js +97 -0
  160. package/dist/src/ui/session_cookie.js.map +1 -0
  161. package/dist/src/watchers/define_config.d.ts +115 -12
  162. package/dist/src/watchers/define_config.d.ts.map +1 -1
  163. package/dist/src/watchers/define_config.js +48 -11
  164. package/dist/src/watchers/define_config.js.map +1 -1
  165. package/dist/src/watchers/http_client_watcher.d.ts +91 -31
  166. package/dist/src/watchers/http_client_watcher.d.ts.map +1 -1
  167. package/dist/src/watchers/http_client_watcher.js +161 -53
  168. package/dist/src/watchers/http_client_watcher.js.map +1 -1
  169. package/dist/src/watchers/index.d.ts +9 -5
  170. package/dist/src/watchers/index.d.ts.map +1 -1
  171. package/dist/src/watchers/index.js +6 -2
  172. package/dist/src/watchers/index.js.map +1 -1
  173. package/dist/src/watchers/lucid_query_watcher.d.ts +20 -2
  174. package/dist/src/watchers/lucid_query_watcher.d.ts.map +1 -1
  175. package/dist/src/watchers/lucid_query_watcher.js +44 -10
  176. package/dist/src/watchers/lucid_query_watcher.js.map +1 -1
  177. package/dist/src/watchers/profiling_watcher.d.ts +144 -0
  178. package/dist/src/watchers/profiling_watcher.d.ts.map +1 -0
  179. package/dist/src/watchers/profiling_watcher.js +231 -0
  180. package/dist/src/watchers/profiling_watcher.js.map +1 -0
  181. package/dist/src/watchers/query_family_hash.d.ts +7 -2
  182. package/dist/src/watchers/query_family_hash.d.ts.map +1 -1
  183. package/dist/src/watchers/query_family_hash.js +8 -3
  184. package/dist/src/watchers/query_family_hash.js.map +1 -1
  185. package/dist/src/watchers/record.d.ts.map +1 -1
  186. package/dist/src/watchers/record.js +4 -0
  187. package/dist/src/watchers/record.js.map +1 -1
  188. package/dist/src/watchers/schedule_watcher.d.ts +143 -0
  189. package/dist/src/watchers/schedule_watcher.d.ts.map +1 -0
  190. package/dist/src/watchers/schedule_watcher.js +195 -0
  191. package/dist/src/watchers/schedule_watcher.js.map +1 -0
  192. package/dist/stubs/config/telescope.stub +0 -65
  193. package/dist/stubs/config/telescope_ai.stub +0 -36
  194. package/dist/stubs/config/telescope_alerts.stub +0 -47
  195. package/dist/stubs/config/telescope_mcp.stub +0 -0
  196. package/dist/stubs/config/telescope_ui.stub +0 -53
  197. package/dist/stubs/config/telescope_watchers.stub +0 -41
  198. package/dist/stubs/database/migrations/create_telescope_entries_table.stub +2 -2
  199. package/package.json +12 -2
@@ -4,6 +4,10 @@ import { queryFamilyHash } from './query_family_hash.js';
4
4
  import { safeRecord } from './record.js';
5
5
  /** The Lucid event name this watcher subscribes to. */
6
6
  export const DB_QUERY_EVENT = 'db:query';
7
+ /** Placeholder a bound value is replaced with when `captureBindings` is off. */
8
+ const REDACTED = '[REDACTED]';
9
+ /** Default slow-query threshold (ms), mirrored from the resolved watcher config. */
10
+ const DEFAULT_SLOW_MS = 500;
7
11
  /** Convert a `process.hrtime()` `[seconds, nanoseconds]` tuple to milliseconds. */
8
12
  function hrtimeToMs(duration) {
9
13
  if (!Array.isArray(duration) || duration.length !== 2)
@@ -38,6 +42,16 @@ function isDbQueryEvent(data) {
38
42
  export class LucidQueryWatcher {
39
43
  type = EntryType.Query;
40
44
  unsubscribe = null;
45
+ slowMs;
46
+ captureBindings;
47
+ ignoreConnections;
48
+ normalize;
49
+ constructor(options = {}) {
50
+ this.slowMs = options.slowMs ?? DEFAULT_SLOW_MS;
51
+ this.captureBindings = options.captureBindings ?? false;
52
+ this.ignoreConnections = new Set((options.ignoreConnections ?? []).map((name) => name.toLowerCase()));
53
+ this.normalize = options.normalize ?? true;
54
+ }
41
55
  start(emitter) {
42
56
  if (this.unsubscribe)
43
57
  return;
@@ -51,34 +65,54 @@ export class LucidQueryWatcher {
51
65
  handle(data) {
52
66
  if (!isDbQueryEvent(data))
53
67
  return;
54
- safeRecord(buildQueryEntry(data), 'LucidQueryWatcher');
68
+ // An ignored connection is dropped before any work — a telescope query that
69
+ // hits the store's own DB, a replica used only for the timeline, etc.
70
+ if (this.ignoreConnections.has(data.connection.toLowerCase()))
71
+ return;
72
+ safeRecord(buildQueryEntry(data, {
73
+ slowMs: this.slowMs,
74
+ captureBindings: this.captureBindings,
75
+ normalize: this.normalize,
76
+ }), 'LucidQueryWatcher');
55
77
  }
56
78
  }
57
- /** Map a Lucid `db:query` payload to a telescope {@link RecordInput}. */
58
- export function buildQueryEntry(event) {
79
+ /** Map a Lucid `db:query` payload to a telescope {@link RecordInput}. Exported so
80
+ * the entry shape can be unit-tested without a running emitter. */
81
+ export function buildQueryEntry(event, options = {}) {
82
+ const slowMs = options.slowMs ?? DEFAULT_SLOW_MS;
83
+ const captureBindings = options.captureBindings ?? false;
84
+ const normalize = options.normalize ?? true;
59
85
  const durationMs = hrtimeToMs(event.duration);
60
86
  const method = typeof event.method === 'string' ? event.method : null;
61
87
  const traceId = currentTraceId();
88
+ const rawBindings = Array.isArray(event.bindings) ? event.bindings : [];
62
89
  const content = {
63
90
  sql: event.sql,
64
- bindings: Array.isArray(event.bindings) ? event.bindings : [],
91
+ // Redact bound VALUES by default (they carry PII/secrets) while preserving
92
+ // arity, so the query's shape stays visible without leaking data.
93
+ bindings: captureBindings ? rawBindings : rawBindings.map(() => REDACTED),
65
94
  durationMs,
66
95
  connection: event.connection,
67
96
  method,
68
97
  inTransaction: typeof event.inTransaction === 'boolean' ? event.inTransaction : null,
69
98
  traceId,
70
99
  };
100
+ const tags = [
101
+ `connection:${event.connection}`,
102
+ ...(method ? [`method:${method}`] : []),
103
+ ...(event.model ? [`model:${event.model}`] : []),
104
+ ];
105
+ if (durationMs !== null && durationMs >= slowMs)
106
+ tags.push('slow');
71
107
  return {
72
108
  type: EntryType.Query,
73
- familyHash: queryFamilyHash(event.sql),
109
+ // Group by SQL template (see queryFamilyHash) so "the same query" rolls up
110
+ // for the Pulse slow-query + N+1 cards. `normalize: false` hashes verbatim.
111
+ familyHash: normalize ? queryFamilyHash(event.sql) : queryFamilyHash(event.sql, false),
74
112
  content,
75
113
  durationMs,
76
114
  traceId,
77
- tags: [
78
- `connection:${event.connection}`,
79
- ...(method ? [`method:${method}`] : []),
80
- ...(event.model ? [`model:${event.model}`] : []),
81
- ],
115
+ tags,
82
116
  };
83
117
  }
84
118
  //# sourceMappingURL=lucid_query_watcher.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lucid_query_watcher.js","sourceRoot":"","sources":["../../../src/watchers/lucid_query_watcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lucid_query_watcher.js","sourceRoot":"","sources":["../../../src/watchers/lucid_query_watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAoB,MAAM,aAAa,CAAC;AAE1D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,uDAAuD;AACvD,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC;AAEzC,gFAAgF;AAChF,MAAM,QAAQ,GAAG,YAAY,CAAC;AAE9B,oFAAoF;AACpF,MAAM,eAAe,GAAG,GAAG,CAAC;AAmD5B,mFAAmF;AACnF,SAAS,UAAU,CAAC,QAAsC;IACxD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACnE,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC;IACxC,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,WAAW,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAChF,OAAO,OAAO,GAAG,IAAI,GAAG,WAAW,GAAG,GAAG,CAAC;AAC5C,CAAC;AAED,uEAAuE;AACvE,SAAS,cAAc,CAAC,IAAa;IACnC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC5D,MAAM,SAAS,GAAG,IAA+B,CAAC;IAClD,OAAO,OAAO,SAAS,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,SAAS,CAAC,UAAU,KAAK,QAAQ,CAAC;AACvF,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,iBAAiB;IACnB,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC;IACxB,WAAW,GAAwB,IAAI,CAAC;IAC/B,MAAM,CAAS;IACf,eAAe,CAAU;IACzB,iBAAiB,CAAc;IAC/B,SAAS,CAAU;IAEpC,YAAY,UAAoC,EAAE;QAChD,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,eAAe,CAAC;QAChD,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,KAAK,CAAC;QACxD,IAAI,CAAC,iBAAiB,GAAG,IAAI,GAAG,CAC9B,CAAC,OAAO,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CACpE,CAAC;QACF,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,OAAoB;QACxB,IAAI,IAAI,CAAC,WAAW;YAAE,OAAO;QAC7B,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,EAAE,CAAC,cAAc,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7E,CAAC;IAED,IAAI;QACF,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACrB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC1B,CAAC;IAED,qEAAqE;IAC7D,MAAM,CAAC,IAAa;QAC1B,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC;YAAE,OAAO;QAClC,4EAA4E;QAC5E,sEAAsE;QACtE,IAAI,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC;YAAE,OAAO;QACtE,UAAU,CACR,eAAe,CAAC,IAAI,EAAE;YACpB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC,EACF,mBAAmB,CACpB,CAAC;IACJ,CAAC;CACF;AAED;oEACoE;AACpE,MAAM,UAAU,eAAe,CAC7B,KAAuB,EACvB,UAAoC,EAAE;IAEtC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,eAAe,CAAC;IACjD,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,KAAK,CAAC;IACzD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC;IAE5C,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IACtE,MAAM,OAAO,GAAG,cAAc,EAAE,CAAC;IACjC,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IACxE,MAAM,OAAO,GAAsB;QACjC,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,2EAA2E;QAC3E,kEAAkE;QAClE,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC;QACzE,UAAU;QACV,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,MAAM;QACN,aAAa,EAAE,OAAO,KAAK,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI;QACpF,OAAO;KACR,CAAC;IACF,MAAM,IAAI,GAAa;QACrB,cAAc,KAAK,CAAC,UAAU,EAAE;QAChC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACvC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KACjD,CAAC;IACF,IAAI,UAAU,KAAK,IAAI,IAAI,UAAU,IAAI,MAAM;QAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEnE,OAAO;QACL,IAAI,EAAE,SAAS,CAAC,KAAK;QACrB,2EAA2E;QAC3E,4EAA4E;QAC5E,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC;QACtF,OAAO;QACP,UAAU;QACV,OAAO;QACP,IAAI;KACL,CAAC;AACJ,CAAC"}
@@ -0,0 +1,144 @@
1
+ import { type RecordInput } from '../entry.js';
2
+ /** The `type` of the entries this watcher records. */
3
+ export declare const PROFILE_ENTRY_TYPE: "profile";
4
+ /** The terminal outcome of a profiling span. */
5
+ export type ProfileStatus = 'completed' | 'failed';
6
+ /** A timing mark taken inside a span, offset (ms) from the span's start. */
7
+ export interface ProfileMark {
8
+ /** The mark label, e.g. `'validated'`, `'db-loaded'`. */
9
+ label: string;
10
+ /** Milliseconds elapsed from the span's start when the mark was taken. */
11
+ atMs: number;
12
+ }
13
+ /** The recorded body of a `profile` entry. */
14
+ export interface ProfileEntryContent {
15
+ /** The span label, e.g. `'checkout'`. */
16
+ label: string;
17
+ /** Total wall-clock duration of the span in milliseconds. */
18
+ durationMs: number;
19
+ /** The span outcome. */
20
+ status: ProfileStatus;
21
+ /** In-order timing marks taken inside the span (nested checkpoints). */
22
+ marks: ProfileMark[];
23
+ /** The failure message when `status` is `'failed'`, else `null`. */
24
+ failureReason: string | null;
25
+ /** The active trace id at record time, or `null`. */
26
+ traceId: string | null;
27
+ }
28
+ /** Options for {@link ProfilingWatcher}. */
29
+ export interface ProfilingWatcherOptions {
30
+ /** Spans at/above this many ms get a `slow` tag. Default 100. */
31
+ slowMs?: number;
32
+ /**
33
+ * Spans whose duration is below this are discarded (too short to be worth a
34
+ * timeline entry). Default `0` (keep all).
35
+ */
36
+ minDurationMs?: number;
37
+ /** Time source; injectable for tests. Default `Date.now`. */
38
+ clock?: {
39
+ now(): number;
40
+ };
41
+ }
42
+ /**
43
+ * An in-flight profiling span. Add {@link mark}s inside the timed section, then
44
+ * call {@link end} (or {@link fail}) exactly once to record it. Recording is
45
+ * fire-and-forget and fully guarded — a telescope failure can never break the
46
+ * code being profiled.
47
+ */
48
+ export interface ProfileSession {
49
+ /** Take a timing mark at the current instant (offset from the span's start). */
50
+ mark(label: string): this;
51
+ /** Finish the span and record it as `completed`. Idempotent. */
52
+ end(): void;
53
+ /** Finish the span and record it as `failed` with the given error. Idempotent. */
54
+ fail(error: unknown): void;
55
+ }
56
+ /** A completed span handed to {@link buildProfileEntry}. */
57
+ export interface CompletedProfile {
58
+ label: string;
59
+ durationMs: number;
60
+ status: ProfileStatus;
61
+ marks: ProfileMark[];
62
+ error?: unknown;
63
+ }
64
+ /**
65
+ * Records user-instrumented profiling spans as `profile` telescope entries — one
66
+ * per timed code section, capturing its label, total duration, in-span timing
67
+ * marks, and outcome (completed/failed), correlated to the active trace.
68
+ *
69
+ * ## How it works
70
+ * Unlike the emitter-driven watchers, profiling is DRIVEN BY THE USER: there is
71
+ * no event to tap. Wrap a code section with {@link profile} (or bracket it with
72
+ * {@link startProfile} + {@link ProfileSession.end}); the watcher times it and
73
+ * records one entry. It never monkey-patches anything and carries no cost while
74
+ * disabled — the standalone helpers are a no-op until the provider calls
75
+ * {@link start}.
76
+ *
77
+ * Each entry carries `familyHash` (the label) and `durationMs`, so repeated spans
78
+ * of the same label roll up and feed the slow-hotspot metrics cards. Recording is
79
+ * fire-and-forget and fully guarded: a telescope failure can never break the code
80
+ * being profiled.
81
+ *
82
+ * Idiomatic Adonis: a plain class, no DI decorators. The provider constructs it
83
+ * from `config/telescope_watchers.ts` and calls {@link start} to publish it as the
84
+ * default backing the bare {@link profile} / {@link startProfile} helpers;
85
+ * {@link stop} unpublishes.
86
+ */
87
+ export declare class ProfilingWatcher {
88
+ readonly type: "profile";
89
+ private readonly slowMs;
90
+ private readonly minDurationMs;
91
+ private readonly clock;
92
+ constructor(options?: ProfilingWatcherOptions);
93
+ /** The watcher's time source (used by its sessions). */
94
+ now(): number;
95
+ /** Publish this configured instance as the default the standalone
96
+ * {@link profile} / {@link startProfile} helpers inherit. Does NOT patch any
97
+ * global. Named `start`/`stop` to match the other watchers' provider lifecycle. */
98
+ start(): void;
99
+ /** Unpublish this instance as the default (if it is). Never touches globals. */
100
+ stop(): void;
101
+ /** Begin a profiling span. Add marks on the returned session, then `end()`/`fail()`. */
102
+ startProfile(label: string): ProfileSession;
103
+ /**
104
+ * Time `fn` as a profiling span. The span's session is passed to `fn` so it can
105
+ * add timing marks. Records `completed` on return / resolve and `failed` on
106
+ * throw / reject, always re-throwing so the caller's control flow is untouched.
107
+ * Works with sync and async `fn`.
108
+ */
109
+ profile<T>(label: string, fn: (session: ProfileSession) => T): T;
110
+ /** Record one already-completed span. Spans below `minDurationMs` are dropped;
111
+ * recording is fire-and-forget and never throws. */
112
+ record(profile: CompletedProfile): void;
113
+ }
114
+ /** Map a completed span to a telescope {@link RecordInput}. Exported so the entry
115
+ * shape can be unit-tested without a live watcher. */
116
+ export declare function buildProfileEntry(profile: CompletedProfile, slowMs?: number): RecordInput<ProfileEntryContent>;
117
+ /**
118
+ * Begin a profiling span through the provider-published default watcher. Returns a
119
+ * NO-OP session (nothing recorded) when the profiling watcher is not enabled, so
120
+ * this is safe to leave in code unconditionally.
121
+ *
122
+ * @example
123
+ * import { startProfile } from '@adonis-agora/telescope/watchers'
124
+ * const span = startProfile('checkout')
125
+ * // ... work ...
126
+ * span.mark('validated')
127
+ * // ... more work ...
128
+ * span.end()
129
+ */
130
+ export declare function startProfile(label: string): ProfileSession;
131
+ /**
132
+ * Time `fn` as a profiling span through the provider-published default watcher.
133
+ * A no-op passthrough (just runs `fn`) when the profiling watcher is not enabled.
134
+ *
135
+ * @example
136
+ * import { profile } from '@adonis-agora/telescope/watchers'
137
+ * const order = await profile('checkout', async (span) => {
138
+ * const cart = await loadCart()
139
+ * span.mark('cart-loaded')
140
+ * return placeOrder(cart)
141
+ * })
142
+ */
143
+ export declare function profile<T>(label: string, fn: (session: ProfileSession) => T): T;
144
+ //# sourceMappingURL=profiling_watcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiling_watcher.d.ts","sourceRoot":"","sources":["../../../src/watchers/profiling_watcher.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1D,sDAAsD;AACtD,eAAO,MAAM,kBAAkB,WAAoB,CAAC;AAEpD,gDAAgD;AAChD,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,QAAQ,CAAC;AAEnD,4EAA4E;AAC5E,MAAM,WAAW,WAAW;IAC1B,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;CACd;AAED,8CAA8C;AAC9C,MAAM,WAAW,mBAAmB;IAClC,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,UAAU,EAAE,MAAM,CAAC;IACnB,wBAAwB;IACxB,MAAM,EAAE,aAAa,CAAC;IACtB,wEAAwE;IACxE,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,oEAAoE;IACpE,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,qDAAqD;IACrD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,4CAA4C;AAC5C,MAAM,WAAW,uBAAuB;IACtC,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6DAA6D;IAC7D,KAAK,CAAC,EAAE;QAAE,GAAG,IAAI,MAAM,CAAA;KAAE,CAAC;CAC3B;AAKD;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,gFAAgF;IAChF,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,gEAAgE;IAChE,GAAG,IAAI,IAAI,CAAC;IACZ,kFAAkF;IAClF,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CAC5B;AAiDD,4DAA4D;AAC5D,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,aAAa,CAAC;IACtB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAoBD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,gBAAgB;IAC3B,QAAQ,CAAC,IAAI,YAAqB;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;gBAE9B,OAAO,GAAE,uBAA4B;IAMjD,wDAAwD;IACxD,GAAG,IAAI,MAAM;IAIb;;wFAEoF;IACpF,KAAK,IAAI,IAAI;IAIb,gFAAgF;IAChF,IAAI,IAAI,IAAI;IAIZ,wFAAwF;IACxF,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc;IAI3C;;;;;OAKG;IACH,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,CAAC,GAAG,CAAC;IAyBhE;yDACqD;IACrD,MAAM,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;CAIxC;AAWD;uDACuD;AACvD,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,gBAAgB,EACzB,MAAM,SAAkB,GACvB,WAAW,CAAC,mBAAmB,CAAC,CA4BlC;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAG1D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,CAAC,GAAG,CAAC,CAI/E"}
@@ -0,0 +1,231 @@
1
+ import { currentTraceId } from '../context_accessor.js';
2
+ import { EntryType } from '../entry.js';
3
+ import { safeRecord } from './record.js';
4
+ /** The `type` of the entries this watcher records. */
5
+ export const PROFILE_ENTRY_TYPE = EntryType.Profile;
6
+ /** Default slow-span threshold in milliseconds. */
7
+ const DEFAULT_SLOW_MS = 100;
8
+ /** A no-op session returned when profiling is not enabled — zero recording cost. */
9
+ const NOOP_SESSION = {
10
+ mark() {
11
+ return this;
12
+ },
13
+ end() { },
14
+ fail() { },
15
+ };
16
+ /** The live session backed by a configured watcher. */
17
+ class ActiveProfileSession {
18
+ watcher;
19
+ label;
20
+ startedAt;
21
+ marks = [];
22
+ settled = false;
23
+ constructor(watcher, label, startedAt) {
24
+ this.watcher = watcher;
25
+ this.label = label;
26
+ this.startedAt = startedAt;
27
+ }
28
+ mark(label) {
29
+ if (this.settled)
30
+ return this;
31
+ this.marks.push({ label, atMs: Math.max(0, this.watcher.now() - this.startedAt) });
32
+ return this;
33
+ }
34
+ end() {
35
+ this.settle('completed', undefined);
36
+ }
37
+ fail(error) {
38
+ this.settle('failed', error);
39
+ }
40
+ settle(status, error) {
41
+ if (this.settled)
42
+ return;
43
+ this.settled = true;
44
+ this.watcher.record({
45
+ label: this.label,
46
+ durationMs: Math.max(0, this.watcher.now() - this.startedAt),
47
+ status,
48
+ marks: this.marks,
49
+ error,
50
+ });
51
+ }
52
+ }
53
+ /**
54
+ * Cross-copy-stable slot holding the provider-configured default watcher, so the
55
+ * standalone {@link profile} / {@link startProfile} helpers inherit the app's
56
+ * configured `slowMs` / `minDurationMs` — and, crucially, are a NO-OP until the
57
+ * provider starts the watcher (profiling stays strictly opt-in). A `Symbol.for`
58
+ * global slot keeps two copies of this package in agreement, mirroring the
59
+ * http-client watcher's default-slot stance.
60
+ */
61
+ const DEFAULT_SLOT = Symbol.for('@agora/telescope:defaultProfilingWatcher');
62
+ const slotHost = globalThis;
63
+ function setDefaultProfilingWatcher(watcher) {
64
+ slotHost[DEFAULT_SLOT] = watcher;
65
+ }
66
+ function getDefaultProfilingWatcher() {
67
+ return slotHost[DEFAULT_SLOT] ?? null;
68
+ }
69
+ /**
70
+ * Records user-instrumented profiling spans as `profile` telescope entries — one
71
+ * per timed code section, capturing its label, total duration, in-span timing
72
+ * marks, and outcome (completed/failed), correlated to the active trace.
73
+ *
74
+ * ## How it works
75
+ * Unlike the emitter-driven watchers, profiling is DRIVEN BY THE USER: there is
76
+ * no event to tap. Wrap a code section with {@link profile} (or bracket it with
77
+ * {@link startProfile} + {@link ProfileSession.end}); the watcher times it and
78
+ * records one entry. It never monkey-patches anything and carries no cost while
79
+ * disabled — the standalone helpers are a no-op until the provider calls
80
+ * {@link start}.
81
+ *
82
+ * Each entry carries `familyHash` (the label) and `durationMs`, so repeated spans
83
+ * of the same label roll up and feed the slow-hotspot metrics cards. Recording is
84
+ * fire-and-forget and fully guarded: a telescope failure can never break the code
85
+ * being profiled.
86
+ *
87
+ * Idiomatic Adonis: a plain class, no DI decorators. The provider constructs it
88
+ * from `config/telescope_watchers.ts` and calls {@link start} to publish it as the
89
+ * default backing the bare {@link profile} / {@link startProfile} helpers;
90
+ * {@link stop} unpublishes.
91
+ */
92
+ export class ProfilingWatcher {
93
+ type = EntryType.Profile;
94
+ slowMs;
95
+ minDurationMs;
96
+ clock;
97
+ constructor(options = {}) {
98
+ this.slowMs = options.slowMs ?? DEFAULT_SLOW_MS;
99
+ this.minDurationMs = Math.max(0, options.minDurationMs ?? 0);
100
+ this.clock = options.clock ?? { now: () => Date.now() };
101
+ }
102
+ /** The watcher's time source (used by its sessions). */
103
+ now() {
104
+ return this.clock.now();
105
+ }
106
+ /** Publish this configured instance as the default the standalone
107
+ * {@link profile} / {@link startProfile} helpers inherit. Does NOT patch any
108
+ * global. Named `start`/`stop` to match the other watchers' provider lifecycle. */
109
+ start() {
110
+ setDefaultProfilingWatcher(this);
111
+ }
112
+ /** Unpublish this instance as the default (if it is). Never touches globals. */
113
+ stop() {
114
+ if (getDefaultProfilingWatcher() === this)
115
+ setDefaultProfilingWatcher(null);
116
+ }
117
+ /** Begin a profiling span. Add marks on the returned session, then `end()`/`fail()`. */
118
+ startProfile(label) {
119
+ return new ActiveProfileSession(this, label, this.clock.now());
120
+ }
121
+ /**
122
+ * Time `fn` as a profiling span. The span's session is passed to `fn` so it can
123
+ * add timing marks. Records `completed` on return / resolve and `failed` on
124
+ * throw / reject, always re-throwing so the caller's control flow is untouched.
125
+ * Works with sync and async `fn`.
126
+ */
127
+ profile(label, fn) {
128
+ const session = this.startProfile(label);
129
+ let result;
130
+ try {
131
+ result = fn(session);
132
+ }
133
+ catch (error) {
134
+ session.fail(error);
135
+ throw error;
136
+ }
137
+ if (isPromiseLike(result)) {
138
+ return result.then((value) => {
139
+ session.end();
140
+ return value;
141
+ }, (error) => {
142
+ session.fail(error);
143
+ throw error;
144
+ });
145
+ }
146
+ session.end();
147
+ return result;
148
+ }
149
+ /** Record one already-completed span. Spans below `minDurationMs` are dropped;
150
+ * recording is fire-and-forget and never throws. */
151
+ record(profile) {
152
+ if (profile.durationMs < this.minDurationMs)
153
+ return;
154
+ safeRecord(buildProfileEntry(profile, this.slowMs), 'ProfilingWatcher');
155
+ }
156
+ }
157
+ /** Narrow a value to a thenable so async `fn`s are awaited without importing a Promise type. */
158
+ function isPromiseLike(value) {
159
+ return (typeof value === 'object' &&
160
+ value !== null &&
161
+ typeof value.then === 'function');
162
+ }
163
+ /** Map a completed span to a telescope {@link RecordInput}. Exported so the entry
164
+ * shape can be unit-tested without a live watcher. */
165
+ export function buildProfileEntry(profile, slowMs = DEFAULT_SLOW_MS) {
166
+ const durationMs = Math.max(0, profile.durationMs);
167
+ const failed = profile.status === 'failed';
168
+ const failureReason = failed && profile.error !== undefined ? errorMessage(profile.error) : null;
169
+ const traceId = currentTraceId();
170
+ const content = {
171
+ label: profile.label,
172
+ durationMs,
173
+ status: profile.status,
174
+ marks: profile.marks,
175
+ failureReason,
176
+ traceId,
177
+ };
178
+ const tags = ['profile', `profile:${profile.label}`];
179
+ if (failed)
180
+ tags.push('failed');
181
+ if (durationMs >= slowMs)
182
+ tags.push('slow');
183
+ return {
184
+ type: EntryType.Profile,
185
+ // Group by label so every run of the same span rolls up — the slow-hotspot key.
186
+ familyHash: `profile:${profile.label}`,
187
+ content,
188
+ durationMs,
189
+ traceId,
190
+ tags,
191
+ };
192
+ }
193
+ function errorMessage(error) {
194
+ return error instanceof Error ? error.message : String(error);
195
+ }
196
+ /**
197
+ * Begin a profiling span through the provider-published default watcher. Returns a
198
+ * NO-OP session (nothing recorded) when the profiling watcher is not enabled, so
199
+ * this is safe to leave in code unconditionally.
200
+ *
201
+ * @example
202
+ * import { startProfile } from '@adonis-agora/telescope/watchers'
203
+ * const span = startProfile('checkout')
204
+ * // ... work ...
205
+ * span.mark('validated')
206
+ * // ... more work ...
207
+ * span.end()
208
+ */
209
+ export function startProfile(label) {
210
+ const watcher = getDefaultProfilingWatcher();
211
+ return watcher ? watcher.startProfile(label) : NOOP_SESSION;
212
+ }
213
+ /**
214
+ * Time `fn` as a profiling span through the provider-published default watcher.
215
+ * A no-op passthrough (just runs `fn`) when the profiling watcher is not enabled.
216
+ *
217
+ * @example
218
+ * import { profile } from '@adonis-agora/telescope/watchers'
219
+ * const order = await profile('checkout', async (span) => {
220
+ * const cart = await loadCart()
221
+ * span.mark('cart-loaded')
222
+ * return placeOrder(cart)
223
+ * })
224
+ */
225
+ export function profile(label, fn) {
226
+ const watcher = getDefaultProfilingWatcher();
227
+ if (watcher)
228
+ return watcher.profile(label, fn);
229
+ return fn(NOOP_SESSION);
230
+ }
231
+ //# sourceMappingURL=profiling_watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiling_watcher.js","sourceRoot":"","sources":["../../../src/watchers/profiling_watcher.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,11 @@
3
3
  * from `nestjs-telescope`'s query family-hash so a dashboard can roll up every
4
4
  * execution of `select * from users where id = ?` regardless of the id.
5
5
  */
6
- /** Grouping key for "the same query" — same template, any bound values. */
7
- export declare function queryFamilyHash(sql: string): string;
6
+ /**
7
+ * Grouping key for "the same query". With `normalize` on (the default) the SQL is
8
+ * templated first, so every execution of the same shape shares a hash regardless
9
+ * of bound values; with it off the raw SQL is hashed verbatim (whitespace/literals
10
+ * distinguish entries — no cross-execution grouping).
11
+ */
12
+ export declare function queryFamilyHash(sql: string, normalize?: boolean): string;
8
13
  //# sourceMappingURL=query_family_hash.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"query_family_hash.d.ts","sourceRoot":"","sources":["../../../src/watchers/query_family_hash.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAyBH,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEnD"}
1
+ {"version":3,"file":"query_family_hash.d.ts","sourceRoot":"","sources":["../../../src/watchers/query_family_hash.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAyBH;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,UAAO,GAAG,MAAM,CAErE"}
@@ -24,8 +24,13 @@ function fnv1a(input) {
24
24
  }
25
25
  return (hash >>> 0).toString(16).padStart(8, '0');
26
26
  }
27
- /** Grouping key for "the same query" — same template, any bound values. */
28
- export function queryFamilyHash(sql) {
29
- return fnv1a(normalizeSql(sql));
27
+ /**
28
+ * Grouping key for "the same query". With `normalize` on (the default) the SQL is
29
+ * templated first, so every execution of the same shape shares a hash regardless
30
+ * of bound values; with it off the raw SQL is hashed verbatim (whitespace/literals
31
+ * distinguish entries — no cross-execution grouping).
32
+ */
33
+ export function queryFamilyHash(sql, normalize = true) {
34
+ return fnv1a(normalize ? normalizeSql(sql) : sql);
30
35
  }
31
36
  //# sourceMappingURL=query_family_hash.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"query_family_hash.js","sourceRoot":"","sources":["../../../src/watchers/query_family_hash.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,SAAS,YAAY,CAAC,GAAW;IAC/B,OAAO,GAAG;SACP,WAAW,EAAE;SACb,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC,kBAAkB;SAClD,OAAO,CAAC,oBAAoB,EAAE,GAAG,CAAC,CAAC,mBAAmB;SACtD,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,8EAA8E;AAC9E,SAAS,KAAK,CAAC,KAAa;IAC1B,IAAI,IAAI,GAAG,UAAU,CAAC;IACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACpD,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,OAAO,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;AAClC,CAAC"}
1
+ {"version":3,"file":"query_family_hash.js","sourceRoot":"","sources":["../../../src/watchers/query_family_hash.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,SAAS,YAAY,CAAC,GAAW;IAC/B,OAAO,GAAG;SACP,WAAW,EAAE;SACb,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC,kBAAkB;SAClD,OAAO,CAAC,oBAAoB,EAAE,GAAG,CAAC,CAAC,mBAAmB;SACtD,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,8EAA8E;AAC9E,SAAS,KAAK,CAAC,KAAa;IAC1B,IAAI,IAAI,GAAG,UAAU,CAAC;IACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACpD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW,EAAE,SAAS,GAAG,IAAI;IAC3D,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AACpD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../../src/watchers/record.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD;;;;;;;GAOG;AACH,wBAAgB,YAAY,IAAI,cAAc,GAAG,IAAI,CAEpD;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAmBnE"}
1
+ {"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../../src/watchers/record.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD;;;;;;;GAOG;AACH,wBAAgB,YAAY,IAAI,cAAc,GAAG,IAAI,CAEpD;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAsBnE"}
@@ -31,6 +31,10 @@ export function safeRecord(input, source) {
31
31
  }
32
32
  if (!store)
33
33
  return;
34
+ // Honour the overload guard's shed flag: while paused, drop new entries so a
35
+ // lagging event loop is never made worse by telescope's own write path.
36
+ if (getTelescopeRuntime().paused)
37
+ return;
34
38
  try {
35
39
  const resolved = input.traceId === undefined ? { ...input, traceId: currentTraceId() } : input;
36
40
  // Fire-and-forget: the store is async but the subscriber is sync. Swallow
@@ -1 +1 @@
1
- {"version":3,"file":"record.js","sourceRoot":"","sources":["../../../src/watchers/record.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAGrD;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,mBAAmB,EAAE,CAAC,KAAK,CAAC;AACrC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,KAAkB,EAAE,MAAc;IAC3D,IAAI,KAA4B,CAAC;IACjC,IAAI,CAAC;QACH,KAAK,GAAG,YAAY,EAAE,CAAC;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACzB,OAAO;IACT,CAAC;IACD,IAAI,CAAC,KAAK;QAAE,OAAO;IAEnB,IAAI,CAAC;QACH,MAAM,QAAQ,GACZ,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QAChF,0EAA0E;QAC1E,sEAAsE;QACtE,KAAK,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IACxF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,MAAc,EAAE,GAAY;IAC/C,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjE,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,uCAAuC,OAAO,EAAE,CAAC,CAAC;AAC3E,CAAC"}
1
+ {"version":3,"file":"record.js","sourceRoot":"","sources":["../../../src/watchers/record.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAGrD;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,mBAAmB,EAAE,CAAC,KAAK,CAAC;AACrC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,KAAkB,EAAE,MAAc;IAC3D,IAAI,KAA4B,CAAC;IACjC,IAAI,CAAC;QACH,KAAK,GAAG,YAAY,EAAE,CAAC;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACzB,OAAO;IACT,CAAC;IACD,IAAI,CAAC,KAAK;QAAE,OAAO;IACnB,6EAA6E;IAC7E,wEAAwE;IACxE,IAAI,mBAAmB,EAAE,CAAC,MAAM;QAAE,OAAO;IAEzC,IAAI,CAAC;QACH,MAAM,QAAQ,GACZ,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QAChF,0EAA0E;QAC1E,sEAAsE;QACtE,KAAK,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IACxF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,MAAc,EAAE,GAAY;IAC/C,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjE,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,uCAAuC,OAAO,EAAE,CAAC,CAAC;AAC3E,CAAC"}