General availability (GA) Open source

database_observability.mysql

database_observability.mysql connects to a MySQL database and collects observability data from the performance_schema and information_schema. The component collects query details, schema information, explain plans, query samples, and lock information. It forwards this data as log entries to Loki receivers and exports targets for Prometheus scraping.

Usage

Alloy
database_observability.mysql "<LABEL>" {
  data_source_name = <DATA_SOURCE_NAME>
  forward_to       = [<LOKI_RECEIVERS>]
}

Arguments

You can use the following arguments with database_observability.mysql:

NameTypeDescriptionDefaultRequired
data_source_namesecretData Source Name for the MySQL server to connect to. Required when no database_instance blocks are defined.no
forward_tolist(LogsReceiver)Where to forward log entries after processing.yes
targetslist(map(string))List of external targets to scrape.no
disable_collectorslist(string)A list of collectors to disable from the default set.no
enable_collectorslist(string)A list of collectors to enable on top of the default set.no
exclude_schemaslist(string)A list of schemas to exclude from monitoring.["alloydbadmin", "alloydbmetadata", "azure_maintenance", "azure_sys", "cloudsqladmin", "rdsadmin"]no
allow_update_performance_schema_settingsbooleanWhether to allow updates to performance_schema settings in any collector. Enable this in conjunction with other collector-specific settings where required.falseno

The following collectors are configurable:

NameDescriptionEnabled by default
query_detailsCollect queries information.yes
schema_detailsCollect schemas and tables from information_schema.yes
query_samplesCollect query samples.yes
setup_consumersCollect enabled performance_schema.setup_consumers.yes
setup_actorsCheck and update performance_schema.setup_actors settings.yes
locksCollect queries that are waiting/blocking other queries.no
explain_plansCollect explain plans information.yes

Blocks

You can use the following blocks with database_observability.mysql:

cloud_provider

The cloud_provider block has no attributes. It contains zero or one of the aws, azure, or gcp blocks. You use the cloud_provider block to provide information related to the cloud provider that hosts the database under observation. This information is appended as labels to the collected metrics. The labels make it easier for you to filter and group your metrics.

aws

The aws block supplies the ARN identifier for the database being monitored.

NameTypeDescriptionDefaultRequired
arnstringThe ARN associated with the database under observation.yes

azure

The azure block supplies the identifying information for the database being monitored.

NameTypeDescriptionDefaultRequired
subscription_idstringThe Subscription ID for your Azure account.yes
resource_groupstringThe Resource Group that holds the database resource.yes
server_namestringThe database server name, for example orders-db for the host orders-db.mysql.database.azure.com.no

gcp

The gcp block supplies the identifying information for the GCP Cloud SQL database being monitored.

NameTypeDescriptionDefaultRequired
connection_namestringThe Cloud SQL instance connection name in the format project:region:instance, for example my-project:us-central1:my-db.yes

database_instance

The database_instance block defines one database server to monitor. Repeat the block to monitor several databases with a single component. The block label must be unique across database_instance blocks and identifies the database in the component’s metrics endpoint path. Each database_instance block must also point to a distinct server: two blocks that resolve to the same host, port, and database name are rejected.

NameTypeDescriptionDefaultRequired
data_source_namesecretData Source Name for the MySQL server to connect to.yes

Each database_instance block can also contain a [cloud_provider][cloud_provider] block that applies to that database only.

The component always embeds a mysqld_exporter for each database_instance block and serves its metrics on the block’s metrics path. Use the [prometheus_exporter][prometheus_exporter] block to configure it. External exporter targets are only supported in the top-level single-DSN form.

When you define database_instance blocks, don’t set the top-level data_source_name, targets, and cloud_provider arguments. They’re mutually exclusive with database_instance blocks. All other arguments and blocks, such as collector settings and prometheus_exporter, apply to every configured database.

The metrics for each database are served on a separate /db/<LABEL>/metrics path under the component’s HTTP endpoint, and the exported targets point to the corresponding path. When you don’t define database_instance blocks, the component serves metrics on its historical /metrics path. The metrics endpoints are served exactly at those paths: requests to any other path under the component’s HTTP endpoint return HTTP 404.

For example:

Alloy
database_observability.mysql "pool" {
  forward_to = [loki.write.logs_service.receiver]

  database_instance "orders" {
    data_source_name = sys.env("ORDERS_DSN")

    cloud_provider {
      aws {
        arn = "orders-rds-db-arn"
      }
    }
  }

  database_instance "billing" {
    data_source_name = sys.env("BILLING_DSN")
  }
}

clustering

NameTypeDescriptionDefaultRequired
enabledboolEnables distributing databases with other cluster nodes.falseyes

When Alloy is using clustering, and enabled is set to true, then this database_observability.mysql component instance opts-in to distributing its configured databases between all cluster nodes.

Clustering assumes that all cluster nodes are running with the same configuration file. All component instances opting in to clustering use the instance key of each configured database, <network>(<host>:<port>)/<dbname>, and a consistent hashing algorithm to determine ownership of each database between the cluster peers. Each peer then only collects from the subset of databases it’s responsible for, and only exports the targets of those databases, so prometheus.scrape components on the same node scrape exactly the databases the node owns. When a node joins or leaves the cluster, every peer recalculates ownership: expect a short gap or a brief duplicate collection for a database while its ownership moves. This includes the collectors that update performance_schema settings, such as setup_actors and setup_consumers, which can briefly run from two nodes during the move: their updates are idempotent. While the cluster isn’t yet ready to admit traffic, for example while it’s still forming and waiting for the minimum cluster size, the component doesn’t collect from any database.

Clustering is also useful with a single database: when several cluster nodes run an identical configuration, exactly one node collects from the database at a time, which gives you a highly available setup without duplicate collection.

