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.
Install Alloy
Section titled “Install Alloy”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.
-
Open collector setup
Log in to Grafana Cloud and open Connections → Collector / Collector setup.
-
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.alloyand setsGCLOUD_RW_API_KEYfor Alloy’s systemd service. Leave that environment variable in place. -
Confirm the service is running
Terminal window sudo systemctl status alloy.service
Create the MySQL exporter user
Section titled “Create the MySQL exporter user”Alloy should not use the database root user. Create a dedicated exporter account with a tight privilege set and a connection cap.
-
Generate a password
Terminal window openssl rand -base64 48 | tr -dc 'A-Za-z0-9' | head -c 32; echoStore the password in 1Password before continuing. The command above produces alphanumeric characters only, so it is safe to paste into the Alloy DSN later.
-
Open a MySQL admin session
Terminal window sudo mysqlUse whatever admin login the server already has if
sudo mysqlis not configured. -
Create the user and grants
Replace
YourGeneratedPasswordwith 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 3stops the exporter from exhausting MySQL connection slots if scrapes overlap.
Configure Alloy
Section titled “Configure Alloy”Edit the Alloy config and merge the MySQL and host-metrics blocks into the file the installer created.
sudo nano /etc/alloy/config.alloyKeep 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"}Restart and verify
Section titled “Restart and verify”-
Restart Alloy
Terminal window sudo systemctl restart alloy.service -
Check the service
Terminal window sudo systemctl status alloy.serviceIt should be
active (running). If it failed, inspect the logs:Terminal window sudo journalctl -u alloy.service -eCommon causes are a syntax error in
config.alloy, a duplicated component label, or a bad MySQL DSN/password. -
Confirm metrics in Grafana
In Grafana Cloud, open Explore against the Prometheus datasource and look for:
mysql_up(should be1)mysql_global_status_uptimenode_cpu_seconds_total(host metrics)
Filter on the server
instancelabel (the machine hostname) if several collectors are reporting.
What this collects
Section titled “What this collects”| Pipeline | Source | Typical use |
|---|---|---|
mysql | prometheus.exporter.mysql | Connections, InnoDB, processlist, statement stats, replication |
integrations/node_exporter | prometheus.exporter.unix | CPU, 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.