Collect MySQL database metrics and logs
You can configure Alloy to collect database observability data from MySQL servers including metrics, logs, and performance schema statistics. Forward this data to Grafana Cloud, Prometheus, Loki, or any compatible observability backend.
You can accomplish the following with Alloy:
- Collect query performance data, explain plans, and lock information from MySQL.
- Monitor schema and table statistics.
- Forward database observability logs to Loki.
- Scrape MySQL metrics with Prometheus.
Components used in this topic
database_observability.mysqlprometheus.exporter.mysqlloki.relabeldiscovery.relabelprometheus.scrapeprometheus.remote_writeloki.write
Before you begin
- Ensure you have a running MySQL server with access credentials.
- Enable the MySQL
performance_schemaon your MySQL server. Refer to the MySQL performance_schema documentation for setup instructions. - Have write access to a Prometheus-compatible endpoint or Grafana Cloud for storing metrics.
- Have write access to a Loki-compatible endpoint or Grafana Cloud for storing logs.
- Be familiar with the concept of Components in Alloy.
Collect MySQL database observability data
The database_observability.mysql component connects to a MySQL database and collects performance schema data.
This data includes query details, execution plans, and lock information forwarded as logs to Loki.
The component also exports targets that can be scraped with Prometheus to collect MySQL metrics.
To collect MySQL observability data and forward it to Grafana Cloud, complete the following steps:
Add a
database_observability.mysqlcomponent to your configuration file.database_observability.mysql "<LABEL>" { data_source_name = "<MYSQL_DSN>" forward_to = [loki.relabel.<LABEL>.receiver] targets = prometheus.exporter.mysql.<LABEL>.targets enable_collectors = ["query_samples", "explain_plans"] cloud_provider { aws { arn = "<AWS_RDS_ARN>" } } }Replace the following:
<LABEL>: The Alloy component label, such asprod_mysql.<MYSQL_DSN>: The MySQL Data Source Name, such asuser:pass@tcp(mysql:3306)/. Refer to the DSN documentation for the full DSN format.<AWS_RDS_ARN>: The ARN of your AWS RDS database instance, such asarn:aws:rds:us-east-1:123456789:db/prod-mysql. If using Azure or GCP, use the corresponding cloud provider block instead.
For more information, refer to the
database_observability.mysqldocumentation.Add a
prometheus.exporter.mysqlcomponent to export MySQL metrics.prometheus.exporter.mysql "<LABEL>" { data_source_name = "<MYSQL_DSN>" enable_collectors = ["perf_schema.eventsstatements"] }Replace the following:
<LABEL>: Must match the label used for thedatabase_observability.mysqlcomponent.<MYSQL_DSN>: The same MySQL Data Source Name as thedatabase_observability.mysqlcomponent.
For more information, refer to the
prometheus.exporter.mysqldocumentation.Add a
loki.relabelcomponent to standardize labels on database logs.loki.relabel "<LABEL>" { forward_to = [loki.write.logs_service.receiver] rule { target_label = "job" replacement = "integrations/db-o11y" } rule { target_label = "instance" replacement = "<LABEL>" } }Replace the following:
<LABEL>: Must match the label used for thedatabase_observability.mysqlcomponent.
For more information, refer to the
loki.relabeldocumentation.Add a
discovery.relabelcomponent to standardize labels on Prometheus targets.discovery.relabel "<LABEL>" { targets = database_observability.mysql.<LABEL>.targets rule { target_label = "job" replacement = "integrations/db-o11y" } rule { target_label = "instance" replacement = "<LABEL>" } }Replace the following:
<LABEL>: Must match the label used for thedatabase_observability.mysqlcomponent.
For more information, refer to the
discovery.relabeldocumentation.Add a
prometheus.scrapecomponent to scrape the relabeled targets fromdiscovery.relabel, which are sourced from thedatabase_observability.mysqlcomponent’s exported targets.prometheus.scrape "<LABEL>" { targets = discovery.relabel.<LABEL>.output job_name = "integrations/db-o11y" forward_to = [prometheus.remote_write.metrics_service.receiver] }Replace the following:
<LABEL>: Must match the label used for thedatabase_observability.mysqlcomponent.
For more information, refer to the
prometheus.scrapedocumentation.Add a
prometheus.remote_writecomponent to send metrics to Grafana Cloud or Prometheus.prometheus.remote_write "metrics_service" { endpoint { url = "<GRAFANA_CLOUD_HOSTED_METRICS_URL>" basic_auth { username = "<GRAFANA_CLOUD_HOSTED_METRICS_ID>" password = "<GRAFANA_CLOUD_RW_API_KEY>" } } }Replace the following:
<GRAFANA_CLOUD_HOSTED_METRICS_URL>: The URL for your Grafana Cloud hosted metrics endpoint.<GRAFANA_CLOUD_HOSTED_METRICS_ID>: The user ID for your Grafana Cloud hosted metrics.<GRAFANA_CLOUD_RW_API_KEY>: Your Grafana Cloud API key.
For more information, refer to the
prometheus.remote_writedocumentation.Add a
loki.writecomponent to send logs to Grafana Cloud or Loki.loki.write "logs_service" { endpoint { url = "<GRAFANA_CLOUD_HOSTED_LOGS_URL>" basic_auth { username = "<GRAFANA_CLOUD_HOSTED_LOGS_ID>" password = "<GRAFANA_CLOUD_RW_API_KEY>" } } }Replace the following:
<GRAFANA_CLOUD_HOSTED_LOGS_URL>: The URL for your Grafana Cloud hosted logs endpoint.<GRAFANA_CLOUD_HOSTED_LOGS_ID>: The user ID for your Grafana Cloud hosted logs.<GRAFANA_CLOUD_RW_API_KEY>: Your Grafana Cloud API key.
For more information, refer to the
loki.writedocumentation.
Complete configuration
The following is a complete configuration that collects MySQL database observability data and forwards it to Grafana Cloud.
database_observability.mysql "example" {
data_source_name = "<MYSQL_DSN>"
forward_to = [loki.relabel.example.receiver]
targets = prometheus.exporter.mysql.example.targets
enable_collectors = ["query_samples", "explain_plans"]
cloud_provider {
aws {
arn = "<AWS_RDS_ARN>"
}
}
}
prometheus.exporter.mysql "example" {
data_source_name = "<MYSQL_DSN>"
enable_collectors = ["perf_schema.eventsstatements"]
}
loki.relabel "example" {
forward_to = [loki.write.logs_service.receiver]
rule {
target_label = "job"
replacement = "integrations/db-o11y"
}
rule {
target_label = "instance"
replacement = "example"
}
}
discovery.relabel "example" {
targets = database_observability.mysql.example.targets
rule {
target_label = "job"
replacement = "integrations/db-o11y"
}
rule {
target_label = "instance"
replacement = "example"
}
}
prometheus.scrape "example" {
targets = discovery.relabel.example.output
job_name = "integrations/db-o11y"
forward_to = [prometheus.remote_write.metrics_service.receiver]
}
prometheus.remote_write "metrics_service" {
endpoint {
url = "<GRAFANA_CLOUD_HOSTED_METRICS_URL>"
basic_auth {
username = "<GRAFANA_CLOUD_HOSTED_METRICS_ID>"
password = "<GRAFANA_CLOUD_RW_API_KEY>"
}
}
}
loki.write "logs_service" {
endpoint {
url = "<GRAFANA_CLOUD_HOSTED_LOGS_URL>"
basic_auth {
username = "<GRAFANA_CLOUD_HOSTED_LOGS_ID>"
password = "<GRAFANA_CLOUD_RW_API_KEY>"
}
}
}Replace the following:
<MYSQL_DSN>: The MySQL Data Source Name for your MySQL server.<AWS_RDS_ARN>: The ARN of your AWS RDS database instance.<GRAFANA_CLOUD_HOSTED_METRICS_URL>: The URL for your Grafana Cloud hosted metrics endpoint.<GRAFANA_CLOUD_HOSTED_METRICS_ID>: The user ID for your Grafana Cloud hosted metrics.<GRAFANA_CLOUD_HOSTED_LOGS_URL>: The URL for your Grafana Cloud hosted logs endpoint.<GRAFANA_CLOUD_HOSTED_LOGS_ID>: The user ID for your Grafana Cloud hosted logs.<GRAFANA_CLOUD_RW_API_KEY>: Your Grafana Cloud API key.