@lunora/do 1.0.0-alpha.44 → 1.0.0-alpha.46
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/dist/index.d.mts +473 -64
- package/dist/index.d.ts +473 -64
- package/dist/index.mjs +1 -44
- package/dist/packem_shared/ADMIN_FUNCTIONS-PxZ8Lr9e.mjs +1 -0
- package/dist/packem_shared/AGGREGATE_SQL_FUNCTION-QYaiuty4.mjs +1 -0
- package/dist/packem_shared/AUTH_METRICS_BUCKETS_TABLE-D0wNaez7.mjs +22 -0
- package/dist/packem_shared/CDC_LOG_TABLE-E_J5LPoK.mjs +8 -0
- package/dist/packem_shared/ConflictError-C8GtJmjS.mjs +1 -0
- package/dist/packem_shared/CountRlsUnsupportedError-Cl8XpYDL.mjs +1 -0
- package/dist/packem_shared/DATA_MIGRATION_STATE_TABLE-CaO6L0Ee.mjs +31 -0
- package/dist/packem_shared/DEFAULT_MAX_RELATION_KEYS-BRdmX7WW.mjs +1 -0
- package/dist/packem_shared/FUNCTION_METRICS_BUCKETS_TABLE-BPPeqM11.mjs +56 -0
- package/dist/packem_shared/GEO_DEFAULT_PRECISION-CWAm_oYY.mjs +1 -0
- package/dist/packem_shared/LogBuffer-bIvCelI-.mjs +1 -0
- package/dist/packem_shared/MAIL_RETENTION-KmozO2NQ.mjs +18 -0
- package/dist/packem_shared/MAX_SQL_ROWS-Bdu25ASB.mjs +2 -0
- package/dist/packem_shared/MIN_ADMIN_TOKEN_LENGTH-Ch6OW6_3.mjs +1 -0
- package/dist/packem_shared/NotFoundError-J3tjf4Uo.mjs +1 -0
- package/dist/packem_shared/NotUniqueError-BcP6GOem.mjs +1 -0
- package/dist/packem_shared/RANK_TIEBREAK-DtX8zQyc.mjs +1 -0
- package/dist/packem_shared/RLS_UNWRAP_SYMBOL-C6_WX3dG.mjs +1 -0
- package/dist/packem_shared/ROOT_DO_SIZE_WARN_BYTES-n4ds54Xa.mjs +101 -0
- package/dist/packem_shared/ReactiveCache-1_9Rs7J_.mjs +1 -0
- package/dist/packem_shared/SCAN_DEP-D_yR9EeV.mjs +1 -0
- package/dist/packem_shared/SESSION_DO_TTL_DEFAULT-GvBy_DBz.mjs +1 -0
- package/dist/packem_shared/SHARD_REGISTRY_DO_NAME-Caa0fR4N.mjs +1 -0
- package/dist/packem_shared/aggregateTableName-G-eXyjcz.mjs +1 -0
- package/dist/packem_shared/applyOnDelete-BvQN7pDL.mjs +1 -0
- package/dist/packem_shared/applySelect-Bq2KOrkL.mjs +1 -0
- package/dist/packem_shared/armRestore-BNzdvQ_o.mjs +1 -0
- package/dist/packem_shared/backfillAggregateIndexes-BAQ3Fwwh.mjs +1 -0
- package/dist/packem_shared/buildFtsMatch-CV0Z7PWv.mjs +1 -0
- package/dist/packem_shared/compileWhereSql-BLcfs4QW.mjs +1 -0
- package/dist/packem_shared/constant-time-equal-BVG05Guz.mjs +1 -0
- package/dist/packem_shared/context-telemetry-O3OwE5Zu.mjs +1 -0
- package/dist/packem_shared/createMetrics-tV8rYTGJ.mjs +1 -0
- package/dist/packem_shared/createSystemReader-DcDcrtM3.mjs +1 -0
- package/dist/packem_shared/ctx-db-idempotency-wiVoGnpQ.mjs +19 -0
- package/dist/packem_shared/ctx-db-shapes-DzX_H5q8.mjs +1 -0
- package/dist/packem_shared/diffExternalSource-DMpkJta1.mjs +1 -0
- package/dist/packem_shared/do-exec-BLe9lLrN.mjs +1 -0
- package/dist/packem_shared/do-sql-BYIQTG3z.mjs +1 -0
- package/dist/packem_shared/exportShardRows-kt42wijd.mjs +1 -0
- package/dist/packem_shared/hasTrigger-_rexbWMO.mjs +1 -0
- package/dist/packem_shared/isSoftDeleted-BvhQov04.mjs +9 -0
- package/dist/packem_shared/json-response-wrh9TBPw.mjs +1 -0
- package/dist/packem_shared/materializeExternalRows-BFmT9gsw.mjs +1 -0
- package/dist/packem_shared/renderSql-B5lF5Jd9.mjs +1 -0
- package/dist/packem_shared/runShardMigrations-bxOHpfID.mjs +5 -0
- package/dist/packem_shared/security-audit-BKUOgE0x.mjs +1 -0
- package/dist/packem_shared/selectExpiredIds-BGVP3d8-.mjs +1 -0
- package/dist/packem_shared/serialize-sql-DiRzL7A4.mjs +1 -0
- package/dist/packem_shared/serveRelationFanout-Ct5D2Tbk.mjs +1 -0
- package/dist/packem_shared/stableStringify-BjLh4gvA.mjs +1 -0
- package/dist/packem_shared/stableWireKey-YEHLaX6X.mjs +1 -0
- package/dist/packem_shared/subscriptionListDeltas-Bs69JbA8.mjs +1 -0
- package/dist/packem_shared/wire-codec-Ctnni0h6.mjs +1 -0
- package/package.json +1 -1
- package/dist/packem_shared/ADMIN_FUNCTIONS-CnZkbXH_.mjs +0 -374
- package/dist/packem_shared/AGGREGATE_SQL_FUNCTION-CQsu2Xga.mjs +0 -56
- package/dist/packem_shared/AUTH_METRICS_BUCKETS_TABLE-CiHHYeJi.mjs +0 -84
- package/dist/packem_shared/CDC_LOG_TABLE-uwOJxJJZ.mjs +0 -107
- package/dist/packem_shared/ConflictError-CLoq37xH.mjs +0 -12
- package/dist/packem_shared/CountRlsUnsupportedError-BGxj0pgS.mjs +0 -133
- package/dist/packem_shared/DATA_MIGRATION_STATE_TABLE-CYwBpyTr.mjs +0 -245
- package/dist/packem_shared/DEFAULT_MAX_RELATION_KEYS-BEan1CRD.mjs +0 -211
- package/dist/packem_shared/FUNCTION_METRICS_BUCKETS_TABLE-UDNVD7FS.mjs +0 -248
- package/dist/packem_shared/GEO_DEFAULT_PRECISION-BWnsNmpP.mjs +0 -114
- package/dist/packem_shared/LogBuffer-B_Ezju_N.mjs +0 -37
- package/dist/packem_shared/MAIL_RETENTION-CPpgl-dX.mjs +0 -104
- package/dist/packem_shared/MAX_SQL_ROWS-iFAA8FbD.mjs +0 -61
- package/dist/packem_shared/MIN_ADMIN_TOKEN_LENGTH-CCAvoFlr.mjs +0 -1
- package/dist/packem_shared/NotFoundError-C70b9hLw.mjs +0 -9
- package/dist/packem_shared/NotUniqueError-DbtlWwcG.mjs +0 -2031
- package/dist/packem_shared/RANK_TIEBREAK-CXhdcA1o.mjs +0 -91
- package/dist/packem_shared/RLS_UNWRAP_SYMBOL-DTvHvRzY.mjs +0 -141
- package/dist/packem_shared/ROOT_DO_SIZE_WARN_BYTES-B_zt4RQE.mjs +0 -7676
- package/dist/packem_shared/ReactiveCache-DnSvbjil.mjs +0 -233
- package/dist/packem_shared/SCAN_DEP-DLJF8dsj.mjs +0 -19
- package/dist/packem_shared/SESSION_DO_TTL_DEFAULT-BnSKgVO4.mjs +0 -169
- package/dist/packem_shared/SHARD_REGISTRY_DO_NAME-D99roc-r.mjs +0 -144
- package/dist/packem_shared/aggregateTableName-CxNqY1Sl.mjs +0 -64
- package/dist/packem_shared/applyOnDelete-BXSq3S70.mjs +0 -176
- package/dist/packem_shared/applySelect-WQY8m62C.mjs +0 -103
- package/dist/packem_shared/armRestore-4Px61hHS.mjs +0 -49
- package/dist/packem_shared/backfillAggregateIndexes-BGTwynwh.mjs +0 -81
- package/dist/packem_shared/buildFtsMatch-BLEMawrp.mjs +0 -38
- package/dist/packem_shared/compileWhereSql-DE6yfRcQ.mjs +0 -129
- package/dist/packem_shared/constant-time-equal-BVRWZgES.mjs +0 -12
- package/dist/packem_shared/context-telemetry-CDpyil58.mjs +0 -223
- package/dist/packem_shared/createMetrics-C4I2Yanj.mjs +0 -1
- package/dist/packem_shared/createSystemReader-D12eNH13.mjs +0 -82
- package/dist/packem_shared/ctx-db-idempotency-BdcNpvY4.mjs +0 -108
- package/dist/packem_shared/ctx-db-shapes-DTeFiHYS.mjs +0 -53
- package/dist/packem_shared/diffExternalSource-CovHfdyo.mjs +0 -44
- package/dist/packem_shared/do-exec-5eQy5cEi.mjs +0 -12
- package/dist/packem_shared/do-sql-CGAgiQUz.mjs +0 -88
- package/dist/packem_shared/exportShardRows-Dy3oFZ26.mjs +0 -157
- package/dist/packem_shared/hasTrigger-5N6_Fx0A.mjs +0 -20
- package/dist/packem_shared/isSoftDeleted-CFJmhjFP.mjs +0 -217
- package/dist/packem_shared/json-response-BdbtpOhm.mjs +0 -3
- package/dist/packem_shared/materializeExternalRows-BtEGs1Fv.mjs +0 -45
- package/dist/packem_shared/renderSql-D6eUcn2N.mjs +0 -16
- package/dist/packem_shared/runShardMigrations-BVax6rYu.mjs +0 -120
- package/dist/packem_shared/security-audit-CucgBice.mjs +0 -158
- package/dist/packem_shared/selectExpiredIds-C5W29Upb.mjs +0 -18
- package/dist/packem_shared/serialize-sql-BlRUoiQe.mjs +0 -14
- package/dist/packem_shared/serveRelationFanout-k7HTh3CC.mjs +0 -21
- package/dist/packem_shared/stableStringify-mC40mZts.mjs +0 -40
- package/dist/packem_shared/stableWireKey-DKuXO7T5.mjs +0 -6
- package/dist/packem_shared/subscriptionListDeltas-CT76bYny.mjs +0 -126
- package/dist/packem_shared/wire-codec-CzQc1pvf.mjs +0 -225
package/dist/index.d.mts
CHANGED
|
@@ -1662,6 +1662,21 @@ interface DatabaseWriterLike {
|
|
|
1662
1662
|
* the table.
|
|
1663
1663
|
*/
|
|
1664
1664
|
aggregate: (tableName: string, options: AggregateOptions) => Promise<AggregateResult>;
|
|
1665
|
+
/**
|
|
1666
|
+
* The throwing sibling of `normalizeId`: returns the id when it is
|
|
1667
|
+
* structurally an id, and throws `BAD_REQUEST` otherwise. Pure — it never reads
|
|
1668
|
+
* the database. Same check as `normalizeId` (ids are opaque strings, so empty /
|
|
1669
|
+
* whitespace-bearing / NUL-bearing values are rejected), just non-nullable.
|
|
1670
|
+
*
|
|
1671
|
+
* This is the parse boundary for an id that arrived as a plain `string` (a wire
|
|
1672
|
+
* payload, a mutator's args, a change plan). Without it every such call site
|
|
1673
|
+
* writes `value as Id<"table">`, which asserts rather than checks.
|
|
1674
|
+
*
|
|
1675
|
+
* Optional on the interface (like the batch methods): the DO writer — the only one
|
|
1676
|
+
* ever assigned to `ctx.db` — always implements it, while the `.global()` (D1 /
|
|
1677
|
+
* Hyperdrive) twins that also satisfy this shape structurally do not.
|
|
1678
|
+
*/
|
|
1679
|
+
asId?: (tableName: string, id: string) => string;
|
|
1665
1680
|
/**
|
|
1666
1681
|
* Count rows in `tableName`. Uses a declared `aggregateIndex` when one
|
|
1667
1682
|
* covers the `where` keys (no scan); otherwise scans. Throws
|
|
@@ -1679,6 +1694,22 @@ interface DatabaseWriterLike {
|
|
|
1679
1694
|
delete: (id: string, expectedTable?: string, options?: {
|
|
1680
1695
|
hard?: boolean;
|
|
1681
1696
|
}) => Promise<void>;
|
|
1697
|
+
/**
|
|
1698
|
+
* Delete EVERY row in `tableName`, chunking internally until the table is
|
|
1699
|
+
* empty. Unlike `deleteWhere(tableName, {})` there is no batch cap — the whole
|
|
1700
|
+
* point is a table of unknown size (GDPR erasure, a tenant teardown), where a
|
|
1701
|
+
* `BATCH_LIMIT_EXCEEDED` at row 501 is a bug rather than a safety rail. Every
|
|
1702
|
+
* row still goes through the single-row delete pipeline so triggers, cascades,
|
|
1703
|
+
* companions, CDC, and broadcast stay correct.
|
|
1704
|
+
*
|
|
1705
|
+
* Optional on the interface (like `deleteMany`): the DO writer implements it.
|
|
1706
|
+
*/
|
|
1707
|
+
deleteAll?: (tableName: string, options?: {
|
|
1708
|
+
chunkSize?: number;
|
|
1709
|
+
hard?: boolean;
|
|
1710
|
+
}) => Promise<{
|
|
1711
|
+
deleted: number;
|
|
1712
|
+
}>;
|
|
1682
1713
|
/**
|
|
1683
1714
|
* Delete many rows by id in one call (a loop over `delete()`). The returned
|
|
1684
1715
|
* `deleted` is the number of ids **requested**, not rows actually removed (an
|
|
@@ -1911,6 +1942,26 @@ interface DatabaseWriterLike {
|
|
|
1911
1942
|
* to `ctx.db`, omits it — same pattern as the optional `rankBefore` above.
|
|
1912
1943
|
*/
|
|
1913
1944
|
system?: SystemDatabaseReader;
|
|
1945
|
+
/**
|
|
1946
|
+
* Erase every shard-local table in the schema — the account-deletion /
|
|
1947
|
+
* tenant-teardown primitive. Iterates the non-`.global()` tables and
|
|
1948
|
+
* `deleteAll`s each, returning the per-table counts.
|
|
1949
|
+
*
|
|
1950
|
+
* `.global()` tables are deliberately skipped: their rows live in D1 and are
|
|
1951
|
+
* shared across shards, so "wipe this shard" must not touch them. Pass
|
|
1952
|
+
* `options.tables` to restrict the sweep, or `options.exclude` to spare a table
|
|
1953
|
+
* (e.g. an audit log that must outlive the data).
|
|
1954
|
+
*
|
|
1955
|
+
* Optional on the interface, like the other batch primitives.
|
|
1956
|
+
*/
|
|
1957
|
+
wipeShard?: (options?: {
|
|
1958
|
+
chunkSize?: number;
|
|
1959
|
+
exclude?: ReadonlyArray<string>;
|
|
1960
|
+
tables?: ReadonlyArray<string>;
|
|
1961
|
+
}) => Promise<{
|
|
1962
|
+
deleted: number;
|
|
1963
|
+
tables: Record<string, number>;
|
|
1964
|
+
}>;
|
|
1914
1965
|
}
|
|
1915
1966
|
/**
|
|
1916
1967
|
* Thrown by `.unique()` when more than one row matches. A `LunoraError` subclass
|
|
@@ -2272,6 +2323,124 @@ interface MetricEvent {
|
|
|
2272
2323
|
*/
|
|
2273
2324
|
value: number;
|
|
2274
2325
|
}
|
|
2326
|
+
/**
|
|
2327
|
+
* Severity of a `ctx.log.*` call. The five console method names (`log` is the
|
|
2328
|
+
* default level, distinct from `info`) plus `trace`/`fatal`, so the logger spans
|
|
2329
|
+
* the full OpenTelemetry severity ramp (`trace`→`fatal`).
|
|
2330
|
+
*/
|
|
2331
|
+
type ContextLogLevel = "debug" | "error" | "fatal" | "info" | "log" | "trace" | "warn";
|
|
2332
|
+
/**
|
|
2333
|
+
* Per-event context handed to a sink alongside the event: lets a sink register
|
|
2334
|
+
* background work (a telemetry POST, a durable pipeline send) with the request's
|
|
2335
|
+
* `waitUntil` so it survives isolate teardown after the response returns. Absent
|
|
2336
|
+
* `waitUntil` (no request context) means the sink falls back to fire-and-forget.
|
|
2337
|
+
*/
|
|
2338
|
+
interface LogSinkContext {
|
|
2339
|
+
/**
|
|
2340
|
+
* Resolves this request's detected OTLP resource attributes (`service.version`,
|
|
2341
|
+
* `cloud.region`, …) on demand, or absent when the host does not detect any.
|
|
2342
|
+
*
|
|
2343
|
+
* Deliberately a resolved, allowlisted bag behind a thunk rather than the raw
|
|
2344
|
+
* `env` and `Request` the host detected them from: this context is fanned out
|
|
2345
|
+
* to **every** registered sink, including user-authored ones, so anything
|
|
2346
|
+
* reachable here should be assumed to end up in someone's debug log — and raw
|
|
2347
|
+
* `env` is every secret binding, while a raw `Request` carries the caller's
|
|
2348
|
+
* `Authorization` and `Cookie`. The thunk keeps detection lazy (a sink that
|
|
2349
|
+
* does not want resource attributes pays nothing) and hosts are expected to
|
|
2350
|
+
* memoize it per request.
|
|
2351
|
+
*/
|
|
2352
|
+
resourceAttributes?: () => Record<string, boolean | number | string>;
|
|
2353
|
+
/** Keep a background promise alive past the response (the request's `waitUntil`). */
|
|
2354
|
+
waitUntil?: (promise: Promise<unknown>) => void;
|
|
2355
|
+
}
|
|
2356
|
+
/**
|
|
2357
|
+
* One application log line emitted from a function handler via `ctx.log`.
|
|
2358
|
+
* Produced per `ctx.log.*` call (unlike a per-dispatch RPC summary).
|
|
2359
|
+
*/
|
|
2360
|
+
interface LogEvent {
|
|
2361
|
+
/** Raw arguments passed to the `ctx.log.*` call, in order. */
|
|
2362
|
+
args: unknown[];
|
|
2363
|
+
/**
|
|
2364
|
+
* OTel `LogRecord.eventName` — set when the line was emitted as a **structured
|
|
2365
|
+
* event** via `ctx.log.event(name, fields)` rather than as a human-readable
|
|
2366
|
+
* log line.
|
|
2367
|
+
*
|
|
2368
|
+
* The distinction is the whole point of the Events API: a log line's payload
|
|
2369
|
+
* is its `message` (prose, for a human, unstable), while an event's payload is
|
|
2370
|
+
* its `fields` (a named schema, for a query, stable). A collector that knows
|
|
2371
|
+
* `eventName` can index and aggregate the latter; without it, "how many
|
|
2372
|
+
* checkouts failed" degrades into a substring search over prose.
|
|
2373
|
+
*
|
|
2374
|
+
* Absent for ordinary `ctx.log.*` calls.
|
|
2375
|
+
*/
|
|
2376
|
+
eventName?: string;
|
|
2377
|
+
/**
|
|
2378
|
+
* Structured fields the caller attached (`ctx.log.info(message, fields)` or a
|
|
2379
|
+
* bound `ctx.log.with(fields)` child), already normalized to a fresh bag of
|
|
2380
|
+
* JSON-safe primitives (see `shared/log-fields.ts`). Absent for a plain
|
|
2381
|
+
* console-style call.
|
|
2382
|
+
*/
|
|
2383
|
+
fields?: LogFields;
|
|
2384
|
+
/** Function path that emitted the line, e.g. `"messages:list"`. */
|
|
2385
|
+
functionPath: string;
|
|
2386
|
+
/** Severity the line was logged at. */
|
|
2387
|
+
level: ContextLogLevel;
|
|
2388
|
+
/** Display string — the message, or the console-style args rendered and space-joined. */
|
|
2389
|
+
message: string;
|
|
2390
|
+
/** Shard key for single-shard calls; absent for the unnamed root DO. */
|
|
2391
|
+
shardKey?: string;
|
|
2392
|
+
/** Span id of the RPC this line was emitted under (trace correlation), or absent. */
|
|
2393
|
+
spanId?: string;
|
|
2394
|
+
/** Trace id this line belongs to (from the inbound `traceparent`), or absent. */
|
|
2395
|
+
traceId?: string;
|
|
2396
|
+
/** Wall-clock millis when the line was emitted. */
|
|
2397
|
+
ts: number;
|
|
2398
|
+
/** Acting userId, or absent when anonymous. */
|
|
2399
|
+
userId?: string;
|
|
2400
|
+
}
|
|
2401
|
+
/**
|
|
2402
|
+
* The OTel `SpanKind` union, in the spec's own words rather than its wire
|
|
2403
|
+
* numbers, so a call site reads `{ kind: "client" }` instead of `{ kind: 3 }`.
|
|
2404
|
+
*
|
|
2405
|
+
* Kind is not cosmetic: a service map is built from it. A CLIENT span with no
|
|
2406
|
+
* matching SERVER span on the other side is a dropped hop; PRODUCER/CONSUMER is
|
|
2407
|
+
* what makes a queue render as an async edge rather than a synchronous call.
|
|
2408
|
+
* Getting it wrong is why "everything is INTERNAL" traces produce no topology.
|
|
2409
|
+
*/
|
|
2410
|
+
type OtlpSpanKind = "client" | "consumer" | "internal" | "producer" | "server";
|
|
2411
|
+
/**
|
|
2412
|
+
* One timestamped occurrence inside a span — OTel's `Span.events`.
|
|
2413
|
+
*
|
|
2414
|
+
* The right shape for something that has a moment but no duration: a retry, a
|
|
2415
|
+
* cache miss, a validation failure, a thrown exception. Modelling those as
|
|
2416
|
+
* near-zero-width child spans clutters the waterfall, and modelling them as
|
|
2417
|
+
* separate log lines loses the "which span was I in" correlation that makes them
|
|
2418
|
+
* useful in the first place.
|
|
2419
|
+
*/
|
|
2420
|
+
interface SpanEventPoint {
|
|
2421
|
+
/** Structured attributes, normalized like a span's own. */
|
|
2422
|
+
attributes?: LogFields;
|
|
2423
|
+
/** Event name, e.g. `"exception"` or `"cache.miss"`. */
|
|
2424
|
+
name: string;
|
|
2425
|
+
/** Wall-clock millis when it happened. */
|
|
2426
|
+
ts: number;
|
|
2427
|
+
}
|
|
2428
|
+
/**
|
|
2429
|
+
* A causal reference to a span in ANOTHER trace — OTel's `Span.links`.
|
|
2430
|
+
*
|
|
2431
|
+
* The standard answer to fan-in: a queue consumer processing a batch of 100
|
|
2432
|
+
* messages links to the 100 producing spans rather than parenting to one of them
|
|
2433
|
+
* (arbitrary) or all of them (impossible). The traces stay separately navigable
|
|
2434
|
+
* and the causal edge survives.
|
|
2435
|
+
*/
|
|
2436
|
+
interface SpanLink {
|
|
2437
|
+
/** Attributes describing the relationship, e.g. `{ "link.kind": "enqueued_by" }`. */
|
|
2438
|
+
attributes?: LogFields;
|
|
2439
|
+
/** Linked span id (16-hex). */
|
|
2440
|
+
spanId: string;
|
|
2441
|
+
/** Linked trace id (32-hex). */
|
|
2442
|
+
traceId: string;
|
|
2443
|
+
}
|
|
2275
2444
|
/**
|
|
2276
2445
|
* One span produced by a `ctx.trace(name, fn)` call, or the synthetic root span
|
|
2277
2446
|
* the shard records for the dispatch itself so a waterfall has a bar to hang
|
|
@@ -2291,10 +2460,61 @@ interface MetricEvent {
|
|
|
2291
2460
|
* value winning on a key clash.
|
|
2292
2461
|
*/
|
|
2293
2462
|
interface SpanHandle {
|
|
2463
|
+
/**
|
|
2464
|
+
* Record a timestamped {@link SpanEventPoint} on the enclosing span — a retry,
|
|
2465
|
+
* a cache miss, a state transition. Prefer this over an extra `ctx.log` line
|
|
2466
|
+
* for anything that only makes sense *relative to this span*: it rides the
|
|
2467
|
+
* span's own export, so it costs no additional log record and can never be
|
|
2468
|
+
* separated from its context.
|
|
2469
|
+
*/
|
|
2470
|
+
addEvent: (name: string, attributes?: LogFields) => void;
|
|
2471
|
+
/**
|
|
2472
|
+
* Link this span to one in another trace (see {@link SpanLink}) — how a batch
|
|
2473
|
+
* consumer points back at the requests that enqueued its items without
|
|
2474
|
+
* collapsing every producer into one giant trace.
|
|
2475
|
+
*/
|
|
2476
|
+
addLink: (link: SpanLink) => void;
|
|
2477
|
+
/**
|
|
2478
|
+
* Record a caught exception as the OTel-conventional `exception` span event
|
|
2479
|
+
* (`exception.type` / `exception.message` / `exception.stacktrace`).
|
|
2480
|
+
*
|
|
2481
|
+
* Distinct from letting the error propagate: this is for an error you
|
|
2482
|
+
* **handled** — a retried request, a fallback that worked — which should be
|
|
2483
|
+
* visible in the trace without marking the span failed. An error that escapes
|
|
2484
|
+
* the span body is recorded automatically and *does* set the error status.
|
|
2485
|
+
*/
|
|
2486
|
+
recordException: (error: unknown) => void;
|
|
2294
2487
|
/** Set one attribute on the enclosing span (merged at record time; post-hoc wins on key clash). */
|
|
2295
2488
|
setAttribute: (key: string, value: LogFields[string]) => void;
|
|
2296
2489
|
/** Merge attributes onto the enclosing span (post-hoc wins on key clash). */
|
|
2297
2490
|
setAttributes: (fields: LogFields) => void;
|
|
2491
|
+
/**
|
|
2492
|
+
* The W3C ids of the span this handle refers to.
|
|
2493
|
+
*
|
|
2494
|
+
* A handle that cannot say WHICH span it is forces every consumer that needs
|
|
2495
|
+
* the identity — a `traceparent` for a hand-rolled outbound call, a trace id
|
|
2496
|
+
* echoed in an error response so a user can quote it in a bug report, an
|
|
2497
|
+
* `@opentelemetry/api` bridge parenting a third-party library's spans — to
|
|
2498
|
+
* reach around the API for it.
|
|
2499
|
+
*/
|
|
2500
|
+
spanContext: () => {
|
|
2501
|
+
spanId: string;
|
|
2502
|
+
traceId: string;
|
|
2503
|
+
};
|
|
2504
|
+
}
|
|
2505
|
+
/** Options accepted by `ctx.trace(name, fn, options)` beyond the plain attribute bag. */
|
|
2506
|
+
interface SpanOptions {
|
|
2507
|
+
/** Start attributes, snapshotted before the body runs. */
|
|
2508
|
+
attributes?: LogFields;
|
|
2509
|
+
/**
|
|
2510
|
+
* OTel `SpanKind`, default `"internal"`. Set `"client"` for a call OUT to
|
|
2511
|
+
* another service, `"producer"`/`"consumer"` for queue hops — this is what a
|
|
2512
|
+
* collector builds its service map from, so leaving everything `"internal"`
|
|
2513
|
+
* yields a trace with no topology.
|
|
2514
|
+
*/
|
|
2515
|
+
kind?: OtlpSpanKind;
|
|
2516
|
+
/** Links to spans in other traces, known at start (see {@link SpanLink}). */
|
|
2517
|
+
links?: SpanLink[];
|
|
2298
2518
|
}
|
|
2299
2519
|
interface SpanEvent {
|
|
2300
2520
|
/**
|
|
@@ -2305,6 +2525,12 @@ interface SpanEvent {
|
|
|
2305
2525
|
attributes?: LogFields;
|
|
2306
2526
|
/** Wall-clock duration of the span body, in milliseconds. */
|
|
2307
2527
|
durationMs: number;
|
|
2528
|
+
/**
|
|
2529
|
+
* Timestamped occurrences inside the span (see {@link SpanEventPoint}) —
|
|
2530
|
+
* `ctx.trace`'s `span.addEvent(...)` / `span.recordException(...)`. Absent
|
|
2531
|
+
* when the body recorded none.
|
|
2532
|
+
*/
|
|
2533
|
+
events?: SpanEventPoint[];
|
|
2308
2534
|
/**
|
|
2309
2535
|
* Populated when the span body threw. `type` is the error's constructor name
|
|
2310
2536
|
* (or its `LunoraError` code); `message` is the human-readable string and may
|
|
@@ -2321,6 +2547,14 @@ interface SpanEvent {
|
|
|
2321
2547
|
* reuses its context — the same attribution rule `ctx.log` follows.
|
|
2322
2548
|
*/
|
|
2323
2549
|
functionPath: string;
|
|
2550
|
+
/**
|
|
2551
|
+
* OTel `SpanKind`. Absent means `"internal"` — the overwhelming majority of
|
|
2552
|
+
* `ctx.trace` spans — so the common case costs no bytes on the wire and every
|
|
2553
|
+
* pre-existing recorded span stays valid.
|
|
2554
|
+
*/
|
|
2555
|
+
kind?: OtlpSpanKind;
|
|
2556
|
+
/** Causal references to spans in other traces (see {@link SpanLink}). Absent when none. */
|
|
2557
|
+
links?: SpanLink[];
|
|
2324
2558
|
/** Caller-supplied span name, e.g. `"stripe.charge"`. */
|
|
2325
2559
|
name: string;
|
|
2326
2560
|
/** True when the span body returned without throwing. */
|
|
@@ -2366,7 +2600,7 @@ interface SpanEvent {
|
|
|
2366
2600
|
* which it can attach attributes only known *after* it resolves (post-hoc). It is
|
|
2367
2601
|
* a trailing parameter, so a `(trace) => …` body that ignores it still conforms.
|
|
2368
2602
|
*/
|
|
2369
|
-
type ContextTracer = <T>(name: string, function_: (trace: ContextTracer, span: SpanHandle) => Promise<T> | T,
|
|
2603
|
+
type ContextTracer = <T>(name: string, function_: (trace: ContextTracer, span: SpanHandle) => Promise<T> | T, options?: LogFields | SpanOptions) => Promise<T>;
|
|
2370
2604
|
/** Structural shape of the `ctx.metrics` recorder (see the server `LunoraMetrics`). */
|
|
2371
2605
|
interface ContextMetrics {
|
|
2372
2606
|
count: (name: string, value?: number, attributes?: LogFields) => void;
|
|
@@ -2452,6 +2686,12 @@ interface MetricsDeps {
|
|
|
2452
2686
|
record: (event: MetricEvent) => void;
|
|
2453
2687
|
shardKey: string | undefined;
|
|
2454
2688
|
}
|
|
2689
|
+
/** Everything a {@link SpanHandle}'s body attached, ready to merge into the recorded span. */
|
|
2690
|
+
interface SpanCollection {
|
|
2691
|
+
attributes: Record<string, LogFields[string]>;
|
|
2692
|
+
events: SpanEventPoint[];
|
|
2693
|
+
links: SpanLink[];
|
|
2694
|
+
}
|
|
2455
2695
|
/**
|
|
2456
2696
|
* Build the `ctx.trace` span factory for one dispatched function.
|
|
2457
2697
|
*
|
|
@@ -2509,6 +2749,8 @@ interface MetricsDeps {
|
|
|
2509
2749
|
* waterfall is unaffected.
|
|
2510
2750
|
*/
|
|
2511
2751
|
declare const createTracer: (deps: TracerDeps) => ContextTracer;
|
|
2752
|
+
/** The `fetch` shape `ctx.fetch` exposes — the platform global's, narrowed to what we wrap. */
|
|
2753
|
+
type ContextFetch = (input: Request | string | URL, init?: RequestInit) => Promise<Response>;
|
|
2512
2754
|
/**
|
|
2513
2755
|
* Build the `ctx.metrics` recorder for one dispatched function.
|
|
2514
2756
|
*
|
|
@@ -2531,6 +2773,14 @@ declare const createMetrics: (deps: MetricsDeps) => ContextMetrics;
|
|
|
2531
2773
|
*/
|
|
2532
2774
|
declare const dispatchRootSpan: (input: {
|
|
2533
2775
|
anchor: TraceAnchor;
|
|
2776
|
+
/**
|
|
2777
|
+
* What the handler attached to the dispatch through `ctx.span` — the **wide
|
|
2778
|
+
* event**. These are the attributes that would otherwise have been scattered
|
|
2779
|
+
* across a dozen `ctx.log` lines; carrying them on the one span that already
|
|
2780
|
+
* exists per request is the OTel-native way to get a wide event without
|
|
2781
|
+
* multiplying log records.
|
|
2782
|
+
*/
|
|
2783
|
+
collected?: SpanCollection;
|
|
2534
2784
|
durationMs: number;
|
|
2535
2785
|
failure: {
|
|
2536
2786
|
thrown: unknown;
|
|
@@ -3736,67 +3986,6 @@ declare const pointInBoundingBox: (point: GeoPoint, box: GeoBoundingBox) => bool
|
|
|
3736
3986
|
* in the box is scanned before the exact `pointInBoundingBox` refine.
|
|
3737
3987
|
*/
|
|
3738
3988
|
declare const boundingBoxGeohashes: (box: GeoBoundingBox) => string[];
|
|
3739
|
-
/**
|
|
3740
|
-
* Severity of a `ctx.log.*` call. The five console method names (`log` is the
|
|
3741
|
-
* default level, distinct from `info`) plus `trace`/`fatal`, so the logger spans
|
|
3742
|
-
* the full OpenTelemetry severity ramp (`trace`→`fatal`).
|
|
3743
|
-
*/
|
|
3744
|
-
type ContextLogLevel = "debug" | "error" | "fatal" | "info" | "log" | "trace" | "warn";
|
|
3745
|
-
/**
|
|
3746
|
-
* Per-event context handed to a sink alongside the event: lets a sink register
|
|
3747
|
-
* background work (a telemetry POST, a durable pipeline send) with the request's
|
|
3748
|
-
* `waitUntil` so it survives isolate teardown after the response returns. Absent
|
|
3749
|
-
* `waitUntil` (no request context) means the sink falls back to fire-and-forget.
|
|
3750
|
-
*/
|
|
3751
|
-
interface LogSinkContext {
|
|
3752
|
-
/**
|
|
3753
|
-
* Resolves this request's detected OTLP resource attributes (`service.version`,
|
|
3754
|
-
* `cloud.region`, …) on demand, or absent when the host does not detect any.
|
|
3755
|
-
*
|
|
3756
|
-
* Deliberately a resolved, allowlisted bag behind a thunk rather than the raw
|
|
3757
|
-
* `env` and `Request` the host detected them from: this context is fanned out
|
|
3758
|
-
* to **every** registered sink, including user-authored ones, so anything
|
|
3759
|
-
* reachable here should be assumed to end up in someone's debug log — and raw
|
|
3760
|
-
* `env` is every secret binding, while a raw `Request` carries the caller's
|
|
3761
|
-
* `Authorization` and `Cookie`. The thunk keeps detection lazy (a sink that
|
|
3762
|
-
* does not want resource attributes pays nothing) and hosts are expected to
|
|
3763
|
-
* memoize it per request.
|
|
3764
|
-
*/
|
|
3765
|
-
resourceAttributes?: () => Record<string, boolean | number | string>;
|
|
3766
|
-
/** Keep a background promise alive past the response (the request's `waitUntil`). */
|
|
3767
|
-
waitUntil?: (promise: Promise<unknown>) => void;
|
|
3768
|
-
}
|
|
3769
|
-
/**
|
|
3770
|
-
* One application log line emitted from a function handler via `ctx.log`.
|
|
3771
|
-
* Produced per `ctx.log.*` call (unlike a per-dispatch RPC summary).
|
|
3772
|
-
*/
|
|
3773
|
-
interface LogEvent {
|
|
3774
|
-
/** Raw arguments passed to the `ctx.log.*` call, in order. */
|
|
3775
|
-
args: unknown[];
|
|
3776
|
-
/**
|
|
3777
|
-
* Structured fields the caller attached (`ctx.log.info(message, fields)` or a
|
|
3778
|
-
* bound `ctx.log.with(fields)` child), already normalized to a fresh bag of
|
|
3779
|
-
* JSON-safe primitives (see `shared/log-fields.ts`). Absent for a plain
|
|
3780
|
-
* console-style call.
|
|
3781
|
-
*/
|
|
3782
|
-
fields?: LogFields;
|
|
3783
|
-
/** Function path that emitted the line, e.g. `"messages:list"`. */
|
|
3784
|
-
functionPath: string;
|
|
3785
|
-
/** Severity the line was logged at. */
|
|
3786
|
-
level: ContextLogLevel;
|
|
3787
|
-
/** Display string — the message, or the console-style args rendered and space-joined. */
|
|
3788
|
-
message: string;
|
|
3789
|
-
/** Shard key for single-shard calls; absent for the unnamed root DO. */
|
|
3790
|
-
shardKey?: string;
|
|
3791
|
-
/** Span id of the RPC this line was emitted under (trace correlation), or absent. */
|
|
3792
|
-
spanId?: string;
|
|
3793
|
-
/** Trace id this line belongs to (from the inbound `traceparent`), or absent. */
|
|
3794
|
-
traceId?: string;
|
|
3795
|
-
/** Wall-clock millis when the line was emitted. */
|
|
3796
|
-
ts: number;
|
|
3797
|
-
/** Acting userId, or absent when anonymous. */
|
|
3798
|
-
userId?: string;
|
|
3799
|
-
}
|
|
3800
3989
|
/**
|
|
3801
3990
|
* Severity of a buffered log entry — the full seven-tier `ctx.log` ramp
|
|
3802
3991
|
* (`trace`→`fatal`), not a console-shaped subset. The buffer used to fold the
|
|
@@ -4166,11 +4355,14 @@ declare class RlsRequiredError extends LunoraError {
|
|
|
4166
4355
|
readonly table: string;
|
|
4167
4356
|
constructor(table: string);
|
|
4168
4357
|
}
|
|
4169
|
-
/** Minimal schema projection the guard reads: the RLS mode + per-table opt-out. */
|
|
4358
|
+
/** Minimal schema projection the guard reads: the RLS mode + per-table opt-out and shard mode. */
|
|
4170
4359
|
interface GuardableSchema {
|
|
4171
4360
|
readonly rlsMode?: "required";
|
|
4172
4361
|
readonly tables: Record<string, {
|
|
4173
4362
|
readonly isPublic?: boolean;
|
|
4363
|
+
readonly shardMode?: {
|
|
4364
|
+
readonly kind?: string;
|
|
4365
|
+
};
|
|
4174
4366
|
}>;
|
|
4175
4367
|
}
|
|
4176
4368
|
/**
|
|
@@ -4359,6 +4551,18 @@ declare class SessionDO {
|
|
|
4359
4551
|
private handleGet;
|
|
4360
4552
|
private handleRevoke;
|
|
4361
4553
|
}
|
|
4554
|
+
/**
|
|
4555
|
+
* How much detail `ctx.db` auto-instrumentation produces.
|
|
4556
|
+
*
|
|
4557
|
+
* `"summary"` (default) — aggregate counters on the dispatch's wide event: no
|
|
4558
|
+
* extra spans, no extra log records, and a cost that does not grow with call count.
|
|
4559
|
+
*
|
|
4560
|
+
* `"spans"` — one span per database call. The full waterfall, at the price of a
|
|
4561
|
+
* span per call; right when diagnosing, noisy as a permanent default.
|
|
4562
|
+
*
|
|
4563
|
+
* `"off"` — no database telemetry at all.
|
|
4564
|
+
*/
|
|
4565
|
+
type DatabaseInstrumentation = "off" | "spans" | "summary";
|
|
4362
4566
|
/** One table's resolved TTL policy, as surfaced to the DO alarm by the generated shard subclass. */
|
|
4363
4567
|
interface TtlSweepSpec {
|
|
4364
4568
|
/** Millisecond offset added to `field` to derive the expiry (`field + after`); absent ⇒ `field` is the absolute expiry. */
|
|
@@ -4427,6 +4631,15 @@ declare const subscriptionListDeltas: (previousJson: string, nextResult: unknown
|
|
|
4427
4631
|
* `@lunora/runtime`'s `ObservabilitySink` without taking a dependency on it.
|
|
4428
4632
|
*/
|
|
4429
4633
|
interface TelemetrySink {
|
|
4634
|
+
/**
|
|
4635
|
+
* Ship anything the sink has buffered, now. Called at the end of every
|
|
4636
|
+
* dispatch (and of an alarm / socket message), so a batching sink — which
|
|
4637
|
+
* exports one request per invocation instead of one per event — is never left
|
|
4638
|
+
* holding telemetry a quiet shard would sit on indefinitely. Optional: a
|
|
4639
|
+
* non-buffering sink simply omits it. Mirror of `@lunora/runtime`'s
|
|
4640
|
+
* `ObservabilitySink.flush`.
|
|
4641
|
+
*/
|
|
4642
|
+
flush?: (context?: LogSinkContext) => void;
|
|
4430
4643
|
/**
|
|
4431
4644
|
* **Opt-in, EXPERIMENTAL, default off.** When `true`, each `ctx.trace` span is
|
|
4432
4645
|
* ALSO emitted as a Cloudflare **custom span** (`tracing.enterSpan` from
|
|
@@ -4441,9 +4654,25 @@ interface TelemetrySink {
|
|
|
4441
4654
|
* `fuseCloudflareTraces`; see {@link createTracer} for the double-export caveat.
|
|
4442
4655
|
*/
|
|
4443
4656
|
fuseCloudflareTraces?: boolean;
|
|
4657
|
+
/**
|
|
4658
|
+
* Detail level for automatic `ctx.db` instrumentation. Default `"summary"` —
|
|
4659
|
+
* aggregate counters folded onto the dispatch's root span when one is recorded,
|
|
4660
|
+
* so cost does not grow with call count and an uninstrumented handler still
|
|
4661
|
+
* emits nothing extra. Mirror of `@lunora/runtime`'s `ObservabilitySink`.
|
|
4662
|
+
*/
|
|
4663
|
+
instrumentDatabase?: DatabaseInstrumentation;
|
|
4444
4664
|
onLog?: (event: LogEventInput, context?: LogSinkContext) => void;
|
|
4445
4665
|
onMetric?: (event: MetricEvent, context?: LogSinkContext) => void;
|
|
4446
4666
|
onSpan?: (event: SpanEvent, context?: LogSinkContext) => void;
|
|
4667
|
+
/**
|
|
4668
|
+
* Whether `ctx.fetch` is instrumented — a CLIENT span per outbound call plus
|
|
4669
|
+
* W3C `traceparent` propagation to the callee. Default on; set `false` to get
|
|
4670
|
+
* the bare platform `fetch`, or an object to control which destinations
|
|
4671
|
+
* receive trace context. Mirror of `@lunora/runtime`'s `ObservabilitySink`.
|
|
4672
|
+
*/
|
|
4673
|
+
traceFetch?: boolean | {
|
|
4674
|
+
propagate?: ((url: URL) => boolean) | boolean;
|
|
4675
|
+
};
|
|
4447
4676
|
}
|
|
4448
4677
|
/**
|
|
4449
4678
|
* Structural shape of the `ctx.log` logger the DO builds (see the server
|
|
@@ -4453,6 +4682,20 @@ interface TelemetrySink {
|
|
|
4453
4682
|
interface ContextLogger {
|
|
4454
4683
|
debug: (...args: unknown[]) => void;
|
|
4455
4684
|
error: (...args: unknown[]) => void;
|
|
4685
|
+
/**
|
|
4686
|
+
* Emit a **structured event** — OTel's Events API — rather than a log line.
|
|
4687
|
+
*
|
|
4688
|
+
* The difference is what carries the meaning. A log line's payload is its
|
|
4689
|
+
* message: prose, written for a human, free to be reworded next week. An
|
|
4690
|
+
* event's payload is its `fields` under a stable `name`, written for a query.
|
|
4691
|
+
* Only the second can answer "how many checkouts failed, by plan, this hour"
|
|
4692
|
+
* without a substring search over English.
|
|
4693
|
+
*
|
|
4694
|
+
* On the wire this sets OTel's `LogRecord.eventName` (plus the `event.name`
|
|
4695
|
+
* attribute for collectors predating that field), so any OTLP backend
|
|
4696
|
+
* recognises it without Lunora-specific configuration.
|
|
4697
|
+
*/
|
|
4698
|
+
event: (name: string, fields?: LogFields) => void;
|
|
4456
4699
|
fatal: (...args: unknown[]) => void;
|
|
4457
4700
|
info: (...args: unknown[]) => void;
|
|
4458
4701
|
log: (...args: unknown[]) => void;
|
|
@@ -4893,6 +5136,34 @@ declare abstract class ShardDO {
|
|
|
4893
5136
|
* by `span.traceId`, and deleted in the `finally`.
|
|
4894
5137
|
*/
|
|
4895
5138
|
private traceSampling;
|
|
5139
|
+
/**
|
|
5140
|
+
* The per-dispatch **wide event** — everything a handler attached through
|
|
5141
|
+
* `ctx.span` — keyed by `traceId` for exactly the reason `traceSampling`
|
|
5142
|
+
* is: a DO interleaves dispatches across `await` points, and a flat field
|
|
5143
|
+
* would let a sibling dispatch's attributes land on this one's span.
|
|
5144
|
+
*
|
|
5145
|
+
* A wide event is the answer to "monitor everything without drowning in
|
|
5146
|
+
* logs": rather than a dozen `ctx.log.info` lines whose only readers are
|
|
5147
|
+
* humans grepping, a handler accumulates its facts onto the ONE span the
|
|
5148
|
+
* dispatch already emits, and the collector gets a single richly-attributed
|
|
5149
|
+
* record it can group and aggregate. Cost is flat — one span per request,
|
|
5150
|
+
* however much you attach.
|
|
5151
|
+
*
|
|
5152
|
+
* Keyed by {@link dispatchSpanKey} (trace id AND root span id) rather than
|
|
5153
|
+
* `traceId` alone — see there for the concurrent-dispatch collision that
|
|
5154
|
+
* distinction prevents.
|
|
5155
|
+
*
|
|
5156
|
+
* Bounded by {@link MAX_TRACKED_DISPATCH_SPANS}: the dispatch `finally`
|
|
5157
|
+
* deletes its own entry, but a ctx built outside a dispatch (an alarm, a
|
|
5158
|
+
* subscription re-run) mints its own anchor and has no such boundary, so the
|
|
5159
|
+
* map is FIFO-capped rather than trusted to drain.
|
|
5160
|
+
*/
|
|
5161
|
+
private dispatchSpans;
|
|
5162
|
+
/**
|
|
5163
|
+
* The most recent telemetry sink seen while building a ctx — the flush handle
|
|
5164
|
+
* for paths that have no ctx of their own (see `flushTelemetry`).
|
|
5165
|
+
*/
|
|
5166
|
+
private lastTelemetrySink;
|
|
4896
5167
|
/**
|
|
4897
5168
|
* Client-issued idempotency key for the in-flight mutation, forwarded via the
|
|
4898
5169
|
* `x-lunora-mutation-id` header. When set, the dispatch path dedups the call
|
|
@@ -5169,6 +5440,19 @@ declare abstract class ShardDO {
|
|
|
5169
5440
|
* Hibernation API: invoked by the runtime when a message arrives on a
|
|
5170
5441
|
* hibernated socket. Subclasses can override this to intercept; the
|
|
5171
5442
|
* default decodes a {@link SubscriptionEnvelope} and updates the registry.
|
|
5443
|
+
*
|
|
5444
|
+
* Deliberately NOT wrapped in {@link withTriggerTrace}, unlike `alarm`. Frame
|
|
5445
|
+
* rate here is unbounded — a whisper fan-out or presence stream drives many
|
|
5446
|
+
* per second — and minting a trace anchor per frame costs two `crypto`
|
|
5447
|
+
* draws plus hex encoding, which measurably regressed the fan-out benchmark
|
|
5448
|
+
* (~30% on `broadcastWhisper` to 128 members). The trade is also worse than it
|
|
5449
|
+
* looks: a frame's work is a subscription re-evaluation whose data flow is
|
|
5450
|
+
* already attributable to the RPC that wrote the data, so the root span buys
|
|
5451
|
+
* little. An alarm is the opposite — low frequency, and genuinely
|
|
5452
|
+
* un-attributable background work — which is why that one keeps the wrapper.
|
|
5453
|
+
*
|
|
5454
|
+
* `ctx.trace`/`ctx.span` inside a frame still record; they just anchor to the
|
|
5455
|
+
* ctx's own trace rather than a per-frame root.
|
|
5172
5456
|
*/
|
|
5173
5457
|
webSocketMessage(ws: WebSocket, message: string | ArrayBuffer): Promise<void>;
|
|
5174
5458
|
/**
|
|
@@ -6017,7 +6301,7 @@ declare abstract class ShardDO {
|
|
|
6017
6301
|
* Unlike request-log args, `ctx.log` args are NOT redacted: the developer
|
|
6018
6302
|
* chose to log them, exactly like a raw `console.log`.
|
|
6019
6303
|
*/
|
|
6020
|
-
protected recordUserLog(functionPath: string, level: ContextLogLevel, args: unknown[], message: string, fields: Record<string, unknown> | undefined, sink?: TelemetrySink): void;
|
|
6304
|
+
protected recordUserLog(functionPath: string, level: ContextLogLevel, args: unknown[], message: string, fields: Record<string, unknown> | undefined, sink?: TelemetrySink, eventName?: string, anchor?: TraceAnchor): void;
|
|
6021
6305
|
/**
|
|
6022
6306
|
* Build the `ctx.log` logger for one dispatched function. Each severity method
|
|
6023
6307
|
* accepts either the structured form (`(message, fields)`) or console-style
|
|
@@ -6043,6 +6327,44 @@ declare abstract class ShardDO {
|
|
|
6043
6327
|
* resolved sink sets `fuseCloudflareTraces` (see {@link resolveCloudflareTracing}).
|
|
6044
6328
|
*/
|
|
6045
6329
|
protected makeTracer(functionPath: string, sink?: TelemetrySink, anchor?: TraceAnchor): ContextTracer;
|
|
6330
|
+
/**
|
|
6331
|
+
* The trace anchor a ctx's `trace` and `span` both hang off.
|
|
6332
|
+
*
|
|
6333
|
+
* Resolved once per `buildCtx` and shared, so `ctx.trace` spans and the
|
|
6334
|
+
* `ctx.span` wide event land in the SAME trace. Previously each consumer
|
|
6335
|
+
* minted its own fallback when there was no current trace, which was fine
|
|
6336
|
+
* while `ctx.trace` was the only consumer and silently splits the two now
|
|
6337
|
+
* that there are two.
|
|
6338
|
+
*
|
|
6339
|
+
* `identityScoped` marks a deferred/interleaved caller (a subscription seed
|
|
6340
|
+
* or refresh): those must NOT inherit the shared per-request trace, which a
|
|
6341
|
+
* concurrent RPC may have re-set, so they mint their own self-contained one.
|
|
6342
|
+
*/
|
|
6343
|
+
protected resolveDispatchAnchor(identityScoped: boolean): TraceAnchor;
|
|
6344
|
+
/**
|
|
6345
|
+
* Wrap `ctx.db` in automatic instrumentation — see {@link instrumentDatabase}
|
|
6346
|
+
* for why the default is aggregate counters rather than a span per call.
|
|
6347
|
+
*
|
|
6348
|
+
* A no-op (returning the database untouched) with no sink configured or with
|
|
6349
|
+
* `instrumentDatabase: "off"`, so a deployment that collects nothing pays
|
|
6350
|
+
* nothing.
|
|
6351
|
+
*/
|
|
6352
|
+
protected instrumentDb<T extends object>(database: T, functionPath: string, anchor: TraceAnchor, sink?: TelemetrySink): T;
|
|
6353
|
+
/**
|
|
6354
|
+
* Build `ctx.fetch` — the platform `fetch`, instrumented.
|
|
6355
|
+
*
|
|
6356
|
+
* Every outbound call becomes a CLIENT span and carries a `traceparent` to
|
|
6357
|
+
* the callee, so time spent waiting on someone else's service stops being an
|
|
6358
|
+
* unexplained gap in the waterfall and the callee's spans join this trace
|
|
6359
|
+
* instead of starting an unrelated one.
|
|
6360
|
+
*
|
|
6361
|
+
* Falls back to the bare global `fetch` when no sink is configured or the
|
|
6362
|
+
* sink opted out via `traceFetch: false` — there is no point paying for spans
|
|
6363
|
+
* nobody collects, and an app calling a third party it would rather not send
|
|
6364
|
+
* trace ids to needs a way to say so.
|
|
6365
|
+
*/
|
|
6366
|
+
protected makeFetch(functionPath: string, anchor: TraceAnchor, sink?: TelemetrySink): ContextFetch;
|
|
6367
|
+
protected makeDispatchSpan(anchor: TraceAnchor, sink?: TelemetrySink): SpanHandle;
|
|
6046
6368
|
/**
|
|
6047
6369
|
* Build the `ctx.metrics` recorder for one dispatched function. Thin wiring
|
|
6048
6370
|
* over {@link createMetrics}, which owns the instrument semantics.
|
|
@@ -6062,6 +6384,70 @@ declare abstract class ShardDO {
|
|
|
6062
6384
|
* cross-instance aggregation is still the sink's job.
|
|
6063
6385
|
*/
|
|
6064
6386
|
protected recordMetric(event: MetricEvent, sink?: TelemetrySink): void;
|
|
6387
|
+
/** The decode + route body of {@link webSocketMessage}, split out so the trace wrapper stays a one-liner. */
|
|
6388
|
+
protected handleWebSocketMessage(ws: WebSocket, message: string | ArrayBuffer): Promise<void>;
|
|
6389
|
+
/**
|
|
6390
|
+
* The alarm's actual work, split out so {@link alarm} is a one-line trace
|
|
6391
|
+
* wrapper. An alarm drives `.global()` shape refreshes and external-source
|
|
6392
|
+
* ingest with no client waiting on a response, which is exactly where a
|
|
6393
|
+
* silent failure hides longest — so it gets a root span like any dispatch.
|
|
6394
|
+
*/
|
|
6395
|
+
private handleAlarmBody;
|
|
6396
|
+
/**
|
|
6397
|
+
* Build `ctx.span` — the handle onto the **dispatch's own span**, and with it
|
|
6398
|
+
* the wide-event surface.
|
|
6399
|
+
*
|
|
6400
|
+
* `ctx.trace(...)` creates a *new* child span for a sub-operation; this
|
|
6401
|
+
* attaches to the one that already exists for the request. That is the
|
|
6402
|
+
* distinction between "time this thing" and "record a fact about this
|
|
6403
|
+
* request", and conflating them is why instrumentation usually degrades into
|
|
6404
|
+
* log spam: with nowhere to put a fact, people reach for `ctx.log.info`.
|
|
6405
|
+
*
|
|
6406
|
+
* Attributes accumulate across the whole dispatch and are folded into the
|
|
6407
|
+
* root span in `recordDispatchRootSpan` — the OTel-native form of a
|
|
6408
|
+
* wide event, needing no non-standard "canonical log line" convention on the
|
|
6409
|
+
* collector side.
|
|
6410
|
+
*
|
|
6411
|
+
* Keyed by `dispatchSpanKey` — trace id AND root span id — so two concurrent
|
|
6412
|
+
* dispatches forwarded under the same client trace accumulate separately.
|
|
6413
|
+
*/
|
|
6414
|
+
/**
|
|
6415
|
+
* The dispatch entry's db tally, created on first use. Shares the entry with
|
|
6416
|
+
* `ctx.span`'s collector but is deliberately a separate slot — see
|
|
6417
|
+
* `instrumentDb`.
|
|
6418
|
+
*/
|
|
6419
|
+
private dispatchTally;
|
|
6420
|
+
/**
|
|
6421
|
+
* Give a NON-`fetch` Durable Object trigger — an alarm, an inbound socket
|
|
6422
|
+
* frame — the same telemetry an RPC dispatch gets: its own trace anchor, a
|
|
6423
|
+
* dispatch root span, and a flush of the batching sink when it finishes.
|
|
6424
|
+
*
|
|
6425
|
+
* These paths were previously invisible. An alarm can drive `.global()` shape
|
|
6426
|
+
* refreshes and external-source ingest, and a socket frame can run a whole
|
|
6427
|
+
* subscription re-evaluation, but neither produced a root span — so any
|
|
6428
|
+
* `ctx.trace` span they created hung off a freshly-minted anchor with nothing
|
|
6429
|
+
* above it, and a collector showed orphans with no bar explaining what caused
|
|
6430
|
+
* them. Alarms are also precisely where a silent failure hides longest,
|
|
6431
|
+
* because no client is waiting on a response to notice.
|
|
6432
|
+
*
|
|
6433
|
+
* The anchor is published on `currentRequestTrace` ONLY when nothing else has
|
|
6434
|
+
* claimed it, and restored afterwards, so a concurrently-interleaved RPC
|
|
6435
|
+
* dispatch (which captured its own anchor in a local at entry) keeps its
|
|
6436
|
+
* attribution. Worst case under interleaving is a mis-attributed inner span —
|
|
6437
|
+
* the same trade the surrounding code already makes with this field — never a
|
|
6438
|
+
* corrupted or lost one.
|
|
6439
|
+
*/
|
|
6440
|
+
private withTriggerTrace;
|
|
6441
|
+
/**
|
|
6442
|
+
* Ask the last-seen telemetry sink to ship what it has buffered.
|
|
6443
|
+
*
|
|
6444
|
+
* Used by the trigger paths ({@link withTriggerTrace}), which have no `ctx`
|
|
6445
|
+
* and therefore no direct handle on `config.observability`. The sink is a
|
|
6446
|
+
* per-worker singleton in every real configuration, so remembering the most
|
|
6447
|
+
* recent one is exact in practice and harmless otherwise: a flush is
|
|
6448
|
+
* idempotent and a sink with an empty buffer is a no-op.
|
|
6449
|
+
*/
|
|
6450
|
+
private flushTelemetry;
|
|
6065
6451
|
/**
|
|
6066
6452
|
* Buffer the synthetic root span for a finished dispatch. The caller gates
|
|
6067
6453
|
* this on the dispatch having actually produced spans (the `hasTrace` check at
|
|
@@ -6072,8 +6458,31 @@ declare abstract class ShardDO {
|
|
|
6072
6458
|
* `anchor` carries the dispatch's trace ids, captured at entry rather than
|
|
6073
6459
|
* read from `this` here — this runs after the handler's awaits, where the
|
|
6074
6460
|
* shared field may already belong to an interleaved dispatch.
|
|
6461
|
+
*
|
|
6462
|
+
* When the handler attached a **wide event** through `ctx.span`, this also
|
|
6463
|
+
* exports it — see {@link exportWideEvent} for why it goes out as an OTel
|
|
6464
|
+
* Event record rather than on the span itself.
|
|
6075
6465
|
*/
|
|
6076
6466
|
private recordDispatchRootSpan;
|
|
6467
|
+
/**
|
|
6468
|
+
* Export a dispatch's wide event as a standard OTel **Event** log record
|
|
6469
|
+
* (`lunora.dispatch`), correlated to the dispatch's trace and span.
|
|
6470
|
+
*
|
|
6471
|
+
* **Why a log record rather than the span's attributes.** The local dispatch
|
|
6472
|
+
* root span shares its `spanId` with the SERVER span `@lunora/runtime` emits
|
|
6473
|
+
* for the same dispatch — they are the same logical span, seen from the two
|
|
6474
|
+
* sides of the shard hop. Exporting our copy too would put two partial spans
|
|
6475
|
+
* with identical `trace_id`/`span_id` on the wire, which collectors resolve
|
|
6476
|
+
* inconsistently (merge, last-write, or duplicate). An Event record carrying
|
|
6477
|
+
* `traceId`/`spanId` is unambiguous, is the OTel-sanctioned shape for exactly
|
|
6478
|
+
* this ("a named, structured occurrence"), and every OTLP backend can group
|
|
6479
|
+
* and aggregate it with no Lunora-specific configuration.
|
|
6480
|
+
*
|
|
6481
|
+
* The span still carries the attributes LOCALLY, which is what the Studio
|
|
6482
|
+
* waterfall renders — so the wide event is visible in both places, exported
|
|
6483
|
+
* exactly once.
|
|
6484
|
+
*/
|
|
6485
|
+
private exportWideEvent;
|
|
6077
6486
|
/**
|
|
6078
6487
|
* Buffer one span for the studio Traces panel and hand it to the optional
|
|
6079
6488
|
* `sink.onSpan`. Best-effort throughout, exactly like {@link recordUserLog}:
|