@uptimizr/collector-server 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -148,8 +148,14 @@ The storage backend is chosen with `COLLECTOR_STORE`:
148
148
  instance per file; back up by copying the file.
149
149
  - `memory` — a dependency-free in-memory store for local dev / E2E only (seed its
150
150
  project/key via `COLLECTOR_MEMORY_PROJECT_ID` / `COLLECTOR_MEMORY_API_KEY`).
151
+ - `clickhouse` — a **single-tenant ClickHouse store** for the scale tier: events **and**
152
+ metadata (projects, API keys, scene representations) live in one ClickHouse database
153
+ (`CLICKHOUSE_URL` / `CLICKHOUSE_DATABASE` / `CLICKHOUSE_USER` / `CLICKHOUSE_PASSWORD`), created
154
+ on first boot. Use it for concurrent writers / horizontal scale and high-volume ingestion. The
155
+ full analytics surface returns results identical to DuckDB (cross-engine parity suite).
151
156
 
152
- The two-store ClickHouse + Postgres path is an optional scale tier and is not required to self-host the OSS collector.
157
+ For multi-writer / horizontal scale, choose the `clickhouse` store; spin up a local ClickHouse
158
+ with `infra/docker` (`pnpm stack:up`). The default DuckDB store needs no external service.
153
159
 
154
160
  ## Develop
155
161
 
@@ -161,8 +167,8 @@ pnpm --filter @uptimizr/collector-server build
161
167
 
162
168
  The data layer is abstracted by `CollectorStore`, so tests run against a fake store
163
169
  with `app.inject()` — no live database required. Local end-to-end runs use the
164
- default DuckDB store (a single file, no service to start); the ClickHouse + Postgres
165
- stack in `infra/docker` backs the optional scale tier only.
170
+ default DuckDB store (a single file, no service to start); the `clickhouse` store in
171
+ `infra/docker` backs the optional scale tier.
166
172
 
167
173
  ## License
168
174
 
