@lunora/runtime 1.0.0-alpha.30 → 1.0.0-alpha.31
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
CHANGED
|
@@ -2,6 +2,7 @@ import { RankDirection, RankPageRow, DatabaseWriterLike } from '@lunora/do';
|
|
|
2
2
|
export type { RankDirection as RankPageDirection, RankPageRowKey as RankPageKey, RankPageRow, ShardRankPageResult } from '@lunora/do';
|
|
3
3
|
import { WorkflowsRestClient } from '@lunora/workflow';
|
|
4
4
|
import { LunoraError as LunoraError$1, ErrorBody } from '@lunora/errors';
|
|
5
|
+
import { R2SqlClient } from '@lunora/bindings/r2sql';
|
|
5
6
|
/**
|
|
6
7
|
* Turn-key incremental-sync source helpers for warehouse connectors
|
|
7
8
|
* (Fivetran custom functions, Airbyte incremental sources).
|
|
@@ -2924,6 +2925,17 @@ interface PipelineLike {
|
|
|
2924
2925
|
interface PipelineLogSinkOptions {
|
|
2925
2926
|
/** The Cloudflare Pipeline binding each log record is durably sent to. */
|
|
2926
2927
|
pipeline: PipelineLike;
|
|
2928
|
+
/**
|
|
2929
|
+
* When true, `fields` is written as a **JSON string** (`JSON.stringify`)
|
|
2930
|
+
* rather than a nested object. Defaults to `false` for back-compatibility.
|
|
2931
|
+
*
|
|
2932
|
+
* Turn it on when the destination Iceberg table types `fields` as a `string`
|
|
2933
|
+
* column so the archive stays queryable (R2 SQL can `LIKE`/compare a string
|
|
2934
|
+
* column, but not index into an arbitrarily-shaped struct). The reader
|
|
2935
|
+
* (`createPipelineLogReader`) parses such a JSON string back to an object on
|
|
2936
|
+
* read. Leave it off when the table types `fields` as a native struct.
|
|
2937
|
+
*/
|
|
2938
|
+
serializeFields?: boolean;
|
|
2927
2939
|
}
|
|
2928
2940
|
/**
|
|
2929
2941
|
* A sink that durably persists each `ctx.log` line to a Cloudflare Pipeline
|
|
@@ -2933,6 +2945,20 @@ interface PipelineLogSinkOptions {
|
|
|
2933
2945
|
* structured record (message, level, function path, fields, trace ids, shard,
|
|
2934
2946
|
* user, timestamp) in object storage under the app's own account.
|
|
2935
2947
|
*
|
|
2948
|
+
* **Written-column contract.** Each record is a flat object; this is the exact
|
|
2949
|
+
* read-side schema `createPipelineLogReader` (`pipeline-log-reader.ts`) mirrors
|
|
2950
|
+
* in its `DEFAULT_LOG_COLUMNS`. Keep the two in lockstep — a column added here
|
|
2951
|
+
* must gain a default there:
|
|
2952
|
+
* - `functionPath` (string) — always present
|
|
2953
|
+
* - `level` (string severity) — always present
|
|
2954
|
+
* - `message` (string) — always present
|
|
2955
|
+
* - `ts` (number, epoch-millis) — always present
|
|
2956
|
+
* - `fields` (nested object, or a JSON string when `serializeFields`) — when set
|
|
2957
|
+
* - `shardKey` (string) — when set
|
|
2958
|
+
* - `userId` (string) — when set
|
|
2959
|
+
* - `traceId` (string) — when set
|
|
2960
|
+
* - `spanId` (string) — when set
|
|
2961
|
+
*
|
|
2936
2962
|
* Only `onLog` is implemented — RPC-span metrics belong in
|
|
2937
2963
|
* {@link analyticsEngineSink}. `Pipeline.send` is durable/fire-and-forget on the
|
|
2938
2964
|
* platform; the call is registered with the request's `context.waitUntil` when
|
|
@@ -2943,7 +2969,8 @@ interface PipelineLogSinkOptions {
|
|
|
2943
2969
|
* Privacy: the persisted record carries `message` + structured `fields` (not the
|
|
2944
2970
|
* raw positional args). They may include user input — the R2 bucket is your own,
|
|
2945
2971
|
* but treat it as a log store and gate PII upstream if that is a concern.
|
|
2946
|
-
* @param options Sink options: `pipeline` is the Cloudflare Pipeline binding
|
|
2972
|
+
* @param options Sink options: `pipeline` is the Cloudflare Pipeline binding;
|
|
2973
|
+
* `serializeFields` stores `fields` as a queryable JSON string.
|
|
2947
2974
|
*/
|
|
2948
2975
|
declare const pipelineLogSink: (options: PipelineLogSinkOptions) => ObservabilitySink;
|
|
2949
2976
|
/** Options for {@link otlpSink}. */
|
|
@@ -3010,5 +3037,140 @@ declare const otlpSink: (options: OtlpSinkOptions) => ObservabilitySink;
|
|
|
3010
3037
|
* @param sinks The sinks to fan out to.
|
|
3011
3038
|
*/
|
|
3012
3039
|
declare const combineSinks: (...sinks: ObservabilitySink[]) => ObservabilitySink;
|
|
3040
|
+
/**
|
|
3041
|
+
* The written-column contract: every field `pipelineLogSink` emits, mapped to the
|
|
3042
|
+
* column it is stored under by default (the identity mapping). Also the source of
|
|
3043
|
+
* truth for the {@link PipelineLogField} union. Mirrors the record built in
|
|
3044
|
+
* `pipelineLogSink` — the read side of the same contract.
|
|
3045
|
+
*/
|
|
3046
|
+
declare const DEFAULT_COLUMNS: {
|
|
3047
|
+
readonly fields: "fields";
|
|
3048
|
+
readonly functionPath: "functionPath";
|
|
3049
|
+
readonly level: "level";
|
|
3050
|
+
readonly message: "message";
|
|
3051
|
+
readonly shardKey: "shardKey";
|
|
3052
|
+
readonly spanId: "spanId";
|
|
3053
|
+
readonly traceId: "traceId";
|
|
3054
|
+
readonly ts: "ts";
|
|
3055
|
+
readonly userId: "userId";
|
|
3056
|
+
};
|
|
3057
|
+
/**
|
|
3058
|
+
* The canonical field names of one persisted log record — the keys
|
|
3059
|
+
* `pipelineLogSink` writes. Used as the {@link PipelineLogColumnMap} keys and the
|
|
3060
|
+
* {@link PipelineLogRow} shape, so the reader stays decoupled from whatever
|
|
3061
|
+
* physical column names the operator's Iceberg table happens to use.
|
|
3062
|
+
*/
|
|
3063
|
+
type PipelineLogField = keyof typeof DEFAULT_COLUMNS;
|
|
3064
|
+
/**
|
|
3065
|
+
* Field-to-column-name map. Defaults to the identity mapping (each field stored
|
|
3066
|
+
* under its own name, matching what `pipelineLogSink` writes). Override per-field
|
|
3067
|
+
* when the Iceberg schema renames a column; unspecified fields keep their
|
|
3068
|
+
* default. This is the single knob that lets one reader serve differently shaped
|
|
3069
|
+
* Data Catalog tables.
|
|
3070
|
+
*/
|
|
3071
|
+
type PipelineLogColumnMap = Partial<Record<PipelineLogField, string>>;
|
|
3072
|
+
/** An opaque keyset cursor: the `ts` of the row after the last one returned. */
|
|
3073
|
+
interface PipelineLogCursor {
|
|
3074
|
+
/** Epoch-millis boundary; the next page is every row strictly older than this. */
|
|
3075
|
+
ts: number;
|
|
3076
|
+
}
|
|
3077
|
+
/** Filters for one {@link PipelineLogReader} query. Every value is inlined safely (`lit`/`sql`). */
|
|
3078
|
+
interface PipelineLogQuery {
|
|
3079
|
+
/** Continue after a previous page (keyset on `ts DESC`). Combined with the other filters. */
|
|
3080
|
+
cursor?: PipelineLogCursor;
|
|
3081
|
+
/** Match only this exact function path's records. Prefer `functionPathPrefix` for a namespace sweep. */
|
|
3082
|
+
functionPath?: string;
|
|
3083
|
+
/** Match records whose `functionPath` starts with this string (rendered as a `LIKE 'prefix%'`). */
|
|
3084
|
+
functionPathPrefix?: string;
|
|
3085
|
+
/** Match only this exact severity. When set, `minLevel` is ignored for the same field. */
|
|
3086
|
+
level?: ContextLogLevel;
|
|
3087
|
+
/** Max rows to return. Clamped to `[1, 10000]`; defaults to {@link DEFAULT_LOG_LIMIT}. */
|
|
3088
|
+
limit?: number;
|
|
3089
|
+
/** Severity floor: keep every level at or above this in {@link LOG_LEVEL_ORDER} (e.g. `warn` keeps warn, error, fatal). */
|
|
3090
|
+
minLevel?: ContextLogLevel;
|
|
3091
|
+
/** Match only this shard key. */
|
|
3092
|
+
shardKey?: string;
|
|
3093
|
+
/** Lower time bound, inclusive (`ts` at or after this), epoch-millis. */
|
|
3094
|
+
sinceTs?: number;
|
|
3095
|
+
/** Match only this trace id. */
|
|
3096
|
+
traceId?: string;
|
|
3097
|
+
/** Upper time bound, inclusive (`ts` at or before this), epoch-millis. */
|
|
3098
|
+
untilTs?: number;
|
|
3099
|
+
/** Match only this acting user id. */
|
|
3100
|
+
userId?: string;
|
|
3101
|
+
}
|
|
3102
|
+
/**
|
|
3103
|
+
* One decoded log record. Always keyed by the canonical {@link PipelineLogField}
|
|
3104
|
+
* names regardless of the physical columns (the reader remaps via `columnMap`),
|
|
3105
|
+
* so consumers never see the operator's storage names.
|
|
3106
|
+
*/
|
|
3107
|
+
interface PipelineLogRow {
|
|
3108
|
+
/**
|
|
3109
|
+
* Structured fields, when the record carried them. A `serializeFields` sink
|
|
3110
|
+
* stores these as a JSON string, which the reader parses back to an object;
|
|
3111
|
+
* a plain string that is not valid JSON is returned verbatim.
|
|
3112
|
+
*/
|
|
3113
|
+
fields?: unknown;
|
|
3114
|
+
/** Function path that emitted the line, e.g. `"messages:list"`. */
|
|
3115
|
+
functionPath: string;
|
|
3116
|
+
/** Severity the line was logged at. */
|
|
3117
|
+
level: ContextLogLevel;
|
|
3118
|
+
/** Rendered message. */
|
|
3119
|
+
message: string;
|
|
3120
|
+
/** Shard key for single-shard calls, when present. */
|
|
3121
|
+
shardKey?: string;
|
|
3122
|
+
/** Span id the line was emitted under, when present. */
|
|
3123
|
+
spanId?: string;
|
|
3124
|
+
/** Trace id the line belongs to, when present. */
|
|
3125
|
+
traceId?: string;
|
|
3126
|
+
/** Epoch-millis the line was emitted. */
|
|
3127
|
+
ts: number;
|
|
3128
|
+
/** Acting user id, when present. */
|
|
3129
|
+
userId?: string;
|
|
3130
|
+
}
|
|
3131
|
+
/** One page of {@link PipelineLogRow}s, newest first, plus the cursor for the next page (absent means last page). */
|
|
3132
|
+
interface PipelineLogPage {
|
|
3133
|
+
/** The cursor to pass as {@link PipelineLogQuery} `cursor` for the following page; absent when this is the last page. */
|
|
3134
|
+
nextCursor?: PipelineLogCursor;
|
|
3135
|
+
/** The rows, ordered `ts DESC` (newest first). At most `limit` of them. */
|
|
3136
|
+
rows: PipelineLogRow[];
|
|
3137
|
+
}
|
|
3138
|
+
/** Options for {@link createPipelineLogReader}. */
|
|
3139
|
+
interface PipelineLogReaderOptions {
|
|
3140
|
+
/**
|
|
3141
|
+
* Override any physical column name that diverges from the default (identity)
|
|
3142
|
+
* mapping. Unspecified fields keep their {@link DEFAULT_LOG_COLUMNS} name.
|
|
3143
|
+
*/
|
|
3144
|
+
columnMap?: PipelineLogColumnMap;
|
|
3145
|
+
/**
|
|
3146
|
+
* The Iceberg namespace the `table` lives in (R2 Data Catalog database).
|
|
3147
|
+
* Combined as `namespace.table` in the `FROM` clause; omit when `table`
|
|
3148
|
+
* already carries its namespace.
|
|
3149
|
+
*/
|
|
3150
|
+
namespace?: string;
|
|
3151
|
+
/** The Iceberg table name the Pipeline writes log records to (e.g. `"logs"`). */
|
|
3152
|
+
table: string;
|
|
3153
|
+
}
|
|
3154
|
+
/** The reader surface: a single keyset-paginated {@link PipelineLogPage} query. */
|
|
3155
|
+
interface PipelineLogReader {
|
|
3156
|
+
/** Run one filtered, keyset-paginated read and return a {@link PipelineLogPage}. */
|
|
3157
|
+
query: (query?: PipelineLogQuery) => Promise<PipelineLogPage>;
|
|
3158
|
+
}
|
|
3159
|
+
/** The written-column contract exposed publicly: canonical field to default physical column name. */
|
|
3160
|
+
declare const DEFAULT_LOG_COLUMNS: Readonly<Record<PipelineLogField, string>>;
|
|
3161
|
+
/** Default page size when a query omits `limit`. */
|
|
3162
|
+
declare const DEFAULT_LOG_LIMIT: number;
|
|
3163
|
+
/**
|
|
3164
|
+
* Build a durable-log reader over one R2 Data Catalog (Iceberg) table.
|
|
3165
|
+
*
|
|
3166
|
+
* The returned {@link PipelineLogReader} compiles each call to a safe
|
|
3167
|
+
* `SELECT ... WHERE ... ORDER BY ts DESC LIMIT n` (over-fetching by one) and
|
|
3168
|
+
* decodes the rows back to the canonical {@link PipelineLogRow} shape. All value
|
|
3169
|
+
* filters are escaped through `@lunora/bindings/r2sql`'s `sql`/`lit`; column
|
|
3170
|
+
* names come from `options.columnMap` (operator config), spliced with `raw`.
|
|
3171
|
+
* @param client An {@link R2SqlClient} (`createR2Sql({ accountId, apiToken, bucket })`).
|
|
3172
|
+
* @param options The target `table` (plus optional `namespace`) and any `columnMap` overrides.
|
|
3173
|
+
*/
|
|
3174
|
+
declare const createPipelineLogReader: (client: R2SqlClient, options: PipelineLogReaderOptions) => PipelineLogReader;
|
|
3013
3175
|
declare const VERSION: string;
|
|
3014
|
-
export { type AdminTableResolver, type AirbyteMessage, type AnalyticsEngineDataPointLike, type AnalyticsEngineDatasetLike, type AnalyticsEngineSinkOptions, type AuthAdmin, type AuthCapabilities, type AuthConfigInfo, type AuthImpersonation, type AuthPage, type AuthSession, type AuthUser, type AuthUserFieldSpec, type BackupManifest, type BackupStore, type ComposeIdentityResolversErrorMode, type ComposeIdentityResolversOptions, type ConnectorChange, type ConnectorSyncPage, type CorsOptions, type CronHandler, type CronJobDispatch, type CronJobInfo, type CrossShardCounter, type CrossShardReader, type CrossShardRelationCapabilities, type CrossShardRelationOptions, type CsrfOptions, DEFAULT_REGISTRY_CACHE_TTL_MS, type DurableObjectJurisdiction, type DynamicShardRegistry, type DynamicShardRegistryOptions, type ExecutionContextLike, type ExportFanOutRequest, type ExportFanOutResult, type FanOutRequest, type FanOutResult, type FanOutSpec, type FivetranResponse, type FrameworkHostHandler, type FrameworkWorkerOptions, type FrameworkWorkerOptionsInput, type FunctionDescriptor, type FunctionRegistryEntry, type FunctionRegistryLike, type GlobalExportFunction as GlobalExportFn, type GlobalImportFunction as GlobalImportFn, type GlobalIntrospector, type GlobalTableInfo as GlobalTableInfoMeta, type GlobalTablePage as GlobalTablePageMeta, type HttpActionContext, type HttpActionLike, type HttpRouterLike, type IdentityContractLike, type IdentityResolver, type IdentityValidation, type ImportFanOutRequest, type ImportFanOutResult, type KvIntrospector, type KvKeyEntry, type KvKeyListResult, type KvNamespaceSummary, type KvValueResult, type ListAuthUsersOptions, type LogEvent, type LogFields, type LogLevel, LunoraError, type LunoraErrorBody, type LunoraHandlerOptions, type LunoraWorker, type MergeStrategy, type MetricEvent, type MetricKind, type MigrationFanOutRequest, type MigrationFanOutResult, NOOP_EXECUTION_CONTEXT, type ObservabilityEvent, type ObservabilitySink, type ObservabilitySinkContext, type OtlpSinkOptions, type PipelineLike, type PipelineLogSinkOptions, type QueryCoordinator, type QueryCoordinatorOptions, type RankFanOutRequest, type RankFanOutResult, type RankPageFanOutRequest, type RankPageFanOutResult, type ResolvedSecurity, type ResolvedShard, type Route, type RpcContext, type RpcEnvelope, SHARD_REGISTRY_DO_NAME, type ScheduledControllerLike, type SecurityHeadersOptions, type SecurityOptions, type SentrySinkOptions, type ShardError, type ShardExportOutcome, type ShardImportOutcome, type ShardMigrationOutcome, type ShardNamespaceLike, type ShardRankOutcome, type ShardRankPageOutcome, type ShardRegistry, type ShardTrafficEntry, type ShardTrafficFanOutRequest, type ShardTrafficFanOutResult, type ShardingInfo, type SpanEvent, type StorageListFunction as StorageListFn, type StorageObject, VERSION, type VectorIndexSummary, type VectorIntrospector, type VectorQueryMatch, type WebhookSinkOptions, type WorkerOptions, analyticsEngineSink, applyJurisdiction, combineSinks, composeIdentityResolvers, composeWorker, consoleSink, createCrossShardRelationCapabilities, createDynamicShardRegistry, createLunoraHandler, createQueryCoordinator, createStaticShardRegistry, createWorker, decorateResponse, defineRpcEnvelope, emitLogEvent, emitRpcEvent, enforceOrigin, handleCorsPreflight, mergeStrategyForAggregate, otlpSink, pipelineLogSink, resolveLunoraOptions, resolveSecurity, resolveShard, routeIdentityResolvers, sentrySink, toAirbyteMessages, toErrorResponse, toFivetranResponse, webhookSink, withFrameworkWorker };
|
|
3176
|
+
export { type AdminTableResolver, type AirbyteMessage, type AnalyticsEngineDataPointLike, type AnalyticsEngineDatasetLike, type AnalyticsEngineSinkOptions, type AuthAdmin, type AuthCapabilities, type AuthConfigInfo, type AuthImpersonation, type AuthPage, type AuthSession, type AuthUser, type AuthUserFieldSpec, type BackupManifest, type BackupStore, type ComposeIdentityResolversErrorMode, type ComposeIdentityResolversOptions, type ConnectorChange, type ConnectorSyncPage, type CorsOptions, type CronHandler, type CronJobDispatch, type CronJobInfo, type CrossShardCounter, type CrossShardReader, type CrossShardRelationCapabilities, type CrossShardRelationOptions, type CsrfOptions, DEFAULT_LOG_COLUMNS, DEFAULT_LOG_LIMIT, DEFAULT_REGISTRY_CACHE_TTL_MS, type DurableObjectJurisdiction, type DynamicShardRegistry, type DynamicShardRegistryOptions, type ExecutionContextLike, type ExportFanOutRequest, type ExportFanOutResult, type FanOutRequest, type FanOutResult, type FanOutSpec, type FivetranResponse, type FrameworkHostHandler, type FrameworkWorkerOptions, type FrameworkWorkerOptionsInput, type FunctionDescriptor, type FunctionRegistryEntry, type FunctionRegistryLike, type GlobalExportFunction as GlobalExportFn, type GlobalImportFunction as GlobalImportFn, type GlobalIntrospector, type GlobalTableInfo as GlobalTableInfoMeta, type GlobalTablePage as GlobalTablePageMeta, type HttpActionContext, type HttpActionLike, type HttpRouterLike, type IdentityContractLike, type IdentityResolver, type IdentityValidation, type ImportFanOutRequest, type ImportFanOutResult, type KvIntrospector, type KvKeyEntry, type KvKeyListResult, type KvNamespaceSummary, type KvValueResult, type ListAuthUsersOptions, type LogEvent, type LogFields, type LogLevel, LunoraError, type LunoraErrorBody, type LunoraHandlerOptions, type LunoraWorker, type MergeStrategy, type MetricEvent, type MetricKind, type MigrationFanOutRequest, type MigrationFanOutResult, NOOP_EXECUTION_CONTEXT, type ObservabilityEvent, type ObservabilitySink, type ObservabilitySinkContext, type OtlpSinkOptions, type PipelineLike, type PipelineLogColumnMap, type PipelineLogCursor, type PipelineLogField, type PipelineLogPage, type PipelineLogQuery, type PipelineLogReader, type PipelineLogReaderOptions, type PipelineLogRow, type PipelineLogSinkOptions, type QueryCoordinator, type QueryCoordinatorOptions, type RankFanOutRequest, type RankFanOutResult, type RankPageFanOutRequest, type RankPageFanOutResult, type ResolvedSecurity, type ResolvedShard, type Route, type RpcContext, type RpcEnvelope, SHARD_REGISTRY_DO_NAME, type ScheduledControllerLike, type SecurityHeadersOptions, type SecurityOptions, type SentrySinkOptions, type ShardError, type ShardExportOutcome, type ShardImportOutcome, type ShardMigrationOutcome, type ShardNamespaceLike, type ShardRankOutcome, type ShardRankPageOutcome, type ShardRegistry, type ShardTrafficEntry, type ShardTrafficFanOutRequest, type ShardTrafficFanOutResult, type ShardingInfo, type SpanEvent, type StorageListFunction as StorageListFn, type StorageObject, VERSION, type VectorIndexSummary, type VectorIntrospector, type VectorQueryMatch, type WebhookSinkOptions, type WorkerOptions, analyticsEngineSink, applyJurisdiction, combineSinks, composeIdentityResolvers, composeWorker, consoleSink, createCrossShardRelationCapabilities, createDynamicShardRegistry, createLunoraHandler, createPipelineLogReader, createQueryCoordinator, createStaticShardRegistry, createWorker, decorateResponse, defineRpcEnvelope, emitLogEvent, emitRpcEvent, enforceOrigin, handleCorsPreflight, mergeStrategyForAggregate, otlpSink, pipelineLogSink, resolveLunoraOptions, resolveSecurity, resolveShard, routeIdentityResolvers, sentrySink, toAirbyteMessages, toErrorResponse, toFivetranResponse, webhookSink, withFrameworkWorker };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { RankDirection, RankPageRow, DatabaseWriterLike } from '@lunora/do';
|
|
|
2
2
|
export type { RankDirection as RankPageDirection, RankPageRowKey as RankPageKey, RankPageRow, ShardRankPageResult } from '@lunora/do';
|
|
3
3
|
import { WorkflowsRestClient } from '@lunora/workflow';
|
|
4
4
|
import { LunoraError as LunoraError$1, ErrorBody } from '@lunora/errors';
|
|
5
|
+
import { R2SqlClient } from '@lunora/bindings/r2sql';
|
|
5
6
|
/**
|
|
6
7
|
* Turn-key incremental-sync source helpers for warehouse connectors
|
|
7
8
|
* (Fivetran custom functions, Airbyte incremental sources).
|
|
@@ -2924,6 +2925,17 @@ interface PipelineLike {
|
|
|
2924
2925
|
interface PipelineLogSinkOptions {
|
|
2925
2926
|
/** The Cloudflare Pipeline binding each log record is durably sent to. */
|
|
2926
2927
|
pipeline: PipelineLike;
|
|
2928
|
+
/**
|
|
2929
|
+
* When true, `fields` is written as a **JSON string** (`JSON.stringify`)
|
|
2930
|
+
* rather than a nested object. Defaults to `false` for back-compatibility.
|
|
2931
|
+
*
|
|
2932
|
+
* Turn it on when the destination Iceberg table types `fields` as a `string`
|
|
2933
|
+
* column so the archive stays queryable (R2 SQL can `LIKE`/compare a string
|
|
2934
|
+
* column, but not index into an arbitrarily-shaped struct). The reader
|
|
2935
|
+
* (`createPipelineLogReader`) parses such a JSON string back to an object on
|
|
2936
|
+
* read. Leave it off when the table types `fields` as a native struct.
|
|
2937
|
+
*/
|
|
2938
|
+
serializeFields?: boolean;
|
|
2927
2939
|
}
|
|
2928
2940
|
/**
|
|
2929
2941
|
* A sink that durably persists each `ctx.log` line to a Cloudflare Pipeline
|
|
@@ -2933,6 +2945,20 @@ interface PipelineLogSinkOptions {
|
|
|
2933
2945
|
* structured record (message, level, function path, fields, trace ids, shard,
|
|
2934
2946
|
* user, timestamp) in object storage under the app's own account.
|
|
2935
2947
|
*
|
|
2948
|
+
* **Written-column contract.** Each record is a flat object; this is the exact
|
|
2949
|
+
* read-side schema `createPipelineLogReader` (`pipeline-log-reader.ts`) mirrors
|
|
2950
|
+
* in its `DEFAULT_LOG_COLUMNS`. Keep the two in lockstep — a column added here
|
|
2951
|
+
* must gain a default there:
|
|
2952
|
+
* - `functionPath` (string) — always present
|
|
2953
|
+
* - `level` (string severity) — always present
|
|
2954
|
+
* - `message` (string) — always present
|
|
2955
|
+
* - `ts` (number, epoch-millis) — always present
|
|
2956
|
+
* - `fields` (nested object, or a JSON string when `serializeFields`) — when set
|
|
2957
|
+
* - `shardKey` (string) — when set
|
|
2958
|
+
* - `userId` (string) — when set
|
|
2959
|
+
* - `traceId` (string) — when set
|
|
2960
|
+
* - `spanId` (string) — when set
|
|
2961
|
+
*
|
|
2936
2962
|
* Only `onLog` is implemented — RPC-span metrics belong in
|
|
2937
2963
|
* {@link analyticsEngineSink}. `Pipeline.send` is durable/fire-and-forget on the
|
|
2938
2964
|
* platform; the call is registered with the request's `context.waitUntil` when
|
|
@@ -2943,7 +2969,8 @@ interface PipelineLogSinkOptions {
|
|
|
2943
2969
|
* Privacy: the persisted record carries `message` + structured `fields` (not the
|
|
2944
2970
|
* raw positional args). They may include user input — the R2 bucket is your own,
|
|
2945
2971
|
* but treat it as a log store and gate PII upstream if that is a concern.
|
|
2946
|
-
* @param options Sink options: `pipeline` is the Cloudflare Pipeline binding
|
|
2972
|
+
* @param options Sink options: `pipeline` is the Cloudflare Pipeline binding;
|
|
2973
|
+
* `serializeFields` stores `fields` as a queryable JSON string.
|
|
2947
2974
|
*/
|
|
2948
2975
|
declare const pipelineLogSink: (options: PipelineLogSinkOptions) => ObservabilitySink;
|
|
2949
2976
|
/** Options for {@link otlpSink}. */
|
|
@@ -3010,5 +3037,140 @@ declare const otlpSink: (options: OtlpSinkOptions) => ObservabilitySink;
|
|
|
3010
3037
|
* @param sinks The sinks to fan out to.
|
|
3011
3038
|
*/
|
|
3012
3039
|
declare const combineSinks: (...sinks: ObservabilitySink[]) => ObservabilitySink;
|
|
3040
|
+
/**
|
|
3041
|
+
* The written-column contract: every field `pipelineLogSink` emits, mapped to the
|
|
3042
|
+
* column it is stored under by default (the identity mapping). Also the source of
|
|
3043
|
+
* truth for the {@link PipelineLogField} union. Mirrors the record built in
|
|
3044
|
+
* `pipelineLogSink` — the read side of the same contract.
|
|
3045
|
+
*/
|
|
3046
|
+
declare const DEFAULT_COLUMNS: {
|
|
3047
|
+
readonly fields: "fields";
|
|
3048
|
+
readonly functionPath: "functionPath";
|
|
3049
|
+
readonly level: "level";
|
|
3050
|
+
readonly message: "message";
|
|
3051
|
+
readonly shardKey: "shardKey";
|
|
3052
|
+
readonly spanId: "spanId";
|
|
3053
|
+
readonly traceId: "traceId";
|
|
3054
|
+
readonly ts: "ts";
|
|
3055
|
+
readonly userId: "userId";
|
|
3056
|
+
};
|
|
3057
|
+
/**
|
|
3058
|
+
* The canonical field names of one persisted log record — the keys
|
|
3059
|
+
* `pipelineLogSink` writes. Used as the {@link PipelineLogColumnMap} keys and the
|
|
3060
|
+
* {@link PipelineLogRow} shape, so the reader stays decoupled from whatever
|
|
3061
|
+
* physical column names the operator's Iceberg table happens to use.
|
|
3062
|
+
*/
|
|
3063
|
+
type PipelineLogField = keyof typeof DEFAULT_COLUMNS;
|
|
3064
|
+
/**
|
|
3065
|
+
* Field-to-column-name map. Defaults to the identity mapping (each field stored
|
|
3066
|
+
* under its own name, matching what `pipelineLogSink` writes). Override per-field
|
|
3067
|
+
* when the Iceberg schema renames a column; unspecified fields keep their
|
|
3068
|
+
* default. This is the single knob that lets one reader serve differently shaped
|
|
3069
|
+
* Data Catalog tables.
|
|
3070
|
+
*/
|
|
3071
|
+
type PipelineLogColumnMap = Partial<Record<PipelineLogField, string>>;
|
|
3072
|
+
/** An opaque keyset cursor: the `ts` of the row after the last one returned. */
|
|
3073
|
+
interface PipelineLogCursor {
|
|
3074
|
+
/** Epoch-millis boundary; the next page is every row strictly older than this. */
|
|
3075
|
+
ts: number;
|
|
3076
|
+
}
|
|
3077
|
+
/** Filters for one {@link PipelineLogReader} query. Every value is inlined safely (`lit`/`sql`). */
|
|
3078
|
+
interface PipelineLogQuery {
|
|
3079
|
+
/** Continue after a previous page (keyset on `ts DESC`). Combined with the other filters. */
|
|
3080
|
+
cursor?: PipelineLogCursor;
|
|
3081
|
+
/** Match only this exact function path's records. Prefer `functionPathPrefix` for a namespace sweep. */
|
|
3082
|
+
functionPath?: string;
|
|
3083
|
+
/** Match records whose `functionPath` starts with this string (rendered as a `LIKE 'prefix%'`). */
|
|
3084
|
+
functionPathPrefix?: string;
|
|
3085
|
+
/** Match only this exact severity. When set, `minLevel` is ignored for the same field. */
|
|
3086
|
+
level?: ContextLogLevel;
|
|
3087
|
+
/** Max rows to return. Clamped to `[1, 10000]`; defaults to {@link DEFAULT_LOG_LIMIT}. */
|
|
3088
|
+
limit?: number;
|
|
3089
|
+
/** Severity floor: keep every level at or above this in {@link LOG_LEVEL_ORDER} (e.g. `warn` keeps warn, error, fatal). */
|
|
3090
|
+
minLevel?: ContextLogLevel;
|
|
3091
|
+
/** Match only this shard key. */
|
|
3092
|
+
shardKey?: string;
|
|
3093
|
+
/** Lower time bound, inclusive (`ts` at or after this), epoch-millis. */
|
|
3094
|
+
sinceTs?: number;
|
|
3095
|
+
/** Match only this trace id. */
|
|
3096
|
+
traceId?: string;
|
|
3097
|
+
/** Upper time bound, inclusive (`ts` at or before this), epoch-millis. */
|
|
3098
|
+
untilTs?: number;
|
|
3099
|
+
/** Match only this acting user id. */
|
|
3100
|
+
userId?: string;
|
|
3101
|
+
}
|
|
3102
|
+
/**
|
|
3103
|
+
* One decoded log record. Always keyed by the canonical {@link PipelineLogField}
|
|
3104
|
+
* names regardless of the physical columns (the reader remaps via `columnMap`),
|
|
3105
|
+
* so consumers never see the operator's storage names.
|
|
3106
|
+
*/
|
|
3107
|
+
interface PipelineLogRow {
|
|
3108
|
+
/**
|
|
3109
|
+
* Structured fields, when the record carried them. A `serializeFields` sink
|
|
3110
|
+
* stores these as a JSON string, which the reader parses back to an object;
|
|
3111
|
+
* a plain string that is not valid JSON is returned verbatim.
|
|
3112
|
+
*/
|
|
3113
|
+
fields?: unknown;
|
|
3114
|
+
/** Function path that emitted the line, e.g. `"messages:list"`. */
|
|
3115
|
+
functionPath: string;
|
|
3116
|
+
/** Severity the line was logged at. */
|
|
3117
|
+
level: ContextLogLevel;
|
|
3118
|
+
/** Rendered message. */
|
|
3119
|
+
message: string;
|
|
3120
|
+
/** Shard key for single-shard calls, when present. */
|
|
3121
|
+
shardKey?: string;
|
|
3122
|
+
/** Span id the line was emitted under, when present. */
|
|
3123
|
+
spanId?: string;
|
|
3124
|
+
/** Trace id the line belongs to, when present. */
|
|
3125
|
+
traceId?: string;
|
|
3126
|
+
/** Epoch-millis the line was emitted. */
|
|
3127
|
+
ts: number;
|
|
3128
|
+
/** Acting user id, when present. */
|
|
3129
|
+
userId?: string;
|
|
3130
|
+
}
|
|
3131
|
+
/** One page of {@link PipelineLogRow}s, newest first, plus the cursor for the next page (absent means last page). */
|
|
3132
|
+
interface PipelineLogPage {
|
|
3133
|
+
/** The cursor to pass as {@link PipelineLogQuery} `cursor` for the following page; absent when this is the last page. */
|
|
3134
|
+
nextCursor?: PipelineLogCursor;
|
|
3135
|
+
/** The rows, ordered `ts DESC` (newest first). At most `limit` of them. */
|
|
3136
|
+
rows: PipelineLogRow[];
|
|
3137
|
+
}
|
|
3138
|
+
/** Options for {@link createPipelineLogReader}. */
|
|
3139
|
+
interface PipelineLogReaderOptions {
|
|
3140
|
+
/**
|
|
3141
|
+
* Override any physical column name that diverges from the default (identity)
|
|
3142
|
+
* mapping. Unspecified fields keep their {@link DEFAULT_LOG_COLUMNS} name.
|
|
3143
|
+
*/
|
|
3144
|
+
columnMap?: PipelineLogColumnMap;
|
|
3145
|
+
/**
|
|
3146
|
+
* The Iceberg namespace the `table` lives in (R2 Data Catalog database).
|
|
3147
|
+
* Combined as `namespace.table` in the `FROM` clause; omit when `table`
|
|
3148
|
+
* already carries its namespace.
|
|
3149
|
+
*/
|
|
3150
|
+
namespace?: string;
|
|
3151
|
+
/** The Iceberg table name the Pipeline writes log records to (e.g. `"logs"`). */
|
|
3152
|
+
table: string;
|
|
3153
|
+
}
|
|
3154
|
+
/** The reader surface: a single keyset-paginated {@link PipelineLogPage} query. */
|
|
3155
|
+
interface PipelineLogReader {
|
|
3156
|
+
/** Run one filtered, keyset-paginated read and return a {@link PipelineLogPage}. */
|
|
3157
|
+
query: (query?: PipelineLogQuery) => Promise<PipelineLogPage>;
|
|
3158
|
+
}
|
|
3159
|
+
/** The written-column contract exposed publicly: canonical field to default physical column name. */
|
|
3160
|
+
declare const DEFAULT_LOG_COLUMNS: Readonly<Record<PipelineLogField, string>>;
|
|
3161
|
+
/** Default page size when a query omits `limit`. */
|
|
3162
|
+
declare const DEFAULT_LOG_LIMIT: number;
|
|
3163
|
+
/**
|
|
3164
|
+
* Build a durable-log reader over one R2 Data Catalog (Iceberg) table.
|
|
3165
|
+
*
|
|
3166
|
+
* The returned {@link PipelineLogReader} compiles each call to a safe
|
|
3167
|
+
* `SELECT ... WHERE ... ORDER BY ts DESC LIMIT n` (over-fetching by one) and
|
|
3168
|
+
* decodes the rows back to the canonical {@link PipelineLogRow} shape. All value
|
|
3169
|
+
* filters are escaped through `@lunora/bindings/r2sql`'s `sql`/`lit`; column
|
|
3170
|
+
* names come from `options.columnMap` (operator config), spliced with `raw`.
|
|
3171
|
+
* @param client An {@link R2SqlClient} (`createR2Sql({ accountId, apiToken, bucket })`).
|
|
3172
|
+
* @param options The target `table` (plus optional `namespace`) and any `columnMap` overrides.
|
|
3173
|
+
*/
|
|
3174
|
+
declare const createPipelineLogReader: (client: R2SqlClient, options: PipelineLogReaderOptions) => PipelineLogReader;
|
|
3013
3175
|
declare const VERSION: string;
|
|
3014
|
-
export { type AdminTableResolver, type AirbyteMessage, type AnalyticsEngineDataPointLike, type AnalyticsEngineDatasetLike, type AnalyticsEngineSinkOptions, type AuthAdmin, type AuthCapabilities, type AuthConfigInfo, type AuthImpersonation, type AuthPage, type AuthSession, type AuthUser, type AuthUserFieldSpec, type BackupManifest, type BackupStore, type ComposeIdentityResolversErrorMode, type ComposeIdentityResolversOptions, type ConnectorChange, type ConnectorSyncPage, type CorsOptions, type CronHandler, type CronJobDispatch, type CronJobInfo, type CrossShardCounter, type CrossShardReader, type CrossShardRelationCapabilities, type CrossShardRelationOptions, type CsrfOptions, DEFAULT_REGISTRY_CACHE_TTL_MS, type DurableObjectJurisdiction, type DynamicShardRegistry, type DynamicShardRegistryOptions, type ExecutionContextLike, type ExportFanOutRequest, type ExportFanOutResult, type FanOutRequest, type FanOutResult, type FanOutSpec, type FivetranResponse, type FrameworkHostHandler, type FrameworkWorkerOptions, type FrameworkWorkerOptionsInput, type FunctionDescriptor, type FunctionRegistryEntry, type FunctionRegistryLike, type GlobalExportFunction as GlobalExportFn, type GlobalImportFunction as GlobalImportFn, type GlobalIntrospector, type GlobalTableInfo as GlobalTableInfoMeta, type GlobalTablePage as GlobalTablePageMeta, type HttpActionContext, type HttpActionLike, type HttpRouterLike, type IdentityContractLike, type IdentityResolver, type IdentityValidation, type ImportFanOutRequest, type ImportFanOutResult, type KvIntrospector, type KvKeyEntry, type KvKeyListResult, type KvNamespaceSummary, type KvValueResult, type ListAuthUsersOptions, type LogEvent, type LogFields, type LogLevel, LunoraError, type LunoraErrorBody, type LunoraHandlerOptions, type LunoraWorker, type MergeStrategy, type MetricEvent, type MetricKind, type MigrationFanOutRequest, type MigrationFanOutResult, NOOP_EXECUTION_CONTEXT, type ObservabilityEvent, type ObservabilitySink, type ObservabilitySinkContext, type OtlpSinkOptions, type PipelineLike, type PipelineLogSinkOptions, type QueryCoordinator, type QueryCoordinatorOptions, type RankFanOutRequest, type RankFanOutResult, type RankPageFanOutRequest, type RankPageFanOutResult, type ResolvedSecurity, type ResolvedShard, type Route, type RpcContext, type RpcEnvelope, SHARD_REGISTRY_DO_NAME, type ScheduledControllerLike, type SecurityHeadersOptions, type SecurityOptions, type SentrySinkOptions, type ShardError, type ShardExportOutcome, type ShardImportOutcome, type ShardMigrationOutcome, type ShardNamespaceLike, type ShardRankOutcome, type ShardRankPageOutcome, type ShardRegistry, type ShardTrafficEntry, type ShardTrafficFanOutRequest, type ShardTrafficFanOutResult, type ShardingInfo, type SpanEvent, type StorageListFunction as StorageListFn, type StorageObject, VERSION, type VectorIndexSummary, type VectorIntrospector, type VectorQueryMatch, type WebhookSinkOptions, type WorkerOptions, analyticsEngineSink, applyJurisdiction, combineSinks, composeIdentityResolvers, composeWorker, consoleSink, createCrossShardRelationCapabilities, createDynamicShardRegistry, createLunoraHandler, createQueryCoordinator, createStaticShardRegistry, createWorker, decorateResponse, defineRpcEnvelope, emitLogEvent, emitRpcEvent, enforceOrigin, handleCorsPreflight, mergeStrategyForAggregate, otlpSink, pipelineLogSink, resolveLunoraOptions, resolveSecurity, resolveShard, routeIdentityResolvers, sentrySink, toAirbyteMessages, toErrorResponse, toFivetranResponse, webhookSink, withFrameworkWorker };
|
|
3176
|
+
export { type AdminTableResolver, type AirbyteMessage, type AnalyticsEngineDataPointLike, type AnalyticsEngineDatasetLike, type AnalyticsEngineSinkOptions, type AuthAdmin, type AuthCapabilities, type AuthConfigInfo, type AuthImpersonation, type AuthPage, type AuthSession, type AuthUser, type AuthUserFieldSpec, type BackupManifest, type BackupStore, type ComposeIdentityResolversErrorMode, type ComposeIdentityResolversOptions, type ConnectorChange, type ConnectorSyncPage, type CorsOptions, type CronHandler, type CronJobDispatch, type CronJobInfo, type CrossShardCounter, type CrossShardReader, type CrossShardRelationCapabilities, type CrossShardRelationOptions, type CsrfOptions, DEFAULT_LOG_COLUMNS, DEFAULT_LOG_LIMIT, DEFAULT_REGISTRY_CACHE_TTL_MS, type DurableObjectJurisdiction, type DynamicShardRegistry, type DynamicShardRegistryOptions, type ExecutionContextLike, type ExportFanOutRequest, type ExportFanOutResult, type FanOutRequest, type FanOutResult, type FanOutSpec, type FivetranResponse, type FrameworkHostHandler, type FrameworkWorkerOptions, type FrameworkWorkerOptionsInput, type FunctionDescriptor, type FunctionRegistryEntry, type FunctionRegistryLike, type GlobalExportFunction as GlobalExportFn, type GlobalImportFunction as GlobalImportFn, type GlobalIntrospector, type GlobalTableInfo as GlobalTableInfoMeta, type GlobalTablePage as GlobalTablePageMeta, type HttpActionContext, type HttpActionLike, type HttpRouterLike, type IdentityContractLike, type IdentityResolver, type IdentityValidation, type ImportFanOutRequest, type ImportFanOutResult, type KvIntrospector, type KvKeyEntry, type KvKeyListResult, type KvNamespaceSummary, type KvValueResult, type ListAuthUsersOptions, type LogEvent, type LogFields, type LogLevel, LunoraError, type LunoraErrorBody, type LunoraHandlerOptions, type LunoraWorker, type MergeStrategy, type MetricEvent, type MetricKind, type MigrationFanOutRequest, type MigrationFanOutResult, NOOP_EXECUTION_CONTEXT, type ObservabilityEvent, type ObservabilitySink, type ObservabilitySinkContext, type OtlpSinkOptions, type PipelineLike, type PipelineLogColumnMap, type PipelineLogCursor, type PipelineLogField, type PipelineLogPage, type PipelineLogQuery, type PipelineLogReader, type PipelineLogReaderOptions, type PipelineLogRow, type PipelineLogSinkOptions, type QueryCoordinator, type QueryCoordinatorOptions, type RankFanOutRequest, type RankFanOutResult, type RankPageFanOutRequest, type RankPageFanOutResult, type ResolvedSecurity, type ResolvedShard, type Route, type RpcContext, type RpcEnvelope, SHARD_REGISTRY_DO_NAME, type ScheduledControllerLike, type SecurityHeadersOptions, type SecurityOptions, type SentrySinkOptions, type ShardError, type ShardExportOutcome, type ShardImportOutcome, type ShardMigrationOutcome, type ShardNamespaceLike, type ShardRankOutcome, type ShardRankPageOutcome, type ShardRegistry, type ShardTrafficEntry, type ShardTrafficFanOutRequest, type ShardTrafficFanOutResult, type ShardingInfo, type SpanEvent, type StorageListFunction as StorageListFn, type StorageObject, VERSION, type VectorIndexSummary, type VectorIntrospector, type VectorQueryMatch, type WebhookSinkOptions, type WorkerOptions, analyticsEngineSink, applyJurisdiction, combineSinks, composeIdentityResolvers, composeWorker, consoleSink, createCrossShardRelationCapabilities, createDynamicShardRegistry, createLunoraHandler, createPipelineLogReader, createQueryCoordinator, createStaticShardRegistry, createWorker, decorateResponse, defineRpcEnvelope, emitLogEvent, emitRpcEvent, enforceOrigin, handleCorsPreflight, mergeStrategyForAggregate, otlpSink, pipelineLogSink, resolveLunoraOptions, resolveSecurity, resolveShard, routeIdentityResolvers, sentrySink, toAirbyteMessages, toErrorResponse, toFivetranResponse, webhookSink, withFrameworkWorker };
|
package/dist/index.mjs
CHANGED
|
@@ -4,7 +4,8 @@ export { createCrossShardRelationCapabilities } from './packem_shared/createCros
|
|
|
4
4
|
export { DEFAULT_REGISTRY_CACHE_TTL_MS, SHARD_REGISTRY_DO_NAME, createDynamicShardRegistry } from './packem_shared/DEFAULT_REGISTRY_CACHE_TTL_MS-B3pA7aXp.mjs';
|
|
5
5
|
export { LunoraError, toErrorResponse } from './packem_shared/LunoraError-Bpb9EFJ3.mjs';
|
|
6
6
|
export { emitLogEvent, emitRpcEvent } from './packem_shared/emitLogEvent-pEdtqAK8.mjs';
|
|
7
|
-
export { analyticsEngineSink, combineSinks, consoleSink, otlpSink, pipelineLogSink, sentrySink, webhookSink } from './packem_shared/analyticsEngineSink-
|
|
7
|
+
export { analyticsEngineSink, combineSinks, consoleSink, otlpSink, pipelineLogSink, sentrySink, webhookSink } from './packem_shared/analyticsEngineSink-Bn7p0URe.mjs';
|
|
8
|
+
export { DEFAULT_LOG_COLUMNS, DEFAULT_LOG_LIMIT, createPipelineLogReader } from './packem_shared/DEFAULT_LOG_COLUMNS-J94BHDTf.mjs';
|
|
8
9
|
export { createQueryCoordinator, createStaticShardRegistry, mergeStrategyForAggregate } from './packem_shared/createQueryCoordinator-DNCJzOZE.mjs';
|
|
9
10
|
export { applyJurisdiction, resolveShard } from './packem_shared/applyJurisdiction-BkZtTkct.mjs';
|
|
10
11
|
export { decorateResponse, enforceOrigin, handleCorsPreflight, resolveSecurity } from './packem_shared/decorateResponse-DRWQFNhF.mjs';
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { raw, sql, desc } from '@lunora/bindings/r2sql';
|
|
2
|
+
|
|
3
|
+
const LOG_LEVEL_ORDER = ["trace", "debug", "log", "info", "warn", "error", "fatal"];
|
|
4
|
+
|
|
5
|
+
const DEFAULT_COLUMNS = {
|
|
6
|
+
fields: "fields",
|
|
7
|
+
functionPath: "functionPath",
|
|
8
|
+
level: "level",
|
|
9
|
+
message: "message",
|
|
10
|
+
shardKey: "shardKey",
|
|
11
|
+
spanId: "spanId",
|
|
12
|
+
traceId: "traceId",
|
|
13
|
+
ts: "ts",
|
|
14
|
+
userId: "userId"
|
|
15
|
+
};
|
|
16
|
+
const DEFAULT_LIMIT = 500;
|
|
17
|
+
const MAX_LIMIT = 1e4;
|
|
18
|
+
const clampLimit = (limit) => {
|
|
19
|
+
if (limit === void 0 || !Number.isFinite(limit)) {
|
|
20
|
+
return DEFAULT_LIMIT;
|
|
21
|
+
}
|
|
22
|
+
const floored = Math.floor(limit);
|
|
23
|
+
if (floored < 1) {
|
|
24
|
+
return 1;
|
|
25
|
+
}
|
|
26
|
+
if (floored > MAX_LIMIT) {
|
|
27
|
+
return MAX_LIMIT;
|
|
28
|
+
}
|
|
29
|
+
return floored;
|
|
30
|
+
};
|
|
31
|
+
const toTs = (value) => typeof value === "number" ? value : Number(value);
|
|
32
|
+
const renderCell = (value) => value === null || value === void 0 ? "" : String(value);
|
|
33
|
+
const decodeFields = (value) => {
|
|
34
|
+
if (typeof value !== "string") {
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
return JSON.parse(value);
|
|
39
|
+
} catch {
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const DEFAULT_LOG_COLUMNS = DEFAULT_COLUMNS;
|
|
44
|
+
const DEFAULT_LOG_LIMIT = DEFAULT_LIMIT;
|
|
45
|
+
const createPipelineLogReader = (client, options) => {
|
|
46
|
+
const columns = { ...DEFAULT_COLUMNS, ...options.columnMap };
|
|
47
|
+
const tableReference = options.namespace === void 0 ? options.table : `${options.namespace}.${options.table}`;
|
|
48
|
+
return {
|
|
49
|
+
query: async (query = {}) => {
|
|
50
|
+
const limit = clampLimit(query.limit);
|
|
51
|
+
const fetchLimit = Math.min(limit + 1, MAX_LIMIT);
|
|
52
|
+
const builder = client.from(tableReference).select(
|
|
53
|
+
raw(columns.functionPath),
|
|
54
|
+
raw(columns.level),
|
|
55
|
+
raw(columns.message),
|
|
56
|
+
raw(columns.ts),
|
|
57
|
+
raw(columns.fields),
|
|
58
|
+
raw(columns.shardKey),
|
|
59
|
+
raw(columns.userId),
|
|
60
|
+
raw(columns.traceId),
|
|
61
|
+
raw(columns.spanId)
|
|
62
|
+
);
|
|
63
|
+
if (query.sinceTs !== void 0) {
|
|
64
|
+
builder.where(sql`${raw(columns.ts)} >= ${query.sinceTs}`);
|
|
65
|
+
}
|
|
66
|
+
if (query.untilTs !== void 0) {
|
|
67
|
+
builder.where(sql`${raw(columns.ts)} <= ${query.untilTs}`);
|
|
68
|
+
}
|
|
69
|
+
if (query.level !== void 0) {
|
|
70
|
+
builder.where(sql`${raw(columns.level)} = ${query.level}`);
|
|
71
|
+
} else if (query.minLevel !== void 0) {
|
|
72
|
+
const floorIndex = LOG_LEVEL_ORDER.indexOf(query.minLevel);
|
|
73
|
+
const allowed = floorIndex === -1 ? [...LOG_LEVEL_ORDER] : LOG_LEVEL_ORDER.slice(floorIndex);
|
|
74
|
+
builder.where(sql`${raw(columns.level)} IN ${allowed}`);
|
|
75
|
+
}
|
|
76
|
+
if (query.functionPath !== void 0) {
|
|
77
|
+
builder.where(sql`${raw(columns.functionPath)} = ${query.functionPath}`);
|
|
78
|
+
}
|
|
79
|
+
if (query.functionPathPrefix !== void 0) {
|
|
80
|
+
builder.where(sql`${raw(columns.functionPath)} LIKE ${`${query.functionPathPrefix}%`}`);
|
|
81
|
+
}
|
|
82
|
+
if (query.traceId !== void 0) {
|
|
83
|
+
builder.where(sql`${raw(columns.traceId)} = ${query.traceId}`);
|
|
84
|
+
}
|
|
85
|
+
if (query.shardKey !== void 0) {
|
|
86
|
+
builder.where(sql`${raw(columns.shardKey)} = ${query.shardKey}`);
|
|
87
|
+
}
|
|
88
|
+
if (query.userId !== void 0) {
|
|
89
|
+
builder.where(sql`${raw(columns.userId)} = ${query.userId}`);
|
|
90
|
+
}
|
|
91
|
+
if (query.cursor !== void 0) {
|
|
92
|
+
builder.where(sql`${raw(columns.ts)} < ${query.cursor.ts}`);
|
|
93
|
+
}
|
|
94
|
+
builder.orderBy(desc(raw(columns.ts))).limit(fetchLimit);
|
|
95
|
+
const { rows } = await builder.run();
|
|
96
|
+
const hasMore = rows.length > limit;
|
|
97
|
+
const pageRows = hasMore ? rows.slice(0, limit) : rows;
|
|
98
|
+
const overflow = hasMore ? rows[limit] : void 0;
|
|
99
|
+
const decoded = pageRows.map((row) => {
|
|
100
|
+
const out = {
|
|
101
|
+
functionPath: renderCell(row[columns.functionPath]),
|
|
102
|
+
// The stored `level` is one of the canonical severities; the
|
|
103
|
+
// reader trusts the writer's contract here rather than re-validating.
|
|
104
|
+
level: renderCell(row[columns.level]),
|
|
105
|
+
message: renderCell(row[columns.message]),
|
|
106
|
+
ts: toTs(row[columns.ts])
|
|
107
|
+
};
|
|
108
|
+
const fields = row[columns.fields];
|
|
109
|
+
if (fields !== void 0 && fields !== null) {
|
|
110
|
+
out.fields = decodeFields(fields);
|
|
111
|
+
}
|
|
112
|
+
const shardKey = row[columns.shardKey];
|
|
113
|
+
if (shardKey !== void 0 && shardKey !== null) {
|
|
114
|
+
out.shardKey = renderCell(shardKey);
|
|
115
|
+
}
|
|
116
|
+
const userId = row[columns.userId];
|
|
117
|
+
if (userId !== void 0 && userId !== null) {
|
|
118
|
+
out.userId = renderCell(userId);
|
|
119
|
+
}
|
|
120
|
+
const traceId = row[columns.traceId];
|
|
121
|
+
if (traceId !== void 0 && traceId !== null) {
|
|
122
|
+
out.traceId = renderCell(traceId);
|
|
123
|
+
}
|
|
124
|
+
const spanId = row[columns.spanId];
|
|
125
|
+
if (spanId !== void 0 && spanId !== null) {
|
|
126
|
+
out.spanId = renderCell(spanId);
|
|
127
|
+
}
|
|
128
|
+
return out;
|
|
129
|
+
});
|
|
130
|
+
return overflow === void 0 ? { rows: decoded } : { nextCursor: { ts: toTs(overflow[columns.ts]) }, rows: decoded };
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
export { DEFAULT_LOG_COLUMNS, DEFAULT_LOG_LIMIT, createPipelineLogReader };
|
package/dist/packem_shared/{analyticsEngineSink-DWUhiYHC.mjs → analyticsEngineSink-Bn7p0URe.mjs}
RENAMED
|
@@ -270,7 +270,7 @@ const analyticsEngineSink = (options) => {
|
|
|
270
270
|
};
|
|
271
271
|
};
|
|
272
272
|
const pipelineLogSink = (options) => {
|
|
273
|
-
const { pipeline } = options;
|
|
273
|
+
const { pipeline, serializeFields } = options;
|
|
274
274
|
return {
|
|
275
275
|
onLog: (event, context) => {
|
|
276
276
|
try {
|
|
@@ -281,7 +281,7 @@ const pipelineLogSink = (options) => {
|
|
|
281
281
|
ts: event.ts
|
|
282
282
|
};
|
|
283
283
|
if (event.fields) {
|
|
284
|
-
record.fields = event.fields;
|
|
284
|
+
record.fields = serializeFields === true ? JSON.stringify(event.fields) : event.fields;
|
|
285
285
|
}
|
|
286
286
|
if (event.shardKey !== void 0) {
|
|
287
287
|
record.shardKey = event.shardKey;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/runtime",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.31",
|
|
4
4
|
"description": "Lunora Worker runtime: the RPC router, shard resolver, and query coordinator",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"access": "public"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
+
"@lunora/bindings": "1.0.0-alpha.9",
|
|
49
50
|
"@lunora/errors": "1.0.0-alpha.6"
|
|
50
51
|
},
|
|
51
52
|
"engines": {
|