Ethereum Prometheus metrics mirror
https://api.triport.io/v1/eth/metrics/eth-el-01/el-gethRead-only proxy that fetches an Ethereum execution- or consensus-client's Prometheus metrics page, strips operator-identifying labels, and serves the sanitized output.
GET /v1/eth/metrics/{host_id}/{layer} returns the raw Prometheus exposition
text (text/plain; version=0.0.4) for a single Ethereum node in the platform's
mesh, identified by host_id, for a single client layer. The platform scrapes
the upstream client's metrics endpoint on your behalf, runs the payload through a
label scrubber that removes operator-identifying data (instance IPs, hostnames,
pod/node/namespace labels, and any raw IP-form label values), and serves the
result. You can point Prometheus, Grafana Agent, or any scraper at this URL.
Responses are cached briefly (default 5 seconds) so that repeated scrapes don't
hammer the upstream node. Every response carries an X-Cache-Status header
(miss, fresh, or stale). If the upstream node is temporarily unreachable,
the mirror serves the last-known-good payload from a stale cache (default ceiling
60 seconds) and marks it X-Cache-Status: stale so your tooling can alert.
Use this when you want to observe the health of a specific node you are routed
through — block height, peer counts, sync status — without exposing the node's
internal address space. The layer selects which client family's metrics port
and path to scrape; the requested layer must match the host's actual client
family, and the host must advertise the corresponding metrics capability.
Parameters
Path parameters
host_idstringrequiredlayer.layerstring (enum)requiredEL-Geth is normalized to el-geth).Response
The body is standard Prometheus exposition text. Note that the instance label
has been rewritten from the upstream node's IP:port to the public host_id,
and any operator-only labels (hostnames, pod/node/namespace, raw IP values) have
been stripped.
Response headers
| Header | Type | Description |
|---|---|---|
Content-Type | string | Always text/plain; version=0.0.4. |
X-Cache-Status | string | miss — freshly scraped and cached; fresh — served from the in-TTL cache; stale — upstream was unreachable, served from the stale cache (data may be up to the stale ceiling old). |
Server | string | Always Triport. |
Errors
Errors are returned as a small JSON envelope: {"error":"<code>","code":<status>}.
| Code | Meaning | When it happens |
|---|---|---|
405 | method_not_allowed | Any method other than GET. |
404 | pprof_not_allowed | The path contains a /debug/pprof/ segment. |
404 | route_not_found | Path does not start with the metrics route base. |
404 | invalid_path | host_id/layer segments are missing or malformed (expected exactly two segments). |
404 | unknown_layer | layer is not one of the 10 supported values. |
403 | tier_locked | Your plan does not include the required feature (eth.chain_metrics_el / eth.chain_metrics_cl). |
503 | pool_not_configured | No pool is configured for the requested namespace (EL or CL). |
404 | unknown_host | No host with the given host_id exists in the target pool. |
400 | family_mismatch | The host's client family does not match the requested layer (e.g. asking for cl-lighthouse on a non-lighthouse host). |
403 | capability_missing | The host does not advertise the required metrics capability. |
502 | upstream_unavailable | The upstream node could not be reached and no stale cache was available. |
See Errors for the shared error envelope and conventions.
Examples
JavaScript (fetch)
const res = await fetch(
"https://api.triport.io/v1/eth/metrics/eth-el-01/el-geth",
{ headers: { Authorization: `Bearer ${process.env.TRIPORT_API_KEY}` } }
);
if (!res.ok) {
const err = await res.json();
throw new Error(`metrics mirror failed: ${err.error} (${err.code})`);
}
const cacheStatus = res.headers.get("X-Cache-Status"); // "miss" | "fresh" | "stale"
const metrics = await res.text();
console.log(cacheStatus, metrics);TypeScript SDK (@triport/sdk)
import { Triport } from "@triport/sdk";
const client = new Triport({ apiKey: process.env.TRIPORT_API_KEY! });
const { body, cacheStatus } = await client.ethereum.metrics.mirror({
hostId: "eth-el-01",
layer: "el-geth",
});
console.log(cacheStatus, body);Python (triport-sdk)
import os
from triport import Triport
client = Triport(api_key=os.environ["TRIPORT_API_KEY"])
result = client.ethereum.metrics.mirror(host_id="eth-el-01", layer="el-geth")
print(result.cache_status, result.body)Notes
- Scraping. Because responses are cached for a few seconds, you can safely
set your scrape interval as low as 5 seconds — within a cache window you'll get
X-Cache-Status: freshand the upstream node is not re-hit. - Stale data. A
stalecache status means the upstream node was unreachable on the last attempt; the payload may be up to the stale ceiling (default 60s) old. Treat sustainedstaleas a node-health signal. - Label scrubbing is one-way. Internal addressing is removed before the
payload leaves the platform; you will never see upstream IPs, hostnames, or
cluster topology labels. The
instancelabel always carries the publichost_id. - Layer ↔ host must agree. The
layeryou request must match the host's client family and the host must expose the corresponding metrics capability; otherwise you getfamily_mismatchorcapability_missing. - Related: Ethereum JSON-RPC transport, Mesh health.