@@ -0,0 +1,17 @@
1
+ import type { CollectorStore } from "./store.js";
2
+ /**
3
+ * Optional single-tenant ClickHouse store (ADR 0020): the scale path for
4
+ * self-hosters who outgrow DuckDB's single read-write process. It carries the
5
+ * **full** analytics surface — no stubbed aggregates — by rendering the same
6
+ * dialect-agnostic builders with {@link clickhouseDialect} and executing them
7
+ * over a ClickHouse server. Events live in the wide `events` table (plus the
8
+ * dedicated `node_samples`); metadata (projects, API keys, scene registry) is
9
+ * re-homed into the same database.
10
+ *
11
+ * The schema is migrated on creation (migrations are idempotent and forward-only),
12
+ * so the store is usable out of the box once a ClickHouse server is reachable.
13
+ * Connection settings come from `readDbSettings().clickhouse` (the `CLICKHOUSE_*`
14
+ * env vars).
15
+ */
16
+ export declare function createClickhouseStore(): Promise<CollectorStore>;
17
+ //# sourceMappingURL=clickhouseStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clickhouseStore.d.ts","sourceRoot":"","sources":["../src/clickhouseStore.ts"],"names":[],"mappings":"AA4FA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,cAAc,CAAC,CAkGrE"}
@@ -0,0 +1,74 @@
1
+ import { buildCameraDirectionHeatmap, buildCameraDistance, buildCameraPositionHeatmap, buildClickGazeRay, buildDeadClicks, buildRageClicks, buildHoverDwell, buildCompileStalls, buildResourceSummary, buildCapabilityChanges, buildCameraGestures, buildDistinctScenes, buildEventTypeCounts, buildFlowHeatmap, buildListSessions, buildNavigationStats, buildXrRotationRate, buildXrSourceUsage, buildXrAbandonment, buildInteractionsBySource, buildMeshDwell, buildPerfSummary, buildPerfDistribution, buildFpsHistogram, buildFrameTimePercentiles, buildJankRate, buildPerfByDevice, buildPerfByScene, buildResourcePercentiles, buildStabilityCounts, buildPointerHeatmap, buildSceneCoverage, buildSessionTrajectory, buildTimeseries, buildTopMeshes, buildWorldHeatmap, buildGazeHeatmap, clickhouseDialect, readDbSettings, } from "@uptimizr/db";
2
+ import { createClickhouseClient, migrateClickhouse, runClickhouseQuery, insertEvents as chInsertEvents, getSessionEvents as chGetSessionEvents, streamSessionEvents as chStreamSessionEvents, getSessionMeta as chGetSessionMeta, getProject as chGetProject, resolveApiKey as chResolveApiKey, upsertSceneProxy as chUpsertSceneProxy, getSceneRepresentation as chGetSceneRepresentation, listSceneRepresentations as chListSceneRepresentations, } from "@uptimizr/db-clickhouse";
3
+ /**
4
+ * Optional single-tenant ClickHouse store (ADR 0020): the scale path for
5
+ * self-hosters who outgrow DuckDB's single read-write process. It carries the
6
+ * **full** analytics surface — no stubbed aggregates — by rendering the same
7
+ * dialect-agnostic builders with {@link clickhouseDialect} and executing them
8
+ * over a ClickHouse server. Events live in the wide `events` table (plus the
9
+ * dedicated `node_samples`); metadata (projects, API keys, scene registry) is
10
+ * re-homed into the same database.
11
+ *
12
+ * The schema is migrated on creation (migrations are idempotent and forward-only),
13
+ * so the store is usable out of the box once a ClickHouse server is reachable.
14
+ * Connection settings come from `readDbSettings().clickhouse` (the `CLICKHOUSE_*`
15
+ * env vars).
16
+ */
17
+ export async function createClickhouseStore() {
18
+ const settings = readDbSettings().clickhouse;
19
+ const ch = createClickhouseClient(settings);
20
+ await migrateClickhouse(ch, settings);
21
+ const d = clickhouseDialect;
22
+ return {
23
+ resolveApiKey: (key) => chResolveApiKey(ch, key),
24
+ projectExists: async (projectId) => (await chGetProject(ch, projectId)) !== null,
25
+ insertEvents: (events) => chInsertEvents(ch, [...events]),
26
+ listSessions: (projectId, opts = {}) => runClickhouseQuery(ch, buildListSessions(projectId, opts, d)),
27
+ pointerHeatmap: (projectId, opts = {}) => runClickhouseQuery(ch, buildPointerHeatmap(projectId, opts, d)),
28
+ worldHeatmap: (projectId, opts = {}) => runClickhouseQuery(ch, buildWorldHeatmap(projectId, opts, d)),
29
+ gazeHeatmap: (projectId, opts = {}) => runClickhouseQuery(ch, buildGazeHeatmap(projectId, opts, d)),
30
+ cameraHeatmap: (projectId, opts = {}) => runClickhouseQuery(ch, buildCameraDirectionHeatmap(projectId, opts, d)),
31
+ cameraPositionHeatmap: (projectId, opts = {}) => runClickhouseQuery(ch, buildCameraPositionHeatmap(projectId, opts, d)),
32
+ sessionTrajectory: (projectId, sessionId, opts = {}) => runClickhouseQuery(ch, buildSessionTrajectory(projectId, { ...opts, session: sessionId }, d)),
33
+ clickGazeRays: (projectId, opts = {}) => runClickhouseQuery(ch, buildClickGazeRay(projectId, opts, d)),
34
+ flowHeatmap: (projectId, opts = {}) => runClickhouseQuery(ch, buildFlowHeatmap(projectId, opts, d)),
35
+ topMeshes: (projectId, opts = {}) => runClickhouseQuery(ch, buildTopMeshes(projectId, opts, d)),
36
+ meshDwell: (projectId, opts = {}) => runClickhouseQuery(ch, buildMeshDwell(projectId, opts, d)),
37
+ deadClicks: (projectId, opts = {}) => runClickhouseQuery(ch, buildDeadClicks(projectId, opts, d)),
38
+ rageClicks: (projectId, opts = {}) => runClickhouseQuery(ch, buildRageClicks(projectId, opts, d)),
39
+ hoverDwell: (projectId, opts = {}) => runClickhouseQuery(ch, buildHoverDwell(projectId, opts, d)),
40
+ compileStalls: (projectId, opts = {}) => runClickhouseQuery(ch, buildCompileStalls(projectId, opts, d)),
41
+ resourceSummary: (projectId, opts = {}) => runClickhouseQuery(ch, buildResourceSummary(projectId, opts, d)),
42
+ capabilityChanges: (projectId, opts = {}) => runClickhouseQuery(ch, buildCapabilityChanges(projectId, opts, d)),
43
+ cameraGestures: (projectId, opts = {}) => runClickhouseQuery(ch, buildCameraGestures(projectId, opts, d)),
44
+ perfSummary: (projectId, opts = {}) => runClickhouseQuery(ch, buildPerfSummary(projectId, opts, d)),
45
+ perfDistribution: (projectId, opts = {}) => runClickhouseQuery(ch, buildPerfDistribution(projectId, opts, d)),
46
+ fpsHistogram: (projectId, opts = {}) => runClickhouseQuery(ch, buildFpsHistogram(projectId, opts, d)),
47
+ frameTimePercentiles: (projectId, opts = {}) => runClickhouseQuery(ch, buildFrameTimePercentiles(projectId, opts, d)),
48
+ jankRate: (projectId, opts = {}) => runClickhouseQuery(ch, buildJankRate(projectId, opts, d)),
49
+ perfByDevice: (projectId, opts = {}) => runClickhouseQuery(ch, buildPerfByDevice(projectId, opts, d)),
50
+ perfByScene: (projectId, opts = {}) => runClickhouseQuery(ch, buildPerfByScene(projectId, opts, d)),
51
+ resourcePercentiles: (projectId, opts = {}) => runClickhouseQuery(ch, buildResourcePercentiles(projectId, opts, d)),
52
+ stabilityCounts: (projectId, opts = {}) => runClickhouseQuery(ch, buildStabilityCounts(projectId, opts, d)),
53
+ sceneCoverage: (projectId, opts = {}) => runClickhouseQuery(ch, buildSceneCoverage(projectId, opts, d)),
54
+ cameraDistance: (projectId, opts = {}) => runClickhouseQuery(ch, buildCameraDistance(projectId, opts, d)),
55
+ navigationStats: (projectId, opts = {}) => runClickhouseQuery(ch, buildNavigationStats(projectId, opts, d)),
56
+ xrRotationRate: (projectId, opts = {}) => runClickhouseQuery(ch, buildXrRotationRate(projectId, opts, d)),
57
+ xrSourceUsage: (projectId, opts = {}) => runClickhouseQuery(ch, buildXrSourceUsage(projectId, opts, d)),
58
+ xrAbandonment: (projectId, opts = {}) => runClickhouseQuery(ch, buildXrAbandonment(projectId, opts, d)),
59
+ interactionsBySource: (projectId, opts = {}) => runClickhouseQuery(ch, buildInteractionsBySource(projectId, opts, d)),
60
+ scenes: (projectId, opts = {}) => runClickhouseQuery(ch, buildDistinctScenes(projectId, opts, d)),
61
+ timeseries: (projectId, opts = {}) => runClickhouseQuery(ch, buildTimeseries(projectId, opts, d)),
62
+ eventTypeCounts: (projectId, opts = {}) => runClickhouseQuery(ch, buildEventTypeCounts(projectId, opts, d)),
63
+ getSessionEvents: (projectId, sessionId) => chGetSessionEvents(ch, projectId, sessionId),
64
+ streamSessionEvents: (projectId, sessionId) => chStreamSessionEvents(ch, projectId, sessionId),
65
+ getSessionMeta: (projectId, sessionId) => chGetSessionMeta(ch, projectId, sessionId),
66
+ putSceneProxy: (projectId, proxy, label) => chUpsertSceneProxy(ch, projectId, proxy, label),
67
+ getSceneRepresentation: (projectId, sceneId) => chGetSceneRepresentation(ch, projectId, sceneId),
68
+ listSceneRepresentations: (projectId) => chListSceneRepresentations(ch, projectId),
69
+ async close() {
70
+ await ch.close();
71
+ },
72
+ };
73
+ }
74
+ //# sourceMappingURL=clickhouseStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clickhouseStore.js","sourceRoot":"","sources":["../src/clickhouseStore.ts"],"names":[],"mappings":"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"}
package/dist/serve.d.ts CHANGED
@@ -4,6 +4,9 @@ import type { CollectorStore } from "./store.js";
4
4
  * - `duckdb` (default) — the OSS single-file DuckDB store (events + metadata in
5
5
  * one file, full analytics, zero external services; ADR 0020). Path from
