Dash0 acquires Polar Signals

Last updated: August 31, 2026

dash0_check_rule

Terraform resource for Dash0 check rules — PromQL-based alerting conditions defined in the Prometheus Rule format.

Manages a Dash0 Check Rule. Check rules define alerting conditions based on PromQL expressions that are continuously evaluated against your telemetry data. See About Alerting and About Creating Check Rules for more details. The check rule definition uses the Prometheus Rule format.

More information on how Prometheus rules are mapped to Dash0 check rules can be found in the Dash0 Operator documentation.

Example Usage

terraform
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
resource "dash0_check_rule" "adservice_error_rate" {
dataset = "production"
# Currently only one group incl. one rule is supported
check_rule_yaml = <<-EOF
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: adservice
spec:
groups:
- name: Alerting
interval: 1m0s
rules:
- alert: adservice
expr: (sum by (service_namespace, service_name) (increase({otel_metric_name = "dash0.spans", service_name = "adservice", service_namespace = "opentelemetry-demo", dash0_operation_name != "", otel_span_status_code = "ERROR"}[5m]))) / (sum by (service_namespace, service_name) (increase({otel_metric_name = "dash0.spans", service_name = "adservice", service_namespace = "opentelemetry-demo", dash0_operation_name != ""}[5m])) > 0)*100 > $__threshold
for: 0s
keep_firing_for: 0s
annotations:
summary: 'High error percentage for adservice: {{$value|printf "%.2f"}}%'
description: 'High error percentage for adservice: {{$value|printf "%.2f"}}%'
dash0-threshold-critical: "40"
dash0-threshold-degraded: "35"
dash0-enabled: true
labels: {}
EOF
}
# Fanning out check rules with `for_each` and routing each rule's alerts to one
# or more notification channels through the `dash0.com/notification-channel-ids`
# annotation. The annotation takes a comma-separated list of channel UUIDs —
# the `id` attribute on `dash0_notification_channel`, not the `origin`.
resource "dash0_notification_channel" "team_oncall" {
for_each = {
backend = "backend-oncall@example.com"
frontend = "frontend-oncall@example.com"
sre = "sre-oncall@example.com"
}
notification_channel_yaml = <<-YAML
kind: Dash0NotificationChannel
metadata:
name: ${each.key} on-call
spec:
type: email_v2
config:
recipients:
- ${each.value}
plaintext: false
frequency: 10m
YAML
}
locals {
service_check_rules = {
backend-api = {
service = "backend-api"
channels = ["backend", "sre"]
}
frontend-web = {
service = "frontend-web"
channels = ["frontend"]
}
checkout = {
service = "checkout"
channels = ["backend", "sre"]
}
}
}
resource "dash0_check_rule" "service_error_rate" {
for_each = local.service_check_rules
dataset = "production"
check_rule_yaml = <<-EOF
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: ${each.key}-error-rate
annotations:
dash0.com/notification-channel-ids: ${join(",", [for c in each.value.channels : dash0_notification_channel.team_oncall[c].id])}
spec:
groups:
- name: Alerting
interval: 1m0s
rules:
- alert: ${each.value.service}-error-rate
expr: (sum by (service_name) (increase({otel_metric_name = "dash0.spans", service_name = "${each.value.service}", otel_span_status_code = "ERROR"}[5m]))) / (sum by (service_name) (increase({otel_metric_name = "dash0.spans", service_name = "${each.value.service}"}[5m])) > 0)*100 > $__threshold
for: 0s
keep_firing_for: 0s
annotations:
summary: 'High error percentage for ${each.value.service}: {{$value|printf "%.2f"}}%'
dash0-threshold-critical: "40"
dash0-threshold-degraded: "35"
dash0-enabled: true
labels: {}
EOF
}

PrometheusRule annotation merge

A check_rule_yaml document's top-level metadata.annotations are merged into the rule's own annotations, key by key. A rule that sets the same key wins for that key only, and still inherits the rest.

A dash0_check_rule holds exactly one group containing exactly one rule, so this is not the way to share a setting across several rules. It matters instead because a PrometheusRule document written for the Dash0 Operator for Kubernetes, or exported from Dash0, can be used here verbatim and its top-level settings still apply. To manage many rules, use for_each over the resource as in the example above, and keep the shared value in Terraform rather than in an annotation.

Below, the rule declares no annotations of its own and is routed by the channel it inherits from the document:

