@wizeworks/lens-cloud 0.3.0-alpha.2 → 0.3.0-alpha.3

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 (215) hide show
  1. package/README.md +1 -0
  2. package/dist/alerts/evaluate.d.ts.map +1 -1
  3. package/dist/alerts/evaluate.js +3 -4
  4. package/dist/alerts/evaluate.js.map +1 -1
  5. package/dist/app.d.ts +6 -0
  6. package/dist/app.d.ts.map +1 -1
  7. package/dist/auth/join-scope.d.ts +7 -0
  8. package/dist/auth/join-scope.d.ts.map +1 -0
  9. package/dist/auth/join-scope.js +17 -0
  10. package/dist/auth/join-scope.js.map +1 -0
  11. package/dist/changes.d.ts +15 -0
  12. package/dist/changes.d.ts.map +1 -0
  13. package/dist/changes.js +45 -0
  14. package/dist/changes.js.map +1 -0
  15. package/dist/cli-args.d.ts +1 -1
  16. package/dist/cli-args.d.ts.map +1 -1
  17. package/dist/cli-args.js +11 -0
  18. package/dist/cli-args.js.map +1 -1
  19. package/dist/cli.js +4 -0
  20. package/dist/cli.js.map +1 -1
  21. package/dist/config.d.ts +5 -1
  22. package/dist/config.d.ts.map +1 -1
  23. package/dist/config.js +2 -0
  24. package/dist/config.js.map +1 -1
  25. package/dist/copy-cli.d.ts +3 -0
  26. package/dist/copy-cli.d.ts.map +1 -0
  27. package/dist/copy-cli.js +24 -0
  28. package/dist/copy-cli.js.map +1 -0
  29. package/dist/db/db.d.ts +2 -0
  30. package/dist/db/db.d.ts.map +1 -1
  31. package/dist/db/db.js +15 -4
  32. package/dist/db/db.js.map +1 -1
  33. package/dist/db/schema-search.d.ts +2 -0
  34. package/dist/db/schema-search.d.ts.map +1 -0
  35. package/dist/db/schema-search.js +16 -0
  36. package/dist/db/schema-search.js.map +1 -0
  37. package/dist/db/schema.d.ts.map +1 -1
  38. package/dist/db/schema.js +2 -0
  39. package/dist/db/schema.js.map +1 -1
  40. package/dist/db/trigram.d.ts +4 -0
  41. package/dist/db/trigram.d.ts.map +1 -0
  42. package/dist/db/trigram.js +34 -0
  43. package/dist/db/trigram.js.map +1 -0
  44. package/dist/jobs.d.ts +1 -1
  45. package/dist/jobs.d.ts.map +1 -1
  46. package/dist/jobs.js +10 -9
  47. package/dist/jobs.js.map +1 -1
  48. package/dist/mail/blocks.d.ts +1 -1
  49. package/dist/mail/blocks.js +2 -2
  50. package/dist/mail/blocks.js.map +1 -1
  51. package/dist/mail/layout.d.ts +1 -1
  52. package/dist/mail/layout.d.ts.map +1 -1
  53. package/dist/mail/layout.js +2 -2
  54. package/dist/mail/layout.js.map +1 -1
  55. package/dist/mail/mailer.d.ts.map +1 -1
  56. package/dist/mail/mailer.js +4 -3
  57. package/dist/mail/mailer.js.map +1 -1
  58. package/dist/mail/resend.d.ts +2 -0
  59. package/dist/mail/resend.d.ts.map +1 -1
  60. package/dist/mail/resend.js +1 -1
  61. package/dist/mail/resend.js.map +1 -1
  62. package/dist/mail/theme.d.ts +7 -1
  63. package/dist/mail/theme.d.ts.map +1 -1
  64. package/dist/mail/theme.js +7 -1
  65. package/dist/mail/theme.js.map +1 -1
  66. package/dist/notify/digest-data.d.ts +2 -1
  67. package/dist/notify/digest-data.d.ts.map +1 -1
  68. package/dist/notify/digest-data.js +4 -10
  69. package/dist/notify/digest-data.js.map +1 -1
  70. package/dist/notify/digest.js +1 -1
  71. package/dist/notify/digest.js.map +1 -1
  72. package/dist/notify/health.d.ts.map +1 -1
  73. package/dist/notify/health.js +4 -5
  74. package/dist/notify/health.js.map +1 -1
  75. package/dist/repo/services.d.ts +6 -0
  76. package/dist/repo/services.d.ts.map +1 -0
  77. package/dist/repo/services.js +16 -0
  78. package/dist/repo/services.js.map +1 -0
  79. package/dist/repo/trace-join.d.ts +9 -0
  80. package/dist/repo/trace-join.d.ts.map +1 -0
  81. package/dist/repo/trace-join.js +35 -0
  82. package/dist/repo/trace-join.js.map +1 -0
  83. package/dist/repo/trace-read.d.ts +6 -13
  84. package/dist/repo/trace-read.d.ts.map +1 -1
  85. package/dist/repo/trace-read.js +8 -3
  86. package/dist/repo/trace-read.js.map +1 -1
  87. package/dist/repo/trace-write.d.ts +5 -1
  88. package/dist/repo/trace-write.d.ts.map +1 -1
  89. package/dist/repo/trace-write.js +11 -2
  90. package/dist/repo/trace-write.js.map +1 -1
  91. package/dist/routes/changes.d.ts +4 -0
  92. package/dist/routes/changes.d.ts.map +1 -0
  93. package/dist/routes/changes.js +19 -0
  94. package/dist/routes/changes.js.map +1 -0
  95. package/dist/routes/data.d.ts.map +1 -1
  96. package/dist/routes/data.js +24 -9
  97. package/dist/routes/data.js.map +1 -1
  98. package/dist/routes/index.d.ts.map +1 -1
  99. package/dist/routes/index.js +4 -0
  100. package/dist/routes/index.js.map +1 -1
  101. package/dist/routes/ingest.d.ts.map +1 -1
  102. package/dist/routes/ingest.js +7 -2
  103. package/dist/routes/ingest.js.map +1 -1
  104. package/dist/routes/mcp.d.ts.map +1 -1
  105. package/dist/routes/mcp.js +42 -25
  106. package/dist/routes/mcp.js.map +1 -1
  107. package/dist/routes/metrics.d.ts +2 -2
  108. package/dist/routes/metrics.d.ts.map +1 -1
  109. package/dist/routes/metrics.js +2 -3
  110. package/dist/routes/metrics.js.map +1 -1
  111. package/dist/routes/models.d.ts +2 -0
  112. package/dist/routes/models.d.ts.map +1 -1
  113. package/dist/routes/models.js +10 -5
  114. package/dist/routes/models.js.map +1 -1
  115. package/dist/routes/orgs.d.ts.map +1 -1
  116. package/dist/routes/orgs.js +4 -0
  117. package/dist/routes/orgs.js.map +1 -1
  118. package/dist/routes/projects.d.ts.map +1 -1
  119. package/dist/routes/projects.js +1 -0
  120. package/dist/routes/projects.js.map +1 -1
  121. package/dist/routes/search.d.ts +4 -0
  122. package/dist/routes/search.d.ts.map +1 -0
  123. package/dist/routes/search.js +33 -0
  124. package/dist/routes/search.js.map +1 -0
  125. package/dist/routes/shares.d.ts.map +1 -1
  126. package/dist/routes/shares.js +8 -5
  127. package/dist/routes/shares.js.map +1 -1
  128. package/dist/server.d.ts.map +1 -1
  129. package/dist/server.js +17 -5
  130. package/dist/server.js.map +1 -1
  131. package/dist/settle.d.ts +7 -6
  132. package/dist/settle.d.ts.map +1 -1
  133. package/dist/settle.js +30 -13
  134. package/dist/settle.js.map +1 -1
  135. package/dist/telemetry/cached.d.ts +11 -0
  136. package/dist/telemetry/cached.d.ts.map +1 -0
  137. package/dist/telemetry/cached.js +30 -0
  138. package/dist/telemetry/cached.js.map +1 -0
  139. package/dist/telemetry/ch/admin.d.ts +10 -0
  140. package/dist/telemetry/ch/admin.d.ts.map +1 -0
  141. package/dist/telemetry/ch/admin.js +65 -0
  142. package/dist/telemetry/ch/admin.js.map +1 -0
  143. package/dist/telemetry/ch/http.d.ts +19 -0
  144. package/dist/telemetry/ch/http.d.ts.map +1 -0
  145. package/dist/telemetry/ch/http.js +91 -0
  146. package/dist/telemetry/ch/http.js.map +1 -0
  147. package/dist/telemetry/ch/metrics.d.ts +10 -0
  148. package/dist/telemetry/ch/metrics.d.ts.map +1 -0
  149. package/dist/telemetry/ch/metrics.js +61 -0
  150. package/dist/telemetry/ch/metrics.js.map +1 -0
  151. package/dist/telemetry/ch/queries.d.ts +19 -0
  152. package/dist/telemetry/ch/queries.d.ts.map +1 -0
  153. package/dist/telemetry/ch/queries.js +30 -0
  154. package/dist/telemetry/ch/queries.js.map +1 -0
  155. package/dist/telemetry/ch/queue.d.ts +34 -0
  156. package/dist/telemetry/ch/queue.d.ts.map +1 -0
  157. package/dist/telemetry/ch/queue.js +79 -0
  158. package/dist/telemetry/ch/queue.js.map +1 -0
  159. package/dist/telemetry/ch/read.d.ts +12 -0
  160. package/dist/telemetry/ch/read.d.ts.map +1 -0
  161. package/dist/telemetry/ch/read.js +72 -0
  162. package/dist/telemetry/ch/read.js.map +1 -0
  163. package/dist/telemetry/ch/schema-facts.d.ts +6 -0
  164. package/dist/telemetry/ch/schema-facts.d.ts.map +1 -0
  165. package/dist/telemetry/ch/schema-facts.js +49 -0
  166. package/dist/telemetry/ch/schema-facts.js.map +1 -0
  167. package/dist/telemetry/ch/schema-raw.d.ts +8 -0
  168. package/dist/telemetry/ch/schema-raw.d.ts.map +1 -0
  169. package/dist/telemetry/ch/schema-raw.js +35 -0
  170. package/dist/telemetry/ch/schema-raw.js.map +1 -0
  171. package/dist/telemetry/ch/schema-rollups.d.ts +2 -0
  172. package/dist/telemetry/ch/schema-rollups.d.ts.map +1 -0
  173. package/dist/telemetry/ch/schema-rollups.js +61 -0
  174. package/dist/telemetry/ch/schema-rollups.js.map +1 -0
  175. package/dist/telemetry/ch/schema.d.ts +12 -0
  176. package/dist/telemetry/ch/schema.d.ts.map +1 -0
  177. package/dist/telemetry/ch/schema.js +25 -0
  178. package/dist/telemetry/ch/schema.js.map +1 -0
  179. package/dist/telemetry/ch/settle-rows.d.ts +13 -0
  180. package/dist/telemetry/ch/settle-rows.d.ts.map +1 -0
  181. package/dist/telemetry/ch/settle-rows.js +67 -0
  182. package/dist/telemetry/ch/settle-rows.js.map +1 -0
  183. package/dist/telemetry/ch/settle.d.ts +7 -0
  184. package/dist/telemetry/ch/settle.d.ts.map +1 -0
  185. package/dist/telemetry/ch/settle.js +96 -0
  186. package/dist/telemetry/ch/settle.js.map +1 -0
  187. package/dist/telemetry/ch/store.d.ts +16 -0
  188. package/dist/telemetry/ch/store.d.ts.map +1 -0
  189. package/dist/telemetry/ch/store.js +65 -0
  190. package/dist/telemetry/ch/store.js.map +1 -0
  191. package/dist/telemetry/ch/util.d.ts +20 -0
  192. package/dist/telemetry/ch/util.d.ts.map +1 -0
  193. package/dist/telemetry/ch/util.js +45 -0
  194. package/dist/telemetry/ch/util.js.map +1 -0
  195. package/dist/telemetry/ch/write.d.ts +11 -0
  196. package/dist/telemetry/ch/write.d.ts.map +1 -0
  197. package/dist/telemetry/ch/write.js +59 -0
  198. package/dist/telemetry/ch/write.js.map +1 -0
  199. package/dist/telemetry/copy.d.ts +9 -0
  200. package/dist/telemetry/copy.d.ts.map +1 -0
  201. package/dist/telemetry/copy.js +60 -0
  202. package/dist/telemetry/copy.js.map +1 -0
  203. package/dist/telemetry/index.d.ts +11 -0
  204. package/dist/telemetry/index.d.ts.map +1 -0
  205. package/dist/telemetry/index.js +21 -0
  206. package/dist/telemetry/index.js.map +1 -0
  207. package/dist/telemetry/pg-store.d.ts +5 -0
  208. package/dist/telemetry/pg-store.d.ts.map +1 -0
  209. package/dist/telemetry/pg-store.js +78 -0
  210. package/dist/telemetry/pg-store.js.map +1 -0
  211. package/dist/telemetry/store.d.ts +74 -0
  212. package/dist/telemetry/store.d.ts.map +1 -0
  213. package/dist/telemetry/store.js +2 -0
  214. package/dist/telemetry/store.js.map +1 -0
  215. package/package.json +6 -5
