# folk-plugin-metrics

[![Vibe Index](https://img.shields.io/static/v1?label=Vibe+Index&message=4.9&color=3399d8&style=flat-square&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iI2ZmZiI%2BPHBhdGggZD0iTTkgNCBROSAxMyAxOCAxMyBROSAxMyA5IDIyIFE5IDEzIDAgMTMgUTkgMTMgOSA0IFoiLz48cGF0aCBkPSJNMTkgMSBRMTkgNiAyNCA2IFExOSA2IDE5IDExIFExOSA2IDE0IDYgUTE5IDYgMTkgMSBaIi8%2BPHBhdGggZD0iTTIwIDE0IFEyMCAxOCAyNCAxOCBRMjAgMTggMjAgMjIgUTIwIDE4IDE2IDE4IFEyMCAxOCAyMCAxNCBaIi8%2BPC9zdmc%2B)](https://github.com/roxblnfk/action-vibe-index)

Prometheus metrics and health check plugin for Folk — serves `/metrics` and `/health` endpoints.

> **Status:** in active development. See [folk-spec](https://github.com/Folk-Project/folk-spec) for the roadmap.

## Requirements

- Rust 1.85+
- [folk-api](https://github.com/Folk-Project/folk-api)

## Installation

```toml
# Cargo.toml
folk-plugin-metrics = "0.1"
```

## Quick start

Add to `folk.build.toml`:

```toml
[[plugin]]
crate_name = "folk-plugin-metrics"
version = "0.1"
config_key = "metrics"
```

Configure in `folk.toml` (or use defaults):

```toml
[metrics]
listen = "0.0.0.0:9090"
```

Query the endpoints:

```bash
curl http://localhost:9090/metrics
```

Example output:

```
# HELP folk_workers_total Current worker count
# TYPE folk_workers_total gauge
folk_workers_total{state="idle"} 3
folk_workers_total{state="busy"} 1
folk_workers_total{state="spawning"} 0
folk_workers_total{state="dead"} 0
# HELP folk_requests_total Total dispatched requests
# TYPE folk_requests_total counter
folk_requests_total 1042
# HELP folk_request_duration_seconds Dispatch duration
# TYPE folk_request_duration_seconds histogram
folk_request_duration_seconds_bucket{le="0.005"} 800
folk_request_duration_seconds_bucket{le="0.01"} 950
folk_request_duration_seconds_bucket{le="+Inf"} 1042
folk_request_duration_seconds_sum 3.21
folk_request_duration_seconds_count 1042
```

```bash
curl http://localhost:9090/health
```

Example output (all healthy):

```json
{
  "status": "healthy",
  "checks": {
    "process": { "healthy": true, "message": null },
    "http": { "healthy": true, "message": null }
  }
}
```

Unhealthy response (HTTP 503):

```json
{
  "status": "unhealthy",
  "checks": {
    "process": { "healthy": false, "message": "tailwind: Failed" }
  }
}
```

## Configuration

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `listen` | `SocketAddr` | `"0.0.0.0:9090"` | Address and port for the metrics/health HTTP server. |

## Built-in metrics

These metrics are registered by folk-core at the worker pool level:

| Metric | Type | Labels | Description |
|--------|------|--------|-------------|
| `folk_workers_total` | Gauge | `state` (idle/busy/spawning/dead) | Current worker count by state. |
| `folk_requests_total` | Counter | — | Total dispatched requests. |
| `folk_request_duration_seconds` | Histogram | — | Request dispatch duration. |

Plugins may register additional metrics via `metrics_registry.counter_vec()`, `.gauge_vec()`, and `.histogram_vec()` from their `PluginContext`.

## How it works

The plugin starts a lightweight hyper HTTP server on the configured address with two endpoints:

**`GET /metrics`** — Calls `metrics_registry.render()` to produce Prometheus text exposition format (`text/plain; version=0.0.4`). Point your Prometheus scrape config here.

**`GET /health`** — Calls `health_registry.check_all()` to aggregate health checks from all plugins. Returns `200` if all checks pass, `503` if any check reports unhealthy. Response is JSON with per-plugin status.

All other routes return `404`.

The plugin also exposes an RPC method `metrics.render` on the admin socket, returning a snapshot of the current metrics.

## License

MIT
