/** * Local-file POC source — the analyze-file flow. * * Reads a log file (typically a fluentd/k8s/docker-wrapped JSONL dump, * e.g. a CloudWatch export) and normalizes it for pattern extraction. * * The normalization is the measured requirement from the engine * handoff §20: wrapped JSON must be pre-extracted before templating — * fed raw, the templater tokenizes the wrapper (mangled names, no * welds); pre-extracted, patterns come out clean and welds hold. * * Mechanism: when the file sniffs as wrapped JSONL, each line is * parsed and handed to `extractPatterns` as an OBJECT. The existing * `coerceToLine` descent unwraps the `log`/`message` payload for the * templater, and `extractEnrichmentFromEnvelope` keeps the container * attribution (kubernetes.container_name / pod labels) that the * container-keyed change rows need — the MCP-native equivalent of the * engine-side `\t` + sourcePattern contract. * * Byte accounting: `totalBytes` counts the UNWRAPPED payload bytes * (what the templater analyses); `rawBytes` keeps the on-disk wrapped * size (what a vendor would bill on) and travels to * RenderInput.rawIngestBytes. */ import type { LocalSourceResult } from './local-source.js'; /** Hard input cap — refuse above rather than OOM. */ export declare const MAX_FILE_BYTES: number; /** * Above this size, the single file is SAMPLED strided across its length rather * than fed whole to the engine. Feeding a 70MB file whole timed out the engine * (120s cap in dev-cli), and a contiguous read under-covers a time-ordered * file's pattern space (F8/F15). 24MB processes in well under the engine * timeout and, sampled strided, spans the whole file. */ export declare const SINGLE_FILE_SAMPLE_BYTES: number; export interface FileSourceResult extends LocalSourceResult { /** What extractPatterns should consume: objects when wrapped * (envelope-aware path), raw strings otherwise. */ records: unknown[]; /** On-disk bytes (wrapped size) — the billable figure. */ rawBytes: number; /** On-disk bytes of the sampled lines, newlines included; equals `rawBytes` when the file was read whole. */ sampledRawBytes: number; /** On-disk bytes of each sampled line, aligned with `records`, newline included. */ lineRawBytes: number[]; /** True when the wrapped-JSON normalization path was taken. */ normalized: boolean; } declare function isWrappedLine(line: string): Record | null; declare function containerOf(rec: Record): string; declare function payloadOf(rec: Record): string; export type CaptureEventSource = 'forwarder' | 'archive' | 'pods' | 'lines'; /** * What a capture's events are, from its records: a forwarder's own output * (a `log` payload, or a CloudWatch export of one), a Datadog log archive * (`message` with Datadog's `status` and `service` or `attributes`), the * pods' own logs (kubectl), or plain lines. The first three hold every event * the services wrote, the ones a Datadog index exclusion filter drops * included; a sample read back from Datadog's API holds indexed events only. */ export declare function captureEventSource(records: unknown[], fromKubectl?: boolean): CaptureEventSource; /** One sentence on which events a capture holds, for the native-filter comparison. */ export declare function captureEventSourceSentence(kind: CaptureEventSource): string; /** * What `extractPatterns` needs to count each event in the Receiver's unit: * the forwarder's record bytes where a line carries one, and every line's * time. Lines without a record are counted as payload plus the assumed * metadata (see receiver-bytes.ts). */ export declare function receiverExtractionInputs(records: unknown[]): { lineRecordBytes: Array; linePayloadJsonBytes: Array; lineTimesMs: Array; }; /** * The order to hand a capture's records to the templater: grouped by * container, file order kept within each. A capture interleaves containers, * and the templater joins a continuation line to the line before it, which * in file order can be another container's; the Receiver joins only within * a container's stream. */ export declare function containerOrder(records: unknown[]): number[]; /** Each record's compact bytes and its payload's JSON bytes, where the record is a forwarder's. */ export declare function receiverRecordBytes(records: unknown[]): { lineRecordBytes: Array; linePayloadJsonBytes: Array; }; export declare function sampleFromFile(path: string): Promise; /** The time span a file sample covers, and what it was read from. */ export interface FileSpan { seconds: number; source: 'timestamps' | 'window'; /** First and last record timestamps, when the span came from them. */ firstIso?: string; lastIso?: string; recordsWithTimestamp: number; records: number; /** The caller's `window`, when one was passed. */ window?: string; } /** A file run with no way to know the span its bytes cover. */ export declare class FileSpanRefusal extends Error { } declare function lineTimestampMs(line: string): number | undefined; /** A record's own event time: an envelope or wrapper field for a JSON record, a leading ISO-8601 time for a plain line. */ export declare function recordTimestampMs(rec: unknown): number | undefined; /** * The span a file sample covers: first to last record timestamp; else the * caller's `window`; else a refusal. A plan's per-window caps divide bytes by * this span, so it is never assumed. */ export declare function resolveFileSpan(records: unknown[], window: string | undefined): FileSpan; /** * One sentence naming the span and where it came from. `sampleShare` is the * sampled share of the files' bytes, when less than all of them was read. */ export declare function describeFileSpan(span: FileSpan, sampleShare?: number): string; /** Exported for tests. */ export declare const _internals: { isWrappedLine: typeof isWrappedLine; containerOf: typeof containerOf; payloadOf: typeof payloadOf; lineTimestampMs: typeof lineTimestampMs; }; export {};