Skip to content

Grafana Alloy MySQL Monitoring

Use Grafana Alloy on MySQL servers to ship MySQL and host metrics to Grafana Cloud. Alloy is Grafana’s collector: it scrapes exporters locally and remote-writes the results.

This guide assumes you are installing Alloy on a Linux server that already runs MySQL (or MariaDB) on localhost:3306. Store generated passwords in 1Password with the rest of the server credentials.

The Grafana Cloud collector wizard generates the fleet-management, Prometheus, and Loki blocks for this stack. Keep those generated values. Do not copy another server’s remotecfg id.

  1. Open collector setup

    Log in to Grafana Cloud and open Connections → Collector / Collector setup.

  2. Install Alloy

    Choose Alloy and follow the Linux install instructions for the target server. Run the install commands on the server itself.

    The installer writes /etc/alloy/config.alloy and sets GCLOUD_RW_API_KEY for Alloy’s systemd service. Leave that environment variable in place.

  3. Confirm the service is running

    Terminal window
    sudo systemctl status alloy.service

Alloy should not use the database root user. Create a dedicated exporter account with a tight privilege set and a connection cap.

  1. Generate a password

    Terminal window
    openssl rand -base64 48 | tr -dc 'A-Za-z0-9' | head -c 32; echo

    Store the password in 1Password before continuing. The command above produces alphanumeric characters only, so it is safe to paste into the Alloy DSN later.

  2. Open a MySQL admin session

    Terminal window
    sudo mysql

    Use whatever admin login the server already has if sudo mysql is not configured.

  3. Create the user and grants

    Replace YourGeneratedPassword with the password from step 1.

    CREATE USER 'exporter'@'localhost' IDENTIFIED BY 'YourGeneratedPassword' WITH MAX_USER_CONNECTIONS 3;
    GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'exporter'@'localhost';
    GRANT SELECT ON performance_schema.* TO 'exporter'@'localhost';
    FLUSH PRIVILEGES;

    MAX_USER_CONNECTIONS 3 stops the exporter from exhausting MySQL connection slots if scrapes overlap.

Edit the Alloy config and merge the MySQL and host-metrics blocks into the file the installer created.

Terminal window
sudo nano /etc/alloy/config.alloy

Keep the generated remotecfg, prometheus.remote_write, and loki.write blocks exactly as the wizard wrote them (URLs, usernames, and GCLOUD_RW_API_KEY). Set remotecfg id to the Forge server name, for example uk-ldn-project-01. Do not copy another server’s id.

Then append the following MySQL and system-metrics pipelines. Replace MYSQL_EXPORTER_PASSWORD with the password created above.

// ------- MySQL Export -------
prometheus.exporter.mysql "mysql" {
data_source_name = "exporter:MYSQL_EXPORTER_PASSWORD@(localhost:3306)/"
enable_collectors = [
"global_status",
"global_variables",
"slave_status",
"info_schema.innodb_metrics",
"info_schema.processlist",
"info_schema.tables",
"perf_schema.eventsstatements",
"perf_schema.file_instances",
"perf_schema.memory_events",
]
}
discovery.relabel "mysql" {
targets = prometheus.exporter.mysql.mysql.targets
rule {
target_label = "instance"
replacement = constants.hostname
}
}
prometheus.scrape "mysql" {
targets = discovery.relabel.mysql.output
forward_to = [prometheus.remote_write.metrics_service.receiver]
job_name = "mysql"
}
// ------- System Stats Export -------
discovery.relabel "integrations_node_exporter" {
targets = prometheus.exporter.unix.integrations_node_exporter.targets
rule {
target_label = "instance"
replacement = constants.hostname
}
rule {
target_label = "job"
replacement = "integrations/node_exporter"
}
}
prometheus.exporter.unix "integrations_node_exporter" {
disable_collectors = ["ipvs", "btrfs", "infiniband", "xfs", "zfs"]
filesystem {
fs_types_exclude = "^(autofs|binfmt_misc|bpf|cgroup2?|configfs|debugfs|devpts|devtmpfs|tmpfs|fusectl|hugetlbfs|iso9660|mqueue|nsfs|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|selinuxfs|squashfs|sysfs|tracefs)$"
mount_points_exclude = "^/(dev|proc|run/credentials/.+|sys|var/lib/docker/.+)($|/)"
mount_timeout = "5s"
}
}
prometheus.scrape "integrations_node_exporter" {
targets = discovery.relabel.integrations_node_exporter.output
forward_to = [prometheus.remote_write.metrics_service.receiver]
job_name = "integrations/node_exporter"
}
  1. Restart Alloy

    Terminal window
    sudo systemctl restart alloy.service
  2. Check the service

    Terminal window
    sudo systemctl status alloy.service

    It should be active (running). If it failed, inspect the logs:

    Terminal window
    sudo journalctl -u alloy.service -e

    Common causes are a syntax error in config.alloy, a duplicated component label, or a bad MySQL DSN/password.

  3. Confirm metrics in Grafana

    In Grafana Cloud, open Explore against the Prometheus datasource and look for:

    • mysql_up (should be 1)
    • mysql_global_status_uptime
    • node_cpu_seconds_total (host metrics)

    Filter on the server instance label (the machine hostname) if several collectors are reporting.

PipelineSourceTypical use
mysqlprometheus.exporter.mysqlConnections, InnoDB, processlist, statement stats, replication
integrations/node_exporterprometheus.exporter.unixCPU, memory, disk, filesystem

Host metrics complement Forge’s server resource monitors. Alloy is the source for Grafana dashboards and longer-term trends; Forge monitors remain the first-line alerting on the server itself.