If Alloy is not running in clustered mode, then the block is a no-op and database_observability.mysql collects from every configured database.

setup_consumers

NameTypeDescriptionDefaultRequired
collect_intervaldurationHow frequently to collect performance_schema.setup_consumers information from the database."1h"no

query_details

NameTypeDescriptionDefaultRequired
collect_intervaldurationHow frequently to collect information from database."1m"no
statements_limitintegerMax number of recent queries to collect details for.250no

schema_details

NameTypeDescriptionDefaultRequired
collect_intervaldurationHow frequently to collect information from database."1m"no
cache_enabledbooleanDeprecated. Whether to enable caching of table definitions.trueno
cache_sizeintegerDeprecated. Cache size.256no
cache_ttldurationDeprecated. Cache TTL."10m"no

The cache_enabled, cache_size, and cache_ttl settings are deprecated: they are accepted for backward compatibility, but ignored.

explain_plans

NameTypeDescriptionDefaultRequired
collect_intervaldurationHow frequently to collect information from database."1m"no
initial_lookbackdurationHow far back to look for explain plan queries on the first collection interval."24h"no
per_collect_ratiofloatRatio of explain plan queries to collect per collect interval.1.0no

locks

NameTypeDescriptionDefaultRequired
collect_intervaldurationHow frequently to collect information from database."30s"no
thresholddurationThreshold for locks to be considered slow. Locks that exceed this duration are logged."1s"no

query_samples

NameTypeDescriptionDefaultRequired
collect_intervaldurationHow frequently to collect information from database."10s"no
disable_query_redactionboolCollect unredacted SQL query text (including query parameters) and query error messages.falseno
auto_enable_setup_consumersbooleanEnables specific performance_schema.setup_consumers options. You must also enable allow_update_performance_schema_settings.falseno
setup_consumers_check_intervaldurationHow frequently to check if setup_consumers are correctly enabled."1h"no
sample_min_durationdurationMinimum duration for query samples to be collected. Set to “0s” to disable filtering and collect all samples regardless of their duration."0s"no
wait_event_min_durationdurationMinimum duration for a wait event to be collected. Set to “0s” to disable filtering and collect all wait events regardless of their duration."1us"no
enable_pre_classified_wait_eventsbooleanWhen true, emits telemetry data with pre-classified wait event information.falseno

setup_actors

NameTypeDescriptionDefaultRequired
auto_update_setup_actorsbooleanEnables updates to performance_schema.setup_actors settings. You must also enable allow_update_performance_schema_settings.falseno
collect_intervaldurationHow frequently to check if setup_actors are configured correctly."1h"no

health_check

NameTypeDescriptionDefaultRequired
collect_intervaldurationHow frequently to run health checks."1h"no

prometheus_exporter

The prometheus_exporter block configures the embedded mysqld_exporter scrapers. The data_source_name is inherited from the parent block.

Refer to prometheus.exporter.mysql docs for the full list of supported arguments and sub-blocks.

Example

Alloy
database_observability.mysql "orders_db" {
  data_source_name = "user:pass@tcp(mysql:3306)/"
  forward_to       = [loki.relabel.orders_db.receiver]
  targets          = prometheus.exporter.mysql.orders_db.targets

  enable_collectors = ["query_samples", "explain_plans"]

  cloud_provider {
    aws {
      arn = "your-rds-db-arn"
    }
  }
}

prometheus.exporter.mysql "orders_db" {
  data_source_name  = "user:pass@tcp(mysql:3306)/"
  enable_collectors = ["perf_schema.eventsstatements"]
}

loki.relabel "orders_db" {
  forward_to = [loki.write.logs_service.receiver]
  rule {
    target_label = "job"
    replacement  = "integrations/db-o11y"
  }
  rule {
    target_label = "instance"
    replacement  = "orders_db"
  }
}

discovery.relabel "orders_db" {
  targets = database_observability.mysql.orders_db.targets

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

prometheus.scrape "orders_db" {
  targets    = discovery.relabel.orders_db.targets
  job_name   = "integrations/db-o11y"
  forward_to = [prometheus.remote_write.metrics_service.receiver]
}

prometheus.remote_write "metrics_service" {
  endpoint {
    url = sys.env("<GRAFANA_CLOUD_HOSTED_METRICS_URL>")
    basic_auth {
      username = sys.env("<GRAFANA_CLOUD_HOSTED_METRICS_ID>")
      password = sys.env("<GRAFANA_CLOUD_RW_API_KEY>")
    }
  }
}

loki.write "logs_service" {
  endpoint {
    url = sys.env("<GRAFANA_CLOUD_HOSTED_LOGS_URL>")
    basic_auth {
      username = sys.env("<GRAFANA_CLOUD_HOSTED_LOGS_ID>")
      password = sys.env("<GRAFANA_CLOUD_RW_API_KEY>")
    }
  }
}

Replace the following:

  • <GRAFANA_CLOUD_HOSTED_METRICS_URL>: The URL for your Grafana Cloud hosted metrics.
  • <GRAFANA_CLOUD_HOSTED_METRICS_ID>: The user ID for your Grafana Cloud hosted metrics.
  • <GRAFANA_CLOUD_RW_API_KEY>: Your Grafana Cloud API key.
  • <GRAFANA_CLOUD_HOSTED_LOGS_URL>: The URL for your Grafana Cloud hosted logs.
  • <GRAFANA_CLOUD_HOSTED_LOGS_ID>: The user ID for your Grafana Cloud hosted logs.

Compatible components

database_observability.mysql can accept arguments from the following components:

database_observability.mysql has exports that can be consumed by the following components:

Note

Connecting some components may not be sensible or components may require further configuration to make the connection work correctly. Refer to the linked documentation for more details.