terraform
123456789101112131415161718
resource "dash0_check_rule" "checkout_error_rate" {
dataset = "production"
check_rule_yaml = <<-EOF
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: checkout-error-rate
annotations:
dash0.com/notification-channel-ids: ${dash0_notification_channel.team_oncall["backend"].id}
spec:
groups:
- name: Alerting
rules:
- alert: Checkout Error Rate
expr: sum(rate(http_server_request_duration_seconds_count{service_name="checkout", http_response_status_code=~"^5[0-9][0-9]$"}[5m])) > 0.1
EOF
}

Dash0 stores the rule with its annotations already merged, so the API returns a document that differs from the one declared in the configuration. The provider normalizes both sides the same way before comparing them, so a configuration that uses top-level annotations plans clean rather than showing a diff on every run.

Annotations that control rule behavior

A few annotations configure how a rule evaluates rather than describing it:

AnnotationControlsAlso accepted
dash0-enabledwhether the rule evaluates at all
dash0-threshold-criticalthe critical thresholdthreshold-critical
dash0-threshold-degradedthe degraded thresholdthreshold-degraded

These are unprefixed, unlike the dash0.com/-prefixed annotations, so they are easy to mistake for ordinary metadata. They inherit and override like any other annotation, so setting one at the top level reaches the rule when the rule does not name it itself. Setting dash0-enabled: "false" stops the rule from evaluating without removing it from the configuration.

Thresholds

The critical and degraded thresholds are two separate annotations, so a document can set one at the top level and a rule can set the other. Both then apply to that rule. Below, the rule inherits a critical threshold of 1000 milliseconds and sets a degraded threshold of 500 milliseconds:

terraform
1234567891011121314151617181920
resource "dash0_check_rule" "checkout_latency" {
dataset = "production"
check_rule_yaml = <<-EOF
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: checkout-latency
annotations:
dash0-threshold-critical: "1000"
spec:
groups:
- name: Alerting
rules:
- alert: Checkout P99 Latency
expr: histogram_quantile(0.99, sum by (le) (rate(http_server_request_duration_seconds_bucket{service_name="checkout"}[5m]))) * 1000 > $__threshold
annotations:
dash0-threshold-degraded: "500"
EOF
}

The check then reports critical above 1000 milliseconds, degraded between 500 and 1000 milliseconds, and healthy below 500 milliseconds. A measurement that crosses both thresholds is reported as critical, never as both.

Dash0 evaluates the critical threshold first, so the critical value has to be the more severe one for the comparison used in the expression: the higher number for >, the lower number for <. Swapping them in the rule above, to a critical threshold of 500 and a degraded threshold of 1000, reports critical from 500 milliseconds upwards and never reports degraded at all.

Use one annotation spelling per document

The prefixed and unprefixed spellings of a setting are different annotation keys, and the prefixed one wins wherever both are present. That takes precedence over the rule-beats-document behavior above: a rule setting threshold-critical does not override a top-level dash0-threshold-critical. The losing value is not discarded either, it stays on the check rule as an ordinary annotation, which is usually how you notice. Use one spelling throughout a document.

Schema

Required

  • check_rule_yaml (String) The check rule definition in YAML format, following the Prometheus alerting rule specification. Must contain exactly one group with exactly one rule. The document's top-level metadata.annotations are merged into the rule's own annotations, and the rule's own annotations take precedence when the same key is set in both places, so a document written for the Dash0 Kubernetes operator can be used here verbatim. Setting dash0.com/sharing controls sharing, and changes to it trigger a resource update.
  • dataset (String) The identifier of the Dash0 dataset that the check rule belongs to. Provide the dataset's identifier, which is immutable, not the 'name'. Datasets are used to separate observability data within a Dash0 organization. Changing this value forces the resource to be recreated.

Read-Only

  • id (String) The server-assigned identifier of the check rule, resolved by the provider after creation. The Dash0 check-rules API addresses rules by their origin, so for this resource id equals origin (the tf_-prefixed value generated by the provider) — unlike dashboards, views, synthetic checks, and notification channels, where id is a distinct server-assigned UUID. The attribute is exposed for symmetry across resources; reference it when wiring the check rule's identifier into another resource.
  • origin (String) A unique identifier for the check rule, automatically generated on creation. Used to reference the check rule for updates, reads, deletes, and imports.
  • url (String) The URL to open this check rule in the Dash0 web app, derived from the Dash0 API URL and the check rule's server-assigned identifier. Computed by the provider after creation. May be empty if the app URL cannot be derived (e.g. for self-hosted deployments with a custom web app domain).

Import

Import is supported using the following syntax:

The terraform import command can be used, for example:

shell
12
#!/bin/bash
terraform import dash0_check_rule.adservice_error_rate production,tf_existing-check-rule-origin