6
6
  * `DUCKDB_PATH`.
7
+ * - `clickhouse` — the optional single-tenant ClickHouse store for scale
8
+ * (concurrent, high-volume ingestion; ADR 0020). Connection from the
9
+ * `CLICKHOUSE_*` env vars. Requires a reachable ClickHouse server.
7
10
  * - `memory` — a dependency-free in-memory store for local dev / E2E tests
8
11
  * (seed its project/key via `COLLECTOR_MEMORY_PROJECT_ID` /
9
12
  * `COLLECTOR_MEMORY_API_KEY`).
@@ -1 +1 @@
1
- {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,cAAc,CAAC,CAazF;AAED;;;;GAIG;AACH,wBAAsB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAqB3C"}
1
+ {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,cAAc,CAAC,CAezF;AAED;;;;GAIG;AACH,wBAAsB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAqB3C"}
package/dist/serve.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { buildApp } from "./app.js";
2
2
  import { loadConfig } from "./config.js";
3
+ import { createClickhouseStore } from "./clickhouseStore.js";
3
4
  import { createDuckdbStore } from "./duckdbStore.js";
4
5
  import { createMemoryStore } from "./memoryStore.js";
5
6
  /**
@@ -7,6 +8,9 @@ import { createMemoryStore } from "./memoryStore.js";
7
8
  * - `duckdb` (default) — the OSS single-file DuckDB store (events + metadata in
8
9
  * one file, full analytics, zero external services; ADR 0020). Path from
9
10
  * `DUCKDB_PATH`.
11
+ * - `clickhouse` — the optional single-tenant ClickHouse store for scale
12
+ * (concurrent, high-volume ingestion; ADR 0020). Connection from the
13
+ * `CLICKHOUSE_*` env vars. Requires a reachable ClickHouse server.
10
14
  * - `memory` — a dependency-free in-memory store for local dev / E2E tests
11
15
  * (seed its project/key via `COLLECTOR_MEMORY_PROJECT_ID` /
12
16
  * `COLLECTOR_MEMORY_API_KEY`).
@@ -18,6 +22,8 @@ export function createStore(env = process.env) {
18
22
  projectId: env.COLLECTOR_MEMORY_PROJECT_ID ?? "demo",
19
23
  apiKey: env.COLLECTOR_MEMORY_API_KEY ?? "utk_memory_dev",
20
24
  }));
25
+ case "clickhouse":
26
+ return createClickhouseStore();
21
27
  case "duckdb":
22
28
  default:
23
29
  return createDuckdbStore();
package/dist/serve.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"serve.js","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrD;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC9D,QAAQ,GAAG,CAAC,eAAe,EAAE,CAAC;QAC5B,KAAK,QAAQ;YACX,OAAO,OAAO,CAAC,OAAO,CACpB,iBAAiB,CAAC;gBAChB,SAAS,EAAE,GAAG,CAAC,2BAA2B,IAAI,MAAM;gBACpD,MAAM,EAAE,GAAG,CAAC,wBAAwB,IAAI,gBAAgB;aACzD,CAAC,CACH,CAAC;QACJ,KAAK,QAAQ,CAAC;QACd;YACE,OAAO,iBAAiB,EAAE,CAAC;IAC/B,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAG,MAAM,WAAW,EAAE,CAAC;IAClC,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAE5D,IAAI,CAAC,MAAM,CAAC,0BAA0B,EAAE,CAAC;QACvC,GAAG,CAAC,GAAG,CAAC,IAAI,CACV,yFAAyF;YACvF,qFAAqF,CACxF,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,IAAI,EAAE;QACvB,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC;QACpB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC5B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAE7B,MAAM,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;AAC7D,CAAC"}
1
+ {"version":3,"file":"serve.js","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,WAAW,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC9D,QAAQ,GAAG,CAAC,eAAe,EAAE,CAAC;QAC5B,KAAK,QAAQ;YACX,OAAO,OAAO,CAAC,OAAO,CACpB,iBAAiB,CAAC;gBAChB,SAAS,EAAE,GAAG,CAAC,2BAA2B,IAAI,MAAM;gBACpD,MAAM,EAAE,GAAG,CAAC,wBAAwB,IAAI,gBAAgB;aACzD,CAAC,CACH,CAAC;QACJ,KAAK,YAAY;YACf,OAAO,qBAAqB,EAAE,CAAC;QACjC,KAAK,QAAQ,CAAC;QACd;YACE,OAAO,iBAAiB,EAAE,CAAC;IAC/B,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAG,MAAM,WAAW,EAAE,CAAC;IAClC,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAE5D,IAAI,CAAC,MAAM,CAAC,0BAA0B,EAAE,CAAC;QACvC,GAAG,CAAC,GAAG,CAAC,IAAI,CACV,yFAAyF;YACvF,qFAAqF,CACxF,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,IAAI,EAAE;QACvB,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC;QACpB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC5B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAE7B,MAAM,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;AAC7D,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uptimizr/collector-server",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Uptimizr ingestion + query API (Fastify). Self-hostable collector for the OSS data-collector.",
5
5
  "keywords": [
6
6
  "uptimizr",
@@ -44,8 +44,9 @@
44
44
  "fastify": "^5.8.5",
45
45
  "fastify-type-provider-zod": "^6.1.0",
46
46
  "zod": "^4.1.5",
47
- "@uptimizr/db": "0.1.0",
48
- "@uptimizr/schema": "0.1.0"
47
+ "@uptimizr/db-clickhouse": "0.2.0",
48
+ "@uptimizr/schema": "0.1.0",
49
+ "@uptimizr/db": "0.2.0"
49
50
  },
50
51
  "devDependencies": {
51
52
  "@types/node": "^22.19.21",