import type { Watcher, WatcherContext } from '../nest/watcher.js';
import { type AxiosInterceptorLike, type CustomAxiosSource } from './axios-source.js';
export interface HttpClientWatcherOptions {
    /** Outbound calls at/above this many ms get a 'slow' tag. Default 1000. */
    slowMs?: number;
    /** Time source; injectable for tests. Default wall clock. */
    clock?: {
        now(): number;
    };
    /**
     * An axios instance (or {@link CustomAxiosSource} for lazy resolution) to
     * capture alongside the global `fetch`. NestJS apps mostly call out through
     * `@nestjs/axios`'s `HttpService`, whose `axiosRef` is exactly an
     * {@link AxiosInterceptorLike}; in Node that traffic uses the http adapter and
     * is invisible to the `fetch` patch. Pass the instance (or a source that
     * resolves `HttpService` from `ctx.moduleRef`) to capture it via axios's
     * public interceptor API — no monkey-patching.
     */
    axios?: AxiosInterceptorLike | CustomAxiosSource;
}
/**
 * Captures outbound HTTP calls made via the global `fetch` and, optionally, via
 * an axios instance (`@nestjs/axios`'s `HttpService.axiosRef` or a bare axios),
 * correlated to the request/job that made them.
 *
 * Both paths run inside the caller's async context, so the active ALS batch
 * (set by the request middleware) is live when we record — no extra wiring is
 * needed for correlation. Recording is guarded so a telescope failure can never
 * change the host's HTTP result, and the host's network error is always
 * re-thrown. The `fetch` patch is idempotent across instances via a symbol
 * marker; axios instrumentation is idempotent via a module-level `WeakSet` of
 * instrumented instances (so two watchers sharing one axios don't double-wrap).
 *
 * ## Why axios needs its own path
 * NestJS apps mostly call out through `@nestjs/axios`. In Node, axios uses the
 * http adapter (not `fetch`), so those calls bypass the `fetch` patch entirely
 * and are invisible without this. We attach via axios's PUBLIC interceptor API
 * (`interceptors.request/response.use`) — never monkey-patching — so we don't
 * fight axios internals or other interceptors the host installs.
 *
 * @remarks
 * Only the global `fetch` and an explicitly-provided axios instance are
 * instrumented. Clients that bypass both (a custom `http.request`, native
 * addons) are not captured. The global `fetch` is replaced for the process
 * lifetime (not restored on shutdown) — appropriate for an always-on
 * observability tool. The captured URL has userinfo stripped and sensitive
 * query-param values redacted; key-based content redaction does not otherwise
 * apply to the URL string.
 *
 * **Double-capture (edge case):** if an axios instance is explicitly configured
 * with a `fetch` adapter AND that `fetch` is our patched global, a single call
 * could record twice (once per path). Node's default is the http adapter, so
 * this only happens when a host opts into the fetch adapter; we don't build
 * detection machinery for it.
 */
export declare class HttpClientWatcher implements Watcher {
    readonly type: "http_client";
    private readonly logger;
    private readonly slowMs;
    private readonly clock;
    private readonly axiosSource;
    /** Per-request start times, keyed by the axios config object. A `WeakMap`
     *  (not a symbol stamped onto the config) keeps the host's object pristine and
     *  lets entries be GC'd if a request never completes — no leak, no mutation. */
    private readonly axiosStartedAt;
    constructor(options?: HttpClientWatcherOptions);
    register(ctx: WatcherContext): void;
    /** Patch the global `fetch` exactly as before — unchanged behavior. Idempotent
     *  process-wide via the {@link PATCHED} marker. Pulled into its own method so
     *  axios instrumentation can run independently (and still attach even when
     *  `fetch` is missing or already patched). */
    private patchFetch;
    /** Wire axios capture if an axios source was provided. The bare-instance form
     *  attaches immediately; the {@link CustomAxiosSource} form hands the host an
     *  `attach` callback so it can resolve `HttpService` from `ctx.moduleRef`
     *  lazily (the instance often doesn't exist yet at construction time). */
    private registerAxios;
    /** Install request/response interceptors on an axios instance via its public
     *  API. Idempotent via the module-level {@link INSTRUMENTED_AXIOS} set: a
     *  second call (re-registration, or two watchers sharing one instance) is a
     *  no-op so no call double-records.
     *
     *  Timing uses {@link axiosStartedAt} — a `WeakMap<config, number>` — rather
     *  than stamping the config: axios passes the SAME config object from the
     *  request interceptor through to the response/error interceptor, so the
     *  config is a stable key, and a `WeakMap` neither mutates the host's object
     *  nor leaks if a request never resolves. */
    private attachAxios;
    /** Compute duration from the stored start time, describe the target, and hand
     *  the entry to {@link safeRecord} — the same content/tags/family-hash shape as
     *  the `fetch` path, so axios and fetch entries are indistinguishable. A
     *  missing start time (interceptor order, or a config we never saw) records
     *  `durationMs: 0` rather than dropping the entry. */
    private recordAxios;
    /** Hand an entry to the Recorder, swallowing any failure so a telescope bug
     *  can never alter the host's HTTP call. */
    private safeRecord;
}
//# sourceMappingURL=http-client.watcher.d.ts.map