Grafana Cloud

Set up MySQL

Note

Database Observability is currently in public preview. Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available.

Set up Database Observability with Grafana Cloud to collect telemetry from MySQL using Grafana Alloy. You configure your database and Alloy to forward telemetry to Grafana Cloud.

What you’ll achieve

In this article, you:

  • Configure MySQL for monitoring.
  • Run Alloy with the public preview Database Observability components.
  • Forward telemetry to Grafana Cloud.

Before you begin

Review these requirements:

  • Use MySQL version 8.0 or later.

Set up the MySQL database

Prepare MySQL for monitoring and query introspection.

Enable Performance Schema

Enable Performance Schema if it’s not already enabled and verify the setting:

SQL
SHOW VARIABLES LIKE 'performance_schema';

Expected result: Value is ON.

Create a monitoring user and grant required privileges

Create the db-o11y user and grant base privileges:

SQL
CREATE USER 'db-o11y'@'%' IDENTIFIED by '<DB_O11Y_PASSWORD>';
GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'db-o11y'@'%';
GRANT SELECT ON performance_schema.* TO 'db-o11y'@'%';

Replace <DB_O11Y_PASSWORD> with the password for the db-o11y MySQL user.

Grant object privileges for detailed data

Grant access to specific schemas when you want detailed information:

SQL
GRANT SELECT, SHOW VIEW ON payments.* TO 'db-o11y'@'%';

Alternatively, grant read access to all schemas:

SQL
GRANT SELECT, SHOW VIEW ON *.* TO 'db-o11y'@'%';

Verify user privileges

Verify that the user exists and has the expected privileges:

SQL
SHOW GRANTS FOR 'db-o11y'@'%';

+-------------------------------------------------------------------+
| Grants for db-o11y@%                                              |
+-------------------------------------------------------------------+
| GRANT PROCESS, REPLICATION CLIENT ON *.* TO `db-o11y`@`%`         |
| GRANT SELECT, SHOW VIEW ON *.* TO `db-o11y`@`%`                   |
+-------------------------------------------------------------------+

Increase digest length limits

Increase max_digest_length and verify the setting:

SQL
SHOW VARIABLES LIKE 'max_digest_length';

Expected result: Value is 4096.

Increase performance_schema_max_digest_length and verify the setting:

SQL
SHOW VARIABLES LIKE 'performance_schema_max_digest_length';

Expected result: Value is 4096.

Increase SQL text length limits (optional)

Increase performance_schema_max_sql_text_length to collect actual SQL text when you disable query redaction later. Verify the setting:

SQL
SHOW VARIABLES LIKE 'performance_schema_max_sql_text_length';

Expected result: Value is 4096.

Grant privileges to auto-enable consumers (optional)

Grant update privileges for the performance_schema.setup_consumers table if you want Alloy to auto-enable consumers:

SQL
GRANT UPDATE ON performance_schema.setup_consumers TO 'db-o11y'@'%';

Then, enable the Alloy option allow_update_performance_schema_settings as described in the reference documentation of the database_observability.mysql component.

Alternatively, enable consumers manually as described in the following sections.

Enable CPU consumer for samples manually (optional)

Enable cpu consumer when you want to collect cpu usage information together with query samples.

Check whether the events_statements_cpu consumer is enabled:

SQL
SELECT * FROM performance_schema.setup_consumers WHERE NAME = 'events_statements_cpu';

Enable the consumer if it’s disabled:

SQL
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME = 'events_statements_cpu';

The events_statements_cpu consumer disables when the database restarts. Recommended: Let Alloy auto-enable Performance Schema consumers. To do so, follow the instructions in the previous section “Grant privileges to auto-enable consumers”.

Enable wait event consumers manually (optional)

Enable wait event consumers when you want to collect wait events together with query samples.

Check whether the events_waits_current and events_waits_history consumers are enabled:

SQL
SELECT * FROM performance_schema.setup_consumers WHERE NAME IN ('events_waits_current', 'events_waits_history');

Enable the consumers if they’re disabled:

SQL
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME IN ('events_waits_current', 'events_waits_history');

These consumers disable when the database restarts. Recommended: Let Alloy auto-enable Performance Schema consumers on your behalf. To do so, follow the instructions in the previous section “Grant privileges to auto-enable consumers”.

Run and configure Alloy

Run Alloy and add the Database Observability configuration.

Run the latest Alloy version

Run Alloy version 1.11.0 or later with the --stability.level=experimental flag for the database_observability.mysql component. Find the latest stable version on Docker Hub.

Add the MySQL configuration blocks

Add these blocks to Alloy. Replace <DB_NAME>. Create a local.file with the Data Source Name string, for example, <DB_USER>:<DB_PASSWORD>@tcp(<DB_HOST>:<DB_PORT>)/:

Alloy
local.file "mysql_secret_<DB_NAME>" {
  filename  = "/var/lib/alloy/mysql_secret_<DB_NAME>"
  is_secret = true
}

