Bundle
dsh-prometheus
Privacy-conscious Prometheus metrics and a Grafana dashboard for DeepSeek Harness
- Source
- xxiaoxiong
- stars
- 2 stars
- License
- MIT
- Updated
- Updated 23 hours ago
Readme
# dsh-prometheus
English | [中文](README.zh.md)
Prometheus metrics and a ready-to-import Grafana dashboard for DeepSeek Harness. The plugin observes public DSH lifecycle seams, keeps metric series bounded, and avoids exporting conversation or tool payloads.
> Release status: `0.1.0` is the first developer-preview release, tested against DSH `0.1.0-rc.6`.
## What it monitors
- Active sessions; agent turns, steps, errors, and duration histograms
- LLM request rate, terminal status, latency, and disjoint input/output/reasoning/cache token counters
- Tool call rate, normalized success/error status, and latency
- Approval request and fixed outcome counters
- Subagent starts, outcomes, and duration
- Active/started/completed/killed/failed background jobs and duration
- Process start time and cardinality-overflow diagnostics
The exact names, labels, and meanings are in [docs/metrics.md](docs/metrics.md).
## Compatibility
| Component | Tested version |
|---|---|
| DeepSeek Harness npm packages | `0.1.0-rc.6` |
| Official source baseline | `47f943859bef60e4160492346772ded9b24f765a` (2026-08-13) |
| Cordis | `^4.0.1` |
| Node.js | `^22.19.0 || >=24.0.0` |
| prom-client | `15.1.3` |
DeepSeek Harness is a developer preview. Treat every DSH upgrade as a compatibility event and run the full test/release checklist.
## Install
Install the package into a DSH profile and verify its bundle layer:
```sh
dsh plugin --profile monitoring add dsh-prometheus
dsh --profile monitoring --dump-config
```
The bundle inserts one row with id `prometheus`. Verify the dump includes the `dsh-prometheus` layer before booting the profile.
## Endpoint selection
The default `mode: auto` makes one activation-time decision:
1. If a public DSH `webServer` is already active and safely bound, register the exact `/metrics` route on it.
2. Otherwise, start a standalone endpoint on `127.0.0.1:9464`.
For the bundled Docker example, force standalone mode so Prometheus has a stable target. Add this row to the profile's `cordis.patch.yml` (later layers replace the whole `config` value):
```yaml
- id: prometheus
config:
enabled: true
mode: standalone
host: 127.0.0.1
port: 9464
path: /metrics
allowRemote: false
maxLabelValues: 64
maxLabelValueLength: 80
```
### Configuration
| Field | Default | Description |
|---|---:|---|
| `enabled` | `true` | Disable all collectors and endpoint without removing the row. |
| `mode` | `auto` | `auto`, `webserver`, or `standalone`. |
| `host` | `127.0.0.1` | Standalone bind address: loopback or `0.0.0.0`. |
| `port` | `9464` | Standalone TCP port; `0` is intended only for tests. |
| `path` | `/metrics` | Exact route, beginning with `/` and without a trailing slash. |
| `allowRemote` | `false` | Required acknowledgement for `0.0.0.0` or a remote-facing WebServer route. |
| `maxLabelValues` | `64` | Per-key dynamic-label vocabulary cap. |
| `maxLabelValueLength` | `80` | Maximum accepted dynamic-label length. |
Remote exposure has no built-in authentication or TLS. Read [SECURITY.md](SECURITY.md) before enabling it.
## Quick scrape
```sh
curl --fail --silent http://127.0.0.1:9464/metrics
```
The endpoint accepts GET and HEAD, returns `405` for other methods, disables caching, and uses the Prometheus/OpenMetrics-compatible `prom-client` content type.
## Prometheus and Grafana
The repository includes a full local stack:
```sh
docker compose -f examples/docker-compose.yml up -d
```
Then open Prometheus at `http://127.0.0.1:9090` and Grafana at `http://127.0.0.1:3000` (`admin` / `admin`; change it outside local development). The datasource and `DeepSeek Harness / Overview` dashboard are provisioned automatically.
The standalone assets are [`examples/prometheus.yml`](examples/prometheus.yml) and [`grafana/dsh-overview.json`](grafana/dsh-overview.json). Security, compatibility, and verification details live in [`docs/security.md`](docs/security.md), [`docs/compatibility.md`](docs/compatibility.md), and [`docs/verification-report.md`](docs/verification-report.md).
Useful queries:
```promql
# Turn throughput
sum(rate(dsh_agent_turns_total[5m]))
# Turn failure ratio
sum(rate(dsh_agent_turns_total{status=~"error|blocked|aborted"}[5m]))
/
clamp_min(sum(rate(dsh_agent_turns_total[5m])), 0.000001)
# P95 LLM latency by provider/model
histogram_quantile(0.95,
sum by (le, provider, model) (rate(dsh_llm_request_duration_seconds_bucket[5m])))
# Tool errors by tool
sum by (tool) (rate(dsh_tool_calls_total{status!="success"}[5m]))
```
See [examples/prometheus/alerts.yml](examples/prometheus/alerts.yml) for starter alerts. Tune thresholds to the workload; quiet agent processes legitimately have zero throughput.
## Privacy and cardinality
The collector never exports prompts, user/assistant messages, system prompts, tool arguments or results, error text, file paths, working directories, arbitrary metadata, or session/agent/call/job/subagent ids.
Only four runtime-controlled label keys exist: `provider`, `model`, `tool`, and job `kind`. Values must match `[A-Za-z0-9][A-Za-z0-9_.:/-]*`, remain within the configured length, and fit the per-key vocabulary cap. Rejected or excess values become `__other__`; the event is counted by `dsh_metrics_label_overflow_total` without logging the original value.
Provider/model/tool/kind names are still operational metadata. Do not put customer identifiers or secrets in those names.
## Lifecycle behavior
All listeners, job observers, routes, sockets, and registries belong to the plugin's Cordis fiber. On hot reload or uninstall, the route is removed or the standalone server is closed and remaining sockets are destroyed. The registry is instance-local, so reload does not collide with process-global collectors.
Existing live sessions and jobs seed gauges only. Historical events are not replayed into counters. Counter resets across process restart/hot reload are normal Prometheus behavior.
## Upgrade, downgrade, remove
```sh
# Upgrade after obtaining a newer tarball/version
dsh plugin --profile monitoring add ./dsh-prometheus-NEW.tgz
dsh --profile monitoring --dump-config
# Remove the dependency and bundle layer
dsh plugin --profile monitoring remove dsh-prometheus
```
Before a downgrade, compare metric and config contracts in [CHANGELOG.md](CHANGELOG.md). Removing the plugin does not delete data already stored by Prometheus.
## Development
```sh
pnpm install --frozen-lockfile
pnpm check
pnpm test:coverage
pnpm pack
```
The suite covers config/cardinality, privacy, LLM/tool waterfalls, endpoint methods, remote-exposure gates, WebServer route teardown, standalone socket teardown, job/subagent lifecycles, and a real rc.6 AgentLoop turn. See [CONTRIBUTING.md](CONTRIBUTING.md), [docs/architecture.md](docs/architecture.md), and [docs/release-checklist.md](docs/release-checklist.md).
## Troubleshooting and limitations
See [docs/troubleshooting.md](docs/troubleshooting.md) and [docs/known-limitations.md](docs/known-limitations.md).
## License
MIT
Install
dsh plugin --profile web add github:xxiaoxiong/dsh-prometheus
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-prometheus from the hub
- This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.