import { EventAttributes, EventSubscriber, EventTrackingOptions, FunnelStatus, OutcomeStatus } from "autotel/event-subscriber"; //#region src/loki.d.ts interface LokiConfig { /** * Base URL of the Loki instance, without the push path. * Falls back to `LOKI_ENDPOINT`, `LOKI_URL`, then `LOKI_BASE_URL`. * * @example 'http://localhost:3100' * @example 'https://logs-prod-eu-west-0.grafana.net' */ endpoint?: string; /** * API token. Paired with {@link LokiConfig.user} it is sent as HTTP Basic, * which is what Grafana Cloud expects. Alone it is sent as Bearer, which * suits an instance behind an authenticating proxy. * Falls back to `LOKI_API_KEY`, then `GRAFANA_API_KEY`. */ apiKey?: string; /** * Grafana Cloud instance ID — the numeric user of the Loki datasource, not * an account email. Supplying it switches authentication to Basic. * Falls back to `LOKI_USER`, then `GRAFANA_USER`. */ user?: string; /** * Tenant for multi-tenant self-hosted Loki, sent as `X-Scope-OrgID`. * Independent of the auth mode. Falls back to `LOKI_TENANT_ID`. */ tenantId?: string; /** * Event fields promoted to stream labels. * Defaults to `['service', 'environment', 'level']`. * * Keep this short and bounded. Promoting `requestId` or `userId` creates one * stream per value, which degrades and eventually breaks an instance. */ labelFields?: string[]; /** Static labels merged into every stream, e.g. `{ cluster: 'prod-eu' }`. */ labels?: Record; /** Events buffered before a push. Default 100. */ batchSize?: number; /** Milliseconds before a partial batch is pushed anyway. Default 5000. */ flushIntervalMs?: number; /** Request timeout in milliseconds. Default 5000. */ timeoutMs?: number; /** Attempts including the first. Default 3. */ maxRetries?: number; /** Set false to construct the subscriber without sending anything. */ enabled?: boolean; } /** One event as it is written to the Loki line. */ type LokiEvent = EventAttributes & { timestamp?: string; }; interface LokiStream { stream: Record; values: [string, string][]; } interface LokiPayload { streams: LokiStream[]; } /** Resolve the push URL, tolerating an endpoint that already carries the path. */ declare function resolveLokiPushUrl(endpoint: string): string; /** Loki entry timestamps are nanosecond epoch strings. */ declare function toLokiTimestamp(timestamp?: string): string; /** * Build the stream labels for one event. * * Only configured fields holding a string, number or boolean become labels. * Objects and arrays are skipped rather than stringified, because a serialised * object is exactly the unbounded label value that wrecks a Loki instance. */ declare function toLokiLabels(event: LokiEvent, config?: Pick): Record; /** * Group events into streams by label set. * * Loki rejects a push whose entries run backwards within a stream, so each * stream's values are sorted by timestamp before they go out. */ declare function buildLokiPayload(events: LokiEvent[], config?: Pick): LokiPayload; /** Auth and tenancy headers for a resolved config. */ declare function toLokiHeaders(config: Pick): Record; /** Push a batch of events without going through a subscriber. */ declare function sendBatchToLoki(events: LokiEvent[], config?: LokiConfig): Promise; /** Push a single event without going through a subscriber. */ declare function sendToLoki(event: LokiEvent, config?: LokiConfig): Promise; /** * Buffers events and pushes them to Loki as grouped streams. * * Batching is not an optimisation here so much as the shape Loki wants: one * request carrying several streams costs far less than one request per event, * and grouping is what lets entries be ordered within a stream. */ declare class LokiSubscriber implements EventSubscriber { readonly name = "LokiSubscriber"; readonly version = "1.0.0"; private readonly config; private readonly endpoint; private readonly enabled; private readonly batchSize; private readonly flushIntervalMs; private readonly httpClient; private buffer; private timer; private readonly pending; private warnedMissingEndpoint; constructor(config?: LokiConfig); private record; /** Push everything buffered so far. Safe to call when empty. */ flush(): Promise; trackEvent(name: string, attributes?: EventAttributes, options?: EventTrackingOptions): Promise; trackFunnelStep(funnelName: string, step: FunnelStatus, attributes?: EventAttributes, options?: EventTrackingOptions): Promise; trackOutcome(operationName: string, outcome: OutcomeStatus, attributes?: EventAttributes, options?: EventTrackingOptions): Promise; trackValue(name: string, value: number, attributes?: EventAttributes, options?: EventTrackingOptions): Promise; private track; shutdown(): Promise; } //#endregion export { LokiConfig, LokiEvent, LokiPayload, LokiSubscriber, buildLokiPayload, resolveLokiPushUrl, sendBatchToLoki, sendToLoki, toLokiHeaders, toLokiLabels, toLokiTimestamp };