1. Documentation
  2. Manage Status Page
  3. Metrics and badges
ReadmeGitHub
  • Introduction
  • Quickstart
  • CLI
  • Configuration
  • Identity
  • Branding
  • Themes
  • Monitors
  • Checks and scheduling
  • Metrics and badges
  • Incidents
  • Maintenance
  • Notifications
  • Subscribers
  • React Router
  • Next.js
  • Astro
  • SQLite
  • Cloudflare D1
  • PostgreSQL
  • Schema and migrations
  • Cloudflare
  • Vercel
  • Self-hosting
  • API overview
  • Status endpoints
  • Incident endpoints
  • Maintenance endpoints
  • Subscriber endpoints
  • Badges, feeds and metrics
  • Admin endpoints
  • The check run
  • Uptime and history
  • Automatic incidents
  • Notification delivery
  • Public subscriptions

Metrics and badges

Control what the page shows, and expose badges and Prometheus metrics.

Choose which uptime and latency figures visitors see on the page. You can also publish SVG badges for READMEs or enable a Prometheus endpoint for scraping. All of these options live under metrics.

ts
metrics: {  showLatency: true,  showLatencyChart: true,  showUptimePercent: true,  uptimePeriods: ["24h", "7d", "30d", "90d"],  badges: true,  prometheus: false,},
showLatencybooleanoptional

Defaults to true. Shows the most recent latency on monitor cards.

showLatencyChartbooleanoptional

Defaults to true. Renders the latency sparkline.

showUptimePercentbooleanoptional

Defaults to true. Shows the uptime meters.

uptimePeriods("24h" | "7d" | "30d" | "90d")[]optional

Defaults to all four. Which meters appear, in order. No duplicates.

badgesbooleanoptional

Defaults to true. Serves /badge/:name.svg.

prometheusbooleanoptional

Defaults to false. Serves /metrics when enabled.

Hiding a figure on the page doesn't stop Heyo Status from calculating it: the API still returns the data. Pass the metrics settings to the UI:

tsx
<StatusPage snapshot={snapshot} metrics={statusPage.metrics} />
Periods are bounded by displayDays

A 90d meter can only report what exists. With checks.displayDays: 30 the 90-day value covers 30 days of history, because nothing older is read.

Add a badge to a README

text
GET /api/heyo-status/badge/API.svgGET /api/heyo-status/badge/overall.svg?metric=statusGET /api/heyo-status/badge/API.svg?metric=uptime&period=30dGET /api/heyo-status/badge/API.svg?metric=latency&label=Latency
QueryValuesDefault
metricstatus, uptime, latencystatus
period24h, 7d, 30d, 90d24h (uptime only)
labelany stringthe monitor name, or status

The reserved name overall renders the page-level state. Percent-encode names containing spaces: /badge/Web%20App.svg.

Badges are SVG, served with cache-control: public, max-age=60, which keeps an embedded badge fresh without turning every README view into a database read. Colours follow the value: green above 99.9% uptime or healthy, amber above 95% or degraded, red below, grey when there is no data.

md
![API](https://status.acme.com/api/heyo-status/badge/API.svg)![Uptime](https://status.acme.com/api/heyo-status/badge/API.svg?metric=uptime&period=30d)

With badges: false, the route answers 404.

Scrape with Prometheus

Set prometheus: true to serve /metrics as text/plain; version=0.0.4.

MetricLabelsMeaning
heyo_status_upmonitor, type, group1 operational, 0 failing.
heyo_status_latency_millisecondsmonitor, type, groupLatency of the most recent check.
heyo_status_uptime_ratiomonitor, periodUptime per period, 0–1.
heyo_status_last_check_timestamp_secondsmonitorUnix time of the last check.
heyo_status_overallstateOne-hot overall state.
heyo_status_monitors—Number of public monitors.
heyo_status_active_incidents—Count of active incidents.
heyo_status_scheduled_maintenances—Count of scheduled or running windows.
heyo_status_snapshot_timestamp_seconds—When the snapshot was generated.
prometheus.yml
scrape_configs:  - job_name: heyo-status    metrics_path: /api/heyo-status/metrics    scheme: https    static_configs:      - targets: ["status.acme.com"]

Only aggregate, already-public data is exposed: no incident text, no monitor targets, and nothing from a private monitor.

/metrics is public

The exposition is not behind the admin token. If a scrape endpoint should not be world-readable, keep prometheus: false and read the same numbers from /status behind your own gateway, or restrict the path at the edge.

Generate the same exposition yourself from any snapshot:

ts
import { createPrometheusMetrics, prometheusContentType } from "@heyo-sh/heyo-status/metrics";const body = createPrometheusMetrics(await statusPage.api.getSnapshot());return new Response(body, { headers: { "content-type": prometheusContentType } });

Building badges programmatically

ts
import { createMonitorBadge, createOverallBadge } from "@heyo-sh/heyo-status/badge";const snapshot = await statusPage.api.getSnapshot();const monitor = snapshot.monitors.find((candidate) => candidate.name === "API")!;createMonitorBadge(monitor, { metric: "uptime", period: "30d", label: "API uptime" });createOverallBadge(snapshot, { label: "Acme" });

Related

  • Badge, feed and metric endpoints
  • How uptime is calculated
  • Themes
Checks and scheduling< PreviousIncidentsNext >

Powered by heyo

On this page

Add a badge to a READMEScrape with PrometheusBuilding badges programmatically