@adriangalilea/utils 4.1.1 → 6.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/README.md +44 -22
- package/dist/metrics/d1-rest.d.ts +15 -0
- package/dist/metrics/d1-rest.d.ts.map +1 -0
- package/dist/metrics/d1-rest.js +26 -0
- package/dist/metrics/d1-rest.js.map +1 -0
- package/dist/metrics/d1.d.ts +16 -0
- package/dist/metrics/d1.d.ts.map +1 -0
- package/dist/metrics/d1.js +11 -0
- package/dist/metrics/d1.js.map +1 -0
- package/dist/metrics/index.d.ts +19 -11
- package/dist/metrics/index.d.ts.map +1 -1
- package/dist/metrics/index.js +18 -9
- package/dist/metrics/index.js.map +1 -1
- package/dist/metrics/libsql.d.ts +11 -0
- package/dist/metrics/libsql.d.ts.map +1 -0
- package/dist/metrics/libsql.js +8 -0
- package/dist/metrics/libsql.js.map +1 -0
- package/dist/metrics/report.d.ts +38 -0
- package/dist/metrics/report.d.ts.map +1 -1
- package/dist/metrics/report.js.map +1 -1
- package/dist/metrics/sqlite.d.ts +44 -17
- package/dist/metrics/sqlite.d.ts.map +1 -1
- package/dist/metrics/sqlite.js +168 -42
- package/dist/metrics/sqlite.js.map +1 -1
- package/package.json +13 -1
package/README.md
CHANGED
|
@@ -7,21 +7,46 @@ TypeScript utilities - logger, currency, offensive programming, file operations,
|
|
|
7
7
|
```ts
|
|
8
8
|
import { createClient } from "@libsql/client"
|
|
9
9
|
import { defineMetrics } from "@adriangalilea/utils/metrics"
|
|
10
|
-
import {
|
|
10
|
+
import { libsqlDriver } from "@adriangalilea/utils/metrics/libsql"
|
|
11
|
+
import { metricsStore } from "@adriangalilea/utils/metrics/sqlite"
|
|
11
12
|
|
|
12
|
-
const
|
|
13
|
+
const driver = libsqlDriver(createClient({ url: process.env.METRICS_DATABASE_URL!, authToken: process.env.METRICS_AUTH_TOKEN }))
|
|
13
14
|
const metrics = defineMetrics({
|
|
14
15
|
installCopy: { kind: "counter", label: "install command copies", dimensions: { component: ["chat", "glass"] } },
|
|
15
|
-
}, {
|
|
16
|
+
}, { store: metricsStore(driver, "my-project") })
|
|
16
17
|
|
|
17
18
|
await metrics.installCopy.bump({ dimensions: { component: "chat" } })
|
|
18
19
|
```
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
the
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
One SQLite dialect, many stores. `metrics/sqlite` holds the schema, the store and
|
|
22
|
+
the readers over a `MetricsDriver`: two verbs, `query(statement)` for rows and
|
|
23
|
+
`transact(statements)` for an all-or-nothing write batch. `metrics/libsql` wraps a
|
|
24
|
+
Turso / libSQL client, `metrics/d1` wraps a Cloudflare D1 binding (`d1Driver(env.DB)`),
|
|
25
|
+
each with the driver's native calls and structural types, so no database client is
|
|
26
|
+
bundled. Any other SQLite driver implements the two verbs in a few lines (the test
|
|
27
|
+
does it over `node:sqlite`). Readers need only `query`, a `MetricsReader`:
|
|
28
|
+
`metrics/d1-rest` reads a D1 database over Cloudflare's REST API from a process with
|
|
29
|
+
no binding (`d1RestReader({ accountId, databaseId, token })`). A store that does not
|
|
30
|
+
speak SQLite implements the `MetricsStore` contract, `declare(schema)` and
|
|
31
|
+
`write(measurement)`, and its own readers returning the `metrics/report` types.
|
|
32
|
+
|
|
33
|
+
**The store describes itself.** `declare` runs once per process before the first
|
|
34
|
+
sample and carries the whole schema: kinds, labels, help, units, per-user flags and
|
|
35
|
+
overlaps. Every later sample is one small transaction. A reader therefore never needs
|
|
36
|
+
the declaring code: `readSchema(reader, project)` returns what a project declared,
|
|
37
|
+
and `readReport(reader, { project, days, includeToday? })` returns everything a panel
|
|
38
|
+
renders in one call, `{ project, window, schema, daily, audience }`. A changed kind or
|
|
39
|
+
unit is refused at declaration and every sample of that process fails loudly; a store
|
|
40
|
+
that was briefly away is asked again by the next sample.
|
|
41
|
+
|
|
42
|
+
Provision the exported `METRICS_SCHEMA` once before collecting. `readMetrics(reader,
|
|
43
|
+
{ from, to, project? })` returns daily rows with labels and dimensions, using inclusive
|
|
44
|
+
UTC dates. `readAudience(reader, { from, to, project }, schema)` answers who did it
|
|
45
|
+
from the opt-in per-user rows: one row per declared per-user metric (zeros when nobody
|
|
46
|
+
touched it), with distinct actors, actors with more than one sample on a single day,
|
|
47
|
+
actors seen on more than one day, then each declared overlap as `fromUsers` and
|
|
48
|
+
`bothUsers`. Readers propagate database errors rather than presenting missing data
|
|
49
|
+
as zero.
|
|
25
50
|
`summarizeMetrics(rows)` from `metrics/report` produces one generic report shape;
|
|
26
51
|
`renderMetrics(rows, { daily? })` from `metrics/cli` renders it with the existing
|
|
27
52
|
ANSI-aware `cli.table` helpers. Both discover every recorded metric from its
|
|
@@ -37,10 +62,7 @@ disappearing series, count changes and weighted timing-average changes. Percent
|
|
|
37
62
|
change is null without a nonzero baseline; missing timing samples stay null.
|
|
38
63
|
Changing a metric's kind or unit across the inputs is rejected. Missing observations
|
|
39
64
|
are not proof that collection was running: deltas compare recorded data only.
|
|
40
|
-
|
|
41
|
-
adding observations. Use a new key for a new meaning; labels and help can be edited.
|
|
42
|
-
The SQL adapter accepts a libSQL-compatible client; D1 or another store can implement
|
|
43
|
-
the injected `write(measurement)` contract instead. No database client is bundled.
|
|
65
|
+
Use a new key for a new meaning; labels, help and the per-user flag can be edited.
|
|
44
66
|
|
|
45
67
|
Measurements validate finite nonnegative samples, positive integer counts, and
|
|
46
68
|
declared dimension values. Calls resolve even when validation or storage fails;
|
|
@@ -55,16 +77,16 @@ Enable it only with a deletion and retention policy; no identity is inferred.
|
|
|
55
77
|
`overlaps: [["a", "b"]]` declares unordered audience overlap, not an ordered funnel.
|
|
56
78
|
Daily totals support counts and averages, not percentile latency or event ordering.
|
|
57
79
|
|
|
58
|
-
**
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
`
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
80
|
+
**6.0 migration:** `defineMetrics` takes `store: metricsStore(driver, project)` instead
|
|
81
|
+
of `write: metricsWriter(...)`; a custom store implements `declare` and `write`, and
|
|
82
|
+
`Measurement` no longer carries `spec`. Existing tables gain a column and a table:
|
|
83
|
+
`ALTER TABLE metric_definition ADD COLUMN per_user INTEGER NOT NULL DEFAULT 0` and the
|
|
84
|
+
`metric_overlap` table from `METRICS_SCHEMA`; the first sample after the deploy
|
|
85
|
+
declares the real flags, labels and overlaps. `readAudience` takes the schema
|
|
86
|
+
(`readSchema(reader, project)`) instead of an overlap list and returns a row per
|
|
87
|
+
declared per-user key. `readReport` replaces hand-rolled window + rows + audience
|
|
88
|
+
composition. Metric keys and dimensions are storage identifiers: introduce a new key
|
|
89
|
+
when changing meaning rather than relabelling history.
|
|
68
90
|
|
|
69
91
|
## Installation
|
|
70
92
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { MetricsReader } from "./sqlite.js";
|
|
2
|
+
export interface D1RestOptions {
|
|
3
|
+
accountId: string;
|
|
4
|
+
databaseId: string;
|
|
5
|
+
/** A Cloudflare API token with D1 read on the database. */
|
|
6
|
+
token: string;
|
|
7
|
+
fetch?: typeof fetch;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A D1 database read over Cloudflare's REST API, for a process that has no binding
|
|
11
|
+
* (a Next server, a CLI). A reader only: one REST call cannot transact, so writes stay
|
|
12
|
+
* with `metrics/d1` inside the Worker that owns the binding.
|
|
13
|
+
*/
|
|
14
|
+
export declare function d1RestReader(options: D1RestOptions): MetricsReader;
|
|
15
|
+
//# sourceMappingURL=d1-rest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"d1-rest.d.ts","sourceRoot":"","sources":["../../src/metrics/d1-rest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,WAAW,aAAa;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa,CAyBlE"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A D1 database read over Cloudflare's REST API, for a process that has no binding
|
|
3
|
+
* (a Next server, a CLI). A reader only: one REST call cannot transact, so writes stay
|
|
4
|
+
* with `metrics/d1` inside the Worker that owns the binding.
|
|
5
|
+
*/
|
|
6
|
+
export function d1RestReader(options) {
|
|
7
|
+
const url = `https://api.cloudflare.com/client/v4/accounts/${options.accountId}/d1/database/${options.databaseId}/query`;
|
|
8
|
+
const call = options.fetch ?? fetch;
|
|
9
|
+
return {
|
|
10
|
+
async query({ sql, args }) {
|
|
11
|
+
const response = await call(url, {
|
|
12
|
+
method: "POST",
|
|
13
|
+
headers: {
|
|
14
|
+
authorization: `Bearer ${options.token}`,
|
|
15
|
+
"content-type": "application/json",
|
|
16
|
+
},
|
|
17
|
+
body: JSON.stringify({ sql, params: args }),
|
|
18
|
+
});
|
|
19
|
+
const data = (await response.json());
|
|
20
|
+
if (!response.ok || !data.success)
|
|
21
|
+
throw new Error(`metrics: d1 ${data.errors?.[0]?.message ?? response.status}`);
|
|
22
|
+
return data.result?.[0]?.results ?? [];
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=d1-rest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"d1-rest.js","sourceRoot":"","sources":["../../src/metrics/d1-rest.ts"],"names":[],"mappings":"AAUA;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,OAAsB;IAClD,MAAM,GAAG,GAAG,iDAAiD,OAAO,CAAC,SAAS,gBAAgB,OAAO,CAAC,UAAU,QAAQ,CAAC;IACzH,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC;IACpC,OAAO;QACN,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE;YACxB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,EAAE;gBAChC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACR,aAAa,EAAE,UAAU,OAAO,CAAC,KAAK,EAAE;oBACxC,cAAc,EAAE,kBAAkB;iBAClC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;aAC3C,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAIlC,CAAC;YACF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO;gBAChC,MAAM,IAAI,KAAK,CACd,eAAe,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,QAAQ,CAAC,MAAM,EAAE,CAC7D,CAAC;YACH,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,EAAE,CAAC;QACxC,CAAC;KACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { MetricsDriver } from "./sqlite.js";
|
|
2
|
+
/** The slice of Cloudflare D1 the metrics driver touches, typed structurally: no workers-types dependency. */
|
|
3
|
+
export interface D1Statement {
|
|
4
|
+
bind(...values: unknown[]): D1Statement;
|
|
5
|
+
all<T = Record<string, unknown>>(): Promise<{
|
|
6
|
+
results: T[];
|
|
7
|
+
}>;
|
|
8
|
+
}
|
|
9
|
+
export interface D1Binding {
|
|
10
|
+
prepare(sql: string): D1Statement;
|
|
11
|
+
/** D1 runs a batch as one transaction: a failing statement rolls back the whole sequence. */
|
|
12
|
+
batch(statements: D1Statement[]): Promise<unknown>;
|
|
13
|
+
}
|
|
14
|
+
/** A D1 binding as a metrics driver. */
|
|
15
|
+
export declare function d1Driver(db: D1Binding): MetricsDriver;
|
|
16
|
+
//# sourceMappingURL=d1.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"d1.d.ts","sourceRoot":"","sources":["../../src/metrics/d1.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,8GAA8G;AAC9G,MAAM,WAAW,WAAW;IAC3B,IAAI,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,WAAW,CAAC;IACxC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC,EAAE,CAAA;KAAE,CAAC,CAAC;CAC9D;AACD,MAAM,WAAW,SAAS;IACzB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC;IAClC,6FAA6F;IAC7F,KAAK,CAAC,UAAU,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACnD;AAED,wCAAwC;AACxC,wBAAgB,QAAQ,CAAC,EAAE,EAAE,SAAS,GAAG,aAAa,CAYrD"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** A D1 binding as a metrics driver. */
|
|
2
|
+
export function d1Driver(db) {
|
|
3
|
+
return {
|
|
4
|
+
query: async ({ sql, args }) => (await db
|
|
5
|
+
.prepare(sql)
|
|
6
|
+
.bind(...args)
|
|
7
|
+
.all()).results,
|
|
8
|
+
transact: (statements) => db.batch(statements.map((s) => db.prepare(s.sql).bind(...s.args))),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=d1.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"d1.js","sourceRoot":"","sources":["../../src/metrics/d1.ts"],"names":[],"mappings":"AAaA,wCAAwC;AACxC,MAAM,UAAU,QAAQ,CAAC,EAAa;IACrC,OAAO;QACN,KAAK,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,CAC9B,CACC,MAAM,EAAE;aACN,OAAO,CAAC,GAAG,CAAC;aACZ,IAAI,CAAC,GAAG,IAAI,CAAC;aACb,GAAG,EAAE,CACP,CAAC,OAAO;QACV,QAAQ,EAAE,CAAC,UAAU,EAAE,EAAE,CACxB,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;KACnE,CAAC;AACH,CAAC"}
|
package/dist/metrics/index.d.ts
CHANGED
|
@@ -14,10 +14,27 @@ export interface Measurement {
|
|
|
14
14
|
sum: number;
|
|
15
15
|
user?: string | number;
|
|
16
16
|
dimensions: Record<string, string>;
|
|
17
|
-
|
|
17
|
+
}
|
|
18
|
+
export interface MetricsSchema {
|
|
19
|
+
metrics: Array<{
|
|
20
|
+
key: string;
|
|
21
|
+
} & MetricSpec>;
|
|
22
|
+
overlaps: Array<{
|
|
23
|
+
from: string;
|
|
24
|
+
to: string;
|
|
25
|
+
}>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Where measurements go. `declare` runs once per process before the first write and
|
|
29
|
+
* carries the whole schema (kinds, labels, per-user flags, overlaps), so a store is
|
|
30
|
+
* self-describing and a reader never needs the declaring code. `write` carries one sample.
|
|
31
|
+
*/
|
|
32
|
+
export interface MetricsStore {
|
|
33
|
+
declare(schema: MetricsSchema): Promise<unknown>;
|
|
34
|
+
write(measurement: Measurement): Promise<unknown>;
|
|
18
35
|
}
|
|
19
36
|
export interface MetricsOptions<Keys extends string = string> {
|
|
20
|
-
|
|
37
|
+
store: MetricsStore;
|
|
21
38
|
/** Unordered user overlap, not an ordered conversion funnel. */
|
|
22
39
|
overlaps?: ReadonlyArray<readonly [Keys, Keys]>;
|
|
23
40
|
/** Failures are visible by default, but never reject a measurement call. */
|
|
@@ -36,15 +53,6 @@ export interface CounterHandle {
|
|
|
36
53
|
export interface TimingHandle {
|
|
37
54
|
record(value: number, options?: SampleOptions): Promise<void>;
|
|
38
55
|
}
|
|
39
|
-
export interface MetricsSchema {
|
|
40
|
-
metrics: Array<{
|
|
41
|
-
key: string;
|
|
42
|
-
} & MetricSpec>;
|
|
43
|
-
overlaps: Array<{
|
|
44
|
-
from: string;
|
|
45
|
-
to: string;
|
|
46
|
-
}>;
|
|
47
|
-
}
|
|
48
56
|
export type Metrics<Spec extends Record<string, MetricSpec>> = {
|
|
49
57
|
[K in keyof Spec]: Spec[K]["kind"] extends "counter" ? CounterHandle : TimingHandle;
|
|
50
58
|
} & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"AAAA,qGAAqG;AACrG,MAAM,MAAM,UAAU,GAAG;IACxB,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC;CAC/C,CAAC;AAEF,MAAM,WAAW,WAAW;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"AAAA,qGAAqG;AACrG,MAAM,MAAM,UAAU,GAAG;IACxB,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC;CAC/C,CAAC;AAEF,MAAM,WAAW,WAAW;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,aAAa;IAC7B,OAAO,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,UAAU,CAAC,CAAC;IAC7C,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC9C;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC5B,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD,KAAK,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAClD;AAED,MAAM,WAAW,cAAc,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM;IAC3D,KAAK,EAAE,YAAY,CAAC;IACpB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAChD,4EAA4E;IAC5E,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC7B,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AACD,MAAM,WAAW,aAAa;IAC7B,IAAI,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG;QAAE,CAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9D;AACD,MAAM,WAAW,YAAY;IAC5B,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9D;AACD,MAAM,MAAM,OAAO,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,IAAI;KAC7D,CAAC,IAAI,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,SAAS,GACjD,aAAa,GACb,YAAY;CACf,GAAG;IAAE,QAAQ,IAAI,aAAa,CAAA;CAAE,CAAC;AAIlC,wBAAgB,aAAa,CAAC,KAAK,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,EAC1E,KAAK,EAAE,IAAI,EACX,IAAI,EAAE,cAAc,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,MAAM,CAAC,CAAC,GAC/C,OAAO,CAAC,IAAI,CAAC,CA8Gf"}
|
package/dist/metrics/index.js
CHANGED
|
@@ -23,8 +23,23 @@ export function defineMetrics(input, opts) {
|
|
|
23
23
|
throw new Error("metrics: overlap requires two declared perUser metrics");
|
|
24
24
|
return { from, to };
|
|
25
25
|
});
|
|
26
|
+
const describe = () => structuredClone({
|
|
27
|
+
metrics: Object.entries(spec).map(([key, s]) => ({ key, ...s })),
|
|
28
|
+
overlaps,
|
|
29
|
+
});
|
|
26
30
|
const report = opts.onError ??
|
|
27
31
|
((_error, key) => console.warn(`metrics: measurement failed (${key})`));
|
|
32
|
+
// The schema reaches the store once per process, ahead of the first sample. A failed
|
|
33
|
+
// declaration is retried by the next sample, so a store that was briefly away recovers
|
|
34
|
+
// and a store that refuses the schema (a changed kind) fails every sample, loudly.
|
|
35
|
+
let declared;
|
|
36
|
+
const declare = () => {
|
|
37
|
+
declared ??= opts.store.declare(describe()).catch((error) => {
|
|
38
|
+
declared = undefined;
|
|
39
|
+
throw error;
|
|
40
|
+
});
|
|
41
|
+
return declared;
|
|
42
|
+
};
|
|
28
43
|
async function write(key, count, sum, options) {
|
|
29
44
|
try {
|
|
30
45
|
if (!Number.isSafeInteger(count) ||
|
|
@@ -49,14 +64,14 @@ export function defineMetrics(input, opts) {
|
|
|
49
64
|
? !Number.isSafeInteger(user)
|
|
50
65
|
: typeof user !== "string" || !user.length || user.length > 128))
|
|
51
66
|
throw new Error("metrics: invalid user identifier");
|
|
52
|
-
await
|
|
67
|
+
await declare();
|
|
68
|
+
await opts.store.write({
|
|
53
69
|
key,
|
|
54
70
|
day: (opts.now?.() ?? new Date()).toISOString().slice(0, 10),
|
|
55
71
|
count,
|
|
56
72
|
sum,
|
|
57
73
|
user,
|
|
58
74
|
dimensions,
|
|
59
|
-
spec: structuredClone(s),
|
|
60
75
|
});
|
|
61
76
|
}
|
|
62
77
|
catch (error) {
|
|
@@ -75,12 +90,6 @@ export function defineMetrics(input, opts) {
|
|
|
75
90
|
? { bump: (o) => write(key, o?.n ?? 1, 0, o) }
|
|
76
91
|
: { record: (value, o) => write(key, 1, value, o) };
|
|
77
92
|
}
|
|
78
|
-
return {
|
|
79
|
-
...out,
|
|
80
|
-
describe: () => structuredClone({
|
|
81
|
-
metrics: Object.entries(spec).map(([key, s]) => ({ key, ...s })),
|
|
82
|
-
overlaps,
|
|
83
|
-
}),
|
|
84
|
-
};
|
|
93
|
+
return { ...out, describe };
|
|
85
94
|
}
|
|
86
95
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { MetricsDriver, SqlStatement } from "./sqlite.js";
|
|
2
|
+
/** The slice of `@libsql/client` the metrics driver touches, typed structurally: no client is bundled. */
|
|
3
|
+
export interface LibsqlClient {
|
|
4
|
+
execute(statement: SqlStatement): Promise<{
|
|
5
|
+
rows: Iterable<Record<string, unknown>>;
|
|
6
|
+
}>;
|
|
7
|
+
batch(statements: SqlStatement[], mode: "write"): Promise<unknown>;
|
|
8
|
+
}
|
|
9
|
+
/** A Turso / libSQL / sqld connection as a metrics driver; `batch` in write mode is one transaction. */
|
|
10
|
+
export declare function libsqlDriver(client: LibsqlClient): MetricsDriver;
|
|
11
|
+
//# sourceMappingURL=libsql.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"libsql.d.ts","sourceRoot":"","sources":["../../src/metrics/libsql.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE/D,0GAA0G;AAC1G,MAAM,WAAW,YAAY;IAC5B,OAAO,CAAC,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC;QACzC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;KACxC,CAAC,CAAC;IACH,KAAK,CAAC,UAAU,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACnE;AAED,wGAAwG;AACxG,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,aAAa,CAKhE"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** A Turso / libSQL / sqld connection as a metrics driver; `batch` in write mode is one transaction. */
|
|
2
|
+
export function libsqlDriver(client) {
|
|
3
|
+
return {
|
|
4
|
+
query: async (statement) => (await client.execute(statement)).rows,
|
|
5
|
+
transact: (statements) => client.batch(statements, "write"),
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=libsql.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"libsql.js","sourceRoot":"","sources":["../../src/metrics/libsql.ts"],"names":[],"mappings":"AAUA,wGAAwG;AACxG,MAAM,UAAU,YAAY,CAAC,MAAoB;IAChD,OAAO;QACN,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;QAClE,QAAQ,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,EAAE,OAAO,CAAC;KAC3D,CAAC;AACH,CAAC"}
|
package/dist/metrics/report.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { MetricsSchema } from "./index.js";
|
|
1
2
|
/** Store-independent daily observations, shared by adapters and renderers. */
|
|
2
3
|
export interface DailyMetric {
|
|
3
4
|
project: string;
|
|
@@ -11,6 +12,43 @@ export interface DailyMetric {
|
|
|
11
12
|
count: number;
|
|
12
13
|
sum: number;
|
|
13
14
|
}
|
|
15
|
+
/** Per key, from opt-in per-user rows: keys nobody touched in the window are absent. */
|
|
16
|
+
export interface AudienceMetric {
|
|
17
|
+
project: string;
|
|
18
|
+
key: string;
|
|
19
|
+
/** Distinct actors. */
|
|
20
|
+
uniques: number;
|
|
21
|
+
/** Actors with more than one sample on a single day. */
|
|
22
|
+
repeatUsers: number;
|
|
23
|
+
/** Actors seen on more than one day. */
|
|
24
|
+
returningUsers: number;
|
|
25
|
+
}
|
|
26
|
+
/** Unordered: how many of `from`'s actors also touched `to`, in the same window. */
|
|
27
|
+
export interface AudienceOverlap {
|
|
28
|
+
project: string;
|
|
29
|
+
from: string;
|
|
30
|
+
to: string;
|
|
31
|
+
fromUsers: number;
|
|
32
|
+
bothUsers: number;
|
|
33
|
+
}
|
|
34
|
+
export interface Audience {
|
|
35
|
+
metrics: AudienceMetric[];
|
|
36
|
+
overlaps: AudienceOverlap[];
|
|
37
|
+
}
|
|
38
|
+
export interface MetricsWindow {
|
|
39
|
+
from: string;
|
|
40
|
+
to: string;
|
|
41
|
+
/** The window ends on the current, incomplete UTC day. */
|
|
42
|
+
partial: boolean;
|
|
43
|
+
}
|
|
44
|
+
/** One project, one window, everything a panel renders; the schema comes from the store. */
|
|
45
|
+
export interface MetricsReport {
|
|
46
|
+
project: string;
|
|
47
|
+
window: MetricsWindow;
|
|
48
|
+
schema: MetricsSchema;
|
|
49
|
+
daily: DailyMetric[];
|
|
50
|
+
audience: Audience;
|
|
51
|
+
}
|
|
14
52
|
export interface MetricTotal {
|
|
15
53
|
project: string;
|
|
16
54
|
key: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/metrics/report.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,YAAY,CAAC;IAC1B,aAAa,EAAE,YAAY,GAAG,IAAI,CAAC;CACnC;AAED,oEAAoE;AACpE,wBAAgB,aAAa,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,IAAI,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO;;;;;;;;;;EAkBpD;AASD,yFAAyF;AACzF,wBAAgB,cAAc,CAC7B,OAAO,EAAE,SAAS,WAAW,EAAE,EAC/B,QAAQ,EAAE,SAAS,WAAW,EAAE,GAC9B,gBAAgB,EAAE,CA4CpB;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,GAAG,WAAW,EAAE,CAqC5E"}
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/metrics/report.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,8EAA8E;AAC9E,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACZ;AAED,wFAAwF;AACxF,MAAM,WAAW,cAAc;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,WAAW,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,cAAc,EAAE,MAAM,CAAC;CACvB;AAED,oFAAoF;AACpF,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACxB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,0DAA0D;IAC1D,OAAO,EAAE,OAAO,CAAC;CACjB;AAED,4FAA4F;AAC5F,MAAM,WAAW,aAAa;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,aAAa,CAAC;IACtB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,QAAQ,EAAE,QAAQ,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,YAAY,CAAC;IAC1B,aAAa,EAAE,YAAY,GAAG,IAAI,CAAC;CACnC;AAED,oEAAoE;AACpE,wBAAgB,aAAa,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,IAAI,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO;;;;;;;;;;EAkBpD;AASD,yFAAyF;AACzF,wBAAgB,cAAc,CAC7B,OAAO,EAAE,SAAS,WAAW,EAAE,EAC/B,QAAQ,EAAE,SAAS,WAAW,EAAE,GAC9B,gBAAgB,EAAE,CA4CpB;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,GAAG,WAAW,EAAE,CAqC5E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/metrics/report.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/metrics/report.ts"],"names":[],"mappings":"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"}
|
package/dist/metrics/sqlite.d.ts
CHANGED
|
@@ -1,25 +1,52 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type
|
|
3
|
-
|
|
4
|
-
export interface
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
import type { MetricsSchema, MetricsStore } from "./index.js";
|
|
2
|
+
import { type Audience, type DailyMetric, type MetricsReport } from "./report.js";
|
|
3
|
+
export type SqlValue = string | number;
|
|
4
|
+
export interface SqlStatement {
|
|
5
|
+
sql: string;
|
|
6
|
+
args: SqlValue[];
|
|
7
|
+
}
|
|
8
|
+
/** Reads need one verb. `metrics/d1-rest` is a reader only: a REST call cannot transact. */
|
|
9
|
+
export interface MetricsReader {
|
|
10
|
+
/** The rows of one read statement. */
|
|
11
|
+
query(statement: SqlStatement): Promise<Iterable<Record<string, unknown>>>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The SQLite dialect below needs exactly two verbs from a store. `metrics/libsql` and
|
|
15
|
+
* `metrics/d1` implement them with each driver's native calls; any driver that speaks
|
|
16
|
+
* SQLite (node:sqlite, bun:sqlite, better-sqlite3) does the same in a few lines.
|
|
17
|
+
*/
|
|
18
|
+
export interface MetricsDriver extends MetricsReader {
|
|
19
|
+
/** Every statement or none: a constraint failure in any of them rolls the batch back. */
|
|
20
|
+
transact(statements: SqlStatement[]): Promise<unknown>;
|
|
15
21
|
}
|
|
16
22
|
/** Run explicitly during provisioning, never on a user's request. */
|
|
17
|
-
export declare const METRICS_SCHEMA: readonly ["CREATE TABLE IF NOT EXISTS metric_definition (project TEXT NOT NULL, key TEXT NOT NULL, kind TEXT NOT NULL, label TEXT NOT NULL, help TEXT NOT NULL, unit TEXT NOT NULL, PRIMARY KEY(project, key))", "CREATE TABLE IF NOT EXISTS metric_daily (project TEXT NOT NULL, key TEXT NOT NULL, dimensions TEXT NOT NULL, day TEXT NOT NULL, count INTEGER NOT NULL CHECK(count >= 0), sum REAL NOT NULL CHECK(sum >= 0), PRIMARY KEY(project, key, dimensions, day))", "CREATE TABLE IF NOT EXISTS metric_user_daily (project TEXT NOT NULL, key TEXT NOT NULL, dimensions TEXT NOT NULL, day TEXT NOT NULL, user TEXT NOT NULL, count INTEGER NOT NULL CHECK(count >= 0), sum REAL NOT NULL CHECK(sum >= 0), PRIMARY KEY(project, key, dimensions, day, user))", "CREATE INDEX IF NOT EXISTS metric_user_identity ON metric_user_daily(project, user)"];
|
|
18
|
-
|
|
23
|
+
export declare const METRICS_SCHEMA: readonly ["CREATE TABLE IF NOT EXISTS metric_definition (project TEXT NOT NULL, key TEXT NOT NULL, kind TEXT NOT NULL, label TEXT NOT NULL, help TEXT NOT NULL, unit TEXT NOT NULL, per_user INTEGER NOT NULL, PRIMARY KEY(project, key))", "CREATE TABLE IF NOT EXISTS metric_overlap (project TEXT NOT NULL, from_key TEXT NOT NULL, to_key TEXT NOT NULL, PRIMARY KEY(project, from_key, to_key))", "CREATE TABLE IF NOT EXISTS metric_daily (project TEXT NOT NULL, key TEXT NOT NULL, dimensions TEXT NOT NULL, day TEXT NOT NULL, count INTEGER NOT NULL CHECK(count >= 0), sum REAL NOT NULL CHECK(sum >= 0), PRIMARY KEY(project, key, dimensions, day))", "CREATE TABLE IF NOT EXISTS metric_user_daily (project TEXT NOT NULL, key TEXT NOT NULL, dimensions TEXT NOT NULL, day TEXT NOT NULL, user TEXT NOT NULL, count INTEGER NOT NULL CHECK(count >= 0), sum REAL NOT NULL CHECK(sum >= 0), PRIMARY KEY(project, key, dimensions, day, user))", "CREATE INDEX IF NOT EXISTS metric_user_identity ON metric_user_daily(project, user)"];
|
|
24
|
+
/** One project's store over a SQLite driver. */
|
|
25
|
+
export declare function metricsStore(driver: MetricsDriver, project: string): MetricsStore;
|
|
26
|
+
/** What one project declared, as the store holds it: the reader needs no declaring code. */
|
|
27
|
+
export declare function readSchema(reader: MetricsReader, project: string): Promise<MetricsSchema>;
|
|
19
28
|
/** Inclusive UTC dates. Errors propagate: unavailable data must never read as zero. */
|
|
20
|
-
export declare function readMetrics(
|
|
29
|
+
export declare function readMetrics(reader: MetricsReader, range: {
|
|
21
30
|
from: string;
|
|
22
31
|
to: string;
|
|
23
32
|
project?: string;
|
|
24
33
|
}): Promise<DailyMetric[]>;
|
|
34
|
+
/**
|
|
35
|
+
* Who did it, over one project's opt-in per-user rows, all dimensions folded: one row per
|
|
36
|
+
* declared per-user metric (zeros when nobody touched it in the window) with distinct
|
|
37
|
+
* actors, actors with more than one sample on a single day, actors seen on more than one
|
|
38
|
+
* day; then every declared unordered overlap.
|
|
39
|
+
*/
|
|
40
|
+
export declare function readAudience(reader: MetricsReader, range: {
|
|
41
|
+
from: string;
|
|
42
|
+
to: string;
|
|
43
|
+
project: string;
|
|
44
|
+
}, schema: MetricsSchema): Promise<Audience>;
|
|
45
|
+
/** Everything a panel renders for one project over the last `days` UTC days, in one call. */
|
|
46
|
+
export declare function readReport(reader: MetricsReader, options: {
|
|
47
|
+
project: string;
|
|
48
|
+
days: number;
|
|
49
|
+
includeToday?: boolean;
|
|
50
|
+
now?: Date;
|
|
51
|
+
}): Promise<MetricsReport>;
|
|
25
52
|
//# sourceMappingURL=sqlite.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/metrics/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/metrics/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC3E,OAAO,EACN,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,KAAK,aAAa,EAElB,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AACvC,MAAM,WAAW,YAAY;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,QAAQ,EAAE,CAAC;CACjB;AAED,4FAA4F;AAC5F,MAAM,WAAW,aAAa;IAC7B,sCAAsC;IACtC,KAAK,CAAC,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;CAC3E;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAc,SAAQ,aAAa;IACnD,yFAAyF;IACzF,QAAQ,CAAC,UAAU,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACvD;AAED,qEAAqE;AACrE,eAAO,MAAM,cAAc,s/BAMjB,CAAC;AAiBX,gDAAgD;AAChD,wBAAgB,YAAY,CAC3B,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,MAAM,GACb,YAAY,CAqDd;AAED,4FAA4F;AAC5F,wBAAsB,UAAU,CAC/B,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,MAAM,GACb,OAAO,CAAC,aAAa,CAAC,CA0BxB;AAED,uFAAuF;AACvF,wBAAsB,WAAW,CAChC,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GACnD,OAAO,CAAC,WAAW,EAAE,CAAC,CAmBxB;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CACjC,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EACpD,MAAM,EAAE,aAAa,GACnB,OAAO,CAAC,QAAQ,CAAC,CAmDnB;AAED,6FAA6F;AAC7F,wBAAsB,UAAU,CAC/B,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE;IACR,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,GAAG,CAAC,EAAE,IAAI,CAAC;CACX,GACC,OAAO,CAAC,aAAa,CAAC,CAkBxB"}
|
package/dist/metrics/sqlite.js
CHANGED
|
@@ -1,64 +1,119 @@
|
|
|
1
|
+
import { metricWindows, } from "./report.js";
|
|
1
2
|
/** Run explicitly during provisioning, never on a user's request. */
|
|
2
3
|
export const METRICS_SCHEMA = [
|
|
3
|
-
`CREATE TABLE IF NOT EXISTS metric_definition (project TEXT NOT NULL, key TEXT NOT NULL, kind TEXT NOT NULL, label TEXT NOT NULL, help TEXT NOT NULL, unit TEXT NOT NULL, PRIMARY KEY(project, key))`,
|
|
4
|
+
`CREATE TABLE IF NOT EXISTS metric_definition (project TEXT NOT NULL, key TEXT NOT NULL, kind TEXT NOT NULL, label TEXT NOT NULL, help TEXT NOT NULL, unit TEXT NOT NULL, per_user INTEGER NOT NULL, PRIMARY KEY(project, key))`,
|
|
5
|
+
`CREATE TABLE IF NOT EXISTS metric_overlap (project TEXT NOT NULL, from_key TEXT NOT NULL, to_key TEXT NOT NULL, PRIMARY KEY(project, from_key, to_key))`,
|
|
4
6
|
`CREATE TABLE IF NOT EXISTS metric_daily (project TEXT NOT NULL, key TEXT NOT NULL, dimensions TEXT NOT NULL, day TEXT NOT NULL, count INTEGER NOT NULL CHECK(count >= 0), sum REAL NOT NULL CHECK(sum >= 0), PRIMARY KEY(project, key, dimensions, day))`,
|
|
5
7
|
`CREATE TABLE IF NOT EXISTS metric_user_daily (project TEXT NOT NULL, key TEXT NOT NULL, dimensions TEXT NOT NULL, day TEXT NOT NULL, user TEXT NOT NULL, count INTEGER NOT NULL CHECK(count >= 0), sum REAL NOT NULL CHECK(sum >= 0), PRIMARY KEY(project, key, dimensions, day, user))`,
|
|
6
8
|
`CREATE INDEX IF NOT EXISTS metric_user_identity ON metric_user_daily(project, user)`,
|
|
7
9
|
];
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
const PROJECT = /^[a-z][a-z0-9-]*$/;
|
|
11
|
+
const DAY = /^\d{4}-\d{2}-\d{2}$/;
|
|
12
|
+
function assertProject(project) {
|
|
13
|
+
if (!PROJECT.test(project))
|
|
10
14
|
throw new Error("metrics: invalid project");
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
}
|
|
16
|
+
function assertRange(range) {
|
|
17
|
+
for (const day of [range.from, range.to]) {
|
|
18
|
+
if (!DAY.test(day) || new Date(day).toISOString().slice(0, 10) !== day)
|
|
19
|
+
throw new Error("metrics: invalid UTC date");
|
|
20
|
+
}
|
|
21
|
+
if (range.from > range.to)
|
|
22
|
+
throw new Error("metrics: reversed date range");
|
|
23
|
+
}
|
|
24
|
+
/** One project's store over a SQLite driver. */
|
|
25
|
+
export function metricsStore(driver, project) {
|
|
26
|
+
assertProject(project);
|
|
27
|
+
return {
|
|
28
|
+
async declare(schema) {
|
|
29
|
+
const statements = schema.metrics.map((m) => ({
|
|
30
|
+
// NOT NULL makes a changed kind/unit fail the whole atomic batch. Labels, help
|
|
31
|
+
// and the per-user flag may evolve; historical measurements keep their meaning.
|
|
32
|
+
sql: `INSERT INTO metric_definition VALUES (?, ?, ?, ?, ?, ?, ?) ON CONFLICT(project, key) DO UPDATE SET kind=CASE WHEN kind=excluded.kind THEN kind ELSE NULL END, label=excluded.label, help=excluded.help, unit=CASE WHEN unit=excluded.unit THEN unit ELSE NULL END, per_user=excluded.per_user`,
|
|
18
33
|
args: [
|
|
19
34
|
project,
|
|
20
35
|
m.key,
|
|
21
|
-
m.
|
|
22
|
-
m.
|
|
23
|
-
m.
|
|
24
|
-
m.
|
|
36
|
+
m.kind,
|
|
37
|
+
m.label,
|
|
38
|
+
m.help ?? "",
|
|
39
|
+
m.unit ?? "",
|
|
40
|
+
m.perUser ? 1 : 0,
|
|
25
41
|
],
|
|
26
|
-
}
|
|
27
|
-
{
|
|
28
|
-
sql: `INSERT INTO metric_daily VALUES (?, ?, ?, ?, ?, ?) ON CONFLICT(project, key, dimensions, day) DO UPDATE SET count=count+excluded.count, sum=sum+excluded.sum`,
|
|
29
|
-
args: [project, m.key, dimensions, m.day, m.count, m.sum],
|
|
30
|
-
},
|
|
31
|
-
];
|
|
32
|
-
if (m.user !== undefined)
|
|
42
|
+
}));
|
|
33
43
|
statements.push({
|
|
34
|
-
sql: `
|
|
35
|
-
args: [
|
|
36
|
-
project,
|
|
37
|
-
m.key,
|
|
38
|
-
dimensions,
|
|
39
|
-
m.day,
|
|
40
|
-
String(m.user),
|
|
41
|
-
m.count,
|
|
42
|
-
m.sum,
|
|
43
|
-
],
|
|
44
|
+
sql: `DELETE FROM metric_overlap WHERE project = ?`,
|
|
45
|
+
args: [project],
|
|
44
46
|
});
|
|
45
|
-
|
|
47
|
+
for (const o of schema.overlaps)
|
|
48
|
+
statements.push({
|
|
49
|
+
sql: `INSERT INTO metric_overlap VALUES (?, ?, ?)`,
|
|
50
|
+
args: [project, o.from, o.to],
|
|
51
|
+
});
|
|
52
|
+
await driver.transact(statements);
|
|
53
|
+
},
|
|
54
|
+
async write(m) {
|
|
55
|
+
const dimensions = JSON.stringify(m.dimensions);
|
|
56
|
+
const statements = [
|
|
57
|
+
{
|
|
58
|
+
sql: `INSERT INTO metric_daily VALUES (?, ?, ?, ?, ?, ?) ON CONFLICT(project, key, dimensions, day) DO UPDATE SET count=count+excluded.count, sum=sum+excluded.sum`,
|
|
59
|
+
args: [project, m.key, dimensions, m.day, m.count, m.sum],
|
|
60
|
+
},
|
|
61
|
+
];
|
|
62
|
+
if (m.user !== undefined)
|
|
63
|
+
statements.push({
|
|
64
|
+
sql: `INSERT INTO metric_user_daily VALUES (?, ?, ?, ?, ?, ?, ?) ON CONFLICT(project, key, dimensions, day, user) DO UPDATE SET count=count+excluded.count, sum=sum+excluded.sum`,
|
|
65
|
+
args: [
|
|
66
|
+
project,
|
|
67
|
+
m.key,
|
|
68
|
+
dimensions,
|
|
69
|
+
m.day,
|
|
70
|
+
String(m.user),
|
|
71
|
+
m.count,
|
|
72
|
+
m.sum,
|
|
73
|
+
],
|
|
74
|
+
});
|
|
75
|
+
await driver.transact(statements);
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/** What one project declared, as the store holds it: the reader needs no declaring code. */
|
|
80
|
+
export async function readSchema(reader, project) {
|
|
81
|
+
assertProject(project);
|
|
82
|
+
const [definitions, overlaps] = await Promise.all([
|
|
83
|
+
reader.query({
|
|
84
|
+
sql: `SELECT key, kind, label, help, unit, per_user FROM metric_definition WHERE project = ? ORDER BY key`,
|
|
85
|
+
args: [project],
|
|
86
|
+
}),
|
|
87
|
+
reader.query({
|
|
88
|
+
sql: `SELECT from_key, to_key FROM metric_overlap WHERE project = ? ORDER BY from_key, to_key`,
|
|
89
|
+
args: [project],
|
|
90
|
+
}),
|
|
91
|
+
]);
|
|
92
|
+
return {
|
|
93
|
+
metrics: Array.from(definitions, (r) => ({
|
|
94
|
+
key: String(r.key),
|
|
95
|
+
kind: String(r.kind),
|
|
96
|
+
label: String(r.label),
|
|
97
|
+
...(r.help ? { help: String(r.help) } : {}),
|
|
98
|
+
...(r.unit ? { unit: String(r.unit) } : {}),
|
|
99
|
+
...(Number(r.per_user) ? { perUser: true } : {}),
|
|
100
|
+
})),
|
|
101
|
+
overlaps: Array.from(overlaps, (r) => ({
|
|
102
|
+
from: String(r.from_key),
|
|
103
|
+
to: String(r.to_key),
|
|
104
|
+
})),
|
|
46
105
|
};
|
|
47
106
|
}
|
|
48
107
|
/** Inclusive UTC dates. Errors propagate: unavailable data must never read as zero. */
|
|
49
|
-
export async function readMetrics(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
if (range.from > range.to)
|
|
56
|
-
throw new Error("metrics: reversed date range");
|
|
57
|
-
const result = await db.execute({
|
|
108
|
+
export async function readMetrics(reader, range) {
|
|
109
|
+
assertRange(range);
|
|
110
|
+
if (range.project !== undefined)
|
|
111
|
+
assertProject(range.project);
|
|
112
|
+
const rows = await reader.query({
|
|
58
113
|
sql: `SELECT d.*, s.label, s.kind, s.help, s.unit FROM metric_daily d JOIN metric_definition s USING(project, key) WHERE day >= ? AND day <= ? ${range.project ? "AND project = ?" : ""} ORDER BY project, key, dimensions, day`,
|
|
59
114
|
args: [range.from, range.to, ...(range.project ? [range.project] : [])],
|
|
60
115
|
});
|
|
61
|
-
return Array.from(
|
|
116
|
+
return Array.from(rows, (r) => ({
|
|
62
117
|
project: String(r.project),
|
|
63
118
|
key: String(r.key),
|
|
64
119
|
label: String(r.label),
|
|
@@ -71,4 +126,75 @@ export async function readMetrics(db, range) {
|
|
|
71
126
|
sum: Number(r.sum),
|
|
72
127
|
}));
|
|
73
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* Who did it, over one project's opt-in per-user rows, all dimensions folded: one row per
|
|
131
|
+
* declared per-user metric (zeros when nobody touched it in the window) with distinct
|
|
132
|
+
* actors, actors with more than one sample on a single day, actors seen on more than one
|
|
133
|
+
* day; then every declared unordered overlap.
|
|
134
|
+
*/
|
|
135
|
+
export async function readAudience(reader, range, schema) {
|
|
136
|
+
assertRange(range);
|
|
137
|
+
assertProject(range.project);
|
|
138
|
+
const perKey = new Map(Array.from(await reader.query({
|
|
139
|
+
sql: `WITH per_day AS (SELECT key, user, day, SUM(count) AS count FROM metric_user_daily WHERE project = ? AND day >= ? AND day <= ? GROUP BY key, user, day), per_user AS (SELECT key, user, COUNT(*) AS days, MAX(count) AS peak FROM per_day GROUP BY key, user) SELECT key, COUNT(*) AS uniques, SUM(CASE WHEN peak > 1 THEN 1 ELSE 0 END) AS repeat_users, SUM(CASE WHEN days > 1 THEN 1 ELSE 0 END) AS returning_users FROM per_user GROUP BY key`,
|
|
140
|
+
args: [range.project, range.from, range.to],
|
|
141
|
+
}), (r) => [String(r.key), r]));
|
|
142
|
+
const metrics = schema.metrics
|
|
143
|
+
.filter((m) => m.perUser)
|
|
144
|
+
.map((m) => {
|
|
145
|
+
const r = perKey.get(m.key);
|
|
146
|
+
return {
|
|
147
|
+
project: range.project,
|
|
148
|
+
key: m.key,
|
|
149
|
+
uniques: Number(r?.uniques ?? 0),
|
|
150
|
+
repeatUsers: Number(r?.repeat_users ?? 0),
|
|
151
|
+
returningUsers: Number(r?.returning_users ?? 0),
|
|
152
|
+
};
|
|
153
|
+
});
|
|
154
|
+
const actors = `SELECT DISTINCT user FROM metric_user_daily WHERE project = ? AND key = ? AND day >= ? AND day <= ?`;
|
|
155
|
+
const overlaps = [];
|
|
156
|
+
for (const pair of schema.overlaps) {
|
|
157
|
+
const [row] = Array.from(await reader.query({
|
|
158
|
+
sql: `WITH a AS (${actors}), b AS (${actors}) SELECT (SELECT COUNT(*) FROM a) AS from_users, (SELECT COUNT(*) FROM a WHERE user IN (SELECT user FROM b)) AS both_users`,
|
|
159
|
+
args: [
|
|
160
|
+
range.project,
|
|
161
|
+
pair.from,
|
|
162
|
+
range.from,
|
|
163
|
+
range.to,
|
|
164
|
+
range.project,
|
|
165
|
+
pair.to,
|
|
166
|
+
range.from,
|
|
167
|
+
range.to,
|
|
168
|
+
],
|
|
169
|
+
}));
|
|
170
|
+
overlaps.push({
|
|
171
|
+
project: range.project,
|
|
172
|
+
from: pair.from,
|
|
173
|
+
to: pair.to,
|
|
174
|
+
fromUsers: Number(row?.from_users ?? 0),
|
|
175
|
+
bothUsers: Number(row?.both_users ?? 0),
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
return { metrics, overlaps };
|
|
179
|
+
}
|
|
180
|
+
/** Everything a panel renders for one project over the last `days` UTC days, in one call. */
|
|
181
|
+
export async function readReport(reader, options) {
|
|
182
|
+
const { current, partial } = metricWindows(options.days, {
|
|
183
|
+
now: options.now,
|
|
184
|
+
includeToday: options.includeToday,
|
|
185
|
+
});
|
|
186
|
+
const range = { ...current, project: options.project };
|
|
187
|
+
const schema = await readSchema(reader, options.project);
|
|
188
|
+
const [daily, audience] = await Promise.all([
|
|
189
|
+
readMetrics(reader, range),
|
|
190
|
+
readAudience(reader, range, schema),
|
|
191
|
+
]);
|
|
192
|
+
return {
|
|
193
|
+
project: options.project,
|
|
194
|
+
window: { ...current, partial },
|
|
195
|
+
schema,
|
|
196
|
+
daily,
|
|
197
|
+
audience,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
74
200
|
//# sourceMappingURL=sqlite.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../src/metrics/sqlite.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../src/metrics/sqlite.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adriangalilea/utils",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "TypeScript utilities - logger, currency, formatter, GramIO bot plugins, and more",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -192,6 +192,18 @@
|
|
|
192
192
|
"types": "./dist/metrics/sqlite.d.ts",
|
|
193
193
|
"default": "./dist/metrics/sqlite.js"
|
|
194
194
|
},
|
|
195
|
+
"./metrics/libsql": {
|
|
196
|
+
"types": "./dist/metrics/libsql.d.ts",
|
|
197
|
+
"default": "./dist/metrics/libsql.js"
|
|
198
|
+
},
|
|
199
|
+
"./metrics/d1": {
|
|
200
|
+
"types": "./dist/metrics/d1.d.ts",
|
|
201
|
+
"default": "./dist/metrics/d1.js"
|
|
202
|
+
},
|
|
203
|
+
"./metrics/d1-rest": {
|
|
204
|
+
"types": "./dist/metrics/d1-rest.d.ts",
|
|
205
|
+
"default": "./dist/metrics/d1-rest.js"
|
|
206
|
+
},
|
|
195
207
|
"./metrics/report": {
|
|
196
208
|
"types": "./dist/metrics/report.d.ts",
|
|
197
209
|
"default": "./dist/metrics/report.js"
|