Policy Observability
Policy decisions emit Prometheus metrics and telemetry events so operators can monitor enforcement health, detect misconfigured rules, and tune thresholds.
Metrics
Python SDK metrics
Exposed on a dedicated CollectorRegistry in the SDK process:
| Metric | Type | Labels | Description |
|---|---|---|---|
pavri_policy_evaluations_total | Counter | result, policy_type | Every policy evaluation |
pavri_policy_evaluation_duration_seconds | Histogram | — | Evaluation latency |
pavri_policy_cache_status | Counter | status (hit/miss/stale) | Cache health |
pavri_policy_sync_lag_seconds | Gauge | — | Time since last successful sync |
pavri_policy_denials_total | Counter | rule_type | Denied actions by rule category |
All labels are low-cardinality per the observability plan. No org_id, agent_id, or session_id in metric labels — those belong in telemetry events and logs.
Go policy-svc metrics
Exposed on /metrics (Prometheus scrape endpoint):
| Metric | Type | Labels | Description |
|---|---|---|---|
pavri_policy_bootstrap_requests_total | Counter | status (ok/error) | Bootstrap request outcomes |
pavri_policy_watch_streams_active | Gauge | — | Currently connected watch streams |
pavri_policy_snapshot_latency_seconds | Histogram | — | Snapshot generation time |
pavri_policy_crud_operations_total | Counter | operation, status | CRUD operation counts |
pavri_policy_postgres_query_latency_seconds | Histogram | operation | Database query latency |
Telemetry events
Every non-allow policy decision emits a policy_eval event to the telemetry pipeline:
{
"event_type": "policy_eval",
"agent_id": "agt-01H...",
"session_id": "ses-01H...",
"payload": {
"action": "tool:http.gateway.submit",
"decision": "deny",
"reason": "tool http.gateway.submit not in allowlist",
"policy_id": "pol-abc123",
"rule_id": "r1"
}
}
These events flow through the standard pipeline: SDK → gateway → ingest → JetStream → ClickHouse. They are queryable alongside tool call and model invocation events for forensic review.
What to monitor
Healthy policy system
pavri_policy_cache_status{status="hit"}is consistently highpavri_policy_sync_lag_secondsstays near zeropavri_policy_evaluations_totalgrows steadilypavri_policy_denials_totalis low relative to total evaluations
Warning signs
- Cache misses spiking — agents are evaluating without a policy snapshot. Check backend connectivity and sync health.
- Sync lag increasing — the watch stream may be disconnected. Check
pavri_policy_watch_streams_activeand policy-svc logs. - Denial rate spiking — either a new restrictive policy was deployed, or agent behavior has changed. Cross-reference with recent policy changes in the audit trail.
- Evaluation latency increasing — too many rules or complex regex patterns. Consider simplifying data classification patterns.
Dashboard visibility
The policy library in the dashboard shows:
- Enabled count — policies actively enforcing
- Shadow count — policies in rollout validation
- Validation warnings — policies with configuration issues
- Critical blocks — policies with blocking effects
Each policy's detail view shows its enforcement mode, scope, rule blocks, and impact metrics.
Operational boundaries
Use the policy detail, rollout, activity, and session views together when investigating a policy decision. Export or route metrics through the observability tooling approved for your deployment.