Export metrics and WAF events
Before you start
Open System → Settings → Observability with Observability.Manage. Reading metrics requires the separate Metrics.Read permission or a scrape token. Administrators have both permissions automatically.
Only Core makes outbound exporter connections. Export is optional and works without a Cloud account. The management route's access controls and rate limits also apply to metric scrapes.
Export metrics over OTLP
Set OTLP endpoint to an absolute http or https URL without embedded credentials or a fragment. An empty or / path becomes /v1/metrics; a custom path is kept.
Core sends OTLP/HTTP protobuf with service.name=clearplane-core and service.version. Saving applies the endpoint immediately after the settings commit. Clearing it stops OTLP export. Neither action requires an Edge apply or restart.
Scrape with Prometheus
Create a named scrape token in Scrape tokens and copy it before closing the dialog. Only its SHA-256 hash is stored; the secret cannot be retrieved later. The list shows creation and last-use times. Revoking a token prevents later scrapes with it.
Send the token as a bearer credential to GET /api/metrics on the public management API route. A ready browser session or API session with Metrics.Read can also read it. Scrape tokens authorize only this endpoint.
scrape_configs:
- job_name: clearplane
scheme: https
metrics_path: /api/metrics
authorization:
type: Bearer
credentials_file: /etc/prometheus/clearplane-token
static_configs:
- targets: ['clearplane.example.com']
The credentials file contains the complete cpst_… token. Requests without valid operator credentials receive 401; an authenticated session without Metrics.Read receives 403.
Metric reference
Counters keep their cumulative totals across Edge restarts while Core remains running. Cross-boot accumulated history is held in Core memory; restarting Core starts from the current Edge counters. Select the clearplane.edge.online gauge when deciding whether the WAF data is current.
While Edge is offline, WAF series stop reporting; the online gauge remains at zero.
| OpenTelemetry name | Prometheus name | Type | Labels | Meaning |
|---|---|---|---|---|
clearplane.waf.evaluations |
clearplane_waf_evaluations_total |
counter | stage | WAF transactions evaluated, including WebSocket messages by stage. |
clearplane.waf.decisions |
clearplane_waf_decisions_total |
counter | stage, decision | Completed WAF decisions. |
clearplane.waf.ruleset.matches |
clearplane_waf_ruleset_matches_total |
counter | ruleset, effective_mode | Evaluations with at least one match for that ruleset; clean evaluations do not count. |
clearplane.waf.budget_exhausted |
clearplane_waf_budget_exhausted_total |
counter | — | Transactions that exhausted their work budget. |
clearplane.waf.challenges |
clearplane_waf_challenges_total |
counter | — | Requests answered with a WAF bot challenge. |
clearplane.waf.connections_closed |
clearplane_waf_connections_closed_total |
counter | — | WebSocket connections closed by the WAF. |
clearplane.waf.body_truncated |
clearplane_waf_body_truncated_total |
counter | — | Request bodies inspected only up to the configured limit. |
clearplane.waf.grpc_messages |
clearplane_waf_grpc_messages_total |
counter | — | gRPC messages inspected. |
clearplane.waf.audit_events_dropped |
clearplane_waf_audit_events_dropped_total |
counter | — | Audit events dropped under back-pressure. |
clearplane.waf.rulesets.active |
clearplane_waf_rulesets_active |
gauge | ruleset, version, stage | One for each currently active ruleset version and stage. |
clearplane.waf.rulesets.skipped |
clearplane_waf_rulesets_skipped |
gauge | ruleset, version | One for a current release Edge skipped because it requires a newer engine. |
clearplane.edge.online |
clearplane_edge_online |
gauge | — | One while Edge statistics are available, zero while unavailable. |
The Prometheus exporter also adds otel_scope_name="Clearplane.Core" and a target_info series containing SDK and service metadata.
Labels never contain rule IDs, request paths, host names, route names or addresses. For decision, score and ruleset meanings, see WAF detections and WAF rulesets.
Stream WAF events
Under Destinations, add syslog, webhook or OTLP log destinations. Choose decision filters, or leave them empty for all decisions, and set a minimum combined blocking score. Filter changes apply to the remaining backlog. The minimum uses the actual blocking contribution, not the sum of configured finding scores: Detection-only matches and Challenge actions contribute zero. Keep the minimum at 0 when exporting those events. See Scoring and integrity tests for the score definitions.
Export includes events newer than the destination's creation time. Delivery is at least once: deduplicate retries using event.id.
The list shows the last successful delivery, consecutive failures and a fixed error such as Destination address is restricted, TLS handshake failed, Connection failed, Timed out, Client certificate is unreadable, HTTP 503, or Delivery failed. Correcting destination settings clears the old retry delay.
Disabling pauses export. Re-enabling sends the backlog that remains on disk. Raw log retention bounds the backlog; deleted source files cannot be recovered by the exporter. Changing a destination's kind requires creating a new destination.
Event fields
The ECS document contains sanitized WAF audit metadata. Request and response bodies, header values and query values are never exported.
| Field | Content |
|---|---|
@timestamp |
Audit event time in UTC. |
event.id |
Stable identifier for the destination’s source-file generation and byte offset, used for retry deduplication. |
event.kind, event.module, event.dataset |
event, clearplane, and clearplane.waf. |
event.category, event.type, event.action |
Web/intrusion-detection categories, denied or informational type, and WAF decision. |
observer.* |
Clearplane vendor, product, WAF type and version. |
http.request.method, http.response.status_code |
Request method and response status. |
url.domain, url.path, source.ip |
Host, path without query values, and source address. |
rule.id, rule.ruleset |
Rule IDs and ruleset IDs represented by audit findings. |
clearplane.waf.* |
Route, stage, mode, scoring mode, decision, failure code, correlation ID and combined scores. |
clearplane.waf.evaluations[] |
Ruleset/version, effective mode, blocking/detection scores, threshold and threshold result. |
clearplane.waf.findings[] |
Ruleset/rule IDs, revision, severity, target, field name and reason code. |
Webhook
A webhook requires HTTPS. Core posts a JSON array with an X-Clearplane-Signature header in the form t=<unix-seconds>,v1=<hex-signature>. The signing key is shown once when the destination is created or its key is rotated. A normal save does not reveal it. Rotation replaces the old key for later batches.
Verify the raw request bytes before processing the array. Use the UTF-8 bytes of the displayed key directly; do not decode it as Base64. This example allows a five-minute timestamp window:
import hashlib
import hmac
import time
def verify(body: bytes, header: str, key: str, tolerance: int = 300) -> bool:
try:
parts = dict(item.split("=", 1) for item in header.split(","))
timestamp = int(parts["t"])
signed = f"{timestamp}.".encode() + body
expected = hmac.new(key.encode(), signed, hashlib.sha256).hexdigest()
return abs(time.time() - timestamp) <= tolerance and hmac.compare_digest(expected, parts["v1"])
except (KeyError, ValueError):
return False
Syslog over TLS
Use host:port, usually port 6514; bracket IPv6 addresses, for example [2001:db8::1]:6514. Messages use RFC 5424 with RFC 5425 octet counting over TLS/TCP, facility local0. Denied events, including challenges, use warning severity; others use informational severity.
By default the destination uses system certificate trust. An optional CA PEM replaces that trust for this destination. The server host name is always validated. The CA field accepts public certificates only. To use mutual TLS, put the client certificate and its private key together in the separate Client certificate PEM field.
OTLP logs
OTLP log destinations accept an absolute HTTP or HTTPS URL. An empty or / path becomes /v1/logs; custom paths are kept. Core sends OTLP/HTTP JSON, using the ECS JSON as each log record's string body. Records carry event.id, event.action, source.ip and url.domain attributes, with service.name=clearplane-core and service.version on the resource.
An optional single-line Authorization header is supported. When editing, leave a replacement secret blank to keep it, or use the explicit remove control to clear it.
Egress and secrets
Every new exporter connection checks resolved destination addresses against the global restricted destination classes. The control-plane network is always refused, even if the operator has not selected that class. Core connects only to an allowed resolved address; HTTP redirects and system proxy routing are disabled.
Webhook signing keys, client certificate PEMs and Authorization headers are encrypted at rest. List and ordinary update responses expose presence flags. Only newly generated webhook keys and scrape tokens are shown once. Keep them with the receiving system's secrets.
See Exposure and network boundaries for management access and network wiring.