Skip to content

Proposal: Prometheus HTTP API client module (prometheus-metrics-api-client) #2306

Description

@gecube

What

A new module — working name prometheus-metrics-api-client — providing a typed Java client for the Prometheus HTTP API (/api/v1/*): instant and range queries, series / labels / metadata, with a typed result model (vector / matrix / scalar / string).

Why revisit this

I'm aware querying has historically been considered out of scope here (#816, #841 — "client_java is for exposing metrics"). Three reasons I think it's worth revisiting:

1. The reference Go client already ships one. client_golang/api/prometheus/v1 provides Query, QueryRange, Series, LabelNames, LabelValues, Metadata, Rules, Targets and more, inside the official client library. So "client libraries are instrumentation-only" isn't consistent across official Prometheus clients — Go users get an API client out of the box, JVM users don't.

2. There is no maintained JVM alternative, so everyone hand-rolls. GitHub code search for "api/v1/query_range" language:Java returns ~350 files. A sample of projects each maintaining their own HTTP + JSON model code for the same API: LinkedIn Cruise Control, Spinnaker Kayenta, OpenSearch SQL, YugabyteDB, Apache SeaTunnel, Kruize, DataStax Fallout. The third-party libraries that exist are unmaintained one-person projects:

3. Hand-rolling keeps producing the same spec-compliance bugs. Current example: linkedin/cruise-control#2389 — timestamps formatted via Double.toString() come out in scientific notation (start=1.784144612388E9). Prometheus happens to accept that (Go's lenient ParseFloat), but stricter API-compatible backends (VictoriaMetrics) reject it with 422. A shared, well-tested client fixes this class of bug once for the whole ecosystem instead of once per project.

Proposed scope (v1)

  • Endpoints: query, query_range, series, labels, label/<name>/values, metadata — the subset that virtually every hand-rolled client reimplements; client_golang's surface as the ceiling, added on demand.
  • Typed result model: vector / matrix / scalar / string; spec-compliant request encoding (plain-decimal or RFC 3339 timestamps, POST for long queries).
  • Auth: basic, bearer token, custom headers (e.g. X-Scope-OrgID for Mimir), TLS config.
  • Dependencies: aiming for zero new runtime deps, in the spirit of prometheus-metrics-exporter-httpserver. Open questions below.
  • Integration tests against Prometheus and API-compatible backends (VictoriaMetrics, Mimir, Thanos) via testcontainers, since compatibility differences are exactly where hand-rolled clients break.

Open questions

  1. Minimum JDK for the module: java.net.http.HttpClient needs 11+; if the module must stay on 8, HttpURLConnection.
  2. JSON parsing without adding a dependency to the BOM: a minimal internal parser vs an optional -jackson binding module.
  3. Module naming: prometheus-metrics-api-client vs something clearer about direction (prometheus-query-client?).

Offer

I'm willing to contribute the initial implementation, tests, and docs, and to help maintain the module afterwards. Before writing code I'd like to hear whether maintainers would consider this in scope at all — and if the answer is no, whether you'd accept a documentation pointer to a community-maintained library instead, so the next person doesn't hand-roll client №351.

Activity

  1. zeitlinger commented on Jul 16, 2026

    @zeitlinger
    Member

    great idea - we'll discuss it in the community call tomorrow - feel free to join 😄

    https://prometheus.io/community/#calendar-for-public-events

  2. arnabnandy7 commented on Jul 18, 2026

    @arnabnandy7
    Contributor

    In case you're proceeding with this, let me know I'm interested in contributing as well. @gecube @zeitlinger

  3. jaydeluca commented on Jul 18, 2026

    @jaydeluca
    Member

    in the community call yesterday this was discussed and decided this is a good addition to this library, published as a separate module.

    The idea will be to try and provide parity with the existing go client.

  4. arnabnandy7 commented on Jul 18, 2026

    @arnabnandy7
    Contributor

    in the community call yesterday this was discussed and decided this is a good addition to this library, published as a separate module.

    The idea will be to try and provide parity with the existing go client.

    any plan for java client?

  5. gecube commented on Jul 18, 2026

    @gecube
    Author

    @arnabnandy7 @jaydeluca I think I would be able to provide smth on the next week, probably closer to the weekend.

  6. arnabnandy7 commented on Jul 18, 2026

    @arnabnandy7
    Contributor

    @arnabnandy7 @jaydeluca I think I would be able to provide smth on the next week, probably closer to the weekend.

    Sure, please assign me if anything found suitable.

  7. gecube commented on Jul 26, 2026

    @gecube
    Author

    Hi @jaydeluca — apologies for the long pause, and thanks for bringing this to the community call.

    I've put together a PoC: https://github.com/gecube/client_java/tree/api-client-module — a single commit on top of current main, so the easiest way to look at it is the diff: main...gecube:client_java:api-client-module

    What's in it:

    • A new module prometheus-metrics-api-client, aiming at parity with client_golang/api/prometheus/v1: query, query_range, series, labels / label/<name>/values, metadata, query_exemplars, rules, alerts, targets (+ target metadata), alertmanagers, the status/* endpoints, format_query, and health/readiness checks. Results come back as a typed model (vector / matrix / scalar / string), with a small CompletableFuture-based wrapper for async use.
    • Zero new runtime dependencies: the module depends only on prometheus-metrics-model. JSON parsing is a minimal internal parser, and transport is HttpURLConnection behind a pluggable HttpConnectionFactory, so it stays on the same JDK baseline as the rest of client_java (no java.net.http).
    • Backend-compat tests: recorded response fixtures for Prometheus, VictoriaMetrics, Mimir, Thanos and Cortex run through a compat matrix, since compatibility quirks were a big part of the motivation. Request encoding is spec-compliant (plain-decimal timestamps), i.e. the start=1.784144612388E9 class of bug from PrometheusMetricSampler emits query timestamps in scientific notation, breaking strict Prometheus-compatible backends (VictoriaMetrics 422) cruise-control-for-kafka/cruise-control#2389 is covered by tests.
    • Integration tests (integration-tests/it-api-client) running real queries against Prometheus and VictoriaMetrics, and a docs page under docs/content/querying/.

    Open to any and all criticism — naming, package layout, API shape, whether the admin/status endpoints belong in v1 scope at all. Happy to open a draft PR if that's a more convenient place to review.

    If it would help to see the client used in a real project rather than in tests, I'm also happy to pick a victim and port it as a demonstration — the natural candidate is LinkedIn Cruise Control, whose hand-rolled Prometheus client is exactly what triggered this proposal.

    @arnabnandy7 you mentioned you'd be interested in contributing — once the maintainers settle the direction, this splits well into independent pieces (per-backend integration coverage, auth options, docs), so there's room for more than one pair of hands.

  8. arnabnandy7 commented on Jul 26, 2026

    @arnabnandy7
    Contributor

    Sure, once you split the PRs we can assign it.

  9. jaydeluca commented on Jul 31, 2026

    @jaydeluca
    Member

    @gecube thanks for putting this together, I will be taking a look at this shortly.

    Opening a draft PR would be a good first step and we can start reviewing and formulating a plan on how we might want to break it up so it's easier to review

  10. jaydeluca commented on Sep 22, 2026

    @jaydeluca
    Member

    i think the best way for this to move forward is to start by creating the infrastructure of the new module, and get the tooling and things put in place for all of that. From there we can see how we can break this into smaller pieces so that they are easier to review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions