/** * Formats + schedules the minutely `rpc_usage` telemetry log lines. Invariants * here: one logfmt line per method, DELTA counts (so `sum_over_time` over any * range is the true request count), logfmt-token safety, idle windows emit * nothing. WHY the accounting exists and how it counts lives in ONE place: * packages/chain/src/rpc-usage.ts (module overview). * * Line shape (parsed in LogQL with `| logfmt` on the log body): * rpc_usage method=eth_call count=42 window_s=60 chain=base:8453 * * Companion diagnostic line shape for `eth_call` attribution: * rpc_usage_by_consumer method=eth_call consumer=pcaNFT.getAccountInfo count=7 window_s=60 chain=base:8453 * * `eth_getLogs` additionally identifies the non-secret configured endpoint slot: * rpc_usage_by_consumer method=eth_getLogs consumer=getContextGraphAuthoritySnapshot endpoint_slot=fallback_1 count=7 window_s=60 chain=base:8453 * * The shared transport budget emits one state + delta line per window: * rpc_request_governor max_rps=10 background_max_rps=2 foreground_queued=0 background_queued=4 ... * * Background views that left in aggregate requests: one summary line, then the * reads each request carried by their own read label. The requests themselves * are already counted above as `eth_call` under `multicall3.aggregate3`: * rpc_read_batching batches=9 failed_batches=0 refused_batches=0 calls=74 reads=81 direct_reads=1 window_s=60 chain=base:8453 * rpc_batched_reads consumer=kas.getLatestMerkleRoot count=27 window_s=60 chain=base:8453 * An aggregate request that one caller sends for itself (the Context Graph * enumeration) is not in these two lines: it is counted once, as `eth_call` * under that caller's own consumer. */ import { type RpcUsageDrainable, type RpcUsageWindow, type RpcReadBatchingWindow, type RpcRequestGovernorWindow } from '@origintrail-official/dkg-chain'; /** * One logfmt line per method with a nonzero count in the window. Returns [] when * the window is empty (the caller skips logging entirely — an idle node emits * nothing rather than a stream of zeros). */ export declare function formatRpcUsageLines(usage: RpcUsageWindow, windowSeconds: number, chainId?: string, requestGovernor?: RpcRequestGovernorWindow, readBatching?: RpcReadBatchingWindow): string[]; /** What the daemon drains: anything (partially) implementing the shared contract. */ export type RpcUsageSource = Partial; /** Process-wide governor state has one drain owner, separate from usage sums. */ export interface RpcTelemetrySource extends RpcUsageSource { drainRpcRequestGovernor?: () => RpcRequestGovernorWindow; /** Process-wide like the governor: one drain owner for every adapter. */ drainRpcReadBatching?: () => RpcReadBatchingWindow; } /** Keep live adapter deltas and the process-owned drains in one telemetry source. */ export declare function createDaemonRpcTelemetrySource(usageSources: readonly (() => RpcUsageWindow | undefined)[], governor?: { drainWindow(): RpcRequestGovernorWindow; }): RpcTelemetrySource; /** * Drain the source's RPC-usage window and emit one `rpc_usage` line per method * through `emit`. The COMPLETE daemon emission step (drain → format → emit), * extracted so the lifecycle timer AND the shutdown final-drain share one * unit-tested implementation. Returns the number of lines emitted (0 for a * missing capability or an empty window). Never throws. */ export declare function emitRpcUsage(source: RpcTelemetrySource | undefined, emit: (line: string) => void, windowSeconds: number, chainId?: string): number; /** Handle returned by {@link startRpcUsageTelemetry}. */ export interface RpcUsageTelemetryHandle { /** * Clear the timer and perform ONE final best-effort drain+emit, so a partial * window (e.g. a publish burst right before a restart) still reaches the log * pipeline instead of dying in memory. Idempotent-safe to call once at * daemon teardown, BEFORE telemetry shuts down. */ stop(): void; } /** * The COMPLETE RPC-usage telemetry lifecycle: schedules the minutely * drain→format→emit tick (unref'd — never keeps the process alive) and owns * the shutdown final-drain. `runDaemonInner` just wires source/emit and calls * `stop()` at teardown — no feature scheduling embedded in the daemon monolith. */ export declare function startRpcUsageTelemetry(opts: { source: RpcTelemetrySource; emit: (line: string) => void; chainId?: string; /** Window length in seconds (default 60). */ windowSeconds?: number; }): RpcUsageTelemetryHandle; //# sourceMappingURL=rpc-usage-log.d.ts.map