Kuadrant / Kuadrant/kuadrant-console-plugin

PlanPolicy View: Metrics Tab with Perses Panels

Open
#687 0 comments 0 reactions 0 assignees View on GitHub
triage/accepted
Dominant language
TypeScript
Stars
10
Forks
65
Avg merge
2d 8h
Merged PRs (30d)
44

Description

## Context

Add a Metrics tab to the PlanPolicy details page showing per-tier rate limiting metrics using embedded Perses panels. This answers: "Which tiers are hitting limits? Should I adjust tier quotas?"

Depends on the shared Perses infrastructure established in #220.

## Requirements

### New Metrics tab

Add a `console.tab/horizontalNav` on `PlanPolicy` (`extensions.kuadrant.io/v1alpha1`):
- Tab name: "Metrics"
- Tab href: `metrics`

**Panels:**

| Panel | Metric | Panel Type |
|-------|--------|-----------|
| Rejections by Tier | `sum(rate(limited_calls{limitador_namespace="/", limit_name=~"gold\|silver\|bronze"}[5m])) by (limit_name)` | TimeSeriesChart stacked by tier |
| Total Authorized Traffic | `sum(rate(authorized_calls{limitador_namespace="/"}[5m]))` | TimeSeriesChart |
| Overall Rejection Rate | `sum(rate(limited_calls{limitador_namespace="/"}[5m])) / (sum(rate(authorized_calls{limitador_namespace="/"}[5m])) + sum(rate(limited_calls{limitador_namespace="/"}[5m]))) * 100` | GaugeChart |
| Rejections per Tier | `sum(rate(limited_calls{limitador_namespace="/", limit_name=""}[5m]))` per tier | StatChart (one per tier) |

**Controls:**
- Time range selector: 15m, 1h, 6h, 24h, 7d (default: 1h)

### How PlanPolicy maps to Limitador metrics

PlanPolicy generates a child RateLimitPolicy with one limit entry per tier. The tier name becomes the `limit_name` in Limitador (e.g. `gold`, `silver`, `bronze`). This label is only available on `limited_calls` and only when Limitador is configured with `telemetry: exhaustive`:

```bash
kubectl patch limitador limitador -n kuadrant-system --type='merge' -p='{"spec":{"telemetry":"exhaustive"}}'
```

### Limitations

- **Per-tier authorized traffic is not available.** `authorized_calls` aggregates all tiers under the same `limitador_namespace`. Only rejections (`limited_calls`) can be broken down by tier via `limit_name`.
- **No per-consumer metrics.** Consumer-to-tier assignment is not reflected in Limitador metrics unless custom labels are added via TelemetryPolicy.

### Limitador namespace scoping

The `limitador_namespace` label format is `"{k8s_namespace}/{route_name}"`. The target HTTPRoute's namespace and name must be resolved from the PlanPolicy's generated RateLimitPolicy `targetRef`.

Tier names should be dynamically read from the PlanPolicy's `spec.plans[].tier` field rather than hardcoded.

### Empty states
- No plan data: "No plan metrics available. Metrics will appear once traffic flows through tiers defined by this policy."
- Exhaustive telemetry not enabled: "Per-tier breakdown requires Limitador exhaustive telemetry to be enabled."
- Prometheus unavailable: shared `EmptyMetricsState` component from #220

## Notes
- Requires React 18 upgrade (OCP 4.22+ only)
- Extension policies (PlanPolicy) are not tracked by `kuadrant_policies_total` / `kuadrant_policies_enforced`

Contributor guide

Open the contributing guide

Research direction

Start at the PlanPolicy console extension and review the shared Perses infrastructure established in #220. Trace how the generated RateLimitPolicy targetRef resolves the HTTPRoute namespace and name, and how spec.plans[].tier supplies tier names. Done means a Metrics tab renders the specified panels, controls, empty states, and dynamic tier breakdown without hardcoded tiers.

Written by the indexing model from the issue text.

Assessment

Tech stack
kubernetes, prometheus, react, typescript
Domain
frontend, observability
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.