/** * WHERE AN OPTED-IN EVENT ACTUALLY GOES. * * `policy.ts` decided whether we may measure and `event.ts` decided what an * event may contain, and between them they did nothing: no importer outside * their own tests existed, so a user who set TOKEN_OPTIMIZER_TELEMETRY=1 got * exactly the same behaviour as a user who set nothing. An opt-in that collects * nothing is worse than no opt-in, because the switch reads as a working * feature. * * LOCAL ONLY, AND THAT IS THE WHOLE DESIGN. This module writes to the user's own * disk and opens no socket. Aggregation and upload are two switches in * `policy.ts` for a reason, and keeping them two modules is what makes the * separation checkable rather than asserted: there is no network call in this * file to gate. * * IT MAY NEVER THROW INTO ITS CALLER. Telemetry is instrumentation, so a full * disk, a read-only home directory or a permissions failure has to degrade to * "no telemetry" and not to a failed tool call. Every entry point swallows, and * the swallow is the feature -- which is also why `lastError` exists, so * `doctor` can say the recording is silently not happening. * * APPEND-ONLY JSONL, BOUNDED. One line per event so a partial write costs one * event rather than the file, and a size ceiling so an unattended machine that * opts in cannot grow this without limit. When the ceiling is reached the file * is rotated once and the old one replaced: a fixed two-file cost, and the most * recent data is the data kept. */ import { type TelemetryEvent } from './event.js'; /** * The directory the rest of the package already uses for per-user state. * * RESOLVED ON EVERY CALL, NOT ONCE AT IMPORT. A module-level constant is the * obvious way to write this and it is the reason the first version could not be * tested: the path was fixed by whichever home directory existed at import, so * no test could put the file somewhere disposable, and a module whose failure * paths cannot be exercised is a module that ships unwired -- which is exactly * what this one did. * * It is also simply more honest. Every other decision here reads the * environment when it is asked, so that a user who changes their mind is obeyed * from the next event. The location is no different. */ export declare function telemetryDir(env?: NodeJS.ProcessEnv): string; /** The live file. */ export declare function eventsFile(env?: NodeJS.ProcessEnv): string; /** The one file kept behind it. */ export declare function rotatedFile(env?: NodeJS.ProcessEnv): string; /** * The ceiling, in bytes, before the live file is rotated. * * An event is a few hundred bytes, so this is on the order of ten thousand * events -- far more than any analysis needs, and small enough that nobody * notices it on disk. */ export declare const MAX_BYTES: number; export declare function libraryVersion(): string; /** Why recording is not happening, or null if nothing has failed. */ export declare function recorderLastError(): string | null; /** Bytes currently held, or null when the file is absent or unreadable. */ export declare function recordedBytes(env?: NodeJS.ProcessEnv): number | null; /** * Record one event, if the user has opted in. * * Returns the event that was written, or null when nothing was written -- which * covers both "not opted in" and "could not write". The caller is not expected * to care about the difference; `doctor` is. * * THE POLICY IS CHECKED HERE RATHER THAN AT THE CALL SITES, deliberately. A call * site that has to remember to ask is a call site that will eventually forget, * and forgetting means transmitting without consent. Reading the environment on * every call also means a user who changes their mind is obeyed from the next * event, with no restart and no cached decision. */ export declare function record(eventType: string, version?: string, properties?: Readonly>, env?: NodeJS.ProcessEnv): TelemetryEvent | null; //# sourceMappingURL=recorder.d.ts.map