@lunora/observability 1.0.0-alpha.4 → 1.0.0-alpha.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.d.mts +294 -55
- package/dist/index.d.ts +294 -55
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/AUTH_METRICS_BUCKETS_TABLE-CeplWoRm.mjs +22 -0
- package/dist/packem_shared/DEFAULT_EXPLAIN_ISSUE_MODEL-BGGX6k5D.mjs +3 -0
- package/dist/packem_shared/FUNCTION_METRICS_BUCKETS_TABLE-ChlIe0vF.mjs +56 -0
- package/dist/packem_shared/ISSUE_SEVERITIES-gLC4VEPQ.mjs +15 -0
- package/dist/packem_shared/MIN_ADMIN_TOKEN_LENGTH-CidkqOQ1.mjs +1 -0
- package/dist/packem_shared/MetricBuffer-DGDoRAig.mjs +1 -0
- package/dist/packem_shared/REQUEST_LOG_TABLE-DMQIHLi_.mjs +1 -0
- package/dist/packem_shared/SpanBuffer-zjqCAuGp.mjs +1 -0
- package/dist/packem_shared/createDatabaseTally-DCMuBKoP.mjs +1 -0
- package/dist/packem_shared/createMetrics-vNIDyAtP.mjs +1 -0
- package/dist/packem_shared/findDanglingReferences-Dxl42LBT.mjs +1 -0
- package/dist/packem_shared/metric-buffer-QGsa8K4_.mjs +1 -0
- package/dist/packem_shared/prune-marker-B4An9Nuj.mjs +1 -0
- package/dist/packem_shared/readMetricHistory-dka8wnH-.mjs +31 -0
- package/dist/packem_shared/readQueryInsights-D37H7MII.mjs +32 -0
- package/dist/packem_shared/request-log-COB2xhns.mjs +22 -0
- package/dist/packem_shared/resolveTraceAnchor-FyCYPLGu.mjs +1 -0
- package/dist/packem_shared/run-sql-0aPgJkIw.mjs +1 -0
- package/dist/packem_shared/trace-context-DfJZi_g2.mjs +1 -0
- package/package.json +5 -5
- package/dist/packem_shared/AUTH_METRICS_BUCKETS_TABLE-C2V-DiGu.mjs +0 -22
- package/dist/packem_shared/DEFAULT_EXPLAIN_ISSUE_MODEL-xF11R4vX.mjs +0 -3
- package/dist/packem_shared/FUNCTION_METRICS_BUCKETS_TABLE-B1U7xWMo.mjs +0 -56
- package/dist/packem_shared/ISSUE_SEVERITIES-Js6lGUG5.mjs +0 -15
- package/dist/packem_shared/MIN_ADMIN_TOKEN_LENGTH-T-zuwRVR.mjs +0 -1
- package/dist/packem_shared/MetricBuffer-CYrLuEsz.mjs +0 -1
- package/dist/packem_shared/REQUEST_LOG_TABLE-Q_BYgAzY.mjs +0 -20
- package/dist/packem_shared/SpanBuffer-BR6Ff0M-.mjs +0 -1
- package/dist/packem_shared/createDatabaseTally-BTqRpC0j.mjs +0 -1
- package/dist/packem_shared/createMetrics-fpVig63l.mjs +0 -1
- package/dist/packem_shared/findDanglingReferences-D-x9LvY0.mjs +0 -1
- package/dist/packem_shared/log-fields-d5ouN1Pe.mjs +0 -1
- package/dist/packem_shared/metric-buffer-CdgXal7w.mjs +0 -1
- package/dist/packem_shared/readMetricHistory-DtnhufUq.mjs +0 -31
- package/dist/packem_shared/readQueryInsights-CwSKB0I1.mjs +0 -32
- package/dist/packem_shared/resolveTraceAnchor-IAN8riI0.mjs +0 -1
- package/dist/packem_shared/trace-context-DrdF960P.mjs +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -64,9 +64,9 @@ declare const ensureAuthMetricsTables: (sql: SqlExec) => void;
|
|
|
64
64
|
* `failures` advances only when `outcome === "fail"`. `since_ms` is set once on
|
|
65
65
|
* the first attempt and never moved (so it stays a true first-seen marker).
|
|
66
66
|
*
|
|
67
|
-
* Exactly two `INSERT … ON CONFLICT … DO UPDATE` statements
|
|
68
|
-
*
|
|
69
|
-
* response path without blocking it.
|
|
67
|
+
* Exactly two `INSERT … ON CONFLICT … DO UPDATE` statements, all keyed by
|
|
68
|
+
* primary key, plus a bounded `DELETE` that runs once per bucket window —
|
|
69
|
+
* cheap enough to fire off the auth response path without blocking it.
|
|
70
70
|
*/
|
|
71
71
|
declare const recordAuthEvent: (sql: SqlExec, input: RecordAuthEventInput) => void;
|
|
72
72
|
/**
|
|
@@ -488,6 +488,15 @@ type HostTracingResolver = () => HostTracingLike | Promise<HostTracingLike | und
|
|
|
488
488
|
interface TracerDeps {
|
|
489
489
|
/** The trace this ctx's spans belong to. */
|
|
490
490
|
anchor: TraceAnchor;
|
|
491
|
+
/**
|
|
492
|
+
* Whether to record a span body's error message (and a `recordException`
|
|
493
|
+
* stacktrace) verbatim rather than redacted. Mirrors the request log's
|
|
494
|
+
* `captureRaw`: `true` in dev (`isDevEnvironment`), `false` in production —
|
|
495
|
+
* the span pipeline is the one sink third-party collectors (Datadog/Axiom
|
|
496
|
+
* via `otlpSink`) receive, so it must not ship raw PII/internals by default
|
|
497
|
+
* the way the request log and function-metrics sinks already don't.
|
|
498
|
+
*/
|
|
499
|
+
captureRaw?: boolean;
|
|
491
500
|
/** Function path the spans are attributed to. */
|
|
492
501
|
functionPath: string;
|
|
493
502
|
/**
|
|
@@ -544,11 +553,17 @@ interface SpanCollector {
|
|
|
544
553
|
* attributes become the canonical one-event-per-request summary. Sharing the
|
|
545
554
|
* implementation is what makes those two feel like the same API instead of two
|
|
546
555
|
* that happen to resemble each other.
|
|
556
|
+
*
|
|
557
|
+
* `captureRaw` (default `false`) gates `recordException`'s `exception.message`/
|
|
558
|
+
* `exception.stacktrace` the same way {@link createTracer} gates a span's own
|
|
559
|
+
* error message — a stack is file paths and internals by definition, the exact
|
|
560
|
+
* class `isInternalCode` redaction exists for, so it rides the same dev-only
|
|
561
|
+
* escape hatch rather than shipping to a third-party collector by default.
|
|
547
562
|
*/
|
|
548
563
|
declare const createSpanCollector: (ids: {
|
|
549
564
|
spanId: string;
|
|
550
565
|
traceId: string;
|
|
551
|
-
}) => SpanCollector;
|
|
566
|
+
}, captureRaw?: boolean) => SpanCollector;
|
|
552
567
|
/**
|
|
553
568
|
* Build the `ctx.trace` span factory for one dispatched function.
|
|
554
569
|
*
|
|
@@ -590,7 +605,7 @@ declare const createSpanCollector: (ids: {
|
|
|
590
605
|
*
|
|
591
606
|
* **DO async-context caveat (EXPERIMENTAL, partially workerd-validated).**
|
|
592
607
|
* `tracing.enterSpan` is now confirmed to EXIST and RUN inside a real Durable
|
|
593
|
-
* Object under `@cloudflare/vitest-
|
|
608
|
+
* Object under `@cloudflare/vitest-plugin` (see
|
|
594
609
|
* `__tests__/workerd/context-telemetry-cf-bridge.workerd.test.ts`): it resolves
|
|
595
610
|
* from `cloudflare:workers`, its callback executes and returns the body value
|
|
596
611
|
* without throwing, `span.isTraced` is a real boolean, and — the key additive
|
|
@@ -673,6 +688,14 @@ declare const createMetrics: (deps: MetricsDeps) => ContextMetrics;
|
|
|
673
688
|
*/
|
|
674
689
|
declare const dispatchRootSpan: (input: {
|
|
675
690
|
anchor: TraceAnchor;
|
|
691
|
+
/**
|
|
692
|
+
* Whether to record the failure message verbatim rather than redacted —
|
|
693
|
+
* the same dev-only escape hatch as {@link TracerDeps.captureRaw}. This
|
|
694
|
+
* synthetic root span carries the SAME error message the request log and
|
|
695
|
+
* function-metrics sinks already redact by default, so it must not be the
|
|
696
|
+
* one durable copy that ships it raw to a third-party collector.
|
|
697
|
+
*/
|
|
698
|
+
captureRaw?: boolean;
|
|
676
699
|
/**
|
|
677
700
|
* What the handler attached to the dispatch through `ctx.span` — the **wide
|
|
678
701
|
* event**. These are the attributes that would otherwise have been scattered
|
|
@@ -715,6 +738,14 @@ type DatabaseInstrumentation = "off" | "spans" | "summary";
|
|
|
715
738
|
interface DatabaseTelemetryDeps {
|
|
716
739
|
/** The trace produced spans belong to (`"spans"` mode only). */
|
|
717
740
|
anchor: TraceAnchor;
|
|
741
|
+
/**
|
|
742
|
+
* Whether to record a failed call's error message verbatim rather than
|
|
743
|
+
* redacted (`"spans"` mode only) — the same dev-only escape hatch as
|
|
744
|
+
* `TracerDeps.captureRaw`. A constraint-error message quotes the
|
|
745
|
+
* conflicting row, so this CLIENT span gets the same default-redacted
|
|
746
|
+
* posture as the request log and function-metrics sinks.
|
|
747
|
+
*/
|
|
748
|
+
captureRaw?: boolean;
|
|
718
749
|
/** Function path spans and attributes are attributed to. */
|
|
719
750
|
functionPath: string;
|
|
720
751
|
/** Detail level; see {@link DatabaseInstrumentation}. */
|
|
@@ -786,13 +817,23 @@ declare const FUNCTION_METRICS_BUCKET_RETENTION = 1440;
|
|
|
786
817
|
/**
|
|
787
818
|
* Maximum distinct function `path`s tracked in the accumulator table. Mirrors
|
|
788
819
|
* `query-metrics.ts`'s `QUERY_METRICS_MAX_STATEMENTS` cap (and exists for the
|
|
789
|
-
* same reason): the
|
|
790
|
-
*
|
|
791
|
-
*
|
|
792
|
-
*
|
|
793
|
-
*
|
|
794
|
-
*
|
|
795
|
-
*
|
|
820
|
+
* same reason): the real bound is the app's own registered-function set plus
|
|
821
|
+
* deploy churn (a rename/removal leaves its old path's row in place, still
|
|
822
|
+
* counted against the cap, until an operator's own retention/cleanup
|
|
823
|
+
* process — there is none built in today) — a few thousand registered
|
|
824
|
+
* functions is already far beyond any real app. `shard-do.ts`'s dispatch
|
|
825
|
+
* handler explicitly does NOT record per-function metrics for an
|
|
826
|
+
* unregistered/`FUNCTION_NOT_FOUND` dispatch (see the guard next to its
|
|
827
|
+
* `FUNCTION_NOT_FOUND` check), so a caller cannot mint arbitrary `path`s here
|
|
828
|
+
* the way a raw caller-supplied SQL shape can in `query-metrics.ts`. Without a
|
|
829
|
+
* cap, deploy churn across the app's lifetime would still grow
|
|
830
|
+
* `__lunora_metrics` (and its bucket/scan satellites) without bound,
|
|
831
|
+
* eventually filling the shard's SQLite store shared with the app's real
|
|
832
|
+
* data. At the cap, a brand-new path is refused — protecting the incumbent
|
|
833
|
+
* leaderboard from a flood of one-off paths is the point, so admission is
|
|
834
|
+
* refused rather than evicting an existing path to make room; already-tracked
|
|
835
|
+
* paths keep accumulating past the cap. `readFunctionMetricsTotals`'s
|
|
836
|
+
* `capped` is the read-side signal for this.
|
|
796
837
|
*/
|
|
797
838
|
declare const FUNCTION_METRICS_MAX_PATHS = 5e3;
|
|
798
839
|
/**
|
|
@@ -814,6 +855,22 @@ interface FunctionMetricBucket {
|
|
|
814
855
|
/** Subset of `calls` that threw. */
|
|
815
856
|
errors: number;
|
|
816
857
|
}
|
|
858
|
+
/** {@link readFunctionMetricBuckets} result: the time-series window plus whether the read limit cut it short. */
|
|
859
|
+
interface FunctionMetricBucketsResult {
|
|
860
|
+
buckets: (FunctionMetricBucket & {
|
|
861
|
+
path: string;
|
|
862
|
+
})[];
|
|
863
|
+
/**
|
|
864
|
+
* True when more rows existed than {@link FUNCTION_METRICS_READ_LIMIT} could
|
|
865
|
+
* return, so `buckets` is a partial (newest) window rather than the app's
|
|
866
|
+
* full retained history. Mirrors `readQueryInsights`'s `capped` and
|
|
867
|
+
* `foldTraces`'s `total`: a silently truncated read looks identical to a
|
|
868
|
+
* complete one to a caller that doesn't check for it — the Metrics chart's
|
|
869
|
+
* window would appear to shrink as the app grows, with a wrong leftmost
|
|
870
|
+
* bar, and nothing would say why.
|
|
871
|
+
*/
|
|
872
|
+
truncated: boolean;
|
|
873
|
+
}
|
|
817
874
|
/** One declared index a dispatch exercised (used to narrow a read). */
|
|
818
875
|
interface IndexHit {
|
|
819
876
|
/** The declared index name. */
|
|
@@ -854,7 +911,7 @@ interface RecordFunctionMetricInput {
|
|
|
854
911
|
* dispatch used no declared index, keeping the hot path unchanged.
|
|
855
912
|
*/
|
|
856
913
|
indexHits?: ReadonlyArray<IndexHit>;
|
|
857
|
-
/** The
|
|
914
|
+
/** The `<file>:<function>` identifier. */
|
|
858
915
|
path: string;
|
|
859
916
|
/**
|
|
860
917
|
* Distinct tables this dispatch full-scanned (read with no index / point
|
|
@@ -879,7 +936,9 @@ interface RecordFunctionMetricInput {
|
|
|
879
936
|
* than baked into the `CREATE` so a shard whose `__lunora_metrics` predates the
|
|
880
937
|
* causal-attribution feature gains the column on the next call without a
|
|
881
938
|
* migration. SQLite has no `ADD COLUMN IF NOT EXISTS`, so the duplicate-column
|
|
882
|
-
* error from a re-run is swallowed.
|
|
939
|
+
* error from a re-run is swallowed. Both the `CREATE`s and the back-fill only
|
|
940
|
+
* run once per handle (see {@link ensuredHandles}) — a handle already marked
|
|
941
|
+
* ensured returns immediately.
|
|
883
942
|
*/
|
|
884
943
|
declare const ensureFunctionMetricsTables: (sql: SqlExec) => void;
|
|
885
944
|
/**
|
|
@@ -934,18 +993,21 @@ declare const readFunctionMetrics: (sql: SqlExec) => FunctionCallStat[];
|
|
|
934
993
|
/**
|
|
935
994
|
* Read the coarse time-series buckets for `path` (every path when omitted),
|
|
936
995
|
* oldest-bucket first so a chart can plot them left-to-right. Creates the table
|
|
937
|
-
* first so reads on a never-called shard return `[]`.
|
|
996
|
+
* first so reads on a never-called shard return `{ buckets: [], truncated: false }`.
|
|
938
997
|
*/
|
|
939
|
-
declare const readFunctionMetricBuckets: (sql: SqlExec, path?: string) =>
|
|
940
|
-
path: string;
|
|
941
|
-
})[];
|
|
998
|
+
declare const readFunctionMetricBuckets: (sql: SqlExec, path?: string) => FunctionMetricBucketsResult;
|
|
942
999
|
/**
|
|
943
1000
|
* Aggregate the persisted accumulators into the lifetime totals the metrics
|
|
944
|
-
* health snapshot reports: total calls (`requests`), total `errors
|
|
945
|
-
*
|
|
946
|
-
*
|
|
1001
|
+
* health snapshot reports: total calls (`requests`), total `errors`. Returns
|
|
1002
|
+
* zeroes on a never-called shard.
|
|
1003
|
+
*
|
|
1004
|
+
* `capped` is true when the distinct-path cap ({@link FUNCTION_METRICS_MAX_PATHS})
|
|
1005
|
+
* has been reached — the write-side signal that a brand-new function path is
|
|
1006
|
+
* currently being refused (see `admitPath`), mirroring `readQueryInsights`'s
|
|
1007
|
+
* `capped` for query-metrics and `readMetricHistory`'s for metric-history.
|
|
947
1008
|
*/
|
|
948
1009
|
declare const readFunctionMetricsTotals: (sql: SqlExec) => {
|
|
1010
|
+
capped: boolean;
|
|
949
1011
|
errors: number;
|
|
950
1012
|
requests: number;
|
|
951
1013
|
};
|
|
@@ -978,7 +1040,7 @@ interface AiRunBinding {
|
|
|
978
1040
|
}
|
|
979
1041
|
/** Parsed `__lunora_admin__:explainIssue` payload: the folded Issue's identifying facts, plus an optional model override. */
|
|
980
1042
|
interface ExplainIssueArgs {
|
|
981
|
-
/** The Issue's culprit (
|
|
1043
|
+
/** The Issue's culprit (`<file>:<function>` or `container:<name>`), for grounding context. */
|
|
982
1044
|
culprit?: string;
|
|
983
1045
|
/** Per-request model-id override; falls back to the caller's `defaultModel`, then {@link DEFAULT_EXPLAIN_ISSUE_MODEL}. */
|
|
984
1046
|
model?: string;
|
|
@@ -1127,13 +1189,15 @@ type LogLevel = ContextLogLevel;
|
|
|
1127
1189
|
*/
|
|
1128
1190
|
interface LogEntry {
|
|
1129
1191
|
exitCode?: number;
|
|
1130
|
-
/** Structured fields from a `ctx.log
|
|
1192
|
+
/** Structured fields from a `ctx.log.<level>(message, fields)` / `ctx.log.with(fields)` call, when present. */
|
|
1131
1193
|
fields?: Record<string, unknown>;
|
|
1132
1194
|
functionPath?: string;
|
|
1133
1195
|
instance?: string;
|
|
1134
1196
|
level: LogLevel;
|
|
1135
1197
|
message: string;
|
|
1136
1198
|
timestamp: number;
|
|
1199
|
+
/** Trace the line was emitted under; absent outside a dispatch (container lifecycle, hibernation-path errors). What the Studio joins a log line to its waterfall on. */
|
|
1200
|
+
traceId?: string;
|
|
1137
1201
|
}
|
|
1138
1202
|
/**
|
|
1139
1203
|
* A bounded, in-memory ring buffer of recent {@link LogEntry} records.
|
|
@@ -1261,6 +1325,17 @@ interface MetricHistorySeries {
|
|
|
1261
1325
|
}
|
|
1262
1326
|
/** {@link readMetricHistory} result: every tracked series with its buckets. */
|
|
1263
1327
|
interface MetricHistoryResult {
|
|
1328
|
+
/**
|
|
1329
|
+
* True when the distinct-series cap has been reached — a **write-side**
|
|
1330
|
+
* signal ("this shard can no longer admit a brand-new series", see
|
|
1331
|
+
* `admitNewSeries`), not a read-side truncation flag. It is computed over
|
|
1332
|
+
* the whole table regardless of `options.sinceMs`/the row-count read
|
|
1333
|
+
* limit, so it can be `true` even when every series `readMetricHistory`
|
|
1334
|
+
* actually returned fits comfortably: the caller should read it as "a
|
|
1335
|
+
* flood of new series would currently be refused", the same thing
|
|
1336
|
+
* `readQueryInsights`'s `capped` already signals for query-metrics.
|
|
1337
|
+
*/
|
|
1338
|
+
capped: boolean;
|
|
1264
1339
|
series: MetricHistorySeries[];
|
|
1265
1340
|
}
|
|
1266
1341
|
/**
|
|
@@ -1269,7 +1344,7 @@ interface MetricHistoryResult {
|
|
|
1269
1344
|
* omitted field keeps the historical behaviour.
|
|
1270
1345
|
*/
|
|
1271
1346
|
interface MetricHistoryOptions {
|
|
1272
|
-
/** Distinct series tracked before
|
|
1347
|
+
/** Distinct series tracked before the least-recently-updated one is evicted to admit a new one (default {@link METRIC_HISTORY_MAX_SERIES}). */
|
|
1273
1348
|
maxSeries?: number;
|
|
1274
1349
|
/** Minute-buckets kept per series before older rows are trimmed (default {@link METRIC_HISTORY_BUCKET_RETENTION}). */
|
|
1275
1350
|
retentionBuckets?: number;
|
|
@@ -1306,9 +1381,12 @@ declare const recordMetricHistory: (sql: SqlExec, event: MetricEvent, exemplarTr
|
|
|
1306
1381
|
* trend line reads oldest→newest.
|
|
1307
1382
|
*
|
|
1308
1383
|
* `options.sinceMs`, when set, returns only buckets at or after this epoch-ms —
|
|
1309
|
-
* the studio's time-window selector.
|
|
1384
|
+
* the studio's time-window selector. `options.maxSeries`, mirroring the write
|
|
1385
|
+
* side's tunable, is only used to compute `capped` — it does not affect which
|
|
1386
|
+
* rows are read.
|
|
1310
1387
|
*/
|
|
1311
1388
|
declare const readMetricHistory: (sql: SqlExec, options?: {
|
|
1389
|
+
maxSeries?: number;
|
|
1312
1390
|
sinceMs?: number;
|
|
1313
1391
|
}) => MetricHistoryResult;
|
|
1314
1392
|
/** One row of the `__lunora_metrics_queries` table, as returned by `readQueryMetrics`. */
|
|
@@ -1369,14 +1447,23 @@ interface QueryInsightsResult {
|
|
|
1369
1447
|
*/
|
|
1370
1448
|
declare const readQueryInsights: (sql: SqlExec, rangeMs: number, now?: number) => QueryInsightsResult;
|
|
1371
1449
|
/**
|
|
1372
|
-
* Record one statement
|
|
1450
|
+
* Record one statement's activity. Creates the table on first call. Silently
|
|
1373
1451
|
* skips recording when the normalised statement is empty (shouldn't happen
|
|
1374
1452
|
* in practice) or when the table is already at the
|
|
1375
1453
|
* {@link QUERY_METRICS_MAX_STATEMENTS} cap and the statement is not yet
|
|
1376
|
-
* tracked.
|
|
1377
|
-
*
|
|
1454
|
+
* tracked. See `admitStatement` for how the cap check avoids an unconditional
|
|
1455
|
+
* `COUNT(*)` on every execution.
|
|
1456
|
+
*
|
|
1457
|
+
* `execCount` (default 1) lets a caller fold several executions of the SAME
|
|
1458
|
+
* statement into one call — `shard-do.ts` does this per dispatch so a
|
|
1459
|
+
* query-in-a-loop handler pays one upsert here instead of one per raw
|
|
1460
|
+
* execution. `durationMs`/`rowsRead`/`rowsWritten` are then the SUM across
|
|
1461
|
+
* `execCount` executions, exactly as `exec_count`/`total_duration_ms` already
|
|
1462
|
+
* accumulate sums across separate calls — folding before calling is
|
|
1463
|
+
* indistinguishable, from this table's point of view, from `execCount`
|
|
1464
|
+
* separate calls with the same totals.
|
|
1378
1465
|
*/
|
|
1379
|
-
declare const recordQueryMetric: (sql: SqlExec, rawSql: string, durationMs: number, rowsRead: number, rowsWritten: number, now?: number) => void;
|
|
1466
|
+
declare const recordQueryMetric: (sql: SqlExec, rawSql: string, durationMs: number, rowsRead: number, rowsWritten: number, now?: number, execCount?: number) => void;
|
|
1380
1467
|
/**
|
|
1381
1468
|
* Read all tracked statement aggregates, ordered by `total_duration_ms DESC`
|
|
1382
1469
|
* (the leaderboard's default). Creates the table first so a read on a
|
|
@@ -1393,9 +1480,9 @@ interface RequestLogEntry {
|
|
|
1393
1480
|
cacheHit?: boolean;
|
|
1394
1481
|
/** Handler wall-clock duration in milliseconds (before the subscription write-flush, matching the per-function metrics). */
|
|
1395
1482
|
durationMs: number;
|
|
1396
|
-
/** Error message when `outcome === "error"
|
|
1483
|
+
/** Error message when `outcome === "error"`, redacted like args/identity; absent on success. */
|
|
1397
1484
|
errorMessage?: string;
|
|
1398
|
-
/** The
|
|
1485
|
+
/** The `<file>:<function>` identifier dispatched, e.g. `messages:list`. */
|
|
1399
1486
|
functionPath: string;
|
|
1400
1487
|
/** Identity-claim envelope forwarded by the runtime, JSON-decoded; leaf values are redacted (the claims are PII), so only the shape survives. Absent for anonymous requests. Correlate on `userId` instead. */
|
|
1401
1488
|
identity?: Record<string, unknown>;
|
|
@@ -1413,6 +1500,8 @@ interface RequestLogEntry {
|
|
|
1413
1500
|
tablesRead: string[];
|
|
1414
1501
|
/** Tables the handler wrote (from the change tracker); empty for a read-only dispatch. */
|
|
1415
1502
|
tablesWritten: string[];
|
|
1503
|
+
/** W3C trace id (32-hex) of the dispatch; `undefined` on a row appended before this column existed. See the module docstring on the retention asymmetry. */
|
|
1504
|
+
traceId?: string;
|
|
1416
1505
|
/** Wall-clock millis when the dispatch completed. */
|
|
1417
1506
|
ts: number;
|
|
1418
1507
|
/** Acting userId forwarded by the runtime, or `undefined` when anonymous. */
|
|
@@ -1431,6 +1520,7 @@ interface AppendRequestLogEntry {
|
|
|
1431
1520
|
subscriptionsReRun?: number;
|
|
1432
1521
|
tablesRead?: string[];
|
|
1433
1522
|
tablesWritten?: string[];
|
|
1523
|
+
traceId?: string;
|
|
1434
1524
|
ts: number;
|
|
1435
1525
|
userId?: string;
|
|
1436
1526
|
}
|
|
@@ -1443,7 +1533,7 @@ interface RequestLogWriteOptions {
|
|
|
1443
1533
|
}
|
|
1444
1534
|
/** Filters for {@link readRequestLog}, all AND-combined; every value is a bound SQL parameter, so nothing here injects SQL. */
|
|
1445
1535
|
interface ReadRequestLogOptions {
|
|
1446
|
-
/** Functions whose path begins with this prefix (a
|
|
1536
|
+
/** Functions whose path begins with this prefix (a `<file>:` or `<file>:<fn>` correlation). */
|
|
1447
1537
|
functionPathPrefix?: string;
|
|
1448
1538
|
/** Upper bound on returned rows, clamped to [1, 10000]. */
|
|
1449
1539
|
limit?: number;
|
|
@@ -1473,15 +1563,20 @@ interface ErrorIssue {
|
|
|
1473
1563
|
assignee?: string;
|
|
1474
1564
|
/** Number of `error` rows folded into this Issue within the scanned window. */
|
|
1475
1565
|
count: number;
|
|
1476
|
-
/** The
|
|
1566
|
+
/** The `<file>:<function>` (or `container:<name>`) the errors came from. */
|
|
1477
1567
|
culprit: string;
|
|
1478
1568
|
/** Wall-clock millis of the oldest folded row. */
|
|
1479
1569
|
firstSeen: number;
|
|
1480
|
-
/**
|
|
1570
|
+
/**
|
|
1571
|
+
* Stable 16-char grouping hash over `functionPath :: bucket(message)`,
|
|
1572
|
+
* computed from the RAW (pre-redaction) message at write time and stored on
|
|
1573
|
+
* the row — see {@link appendRequestLogEntry} — so redacting `sampleMessage`
|
|
1574
|
+
* below can't change the grouping.
|
|
1575
|
+
*/
|
|
1481
1576
|
hash: string;
|
|
1482
1577
|
/** Wall-clock millis of the newest folded row. */
|
|
1483
1578
|
lastSeen: number;
|
|
1484
|
-
/** A representative
|
|
1579
|
+
/** A representative error message (redacted, like the durable row) — taken from the most recent folded row. */
|
|
1485
1580
|
sampleMessage: string;
|
|
1486
1581
|
/** Developer-tagged severity from the persisted triage state; absent when untriaged. */
|
|
1487
1582
|
severity?: IssueSeverity;
|
|
@@ -1507,7 +1602,7 @@ interface IssuesResult {
|
|
|
1507
1602
|
}
|
|
1508
1603
|
/** Filters for {@link readErrorIssues}; forwarded to {@link readRequestLog} with `outcome` forced to `error`. */
|
|
1509
1604
|
interface ReadIssuesOptions {
|
|
1510
|
-
/** Functions whose path begins with this prefix (a
|
|
1605
|
+
/** Functions whose path begins with this prefix (a `<file>:` or `<file>:<fn>` correlation). */
|
|
1511
1606
|
functionPathPrefix?: string;
|
|
1512
1607
|
/** Upper bound on error rows scanned before grouping, clamped to [1, 10000]. */
|
|
1513
1608
|
limit?: number;
|
|
@@ -1518,21 +1613,78 @@ interface ReadIssuesOptions {
|
|
|
1518
1613
|
/** Exact acting-userId match. */
|
|
1519
1614
|
userId?: string;
|
|
1520
1615
|
}
|
|
1616
|
+
/**
|
|
1617
|
+
* Redact the secrets / PII out of a value before it reaches the durable log or a
|
|
1618
|
+
* Logpush event, via `@visulima/redact`'s `standardRules`. Unlike a blunt
|
|
1619
|
+
* type-tag stamp this masks sensitive values by PATTERN (not just by key name)
|
|
1620
|
+
* while leaving benign values readable, so the studio's args/identity columns
|
|
1621
|
+
* stay useful. `null` / `undefined` pass through unchanged.
|
|
1622
|
+
*
|
|
1623
|
+
* What `standardRules` actually catches differs by shape, verified against its
|
|
1624
|
+
* real behavior rather than assumed from its name: on a KEYED object (`args`,
|
|
1625
|
+
* `identity`) it also matches by key name, so `{ password: "hunter2" }` and
|
|
1626
|
+
* `{ token: "…" }` ARE masked regardless of the value's shape. On a PLAIN
|
|
1627
|
+
* STRING — which is what `errorMessage`/log `fields`-as-rendered-text are —
|
|
1628
|
+
* only pattern-shaped matches apply: emails, long digit runs / structured
|
|
1629
|
+
* numeric IDs (credit-card, phone, SSN, AWS-access-key-style), and an explicit
|
|
1630
|
+
* `Bearer <token>` / `token=…`-shaped substring. A free-text `password=hunter2`
|
|
1631
|
+
* or a bare provider API key embedded in prose (e.g. `sk-live-…`) is NOT
|
|
1632
|
+
* caught on a plain string — there is no key to match against, and neither is
|
|
1633
|
+
* a recognized value pattern. So this is a PII-pattern net for rendered text,
|
|
1634
|
+
* not a general secrets scrubber; a handler that echoes a raw credential into
|
|
1635
|
+
* an error message or a log string can still leak it through here. Works on a
|
|
1636
|
+
* plain string too (`redact` traverses whatever value it's handed), which is
|
|
1637
|
+
* how {@link appendRequestLogEntry} and {@link emitRequestLogEvent} reuse this
|
|
1638
|
+
* for `errorMessage` — a validation error echoes the offending value, a
|
|
1639
|
+
* constraint error quotes the conflicting row, so the error message is at
|
|
1640
|
+
* least as PII-dense as args and gets the same treatment (with the free-text
|
|
1641
|
+
* caveat above).
|
|
1642
|
+
*
|
|
1643
|
+
* `captureRaw` is the development escape hatch: in a dev environment the dispatch
|
|
1644
|
+
* site (`isDevEnvironment`) passes `true` to skip redaction so a developer can
|
|
1645
|
+
* see real arg/identity/error values; production always redacts. The dev
|
|
1646
|
+
* decision is made at the call site from the deployment env, never inferred
|
|
1647
|
+
* here — so a real deploy that omits the env var stays redacted.
|
|
1648
|
+
*/
|
|
1649
|
+
declare const redactArgs: (value: unknown, captureRaw?: boolean) => unknown;
|
|
1521
1650
|
/**
|
|
1522
1651
|
* Create the `__lunora_reqlog__` table. `seq` is an `AUTOINCREMENT` primary
|
|
1523
1652
|
* key, giving each shard a monotonic cursor the Logs tab pages through; the
|
|
1524
1653
|
* `args`/`identity`/`tables_read`/`tables_written` columns hold JSON and are
|
|
1525
1654
|
* `NULL`/empty when none was recorded. Idempotent, so read and write paths can
|
|
1526
1655
|
* call it defensively.
|
|
1656
|
+
*
|
|
1657
|
+
* `error_fingerprint` is the {@link fingerprintError} grouping hash captured
|
|
1658
|
+
* from the RAW `error_message` at write time, before {@link appendRequestLogEntry}
|
|
1659
|
+
* redacts it — see that function's docstring. `trace_id` is the dispatch's W3C
|
|
1660
|
+
* trace id, the correlation key to the span ring and to whatever collector
|
|
1661
|
+
* `otlpSink` ships to.
|
|
1662
|
+
*
|
|
1663
|
+
* Both are also added via a guarded `ALTER TABLE`, mirroring
|
|
1664
|
+
* `function-metrics.ts`'s `ensureFunctionMetricsTables`, so a shard whose
|
|
1665
|
+
* `__lunora_reqlog__` predates a column gains it on the next call without a
|
|
1666
|
+
* migration. SQLite has no `ADD COLUMN IF NOT EXISTS`, so the duplicate-column
|
|
1667
|
+
* error from a re-run (or from the freshly-created schema above) is swallowed
|
|
1668
|
+
* per column — the loop is what keeps one column's duplicate from skipping the
|
|
1669
|
+
* next column's add.
|
|
1527
1670
|
*/
|
|
1528
1671
|
declare const ensureRequestLogTable: (sql: SqlExec) => void;
|
|
1529
1672
|
/**
|
|
1530
1673
|
* Append one dispatch to the request log, then trim the log back to the most
|
|
1531
1674
|
* recent `retention` rows (default {@link REQUEST_LOG_RETENTION}). Creates the
|
|
1532
|
-
* table first so callers needn't. Args/identity are redacted here
|
|
1533
|
-
* never reaches the durable table — callers pass the unredacted
|
|
1534
|
-
* this, unless `captureRaw` (dev only) is set. `retention` is
|
|
1535
|
-
* `LUNORA_REQUEST_LOG_RETENTION` override, threaded in by the
|
|
1675
|
+
* table first so callers needn't. Args/identity/error message are redacted here
|
|
1676
|
+
* so a raw value never reaches the durable table — callers pass the unredacted
|
|
1677
|
+
* entry and rely on this, unless `captureRaw` (dev only) is set. `retention` is
|
|
1678
|
+
* the operator's `LUNORA_REQUEST_LOG_RETENTION` override, threaded in by the
|
|
1679
|
+
* dispatch site.
|
|
1680
|
+
*
|
|
1681
|
+
* The error-grouping fingerprint is computed from `entry.errorMessage` BEFORE
|
|
1682
|
+
* it's redacted below, and the resulting hash is persisted in
|
|
1683
|
+
* `error_fingerprint`. `readErrorIssues` groups off that stored hash instead of
|
|
1684
|
+
* recomputing `fingerprintError` from the (redacted) `error_message` column, so
|
|
1685
|
+
* masking a PII-bearing value — e.g. two different `<n>`-bucketed IDs that
|
|
1686
|
+
* redact to two different tag lengths (`<DL>` vs `<BANKACC>`) — can't split an
|
|
1687
|
+
* existing Issue or change its identity.
|
|
1536
1688
|
*/
|
|
1537
1689
|
declare const appendRequestLogEntry: (sql: SqlExec, entry: AppendRequestLogEntry, options?: RequestLogWriteOptions) => void;
|
|
1538
1690
|
/**
|
|
@@ -1541,8 +1693,8 @@ declare const appendRequestLogEntry: (sql: SqlExec, entry: AppendRequestLogEntry
|
|
|
1541
1693
|
* NOT reimplement a transport: it produces a richer, lunora-attributed event and
|
|
1542
1694
|
* lets CF's existing trace-log pipe ship it. The event mirrors the durable
|
|
1543
1695
|
* `__lunora_reqlog__` row (function path, shard, user, outcome, duration, tables
|
|
1544
|
-
* read/written, cache hit), with `args` AND `
|
|
1545
|
-
* durable write so no raw PII/secret reaches the log pipeline.
|
|
1696
|
+
* read/written, cache hit), with `args`, `identity`, AND `error` redacted
|
|
1697
|
+
* exactly like the durable write so no raw PII/secret reaches the log pipeline.
|
|
1546
1698
|
*
|
|
1547
1699
|
* An `error` outcome goes to `console.error` (surfacing at error level in the
|
|
1548
1700
|
* trace so a SIEM can alert on it); everything else to `console.log`. The
|
|
@@ -1560,7 +1712,7 @@ declare const emitRequestLogEvent: (entry: AppendRequestLogEntry, options?: Requ
|
|
|
1560
1712
|
*/
|
|
1561
1713
|
type LogEventInput = LogEvent;
|
|
1562
1714
|
/**
|
|
1563
|
-
* Split a `ctx.log
|
|
1715
|
+
* Split a `ctx.log.<level>(...)` call's raw arguments into a display `message`
|
|
1564
1716
|
* and optional structured `fields`. The structured form — a message string plus
|
|
1565
1717
|
* a plain-object fields bag — is matched only for exactly `(string, object)`;
|
|
1566
1718
|
* every other shape is console-style and rendered whole (so existing
|
|
@@ -1591,11 +1743,19 @@ declare const parseLogArgs: (args: unknown[], boundFields?: LogFields) => {
|
|
|
1591
1743
|
*
|
|
1592
1744
|
* Structured `fields` (plus `traceId`/`spanId` for correlation) ARE emitted here
|
|
1593
1745
|
* — they are intentional metadata a log pipeline filters on, unlike raw `args`.
|
|
1594
|
-
*
|
|
1595
|
-
*
|
|
1596
|
-
*
|
|
1597
|
-
|
|
1598
|
-
|
|
1746
|
+
* Unlike `args`, `fields` IS redacted before it rides this console line — a
|
|
1747
|
+
* developer can attach anything to a fields bag (`ctx.log.info("charged",
|
|
1748
|
+
* { email, cardLast4 })`), and this is the one line that's told to a SIEM as
|
|
1749
|
+
* trustworthy, exactly like the request-log `args`/`identity`/`error` columns.
|
|
1750
|
+
* `options.captureRaw` (dev only) skips it, mirroring every other redaction
|
|
1751
|
+
* point in this module; the sole current caller (`ShardDO.recordUserLog`)
|
|
1752
|
+
* doesn't yet thread a dev flag through, so `fields` redacts unconditionally
|
|
1753
|
+
* there today — a conservative default, never a correctness gap. A field value
|
|
1754
|
+
* that can't be serialised (a circular object) would make `JSON.stringify`
|
|
1755
|
+
* throw and drop the whole line, so serialisation falls back to a fields-free
|
|
1756
|
+
* line rather than losing the event.
|
|
1757
|
+
*/
|
|
1758
|
+
declare const emitLogEvent: (input: LogEventInput, options?: RequestLogWriteOptions) => void;
|
|
1599
1759
|
/**
|
|
1600
1760
|
* Read request-log entries newest-first, AND-combining the supplied filters
|
|
1601
1761
|
* (function-path prefix, exact userId/shardKey/outcome, and a table-touched
|
|
@@ -1692,6 +1852,15 @@ interface TraceSpan {
|
|
|
1692
1852
|
message: string;
|
|
1693
1853
|
type: string;
|
|
1694
1854
|
};
|
|
1855
|
+
/**
|
|
1856
|
+
* Timestamped occurrences inside the span — `span.addEvent(...)` and
|
|
1857
|
+
* `span.recordException(...)`. Carried through so a handled retry or a
|
|
1858
|
+
* swallowed exception is visible on the span it happened in, which is the
|
|
1859
|
+
* only place it is interpretable. Absent when the body recorded none.
|
|
1860
|
+
*/
|
|
1861
|
+
events?: SpanEventPoint[];
|
|
1862
|
+
/** OTel `SpanKind`; absent means `"internal"`. */
|
|
1863
|
+
kind?: OtlpSpanKind;
|
|
1695
1864
|
name: string;
|
|
1696
1865
|
/** Start of this span relative to the trace's start, in ms. */
|
|
1697
1866
|
offsetMs: number;
|
|
@@ -1710,12 +1879,25 @@ interface TraceSummary {
|
|
|
1710
1879
|
rootName: string;
|
|
1711
1880
|
shardKey?: string;
|
|
1712
1881
|
/**
|
|
1713
|
-
* Spans
|
|
1714
|
-
*
|
|
1715
|
-
*
|
|
1716
|
-
*
|
|
1717
|
-
*
|
|
1718
|
-
*
|
|
1882
|
+
* Spans in **pre-order**, ready to render as waterfall rows: every span is
|
|
1883
|
+
* immediately followed by its own subtree, siblings in start order. So
|
|
1884
|
+
* indenting each row by its `depth` yields the real nesting — the row above
|
|
1885
|
+
* a `depth`-`n+1` row is genuinely its parent.
|
|
1886
|
+
*
|
|
1887
|
+
* This is a tree walk, not a sort, because no ordering on `(offsetMs,
|
|
1888
|
+
* depth)` can produce it. Given a parent, its child `a`, `a`'s child `a1`
|
|
1889
|
+
* and `a`'s sibling `b` all at offset 0, that comparator yields
|
|
1890
|
+
* `parent, a, b, a1` — which renders `a1` indented beneath `b`, under a
|
|
1891
|
+
* parent it does not belong to.
|
|
1892
|
+
*
|
|
1893
|
+
* **Why they tie is not millisecond resolution.** On the Workers runtime
|
|
1894
|
+
* `Date.now()` is pinned to the time of the last I/O — a Spectre mitigation,
|
|
1895
|
+
* not a bug — so it does not advance at all across pure computation. Every
|
|
1896
|
+
* duration in this package is `Date.now() - startTs`, which means a span
|
|
1897
|
+
* wrapping CPU-only work reports `0`, and a parent whose child performed no
|
|
1898
|
+
* I/O shares its exact start and end. See `docs/concepts/observability`
|
|
1899
|
+
* ("Span durations on Workers"); the practical consequence is that a `0 ms`
|
|
1900
|
+
* span means "no I/O happened here", not "this was fast".
|
|
1719
1901
|
*/
|
|
1720
1902
|
spans: TraceSpan[];
|
|
1721
1903
|
startTs: number;
|
|
@@ -1815,4 +1997,61 @@ declare const resolveTraceAnchor: (traceparent: string | undefined) => {
|
|
|
1815
1997
|
sampled: boolean;
|
|
1816
1998
|
traceId: string;
|
|
1817
1999
|
};
|
|
1818
|
-
export { AUTH_METRICS_BUCKETS_TABLE, AUTH_METRICS_BUCKET_MS, AUTH_METRICS_BUCKET_RETENTION, AUTH_METRICS_TABLE, type AiRunBinding, type AppendRequestLogEntry,
|
|
2000
|
+
export { AUTH_METRICS_BUCKETS_TABLE, AUTH_METRICS_BUCKET_MS, AUTH_METRICS_BUCKET_RETENTION, AUTH_METRICS_TABLE, type AiRunBinding, type AppendRequestLogEntry,
|
|
2001
|
+
/**
|
|
2002
|
+
* `@lunora/observability` — host-neutral telemetry storage and read models.
|
|
2003
|
+
*
|
|
2004
|
+
* Logs, traces, metrics, issue grouping and the security-audit view: the data
|
|
2005
|
+
* behind the Studio's observability pages. None of it is Cloudflare-specific —
|
|
2006
|
+
* it reads and writes through the SQL handle the engine hands it, and it lived
|
|
2007
|
+
* inside `@lunora/do` only because that is where the Durable Object it
|
|
2008
|
+
* instruments happens to live.
|
|
2009
|
+
*
|
|
2010
|
+
* The dependency runs `@lunora/do` → here → `@lunora/shard-engine`, never the
|
|
2011
|
+
* reverse, which is what makes this reusable by a second host rather than
|
|
2012
|
+
* merely relocated.
|
|
2013
|
+
*
|
|
2014
|
+
* This barrel is deliberately curated rather than `export *`. A star export
|
|
2015
|
+
* would promote every module internal to permanent public API — the exact
|
|
2016
|
+
* mistake `@lunora/do`'s own barrel documents having made once with the search
|
|
2017
|
+
* core. What is exported here is what a consumer actually needs.
|
|
2018
|
+
*/
|
|
2019
|
+
type AuthMetrics,
|
|
2020
|
+
/**
|
|
2021
|
+
* `@lunora/observability` — host-neutral telemetry storage and read models.
|
|
2022
|
+
*
|
|
2023
|
+
* Logs, traces, metrics, issue grouping and the security-audit view: the data
|
|
2024
|
+
* behind the Studio's observability pages. None of it is Cloudflare-specific —
|
|
2025
|
+
* it reads and writes through the SQL handle the engine hands it, and it lived
|
|
2026
|
+
* inside `@lunora/do` only because that is where the Durable Object it
|
|
2027
|
+
* instruments happens to live.
|
|
2028
|
+
*
|
|
2029
|
+
* The dependency runs `@lunora/do` → here → `@lunora/shard-engine`, never the
|
|
2030
|
+
* reverse, which is what makes this reusable by a second host rather than
|
|
2031
|
+
* merely relocated.
|
|
2032
|
+
*
|
|
2033
|
+
* This barrel is deliberately curated rather than `export *`. A star export
|
|
2034
|
+
* would promote every module internal to permanent public API — the exact
|
|
2035
|
+
* mistake `@lunora/do`'s own barrel documents having made once with the search
|
|
2036
|
+
* core. What is exported here is what a consumer actually needs.
|
|
2037
|
+
*/
|
|
2038
|
+
type AuthMetricsBucket, type ContextFetch, type ContextLogLevel, type ContextMetrics, type ContextTracer, DEFAULT_EXPLAIN_ISSUE_MODEL, type DanglingReference, type DanglingReferenceResult, type DatabaseInstrumentation, type DatabaseTally, type DatabaseTelemetryDeps, type ErrorIssue, type ExplainIssueArgs, type ExplainIssueDegradedReason, type ExplainIssueGrounding, type ExplainIssueResult, FUNCTION_METRICS_BUCKETS_TABLE, FUNCTION_METRICS_BUCKET_MS, FUNCTION_METRICS_BUCKET_RETENTION, FUNCTION_METRICS_INDEX_TABLE, FUNCTION_METRICS_MAX_PATHS, FUNCTION_METRICS_READ_LIMIT, FUNCTION_METRICS_SCANS_TABLE, FUNCTION_METRICS_TABLE, type FoldedTraces, type FunctionMetricBucket, type FunctionMetricBucketsResult, type FunctionMetricIndexHit, type HostSpanLike, type HostTracingLike, type HostTracingResolver, ISSUE_SEVERITIES, ISSUE_STATE_TABLE, ISSUE_STATUSES, type IndexHit, type IssueSeverity, type IssueState, type IssueStatePatch, type IssueStatus, type IssuesResult, LogBuffer, type LogEntry, type LogEventInput, type LogLevel, MIN_ADMIN_TOKEN_LENGTH, MIN_AUTH_SECRET_LENGTH, MetricBuffer, type MetricEvent, type MetricHistoryOptions, type MetricHistoryPoint, type MetricHistoryResult, type MetricHistorySeries, type MetricKind, type MetricSeries, type MetricsDeps, type QueryInsightBucket, type QueryInsightEntry, type QueryInsightsResult, type QueryStatEntry, REQUEST_LOG_TABLE, type ReadIssuesOptions, type ReadRequestLogOptions,
|
|
2039
|
+
/**
|
|
2040
|
+
* `@lunora/observability` — host-neutral telemetry storage and read models.
|
|
2041
|
+
*
|
|
2042
|
+
* Logs, traces, metrics, issue grouping and the security-audit view: the data
|
|
2043
|
+
* behind the Studio's observability pages. None of it is Cloudflare-specific —
|
|
2044
|
+
* it reads and writes through the SQL handle the engine hands it, and it lived
|
|
2045
|
+
* inside `@lunora/do` only because that is where the Durable Object it
|
|
2046
|
+
* instruments happens to live.
|
|
2047
|
+
*
|
|
2048
|
+
* The dependency runs `@lunora/do` → here → `@lunora/shard-engine`, never the
|
|
2049
|
+
* reverse, which is what makes this reusable by a second host rather than
|
|
2050
|
+
* merely relocated.
|
|
2051
|
+
*
|
|
2052
|
+
* This barrel is deliberately curated rather than `export *`. A star export
|
|
2053
|
+
* would promote every module internal to permanent public API — the exact
|
|
2054
|
+
* mistake `@lunora/do`'s own barrel documents having made once with the search
|
|
2055
|
+
* core. What is exported here is what a consumer actually needs.
|
|
2056
|
+
*/
|
|
2057
|
+
type RecordAuthEventInput, type RecordFunctionMetricInput, type RequestLogEntry, type RequestLogResult, type RequestLogWriteOptions, type RequestOutcome, type SecurityAuditResult, type SecurityFinding, type SecurityFindingKind, type SecurityFindingLevel, SpanBuffer, type SpanCollection, type SpanCollector, type SpanEvent, type SpanEventPoint, type SpanHandle, type OtlpSpanKind as SpanKind, type SpanLink, type SpanOptions, type TraceAnchor, type TraceSpan, type TraceSummary, type TracedFetchDeps, type TracerDeps, appendRequestLogEntry, buildSecurityAudit, createDatabaseTally, createMetrics, createSpanCollector, createTracedFetch, createTracer, dispatchRootSpan, emitLogEvent, emitRequestLogEvent, ensureAuthMetricsTables, ensureFunctionMetricsTables, ensureRequestLogTable, explainIssue, findDanglingReferences, foldTraces, formatTally, instrumentDatabase, mergeScanAttribution, parseExplainIssueArgs, parseLogArgs, readAuthMetrics, readErrorIssues, readFunctionMetricBuckets, readFunctionMetricIndexHits, readFunctionMetricScans, readFunctionMetrics, readFunctionMetricsTotals, readMetricHistory, readQueryInsights, readQueryMetrics, readRequestLog, recordAuthEvent, recordFunctionMetric, recordMetricHistory, recordQueryMetric, redactArgs, resolveTraceAnchor, upsertIssueState };
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AUTH_METRICS_BUCKETS_TABLE as t,AUTH_METRICS_BUCKET_MS as T,AUTH_METRICS_BUCKET_RETENTION as o,AUTH_METRICS_TABLE as
|
|
1
|
+
import{AUTH_METRICS_BUCKETS_TABLE as t,AUTH_METRICS_BUCKET_MS as T,AUTH_METRICS_BUCKET_RETENTION as o,AUTH_METRICS_TABLE as a,ensureAuthMetricsTables as s,readAuthMetrics as E,recordAuthEvent as _}from"./packem_shared/AUTH_METRICS_BUCKETS_TABLE-CeplWoRm.mjs";import{createMetrics as S,createSpanCollector as I,createTracedFetch as i,createTracer as n,dispatchRootSpan as M}from"./packem_shared/createMetrics-vNIDyAtP.mjs";import{createDatabaseTally as A,formatTally as C,instrumentDatabase as N}from"./packem_shared/createDatabaseTally-DCMuBKoP.mjs";import{FUNCTION_METRICS_BUCKETS_TABLE as f,FUNCTION_METRICS_BUCKET_MS as U,FUNCTION_METRICS_BUCKET_RETENTION as d,FUNCTION_METRICS_INDEX_TABLE as R,FUNCTION_METRICS_MAX_PATHS as L,FUNCTION_METRICS_READ_LIMIT as m,FUNCTION_METRICS_SCANS_TABLE as x,FUNCTION_METRICS_TABLE as B,ensureFunctionMetricsTables as F,mergeScanAttribution as l,readFunctionMetricBuckets as g,readFunctionMetricIndexHits as O,readFunctionMetricScans as H,readFunctionMetrics as y,readFunctionMetricsTotals as b,recordFunctionMetric as D}from"./packem_shared/FUNCTION_METRICS_BUCKETS_TABLE-ChlIe0vF.mjs";import{DEFAULT_EXPLAIN_ISSUE_MODEL as K,explainIssue as q,parseExplainIssueArgs as v}from"./packem_shared/DEFAULT_EXPLAIN_ISSUE_MODEL-BGGX6k5D.mjs";import{ISSUE_SEVERITIES as G,ISSUE_STATE_TABLE as X,ISSUE_STATUSES as P,upsertIssueState as k}from"./packem_shared/ISSUE_SEVERITIES-gLC4VEPQ.mjs";import{LogBuffer as j}from"./packem_shared/LogBuffer-bIvCelI-.mjs";import{M as z}from"./packem_shared/metric-buffer-QGsa8K4_.mjs";import{readMetricHistory as W,recordMetricHistory as Y}from"./packem_shared/readMetricHistory-dka8wnH-.mjs";import{readQueryInsights as $,readQueryMetrics as ee,recordQueryMetric as re}from"./packem_shared/readQueryInsights-D37H7MII.mjs";import{R as Te,a as oe,e as ae,b as se,c as Ee,p as _e,r as ce,d as Se,f as Ie}from"./packem_shared/request-log-COB2xhns.mjs";import{MIN_ADMIN_TOKEN_LENGTH as ne,MIN_AUTH_SECRET_LENGTH as Me,buildSecurityAudit as ue}from"./packem_shared/MIN_ADMIN_TOKEN_LENGTH-CidkqOQ1.mjs";import{SpanBuffer as Ce,foldTraces as Ne}from"./packem_shared/SpanBuffer-zjqCAuGp.mjs";import{findDanglingReferences as fe}from"./packem_shared/findDanglingReferences-Dxl42LBT.mjs";import{r as de}from"./packem_shared/trace-context-DfJZi_g2.mjs";export{t as AUTH_METRICS_BUCKETS_TABLE,T as AUTH_METRICS_BUCKET_MS,o as AUTH_METRICS_BUCKET_RETENTION,a as AUTH_METRICS_TABLE,K as DEFAULT_EXPLAIN_ISSUE_MODEL,f as FUNCTION_METRICS_BUCKETS_TABLE,U as FUNCTION_METRICS_BUCKET_MS,d as FUNCTION_METRICS_BUCKET_RETENTION,R as FUNCTION_METRICS_INDEX_TABLE,L as FUNCTION_METRICS_MAX_PATHS,m as FUNCTION_METRICS_READ_LIMIT,x as FUNCTION_METRICS_SCANS_TABLE,B as FUNCTION_METRICS_TABLE,G as ISSUE_SEVERITIES,X as ISSUE_STATE_TABLE,P as ISSUE_STATUSES,j as LogBuffer,ne as MIN_ADMIN_TOKEN_LENGTH,Me as MIN_AUTH_SECRET_LENGTH,z as MetricBuffer,Te as REQUEST_LOG_TABLE,Ce as SpanBuffer,oe as appendRequestLogEntry,ue as buildSecurityAudit,A as createDatabaseTally,S as createMetrics,I as createSpanCollector,i as createTracedFetch,n as createTracer,M as dispatchRootSpan,ae as emitLogEvent,se as emitRequestLogEvent,s as ensureAuthMetricsTables,F as ensureFunctionMetricsTables,Ee as ensureRequestLogTable,q as explainIssue,fe as findDanglingReferences,Ne as foldTraces,C as formatTally,N as instrumentDatabase,l as mergeScanAttribution,v as parseExplainIssueArgs,_e as parseLogArgs,E as readAuthMetrics,ce as readErrorIssues,g as readFunctionMetricBuckets,O as readFunctionMetricIndexHits,H as readFunctionMetricScans,y as readFunctionMetrics,b as readFunctionMetricsTotals,W as readMetricHistory,$ as readQueryInsights,ee as readQueryMetrics,Se as readRequestLog,_ as recordAuthEvent,D as recordFunctionMetric,Y as recordMetricHistory,re as recordQueryMetric,Ie as redactArgs,de as resolveTraceAnchor,k as upsertIssueState};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import{s as n}from"./prune-marker-B4An9Nuj.mjs";import{r as e}from"./run-sql-0aPgJkIw.mjs";const u="__lunora_auth_metrics",r="__lunora_auth_metrics_buckets",_="app",c=6e4,N=1440,A=t=>Math.floor(t/c)*c,m=t=>{e(t,`CREATE TABLE IF NOT EXISTS "${u}" (
|
|
2
|
+
key TEXT PRIMARY KEY,
|
|
3
|
+
attempts INTEGER NOT NULL DEFAULT 0,
|
|
4
|
+
failures INTEGER NOT NULL DEFAULT 0,
|
|
5
|
+
since_ms INTEGER NOT NULL DEFAULT 0
|
|
6
|
+
)`),e(t,`CREATE TABLE IF NOT EXISTS "${r}" (
|
|
7
|
+
bucket_ms INTEGER PRIMARY KEY,
|
|
8
|
+
attempts INTEGER NOT NULL DEFAULT 0,
|
|
9
|
+
failures INTEGER NOT NULL DEFAULT 0
|
|
10
|
+
)`)},I=(t,s)=>{m(t);const E=s.outcome==="fail"?1:0;e(t,`INSERT INTO "${u}" (key, attempts, failures, since_ms)
|
|
11
|
+
VALUES (?, 1, ?, ?)
|
|
12
|
+
ON CONFLICT(key) DO UPDATE SET
|
|
13
|
+
attempts = attempts + 1,
|
|
14
|
+
failures = failures + excluded.failures,
|
|
15
|
+
since_ms = CASE WHEN since_ms = 0 THEN excluded.since_ms ELSE since_ms END`,_,E,s.ts);const T=A(s.ts);e(t,`INSERT INTO "${r}" (bucket_ms, attempts, failures)
|
|
16
|
+
VALUES (?, 1, ?)
|
|
17
|
+
ON CONFLICT(bucket_ms) DO UPDATE SET
|
|
18
|
+
attempts = attempts + 1,
|
|
19
|
+
failures = failures + excluded.failures`,T,E),n(t,T)&&e(t,`DELETE FROM "${r}"
|
|
20
|
+
WHERE bucket_ms <= (
|
|
21
|
+
SELECT MAX(bucket_ms) - ? FROM "${r}"
|
|
22
|
+
)`,N*c)},S=t=>{m(t);const s=e(t,`SELECT attempts, failures, since_ms FROM "${u}" WHERE key = ?`,_).toArray()[0],E=s?.attempts??0,T=s?.failures??0,o=s?.since_ms??0,i=e(t,`SELECT bucket_ms, attempts, failures FROM "${r}" ORDER BY bucket_ms ASC`).toArray().map(a=>({attempts:a.attempts,bucketMs:a.bucket_ms,failures:a.failures}));return{attempts:E,failureRate:E===0?0:T/E,failures:T,history:i,sinceMs:o}};export{r as AUTH_METRICS_BUCKETS_TABLE,c as AUTH_METRICS_BUCKET_MS,N as AUTH_METRICS_BUCKET_RETENTION,_ as AUTH_METRICS_ROW_KEY,u as AUTH_METRICS_TABLE,m as ensureAuthMetricsTables,S as readAuthMetrics,I as recordAuthEvent};
|