Skip to main content

Pyrra

Telemetry Provided
  • SLOs - Service Level Objectives and reliability metrics

Overview

Pyrra turns SLO definitions into Prometheus recording rules: metrics whose names include :burnrate, carrying labels such as slo, backstage_component, or team. Causely reads those rules on its next Prometheus sync and creates an SLO entity for each one, attached to the entity that owns it:

  • a single Service, or
  • a Component (one logical piece of software, often several Kubernetes Services), for example a Backstage component, or
  • a Business Application (a whole product or system).

This integration builds on the Prometheus scraper. Make sure Prometheus is enabled and reachable by the mediator before configuring Pyrra. See Prometheus.

Configuration

Causely resolves the owner of each SLO from the labels on its recording rule. Two Helm settings are involved:

SettingHelm locationWhen you need it
pyrra.associationsscrapers.prometheus.pyrraAlways. Maps the labels on a recording rule to the owner type and to the entity that should own the SLO.
label_assignmentsscrapers.kubernetesOnly for Component-owned SLOs. A rule label such as backstage_component=loki does not tell Causely which Kubernetes Services make up Component loki; label_assignments supplies that link.
Defaults are not merged

When you set associations explicitly, list every pattern your rules use—Causely does not merge in defaults. Causely tries the blocks top to bottom and uses the first match whose rule labels are all present, so put specific Component patterns before generic Service or Business Application ones.

Service-owned SLOs

The recording rule names the Kubernetes Service directly:

# Rule labels
slo: loki-querier-availability
service_id: loki-querier
k8s_ns: observability
causely-values.yaml
scrapers:
prometheus:
pyrra:
associations:
- entity: { service: {} }
discovery:
- kubernetes_service:
service_name: service_id # rule label holding the Service name
namespace: k8s_ns # rule label holding the namespace

The SLO attaches to Service/observability/loki-querier only.

Business Application-owned SLOs

The recording rule is scoped to a whole product or system:

# Rule labels
slo: observability-ingest-availability
backstage_system: grafana-observability
causely-values.yaml
scrapers:
prometheus:
pyrra:
associations:
- entity: { business_application: {} }
discovery:
- business_application:
name: backstage_system # rule label holding the application name

The SLO attaches under Business Application/grafana-observability.

Component-owned SLOs

The recording rule names a Component that spans several Kubernetes Services:

# Rule labels
slo: loki-querier-availability
backstage_component: loki
backstage_system: grafana-observability
backstage_domain: observability

Causely should create SLO loki-querier-availability, attach it to Component loki, and treat Services loki-querier and loki-ingester as members of that Component—not tempo-querier and tempo-ingestor, which run in the same observability namespace under sibling Component tempo. Neither the recording rule nor the cluster carries that link, so this case takes both settings.

1. Tag the Services with label_assignments. Select Services by labels they already carry (the Loki and Tempo Helm charts stamp app.kubernetes.io/name on every Service they create) and assign the catalog labels your Pyrra rules use. Nothing is written back to the cluster; the labels land only on Causely Service entities, and no Component or SLO is created at this point.

causely-values.yaml
scrapers:
kubernetes:
label_assignments:
- service_selector:
app.kubernetes.io/name: loki # already on loki-querier, loki-ingester, …
labels:
causely.ai/backstage-component-name: loki
causely.ai/backstage-system: grafana-observability
causely.ai/backstage-domain: observability
- service_selector:
app.kubernetes.io/name: tempo # already on tempo-querier, tempo-ingestor, …
labels:
causely.ai/backstage-component-name: tempo
causely.ai/backstage-system: grafana-observability
causely.ai/backstage-domain: observability

2. Match those labels in pyrra.associations.

causely-values.yaml
scrapers:
prometheus:
pyrra:
associations:
- entity: { component: {} }
discovery:
- component:
component_name: backstage_component # rule label → Component name
system_name: backstage_system
domain_name: backstage_domain
service_labels: # rule label → Service entity label
- metric_label: backstage_component
entity_label: causely.ai/backstage-component-name
- metric_label: backstage_system
entity_label: causely.ai/backstage-system

Together, the two settings resolve the Loki rule like this:

  1. The rule has backstage_component=loki, so the Component name is loki.
  2. service_labels maps rule labels backstage_component and backstage_system to the entity labels set by label_assignments.
  3. Causely finds Services observability/loki-querier and observability/loki-ingester. Tempo's Services do not match—they carry causely.ai/backstage-component-name=tempo.
  4. Causely creates or updates Component/loki, links both Loki Services to it, and attaches SLO loki-querier-availability.

service_labels is the bridge between the two settings: the value of a rule label must match the value of the Service entity label that label_assignments set.

Full example

The overlay below combines all three patterns, with label_assignments supporting the Component-owned one:

causely-values.yaml
scrapers:
kubernetes:
# Map existing Helm chart labels → Backstage catalog labels on Causely Service entities.
label_assignments:
- service_selector:
app.kubernetes.io/name: loki
labels:
causely.ai/backstage-component-name: loki
causely.ai/backstage-system: grafana-observability
causely.ai/backstage-domain: observability
- service_selector:
app.kubernetes.io/name: tempo
labels:
causely.ai/backstage-component-name: tempo
causely.ai/backstage-system: grafana-observability
causely.ai/backstage-domain: observability

prometheus:
pyrra:
associations:
# Component-owned SLOs (backstage_component + backstage_system on recording rules)
- entity: { component: {} }
discovery:
- component:
component_name: backstage_component
system_name: backstage_system
domain_name: backstage_domain
service_labels:
- metric_label: backstage_component
entity_label: causely.ai/backstage-component-name
- metric_label: backstage_system
entity_label: causely.ai/backstage-system

# Service-owned SLOs (service_id + k8s_ns on recording rules)
- entity: { service: {} }
discovery:
- kubernetes_service:
service_name: service_id
namespace: k8s_ns

# Business Application-owned SLOs (backstage_system only on recording rules)
- entity: { business_application: {} }
discovery:
- business_application:
name: backstage_system

Burn alerts

When Pyrra fires an ErrorBudgetBurn alert with slo=loki-querier-availability, Causely activates burn state on that SLO and elevates related Diagnoses as urgent. For how Causely uses SLO targets and burn rates in causal reasoning, see SLO Targets and Burn Rates.