PrometheusStore — Prometheus time-series monitoring
Read this page in the documentation
PrometheusStore — Prometheus time-series monitoring Overview Prometheus is a pull-based time-series monitoring system. It is queried over its HTTP API using PromQL (Prometheus Query Language). There is no SQL-shaped query surface, no row-level UPDATE/DELETE, and no client-side ingestion path — Prometheus scrapes targets itself. It therefore does not fit the SQL Dialect interface. PrometheusStore implements the minimal NoSqlStore marker interface (src/nosql/store.ts) — connection lifecycle plus a getClient() escape hatch — and exposes Prometheus's read-only HTTP query API directly. It performs no writes. Identity: Property | Value | --------- | -------------- | name | 'prometheus' | library | 'fetch' | No npm driver — HTTP over fetch Prometheus has no single canonical npm client library; it is just an HTTP/JSON API. Rather than depend on any package, this store talks to the server with the global fetch — hence library is 'fetch', not the name of a driver package. There is nothing to lazy-require(): when no client is injected, a tiny internal fetch-based client (built by createFetchClient(baseURL, headers)) is constructed at connect time. All wrapped endpoints are read-only and live under /api/v1. Each method returns the parsed data field of the Prometheus response envelope ({ status: 'success', data: ... }): instantQuery(promql, time?) → GET /api/v1/query rangeQuery(promql, {start,end,step}) → GET /api/v1/queryrange series(match) → GET /api/v1/series labelValues(label) → GET /api/v1/label/<label>/values Injected client PrometheusStoreOptions.client accepts a pre-built HTTP client (typed as PrometheusHttpClient). When provided it is used verbatim and baseURL is ignored; otherwise the internal fetch-based client is built against baseURL. This is how the test suite injects a mock (no network) and how callers route requests through a custom transport. Connection Build a store from connection options and call connect(): Option | Type | Purpose | --------- | --------------------------- | ----------------------------------------------------------------------------------------------------- | baseURL | string | Base URL of the Prometheus server. Defaults to http://localhost:9090 (DEFAULTPROMETHEUSBASEURL).| client | PrometheusHttpClient | Optional pre-built HTTP client. When set, used verbatim and baseURL is ignored. | headers | Record<string, string> | Extra HTTP headers sent with every internal-client request. | Injected-client form Methods Every query method issues a GET through the client and returns body?.data. Failures are wrapped in a DatabaseError (preserving the original error, e.g. Prometheus instantQuery failed: ...); using any method before connect() (or after disconnect()) throws a ConnectionError. Lifecycle Method | Signature | Behavior | ------------ | ------------------------------------ | ------------------------------------------------------------------------------------------------------------ | connect | connect(): Promise<void> | Uses an injected client if provided, otherwise builds an internal fetch-based client against baseURL. Idempotent when already connected. Does not open a socket or make a request. | disconnect | disconnect(): Promise<void> | Drops the client reference (stateless HTTP — no socket to close). | isConnected| isConnected(): boolean | true only when connected and a client is present. | getClient | getClient(): PrometheusHttpClient | Returns the underlying (internal or injected) HTTP client. Throws ConnectionError if not connected. | Query API (read-only) Method | Signature | Endpoint | Behavior | -------------- | -------------------------------------------------------------------- | --------------------------------- | ------------------------------------------------------------------------------------------ | instantQuery | instantQuery(promql: string, time?: string \| number): Promise<any>| GET /api/v1/query | Runs a PromQL instant query at a single point in time. time is stringified when provided. Returns the data payload (result type + result). | rangeQuery | rangeQuery(promql: string, options: RangeQueryOptions): Promise<any>| GET /api/v1/queryrange | Runs a PromQL range query over [start, end] at step resolution. Returns the data payload (matrix result). | series | series(match: string \| string[]): Promise<any> | GET /api/v1/series | Finds series matching one or more PromQL selectors (sent as repeated match[] params). Returns the array of matching label sets. | labelValues | labelValues(label: string): Promise<any> | GET /api/v1/label/<label>/values| Lists the distinct values of a label (the label is URL-encoded into the path). Returns the array of values. | RangeQueryOptions Example Verification status Unit / mock-verified only. The tests in tests/nosql/prometheus.test.ts are fully mock-driven: an in-memory mock HTTP client is injected via PrometheusStoreOptions.client; it records every request (path + params) and returns canned Prometheus response envelopes. There is no network in the test run — the internal fetch-based client is never exercised against a live server. What this proves: Each method issues a GET to the correct path with the expected params: instantQuery sends { query, time } (omitting time when absent, stringifying it when present); rangeQuery sends stringified { query, start, end, step }; series sends { 'match[]': [...] } (single or multiple selectors); labelValues targets /api/v1/label/<label>/values. Each method returns the unwrapped data field of the response envelope. Lifecycle: not connected before connect(), idempotent double-connect, clean disconnect, getClient() returning the injected client, and ConnectionError when querying or calling getClient() before connect(). Error handling: client failures wrapped in DatabaseError. What this does not prove: live execution against a real Prometheus server, nor the internal createFetchClient transport (URL building, header forwarding, HTTP status handling) end-to-end over the wire. Related reading All data stores — the full catalogue, grouped by purpose Database types — where this sits among the 22 categories