{"id":17442375,"url":"https://github.com/kashalls/kromgo","last_synced_at":"2026-03-08T06:01:40.795Z","repository":{"id":212713016,"uuid":"731863942","full_name":"kashalls/kromgo","owner":"kashalls","description":"Easily expose preconfigured prometheus metrics to the outside using badges.","archived":false,"fork":false,"pushed_at":"2026-03-05T04:27:05.000Z","size":295,"stargazers_count":132,"open_issues_count":5,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-05T08:51:20.902Z","etag":null,"topics":["go","kubernetes","prometheus","promql"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kashalls.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-12-15T03:57:59.000Z","updated_at":"2026-03-05T03:26:35.000Z","dependencies_parsed_at":"2024-08-28T21:27:42.833Z","dependency_job_id":"53f59a25-9920-4b4f-8fca-433817814c6a","html_url":"https://github.com/kashalls/kromgo","commit_stats":{"total_commits":21,"total_committers":5,"mean_commits":4.2,"dds":"0.23809523809523814","last_synced_commit":"79574e5ec34039b94d705cefe84eef82cb93038d"},"previous_names":["kashalls/kubernetes-json-shields"],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/kashalls/kromgo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kashalls%2Fkromgo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kashalls%2Fkromgo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kashalls%2Fkromgo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kashalls%2Fkromgo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kashalls","download_url":"https://codeload.github.com/kashalls/kromgo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kashalls%2Fkromgo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30118934,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-05T09:35:22.236Z","status":"ssl_error","status_checked_at":"2026-03-05T09:35:20.028Z","response_time":93,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","kubernetes","prometheus","promql"],"created_at":"2024-10-17T16:01:34.093Z","updated_at":"2026-03-08T06:01:38.751Z","avatar_url":"https://github.com/kashalls.png","language":"Go","funding_links":[],"categories":["Go","kubernetes"],"sub_categories":[],"readme":"# Kromgo\n\nSafely expose individual Prometheus metric values to the public web. Define named metrics backed by PromQL queries and serve them as JSON, SVG badges, or raw Prometheus data — without exposing your Prometheus instance directly.\n\nWorks out of the box with [shields.io Endpoint Badges](https://shields.io/badges/endpoint-badge).\n\n## Quick Start\n\n```bash\ndocker run -d \\\n  -e PROMETHEUS_URL=http://prometheus:9090 \\\n  -v /path/to/config.yaml:/kromgo/config.yaml \\\n  -p 8080:8080 \\\n  ghcr.io/kashalls/kromgo:latest\n```\n\nThen query a metric:\n\n```\nGET http://localhost:8080/node_cpu_usage\n```\n\n## Configuration\n\nKromgo reads its metric definitions from `/kromgo/config.yaml` inside the container. Mount your config file there.\n\n**Minimal example:**\n\n```yaml\nmetrics:\n  - name: node_cpu_usage\n    query: \"round(cluster:node_cpu:ratio_rate5m * 100, 0.1)\"\n    suffix: \"%\"\n```\n\nSee [config.yaml.example](./config.yaml.example) for a full example with colors, templates, and badges.\n\n### Docker Compose\n\n```yaml\nservices:\n  kromgo:\n    image: ghcr.io/kashalls/kromgo:latest\n    environment:\n      PROMETHEUS_URL: http://prometheus:9090\n    volumes:\n      - ./config.yaml:/kromgo/config.yaml:ro\n    ports:\n      - \"8080:8080\"\n```\n\n## Environment Variables\n\n| Variable | Required | Default | Description |\n|---|---|---|---|\n| `PROMETHEUS_URL` | yes | — | URL of your Prometheus instance |\n| `SERVER_HOST` | no | `0.0.0.0` | Host to bind the main server |\n| `SERVER_PORT` | no | `8080` | Port for the main server |\n| `HEALTH_HOST` | no | `0.0.0.0` | Host to bind the health server |\n| `HEALTH_PORT` | no | `8888` | Port for the health/metrics server |\n| `SERVER_LOGGING` | no | `false` | Enable HTTP request logging |\n| `SERVER_READ_TIMEOUT` | no | — | HTTP read timeout (e.g. `5s`) |\n| `SERVER_WRITE_TIMEOUT` | no | — | HTTP write timeout (e.g. `10s`) |\n| `RATELIMIT_ENABLE` | no | `false` | Enable rate limiting |\n| `RATELIMIT_ALL` | no | `false` | Rate limit all requests globally |\n| `RATELIMIT_BY_REAL_IP` | no | `false` | Rate limit by `X-Real-IP` header |\n| `RATELIMIT_REQUEST_LIMIT` | no | `100` | Max requests per window |\n| `RATELIMIT_WINDOW_LENGTH` | no | `1m` | Rate limit window duration |\n| `LOG_LEVEL` | no | `info` | Log level: `debug`, `info`, `warn`, `error` |\n| `LOG_FORMAT` | no | `json` | Log format: `json` or `text` |\n\n## Metric Configuration\n\nEach entry under `metrics:` defines one queryable endpoint at `/{name}`.\n\n| Field | Required | Description |\n|---|---|---|\n| `name` | yes | URL path segment — `node_cpu_usage` → `GET /node_cpu_usage` |\n| `query` | yes | PromQL expression, must return a single scalar or vector value |\n| `title` | no | Display label in badge/endpoint responses (defaults to `name`) |\n| `label` | no | Extract value from this metric label instead of the sample value |\n| `prefix` | no | String prepended to the value in the response (e.g. `v`) |\n| `suffix` | no | String appended to the value in the response (e.g. `%`) |\n| `valueTemplate` | no | Go template applied to the value before prefix/suffix — see [Value Templates](#value-templates) |\n| `colors` | no | List of color ranges for the response — see [Colors](#colors) |\n| `hidden` | no | Hide from the index page (`GET /`) — see [Index Page](#index-page) |\n\n### Colors\n\nAssign a badge color based on the numeric value. Use `valueOverride` to replace the displayed value text entirely.\n\n```yaml\nmetrics:\n  - name: node_cpu_usage\n    query: \"round(cluster:node_cpu:ratio_rate5m * 100, 0.1)\"\n    suffix: \"%\"\n    colors:\n      - { color: \"green\",  min: 0,  max: 35  }\n      - { color: \"orange\", min: 36, max: 75  }\n      - { color: \"red\",    min: 76, max: 1000 }\n\n  - name: ceph_health\n    query: \"ceph_health_status{}\"\n    colors:\n      - { color: \"green\",  min: 0, max: 0, valueOverride: \"Healthy\"  }\n      - { color: \"orange\", min: 1, max: 1, valueOverride: \"Warning\"  }\n      - { color: \"red\",    min: 2, max: 2, valueOverride: \"Critical\" }\n```\n\nSupported color names: `blue`, `brightgreen`, `green`, `grey`, `lightgrey`, `orange`, `red`, `yellow`, `yellowgreen`, `success`, `important`, `critical`, `informational`, `inactive`. Hex values (e.g. `#e05d44`) are also accepted.\n\n## Value Templates\n\nThe `valueTemplate` field applies a [Go template](https://pkg.go.dev/text/template) to the raw Prometheus value before `prefix` and `suffix` are added.\n\n### Built-in functions\n\n| Function | Example input | Example output | Description |\n|---|---|---|---|\n| `simplifyDays` | `\"1159\"` | `3y64d` | Converts a day count to years and days |\n| `humanBytes` | `\"1572864\"` | `1.5MB` | Converts bytes to a human-readable size |\n| `humanDuration` | `\"9000\"` | `2h30m` | Converts seconds to a compact duration string |\n| `toUpper` | `\"v1.31.0\"` | `V1.31.0` | Uppercases the string |\n| `toLower` | `\"HEALTHY\"` | `healthy` | Lowercases the string |\n| `trim` | `\" ok \"` | `ok` | Strips leading and trailing whitespace |\n\n### Inline template\n\n```yaml\nmetrics:\n  - name: cluster_age\n    query: \"floor((time() - k8s_cluster_created_timestamp) / 86400)\"\n    valueTemplate: \"{{ . | simplifyDays }}\"   # 1159 → 3y64d\n\n  - name: node_memory_used\n    query: \"node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes\"\n    valueTemplate: \"{{ . | humanBytes }}\"     # 1572864 → 1.5MB\n```\n\n### Named templates\n\nDefine reusable snippets at the top level and reference them by name:\n\n```yaml\ntemplates:\n  clusterAge: \"{{ . | simplifyDays }}\"\n  uptime:     \"{{ . | humanDuration }}\"\n\nmetrics:\n  - name: cluster_age\n    query: \"floor((time() - k8s_cluster_created_timestamp) / 86400)\"\n    valueTemplate: clusterAge   # resolved from templates map\n\n  - name: node_uptime\n    query: \"time() - node_boot_time_seconds\"\n    valueTemplate: uptime\n```\n\n## Index Page\n\n`GET /` returns an HTML page listing all visible metrics as clickable links. By default all metrics are hidden.\n\nSet `hideAll: false` in your config to show all metrics, then opt individual ones out with `hidden: true`, or keep `hideAll` at its default and opt specific metrics in with `hidden: false`.\n\n```yaml\nhideAll: false   # show all metrics on the index page by default\n\nmetrics:\n  - name: node_cpu_usage\n    query: \"...\"\n  - name: internal_metric\n    query: \"...\"\n    hidden: true   # this one won't appear on the index page\n```\n\nWhen no metrics are visible, the page displays *page intentionally blank*.\n\n## API Reference\n\n### Endpoint format (default)\n\nCompatible with [shields.io Endpoint Badge](https://shields.io/badges/endpoint-badge).\n\n```\nGET /node_cpu_usage\n```\n\n```json\n{\n    \"schemaVersion\": 1,\n    \"label\": \"node_cpu_usage\",\n    \"message\": \"17.5%\",\n    \"color\": \"green\"\n}\n```\n\n### Raw format\n\nReturns the raw Prometheus query result.\n\n```\nGET /node_cpu_usage?format=raw\n```\n\n```json\n[{\"metric\": {}, \"value\": [1702664619.78, \"17.5\"]}]\n```\n\n### Badge format\n\nReturns an SVG badge directly.\n\n```\nGET /node_cpu_usage?format=badge\nGET /node_cpu_usage?format=badge\u0026style=flat-square\nGET /node_cpu_usage?format=badge\u0026style=plastic\n```\n\n```\ncontent-type: image/svg+xml\n\u003csvg xmlns=\"http://www.w3.org/2000/svg\" ...\n```\n\n## Ports\n\n| Port | Purpose |\n|---|---|\n| `8080` | Main server — metric queries |\n| `8888` | Health server — `/healthz`, `/readyz`, `/metrics` (Prometheus) |\n\nThe health server's `/metrics` endpoint exposes Go runtime metrics plus `kromgo_requests_total{metric, format}` — a counter of requests handled, broken down by metric name and response format.\n\n## Image Verification\n\nContainer images are signed with [Cosign](https://docs.sigstore.dev/cosign/overview/) keyless signing. Verify an image before running it:\n\n```bash\ncosign verify ghcr.io/kashalls/kromgo:\u003ctag\u003e \\\n  --certificate-identity-regexp=\"https://github.com/kashalls/kromgo/\" \\\n  --certificate-oidc-issuer=\"https://token.actions.githubusercontent.com\"\n```\n\n## 🤝 Gratitude and Thanks\n\nThanks to all of the people at the [Home Operations](https://discord.gg/home-operations) Discord community. Be sure to check it out, it's a blast!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkashalls%2Fkromgo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkashalls%2Fkromgo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkashalls%2Fkromgo/lists"}