/** * backend-fetch — shared retry+timeout primitive for every PromQL-compatible * backend the MCP talks to. * * The single retry+timeout contract for metrics-backend.ts and * customer-metrics.ts, in place of per-backend bespoke `fetch(...)` blocks: * * - Default 3 attempts (`LOG10X_RETRY_ATTEMPTS` override). * - 250ms base backoff, exponential with jitter (`LOG10X_RETRY_BASE_MS`). * - 30s per-attempt timeout via AbortController (`LOG10X_REQUEST_TIMEOUT_MS`). * - Retry classes: network exception, HTTP 5xx, HTTP 429. * - Timeout (AbortError) is NOT retried by default: re-issuing an identical * query with an identical budget almost always times out again, so * retrying a single slow read costs up to attempts×timeout (~90s) of * wall-clock before failing. Set `LOG10X_RETRY_TIMEOUTS=true` (or * opts.retryTimeouts) for retry-on-timeout — an escape hatch for * cold-warmup self-hosted stores (e.g. Mimir/Cortex store-gateway lazy load). * - Non-retryable: any other 4xx — surfaced immediately with kind-labelled body. * - AMP path: `reSignPerAttempt` callback rebuilds the signed init each * attempt so SigV4 timestamps stay fresh. * * Error envelope: * `${kindLabel} HTTP : ` * `${kindLabel}: request timed out after ${timeoutMs}ms` * `${kindLabel}: fetch failed after ${attempts} attempts` * * Consumed by promJsonFetch (metrics-backend.ts) and all six customer-metrics * backends. tool-errors.ts widens its transient-failure regex to match these * error tails. */ export interface BackendFetchOpts { /** Short identifier for error envelopes + console.warn lines. */ kindLabel: string; /** Per-attempt timeout. Defaults to LOG10X_REQUEST_TIMEOUT_MS or 30000. */ timeoutMs?: number; /** Max attempts (1 = no retry). Defaults to LOG10X_RETRY_ATTEMPTS or 3. */ attempts?: number; /** Exponential backoff base. Defaults to LOG10X_RETRY_BASE_MS or 250. */ baseMs?: number; /** * Retry on timeout (AbortError). Defaults to false (fail fast on the first * timeout). Falls back to the LOG10X_RETRY_TIMEOUTS env flag when unset. * Network / 5xx / 429 retries are unaffected by this. */ retryTimeouts?: boolean; /** * AMP-style: rebuild a freshly-signed init each attempt. When provided, * the caller-supplied `init` is ignored and replaced per attempt with * the return value of `reSignPerAttempt()`. The `signal` from the * per-attempt AbortController is merged in. */ reSignPerAttempt?: () => Promise; } /** * Core fetch primitive. Returns the Response on success (2xx). Throws on: * - retryable exhaustion (5xx / 429 / network / timeout × attempts) * - non-retryable 4xx (status < 500, status !== 429) — immediately. */ export declare function backendFetch(url: string, init: RequestInit, opts: BackendFetchOpts): Promise; /** * JSON wrapper. Parses .json() on success. Error envelope on non-ok was * already thrown by backendFetch. Network/timeout failures bubble up * unchanged. */ export declare function backendJsonFetch(url: string, init: RequestInit, opts: BackendFetchOpts): Promise;