<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Manage Knowledge Graph in Grafana Cloud using Terraform on Grafana Labs</title><link>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/</link><description>Recent content in Manage Knowledge Graph in Grafana Cloud using Terraform on Grafana Labs</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/index.xml" rel="self" type="application/rss+xml"/><item><title>Get started with Terraform for Knowledge Graph</title><link>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/getting-started/</link><pubDate>Fri, 03 Apr 2026 19:43:06 +0000</pubDate><guid>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/getting-started/</guid><content><![CDATA[&lt;h1 id=&#34;get-started-with-terraform-for-knowledge-graph&#34;&gt;Get started with Terraform for Knowledge Graph&lt;/h1&gt;
&lt;p&gt;Learn how to configure Terraform to manage Grafana Cloud Knowledge Graph resources. This guide walks you through setting up the Grafana Terraform provider and preparing your environment.&lt;/p&gt;
&lt;h2 id=&#34;before-you-begin&#34;&gt;Before you begin&lt;/h2&gt;
&lt;p&gt;Before you begin, ensure you have the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Grafana Cloud account, as shown in &lt;a href=&#34;/docs/grafana-cloud/get-started/&#34;&gt;Get started&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.terraform.io/downloads&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Terraform&lt;/a&gt; installed on your machine&lt;/li&gt;
&lt;li&gt;Administrator permissions in your Grafana instance&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/get-started/&#34;&gt;Knowledge Graph enabled&lt;/a&gt; in your Grafana Cloud stack&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;All Terraform configuration files should be saved in the same directory.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;configure-the-grafana-provider&#34;&gt;Configure the Grafana provider&lt;/h2&gt;
&lt;p&gt;This Terraform configuration sets up the &lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Grafana provider&lt;/a&gt; to provide necessary authentication when managing knowledge graph resources.&lt;/p&gt;
&lt;p&gt;You can reuse a similar setup to the one described in &lt;a href=&#34;/docs/grafana-cloud/as-code/infrastructure-as-code/terraform/terraform-cloud-stack/&#34;&gt;Creating and managing a Grafana Cloud stack using Terraform&lt;/a&gt; to set up a service account and a token.&lt;/p&gt;
&lt;h3 id=&#34;steps&#34;&gt;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a Service account and token in Grafana.&lt;/p&gt;
&lt;p&gt;To create a new one, refer to &lt;a href=&#34;/docs/grafana/latest/administration/service-accounts/#service-account-tokens&#34;&gt;Service account tokens&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a file named &lt;code&gt;main.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;terraform {
  required_providers {
    grafana = {
      source  = &amp;#34;grafana/grafana&amp;#34;
      version = &amp;#34;&amp;gt;= 2.9.0&amp;#34;
    }
  }
}

provider &amp;#34;grafana&amp;#34; {
  alias = &amp;#34;asserts&amp;#34;

  url      = &amp;#34;&amp;lt;Stack-URL&amp;gt;&amp;#34;
  auth     = &amp;#34;&amp;lt;Service-account-token&amp;gt;&amp;#34;
  stack_id = &amp;#34;&amp;lt;Stack-ID&amp;gt;&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Replace the following field values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;Stack-URL&amp;gt;&lt;/code&gt; with the URL of your Grafana stack (for example, &lt;code&gt;https://my-stack.grafana.net/&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;Service-account-token&amp;gt;&lt;/code&gt; with the service account token that you created&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;Stack-ID&amp;gt;&lt;/code&gt; with your Grafana Cloud stack ID&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;The &lt;code&gt;stack_id&lt;/code&gt; parameter is required for Knowledge Graph resources to identify the stack where the resources belong.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;apply-terraform-configurations&#34;&gt;Apply Terraform configurations&lt;/h2&gt;
&lt;p&gt;After creating your Terraform configuration files, apply them using the following commands:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Initialize a working directory containing Terraform configuration files:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;terraform init&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Preview the changes that Terraform makes:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;terraform plan&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Apply the configuration files:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;terraform apply&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;verify-your-setup&#34;&gt;Verify your setup&lt;/h2&gt;
&lt;p&gt;After applying the configuration, verify your setup by checking that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Terraform can authenticate with your Grafana Cloud stack&lt;/li&gt;
&lt;li&gt;The provider is properly configured with the correct stack ID&lt;/li&gt;
&lt;li&gt;No errors appear in the Terraform output&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;best-practices&#34;&gt;Best practices&lt;/h2&gt;
&lt;p&gt;When managing Knowledge Graph resources with Terraform, consider the following best practices.&lt;/p&gt;
&lt;h3 id=&#34;name-conventions&#34;&gt;Name conventions&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Use descriptive names that clearly indicate the purpose of each resource&lt;/li&gt;
&lt;li&gt;Follow a consistent naming pattern across your organization&lt;/li&gt;
&lt;li&gt;Include environment or team identifiers in names when appropriate&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;version-control&#34;&gt;Version control&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Store your Terraform configurations in version control (Git)&lt;/li&gt;
&lt;li&gt;Use separate directories or workspaces for different environments&lt;/li&gt;
&lt;li&gt;Document changes in commit messages&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;state-management&#34;&gt;State management&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Use remote state backends for team collaboration&lt;/li&gt;
&lt;li&gt;Enable state locking to prevent concurrent modifications&lt;/li&gt;
&lt;li&gt;Regularly back up your Terraform state files&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;security&#34;&gt;Security&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Never commit service account tokens or sensitive data to version control&lt;/li&gt;
&lt;li&gt;Use environment variables or secret management tools for credentials&lt;/li&gt;
&lt;li&gt;Rotate service account tokens regularly&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;next-steps&#34;&gt;Next steps&lt;/h2&gt;
&lt;p&gt;Now that you have configured the Terraform provider, you can start managing knowledge graph resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;../notification-alerts/&#34;&gt;Configure notification alerts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../suppressed-assertions/&#34;&gt;Define suppressed assertions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../custom-model-rules/&#34;&gt;Create custom model rules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../log-configurations/&#34;&gt;Set up log configurations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../thresholds/&#34;&gt;Configure thresholds&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../knowledge-graph-stack/&#34;&gt;Configure the Knowledge Graph stack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../prometheus-rules/&#34;&gt;Define Prometheus rules&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="get-started-with-terraform-for-knowledge-graph">Get started with Terraform for Knowledge Graph&lt;/h1>
&lt;p>Learn how to configure Terraform to manage Grafana Cloud Knowledge Graph resources. This guide walks you through setting up the Grafana Terraform provider and preparing your environment.&lt;/p></description></item><item><title>Configure the Knowledge Graph stack using Terraform</title><link>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/knowledge-graph-stack/</link><pubDate>Fri, 03 Apr 2026 19:43:06 +0000</pubDate><guid>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/knowledge-graph-stack/</guid><content><![CDATA[&lt;h1 id=&#34;configure-the-knowledge-graph-stack-using-terraform&#34;&gt;Configure the Knowledge Graph stack using Terraform&lt;/h1&gt;
&lt;p&gt;The Knowledge Graph stack resource manages the full onboarding flow for your Grafana Cloud stack. It provisions API tokens, configures datasets based on available metrics, and enables the stack.&lt;/p&gt;
&lt;p&gt;By default, datasets are auto-configured based on detected metrics. To manually configure datasets, for example when your metrics use non-standard label names, use the &lt;code&gt;dataset&lt;/code&gt; block.&lt;/p&gt;
&lt;h2 id=&#34;before-you-begin&#34;&gt;Before you begin&lt;/h2&gt;
&lt;p&gt;Before you begin, ensure you have the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Grafana Cloud account, as shown in &lt;a href=&#34;/docs/grafana-cloud/get-started/&#34;&gt;Get started&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.terraform.io/downloads&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Terraform&lt;/a&gt; installed on your machine&lt;/li&gt;
&lt;li&gt;The Grafana Terraform provider configured, as shown in &lt;a href=&#34;../getting-started/&#34;&gt;Get started with Terraform for Knowledge Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/get-started/&#34;&gt;Knowledge Graph enabled&lt;/a&gt; on your Grafana Cloud stack&lt;/li&gt;
&lt;li&gt;A Cloud Access Policy with the following scopes: &lt;code&gt;stacks:read&lt;/code&gt;, &lt;code&gt;metrics:read&lt;/code&gt;, &lt;code&gt;metrics:write&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;dataset-types&#34;&gt;Dataset types&lt;/h2&gt;
&lt;p&gt;The following dataset types are available:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;kubernetes&lt;/code&gt;&lt;/strong&gt;: Kubernetes metrics. Requires &lt;a href=&#34;/docs/grafana-cloud/monitor-infrastructure/kubernetes-monitoring/&#34;&gt;Kubernetes Monitoring&lt;/a&gt; to be enabled on your stack.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;otel&lt;/code&gt;&lt;/strong&gt;: Application Observability metrics. Requires &lt;a href=&#34;/docs/grafana-cloud/monitor-applications/application-observability/&#34;&gt;Application Observability&lt;/a&gt; to be enabled on your stack.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;prometheus&lt;/code&gt;&lt;/strong&gt;: Standard Prometheus metrics.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;aws&lt;/code&gt;&lt;/strong&gt;: Amazon Web Services metrics.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;create-the-required-tokens&#34;&gt;Create the required tokens&lt;/h2&gt;
&lt;p&gt;Before you configure the Knowledge Graph stack, create the Cloud Access Policy and Grafana Service Account tokens that the resource requires.&lt;/p&gt;
&lt;p&gt;Create a file named &lt;code&gt;knowledge-graph-stack.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Create a Cloud Access Policy with required scopes
resource &amp;#34;grafana_cloud_access_policy&amp;#34; &amp;#34;knowledge_graph&amp;#34; {
  name         = &amp;#34;knowledge-graph-stack-policy&amp;#34;
  display_name = &amp;#34;Knowledge Graph Stack Policy&amp;#34;

  scopes = [
    &amp;#34;stacks:read&amp;#34;,
    &amp;#34;metrics:read&amp;#34;,
    &amp;#34;metrics:write&amp;#34;,
  ]

  realm {
    type       = &amp;#34;stack&amp;#34;
    identifier = var.stack_id
  }
}

# Create a token from the Cloud Access Policy
resource &amp;#34;grafana_cloud_access_policy_token&amp;#34; &amp;#34;knowledge_graph&amp;#34; {
  name             = &amp;#34;knowledge-graph-stack-token&amp;#34;
  access_policy_id = grafana_cloud_access_policy.knowledge_graph.policy_id
}

# Create a Grafana Service Account for dashboards and Grafana Managed Alerts
resource &amp;#34;grafana_cloud_stack_service_account&amp;#34; &amp;#34;knowledge_graph&amp;#34; {
  stack_slug  = var.stack_slug
  name        = &amp;#34;knowledge-graph-managed-alerts-sa&amp;#34;
  role        = &amp;#34;Admin&amp;#34;
  is_disabled = false
}

resource &amp;#34;grafana_cloud_stack_service_account_token&amp;#34; &amp;#34;knowledge_graph&amp;#34; {
  stack_slug         = var.stack_slug
  service_account_id = grafana_cloud_stack_service_account.knowledge_graph.id
  name               = &amp;#34;knowledge-graph-managed-alerts-token&amp;#34;
}

variable &amp;#34;stack_id&amp;#34; {
  description = &amp;#34;The Grafana Cloud stack ID&amp;#34;
  type        = string
}