@@ -0,0 +1,49 @@
1
+ // ClickHouse fact tables (one row per request, trace, log line, slow span, search document, attribute), and views with the Postgres names.
2
+ import { EXPIRE, monthOf } from "./schema-raw.js";
3
+ const P = "project_id LowCardinality(String), trace_id String";
4
+ const VERSIONED = "ver UInt64, is_deleted UInt8, expire_ms Float64";
5
+ /** A fact table: replaced by version, deleted by tombstone; the view reads only live rows, with the Postgres columns. */
6
+ function fact(name, cols, order, time, indexes = "") {
7
+ const names = cols.split(/,\s*/).map((c) => c.trim().split(/\s+/)[0]);
8
+ return [
9
+ `CREATE TABLE IF NOT EXISTS ${name}_t (${P}, ${cols}, ${VERSIONED}${indexes ? `, ${indexes}` : ""})
10
+ ENGINE = ReplacingMergeTree(ver, is_deleted) PARTITION BY ${monthOf(time)} ORDER BY (${order}) ${EXPIRE}`,
11
+ `CREATE OR REPLACE VIEW ${name} AS SELECT project_id, trace_id, ${names.join(", ")} FROM ${name}_t FINAL`,
12
+ ];
13
+ }
14
+ const REQUEST_COLS = [
15
+ "env LowCardinality(String), start_ms Float64, method LowCardinality(String), path String, endpoint String, status Nullable(Int32)",
16
+ "status_class LowCardinality(String), failed Bool, dur_class LowCardinality(String), aborted Bool, duration_ms Float64, server_ms Nullable(Float64)",
17
+ "db_ms Float64, db_count Int32, fetch_count Int32, fetch_ms Float64, render_ms Nullable(Float64), network_ms Nullable(Float64)",
18
+ "service LowCardinality(String), services String, errors Int32, insights Int32, health LowCardinality(String), user_agent Nullable(String)",
19
+ "client_address Nullable(String), end_user Nullable(String), request_id Nullable(String), tags String, search String",
20
+ ].join(", ");
21
+ const SEARCH_COLS = [
22
+ "kind LowCardinality(String), owner String, env LowCardinality(String), time_ms Float64, span_id Nullable(String), service String",
23
+ "name Nullable(String), method Nullable(String), path Nullable(String), route Nullable(String), status Nullable(Int32), outcome Nullable(String)",
24
+ "duration_ms Nullable(Float64), level_rank Nullable(Int16), category Nullable(String), span_kind Nullable(String), end_user Nullable(String)",
25
+ "error Bool, message Nullable(String), text String",
26
+ ].join(", ");
27
+ export const FACT_DDL = [
28
+ ...fact("fact_requests", REQUEST_COLS, "project_id, start_ms, trace_id", "start_ms"),
29
+ ...fact("fact_traces", "env LowCardinality(String), start_ms Float64, path String, duration_ms Float64, health Nullable(String), status String, services String, span_count Int32, slow Bool, search String", "project_id, start_ms, trace_id", "start_ms"),
30
+ ...fact("fact_logs", "idx Int32, env LowCardinality(String), time_ms Float64, level LowCardinality(String), level_rank Int16, service LowCardinality(String), category String, message String, trace_name String, span_id Nullable(String), attributes String, search String", "project_id, time_ms, trace_id, idx", "time_ms"),
31
+ ...fact("fact_critical", "span_id String, env LowCardinality(String), start_ms Float64, duration_ms Float64, name String, service LowCardinality(String), layer LowCardinality(String)", "project_id, start_ms, trace_id, span_id", "start_ms"),
32
+ ...fact("fact_search", SEARCH_COLS, "project_id, kind, time_ms, trace_id, owner", "time_ms", "INDEX ix_text text TYPE ngrambf_v1(3, 65536, 2, 0) GRANULARITY 1, INDEX ix_trace trace_id TYPE bloom_filter GRANULARITY 1"),
33
+ ...fact("fact_attrs", "src LowCardinality(String), owner String, key LowCardinality(String), value String, num Nullable(Float64), time_ms Float64", "project_id, key, value, trace_id, src, owner", "time_ms", "INDEX ix_trace trace_id TYPE bloom_filter GRANULARITY 1"),
34
+ ];
35
+ /** Changes to shipped fact tables, in order. The n-gram bloom filled up at 8,192 rows a block and skipped nothing; the text index lists each block's n-grams. */
36
+ export const FACT_ALTERS = [
37
+ "ALTER TABLE fact_search_t ADD INDEX IF NOT EXISTS ix_text_ngrams text TYPE text(tokenizer = ngrams(3)) GRANULARITY 1",
38
+ "ALTER TABLE fact_search_t DROP INDEX IF EXISTS ix_text",
39
+ ];
40
+ /** Fact tables (storage names) and the columns that identify a row within a trace, for tombstones. */
41
+ export const FACT_KEYS = {
42
+ fact_requests_t: ["start_ms"],
43
+ fact_traces_t: ["start_ms"],
44
+ fact_logs_t: ["time_ms", "idx"],
45
+ fact_critical_t: ["start_ms", "span_id"],
46
+ fact_search_t: ["kind", "time_ms", "owner"],
47
+ fact_attrs_t: ["key", "value", "src", "owner"],
48
+ };
49
+ //# sourceMappingURL=schema-facts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-facts.js","sourceRoot":"","sources":["../../../src/telemetry/ch/schema-facts.ts"],"names":[],"mappings":"AAAA,2IAA2I;AAC3I,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,CAAC,GAAG,oDAAoD,CAAC;AAC/D,MAAM,SAAS,GAAG,iDAAiD,CAAC;AAEpE,yHAAyH;AACzH,SAAS,IAAI,CAAC,IAAY,EAAE,IAAY,EAAE,KAAa,EAAE,IAAY,EAAE,OAAO,GAAG,EAAE;IACjF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC;IACvE,OAAO;QACL,8BAA8B,IAAI,OAAO,CAAC,KAAK,IAAI,KAAK,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE;iEACpC,OAAO,CAAC,IAAI,CAAC,cAAc,KAAK,KAAK,MAAM,EAAE;QAC1G,0BAA0B,IAAI,oCAAoC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,UAAU;KAC1G,CAAC;AACJ,CAAC;AAED,MAAM,YAAY,GAAG;IACnB,mIAAmI;IACnI,oJAAoJ;IACpJ,+HAA+H;IAC/H,2IAA2I;IAC3I,qHAAqH;CACtH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,WAAW,GAAG;IAClB,kIAAkI;IAClI,iJAAiJ;IACjJ,6IAA6I;IAC7I,mDAAmD;CACpD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,CAAC,MAAM,QAAQ,GAAsB;IACzC,GAAG,IAAI,CAAC,eAAe,EAAE,YAAY,EAAE,gCAAgC,EAAE,UAAU,CAAC;IACpF,GAAG,IAAI,CAAC,aAAa,EAAE,qLAAqL,EAAE,gCAAgC,EAAE,UAAU,CAAC;IAC3P,GAAG,IAAI,CAAC,WAAW,EAAE,wPAAwP,EAAE,oCAAoC,EAAE,SAAS,CAAC;IAC/T,GAAG,IAAI,CAAC,eAAe,EAAE,8JAA8J,EAAE,yCAAyC,EAAE,UAAU,CAAC;IAC/O,GAAG,IAAI,CAAC,aAAa,EAAE,WAAW,EAAE,4CAA4C,EAAE,SAAS,EACzF,2HAA2H,CAAC;IAC9H,GAAG,IAAI,CAAC,YAAY,EAAE,4HAA4H,EAAE,8CAA8C,EAAE,SAAS,EAC3M,yDAAyD,CAAC;CAC7D,CAAC;AAEF,iKAAiK;AACjK,MAAM,CAAC,MAAM,WAAW,GAAsB;IAC5C,sHAAsH;IACtH,wDAAwD;CACzD,CAAC;AAEF,sGAAsG;AACtG,MAAM,CAAC,MAAM,SAAS,GAAsC;IAC1D,eAAe,EAAE,CAAC,UAAU,CAAC;IAC7B,aAAa,EAAE,CAAC,UAAU,CAAC;IAC3B,WAAW,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC;IAC/B,eAAe,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC;IACxC,aAAa,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC;IAC3C,YAAY,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC;CAC/C,CAAC"}
@@ -0,0 +1,8 @@
1
+ /** Epoch ms in a column as a DateTime, for partitions and TTLs. */
2
+ export declare const secondsOf: (col: string) => string;
3
+ export declare const monthOf: (col: string) => string;
4
+ export declare const dayOf: (col: string) => string;
5
+ /** Rows go when their organization's retention runs out, set when they are written. */
6
+ export declare const EXPIRE: string;
7
+ export declare const RAW_TABLES: readonly string[];
8
+ //# sourceMappingURL=schema-raw.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-raw.d.ts","sourceRoot":"","sources":["../../../src/telemetry/ch/schema-raw.ts"],"names":[],"mappings":"AAEA,mEAAmE;AACnE,eAAO,MAAM,SAAS,QAAS,MAAM,KAAG,MAA2F,CAAC;AACpI,eAAO,MAAM,OAAO,QAAS,MAAM,KAAG,MAAuC,CAAC;AAC9E,eAAO,MAAM,KAAK,QAAS,MAAM,KAAG,MAAyC,CAAC;AAC9E,uFAAuF;AACvF,eAAO,MAAM,MAAM,QAAyC,CAAC;AAE7D,eAAO,MAAM,UAAU,EAAE,SAAS,MAAM,EA0BvC,CAAC"}
@@ -0,0 +1,35 @@
1
+ // ClickHouse tables for what add-ons send: spans, logs, trace bounds, metric points, and the settle state.
2
+ /** Epoch ms in a column as a DateTime, for partitions and TTLs. */
3
+ export const secondsOf = (col) => `toDateTime(intDiv(toUInt64(least(greatest(${col}, 0.), 4102444800000.)), 1000))`;
4
+ export const monthOf = (col) => `toYYYYMM(${secondsOf(col)})`;
5
+ export const dayOf = (col) => `toYYYYMMDD(${secondsOf(col)})`;
6
+ /** Rows go when their organization's retention runs out, set when they are written. */
7
+ export const EXPIRE = `TTL ${secondsOf("expire_ms")} DELETE`;
8
+ export const RAW_TABLES = [
9
+ `CREATE TABLE IF NOT EXISTS spans_raw (
10
+ project_id LowCardinality(String), trace_id String, span_id String, service LowCardinality(String), start_ms Float64, duration_ms Float64,
11
+ session Nullable(String), json String CODEC(ZSTD(3)), ver UInt64, expire_ms Float64,
12
+ INDEX ix_session session TYPE bloom_filter GRANULARITY 4
13
+ ) ENGINE = ReplacingMergeTree(ver) PARTITION BY ${monthOf("start_ms")} ORDER BY (project_id, trace_id, span_id) ${EXPIRE}`,
14
+ `CREATE TABLE IF NOT EXISTS logs_raw (
15
+ project_id LowCardinality(String), trace_id String, key String, time_ms Float64, json String CODEC(ZSTD(3)), ver UInt64, expire_ms Float64
16
+ ) ENGINE = ReplacingMergeTree(ver) PARTITION BY ${monthOf("time_ms")} ORDER BY (project_id, trace_id, key) ${EXPIRE}`,
17
+ `CREATE TABLE IF NOT EXISTS trace_heads (
18
+ project_id LowCardinality(String), trace_id String, start_ms SimpleAggregateFunction(min, Float64), end_ms SimpleAggregateFunction(max, Float64),
19
+ updated_ms SimpleAggregateFunction(max, Float64), env SimpleAggregateFunction(max, String), expire_ms SimpleAggregateFunction(max, Float64)
20
+ ) ENGINE = AggregatingMergeTree ORDER BY (project_id, trace_id) ${EXPIRE}`,
21
+ `CREATE TABLE IF NOT EXISTS trace_updates (
22
+ project_id LowCardinality(String), trace_id String, updated_ms Float64, env String
23
+ ) ENGINE = MergeTree ORDER BY updated_ms TTL ${secondsOf("updated_ms")} + INTERVAL 2 DAY DELETE`,
24
+ `CREATE TABLE IF NOT EXISTS settle_state (
25
+ project_id LowCardinality(String), trace_id String, settled_ms Float64, contrib String CODEC(ZSTD(3)), ver UInt64, expire_ms Float64
26
+ ) ENGINE = ReplacingMergeTree(ver) ORDER BY (project_id, trace_id) ${EXPIRE}`,
27
+ `CREATE TABLE IF NOT EXISTS metric_points_raw (
28
+ project_id LowCardinality(String), time_ms Float64, env LowCardinality(String), service LowCardinality(String), name LowCardinality(String),
29
+ series_key String, json String CODEC(ZSTD(3)), expire_ms Float64
30
+ ) ENGINE = MergeTree PARTITION BY ${monthOf("time_ms")} ORDER BY (project_id, name, time_ms) ${EXPIRE}`,
31
+ `CREATE TABLE IF NOT EXISTS project_retention (
32
+ project_id String, days UInt32, ver UInt64
33
+ ) ENGINE = ReplacingMergeTree(ver) ORDER BY project_id`,
34
+ ];
35
+ //# sourceMappingURL=schema-raw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-raw.js","sourceRoot":"","sources":["../../../src/telemetry/ch/schema-raw.ts"],"names":[],"mappings":"AAAA,2GAA2G;AAE3G,mEAAmE;AACnE,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAW,EAAU,EAAE,CAAC,6CAA6C,GAAG,iCAAiC,CAAC;AACpI,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,GAAW,EAAU,EAAE,CAAC,YAAY,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC;AAC9E,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,GAAW,EAAU,EAAE,CAAC,cAAc,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC;AAC9E,uFAAuF;AACvF,MAAM,CAAC,MAAM,MAAM,GAAG,OAAO,SAAS,CAAC,WAAW,CAAC,SAAS,CAAC;AAE7D,MAAM,CAAC,MAAM,UAAU,GAAsB;IAC3C;;;;oDAIkD,OAAO,CAAC,UAAU,CAAC,6CAA6C,MAAM,EAAE;IAC1H;;oDAEkD,OAAO,CAAC,SAAS,CAAC,yCAAyC,MAAM,EAAE;IACrH;;;oEAGkE,MAAM,EAAE;IAC1E;;iDAE+C,SAAS,CAAC,YAAY,CAAC,0BAA0B;IAChG;;uEAEqE,MAAM,EAAE;IAC7E;;;sCAGoC,OAAO,CAAC,SAAS,CAAC,yCAAyC,MAAM,EAAE;IACvG;;yDAEuD;CACxD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const ROLLUP_DDL: readonly string[];
2
+ //# sourceMappingURL=schema-rollups.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-rollups.d.ts","sourceRoot":"","sources":["../../../src/telemetry/ch/schema-rollups.ts"],"names":[],"mappings":"AAiEA,eAAO,MAAM,UAAU,EAAE,SAAS,MAAM,EAA8E,CAAC"}
@@ -0,0 +1,61 @@
1
+ // ClickHouse rollup, histogram, and metric tiers: rows add up when they merge, and views read them merged with the Postgres names.
2
+ import { IDS_MAX, TIERS } from "@wizeworks/lens-core";
3
+ import { dayOf, EXPIRE, monthOf, secondsOf } from "./schema-raw.js";
4
+ const sum = (c) => `${c} SimpleAggregateFunction(sum, Float64)`;
5
+ const COUNTERS = ["c0", "c1", "c2", "c3", "c4", "c5"];
6
+ /** Short tiers age out by bucket; the 1 h tier by retention. Day partitions for short tiers, month for 1 h. */
7
+ function tierTail(tier) {
8
+ const ttl = tier.keepMs === null ? EXPIRE : `TTL ${secondsOf("bucket_ms")} + INTERVAL ${Math.ceil(tier.keepMs / 1000)} SECOND DELETE`;
9
+ return `PARTITION BY ${tier.keepMs === null ? monthOf("bucket_ms") : dayOf("bucket_ms")} ${ttl}`;
10
+ }
11
+ function rollupDdl(tier) {
12
+ const t = tier.table;
13
+ const cols = [
14
+ "project_id LowCardinality(String), env LowCardinality(String), kind LowCardinality(String), key String, bucket_ms Float64",
15
+ ...["n", "err", "sum_v", ...COUNTERS].map(sum),
16
+ "first_ms SimpleAggregateFunction(min, Float64), last_ms SimpleAggregateFunction(max, Float64), top_rank SimpleAggregateFunction(max, Float64)",
17
+ `top AggregateFunction(argMax, Nullable(String), Float64), ids AggregateFunction(groupArraySorted(${IDS_MAX}), Tuple(Float64, String))`,
18
+ "expire_ms SimpleAggregateFunction(max, Float64)",
19
+ ].join(", ");
20
+ const read = ["project_id", "env", "kind", "key", "bucket_ms", "n", "err", "sum_v", ...COUNTERS, "first_ms", "last_ms", "top_rank"].join(", ");
21
+ const finals = "finalizeAggregation(top) AS top, arrayStringConcat(arrayMap(x -> x.2, finalizeAggregation(ids)), ' ') AS ids";
22
+ return [
23
+ `CREATE TABLE IF NOT EXISTS ${t}_t (${cols}) ENGINE = AggregatingMergeTree ORDER BY (project_id, kind, bucket_ms, env, key) ${tierTail(tier)}`,
24
+ `CREATE OR REPLACE VIEW ${t} AS SELECT ${read}, ${finals} FROM ${t}_t FINAL`,
25
+ `CREATE TABLE IF NOT EXISTS ${tier.hist}_t (
26
+ project_id LowCardinality(String), env LowCardinality(String), kind LowCardinality(String), key String, bucket_ms Float64, bin Int32,
27
+ cnt SimpleAggregateFunction(sum, Float64), expire_ms SimpleAggregateFunction(max, Float64)
28
+ ) ENGINE = AggregatingMergeTree ORDER BY (project_id, kind, bucket_ms, env, key, bin) ${tierTail(tier)}`,
29
+ `CREATE OR REPLACE VIEW ${tier.hist} AS SELECT project_id, env, kind, key, bucket_ms, bin, cnt FROM ${tier.hist}_t FINAL`,
30
+ ];
31
+ }
32
+ function metricDdl(tier) {
33
+ const t = `metric_${tier.name}`;
34
+ const nmin = (c) => `${c} SimpleAggregateFunction(min, Nullable(Float64))`;
35
+ const nmax = (c) => `${c} SimpleAggregateFunction(max, Nullable(Float64))`;
36
+ const cols = [
37
+ "project_id LowCardinality(String), env LowCardinality(String), series_key String, name LowCardinality(String), bucket_ms Float64",
38
+ sum("cnt"), sum("vsum"), nmin("vmin"), nmax("vmax"), "first_ms SimpleAggregateFunction(min, Float64)",
39
+ "first_v AggregateFunction(argMin, Nullable(Float64), Float64)", "last_ms SimpleAggregateFunction(max, Float64)",
40
+ "last_v AggregateFunction(argMax, Nullable(Float64), Float64)", sum("rate_delta"), sum("rate_ms"), sum("h_count"), sum("h_sum"), nmin("h_min"), nmax("h_max"),
41
+ "h_bounds AggregateFunction(argMax, Nullable(String), UInt64), h_counts AggregateFunction(argMax, Nullable(String), UInt64)",
42
+ "expire_ms SimpleAggregateFunction(max, Float64)",
43
+ ].join(", ");
44
+ const read = "project_id, env, series_key, name, bucket_ms, cnt, vsum, vmin, vmax, first_ms, last_ms, rate_delta, rate_ms, h_count, h_sum, h_min, h_max";
45
+ const finals = ["first_v", "last_v", "h_bounds", "h_counts"].map((c) => `finalizeAggregation(${c}) AS ${c}`).join(", ");
46
+ return [
47
+ `CREATE TABLE IF NOT EXISTS ${t}_t (${cols}) ENGINE = AggregatingMergeTree ORDER BY (project_id, name, bucket_ms, env, series_key) ${tierTail(tier)}`,
48
+ `CREATE OR REPLACE VIEW ${t} AS SELECT ${read}, ${finals} FROM ${t}_t FINAL`,
49
+ ];
50
+ }
51
+ const SERIES_DDL = [
52
+ `CREATE TABLE IF NOT EXISTS metric_series_t (
53
+ project_id LowCardinality(String), env LowCardinality(String), series_key String, name LowCardinality(String), service LowCardinality(String),
54
+ kind LowCardinality(String), unit String, description String, monotonic Bool, temporality String, attributes String, last_ms Float64,
55
+ last_value Nullable(Float64), last_hist Nullable(String), ver UInt64, expire_ms Float64
56
+ ) ENGINE = ReplacingMergeTree(ver) ORDER BY (project_id, env, series_key) ${EXPIRE}`,
57
+ `CREATE OR REPLACE VIEW metric_series AS SELECT project_id, env, series_key, name, service, kind, unit, description, monotonic, temporality,
58
+ attributes, last_ms, last_value, last_hist FROM metric_series_t FINAL`,
59
+ ];
60
+ export const ROLLUP_DDL = [...TIERS.flatMap(rollupDdl), ...TIERS.flatMap(metricDdl), ...SERIES_DDL];
61
+ //# sourceMappingURL=schema-rollups.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-rollups.js","sourceRoot":"","sources":["../../../src/telemetry/ch/schema-rollups.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { type ChClient } from "./http.js";
2
+ /** Every statement, in order. A change to a shipped table needs an ALTER added here, never an edit to its CREATE. */
3
+ export declare const CH_SCHEMA: readonly string[];
4
+ /** Tables whose rows belong to one project, for clearing it. Views are left out. */
5
+ export declare const PROJECT_TABLES: readonly string[];
6
+ /** Every statement without its TTL clauses: for tests on a fixed clock, whose rows would expire on insert. */
7
+ export declare const withoutTtl: (sql: string) => string;
8
+ /** Create the database (through the default one) and every table and view. `ttl: false` keeps every row (tests only). */
9
+ export declare function migrateClickHouse(url: string, client: ChClient, o?: {
10
+ ttl?: boolean;
11
+ }): Promise<void>;
12
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/telemetry/ch/schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,QAAQ,EAAY,MAAM,WAAW,CAAC;AAapD,qHAAqH;AACrH,eAAO,MAAM,SAAS,EAAE,SAAS,MAAM,EAAmG,CAAC;AAE3I,oFAAoF;AACpF,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EAAgD,CAAC;AAE7F,8GAA8G;AAC9G,eAAO,MAAM,UAAU,QAAS,MAAM,KAAG,MAAmD,CAAC;AAE7F,yHAAyH;AACzH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAK/G"}
@@ -0,0 +1,25 @@
1
+ // ClickHouse schema setup: the database, then every table and view. Statements are idempotent, so each start runs them all.
2
+ import { chClient } from "./http.js";
3
+ import { FACT_ALTERS, FACT_DDL } from "./schema-facts.js";
4
+ import { RAW_TABLES } from "./schema-raw.js";
5
+ import { ROLLUP_DDL } from "./schema-rollups.js";
6
+ const TABLES = [...RAW_TABLES, ...FACT_DDL, ...ROLLUP_DDL].map((s) => /^CREATE TABLE IF NOT EXISTS (\w+)/.exec(s)?.[1]).filter((t) => !!t);
7
+ /** New parts write no column statistics (see http.ts); old parts lose theirs as they merge. */
8
+ const NO_STATISTICS = TABLES.map((t) => `ALTER TABLE ${t} MODIFY SETTING auto_statistics_types = ''`);
9
+ /** Tables only settling writes, always with a token: a retried insert lands once (see settle-rows.ts, Label). */
10
+ const DEDUPLICATED = TABLES.filter((t) => /^(fact_|rollup_|hist_)|^settle_state$/.test(t)).map((t) => `ALTER TABLE ${t} MODIFY SETTING non_replicated_deduplication_window = 1000`);
11
+ /** Every statement, in order. A change to a shipped table needs an ALTER added here, never an edit to its CREATE. */
12
+ export const CH_SCHEMA = [...RAW_TABLES, ...FACT_DDL, ...FACT_ALTERS, ...ROLLUP_DDL, ...NO_STATISTICS, ...DEDUPLICATED];
13
+ /** Tables whose rows belong to one project, for clearing it. Views are left out. */
14
+ export const PROJECT_TABLES = TABLES.filter((t) => t !== "trace_updates");
15
+ /** Every statement without its TTL clauses: for tests on a fixed clock, whose rows would expire on insert. */
16
+ export const withoutTtl = (sql) => sql.replace(/\sTTL\s[\s\S]*?DELETE/g, "");
17
+ /** Create the database (through the default one) and every table and view. `ttl: false` keeps every row (tests only). */
18
+ export async function migrateClickHouse(url, client, o = {}) {
19
+ const u = new URL(url);
20
+ u.pathname = "/default";
21
+ await chClient({ url: u.toString() }).command(`CREATE DATABASE IF NOT EXISTS \`${client.database.replace(/`/g, "")}\``);
22
+ for (const sql of CH_SCHEMA)
23
+ await client.command(o.ttl === false ? withoutTtl(sql) : sql);
24
+ }
25
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/telemetry/ch/schema.ts"],"names":[],"mappings":"AAAA,4HAA4H;AAC5H,OAAO,EAAiB,QAAQ,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,MAAM,MAAM,GAAG,CAAC,GAAG,UAAU,EAAE,GAAG,QAAQ,EAAE,GAAG,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,mCAAmC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAExJ,+FAA+F;AAC/F,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,4CAA4C,CAAC,CAAC;AAEtG,iHAAiH;AACjH,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,uCAAuC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,4DAA4D,CAAC,CAAC;AAEpL,qHAAqH;AACrH,MAAM,CAAC,MAAM,SAAS,GAAsB,CAAC,GAAG,UAAU,EAAE,GAAG,QAAQ,EAAE,GAAG,WAAW,EAAE,GAAG,UAAU,EAAE,GAAG,aAAa,EAAE,GAAG,YAAY,CAAC,CAAC;AAE3I,oFAAoF;AACpF,MAAM,CAAC,MAAM,cAAc,GAAsB,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,eAAe,CAAC,CAAC;AAE7F,8GAA8G;AAC9G,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAW,EAAU,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,wBAAwB,EAAE,EAAE,CAAC,CAAC;AAE7F,yHAAyH;AACzH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,GAAW,EAAE,MAAgB,EAAE,CAAC,GAAsB,EAAE;IAC9F,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC,CAAC,QAAQ,GAAG,UAAU,CAAC;IACxB,MAAM,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,mCAAmC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;IACxH,KAAK,MAAM,GAAG,IAAI,SAAS;QAAE,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AAC7F,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { type FactTable, type SettleDelta } from "@wizeworks/lens-core";
2
+ import type { ChClient } from "./http.js";
3
+ type Row = Record<string, unknown>;
4
+ /** Fact rows as objects, with their version and expiry. `expire` maps a trace id to its row expiry base. */
5
+ export declare function factObjects(rows: Record<FactTable, unknown[][]>, ver: number, expireOf: (r: Row) => number): Record<FactTable, Row[]>;
6
+ /** Rows the re-settled traces had before and no longer have, as tombstones. Only traces settled before can have any. */
7
+ export declare function tombstones(ch: ChClient, project: string, traceIds: readonly string[], fresh: Record<FactTable, Row[]>, ver: number): Promise<Record<FactTable, Row[]>>;
8
+ /** Settings that make one batch's insert into a table safe to send again: ClickHouse keeps the first copy of a token. */
9
+ export type Label = (table: string) => Record<string, string>;
10
+ /** Write a merged settle delta into every tier. `retentionMs` is per project. */
11
+ export declare function writeDeltas(ch: ChClient, delta: SettleDelta, retentionMs: (project: string) => number, label: Label): Promise<void>;
12
+ export {};
13
+ //# sourceMappingURL=settle-rows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settle-rows.d.ts","sourceRoot":"","sources":["../../../src/telemetry/ch/settle-rows.ts"],"names":[],"mappings":"AACA,OAAO,EAA6B,KAAK,SAAS,EAAgC,KAAK,WAAW,EAAS,MAAM,sBAAsB,CAAC;AAExI,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAG1C,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAMnC,4GAA4G;AAC5G,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,CAUrI;AAED,wHAAwH;AACxH,wBAAsB,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,CAa5K;AAoBD,yHAAyH;AACzH,MAAM,MAAM,KAAK,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE9D,iFAAiF;AACjF,wBAAsB,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAczI"}
@@ -0,0 +1,67 @@
1
+ // What one settle batch writes to ClickHouse: fact rows, tombstones for rows a trace no longer has, and rollup deltas.
2
+ import { FACT_COLUMNS, FACT_TABLES, IDS_MAX, NONE_HIGH, NONE_LOW, TIERS } from "@wizeworks/lens-core";
3
+ import { FACT_KEYS } from "./schema-facts.js";
4
+ import { rowOf } from "./util.js";
5
+ const COUNTERS = ["c0", "c1", "c2", "c3", "c4", "c5"];
6
+ const keyCols = (t) => FACT_KEYS[`${t}_t`];
7
+ const keyOf = (t, r) => [r.trace_id, ...keyCols(t).map((c) => r[c])].map((v) => JSON.stringify(v ?? null)).join("|");
8
+ /** Fact rows as objects, with their version and expiry. `expire` maps a trace id to its row expiry base. */
9
+ export function factObjects(rows, ver, expireOf) {
10
+ const out = {};
11
+ for (const t of FACT_TABLES) {
12
+ const cols = ["project_id", ...FACT_COLUMNS[t]];
13
+ out[t] = rows[t].map((values) => {
14
+ const r = rowOf(cols, values);
15
+ return { ...r, ver, is_deleted: 0, expire_ms: expireOf(r) };
16
+ });
17
+ }
18
+ return out;
19
+ }
20
+ /** Rows the re-settled traces had before and no longer have, as tombstones. Only traces settled before can have any. */
21
+ export async function tombstones(ch, project, traceIds, fresh, ver) {
22
+ const out = {};
23
+ for (const t of FACT_TABLES) {
24
+ out[t] = [];
25
+ if (!traceIds.length)
26
+ continue;
27
+ const cols = ["trace_id", ...keyCols(t)];
28
+ const sql = `SELECT ${cols.join(", ")} FROM ${t}_t FINAL WHERE project_id = {p1:String} AND has({p2:Array(String)}, trace_id)`;
29
+ const keep = new Set(fresh[t].map((r) => keyOf(t, r)));
30
+ for (const old of await ch.query(sql, [project, traceIds])) {
31
+ if (!keep.has(keyOf(t, old)))
32
+ out[t].push({ project_id: project, ...old, ver, is_deleted: 1, expire_ms: NONE_HIGH });
33
+ }
34
+ }
35
+ return out;
36
+ }
37
+ const ROLLUP_INPUT = [
38
+ "project_id String, env String, kind String, key String, bucket_ms Float64, n Float64, err Float64, sum_v Float64",
39
+ ...COUNTERS.map((c) => `${c} Float64`),
40
+ "first_ms Float64, last_ms Float64, top_rank Float64, top Nullable(String), ids String, expire_ms Float64",
41
+ ].join(", ");
42
+ /** Deltas add into the merge tables; a batch's deltas for one bucket and key become one row. */
43
+ function rollupInsert(table) {
44
+ const sums = ["n", "err", "sum_v", ...COUNTERS].map((c) => `sum(${c})`).join(", ");
45
+ const ids = `groupArraySortedArrayState(${IDS_MAX})(arrayMap(x -> (-last_ms, x), arrayFilter(x -> x != '', splitByChar(' ', ids))))`;
46
+ return `${table}_t SELECT project_id, env, kind, key, bucket_ms, ${sums}, min(first_ms), max(last_ms), max(top_rank), argMaxState(top, top_rank), ${ids}, max(expire_ms)
47
+ FROM input('${ROLLUP_INPUT}') GROUP BY project_id, env, kind, key, bucket_ms`;
48
+ }
49
+ const HIST_INPUT = "project_id String, env String, kind String, key String, bucket_ms Float64, bin Int32, cnt Float64, expire_ms Float64";
50
+ const histInsert = (table) => `${table}_t SELECT project_id, env, kind, key, bucket_ms, bin, sum(cnt), max(expire_ms) FROM input('${HIST_INPUT}') GROUP BY project_id, env, kind, key, bucket_ms, bin`;
51
+ /** Write a merged settle delta into every tier. `retentionMs` is per project. */
52
+ export async function writeDeltas(ch, delta, retentionMs, label) {
53
+ const writes = [];
54
+ for (const tier of TIERS) {
55
+ const rollups = delta.rollup.filter((r) => r.tier === tier.name).map((r) => ({
56
+ project_id: r.project, env: r.env, kind: r.kind, key: r.key, bucket_ms: r.bucket, n: r.n, err: r.err, sum_v: r.sum,
57
+ ...Object.fromEntries(COUNTERS.map((c, i) => [c, r.c[i] ?? 0])), first_ms: r.firstMs ?? NONE_HIGH, last_ms: r.lastMs ?? NONE_LOW,
58
+ top_rank: r.topRank ?? NONE_LOW, top: r.topRank === null ? null : JSON.stringify(r.top ?? null), ids: r.ids, expire_ms: r.bucket + retentionMs(r.project),
59
+ }));
60
+ const hists = delta.hist.filter((h) => h.tier === tier.name).map((h) => ({
61
+ project_id: h.project, env: h.env, kind: h.kind, key: h.key, bucket_ms: h.bucket, bin: h.bin, cnt: h.cnt, expire_ms: h.bucket + retentionMs(h.project),
62
+ }));
63
+ writes.push(ch.insert(rollupInsert(tier.table), rollups, label(tier.table)), ch.insert(histInsert(tier.hist), hists, label(tier.hist)));
64
+ }
65
+ await Promise.all(writes);
66
+ }
67
+ //# sourceMappingURL=settle-rows.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settle-rows.js","sourceRoot":"","sources":["../../../src/telemetry/ch/settle-rows.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { SettleOptions } from "../store.js";
2
+ import type { ChClient } from "./http.js";
3
+ import type { SettleQueue } from "./queue.js";
4
+ import { type RetentionCache } from "./util.js";
5
+ /** Settle due traces until none are left or the budget is spent. Batches overlap (`DEPTH` at once): one reads and computes while others wait on their writes. */
6
+ export declare function settleClickHouse(ch: ChClient, queue: SettleQueue, retention: RetentionCache, now: number, o?: SettleOptions): Promise<number>;
7
+ //# sourceMappingURL=settle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settle.d.ts","sourceRoot":"","sources":["../../../src/telemetry/ch/settle.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAS,WAAW,EAAE,MAAM,YAAY,CAAC;AAGrD,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AA6EpE,iKAAiK;AACjK,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,GAAE,aAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBvJ"}
@@ -0,0 +1,96 @@
1
+ // Settling on ClickHouse: the same facts and deltas as Postgres, written as inserts. One process settles, so no lock is needed.
2
+ import { compact, factRows, FACT_TABLES, mergeDeltas, settleDelta, storedOf, traceFacts, withoutTop } from "@wizeworks/lens-core";
3
+ import { loadTraces } from "./read.js";
4
+ import { factObjects, tombstones, writeDeltas } from "./settle-rows.js";
5
+ import { byProject, nextVer } from "./util.js";
6
+ const BATCH = 2_000;
7
+ const BUDGET_MS = 2_000;
8
+ const DEPTH = 3;
9
+ const hasData = (t) => !!t && t.spanCount + t.logs.length > 0;
10
+ /** Stored contributions of some traces, by trace id. */
11
+ async function storedContribs(ch, project, ids) {
12
+ const rows = await ch.query("SELECT trace_id, contrib FROM settle_state FINAL WHERE project_id = {p1:String} AND has({p2:Array(String)}, trace_id)", [project, ids]);
13
+ return new Map(rows.map((r) => [r.trace_id, r.contrib]));
14
+ }
15
+ /** Facts, deltas, and new settle states for one project's dirty traces. */
16
+ async function projectWork(ch, project, items, now, retentionMs, ver) {
17
+ const ids = items.map((d) => d.traceId);
18
+ const [traces, stored] = await Promise.all([loadTraces(ch, [project], ids), storedContribs(ch, project, ids)]);
19
+ const raw = Object.fromEntries(FACT_TABLES.map((t) => [t, []]));
20
+ const work = { facts: {}, deltas: [], states: [], resettled: [] };
21
+ items.forEach((d, i) => {
22
+ const trace = traces[i];
23
+ const scope = { project, env: d.env };
24
+ const facts = hasData(trace) ? traceFacts(trace) : null;
25
+ const next = facts ? compact(facts, scope) : null;
26
+ const old = stored.get(d.traceId);
27
+ if (old !== undefined)
28
+ work.resettled.push(d.traceId);
29
+ work.deltas.push(settleDelta(storedOf(old || null), next, now, retentionMs));
30
+ if (facts)
31
+ for (const [t, rows] of Object.entries(factRows(facts, scope, trace)))
32
+ raw[t].push(...rows);
33
+ const start = trace?.startMs ?? now;
34
+ work.states.push({ project_id: project, trace_id: d.traceId, settled_ms: d.updatedMs, contrib: next ? JSON.stringify(withoutTop(next)) : "", ver, expire_ms: start + retentionMs });
35
+ });
36
+ const timeOf = (r) => Number(r.start_ms ?? r.time_ms ?? now);
37
+ work.facts = factObjects(raw, ver, (r) => timeOf(r) + retentionMs);
38
+ return work;
39
+ }
40
+ /** Write one project's work: facts (with tombstones) and rollups at once, then the settle states, so a failed write settles again. */
41
+ async function writeWork(ch, project, w, ver, retentionMs, label) {
42
+ const dead = await tombstones(ch, project, w.resettled, w.facts, ver);
43
+ const facts = FACT_TABLES.map((t) => ch.insert(`${t}_t`, [...dead[t], ...w.facts[t]], label(t)));
44
+ await Promise.all([...facts, writeDeltas(ch, mergeDeltas(w.deltas), () => retentionMs, label)]);
45
+ await ch.insert("settle_state", w.states, label("settle_state"));
46
+ }
47
+ /** Settle one batch of taken traces. A failure releases the ones not written yet. */
48
+ async function settleItems(ch, queue, retention, now, due, o) {
49
+ let left = [...due];
50
+ try {
51
+ const days = await retention.daysOf(due.map((d) => d.project));
52
+ for (const [project, items] of byProject(due)) {
53
+ const retentionMs = days.get(project) * 86_400_000;
54
+ const ver = nextVer(now);
55
+ const label = (table) => ({ insert_deduplication_token: `${ver}:${project}:${table}` });
56
+ await writeWork(ch, project, await projectWork(ch, project, items, now, retentionMs, ver), ver, retentionMs, label);
57
+ for (const d of items)
58
+ queue.settled(d, d.updatedMs);
59
+ left = left.filter((d) => d.project !== project);
60
+ o.onSettled?.(project);
61
+ }
62
+ return due.length;
63
+ }
64
+ finally {
65
+ queue.release(left);
66
+ }
67
+ }
68
+ /** Settle due traces until none are left or the budget is spent. Batches overlap (`DEPTH` at once): one reads and computes while others wait on their writes. */
69
+ export async function settleClickHouse(ch, queue, retention, now, o = {}) {
70
+ const start = Date.now();
71
+ const batch = o.batch ?? BATCH;
72
+ const running = [];
73
+ const started = [];
74
+ let total = 0;
75
+ try {
76
+ for (;;) {
77
+ const due = queue.take(now, batch);
78
+ if (due.length) {
79
+ const run = settleItems(ch, queue, retention, now, due, o);
80
+ // Handled now, awaited in turn: a batch that fails while another is awaited must not end the process.
81
+ run.catch(() => undefined);
82
+ running.push(run);
83
+ started.push(run);
84
+ }
85
+ const last = !due.length || due.length < batch || Date.now() - start >= (o.budgetMs ?? BUDGET_MS);
86
+ while (running.length && (last || running.length >= DEPTH))
87
+ total += await running.shift();
88
+ if (last)
89
+ return total;
90
+ }
91
+ }
92
+ finally {
93
+ await Promise.allSettled(started);
94
+ }
95
+ }
96
+ //# sourceMappingURL=settle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settle.js","sourceRoot":"","sources":["../../../src/telemetry/ch/settle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type SqlRunner } from "@wizeworks/lens-core";
2
+ import type { RetentionOf, TelemetryStore } from "../store.js";
3
+ import { type ChClient } from "./http.js";
4
+ export interface ChStoreOptions {
5
+ url: string;
6
+ retentionOf: RetentionOf;
7
+ defaultRetentionDays: number;
8
+ /** The clock for recovery on start. */
9
+ now: () => number;
10
+ /** False leaves the TTLs out (tests on a fixed clock). Default true. */
11
+ ttl?: boolean;
12
+ }
13
+ export declare const chRunner: (ch: ChClient) => SqlRunner;
14
+ /** Create the schema, rebuild the settle queue, and return the store. */
15
+ export declare function openClickHouse(o: ChStoreOptions): Promise<TelemetryStore>;
16
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/telemetry/ch/store.ts"],"names":[],"mappings":"AACA,OAAO,EAAoH,KAAK,SAAS,EAAc,MAAM,sBAAsB,CAAC;AACpL,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE/D,OAAO,EAAE,KAAK,QAAQ,EAAY,MAAM,WAAW,CAAC;AAUpD,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,WAAW,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,uCAAuC;IACvC,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,wEAAwE;IACxE,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,eAAO,MAAM,QAAQ,OAAQ,QAAQ,KAAG,SAAuF,CAAC;AAWhI,yEAAyE;AACzE,wBAAsB,cAAc,CAAC,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAO/E"}
@@ -0,0 +1,65 @@
1
+ // Scale mode: telemetry in ClickHouse. Reads go through views with the Postgres names, so the shared SQL answers pages and searches.
2
+ import { alignNow, CH_DIALECT, metricAlertSteps, metricPageSteps, runMetricAsync, searchSql, sqlExecutor, suggestSql } from "@wizeworks/lens-core";
3
+ import { checkFactsVersionCh, clearProjectCh, syncProjects } from "./admin.js";
4
+ import { chClient } from "./http.js";
5
+ import { MetricWriter } from "./metrics.js";
6
+ import { activeHours, counts, lastTraceMs, slowestEndpoints, traceEnvs } from "./queries.js";
7
+ import { SettleQueue } from "./queue.js";
8
+ import { findTraceIds, getTrace, joinedTrace, loadTraces } from "./read.js";
9
+ import { migrateClickHouse } from "./schema.js";
10
+ import { settleClickHouse } from "./settle.js";
11
+ import { RetentionCache } from "./util.js";
12
+ import { writeRaw } from "./write.js";
13
+ export const chRunner = (ch) => ({ all: (sql, params) => ch.query(sql, params) });
14
+ /** ClickHouse may still be starting (a deploy starts both at once): wait up to two minutes. */
15
+ async function waitReady(ch) {
16
+ for (let i = 0; i < 60; i++) {
17
+ if (await ch.ping())
18
+ return;
19
+ await new Promise((r) => setTimeout(r, 2_000));
20
+ }
21
+ throw new Error("ClickHouse did not answer /ping for two minutes. Check --clickhouse and that the server runs.");
22
+ }
23
+ /** Create the schema, rebuild the settle queue, and return the store. */
24
+ export async function openClickHouse(o) {
25
+ const ch = chClient({ url: o.url });
26
+ await waitReady(ch);
27
+ await migrateClickHouse(o.url, ch, { ttl: o.ttl });
28
+ const queue = new SettleQueue();
29
+ await queue.recover(ch, o.now());
30
+ return chTelemetry(ch, queue, new RetentionCache(o.retentionOf, o.defaultRetentionDays), o.retentionOf);
31
+ }
32
+ function chTelemetry(ch, queue, retention, retentionOf) {
33
+ const src = (projectId) => ({ d: CH_DIALECT, run: chRunner(ch), scope: { project: projectId } });
34
+ const metrics = new MetricWriter(ch);
35
+ const runMetric = (s) => ch.query(s.sql, s.args);
36
+ return {
37
+ kind: "clickhouse",
38
+ async write(projectId, w, now) {
39
+ const retentionMs = await retention.msOf(projectId);
40
+ await writeRaw(ch, queue, projectId, w, now, retentionMs);
41
+ await metrics.write(projectId, w.sender.environment ?? "", w.metrics ?? [], now, retentionMs);
42
+ },
43
+ traces: async (t) => loadTraces(ch, [t.projectId], await findTraceIds(ch, t, Date.now())),
44
+ trace: (projectId, traceId) => getTrace(ch, [projectId], traceId),
45
+ joinedTrace: (primaryId, scope, traceId) => joinedTrace(ch, primaryId, scope, traceId),
46
+ counts: (projectId) => counts(ch, projectId),
47
+ traceEnvs: (projectId) => traceEnvs(ch, projectId),
48
+ activeHours: (projectId, from, to) => activeHours(ch, projectId, from, to),
49
+ lastTraceMs: () => lastTraceMs(ch, Date.now()),
50
+ executor: (projectId, retentionMs, env) => sqlExecutor({ ...src(projectId), scope: { project: projectId, env }, retentionMs, loadTrace: (id) => getTrace(ch, [projectId], id).then((t) => t ?? null) }),
51
+ settling: async (projectId, env) => queue.count(projectId, env) || null,
52
+ search: (projectId, q) => searchSql(src(projectId), q),
53
+ suggest: (projectId, r) => suggestSql(src(projectId), r),
54
+ slowestEndpoints: (projectId, w, minCount, limit) => slowestEndpoints(ch, projectId, w, minCount, limit),
55
+ metricData: (m, range, params, now) => runMetricAsync(metricPageSteps("ch", { project: m.projectId, env: m.env }, range, alignNow(now), params), runMetric),
56
+ metricAlertData: (m, name, w, now) => runMetricAsync(metricAlertSteps("ch", { project: m.projectId, env: m.env, service: m.service }, name, w, now), runMetric),
57
+ settle: (now, o) => settleClickHouse(ch, queue, retention, now, o),
58
+ prune: (now) => syncProjects(ch, queue, retentionOf, now),
59
+ pruneRollups: async () => undefined,
60
+ checkFactsVersion: () => checkFactsVersionCh(ch, queue),
61
+ clearProject: (projectId) => clearProjectCh(ch, queue, projectId),
62
+ close: async () => undefined,
63
+ };
64
+ }
65
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/telemetry/ch/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { RetentionOf } from "../store.js";
2
+ declare const DAY_MS = 86400000;
3
+ /** A row version that only grows: ms times 1000, plus a counter within the same ms. */
4
+ export declare function nextVer(now: number): number;
5
+ /** Retention days per project, from Postgres, cached for a minute. */
6
+ export declare class RetentionCache {
7
+ private readonly lookup;
8
+ private readonly defaultDays;
9
+ private readonly cache;
10
+ constructor(lookup: RetentionOf, defaultDays: number);
11
+ daysOf(projectIds: readonly string[]): Promise<Map<string, number>>;
12
+ msOf(projectId: string): Promise<number>;
13
+ }
14
+ /** A row object from a column list and values in the same order. */
15
+ export declare function rowOf(cols: readonly string[], values: readonly unknown[]): Record<string, unknown>;
16
+ export declare const byProject: <T extends {
17
+ project: string;
18
+ }>(items: readonly T[]) => Map<string, T[]>;
19
+ export { DAY_MS };
20
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../src/telemetry/ch/util.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,QAAA,MAAM,MAAM,WAAa,CAAC;AAK1B,uFAAuF;AACvF,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG3C;AAED,sEAAsE;AACtE,qBAAa,cAAc;IAIvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAJ9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqD;IAE3E,YACmB,MAAM,EAAE,WAAW,EACnB,WAAW,EAAE,MAAM,EAClC;IAEE,MAAM,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAQxE;IAEK,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE7C;CACF;AAED,oEAAoE;AACpE,wBAAgB,KAAK,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,MAAM,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAIlG;AAED,eAAO,MAAM,SAAS,GAAI,CAAC,SAAS;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,SAAS,SAAS,CAAC,EAAE,KAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,CAI7F,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,CAAC"}