@uptimizr/db 1.0.1 → 2.0.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/AGENTS.md +103 -1
- package/README.md +100 -3
- package/dist/cli/createProject.js +23 -6
- package/dist/cli/createProject.js.map +1 -1
- package/dist/cli/seed.js +12 -4
- package/dist/cli/seed.js.map +1 -1
- package/dist/duckdb/audit.d.ts +13 -0
- package/dist/duckdb/audit.d.ts.map +1 -0
- package/dist/duckdb/audit.js +67 -0
- package/dist/duckdb/audit.js.map +1 -0
- package/dist/duckdb/client.d.ts.map +1 -1
- package/dist/duckdb/client.js +4 -0
- package/dist/duckdb/client.js.map +1 -1
- package/dist/duckdb/migrations.d.ts.map +1 -1
- package/dist/duckdb/migrations.js +97 -0
- package/dist/duckdb/migrations.js.map +1 -1
- package/dist/duckdb/projects.d.ts +9 -5
- package/dist/duckdb/projects.d.ts.map +1 -1
- package/dist/duckdb/projects.js +54 -24
- package/dist/duckdb/projects.js.map +1 -1
- package/dist/duckdb/queries.d.ts +7 -0
- package/dist/duckdb/queries.d.ts.map +1 -1
- package/dist/duckdb/queries.js +10 -1
- package/dist/duckdb/queries.js.map +1 -1
- package/dist/duckdb/sceneRegions.d.ts +24 -0
- package/dist/duckdb/sceneRegions.d.ts.map +1 -0
- package/dist/duckdb/sceneRegions.js +72 -0
- package/dist/duckdb/sceneRegions.js.map +1 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -1
- package/dist/index.js.map +1 -1
- package/dist/metadata.d.ts +195 -9
- package/dist/metadata.d.ts.map +1 -1
- package/dist/metadata.js +192 -0
- package/dist/metadata.js.map +1 -1
- package/dist/parity/compare.d.ts +22 -0
- package/dist/parity/compare.d.ts.map +1 -1
- package/dist/parity/compare.js +31 -0
- package/dist/parity/compare.js.map +1 -1
- package/dist/query/aggregations.d.ts +8 -0
- package/dist/query/aggregations.d.ts.map +1 -1
- package/dist/query/aggregations.js +78 -0
- package/dist/query/aggregations.js.map +1 -1
- package/dist/query/coerce.d.ts +94 -0
- package/dist/query/coerce.d.ts.map +1 -0
- package/dist/query/coerce.js +191 -0
- package/dist/query/coerce.js.map +1 -0
- package/dist/query/summary/cluster.d.ts +78 -0
- package/dist/query/summary/cluster.d.ts.map +1 -0
- package/dist/query/summary/cluster.js +200 -0
- package/dist/query/summary/cluster.js.map +1 -0
- package/dist/query/summary/columns.d.ts +66 -0
- package/dist/query/summary/columns.d.ts.map +1 -0
- package/dist/query/summary/columns.js +98 -0
- package/dist/query/summary/columns.js.map +1 -0
- package/dist/query/summary/format.d.ts +31 -0
- package/dist/query/summary/format.d.ts.map +1 -0
- package/dist/query/summary/format.js +119 -0
- package/dist/query/summary/format.js.map +1 -0
- package/dist/query/summary/index.d.ts +19 -0
- package/dist/query/summary/index.d.ts.map +1 -0
- package/dist/query/summary/index.js +16 -0
- package/dist/query/summary/index.js.map +1 -0
- package/dist/query/summary/reading.d.ts +26 -0
- package/dist/query/summary/reading.d.ts.map +1 -0
- package/dist/query/summary/reading.js +169 -0
- package/dist/query/summary/reading.js.map +1 -0
- package/dist/query/summary/schema.d.ts +217 -0
- package/dist/query/summary/schema.d.ts.map +1 -0
- package/dist/query/summary/schema.js +167 -0
- package/dist/query/summary/schema.js.map +1 -0
- package/dist/query/summary/stats.d.ts +33 -0
- package/dist/query/summary/stats.d.ts.map +1 -0
- package/dist/query/summary/stats.js +73 -0
- package/dist/query/summary/stats.js.map +1 -0
- package/dist/query/summary/summarize.d.ts +57 -0
- package/dist/query/summary/summarize.d.ts.map +1 -0
- package/dist/query/summary/summarize.js +424 -0
- package/dist/query/summary/summarize.js.map +1 -0
- package/dist/query/summary/types.d.ts +223 -0
- package/dist/query/summary/types.d.ts.map +1 -0
- package/dist/query/summary/types.js +8 -0
- package/dist/query/summary/types.js.map +1 -0
- package/dist/query/types.d.ts +13 -0
- package/dist/query/types.d.ts.map +1 -1
- package/llms.txt +7 -3
- package/package.json +10 -4
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two small statistics a summary needs: an interval on a share, and the
|
|
3
|
+
* slope of an ordered series. Both are pure, closed-form and deterministic —
|
|
4
|
+
* a summary must say the same thing every time it is asked.
|
|
5
|
+
*/
|
|
6
|
+
import type { ShareInterval, TrendDirection } from "./types.js";
|
|
7
|
+
/** z for a two-sided 95% normal interval. */
|
|
8
|
+
export declare const Z_95 = 1.959963984540054;
|
|
9
|
+
/**
|
|
10
|
+
* **Wilson score interval** on a proportion.
|
|
11
|
+
*
|
|
12
|
+
* Used instead of the textbook normal approximation because a summary's shares
|
|
13
|
+
* are routinely extreme: a mesh with 3 clicks out of 9,130 has `p̂ ≈ 0.0003`,
|
|
14
|
+
* where `p̂ ± z·√(p̂(1-p̂)/n)` happily reaches below zero. Wilson stays inside
|
|
15
|
+
* `[0, 1]` and behaves at small `n`, which is exactly the regime an agent is
|
|
16
|
+
* most likely to over-read.
|
|
17
|
+
*
|
|
18
|
+
* Returns `null` when the proportion is not defined (no trials, or a count
|
|
19
|
+
* outside `0..trials` — which happens whenever the "total" is not really the
|
|
20
|
+
* denominator of the row, e.g. a truncated top-N list).
|
|
21
|
+
*/
|
|
22
|
+
export declare function wilsonInterval(successes: number, trials: number, z?: number): ShareInterval | null;
|
|
23
|
+
/** The least-squares slope of `values` against their index; `null` under 2 points. */
|
|
24
|
+
export declare function leastSquaresSlope(values: readonly number[]): number | null;
|
|
25
|
+
/**
|
|
26
|
+
* Classify a slope as a direction.
|
|
27
|
+
*
|
|
28
|
+
* "Flat" is deliberately generous: the total drift across the series has to
|
|
29
|
+
* exceed 5% of the series' mean magnitude before it is called a trend, so
|
|
30
|
+
* ordinary sampling noise on a short range does not get reported as a move.
|
|
31
|
+
*/
|
|
32
|
+
export declare function trendOf(values: readonly number[], slope: number | null): TrendDirection;
|
|
33
|
+
//# sourceMappingURL=stats.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../../src/query/summary/stats.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEhE,6CAA6C;AAC7C,eAAO,MAAM,IAAI,oBAAoB,CAAC;AAEtC;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,CAAC,GAAE,MAAa,GACf,aAAa,GAAG,IAAI,CAStB;AAED,sFAAsF;AACtF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAe1E;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,CASvF"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two small statistics a summary needs: an interval on a share, and the
|
|
3
|
+
* slope of an ordered series. Both are pure, closed-form and deterministic —
|
|
4
|
+
* a summary must say the same thing every time it is asked.
|
|
5
|
+
*/
|
|
6
|
+
/** z for a two-sided 95% normal interval. */
|
|
7
|
+
export const Z_95 = 1.959963984540054;
|
|
8
|
+
/**
|
|
9
|
+
* **Wilson score interval** on a proportion.
|
|
10
|
+
*
|
|
11
|
+
* Used instead of the textbook normal approximation because a summary's shares
|
|
12
|
+
* are routinely extreme: a mesh with 3 clicks out of 9,130 has `p̂ ≈ 0.0003`,
|
|
13
|
+
* where `p̂ ± z·√(p̂(1-p̂)/n)` happily reaches below zero. Wilson stays inside
|
|
14
|
+
* `[0, 1]` and behaves at small `n`, which is exactly the regime an agent is
|
|
15
|
+
* most likely to over-read.
|
|
16
|
+
*
|
|
17
|
+
* Returns `null` when the proportion is not defined (no trials, or a count
|
|
18
|
+
* outside `0..trials` — which happens whenever the "total" is not really the
|
|
19
|
+
* denominator of the row, e.g. a truncated top-N list).
|
|
20
|
+
*/
|
|
21
|
+
export function wilsonInterval(successes, trials, z = Z_95) {
|
|
22
|
+
if (!Number.isFinite(successes) || !Number.isFinite(trials))
|
|
23
|
+
return null;
|
|
24
|
+
if (trials <= 0 || successes < 0 || successes > trials)
|
|
25
|
+
return null;
|
|
26
|
+
const p = successes / trials;
|
|
27
|
+
const z2 = z * z;
|
|
28
|
+
const denominator = 1 + z2 / trials;
|
|
29
|
+
const centre = (p + z2 / (2 * trials)) / denominator;
|
|
30
|
+
const margin = (z / denominator) * Math.sqrt((p * (1 - p)) / trials + z2 / (4 * trials * trials));
|
|
31
|
+
return { low: Math.max(0, centre - margin), high: Math.min(1, centre + margin) };
|
|
32
|
+
}
|
|
33
|
+
/** The least-squares slope of `values` against their index; `null` under 2 points. */
|
|
34
|
+
export function leastSquaresSlope(values) {
|
|
35
|
+
const n = values.length;
|
|
36
|
+
if (n < 2)
|
|
37
|
+
return null;
|
|
38
|
+
const meanX = (n - 1) / 2;
|
|
39
|
+
let meanY = 0;
|
|
40
|
+
for (const value of values)
|
|
41
|
+
meanY += value;
|
|
42
|
+
meanY /= n;
|
|
43
|
+
let covariance = 0;
|
|
44
|
+
let variance = 0;
|
|
45
|
+
for (let i = 0; i < n; i++) {
|
|
46
|
+
const dx = i - meanX;
|
|
47
|
+
covariance += dx * (values[i] - meanY);
|
|
48
|
+
variance += dx * dx;
|
|
49
|
+
}
|
|
50
|
+
return variance === 0 ? null : covariance / variance;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Classify a slope as a direction.
|
|
54
|
+
*
|
|
55
|
+
* "Flat" is deliberately generous: the total drift across the series has to
|
|
56
|
+
* exceed 5% of the series' mean magnitude before it is called a trend, so
|
|
57
|
+
* ordinary sampling noise on a short range does not get reported as a move.
|
|
58
|
+
*/
|
|
59
|
+
export function trendOf(values, slope) {
|
|
60
|
+
if (slope == null || values.length < 2)
|
|
61
|
+
return "flat";
|
|
62
|
+
let magnitude = 0;
|
|
63
|
+
for (const value of values)
|
|
64
|
+
magnitude += Math.abs(value);
|
|
65
|
+
magnitude /= values.length;
|
|
66
|
+
const drift = Math.abs(slope) * (values.length - 1);
|
|
67
|
+
if (magnitude === 0)
|
|
68
|
+
return drift === 0 ? "flat" : slope > 0 ? "up" : "down";
|
|
69
|
+
if (drift < 0.05 * magnitude)
|
|
70
|
+
return "flat";
|
|
71
|
+
return slope > 0 ? "up" : "down";
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=stats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../../src/query/summary/stats.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **Agent-shaped result envelopes** (ADR 0051 §2, design sketch §B.1).
|
|
3
|
+
*
|
|
4
|
+
* `summarizeRows(metric, rows, ctx)` and `tableResult(metric, rows, ctx)` are
|
|
5
|
+
* the two functions the collector calls to turn an aggregation's rows into the
|
|
6
|
+
* `table` and `summary` envelopes. They are pure, registry-driven and
|
|
7
|
+
* browser-safe: no store, no I/O, no `node:` import — everything they know about
|
|
8
|
+
* a metric comes from its {@link MetricDefinition}.
|
|
9
|
+
*
|
|
10
|
+
* ## Which summary a metric gets
|
|
11
|
+
*
|
|
12
|
+
* The `grain` decides, because the grain is what makes a row *mean* something:
|
|
13
|
+
*
|
|
14
|
+
* | grain | shape | what it reports |
|
|
15
|
+
* | -------------------------- | ----------- | -------------------------------------------- |
|
|
16
|
+
* | `bucket` | `series` | first/last/min/max, trend and slope |
|
|
17
|
+
* | `bin`, `voxel` | `clusters` | greedily merged hotspots (`cluster.ts`) |
|
|
18
|
+
* | `project` (or no `label`) | `record` | the single row, plus its `rateOf` rates |
|
|
19
|
+
* | everything else | `ranked` | top rows by the measure, with a `rest` bucket |
|
|
20
|
+
*
|
|
21
|
+
* A metric that cannot produce its grain's shape (a `bin` metric that declares
|
|
22
|
+
* too few `index` columns, say) falls back to `ranked`, so every metric always
|
|
23
|
+
* gets *a* summary.
|
|
24
|
+
*
|
|
25
|
+
* ## Shares are only claimed where they are true
|
|
26
|
+
*
|
|
27
|
+
* `total` and every `share` are reported only when the measure's unit is
|
|
28
|
+
* additive (`format.ts`). Summing FPS or a ratio across meshes produces a number
|
|
29
|
+
* that means nothing, and a share derived from it would be worse than no share
|
|
30
|
+
* at all — so those come back `null` and the `reading` says why.
|
|
31
|
+
*
|
|
32
|
+
* ## Bounded, always
|
|
33
|
+
*
|
|
34
|
+
* `top` and `clusters` are capped at the registry's `limits.maxSummaryRows`.
|
|
35
|
+
* That is the whole point of the envelope: a 500-bin heatmap must cost the same
|
|
36
|
+
* number of tokens as a 5-bin one.
|
|
37
|
+
*/
|
|
38
|
+
import { type MetricDefinition, type MetricId } from "@uptimizr/metrics";
|
|
39
|
+
import type { ResultSummary, SummaryContext, TableResult } from "./types.js";
|
|
40
|
+
/** A row as it leaves a store: a flat bag of scalars. */
|
|
41
|
+
export type ResultRow = Readonly<Record<string, unknown>>;
|
|
42
|
+
/**
|
|
43
|
+
* `format=table`: the same rows as `full`, wrapped in a `meta` envelope that
|
|
44
|
+
* says what they are, what was asked for, how much data is behind them and
|
|
45
|
+
* whether the row cap hid any.
|
|
46
|
+
*/
|
|
47
|
+
export declare function tableResult<Row extends ResultRow>(metric: MetricId | MetricDefinition, rows: readonly Row[], ctx?: SummaryContext): TableResult<Row> | null;
|
|
48
|
+
/**
|
|
49
|
+
* Summarise a metric's rows into the bounded `format=summary` envelope.
|
|
50
|
+
*
|
|
51
|
+
* `metric` may be a registry id or a resolved definition; an unknown id returns
|
|
52
|
+
* `null` so a caller can fall back to the raw rows rather than fail a request.
|
|
53
|
+
* `rows` must be the rows the store produced, already numerically coerced
|
|
54
|
+
* (every store runner does that at its edge — ADR 0051 §2).
|
|
55
|
+
*/
|
|
56
|
+
export declare function summarizeRows(metric: MetricId | MetricDefinition, rows: readonly ResultRow[], ctx?: SummaryContext): ResultSummary | null;
|
|
57
|
+
//# sourceMappingURL=summarize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summarize.d.ts","sourceRoot":"","sources":["../../../src/query/summary/summarize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,EAAa,KAAK,gBAAgB,EAAE,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAiBpF,OAAO,KAAK,EAUV,aAAa,EAKb,cAAc,EAEd,WAAW,EACZ,MAAM,YAAY,CAAC;AAEpB,yDAAyD;AACzD,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAmH1D;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,SAAS,SAAS,EAC/C,MAAM,EAAE,QAAQ,GAAG,gBAAgB,EACnC,IAAI,EAAE,SAAS,GAAG,EAAE,EACpB,GAAG,GAAE,cAAmB,GACvB,WAAW,CAAC,GAAG,CAAC,GAAG,IAAI,CAezB;AA+RD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,QAAQ,GAAG,gBAAgB,EACnC,IAAI,EAAE,SAAS,SAAS,EAAE,EAC1B,GAAG,GAAE,cAAmB,GACvB,aAAa,GAAG,IAAI,CAkBtB"}
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **Agent-shaped result envelopes** (ADR 0051 §2, design sketch §B.1).
|
|
3
|
+
*
|
|
4
|
+
* `summarizeRows(metric, rows, ctx)` and `tableResult(metric, rows, ctx)` are
|
|
5
|
+
* the two functions the collector calls to turn an aggregation's rows into the
|
|
6
|
+
* `table` and `summary` envelopes. They are pure, registry-driven and
|
|
7
|
+
* browser-safe: no store, no I/O, no `node:` import — everything they know about
|
|
8
|
+
* a metric comes from its {@link MetricDefinition}.
|
|
9
|
+
*
|
|
10
|
+
* ## Which summary a metric gets
|
|
11
|
+
*
|
|
12
|
+
* The `grain` decides, because the grain is what makes a row *mean* something:
|
|
13
|
+
*
|
|
14
|
+
* | grain | shape | what it reports |
|
|
15
|
+
* | -------------------------- | ----------- | -------------------------------------------- |
|
|
16
|
+
* | `bucket` | `series` | first/last/min/max, trend and slope |
|
|
17
|
+
* | `bin`, `voxel` | `clusters` | greedily merged hotspots (`cluster.ts`) |
|
|
18
|
+
* | `project` (or no `label`) | `record` | the single row, plus its `rateOf` rates |
|
|
19
|
+
* | everything else | `ranked` | top rows by the measure, with a `rest` bucket |
|
|
20
|
+
*
|
|
21
|
+
* A metric that cannot produce its grain's shape (a `bin` metric that declares
|
|
22
|
+
* too few `index` columns, say) falls back to `ranked`, so every metric always
|
|
23
|
+
* gets *a* summary.
|
|
24
|
+
*
|
|
25
|
+
* ## Shares are only claimed where they are true
|
|
26
|
+
*
|
|
27
|
+
* `total` and every `share` are reported only when the measure's unit is
|
|
28
|
+
* additive (`format.ts`). Summing FPS or a ratio across meshes produces a number
|
|
29
|
+
* that means nothing, and a share derived from it would be worse than no share
|
|
30
|
+
* at all — so those come back `null` and the `reading` says why.
|
|
31
|
+
*
|
|
32
|
+
* ## Bounded, always
|
|
33
|
+
*
|
|
34
|
+
* `top` and `clusters` are capped at the registry's `limits.maxSummaryRows`.
|
|
35
|
+
* That is the whole point of the envelope: a 500-bin heatmap must cost the same
|
|
36
|
+
* number of tokens as a 5-bin one.
|
|
37
|
+
*/
|
|
38
|
+
import { getMetric } from "@uptimizr/metrics";
|
|
39
|
+
import { clusterCells } from "./cluster.js";
|
|
40
|
+
import { axisColumn, columnsOf, gridColumns, labelColumn, measureColumn, numberAt, sampleSizeOf, sumColumn, weightColumn, } from "./columns.js";
|
|
41
|
+
import { isAdditiveUnit } from "./format.js";
|
|
42
|
+
import { readingFor } from "./reading.js";
|
|
43
|
+
import { leastSquaresSlope, trendOf, wilsonInterval, Z_95 } from "./stats.js";
|
|
44
|
+
/**
|
|
45
|
+
* Filters a summarised row can be narrowed by. Restricted to the filters the
|
|
46
|
+
* metric itself accepts, so every hint is directly actionable — a hint an
|
|
47
|
+
* endpoint would silently ignore is worse than no hint.
|
|
48
|
+
*/
|
|
49
|
+
const DRILL_FILTERS = ["scene", "session", "mesh", "source"];
|
|
50
|
+
/** Resolve an id or a definition to a definition. */
|
|
51
|
+
function resolve(metric) {
|
|
52
|
+
return typeof metric === "string" ? getMetric(metric) : metric;
|
|
53
|
+
}
|
|
54
|
+
/** The requested window, normalised to `null` where the caller omitted it. */
|
|
55
|
+
function rangeOf(ctx) {
|
|
56
|
+
return { since: ctx.range?.since ?? null, until: ctx.range?.until ?? null };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Applied filters with `format` and anything unset stripped. Iterates the
|
|
60
|
+
* metric's **declared** filter and path-parameter ids (a closed registry
|
|
61
|
+
* allowlist) rather than the keys of the request object, so an unexpected key
|
|
62
|
+
* can never become a property of the envelope.
|
|
63
|
+
*/
|
|
64
|
+
function filtersOf(metric, ctx) {
|
|
65
|
+
const out = {};
|
|
66
|
+
const source = ctx.filters ?? {};
|
|
67
|
+
const declared = [...metric.filters, ...(metric.endpoint?.pathParams ?? [])];
|
|
68
|
+
for (const id of declared) {
|
|
69
|
+
if (id === "format")
|
|
70
|
+
continue;
|
|
71
|
+
const value = Object.hasOwn(source, id) ? source[id] : undefined;
|
|
72
|
+
if (value === undefined || value === null)
|
|
73
|
+
continue;
|
|
74
|
+
out[id] = value;
|
|
75
|
+
}
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
function limitsOf(metric) {
|
|
79
|
+
return { maxRows: metric.limits.maxRows, maxSummaryRows: metric.limits.maxSummaryRows };
|
|
80
|
+
}
|
|
81
|
+
/** Whether the row cap was reached, so more rows may exist behind it. */
|
|
82
|
+
function isTruncated(metric, rows, ctx) {
|
|
83
|
+
const cap = ctx.limit ?? metric.limits.maxRows;
|
|
84
|
+
return Number.isFinite(cap) && rows.length >= cap;
|
|
85
|
+
}
|
|
86
|
+
/** What `total` counts, and whether it may be summed at all. */
|
|
87
|
+
function measureOf(column) {
|
|
88
|
+
if (column == null)
|
|
89
|
+
return null;
|
|
90
|
+
const [name, semantics] = column;
|
|
91
|
+
return { column: name, unit: semantics.unit ?? null, additive: isAdditiveUnit(semantics.unit) };
|
|
92
|
+
}
|
|
93
|
+
/** Registry caveats plus the ones that are only true of *this* result. */
|
|
94
|
+
function caveatsFor(metric, rows, ctx, extra = []) {
|
|
95
|
+
const caveats = [...metric.caveats, ...extra, ...(ctx.caveats ?? [])];
|
|
96
|
+
if (rows.length === 0) {
|
|
97
|
+
caveats.push("No rows matched the selected range and filters — read this as 'no data', not as zero.");
|
|
98
|
+
}
|
|
99
|
+
if (isTruncated(metric, rows, ctx)) {
|
|
100
|
+
caveats.push(`Rows were capped at ${ctx.limit ?? metric.limits.maxRows}; totals and shares below describe ` +
|
|
101
|
+
"the returned rows only, not the whole range.");
|
|
102
|
+
}
|
|
103
|
+
return caveats;
|
|
104
|
+
}
|
|
105
|
+
/** Filters that would narrow a subsequent query to this row. */
|
|
106
|
+
function drillFor(metric, row) {
|
|
107
|
+
const hints = {};
|
|
108
|
+
for (const filter of DRILL_FILTERS) {
|
|
109
|
+
if (!metric.filters.includes(filter))
|
|
110
|
+
continue;
|
|
111
|
+
const column = [filter, `${filter}_id`].find((candidate) => candidate in metric.columns && candidate in row);
|
|
112
|
+
if (column == null)
|
|
113
|
+
continue;
|
|
114
|
+
const value = row[column];
|
|
115
|
+
if (typeof value === "string" && value.length > 0)
|
|
116
|
+
hints[filter] = value;
|
|
117
|
+
}
|
|
118
|
+
return Object.keys(hints).length > 0 ? hints : undefined;
|
|
119
|
+
}
|
|
120
|
+
/** The Wilson note, present only when the shares really are proportions. */
|
|
121
|
+
function confidenceFor(measure, total) {
|
|
122
|
+
if (measure == null || !measure.additive || total == null || total <= 0)
|
|
123
|
+
return undefined;
|
|
124
|
+
if (measure.unit !== "count" && measure.unit !== "sessions")
|
|
125
|
+
return undefined;
|
|
126
|
+
const noun = measure.unit === "sessions" ? "sessions" : "events";
|
|
127
|
+
return {
|
|
128
|
+
kind: "wilson",
|
|
129
|
+
level: 0.95,
|
|
130
|
+
note: `Shares are proportions of ${total} ${noun}; each \`shareInterval\` is a 95% Wilson score ` +
|
|
131
|
+
"interval, which stays inside 0..1 at the small counts a long tail produces.",
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
// --- table ----------------------------------------------------------------
|
|
135
|
+
/**
|
|
136
|
+
* `format=table`: the same rows as `full`, wrapped in a `meta` envelope that
|
|
137
|
+
* says what they are, what was asked for, how much data is behind them and
|
|
138
|
+
* whether the row cap hid any.
|
|
139
|
+
*/
|
|
140
|
+
export function tableResult(metric, rows, ctx = {}) {
|
|
141
|
+
const definition = resolve(metric);
|
|
142
|
+
if (definition == null)
|
|
143
|
+
return null;
|
|
144
|
+
return {
|
|
145
|
+
meta: {
|
|
146
|
+
metric: definition.id,
|
|
147
|
+
range: rangeOf(ctx),
|
|
148
|
+
filters: filtersOf(definition, ctx),
|
|
149
|
+
sampleSize: sampleSizeOf(definition, rows),
|
|
150
|
+
rows: rows.length,
|
|
151
|
+
truncated: isTruncated(definition, rows, ctx),
|
|
152
|
+
limits: limitsOf(definition),
|
|
153
|
+
},
|
|
154
|
+
rows,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
// --- summary --------------------------------------------------------------
|
|
158
|
+
/** Fields every summary shares, computed once. */
|
|
159
|
+
function baseOf(metric, rows, ctx, measure, total, extraCaveats = []) {
|
|
160
|
+
const confidence = confidenceFor(measure, total);
|
|
161
|
+
return {
|
|
162
|
+
metric: metric.id,
|
|
163
|
+
range: rangeOf(ctx),
|
|
164
|
+
filters: filtersOf(metric, ctx),
|
|
165
|
+
sampleSize: sampleSizeOf(metric, rows),
|
|
166
|
+
total,
|
|
167
|
+
measure,
|
|
168
|
+
...(confidence != null ? { confidence } : {}),
|
|
169
|
+
caveats: caveatsFor(metric, rows, ctx, extraCaveats),
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
function rankedSummary(metric, rows, ctx, cap) {
|
|
173
|
+
const measureCol = measureColumn(metric);
|
|
174
|
+
const labelCol = labelColumn(metric);
|
|
175
|
+
const measure = measureOf(measureCol);
|
|
176
|
+
const total = measure?.additive === true ? sumColumn(rows, measureCol?.[0]) : null;
|
|
177
|
+
// Rank by the measure, highest first; ties fall back to the label so the order
|
|
178
|
+
// is a function of the row *set* rather than of what the store happened to emit.
|
|
179
|
+
const ordered = [...rows].sort((a, b) => {
|
|
180
|
+
const left = measureCol == null ? null : numberAt(a, measureCol[0]);
|
|
181
|
+
const right = measureCol == null ? null : numberAt(b, measureCol[0]);
|
|
182
|
+
if (left !== right) {
|
|
183
|
+
if (left == null)
|
|
184
|
+
return 1;
|
|
185
|
+
if (right == null)
|
|
186
|
+
return -1;
|
|
187
|
+
return right - left;
|
|
188
|
+
}
|
|
189
|
+
const leftLabel = labelCol == null ? "" : String(a[labelCol[0]] ?? "");
|
|
190
|
+
const rightLabel = labelCol == null ? "" : String(b[labelCol[0]] ?? "");
|
|
191
|
+
return leftLabel < rightLabel ? -1 : leftLabel > rightLabel ? 1 : 0;
|
|
192
|
+
});
|
|
193
|
+
const listed = ordered.slice(0, cap);
|
|
194
|
+
// A Wilson interval is only meaningful where the share really is a proportion
|
|
195
|
+
// of a count — the same condition that decides whether `confidence` is present.
|
|
196
|
+
const proportional = confidenceFor(measure, total) != null;
|
|
197
|
+
const top = listed.map((row) => {
|
|
198
|
+
const value = measureCol == null ? null : numberAt(row, measureCol[0]);
|
|
199
|
+
const share = total != null && total > 0 && value != null ? value / total : null;
|
|
200
|
+
const interval = proportional && value != null && total != null ? wilsonInterval(value, total, Z_95) : null;
|
|
201
|
+
const drill = drillFor(metric, row);
|
|
202
|
+
return {
|
|
203
|
+
label: labelCol == null ? "" : String(row[labelCol[0]] ?? ""),
|
|
204
|
+
value,
|
|
205
|
+
share,
|
|
206
|
+
...(interval != null ? { shareInterval: interval } : {}),
|
|
207
|
+
...(drill != null ? { drill } : {}),
|
|
208
|
+
};
|
|
209
|
+
});
|
|
210
|
+
const listedValue = measureCol == null ? null : sumColumn(listed, measureCol[0]);
|
|
211
|
+
const restValue = total != null && listedValue != null ? total - listedValue : null;
|
|
212
|
+
return {
|
|
213
|
+
...baseOf(metric, rows, ctx, measure, total),
|
|
214
|
+
kind: "ranked",
|
|
215
|
+
top,
|
|
216
|
+
rest: {
|
|
217
|
+
rows: Math.max(0, rows.length - listed.length),
|
|
218
|
+
value: restValue,
|
|
219
|
+
share: total != null && total > 0 && restValue != null ? restValue / total : null,
|
|
220
|
+
},
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
function seriesSummary(metric, rows, ctx) {
|
|
224
|
+
const axis = axisColumn(metric);
|
|
225
|
+
const measureCol = measureColumn(metric);
|
|
226
|
+
if (axis == null || measureCol == null)
|
|
227
|
+
return null;
|
|
228
|
+
const measure = measureOf(measureCol);
|
|
229
|
+
// Collapse every row sharing a bucket. Additive measures sum (`mesh_trend` is
|
|
230
|
+
// one row per mesh *and* bucket); non-additive ones average, because adding
|
|
231
|
+
// two days' median FPS together would be meaningless.
|
|
232
|
+
const buckets = new Map();
|
|
233
|
+
for (const row of rows) {
|
|
234
|
+
const key = row[axis[0]];
|
|
235
|
+
const value = numberAt(row, measureCol[0]);
|
|
236
|
+
if (value == null)
|
|
237
|
+
continue;
|
|
238
|
+
const id = typeof key === "number" ? `n:${key}` : `s:${String(key ?? "")}`;
|
|
239
|
+
const bucket = buckets.get(id);
|
|
240
|
+
if (bucket) {
|
|
241
|
+
bucket.sum += value;
|
|
242
|
+
bucket.count += 1;
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
buckets.set(id, { key, sum: value, count: 1 });
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
const points = [...buckets.values()]
|
|
249
|
+
.map((bucket) => ({
|
|
250
|
+
key: bucket.key,
|
|
251
|
+
value: measure?.additive === true ? bucket.sum : bucket.sum / bucket.count,
|
|
252
|
+
}))
|
|
253
|
+
.sort((a, b) => {
|
|
254
|
+
if (typeof a.key === "number" && typeof b.key === "number")
|
|
255
|
+
return a.key - b.key;
|
|
256
|
+
const left = String(a.key ?? "");
|
|
257
|
+
const right = String(b.key ?? "");
|
|
258
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
259
|
+
});
|
|
260
|
+
const values = points.map((point) => point.value);
|
|
261
|
+
const slope = leastSquaresSlope(values);
|
|
262
|
+
const lowest = points.reduce((best, point) => (best == null || point.value < best.value ? point : best), undefined);
|
|
263
|
+
const highest = points.reduce((best, point) => (best == null || point.value > best.value ? point : best), undefined);
|
|
264
|
+
const first = points[0];
|
|
265
|
+
const last = points[points.length - 1];
|
|
266
|
+
const total = measure?.additive === true ? sumColumn(rows, measureCol[0]) : null;
|
|
267
|
+
const labelOf = (point) => point == null ? null : point.key == null ? null : String(point.key);
|
|
268
|
+
return {
|
|
269
|
+
...baseOf(metric, rows, ctx, measure, total),
|
|
270
|
+
kind: "series",
|
|
271
|
+
series: {
|
|
272
|
+
axis: axis[0],
|
|
273
|
+
points: points.length,
|
|
274
|
+
first: first?.value ?? null,
|
|
275
|
+
last: last?.value ?? null,
|
|
276
|
+
min: lowest?.value ?? null,
|
|
277
|
+
max: highest?.value ?? null,
|
|
278
|
+
firstLabel: labelOf(first),
|
|
279
|
+
lastLabel: labelOf(last),
|
|
280
|
+
minLabel: labelOf(lowest),
|
|
281
|
+
maxLabel: labelOf(highest),
|
|
282
|
+
trend: trendOf(values, slope),
|
|
283
|
+
slope,
|
|
284
|
+
},
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
function clusterSummary(metric, rows, ctx, cap) {
|
|
288
|
+
const axes = gridColumns(metric, metric.grain === "voxel" ? 3 : 2);
|
|
289
|
+
const weightCol = weightColumn(metric);
|
|
290
|
+
if (axes == null || weightCol == null)
|
|
291
|
+
return null;
|
|
292
|
+
const measure = measureOf(weightCol);
|
|
293
|
+
if (measure == null || !measure.additive)
|
|
294
|
+
return null;
|
|
295
|
+
const cells = [];
|
|
296
|
+
for (const row of rows) {
|
|
297
|
+
const coords = axes.map(([name]) => numberAt(row, name));
|
|
298
|
+
if (coords.some((coordinate) => coordinate == null))
|
|
299
|
+
continue;
|
|
300
|
+
const weight = numberAt(row, weightCol[0]);
|
|
301
|
+
if (weight == null)
|
|
302
|
+
continue;
|
|
303
|
+
cells.push({ coords: coords, weight });
|
|
304
|
+
}
|
|
305
|
+
const result = clusterCells(cells, {
|
|
306
|
+
densityThreshold: ctx.densityThreshold,
|
|
307
|
+
maxClusters: cap,
|
|
308
|
+
});
|
|
309
|
+
const total = result.totalWeight > 0 ? result.totalWeight : null;
|
|
310
|
+
// A cluster's world-space box, when the collector told us the effective cell
|
|
311
|
+
// size and the metric accepts a `region` drill-down (ADR 0040 §4).
|
|
312
|
+
const canDrillRegion = ctx.cellSize != null &&
|
|
313
|
+
ctx.cellSize > 0 &&
|
|
314
|
+
axes.length === 3 &&
|
|
315
|
+
metric.filters.includes("region");
|
|
316
|
+
const clusters = result.clusters.map((cluster) => {
|
|
317
|
+
if (!canDrillRegion)
|
|
318
|
+
return cluster;
|
|
319
|
+
const size = ctx.cellSize;
|
|
320
|
+
const box = [
|
|
321
|
+
...cluster.extent.min.map((value) => value * size),
|
|
322
|
+
...cluster.extent.max.map((value) => (value + 1) * size),
|
|
323
|
+
];
|
|
324
|
+
return { ...cluster, drill: { region: box.join(",") } };
|
|
325
|
+
});
|
|
326
|
+
const extraCaveats = result.occupiedCells > 0
|
|
327
|
+
? [
|
|
328
|
+
`Hotspots are merged from cells at or above a density threshold of ` +
|
|
329
|
+
`${result.densityThreshold} (the mean weight per occupied cell); looser cells are ` +
|
|
330
|
+
"reported in `rest` rather than clustered.",
|
|
331
|
+
"Cluster coordinates are grid indices, not world coordinates — multiply by the " +
|
|
332
|
+
"effective `cellSize` to place them (ADR 0040 §1). Spatial labelling (nearest mesh, " +
|
|
333
|
+
"named region) is not part of this envelope.",
|
|
334
|
+
]
|
|
335
|
+
: [];
|
|
336
|
+
return {
|
|
337
|
+
...baseOf(metric, rows, ctx, measure, total, extraCaveats),
|
|
338
|
+
kind: "clusters",
|
|
339
|
+
axes: axes.map(([name]) => name),
|
|
340
|
+
occupiedCells: result.occupiedCells,
|
|
341
|
+
densityThreshold: result.densityThreshold,
|
|
342
|
+
clusters,
|
|
343
|
+
rest: {
|
|
344
|
+
clusters: result.rest.clusters,
|
|
345
|
+
cells: result.rest.cells,
|
|
346
|
+
weight: total == null ? null : result.rest.weight,
|
|
347
|
+
share: total != null && total > 0 ? result.rest.weight / total : null,
|
|
348
|
+
},
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
function recordSummary(metric, rows, ctx) {
|
|
352
|
+
const row = rows[0];
|
|
353
|
+
const measureCol = measureColumn(metric);
|
|
354
|
+
const measure = measureOf(measureCol);
|
|
355
|
+
const record = {};
|
|
356
|
+
if (row != null) {
|
|
357
|
+
for (const [name] of columnsOf(metric)) {
|
|
358
|
+
if (!(name in row))
|
|
359
|
+
continue;
|
|
360
|
+
const value = row[name];
|
|
361
|
+
record[name] =
|
|
362
|
+
value == null
|
|
363
|
+
? null
|
|
364
|
+
: typeof value === "number" || typeof value === "string" || typeof value === "boolean"
|
|
365
|
+
? value
|
|
366
|
+
: null;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
// Every column that declares itself a rate of another one, resolved against
|
|
370
|
+
// the row — the numbers a reader would otherwise have to divide by hand.
|
|
371
|
+
const rates = {};
|
|
372
|
+
for (const [name, semantics] of columnsOf(metric)) {
|
|
373
|
+
if (semantics.rateOf == null || row == null)
|
|
374
|
+
continue;
|
|
375
|
+
const numerator = numberAt(row, name);
|
|
376
|
+
const denominator = numberAt(row, semantics.rateOf);
|
|
377
|
+
rates[name] = {
|
|
378
|
+
value: numerator != null && denominator != null && denominator > 0
|
|
379
|
+
? numerator / denominator
|
|
380
|
+
: null,
|
|
381
|
+
numerator: name,
|
|
382
|
+
denominator: semantics.rateOf,
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
const total = row == null || measureCol == null ? null : numberAt(row, measureCol[0]);
|
|
386
|
+
const extra = rows.length > 1
|
|
387
|
+
? [`Only the first of ${rows.length} rows is summarised; read \`format=table\` for the rest.`]
|
|
388
|
+
: [];
|
|
389
|
+
return {
|
|
390
|
+
...baseOf(metric, rows, ctx, measure, total, extra),
|
|
391
|
+
kind: "record",
|
|
392
|
+
record,
|
|
393
|
+
rates,
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Summarise a metric's rows into the bounded `format=summary` envelope.
|
|
398
|
+
*
|
|
399
|
+
* `metric` may be a registry id or a resolved definition; an unknown id returns
|
|
400
|
+
* `null` so a caller can fall back to the raw rows rather than fail a request.
|
|
401
|
+
* `rows` must be the rows the store produced, already numerically coerced
|
|
402
|
+
* (every store runner does that at its edge — ADR 0051 §2).
|
|
403
|
+
*/
|
|
404
|
+
export function summarizeRows(metric, rows, ctx = {}) {
|
|
405
|
+
const definition = resolve(metric);
|
|
406
|
+
if (definition == null)
|
|
407
|
+
return null;
|
|
408
|
+
const cap = Math.max(0, ctx.maxRows ?? definition.limits.maxSummaryRows);
|
|
409
|
+
let summary = null;
|
|
410
|
+
if (definition.grain === "bucket") {
|
|
411
|
+
summary = seriesSummary(definition, rows, ctx);
|
|
412
|
+
}
|
|
413
|
+
else if (definition.grain === "bin" || definition.grain === "voxel") {
|
|
414
|
+
summary = clusterSummary(definition, rows, ctx, cap);
|
|
415
|
+
}
|
|
416
|
+
else if (definition.grain === "project" || labelColumn(definition) == null) {
|
|
417
|
+
summary = recordSummary(definition, rows, ctx);
|
|
418
|
+
}
|
|
419
|
+
// Leaderboards, and the fallback for any metric that cannot produce its
|
|
420
|
+
// grain's shape (too few `index` columns, no axis, a non-additive weight).
|
|
421
|
+
summary ??= rankedSummary(definition, rows, ctx, cap);
|
|
422
|
+
return { ...summary, reading: readingFor(definition, summary) };
|
|
423
|
+
}
|
|
424
|
+
//# sourceMappingURL=summarize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summarize.js","sourceRoot":"","sources":["../../../src/query/summary/summarize.ts"],"names":[],"mappings":"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"}
|