variable &amp;#34;stack_slug&amp;#34; {
  description = &amp;#34;The Grafana Cloud stack slug&amp;#34;
  type        = string
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Replace the following values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;code&gt;&amp;lt;STACK_ID&amp;gt;&lt;/code&gt;&lt;/em&gt; with your Grafana Cloud stack ID&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;code&gt;&amp;lt;STACK_SLUG&amp;gt;&lt;/code&gt;&lt;/em&gt; with your Grafana Cloud stack slug&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;basic-stack-configuration-with-auto-detected-datasets&#34;&gt;Basic stack configuration with auto-detected datasets&lt;/h2&gt;
&lt;p&gt;The simplest configuration provisions tokens and auto-detects datasets based on available metrics. This is the recommended approach when your metrics use standard label names.&lt;/p&gt;
&lt;p&gt;Add the following to &lt;code&gt;knowledge-graph-stack.tf&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_asserts_stack&amp;#34; &amp;#34;main&amp;#34; {
  cloud_access_policy_token = grafana_cloud_access_policy_token.knowledge_graph.token
  grafana_token             = grafana_cloud_stack_service_account_token.knowledge_graph.key
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;When you apply this configuration, the resource:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Provisions API tokens for Grafana Cloud, Mimir, and the assertion detector&lt;/li&gt;
&lt;li&gt;Auto-detects available datasets based on your stack&amp;rsquo;s metrics&lt;/li&gt;
&lt;li&gt;Enables the stack with the detected datasets&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;configure-the-dataset-manually&#34;&gt;Configure the dataset manually&lt;/h2&gt;
&lt;p&gt;Use manual configuration when your metrics use non-standard label names, for example a custom environment label. Each &lt;code&gt;dataset&lt;/code&gt; block configures one dataset type.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_asserts_stack&amp;#34; &amp;#34;manual&amp;#34; {
  cloud_access_policy_token = grafana_cloud_access_policy_token.knowledge_graph.token
  grafana_token             = grafana_cloud_stack_service_account_token.knowledge_graph.key

  dataset {
    type = &amp;#34;kubernetes&amp;#34;

    filter_group {
      env_label  = &amp;#34;deployment_environment&amp;#34;
      site_label = &amp;#34;cluster&amp;#34;

      env_label_values  = [&amp;#34;production&amp;#34;, &amp;#34;staging&amp;#34;]
      site_label_values = [&amp;#34;us-east-1&amp;#34;, &amp;#34;eu-west-1&amp;#34;]
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;When you specify one or more &lt;code&gt;dataset&lt;/code&gt; blocks, auto-detection is skipped. You must define all datasets you want to configure.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;configure-multiple-datasets-with-filters&#34;&gt;Configure multiple datasets with filters&lt;/h2&gt;
&lt;p&gt;Configure multiple dataset types with custom label mappings and metric filters:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_asserts_stack&amp;#34; &amp;#34;multi_dataset&amp;#34; {
  cloud_access_policy_token = grafana_cloud_access_policy_token.knowledge_graph.token
  grafana_token             = grafana_cloud_stack_service_account_token.knowledge_graph.key

  dataset {
    type = &amp;#34;kubernetes&amp;#34;

    filter_group {
      env_label  = &amp;#34;deployment_environment&amp;#34;
      site_label = &amp;#34;cluster&amp;#34;

      env_label_values  = [&amp;#34;production&amp;#34;, &amp;#34;staging&amp;#34;]
      site_label_values = [&amp;#34;us-east-1&amp;#34;, &amp;#34;eu-west-1&amp;#34;]
    }
  }

  dataset {
    type = &amp;#34;prometheus&amp;#34;

    filter_group {
      env_label = &amp;#34;environment&amp;#34;
      env_name  = &amp;#34;prod&amp;#34;

      filter {
        name     = &amp;#34;region&amp;#34;
        operator = &amp;#34;=~&amp;#34;
        values   = [&amp;#34;us-.*&amp;#34;, &amp;#34;eu-.*&amp;#34;]
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;resource-reference&#34;&gt;Resource reference&lt;/h2&gt;
&lt;h3 id=&#34;grafana_asserts_stack&#34;&gt;&lt;code&gt;grafana_asserts_stack&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Manage the Knowledge Graph stack configuration through the Grafana API. This resource handles the full onboarding flow including token provisioning, dataset configuration, and stack enablement.&lt;/p&gt;
&lt;h4 id=&#34;arguments&#34;&gt;Arguments&lt;/h4&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;cloud_access_policy_token&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;A Grafana Cloud Access Policy token with the following scopes: &lt;code&gt;stacks:read&lt;/code&gt;, &lt;code&gt;metrics:read&lt;/code&gt;, &lt;code&gt;metrics:write&lt;/code&gt;. Used for Grafana Cloud API access, Mimir authentication, and assertion detector webhook authentication. Sensitive.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;grafana_token&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;A Grafana Service Account token for installing dashboards and Grafana Managed Alerts. Create using &lt;code&gt;grafana_cloud_stack_service_account_token&lt;/code&gt;. Sensitive.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;dataset&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(object)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Manual dataset configuration. When specified, auto-detection is skipped. Refer to &lt;a href=&#34;#dataset-block&#34;&gt;dataset block&lt;/a&gt; for details.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;attributes&#34;&gt;Attributes&lt;/h4&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;enabled&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;bool&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Whether the stack is currently enabled.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;status&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Current onboarding status of the stack.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;version&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;int&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Configuration version number.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;dataset-block&#34;&gt;Dataset block&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;dataset&lt;/code&gt; block supports the following:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;type&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The dataset type: &lt;code&gt;kubernetes&lt;/code&gt;, &lt;code&gt;otel&lt;/code&gt;, &lt;code&gt;prometheus&lt;/code&gt;, or &lt;code&gt;aws&lt;/code&gt;.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;disabled_vendors&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(string)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;List of vendors to disable for this dataset.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;filter_group&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(object)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Filter groups for custom label mappings. Refer to &lt;a href=&#34;#filter-group-block&#34;&gt;filter group block&lt;/a&gt; for details.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;filter-group-block&#34;&gt;Filter group block&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;filter_group&lt;/code&gt; block supports the following:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;env_label&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;The metric label name used for environment (for example, &lt;code&gt;env&lt;/code&gt;, &lt;code&gt;environment&lt;/code&gt;, &lt;code&gt;deployment_environment&lt;/code&gt;).&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;env_name&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;A friendly name for the environment.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;site_label&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;The metric label name used for site or cluster.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;env_label_values&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(string)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Specific values of the environment label to match.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;site_label_values&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(string)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Specific values of the site label to match.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;filter&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(object)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Additional metric filters. Refer to &lt;a href=&#34;#filter-block&#34;&gt;filter block&lt;/a&gt; for details.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;filter-block&#34;&gt;Filter block&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;filter&lt;/code&gt; block supports the following:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The label name to filter on.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;operator&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The filter operator: &lt;code&gt;=&lt;/code&gt;, &lt;code&gt;!=&lt;/code&gt;, &lt;code&gt;=~&lt;/code&gt;, or &lt;code&gt;!~&lt;/code&gt;.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;values&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(string)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The values to match against.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;example&#34;&gt;Example&lt;/h4&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_asserts_stack&amp;#34; &amp;#34;example&amp;#34; {
  cloud_access_policy_token = grafana_cloud_access_policy_token.knowledge_graph.token
  grafana_token             = grafana_cloud_stack_service_account_token.knowledge_graph.key

  dataset {
    type = &amp;#34;kubernetes&amp;#34;

    filter_group {
      env_label         = &amp;#34;deployment_environment&amp;#34;
      site_label        = &amp;#34;cluster&amp;#34;
      env_label_values  = [&amp;#34;production&amp;#34;]
      site_label_values = [&amp;#34;us-east-1&amp;#34;]
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;best-practices&#34;&gt;Best practices&lt;/h2&gt;
&lt;p&gt;Consider the following best practices when configuring the Knowledge Graph stack with Terraform.&lt;/p&gt;
&lt;h3 id=&#34;token-management&#34;&gt;Token management&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Create a dedicated Cloud Access Policy for the Knowledge Graph stack with only the required scopes&lt;/li&gt;
&lt;li&gt;Use separate Service Accounts for different purposes rather than sharing a single admin token&lt;/li&gt;
&lt;li&gt;Rotate tokens regularly and use sensitive variable handling in Terraform to avoid exposing tokens in logs&lt;/li&gt;
&lt;li&gt;Store tokens in a secret management system and reference them through Terraform variables&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;dataset-configuration&#34;&gt;Dataset configuration&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Start with auto-detected datasets and switch to manual configuration only when needed&lt;/li&gt;
&lt;li&gt;When using manual configuration, define all datasets you want to monitor&lt;/li&gt;
&lt;li&gt;Use specific &lt;code&gt;env_label_values&lt;/code&gt; and &lt;code&gt;site_label_values&lt;/code&gt; to limit the scope of monitoring&lt;/li&gt;
&lt;li&gt;Test dataset configurations in a non-production stack first&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;filter-groups&#34;&gt;Filter groups&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Use filter groups when your metrics use non-standard label names&lt;/li&gt;
&lt;li&gt;Match your &lt;code&gt;env_label&lt;/code&gt; and &lt;code&gt;site_label&lt;/code&gt; values to the actual label names in your Prometheus metrics&lt;/li&gt;
&lt;li&gt;Use regular expression operators (&lt;code&gt;=~&lt;/code&gt;, &lt;code&gt;!~&lt;/code&gt;) in filters for flexible value matching across regions or environments&lt;/li&gt;
&lt;li&gt;Keep filter configurations consistent across datasets for predictable behavior&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;validation&#34;&gt;Validation&lt;/h2&gt;
&lt;p&gt;After applying the Terraform configuration, verify that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The stack status shows as enabled by checking the &lt;code&gt;enabled&lt;/code&gt; output attribute&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;status&lt;/code&gt; attribute indicates successful onboarding&lt;/li&gt;
&lt;li&gt;Datasets are configured correctly in the Knowledge Graph UI&lt;/li&gt;
&lt;li&gt;Dashboards and alerting rules are installed when &lt;code&gt;grafana_token&lt;/code&gt; is provided&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can inspect the stack status using Terraform outputs:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;output &amp;#34;stack_enabled&amp;#34; {
  value       = grafana_asserts_stack.main.enabled
  description = &amp;#34;Whether the Knowledge Graph stack is enabled&amp;#34;
}

output &amp;#34;stack_status&amp;#34; {
  value       = grafana_asserts_stack.main.status
  description = &amp;#34;Current onboarding status of the stack&amp;#34;
}

output &amp;#34;stack_version&amp;#34; {
  value       = grafana_asserts_stack.main.version
  description = &amp;#34;Configuration version number&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;related-documentation&#34;&gt;Related documentation&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/&#34;&gt;Knowledge Graph documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../getting-started/&#34;&gt;Get started with Terraform for Knowledge Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://registry.terraform.io/providers/grafana/grafana/latest/docs&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Grafana Terraform Provider documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/account-management/authentication-and-permissions/access-policies/&#34;&gt;Cloud Access Policies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana/latest/administration/service-accounts/&#34;&gt;Service accounts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="configure-the-knowledge-graph-stack-using-terraform">Configure the Knowledge Graph stack using Terraform&lt;/h1>
&lt;p>The Knowledge Graph stack resource manages the full onboarding flow for your Grafana Cloud stack. It provisions API tokens, configures datasets based on available metrics, and enables the stack.&lt;/p></description></item><item><title>Configure notification alerts using Terraform</title><link>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/notification-alerts/</link><pubDate>Fri, 03 Apr 2026 19:43:06 +0000</pubDate><guid>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/notification-alerts/</guid><content><![CDATA[&lt;h1 id=&#34;configure-notification-alerts-using-terraform&#34;&gt;Configure notification alerts using Terraform&lt;/h1&gt;
&lt;p&gt;Notification alerts configurations in &lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/&#34;&gt;Knowledge Graph&lt;/a&gt; allow you to manage how alerts are processed and routed. You can specify match labels to filter alerts, add custom labels, set duration requirements, and control silencing.&lt;/p&gt;
&lt;p&gt;For information about configuring notification alerts in the Knowledge Graph UI, refer to &lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/configure/notifications/&#34;&gt;Configure notifications&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;basic-notification-alerts-configuration&#34;&gt;Basic notification alerts configuration&lt;/h2&gt;
&lt;p&gt;Create a file named &lt;code&gt;alert-configs.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Basic alert configuration with silencing
resource &amp;#34;grafana_asserts_notification_alerts_config&amp;#34; &amp;#34;prometheus_remote_storage_failures&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;PrometheusRemoteStorageFailures&amp;#34;

  match_labels = {
    alertname   = &amp;#34;PrometheusRemoteStorageFailures&amp;#34;
    alertgroup  = &amp;#34;prometheus.alerts&amp;#34;
    asserts_env = &amp;#34;prod&amp;#34;
  }

  silenced = true
}

# High severity alert with specific job and context matching
resource &amp;#34;grafana_asserts_notification_alerts_config&amp;#34; &amp;#34;error_buildup_notify&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;ErrorBuildupNotify&amp;#34;

  match_labels = {
    alertname               = &amp;#34;ErrorBuildup&amp;#34;
    job                     = &amp;#34;acai&amp;#34;
    asserts_request_type    = &amp;#34;inbound&amp;#34;
    asserts_request_context = &amp;#34;/auth&amp;#34;
  }

  silenced = false
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;notification-alerts-with-additional-labels-and-duration&#34;&gt;Notification alerts with additional labels and duration&lt;/h2&gt;
&lt;p&gt;Configure alerts with custom labels and timing requirements:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Alert with additional labels and custom duration
resource &amp;#34;grafana_asserts_notification_alerts_config&amp;#34; &amp;#34;payment_test_alert&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;PaymentTestAlert&amp;#34;

  match_labels = {
    alertname         = &amp;#34;PaymentTestAlert&amp;#34;
    additional_labels = &amp;#34;asserts_severity=~\&amp;#34;critical\&amp;#34;&amp;#34;
    alertgroup        = &amp;#34;alex-k8s-integration-test.alerts&amp;#34;
  }

  alert_labels = {
    testing = &amp;#34;onetwothree&amp;#34;
  }

  duration = &amp;#34;5m&amp;#34;
  silenced = false
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;latency-and-performance-notification-alerts&#34;&gt;Latency and performance notification alerts&lt;/h2&gt;
&lt;p&gt;Monitor and alert on latency and performance issues:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Latency alert for shipping service
resource &amp;#34;grafana_asserts_notification_alerts_config&amp;#34; &amp;#34;high_shipping_latency&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;high shipping latency&amp;#34;

  match_labels = {
    alertname            = &amp;#34;LatencyP99ErrorBuildup&amp;#34;
    job                  = &amp;#34;shipping&amp;#34;
    asserts_request_type = &amp;#34;inbound&amp;#34;
  }

  silenced = false
}

# CPU throttling alert with warning severity
resource &amp;#34;grafana_asserts_notification_alerts_config&amp;#34; &amp;#34;cpu_throttling_sustained&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;CPUThrottlingSustained&amp;#34;

  match_labels = {
    alertname         = &amp;#34;CPUThrottlingSustained&amp;#34;
    additional_labels = &amp;#34;asserts_severity=~\&amp;#34;warning\&amp;#34;&amp;#34;
  }

  silenced = true
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;infrastructure-and-service-notification-alerts&#34;&gt;Infrastructure and service notification alerts&lt;/h2&gt;
&lt;p&gt;Configure alerts for infrastructure components and services:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Ingress error rate alert
resource &amp;#34;grafana_asserts_notification_alerts_config&amp;#34; &amp;#34;ingress_error&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;ingress error&amp;#34;

  match_labels = {
    alertname            = &amp;#34;ErrorRatioBreach&amp;#34;
    job                  = &amp;#34;ingress-nginx-controller-metrics&amp;#34;
    asserts_request_type = &amp;#34;inbound&amp;#34;
  }

  silenced = false
}

# MySQL Galera cluster alert
resource &amp;#34;grafana_asserts_notification_alerts_config&amp;#34; &amp;#34;mysql_galera_not_ready&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;MySQLGaleraNotReady&amp;#34;

  match_labels = {
    alertname = &amp;#34;MySQLGaleraNotReady&amp;#34;
  }

  silenced = false
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;resource-reference&#34;&gt;Resource reference&lt;/h2&gt;
&lt;h3 id=&#34;grafana_asserts_notification_alerts_config&#34;&gt;&lt;code&gt;grafana_asserts_notification_alerts_config&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Manage Knowledge Graph notification alerts configurations through the Grafana API.&lt;/p&gt;
&lt;h4 id=&#34;arguments&#34;&gt;Arguments&lt;/h4&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The name of the notification alerts configuration. This field is immutable and forces recreation if changed.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;match_labels&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;map(string)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Labels to match for this notification alerts configuration. Used to filter which alerts this configuration applies to.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;alert_labels&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;map(string)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Labels to add to alerts generated by this notification alerts configuration.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;duration&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Duration for which the condition must be true before firing (for example, &amp;lsquo;5m&amp;rsquo;, &amp;rsquo;30s&amp;rsquo;). Maps to &amp;lsquo;for&amp;rsquo; in Knowledge Graph API.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;silenced&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;bool&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Whether this notification alerts configuration is silenced. Defaults to &lt;code&gt;false&lt;/code&gt;.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;example&#34;&gt;Example&lt;/h4&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_asserts_notification_alerts_config&amp;#34; &amp;#34;example&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;ExampleAlert&amp;#34;

  match_labels = {
    alertname = &amp;#34;HighCPUUsage&amp;#34;
    job       = &amp;#34;monitoring&amp;#34;
  }

  alert_labels = {
    severity = &amp;#34;warning&amp;#34;
    team     = &amp;#34;platform&amp;#34;
  }

  duration = &amp;#34;5m&amp;#34;
  silenced = false
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;best-practices&#34;&gt;Best practices&lt;/h2&gt;
&lt;p&gt;Consider the following best practices when managing notification alerts with Terraform.&lt;/p&gt;
&lt;h3 id=&#34;label-management&#34;&gt;Label management&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Use specific and meaningful labels in &lt;code&gt;match_labels&lt;/code&gt; to ensure precise alert filtering&lt;/li&gt;
&lt;li&gt;Leverage existing label conventions from your monitoring setup&lt;/li&gt;
&lt;li&gt;Consider using &lt;code&gt;asserts_env&lt;/code&gt; and &lt;code&gt;asserts_site&lt;/code&gt; labels for multi-environment setups&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;silence-strategy&#34;&gt;Silence strategy&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Use the &lt;code&gt;silenced&lt;/code&gt; parameter for temporary suppression rather than deleting notification alerts configurations&lt;/li&gt;
&lt;li&gt;Document the reason for silencing in your Terraform configuration comments&lt;/li&gt;
&lt;li&gt;Regularly review silenced configurations to ensure they&amp;rsquo;re still needed&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;duration-configuration&#34;&gt;Duration configuration&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Set appropriate duration values based on your alerting requirements&lt;/li&gt;
&lt;li&gt;Consider the nature of the monitored condition when choosing duration&lt;/li&gt;
&lt;li&gt;Use consistent duration formats across similar alert types&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;validation&#34;&gt;Validation&lt;/h2&gt;
&lt;p&gt;After applying the Terraform configuration, verify that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Notification alerts configurations are created in your Knowledge Graph instance&lt;/li&gt;
&lt;li&gt;Configurations appear in the Knowledge Graph UI under &lt;strong&gt;Observability &amp;gt; Rules &amp;gt; Notify&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Match labels correctly filter the intended alerts&lt;/li&gt;
&lt;li&gt;Custom labels are properly applied to generated alerts&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;related-documentation&#34;&gt;Related documentation&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/configure/notifications/&#34;&gt;Configure notifications in Knowledge Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../getting-started/&#34;&gt;Get started with Terraform for Knowledge Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/configure/alerts/&#34;&gt;Configure alerts in Knowledge Graph&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="configure-notification-alerts-using-terraform">Configure notification alerts using Terraform&lt;/h1>
&lt;p>Notification alerts configurations in &lt;a href="/docs/grafana-cloud/knowledge-graph/">Knowledge Graph&lt;/a> allow you to manage how alerts are processed and routed. You can specify match labels to filter alerts, add custom labels, set duration requirements, and control silencing.&lt;/p></description></item><item><title>Configure suppressed assertions using Terraform</title><link>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/suppressed-assertions/</link><pubDate>Fri, 03 Apr 2026 19:43:06 +0000</pubDate><guid>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/suppressed-assertions/</guid><content><![CDATA[&lt;h1 id=&#34;configure-suppressed-assertions-using-terraform&#34;&gt;Configure suppressed assertions using Terraform&lt;/h1&gt;
&lt;p&gt;Suppressed assertions configurations allow you to disable specific alerts or assertions based on label matching in &lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/&#34;&gt;Knowledge Graph&lt;/a&gt;. This is useful for maintenance windows, test environments, or when you want to temporarily suppress certain types of alerts.&lt;/p&gt;
&lt;p&gt;For information about suppressing insights in the Knowledge Graph UI, refer to &lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/troubleshoot-infra-apps/suppress-insights/&#34;&gt;Suppress insights&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;basic-suppressed-assertions-configuration&#34;&gt;Basic suppressed assertions configuration&lt;/h2&gt;
&lt;p&gt;Create a file named &lt;code&gt;suppressed-assertions.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Basic suppressed alert configuration for maintenance
resource &amp;#34;grafana_asserts_suppressed_assertions_config&amp;#34; &amp;#34;maintenance_window&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;MaintenanceWindow&amp;#34;

  match_labels = {
    service     = &amp;#34;api-service&amp;#34;
    maintenance = &amp;#34;true&amp;#34;
  }
}

# Suppress specific alertname during deployment
resource &amp;#34;grafana_asserts_suppressed_assertions_config&amp;#34; &amp;#34;deployment_suppression&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;DeploymentSuppression&amp;#34;

  match_labels = {
    alertname = &amp;#34;HighLatency&amp;#34;
    job       = &amp;#34;web-service&amp;#34;
    env       = &amp;#34;staging&amp;#34;
  }
}

# Suppress alerts for specific test environment
resource &amp;#34;grafana_asserts_suppressed_assertions_config&amp;#34; &amp;#34;test_environment_suppression&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;TestEnvironmentSuppression&amp;#34;

  match_labels = {
    alertgroup  = &amp;#34;test.alerts&amp;#34;
    environment = &amp;#34;test&amp;#34;
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;service-specific-suppression-configurations&#34;&gt;Service-specific suppression configurations&lt;/h2&gt;
&lt;p&gt;Suppress alerts for specific services during maintenance or operational activities:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Suppress alerts for specific services during maintenance
resource &amp;#34;grafana_asserts_suppressed_assertions_config&amp;#34; &amp;#34;api_service_maintenance&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;APIServiceMaintenance&amp;#34;

  match_labels = {
    service     = &amp;#34;api-gateway&amp;#34;
    job         = &amp;#34;api-gateway&amp;#34;
    maintenance = &amp;#34;scheduled&amp;#34;
  }
}

# Suppress database alerts during backup operations
resource &amp;#34;grafana_asserts_suppressed_assertions_config&amp;#34; &amp;#34;database_backup&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;DatabaseBackupSuppression&amp;#34;

  match_labels = {
    service     = &amp;#34;postgresql&amp;#34;
    job         = &amp;#34;postgres-exporter&amp;#34;
    backup_mode = &amp;#34;active&amp;#34;
  }
}

# Suppress monitoring system alerts during updates
resource &amp;#34;grafana_asserts_suppressed_assertions_config&amp;#34; &amp;#34;monitoring_update&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;MonitoringSystemUpdate&amp;#34;

  match_labels = {
    service = &amp;#34;prometheus&amp;#34;
    job     = &amp;#34;prometheus&amp;#34;
    update  = &amp;#34;in_progress&amp;#34;
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;environment-and-team-based-suppression&#34;&gt;Environment and team-based suppression&lt;/h2&gt;
&lt;p&gt;Create suppression rules based on environment or team:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Suppress all alerts for development environment
resource &amp;#34;grafana_asserts_suppressed_assertions_config&amp;#34; &amp;#34;dev_environment&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;DevelopmentEnvironmentSuppression&amp;#34;

  match_labels = {
    environment = &amp;#34;development&amp;#34;
    team        = &amp;#34;platform&amp;#34;
  }
}

# Suppress alerts for specific team during their maintenance window
resource &amp;#34;grafana_asserts_suppressed_assertions_config&amp;#34; &amp;#34;team_maintenance&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;TeamMaintenanceWindow&amp;#34;

  match_labels = {
    team        = &amp;#34;backend&amp;#34;
    maintenance = &amp;#34;team_scheduled&amp;#34;
    timezone    = &amp;#34;UTC&amp;#34;
  }
}

# Suppress alerts for staging environment during testing
resource &amp;#34;grafana_asserts_suppressed_assertions_config&amp;#34; &amp;#34;staging_testing&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;StagingTestingSuppression&amp;#34;

  match_labels = {
    environment = &amp;#34;staging&amp;#34;
    testing     = &amp;#34;automated&amp;#34;
    job         = &amp;#34;integration-tests&amp;#34;
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;alert-type-and-severity-based-suppression&#34;&gt;Alert type and severity-based suppression&lt;/h2&gt;
&lt;p&gt;Suppress alerts based on their type or severity:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Suppress low severity alerts during business hours
resource &amp;#34;grafana_asserts_suppressed_assertions_config&amp;#34; &amp;#34;low_severity_business_hours&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;LowSeverityBusinessHours&amp;#34;

  match_labels = {
    severity = &amp;#34;warning&amp;#34;
    timezone = &amp;#34;business_hours&amp;#34;
  }
}

# Suppress specific alert types during known issues
resource &amp;#34;grafana_asserts_suppressed_assertions_config&amp;#34; &amp;#34;known_issue_suppression&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;KnownIssueSuppression&amp;#34;

  match_labels = {
    alertname = &amp;#34;HighMemoryUsage&amp;#34;
    service   = &amp;#34;legacy-service&amp;#34;
    issue_id  = &amp;#34;LEG-123&amp;#34;
  }
}

# Suppress infrastructure alerts during planned maintenance
resource &amp;#34;grafana_asserts_suppressed_assertions_config&amp;#34; &amp;#34;infrastructure_maintenance&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;InfrastructureMaintenance&amp;#34;

  match_labels = {
    alertgroup = &amp;#34;infrastructure.alerts&amp;#34;
    maintenance_type = &amp;#34;planned&amp;#34;
    affected_services = &amp;#34;all&amp;#34;
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;complex-multi-label-suppression&#34;&gt;Complex multi-label suppression&lt;/h2&gt;
&lt;p&gt;Define complex suppression rules with multiple labels:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Complex suppression for multi-service deployments
resource &amp;#34;grafana_asserts_suppressed_assertions_config&amp;#34; &amp;#34;multi_service_deployment&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;MultiServiceDeploymentSuppression&amp;#34;

  match_labels = {
    deployment_id = &amp;#34;deploy-2024-01-15&amp;#34;
    services      = &amp;#34;api,worker,frontend&amp;#34;
    environment   = &amp;#34;production&amp;#34;
    deployment_type = &amp;#34;blue_green&amp;#34;
  }
}

# Suppress alerts for specific cluster during maintenance
resource &amp;#34;grafana_asserts_suppressed_assertions_config&amp;#34; &amp;#34;cluster_maintenance&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;ClusterMaintenanceSuppression&amp;#34;

  match_labels = {
    cluster     = &amp;#34;production-cluster-1&amp;#34;
    maintenance = &amp;#34;cluster_upgrade&amp;#34;
    affected_nodes = &amp;#34;all&amp;#34;
    estimated_duration = &amp;#34;2h&amp;#34;
  }
}

# Suppress alerts for specific region during network issues
resource &amp;#34;grafana_asserts_suppressed_assertions_config&amp;#34; &amp;#34;regional_network_issue&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;RegionalNetworkIssueSuppression&amp;#34;

  match_labels = {
    region      = &amp;#34;us-west-2&amp;#34;
    issue_type  = &amp;#34;network&amp;#34;
    affected_services = &amp;#34;external_dependencies&amp;#34;
    incident_id = &amp;#34;NET-456&amp;#34;
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;resource-reference&#34;&gt;Resource reference&lt;/h2&gt;
&lt;h3 id=&#34;grafana_asserts_suppressed_assertions_config&#34;&gt;&lt;code&gt;grafana_asserts_suppressed_assertions_config&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Manage Knowledge Graph suppressed assertions configurations through the Grafana API.&lt;/p&gt;
&lt;h4 id=&#34;arguments&#34;&gt;Arguments&lt;/h4&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The name of the suppressed assertions configuration. This field is immutable and forces recreation if changed.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;match_labels&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;map(string)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Labels to match for this suppressed assertions configuration. Used to determine which alerts should be suppressed.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;example&#34;&gt;Example&lt;/h4&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_asserts_suppressed_assertions_config&amp;#34; &amp;#34;example&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;ExampleSuppression&amp;#34;

  match_labels = {
    alertname = &amp;#34;TestAlert&amp;#34;
    env       = &amp;#34;development&amp;#34;
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;best-practices&#34;&gt;Best practices&lt;/h2&gt;
&lt;p&gt;Consider the following best practices when managing suppressed assertions with Terraform.&lt;/p&gt;
&lt;h3 id=&#34;suppression-strategy&#34;&gt;Suppression strategy&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Use suppression rules for temporary situations rather than permanent solutions&lt;/li&gt;
&lt;li&gt;Document the reason for suppression in your Terraform configuration comments&lt;/li&gt;
&lt;li&gt;Set expiration dates or reminders to review suppression rules&lt;/li&gt;
&lt;li&gt;Prefer fixing alert thresholds over suppressing recurring false positives&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;label-match-rules&#34;&gt;Label match rules&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Be specific with match labels to avoid suppressing unintended alerts&lt;/li&gt;
&lt;li&gt;Test suppression rules in non-production environments first&lt;/li&gt;
&lt;li&gt;Use descriptive names that indicate the purpose and scope of the suppression&lt;/li&gt;
&lt;li&gt;Include relevant context in labels (for example, incident IDs, maintenance windows)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;lifecycle-management&#34;&gt;Lifecycle management&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Regularly review active suppression rules to ensure they&amp;rsquo;re still needed&lt;/li&gt;
&lt;li&gt;Remove or update suppression rules after maintenance windows or deployments&lt;/li&gt;
&lt;li&gt;Use version control to track when suppression rules were added and why&lt;/li&gt;
&lt;li&gt;Consider using time-based automation to enable or disable suppression rules&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;validation&#34;&gt;Validation&lt;/h2&gt;
&lt;p&gt;After applying the Terraform configuration, verify that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Suppressed assertions configurations are active in your Knowledge Graph instance&lt;/li&gt;
&lt;li&gt;Configurations appear in the Knowledge Graph UI under &lt;strong&gt;Observability &amp;gt; Rules &amp;gt; Suppress&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Matching alerts are properly suppressed&lt;/li&gt;
&lt;li&gt;Suppression rules don&amp;rsquo;t affect unintended alerts&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;related-documentation&#34;&gt;Related documentation&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/troubleshoot-infra-apps/suppress-insights/&#34;&gt;Suppress insights in Knowledge Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../getting-started/&#34;&gt;Get started with Terraform for Knowledge Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/configure/notifications/&#34;&gt;Configure notifications&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="configure-suppressed-assertions-using-terraform">Configure suppressed assertions using Terraform&lt;/h1>
&lt;p>Suppressed assertions configurations allow you to disable specific alerts or assertions based on label matching in &lt;a href="/docs/grafana-cloud/knowledge-graph/">Knowledge Graph&lt;/a>. This is useful for maintenance windows, test environments, or when you want to temporarily suppress certain types of alerts.&lt;/p></description></item><item><title>Create custom model rules using Terraform</title><link>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/custom-model-rules/</link><pubDate>Fri, 03 Apr 2026 19:43:06 +0000</pubDate><guid>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/custom-model-rules/</guid><content><![CDATA[&lt;h1 id=&#34;create-custom-model-rules-using-terraform&#34;&gt;Create custom model rules using Terraform&lt;/h1&gt;
&lt;p&gt;Custom model rules in &lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/&#34;&gt;Knowledge Graph&lt;/a&gt; allow you to define how entities are discovered and modeled based on Prometheus queries. These rules enable you to create custom entity types, define their relationships, and specify how they should be enriched with additional data.&lt;/p&gt;
&lt;p&gt;For information about managing entities and relations in the Knowledge Graph UI, refer to &lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/configure/manage-entities-relations/&#34;&gt;Manage entities and relations&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;basic-custom-model-rules&#34;&gt;Basic custom model rules&lt;/h2&gt;
&lt;p&gt;Create a file named &lt;code&gt;custom-model-rules.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Basic custom model rule for services
resource &amp;#34;grafana_asserts_custom_model_rules&amp;#34; &amp;#34;basic_service&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;basic-service-model&amp;#34;

  rules {
    entity {
      type = &amp;#34;Service&amp;#34;
      name = &amp;#34;service&amp;#34;

      defined_by {
        query = &amp;#34;up{job!=&amp;#39;&amp;#39;}&amp;#34;
        label_values = {
          service = &amp;#34;job&amp;#34;
        }
        literals = {
          _source = &amp;#34;up_query&amp;#34;
        }
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;advanced-service-model-with-scope-and-lookup&#34;&gt;Advanced service model with scope and lookup&lt;/h2&gt;
&lt;p&gt;Define service entities with environment scoping and relationship mappings:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Advanced service model with environment scoping
resource &amp;#34;grafana_asserts_custom_model_rules&amp;#34; &amp;#34;advanced_service&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;advanced-service-model&amp;#34;

  rules {
    entity {
      type = &amp;#34;Service&amp;#34;
      name = &amp;#34;workload | service | job&amp;#34;

      scope = {
        namespace = &amp;#34;namespace&amp;#34;
        env       = &amp;#34;asserts_env&amp;#34;
        site      = &amp;#34;asserts_site&amp;#34;
      }

      lookup = {
        workload  = &amp;#34;workload | deployment | statefulset | daemonset | replicaset&amp;#34;
        service   = &amp;#34;service&amp;#34;
        job       = &amp;#34;job&amp;#34;
        proxy_job = &amp;#34;job&amp;#34;
      }

      defined_by {
        query = &amp;#34;up{job!=&amp;#39;&amp;#39;, asserts_env!=&amp;#39;&amp;#39;}&amp;#34;
        label_values = {
          service     = &amp;#34;service&amp;#34;
          job         = &amp;#34;job&amp;#34;
          workload    = &amp;#34;workload&amp;#34;
          namespace   = &amp;#34;namespace&amp;#34;
        }
        literals = {
          _source = &amp;#34;up_with_workload&amp;#34;
        }
      }

      defined_by {
        query    = &amp;#34;up{job=&amp;#39;maintenance&amp;#39;}&amp;#34;
        disabled = true
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;multi-entity-model-configuration&#34;&gt;Multi-entity model configuration&lt;/h2&gt;
&lt;p&gt;Define multiple entity types in a single configuration:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Multiple entity types in a single model
resource &amp;#34;grafana_asserts_custom_model_rules&amp;#34; &amp;#34;multi_entity&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;kubernetes-entities&amp;#34;

  rules {
    # Service entity
    entity {
      type = &amp;#34;Service&amp;#34;
      name = &amp;#34;service&amp;#34;

      scope = {
        namespace = &amp;#34;namespace&amp;#34;
        cluster   = &amp;#34;cluster&amp;#34;
      }

      defined_by {
        query = &amp;#34;up{service!=&amp;#39;&amp;#39;}&amp;#34;
        label_values = {
          service   = &amp;#34;service&amp;#34;
          namespace = &amp;#34;namespace&amp;#34;
          cluster   = &amp;#34;cluster&amp;#34;
        }
      }
    }

    # Pod entity
    entity {
      type = &amp;#34;Pod&amp;#34;
      name = &amp;#34;Pod&amp;#34;

      scope = {
        namespace = &amp;#34;namespace&amp;#34;
        cluster   = &amp;#34;cluster&amp;#34;
      }

      lookup = {
        service   = &amp;#34;service&amp;#34;
        workload  = &amp;#34;workload&amp;#34;
      }

      defined_by {
        query = &amp;#34;kube_pod_info{pod!=&amp;#39;&amp;#39;}&amp;#34;
        label_values = {
          Pod       = &amp;#34;pod&amp;#34;
          namespace = &amp;#34;namespace&amp;#34;
          cluster   = &amp;#34;cluster&amp;#34;
          service   = &amp;#34;service&amp;#34;
        }
        literals = {
          _entity_type = &amp;#34;Pod&amp;#34;
        }
      }
    }

    # Namespace entity
    entity {
      type = &amp;#34;Namespace&amp;#34;
      name = &amp;#34;namespace&amp;#34;

      scope = {
        cluster = &amp;#34;cluster&amp;#34;
      }

      defined_by {
        query = &amp;#34;kube_namespace_status_phase{namespace!=&amp;#39;&amp;#39;}&amp;#34;
        label_values = {
          namespace = &amp;#34;namespace&amp;#34;
          cluster   = &amp;#34;cluster&amp;#34;
        }
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;complex-entity-with-enrichment&#34;&gt;Complex entity with enrichment&lt;/h2&gt;
&lt;p&gt;Create service entities with multiple data sources and enrichment:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Service entity with enrichment from multiple sources
resource &amp;#34;grafana_asserts_custom_model_rules&amp;#34; &amp;#34;enriched_service&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;enriched-service-model&amp;#34;

  rules {
    entity {
      type = &amp;#34;Service&amp;#34;
      name = &amp;#34;service&amp;#34;

      enriched_by = [
        &amp;#34;prometheus_metrics&amp;#34;,
        &amp;#34;kubernetes_metadata&amp;#34;,
        &amp;#34;application_logs&amp;#34;
      ]

      scope = {
        environment = &amp;#34;asserts_env&amp;#34;
        region      = &amp;#34;asserts_site&amp;#34;
        team        = &amp;#34;team&amp;#34;
      }

      lookup = {
        deployment = &amp;#34;workload&amp;#34;
        Pod        = &amp;#34;pod&amp;#34;
        container  = &amp;#34;container&amp;#34;
      }

      # Primary definition from service up metrics
      defined_by {
        query = &amp;#34;up{service!=&amp;#39;&amp;#39;, asserts_env!=&amp;#39;&amp;#39;}&amp;#34;
        label_values = {
          service     = &amp;#34;service&amp;#34;
          environment = &amp;#34;asserts_env&amp;#34;
          region      = &amp;#34;asserts_site&amp;#34;
          team        = &amp;#34;team&amp;#34;
        }
        literals = {
          _primary_source = &amp;#34;service_up&amp;#34;
        }
      }

      # Secondary definition from application metrics
      defined_by {
        query = &amp;#34;http_requests_total{service!=&amp;#39;&amp;#39;}&amp;#34;
        label_values = {
          service     = &amp;#34;service&amp;#34;
          environment = &amp;#34;environment&amp;#34;
          version     = &amp;#34;version&amp;#34;
        }
        literals = {
          _secondary_source = &amp;#34;http_metrics&amp;#34;
        }
      }

      # Disabled definition for testing
      defined_by {
        query    = &amp;#34;test_metric{service!=&amp;#39;&amp;#39;}&amp;#34;
        disabled = true
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;database-and-infrastructure-entities&#34;&gt;Database and infrastructure entities&lt;/h2&gt;
&lt;p&gt;Define database and infrastructure entity models:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Database and infrastructure entity models
resource &amp;#34;grafana_asserts_custom_model_rules&amp;#34; &amp;#34;infrastructure&amp;#34; {
  provider = grafana.asserts

  name = &amp;#34;infrastructure-entities&amp;#34;

  rules {
    # Database entity
    entity {
      type = &amp;#34;Database&amp;#34;
      name = &amp;#34;database_instance&amp;#34;

      scope = {
        environment = &amp;#34;env&amp;#34;
        region      = &amp;#34;region&amp;#34;
      }

      lookup = {
        host     = &amp;#34;instance&amp;#34;
        port     = &amp;#34;port&amp;#34;
        db_name  = &amp;#34;database&amp;#34;
      }

      defined_by {
        query = &amp;#34;mysql_up{instance!=&amp;#39;&amp;#39;}&amp;#34;
        label_values = {
          database_instance = &amp;#34;instance&amp;#34;
          database         = &amp;#34;database&amp;#34;
          env             = &amp;#34;environment&amp;#34;
          region          = &amp;#34;region&amp;#34;
        }
        literals = {
          _db_type = &amp;#34;mysql&amp;#34;
        }
        metric_value = &amp;#34;1&amp;#34;
      }

      defined_by {
        query = &amp;#34;postgres_up{instance!=&amp;#39;&amp;#39;}&amp;#34;
        label_values = {
          database_instance = &amp;#34;instance&amp;#34;
          database         = &amp;#34;datname&amp;#34;
          env             = &amp;#34;environment&amp;#34;
        }
        literals = {
          _db_type = &amp;#34;postgresql&amp;#34;
        }
      }
    }

    # Load balancer entity
    entity {
      type = &amp;#34;LoadBalancer&amp;#34;
      name = &amp;#34;lb_instance&amp;#34;

      scope = {
        environment = &amp;#34;env&amp;#34;
      }

      defined_by {
        query = &amp;#34;haproxy_up{proxy!=&amp;#39;&amp;#39;}&amp;#34;
        label_values = {
          lb_instance = &amp;#34;instance&amp;#34;
          proxy      = &amp;#34;proxy&amp;#34;
          env        = &amp;#34;environment&amp;#34;
        }
        literals = {
          _lb_type = &amp;#34;haproxy&amp;#34;
        }
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;resource-reference&#34;&gt;Resource reference&lt;/h2&gt;
&lt;h3 id=&#34;grafana_asserts_custom_model_rules&#34;&gt;&lt;code&gt;grafana_asserts_custom_model_rules&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Manage Knowledge Graph custom model rules through the Grafana API. This resource allows you to define custom entity models based on Prometheus queries with advanced mapping and enrichment capabilities.&lt;/p&gt;
&lt;h4 id=&#34;arguments&#34;&gt;Arguments&lt;/h4&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The name of the custom model rules. This field is immutable and forces recreation if changed.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;rules&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(object)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The rules configuration containing entity definitions. Refer to &lt;a href=&#34;#rules-block&#34;&gt;rules block&lt;/a&gt; for details.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;rules-block&#34;&gt;Rules block&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;rules&lt;/code&gt; block supports the following:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;entity&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(object)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;List of entity definitions. Refer to &lt;a href=&#34;#entity-block&#34;&gt;entity block&lt;/a&gt; for details.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;entity-block&#34;&gt;Entity block&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;entity&lt;/code&gt; block supports the following:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;type&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The type of the entity (for example, Service, Pod, Namespace).&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The name pattern for the entity. Can include pipe-separated alternatives.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;defined_by&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(object)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;List of queries that define this entity. Refer to &lt;a href=&#34;#defined_by-block&#34;&gt;&lt;code&gt;defined_by&lt;/code&gt; block&lt;/a&gt; for details.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;disabled&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;bool&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Whether this entity is disabled. Defaults to &lt;code&gt;false&lt;/code&gt;.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;enriched_by&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(string)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;List of enrichment sources for the entity.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;lookup&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;map(string)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Lookup mappings for the entity to relate different label names.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;scope&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;map(string)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Scope labels that define the boundaries of this entity type.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;defined_by-block&#34;&gt;&lt;code&gt;defined_by&lt;/code&gt; block&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;defined_by&lt;/code&gt; block supports the following:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;query&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The Prometheus query that defines this entity.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;disabled&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;bool&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Whether this query is disabled. Defaults to &lt;code&gt;false&lt;/code&gt;.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;label_values&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;map(string)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Label value mappings for extracting entity attributes from query results.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;literals&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;map(string)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Literal value mappings for adding static attributes to entities.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;metric_value&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Metric value to use from the query result.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;

&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;When &lt;code&gt;disabled = true&lt;/code&gt; is set for a &lt;code&gt;defined_by&lt;/code&gt; query, only the &lt;code&gt;query&lt;/code&gt; field is used for matching. All other fields in the block are ignored.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;best-practices&#34;&gt;Best practices&lt;/h2&gt;
&lt;p&gt;Consider the following best practices when creating custom model rules with Terraform.&lt;/p&gt;
&lt;h3 id=&#34;entity-models&#34;&gt;Entity models&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Design your entity models to reflect your actual infrastructure and application architecture&lt;/li&gt;
&lt;li&gt;Use descriptive names for custom model rules that indicate their purpose and scope&lt;/li&gt;
&lt;li&gt;Start with basic entity definitions and gradually add complexity as needed&lt;/li&gt;
&lt;li&gt;Define clear entity scopes using the &lt;code&gt;scope&lt;/code&gt; parameter to organize entities by environment, region, or team&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;query-design-and-performance&#34;&gt;Query design and performance&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Write efficient Prometheus queries that don&amp;rsquo;t overload your monitoring system&lt;/li&gt;
&lt;li&gt;Test your Prometheus queries independently before using them in model rules&lt;/li&gt;
&lt;li&gt;Use specific label filters to reduce the scope of your queries where possible&lt;/li&gt;
&lt;li&gt;Consider the cardinality implications of your entity definitions&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;disabled&lt;/code&gt; flag to temporarily disable problematic queries during debugging&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;relationships-and-enrichment&#34;&gt;Relationships and enrichment&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;lookup&lt;/code&gt; mappings to establish relationships between different entity types&lt;/li&gt;
&lt;li&gt;Leverage &lt;code&gt;enriched_by&lt;/code&gt; to specify additional data sources for entity enrichment&lt;/li&gt;
&lt;li&gt;Map Prometheus labels to entity attributes using clear and descriptive names&lt;/li&gt;
&lt;li&gt;Use meaningful &lt;code&gt;literals&lt;/code&gt; to add static metadata that helps with entity identification&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;label-and-attribute-management&#34;&gt;Label and attribute management&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Establish consistent labeling conventions across your infrastructure&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;label_values&lt;/code&gt; to extract dynamic attributes from your metrics&lt;/li&gt;
&lt;li&gt;Document the meaning and expected values of custom literals&lt;/li&gt;
&lt;li&gt;Ensure label names match across different entity definitions for proper relationship discovery&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;validation&#34;&gt;Validation&lt;/h2&gt;
&lt;p&gt;After applying the Terraform configuration, verify that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Custom model rules are applied in your Knowledge Graph instance&lt;/li&gt;
&lt;li&gt;Entities are being discovered according to your defined queries&lt;/li&gt;
&lt;li&gt;Entity relationships and enrichment are working as expected&lt;/li&gt;
&lt;li&gt;Entity graphs display the correct entity types and connections&lt;/li&gt;
&lt;li&gt;Queries perform well without causing excessive load&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;related-documentation&#34;&gt;Related documentation&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/configure/manage-entities-relations/&#34;&gt;Manage entities and relations in Knowledge Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../getting-started/&#34;&gt;Get started with Terraform for Knowledge Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/knowledge-graph-basics/&#34;&gt;Knowledge graph basics&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="create-custom-model-rules-using-terraform">Create custom model rules using Terraform&lt;/h1>
&lt;p>Custom model rules in &lt;a href="/docs/grafana-cloud/knowledge-graph/">Knowledge Graph&lt;/a> allow you to define how entities are discovered and modeled based on Prometheus queries. These rules enable you to create custom entity types, define their relationships, and specify how they should be enriched with additional data.&lt;/p></description></item><item><title>Manage Prometheus rules using Terraform</title><link>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/prometheus-rules/</link><pubDate>Fri, 03 Apr 2026 19:43:06 +0000</pubDate><guid>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/prometheus-rules/</guid><content><![CDATA[&lt;h1 id=&#34;manage-prometheus-rules-using-terraform&#34;&gt;Manage Prometheus rules using Terraform&lt;/h1&gt;
&lt;p&gt;Prometheus rules in the &lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/&#34;&gt;Knowledge Graph&lt;/a&gt; allow you to define custom recording and alerting rules that are evaluated against your metrics data. Recording rules pre-compute frequently used or computationally expensive expressions and save the results as new time series. Alerting rules define conditions that, when met, trigger alerts.&lt;/p&gt;
&lt;p&gt;Using the &lt;code&gt;grafana_asserts_prom_rule_file&lt;/code&gt; resource, you can manage these rules as code, enabling version control, review processes, and consistent deployments across environments.&lt;/p&gt;
&lt;h2 id=&#34;before-you-begin&#34;&gt;Before you begin&lt;/h2&gt;
&lt;p&gt;To manage Prometheus rules using Terraform, you need:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Grafana Cloud stack with Knowledge Graph enabled&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../getting-started/&#34;&gt;Terraform configured for Knowledge Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;An understanding of PromQL and Prometheus rule concepts&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;create-a-basic-recording-rule&#34;&gt;Create a basic recording rule&lt;/h2&gt;
&lt;p&gt;Recording rules allow you to pre-compute PromQL expressions and store the results as new metrics. This is useful for expensive queries that you run frequently.&lt;/p&gt;
&lt;p&gt;Create a file named &lt;code&gt;prom-rules.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Basic recording rule for request rate
resource &amp;#34;grafana_asserts_prom_rule_file&amp;#34; &amp;#34;request_rates&amp;#34; {
  provider = grafana.asserts

  name   = &amp;#34;request-rates&amp;#34;
  active = true

  group {
    name     = &amp;#34;request_rate_rules&amp;#34;
    interval = &amp;#34;30s&amp;#34;

    rule {
      record = &amp;#34;job:http_requests_total:rate5m&amp;#34;
      expr   = &amp;#34;sum(rate(http_requests_total[5m])) by (job)&amp;#34;

      labels = {
        aggregation = &amp;#34;job&amp;#34;
        source      = &amp;#34;custom&amp;#34;
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;create-alerting-rules&#34;&gt;Create alerting rules&lt;/h2&gt;
&lt;p&gt;Alerting rules define conditions that trigger alerts when met. Use the &lt;code&gt;alert&lt;/code&gt; field instead of &lt;code&gt;record&lt;/code&gt; to define an alerting rule.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Alerting rules for service health
resource &amp;#34;grafana_asserts_prom_rule_file&amp;#34; &amp;#34;service_alerts&amp;#34; {
  provider = grafana.asserts

  name   = &amp;#34;service-health-alerts&amp;#34;
  active = true

  group {
    name     = &amp;#34;service_health&amp;#34;
    interval = &amp;#34;1m&amp;#34;

    rule {
      alert    = &amp;#34;HighErrorRate&amp;#34;
      expr     = &amp;#34;sum(rate(http_requests_total{code=~\&amp;#34;5..\&amp;#34;}[5m])) / sum(rate(http_requests_total[5m])) &amp;gt; 0.05&amp;#34;
      duration = &amp;#34;5m&amp;#34;

      labels = {
        severity = &amp;#34;critical&amp;#34;
        team     = &amp;#34;platform&amp;#34;
      }

      annotations = {
        summary     = &amp;#34;High error rate detected&amp;#34;
        description = &amp;#34;Error rate is above 5% for the last 5 minutes&amp;#34;
        runbook_url = &amp;#34;https://docs.example.com/runbooks/high-error-rate&amp;#34;
      }
    }

    rule {
      alert    = &amp;#34;ServiceDown&amp;#34;
      expr     = &amp;#34;up == 0&amp;#34;
      duration = &amp;#34;2m&amp;#34;

      labels = {
        severity = &amp;#34;critical&amp;#34;
      }

      annotations = {
        summary     = &amp;#34;Service is down&amp;#34;
        description = &amp;#34;{{ $labels.job }} has been down for more than 2 minutes&amp;#34;
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;create-multiple-rule-groups&#34;&gt;Create multiple rule groups&lt;/h2&gt;
&lt;p&gt;Organize related rules into groups with their own evaluation intervals:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Multiple rule groups for comprehensive monitoring
resource &amp;#34;grafana_asserts_prom_rule_file&amp;#34; &amp;#34;comprehensive_rules&amp;#34; {
  provider = grafana.asserts

  name   = &amp;#34;comprehensive-monitoring&amp;#34;
  active = true

  # Latency recording rules
  group {
    name     = &amp;#34;latency_recording&amp;#34;
    interval = &amp;#34;30s&amp;#34;

    rule {
      record = &amp;#34;job:http_request_duration_seconds:p99&amp;#34;
      expr   = &amp;#34;histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (job, le))&amp;#34;

      labels = {
        quantile = &amp;#34;0.99&amp;#34;
      }
    }

    rule {
      record = &amp;#34;job:http_request_duration_seconds:p95&amp;#34;
      expr   = &amp;#34;histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (job, le))&amp;#34;

      labels = {
        quantile = &amp;#34;0.95&amp;#34;
      }
    }

    rule {
      record = &amp;#34;job:http_request_duration_seconds:p50&amp;#34;
      expr   = &amp;#34;histogram_quantile(0.50, sum(rate(http_request_duration_seconds_bucket[5m])) by (job, le))&amp;#34;

      labels = {
        quantile = &amp;#34;0.50&amp;#34;
      }
    }
  }

  # Latency alerting rules
  group {
    name     = &amp;#34;latency_alerts&amp;#34;
    interval = &amp;#34;1m&amp;#34;

    rule {
      alert    = &amp;#34;HighP99Latency&amp;#34;
      expr     = &amp;#34;job:http_request_duration_seconds:p99 &amp;gt; 1&amp;#34;
      duration = &amp;#34;5m&amp;#34;

      labels = {
        severity = &amp;#34;warning&amp;#34;
      }

      annotations = {
        summary     = &amp;#34;High P99 latency detected&amp;#34;
        description = &amp;#34;P99 latency for {{ $labels.job }} is above 1 second&amp;#34;
      }
    }

    rule {
      alert    = &amp;#34;CriticalLatency&amp;#34;
      expr     = &amp;#34;job:http_request_duration_seconds:p99 &amp;gt; 5&amp;#34;
      duration = &amp;#34;2m&amp;#34;

      labels = {
        severity = &amp;#34;critical&amp;#34;
      }

      annotations = {
        summary     = &amp;#34;Critical latency detected&amp;#34;
        description = &amp;#34;P99 latency for {{ $labels.job }} is above 5 seconds&amp;#34;
      }
    }
  }

  # Throughput rules
  group {
    name     = &amp;#34;throughput_rules&amp;#34;
    interval = &amp;#34;1m&amp;#34;

    rule {
      record = &amp;#34;job:http_requests:rate1m&amp;#34;
      expr   = &amp;#34;sum(rate(http_requests_total[1m])) by (job)&amp;#34;
    }

    rule {
      alert    = &amp;#34;LowThroughput&amp;#34;
      expr     = &amp;#34;job:http_requests:rate1m &amp;lt; 10&amp;#34;
      duration = &amp;#34;10m&amp;#34;

      labels = {
        severity = &amp;#34;warning&amp;#34;
      }

      annotations = {
        summary     = &amp;#34;Low throughput detected&amp;#34;
        description = &amp;#34;Request rate for {{ $labels.job }} is below 10 requests per second&amp;#34;
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;create-resource-utilization-rules&#34;&gt;Create resource utilization rules&lt;/h2&gt;
&lt;p&gt;Define rules to monitor resource utilization across your infrastructure:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Resource utilization monitoring rules
resource &amp;#34;grafana_asserts_prom_rule_file&amp;#34; &amp;#34;resource_utilization&amp;#34; {
  provider = grafana.asserts

  name   = &amp;#34;resource-utilization&amp;#34;
  active = true

  group {
    name     = &amp;#34;cpu_rules&amp;#34;
    interval = &amp;#34;30s&amp;#34;

    rule {
      record = &amp;#34;instance:cpu_utilization:avg5m&amp;#34;
      expr   = &amp;#34;1 - avg(rate(node_cpu_seconds_total{mode=\&amp;#34;idle\&amp;#34;}[5m])) by (instance)&amp;#34;
    }

    rule {
      alert    = &amp;#34;HighCPUUtilization&amp;#34;
      expr     = &amp;#34;instance:cpu_utilization:avg5m &amp;gt; 0.85&amp;#34;
      duration = &amp;#34;10m&amp;#34;

      labels = {
        severity = &amp;#34;warning&amp;#34;
        resource = &amp;#34;cpu&amp;#34;
      }

      annotations = {
        summary     = &amp;#34;High CPU utilization&amp;#34;
        description = &amp;#34;CPU utilization on {{ $labels.instance }} is above 85%&amp;#34;
      }
    }

    rule {
      alert    = &amp;#34;CriticalCPUUtilization&amp;#34;
      expr     = &amp;#34;instance:cpu_utilization:avg5m &amp;gt; 0.95&amp;#34;
      duration = &amp;#34;5m&amp;#34;

      labels = {
        severity = &amp;#34;critical&amp;#34;
        resource = &amp;#34;cpu&amp;#34;
      }

      annotations = {
        summary     = &amp;#34;Critical CPU utilization&amp;#34;
        description = &amp;#34;CPU utilization on {{ $labels.instance }} is above 95%&amp;#34;
      }
    }
  }

  group {
    name     = &amp;#34;memory_rules&amp;#34;
    interval = &amp;#34;30s&amp;#34;

    rule {
      record = &amp;#34;instance:memory_utilization:ratio&amp;#34;
      expr   = &amp;#34;1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)&amp;#34;
    }

    rule {
      alert    = &amp;#34;HighMemoryUtilization&amp;#34;
      expr     = &amp;#34;instance:memory_utilization:ratio &amp;gt; 0.85&amp;#34;
      duration = &amp;#34;10m&amp;#34;

      labels = {
        severity = &amp;#34;warning&amp;#34;
        resource = &amp;#34;memory&amp;#34;
      }

      annotations = {
        summary     = &amp;#34;High memory utilization&amp;#34;
        description = &amp;#34;Memory utilization on {{ $labels.instance }} is above 85%&amp;#34;
      }
    }
  }

  group {
    name     = &amp;#34;disk_rules&amp;#34;
    interval = &amp;#34;1m&amp;#34;

    rule {
      record = &amp;#34;instance:disk_utilization:ratio&amp;#34;
      expr   = &amp;#34;1 - (node_filesystem_avail_bytes{mountpoint=\&amp;#34;/\&amp;#34;} / node_filesystem_size_bytes{mountpoint=\&amp;#34;/\&amp;#34;})&amp;#34;
    }

    rule {
      alert    = &amp;#34;DiskSpaceLow&amp;#34;
      expr     = &amp;#34;instance:disk_utilization:ratio &amp;gt; 0.80&amp;#34;
      duration = &amp;#34;15m&amp;#34;

      labels = {
        severity = &amp;#34;warning&amp;#34;
        resource = &amp;#34;disk&amp;#34;
      }

      annotations = {
        summary     = &amp;#34;Disk space running low&amp;#34;
        description = &amp;#34;Disk utilization on {{ $labels.instance }} is above 80%&amp;#34;
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;create-kubernetes-specific-rules&#34;&gt;Create Kubernetes-specific rules&lt;/h2&gt;
&lt;p&gt;Define rules for monitoring Kubernetes workloads:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Kubernetes workload monitoring rules
resource &amp;#34;grafana_asserts_prom_rule_file&amp;#34; &amp;#34;kubernetes_rules&amp;#34; {
  provider = grafana.asserts

  name   = &amp;#34;kubernetes-workloads&amp;#34;
  active = true

  group {
    name     = &amp;#34;kubernetes_pod_rules&amp;#34;
    interval = &amp;#34;30s&amp;#34;

    rule {
      record = &amp;#34;namespace:pod_restarts:rate1h&amp;#34;
      expr   = &amp;#34;sum(increase(kube_pod_container_status_restarts_total[1h])) by (namespace)&amp;#34;
    }

    rule {
      alert    = &amp;#34;PodCrashLooping&amp;#34;
      expr     = &amp;#34;rate(kube_pod_container_status_restarts_total[15m]) * 60 * 15 &amp;gt; 3&amp;#34;
      duration = &amp;#34;5m&amp;#34;

      labels = {
        severity = &amp;#34;warning&amp;#34;
      }

      annotations = {
        summary     = &amp;#34;Pod is crash looping&amp;#34;
        description = &amp;#34;Pod {{ $labels.namespace }}/{{ $labels.pod }} is restarting frequently&amp;#34;
      }
    }

    rule {
      alert    = &amp;#34;PodNotReady&amp;#34;
      expr     = &amp;#34;kube_pod_status_ready{condition=\&amp;#34;true\&amp;#34;} == 0&amp;#34;
      duration = &amp;#34;10m&amp;#34;

      labels = {
        severity = &amp;#34;warning&amp;#34;
      }

      annotations = {
        summary     = &amp;#34;Pod not ready&amp;#34;
        description = &amp;#34;Pod {{ $labels.namespace }}/{{ $labels.pod }} has been in a non-ready state for more than 10 minutes&amp;#34;
      }
    }
  }

  group {
    name     = &amp;#34;kubernetes_deployment_rules&amp;#34;
    interval = &amp;#34;1m&amp;#34;

    rule {
      record = &amp;#34;deployment:replicas_unavailable:count&amp;#34;
      expr   = &amp;#34;kube_deployment_status_replicas_unavailable&amp;#34;
    }

    rule {
      alert    = &amp;#34;DeploymentReplicasMismatch&amp;#34;
      expr     = &amp;#34;kube_deployment_spec_replicas != kube_deployment_status_replicas_available&amp;#34;
      duration = &amp;#34;10m&amp;#34;

      labels = {
        severity = &amp;#34;warning&amp;#34;
      }

      annotations = {
        summary     = &amp;#34;Deployment replicas mismatch&amp;#34;
        description = &amp;#34;Deployment {{ $labels.namespace }}/{{ $labels.deployment }} has not matched the expected number of replicas for more than 10 minutes&amp;#34;
      }
    }
  }

  group {
    name     = &amp;#34;kubernetes_node_rules&amp;#34;
    interval = &amp;#34;1m&amp;#34;

    rule {
      alert    = &amp;#34;NodeNotReady&amp;#34;
      expr     = &amp;#34;kube_node_status_condition{condition=\&amp;#34;Ready\&amp;#34;,status=\&amp;#34;true\&amp;#34;} == 0&amp;#34;
      duration = &amp;#34;5m&amp;#34;

      labels = {
        severity = &amp;#34;critical&amp;#34;
      }

      annotations = {
        summary     = &amp;#34;Kubernetes node not ready&amp;#34;
        description = &amp;#34;Node {{ $labels.node }} has been unready for more than 5 minutes&amp;#34;
      }
    }

    rule {
      alert    = &amp;#34;NodeMemoryPressure&amp;#34;
      expr     = &amp;#34;kube_node_status_condition{condition=\&amp;#34;MemoryPressure\&amp;#34;,status=\&amp;#34;true\&amp;#34;} == 1&amp;#34;
      duration = &amp;#34;5m&amp;#34;

      labels = {
        severity = &amp;#34;warning&amp;#34;
      }

      annotations = {
        summary     = &amp;#34;Node under memory pressure&amp;#34;
        description = &amp;#34;Node {{ $labels.node }} is under memory pressure&amp;#34;
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;use-conditional-rule-disabling&#34;&gt;Use conditional rule disabling&lt;/h2&gt;
&lt;p&gt;Disable specific rules in certain groups using the &lt;code&gt;disable_in_groups&lt;/code&gt; field:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Rules with conditional disabling
resource &amp;#34;grafana_asserts_prom_rule_file&amp;#34; &amp;#34;conditional_rules&amp;#34; {
  provider = grafana.asserts

  name   = &amp;#34;conditional-alerting&amp;#34;
  active = true

  group {
    name     = &amp;#34;production_alerts&amp;#34;
    interval = &amp;#34;1m&amp;#34;

    rule {
      alert    = &amp;#34;HighErrorRate&amp;#34;
      expr     = &amp;#34;sum(rate(http_requests_total{code=~\&amp;#34;5..\&amp;#34;}[5m])) / sum(rate(http_requests_total[5m])) &amp;gt; 0.01&amp;#34;
      duration = &amp;#34;5m&amp;#34;

      labels = {
        severity    = &amp;#34;critical&amp;#34;
        environment = &amp;#34;production&amp;#34;
      }

      annotations = {
        summary     = &amp;#34;High error rate in production&amp;#34;
        description = &amp;#34;Error rate is above 1% for the last 5 minutes&amp;#34;
      }

      # Disable this rule in staging group
      disable_in_groups = [&amp;#34;staging_alerts&amp;#34;]
    }
  }

  group {
    name     = &amp;#34;staging_alerts&amp;#34;
    interval = &amp;#34;1m&amp;#34;

    rule {
      alert    = &amp;#34;HighErrorRate&amp;#34;
      expr     = &amp;#34;sum(rate(http_requests_total{code=~\&amp;#34;5..\&amp;#34;}[5m])) / sum(rate(http_requests_total[5m])) &amp;gt; 0.10&amp;#34;
      duration = &amp;#34;10m&amp;#34;

      labels = {
        severity    = &amp;#34;warning&amp;#34;
        environment = &amp;#34;staging&amp;#34;
      }

      annotations = {
        summary     = &amp;#34;High error rate in staging&amp;#34;
        description = &amp;#34;Error rate is above 10% for the last 10 minutes&amp;#34;
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;manage-inactive-rule-files&#34;&gt;Manage inactive rule files&lt;/h2&gt;
&lt;p&gt;Temporarily disable an entire rules file without deleting it:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Inactive rules file (not evaluated)
resource &amp;#34;grafana_asserts_prom_rule_file&amp;#34; &amp;#34;experimental_rules&amp;#34; {
  provider = grafana.asserts

  name   = &amp;#34;experimental-rules&amp;#34;
  active = false  # Rules are not evaluated

  group {
    name     = &amp;#34;experimental_alerts&amp;#34;
    interval = &amp;#34;1m&amp;#34;

    rule {
      alert    = &amp;#34;ExperimentalAlert&amp;#34;
      expr     = &amp;#34;some_experimental_metric &amp;gt; 100&amp;#34;
      duration = &amp;#34;5m&amp;#34;

      labels = {
        severity = &amp;#34;info&amp;#34;
      }

      annotations = {
        summary = &amp;#34;Experimental alert triggered&amp;#34;
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;resource-reference&#34;&gt;Resource reference&lt;/h2&gt;
&lt;h3 id=&#34;grafana_asserts_prom_rule_file&#34;&gt;&lt;code&gt;grafana_asserts_prom_rule_file&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Manage Prometheus recording and alerting rules through the Knowledge Graph API. This resource allows you to create and manage custom Prometheus rules that are evaluated against your metrics data.&lt;/p&gt;
&lt;h4 id=&#34;arguments&#34;&gt;Arguments&lt;/h4&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The name of the Prometheus rules file. This field is immutable and forces recreation if changed.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;active&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;bool&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Whether the rules file is active. Inactive rules are not evaluated. Defaults to &lt;code&gt;true&lt;/code&gt;.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;group&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(object)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;List of Prometheus rule groups. Refer to &lt;a href=&#34;#group-block&#34;&gt;group block&lt;/a&gt; for details.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;group-block&#34;&gt;Group block&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;group&lt;/code&gt; block contains a set of related rules with a shared evaluation interval:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The name of the rule group (for example, &lt;code&gt;latency_monitoring&lt;/code&gt;).&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;interval&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Evaluation interval for this group (for example, &lt;code&gt;30s&lt;/code&gt;, &lt;code&gt;1m&lt;/code&gt;). If not specified, uses the global evaluation interval.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;rule&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(object)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;List of Prometheus rules in this group. Refer to &lt;a href=&#34;#rule-block&#34;&gt;rule block&lt;/a&gt; for details.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;rule-block&#34;&gt;Rule block&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;rule&lt;/code&gt; block defines a recording or alerting rule. Either &lt;code&gt;record&lt;/code&gt; or &lt;code&gt;alert&lt;/code&gt; must be specified, but not both:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;record&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Conditional&lt;/td&gt;
              &lt;td&gt;The name of the time series to output for recording rules. Required if &lt;code&gt;alert&lt;/code&gt; is not specified.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;alert&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Conditional&lt;/td&gt;
              &lt;td&gt;The name of the alert for alerting rules. Required if &lt;code&gt;record&lt;/code&gt; is not specified.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;expr&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The PromQL expression to evaluate.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;duration&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;How long the condition must be true before firing the alert (for example, &lt;code&gt;5m&lt;/code&gt;). Only for alerting rules. Maps to &lt;code&gt;for&lt;/code&gt; in Prometheus.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;labels&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;map(string)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Labels to attach to the resulting time series or alert.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;annotations&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;map(string)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Annotations to add to alerts (for example, &lt;code&gt;summary&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;). Only applicable for alerting rules.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;disable_in_groups&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;set(string)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;List of group names where this rule should be disabled. Useful for conditional rule enablement.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;example&#34;&gt;Example&lt;/h4&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_asserts_prom_rule_file&amp;#34; &amp;#34;example&amp;#34; {
  provider = grafana.asserts

  name   = &amp;#34;example-rules&amp;#34;
  active = true

  group {
    name     = &amp;#34;example_group&amp;#34;
    interval = &amp;#34;1m&amp;#34;

    # Recording rule
    rule {
      record = &amp;#34;job:http_requests:rate5m&amp;#34;
      expr   = &amp;#34;sum(rate(http_requests_total[5m])) by (job)&amp;#34;
    }

    # Alerting rule
    rule {
      alert    = &amp;#34;HighErrorRate&amp;#34;
      expr     = &amp;#34;job:http_errors:rate5m &amp;gt; 0.05&amp;#34;
      duration = &amp;#34;5m&amp;#34;

      labels = {
        severity = &amp;#34;critical&amp;#34;
      }

      annotations = {
        summary     = &amp;#34;High error rate detected&amp;#34;
        description = &amp;#34;Error rate for {{ $labels.job }} is above 5%&amp;#34;
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;best-practices&#34;&gt;Best practices&lt;/h2&gt;
&lt;p&gt;Consider the following best practices when managing Prometheus rules with Terraform.&lt;/p&gt;
&lt;h3 id=&#34;rule-organization&#34;&gt;Rule organization&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Group related rules together in the same rule group&lt;/li&gt;
&lt;li&gt;Use descriptive names for rules that indicate their purpose&lt;/li&gt;
&lt;li&gt;Separate recording rules from alerting rules into different groups when they have different evaluation needs&lt;/li&gt;
&lt;li&gt;Use consistent naming conventions for recorded metrics, such as &lt;code&gt;level:metric:operation&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;recording-rules&#34;&gt;Recording rules&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Use recording rules for expensive queries that are run frequently&lt;/li&gt;
&lt;li&gt;Pre-compute aggregations that are used by multiple dashboards or alerts&lt;/li&gt;
&lt;li&gt;Choose appropriate evaluation intervals based on how frequently the data changes&lt;/li&gt;
&lt;li&gt;Follow Prometheus naming conventions, such as &lt;code&gt;job:metric:aggregation&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;alerting-rules&#34;&gt;Alerting rules&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Set appropriate &lt;code&gt;duration&lt;/code&gt; values to avoid flapping alerts&lt;/li&gt;
&lt;li&gt;Include meaningful labels like &lt;code&gt;severity&lt;/code&gt; and &lt;code&gt;team&lt;/code&gt; for routing&lt;/li&gt;
&lt;li&gt;Provide comprehensive annotations including &lt;code&gt;summary&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, and &lt;code&gt;runbook_url&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Use template variables in annotations such as &lt;code&gt;{{ $labels.job }}&lt;/code&gt; to provide context&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;performance-considerations&#34;&gt;Performance considerations&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Avoid overly complex PromQL expressions that may timeout&lt;/li&gt;
&lt;li&gt;Use appropriate evaluation intervals; don&amp;rsquo;t evaluate faster than needed&lt;/li&gt;
&lt;li&gt;Test your PromQL queries in Grafana before adding them to Terraform&lt;/li&gt;
&lt;li&gt;Consider the cardinality impact of recording rules that create new time series&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;testing-and-validation&#34;&gt;Testing and validation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Test rules in a non-production environment before deploying to production&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;active = false&lt;/code&gt; flag to stage rules without evaluating them&lt;/li&gt;
&lt;li&gt;Monitor the performance impact of new rules after deployment&lt;/li&gt;
&lt;li&gt;Review and prune unused rules periodically&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;validation&#34;&gt;Validation&lt;/h2&gt;
&lt;p&gt;After applying the Terraform configuration, verify that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rule files are created and visible in the Knowledge Graph rules configuration&lt;/li&gt;
&lt;li&gt;Recording rules are generating the expected time series&lt;/li&gt;
&lt;li&gt;Alerting rules are evaluating correctly&lt;/li&gt;
&lt;li&gt;Alert thresholds trigger notifications as expected&lt;/li&gt;
&lt;li&gt;Rule evaluation times are within acceptable ranges&lt;/li&gt;
&lt;li&gt;No errors appear in the rule evaluation logs&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;troubleshooting&#34;&gt;Troubleshooting&lt;/h2&gt;
&lt;h3 id=&#34;rules-not-being-evaluated&#34;&gt;Rules not being evaluated&lt;/h3&gt;
&lt;p&gt;If your rules are not being evaluated:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Verify that &lt;code&gt;active = true&lt;/code&gt; is set on the rule file&lt;/li&gt;
&lt;li&gt;Check that the rule filename follows naming validation rules (alphanumeric, hyphens, underscores)&lt;/li&gt;
&lt;li&gt;Ensure the PromQL expression is valid by testing it in Grafana&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;recording-rule-not-producing-data&#34;&gt;Recording rule not producing data&lt;/h3&gt;
&lt;p&gt;If a recording rule is not producing data:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Verify the source metrics exist and have data&lt;/li&gt;
&lt;li&gt;Check the PromQL expression returns results&lt;/li&gt;
&lt;li&gt;Ensure the evaluation interval is appropriate&lt;/li&gt;
&lt;li&gt;Review the rule evaluation logs for errors&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;alerts-not-firing&#34;&gt;Alerts not firing&lt;/h3&gt;
&lt;p&gt;If alerting rules are not firing:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Verify the condition is actually met by querying the expression manually&lt;/li&gt;
&lt;li&gt;Check that the &lt;code&gt;duration&lt;/code&gt; period has elapsed&lt;/li&gt;
&lt;li&gt;Ensure the alerting system is properly configured to receive alerts&lt;/li&gt;
&lt;li&gt;Review annotation templates for syntax errors&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;import-error-when-recreating-rules&#34;&gt;Import error when recreating rules&lt;/h3&gt;
&lt;p&gt;If you receive errors when recreating rules:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;name&lt;/code&gt; field is immutable and forces recreation if changed&lt;/li&gt;
&lt;li&gt;Ensure no conflicting rule files exist with the same name&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;terraform import&lt;/code&gt; to import existing resources if needed&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;related-documentation&#34;&gt;Related documentation&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;../getting-started/&#34;&gt;Get started with Terraform for Knowledge Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../custom-model-rules/&#34;&gt;Create custom model rules using Terraform&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Prometheus recording rules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Prometheus alerting rules&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="manage-prometheus-rules-using-terraform">Manage Prometheus rules using Terraform&lt;/h1>
&lt;p>Prometheus rules in the &lt;a href="/docs/grafana-cloud/knowledge-graph/">Knowledge Graph&lt;/a> allow you to define custom recording and alerting rules that are evaluated against your metrics data. Recording rules pre-compute frequently used or computationally expensive expressions and save the results as new time series. Alerting rules define conditions that, when met, trigger alerts.&lt;/p></description></item><item><title>Configure log correlation using Terraform</title><link>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/log-configurations/</link><pubDate>Fri, 03 Apr 2026 19:43:06 +0000</pubDate><guid>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/log-configurations/</guid><content><![CDATA[&lt;h1 id=&#34;configure-log-correlation-using-terraform&#34;&gt;Configure log correlation using Terraform&lt;/h1&gt;
&lt;p&gt;Log configurations in &lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/&#34;&gt;Knowledge Graph&lt;/a&gt; allow you to define how log data is queried and correlated with entities. You can specify data sources, entity matching rules, label mappings, and filtering options for spans and traces.&lt;/p&gt;
&lt;p&gt;For information about configuring log correlation in the Knowledge Graph UI, refer to &lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/configure/logs-correlation/&#34;&gt;Configure logs correlation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;basic-log-configuration&#34;&gt;Basic log configuration&lt;/h2&gt;
&lt;p&gt;Create a file named &lt;code&gt;log-configs.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Basic log configuration for services
resource &amp;#34;grafana_asserts_log_config&amp;#34; &amp;#34;production&amp;#34; {
  provider = grafana.asserts

  name            = &amp;#34;production&amp;#34;
  priority        = 1000
  default_config  = false
  data_source_uid = &amp;#34;grafanacloud-logs&amp;#34;
  error_label     = &amp;#34;error&amp;#34;

  match {
    property = &amp;#34;asserts_entity_type&amp;#34;
    op       = &amp;#34;EQUALS&amp;#34;
    values   = [&amp;#34;Service&amp;#34;]
  }

  match {
    property = &amp;#34;environment&amp;#34;
    op       = &amp;#34;EQUALS&amp;#34;
    values   = [&amp;#34;production&amp;#34;, &amp;#34;staging&amp;#34;]
  }

  entity_property_to_log_label_mapping = {
    &amp;#34;otel_namespace&amp;#34; = &amp;#34;service_namespace&amp;#34;
    &amp;#34;otel_service&amp;#34;   = &amp;#34;service_name&amp;#34;
    &amp;#34;environment&amp;#34;    = &amp;#34;env&amp;#34;
    &amp;#34;site&amp;#34;           = &amp;#34;region&amp;#34;
  }

  filter_by_span_id  = true
  filter_by_trace_id = true
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;log-configuration-with-multiple-match-rules&#34;&gt;Log configuration with multiple match rules&lt;/h2&gt;
&lt;p&gt;Configure log correlation with multiple entity matching criteria:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Development environment log configuration
resource &amp;#34;grafana_asserts_log_config&amp;#34; &amp;#34;development&amp;#34; {
  provider = grafana.asserts

  name            = &amp;#34;development&amp;#34;
  priority        = 2000
  default_config  = true
  data_source_uid = &amp;#34;elasticsearch-dev&amp;#34;
  error_label     = &amp;#34;error&amp;#34;

  match {
    property = &amp;#34;asserts_entity_type&amp;#34;
    op       = &amp;#34;EQUALS&amp;#34;
    values   = [&amp;#34;Service&amp;#34;]
  }

  match {
    property = &amp;#34;environment&amp;#34;
    op       = &amp;#34;EQUALS&amp;#34;
    values   = [&amp;#34;development&amp;#34;, &amp;#34;testing&amp;#34;]
  }

  match {
    property = &amp;#34;site&amp;#34;
    op       = &amp;#34;EQUALS&amp;#34;
    values   = [&amp;#34;us-east-1&amp;#34;]
  }

  match {
    property = &amp;#34;service&amp;#34;
    op       = &amp;#34;EQUALS&amp;#34;
    values   = [&amp;#34;api&amp;#34;]
  }

  entity_property_to_log_label_mapping = {
    &amp;#34;otel_namespace&amp;#34; = &amp;#34;service_namespace&amp;#34;
    &amp;#34;otel_service&amp;#34;   = &amp;#34;service_name&amp;#34;
    &amp;#34;environment&amp;#34;    = &amp;#34;env&amp;#34;
    &amp;#34;site&amp;#34;           = &amp;#34;region&amp;#34;
    &amp;#34;service&amp;#34;        = &amp;#34;app&amp;#34;
  }

  filter_by_span_id  = true
  filter_by_trace_id = true
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;minimal-log-configuration&#34;&gt;Minimal log configuration&lt;/h2&gt;
&lt;p&gt;Create a minimal configuration for all entities:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Minimal configuration for all entities
resource &amp;#34;grafana_asserts_log_config&amp;#34; &amp;#34;minimal&amp;#34; {
  provider = grafana.asserts

  name            = &amp;#34;minimal&amp;#34;
  priority        = 3000
  default_config  = false
  data_source_uid = &amp;#34;loki-minimal&amp;#34;

  match {
    property = &amp;#34;asserts_entity_type&amp;#34;
    op       = &amp;#34;IS_NOT_NULL&amp;#34;
    values   = []
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;advanced-log-configuration-with-complex-match-rules&#34;&gt;Advanced log configuration with complex match rules&lt;/h2&gt;
&lt;p&gt;Configure logs with multiple operations and advanced match rules:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Advanced configuration with multiple operations
resource &amp;#34;grafana_asserts_log_config&amp;#34; &amp;#34;advanced&amp;#34; {
  provider = grafana.asserts

  name            = &amp;#34;advanced&amp;#34;
  priority        = 1500
  default_config  = false
  data_source_uid = &amp;#34;loki-advanced&amp;#34;
  error_label     = &amp;#34;level&amp;#34;

  match {
    property = &amp;#34;service_type&amp;#34;
    op       = &amp;#34;CONTAINS&amp;#34;
    values   = [&amp;#34;web&amp;#34;, &amp;#34;api&amp;#34;]
  }

  match {
    property = &amp;#34;environment&amp;#34;
    op       = &amp;#34;NOT_EQUALS&amp;#34;
    values   = [&amp;#34;test&amp;#34;]
  }

  match {
    property = &amp;#34;team&amp;#34;
    op       = &amp;#34;IS_NOT_NULL&amp;#34;
    values   = []
  }

  entity_property_to_log_label_mapping = {
    &amp;#34;service_type&amp;#34;   = &amp;#34;type&amp;#34;
    &amp;#34;team&amp;#34;           = &amp;#34;owner&amp;#34;
    &amp;#34;environment&amp;#34;    = &amp;#34;env&amp;#34;
    &amp;#34;version&amp;#34;        = &amp;#34;app_version&amp;#34;
  }

  filter_by_span_id  = true
  filter_by_trace_id = false
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;resource-reference&#34;&gt;Resource reference&lt;/h2&gt;
&lt;h3 id=&#34;grafana_asserts_log_config&#34;&gt;&lt;code&gt;grafana_asserts_log_config&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Manage Knowledge Graph log configurations through the Grafana API.&lt;/p&gt;
&lt;h4 id=&#34;arguments&#34;&gt;Arguments&lt;/h4&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The name of the log configuration. This field is immutable and forces recreation if changed.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;priority&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Priority of the log configuration. Higher priority configurations are evaluated first.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;default_config&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;bool&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Whether this is the default configuration. Default configurations cannot be deleted.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;data_source_uid&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;DataSource UID to be queried (for example, a Loki instance).&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;match&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(object)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;List of match rules for entity properties. Refer to &lt;a href=&#34;#match-block&#34;&gt;match block&lt;/a&gt; for details.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;error_label&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Label name used to identify error logs.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;entity_property_to_log_label_mapping&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;map(string)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Mapping of entity properties to log labels for correlation.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;filter_by_span_id&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;bool&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Whether to filter logs by span ID for distributed tracing correlation.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;filter_by_trace_id&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;bool&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Whether to filter logs by trace ID for distributed tracing correlation.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;match-block&#34;&gt;Match block&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;match&lt;/code&gt; block supports the following:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;property&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Entity property to match against.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;op&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Operation to use for matching. One of: &lt;code&gt;EQUALS&lt;/code&gt;, &lt;code&gt;NOT_EQUALS&lt;/code&gt;, &lt;code&gt;CONTAINS&lt;/code&gt;, &lt;code&gt;DOES_NOT_CONTAIN&lt;/code&gt;, &lt;code&gt;IS_NULL&lt;/code&gt;, &lt;code&gt;IS_NOT_NULL&lt;/code&gt;.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;values&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(string)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Values to match against. Can be empty for &lt;code&gt;IS_NULL&lt;/code&gt; and &lt;code&gt;IS_NOT_NULL&lt;/code&gt; operations.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;example&#34;&gt;Example&lt;/h4&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_asserts_log_config&amp;#34; &amp;#34;example&amp;#34; {
  provider = grafana.asserts

  name            = &amp;#34;example-logs&amp;#34;
  priority        = 1000
  default_config  = false
  data_source_uid = &amp;#34;loki-prod&amp;#34;
  error_label     = &amp;#34;level&amp;#34;

  match {
    property = &amp;#34;asserts_entity_type&amp;#34;
    op       = &amp;#34;EQUALS&amp;#34;
    values   = [&amp;#34;Service&amp;#34;, &amp;#34;Pod&amp;#34;]
  }

  entity_property_to_log_label_mapping = {
    &amp;#34;service&amp;#34;     = &amp;#34;app&amp;#34;
    &amp;#34;namespace&amp;#34;   = &amp;#34;k8s_namespace&amp;#34;
    &amp;#34;environment&amp;#34; = &amp;#34;env&amp;#34;
  }

  filter_by_span_id  = true
  filter_by_trace_id = true
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;best-practices&#34;&gt;Best practices&lt;/h2&gt;
&lt;p&gt;Consider the following best practices when configuring log correlation with Terraform.&lt;/p&gt;
&lt;h3 id=&#34;priority-management&#34;&gt;Priority management&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Assign lower priority numbers to more specific configurations&lt;/li&gt;
&lt;li&gt;Higher priority configurations are evaluated first&lt;/li&gt;
&lt;li&gt;Use consistent priority ranges for different configuration types&lt;/li&gt;
&lt;li&gt;Document the reasoning behind priority assignments&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;data-source-configuration&#34;&gt;Data source configuration&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Ensure the data source UID matches your actual Loki or log aggregation system&lt;/li&gt;
&lt;li&gt;Test data source connectivity before applying configurations&lt;/li&gt;
&lt;li&gt;Use descriptive names for log configurations to indicate their purpose&lt;/li&gt;
&lt;li&gt;Consider using separate data sources for different environments&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;label-map-strategy&#34;&gt;Label map strategy&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Map entity properties consistently across all log configurations&lt;/li&gt;
&lt;li&gt;Use meaningful log label names that match your logging standards&lt;/li&gt;
&lt;li&gt;Document the mapping relationships in configuration comments&lt;/li&gt;
&lt;li&gt;Verify that mapped labels exist in your log data&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;match-rules-design&#34;&gt;Match rules design&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Start with broad match rules and refine based on needs&lt;/li&gt;
&lt;li&gt;Use specific property names that exist in your entity model&lt;/li&gt;
&lt;li&gt;Test match rules with sample data before deploying&lt;/li&gt;
&lt;li&gt;Combine multiple match rules for precise entity targeting&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;distributed-trace-integration&#34;&gt;Distributed trace integration&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Enable &lt;code&gt;filter_by_span_id&lt;/code&gt; and &lt;code&gt;filter_by_trace_id&lt;/code&gt; when using OpenTelemetry&lt;/li&gt;
&lt;li&gt;Ensure your logs contain the appropriate trace and span ID labels&lt;/li&gt;
&lt;li&gt;Use consistent label names for trace IDs across your logging infrastructure&lt;/li&gt;
&lt;li&gt;Test trace correlation to verify it works as expected&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;validation&#34;&gt;Validation&lt;/h2&gt;
&lt;p&gt;After applying the Terraform configuration, verify that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Log configurations are created in your Knowledge Graph instance&lt;/li&gt;
&lt;li&gt;Configurations appear in the Knowledge Graph UI under &lt;strong&gt;Observability &amp;gt; Configuration &amp;gt; Logs&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Log correlation works when drilling down from entities&lt;/li&gt;
&lt;li&gt;Label mappings correctly translate entity properties to log labels&lt;/li&gt;
&lt;li&gt;Match rules properly filter entities&lt;/li&gt;
&lt;li&gt;Trace and span ID filtering works for distributed tracing&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;related-documentation&#34;&gt;Related documentation&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/configure/logs-correlation/&#34;&gt;Configure logs correlation in Knowledge Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../getting-started/&#34;&gt;Get started with Terraform for Knowledge Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/loki/latest/&#34;&gt;Loki documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="configure-log-correlation-using-terraform">Configure log correlation using Terraform&lt;/h1>
&lt;p>Log configurations in &lt;a href="/docs/grafana-cloud/knowledge-graph/">Knowledge Graph&lt;/a> allow you to define how log data is queried and correlated with entities. You can specify data sources, entity matching rules, label mappings, and filtering options for spans and traces.&lt;/p></description></item><item><title>Configure thresholds using Terraform</title><link>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/thresholds/</link><pubDate>Fri, 03 Apr 2026 19:43:06 +0000</pubDate><guid>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/thresholds/</guid><content><![CDATA[&lt;h1 id=&#34;configure-thresholds-using-terraform&#34;&gt;Configure thresholds using Terraform&lt;/h1&gt;
&lt;p&gt;Threshold configurations in &lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/&#34;&gt;Knowledge Graph&lt;/a&gt; allow you to define custom thresholds for request, resource, and health assertions. These configurations help you set specific limits and conditions for monitoring your services and infrastructure.&lt;/p&gt;
&lt;p&gt;For information about managing thresholds in the Knowledge Graph UI, refer to &lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/configure/manage-thresholds/&#34;&gt;Manage thresholds&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;basic-threshold-configuration&#34;&gt;Basic threshold configuration&lt;/h2&gt;
&lt;p&gt;Create a file named &lt;code&gt;thresholds.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Basic threshold configuration with all three types
resource &amp;#34;grafana_asserts_thresholds&amp;#34; &amp;#34;basic&amp;#34; {
  provider = grafana.asserts

  request_thresholds = [{
    entity_name     = &amp;#34;payment-service&amp;#34;
    assertion_name  = &amp;#34;ErrorRatioBreach&amp;#34;
    request_type    = &amp;#34;inbound&amp;#34;
    request_context = &amp;#34;/charge&amp;#34;
    value           = 0.01
  }]

  resource_thresholds = [{
    assertion_name = &amp;#34;Saturation&amp;#34;
    resource_type  = &amp;#34;container&amp;#34;
    container_name = &amp;#34;worker&amp;#34;
    source         = &amp;#34;metrics&amp;#34;
    severity       = &amp;#34;warning&amp;#34;
    value          = 75
  }]

  health_thresholds = [{
    assertion_name = &amp;#34;ServiceDown&amp;#34;
    expression     = &amp;#34;up &amp;lt; 1&amp;#34;
    entity_type    = &amp;#34;Service&amp;#34;
  }]
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;request-threshold-configurations&#34;&gt;Request threshold configurations&lt;/h2&gt;
&lt;p&gt;Configure thresholds for different service request types and contexts:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Multiple request thresholds for different services
resource &amp;#34;grafana_asserts_thresholds&amp;#34; &amp;#34;request_thresholds&amp;#34; {
  provider = grafana.asserts

  request_thresholds = [
    {
      entity_name     = &amp;#34;api-service&amp;#34;
      assertion_name  = &amp;#34;ErrorRatioBreach&amp;#34;
      request_type    = &amp;#34;inbound&amp;#34;
      request_context = &amp;#34;/api/v1/users&amp;#34;
      value           = 0.02
    },
    {
      entity_name     = &amp;#34;api-service&amp;#34;
      assertion_name  = &amp;#34;LatencyP99ErrorBuildup&amp;#34;
      request_type    = &amp;#34;inbound&amp;#34;
      request_context = &amp;#34;/api/v1/orders&amp;#34;
      value           = 500
    },
    {
      entity_name     = &amp;#34;payment-gateway&amp;#34;
      assertion_name  = &amp;#34;RequestRateAnomaly&amp;#34;
      request_type    = &amp;#34;outbound&amp;#34;
      request_context = &amp;#34;/payment/process&amp;#34;
      value           = 1000
    }
  ]
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;resource-threshold-configurations&#34;&gt;Resource threshold configurations&lt;/h2&gt;
&lt;p&gt;Define resource thresholds for different severity levels:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Resource thresholds for different severity levels
resource &amp;#34;grafana_asserts_thresholds&amp;#34; &amp;#34;resource_thresholds&amp;#34; {
  provider = grafana.asserts

  resource_thresholds = [
    {
      assertion_name = &amp;#34;Saturation&amp;#34;
      resource_type  = &amp;#34;container&amp;#34;
      container_name = &amp;#34;web-server&amp;#34;
      source         = &amp;#34;metrics&amp;#34;
      severity       = &amp;#34;warning&amp;#34;
      value          = 75
    },
    {
      assertion_name = &amp;#34;Saturation&amp;#34;
      resource_type  = &amp;#34;container&amp;#34;
      container_name = &amp;#34;web-server&amp;#34;
      source         = &amp;#34;metrics&amp;#34;
      severity       = &amp;#34;critical&amp;#34;
      value          = 90
    },
    {
      assertion_name = &amp;#34;ResourceRateBreach&amp;#34;
      resource_type  = &amp;#34;Pod&amp;#34;
      container_name = &amp;#34;database&amp;#34;
      source         = &amp;#34;logs&amp;#34;
      severity       = &amp;#34;warning&amp;#34;
      value          = 80
    }
  ]
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;health-threshold-configurations&#34;&gt;Health threshold configurations&lt;/h2&gt;
&lt;p&gt;Configure health checks with Prometheus expressions:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Health thresholds with Prometheus expressions
resource &amp;#34;grafana_asserts_thresholds&amp;#34; &amp;#34;health_thresholds&amp;#34; {
  provider = grafana.asserts

  health_thresholds = [
    {
      assertion_name = &amp;#34;ServiceDown&amp;#34;
      expression     = &amp;#34;up{job=\&amp;#34;api-service\&amp;#34;} &amp;lt; 1&amp;#34;
      entity_type    = &amp;#34;Service&amp;#34;
    },
    {
      assertion_name = &amp;#34;HighMemoryUsage&amp;#34;
      expression     = &amp;#34;memory_usage_percent &amp;gt; 85&amp;#34;
      entity_type    = &amp;#34;Service&amp;#34;
    },
    {
      assertion_name = &amp;#34;DatabaseConnectivity&amp;#34;
      expression     = &amp;#34;db_connection_pool_active / db_connection_pool_max &amp;gt; 0.9&amp;#34;
      entity_type    = &amp;#34;Service&amp;#34;
    }
  ]
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;comprehensive-threshold-configuration&#34;&gt;Comprehensive threshold configuration&lt;/h2&gt;
&lt;p&gt;Define comprehensive thresholds for production environments:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Production environment with comprehensive thresholds
resource &amp;#34;grafana_asserts_thresholds&amp;#34; &amp;#34;production&amp;#34; {
  provider = grafana.asserts

  request_thresholds = [
    {
      entity_name     = &amp;#34;frontend&amp;#34;
      assertion_name  = &amp;#34;ErrorRatioBreach&amp;#34;
      request_type    = &amp;#34;inbound&amp;#34;
      request_context = &amp;#34;/&amp;#34;
      value           = 0.005
    },
    {
      entity_name     = &amp;#34;backend-api&amp;#34;
      assertion_name  = &amp;#34;LatencyP99ErrorBuildup&amp;#34;
      request_type    = &amp;#34;inbound&amp;#34;
      request_context = &amp;#34;/api&amp;#34;
      value           = 200
    }
  ]

  resource_thresholds = [
    {
      assertion_name = &amp;#34;Saturation&amp;#34;
      resource_type  = &amp;#34;container&amp;#34;
      container_name = &amp;#34;frontend&amp;#34;
      source         = &amp;#34;metrics&amp;#34;
      severity       = &amp;#34;warning&amp;#34;
      value          = 70
    },
    {
      assertion_name = &amp;#34;Saturation&amp;#34;
      resource_type  = &amp;#34;container&amp;#34;
      container_name = &amp;#34;backend-api&amp;#34;
      source         = &amp;#34;metrics&amp;#34;
      severity       = &amp;#34;critical&amp;#34;
      value          = 85
    }
  ]

  health_thresholds = [
    {
      assertion_name = &amp;#34;ServiceDown&amp;#34;
      expression     = &amp;#34;up &amp;lt; 1&amp;#34;
      entity_type    = &amp;#34;Service&amp;#34;
    },
    {
      assertion_name = &amp;#34;NodeDown&amp;#34;
      expression     = &amp;#34;up{job=\&amp;#34;node-exporter\&amp;#34;} &amp;lt; 1&amp;#34;
      entity_type    = &amp;#34;Service&amp;#34;
    }
  ]
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;resource-reference&#34;&gt;Resource reference&lt;/h2&gt;
&lt;h3 id=&#34;grafana_asserts_thresholds&#34;&gt;&lt;code&gt;grafana_asserts_thresholds&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Manage Knowledge Graph threshold configurations through the Grafana API. This resource allows you to define custom thresholds for request, resource, and health assertions.&lt;/p&gt;
&lt;h4 id=&#34;arguments&#34;&gt;Arguments&lt;/h4&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;request_thresholds&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(object)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;List of request threshold configurations. Refer to &lt;a href=&#34;#request-thresholds-block&#34;&gt;request thresholds block&lt;/a&gt; for details.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;resource_thresholds&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(object)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;List of resource threshold configurations. Refer to &lt;a href=&#34;#resource-thresholds-block&#34;&gt;resource thresholds block&lt;/a&gt; for details.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;health_thresholds&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(object)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;List of health threshold configurations. Refer to &lt;a href=&#34;#health-thresholds-block&#34;&gt;health thresholds block&lt;/a&gt; for details.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;request-thresholds-block&#34;&gt;Request thresholds block&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;request_thresholds&lt;/code&gt; block supports the following:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;entity_name&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The name of the entity to apply the threshold to.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;assertion_name&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The name of the assertion to configure.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;request_type&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The type of request (inbound, outbound).&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;request_context&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The request context or path to apply the threshold to.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;value&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The threshold value.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;resource-thresholds-block&#34;&gt;Resource thresholds block&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;resource_thresholds&lt;/code&gt; block supports the following:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;assertion_name&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The name of the assertion to configure.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;resource_type&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The type of resource (container, Pod, node).&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;container_name&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The name of the container to apply the threshold to.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;source&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The source of the metrics (metrics, logs).&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;severity&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The severity level (warning, critical).&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;value&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The threshold value.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;health-thresholds-block&#34;&gt;Health thresholds block&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;health_thresholds&lt;/code&gt; block supports the following:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;assertion_name&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The name of the assertion to configure.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;expression&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The Prometheus expression for the health check.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;entity_type&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Entity type for the health threshold (for example, Service, Pod, Namespace, Volume).&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;alert_category&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Optional alert category label for the health threshold.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;example&#34;&gt;Example&lt;/h4&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_asserts_thresholds&amp;#34; &amp;#34;example&amp;#34; {
  provider = grafana.asserts

  request_thresholds = [{
    entity_name     = &amp;#34;api-service&amp;#34;
    assertion_name  = &amp;#34;ErrorRatioBreach&amp;#34;
    request_type    = &amp;#34;inbound&amp;#34;
    request_context = &amp;#34;/api/v1/users&amp;#34;
    value           = 0.02
  }]

  resource_thresholds = [{
    assertion_name = &amp;#34;Saturation&amp;#34;
    resource_type  = &amp;#34;container&amp;#34;
    container_name = &amp;#34;web-server&amp;#34;
    source         = &amp;#34;metrics&amp;#34;
    severity       = &amp;#34;warning&amp;#34;
    value          = 75
  }]

  health_thresholds = [{
    assertion_name = &amp;#34;ServiceDown&amp;#34;
    expression     = &amp;#34;up{job=\&amp;#34;api-service\&amp;#34;} &amp;lt; 1&amp;#34;
    entity_type    = &amp;#34;Service&amp;#34;
  }]
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;best-practices&#34;&gt;Best practices&lt;/h2&gt;
&lt;p&gt;Consider the following best practices when configuring thresholds with Terraform.&lt;/p&gt;
&lt;h3 id=&#34;threshold-configuration-management&#34;&gt;Threshold configuration management&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Set appropriate threshold values based on your service level objectives (SLOs)&lt;/li&gt;
&lt;li&gt;Use different severity levels (warning, critical) to create escalation paths&lt;/li&gt;
&lt;li&gt;Test threshold configurations in non-production environments first&lt;/li&gt;
&lt;li&gt;Monitor threshold effectiveness and adjust values based on actual performance data&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;request-threshold-best-practices&#34;&gt;Request threshold best practices&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Configure request thresholds for critical user-facing endpoints&lt;/li&gt;
&lt;li&gt;Set different thresholds for different request types (inbound vs outbound)&lt;/li&gt;
&lt;li&gt;Consider request context when setting thresholds for specific API paths&lt;/li&gt;
&lt;li&gt;Use error ratio thresholds to catch service degradation early&lt;/li&gt;
&lt;li&gt;Review historical performance data to set realistic threshold values&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;resource-threshold-best-practices&#34;&gt;Resource threshold best practices&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Set resource thresholds based on your infrastructure capacity&lt;/li&gt;
&lt;li&gt;Use container-specific thresholds for microservices architectures&lt;/li&gt;
&lt;li&gt;Configure both warning and critical thresholds for gradual escalation&lt;/li&gt;
&lt;li&gt;Monitor resource utilization patterns to set realistic threshold values&lt;/li&gt;
&lt;li&gt;Consider seasonal or periodic patterns in resource usage&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;health-threshold-best-practices&#34;&gt;Health threshold best practices&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Use Prometheus expressions that accurately reflect service health&lt;/li&gt;
&lt;li&gt;Test health check expressions independently before applying them&lt;/li&gt;
&lt;li&gt;Set up health thresholds for critical dependencies and external services&lt;/li&gt;
&lt;li&gt;Use composite expressions for complex health checks&lt;/li&gt;
&lt;li&gt;Ensure expressions perform efficiently without causing excessive load&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;value-selection-guidelines&#34;&gt;Value selection guidelines&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Start conservative and adjust based on real-world performance&lt;/li&gt;
&lt;li&gt;Use percentages (0-1 range) for ratio-based metrics&lt;/li&gt;
&lt;li&gt;Use milliseconds for latency thresholds&lt;/li&gt;
&lt;li&gt;Document the reasoning behind specific threshold values&lt;/li&gt;
&lt;li&gt;Review and update thresholds regularly based on system evolution&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;validation&#34;&gt;Validation&lt;/h2&gt;
&lt;p&gt;After applying the Terraform configuration, verify that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Threshold configurations are applied in your Knowledge Graph instance&lt;/li&gt;
&lt;li&gt;Configurations appear in the Knowledge Graph UI under &lt;strong&gt;Observability &amp;gt; Rules &amp;gt; Threshold&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Request thresholds correctly identify breaches for specified services&lt;/li&gt;
&lt;li&gt;Resource thresholds trigger at appropriate severity levels&lt;/li&gt;
&lt;li&gt;Health thresholds accurately reflect service status&lt;/li&gt;
&lt;li&gt;Threshold values align with your SLO commitments&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;related-documentation&#34;&gt;Related documentation&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/configure/manage-thresholds/&#34;&gt;Manage thresholds in Knowledge Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../getting-started/&#34;&gt;Get started with Terraform for Knowledge Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/configure/alerts/&#34;&gt;Configure alerts in Knowledge Graph&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="configure-thresholds-using-terraform">Configure thresholds using Terraform&lt;/h1>
&lt;p>Threshold configurations in &lt;a href="/docs/grafana-cloud/knowledge-graph/">Knowledge Graph&lt;/a> allow you to define custom thresholds for request, resource, and health assertions. These configurations help you set specific limits and conditions for monitoring your services and infrastructure.&lt;/p></description></item><item><title>Configure trace correlation using Terraform</title><link>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/trace-configurations/</link><pubDate>Fri, 03 Apr 2026 19:43:06 +0000</pubDate><guid>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/trace-configurations/</guid><content><![CDATA[&lt;h1 id=&#34;configure-trace-correlation-using-terraform&#34;&gt;Configure trace correlation using Terraform&lt;/h1&gt;
&lt;p&gt;Trace configurations in &lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/&#34;&gt;Knowledge Graph&lt;/a&gt; allow you to define how trace data is queried and correlated with entities. You can specify data sources, entity matching rules, and label mappings for distributed tracing.&lt;/p&gt;
&lt;p&gt;For information about configuring trace correlation in the Knowledge Graph UI, refer to &lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/configure/traces-correlation/&#34;&gt;Configure traces correlation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;basic-trace-configuration&#34;&gt;Basic trace configuration&lt;/h2&gt;
&lt;p&gt;Create a file named &lt;code&gt;trace-configs.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Basic trace configuration for services
resource &amp;#34;grafana_asserts_trace_config&amp;#34; &amp;#34;production&amp;#34; {
  provider = grafana.asserts

  name            = &amp;#34;production&amp;#34;
  priority        = 1000
  default_config  = false
  data_source_uid = &amp;#34;grafanacloud-traces&amp;#34;

  match {
    property = &amp;#34;asserts_entity_type&amp;#34;
    op       = &amp;#34;=&amp;#34;
    values   = [&amp;#34;Service&amp;#34;]
  }

  match {
    property = &amp;#34;deployment_environment&amp;#34;
    op       = &amp;#34;=&amp;#34;
    values   = [&amp;#34;production&amp;#34;, &amp;#34;staging&amp;#34;]
  }

  entity_property_to_trace_label_mapping = {
    &amp;#34;cluster&amp;#34;        = &amp;#34;resource.k8s.cluster.name&amp;#34;
    &amp;#34;namespace&amp;#34;      = &amp;#34;resource.k8s.namespace&amp;#34;
    &amp;#34;container&amp;#34;      = &amp;#34;resource.container.name&amp;#34;
    &amp;#34;otel_service&amp;#34;   = &amp;#34;resource.service.name&amp;#34;
    &amp;#34;otel_namespace&amp;#34; = &amp;#34;resource.service.namespace&amp;#34;
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;trace-configuration-with-multiple-match-rules&#34;&gt;Trace configuration with multiple match rules&lt;/h2&gt;
&lt;p&gt;Configure trace correlation with multiple entity matching criteria:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Development environment trace configuration
resource &amp;#34;grafana_asserts_trace_config&amp;#34; &amp;#34;development&amp;#34; {
  provider = grafana.asserts

  name            = &amp;#34;development&amp;#34;
  priority        = 2000
  default_config  = false
  data_source_uid = &amp;#34;tempo-dev&amp;#34;

  match {
    property = &amp;#34;asserts_entity_type&amp;#34;
    op       = &amp;#34;=&amp;#34;
    values   = [&amp;#34;Service&amp;#34;]
  }

  match {
    property = &amp;#34;deployment_environment&amp;#34;
    op       = &amp;#34;=&amp;#34;
    values   = [&amp;#34;development&amp;#34;, &amp;#34;testing&amp;#34;]
  }

  match {
    property = &amp;#34;asserts_site&amp;#34;
    op       = &amp;#34;=&amp;#34;
    values   = [&amp;#34;us-east-1&amp;#34;]
  }

  match {
    property = &amp;#34;service&amp;#34;
    op       = &amp;#34;=&amp;#34;
    values   = [&amp;#34;api&amp;#34;]
  }

  entity_property_to_trace_label_mapping = {
    &amp;#34;cluster&amp;#34;        = &amp;#34;resource.k8s.cluster.name&amp;#34;
    &amp;#34;namespace&amp;#34;      = &amp;#34;resource.k8s.namespace&amp;#34;
    &amp;#34;container&amp;#34;      = &amp;#34;resource.container.name&amp;#34;
    &amp;#34;otel_service&amp;#34;   = &amp;#34;resource.service.name&amp;#34;
    &amp;#34;otel_namespace&amp;#34; = &amp;#34;resource.service.namespace&amp;#34;
    &amp;#34;pod&amp;#34;            = &amp;#34;span.k8s.pod.name&amp;#34;
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;minimal-trace-configuration&#34;&gt;Minimal trace configuration&lt;/h2&gt;
&lt;p&gt;Create a minimal configuration for all entities:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Minimal configuration for all entities
resource &amp;#34;grafana_asserts_trace_config&amp;#34; &amp;#34;minimal&amp;#34; {
  provider = grafana.asserts

  name            = &amp;#34;minimal&amp;#34;
  priority        = 3000
  default_config  = false
  data_source_uid = &amp;#34;tempo-minimal&amp;#34;

  match {
    property = &amp;#34;asserts_entity_type&amp;#34;
    op       = &amp;#34;IS NOT NULL&amp;#34;
    values   = []
  }

  entity_property_to_trace_label_mapping = {
    &amp;#34;cluster&amp;#34;        = &amp;#34;resource.k8s.cluster.name&amp;#34;
    &amp;#34;otel_service&amp;#34;   = &amp;#34;resource.service.name&amp;#34;
    &amp;#34;otel_namespace&amp;#34; = &amp;#34;resource.service.namespace&amp;#34;
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;advanced-trace-configuration-with-complex-match-rules&#34;&gt;Advanced trace configuration with complex match rules&lt;/h2&gt;
&lt;p&gt;Configure traces with multiple operations and advanced match rules:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Advanced configuration with multiple operations
resource &amp;#34;grafana_asserts_trace_config&amp;#34; &amp;#34;advanced&amp;#34; {
  provider = grafana.asserts

  name            = &amp;#34;advanced&amp;#34;
  priority        = 1500
  default_config  = false
  data_source_uid = &amp;#34;tempo-advanced&amp;#34;

  match {
    property = &amp;#34;service_type&amp;#34;
    op       = &amp;#34;CONTAINS&amp;#34;
    values   = [&amp;#34;web&amp;#34;, &amp;#34;api&amp;#34;]
  }

  match {
    property = &amp;#34;deployment_environment&amp;#34;
    op       = &amp;#34;&amp;lt;&amp;gt;&amp;#34;
    values   = [&amp;#34;test&amp;#34;]
  }

  match {
    property = &amp;#34;team&amp;#34;
    op       = &amp;#34;IS NOT NULL&amp;#34;
    values   = []
  }

  match {
    property = &amp;#34;priority_level&amp;#34;
    op       = &amp;#34;&amp;gt;=&amp;#34;
    values   = [&amp;#34;5&amp;#34;]
  }

  entity_property_to_trace_label_mapping = {
    &amp;#34;service_type&amp;#34;   = &amp;#34;resource.service.type&amp;#34;
    &amp;#34;team&amp;#34;           = &amp;#34;resource.team.owner&amp;#34;
    &amp;#34;environment&amp;#34;    = &amp;#34;resource.deployment.environment&amp;#34;
    &amp;#34;version&amp;#34;        = &amp;#34;resource.service.version&amp;#34;
    &amp;#34;region&amp;#34;         = &amp;#34;resource.cloud.region&amp;#34;
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;resource-reference&#34;&gt;Resource reference&lt;/h2&gt;
&lt;h3 id=&#34;grafana_asserts_trace_config&#34;&gt;&lt;code&gt;grafana_asserts_trace_config&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Manage Knowledge Graph trace configurations through the Grafana API.&lt;/p&gt;
&lt;h4 id=&#34;arguments&#34;&gt;Arguments&lt;/h4&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The name of the trace configuration. This field is immutable and forces recreation if changed.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;priority&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Priority of the trace configuration. A lower number means a higher priority.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;default_config&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;bool&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Whether this is the default configuration. Default configurations cannot be deleted.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;data_source_uid&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;DataSource UID to be queried (for example, a Tempo instance).&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;match&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(object)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;List of match rules for entity properties. Refer to &lt;a href=&#34;#match-block&#34;&gt;match block&lt;/a&gt; for details.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;entity_property_to_trace_label_mapping&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;map(string)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Mapping of entity properties to trace labels for correlation.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;match-block&#34;&gt;Match block&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;match&lt;/code&gt; block supports the following:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;property&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Entity property to match against.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;op&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Operation to use for matching. One of: &lt;code&gt;=&lt;/code&gt;, &lt;code&gt;&amp;lt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;=&lt;/code&gt;, &lt;code&gt;&amp;gt;=&lt;/code&gt;, &lt;code&gt;IS NULL&lt;/code&gt;, &lt;code&gt;IS NOT NULL&lt;/code&gt;, &lt;code&gt;STARTS WITH&lt;/code&gt;, &lt;code&gt;CONTAINS&lt;/code&gt;.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;values&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(string)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Values to match against. Can be empty for &lt;code&gt;IS NULL&lt;/code&gt; and &lt;code&gt;IS NOT NULL&lt;/code&gt; operations.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;example&#34;&gt;Example&lt;/h4&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_asserts_trace_config&amp;#34; &amp;#34;example&amp;#34; {
  provider = grafana.asserts

  name            = &amp;#34;example-traces&amp;#34;
  priority        = 1000
  default_config  = false
  data_source_uid = &amp;#34;tempo-prod&amp;#34;

  match {
    property = &amp;#34;asserts_entity_type&amp;#34;
    op       = &amp;#34;=&amp;#34;
    values   = [&amp;#34;Service&amp;#34;, &amp;#34;Pod&amp;#34;]
  }

  match {
    property = &amp;#34;deployment_environment&amp;#34;
    op       = &amp;#34;STARTS WITH&amp;#34;
    values   = [&amp;#34;prod&amp;#34;]
  }

  entity_property_to_trace_label_mapping = {
    &amp;#34;service&amp;#34;     = &amp;#34;resource.service.name&amp;#34;
    &amp;#34;namespace&amp;#34;   = &amp;#34;resource.k8s.namespace&amp;#34;
    &amp;#34;environment&amp;#34; = &amp;#34;resource.deployment.environment&amp;#34;
    &amp;#34;cluster&amp;#34;     = &amp;#34;resource.k8s.cluster.name&amp;#34;
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;best-practices&#34;&gt;Best practices&lt;/h2&gt;
&lt;p&gt;Consider the following best practices when configuring trace correlation with Terraform.&lt;/p&gt;
&lt;h3 id=&#34;priority-management&#34;&gt;Priority management&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Assign lower priority numbers to more specific configurations&lt;/li&gt;
&lt;li&gt;A lower priority number means higher priority (configurations are evaluated in ascending priority order)&lt;/li&gt;
&lt;li&gt;Use consistent priority ranges for different configuration types&lt;/li&gt;
&lt;li&gt;Document the reasoning behind priority assignments&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;data-source-configuration&#34;&gt;Data source configuration&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Ensure the data source UID matches your actual Tempo or trace aggregation system&lt;/li&gt;
&lt;li&gt;Test data source connectivity before applying configurations&lt;/li&gt;
&lt;li&gt;Use descriptive names for trace configurations to indicate their purpose&lt;/li&gt;
&lt;li&gt;Consider using separate data sources for different environments&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;label-map-strategy&#34;&gt;Label map strategy&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Map entity properties consistently across all trace configurations&lt;/li&gt;
&lt;li&gt;Use OpenTelemetry semantic conventions for trace label names (e.g., &lt;code&gt;resource.service.name&lt;/code&gt;, &lt;code&gt;resource.k8s.namespace&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Document the mapping relationships in configuration comments&lt;/li&gt;
&lt;li&gt;Verify that mapped labels exist in your trace data&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;match-rules-design&#34;&gt;Match rules design&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Start with broad match rules and refine based on needs&lt;/li&gt;
&lt;li&gt;Use specific property names that exist in your entity model&lt;/li&gt;
&lt;li&gt;Test match rules with sample data before deploying&lt;/li&gt;
&lt;li&gt;Combine multiple match rules for precise entity targeting&lt;/li&gt;
&lt;li&gt;Leverage comparison operators (&lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;=&lt;/code&gt;, &lt;code&gt;&amp;gt;=&lt;/code&gt;) for numeric or version-based filtering&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;distributed-trace-integration&#34;&gt;Distributed trace integration&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Ensure your traces follow OpenTelemetry semantic conventions&lt;/li&gt;
&lt;li&gt;Use consistent label names for resource attributes across your tracing infrastructure&lt;/li&gt;
&lt;li&gt;Map both service-level and infrastructure-level properties for comprehensive correlation&lt;/li&gt;
&lt;li&gt;Test trace correlation to verify it works as expected&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;validation&#34;&gt;Validation&lt;/h2&gt;
&lt;p&gt;After applying the Terraform configuration, verify that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Trace configurations are created in your Knowledge Graph instance&lt;/li&gt;
&lt;li&gt;Configurations appear in the Knowledge Graph UI under &lt;strong&gt;Observability &amp;gt; Configuration &amp;gt; Traces&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Trace correlation works when drilling down from entities&lt;/li&gt;
&lt;li&gt;Label mappings correctly translate entity properties to trace resource attributes&lt;/li&gt;
&lt;li&gt;Match rules properly filter entities&lt;/li&gt;
&lt;li&gt;Trace queries return expected results in the Knowledge Graph UI&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;related-documentation&#34;&gt;Related documentation&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/configure/traces-correlation/&#34;&gt;Configure traces correlation in Knowledge Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../getting-started/&#34;&gt;Get started with Terraform for Knowledge Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/tempo/latest/&#34;&gt;Tempo documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://opentelemetry.io/docs/specs/semconv/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;OpenTelemetry semantic conventions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="configure-trace-correlation-using-terraform">Configure trace correlation using Terraform&lt;/h1>
&lt;p>Trace configurations in &lt;a href="/docs/grafana-cloud/knowledge-graph/">Knowledge Graph&lt;/a> allow you to define how trace data is queried and correlated with entities. You can specify data sources, entity matching rules, and label mappings for distributed tracing.&lt;/p></description></item><item><title>Configure knowledge graph SLOs using Terraform</title><link>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/knowledge-graph-slo/</link><pubDate>Fri, 03 Apr 2026 19:43:06 +0000</pubDate><guid>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/knowledge-graph-slo/</guid><content><![CDATA[&lt;h1 id=&#34;configure-knowledge-graph-slos-using-terraform&#34;&gt;Configure knowledge graph SLOs using Terraform&lt;/h1&gt;
&lt;p&gt;Service level objectives (SLOs) in the &lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/&#34;&gt;knowledge graph&lt;/a&gt; provide entity-centric service level monitoring with integrated root cause analysis capabilities. By using the &lt;code&gt;grafana_slo_provenance&lt;/code&gt; label with the value &lt;code&gt;asserts&lt;/code&gt;, you can create SLOs that display the &amp;ldquo;asserts&amp;rdquo; badge in the UI and enable the &lt;strong&gt;Open RCA workbench&lt;/strong&gt; button for seamless troubleshooting.&lt;/p&gt;
&lt;p&gt;For details about creating and managing SLOs in the knowledge graph UI, refer to &lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/configure/manage-slos/&#34;&gt;Create and manage the knowledge graph SLOs&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;overview&#34;&gt;Overview&lt;/h2&gt;
&lt;p&gt;Knowledge graph SLOs extend standard Grafana SLOs with entity-centric monitoring and root cause analysis features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Entity-centric monitoring:&lt;/strong&gt; SLOs are tied to specific services, applications, or infrastructure entities tracked by the knowledge graph&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RCA workbench integration:&lt;/strong&gt; The &lt;strong&gt;Open RCA workbench&lt;/strong&gt; button enables deep-linking to pre-filtered troubleshooting views&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Knowledge graph provenance badge:&lt;/strong&gt; SLOs display an &amp;ldquo;asserts&amp;rdquo; badge instead of &amp;ldquo;provisioned&amp;rdquo; in the UI&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Search expressions:&lt;/strong&gt; Define custom search expressions to filter entities in RCA workbench when troubleshooting an SLO breach&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;before-you-begin&#34;&gt;Before you begin&lt;/h2&gt;
&lt;p&gt;To create a knowledge graph SLO using Terraform, you need to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Configure the knowledge graph and have metrics flowing into Grafana Cloud&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../getting-started/&#34;&gt;Set up Terraform for the knowledge Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Possess knowledge of and have experience with defining SLOs, SLIs, SLAs, and error budgets&lt;/li&gt;
&lt;li&gt;Have an understanding of PromQL&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;create-a-basic-knowledge-graph-slo&#34;&gt;Create a basic knowledge graph SLO&lt;/h2&gt;
&lt;p&gt;Create a file named &lt;code&gt;kg-slo.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Basic knowledge graph SLO with entity-centric monitoring
resource &amp;#34;grafana_slo&amp;#34; &amp;#34;kg_example&amp;#34; {
  name        = &amp;#34;API Service Availability&amp;#34;
  description = &amp;#34;SLO managed by knowledge graph for entity-centric monitoring and RCA&amp;#34;

  query {
    freeform {
      query = &amp;#34;sum(rate(http_requests_total{code!~\&amp;#34;5..\&amp;#34;}[$__rate_interval])) / sum(rate(http_requests_total[$__rate_interval]))&amp;#34;
    }
    type = &amp;#34;freeform&amp;#34;
  }

  objectives {
    value  = 0.995
    window = &amp;#34;30d&amp;#34;
  }

  destination_datasource {
    uid = &amp;#34;grafanacloud-prom&amp;#34;
  }

  # Knowledge graph integration labels
  # The grafana_slo_provenance label triggers knowledge graph-specific behavior:
  # - Displays &amp;#34;asserts&amp;#34; badge instead of &amp;#34;provisioned&amp;#34;
  # - Shows &amp;#34;Open RCA workbench&amp;#34; button in the SLO UI
  # - Enables correlation with knowledge graph entity-centric monitoring
  label {
    key   = &amp;#34;grafana_slo_provenance&amp;#34;
    value = &amp;#34;asserts&amp;#34;
  }

  label {
    key   = &amp;#34;service_name&amp;#34;
    value = &amp;#34;api-service&amp;#34;
  }

  # Search expression for RCA workbench
  # This enables the &amp;#34;Open RCA workbench&amp;#34; button to deep-link with pre-filtered context
  search_expression = &amp;#34;service=api-service&amp;#34;

  alerting {
    fastburn {
      annotation {
        key   = &amp;#34;name&amp;#34;
        value = &amp;#34;SLO Burn Rate Very High&amp;#34;
      }
      annotation {
        key   = &amp;#34;description&amp;#34;
        value = &amp;#34;Error budget is burning too fast&amp;#34;
      }
    }
    slowburn {
      annotation {
        key   = &amp;#34;name&amp;#34;
        value = &amp;#34;SLO Burn Rate High&amp;#34;
      }
      annotation {
        key   = &amp;#34;description&amp;#34;
        value = &amp;#34;Error budget is burning too fast&amp;#34;
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;configure-an-slo-with-multiple-entity-labels&#34;&gt;Configure an SLO with multiple entity labels&lt;/h2&gt;
&lt;p&gt;Configure SLOs with multiple entity labels for fine-grained filtering in RCA workbench:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Knowledge graph SLO with comprehensive entity labels
resource &amp;#34;grafana_slo&amp;#34; &amp;#34;payment_service&amp;#34; {
  name        = &amp;#34;Payment Service Latency SLO&amp;#34;
  description = &amp;#34;Latency SLO for payment processing with team and environment context&amp;#34;

  query {
    freeform {
      query = &amp;#34;histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket{service=\&amp;#34;payment\&amp;#34;}[$__rate_interval])) by (le)) &amp;lt; 0.5&amp;#34;
    }
    type = &amp;#34;freeform&amp;#34;
  }

  objectives {
    value  = 0.99
    window = &amp;#34;7d&amp;#34;
  }

  destination_datasource {
    uid = &amp;#34;grafanacloud-prom&amp;#34;
  }

  # Knowledge graph provenance - required for RCA workbench integration
  label {
    key   = &amp;#34;grafana_slo_provenance&amp;#34;
    value = &amp;#34;asserts&amp;#34;
  }

  # Service identification
  label {
    key   = &amp;#34;service_name&amp;#34;
    value = &amp;#34;payment-service&amp;#34;
  }

  # Team ownership
  label {
    key   = &amp;#34;team_name&amp;#34;
    value = &amp;#34;payments-team&amp;#34;
  }

  # Environment
  label {
    key   = &amp;#34;environment&amp;#34;
    value = &amp;#34;production&amp;#34;
  }

  # Business unit
  label {
    key   = &amp;#34;business_unit&amp;#34;
    value = &amp;#34;fintech&amp;#34;
  }

  # Search expression with multiple filters
  search_expression = &amp;#34;service=payment-service AND environment=production&amp;#34;

  alerting {
    fastburn {
      annotation {
        key   = &amp;#34;name&amp;#34;
        value = &amp;#34;Payment Latency Critical&amp;#34;
      }
      annotation {
        key   = &amp;#34;description&amp;#34;
        value = &amp;#34;Payment service P99 latency exceeding SLO - immediate attention required&amp;#34;
      }
      annotation {
        key   = &amp;#34;runbook_url&amp;#34;
        value = &amp;#34;https://docs.example.com/runbooks/payment-latency&amp;#34;
      }
    }
    slowburn {
      annotation {
        key   = &amp;#34;name&amp;#34;
        value = &amp;#34;Payment Latency Warning&amp;#34;
      }
      annotation {
        key   = &amp;#34;description&amp;#34;
        value = &amp;#34;Payment service experiencing elevated latency&amp;#34;
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;configure-a-kubernetes-service-slo&#34;&gt;Configure a Kubernetes service SLO&lt;/h2&gt;
&lt;p&gt;Configure knowledge graph SLOs for Kubernetes services with Pod and namespace context:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Knowledge graph SLO for Kubernetes service
resource &amp;#34;grafana_slo&amp;#34; &amp;#34;k8s_frontend&amp;#34; {
  name        = &amp;#34;Frontend Service Availability&amp;#34;
  description = &amp;#34;Availability SLO for frontend service in Kubernetes&amp;#34;

  query {
    freeform {
      query = &amp;#34;sum(rate(http_requests_total{namespace=\&amp;#34;frontend\&amp;#34;,code!~\&amp;#34;5..\&amp;#34;}[$__rate_interval])) / sum(rate(http_requests_total{namespace=\&amp;#34;frontend\&amp;#34;}[$__rate_interval]))&amp;#34;
    }
    type = &amp;#34;freeform&amp;#34;
  }

  objectives {
    value  = 0.999
    window = &amp;#34;30d&amp;#34;
  }

  destination_datasource {
    uid = &amp;#34;grafanacloud-prom&amp;#34;
  }

  label {
    key   = &amp;#34;grafana_slo_provenance&amp;#34;
    value = &amp;#34;asserts&amp;#34;
  }

  label {
    key   = &amp;#34;service_name&amp;#34;
    value = &amp;#34;frontend&amp;#34;
  }

  label {
    key   = &amp;#34;namespace&amp;#34;
    value = &amp;#34;frontend&amp;#34;
  }

  label {
    key   = &amp;#34;cluster&amp;#34;
    value = &amp;#34;prod-us-west-2&amp;#34;
  }

  # Search expression targeting Kubernetes entities
  search_expression = &amp;#34;namespace=frontend AND cluster=prod-us-west-2&amp;#34;

  alerting {
    fastburn {
      annotation {
        key   = &amp;#34;name&amp;#34;
        value = &amp;#34;Frontend Service Critical&amp;#34;
      }
      annotation {
        key   = &amp;#34;description&amp;#34;
        value = &amp;#34;Frontend service availability below SLO&amp;#34;
      }
      annotation {
        key   = &amp;#34;severity&amp;#34;
        value = &amp;#34;critical&amp;#34;
      }
    }
    slowburn {
      annotation {
        key   = &amp;#34;name&amp;#34;
        value = &amp;#34;Frontend Service Degraded&amp;#34;
      }
      annotation {
        key   = &amp;#34;description&amp;#34;
        value = &amp;#34;Frontend service showing signs of degradation&amp;#34;
      }
      annotation {
        key   = &amp;#34;severity&amp;#34;
        value = &amp;#34;warning&amp;#34;
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;configure-an-api-endpoint-specific-slo&#34;&gt;Configure an API endpoint-specific SLO&lt;/h2&gt;
&lt;p&gt;Configure knowledge graph SLOs for specific API endpoints with request context:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Knowledge graph SLO for critical API endpoint
resource &amp;#34;grafana_slo&amp;#34; &amp;#34;checkout_api&amp;#34; {
  name        = &amp;#34;Checkout API Availability&amp;#34;
  description = &amp;#34;Availability SLO for /api/checkout endpoint&amp;#34;

  query {
    freeform {
      query = &amp;#34;sum(rate(http_requests_total{path=\&amp;#34;/api/checkout\&amp;#34;,code!~\&amp;#34;5..\&amp;#34;}[$__rate_interval])) / sum(rate(http_requests_total{path=\&amp;#34;/api/checkout\&amp;#34;}[$__rate_interval]))&amp;#34;
    }
    type = &amp;#34;freeform&amp;#34;
  }

  objectives {
    value  = 0.9999
    window = &amp;#34;30d&amp;#34;
  }

  destination_datasource {
    uid = &amp;#34;grafanacloud-prom&amp;#34;
  }

  label {
    key   = &amp;#34;grafana_slo_provenance&amp;#34;
    value = &amp;#34;asserts&amp;#34;
  }

  label {
    key   = &amp;#34;service_name&amp;#34;
    value = &amp;#34;checkout-service&amp;#34;
  }

  label {
    key   = &amp;#34;endpoint&amp;#34;
    value = &amp;#34;/api/checkout&amp;#34;
  }

  label {
    key   = &amp;#34;criticality&amp;#34;
    value = &amp;#34;high&amp;#34;
  }

  # Search expression with endpoint context
  search_expression = &amp;#34;service=checkout-service AND path=/api/checkout&amp;#34;

  alerting {
    fastburn {
      annotation {
        key   = &amp;#34;name&amp;#34;
        value = &amp;#34;Checkout API Critical Failure&amp;#34;
      }
      annotation {
        key   = &amp;#34;description&amp;#34;
        value = &amp;#34;Checkout API experiencing high error rates - revenue impact&amp;#34;
      }
      annotation {
        key   = &amp;#34;severity&amp;#34;
        value = &amp;#34;critical&amp;#34;
      }
      annotation {
        key   = &amp;#34;alert_priority&amp;#34;
        value = &amp;#34;P0&amp;#34;
      }
    }
    slowburn {
      annotation {
        key   = &amp;#34;name&amp;#34;
        value = &amp;#34;Checkout API Degradation&amp;#34;
      }
      annotation {
        key   = &amp;#34;description&amp;#34;
        value = &amp;#34;Checkout API showing elevated error rates&amp;#34;
      }
      annotation {
        key   = &amp;#34;severity&amp;#34;
        value = &amp;#34;warning&amp;#34;
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;configure-a-multi-environment-slo&#34;&gt;Configure a multi-environment SLO&lt;/h2&gt;
&lt;p&gt;Manage knowledge graph SLOs across multiple environments using Terraform workspaces or modules:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Variable for environment-specific configuration
variable &amp;#34;environment&amp;#34; {
  description = &amp;#34;Environment name&amp;#34;
  type        = string
}

variable &amp;#34;slo_target&amp;#34; {
  description = &amp;#34;SLO target percentage&amp;#34;
  type        = number
}

# Environment-aware knowledge graph SLO
resource &amp;#34;grafana_slo&amp;#34; &amp;#34;api_service&amp;#34; {
  name        = &amp;#34;${var.environment} - API Service Availability&amp;#34;
  description = &amp;#34;API service availability SLO for ${var.environment} environment&amp;#34;

  query {
    freeform {
      query = &amp;#34;sum(rate(http_requests_total{environment=\&amp;#34;${var.environment}\&amp;#34;,code!~\&amp;#34;5..\&amp;#34;}[$__rate_interval])) / sum(rate(http_requests_total{environment=\&amp;#34;${var.environment}\&amp;#34;}[$__rate_interval]))&amp;#34;
    }
    type = &amp;#34;freeform&amp;#34;
  }

  objectives {
    value  = var.slo_target
    window = &amp;#34;30d&amp;#34;
  }

  destination_datasource {
    uid = &amp;#34;grafanacloud-prom&amp;#34;
  }

  label {
    key   = &amp;#34;grafana_slo_provenance&amp;#34;
    value = &amp;#34;asserts&amp;#34;
  }

  label {
    key   = &amp;#34;service_name&amp;#34;
    value = &amp;#34;api-service&amp;#34;
  }

  label {
    key   = &amp;#34;environment&amp;#34;
    value = var.environment
  }

  search_expression = &amp;#34;service=api-service AND environment=${var.environment}&amp;#34;

  alerting {
    fastburn {
      annotation {
        key   = &amp;#34;name&amp;#34;
        value = &amp;#34;${var.environment} API Critical&amp;#34;
      }
      annotation {
        key   = &amp;#34;description&amp;#34;
        value = &amp;#34;API service in ${var.environment} experiencing critical errors&amp;#34;
      }
    }
    slowburn {
      annotation {
        key   = &amp;#34;name&amp;#34;
        value = &amp;#34;${var.environment} API Warning&amp;#34;
      }
      annotation {
        key   = &amp;#34;description&amp;#34;
        value = &amp;#34;API service in ${var.environment} showing elevated errors&amp;#34;
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;resource-reference&#34;&gt;Resource reference&lt;/h2&gt;
&lt;h3 id=&#34;grafana_slo-with-knowledge-graph-provenance&#34;&gt;&lt;code&gt;grafana_slo&lt;/code&gt; with knowledge graph provenance&lt;/h3&gt;
&lt;p&gt;When creating knowledge graph-managed SLOs, the &lt;code&gt;grafana_slo&lt;/code&gt; resource requires the &lt;code&gt;grafana_slo_provenance&lt;/code&gt; label set to &lt;code&gt;asserts&lt;/code&gt; to enable RCA workbench integration.&lt;/p&gt;
&lt;h4 id=&#34;required-knowledge-graph-configuration&#34;&gt;Required knowledge graph configuration&lt;/h4&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;grafana_slo_provenance&lt;/code&gt; label&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Must be set to &lt;code&gt;asserts&lt;/code&gt; to enable knowledge graph-specific features and RCA workbench integration&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;search_expression&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Recommended&lt;/td&gt;
              &lt;td&gt;Search expression for filtering entities in RCA workbench&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;key-arguments-for-knowledge-graph-slos&#34;&gt;Key arguments for knowledge graph SLOs&lt;/h4&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The name of the SLO&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Description of the SLO purpose and scope&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;query&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;object&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Query configuration defining how SLO is calculated&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;objectives&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;object&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Target objectives including value and time window&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;destination_datasource&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;object&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Destination data source for SLO metrics&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;label&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(object)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Labels for the SLO, must include &lt;code&gt;grafana_slo_provenance=asserts&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;search_expression&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Search expression for RCA workbench filtering&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;alerting&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;object&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Alerting configuration for fast burn and slow burn alerts&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;query-block&#34;&gt;Query block&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;query&lt;/code&gt; block supports the following:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;type&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Query type, typically &lt;code&gt;freeform&lt;/code&gt; for knowledge graph SLOs&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;freeform&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;object&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Freeform query configuration&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;The &lt;code&gt;freeform&lt;/code&gt; block supports:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;query&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;PromQL query for SLO calculation&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;objectives-block&#34;&gt;Objectives block&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;objectives&lt;/code&gt; block supports the following:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;value&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Target SLO value (for example, 0.995 for 99.5%)&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;window&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Time window for SLO evaluation (for example, &amp;ldquo;30d&amp;rdquo;)&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;label-block&#34;&gt;Label block&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;label&lt;/code&gt; block supports the following:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;key&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Label key&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;value&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Label value&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;&lt;strong&gt;Required label for knowledge graph SLOs:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;grafana_slo_provenance&lt;/code&gt; = &lt;code&gt;asserts&lt;/code&gt; (enables knowledge graph features)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Recommended labels for entity tracking:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;service_name&lt;/code&gt; - Name of the service&lt;/li&gt;
&lt;li&gt;&lt;code&gt;team_name&lt;/code&gt; - Team responsible for the service&lt;/li&gt;
&lt;li&gt;&lt;code&gt;environment&lt;/code&gt; - Environment (prod, staging, development)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;namespace&lt;/code&gt; - Kubernetes namespace&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cluster&lt;/code&gt; - Kubernetes cluster name&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- vale Grafana.Gerunds = NO --&gt;
&lt;h4 id=&#34;alerting-block&#34;&gt;Alerting block&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;alerting&lt;/code&gt; block supports the following:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;fastburn&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;object&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Fast burn rate alert configuration&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;slowburn&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;object&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Slow burn rate alert configuration&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;Each alert block (&lt;code&gt;fastburn&lt;/code&gt;, &lt;code&gt;slowburn&lt;/code&gt;) supports:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;annotation&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(object)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Annotations to add to the alert&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;Each &lt;code&gt;annotation&lt;/code&gt; block supports:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;key&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Annotation key&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;value&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Annotation value&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;Common annotation keys:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;name&lt;/code&gt; - Alert name&lt;/li&gt;
&lt;li&gt;&lt;code&gt;description&lt;/code&gt; - Alert description&lt;/li&gt;
&lt;li&gt;&lt;code&gt;severity&lt;/code&gt; - Alert severity level&lt;/li&gt;
&lt;li&gt;&lt;code&gt;runbook_url&lt;/code&gt; - Link to runbook documentation&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- vale Grafana.Gerunds = YES --&gt;
&lt;h4 id=&#34;example&#34;&gt;Example&lt;/h4&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_slo&amp;#34; &amp;#34;kg_example&amp;#34; {
  name        = &amp;#34;My Service SLO&amp;#34;
  description = &amp;#34;SLO with knowledge graph RCA integration&amp;#34;

  query {
    freeform {
      query = &amp;#34;sum(rate(http_requests_total{code!~\&amp;#34;5..\&amp;#34;}[$__rate_interval])) / sum(rate(http_requests_total[$__rate_interval]))&amp;#34;
    }
    type = &amp;#34;freeform&amp;#34;
  }

  objectives {
    value  = 0.995
    window = &amp;#34;30d&amp;#34;
  }

  destination_datasource {
    uid = &amp;#34;grafanacloud-prom&amp;#34;
  }

  label {
    key   = &amp;#34;grafana_slo_provenance&amp;#34;
    value = &amp;#34;asserts&amp;#34;
  }

  label {
    key   = &amp;#34;service_name&amp;#34;
    value = &amp;#34;my-service&amp;#34;
  }

  search_expression = &amp;#34;service=my-service&amp;#34;

  alerting {
    fastburn {
      annotation {
        key   = &amp;#34;name&amp;#34;
        value = &amp;#34;SLO Fast Burn&amp;#34;
      }
    }
    slowburn {
      annotation {
        key   = &amp;#34;name&amp;#34;
        value = &amp;#34;SLO Slow Burn&amp;#34;
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;best-practices&#34;&gt;Best practices&lt;/h2&gt;
&lt;p&gt;Follow these best practices when setting knowledge graph SLOs.&lt;/p&gt;
&lt;h3 id=&#34;use-the-knowledge-graph-provenance-label&#34;&gt;Use the knowledge graph provenance label&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Always include the &lt;code&gt;grafana_slo_provenance&lt;/code&gt; label with value &lt;code&gt;asserts&lt;/code&gt; for knowledge graph-managed SLOs&lt;/li&gt;
&lt;li&gt;This label enables the &amp;ldquo;asserts&amp;rdquo; badge in the UI instead of &amp;ldquo;provisioned&amp;rdquo;&lt;/li&gt;
&lt;li&gt;It also enables the &lt;strong&gt;Open RCA workbench&lt;/strong&gt; button for troubleshooting SLO breaches&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;define-search-expressions&#34;&gt;Define search expressions&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Define meaningful search expressions that filter relevant entities in RCA workbench&lt;/li&gt;
&lt;li&gt;The search expression defines which entities populate RCA workbench when you troubleshoot an SLO breach&lt;/li&gt;
&lt;li&gt;Use entity attributes like service name, environment, namespace, and cluster&lt;/li&gt;
&lt;li&gt;Combine multiple filters with &lt;code&gt;AND&lt;/code&gt; operators for precise filtering&lt;/li&gt;
&lt;li&gt;Test search expressions in RCA workbench before codifying them in Terraform&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;add-entity-labels&#34;&gt;Add entity labels&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Add descriptive labels to track service ownership, environment, and criticality&lt;/li&gt;
&lt;li&gt;Use consistent label naming conventions across all SLOs&lt;/li&gt;
&lt;li&gt;Include team names to enable quick identification of ownership&lt;/li&gt;
&lt;li&gt;Tag critical business services with appropriate labels&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;set-slo-targets&#34;&gt;Set SLO targets&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Set realistic SLO targets based on service requirements and capabilities&lt;/li&gt;
&lt;li&gt;Use higher targets (0.999&#43;) for critical user-facing services&lt;/li&gt;
&lt;li&gt;Consider different targets for different environments (production vs staging)&lt;/li&gt;
&lt;li&gt;Review and adjust targets based on actual service performance&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;add-alert-annotations&#34;&gt;Add alert annotations&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Add comprehensive descriptions to help on-call engineers understand the alert&lt;/li&gt;
&lt;li&gt;Include runbook URLs in annotations for quick access to troubleshooting guides&lt;/li&gt;
&lt;li&gt;Set appropriate severity levels (critical, warning) based on business impact&lt;/li&gt;
&lt;li&gt;Customize alert names to clearly identify the affected service and issue&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;configure-queries&#34;&gt;Configure queries&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Use PromQL queries that accurately represent service health&lt;/li&gt;
&lt;li&gt;Exclude expected error codes, such as 404, from error calculations when appropriate&lt;/li&gt;
&lt;li&gt;Leverage rate intervals with &lt;code&gt;$__rate_interval&lt;/code&gt; for dynamic time range support&lt;/li&gt;
&lt;li&gt;Test queries in Grafana before adding them to Terraform configurations&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;set-compliance-windows&#34;&gt;Set compliance windows&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Use 30-day windows for production SLOs to align with monthly reporting&lt;/li&gt;
&lt;li&gt;Consider shorter windows (7d) for development or testing environments&lt;/li&gt;
&lt;li&gt;Ensure compliance windows align with business requirements and error budget policies&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;verify-the-configuration&#34;&gt;Verify the configuration&lt;/h2&gt;
&lt;p&gt;After applying the Terraform configuration, verify that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SLOs are created in your Grafana Cloud stack&lt;/li&gt;
&lt;li&gt;SLOs appear in &lt;strong&gt;Observability &amp;gt; SLO&lt;/strong&gt; with the &amp;ldquo;asserts&amp;rdquo; badge&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Open RCA workbench&lt;/strong&gt; button is visible when you expand &lt;strong&gt;Objective&lt;/strong&gt; for an SLO&lt;/li&gt;
&lt;li&gt;You can select a time range in the &lt;strong&gt;Error Budget Burndown&lt;/strong&gt; panel and click &lt;strong&gt;Open in RCA workbench&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Search expressions correctly filter entities in RCA workbench&lt;/li&gt;
&lt;li&gt;Fast burn and slow burn alerts are configured with appropriate thresholds&lt;/li&gt;
&lt;li&gt;Labels are correctly applied and visible in the SLO details&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;troubleshooting&#34;&gt;Troubleshooting&lt;/h2&gt;
&lt;p&gt;Follow these troubleshooting steps if you experience issues setting knowledge graph SLOs.&lt;/p&gt;
&lt;h3 id=&#34;slo-shows-provisioned-instead-of-asserts-badge&#34;&gt;SLO shows &amp;ldquo;provisioned&amp;rdquo; instead of &amp;ldquo;asserts&amp;rdquo; badge&lt;/h3&gt;
&lt;p&gt;Ensure the &lt;code&gt;grafana_slo_provenance&lt;/code&gt; label is set to &lt;code&gt;asserts&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;label {
  key   = &amp;#34;grafana_slo_provenance&amp;#34;
  value = &amp;#34;asserts&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;open-rca-workbench-button-not-appearing&#34;&gt;Open RCA workbench button not appearing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Verify the &lt;code&gt;search_expression&lt;/code&gt; field is populated&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Open RCA workbench&lt;/strong&gt; button appears after you have added a search expression in the &lt;strong&gt;RCA workbench Context&lt;/strong&gt; section&lt;/li&gt;
&lt;li&gt;Ensure the search expression uses valid entity attributes&lt;/li&gt;
&lt;li&gt;Check that the knowledge graph is properly configured and receiving data&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;alerts-not-triggering&#34;&gt;Alerts not triggering&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Verify the PromQL query returns valid results in Grafana&lt;/li&gt;
&lt;li&gt;Check that the destination data source is correctly configured&lt;/li&gt;
&lt;li&gt;Ensure alerting blocks are properly defined with annotations&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;related-documentation&#34;&gt;Related documentation&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/configure/manage-slos/&#34;&gt;Create and manage knowledge graph SLOs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/troubleshoot-infra-apps/slos/&#34;&gt;Troubleshoot an SLO breach with the knowledge graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../getting-started/&#34;&gt;Get started with Terraform for the knowledge graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/alerting-and-irm/slo/introduction/&#34;&gt;Introduction to Grafana SLO&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/configure/notifications/&#34;&gt;Configure notifications in the knowledge graph&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="configure-knowledge-graph-slos-using-terraform">Configure knowledge graph SLOs using Terraform&lt;/h1>
&lt;p>Service level objectives (SLOs) in the &lt;a href="/docs/grafana-cloud/knowledge-graph/">knowledge graph&lt;/a> provide entity-centric service level monitoring with integrated root cause analysis capabilities. By using the &lt;code>grafana_slo_provenance&lt;/code> label with the value &lt;code>asserts&lt;/code>, you can create SLOs that display the &amp;ldquo;asserts&amp;rdquo; badge in the UI and enable the &lt;strong>Open RCA workbench&lt;/strong> button for seamless troubleshooting.&lt;/p></description></item><item><title>Configure profile correlation using Terraform</title><link>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/profile-configurations/</link><pubDate>Fri, 03 Apr 2026 19:43:06 +0000</pubDate><guid>https://grafana.com/docs/grafana/v12.4/as-code/infrastructure-as-code/terraform/terraform-knowledge-graph/profile-configurations/</guid><content><![CDATA[&lt;h1 id=&#34;configure-profile-correlation-using-terraform&#34;&gt;Configure profile correlation using Terraform&lt;/h1&gt;
&lt;p&gt;Profile configurations in &lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/&#34;&gt;Knowledge Graph&lt;/a&gt; allow you to define how continuous profiling data is queried and correlated with entities. You can specify data sources, entity matching rules, and label mappings for performance profiling.&lt;/p&gt;
&lt;p&gt;For information about configuring profile correlation in the Knowledge Graph UI, refer to &lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/configure/profiles-correlation/&#34;&gt;Configure profiles correlation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;basic-profile-configuration&#34;&gt;Basic profile configuration&lt;/h2&gt;
&lt;p&gt;Create a file named &lt;code&gt;profile-configs.tf&lt;/code&gt; and add the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Basic profile configuration for services
resource &amp;#34;grafana_asserts_profile_config&amp;#34; &amp;#34;production&amp;#34; {
  provider = grafana.asserts

  name            = &amp;#34;production&amp;#34;
  priority        = 1000
  default_config  = false
  data_source_uid = &amp;#34;grafanacloud-profiles&amp;#34;

  match {
    property = &amp;#34;asserts_entity_type&amp;#34;
    op       = &amp;#34;=&amp;#34;
    values   = [&amp;#34;Service&amp;#34;]
  }

  match {
    property = &amp;#34;deployment_environment&amp;#34;
    op       = &amp;#34;=&amp;#34;
    values   = [&amp;#34;production&amp;#34;, &amp;#34;staging&amp;#34;]
  }

  entity_property_to_profile_label_mapping = {
    &amp;#34;cluster&amp;#34;        = &amp;#34;k8s_cluster_name&amp;#34;
    &amp;#34;namespace&amp;#34;      = &amp;#34;k8s_namespace_name&amp;#34;
    &amp;#34;container&amp;#34;      = &amp;#34;k8s_container_name&amp;#34;
    &amp;#34;otel_service&amp;#34;   = &amp;#34;service_name&amp;#34;
    &amp;#34;otel_namespace&amp;#34; = &amp;#34;service_namespace&amp;#34;
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;profile-configuration-with-multiple-match-rules&#34;&gt;Profile configuration with multiple match rules&lt;/h2&gt;
&lt;p&gt;Configure profile correlation with multiple entity matching criteria:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Development environment profile configuration
resource &amp;#34;grafana_asserts_profile_config&amp;#34; &amp;#34;development&amp;#34; {
  provider = grafana.asserts

  name            = &amp;#34;development&amp;#34;
  priority        = 2000
  default_config  = false
  data_source_uid = &amp;#34;pyroscope-dev&amp;#34;

  match {
    property = &amp;#34;asserts_entity_type&amp;#34;
    op       = &amp;#34;=&amp;#34;
    values   = [&amp;#34;Service&amp;#34;]
  }

  match {
    property = &amp;#34;deployment_environment&amp;#34;
    op       = &amp;#34;=&amp;#34;
    values   = [&amp;#34;development&amp;#34;, &amp;#34;testing&amp;#34;]
  }

  match {
    property = &amp;#34;asserts_site&amp;#34;
    op       = &amp;#34;=&amp;#34;
    values   = [&amp;#34;us-east-1&amp;#34;]
  }

  match {
    property = &amp;#34;service&amp;#34;
    op       = &amp;#34;=&amp;#34;
    values   = [&amp;#34;api&amp;#34;]
  }

  entity_property_to_profile_label_mapping = {
    &amp;#34;cluster&amp;#34;        = &amp;#34;k8s_cluster_name&amp;#34;
    &amp;#34;namespace&amp;#34;      = &amp;#34;k8s_namespace_name&amp;#34;
    &amp;#34;container&amp;#34;      = &amp;#34;k8s_container_name&amp;#34;
    &amp;#34;otel_service&amp;#34;   = &amp;#34;service_name&amp;#34;
    &amp;#34;otel_namespace&amp;#34; = &amp;#34;service_namespace&amp;#34;
    &amp;#34;pod&amp;#34;            = &amp;#34;k8s_pod_name&amp;#34;
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;minimal-profile-configuration&#34;&gt;Minimal profile configuration&lt;/h2&gt;
&lt;p&gt;Create a minimal configuration for all entities:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Minimal configuration for all entities
resource &amp;#34;grafana_asserts_profile_config&amp;#34; &amp;#34;minimal&amp;#34; {
  provider = grafana.asserts

  name            = &amp;#34;minimal&amp;#34;
  priority        = 3000
  default_config  = false
  data_source_uid = &amp;#34;pyroscope-minimal&amp;#34;

  match {
    property = &amp;#34;asserts_entity_type&amp;#34;
    op       = &amp;#34;IS NOT NULL&amp;#34;
    values   = []
  }

  entity_property_to_profile_label_mapping = {
    &amp;#34;cluster&amp;#34;        = &amp;#34;k8s_cluster_name&amp;#34;
    &amp;#34;otel_service&amp;#34;   = &amp;#34;service_name&amp;#34;
    &amp;#34;otel_namespace&amp;#34; = &amp;#34;service_namespace&amp;#34;
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;advanced-profile-configuration-with-complex-match-rules&#34;&gt;Advanced profile configuration with complex match rules&lt;/h2&gt;
&lt;p&gt;Configure profiles with multiple operations and advanced match rules:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;# Advanced configuration with multiple operations
resource &amp;#34;grafana_asserts_profile_config&amp;#34; &amp;#34;advanced&amp;#34; {
  provider = grafana.asserts

  name            = &amp;#34;advanced&amp;#34;
  priority        = 1500
  default_config  = false
  data_source_uid = &amp;#34;pyroscope-advanced&amp;#34;

  match {
    property = &amp;#34;service_type&amp;#34;
    op       = &amp;#34;CONTAINS&amp;#34;
    values   = [&amp;#34;web&amp;#34;, &amp;#34;api&amp;#34;]
  }

  match {
    property = &amp;#34;deployment_environment&amp;#34;
    op       = &amp;#34;&amp;lt;&amp;gt;&amp;#34;
    values   = [&amp;#34;test&amp;#34;]
  }

  match {
    property = &amp;#34;team&amp;#34;
    op       = &amp;#34;IS NOT NULL&amp;#34;
    values   = []
  }

  match {
    property = &amp;#34;cpu_threshold&amp;#34;
    op       = &amp;#34;&amp;gt;=&amp;#34;
    values   = [&amp;#34;80&amp;#34;]
  }

  entity_property_to_profile_label_mapping = {
    &amp;#34;service_type&amp;#34;   = &amp;#34;service_type&amp;#34;
    &amp;#34;team&amp;#34;           = &amp;#34;team_owner&amp;#34;
    &amp;#34;environment&amp;#34;    = &amp;#34;deployment_env&amp;#34;
    &amp;#34;version&amp;#34;        = &amp;#34;app_version&amp;#34;
    &amp;#34;region&amp;#34;         = &amp;#34;cloud_region&amp;#34;
    &amp;#34;node&amp;#34;           = &amp;#34;k8s_node_name&amp;#34;
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;resource-reference&#34;&gt;Resource reference&lt;/h2&gt;
&lt;h3 id=&#34;grafana_asserts_profile_config&#34;&gt;&lt;code&gt;grafana_asserts_profile_config&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Manage Knowledge Graph profile configurations through the Grafana API.&lt;/p&gt;
&lt;h4 id=&#34;arguments&#34;&gt;Arguments&lt;/h4&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;The name of the profile configuration. This field is immutable and forces recreation if changed.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;priority&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Priority of the profile configuration. A lower number means a higher priority.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;default_config&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;bool&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Whether this is the default configuration. Default configurations cannot be deleted.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;data_source_uid&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;DataSource UID to be queried (for example, a Pyroscope instance).&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;match&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(object)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;List of match rules for entity properties. Refer to &lt;a href=&#34;#match-block&#34;&gt;match block&lt;/a&gt; for details.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;entity_property_to_profile_label_mapping&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;map(string)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;No&lt;/td&gt;
              &lt;td&gt;Mapping of entity properties to profile labels for correlation.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;match-block&#34;&gt;Match block&lt;/h4&gt;
&lt;p&gt;Each &lt;code&gt;match&lt;/code&gt; block supports the following:&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Name&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Required&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;property&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Entity property to match against.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;op&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Operation to use for matching. One of: &lt;code&gt;=&lt;/code&gt;, &lt;code&gt;&amp;lt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;=&lt;/code&gt;, &lt;code&gt;&amp;gt;=&lt;/code&gt;, &lt;code&gt;IS NULL&lt;/code&gt;, &lt;code&gt;IS NOT NULL&lt;/code&gt;, &lt;code&gt;STARTS WITH&lt;/code&gt;, &lt;code&gt;CONTAINS&lt;/code&gt;.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;values&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;list(string)&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Yes&lt;/td&gt;
              &lt;td&gt;Values to match against. Can be empty for &lt;code&gt;IS NULL&lt;/code&gt; and &lt;code&gt;IS NOT NULL&lt;/code&gt; operations.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h4 id=&#34;example&#34;&gt;Example&lt;/h4&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;terraform&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;grafana_asserts_profile_config&amp;#34; &amp;#34;example&amp;#34; {
  provider = grafana.asserts

  name            = &amp;#34;example-profiles&amp;#34;
  priority        = 1000
  default_config  = false
  data_source_uid = &amp;#34;pyroscope-prod&amp;#34;

  match {
    property = &amp;#34;asserts_entity_type&amp;#34;
    op       = &amp;#34;=&amp;#34;
    values   = [&amp;#34;Service&amp;#34;, &amp;#34;Pod&amp;#34;]
  }

  match {
    property = &amp;#34;deployment_environment&amp;#34;
    op       = &amp;#34;STARTS WITH&amp;#34;
    values   = [&amp;#34;prod&amp;#34;]
  }

  entity_property_to_profile_label_mapping = {
    &amp;#34;service&amp;#34;     = &amp;#34;service_name&amp;#34;
    &amp;#34;namespace&amp;#34;   = &amp;#34;k8s_namespace_name&amp;#34;
    &amp;#34;environment&amp;#34; = &amp;#34;deployment_env&amp;#34;
    &amp;#34;cluster&amp;#34;     = &amp;#34;k8s_cluster_name&amp;#34;
    &amp;#34;container&amp;#34;   = &amp;#34;k8s_container_name&amp;#34;
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;best-practices&#34;&gt;Best practices&lt;/h2&gt;
&lt;p&gt;Consider the following best practices when configuring profile correlation with Terraform.&lt;/p&gt;
&lt;h3 id=&#34;priority-management&#34;&gt;Priority management&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Assign lower priority numbers to more specific configurations&lt;/li&gt;
&lt;li&gt;A lower priority number means higher priority (configurations are evaluated in ascending priority order)&lt;/li&gt;
&lt;li&gt;Use consistent priority ranges for different configuration types&lt;/li&gt;
&lt;li&gt;Document the reasoning behind priority assignments&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;data-source-configuration&#34;&gt;Data source configuration&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Ensure the data source UID matches your actual Pyroscope or profiling system&lt;/li&gt;
&lt;li&gt;Test data source connectivity before applying configurations&lt;/li&gt;
&lt;li&gt;Use descriptive names for profile configurations to indicate their purpose&lt;/li&gt;
&lt;li&gt;Consider using separate data sources for different environments&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;label-map-strategy&#34;&gt;Label map strategy&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Map entity properties consistently across all profile configurations&lt;/li&gt;
&lt;li&gt;Use meaningful profile label names that match your profiling standards&lt;/li&gt;
&lt;li&gt;Document the mapping relationships in configuration comments&lt;/li&gt;
&lt;li&gt;Verify that mapped labels exist in your profile data&lt;/li&gt;
&lt;li&gt;Align label names with your continuous profiling setup (Pyroscope, Grafana Agent, etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;match-rules-design&#34;&gt;Match rules design&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Start with broad match rules and refine based on needs&lt;/li&gt;
&lt;li&gt;Use specific property names that exist in your entity model&lt;/li&gt;
&lt;li&gt;Test match rules with sample data before deploying&lt;/li&gt;
&lt;li&gt;Combine multiple match rules for precise entity targeting&lt;/li&gt;
&lt;li&gt;Leverage comparison operators (&lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;=&lt;/code&gt;, &lt;code&gt;&amp;gt;=&lt;/code&gt;) for numeric thresholds or performance-based filtering&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;continuous-profiling-integration&#34;&gt;Continuous profiling integration&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Ensure your profiling agents are configured with appropriate labels&lt;/li&gt;
&lt;li&gt;Use consistent label names across your profiling infrastructure&lt;/li&gt;
&lt;li&gt;Map both service-level and infrastructure-level properties for comprehensive correlation&lt;/li&gt;
&lt;li&gt;Consider including pod, node, and container information for Kubernetes deployments&lt;/li&gt;
&lt;li&gt;Test profile correlation to verify it works as expected&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;validation&#34;&gt;Validation&lt;/h2&gt;
&lt;p&gt;After applying the Terraform configuration, verify that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Profile configurations are created in your Knowledge Graph instance&lt;/li&gt;
&lt;li&gt;Configurations appear in the Knowledge Graph UI under &lt;strong&gt;Observability &amp;gt; Configuration &amp;gt; Profiles&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Profile correlation works when drilling down from entities&lt;/li&gt;
&lt;li&gt;Label mappings correctly translate entity properties to profile labels&lt;/li&gt;
&lt;li&gt;Match rules properly filter entities&lt;/li&gt;
&lt;li&gt;Profile queries return expected results in the Knowledge Graph UI&lt;/li&gt;
&lt;li&gt;Flame graphs and profiling data display correctly when accessed through Knowledge Graph&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;related-documentation&#34;&gt;Related documentation&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;/docs/grafana-cloud/knowledge-graph/configure/profiles-correlation/&#34;&gt;Configure profiles correlation in Knowledge Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../getting-started/&#34;&gt;Get started with Terraform for Knowledge Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/pyroscope/latest/&#34;&gt;Pyroscope documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/docs/agent/latest/flow/reference/components/pyroscope.scrape/&#34;&gt;Grafana Agent profiling&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="configure-profile-correlation-using-terraform">Configure profile correlation using Terraform&lt;/h1>
&lt;p>Profile configurations in &lt;a href="/docs/grafana-cloud/knowledge-graph/">Knowledge Graph&lt;/a> allow you to define how continuous profiling data is queried and correlated with entities. You can specify data sources, entity matching rules, and label mappings for performance profiling.&lt;/p></description></item></channel></rss>