@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.
- package/README.md +1 -0
- package/dist/alerts/evaluate.d.ts.map +1 -1
- package/dist/alerts/evaluate.js +3 -4
- package/dist/alerts/evaluate.js.map +1 -1
- package/dist/app.d.ts +6 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/auth/join-scope.d.ts +7 -0
- package/dist/auth/join-scope.d.ts.map +1 -0
- package/dist/auth/join-scope.js +17 -0
- package/dist/auth/join-scope.js.map +1 -0
- package/dist/changes.d.ts +15 -0
- package/dist/changes.d.ts.map +1 -0
- package/dist/changes.js +45 -0
- package/dist/changes.js.map +1 -0
- package/dist/cli-args.d.ts +1 -1
- package/dist/cli-args.d.ts.map +1 -1
- package/dist/cli-args.js +11 -0
- package/dist/cli-args.js.map +1 -1
- package/dist/cli.js +4 -0
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +5 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -0
- package/dist/config.js.map +1 -1
- package/dist/copy-cli.d.ts +3 -0
- package/dist/copy-cli.d.ts.map +1 -0
- package/dist/copy-cli.js +24 -0
- package/dist/copy-cli.js.map +1 -0
- package/dist/db/db.d.ts +2 -0
- package/dist/db/db.d.ts.map +1 -1
- package/dist/db/db.js +15 -4
- package/dist/db/db.js.map +1 -1
- package/dist/db/schema-search.d.ts +2 -0
- package/dist/db/schema-search.d.ts.map +1 -0
- package/dist/db/schema-search.js +16 -0
- package/dist/db/schema-search.js.map +1 -0
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +2 -0
- package/dist/db/schema.js.map +1 -1
- package/dist/db/trigram.d.ts +4 -0
- package/dist/db/trigram.d.ts.map +1 -0
- package/dist/db/trigram.js +34 -0
- package/dist/db/trigram.js.map +1 -0
- package/dist/jobs.d.ts +1 -1
- package/dist/jobs.d.ts.map +1 -1
- package/dist/jobs.js +10 -9
- package/dist/jobs.js.map +1 -1
- package/dist/mail/blocks.d.ts +1 -1
- package/dist/mail/blocks.js +2 -2
- package/dist/mail/blocks.js.map +1 -1
- package/dist/mail/layout.d.ts +1 -1
- package/dist/mail/layout.d.ts.map +1 -1
- package/dist/mail/layout.js +2 -2
- package/dist/mail/layout.js.map +1 -1
- package/dist/mail/mailer.d.ts.map +1 -1
- package/dist/mail/mailer.js +4 -3
- package/dist/mail/mailer.js.map +1 -1
- package/dist/mail/resend.d.ts +2 -0
- package/dist/mail/resend.d.ts.map +1 -1
- package/dist/mail/resend.js +1 -1
- package/dist/mail/resend.js.map +1 -1
- package/dist/mail/theme.d.ts +7 -1
- package/dist/mail/theme.d.ts.map +1 -1
- package/dist/mail/theme.js +7 -1
- package/dist/mail/theme.js.map +1 -1
- package/dist/notify/digest-data.d.ts +2 -1
- package/dist/notify/digest-data.d.ts.map +1 -1
- package/dist/notify/digest-data.js +4 -10
- package/dist/notify/digest-data.js.map +1 -1
- package/dist/notify/digest.js +1 -1
- package/dist/notify/digest.js.map +1 -1
- package/dist/notify/health.d.ts.map +1 -1
- package/dist/notify/health.js +4 -5
- package/dist/notify/health.js.map +1 -1
- package/dist/repo/services.d.ts +6 -0
- package/dist/repo/services.d.ts.map +1 -0
- package/dist/repo/services.js +16 -0
- package/dist/repo/services.js.map +1 -0
- package/dist/repo/trace-join.d.ts +9 -0
- package/dist/repo/trace-join.d.ts.map +1 -0
- package/dist/repo/trace-join.js +35 -0
- package/dist/repo/trace-join.js.map +1 -0
- package/dist/repo/trace-read.d.ts +6 -13
- package/dist/repo/trace-read.d.ts.map +1 -1
- package/dist/repo/trace-read.js +8 -3
- package/dist/repo/trace-read.js.map +1 -1
- package/dist/repo/trace-write.d.ts +5 -1
- package/dist/repo/trace-write.d.ts.map +1 -1
- package/dist/repo/trace-write.js +11 -2
- package/dist/repo/trace-write.js.map +1 -1
- package/dist/routes/changes.d.ts +4 -0
- package/dist/routes/changes.d.ts.map +1 -0
- package/dist/routes/changes.js +19 -0
- package/dist/routes/changes.js.map +1 -0
- package/dist/routes/data.d.ts.map +1 -1
- package/dist/routes/data.js +24 -9
- package/dist/routes/data.js.map +1 -1
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/routes/index.js +4 -0
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/ingest.d.ts.map +1 -1
- package/dist/routes/ingest.js +7 -2
- package/dist/routes/ingest.js.map +1 -1
- package/dist/routes/mcp.d.ts.map +1 -1
- package/dist/routes/mcp.js +42 -25
- package/dist/routes/mcp.js.map +1 -1
- package/dist/routes/metrics.d.ts +2 -2
- package/dist/routes/metrics.d.ts.map +1 -1
- package/dist/routes/metrics.js +2 -3
- package/dist/routes/metrics.js.map +1 -1
- package/dist/routes/models.d.ts +2 -0
- package/dist/routes/models.d.ts.map +1 -1
- package/dist/routes/models.js +10 -5
- package/dist/routes/models.js.map +1 -1
- package/dist/routes/orgs.d.ts.map +1 -1
- package/dist/routes/orgs.js +4 -0
- package/dist/routes/orgs.js.map +1 -1
- package/dist/routes/projects.d.ts.map +1 -1
- package/dist/routes/projects.js +1 -0
- package/dist/routes/projects.js.map +1 -1
- package/dist/routes/search.d.ts +4 -0
- package/dist/routes/search.d.ts.map +1 -0
- package/dist/routes/search.js +33 -0
- package/dist/routes/search.js.map +1 -0
- package/dist/routes/shares.d.ts.map +1 -1
- package/dist/routes/shares.js +8 -5
- package/dist/routes/shares.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +17 -5
- package/dist/server.js.map +1 -1
- package/dist/settle.d.ts +7 -6
- package/dist/settle.d.ts.map +1 -1
- package/dist/settle.js +30 -13
- package/dist/settle.js.map +1 -1
- package/dist/telemetry/cached.d.ts +11 -0
- package/dist/telemetry/cached.d.ts.map +1 -0
- package/dist/telemetry/cached.js +30 -0
- package/dist/telemetry/cached.js.map +1 -0
- package/dist/telemetry/ch/admin.d.ts +10 -0
- package/dist/telemetry/ch/admin.d.ts.map +1 -0
- package/dist/telemetry/ch/admin.js +65 -0
- package/dist/telemetry/ch/admin.js.map +1 -0
- package/dist/telemetry/ch/http.d.ts +19 -0
- package/dist/telemetry/ch/http.d.ts.map +1 -0
- package/dist/telemetry/ch/http.js +91 -0
- package/dist/telemetry/ch/http.js.map +1 -0
- package/dist/telemetry/ch/metrics.d.ts +10 -0
- package/dist/telemetry/ch/metrics.d.ts.map +1 -0
- package/dist/telemetry/ch/metrics.js +61 -0
- package/dist/telemetry/ch/metrics.js.map +1 -0
- package/dist/telemetry/ch/queries.d.ts +19 -0
- package/dist/telemetry/ch/queries.d.ts.map +1 -0
- package/dist/telemetry/ch/queries.js +30 -0
- package/dist/telemetry/ch/queries.js.map +1 -0
- package/dist/telemetry/ch/queue.d.ts +34 -0
- package/dist/telemetry/ch/queue.d.ts.map +1 -0
- package/dist/telemetry/ch/queue.js +79 -0
- package/dist/telemetry/ch/queue.js.map +1 -0
- package/dist/telemetry/ch/read.d.ts +12 -0
- package/dist/telemetry/ch/read.d.ts.map +1 -0
- package/dist/telemetry/ch/read.js +72 -0
- package/dist/telemetry/ch/read.js.map +1 -0
- package/dist/telemetry/ch/schema-facts.d.ts +6 -0
- package/dist/telemetry/ch/schema-facts.d.ts.map +1 -0
- package/dist/telemetry/ch/schema-facts.js +49 -0
- package/dist/telemetry/ch/schema-facts.js.map +1 -0
- package/dist/telemetry/ch/schema-raw.d.ts +8 -0
- package/dist/telemetry/ch/schema-raw.d.ts.map +1 -0
- package/dist/telemetry/ch/schema-raw.js +35 -0
- package/dist/telemetry/ch/schema-raw.js.map +1 -0
- package/dist/telemetry/ch/schema-rollups.d.ts +2 -0
- package/dist/telemetry/ch/schema-rollups.d.ts.map +1 -0
- package/dist/telemetry/ch/schema-rollups.js +61 -0
- package/dist/telemetry/ch/schema-rollups.js.map +1 -0
- package/dist/telemetry/ch/schema.d.ts +12 -0
- package/dist/telemetry/ch/schema.d.ts.map +1 -0
- package/dist/telemetry/ch/schema.js +25 -0
- package/dist/telemetry/ch/schema.js.map +1 -0
- package/dist/telemetry/ch/settle-rows.d.ts +13 -0
- package/dist/telemetry/ch/settle-rows.d.ts.map +1 -0
- package/dist/telemetry/ch/settle-rows.js +67 -0
- package/dist/telemetry/ch/settle-rows.js.map +1 -0
- package/dist/telemetry/ch/settle.d.ts +7 -0
- package/dist/telemetry/ch/settle.d.ts.map +1 -0
- package/dist/telemetry/ch/settle.js +96 -0
- package/dist/telemetry/ch/settle.js.map +1 -0
- package/dist/telemetry/ch/store.d.ts +16 -0
- package/dist/telemetry/ch/store.d.ts.map +1 -0
- package/dist/telemetry/ch/store.js +65 -0
- package/dist/telemetry/ch/store.js.map +1 -0
- package/dist/telemetry/ch/util.d.ts +20 -0
- package/dist/telemetry/ch/util.d.ts.map +1 -0
- package/dist/telemetry/ch/util.js +45 -0
- package/dist/telemetry/ch/util.js.map +1 -0
- package/dist/telemetry/ch/write.d.ts +11 -0
- package/dist/telemetry/ch/write.d.ts.map +1 -0
- package/dist/telemetry/ch/write.js +59 -0
- package/dist/telemetry/ch/write.js.map +1 -0
- package/dist/telemetry/copy.d.ts +9 -0
- package/dist/telemetry/copy.d.ts.map +1 -0
- package/dist/telemetry/copy.js +60 -0
- package/dist/telemetry/copy.js.map +1 -0
- package/dist/telemetry/index.d.ts +11 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +21 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/pg-store.d.ts +5 -0
- package/dist/telemetry/pg-store.d.ts.map +1 -0
- package/dist/telemetry/pg-store.js +78 -0
- package/dist/telemetry/pg-store.js.map +1 -0
- package/dist/telemetry/store.d.ts +74 -0
- package/dist/telemetry/store.d.ts.map +1 -0
- package/dist/telemetry/store.js +2 -0
- package/dist/telemetry/store.js.map +1 -0
- package/package.json +6 -5
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const DAY_MS = 86_400_000;
|
|
2
|
+
const RETENTION_CACHE_MS = 60_000;
|
|
3
|
+
let lastVer = 0;
|
|
4
|
+
/** A row version that only grows: ms times 1000, plus a counter within the same ms. */
|
|
5
|
+
export function nextVer(now) {
|
|
6
|
+
lastVer = Math.max(lastVer + 1, Math.floor(now) * 1000);
|
|
7
|
+
return lastVer;
|
|
8
|
+
}
|
|
9
|
+
/** Retention days per project, from Postgres, cached for a minute. */
|
|
10
|
+
export class RetentionCache {
|
|
11
|
+
lookup;
|
|
12
|
+
defaultDays;
|
|
13
|
+
cache = new Map();
|
|
14
|
+
constructor(lookup, defaultDays) {
|
|
15
|
+
this.lookup = lookup;
|
|
16
|
+
this.defaultDays = defaultDays;
|
|
17
|
+
}
|
|
18
|
+
async daysOf(projectIds) {
|
|
19
|
+
const now = Date.now();
|
|
20
|
+
const missing = [...new Set(projectIds)].filter((id) => !this.cache.has(id) || now - this.cache.get(id).atMs > RETENTION_CACHE_MS);
|
|
21
|
+
if (missing.length) {
|
|
22
|
+
const found = await this.lookup(missing);
|
|
23
|
+
for (const id of missing)
|
|
24
|
+
this.cache.set(id, { days: found.get(id) ?? this.defaultDays, atMs: now });
|
|
25
|
+
}
|
|
26
|
+
return new Map(projectIds.map((id) => [id, this.cache.get(id).days]));
|
|
27
|
+
}
|
|
28
|
+
async msOf(projectId) {
|
|
29
|
+
return (await this.daysOf([projectId])).get(projectId) * DAY_MS;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** A row object from a column list and values in the same order. */
|
|
33
|
+
export function rowOf(cols, values) {
|
|
34
|
+
const out = {};
|
|
35
|
+
cols.forEach((c, i) => (out[c] = values[i] ?? null));
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
export const byProject = (items) => {
|
|
39
|
+
const out = new Map();
|
|
40
|
+
for (const it of items)
|
|
41
|
+
out.set(it.project, [...(out.get(it.project) ?? []), it]);
|
|
42
|
+
return out;
|
|
43
|
+
};
|
|
44
|
+
export { DAY_MS };
|
|
45
|
+
//# sourceMappingURL=util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../../src/telemetry/ch/util.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,GAAG,UAAU,CAAC;AAC1B,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAElC,IAAI,OAAO,GAAG,CAAC,CAAC;AAEhB,uFAAuF;AACvF,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IACxD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,sEAAsE;AACtE,MAAM,OAAO,cAAc;IAIN,MAAM;IACN,WAAW;IAJb,KAAK,GAAG,IAAI,GAAG,EAA0C,CAAC;IAE3E,YACmB,MAAmB,EACnB,WAAmB;sBADnB,MAAM;2BACN,WAAW;IAC3B,CAAC;IAEJ,KAAK,CAAC,MAAM,CAAC,UAA6B;QACxC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC,IAAI,GAAG,kBAAkB,CAAC,CAAC;QACpI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACzC,KAAK,MAAM,EAAE,IAAI,OAAO;gBAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QACvG,CAAC;QACD,OAAO,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACzE,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,SAAiB;QAC1B,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAE,GAAG,MAAM,CAAC;IACnE,CAAC;CACF;AAED,oEAAoE;AACpE,MAAM,UAAU,KAAK,CAAC,IAAuB,EAAE,MAA0B;IACvE,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;IACrD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,CAAgC,KAAmB,EAAoB,EAAE;IAChG,MAAM,GAAG,GAAG,IAAI,GAAG,EAAe,CAAC;IACnC,KAAK,MAAM,EAAE,IAAI,KAAK;QAAE,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAClF,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { HubWrite } from "@wizeworks/lens-hub/kit";
|
|
2
|
+
import type { ChClient } from "./http.js";
|
|
3
|
+
import type { SettleQueue } from "./queue.js";
|
|
4
|
+
/** Small batches from many add-ons: ClickHouse buffers them into one part, and answers once they are written. */
|
|
5
|
+
export declare const ASYNC: {
|
|
6
|
+
async_insert: string;
|
|
7
|
+
wait_for_async_insert: string;
|
|
8
|
+
};
|
|
9
|
+
/** Save one batch's raw telemetry and queue its traces for settling. Metric rollups are written by the caller. */
|
|
10
|
+
export declare function writeRaw(ch: ChClient, queue: SettleQueue, projectId: string, w: HubWrite, now: number, retentionMs: number): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=write.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../../src/telemetry/ch/write.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,iHAAiH;AACjH,eAAO,MAAM,KAAK;IAAK,YAAY;IAAO,qBAAqB;CAAO,CAAC;AA0CvE,kHAAkH;AAClH,wBAAsB,QAAQ,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAahJ"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Ingest into ClickHouse: raw spans, logs, trace bounds, the update log, and metric points. Server-side async inserts batch the small writes.
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { ATTR_BROWSER_SESSION, logKey, seriesKeyOf } from "@wizeworks/lens-core";
|
|
4
|
+
import { nextVer } from "./util.js";
|
|
5
|
+
/** Small batches from many add-ons: ClickHouse buffers them into one part, and answers once they are written. */
|
|
6
|
+
export const ASYNC = { async_insert: "1", wait_for_async_insert: "1" };
|
|
7
|
+
const sha1 = (text) => createHash("sha1").update(text).digest("hex");
|
|
8
|
+
const sessionOf = (s) => {
|
|
9
|
+
const v = s.attributes[ATTR_BROWSER_SESSION];
|
|
10
|
+
return typeof v === "string" && v ? v : null;
|
|
11
|
+
};
|
|
12
|
+
/** One bounds row per trace in the batch: its earliest start and latest end here. */
|
|
13
|
+
function headRows(w, projectId, now, expire) {
|
|
14
|
+
const bounds = new Map();
|
|
15
|
+
const touch = (id, start, end) => {
|
|
16
|
+
const b = bounds.get(id);
|
|
17
|
+
bounds.set(id, b ? [Math.min(b[0], start), Math.max(b[1], end)] : [start, end]);
|
|
18
|
+
};
|
|
19
|
+
for (const s of w.spans)
|
|
20
|
+
touch(s.traceId, s.startMs, s.startMs + s.durationMs);
|
|
21
|
+
for (const { traceId, log } of w.logs)
|
|
22
|
+
touch(traceId, log.timeMs, log.timeMs);
|
|
23
|
+
const env = w.sender.environment ?? "";
|
|
24
|
+
return [...bounds].map(([trace_id, [start, end]]) => ({ project_id: projectId, trace_id, start_ms: start, end_ms: end, updated_ms: now, env, expire_ms: expire(start) }));
|
|
25
|
+
}
|
|
26
|
+
function spanRows(w, projectId, ver, expire) {
|
|
27
|
+
return w.spans.map((s) => ({
|
|
28
|
+
project_id: projectId, trace_id: s.traceId, span_id: s.spanId, service: s.service, start_ms: s.startMs, duration_ms: s.durationMs,
|
|
29
|
+
session: sessionOf(s), json: JSON.stringify(s), ver, expire_ms: expire(s.startMs),
|
|
30
|
+
}));
|
|
31
|
+
}
|
|
32
|
+
function logRows(w, projectId, ver, expire) {
|
|
33
|
+
return w.logs.map(({ traceId, log }) => ({
|
|
34
|
+
project_id: projectId, trace_id: traceId, key: sha1(logKey(log)), time_ms: log.timeMs, json: JSON.stringify(log), ver, expire_ms: expire(log.timeMs),
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
function pointRows(w, projectId, expire) {
|
|
38
|
+
const env = w.sender.environment ?? "";
|
|
39
|
+
return (w.metrics ?? []).map((p) => ({
|
|
40
|
+
project_id: projectId, time_ms: p.timeMs, env, service: p.service, name: p.name, series_key: sha1(seriesKeyOf(p)), json: JSON.stringify(p), expire_ms: expire(p.timeMs),
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
/** Save one batch's raw telemetry and queue its traces for settling. Metric rollups are written by the caller. */
|
|
44
|
+
export async function writeRaw(ch, queue, projectId, w, now, retentionMs) {
|
|
45
|
+
const expire = (ms) => ms + retentionMs;
|
|
46
|
+
const ver = nextVer(now);
|
|
47
|
+
const heads = headRows(w, projectId, now, expire);
|
|
48
|
+
await Promise.all([
|
|
49
|
+
ch.insert("spans_raw", spanRows(w, projectId, ver, expire), ASYNC),
|
|
50
|
+
ch.insert("logs_raw", logRows(w, projectId, ver, expire), ASYNC),
|
|
51
|
+
ch.insert("metric_points_raw", pointRows(w, projectId, expire), ASYNC),
|
|
52
|
+
]);
|
|
53
|
+
// Bounds and the update log go last, so a settle never sees a trace before its parts.
|
|
54
|
+
const updates = heads.map((h) => ({ project_id: h.project_id, trace_id: h.trace_id, updated_ms: now, env: h.env }));
|
|
55
|
+
await Promise.all([ch.insert("trace_heads", heads, ASYNC), ch.insert("trace_updates", updates, ASYNC)]);
|
|
56
|
+
for (const h of heads)
|
|
57
|
+
queue.touch(projectId, h.trace_id, h.env, now);
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../../src/telemetry/ch/write.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Db } from "../db/db.js";
|
|
2
|
+
import type { TelemetryStore } from "./store.js";
|
|
3
|
+
export interface CopyResult {
|
|
4
|
+
traces: number;
|
|
5
|
+
points: number;
|
|
6
|
+
}
|
|
7
|
+
/** Copy everything (the target settles it later); projects the target has are skipped, else rollups count twice; `force` copies them too, after the switch. */
|
|
8
|
+
export declare function copyTelemetry(db: Db, to: TelemetryStore, now: number, log?: (line: string) => void, force?: boolean): Promise<CopyResult>;
|
|
9
|
+
//# sourceMappingURL=copy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy.d.ts","sourceRoot":"","sources":["../../src/telemetry/copy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAIjD,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAoDD,+JAA+J;AAC/J,wBAAsB,aAAa,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAe,EAAE,KAAK,UAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAcvJ"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
const PAGE = 500;
|
|
2
|
+
/** One page of a project's traces, newest first, after the (start, id) cursor. */
|
|
3
|
+
async function tracePage(db, projectId, after) {
|
|
4
|
+
const cursor = after ? "AND (start_ms < $2 OR (start_ms = $2 AND trace_id > $3))" : "";
|
|
5
|
+
return db.query(`SELECT trace_id, start_ms, env FROM traces WHERE project_id = $1 ${cursor} ORDER BY start_ms DESC, trace_id LIMIT ${PAGE}`, after ? [projectId, after[0], after[1]] : [projectId]);
|
|
6
|
+
}
|
|
7
|
+
async function partsOf(db, projectId, ids) {
|
|
8
|
+
const spans = await db.query("SELECT trace_id, json FROM spans WHERE project_id = $1 AND trace_id = ANY($2)", [projectId, [...ids]]);
|
|
9
|
+
const logs = await db.query("SELECT trace_id, json FROM logs WHERE project_id = $1 AND trace_id = ANY($2)", [projectId, [...ids]]);
|
|
10
|
+
return { spans, logs };
|
|
11
|
+
}
|
|
12
|
+
/** Every trace of a project, written one trace at a time so each keeps its environment. */
|
|
13
|
+
async function copyTraces(db, to, projectId, now) {
|
|
14
|
+
let after = null;
|
|
15
|
+
let n = 0;
|
|
16
|
+
for (;;) {
|
|
17
|
+
const page = await tracePage(db, projectId, after);
|
|
18
|
+
if (!page.length)
|
|
19
|
+
return n;
|
|
20
|
+
const { spans, logs } = await partsOf(db, projectId, page.map((t) => t.trace_id));
|
|
21
|
+
for (const t of page) {
|
|
22
|
+
const s = spans.filter((r) => r.trace_id === t.trace_id).map((r) => JSON.parse(r.json));
|
|
23
|
+
const l = logs.filter((r) => r.trace_id === t.trace_id).map((r) => ({ traceId: t.trace_id, log: JSON.parse(r.json) }));
|
|
24
|
+
await to.write(projectId, { sender: { service: s[0]?.service ?? "copy", environment: t.env }, via: "addon", spans: s, logs: l, remotes: [] }, now);
|
|
25
|
+
}
|
|
26
|
+
n += page.length;
|
|
27
|
+
after = [page[page.length - 1].start_ms, page[page.length - 1].trace_id];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** Every metric point of a project, oldest first, in batches of one environment, so counters and rates come out as at ingest. */
|
|
31
|
+
async function copyPoints(db, to, projectId, now) {
|
|
32
|
+
let n = 0;
|
|
33
|
+
for (let offset = 0;; offset += PAGE * 10) {
|
|
34
|
+
const rows = await db.query(`SELECT env, json FROM metric_points WHERE project_id = $1 ORDER BY time_ms, series_key LIMIT ${PAGE * 10} OFFSET ${offset}`, [projectId]);
|
|
35
|
+
if (!rows.length)
|
|
36
|
+
return n;
|
|
37
|
+
for (const env of [...new Set(rows.map((r) => r.env))]) {
|
|
38
|
+
const metrics = rows.filter((r) => r.env === env).map((r) => JSON.parse(r.json));
|
|
39
|
+
await to.write(projectId, { sender: { service: "copy", environment: env }, via: "otlp", spans: [], logs: [], remotes: [], metrics }, now);
|
|
40
|
+
}
|
|
41
|
+
n += rows.length;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/** Copy everything (the target settles it later); projects the target has are skipped, else rollups count twice; `force` copies them too, after the switch. */
|
|
45
|
+
export async function copyTelemetry(db, to, now, log = () => { }, force = false) {
|
|
46
|
+
const out = { traces: 0, points: 0 };
|
|
47
|
+
for (const { id } of await db.query("SELECT id FROM projects ORDER BY id")) {
|
|
48
|
+
if (!force && (await to.counts(id)).traces > 0) {
|
|
49
|
+
log(` ${id}: already copied, skipped`);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const traces = await copyTraces(db, to, id, now);
|
|
53
|
+
const points = await copyPoints(db, to, id, now);
|
|
54
|
+
log(` ${id}: ${traces} traces, ${points} metric points`);
|
|
55
|
+
out.traces += traces;
|
|
56
|
+
out.points += points;
|
|
57
|
+
}
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=copy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy.js","sourceRoot":"","sources":["../../src/telemetry/copy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CloudConfig } from "../config.js";
|
|
2
|
+
import type { Db } from "../db/db.js";
|
|
3
|
+
import type { RetentionOf, TelemetryStore } from "./store.js";
|
|
4
|
+
export type { MetricQuery, SettleOptions, TelemetryStore, TraceQuery } from "./store.js";
|
|
5
|
+
/** Retention days of the projects that still exist; deleted projects are left out. */
|
|
6
|
+
export declare const pgRetentionOf: (db: Db) => RetentionOf;
|
|
7
|
+
/** The telemetry store for this cloud: ClickHouse (scale mode) when a URL is set, else the cloud's own database. */
|
|
8
|
+
export declare function openTelemetry(config: CloudConfig, db: Db): Promise<TelemetryStore>;
|
|
9
|
+
/** Drop the telemetry of projects that were deleted (or cleared) in Postgres. */
|
|
10
|
+
export declare function clearProjects(t: TelemetryStore, projectIds: readonly string[]): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/telemetry/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAItC,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE9D,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEzF,sFAAsF;AACtF,eAAO,MAAM,aAAa,OAAQ,EAAE,KAAG,WAGtC,CAAC;AAEF,oHAAoH;AACpH,wBAAsB,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAKxF;AAED,iFAAiF;AACjF,wBAAsB,aAAa,CAAC,CAAC,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAEnG"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { withCachedCounts } from "./cached.js";
|
|
2
|
+
import { openClickHouse } from "./ch/store.js";
|
|
3
|
+
import { pgTelemetry } from "./pg-store.js";
|
|
4
|
+
/** Retention days of the projects that still exist; deleted projects are left out. */
|
|
5
|
+
export const pgRetentionOf = (db) => async (ids) => {
|
|
6
|
+
const rows = await db.query("SELECT p.id, o.retention_days AS d FROM projects p JOIN orgs o ON o.id = p.org_id WHERE p.id = ANY($1)", [[...ids]]);
|
|
7
|
+
return new Map(rows.map((r) => [r.id, r.d]));
|
|
8
|
+
};
|
|
9
|
+
/** The telemetry store for this cloud: ClickHouse (scale mode) when a URL is set, else the cloud's own database. */
|
|
10
|
+
export async function openTelemetry(config, db) {
|
|
11
|
+
const store = config.clickhouseUrl
|
|
12
|
+
? await openClickHouse({ url: config.clickhouseUrl, retentionOf: pgRetentionOf(db), defaultRetentionDays: config.retentionDays, now: config.now })
|
|
13
|
+
: pgTelemetry(db);
|
|
14
|
+
return withCachedCounts(store, Date.now);
|
|
15
|
+
}
|
|
16
|
+
/** Drop the telemetry of projects that were deleted (or cleared) in Postgres. */
|
|
17
|
+
export async function clearProjects(t, projectIds) {
|
|
18
|
+
for (const id of projectIds)
|
|
19
|
+
await t.clearProject(id);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/telemetry/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAK5C,sFAAsF;AACtF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAM,EAAe,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;IAClE,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,KAAK,CAA4B,wGAAwG,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7K,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC,CAAC;AAEF,oHAAoH;AACpH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAmB,EAAE,EAAM;IAC7D,MAAM,KAAK,GAAG,MAAM,CAAC,aAAa;QAChC,CAAC,CAAC,MAAM,cAAc,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,aAAa,EAAE,WAAW,EAAE,aAAa,CAAC,EAAE,CAAC,EAAE,oBAAoB,EAAE,MAAM,CAAC,aAAa,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC;QAClJ,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IACpB,OAAO,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3C,CAAC;AAED,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,CAAiB,EAAE,UAA6B;IAClF,KAAK,MAAM,EAAE,IAAI,UAAU;QAAE,MAAM,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Db } from "../db/db.js";
|
|
2
|
+
import type { TelemetryStore } from "./store.js";
|
|
3
|
+
/** Telemetry in the cloud's own database. Retention reads the organizations from the same database. */
|
|
4
|
+
export declare function pgTelemetry(db: Db): TelemetryStore;
|
|
5
|
+
//# sourceMappingURL=pg-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pg-store.d.ts","sourceRoot":"","sources":["../../src/telemetry/pg-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAStC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AA0BjD,uGAAuG;AACvG,wBAAgB,WAAW,CAAC,EAAE,EAAE,EAAE,GAAG,cAAc,CAgDlD"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// Small mode: telemetry in the same Postgres (or PGlite) as accounts. The default, and what self-hosters and tests run.
|
|
2
|
+
import { PG_DIALECT, searchSql, suggestSql } from "@wizeworks/lens-core";
|
|
3
|
+
import { ensureTrigram } from "../db/trigram.js";
|
|
4
|
+
import { loadMetricAlertData, loadMetricData } from "../repo/metric-read.js";
|
|
5
|
+
import { METRIC_TABLES } from "../repo/metric-write.js";
|
|
6
|
+
import { getJoinedTrace } from "../repo/trace-join.js";
|
|
7
|
+
import { countRows, getTrace, queryTraces, traceEnvsPg } from "../repo/trace-read.js";
|
|
8
|
+
import { pruneByRetention, pruneMetricsByRetention, writeTelemetry } from "../repo/trace-write.js";
|
|
9
|
+
import { cloudExecutor, cloudSettling, pgRunner } from "../scale-exec.js";
|
|
10
|
+
import { factsStale, pruneRollups, resetFacts, settleCloud, STATS_TABLES } from "../settle.js";
|
|
11
|
+
const TELEMETRY_TABLES = ["spans", "logs", "traces", "metric_points", ...METRIC_TABLES, ...STATS_TABLES];
|
|
12
|
+
async function slowestEndpoints(db, projectId, w, minCount, limit) {
|
|
13
|
+
const rows = await db.query(`SELECT endpoint, percentile_cont(0.95) WITHIN GROUP (ORDER BY duration_ms) AS p95, count(*)::int AS n FROM fact_requests
|
|
14
|
+
WHERE project_id = $1 AND start_ms >= $2 AND start_ms < $3 GROUP BY endpoint HAVING count(*) >= $4 ORDER BY p95 DESC LIMIT $5`, [projectId, w.from, w.to, minCount, limit]);
|
|
15
|
+
return rows.map((r) => ({ endpoint: r.endpoint, p95Ms: Number(r.p95), count: r.n }));
|
|
16
|
+
}
|
|
17
|
+
async function lastTraceMs(db) {
|
|
18
|
+
const rows = await db.query("SELECT project_id, max(start_ms) AS last_ms FROM traces GROUP BY project_id");
|
|
19
|
+
return new Map(rows.map((r) => [r.project_id, Number(r.last_ms)]));
|
|
20
|
+
}
|
|
21
|
+
async function activeHours(db, projectId, from, to) {
|
|
22
|
+
const [row] = await db.query("SELECT count(DISTINCT floor(start_ms / 3600000))::int AS n FROM traces WHERE project_id = $1 AND start_ms > $2 AND start_ms <= $3", [projectId, from, to]);
|
|
23
|
+
return row?.n ?? 0;
|
|
24
|
+
}
|
|
25
|
+
/** Telemetry in the cloud's own database. Retention reads the organizations from the same database. */
|
|
26
|
+
export function pgTelemetry(db) {
|
|
27
|
+
const src = (projectId) => ({ d: PG_DIALECT, run: pgRunner(db), scope: { project: projectId } });
|
|
28
|
+
// A facts reset can take minutes on a big database, so it runs after start; settling waits for it, and tries again if it failed.
|
|
29
|
+
let reset = Promise.resolve();
|
|
30
|
+
const startReset = () => {
|
|
31
|
+
reset = resetFacts(db);
|
|
32
|
+
reset.catch((err) => console.error("Facts reset failed; settling tries again.", err));
|
|
33
|
+
};
|
|
34
|
+
// Trigram indexes build in the background too; close waits for them.
|
|
35
|
+
let trigram = Promise.resolve();
|
|
36
|
+
return {
|
|
37
|
+
kind: "postgres",
|
|
38
|
+
write: (projectId, w, now) => db.tx((q) => writeTelemetry(q, projectId, w, now)),
|
|
39
|
+
traces: (t) => queryTraces(db, t),
|
|
40
|
+
trace: (projectId, traceId) => getTrace(db, projectId, traceId),
|
|
41
|
+
joinedTrace: (primaryId, scope, traceId) => getJoinedTrace(db, primaryId, scope, traceId),
|
|
42
|
+
counts: (projectId) => countRows(db, projectId),
|
|
43
|
+
traceEnvs: (projectId) => traceEnvsPg(db, projectId),
|
|
44
|
+
activeHours: (projectId, from, to) => activeHours(db, projectId, from, to),
|
|
45
|
+
lastTraceMs: () => lastTraceMs(db),
|
|
46
|
+
executor: (projectId, retentionMs, env) => cloudExecutor(db, projectId, retentionMs, env),
|
|
47
|
+
settling: (projectId, env) => cloudSettling(db, projectId, env),
|
|
48
|
+
search: (projectId, q) => searchSql(src(projectId), q),
|
|
49
|
+
suggest: (projectId, r) => suggestSql(src(projectId), r),
|
|
50
|
+
slowestEndpoints: (projectId, w, minCount, limit) => slowestEndpoints(db, projectId, w, minCount, limit),
|
|
51
|
+
metricData: (m, range, params, now) => loadMetricData(db, m, range, params, now),
|
|
52
|
+
metricAlertData: (m, name, w, now) => loadMetricAlertData(db, m, name, w, now),
|
|
53
|
+
async settle(now, o) {
|
|
54
|
+
await reset.catch(() => (startReset(), reset));
|
|
55
|
+
return settleCloud(db, now, o);
|
|
56
|
+
},
|
|
57
|
+
async prune(now) {
|
|
58
|
+
while ((await pruneByRetention(db, now)) > 0)
|
|
59
|
+
;
|
|
60
|
+
await pruneMetricsByRetention(db, now);
|
|
61
|
+
await pruneRollups(db, now, true);
|
|
62
|
+
},
|
|
63
|
+
pruneRollups: (now) => pruneRollups(db, now),
|
|
64
|
+
async checkFactsVersion() {
|
|
65
|
+
trigram = ensureTrigram(db).catch((err) => console.error("Trigram indexes failed; text searches scan until the next start.", err));
|
|
66
|
+
if (!(await factsStale(db)))
|
|
67
|
+
return false;
|
|
68
|
+
startReset();
|
|
69
|
+
return true;
|
|
70
|
+
},
|
|
71
|
+
async clearProject(projectId) {
|
|
72
|
+
for (const table of TELEMETRY_TABLES)
|
|
73
|
+
await db.query(`DELETE FROM ${table} WHERE project_id = $1`, [projectId]);
|
|
74
|
+
},
|
|
75
|
+
close: async () => void (await trigram),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=pg-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pg-store.js","sourceRoot":"","sources":["../../src/telemetry/pg-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { Executor, MetricAlertData, MetricData, SearchPage, SearchQuery, Suggestion, SuggestRequest, TimeRange, TimeWindow, Trace } from "@wizeworks/lens-core";
|
|
2
|
+
import type { HubWrite } from "@wizeworks/lens-hub/kit";
|
|
3
|
+
export interface TraceQuery {
|
|
4
|
+
projectId: string;
|
|
5
|
+
/** Changed at or after (server clock). */
|
|
6
|
+
since?: number;
|
|
7
|
+
/** Started before. For paging back. */
|
|
8
|
+
before?: number;
|
|
9
|
+
/** Started at or after. For time windows. */
|
|
10
|
+
from?: number;
|
|
11
|
+
env?: string;
|
|
12
|
+
session?: string;
|
|
13
|
+
limit: number;
|
|
14
|
+
}
|
|
15
|
+
export interface MetricQuery {
|
|
16
|
+
projectId: string;
|
|
17
|
+
env?: string;
|
|
18
|
+
service?: string;
|
|
19
|
+
}
|
|
20
|
+
/** How long each project's organization keeps data, in days; the default when a project has none. */
|
|
21
|
+
export type RetentionOf = (projectIds: readonly string[]) => Promise<Map<string, number>>;
|
|
22
|
+
export interface SettleOptions {
|
|
23
|
+
defaultRetentionDays?: number;
|
|
24
|
+
batch?: number;
|
|
25
|
+
budgetMs?: number;
|
|
26
|
+
/** Called for each project whose stats a batch wrote. */
|
|
27
|
+
onSettled?: (projectId: string) => void;
|
|
28
|
+
}
|
|
29
|
+
/** One telemetry backend. Postgres ("small mode") and ClickHouse ("scale mode") answer the same calls with the same results. */
|
|
30
|
+
export interface TelemetryStore {
|
|
31
|
+
readonly kind: "postgres" | "clickhouse";
|
|
32
|
+
/** Spans, logs, trace bounds, and metric points of one batch. */
|
|
33
|
+
write(projectId: string, w: HubWrite, now: number): Promise<void>;
|
|
34
|
+
traces(t: TraceQuery): Promise<Trace[]>;
|
|
35
|
+
trace(projectId: string, traceId: string): Promise<Trace | undefined>;
|
|
36
|
+
/** One trace with its parts from the other projects in `scope` (already checked by the caller). */
|
|
37
|
+
joinedTrace(primaryId: string, scope: readonly string[], traceId: string): Promise<Trace | undefined>;
|
|
38
|
+
counts(projectId: string): Promise<{
|
|
39
|
+
traces: number;
|
|
40
|
+
spans: number;
|
|
41
|
+
}>;
|
|
42
|
+
/** Environments seen on traces. */
|
|
43
|
+
traceEnvs(projectId: string): Promise<string[]>;
|
|
44
|
+
/** Distinct hours with a trace in (from, to]. */
|
|
45
|
+
activeHours(projectId: string, from: number, to: number): Promise<number>;
|
|
46
|
+
/** The newest trace start per project; projects without traces are left out. */
|
|
47
|
+
lastTraceMs(): Promise<Map<string, number>>;
|
|
48
|
+
/** Page needs from the project's stats. */
|
|
49
|
+
executor(projectId: string, retentionMs: number, env?: string): Executor;
|
|
50
|
+
/** Traces still waiting for their stats, or null when none. */
|
|
51
|
+
settling(projectId: string, env?: string): Promise<number | null>;
|
|
52
|
+
search(projectId: string, q: SearchQuery): Promise<SearchPage>;
|
|
53
|
+
suggest(projectId: string, r: SuggestRequest): Promise<Suggestion[]>;
|
|
54
|
+
/** The slowest endpoints by p95 in a window, with at least `minCount` requests. */
|
|
55
|
+
slowestEndpoints(projectId: string, w: TimeWindow, minCount: number, limit: number): Promise<{
|
|
56
|
+
endpoint: string;
|
|
57
|
+
p95Ms: number;
|
|
58
|
+
count: number;
|
|
59
|
+
}[]>;
|
|
60
|
+
metricData(m: MetricQuery, range: TimeRange, params: Readonly<Record<string, string>>, now: number): Promise<MetricData>;
|
|
61
|
+
metricAlertData(m: MetricQuery, name: string, w: TimeWindow, now: number): Promise<MetricAlertData>;
|
|
62
|
+
/** Build stats for quiet traces. Returns how many settled. */
|
|
63
|
+
settle(now: number, o?: SettleOptions): Promise<number>;
|
|
64
|
+
/** Drop traces, metrics, and rollups past each organization's retention. */
|
|
65
|
+
prune(now: number): Promise<void>;
|
|
66
|
+
/** Age out the short rollup tiers. */
|
|
67
|
+
pruneRollups(now: number): Promise<void>;
|
|
68
|
+
/** On startup: rebuild the stats when the facts version changed. True when it did. */
|
|
69
|
+
checkFactsVersion(): Promise<boolean>;
|
|
70
|
+
/** Delete every trace, span, log, metric, and stat of a project. */
|
|
71
|
+
clearProject(projectId: string): Promise<void>;
|
|
72
|
+
close(): Promise<void>;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/telemetry/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/telemetry/store.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wizeworks/lens-cloud",
|
|
3
|
-
"version": "0.3.0-alpha.
|
|
3
|
+
"version": "0.3.0-alpha.3",
|
|
4
4
|
"description": "The WizeLens cloud service: many organizations, accounts and teams, server-side stats, alerts, sharing, and scoped AI access, on Postgres.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "WizeWorks LLC",
|
|
@@ -53,12 +53,13 @@
|
|
|
53
53
|
"pg": "^8.23.1",
|
|
54
54
|
"react": "^19.3.1",
|
|
55
55
|
"react-dom": "^19.3.1",
|
|
56
|
-
"@wizeworks/lens-core": "^0.3.0-alpha.
|
|
57
|
-
"@wizeworks/lens-hub": "^0.3.0-alpha.
|
|
58
|
-
"@wizeworks/lens-
|
|
59
|
-
"@wizeworks/lens-
|
|
56
|
+
"@wizeworks/lens-core": "^0.3.0-alpha.3",
|
|
57
|
+
"@wizeworks/lens-hub": "^0.3.0-alpha.3",
|
|
58
|
+
"@wizeworks/lens-node": "^0.3.0-alpha.3",
|
|
59
|
+
"@wizeworks/lens-ui": "^0.3.0-alpha.3"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
|
+
"@modelcontextprotocol/sdk": "^1.32.1",
|
|
62
63
|
"@types/node": "^24.19.2",
|
|
63
64
|
"@types/nodemailer": "^8.0.2",
|
|
64
65
|
"@types/pg": "^8.23.1",
|