MySQL OpenTelemetry Dashboards¶
MySQL database monitoring dashboards using OpenTelemetry MySQL receiver metrics.
Overview¶
These dashboards provide comprehensive monitoring for MySQL database instances, including connections, buffer pool efficiency, query performance, and InnoDB metrics.
Dashboards¶
| Dashboard | File | Description |
|---|---|---|
| Overview | mysql-overview-esql.yaml |
Comprehensive MySQL metrics using ES|QL queries |
| Extended | mysql-extended-esql.yaml |
Extended MySQL metrics for optional/disabled metrics |
Both dashboards include navigation links for easy switching between views.
Dashboard Definitions¶
Overview (mysql-overview-esql.yaml)
---
# MySQL OpenTelemetry Overview Dashboard (ES|QL Version)
# Comprehensive MySQL metrics dashboard using OpenTelemetry MySQL receiver
# Uses ES|QL with TS command for time-series optimization
#
# Metrics reference: https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/mysqlreceiver
dashboards:
- id: mysql-otel-overview-esql
name: '[Metrics MySQL] Overview'
description: Comprehensive MySQL metrics dashboard using OpenTelemetry MySQL receiver (ES|QL version with TS command)
controls:
- type: options
label: MySQL Host
data_view: metrics-*
field: resource.attributes.host.name
- type: options
label: MySQL Instance
data_view: metrics-*
field: resource.attributes.service.instance.id
filters:
- field: data_stream.dataset
equals: mysqlreceiver.otel
panels:
# Navigation Links
- title: Navigation Links
size: {w: 48, h: 2}
links:
layout: horizontal
items:
- label: MySQL Overview
dashboard: mysql-otel-overview-esql
- label: MySQL Extended
dashboard: mysql-otel-extended-esql
# Overview Metrics Row (y=2, h=6)
- title: Active Connections
description: Connected client threads. Excludes aborted and disconnected threads.
hide_title: true
size: {w: 12, h: 4}
esql:
type: metric
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE attributes.kind == "connected"
- STATS active_connections = MAX(mysql.threads)
primary:
field: active_connections
label: Active Connections
format:
type: number
decimals: 0
- title: Buffer Pool Efficiency
description: >-
Clean pages / total pages. Higher = efficient memory use. Lower =
more dirty pages requiring flush.
hide_title: true
size: {w: 12, h: 4}
esql:
type: metric
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.buffer_pool.usage IS NOT NULL
- STATS clean_pages = MAX(mysql.buffer_pool.usage) BY attributes.status
- STATS total = SUM(clean_pages), clean = SUM(CASE(attributes.status == "clean", clean_pages, 0))
- EVAL efficiency = clean / total
primary:
field: efficiency
label: Buffer Pool Efficiency
format:
type: percent
- title: InnoDB Operations Rate
hide_title: true
size: {w: 12, h: 4}
esql:
type: metric
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.operations IS NOT NULL
- STATS ops_rate = SUM(RATE(mysql.operations))
primary:
field: ops_rate
label: InnoDB Ops/sec
- title: Handler Operations Rate
hide_title: true
size: {w: 12, h: 4}
esql:
type: metric
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.handlers IS NOT NULL
- STATS handler_rate = SUM(RATE(mysql.handlers))
primary:
field: handler_rate
label: Handler Ops/sec
# Buffer Pool Performance Section (y=8)
- title: Buffer Pool Usage Over Time
size: {w: 24, h: 9}
esql:
type: line
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.buffer_pool.usage IS NOT NULL
- STATS usage = MAX(mysql.buffer_pool.usage) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), status = attributes.status
- SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: usage
label: Buffer Pool Usage
format:
type: bytes
breakdown:
field: status
- title: Buffer Pool Pages
size: {w: 24, h: 9}
esql:
type: line
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.buffer_pool.pages IS NOT NULL
- STATS pages = MAX(mysql.buffer_pool.pages) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), kind = attributes.kind
- SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: pages
label: Buffer Pool Pages
breakdown:
field: kind
- title: Buffer Pool Operations
size: {w: 24, h: 9}
esql:
type: line
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.buffer_pool.operations IS NOT NULL
- STATS ops_rate = SUM(RATE(mysql.buffer_pool.operations)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), operation =
attributes.operation
- SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: ops_rate
label: Operations/sec
breakdown:
field: operation
- title: Buffer Pool Page Flushes
size: {w: 24, h: 9}
esql:
type: line
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.buffer_pool.page_flushes IS NOT NULL
- STATS flush_rate = SUM(RATE(mysql.buffer_pool.page_flushes)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend)
- SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: flush_rate
label: Page Flushes/sec
# InnoDB Operations Section (y=26)
- title: Row Operations
size: {w: 24, h: 9}
esql:
type: line
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.row_operations IS NOT NULL
- STATS row_ops_rate = SUM(RATE(mysql.row_operations)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), operation = attributes.operation
- SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: row_ops_rate
label: Row Ops/sec
breakdown:
field: operation
- title: Page Operations
size: {w: 24, h: 9}
esql:
type: line
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.page_operations IS NOT NULL
- STATS page_ops_rate = SUM(RATE(mysql.page_operations)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), operation = attributes.operation
- SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: page_ops_rate
label: Page Ops/sec
breakdown:
field: operation
- title: InnoDB Operations (fsyncs, reads, writes)
size: {w: 24, h: 9}
esql:
type: line
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.operations IS NOT NULL
- STATS ops_rate = SUM(RATE(mysql.operations)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), operation = attributes.operation
- SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: ops_rate
label: Operations/sec
breakdown:
field: operation
- title: Double Writes
size: {w: 24, h: 9}
esql:
type: line
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.double_writes IS NOT NULL
- STATS double_writes_rate = SUM(RATE(mysql.double_writes)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), kind = attributes.kind
- SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: double_writes_rate
label: Double Writes/sec
breakdown:
field: kind
# Handler Operations Section (y=44)
- title: Handler Operations
size: {w: 48, h: 9}
description: Handler operations rate by type
esql:
type: line
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.handlers IS NOT NULL
- STATS handler_rate = SUM(RATE(mysql.handlers)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), kind = attributes.kind
- SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: handler_rate
label: Handler Ops/sec
breakdown:
field: kind
# Locks & Waits Section (y=53)
- title: Lock Waits
size: {w: 24, h: 9}
esql:
type: line
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.locks IS NOT NULL
- STATS lock_rate = SUM(RATE(mysql.locks)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), kind = attributes.kind
- SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: lock_rate
label: Locks/sec
breakdown:
field: kind
- title: Row Lock Waits
size: {w: 24, h: 9}
esql:
type: line
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.row_locks IS NOT NULL
- STATS row_lock_rate = SUM(RATE(mysql.row_locks)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), kind = attributes.kind
- SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: row_lock_rate
label: Row Locks/sec
breakdown:
field: kind
# Log Operations Section (y=62)
- title: Log Operations
size: {w: 48, h: 9}
esql:
type: line
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.log_operations IS NOT NULL
- STATS log_ops_rate = SUM(RATE(mysql.log_operations)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), operation = attributes.operation
- SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: log_ops_rate
label: Log Ops/sec
breakdown:
field: operation
# Table I/O Waits Section (y=71)
- title: Table I/O Waits/sec by Table
size: {w: 24, h: 9}
esql:
type: line
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.table.io.wait.count IS NOT NULL
- STATS table_io_wait_rate = SUM(RATE(mysql.table.io.wait.count)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), table
= attributes.table
- SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: table_io_wait_rate
label: Table I/O Waits/sec
breakdown:
field: table
- title: Index I/O Waits/sec by Index
size: {w: 24, h: 9}
esql:
type: line
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.index.io.wait.count IS NOT NULL
- STATS index_io_wait_rate = SUM(RATE(mysql.index.io.wait.count)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), index
= attributes.index
- SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: index_io_wait_rate
label: Index I/O Waits/sec
breakdown:
field: index
# Resources Section (y=80)
- title: Opened Resources
size: {w: 24, h: 9}
esql:
type: line
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.opened_resources IS NOT NULL
- STATS opened_rate = SUM(RATE(mysql.opened_resources)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), kind = attributes.kind
- SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: opened_rate
label: Opened Resources/sec
breakdown:
field: kind
- title: Temporary Resources
size: {w: 24, h: 9}
esql:
type: line
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.tmp_resources IS NOT NULL
- STATS tmp_rate = SUM(RATE(mysql.tmp_resources)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), resource = attributes.resource
- SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: tmp_rate
label: Temp Resources/sec
breakdown:
field: resource
# Threads & Sorts Section (y=89)
- title: Thread Metrics
size: {w: 24, h: 9}
esql:
type: line
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.threads IS NOT NULL
- STATS thread_count = MAX(mysql.threads) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), kind = attributes.kind
- SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: thread_count
label: Threads
format:
type: number
decimals: 0
breakdown:
field: kind
- title: Sort Operations
size: {w: 24, h: 9}
esql:
type: line
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.sorts IS NOT NULL
- STATS sorts_rate = SUM(RATE(mysql.sorts)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), kind = attributes.kind
- SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: sorts_rate
label: Sorts/sec
breakdown:
field: kind
# Uptime & Connection Stats (y=98)
- title: MySQL Uptime
size: {w: 24, h: 9}
description: MySQL server uptime rate (should be 1 second/second when running)
esql:
type: line
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.uptime IS NOT NULL
- STATS uptime_rate = SUM(RATE(mysql.uptime)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend)
- SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: uptime_rate
label: Uptime Rate (sec/sec)
- title: MySQLx Connections
size: {w: 24, h: 9}
esql:
type: line
query:
- TS metrics-*
- WHERE data_stream.dataset == "mysqlreceiver.otel"
- WHERE mysql.mysqlx_connections IS NOT NULL
- STATS mysqlx_conn_rate = SUM(RATE(mysql.mysqlx_connections)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), status =
attributes.status
- SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: mysqlx_conn_rate
label: MySQLx Connections/sec
breakdown:
field: status
Extended (mysql-extended-esql.yaml)
---
# MySQL OpenTelemetry Extended Dashboard (ES|QL Version)
# Dashboard for optional MySQL metrics that require explicit configuration to enable
# Uses ES|QL with TS command for time-series optimization
#
# These metrics are disabled by default in the MySQL receiver. To enable them, update
# your OpenTelemetry Collector configuration for the MySQL receiver.
#
# Metrics reference: https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/mysqlreceiver
dashboards:
- id: mysql-otel-extended-esql
name: '[Metrics MySQL] Extended'
description: Extended MySQL metrics dashboard for optional metrics (connection, query, replication, table metrics)
controls:
- type: options
label: MySQL Host
data_view: metrics-*
field: resource.attributes.host.name
- type: options
label: MySQL Instance
data_view: metrics-*
field: resource.attributes.service.instance.id
filters:
- field: data_stream.dataset
equals: mysqlreceiver.otel
panels:
# Navigation Links
- title: Navigation Links
size: {w: 48, h: 2}
links:
layout: horizontal
items:
- label: MySQL Overview
dashboard: mysql-otel-overview-esql
- label: MySQL Extended
dashboard: mysql-otel-extended-esql
# Info Panel about Optional Metrics
- size: {w: 48, h: 5}
markdown:
content: |
## Optional Metrics Dashboard
This dashboard displays **optional metrics** that are disabled by default in the MySQL receiver.
To enable these metrics, update your MySQL receiver configuration in the OpenTelemetry Collector.
If panels show no data, the corresponding metric has not been enabled.
# Connection Metrics Section (y=7)
- title: Connection Count
size: {w: 24, h: 9}
description: Number of connections (mysql.connection.count)
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "mysqlreceiver.otel"
| WHERE mysql.connection.count IS NOT NULL
| STATS connection_count = MAX(mysql.connection.count) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend)
| SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: connection_count
label: Connection Count
format:
type: number
decimals: 0
- title: Max Used Connections
size: {w: 24, h: 9}
description: Maximum number of connections used (mysql.max_used_connections)
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "mysqlreceiver.otel"
| WHERE mysql.max_used_connections IS NOT NULL
| STATS max_connections = MAX(mysql.max_used_connections) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend)
| SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: max_connections
label: Max Used Connections
format:
type: number
decimals: 0
- title: Connection Errors
size: {w: 48, h: 9}
description: Connection errors by type (mysql.connection.errors)
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "mysqlreceiver.otel"
| WHERE mysql.connection.errors IS NOT NULL
| STATS error_count = MAX(mysql.connection.errors) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), error = attributes.error
| SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: error_count
label: Errors
format:
type: number
decimals: 0
breakdown:
field: error
# Query Metrics Section (y=25)
- title: Query Count
size: {w: 24, h: 9}
description: Total query count rate (mysql.query.count)
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "mysqlreceiver.otel"
| WHERE mysql.query.count IS NOT NULL
| STATS query_rate = SUM(RATE(mysql.query.count)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend)
| SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: query_rate
label: Queries/sec
- title: Slow Query Count
size: {w: 24, h: 9}
description: Slow query rate (mysql.query.slow.count)
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "mysqlreceiver.otel"
| WHERE mysql.query.slow.count IS NOT NULL
| STATS slow_query_rate = SUM(RATE(mysql.query.slow.count)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend)
| SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: slow_query_rate
label: Slow Queries/sec
- title: Client Query Count
size: {w: 48, h: 9}
description: Client query count rate (mysql.query.client.count)
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "mysqlreceiver.otel"
| WHERE mysql.query.client.count IS NOT NULL
| STATS client_query_rate = SUM(RATE(mysql.query.client.count)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend)
| SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: client_query_rate
label: Client Queries/sec
# Command Metrics Section (y=43)
- title: Commands by Type
size: {w: 48, h: 9}
description: Command execution rate by type (mysql.commands)
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "mysqlreceiver.otel"
| WHERE mysql.commands IS NOT NULL
| STATS command_rate = SUM(RATE(mysql.commands)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), command = attributes.command
| SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: command_rate
label: Commands/sec
breakdown:
field: command
# Replication Metrics Section (y=52)
- title: Replica Time Behind Source
size: {w: 24, h: 9}
description: Replication lag in seconds (mysql.replica.time_behind_source)
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "mysqlreceiver.otel"
| WHERE mysql.replica.time_behind_source IS NOT NULL
| STATS lag_seconds = MAX(mysql.replica.time_behind_source) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend)
| SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: lag_seconds
label: Seconds Behind Source
- title: Replica SQL Delay
size: {w: 24, h: 9}
description: Configured replication delay (mysql.replica.sql_delay)
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "mysqlreceiver.otel"
| WHERE mysql.replica.sql_delay IS NOT NULL
| STATS sql_delay = MAX(mysql.replica.sql_delay) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend)
| SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: sql_delay
label: SQL Delay (seconds)
# Table Metrics Section (y=61)
- title: Table Rows by Table
size: {w: 24, h: 9}
description: Row count per table (mysql.table.rows)
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "mysqlreceiver.otel"
| WHERE mysql.table.rows IS NOT NULL
| STATS row_count = MAX(mysql.table.rows) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), table = attributes.table
| SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: row_count
label: Rows
format:
type: number
decimals: 0
breakdown:
field: table
- title: Table Size by Table
size: {w: 24, h: 9}
description: Table size in bytes by table (mysql.table.size)
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "mysqlreceiver.otel"
| WHERE mysql.table.size IS NOT NULL
| STATS size_bytes = MAX(mysql.table.size) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), table = attributes.table
| SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: size_bytes
label: Size
format:
type: bytes
breakdown:
field: table
- title: Table Average Row Length
size: {w: 48, h: 9}
description: Average row length per table (mysql.table.average_row_length)
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "mysqlreceiver.otel"
| WHERE mysql.table.average_row_length IS NOT NULL
| STATS avg_row_length = MAX(mysql.table.average_row_length) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), table = attributes.table
| SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: avg_row_length
label: Avg Row Length
format:
type: bytes
breakdown:
field: table
# Additional Optional Metrics (y=79)
- title: Client Network I/O
size: {w: 24, h: 9}
description: Network bytes sent/received (mysql.client.network.io)
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "mysqlreceiver.otel"
| WHERE mysql.client.network.io IS NOT NULL
| STATS io_bytes = SUM(RATE(mysql.client.network.io)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), kind = attributes.kind
| SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: io_bytes
label: Bytes/sec
format:
type: bytes
breakdown:
field: kind
- title: Joins by Type
size: {w: 24, h: 9}
description: Join operations by type (mysql.joins)
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "mysqlreceiver.otel"
| WHERE mysql.joins IS NOT NULL
| STATS joins_rate = SUM(RATE(mysql.joins)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), kind = attributes.kind
| SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: joins_rate
label: Joins/sec
breakdown:
field: kind
# Table Lock Metrics (y=88)
- title: Table Lock Wait Read
size: {w: 24, h: 9}
description: Table read lock wait count (mysql.table.lock_wait.read.count)
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "mysqlreceiver.otel"
| WHERE mysql.table.lock_wait.read.count IS NOT NULL
| STATS lock_count = SUM(RATE(mysql.table.lock_wait.read.count)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), kind = attributes.kind
| SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: lock_count
label: Read Lock Waits/sec
breakdown:
field: kind
- title: Table Lock Wait Write
size: {w: 24, h: 9}
description: Table write lock wait count (mysql.table.lock_wait.write.count)
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "mysqlreceiver.otel"
| WHERE mysql.table.lock_wait.write.count IS NOT NULL
| STATS lock_count = SUM(RATE(mysql.table.lock_wait.write.count)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), kind = attributes.kind
| SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: lock_count
label: Write Lock Waits/sec
breakdown:
field: kind
# Table Open Cache and Prepared Statements (y=97)
- title: Table Open Cache
size: {w: 24, h: 9}
description: Table open cache hits/misses (mysql.table_open_cache)
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "mysqlreceiver.otel"
| WHERE mysql.table_open_cache IS NOT NULL
| STATS cache_count = SUM(RATE(mysql.table_open_cache)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), status = attributes.status
| SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: cache_count
label: Operations/sec
breakdown:
field: status
- title: Prepared Statements
size: {w: 24, h: 9}
description: Prepared statement operations (mysql.prepared_statements)
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "mysqlreceiver.otel"
| WHERE mysql.prepared_statements IS NOT NULL
| STATS stmt_count = SUM(RATE(mysql.prepared_statements)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), command = attributes.command
| SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: stmt_count
label: Statements/sec
breakdown:
field: command
# Statement Events (y=106)
- title: Statement Events by Schema
size: {w: 48, h: 9}
description: Statement event count by schema (mysql.statement_event.count)
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "mysqlreceiver.otel"
| WHERE mysql.statement_event.count IS NOT NULL
| STATS event_count = SUM(RATE(mysql.statement_event.count)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), schema = attributes.schema
| SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: event_count
label: Events/sec
breakdown:
field: schema
# MySQLx Worker Threads (y=115)
- title: MySQLx Worker Threads
size: {w: 48, h: 9}
description: MySQLx worker threads by status (mysql.mysqlx_worker_threads)
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "mysqlreceiver.otel"
| WHERE mysql.mysqlx_worker_threads IS NOT NULL
| STATS thread_count = MAX(mysql.mysqlx_worker_threads) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), kind = attributes.kind
| SORT time_bucket ASC
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: thread_count
label: Threads
format:
type: number
decimals: 0
breakdown:
field: kind
Prerequisites¶
- MySQL: MySQL 5.7+ or 8.x database server
- OpenTelemetry Collector: Collector Contrib with MySQL receiver configured
- Kibana: Version 9.2 or later (dashboards use ES|QL TS command)
Data Requirements¶
- Data stream dataset:
mysqlreceiver.otel - Data view:
metrics-*
OpenTelemetry Collector Configuration¶
receivers:
mysql:
endpoint: localhost:3306
username: ${env:MYSQL_USERNAME}
password: ${env:MYSQL_PASSWORD}
collection_interval: 10s
exporters:
elasticsearch:
endpoints: ["https://your-elasticsearch-instance:9200"]
service:
pipelines:
metrics:
receivers: [mysql]
exporters: [elasticsearch]
Metrics Reference¶
Default Metrics¶
| Metric | Type | Unit | Description | Attributes |
|---|---|---|---|---|
mysql.buffer_pool.data_pages |
Sum | 1 |
Number of data pages in the InnoDB buffer pool | status |
mysql.buffer_pool.limit |
Sum | By |
Configured size of the InnoDB buffer pool | — |
mysql.buffer_pool.operations |
Sum | 1 |
Number of operations on the InnoDB buffer pool | operation |
mysql.buffer_pool.page_flushes |
Sum | 1 |
Number of requests to flush pages from buffer pool | — |
mysql.buffer_pool.pages |
Sum | 1 |
Number of pages in the InnoDB buffer pool | kind |
mysql.buffer_pool.usage |
Sum | By |
Bytes in the InnoDB buffer pool | status |
mysql.double_writes |
Sum | 1 |
Writes to the InnoDB doublewrite buffer | kind |
mysql.handlers |
Sum | 1 |
Requests to various MySQL handlers | kind |
mysql.index.io.wait.count |
Sum | 1 |
Total I/O wait count for an index | operation, table, schema, index |
mysql.index.io.wait.time |
Sum | ns |
Total I/O wait time for an index | operation, table, schema, index |
mysql.locks |
Sum | 1 |
Number of MySQL locks | kind |
mysql.log_operations |
Sum | 1 |
Number of InnoDB log operations | operation |
mysql.mysqlx_connections |
Sum | 1 |
Document Store connections | status |
mysql.opened_resources |
Sum | 1 |
Number of opened resources | kind |
mysql.operations |
Sum | 1 |
Number of InnoDB operations | operation |
mysql.page_operations |
Sum | 1 |
Number of InnoDB page operations | operation |
mysql.prepared_statements |
Sum | 1 |
Prepared statement commands issued | command |
mysql.row_locks |
Sum | 1 |
Number of InnoDB row locks | kind |
mysql.row_operations |
Sum | 1 |
Number of InnoDB row operations | operation |
mysql.sorts |
Sum | 1 |
Number of MySQL sorts | kind |
mysql.table.io.wait.count |
Sum | 1 |
Total I/O wait count for a table | operation, table, schema |
mysql.table.io.wait.time |
Sum | ns |
Total I/O wait time for a table | operation, table, schema |
mysql.threads |
Sum | 1 |
State of MySQL threads | kind |
mysql.tmp_resources |
Sum | 1 |
Number of created temporary resources | resource |
mysql.uptime |
Sum | s |
Seconds the server has been up | — |
Optional Metrics (disabled by default)¶
| Metric | Type | Unit | Description | Attributes |
|---|---|---|---|---|
mysql.client.network.io |
Sum | By |
Bytes transmitted between server and clients | kind |
mysql.commands |
Sum | 1 |
Number of times each command has been executed | command |
mysql.connection.count |
Sum | 1 |
Connection attempts to the MySQL server | — |
mysql.connection.errors |
Sum | 1 |
Errors during client connection process | error |
mysql.joins |
Sum | 1 |
Joins that perform table scans | kind |
mysql.max_used_connections |
Sum | 1 |
Maximum connections used since server started | — |
mysql.mysqlx_worker_threads |
Sum | 1 |
MySQLx worker thread count | kind |
mysql.query.client.count |
Sum | 1 |
Number of client statements executed | — |
mysql.query.count |
Sum | 1 |
Number of queries executed | — |
mysql.query.slow.count |
Sum | 1 |
Number of slow queries | — |
mysql.replica.sql_delay |
Sum | s |
Configured replication delay in seconds | — |
mysql.replica.time_behind_source |
Sum | s |
Replication lag in seconds | — |
mysql.statement_event.count |
Sum | 1 |
Statement event count by schema | schema, digest, digest_text, kind |
mysql.table.average_row_length |
Sum | By |
Average row length per table | table, schema |
mysql.table.lock_wait.read.count |
Sum | 1 |
Table read lock wait count | schema, table, kind |
mysql.table.lock_wait.write.count |
Sum | 1 |
Table write lock wait count | schema, table, kind |
mysql.table.rows |
Sum | 1 |
Number of rows for a given table | table, schema |
mysql.table.size |
Sum | By |
Table size in bytes | table, schema, kind |
mysql.table_open_cache |
Sum | 1 |
Table open cache operations | status |
Metric Attributes¶
| Attribute | Values | Description |
|---|---|---|
status |
dirty, clean |
Buffer pool status |
kind (pages) |
data, free, misc, total |
Page type |
kind (handlers) |
commit, delete, update, write, read_first, read_key, read_next, read_prev, read_rnd, read_rnd_next |
Handler type |
kind (locks) |
immediate, waited |
Lock type |
kind (double_writes) |
pages_written, writes |
Double write type |
kind (row_locks) |
waits, time |
Row lock type |
kind (sorts) |
merge_passes, range, rows, scan |
Sort type |
kind (threads) |
cached, connected, created, running |
Thread state |
operation (log) |
waits, write_requests, writes, fsyncs |
Log operation type |
operation (InnoDB) |
fsyncs, reads, writes |
InnoDB operation type |
operation (page) |
created, read, written |
Page operation type |
operation (row) |
deleted, inserted, read, updated |
Row operation type |
resource |
disk_tables, files, tables |
Temporary resource type |
kind (mysqlx_threads) |
available, active |
MySQLx worker thread state |
kind (read_lock) |
normal, with_shared_locks, high_priority, no_insert, external |
Read lock type |
kind (write_lock) |
allow_write, concurrent_insert, low_priority, normal, external |
Write lock type |
kind (table_size) |
data, index |
Table size type |
kind (joins) |
full, full_range, range, range_check, scan |
Join type |
kind (event_state) |
errors, warnings, rows_affected, rows_sent, rows_examined, created_tmp_disk_tables, created_tmp_tables, sort_merge_passes, sort_rows, no_index_used |
Statement event state |
status (cache) |
hit, miss, overflow |
Cache access status |
status (connection) |
accepted, closed, rejected |
Connection status |
error |
accept, internal, max_connections, peer_address, select, tcpwrap, aborted, aborted_clients, locked |
Connection error type |
command |
delete, delete_multi, insert, select, update, update_multi |
Command type |
command (prepared) |
execute, close, fetch, prepare, reset, send_long_data |
Prepared statement command |
Resource Attributes¶
| Attribute | Description |
|---|---|
host.name |
MySQL host name |
service.instance.id |
MySQL instance identifier |
Metrics Not Used in Dashboards¶
The following default metrics are available from the MySQL receiver but are not currently visualized in the dashboards:
| Metric | Type | Unit | Description | Attributes |
|---|---|---|---|---|
mysql.buffer_pool.data_pages |
Sum | 1 |
Number of data pages in the InnoDB buffer pool | status |
mysql.buffer_pool.limit |
Sum | By |
Configured size of the InnoDB buffer pool | — |
mysql.index.io.wait.time |
Sum | ns |
Total I/O wait time for an index | operation, table, schema, index |
mysql.table.io.wait.time |
Sum | ns |
Total I/O wait time for a table | operation, table, schema |
All optional metrics listed above are used in the Extended dashboard.