Skip to main content
Docs / Dashboard

Detection Events Dashboard

In-cluster visibility into what PandoCore is detecting and protecting.

There are three places to see what PandoCore is doing, and which one you want depends on the question. The portal is for detections and entitlements, Prometheus is for coverage and health, and kubectl is for what is true in the cluster right now.

Portal Dashboard

Evidence is delivered by the controller to portal.pandocore.io, which is where detections, their reasons and their outcomes are read. No extra configuration is needed: the portal is a destination the controller carries by default.

Event data flow

  1. A sensor detects behaviour diverging from a workload's profile
  2. It seals and signs an evidence record, and delivers it to the controller over mTLS
  3. The controller writes it to a durable spool and only then acknowledges it
  4. The controller delivers it onward to the portal, and to any SIEM, Slack or webhook destinations you have configured
  5. If a response ran, a second pando.response record follows carrying what it actually did
Two records per response, and why

The trip record is sealed and shipped before the response chain resolves, because there is no action without a durable record first. So the first record carries the intended response and the receipt carries the outcome. They are correlated by trip_evidence_id, not by sharing an id. See Evidence Format.

What the portal shows

Retention is a floor, not a query window

Your plan's retention figure is the period the portal undertakes to keep evidence for. Nothing deletes an event at the end of it, so it is not a promise that older evidence is gone, and it is not an availability claim about querying it. If you need evidence for a defined period under your own control, deliver it to your SIEM and apply your retention policy there.

Coverage And Health, In Prometheus

The portal shows what was detected. It does not tell you whether a node stopped being watched, and that is the question worth alerting on.

Metric What it answers
pando_node_sensor_pods_unmonitored Pods getting no engine. With reason="cap", pods you wanted watched that the node had no room for
pando_operating_mode The mode in force (0 monitor, 1 alert, 2 isolate, 4 debug)
pando_mode_ceiling The ceiling the license permits, same encoding
pando_isolations_total Isolation policies successfully applied

The sensor chart ships PrometheusRules covering coverage at the cap, the series going absent, a refusal at startup, and a cadence stretched past its configured interval. Absence matters most: it is the one condition no self-report can distinguish from healthy.

Two ways this dashboard lies by omission

A job selecting on the protect label matches nothing. The sensor's own pod carries pandocore.io/protect: "false", so a Prometheus job written against protect=true finds no targets and reports a clean scrape of nothing, which renders identically to healthy. Select on app.kubernetes.io/name=pando-node-sensor.

On GKE managed Prometheus the shipped rules are inert. It honours neither the chart's scrape annotations nor a PrometheusRule, so set metrics.podMonitoring.enabled=true to get scraping at all, and port the coverage and absence rules across by hand. See Configuration.

Right Now, With kubectl

# One sensor per node, all Ready
kubectl get pods -n pando-system -l app.kubernetes.io/name=pando-node-sensor -o wide

# Engine count, license ceiling, node clamp, for one node
kubectl exec -n pando-system <sensor-pod> -- wget -qO- http://localhost:9090/status

# What is contained at this moment
kubectl get networkpolicy --all-namespaces \
  -l app.kubernetes.io/managed-by=pandocore

# Detections as Kubernetes events
kubectl get events -n <namespace> --field-selector reason=PandoCollapse

# Collapse-grade conditions where nothing acted
kubectl get events -n <namespace> --field-selector reason=PandoRefrained

What a detection looks like as an event

Reason Type Meaning
PandoAlert Normal A detection that called for no response chain
PandoRefrained Warning A collapse-grade condition was detected and nothing acted, because of the mode, the license ceiling or the learning window
PandoCollapse Warning A containment action was attempted
PandoRefrained is how you evaluate before you let it act

On a free license nothing is ever contained, so every collapse-grade finding arrives as PandoRefrained: this was serious enough to act on, and nothing did. That is the list to read before deciding whether to raise the ceiling, and it is evidence from your own cluster rather than a projection.

It pairs with pando_collapses_total{outcome="refrained"}, which is deliberately the same word so the event and the metric are recognisably the same fact. The event's machine-readable event_type_label remains would-collapse, unchanged on purpose: it is a selector, and changing one quietly is worse than a stale word inside it.

/status reports the license ceiling and any node clamp as separate lines, deliberately: a clamped node is held to monitor by a portal-side verdict rather than by your license, so an operator reading one must not be sent to upgrade a license that was never the constraint. node_clamp: none means no clamp applies and the node is fully protected.

In-Cluster Dashboard

Deprecated with the admission webhook

The in-cluster dashboard shipped as an optional component of the pando-webhook chart, off by default, and it worked by polling each protected pod's sidecar on port 9090. Neither that chart nor those per-pod endpoints is part of the supported install: a node sensor serves one /status per node, not one per pod. It receives no further release.

Use the portal for detections, Prometheus for coverage and health, and kubectl for current state. Between them they cover everything it showed, and the Prometheus route covers the coverage question it never answered.

Troubleshooting

The portal shows no activity

  1. Confirm the sensors are ready: /readyz returns 503 during learning and while refusing
  2. Confirm the controller is running and receiving. It is what delivers to the portal, so healthy sensors with an empty portal is a controller question
  3. Check the controller's logs for delivery errors, and your egress rules for blocked outbound calls

Prometheus shows no PandoCore data

  1. Check your job selects app.kubernetes.io/name=pando-node-sensor rather than the protect label
  2. Confirm the metrics port is 9090
  3. On GKE managed Prometheus, confirm metrics.podMonitoring.enabled=true

Some pods never appear

Check pando_node_sensor_pods_unmonitored{reason="cap"} first. Then check whether the pod is opted out, in an excluded namespace, or using hostPID or hostNetwork. See Troubleshooting.

Next Steps