prometheus.exporter.mysql "mysql_<DB_NAME>" {
  data_source_name  = local.file.mysql_secret_<DB_NAME>.content
  enable_collectors = ["perf_schema.eventsstatements"]
}

database_observability.mysql "mysql_<DB_NAME>" {
  data_source_name  = local.file.mysql_secret_<DB_NAME>.content
  forward_to        = [loki.relabel.database_observability_mysql_<DB_NAME>.receiver]
  targets           = prometheus.exporter.mysql.mysql_<DB_NAME>.targets

  // OPTIONAL: provide additional information specific to the cloud provider
  // that hosts the database to enable certain infrastructure observability
  // features. See documentation of `database_observability.mysql` for
  // other cloud providers.
  cloud_provider {
    aws {
      arn = "<AWS_RDS_DB_ARN>"
    }
  }
}

loki.relabel "database_observability_mysql_<DB_NAME>" {
  forward_to = [loki.write.logs_service.receiver]

  // OPTIONAL: add any additional relabeling rules
  // (must be consistent with rules in "discovery.relabel")
  rule {
    target_label = "instance"
    replacement  = "<INSTANCE_LABEL>"
  }
  rule {
    target_label = "<CUSTOM_LABEL_1>"
    replacement  = "<CUSTOM_VALUE_1>"
  }
}

discovery.relabel "database_observability_mysql_<DB_NAME>" {
  targets = database_observability.mysql.mysql_<DB_NAME>.targets

  rule {
    target_label = "job"
    replacement  = "integrations/db-o11y"
  }

  // OPTIONAL: add any additional relabeling rules
  // (must be consistent with rules in "loki.relabel")
  rule {
    target_label = "instance"
    replacement  = "<INSTANCE_LABEL>"
  }
  rule {
    target_label = "<CUSTOM_LABEL_1>"
    replacement  = "<CUSTOM_VALUE_1>"
  }
}

prometheus.scrape "database_observability_mysql_<DB_NAME>" {
  targets    = discovery.relabel.database_observability_mysql_<DB_NAME>.output
  forward_to = [prometheus.remote_write.metrics_service.receiver]
}

Replace the placeholders:

  • DB_NAME: Database name Alloy uses in component identifiers (appears in component names and secret filenames).
  • AWS_RDS_DB_ARN: AWS RDS database ARN for cloud provider integration (optional).
  • INSTANCE_LABEL: Value that sets the instance label on logs and metrics (optional).
  • CUSTOM_LABEL_1, CUSTOM_VALUE_1: Optional custom label key and value you attach to logs and metrics.
  • Secret file content DSN example: DB_USER:DB_PASSWORD@tcp(DB_HOST:DB_PORT)/".
    • DB_USER: Database user Alloy uses to connect (e.g. db-o11y).
    • DB_PASSWORD: Password for the database user.
    • DB_HOST: Hostname or IP address of the database.
    • DB_PORT: Database port number.

Find more about the options supported by the database_observability.mysql component in the reference documentation.

Add Prometheus and Loki write configuration

Add the Prometheus remote write and Loki write configuration. From Grafana Cloud, open your stack to get the URLs and generate API tokens:

Alloy
prometheus.remote_write "metrics_service" {
  endpoint {
    url = sys.env("GCLOUD_HOSTED_METRICS_URL")

    basic_auth {
      password = sys.env("GCLOUD_RW_API_KEY")
      username = sys.env("GCLOUD_HOSTED_METRICS_ID")
    }
  }
}

loki.write "logs_service" {
  endpoint {
    url = sys.env("GCLOUD_HOSTED_LOGS_URL")

    basic_auth {
      password = sys.env("GCLOUD_RW_API_KEY")
      username = sys.env("GCLOUD_HOSTED_LOGS_ID")
    }
  }
}

Replace the placeholders:

  • GCLOUD_HOSTED_METRICS_URL: Your Grafana Cloud Prometheus remote write URL.
  • GCLOUD_HOSTED_METRICS_ID: Your Grafana Cloud Prometheus instance ID (username).
  • GCLOUD_HOSTED_LOGS_URL: Your Grafana Cloud Loki write URL.
  • GCLOUD_HOSTED_LOGS_ID: Your Grafana Cloud Loki instance ID (username).
  • GCLOUD_RW_API_KEY: Grafana Cloud API token with write permissions.

Configure the k8s-monitoring Helm chart

Extend your values.yaml when you use the k8s-monitoring Helm chart:

YAML
alloy:
  image:
    repository: 'grafana/alloy'
    tag: <ALLOY_VERSION> # e.g. "v1.11.0"

  alloy:
    stabilityLevel: experimental

extraConfig: |
  // Add the config blocks for Database Observability
  prometheus.exporter.mysql "mysql_<DB_NAME>" {
    ...
  }
  ...
  database_observability.mysql "mysql_<DB_NAME>" {
    ...
  }
  ...

Replace the placeholders:

  • ALLOY_VERSION: Alloy stable release version you use, for example, v1.11.0.
  • DB_NAME: Database name Alloy uses in component identifiers.

Next steps

For an overview of key concepts, refer to Introduction to Database Observability.