Skip to content

Service Discovery

Prometheus Proxy supports Prometheus HTTP service discovery, allowing Prometheus to automatically discover scrape targets as agents register paths.

Enabling Service Discovery

# Enable service discovery via CLI:
java -jar prometheus-proxy.jar \
  --sd_enabled \
  --sd_path discovery \
  --sd_target_prefix proxy-host.example.com:8080
proxy {
  service.discovery {
    enabled = true
    path = "discovery"
    targetPrefix = "proxy-host.example.com:8080"
  }
}
# Enable service discovery via environment variables:
SD_ENABLED=true
SD_PATH=discovery
SD_TARGET_PREFIX=proxy-host.example.com:8080

Discovery Endpoint

Once enabled, the proxy exposes a JSON endpoint at the configured path (default: /discovery).

Query it with:

curl -s http://proxy-host.example.com:8080/discovery | jq '.'

Response Format

The endpoint returns a JSON array in the format expected by Prometheus HTTP SD:

[
  {
    "targets": ["proxy-host.example.com:8080"],
    "labels": {
      "__metrics_path__": "/app1_metrics",
      "agentName": "agent-01",
      "hostName": "internal.host.com",
      "env": "production",
      "team": "backend"
    }
  },
  {
    "targets": ["proxy-host.example.com:8080"],
    "labels": {
      "__metrics_path__": "/app2_metrics",
      "agentName": "agent-01",
      "hostName": "internal.host.com",
      "env": "staging",
      "team": "backend"
    }
  }
]

Each entry contains:

Field Description
targets The proxy's address, host:port, from targetPrefix
labels.__metrics_path__ The path to scrape on the proxy, after any path in targetPrefix
labels.__scheme__ The scheme, when targetPrefix is a URL
labels.agentName Name(s) of agent(s) serving this path
labels.hostName Hostname(s) of agent(s) serving this path
labels.* Custom labels from agent pathConfigs

Prometheus Configuration

Configure Prometheus to use HTTP service discovery:

scrape_configs:
  - job_name: 'prometheus-proxy-sd'
    http_sd_configs:
      - url: 'http://proxy-host.example.com:8080/discovery'
        refresh_interval: 30s

The refresh_interval controls how often Prometheus queries the discovery endpoint for changes.

Dynamic target management

With service discovery enabled, you don't need to update prometheus.yml when agents register new paths. Prometheus automatically picks up new targets on the next refresh interval.

Target Prefix

The targetPrefix setting is the address Prometheus scrapes the advertised paths at: the external host:port of your proxy, as Prometheus reaches it. The default is localhost:8080.

proxy.service.discovery.targetPrefix = "proxy.example.com:8080"

It can also be an http or https URL, such as https://proxy.example.com/prometheus/. Prometheus doesn't accept a URL as a target, so the proxy splits it: the host and port become the target, the scheme becomes each target's __scheme__ label, and any path goes in front of __metrics_path__. A value that is neither fails the proxy's startup when service discovery is enabled.

Labels

Labels configured in agent pathConfigs are included in the service discovery response. Prometheus can use these for relabeling, filtering, or target grouping:

agent.pathConfigs: [
  {
    name: "Production API"
    path: prod_api_metrics
    labels: "{\"env\": \"production\", \"team\": \"backend\", \"service\": \"api\"}"
    url: "http://api.internal:9100/metrics"
  }
]

The labels appear in the discovery response and can be used in Prometheus relabeling rules. They must be a JSON object whose keys are label names that every Prometheus version accepts ([a-zA-Z_][a-zA-Z0-9_]*) and whose values are strings. Prometheus decodes the labels as a map of string to string, and one entry that isn't fails its whole discovery response, so the proxy leaves such entries out. The proxy logs a warning naming them when the path registers, and the agent logs one at startup for a pathConfigs entry. The path itself still registers.

A path can't be the discovery path, favicon.ico, or the blitz path: the proxy serves those itself, so it refuses to register them.

Reserved label keys

The proxy computes __metrics_path__, agentName, and hostName itself, and it also drops every agent-supplied label whose key starts with __. In HTTP service discovery a target's labels override the scrape config's __scheme__, __scrape_interval__, __scrape_timeout__, and __param_*, so these would let an agent change how Prometheus scrapes it. The proxy logs a warning naming the dropped keys when the path registers.

Agent labels can set job and instance by default. When agents run under separate per-agent identities, set proxy.service.discovery.reserveJobAndInstanceLabels = true so one team's agent can't label its targets as another team's job or instance.