diff options
Diffstat (limited to '')
17 files changed, 3416 insertions, 0 deletions
diff --git a/src/go/collectors/go.d.plugin/modules/proxysql/README.md b/src/go/collectors/go.d.plugin/modules/proxysql/README.md new file mode 120000 index 000000000..06223157d --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/proxysql/README.md @@ -0,0 +1 @@ +integrations/proxysql.md
\ No newline at end of file diff --git a/src/go/collectors/go.d.plugin/modules/proxysql/cache.go b/src/go/collectors/go.d.plugin/modules/proxysql/cache.go new file mode 100644 index 000000000..c4fccefff --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/proxysql/cache.go @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package proxysql + +type ( + cache struct { + commands map[string]*commandCache + users map[string]*userCache + backends map[string]*backendCache + } + commandCache struct { + command string + hasCharts, updated bool + } + userCache struct { + user string + hasCharts, updated bool + } + backendCache struct { + hg, host, port string + hasCharts, updated bool + } +) + +func (c *cache) reset() { + for k, m := range c.commands { + c.commands[k] = &commandCache{command: m.command, hasCharts: m.hasCharts} + } + for k, m := range c.users { + c.users[k] = &userCache{user: m.user, hasCharts: m.hasCharts} + } + for k, m := range c.backends { + c.backends[k] = &backendCache{hg: m.hg, host: m.host, port: m.port, hasCharts: m.hasCharts} + } +} + +func (c *cache) getCommand(command string) *commandCache { + v, ok := c.commands[command] + if !ok { + v = &commandCache{command: command} + c.commands[command] = v + } + return v +} + +func (c *cache) getUser(user string) *userCache { + v, ok := c.users[user] + if !ok { + v = &userCache{user: user} + c.users[user] = v + } + return v +} + +func (c *cache) getBackend(hg, host, port string) *backendCache { + id := backendID(hg, host, port) + v, ok := c.backends[id] + if !ok { + v = &backendCache{hg: hg, host: host, port: port} + c.backends[id] = v + } + return v +} diff --git a/src/go/collectors/go.d.plugin/modules/proxysql/charts.go b/src/go/collectors/go.d.plugin/modules/proxysql/charts.go new file mode 100644 index 000000000..34e012740 --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/proxysql/charts.go @@ -0,0 +1,726 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package proxysql + +import ( + "fmt" + "strings" + + "github.com/netdata/netdata/go/go.d.plugin/agent/module" +) + +// TODO: check https://github.com/ProxySQL/proxysql-grafana-prometheus/blob/main/grafana/provisioning/dashboards/ProxySQL-Host-Statistics.json + +const ( + prioClientConnectionsCount = module.Priority + iota + prioClientConnectionsRate + prioServerConnectionsCount + prioServerConnectionsRate + prioBackendsTraffic + prioFrontendsTraffic + prioActiveTransactionsCount + prioQuestionsRate + prioSlowQueriesRate + prioQueriesRate + prioBackendStatementsCount + prioBackendStatementsRate + prioFrontendStatementsCount + prioFrontendStatementsRate + prioCachedStatementsCount + prioQueryCacheEntriesCount + prioQueryCacheIO + prioQueryCacheRequestsRate + prioQueryCacheMemoryUsed + prioMySQLMonitorWorkersCount + prioMySQLMonitorWorkersRate + prioMySQLMonitorConnectChecksRate + prioMySQLMonitorPingChecksRate + prioMySQLMonitorReadOnlyChecksRate + prioMySQLMonitorReplicationLagChecksRate + prioJemallocMemoryUsed + prioMemoryUsed + prioMySQLCommandExecutionsRate + prioMySQLCommandExecutionTime + prioMySQLCommandExecutionDurationHistogram + prioMySQLUserConnectionsUtilization + prioMySQLUserConnectionsCount + prioBackendStatus + prioBackendConnectionsUsage + prioBackendConnectionsRate + prioBackendQueriesRateRate + prioBackendTraffic + prioBackendLatency + prioUptime +) + +var ( + baseCharts = module.Charts{ + clientConnectionsCountChart.Copy(), + clientConnectionsRateChart.Copy(), + serverConnectionsCountChart.Copy(), + serverConnectionsRateChart.Copy(), + backendsTrafficChart.Copy(), + frontendsTrafficChart.Copy(), + activeTransactionsCountChart.Copy(), + questionsRateChart.Copy(), + slowQueriesRateChart.Copy(), + queriesRateChart.Copy(), + backendStatementsCountChart.Copy(), + backendStatementsRateChart.Copy(), + clientStatementsCountChart.Copy(), + clientStatementsRateChart.Copy(), + cachedStatementsCountChart.Copy(), + queryCacheEntriesCountChart.Copy(), + queryCacheIOChart.Copy(), + queryCacheRequestsRateChart.Copy(), + queryCacheMemoryUsedChart.Copy(), + mySQLMonitorWorkersCountChart.Copy(), + mySQLMonitorWorkersRateChart.Copy(), + mySQLMonitorConnectChecksRateChart.Copy(), + mySQLMonitorPingChecksRateChart.Copy(), + mySQLMonitorReadOnlyChecksRateChart.Copy(), + mySQLMonitorReplicationLagChecksRateChart.Copy(), + jemallocMemoryUsedChart.Copy(), + memoryUsedCountChart.Copy(), + uptimeChart.Copy(), + } + + clientConnectionsCountChart = module.Chart{ + ID: "client_connections_count", + Title: "Client connections", + Units: "connections", + Fam: "connections", + Ctx: "proxysql.client_connections_count", + Priority: prioClientConnectionsCount, + Dims: module.Dims{ + {ID: "Client_Connections_connected", Name: "connected"}, + {ID: "Client_Connections_non_idle", Name: "non_idle"}, + {ID: "Client_Connections_hostgroup_locked", Name: "hostgroup_locked"}, + }, + } + clientConnectionsRateChart = module.Chart{ + ID: "client_connections_rate", + Title: "Client connections rate", + Units: "connections/s", + Fam: "connections", + Ctx: "proxysql.client_connections_rate", + Priority: prioClientConnectionsRate, + Dims: module.Dims{ + {ID: "Client_Connections_created", Name: "created", Algo: module.Incremental}, + {ID: "Client_Connections_aborted", Name: "aborted", Algo: module.Incremental}, + }, + } + + serverConnectionsCountChart = module.Chart{ + ID: "server_connections_count", + Title: "Server connections", + Units: "connections", + Fam: "connections", + Ctx: "proxysql.server_connections_count", + Priority: prioServerConnectionsCount, + Dims: module.Dims{ + {ID: "Server_Connections_connected", Name: "connected"}, + }, + } + serverConnectionsRateChart = module.Chart{ + ID: "server_connections_rate", + Title: "Server connections rate", + Units: "connections/s", + Fam: "connections", + Ctx: "proxysql.server_connections_rate", + Priority: prioServerConnectionsRate, + Dims: module.Dims{ + {ID: "Server_Connections_created", Name: "created", Algo: module.Incremental}, + {ID: "Server_Connections_aborted", Name: "aborted", Algo: module.Incremental}, + {ID: "Server_Connections_delayed", Name: "delayed", Algo: module.Incremental}, + }, + } + + backendsTrafficChart = module.Chart{ + ID: "backends_traffic", + Title: "Backends traffic", + Units: "B/s", + Fam: "traffic", + Ctx: "proxysql.backends_traffic", + Priority: prioBackendsTraffic, + Dims: module.Dims{ + {ID: "Queries_backends_bytes_recv", Name: "recv", Algo: module.Incremental}, + {ID: "Queries_backends_bytes_sent", Name: "sent", Algo: module.Incremental}, + }, + } + frontendsTrafficChart = module.Chart{ + ID: "clients_traffic", + Title: "Clients traffic", + Units: "B/s", + Fam: "traffic", + Ctx: "proxysql.clients_traffic", + Priority: prioFrontendsTraffic, + Dims: module.Dims{ + {ID: "Queries_frontends_bytes_recv", Name: "recv", Algo: module.Incremental}, + {ID: "Queries_frontends_bytes_sent", Name: "sent", Algo: module.Incremental}, + }, + } + + activeTransactionsCountChart = module.Chart{ + ID: "active_transactions_count", + Title: "Client connections that are currently processing a transaction", + Units: "transactions", + Fam: "transactions", + Ctx: "proxysql.active_transactions_count", + Priority: prioActiveTransactionsCount, + Dims: module.Dims{ + {ID: "Active_Transactions", Name: "active"}, + }, + } + questionsRateChart = module.Chart{ + ID: "questions_rate", + Title: "Client requests / statements executed", + Units: "questions/s", + Fam: "queries", + Ctx: "proxysql.questions_rate", + Priority: prioQuestionsRate, + Dims: module.Dims{ + {ID: "Questions", Name: "questions", Algo: module.Incremental}, + }, + } + slowQueriesRateChart = module.Chart{ + ID: "slow_queries_rate", + Title: "Slow queries", + Units: "queries/s", + Fam: "queries", + Ctx: "proxysql.slow_queries_rate", + Priority: prioSlowQueriesRate, + Dims: module.Dims{ + {ID: "Slow_queries", Name: "slow", Algo: module.Incremental}, + }, + } + queriesRateChart = module.Chart{ + ID: "queries_rate", + Title: "Queries rate", + Units: "queries/s", + Fam: "queries", + Ctx: "proxysql.queries_rate", + Priority: prioQueriesRate, + Type: module.Stacked, + Dims: module.Dims{ + {ID: "Com_autocommit", Name: "autocommit", Algo: module.Incremental}, + {ID: "Com_autocommit_filtered", Name: "autocommit_filtered", Algo: module.Incremental}, + {ID: "Com_commit", Name: "commit", Algo: module.Incremental}, + {ID: "Com_commit_filtered", Name: "commit_filtered", Algo: module.Incremental}, + {ID: "Com_rollback", Name: "rollback", Algo: module.Incremental}, + {ID: "Com_rollback_filtered", Name: "rollback_filtered", Algo: module.Incremental}, + {ID: "Com_backend_change_user", Name: "backend_change_user", Algo: module.Incremental}, + {ID: "Com_backend_init_db", Name: "backend_init_db", Algo: module.Incremental}, + {ID: "Com_backend_set_names", Name: "backend_set_names", Algo: module.Incremental}, + {ID: "Com_frontend_init_db", Name: "frontend_init_db", Algo: module.Incremental}, + {ID: "Com_frontend_set_names", Name: "frontend_set_names", Algo: module.Incremental}, + {ID: "Com_frontend_use_db", Name: "frontend_use_db", Algo: module.Incremental}, + }, + } + + backendStatementsCountChart = module.Chart{ + ID: "backend_statements_count", + Title: "Statements available across all backend connections", + Units: "statements", + Fam: "statements", + Ctx: "proxysql.backend_statements_count", + Priority: prioBackendStatementsCount, + Dims: module.Dims{ + {ID: "Stmt_Server_Active_Total", Name: "total"}, + {ID: "Stmt_Server_Active_Unique", Name: "unique"}, + }, + } + backendStatementsRateChart = module.Chart{ + ID: "backend_statements_rate", + Title: "Statements executed against the backends", + Units: "statements/s", + Fam: "statements", + Ctx: "proxysql.backend_statements_rate", + Priority: prioBackendStatementsRate, + Type: module.Stacked, + Dims: module.Dims{ + {ID: "Com_backend_stmt_prepare", Name: "prepare", Algo: module.Incremental}, + {ID: "Com_backend_stmt_execute", Name: "execute", Algo: module.Incremental}, + {ID: "Com_backend_stmt_close", Name: "close", Algo: module.Incremental}, + }, + } + clientStatementsCountChart = module.Chart{ + ID: "client_statements_count", + Title: "Statements that are in use by clients", + Units: "statements", + Fam: "statements", + Ctx: "proxysql.client_statements_count", + Priority: prioFrontendStatementsCount, + Dims: module.Dims{ + {ID: "Stmt_Client_Active_Total", Name: "total"}, + {ID: "Stmt_Client_Active_Unique", Name: "unique"}, + }, + } + clientStatementsRateChart = module.Chart{ + ID: "client_statements_rate", + Title: "Statements executed by clients", + Units: "statements/s", + Fam: "statements", + Ctx: "proxysql.client_statements_rate", + Priority: prioFrontendStatementsRate, + Type: module.Stacked, + Dims: module.Dims{ + {ID: "Com_frontend_stmt_prepare", Name: "prepare", Algo: module.Incremental}, + {ID: "Com_frontend_stmt_execute", Name: "execute", Algo: module.Incremental}, + {ID: "Com_frontend_stmt_close", Name: "close", Algo: module.Incremental}, + }, + } + cachedStatementsCountChart = module.Chart{ + ID: "cached_statements_count", + Title: "Global prepared statements", + Units: "statements", + Fam: "statements", + Ctx: "proxysql.cached_statements_count", + Priority: prioCachedStatementsCount, + Dims: module.Dims{ + {ID: "Stmt_Cached", Name: "cached"}, + }, + } + + queryCacheEntriesCountChart = module.Chart{ + ID: "query_cache_entries_count", + Title: "Query Cache entries", + Units: "entries", + Fam: "query cache", + Ctx: "proxysql.query_cache_entries_count", + Priority: prioQueryCacheEntriesCount, + Dims: module.Dims{ + {ID: "Query_Cache_Entries", Name: "entries"}, + }, + } + queryCacheMemoryUsedChart = module.Chart{ + ID: "query_cache_memory_used", + Title: "Query Cache memory used", + Units: "B", + Fam: "query cache", + Ctx: "proxysql.query_cache_memory_used", + Priority: prioQueryCacheMemoryUsed, + Dims: module.Dims{ + {ID: "Query_Cache_Memory_bytes", Name: "used"}, + }, + } + queryCacheIOChart = module.Chart{ + ID: "query_cache_io", + Title: "Query Cache I/O", + Units: "B/s", + Fam: "query cache", + Ctx: "proxysql.query_cache_io", + Priority: prioQueryCacheIO, + Dims: module.Dims{ + {ID: "Query_Cache_bytes_IN", Name: "in", Algo: module.Incremental}, + {ID: "Query_Cache_bytes_OUT", Name: "out", Algo: module.Incremental}, + }, + } + queryCacheRequestsRateChart = module.Chart{ + ID: "query_cache_requests_rate", + Title: "Query Cache requests", + Units: "requests/s", + Fam: "query cache", + Ctx: "proxysql.query_cache_requests_rate", + Priority: prioQueryCacheRequestsRate, + Dims: module.Dims{ + {ID: "Query_Cache_count_GET", Name: "read", Algo: module.Incremental}, + {ID: "Query_Cache_count_SET", Name: "write", Algo: module.Incremental}, + {ID: "Query_Cache_count_GET_OK", Name: "read_success", Algo: module.Incremental}, + }, + } + + mySQLMonitorWorkersCountChart = module.Chart{ + ID: "mysql_monitor_workers_count", + Title: "MySQL monitor workers", + Units: "threads", + Fam: "monitor", + Ctx: "proxysql.mysql_monitor_workers_count", + Priority: prioMySQLMonitorWorkersCount, + Dims: module.Dims{ + {ID: "MySQL_Monitor_Workers", Name: "workers"}, + {ID: "MySQL_Monitor_Workers_Aux", Name: "auxiliary"}, + }, + } + mySQLMonitorWorkersRateChart = module.Chart{ + ID: "mysql_monitor_workers_rate", + Title: "MySQL monitor workers rate", + Units: "workers/s", + Fam: "monitor", + Ctx: "proxysql.mysql_monitor_workers_rate", + Priority: prioMySQLMonitorWorkersRate, + Dims: module.Dims{ + {ID: "MySQL_Monitor_Workers_Started", Name: "started", Algo: module.Incremental}, + }, + } + mySQLMonitorConnectChecksRateChart = module.Chart{ + ID: "mysql_monitor_connect_checks_rate", + Title: "MySQL monitor connect checks", + Units: "checks/s", + Fam: "monitor", + Ctx: "proxysql.mysql_monitor_connect_checks_rate", + Priority: prioMySQLMonitorConnectChecksRate, + Dims: module.Dims{ + {ID: "MySQL_Monitor_connect_check_OK", Name: "succeed", Algo: module.Incremental}, + {ID: "MySQL_Monitor_connect_check_ERR", Name: "failed", Algo: module.Incremental}, + }, + } + mySQLMonitorPingChecksRateChart = module.Chart{ + ID: "mysql_monitor_ping_checks_rate", + Title: "MySQL monitor ping checks", + Units: "checks/s", + Fam: "monitor", + Ctx: "proxysql.mysql_monitor_ping_checks_rate", + Priority: prioMySQLMonitorPingChecksRate, + Dims: module.Dims{ + {ID: "MySQL_Monitor_ping_check_OK", Name: "succeed", Algo: module.Incremental}, + {ID: "MySQL_Monitor_ping_check_ERR", Name: "failed", Algo: module.Incremental}, + }, + } + mySQLMonitorReadOnlyChecksRateChart = module.Chart{ + ID: "mysql_monitor_read_only_checks_rate", + Title: "MySQL monitor read only checks", + Units: "checks/s", + Fam: "monitor", + Ctx: "proxysql.mysql_monitor_read_only_checks_rate", + Priority: prioMySQLMonitorReadOnlyChecksRate, + Dims: module.Dims{ + {ID: "MySQL_Monitor_read_only_check_OK", Name: "succeed", Algo: module.Incremental}, + {ID: "MySQL_Monitor_read_only_check_ERR", Name: "failed", Algo: module.Incremental}, + }, + } + mySQLMonitorReplicationLagChecksRateChart = module.Chart{ + ID: "mysql_monitor_replication_lag_checks_rate", + Title: "MySQL monitor replication lag checks", + Units: "checks/s", + Fam: "monitor", + Ctx: "proxysql.mysql_monitor_replication_lag_checks_rate", + Priority: prioMySQLMonitorReplicationLagChecksRate, + Dims: module.Dims{ + {ID: "MySQL_Monitor_replication_lag_check_OK", Name: "succeed", Algo: module.Incremental}, + {ID: "MySQL_Monitor_replication_lag_check_ERR", Name: "failed", Algo: module.Incremental}, + }, + } + + jemallocMemoryUsedChart = module.Chart{ + ID: "jemalloc_memory_used", + Title: "Jemalloc used memory", + Units: "bytes", + Fam: "memory", + Ctx: "proxysql.jemalloc_memory_used", + Type: module.Stacked, + Priority: prioJemallocMemoryUsed, + Dims: module.Dims{ + {ID: "jemalloc_active", Name: "active"}, + {ID: "jemalloc_allocated", Name: "allocated"}, + {ID: "jemalloc_mapped", Name: "mapped"}, + {ID: "jemalloc_metadata", Name: "metadata"}, + {ID: "jemalloc_resident", Name: "resident"}, + {ID: "jemalloc_retained", Name: "retained"}, + }, + } + memoryUsedCountChart = module.Chart{ + ID: "memory_used", + Title: "Memory used", + Units: "bytes", + Fam: "memory", + Ctx: "proxysql.memory_used", + Priority: prioMemoryUsed, + Type: module.Stacked, + Dims: module.Dims{ + {ID: "Auth_memory", Name: "auth"}, + {ID: "SQLite3_memory_bytes", Name: "sqlite3"}, + {ID: "query_digest_memory", Name: "query_digest"}, + {ID: "mysql_query_rules_memory", Name: "query_rules"}, + {ID: "mysql_firewall_users_table", Name: "firewall_users_table"}, + {ID: "mysql_firewall_users_config", Name: "firewall_users_config"}, + {ID: "mysql_firewall_rules_table", Name: "firewall_rules_table"}, + {ID: "mysql_firewall_rules_config", Name: "firewall_rules_config"}, + {ID: "stack_memory_mysql_threads", Name: "mysql_threads"}, + {ID: "stack_memory_admin_threads", Name: "admin_threads"}, + {ID: "stack_memory_cluster_threads", Name: "cluster_threads"}, + }, + } + uptimeChart = module.Chart{ + ID: "proxysql_uptime", + Title: "Uptime", + Units: "seconds", + Fam: "uptime", + Ctx: "proxysql.uptime", + Priority: prioUptime, + Dims: module.Dims{ + {ID: "ProxySQL_Uptime", Name: "uptime"}, + }, + } +) + +var ( + mySQLCommandChartsTmpl = module.Charts{ + mySQLCommandExecutionRateChartTmpl.Copy(), + mySQLCommandExecutionTimeChartTmpl.Copy(), + mySQLCommandExecutionDurationHistogramChartTmpl.Copy(), + } + + mySQLCommandExecutionRateChartTmpl = module.Chart{ + ID: "mysql_command_%s_execution_rate", + Title: "MySQL command execution", + Units: "commands/s", + Fam: "command exec", + Ctx: "proxysql.mysql_command_execution_rate", + Priority: prioMySQLCommandExecutionsRate, + Dims: module.Dims{ + {ID: "mysql_command_%s_Total_cnt", Name: "commands", Algo: module.Incremental}, + }, + } + mySQLCommandExecutionTimeChartTmpl = module.Chart{ + ID: "mysql_command_%s_execution_time", + Title: "MySQL command execution time", + Units: "microseconds", + Fam: "command exec time", + Ctx: "proxysql.mysql_command_execution_time", + Priority: prioMySQLCommandExecutionTime, + Dims: module.Dims{ + {ID: "mysql_command_%s_Total_Time_us", Name: "time", Algo: module.Incremental}, + }, + } + mySQLCommandExecutionDurationHistogramChartTmpl = module.Chart{ + ID: "mysql_command_%s_execution_duration", + Title: "MySQL command execution duration histogram", + Units: "commands/s", + Fam: "command exec duration", + Ctx: "proxysql.mysql_command_execution_duration", + Type: module.Stacked, + Priority: prioMySQLCommandExecutionDurationHistogram, + Dims: module.Dims{ + {ID: "mysql_command_%s_cnt_100us", Name: "100us", Algo: module.Incremental}, + {ID: "mysql_command_%s_cnt_500us", Name: "500us", Algo: module.Incremental}, + {ID: "mysql_command_%s_cnt_1ms", Name: "1ms", Algo: module.Incremental}, + {ID: "mysql_command_%s_cnt_5ms", Name: "5ms", Algo: module.Incremental}, + {ID: "mysql_command_%s_cnt_10ms", Name: "10ms", Algo: module.Incremental}, + {ID: "mysql_command_%s_cnt_50ms", Name: "50ms", Algo: module.Incremental}, + {ID: "mysql_command_%s_cnt_100ms", Name: "100ms", Algo: module.Incremental}, + {ID: "mysql_command_%s_cnt_500ms", Name: "500ms", Algo: module.Incremental}, + {ID: "mysql_command_%s_cnt_1s", Name: "1s", Algo: module.Incremental}, + {ID: "mysql_command_%s_cnt_5s", Name: "5s", Algo: module.Incremental}, + {ID: "mysql_command_%s_cnt_10s", Name: "10s", Algo: module.Incremental}, + {ID: "mysql_command_%s_cnt_INFs", Name: "+Inf", Algo: module.Incremental}, + }, + } +) + +func newMySQLCommandCountersCharts(command string) *module.Charts { + charts := mySQLCommandChartsTmpl.Copy() + + for _, chart := range *charts { + chart.ID = fmt.Sprintf(chart.ID, strings.ToLower(command)) + chart.Labels = []module.Label{{Key: "command", Value: command}} + for _, dim := range chart.Dims { + dim.ID = fmt.Sprintf(dim.ID, command) + } + } + + return charts +} + +func (p *ProxySQL) addMySQLCommandCountersCharts(command string) { + charts := newMySQLCommandCountersCharts(command) + + if err := p.Charts().Add(*charts...); err != nil { + p.Warning(err) + } +} + +func (p *ProxySQL) removeMySQLCommandCountersCharts(command string) { + prefix := "mysql_command_" + strings.ToLower(command) + + for _, chart := range *p.Charts() { + if strings.HasPrefix(chart.ID, prefix) { + chart.MarkRemove() + chart.MarkNotCreated() + } + } +} + +var ( + mySQLUserChartsTmpl = module.Charts{ + mySQLUserConnectionsUtilizationChartTmpl.Copy(), + mySQLUserConnectionsCountChartTmpl.Copy(), + } + + mySQLUserConnectionsUtilizationChartTmpl = module.Chart{ + ID: "mysql_user_%s_connections_utilization", + Title: "MySQL user connections utilization", + Units: "percentage", + Fam: "user conns", + Ctx: "proxysql.mysql_user_connections_utilization", + Priority: prioMySQLUserConnectionsUtilization, + Dims: module.Dims{ + {ID: "mysql_user_%s_frontend_connections_utilization", Name: "used"}, + }, + } + mySQLUserConnectionsCountChartTmpl = module.Chart{ + ID: "mysql_user_%s_connections_count", + Title: "MySQL user connections used", + Units: "connections", + Fam: "user conns", + Ctx: "proxysql.mysql_user_connections_count", + Priority: prioMySQLUserConnectionsCount, + Dims: module.Dims{ + {ID: "mysql_user_%s_frontend_connections", Name: "used"}, + }, + } +) + +func newMySQLUserCharts(username string) *module.Charts { + charts := mySQLUserChartsTmpl.Copy() + + for _, chart := range *charts { + chart.ID = fmt.Sprintf(chart.ID, username) + chart.Labels = []module.Label{{Key: "user", Value: username}} + for _, dim := range chart.Dims { + dim.ID = fmt.Sprintf(dim.ID, username) + } + } + + return charts +} + +func (p *ProxySQL) addMySQLUsersCharts(username string) { + charts := newMySQLUserCharts(username) + + if err := p.Charts().Add(*charts...); err != nil { + p.Warning(err) + } +} + +func (p *ProxySQL) removeMySQLUserCharts(user string) { + prefix := "mysql_user_" + user + + for _, chart := range *p.Charts() { + if strings.HasPrefix(chart.ID, prefix) { + chart.MarkRemove() + chart.MarkNotCreated() + } + } +} + +var ( + backendChartsTmpl = module.Charts{ + backendStatusChartTmpl.Copy(), + backendConnectionsUsageChartTmpl.Copy(), + backendConnectionsRateChartTmpl.Copy(), + backendQueriesRateRateChartTmpl.Copy(), + backendTrafficChartTmpl.Copy(), + backendLatencyChartTmpl.Copy(), + } + + backendStatusChartTmpl = module.Chart{ + ID: "backend_%s_status", + Title: "Backend status", + Units: "status", + Fam: "backend status", + Ctx: "proxysql.backend_status", + Priority: prioBackendStatus, + Dims: module.Dims{ + {ID: "backend_%s_status_ONLINE", Name: "online"}, + {ID: "backend_%s_status_SHUNNED", Name: "shunned"}, + {ID: "backend_%s_status_OFFLINE_SOFT", Name: "offline_soft"}, + {ID: "backend_%s_status_OFFLINE_HARD", Name: "offline_hard"}, + }, + } + backendConnectionsUsageChartTmpl = module.Chart{ + ID: "backend_%s_connections_usage", + Title: "Backend connections usage", + Units: "connections", + Fam: "backend conns usage", + Ctx: "proxysql.backend_connections_usage", + Type: module.Stacked, + Priority: prioBackendConnectionsUsage, + Dims: module.Dims{ + {ID: "backend_%s_ConnFree", Name: "free"}, + {ID: "backend_%s_ConnUsed", Name: "used"}, + }, + } + backendConnectionsRateChartTmpl = module.Chart{ + ID: "backend_%s_connections_rate", + Title: "Backend connections established", + Units: "connections/s", + Fam: "backend conns established", + Ctx: "proxysql.backend_connections_rate", + Priority: prioBackendConnectionsRate, + Dims: module.Dims{ + {ID: "backend_%s_ConnOK", Name: "succeed", Algo: module.Incremental}, + {ID: "backend_%s_ConnERR", Name: "failed", Algo: module.Incremental}, + }, + } + backendQueriesRateRateChartTmpl = module.Chart{ + ID: "backend_%s_queries_rate", + Title: "Backend queries", + Units: "queries/s", + Fam: "backend queries", + Ctx: "proxysql.backend_queries_rate", + Priority: prioBackendQueriesRateRate, + Dims: module.Dims{ + {ID: "backend_%s_Queries", Name: "queries", Algo: module.Incremental}, + }, + } + backendTrafficChartTmpl = module.Chart{ + ID: "backend_%s_traffic", + Title: "Backend traffic", + Units: "B/s", + Fam: "backend traffic", + Ctx: "proxysql.backend_traffic", + Priority: prioBackendTraffic, + Dims: module.Dims{ + {ID: "backend_%s_Bytes_data_recv", Name: "recv", Algo: module.Incremental}, + {ID: "backend_%s_Bytes_data_sent", Name: "sent", Algo: module.Incremental}, + }, + } + backendLatencyChartTmpl = module.Chart{ + ID: "backend_%s_latency", + Title: "Backend latency", + Units: "microseconds", + Fam: "backend latency", + Ctx: "proxysql.backend_latency", + Priority: prioBackendLatency, + Dims: module.Dims{ + {ID: "backend_%s_Latency_us", Name: "latency"}, + }, + } +) + +func newBackendCharts(hg, host, port string) *module.Charts { + charts := backendChartsTmpl.Copy() + + for _, chart := range *charts { + chart.ID = fmt.Sprintf(chart.ID, backendID(hg, host, port)) + chart.Labels = []module.Label{ + {Key: "host", Value: host}, + {Key: "port", Value: port}, + } + for _, dim := range chart.Dims { + dim.ID = fmt.Sprintf(dim.ID, backendID(hg, host, port)) + } + } + + return charts +} + +func (p *ProxySQL) addBackendCharts(hg, host, port string) { + charts := newBackendCharts(hg, host, port) + + if err := p.Charts().Add(*charts...); err != nil { + p.Warning(err) + } +} + +func (p *ProxySQL) removeBackendCharts(hg, host, port string) { + prefix := "backend_" + backendID(hg, host, port) + + for _, chart := range *p.Charts() { + if strings.HasPrefix(chart.ID, prefix) { + chart.MarkRemove() + chart.MarkNotCreated() + } + } +} diff --git a/src/go/collectors/go.d.plugin/modules/proxysql/collect.go b/src/go/collectors/go.d.plugin/modules/proxysql/collect.go new file mode 100644 index 000000000..dfc559a97 --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/proxysql/collect.go @@ -0,0 +1,308 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package proxysql + +import ( + "context" + "database/sql" + "fmt" + "strconv" + "strings" + "time" +) + +const ( + queryVersion = "select version();" + queryStatsMySQLGlobal = "SELECT * FROM stats_mysql_global;" + queryStatsMySQLMemoryMetrics = "SELECT * FROM stats_memory_metrics;" + queryStatsMySQLCommandsCounters = "SELECT * FROM stats_mysql_commands_counters;" + queryStatsMySQLUsers = "SELECT * FROM stats_mysql_users;" + queryStatsMySQLConnectionPool = "SELECT * FROM stats_mysql_connection_pool;" +) + +func (p *ProxySQL) collect() (map[string]int64, error) { + if p.db == nil { + if err := p.openConnection(); err != nil { + return nil, err + } + } + + p.once.Do(func() { + v, err := p.doQueryVersion() + if err != nil { + p.Warningf("error on querying version: %v", err) + } else { + p.Debugf("connected to ProxySQL version: %s", v) + } + }) + + p.cache.reset() + + mx := make(map[string]int64) + + if err := p.collectStatsMySQLGlobal(mx); err != nil { + return nil, fmt.Errorf("error on collecting mysql global status: %v", err) + } + if err := p.collectStatsMySQLMemoryMetrics(mx); err != nil { + return nil, fmt.Errorf("error on collecting memory metrics: %v", err) + } + if err := p.collectStatsMySQLCommandsCounters(mx); err != nil { + return nil, fmt.Errorf("error on collecting mysql command counters: %v", err) + } + if err := p.collectStatsMySQLUsers(mx); err != nil { + return nil, fmt.Errorf("error on collecting mysql users: %v", err) + } + if err := p.collectStatsMySQLConnectionPool(mx); err != nil { + return nil, fmt.Errorf("error on collecting mysql connection pool: %v", err) + } + + p.updateCharts() + + return mx, nil +} + +func (p *ProxySQL) doQueryVersion() (string, error) { + q := queryVersion + p.Debugf("executing query: '%s'", q) + + var v string + if err := p.doQueryRow(q, &v); err != nil { + return "", err + } + + return v, nil +} + +func (p *ProxySQL) collectStatsMySQLGlobal(mx map[string]int64) error { + // https://proxysql.com/documentation/stats-statistics/#stats_mysql_global + q := queryStatsMySQLGlobal + p.Debugf("executing query: '%s'", q) + + var name string + return p.doQuery(q, func(column, value string, rowEnd bool) { + switch column { + case "Variable_Name": + name = value + case "Variable_Value": + mx[name] = parseInt(value) + } + }) +} + +func (p *ProxySQL) collectStatsMySQLMemoryMetrics(mx map[string]int64) error { + // https://proxysql.com/documentation/stats-statistics/#stats_mysql_memory_metrics + q := queryStatsMySQLMemoryMetrics + p.Debugf("executing query: '%s'", q) + + var name string + return p.doQuery(q, func(column, value string, rowEnd bool) { + switch column { + case "Variable_Name": + name = value + case "Variable_Value": + mx[name] = parseInt(value) + } + }) +} + +func (p *ProxySQL) collectStatsMySQLCommandsCounters(mx map[string]int64) error { + // https://proxysql.com/documentation/stats-statistics/#stats_mysql_commands_counters + q := queryStatsMySQLCommandsCounters + p.Debugf("executing query: '%s'", q) + + var command string + return p.doQuery(q, func(column, value string, rowEnd bool) { + switch column { + case "Command": + command = value + p.cache.getCommand(command).updated = true + default: + mx["mysql_command_"+command+"_"+column] = parseInt(value) + } + }) +} + +func (p *ProxySQL) collectStatsMySQLUsers(mx map[string]int64) error { + // https://proxysql.com/documentation/stats-statistics/#stats_mysql_users + q := queryStatsMySQLUsers + p.Debugf("executing query: '%s'", q) + + var user string + var used int64 + return p.doQuery(q, func(column, value string, rowEnd bool) { + switch column { + case "username": + user = value + p.cache.getUser(user).updated = true + case "frontend_connections": + used = parseInt(value) + mx["mysql_user_"+user+"_"+column] = used + case "frontend_max_connections": + mx["mysql_user_"+user+"_frontend_connections_utilization"] = calcPercentage(used, parseInt(value)) + } + }) +} + +func (p *ProxySQL) collectStatsMySQLConnectionPool(mx map[string]int64) error { + // https://proxysql.com/documentation/stats-statistics/#stats_mysql_connection_pool + q := queryStatsMySQLConnectionPool + p.Debugf("executing query: '%s'", q) + + var hg, host, port string + var px string + return p.doQuery(q, func(column, value string, rowEnd bool) { + switch column { + case "hg", "hostgroup": + hg = value + case "srv_host": + host = value + case "srv_port": + port = value + p.cache.getBackend(hg, host, port).updated = true + px = "backend_" + backendID(hg, host, port) + "_" + case "status": + mx[px+"status_ONLINE"] = boolToInt(value == "1") + mx[px+"status_SHUNNED"] = boolToInt(value == "2") + mx[px+"status_OFFLINE_SOFT"] = boolToInt(value == "3") + mx[px+"status_OFFLINE_HARD"] = boolToInt(value == "4") + default: + mx[px+column] = parseInt(value) + } + }) +} + +func (p *ProxySQL) updateCharts() { + for k, m := range p.cache.commands { + if !m.updated { + delete(p.cache.commands, k) + p.removeMySQLCommandCountersCharts(m.command) + continue + } + if !m.hasCharts { + m.hasCharts = true + p.addMySQLCommandCountersCharts(m.command) + } + } + for k, m := range p.cache.users { + if !m.updated { + delete(p.cache.users, k) + p.removeMySQLUserCharts(m.user) + continue + } + if !m.hasCharts { + m.hasCharts = true + p.addMySQLUsersCharts(m.user) + } + } + for k, m := range p.cache.backends { + if !m.updated { + delete(p.cache.backends, k) + p.removeBackendCharts(m.hg, m.host, m.port) + continue + } + if !m.hasCharts { + m.hasCharts = true + p.addBackendCharts(m.hg, m.host, m.port) + } + } +} + +func (p *ProxySQL) openConnection() error { + db, err := sql.Open("mysql", p.DSN) + if err != nil { + return fmt.Errorf("error on opening a connection with the proxysql instance [%s]: %v", p.DSN, err) + } + + db.SetConnMaxLifetime(10 * time.Minute) + + if err := db.Ping(); err != nil { + _ = db.Close() + return fmt.Errorf("error on pinging the proxysql instance [%s]: %v", p.DSN, err) + } + + p.db = db + return nil +} + +func (p *ProxySQL) doQueryRow(query string, v any) error { + ctx, cancel := context.WithTimeout(context.Background(), p.Timeout.Duration()) + defer cancel() + + return p.db.QueryRowContext(ctx, query).Scan(v) +} + +func (p *ProxySQL) doQuery(query string, assign func(column, value string, rowEnd bool)) error { + ctx, cancel := context.WithTimeout(context.Background(), p.Timeout.Duration()) + defer cancel() + + rows, err := p.db.QueryContext(ctx, query) + if err != nil { + return err + } + defer func() { _ = rows.Close() }() + + return readRows(rows, assign) +} + +func readRows(rows *sql.Rows, assign func(column, value string, rowEnd bool)) error { + columns, err := rows.Columns() + if err != nil { + return err + } + + values := makeValues(len(columns)) + + for rows.Next() { + if err := rows.Scan(values...); err != nil { + return err + } + for i, l := 0, len(values); i < l; i++ { + assign(columns[i], valueToString(values[i]), i == l-1) + } + } + return rows.Err() +} + +func valueToString(value any) string { + v, ok := value.(*sql.NullString) + if !ok || !v.Valid { + return "" + } + return v.String +} + +func makeValues(size int) []any { + vs := make([]any, size) + for i := range vs { + vs[i] = &sql.NullString{} + } + return vs +} + +func parseInt(value string) int64 { + v, _ := strconv.ParseInt(value, 10, 64) + return v +} + +func calcPercentage(value, total int64) (v int64) { + if total == 0 { + return 0 + } + if v = value * 100 / total; v < 0 { + v = -v + } + return v +} + +func boolToInt(v bool) int64 { + if v { + return 1 + } + return 0 +} + +func backendID(hg, host, port string) string { + hg = strings.ReplaceAll(strings.ToLower(hg), " ", "_") + host = strings.ReplaceAll(host, ".", "_") + return hg + "_" + host + "_" + port +} diff --git a/src/go/collectors/go.d.plugin/modules/proxysql/config_schema.json b/src/go/collectors/go.d.plugin/modules/proxysql/config_schema.json new file mode 100644 index 000000000..c0c880a2e --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/proxysql/config_schema.json @@ -0,0 +1,47 @@ +{ + "jsonSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ProxySQL collector configuration.", + "type": "object", + "properties": { + "update_every": { + "title": "Update every", + "description": "Data collection interval, measured in seconds.", + "type": "integer", + "minimum": 1, + "default": 1 + }, + "dsn": { + "title": "DSN", + "description": "ProxySQL server [Data Source Name (DSN)](https://github.com/go-sql-driver/mysql#dsn-data-source-name) specifying the connection details.", + "type": "string", + "default": "stats:stats@tcp(127.0.0.1:6032)/" + }, + "timeout": { + "title": "Timeout", + "description": "Timeout for queries, in seconds.", + "type": "number", + "minimum": 0.5, + "default": 1 + } + }, + "required": [ + "dsn" + ], + "additionalProperties": false, + "patternProperties": { + "^name$": {} + } + }, + "uiSchema": { + "uiOptions": { + "fullPage": true + }, + "dsn": { + "ui:placeholder": "username:password@protocol(address)/dbname" + }, + "timeout": { + "ui:help": "Accepts decimals for precise control (e.g., type 1.5 for 1.5 seconds)." + } + } +} diff --git a/src/go/collectors/go.d.plugin/modules/proxysql/integrations/proxysql.md b/src/go/collectors/go.d.plugin/modules/proxysql/integrations/proxysql.md new file mode 100644 index 000000000..2cfb0b065 --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/proxysql/integrations/proxysql.md @@ -0,0 +1,274 @@ +<!--startmeta +custom_edit_url: "https://github.com/netdata/netdata/edit/master/src/go/collectors/go.d.plugin/modules/proxysql/README.md" +meta_yaml: "https://github.com/netdata/netdata/edit/master/src/go/collectors/go.d.plugin/modules/proxysql/metadata.yaml" +sidebar_label: "ProxySQL" +learn_status: "Published" +learn_rel_path: "Collecting Metrics/Databases" +most_popular: False +message: "DO NOT EDIT THIS FILE DIRECTLY, IT IS GENERATED BY THE COLLECTOR'S metadata.yaml FILE" +endmeta--> + +# ProxySQL + + +<img src="https://netdata.cloud/img/proxysql.png" width="150"/> + + +Plugin: go.d.plugin +Module: proxysql + +<img src="https://img.shields.io/badge/maintained%20by-Netdata-%2300ab44" /> + +## Overview + +This collector monitors ProxySQL servers. + + + + +This collector is supported on all platforms. + +This collector supports collecting metrics from multiple instances of this integration, including remote instances. + + +### Default Behavior + +#### Auto-Detection + +This integration doesn't support auto-detection. + +#### Limits + +The default configuration for this integration does not impose any limits on data collection. + +#### Performance Impact + +The default configuration for this integration is not expected to impose a significant performance impact on the system. + + +## Metrics + +Metrics grouped by *scope*. + +The scope defines the instance that the metric belongs to. An instance is uniquely identified by a set of labels. + + + +### Per ProxySQL instance + +These metrics refer to the entire monitored application. + +This scope has no labels. + +Metrics: + +| Metric | Dimensions | Unit | +|:------|:----------|:----| +| proxysql.client_connections_count | connected, non_idle, hostgroup_locked | connections | +| proxysql.client_connections_rate | created, aborted | connections/s | +| proxysql.server_connections_count | connected | connections | +| proxysql.server_connections_rate | created, aborted, delayed | connections/s | +| proxysql.backends_traffic | recv, sent | B/s | +| proxysql.clients_traffic | recv, sent | B/s | +| proxysql.active_transactions_count | client | connections | +| proxysql.questions_rate | questions | questions/s | +| proxysql.slow_queries_rate | slow | queries/s | +| proxysql.queries_rate | autocommit, autocommit_filtered, commit_filtered, rollback, rollback_filtered, backend_change_user, backend_init_db, backend_set_names, frontend_init_db, frontend_set_names, frontend_use_db | queries/s | +| proxysql.backend_statements_count | total, unique | statements | +| proxysql.backend_statements_rate | prepare, execute, close | statements/s | +| proxysql.client_statements_count | total, unique | statements | +| proxysql.client_statements_rate | prepare, execute, close | statements/s | +| proxysql.cached_statements_count | cached | statements | +| proxysql.query_cache_entries_count | entries | entries | +| proxysql.query_cache_memory_used | used | B | +| proxysql.query_cache_io | in, out | B/s | +| proxysql.query_cache_requests_rate | read, write, read_success | requests/s | +| proxysql.mysql_monitor_workers_count | workers, auxiliary | threads | +| proxysql.mysql_monitor_workers_rate | started | workers/s | +| proxysql.mysql_monitor_connect_checks_rate | succeed, failed | checks/s | +| proxysql.mysql_monitor_ping_checks_rate | succeed, failed | checks/s | +| proxysql.mysql_monitor_read_only_checks_rate | succeed, failed | checks/s | +| proxysql.mysql_monitor_replication_lag_checks_rate | succeed, failed | checks/s | +| proxysql.jemalloc_memory_used | active, allocated, mapped, metadata, resident, retained | B | +| proxysql.memory_used | auth, sqlite3, query_digest, query_rules, firewall_users_table, firewall_users_config, firewall_rules_table, firewall_rules_config, mysql_threads, admin_threads, cluster_threads | B | +| proxysql.uptime | uptime | seconds | + +### Per command + +These metrics refer to the SQL command. + +Labels: + +| Label | Description | +|:-----------|:----------------| +| command | SQL command. | + +Metrics: + +| Metric | Dimensions | Unit | +|:------|:----------|:----| +| proxysql.mysql_command_execution_rate | uptime | seconds | +| proxysql.mysql_command_execution_time | time | microseconds | +| proxysql.mysql_command_execution_duration | 100us, 500us, 1ms, 5ms, 10ms, 50ms, 100ms, 500ms, 1s, 5s, 10s, +Inf | microseconds | + +### Per user + +These metrics refer to the user. + +Labels: + +| Label | Description | +|:-----------|:----------------| +| user | username from the mysql_users table | + +Metrics: + +| Metric | Dimensions | Unit | +|:------|:----------|:----| +| proxysql.mysql_user_connections_utilization | used | percentage | +| proxysql.mysql_user_connections_count | used | connections | + +### Per backend + +These metrics refer to the backend server. + +Labels: + +| Label | Description | +|:-----------|:----------------| +| host | backend server host | +| port | backend server port | + +Metrics: + +| Metric | Dimensions | Unit | +|:------|:----------|:----| +| proxysql.backend_status | online, shunned, offline_soft, offline_hard | status | +| proxysql.backend_connections_usage | free, used | connections | +| proxysql.backend_connections_rate | succeed, failed | connections/s | +| proxysql.backend_queries_rate | queries | queries/s | +| proxysql.backend_traffic | recv, send | B/s | +| proxysql.backend_latency | latency | microseconds | + + + +## Alerts + +There are no alerts configured by default for this integration. + + +## Setup + +### Prerequisites + +No action required. + +### Configuration + +#### File + +The configuration file name for this integration is `go.d/proxysql.conf`. + + +You can edit the configuration file using the `edit-config` script from the +Netdata [config directory](/docs/netdata-agent/configuration/README.md#the-netdata-config-directory). + +```bash +cd /etc/netdata 2>/dev/null || cd /opt/netdata/etc/netdata +sudo ./edit-config go.d/proxysql.conf +``` +#### Options + +The following options can be defined globally: update_every, autodetection_retry. + + +<details open><summary>Config options</summary> + +| Name | Description | Default | Required | +|:----|:-----------|:-------|:--------:| +| update_every | Data collection frequency. | 1 | no | +| autodetection_retry | Recheck interval in seconds. Zero means no recheck will be scheduled. | 0 | no | +| dsn | Data Source Name. See [DSN syntax](https://github.com/go-sql-driver/mysql#dsn-data-source-name). | stats:stats@tcp(127.0.0.1:6032)/ | yes | +| timeout | Query timeout in seconds. | 1 | no | + +</details> + +#### Examples + +##### TCP socket + +An example configuration. + +<details open><summary>Config</summary> + +```yaml +jobs: + - name: local + dsn: stats:stats@tcp(127.0.0.1:6032)/ + +``` +</details> + +##### my.cnf + +An example configuration. + +<details open><summary>Config</summary> + +```yaml +jobs: + - name: local + my.cnf: '/etc/my.cnf' + +``` +</details> + +##### Multi-instance + +> **Note**: When you define multiple jobs, their names must be unique. + +Local and remote instances. + + +<details open><summary>Config</summary> + +```yaml +jobs: + - name: local + dsn: stats:stats@tcp(127.0.0.1:6032)/ + + - name: remote + dsn: stats:stats@tcp(203.0.113.0:6032)/ + +``` +</details> + + + +## Troubleshooting + +### Debug Mode + +To troubleshoot issues with the `proxysql` collector, run the `go.d.plugin` with the debug option enabled. The output +should give you clues as to why the collector isn't working. + +- Navigate to the `plugins.d` directory, usually at `/usr/libexec/netdata/plugins.d/`. If that's not the case on + your system, open `netdata.conf` and look for the `plugins` setting under `[directories]`. + + ```bash + cd /usr/libexec/netdata/plugins.d/ + ``` + +- Switch to the `netdata` user. + + ```bash + sudo -u netdata -s + ``` + +- Run the `go.d.plugin` to debug the collector: + + ```bash + ./go.d.plugin -d -m proxysql + ``` + + diff --git a/src/go/collectors/go.d.plugin/modules/proxysql/metadata.yaml b/src/go/collectors/go.d.plugin/modules/proxysql/metadata.yaml new file mode 100644 index 000000000..2c9562d99 --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/proxysql/metadata.yaml @@ -0,0 +1,430 @@ +plugin_name: go.d.plugin +modules: + - meta: + id: collector-go.d.plugin-proxysql + plugin_name: go.d.plugin + module_name: proxysql + monitored_instance: + name: ProxySQL + link: https://www.proxysql.com/ + icon_filename: proxysql.png + categories: + - data-collection.database-servers + keywords: + - proxysql + - databases + - sql + related_resources: + integrations: + list: [] + info_provided_to_referring_integrations: + description: "" + most_popular: false + overview: + data_collection: + metrics_description: | + This collector monitors ProxySQL servers. + method_description: "" + supported_platforms: + include: [] + exclude: [] + multi_instance: true + additional_permissions: + description: "" + default_behavior: + auto_detection: + description: "" + limits: + description: "" + performance_impact: + description: "" + setup: + prerequisites: + list: [] + configuration: + file: + name: go.d/proxysql.conf + options: + description: | + The following options can be defined globally: update_every, autodetection_retry. + folding: + title: Config options + enabled: true + list: + - name: update_every + description: Data collection frequency. + default_value: 1 + required: false + - name: autodetection_retry + description: Recheck interval in seconds. Zero means no recheck will be scheduled. + default_value: 0 + required: false + - name: dsn + description: Data Source Name. See [DSN syntax](https://github.com/go-sql-driver/mysql#dsn-data-source-name). + default_value: stats:stats@tcp(127.0.0.1:6032)/ + required: true + - name: timeout + description: Query timeout in seconds. + default_value: 1 + required: false + examples: + folding: + title: Config + enabled: true + list: + - name: TCP socket + description: An example configuration. + config: | + jobs: + - name: local + dsn: stats:stats@tcp(127.0.0.1:6032)/ + - name: my.cnf + description: An example configuration. + config: | + jobs: + - name: local + my.cnf: '/etc/my.cnf' + - name: Multi-instance + description: | + > **Note**: When you define multiple jobs, their names must be unique. + + Local and remote instances. + config: | + jobs: + - name: local + dsn: stats:stats@tcp(127.0.0.1:6032)/ + + - name: remote + dsn: stats:stats@tcp(203.0.113.0:6032)/ + troubleshooting: + problems: + list: [] + alerts: [] + metrics: + folding: + title: Metrics + enabled: false + description: "" + availability: [] + scopes: + - name: global + description: These metrics refer to the entire monitored application. + labels: [] + metrics: + - name: proxysql.client_connections_count + description: Client connections + unit: connections + chart_type: line + dimensions: + - name: connected + - name: non_idle + - name: hostgroup_locked + - name: proxysql.client_connections_rate + description: Client connections rate + unit: connections/s + chart_type: line + dimensions: + - name: created + - name: aborted + - name: proxysql.server_connections_count + description: Server connections + unit: connections + chart_type: line + dimensions: + - name: connected + - name: proxysql.server_connections_rate + description: Server connections rate + unit: connections/s + chart_type: line + dimensions: + - name: created + - name: aborted + - name: delayed + - name: proxysql.backends_traffic + description: Backends traffic + unit: B/s + chart_type: line + dimensions: + - name: recv + - name: sent + - name: proxysql.clients_traffic + description: Clients traffic + unit: B/s + chart_type: line + dimensions: + - name: recv + - name: sent + - name: proxysql.active_transactions_count + description: Client connections that are currently processing a transaction + unit: connections + chart_type: line + dimensions: + - name: client + - name: proxysql.questions_rate + description: Client requests / statements executed + unit: questions/s + chart_type: line + dimensions: + - name: questions + - name: proxysql.slow_queries_rate + description: Slow queries + unit: queries/s + chart_type: line + dimensions: + - name: slow + - name: proxysql.queries_rate + description: Queries rate + unit: queries/s + chart_type: stacked + dimensions: + - name: autocommit + - name: autocommit_filtered + - name: commit_filtered + - name: rollback + - name: rollback_filtered + - name: backend_change_user + - name: backend_init_db + - name: backend_set_names + - name: frontend_init_db + - name: frontend_set_names + - name: frontend_use_db + - name: proxysql.backend_statements_count + description: Statements available across all backend connections + unit: statements + chart_type: line + dimensions: + - name: total + - name: unique + - name: proxysql.backend_statements_rate + description: Statements executed against the backends + unit: statements/s + chart_type: stacked + dimensions: + - name: prepare + - name: execute + - name: close + - name: proxysql.client_statements_count + description: Statements that are in use by clients + unit: statements + chart_type: line + dimensions: + - name: total + - name: unique + - name: proxysql.client_statements_rate + description: Statements executed by clients + unit: statements/s + chart_type: stacked + dimensions: + - name: prepare + - name: execute + - name: close + - name: proxysql.cached_statements_count + description: Global prepared statements + unit: statements + chart_type: line + dimensions: + - name: cached + - name: proxysql.query_cache_entries_count + description: Query Cache entries + unit: entries + chart_type: line + dimensions: + - name: entries + - name: proxysql.query_cache_memory_used + description: Query Cache memory used + unit: B + chart_type: line + dimensions: + - name: used + - name: proxysql.query_cache_io + description: Query Cache I/O + unit: B/s + chart_type: line + dimensions: + - name: in + - name: out + - name: proxysql.query_cache_requests_rate + description: Query Cache requests + unit: requests/s + chart_type: line + dimensions: + - name: read + - name: write + - name: read_success + - name: proxysql.mysql_monitor_workers_count + description: MySQL monitor workers + unit: threads + chart_type: line + dimensions: + - name: workers + - name: auxiliary + - name: proxysql.mysql_monitor_workers_rate + description: MySQL monitor workers rate + unit: workers/s + chart_type: line + dimensions: + - name: started + - name: proxysql.mysql_monitor_connect_checks_rate + description: MySQL monitor connect checks + unit: checks/s + chart_type: line + dimensions: + - name: succeed + - name: failed + - name: proxysql.mysql_monitor_ping_checks_rate + description: MySQL monitor ping checks + unit: checks/s + chart_type: line + dimensions: + - name: succeed + - name: failed + - name: proxysql.mysql_monitor_read_only_checks_rate + description: MySQL monitor read only checks + unit: checks/s + chart_type: line + dimensions: + - name: succeed + - name: failed + - name: proxysql.mysql_monitor_replication_lag_checks_rate + description: MySQL monitor replication lag checks + unit: checks/s + chart_type: line + dimensions: + - name: succeed + - name: failed + - name: proxysql.jemalloc_memory_used + description: Jemalloc used memory + unit: B + chart_type: stacked + dimensions: + - name: active + - name: allocated + - name: mapped + - name: metadata + - name: resident + - name: retained + - name: proxysql.memory_used + description: Memory used + unit: B + chart_type: stacked + dimensions: + - name: auth + - name: sqlite3 + - name: query_digest + - name: query_rules + - name: firewall_users_table + - name: firewall_users_config + - name: firewall_rules_table + - name: firewall_rules_config + - name: mysql_threads + - name: admin_threads + - name: cluster_threads + - name: proxysql.uptime + description: Uptime + unit: seconds + chart_type: line + dimensions: + - name: uptime + - name: command + description: These metrics refer to the SQL command. + labels: + - name: command + description: SQL command. + metrics: + - name: proxysql.mysql_command_execution_rate + description: MySQL command execution + unit: seconds + chart_type: line + dimensions: + - name: uptime + - name: proxysql.mysql_command_execution_time + description: MySQL command execution time + unit: microseconds + chart_type: line + dimensions: + - name: time + - name: proxysql.mysql_command_execution_duration + description: MySQL command execution duration histogram + unit: microseconds + chart_type: stacked + dimensions: + - name: 100us + - name: 500us + - name: 1ms + - name: 5ms + - name: 10ms + - name: 50ms + - name: 100ms + - name: 500ms + - name: 1s + - name: 5s + - name: 10s + - name: +Inf + - name: user + description: These metrics refer to the user. + labels: + - name: user + description: username from the mysql_users table + metrics: + - name: proxysql.mysql_user_connections_utilization + description: MySQL user connections utilization + unit: percentage + chart_type: line + dimensions: + - name: used + - name: proxysql.mysql_user_connections_count + description: MySQL user connections used + unit: connections + chart_type: line + dimensions: + - name: used + - name: backend + description: These metrics refer to the backend server. + labels: + - name: host + description: backend server host + - name: port + description: backend server port + metrics: + - name: proxysql.backend_status + description: Backend status + unit: status + chart_type: line + dimensions: + - name: online + - name: shunned + - name: offline_soft + - name: offline_hard + - name: proxysql.backend_connections_usage + description: Backend connections usage + unit: connections + chart_type: line + dimensions: + - name: free + - name: used + - name: proxysql.backend_connections_rate + description: Backend connections established + unit: connections/s + chart_type: line + dimensions: + - name: succeed + - name: failed + - name: proxysql.backend_queries_rate + description: Backend queries + unit: queries/s + chart_type: line + dimensions: + - name: queries + - name: proxysql.backend_traffic + description: Backend traffic + unit: B/s + chart_type: line + dimensions: + - name: recv + - name: send + - name: proxysql.backend_latency + description: Backend latency + unit: microseconds + chart_type: line + dimensions: + - name: latency diff --git a/src/go/collectors/go.d.plugin/modules/proxysql/proxysql.go b/src/go/collectors/go.d.plugin/modules/proxysql/proxysql.go new file mode 100644 index 000000000..4fe08b8b0 --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/proxysql/proxysql.go @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package proxysql + +import ( + "database/sql" + _ "embed" + "errors" + _ "github.com/go-sql-driver/mysql" + "sync" + "time" + + "github.com/netdata/netdata/go/go.d.plugin/agent/module" + "github.com/netdata/netdata/go/go.d.plugin/pkg/web" +) + +//go:embed "config_schema.json" +var configSchema string + +func init() { + module.Register("proxysql", module.Creator{ + JobConfigSchema: configSchema, + Create: func() module.Module { return New() }, + Config: func() any { return &Config{} }, + }) +} + +func New() *ProxySQL { + return &ProxySQL{ + Config: Config{ + DSN: "stats:stats@tcp(127.0.0.1:6032)/", + Timeout: web.Duration(time.Second), + }, + + charts: baseCharts.Copy(), + once: &sync.Once{}, + cache: &cache{ + commands: make(map[string]*commandCache), + users: make(map[string]*userCache), + backends: make(map[string]*backendCache), + }, + } +} + +type Config struct { + UpdateEvery int `yaml:"update_every,omitempty" json:"update_every"` + DSN string `yaml:"dsn" json:"dsn"` + Timeout web.Duration `yaml:"timeout,omitempty" json:"timeout"` +} + +type ProxySQL struct { + module.Base + Config `yaml:",inline" json:""` + + charts *module.Charts + + db *sql.DB + + once *sync.Once + cache *cache +} + +func (p *ProxySQL) Configuration() any { + return p.Config +} + +func (p *ProxySQL) Init() error { + if p.DSN == "" { + p.Error("dsn not set") + return errors.New("dsn not set") + } + + p.Debugf("using DSN [%s]", p.DSN) + + return nil +} + +func (p *ProxySQL) Check() error { + mx, err := p.collect() + if err != nil { + p.Error(err) + return err + } + if len(mx) == 0 { + return errors.New("no metrics collected") + } + return nil +} + +func (p *ProxySQL) Charts() *module.Charts { + return p.charts +} + +func (p *ProxySQL) Collect() map[string]int64 { + mx, err := p.collect() + if err != nil { + p.Error(err) + } + + if len(mx) == 0 { + return nil + } + return mx +} + +func (p *ProxySQL) Cleanup() { + if p.db == nil { + return + } + if err := p.db.Close(); err != nil { + p.Errorf("cleanup: error on closing the ProxySQL instance [%s]: %v", p.DSN, err) + } + p.db = nil +} diff --git a/src/go/collectors/go.d.plugin/modules/proxysql/proxysql_test.go b/src/go/collectors/go.d.plugin/modules/proxysql/proxysql_test.go new file mode 100644 index 000000000..3dfaf1bf3 --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/proxysql/proxysql_test.go @@ -0,0 +1,1240 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package proxysql + +import ( + "bufio" + "bytes" + "database/sql/driver" + "errors" + "fmt" + "os" + "strings" + "testing" + + "github.com/netdata/netdata/go/go.d.plugin/agent/module" + + "github.com/DATA-DOG/go-sqlmock" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +var ( + dataConfigJSON, _ = os.ReadFile("testdata/config.json") + dataConfigYAML, _ = os.ReadFile("testdata/config.yaml") + + dataVer2010Version, _ = os.ReadFile("testdata/v2.0.10/version.txt") + dataVer2010StatsMySQLGlobal, _ = os.ReadFile("testdata/v2.0.10/stats_mysql_global.txt") + dataVer2010StatsMemoryMetrics, _ = os.ReadFile("testdata/v2.0.10/stats_memory_metrics.txt") + dataVer2010StatsMySQLCommandsCounters, _ = os.ReadFile("testdata/v2.0.10/stats_mysql_commands_counters.txt") + dataVer2010StatsMySQLUsers, _ = os.ReadFile("testdata/v2.0.10/stats_mysql_users.txt") + dataVer2010StatsMySQLConnectionPool, _ = os.ReadFile("testdata/v2.0.10/stats_mysql_connection_pool .txt") +) + +func Test_testDataIsValid(t *testing.T) { + for name, data := range map[string][]byte{ + "dataConfigJSON": dataConfigJSON, + "dataConfigYAML": dataConfigYAML, + "dataVer2010Version": dataVer2010Version, + "dataVer2010StatsMySQLGlobal": dataVer2010StatsMySQLGlobal, + "dataVer2010StatsMemoryMetrics": dataVer2010StatsMemoryMetrics, + "dataVer2010StatsMySQLCommandsCounters": dataVer2010StatsMySQLCommandsCounters, + "dataVer2010StatsMySQLUsers": dataVer2010StatsMySQLUsers, + "dataVer2010StatsMySQLConnectionPool": dataVer2010StatsMySQLConnectionPool, + } { + require.NotNil(t, data, name) + _, err := prepareMockRows(data) + require.NoError(t, err, name) + } +} + +func TestProxySQL_ConfigurationSerialize(t *testing.T) { + module.TestConfigurationSerialize(t, &ProxySQL{}, dataConfigJSON, dataConfigYAML) +} + +func TestProxySQL_Init(t *testing.T) { + tests := map[string]struct { + config Config + wantFail bool + }{ + "default": { + wantFail: false, + config: New().Config, + }, + "empty DSN": { + wantFail: true, + config: Config{DSN: ""}, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + proxySQL := New() + proxySQL.Config = test.config + + if test.wantFail { + assert.Error(t, proxySQL.Init()) + } else { + assert.NoError(t, proxySQL.Init()) + } + }) + } +} + +func TestProxySQL_Cleanup(t *testing.T) { + tests := map[string]func(t *testing.T) (proxySQL *ProxySQL, cleanup func()){ + "db connection not initialized": func(t *testing.T) (proxySQL *ProxySQL, cleanup func()) { + return New(), func() {} + }, + "db connection initialized": func(t *testing.T) (proxySQL *ProxySQL, cleanup func()) { + db, mock, err := sqlmock.New() + require.NoError(t, err) + + mock.ExpectClose() + proxySQL = New() + proxySQL.db = db + cleanup = func() { _ = db.Close() } + + return proxySQL, cleanup + }, + } + + for name, prepare := range tests { + t.Run(name, func(t *testing.T) { + proxySQL, cleanup := prepare(t) + defer cleanup() + + assert.NotPanics(t, proxySQL.Cleanup) + assert.Nil(t, proxySQL.db) + }) + } +} + +func TestProxySQL_Charts(t *testing.T) { + assert.NotNil(t, New().Charts()) +} + +func TestProxySQL_Check(t *testing.T) { + tests := map[string]struct { + prepareMock func(t *testing.T, m sqlmock.Sqlmock) + wantFail bool + }{ + "success on all queries": { + wantFail: false, + prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { + mockExpect(t, m, queryVersion, dataVer2010Version) + mockExpect(t, m, queryStatsMySQLGlobal, dataVer2010StatsMySQLGlobal) + mockExpect(t, m, queryStatsMySQLMemoryMetrics, dataVer2010StatsMemoryMetrics) + mockExpect(t, m, queryStatsMySQLCommandsCounters, dataVer2010StatsMySQLCommandsCounters) + mockExpect(t, m, queryStatsMySQLUsers, dataVer2010StatsMySQLUsers) + mockExpect(t, m, queryStatsMySQLConnectionPool, dataVer2010StatsMySQLConnectionPool) + }, + }, + "fails when error on querying global stats": { + wantFail: true, + prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { + mockExpect(t, m, queryVersion, dataVer2010Version) + mockExpectErr(m, queryStatsMySQLGlobal) + }, + }, + "fails when error on querying memory metrics": { + wantFail: true, + prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { + mockExpect(t, m, queryVersion, dataVer2010Version) + mockExpect(t, m, queryStatsMySQLGlobal, dataVer2010StatsMySQLGlobal) + mockExpectErr(m, queryStatsMySQLMemoryMetrics) + }, + }, + "fails when error on querying mysql command counters": { + wantFail: true, + prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { + mockExpect(t, m, queryVersion, dataVer2010Version) + mockExpect(t, m, queryStatsMySQLGlobal, dataVer2010StatsMySQLGlobal) + mockExpect(t, m, queryStatsMySQLMemoryMetrics, dataVer2010StatsMemoryMetrics) + mockExpectErr(m, queryStatsMySQLCommandsCounters) + }, + }, + "fails when error on querying mysql users": { + wantFail: true, + prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { + mockExpect(t, m, queryVersion, dataVer2010Version) + mockExpect(t, m, queryStatsMySQLGlobal, dataVer2010StatsMySQLGlobal) + mockExpect(t, m, queryStatsMySQLMemoryMetrics, dataVer2010StatsMemoryMetrics) + mockExpect(t, m, queryStatsMySQLCommandsCounters, dataVer2010StatsMySQLCommandsCounters) + mockExpectErr(m, queryStatsMySQLUsers) + }, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + db, mock, err := sqlmock.New( + sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual), + ) + require.NoError(t, err) + proxySQL := New() + proxySQL.db = db + defer func() { _ = db.Close() }() + + require.NoError(t, proxySQL.Init()) + + test.prepareMock(t, mock) + + if test.wantFail { + assert.Error(t, proxySQL.Check()) + } else { + assert.NoError(t, proxySQL.Check()) + } + assert.NoError(t, mock.ExpectationsWereMet()) + }) + } +} + +func TestProxySQL_Collect(t *testing.T) { + type testCaseStep struct { + prepareMock func(t *testing.T, m sqlmock.Sqlmock) + check func(t *testing.T, my *ProxySQL) + } + tests := map[string][]testCaseStep{ + + "success on all queries (v2.0.10)": { + { + prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { + mockExpect(t, m, queryVersion, dataVer2010Version) + mockExpect(t, m, queryStatsMySQLGlobal, dataVer2010StatsMySQLGlobal) + mockExpect(t, m, queryStatsMySQLMemoryMetrics, dataVer2010StatsMemoryMetrics) + mockExpect(t, m, queryStatsMySQLCommandsCounters, dataVer2010StatsMySQLCommandsCounters) + mockExpect(t, m, queryStatsMySQLUsers, dataVer2010StatsMySQLUsers) + mockExpect(t, m, queryStatsMySQLConnectionPool, dataVer2010StatsMySQLConnectionPool) + }, + check: func(t *testing.T, my *ProxySQL) { + mx := my.Collect() + + expected := map[string]int64{ + "Access_Denied_Max_Connections": 0, + "Access_Denied_Max_User_Connections": 0, + "Access_Denied_Wrong_Password": 2, + "Active_Transactions": 0, + "Auth_memory": 1044, + "Backend_query_time_nsec": 0, + "Client_Connections_aborted": 2, + "Client_Connections_connected": 3, + "Client_Connections_created": 5458991, + "Client_Connections_hostgroup_locked": 0, + "Client_Connections_non_idle": 3, + "Com_autocommit": 0, + "Com_autocommit_filtered": 0, + "Com_backend_change_user": 188694, + "Com_backend_init_db": 0, + "Com_backend_set_names": 1517893, + "Com_backend_stmt_close": 0, + "Com_backend_stmt_execute": 36303146, + "Com_backend_stmt_prepare": 16858208, + "Com_commit": 0, + "Com_commit_filtered": 0, + "Com_frontend_init_db": 2, + "Com_frontend_set_names": 0, + "Com_frontend_stmt_close": 32137933, + "Com_frontend_stmt_execute": 36314138, + "Com_frontend_stmt_prepare": 32185987, + "Com_frontend_use_db": 0, + "Com_rollback": 0, + "Com_rollback_filtered": 0, + "ConnPool_get_conn_failure": 212943, + "ConnPool_get_conn_immediate": 13361, + "ConnPool_get_conn_latency_awareness": 0, + "ConnPool_get_conn_success": 36319474, + "ConnPool_memory_bytes": 932248, + "GTID_consistent_queries": 0, + "GTID_session_collected": 0, + "Mirror_concurrency": 0, + "Mirror_queue_length": 0, + "MyHGM_myconnpoll_destroy": 15150, + "MyHGM_myconnpoll_get": 36519056, + "MyHGM_myconnpoll_get_ok": 36306113, + "MyHGM_myconnpoll_push": 37358734, + "MyHGM_myconnpoll_reset": 2, + "MySQL_Monitor_Workers": 10, + "MySQL_Monitor_Workers_Aux": 0, + "MySQL_Monitor_Workers_Started": 10, + "MySQL_Monitor_connect_check_ERR": 130, + "MySQL_Monitor_connect_check_OK": 3548306, + "MySQL_Monitor_ping_check_ERR": 108271, + "MySQL_Monitor_ping_check_OK": 21289849, + "MySQL_Monitor_read_only_check_ERR": 19610, + "MySQL_Monitor_read_only_check_OK": 106246409, + "MySQL_Monitor_replication_lag_check_ERR": 482, + "MySQL_Monitor_replication_lag_check_OK": 28702388, + "MySQL_Thread_Workers": 4, + "ProxySQL_Uptime": 26748286, + "Queries_backends_bytes_recv": 5896210168, + "Queries_backends_bytes_sent": 4329581500, + "Queries_frontends_bytes_recv": 7434816962, + "Queries_frontends_bytes_sent": 11643634097, + "Query_Cache_Entries": 0, + "Query_Cache_Memory_bytes": 0, + "Query_Cache_Purged": 0, + "Query_Cache_bytes_IN": 0, + "Query_Cache_bytes_OUT": 0, + "Query_Cache_count_GET": 0, + "Query_Cache_count_GET_OK": 0, + "Query_Cache_count_SET": 0, + "Query_Processor_time_nsec": 0, + "Questions": 100638067, + "SQLite3_memory_bytes": 6017144, + "Selects_for_update__autocommit0": 0, + "Server_Connections_aborted": 9979, + "Server_Connections_connected": 13, + "Server_Connections_created": 2122254, + "Server_Connections_delayed": 0, + "Servers_table_version": 37, + "Slow_queries": 405818, + "Stmt_Cached": 65, + "Stmt_Client_Active_Total": 18, + "Stmt_Client_Active_Unique": 18, + "Stmt_Max_Stmt_id": 66, + "Stmt_Server_Active_Total": 101, + "Stmt_Server_Active_Unique": 39, + "automatic_detected_sql_injection": 0, + "aws_aurora_replicas_skipped_during_query": 0, + "backend_10_back001-db-master_6001_Bytes_data_recv": 145193069937, + "backend_10_back001-db-master_6001_Bytes_data_sent": 9858463664, + "backend_10_back001-db-master_6001_ConnERR": 0, + "backend_10_back001-db-master_6001_ConnFree": 423, + "backend_10_back001-db-master_6001_ConnOK": 524, + "backend_10_back001-db-master_6001_ConnUsed": 69, + "backend_10_back001-db-master_6001_Latency_us": 17684, + "backend_10_back001-db-master_6001_Queries": 8970367, + "backend_10_back001-db-master_6001_status_OFFLINE_HARD": 0, + "backend_10_back001-db-master_6001_status_OFFLINE_SOFT": 0, + "backend_10_back001-db-master_6001_status_ONLINE": 0, + "backend_10_back001-db-master_6001_status_SHUNNED": 0, + "backend_11_back001-db-master_6002_Bytes_data_recv": 2903, + "backend_11_back001-db-master_6002_Bytes_data_sent": 187675, + "backend_11_back001-db-master_6002_ConnERR": 0, + "backend_11_back001-db-master_6002_ConnFree": 1, + "backend_11_back001-db-master_6002_ConnOK": 1, + "backend_11_back001-db-master_6002_ConnUsed": 0, + "backend_11_back001-db-master_6002_Latency_us": 17684, + "backend_11_back001-db-master_6002_Queries": 69, + "backend_11_back001-db-master_6002_status_OFFLINE_HARD": 0, + "backend_11_back001-db-master_6002_status_OFFLINE_SOFT": 0, + "backend_11_back001-db-master_6002_status_ONLINE": 0, + "backend_11_back001-db-master_6002_status_SHUNNED": 0, + "backend_11_back001-db-reader_6003_Bytes_data_recv": 4994101, + "backend_11_back001-db-reader_6003_Bytes_data_sent": 163690013, + "backend_11_back001-db-reader_6003_ConnERR": 0, + "backend_11_back001-db-reader_6003_ConnFree": 11, + "backend_11_back001-db-reader_6003_ConnOK": 11, + "backend_11_back001-db-reader_6003_ConnUsed": 0, + "backend_11_back001-db-reader_6003_Latency_us": 113, + "backend_11_back001-db-reader_6003_Queries": 63488, + "backend_11_back001-db-reader_6003_status_OFFLINE_HARD": 0, + "backend_11_back001-db-reader_6003_status_OFFLINE_SOFT": 0, + "backend_11_back001-db-reader_6003_status_ONLINE": 0, + "backend_11_back001-db-reader_6003_status_SHUNNED": 0, + "backend_20_back002-db-master_6004_Bytes_data_recv": 266034339, + "backend_20_back002-db-master_6004_Bytes_data_sent": 1086994186, + "backend_20_back002-db-master_6004_ConnERR": 2, + "backend_20_back002-db-master_6004_ConnFree": 188, + "backend_20_back002-db-master_6004_ConnOK": 197, + "backend_20_back002-db-master_6004_ConnUsed": 9, + "backend_20_back002-db-master_6004_Latency_us": 101981, + "backend_20_back002-db-master_6004_Queries": 849461, + "backend_20_back002-db-master_6004_status_OFFLINE_HARD": 0, + "backend_20_back002-db-master_6004_status_OFFLINE_SOFT": 0, + "backend_20_back002-db-master_6004_status_ONLINE": 0, + "backend_20_back002-db-master_6004_status_SHUNNED": 0, + "backend_21_back002-db-reader_6005_Bytes_data_recv": 984, + "backend_21_back002-db-reader_6005_Bytes_data_sent": 6992, + "backend_21_back002-db-reader_6005_ConnERR": 0, + "backend_21_back002-db-reader_6005_ConnFree": 1, + "backend_21_back002-db-reader_6005_ConnOK": 1, + "backend_21_back002-db-reader_6005_ConnUsed": 0, + "backend_21_back002-db-reader_6005_Latency_us": 230, + "backend_21_back002-db-reader_6005_Queries": 8, + "backend_21_back002-db-reader_6005_status_OFFLINE_HARD": 0, + "backend_21_back002-db-reader_6005_status_OFFLINE_SOFT": 0, + "backend_21_back002-db-reader_6005_status_ONLINE": 0, + "backend_21_back002-db-reader_6005_status_SHUNNED": 0, + "backend_31_back003-db-master_6006_Bytes_data_recv": 81438709, + "backend_31_back003-db-master_6006_Bytes_data_sent": 712803, + "backend_31_back003-db-master_6006_ConnERR": 0, + "backend_31_back003-db-master_6006_ConnFree": 3, + "backend_31_back003-db-master_6006_ConnOK": 3, + "backend_31_back003-db-master_6006_ConnUsed": 0, + "backend_31_back003-db-master_6006_Latency_us": 231, + "backend_31_back003-db-master_6006_Queries": 3276, + "backend_31_back003-db-master_6006_status_OFFLINE_HARD": 0, + "backend_31_back003-db-master_6006_status_OFFLINE_SOFT": 0, + "backend_31_back003-db-master_6006_status_ONLINE": 0, + "backend_31_back003-db-master_6006_status_SHUNNED": 0, + "backend_31_back003-db-reader_6007_Bytes_data_recv": 115810708275, + "backend_31_back003-db-reader_6007_Bytes_data_sent": 411900849, + "backend_31_back003-db-reader_6007_ConnERR": 0, + "backend_31_back003-db-reader_6007_ConnFree": 70, + "backend_31_back003-db-reader_6007_ConnOK": 71, + "backend_31_back003-db-reader_6007_ConnUsed": 1, + "backend_31_back003-db-reader_6007_Latency_us": 230, + "backend_31_back003-db-reader_6007_Queries": 2356904, + "backend_31_back003-db-reader_6007_status_OFFLINE_HARD": 0, + "backend_31_back003-db-reader_6007_status_OFFLINE_SOFT": 0, + "backend_31_back003-db-reader_6007_status_ONLINE": 0, + "backend_31_back003-db-reader_6007_status_SHUNNED": 0, + "backend_lagging_during_query": 8880, + "backend_offline_during_query": 8, + "generated_error_packets": 231, + "hostgroup_locked_queries": 0, + "hostgroup_locked_set_cmds": 0, + "jemalloc_active": 385101824, + "jemalloc_allocated": 379402432, + "jemalloc_mapped": 430993408, + "jemalloc_metadata": 17418872, + "jemalloc_resident": 403759104, + "jemalloc_retained": 260542464, + "max_connect_timeouts": 227, + "mysql_backend_buffers_bytes": 0, + "mysql_command_ALTER_TABLE_Total_Time_us": 0, + "mysql_command_ALTER_TABLE_Total_cnt": 0, + "mysql_command_ALTER_TABLE_cnt_100ms": 0, + "mysql_command_ALTER_TABLE_cnt_100us": 0, + "mysql_command_ALTER_TABLE_cnt_10ms": 0, + "mysql_command_ALTER_TABLE_cnt_10s": 0, + "mysql_command_ALTER_TABLE_cnt_1ms": 0, + "mysql_command_ALTER_TABLE_cnt_1s": 0, + "mysql_command_ALTER_TABLE_cnt_500ms": 0, + "mysql_command_ALTER_TABLE_cnt_500us": 0, + "mysql_command_ALTER_TABLE_cnt_50ms": 0, + "mysql_command_ALTER_TABLE_cnt_5ms": 0, + "mysql_command_ALTER_TABLE_cnt_5s": 0, + "mysql_command_ALTER_TABLE_cnt_INFs": 0, + "mysql_command_ALTER_VIEW_Total_Time_us": 0, + "mysql_command_ALTER_VIEW_Total_cnt": 0, + "mysql_command_ALTER_VIEW_cnt_100ms": 0, + "mysql_command_ALTER_VIEW_cnt_100us": 0, + "mysql_command_ALTER_VIEW_cnt_10ms": 0, + "mysql_command_ALTER_VIEW_cnt_10s": 0, + "mysql_command_ALTER_VIEW_cnt_1ms": 0, + "mysql_command_ALTER_VIEW_cnt_1s": 0, + "mysql_command_ALTER_VIEW_cnt_500ms": 0, + "mysql_command_ALTER_VIEW_cnt_500us": 0, + "mysql_command_ALTER_VIEW_cnt_50ms": 0, + "mysql_command_ALTER_VIEW_cnt_5ms": 0, + "mysql_command_ALTER_VIEW_cnt_5s": 0, + "mysql_command_ALTER_VIEW_cnt_INFs": 0, + "mysql_command_ANALYZE_TABLE_Total_Time_us": 0, + "mysql_command_ANALYZE_TABLE_Total_cnt": 0, + "mysql_command_ANALYZE_TABLE_cnt_100ms": 0, + "mysql_command_ANALYZE_TABLE_cnt_100us": 0, + "mysql_command_ANALYZE_TABLE_cnt_10ms": 0, + "mysql_command_ANALYZE_TABLE_cnt_10s": 0, + "mysql_command_ANALYZE_TABLE_cnt_1ms": 0, + "mysql_command_ANALYZE_TABLE_cnt_1s": 0, + "mysql_command_ANALYZE_TABLE_cnt_500ms": 0, + "mysql_command_ANALYZE_TABLE_cnt_500us": 0, + "mysql_command_ANALYZE_TABLE_cnt_50ms": 0, + "mysql_command_ANALYZE_TABLE_cnt_5ms": 0, + "mysql_command_ANALYZE_TABLE_cnt_5s": 0, + "mysql_command_ANALYZE_TABLE_cnt_INFs": 0, + "mysql_command_BEGIN_Total_Time_us": 0, + "mysql_command_BEGIN_Total_cnt": 0, + "mysql_command_BEGIN_cnt_100ms": 0, + "mysql_command_BEGIN_cnt_100us": 0, + "mysql_command_BEGIN_cnt_10ms": 0, + "mysql_command_BEGIN_cnt_10s": 0, + "mysql_command_BEGIN_cnt_1ms": 0, + "mysql_command_BEGIN_cnt_1s": 0, + "mysql_command_BEGIN_cnt_500ms": 0, + "mysql_command_BEGIN_cnt_500us": 0, + "mysql_command_BEGIN_cnt_50ms": 0, + "mysql_command_BEGIN_cnt_5ms": 0, + "mysql_command_BEGIN_cnt_5s": 0, + "mysql_command_BEGIN_cnt_INFs": 0, + "mysql_command_CALL_Total_Time_us": 0, + "mysql_command_CALL_Total_cnt": 0, + "mysql_command_CALL_cnt_100ms": 0, + "mysql_command_CALL_cnt_100us": 0, + "mysql_command_CALL_cnt_10ms": 0, + "mysql_command_CALL_cnt_10s": 0, + "mysql_command_CALL_cnt_1ms": 0, + "mysql_command_CALL_cnt_1s": 0, + "mysql_command_CALL_cnt_500ms": 0, + "mysql_command_CALL_cnt_500us": 0, + "mysql_command_CALL_cnt_50ms": 0, + "mysql_command_CALL_cnt_5ms": 0, + "mysql_command_CALL_cnt_5s": 0, + "mysql_command_CALL_cnt_INFs": 0, + "mysql_command_CHANGE_MASTER_Total_Time_us": 0, + "mysql_command_CHANGE_MASTER_Total_cnt": 0, + "mysql_command_CHANGE_MASTER_cnt_100ms": 0, + "mysql_command_CHANGE_MASTER_cnt_100us": 0, + "mysql_command_CHANGE_MASTER_cnt_10ms": 0, + "mysql_command_CHANGE_MASTER_cnt_10s": 0, + "mysql_command_CHANGE_MASTER_cnt_1ms": 0, + "mysql_command_CHANGE_MASTER_cnt_1s": 0, + "mysql_command_CHANGE_MASTER_cnt_500ms": 0, + "mysql_command_CHANGE_MASTER_cnt_500us": 0, + "mysql_command_CHANGE_MASTER_cnt_50ms": 0, + "mysql_command_CHANGE_MASTER_cnt_5ms": 0, + "mysql_command_CHANGE_MASTER_cnt_5s": 0, + "mysql_command_CHANGE_MASTER_cnt_INFs": 0, + "mysql_command_COMMIT_Total_Time_us": 0, + "mysql_command_COMMIT_Total_cnt": 0, + "mysql_command_COMMIT_cnt_100ms": 0, + "mysql_command_COMMIT_cnt_100us": 0, + "mysql_command_COMMIT_cnt_10ms": 0, + "mysql_command_COMMIT_cnt_10s": 0, + "mysql_command_COMMIT_cnt_1ms": 0, + "mysql_command_COMMIT_cnt_1s": 0, + "mysql_command_COMMIT_cnt_500ms": 0, + "mysql_command_COMMIT_cnt_500us": 0, + "mysql_command_COMMIT_cnt_50ms": 0, + "mysql_command_COMMIT_cnt_5ms": 0, + "mysql_command_COMMIT_cnt_5s": 0, + "mysql_command_COMMIT_cnt_INFs": 0, + "mysql_command_CREATE_DATABASE_Total_Time_us": 0, + "mysql_command_CREATE_DATABASE_Total_cnt": 0, + "mysql_command_CREATE_DATABASE_cnt_100ms": 0, + "mysql_command_CREATE_DATABASE_cnt_100us": 0, + "mysql_command_CREATE_DATABASE_cnt_10ms": 0, + "mysql_command_CREATE_DATABASE_cnt_10s": 0, + "mysql_command_CREATE_DATABASE_cnt_1ms": 0, + "mysql_command_CREATE_DATABASE_cnt_1s": 0, + "mysql_command_CREATE_DATABASE_cnt_500ms": 0, + "mysql_command_CREATE_DATABASE_cnt_500us": 0, + "mysql_command_CREATE_DATABASE_cnt_50ms": 0, + "mysql_command_CREATE_DATABASE_cnt_5ms": 0, + "mysql_command_CREATE_DATABASE_cnt_5s": 0, + "mysql_command_CREATE_DATABASE_cnt_INFs": 0, + "mysql_command_CREATE_INDEX_Total_Time_us": 0, + "mysql_command_CREATE_INDEX_Total_cnt": 0, + "mysql_command_CREATE_INDEX_cnt_100ms": 0, + "mysql_command_CREATE_INDEX_cnt_100us": 0, + "mysql_command_CREATE_INDEX_cnt_10ms": 0, + "mysql_command_CREATE_INDEX_cnt_10s": 0, + "mysql_command_CREATE_INDEX_cnt_1ms": 0, + "mysql_command_CREATE_INDEX_cnt_1s": 0, + "mysql_command_CREATE_INDEX_cnt_500ms": 0, + "mysql_command_CREATE_INDEX_cnt_500us": 0, + "mysql_command_CREATE_INDEX_cnt_50ms": 0, + "mysql_command_CREATE_INDEX_cnt_5ms": 0, + "mysql_command_CREATE_INDEX_cnt_5s": 0, + "mysql_command_CREATE_INDEX_cnt_INFs": 0, + "mysql_command_CREATE_TABLE_Total_Time_us": 0, + "mysql_command_CREATE_TABLE_Total_cnt": 0, + "mysql_command_CREATE_TABLE_cnt_100ms": 0, + "mysql_command_CREATE_TABLE_cnt_100us": 0, + "mysql_command_CREATE_TABLE_cnt_10ms": 0, + "mysql_command_CREATE_TABLE_cnt_10s": 0, + "mysql_command_CREATE_TABLE_cnt_1ms": 0, + "mysql_command_CREATE_TABLE_cnt_1s": 0, + "mysql_command_CREATE_TABLE_cnt_500ms": 0, + "mysql_command_CREATE_TABLE_cnt_500us": 0, + "mysql_command_CREATE_TABLE_cnt_50ms": 0, + "mysql_command_CREATE_TABLE_cnt_5ms": 0, + "mysql_command_CREATE_TABLE_cnt_5s": 0, + "mysql_command_CREATE_TABLE_cnt_INFs": 0, + "mysql_command_CREATE_TEMPORARY_Total_Time_us": 0, + "mysql_command_CREATE_TEMPORARY_Total_cnt": 0, + "mysql_command_CREATE_TEMPORARY_cnt_100ms": 0, + "mysql_command_CREATE_TEMPORARY_cnt_100us": 0, + "mysql_command_CREATE_TEMPORARY_cnt_10ms": 0, + "mysql_command_CREATE_TEMPORARY_cnt_10s": 0, + "mysql_command_CREATE_TEMPORARY_cnt_1ms": 0, + "mysql_command_CREATE_TEMPORARY_cnt_1s": 0, + "mysql_command_CREATE_TEMPORARY_cnt_500ms": 0, + "mysql_command_CREATE_TEMPORARY_cnt_500us": 0, + "mysql_command_CREATE_TEMPORARY_cnt_50ms": 0, + "mysql_command_CREATE_TEMPORARY_cnt_5ms": 0, + "mysql_command_CREATE_TEMPORARY_cnt_5s": 0, + "mysql_command_CREATE_TEMPORARY_cnt_INFs": 0, + "mysql_command_CREATE_TRIGGER_Total_Time_us": 0, + "mysql_command_CREATE_TRIGGER_Total_cnt": 0, + "mysql_command_CREATE_TRIGGER_cnt_100ms": 0, + "mysql_command_CREATE_TRIGGER_cnt_100us": 0, + "mysql_command_CREATE_TRIGGER_cnt_10ms": 0, + "mysql_command_CREATE_TRIGGER_cnt_10s": 0, + "mysql_command_CREATE_TRIGGER_cnt_1ms": 0, + "mysql_command_CREATE_TRIGGER_cnt_1s": 0, + "mysql_command_CREATE_TRIGGER_cnt_500ms": 0, + "mysql_command_CREATE_TRIGGER_cnt_500us": 0, + "mysql_command_CREATE_TRIGGER_cnt_50ms": 0, + "mysql_command_CREATE_TRIGGER_cnt_5ms": 0, + "mysql_command_CREATE_TRIGGER_cnt_5s": 0, + "mysql_command_CREATE_TRIGGER_cnt_INFs": 0, + "mysql_command_CREATE_USER_Total_Time_us": 0, + "mysql_command_CREATE_USER_Total_cnt": 0, + "mysql_command_CREATE_USER_cnt_100ms": 0, + "mysql_command_CREATE_USER_cnt_100us": 0, + "mysql_command_CREATE_USER_cnt_10ms": 0, + "mysql_command_CREATE_USER_cnt_10s": 0, + "mysql_command_CREATE_USER_cnt_1ms": 0, + "mysql_command_CREATE_USER_cnt_1s": 0, + "mysql_command_CREATE_USER_cnt_500ms": 0, + "mysql_command_CREATE_USER_cnt_500us": 0, + "mysql_command_CREATE_USER_cnt_50ms": 0, + "mysql_command_CREATE_USER_cnt_5ms": 0, + "mysql_command_CREATE_USER_cnt_5s": 0, + "mysql_command_CREATE_USER_cnt_INFs": 0, + "mysql_command_CREATE_VIEW_Total_Time_us": 0, + "mysql_command_CREATE_VIEW_Total_cnt": 0, + "mysql_command_CREATE_VIEW_cnt_100ms": 0, + "mysql_command_CREATE_VIEW_cnt_100us": 0, + "mysql_command_CREATE_VIEW_cnt_10ms": 0, + "mysql_command_CREATE_VIEW_cnt_10s": 0, + "mysql_command_CREATE_VIEW_cnt_1ms": 0, + "mysql_command_CREATE_VIEW_cnt_1s": 0, + "mysql_command_CREATE_VIEW_cnt_500ms": 0, + "mysql_command_CREATE_VIEW_cnt_500us": 0, + "mysql_command_CREATE_VIEW_cnt_50ms": 0, + "mysql_command_CREATE_VIEW_cnt_5ms": 0, + "mysql_command_CREATE_VIEW_cnt_5s": 0, + "mysql_command_CREATE_VIEW_cnt_INFs": 0, + "mysql_command_DEALLOCATE_Total_Time_us": 0, + "mysql_command_DEALLOCATE_Total_cnt": 0, + "mysql_command_DEALLOCATE_cnt_100ms": 0, + "mysql_command_DEALLOCATE_cnt_100us": 0, + "mysql_command_DEALLOCATE_cnt_10ms": 0, + "mysql_command_DEALLOCATE_cnt_10s": 0, + "mysql_command_DEALLOCATE_cnt_1ms": 0, + "mysql_command_DEALLOCATE_cnt_1s": 0, + "mysql_command_DEALLOCATE_cnt_500ms": 0, + "mysql_command_DEALLOCATE_cnt_500us": 0, + "mysql_command_DEALLOCATE_cnt_50ms": 0, + "mysql_command_DEALLOCATE_cnt_5ms": 0, + "mysql_command_DEALLOCATE_cnt_5s": 0, + "mysql_command_DEALLOCATE_cnt_INFs": 0, + "mysql_command_DELETE_Total_Time_us": 0, + "mysql_command_DELETE_Total_cnt": 0, + "mysql_command_DELETE_cnt_100ms": 0, + "mysql_command_DELETE_cnt_100us": 0, + "mysql_command_DELETE_cnt_10ms": 0, + "mysql_command_DELETE_cnt_10s": 0, + "mysql_command_DELETE_cnt_1ms": 0, + "mysql_command_DELETE_cnt_1s": 0, + "mysql_command_DELETE_cnt_500ms": 0, + "mysql_command_DELETE_cnt_500us": 0, + "mysql_command_DELETE_cnt_50ms": 0, + "mysql_command_DELETE_cnt_5ms": 0, + "mysql_command_DELETE_cnt_5s": 0, + "mysql_command_DELETE_cnt_INFs": 0, + "mysql_command_DESCRIBE_Total_Time_us": 0, + "mysql_command_DESCRIBE_Total_cnt": 0, + "mysql_command_DESCRIBE_cnt_100ms": 0, + "mysql_command_DESCRIBE_cnt_100us": 0, + "mysql_command_DESCRIBE_cnt_10ms": 0, + "mysql_command_DESCRIBE_cnt_10s": 0, + "mysql_command_DESCRIBE_cnt_1ms": 0, + "mysql_command_DESCRIBE_cnt_1s": 0, + "mysql_command_DESCRIBE_cnt_500ms": 0, + "mysql_command_DESCRIBE_cnt_500us": 0, + "mysql_command_DESCRIBE_cnt_50ms": 0, + "mysql_command_DESCRIBE_cnt_5ms": 0, + "mysql_command_DESCRIBE_cnt_5s": 0, + "mysql_command_DESCRIBE_cnt_INFs": 0, + "mysql_command_DROP_DATABASE_Total_Time_us": 0, + "mysql_command_DROP_DATABASE_Total_cnt": 0, + "mysql_command_DROP_DATABASE_cnt_100ms": 0, + "mysql_command_DROP_DATABASE_cnt_100us": 0, + "mysql_command_DROP_DATABASE_cnt_10ms": 0, + "mysql_command_DROP_DATABASE_cnt_10s": 0, + "mysql_command_DROP_DATABASE_cnt_1ms": 0, + "mysql_command_DROP_DATABASE_cnt_1s": 0, + "mysql_command_DROP_DATABASE_cnt_500ms": 0, + "mysql_command_DROP_DATABASE_cnt_500us": 0, + "mysql_command_DROP_DATABASE_cnt_50ms": 0, + "mysql_command_DROP_DATABASE_cnt_5ms": 0, + "mysql_command_DROP_DATABASE_cnt_5s": 0, + "mysql_command_DROP_DATABASE_cnt_INFs": 0, + "mysql_command_DROP_INDEX_Total_Time_us": 0, + "mysql_command_DROP_INDEX_Total_cnt": 0, + "mysql_command_DROP_INDEX_cnt_100ms": 0, + "mysql_command_DROP_INDEX_cnt_100us": 0, + "mysql_command_DROP_INDEX_cnt_10ms": 0, + "mysql_command_DROP_INDEX_cnt_10s": 0, + "mysql_command_DROP_INDEX_cnt_1ms": 0, + "mysql_command_DROP_INDEX_cnt_1s": 0, + "mysql_command_DROP_INDEX_cnt_500ms": 0, + "mysql_command_DROP_INDEX_cnt_500us": 0, + "mysql_command_DROP_INDEX_cnt_50ms": 0, + "mysql_command_DROP_INDEX_cnt_5ms": 0, + "mysql_command_DROP_INDEX_cnt_5s": 0, + "mysql_command_DROP_INDEX_cnt_INFs": 0, + "mysql_command_DROP_TABLE_Total_Time_us": 0, + "mysql_command_DROP_TABLE_Total_cnt": 0, + "mysql_command_DROP_TABLE_cnt_100ms": 0, + "mysql_command_DROP_TABLE_cnt_100us": 0, + "mysql_command_DROP_TABLE_cnt_10ms": 0, + "mysql_command_DROP_TABLE_cnt_10s": 0, + "mysql_command_DROP_TABLE_cnt_1ms": 0, + "mysql_command_DROP_TABLE_cnt_1s": 0, + "mysql_command_DROP_TABLE_cnt_500ms": 0, + "mysql_command_DROP_TABLE_cnt_500us": 0, + "mysql_command_DROP_TABLE_cnt_50ms": 0, + "mysql_command_DROP_TABLE_cnt_5ms": 0, + "mysql_command_DROP_TABLE_cnt_5s": 0, + "mysql_command_DROP_TABLE_cnt_INFs": 0, + "mysql_command_DROP_TRIGGER_Total_Time_us": 0, + "mysql_command_DROP_TRIGGER_Total_cnt": 0, + "mysql_command_DROP_TRIGGER_cnt_100ms": 0, + "mysql_command_DROP_TRIGGER_cnt_100us": 0, + "mysql_command_DROP_TRIGGER_cnt_10ms": 0, + "mysql_command_DROP_TRIGGER_cnt_10s": 0, + "mysql_command_DROP_TRIGGER_cnt_1ms": 0, + "mysql_command_DROP_TRIGGER_cnt_1s": 0, + "mysql_command_DROP_TRIGGER_cnt_500ms": 0, + "mysql_command_DROP_TRIGGER_cnt_500us": 0, + "mysql_command_DROP_TRIGGER_cnt_50ms": 0, + "mysql_command_DROP_TRIGGER_cnt_5ms": 0, + "mysql_command_DROP_TRIGGER_cnt_5s": 0, + "mysql_command_DROP_TRIGGER_cnt_INFs": 0, + "mysql_command_DROP_USER_Total_Time_us": 0, + "mysql_command_DROP_USER_Total_cnt": 0, + "mysql_command_DROP_USER_cnt_100ms": 0, + "mysql_command_DROP_USER_cnt_100us": 0, + "mysql_command_DROP_USER_cnt_10ms": 0, + "mysql_command_DROP_USER_cnt_10s": 0, + "mysql_command_DROP_USER_cnt_1ms": 0, + "mysql_command_DROP_USER_cnt_1s": 0, + "mysql_command_DROP_USER_cnt_500ms": 0, + "mysql_command_DROP_USER_cnt_500us": 0, + "mysql_command_DROP_USER_cnt_50ms": 0, + "mysql_command_DROP_USER_cnt_5ms": 0, + "mysql_command_DROP_USER_cnt_5s": 0, + "mysql_command_DROP_USER_cnt_INFs": 0, + "mysql_command_DROP_VIEW_Total_Time_us": 0, + "mysql_command_DROP_VIEW_Total_cnt": 0, + "mysql_command_DROP_VIEW_cnt_100ms": 0, + "mysql_command_DROP_VIEW_cnt_100us": 0, + "mysql_command_DROP_VIEW_cnt_10ms": 0, + "mysql_command_DROP_VIEW_cnt_10s": 0, + "mysql_command_DROP_VIEW_cnt_1ms": 0, + "mysql_command_DROP_VIEW_cnt_1s": 0, + "mysql_command_DROP_VIEW_cnt_500ms": 0, + "mysql_command_DROP_VIEW_cnt_500us": 0, + "mysql_command_DROP_VIEW_cnt_50ms": 0, + "mysql_command_DROP_VIEW_cnt_5ms": 0, + "mysql_command_DROP_VIEW_cnt_5s": 0, + "mysql_command_DROP_VIEW_cnt_INFs": 0, + "mysql_command_EXECUTE_Total_Time_us": 0, + "mysql_command_EXECUTE_Total_cnt": 0, + "mysql_command_EXECUTE_cnt_100ms": 0, + "mysql_command_EXECUTE_cnt_100us": 0, + "mysql_command_EXECUTE_cnt_10ms": 0, + "mysql_command_EXECUTE_cnt_10s": 0, + "mysql_command_EXECUTE_cnt_1ms": 0, + "mysql_command_EXECUTE_cnt_1s": 0, + "mysql_command_EXECUTE_cnt_500ms": 0, + "mysql_command_EXECUTE_cnt_500us": 0, + "mysql_command_EXECUTE_cnt_50ms": 0, + "mysql_command_EXECUTE_cnt_5ms": 0, + "mysql_command_EXECUTE_cnt_5s": 0, + "mysql_command_EXECUTE_cnt_INFs": 0, + "mysql_command_EXPLAIN_Total_Time_us": 0, + "mysql_command_EXPLAIN_Total_cnt": 0, + "mysql_command_EXPLAIN_cnt_100ms": 0, + "mysql_command_EXPLAIN_cnt_100us": 0, + "mysql_command_EXPLAIN_cnt_10ms": 0, + "mysql_command_EXPLAIN_cnt_10s": 0, + "mysql_command_EXPLAIN_cnt_1ms": 0, + "mysql_command_EXPLAIN_cnt_1s": 0, + "mysql_command_EXPLAIN_cnt_500ms": 0, + "mysql_command_EXPLAIN_cnt_500us": 0, + "mysql_command_EXPLAIN_cnt_50ms": 0, + "mysql_command_EXPLAIN_cnt_5ms": 0, + "mysql_command_EXPLAIN_cnt_5s": 0, + "mysql_command_EXPLAIN_cnt_INFs": 0, + "mysql_command_FLUSH_Total_Time_us": 0, + "mysql_command_FLUSH_Total_cnt": 0, + "mysql_command_FLUSH_cnt_100ms": 0, + "mysql_command_FLUSH_cnt_100us": 0, + "mysql_command_FLUSH_cnt_10ms": 0, + "mysql_command_FLUSH_cnt_10s": 0, + "mysql_command_FLUSH_cnt_1ms": 0, + "mysql_command_FLUSH_cnt_1s": 0, + "mysql_command_FLUSH_cnt_500ms": 0, + "mysql_command_FLUSH_cnt_500us": 0, + "mysql_command_FLUSH_cnt_50ms": 0, + "mysql_command_FLUSH_cnt_5ms": 0, + "mysql_command_FLUSH_cnt_5s": 0, + "mysql_command_FLUSH_cnt_INFs": 0, + "mysql_command_GRANT_Total_Time_us": 0, + "mysql_command_GRANT_Total_cnt": 0, + "mysql_command_GRANT_cnt_100ms": 0, + "mysql_command_GRANT_cnt_100us": 0, + "mysql_command_GRANT_cnt_10ms": 0, + "mysql_command_GRANT_cnt_10s": 0, + "mysql_command_GRANT_cnt_1ms": 0, + "mysql_command_GRANT_cnt_1s": 0, + "mysql_command_GRANT_cnt_500ms": 0, + "mysql_command_GRANT_cnt_500us": 0, + "mysql_command_GRANT_cnt_50ms": 0, + "mysql_command_GRANT_cnt_5ms": 0, + "mysql_command_GRANT_cnt_5s": 0, + "mysql_command_GRANT_cnt_INFs": 0, + "mysql_command_INSERT_Total_Time_us": 0, + "mysql_command_INSERT_Total_cnt": 0, + "mysql_command_INSERT_cnt_100ms": 0, + "mysql_command_INSERT_cnt_100us": 0, + "mysql_command_INSERT_cnt_10ms": 0, + "mysql_command_INSERT_cnt_10s": 0, + "mysql_command_INSERT_cnt_1ms": 0, + "mysql_command_INSERT_cnt_1s": 0, + "mysql_command_INSERT_cnt_500ms": 0, + "mysql_command_INSERT_cnt_500us": 0, + "mysql_command_INSERT_cnt_50ms": 0, + "mysql_command_INSERT_cnt_5ms": 0, + "mysql_command_INSERT_cnt_5s": 0, + "mysql_command_INSERT_cnt_INFs": 0, + "mysql_command_KILL_Total_Time_us": 0, + "mysql_command_KILL_Total_cnt": 0, + "mysql_command_KILL_cnt_100ms": 0, + "mysql_command_KILL_cnt_100us": 0, + "mysql_command_KILL_cnt_10ms": 0, + "mysql_command_KILL_cnt_10s": 0, + "mysql_command_KILL_cnt_1ms": 0, + "mysql_command_KILL_cnt_1s": 0, + "mysql_command_KILL_cnt_500ms": 0, + "mysql_command_KILL_cnt_500us": 0, + "mysql_command_KILL_cnt_50ms": 0, + "mysql_command_KILL_cnt_5ms": 0, + "mysql_command_KILL_cnt_5s": 0, + "mysql_command_KILL_cnt_INFs": 0, + "mysql_command_LOAD_Total_Time_us": 0, + "mysql_command_LOAD_Total_cnt": 0, + "mysql_command_LOAD_cnt_100ms": 0, + "mysql_command_LOAD_cnt_100us": 0, + "mysql_command_LOAD_cnt_10ms": 0, + "mysql_command_LOAD_cnt_10s": 0, + "mysql_command_LOAD_cnt_1ms": 0, + "mysql_command_LOAD_cnt_1s": 0, + "mysql_command_LOAD_cnt_500ms": 0, + "mysql_command_LOAD_cnt_500us": 0, + "mysql_command_LOAD_cnt_50ms": 0, + "mysql_command_LOAD_cnt_5ms": 0, + "mysql_command_LOAD_cnt_5s": 0, + "mysql_command_LOAD_cnt_INFs": 0, + "mysql_command_LOCK_TABLE_Total_Time_us": 0, + "mysql_command_LOCK_TABLE_Total_cnt": 0, + "mysql_command_LOCK_TABLE_cnt_100ms": 0, + "mysql_command_LOCK_TABLE_cnt_100us": 0, + "mysql_command_LOCK_TABLE_cnt_10ms": 0, + "mysql_command_LOCK_TABLE_cnt_10s": 0, + "mysql_command_LOCK_TABLE_cnt_1ms": 0, + "mysql_command_LOCK_TABLE_cnt_1s": 0, + "mysql_command_LOCK_TABLE_cnt_500ms": 0, + "mysql_command_LOCK_TABLE_cnt_500us": 0, + "mysql_command_LOCK_TABLE_cnt_50ms": 0, + "mysql_command_LOCK_TABLE_cnt_5ms": 0, + "mysql_command_LOCK_TABLE_cnt_5s": 0, + "mysql_command_LOCK_TABLE_cnt_INFs": 0, + "mysql_command_OPTIMIZE_Total_Time_us": 0, + "mysql_command_OPTIMIZE_Total_cnt": 0, + "mysql_command_OPTIMIZE_cnt_100ms": 0, + "mysql_command_OPTIMIZE_cnt_100us": 0, + "mysql_command_OPTIMIZE_cnt_10ms": 0, + "mysql_command_OPTIMIZE_cnt_10s": 0, + "mysql_command_OPTIMIZE_cnt_1ms": 0, + "mysql_command_OPTIMIZE_cnt_1s": 0, + "mysql_command_OPTIMIZE_cnt_500ms": 0, + "mysql_command_OPTIMIZE_cnt_500us": 0, + "mysql_command_OPTIMIZE_cnt_50ms": 0, + "mysql_command_OPTIMIZE_cnt_5ms": 0, + "mysql_command_OPTIMIZE_cnt_5s": 0, + "mysql_command_OPTIMIZE_cnt_INFs": 0, + "mysql_command_PREPARE_Total_Time_us": 0, + "mysql_command_PREPARE_Total_cnt": 0, + "mysql_command_PREPARE_cnt_100ms": 0, + "mysql_command_PREPARE_cnt_100us": 0, + "mysql_command_PREPARE_cnt_10ms": 0, + "mysql_command_PREPARE_cnt_10s": 0, + "mysql_command_PREPARE_cnt_1ms": 0, + "mysql_command_PREPARE_cnt_1s": 0, + "mysql_command_PREPARE_cnt_500ms": 0, + "mysql_command_PREPARE_cnt_500us": 0, + "mysql_command_PREPARE_cnt_50ms": 0, + "mysql_command_PREPARE_cnt_5ms": 0, + "mysql_command_PREPARE_cnt_5s": 0, + "mysql_command_PREPARE_cnt_INFs": 0, + "mysql_command_PURGE_Total_Time_us": 0, + "mysql_command_PURGE_Total_cnt": 0, + "mysql_command_PURGE_cnt_100ms": 0, + "mysql_command_PURGE_cnt_100us": 0, + "mysql_command_PURGE_cnt_10ms": 0, + "mysql_command_PURGE_cnt_10s": 0, + "mysql_command_PURGE_cnt_1ms": 0, + "mysql_command_PURGE_cnt_1s": 0, + "mysql_command_PURGE_cnt_500ms": 0, + "mysql_command_PURGE_cnt_500us": 0, + "mysql_command_PURGE_cnt_50ms": 0, + "mysql_command_PURGE_cnt_5ms": 0, + "mysql_command_PURGE_cnt_5s": 0, + "mysql_command_PURGE_cnt_INFs": 0, + "mysql_command_RENAME_TABLE_Total_Time_us": 0, + "mysql_command_RENAME_TABLE_Total_cnt": 0, + "mysql_command_RENAME_TABLE_cnt_100ms": 0, + "mysql_command_RENAME_TABLE_cnt_100us": 0, + "mysql_command_RENAME_TABLE_cnt_10ms": 0, + "mysql_command_RENAME_TABLE_cnt_10s": 0, + "mysql_command_RENAME_TABLE_cnt_1ms": 0, + "mysql_command_RENAME_TABLE_cnt_1s": 0, + "mysql_command_RENAME_TABLE_cnt_500ms": 0, + "mysql_command_RENAME_TABLE_cnt_500us": 0, + "mysql_command_RENAME_TABLE_cnt_50ms": 0, + "mysql_command_RENAME_TABLE_cnt_5ms": 0, + "mysql_command_RENAME_TABLE_cnt_5s": 0, + "mysql_command_RENAME_TABLE_cnt_INFs": 0, + "mysql_command_REPLACE_Total_Time_us": 0, + "mysql_command_REPLACE_Total_cnt": 0, + "mysql_command_REPLACE_cnt_100ms": 0, + "mysql_command_REPLACE_cnt_100us": 0, + "mysql_command_REPLACE_cnt_10ms": 0, + "mysql_command_REPLACE_cnt_10s": 0, + "mysql_command_REPLACE_cnt_1ms": 0, + "mysql_command_REPLACE_cnt_1s": 0, + "mysql_command_REPLACE_cnt_500ms": 0, + "mysql_command_REPLACE_cnt_500us": 0, + "mysql_command_REPLACE_cnt_50ms": 0, + "mysql_command_REPLACE_cnt_5ms": 0, + "mysql_command_REPLACE_cnt_5s": 0, + "mysql_command_REPLACE_cnt_INFs": 0, + "mysql_command_RESET_MASTER_Total_Time_us": 0, + "mysql_command_RESET_MASTER_Total_cnt": 0, + "mysql_command_RESET_MASTER_cnt_100ms": 0, + "mysql_command_RESET_MASTER_cnt_100us": 0, + "mysql_command_RESET_MASTER_cnt_10ms": 0, + "mysql_command_RESET_MASTER_cnt_10s": 0, + "mysql_command_RESET_MASTER_cnt_1ms": 0, + "mysql_command_RESET_MASTER_cnt_1s": 0, + "mysql_command_RESET_MASTER_cnt_500ms": 0, + "mysql_command_RESET_MASTER_cnt_500us": 0, + "mysql_command_RESET_MASTER_cnt_50ms": 0, + "mysql_command_RESET_MASTER_cnt_5ms": 0, + "mysql_command_RESET_MASTER_cnt_5s": 0, + "mysql_command_RESET_MASTER_cnt_INFs": 0, + "mysql_command_RESET_SLAVE_Total_Time_us": 0, + "mysql_command_RESET_SLAVE_Total_cnt": 0, + "mysql_command_RESET_SLAVE_cnt_100ms": 0, + "mysql_command_RESET_SLAVE_cnt_100us": 0, + "mysql_command_RESET_SLAVE_cnt_10ms": 0, + "mysql_command_RESET_SLAVE_cnt_10s": 0, + "mysql_command_RESET_SLAVE_cnt_1ms": 0, + "mysql_command_RESET_SLAVE_cnt_1s": 0, + "mysql_command_RESET_SLAVE_cnt_500ms": 0, + "mysql_command_RESET_SLAVE_cnt_500us": 0, + "mysql_command_RESET_SLAVE_cnt_50ms": 0, + "mysql_command_RESET_SLAVE_cnt_5ms": 0, + "mysql_command_RESET_SLAVE_cnt_5s": 0, + "mysql_command_RESET_SLAVE_cnt_INFs": 0, + "mysql_command_REVOKE_Total_Time_us": 0, + "mysql_command_REVOKE_Total_cnt": 0, + "mysql_command_REVOKE_cnt_100ms": 0, + "mysql_command_REVOKE_cnt_100us": 0, + "mysql_command_REVOKE_cnt_10ms": 0, + "mysql_command_REVOKE_cnt_10s": 0, + "mysql_command_REVOKE_cnt_1ms": 0, + "mysql_command_REVOKE_cnt_1s": 0, + "mysql_command_REVOKE_cnt_500ms": 0, + "mysql_command_REVOKE_cnt_500us": 0, + "mysql_command_REVOKE_cnt_50ms": 0, + "mysql_command_REVOKE_cnt_5ms": 0, + "mysql_command_REVOKE_cnt_5s": 0, + "mysql_command_REVOKE_cnt_INFs": 0, + "mysql_command_ROLLBACK_Total_Time_us": 0, + "mysql_command_ROLLBACK_Total_cnt": 0, + "mysql_command_ROLLBACK_cnt_100ms": 0, + "mysql_command_ROLLBACK_cnt_100us": 0, + "mysql_command_ROLLBACK_cnt_10ms": 0, + "mysql_command_ROLLBACK_cnt_10s": 0, + "mysql_command_ROLLBACK_cnt_1ms": 0, + "mysql_command_ROLLBACK_cnt_1s": 0, + "mysql_command_ROLLBACK_cnt_500ms": 0, + "mysql_command_ROLLBACK_cnt_500us": 0, + "mysql_command_ROLLBACK_cnt_50ms": 0, + "mysql_command_ROLLBACK_cnt_5ms": 0, + "mysql_command_ROLLBACK_cnt_5s": 0, + "mysql_command_ROLLBACK_cnt_INFs": 0, + "mysql_command_SAVEPOINT_Total_Time_us": 0, + "mysql_command_SAVEPOINT_Total_cnt": 0, + "mysql_command_SAVEPOINT_cnt_100ms": 0, + "mysql_command_SAVEPOINT_cnt_100us": 0, + "mysql_command_SAVEPOINT_cnt_10ms": 0, + "mysql_command_SAVEPOINT_cnt_10s": 0, + "mysql_command_SAVEPOINT_cnt_1ms": 0, + "mysql_command_SAVEPOINT_cnt_1s": 0, + "mysql_command_SAVEPOINT_cnt_500ms": 0, + "mysql_command_SAVEPOINT_cnt_500us": 0, + "mysql_command_SAVEPOINT_cnt_50ms": 0, + "mysql_command_SAVEPOINT_cnt_5ms": 0, + "mysql_command_SAVEPOINT_cnt_5s": 0, + "mysql_command_SAVEPOINT_cnt_INFs": 0, + "mysql_command_SELECT_FOR_UPDATE_Total_Time_us": 0, + "mysql_command_SELECT_FOR_UPDATE_Total_cnt": 0, + "mysql_command_SELECT_FOR_UPDATE_cnt_100ms": 0, + "mysql_command_SELECT_FOR_UPDATE_cnt_100us": 0, + "mysql_command_SELECT_FOR_UPDATE_cnt_10ms": 0, + "mysql_command_SELECT_FOR_UPDATE_cnt_10s": 0, + "mysql_command_SELECT_FOR_UPDATE_cnt_1ms": 0, + "mysql_command_SELECT_FOR_UPDATE_cnt_1s": 0, + "mysql_command_SELECT_FOR_UPDATE_cnt_500ms": 0, + "mysql_command_SELECT_FOR_UPDATE_cnt_500us": 0, + "mysql_command_SELECT_FOR_UPDATE_cnt_50ms": 0, + "mysql_command_SELECT_FOR_UPDATE_cnt_5ms": 0, + "mysql_command_SELECT_FOR_UPDATE_cnt_5s": 0, + "mysql_command_SELECT_FOR_UPDATE_cnt_INFs": 0, + "mysql_command_SELECT_Total_Time_us": 4673958076637, + "mysql_command_SELECT_Total_cnt": 68490650, + "mysql_command_SELECT_cnt_100ms": 4909816, + "mysql_command_SELECT_cnt_100us": 32185976, + "mysql_command_SELECT_cnt_10ms": 2955830, + "mysql_command_SELECT_cnt_10s": 497, + "mysql_command_SELECT_cnt_1ms": 481335, + "mysql_command_SELECT_cnt_1s": 1321917, + "mysql_command_SELECT_cnt_500ms": 11123900, + "mysql_command_SELECT_cnt_500us": 36650, + "mysql_command_SELECT_cnt_50ms": 10468460, + "mysql_command_SELECT_cnt_5ms": 4600948, + "mysql_command_SELECT_cnt_5s": 403451, + "mysql_command_SELECT_cnt_INFs": 1870, + "mysql_command_SET_Total_Time_us": 0, + "mysql_command_SET_Total_cnt": 0, + "mysql_command_SET_cnt_100ms": 0, + "mysql_command_SET_cnt_100us": 0, + "mysql_command_SET_cnt_10ms": 0, + "mysql_command_SET_cnt_10s": 0, + "mysql_command_SET_cnt_1ms": 0, + "mysql_command_SET_cnt_1s": 0, + "mysql_command_SET_cnt_500ms": 0, + "mysql_command_SET_cnt_500us": 0, + "mysql_command_SET_cnt_50ms": 0, + "mysql_command_SET_cnt_5ms": 0, + "mysql_command_SET_cnt_5s": 0, + "mysql_command_SET_cnt_INFs": 0, + "mysql_command_SHOW_TABLE_STATUS_Total_Time_us": 0, + "mysql_command_SHOW_TABLE_STATUS_Total_cnt": 0, + "mysql_command_SHOW_TABLE_STATUS_cnt_100ms": 0, + "mysql_command_SHOW_TABLE_STATUS_cnt_100us": 0, + "mysql_command_SHOW_TABLE_STATUS_cnt_10ms": 0, + "mysql_command_SHOW_TABLE_STATUS_cnt_10s": 0, + "mysql_command_SHOW_TABLE_STATUS_cnt_1ms": 0, + "mysql_command_SHOW_TABLE_STATUS_cnt_1s": 0, + "mysql_command_SHOW_TABLE_STATUS_cnt_500ms": 0, + "mysql_command_SHOW_TABLE_STATUS_cnt_500us": 0, + "mysql_command_SHOW_TABLE_STATUS_cnt_50ms": 0, + "mysql_command_SHOW_TABLE_STATUS_cnt_5ms": 0, + "mysql_command_SHOW_TABLE_STATUS_cnt_5s": 0, + "mysql_command_SHOW_TABLE_STATUS_cnt_INFs": 0, + "mysql_command_SHOW_Total_Time_us": 2158, + "mysql_command_SHOW_Total_cnt": 1, + "mysql_command_SHOW_cnt_100ms": 0, + "mysql_command_SHOW_cnt_100us": 0, + "mysql_command_SHOW_cnt_10ms": 0, + "mysql_command_SHOW_cnt_10s": 0, + "mysql_command_SHOW_cnt_1ms": 0, + "mysql_command_SHOW_cnt_1s": 0, + "mysql_command_SHOW_cnt_500ms": 0, + "mysql_command_SHOW_cnt_500us": 0, + "mysql_command_SHOW_cnt_50ms": 0, + "mysql_command_SHOW_cnt_5ms": 1, + "mysql_command_SHOW_cnt_5s": 0, + "mysql_command_SHOW_cnt_INFs": 0, + "mysql_command_START_TRANSACTION_Total_Time_us": 0, + "mysql_command_START_TRANSACTION_Total_cnt": 0, + "mysql_command_START_TRANSACTION_cnt_100ms": 0, + "mysql_command_START_TRANSACTION_cnt_100us": 0, + "mysql_command_START_TRANSACTION_cnt_10ms": 0, + "mysql_command_START_TRANSACTION_cnt_10s": 0, + "mysql_command_START_TRANSACTION_cnt_1ms": 0, + "mysql_command_START_TRANSACTION_cnt_1s": 0, + "mysql_command_START_TRANSACTION_cnt_500ms": 0, + "mysql_command_START_TRANSACTION_cnt_500us": 0, + "mysql_command_START_TRANSACTION_cnt_50ms": 0, + "mysql_command_START_TRANSACTION_cnt_5ms": 0, + "mysql_command_START_TRANSACTION_cnt_5s": 0, + "mysql_command_START_TRANSACTION_cnt_INFs": 0, + "mysql_command_TRUNCATE_TABLE_Total_Time_us": 0, + "mysql_command_TRUNCATE_TABLE_Total_cnt": 0, + "mysql_command_TRUNCATE_TABLE_cnt_100ms": 0, + "mysql_command_TRUNCATE_TABLE_cnt_100us": 0, + "mysql_command_TRUNCATE_TABLE_cnt_10ms": 0, + "mysql_command_TRUNCATE_TABLE_cnt_10s": 0, + "mysql_command_TRUNCATE_TABLE_cnt_1ms": 0, + "mysql_command_TRUNCATE_TABLE_cnt_1s": 0, + "mysql_command_TRUNCATE_TABLE_cnt_500ms": 0, + "mysql_command_TRUNCATE_TABLE_cnt_500us": 0, + "mysql_command_TRUNCATE_TABLE_cnt_50ms": 0, + "mysql_command_TRUNCATE_TABLE_cnt_5ms": 0, + "mysql_command_TRUNCATE_TABLE_cnt_5s": 0, + "mysql_command_TRUNCATE_TABLE_cnt_INFs": 0, + "mysql_command_UNKNOWN_Total_Time_us": 0, + "mysql_command_UNKNOWN_Total_cnt": 0, + "mysql_command_UNKNOWN_cnt_100ms": 0, + "mysql_command_UNKNOWN_cnt_100us": 0, + "mysql_command_UNKNOWN_cnt_10ms": 0, + "mysql_command_UNKNOWN_cnt_10s": 0, + "mysql_command_UNKNOWN_cnt_1ms": 0, + "mysql_command_UNKNOWN_cnt_1s": 0, + "mysql_command_UNKNOWN_cnt_500ms": 0, + "mysql_command_UNKNOWN_cnt_500us": 0, + "mysql_command_UNKNOWN_cnt_50ms": 0, + "mysql_command_UNKNOWN_cnt_5ms": 0, + "mysql_command_UNKNOWN_cnt_5s": 0, + "mysql_command_UNKNOWN_cnt_INFs": 0, + "mysql_command_UNLOCK_TABLES_Total_Time_us": 0, + "mysql_command_UNLOCK_TABLES_Total_cnt": 0, + "mysql_command_UNLOCK_TABLES_cnt_100ms": 0, + "mysql_command_UNLOCK_TABLES_cnt_100us": 0, + "mysql_command_UNLOCK_TABLES_cnt_10ms": 0, + "mysql_command_UNLOCK_TABLES_cnt_10s": 0, + "mysql_command_UNLOCK_TABLES_cnt_1ms": 0, + "mysql_command_UNLOCK_TABLES_cnt_1s": 0, + "mysql_command_UNLOCK_TABLES_cnt_500ms": 0, + "mysql_command_UNLOCK_TABLES_cnt_500us": 0, + "mysql_command_UNLOCK_TABLES_cnt_50ms": 0, + "mysql_command_UNLOCK_TABLES_cnt_5ms": 0, + "mysql_command_UNLOCK_TABLES_cnt_5s": 0, + "mysql_command_UNLOCK_TABLES_cnt_INFs": 0, + "mysql_command_UPDATE_Total_Time_us": 0, + "mysql_command_UPDATE_Total_cnt": 0, + "mysql_command_UPDATE_cnt_100ms": 0, + "mysql_command_UPDATE_cnt_100us": 0, + "mysql_command_UPDATE_cnt_10ms": 0, + "mysql_command_UPDATE_cnt_10s": 0, + "mysql_command_UPDATE_cnt_1ms": 0, + "mysql_command_UPDATE_cnt_1s": 0, + "mysql_command_UPDATE_cnt_500ms": 0, + "mysql_command_UPDATE_cnt_500us": 0, + "mysql_command_UPDATE_cnt_50ms": 0, + "mysql_command_UPDATE_cnt_5ms": 0, + "mysql_command_UPDATE_cnt_5s": 0, + "mysql_command_UPDATE_cnt_INFs": 0, + "mysql_command_USE_Total_Time_us": 0, + "mysql_command_USE_Total_cnt": 0, + "mysql_command_USE_cnt_100ms": 0, + "mysql_command_USE_cnt_100us": 0, + "mysql_command_USE_cnt_10ms": 0, + "mysql_command_USE_cnt_10s": 0, + "mysql_command_USE_cnt_1ms": 0, + "mysql_command_USE_cnt_1s": 0, + "mysql_command_USE_cnt_500ms": 0, + "mysql_command_USE_cnt_500us": 0, + "mysql_command_USE_cnt_50ms": 0, + "mysql_command_USE_cnt_5ms": 0, + "mysql_command_USE_cnt_5s": 0, + "mysql_command_USE_cnt_INFs": 0, + "mysql_firewall_rules_config": 329, + "mysql_firewall_rules_table": 0, + "mysql_firewall_users_config": 0, + "mysql_firewall_users_table": 0, + "mysql_frontend_buffers_bytes": 196608, + "mysql_killed_backend_connections": 0, + "mysql_killed_backend_queries": 0, + "mysql_query_rules_memory": 22825, + "mysql_session_internal_bytes": 20232, + "mysql_unexpected_frontend_com_quit": 0, + "mysql_unexpected_frontend_packets": 0, + "mysql_user_first_user_frontend_connections": 0, + "mysql_user_first_user_frontend_connections_utilization": 0, + "mysql_user_second_user_frontend_connections": 3, + "mysql_user_second_user_frontend_connections_utilization": 20, + "queries_with_max_lag_ms": 0, + "queries_with_max_lag_ms__delayed": 0, + "queries_with_max_lag_ms__total_wait_time_us": 0, + "query_digest_memory": 13688, + "stack_memory_admin_threads": 16777216, + "stack_memory_cluster_threads": 0, + "stack_memory_mysql_threads": 33554432, + "whitelisted_sqli_fingerprint": 0, + } + + require.Equal(t, expected, mx) + }, + }, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + db, mock, err := sqlmock.New( + sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual), + ) + require.NoError(t, err) + my := New() + my.db = db + defer func() { _ = db.Close() }() + + require.NoError(t, my.Init()) + + for i, step := range test { + t.Run(fmt.Sprintf("step[%d]", i), func(t *testing.T) { + step.prepareMock(t, mock) + step.check(t, my) + }) + } + assert.NoError(t, mock.ExpectationsWereMet()) + }) + } +} + +func mustMockRows(t *testing.T, data []byte) *sqlmock.Rows { + rows, err := prepareMockRows(data) + require.NoError(t, err) + return rows +} + +func mockExpect(t *testing.T, mock sqlmock.Sqlmock, query string, rows []byte) { + mock.ExpectQuery(query).WillReturnRows(mustMockRows(t, rows)).RowsWillBeClosed() +} + +func mockExpectErr(mock sqlmock.Sqlmock, query string) { + mock.ExpectQuery(query).WillReturnError(fmt.Errorf("mock error (%s)", query)) +} + +func prepareMockRows(data []byte) (*sqlmock.Rows, error) { + if len(data) == 0 { + return sqlmock.NewRows(nil), nil + } + + r := bytes.NewReader(data) + sc := bufio.NewScanner(r) + + var numColumns int + var rows *sqlmock.Rows + + for sc.Scan() { + s := strings.TrimSpace(strings.Trim(sc.Text(), "|")) + switch { + case s == "", + strings.HasPrefix(s, "+"), + strings.HasPrefix(s, "ft_boolean_syntax"): + continue + } + + parts := strings.Split(s, "|") + for i, v := range parts { + parts[i] = strings.TrimSpace(v) + } + + if rows == nil { + numColumns = len(parts) + rows = sqlmock.NewRows(parts) + continue + } + + if len(parts) != numColumns { + return nil, fmt.Errorf("prepareMockRows(): columns != values (%d/%d)", numColumns, len(parts)) + } + + values := make([]driver.Value, len(parts)) + for i, v := range parts { + values[i] = v + } + rows.AddRow(values...) + } + + if rows == nil { + return nil, errors.New("prepareMockRows(): nil rows result") + } + + return rows, sc.Err() +} diff --git a/src/go/collectors/go.d.plugin/modules/proxysql/testdata/config.json b/src/go/collectors/go.d.plugin/modules/proxysql/testdata/config.json new file mode 100644 index 000000000..ed8b72dcb --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/proxysql/testdata/config.json @@ -0,0 +1,5 @@ +{ + "update_every": 123, + "dsn": "ok", + "timeout": 123.123 +} diff --git a/src/go/collectors/go.d.plugin/modules/proxysql/testdata/config.yaml b/src/go/collectors/go.d.plugin/modules/proxysql/testdata/config.yaml new file mode 100644 index 000000000..caff49039 --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/proxysql/testdata/config.yaml @@ -0,0 +1,3 @@ +update_every: 123 +dsn: "ok" +timeout: 123.123 diff --git a/src/go/collectors/go.d.plugin/modules/proxysql/testdata/v2.0.10/stats_memory_metrics.txt b/src/go/collectors/go.d.plugin/modules/proxysql/testdata/v2.0.10/stats_memory_metrics.txt new file mode 100644 index 000000000..99ec093e1 --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/proxysql/testdata/v2.0.10/stats_memory_metrics.txt @@ -0,0 +1,21 @@ ++------------------------------+----------------+ +| Variable_Name | Variable_Value | ++------------------------------+----------------+ +| SQLite3_memory_bytes | 6017144 | +| jemalloc_resident | 403759104 | +| jemalloc_active | 385101824 | +| jemalloc_allocated | 379402432 | +| jemalloc_mapped | 430993408 | +| jemalloc_metadata | 17418872 | +| jemalloc_retained | 260542464 | +| Auth_memory | 1044 | +| query_digest_memory | 13688 | +| mysql_query_rules_memory | 22825 | +| mysql_firewall_users_table | 0 | +| mysql_firewall_users_config | 0 | +| mysql_firewall_rules_table | 0 | +| mysql_firewall_rules_config | 329 | +| stack_memory_mysql_threads | 33554432 | +| stack_memory_admin_threads | 16777216 | +| stack_memory_cluster_threads | 0 | ++------------------------------+----------------+
\ No newline at end of file diff --git a/src/go/collectors/go.d.plugin/modules/proxysql/testdata/v2.0.10/stats_mysql_commands_counters.txt b/src/go/collectors/go.d.plugin/modules/proxysql/testdata/v2.0.10/stats_mysql_commands_counters.txt new file mode 100644 index 000000000..6ab6bb830 --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/proxysql/testdata/v2.0.10/stats_mysql_commands_counters.txt @@ -0,0 +1,56 @@ ++-------------------+---------------+-----------+-----------+-----------+---------+---------+----------+----------+-----------+-----------+---------+--------+---------+----------+ +| Command | Total_Time_us | Total_cnt | cnt_100us | cnt_500us | cnt_1ms | cnt_5ms | cnt_10ms | cnt_50ms | cnt_100ms | cnt_500ms | cnt_1s | cnt_5s | cnt_10s | cnt_INFs | ++-------------------+---------------+-----------+-----------+-----------+---------+---------+----------+----------+-----------+-----------+---------+--------+---------+----------+ +| ALTER_TABLE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| ALTER_VIEW | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| ANALYZE_TABLE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| BEGIN | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| CALL | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| CHANGE_MASTER | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| COMMIT | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| CREATE_DATABASE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| CREATE_INDEX | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| CREATE_TABLE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| CREATE_TEMPORARY | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| CREATE_TRIGGER | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| CREATE_USER | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| CREATE_VIEW | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| DEALLOCATE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| DELETE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| DESCRIBE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| DROP_DATABASE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| DROP_INDEX | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| DROP_TABLE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| DROP_TRIGGER | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| DROP_USER | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| DROP_VIEW | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| GRANT | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| EXECUTE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| EXPLAIN | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| FLUSH | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| INSERT | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| KILL | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| LOAD | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| LOCK_TABLE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| OPTIMIZE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| PREPARE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| PURGE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| RENAME_TABLE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| RESET_MASTER | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| RESET_SLAVE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| REPLACE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| REVOKE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| ROLLBACK | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| SAVEPOINT | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| SELECT | 4673958076637 | 68490650 | 32185976 | 36650 | 481335 | 4600948 | 2955830 | 10468460 | 4909816 | 11123900 | 1321917 | 403451 | 497 | 1870 | +| SELECT_FOR_UPDATE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| SET | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| SHOW_TABLE_STATUS | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| START_TRANSACTION | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| TRUNCATE_TABLE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| UNLOCK_TABLES | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| UPDATE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| USE | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| SHOW | 2158 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| UNKNOWN | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ++-------------------+---------------+-----------+-----------+-----------+---------+---------+----------+----------+-----------+-----------+---------+--------+---------+----------+ diff --git a/src/go/collectors/go.d.plugin/modules/proxysql/testdata/v2.0.10/stats_mysql_connection_pool .txt b/src/go/collectors/go.d.plugin/modules/proxysql/testdata/v2.0.10/stats_mysql_connection_pool .txt new file mode 100644 index 000000000..80b53e1af --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/proxysql/testdata/v2.0.10/stats_mysql_connection_pool .txt @@ -0,0 +1,11 @@ ++----+-------------------+--------+--------+----------+----------+--------+---------+---------+-----------------+-----------------+------------+ +| hostgroup | srv_host | srv_port | status | ConnUsed | ConnFree | ConnOK | ConnERR | Queries | Bytes_data_sent | Bytes_data_recv | Latency_us | ++-----------+-------------------+----------+--------+----------+----------+--------+---------+---------+-----------------+-----------------+------------+ +| 10 | back001-db-master | 6001 | ONLINE | 69 | 423 | 524 | 0 | 8970367 | 9858463664 | 145193069937 | 17684 | +| 11 | back001-db-master | 6002 | ONLINE | 0 | 1 | 1 | 0 | 69 | 187675 | 2903 | 17684 | +| 11 | back001-db-reader | 6003 | ONLINE | 0 | 11 | 11 | 0 | 63488 | 163690013 | 4994101 | 113 | +| 20 | back002-db-master | 6004 | ONLINE | 9 | 188 | 197 | 2 | 849461 | 1086994186 | 266034339 | 101981 | +| 21 | back002-db-reader | 6005 | ONLINE | 0 | 1 | 1 | 0 | 8 | 6992 | 984 | 230 | +| 31 | back003-db-master | 6006 | ONLINE | 0 | 3 | 3 | 0 | 3276 | 712803 | 81438709 | 231 | +| 31 | back003-db-reader | 6007 | ONLINE | 1 | 70 | 71 | 0 | 2356904 | 411900849 | 115810708275 | 230 | ++-----------+-------------------+--------+--------+----------+----------+--------+---------+---------+-----------------+-----------------+--------------+
\ No newline at end of file diff --git a/src/go/collectors/go.d.plugin/modules/proxysql/testdata/v2.0.10/stats_mysql_global.txt b/src/go/collectors/go.d.plugin/modules/proxysql/testdata/v2.0.10/stats_mysql_global.txt new file mode 100644 index 000000000..442266c45 --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/proxysql/testdata/v2.0.10/stats_mysql_global.txt @@ -0,0 +1,106 @@ ++---------------------------------------------+----------------+ +| Variable_Name | Variable_Value | ++---------------------------------------------+----------------+ +| ProxySQL_Uptime | 26748286 | +| Active_Transactions | 0 | +| Client_Connections_aborted | 2 | +| Client_Connections_connected | 3 | +| Client_Connections_created | 5458991 | +| Server_Connections_aborted | 9979 | +| Server_Connections_connected | 13 | +| Server_Connections_created | 2122254 | +| Server_Connections_delayed | 0 | +| Client_Connections_non_idle | 3 | +| Queries_backends_bytes_recv | 5896210168 | +| Queries_backends_bytes_sent | 4329581500 | +| Queries_frontends_bytes_recv | 7434816962 | +| Queries_frontends_bytes_sent | 11643634097 | +| Query_Processor_time_nsec | 0 | +| Backend_query_time_nsec | 0 | +| mysql_backend_buffers_bytes | 0 | +| mysql_frontend_buffers_bytes | 196608 | +| mysql_session_internal_bytes | 20232 | +| Com_autocommit | 0 | +| Com_autocommit_filtered | 0 | +| Com_commit | 0 | +| Com_commit_filtered | 0 | +| Com_rollback | 0 | +| Com_rollback_filtered | 0 | +| Com_backend_change_user | 188694 | +| Com_backend_init_db | 0 | +| Com_backend_set_names | 1517893 | +| Com_frontend_init_db | 2 | +| Com_frontend_set_names | 0 | +| Com_frontend_use_db | 0 | +| Com_backend_stmt_prepare | 16858208 | +| Com_backend_stmt_execute | 36303146 | +| Com_backend_stmt_close | 0 | +| Com_frontend_stmt_prepare | 32185987 | +| Com_frontend_stmt_execute | 36314138 | +| Com_frontend_stmt_close | 32137933 | +| Mirror_concurrency | 0 | +| Mirror_queue_length | 0 | +| Questions | 100638067 | +| Selects_for_update__autocommit0 | 0 | +| Slow_queries | 405818 | +| GTID_consistent_queries | 0 | +| GTID_session_collected | 0 | +| Servers_table_version | 37 | +| MySQL_Thread_Workers | 4 | +| Access_Denied_Wrong_Password | 2 | +| Access_Denied_Max_Connections | 0 | +| Access_Denied_Max_User_Connections | 0 | +| MySQL_Monitor_Workers | 10 | +| MySQL_Monitor_Workers_Aux | 0 | +| MySQL_Monitor_Workers_Started | 10 | +| MySQL_Monitor_connect_check_OK | 3548306 | +| MySQL_Monitor_connect_check_ERR | 130 | +| MySQL_Monitor_ping_check_OK | 21289849 | +| MySQL_Monitor_ping_check_ERR | 108271 | +| MySQL_Monitor_read_only_check_OK | 106246409 | +| MySQL_Monitor_read_only_check_ERR | 19610 | +| MySQL_Monitor_replication_lag_check_OK | 28702388 | +| MySQL_Monitor_replication_lag_check_ERR | 482 | +| ConnPool_get_conn_latency_awareness | 0 | +| ConnPool_get_conn_immediate | 13361 | +| ConnPool_get_conn_success | 36319474 | +| ConnPool_get_conn_failure | 212943 | +| generated_error_packets | 231 | +| max_connect_timeouts | 227 | +| backend_lagging_during_query | 8880 | +| backend_offline_during_query | 8 | +| queries_with_max_lag_ms | 0 | +| queries_with_max_lag_ms__delayed | 0 | +| queries_with_max_lag_ms__total_wait_time_us | 0 | +| mysql_unexpected_frontend_com_quit | 0 | +| Client_Connections_hostgroup_locked | 0 | +| hostgroup_locked_set_cmds | 0 | +| hostgroup_locked_queries | 0 | +| mysql_unexpected_frontend_packets | 0 | +| aws_aurora_replicas_skipped_during_query | 0 | +| automatic_detected_sql_injection | 0 | +| whitelisted_sqli_fingerprint | 0 | +| mysql_killed_backend_connections | 0 | +| mysql_killed_backend_queries | 0 | +| MyHGM_myconnpoll_get | 36519056 | +| MyHGM_myconnpoll_get_ok | 36306113 | +| MyHGM_myconnpoll_push | 37358734 | +| MyHGM_myconnpoll_destroy | 15150 | +| MyHGM_myconnpoll_reset | 2 | +| SQLite3_memory_bytes | 6021248 | +| ConnPool_memory_bytes | 932248 | +| Stmt_Client_Active_Total | 18 | +| Stmt_Client_Active_Unique | 18 | +| Stmt_Server_Active_Total | 101 | +| Stmt_Server_Active_Unique | 39 | +| Stmt_Max_Stmt_id | 66 | +| Stmt_Cached | 65 | +| Query_Cache_Memory_bytes | 0 | +| Query_Cache_count_GET | 0 | +| Query_Cache_count_GET_OK | 0 | +| Query_Cache_count_SET | 0 | +| Query_Cache_bytes_IN | 0 | +| Query_Cache_bytes_OUT | 0 | +| Query_Cache_Purged | 0 | +| Query_Cache_Entries | 0 | ++---------------------------------------------+----------------+ diff --git a/src/go/collectors/go.d.plugin/modules/proxysql/testdata/v2.0.10/stats_mysql_users.txt b/src/go/collectors/go.d.plugin/modules/proxysql/testdata/v2.0.10/stats_mysql_users.txt new file mode 100644 index 000000000..900776b76 --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/proxysql/testdata/v2.0.10/stats_mysql_users.txt @@ -0,0 +1,6 @@ ++-------------------------+----------------------+--------------------------+ +| username | frontend_connections | frontend_max_connections | ++-------------------------+----------------------+--------------------------+ +| first_user | 0 | 200 | +| second_user | 3 | 15 | ++-------------------------+----------------------+--------------------------+ diff --git a/src/go/collectors/go.d.plugin/modules/proxysql/testdata/v2.0.10/version.txt b/src/go/collectors/go.d.plugin/modules/proxysql/testdata/v2.0.10/version.txt new file mode 100644 index 000000000..429a880b7 --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/proxysql/testdata/v2.0.10/version.txt @@ -0,0 +1,5 @@ ++---------------------+ +| version() | ++---------------------+ +| 2.0.10-27-g5b319972 | ++---------------------+
\ No newline at end of file |