diff options
Diffstat (limited to '')
-rw-r--r-- | src/go/collectors/go.d.plugin/modules/mysql/mysql_test.go | 1759 |
1 files changed, 1759 insertions, 0 deletions
diff --git a/src/go/collectors/go.d.plugin/modules/mysql/mysql_test.go b/src/go/collectors/go.d.plugin/modules/mysql/mysql_test.go new file mode 100644 index 000000000..da64507e4 --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/mysql/mysql_test.go @@ -0,0 +1,1759 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package mysql + +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/blang/semver/v4" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +var ( + dataConfigJSON, _ = os.ReadFile("testdata/config.json") + dataConfigYAML, _ = os.ReadFile("testdata/config.yaml") + + dataSessionVariables, _ = os.ReadFile("testdata/session_variables.txt") + + dataMySQLVer8030Version, _ = os.ReadFile("testdata/mysql/v8.0.30/version.txt") + dataMySQLVer8030GlobalStatus, _ = os.ReadFile("testdata/mysql/v8.0.30/global_status.txt") + dataMySQLVer8030GlobalVariables, _ = os.ReadFile("testdata/mysql/v8.0.30/global_variables.txt") + dataMySQLVer8030ReplicaStatusMultiSource, _ = os.ReadFile("testdata/mysql/v8.0.30/replica_status_multi_source.txt") + dataMySQLVer8030ProcessList, _ = os.ReadFile("testdata/mysql/v8.0.30/process_list.txt") + + dataPerconaVer8029Version, _ = os.ReadFile("testdata/percona/v8.0.29/version.txt") + dataPerconaVer8029GlobalStatus, _ = os.ReadFile("testdata/percona/v8.0.29/global_status.txt") + dataPerconaVer8029GlobalVariables, _ = os.ReadFile("testdata/percona/v8.0.29/global_variables.txt") + dataPerconaVer8029UserStatistics, _ = os.ReadFile("testdata/percona/v8.0.29/user_statistics.txt") + dataPerconaV8029ProcessList, _ = os.ReadFile("testdata/percona/v8.0.29/process_list.txt") + + dataMariaVer5564Version, _ = os.ReadFile("testdata/mariadb/v5.5.64/version.txt") + dataMariaVer5564GlobalStatus, _ = os.ReadFile("testdata/mariadb/v5.5.64/global_status.txt") + dataMariaVer5564GlobalVariables, _ = os.ReadFile("testdata/mariadb/v5.5.64/global_variables.txt") + dataMariaVer5564ProcessList, _ = os.ReadFile("testdata/mariadb/v5.5.64/process_list.txt") + + dataMariaVer1084Version, _ = os.ReadFile("testdata/mariadb/v10.8.4/version.txt") + dataMariaVer1084GlobalStatus, _ = os.ReadFile("testdata/mariadb/v10.8.4/global_status.txt") + dataMariaVer1084GlobalVariables, _ = os.ReadFile("testdata/mariadb/v10.8.4/global_variables.txt") + dataMariaVer1084AllSlavesStatusSingleSource, _ = os.ReadFile("testdata/mariadb/v10.8.4/all_slaves_status_single_source.txt") + dataMariaVer1084AllSlavesStatusMultiSource, _ = os.ReadFile("testdata/mariadb/v10.8.4/all_slaves_status_multi_source.txt") + dataMariaVer1084UserStatistics, _ = os.ReadFile("testdata/mariadb/v10.8.4/user_statistics.txt") + dataMariaVer1084ProcessList, _ = os.ReadFile("testdata/mariadb/v10.8.4/process_list.txt") + + dataMariaGaleraClusterVer1084Version, _ = os.ReadFile("testdata/mariadb/v10.8.4-galera-cluster/version.txt") + dataMariaGaleraClusterVer1084GlobalStatus, _ = os.ReadFile("testdata/mariadb/v10.8.4-galera-cluster/global_status.txt") + dataMariaGaleraClusterVer1084GlobalVariables, _ = os.ReadFile("testdata/mariadb/v10.8.4-galera-cluster/global_variables.txt") + dataMariaGaleraClusterVer1084UserStatistics, _ = os.ReadFile("testdata/mariadb/v10.8.4-galera-cluster/user_statistics.txt") + dataMariaGaleraClusterVer1084ProcessList, _ = os.ReadFile("testdata/mariadb/v10.8.4-galera-cluster/process_list.txt") +) + +func Test_testDataIsValid(t *testing.T) { + for name, data := range map[string][]byte{ + "dataConfigJSON": dataConfigJSON, + "dataConfigYAML": dataConfigYAML, + "dataSessionVariables": dataSessionVariables, + "dataMySQLVer8030Version": dataMySQLVer8030Version, + "dataMySQLVer8030GlobalStatus": dataMySQLVer8030GlobalStatus, + "dataMySQLVer8030GlobalVariables": dataMySQLVer8030GlobalVariables, + "dataMySQLVer8030ReplicaStatusMultiSource": dataMySQLVer8030ReplicaStatusMultiSource, + "dataMySQLVer8030ProcessList": dataMySQLVer8030ProcessList, + "dataPerconaVer8029Version": dataPerconaVer8029Version, + "dataPerconaVer8029GlobalStatus": dataPerconaVer8029GlobalStatus, + "dataPerconaVer8029GlobalVariables": dataPerconaVer8029GlobalVariables, + "dataPerconaVer8029UserStatistics": dataPerconaVer8029UserStatistics, + "dataPerconaV8029ProcessList": dataPerconaV8029ProcessList, + "dataMariaVer5564Version": dataMariaVer5564Version, + "dataMariaVer5564GlobalStatus": dataMariaVer5564GlobalStatus, + "dataMariaVer5564GlobalVariables": dataMariaVer5564GlobalVariables, + "dataMariaVer5564ProcessList": dataMariaVer5564ProcessList, + "dataMariaVer1084Version": dataMariaVer1084Version, + "dataMariaVer1084GlobalStatus": dataMariaVer1084GlobalStatus, + "dataMariaVer1084GlobalVariables": dataMariaVer1084GlobalVariables, + "dataMariaVer1084AllSlavesStatusSingleSource": dataMariaVer1084AllSlavesStatusSingleSource, + "dataMariaVer1084AllSlavesStatusMultiSource": dataMariaVer1084AllSlavesStatusMultiSource, + "dataMariaVer1084UserStatistics": dataMariaVer1084UserStatistics, + "dataMariaVer1084ProcessList": dataMariaVer1084ProcessList, + "dataMariaGaleraClusterVer1084Version": dataMariaGaleraClusterVer1084Version, + "dataMariaGaleraClusterVer1084GlobalStatus": dataMariaGaleraClusterVer1084GlobalStatus, + "dataMariaGaleraClusterVer1084GlobalVariables": dataMariaGaleraClusterVer1084GlobalVariables, + "dataMariaGaleraClusterVer1084UserStatistics": dataMariaGaleraClusterVer1084UserStatistics, + "dataMariaGaleraClusterVer1084ProcessList": dataMariaGaleraClusterVer1084ProcessList, + } { + require.NotNil(t, data, fmt.Sprintf("read data: %s", name)) + _, err := prepareMockRows(data) + require.NoError(t, err, fmt.Sprintf("prepare mock rows: %s", name)) + } +} + +func TestMySQL_ConfigurationSerialize(t *testing.T) { + module.TestConfigurationSerialize(t, &MySQL{}, dataConfigJSON, dataConfigYAML) +} + +func TestMySQL_Init(t *testing.T) { + tests := map[string]struct { + config Config + wantFail bool + }{ + "empty DSN": { + config: Config{DSN: ""}, + wantFail: true, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + mySQL := New() + mySQL.Config = test.config + + if test.wantFail { + assert.Error(t, mySQL.Init()) + } else { + assert.NoError(t, mySQL.Init()) + } + }) + } +} + +func TestMySQL_Cleanup(t *testing.T) { + tests := map[string]func(t *testing.T) (mySQL *MySQL, cleanup func()){ + "db connection not initialized": func(t *testing.T) (mySQL *MySQL, cleanup func()) { + return New(), func() {} + }, + "db connection initialized": func(t *testing.T) (mySQL *MySQL, cleanup func()) { + db, mock, err := sqlmock.New() + require.NoError(t, err) + + mock.ExpectClose() + mySQL = New() + mySQL.db = db + cleanup = func() { _ = db.Close() } + + return mySQL, cleanup + }, + } + + for name, prepare := range tests { + t.Run(name, func(t *testing.T) { + mySQL, cleanup := prepare(t) + defer cleanup() + + assert.NotPanics(t, mySQL.Cleanup) + assert.Nil(t, mySQL.db) + }) + } +} + +func TestMySQL_Charts(t *testing.T) { + assert.NotNil(t, New().Charts()) +} + +func TestMySQL_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, queryShowVersion, dataMariaVer1084Version) + mockExpect(t, m, queryShowSessionVariables, dataSessionVariables) + mockExpect(t, m, queryDisableSessionQueryLog, nil) + mockExpect(t, m, queryDisableSessionSlowQueryLog, nil) + mockExpect(t, m, queryShowGlobalStatus, dataMariaVer1084GlobalStatus) + mockExpect(t, m, queryShowGlobalVariables, dataMariaVer1084GlobalVariables) + mockExpect(t, m, queryShowAllSlavesStatus, dataMariaVer1084AllSlavesStatusMultiSource) + mockExpect(t, m, queryShowUserStatistics, dataMariaVer1084UserStatistics) + mockExpect(t, m, queryShowProcessList, dataMariaVer1084ProcessList) + }, + }, + "fails when error on querying version": { + wantFail: true, + prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { + mockExpectErr(m, queryShowVersion) + }, + }, + "fails when error on querying global status": { + wantFail: true, + prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { + mockExpect(t, m, queryShowVersion, dataMariaVer1084Version) + mockExpect(t, m, queryShowSessionVariables, dataSessionVariables) + mockExpect(t, m, queryDisableSessionQueryLog, nil) + mockExpect(t, m, queryDisableSessionSlowQueryLog, nil) + mockExpectErr(m, queryShowGlobalStatus) + }, + }, + "fails when error on querying global variables": { + wantFail: true, + prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { + mockExpect(t, m, queryShowVersion, dataMariaVer1084Version) + mockExpect(t, m, queryShowSessionVariables, dataSessionVariables) + mockExpect(t, m, queryDisableSessionQueryLog, nil) + mockExpect(t, m, queryDisableSessionSlowQueryLog, nil) + mockExpectErr(m, queryShowGlobalStatus) + }, + }, + "success when error on querying slave status": { + wantFail: false, + prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { + mockExpect(t, m, queryShowVersion, dataMariaVer1084Version) + mockExpect(t, m, queryShowSessionVariables, dataSessionVariables) + mockExpect(t, m, queryDisableSessionQueryLog, nil) + mockExpect(t, m, queryDisableSessionSlowQueryLog, nil) + mockExpect(t, m, queryShowGlobalStatus, dataMariaVer1084GlobalStatus) + mockExpect(t, m, queryShowGlobalVariables, dataMariaVer1084GlobalVariables) + mockExpectErr(m, queryShowAllSlavesStatus) + mockExpect(t, m, queryShowUserStatistics, dataMariaVer1084UserStatistics) + mockExpect(t, m, queryShowProcessList, dataMariaVer1084ProcessList) + }, + }, + "success when error on querying user statistics": { + wantFail: false, + prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { + mockExpect(t, m, queryShowVersion, dataMariaVer1084Version) + mockExpect(t, m, queryShowSessionVariables, dataSessionVariables) + mockExpect(t, m, queryDisableSessionQueryLog, nil) + mockExpect(t, m, queryDisableSessionSlowQueryLog, nil) + mockExpect(t, m, queryShowGlobalStatus, dataMariaVer1084GlobalStatus) + mockExpect(t, m, queryShowGlobalVariables, dataMariaVer1084GlobalVariables) + mockExpect(t, m, queryShowAllSlavesStatus, dataMariaVer1084AllSlavesStatusMultiSource) + mockExpectErr(m, queryShowUserStatistics) + mockExpect(t, m, queryShowProcessList, dataMariaVer1084ProcessList) + }, + }, + "success when error on querying process list": { + wantFail: false, + prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { + mockExpect(t, m, queryShowVersion, dataMariaVer1084Version) + mockExpect(t, m, queryShowSessionVariables, dataSessionVariables) + mockExpect(t, m, queryDisableSessionQueryLog, nil) + mockExpect(t, m, queryDisableSessionSlowQueryLog, nil) + mockExpect(t, m, queryShowGlobalStatus, dataMariaVer1084GlobalStatus) + mockExpect(t, m, queryShowGlobalVariables, dataMariaVer1084GlobalVariables) + mockExpect(t, m, queryShowAllSlavesStatus, dataMariaVer1084AllSlavesStatusMultiSource) + mockExpect(t, m, queryShowUserStatistics, dataMariaVer1084UserStatistics) + mockExpectErr(m, queryShowProcessList) + }, + }, + } + + 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()) + + test.prepareMock(t, mock) + + if test.wantFail { + assert.Error(t, my.Check()) + } else { + assert.NoError(t, my.Check()) + } + assert.NoError(t, mock.ExpectationsWereMet()) + }) + } +} + +func TestMySQL_Collect(t *testing.T) { + type testCaseStep struct { + prepareMock func(t *testing.T, m sqlmock.Sqlmock) + check func(t *testing.T, my *MySQL) + } + tests := map[string][]testCaseStep{ + "MariaDB-Standalone[v5.5.46]: success on all queries": { + { + prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { + mockExpect(t, m, queryShowVersion, dataMariaVer5564Version) + mockExpect(t, m, queryShowSessionVariables, dataSessionVariables) + mockExpect(t, m, queryDisableSessionQueryLog, nil) + mockExpect(t, m, queryDisableSessionSlowQueryLog, nil) + mockExpect(t, m, queryShowGlobalStatus, dataMariaVer5564GlobalStatus) + mockExpect(t, m, queryShowGlobalVariables, dataMariaVer5564GlobalVariables) + mockExpect(t, m, queryShowSlaveStatus, nil) + mockExpect(t, m, queryShowProcessList, dataMariaVer5564ProcessList) + }, + check: func(t *testing.T, my *MySQL) { + mx := my.Collect() + + expected := map[string]int64{ + "aborted_connects": 0, + "binlog_cache_disk_use": 0, + "binlog_cache_use": 0, + "binlog_stmt_cache_disk_use": 0, + "binlog_stmt_cache_use": 0, + "bytes_received": 639, + "bytes_sent": 41620, + "com_delete": 0, + "com_insert": 0, + "com_replace": 0, + "com_select": 4, + "com_update": 0, + "connections": 4, + "created_tmp_disk_tables": 0, + "created_tmp_files": 6, + "created_tmp_tables": 5, + "handler_commit": 0, + "handler_delete": 0, + "handler_prepare": 0, + "handler_read_first": 0, + "handler_read_key": 0, + "handler_read_next": 0, + "handler_read_prev": 0, + "handler_read_rnd": 0, + "handler_read_rnd_next": 1264, + "handler_rollback": 0, + "handler_savepoint": 0, + "handler_savepoint_rollback": 0, + "handler_update": 0, + "handler_write": 0, + "innodb_buffer_pool_bytes_data": 2342912, + "innodb_buffer_pool_bytes_dirty": 0, + "innodb_buffer_pool_pages_data": 143, + "innodb_buffer_pool_pages_dirty": 0, + "innodb_buffer_pool_pages_flushed": 0, + "innodb_buffer_pool_pages_free": 16240, + "innodb_buffer_pool_pages_misc": 0, + "innodb_buffer_pool_pages_total": 16383, + "innodb_buffer_pool_read_ahead": 0, + "innodb_buffer_pool_read_ahead_evicted": 0, + "innodb_buffer_pool_read_ahead_rnd": 0, + "innodb_buffer_pool_read_requests": 459, + "innodb_buffer_pool_reads": 144, + "innodb_buffer_pool_wait_free": 0, + "innodb_buffer_pool_write_requests": 0, + "innodb_data_fsyncs": 3, + "innodb_data_pending_fsyncs": 0, + "innodb_data_pending_reads": 0, + "innodb_data_pending_writes": 0, + "innodb_data_read": 4542976, + "innodb_data_reads": 155, + "innodb_data_writes": 3, + "innodb_data_written": 1536, + "innodb_deadlocks": 0, + "innodb_log_waits": 0, + "innodb_log_write_requests": 0, + "innodb_log_writes": 1, + "innodb_os_log_fsyncs": 3, + "innodb_os_log_pending_fsyncs": 0, + "innodb_os_log_pending_writes": 0, + "innodb_os_log_written": 512, + "innodb_row_lock_current_waits": 0, + "innodb_rows_deleted": 0, + "innodb_rows_inserted": 0, + "innodb_rows_read": 0, + "innodb_rows_updated": 0, + "key_blocks_not_flushed": 0, + "key_blocks_unused": 107171, + "key_blocks_used": 0, + "key_read_requests": 0, + "key_reads": 0, + "key_write_requests": 0, + "key_writes": 0, + "max_connections": 100, + "max_used_connections": 1, + "open_files": 21, + "open_tables": 26, + "opened_files": 84, + "opened_tables": 0, + "process_list_fetch_query_duration": 0, + "process_list_longest_query_duration": 9, + "process_list_queries_count_system": 0, + "process_list_queries_count_user": 2, + "qcache_free_blocks": 1, + "qcache_free_memory": 67091120, + "qcache_hits": 0, + "qcache_inserts": 0, + "qcache_lowmem_prunes": 0, + "qcache_not_cached": 4, + "qcache_queries_in_cache": 0, + "qcache_total_blocks": 1, + "queries": 12, + "questions": 11, + "select_full_join": 0, + "select_full_range_join": 0, + "select_range": 0, + "select_range_check": 0, + "select_scan": 5, + "slow_queries": 0, + "sort_merge_passes": 0, + "sort_range": 0, + "sort_scan": 0, + "table_locks_immediate": 36, + "table_locks_waited": 0, + "table_open_cache": 400, + "thread_cache_misses": 2500, + "threads_cached": 0, + "threads_connected": 1, + "threads_created": 1, + "threads_running": 1, + } + + copyProcessListQueryDuration(mx, expected) + require.Equal(t, expected, mx) + ensureCollectedHasAllChartsDimsVarsIDs(t, my, mx) + }, + }, + }, + "MariaDB-Standalone[v10.8.4]: success on all queries": { + { + prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { + mockExpect(t, m, queryShowVersion, dataMariaVer1084Version) + mockExpect(t, m, queryShowSessionVariables, dataSessionVariables) + mockExpect(t, m, queryDisableSessionQueryLog, nil) + mockExpect(t, m, queryDisableSessionSlowQueryLog, nil) + mockExpect(t, m, queryShowGlobalStatus, dataMariaVer1084GlobalStatus) + mockExpect(t, m, queryShowGlobalVariables, dataMariaVer1084GlobalVariables) + mockExpect(t, m, queryShowAllSlavesStatus, nil) + mockExpect(t, m, queryShowUserStatistics, dataMariaVer1084UserStatistics) + mockExpect(t, m, queryShowProcessList, dataMariaVer1084ProcessList) + }, + check: func(t *testing.T, my *MySQL) { + mx := my.Collect() + + expected := map[string]int64{ + + "aborted_connects": 2, + "binlog_cache_disk_use": 0, + "binlog_cache_use": 0, + "binlog_stmt_cache_disk_use": 0, + "binlog_stmt_cache_use": 0, + "bytes_received": 81392, + "bytes_sent": 56794, + "com_delete": 0, + "com_insert": 0, + "com_replace": 0, + "com_select": 6, + "com_update": 0, + "connection_errors_accept": 0, + "connection_errors_internal": 0, + "connection_errors_max_connections": 0, + "connection_errors_peer_address": 0, + "connection_errors_select": 0, + "connection_errors_tcpwrap": 0, + "connections": 12, + "created_tmp_disk_tables": 0, + "created_tmp_files": 5, + "created_tmp_tables": 2, + "handler_commit": 30, + "handler_delete": 0, + "handler_prepare": 0, + "handler_read_first": 7, + "handler_read_key": 7, + "handler_read_next": 3, + "handler_read_prev": 0, + "handler_read_rnd": 0, + "handler_read_rnd_next": 626, + "handler_rollback": 0, + "handler_savepoint": 0, + "handler_savepoint_rollback": 0, + "handler_update": 3, + "handler_write": 13, + "innodb_buffer_pool_bytes_data": 5062656, + "innodb_buffer_pool_bytes_dirty": 475136, + "innodb_buffer_pool_pages_data": 309, + "innodb_buffer_pool_pages_dirty": 29, + "innodb_buffer_pool_pages_flushed": 0, + "innodb_buffer_pool_pages_free": 7755, + "innodb_buffer_pool_pages_misc": 0, + "innodb_buffer_pool_pages_total": 8064, + "innodb_buffer_pool_read_ahead": 0, + "innodb_buffer_pool_read_ahead_evicted": 0, + "innodb_buffer_pool_read_ahead_rnd": 0, + "innodb_buffer_pool_read_requests": 1911, + "innodb_buffer_pool_reads": 171, + "innodb_buffer_pool_wait_free": 0, + "innodb_buffer_pool_write_requests": 148, + "innodb_data_fsyncs": 17, + "innodb_data_pending_fsyncs": 0, + "innodb_data_pending_reads": 0, + "innodb_data_pending_writes": 0, + "innodb_data_read": 2801664, + "innodb_data_reads": 185, + "innodb_data_writes": 16, + "innodb_data_written": 0, + "innodb_deadlocks": 0, + "innodb_log_waits": 0, + "innodb_log_write_requests": 109, + "innodb_log_writes": 15, + "innodb_os_log_written": 6097, + "innodb_row_lock_current_waits": 0, + "innodb_rows_deleted": 0, + "innodb_rows_inserted": 0, + "innodb_rows_read": 0, + "innodb_rows_updated": 0, + "key_blocks_not_flushed": 0, + "key_blocks_unused": 107163, + "key_blocks_used": 0, + "key_read_requests": 0, + "key_reads": 0, + "key_write_requests": 0, + "key_writes": 0, + "max_connections": 151, + "max_used_connections": 1, + "open_files": 29, + "open_tables": 10, + "opened_files": 100, + "opened_tables": 16, + "process_list_fetch_query_duration": 0, + "process_list_longest_query_duration": 9, + "process_list_queries_count_system": 0, + "process_list_queries_count_user": 2, + "qcache_free_blocks": 1, + "qcache_free_memory": 1031272, + "qcache_hits": 0, + "qcache_inserts": 0, + "qcache_lowmem_prunes": 0, + "qcache_not_cached": 0, + "qcache_queries_in_cache": 0, + "qcache_total_blocks": 1, + "queries": 33, + "questions": 24, + "select_full_join": 0, + "select_full_range_join": 0, + "select_range": 0, + "select_range_check": 0, + "select_scan": 2, + "slow_queries": 0, + "sort_merge_passes": 0, + "sort_range": 0, + "sort_scan": 0, + "table_locks_immediate": 60, + "table_locks_waited": 0, + "table_open_cache": 2000, + "table_open_cache_overflows": 0, + "thread_cache_misses": 1666, + "threads_cached": 0, + "threads_connected": 1, + "threads_created": 2, + "threads_running": 3, + "userstats_netdata_access_denied": 33, + "userstats_netdata_binlog_bytes_written": 0, + "userstats_netdata_commit_transactions": 0, + "userstats_netdata_cpu_time": 77, + "userstats_netdata_denied_connections": 49698, + "userstats_netdata_empty_queries": 66, + "userstats_netdata_lost_connections": 0, + "userstats_netdata_other_commands": 0, + "userstats_netdata_rollback_transactions": 0, + "userstats_netdata_rows_deleted": 0, + "userstats_netdata_rows_inserted": 0, + "userstats_netdata_rows_read": 0, + "userstats_netdata_rows_sent": 99, + "userstats_netdata_rows_updated": 0, + "userstats_netdata_select_commands": 33, + "userstats_netdata_total_connections": 1, + "userstats_netdata_update_commands": 0, + "userstats_root_access_denied": 0, + "userstats_root_binlog_bytes_written": 0, + "userstats_root_commit_transactions": 0, + "userstats_root_cpu_time": 0, + "userstats_root_denied_connections": 0, + "userstats_root_empty_queries": 0, + "userstats_root_lost_connections": 0, + "userstats_root_other_commands": 0, + "userstats_root_rollback_transactions": 0, + "userstats_root_rows_deleted": 0, + "userstats_root_rows_inserted": 0, + "userstats_root_rows_read": 0, + "userstats_root_rows_sent": 2, + "userstats_root_rows_updated": 0, + "userstats_root_select_commands": 0, + "userstats_root_total_connections": 1, + "userstats_root_update_commands": 0, + "wsrep_cluster_size": 0, + "wsrep_cluster_status_disconnected": 1, + "wsrep_cluster_status_non_primary": 0, + "wsrep_cluster_status_primary": 0, + "wsrep_connected": 0, + "wsrep_local_bf_aborts": 0, + "wsrep_ready": 0, + "wsrep_thread_count": 0, + } + + copyProcessListQueryDuration(mx, expected) + require.Equal(t, expected, mx) + ensureCollectedHasAllChartsDimsVarsIDs(t, my, mx) + }, + }, + }, + "MariaDB-SingleSourceReplication[v10.8.4]: success on all queries": { + { + prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { + mockExpect(t, m, queryShowVersion, dataMariaVer1084Version) + mockExpect(t, m, queryShowSessionVariables, dataSessionVariables) + mockExpect(t, m, queryDisableSessionQueryLog, nil) + mockExpect(t, m, queryDisableSessionSlowQueryLog, nil) + mockExpect(t, m, queryShowGlobalStatus, dataMariaVer1084GlobalStatus) + mockExpect(t, m, queryShowGlobalVariables, dataMariaVer1084GlobalVariables) + mockExpect(t, m, queryShowAllSlavesStatus, dataMariaVer1084AllSlavesStatusSingleSource) + mockExpect(t, m, queryShowUserStatistics, dataMariaVer1084UserStatistics) + mockExpect(t, m, queryShowProcessList, dataMariaVer1084ProcessList) + }, + check: func(t *testing.T, my *MySQL) { + mx := my.Collect() + + expected := map[string]int64{ + "aborted_connects": 2, + "binlog_cache_disk_use": 0, + "binlog_cache_use": 0, + "binlog_stmt_cache_disk_use": 0, + "binlog_stmt_cache_use": 0, + "bytes_received": 81392, + "bytes_sent": 56794, + "com_delete": 0, + "com_insert": 0, + "com_replace": 0, + "com_select": 6, + "com_update": 0, + "connection_errors_accept": 0, + "connection_errors_internal": 0, + "connection_errors_max_connections": 0, + "connection_errors_peer_address": 0, + "connection_errors_select": 0, + "connection_errors_tcpwrap": 0, + "connections": 12, + "created_tmp_disk_tables": 0, + "created_tmp_files": 5, + "created_tmp_tables": 2, + "handler_commit": 30, + "handler_delete": 0, + "handler_prepare": 0, + "handler_read_first": 7, + "handler_read_key": 7, + "handler_read_next": 3, + "handler_read_prev": 0, + "handler_read_rnd": 0, + "handler_read_rnd_next": 626, + "handler_rollback": 0, + "handler_savepoint": 0, + "handler_savepoint_rollback": 0, + "handler_update": 3, + "handler_write": 13, + "innodb_buffer_pool_bytes_data": 5062656, + "innodb_buffer_pool_bytes_dirty": 475136, + "innodb_buffer_pool_pages_data": 309, + "innodb_buffer_pool_pages_dirty": 29, + "innodb_buffer_pool_pages_flushed": 0, + "innodb_buffer_pool_pages_free": 7755, + "innodb_buffer_pool_pages_misc": 0, + "innodb_buffer_pool_pages_total": 8064, + "innodb_buffer_pool_read_ahead": 0, + "innodb_buffer_pool_read_ahead_evicted": 0, + "innodb_buffer_pool_read_ahead_rnd": 0, + "innodb_buffer_pool_read_requests": 1911, + "innodb_buffer_pool_reads": 171, + "innodb_buffer_pool_wait_free": 0, + "innodb_buffer_pool_write_requests": 148, + "innodb_data_fsyncs": 17, + "innodb_data_pending_fsyncs": 0, + "innodb_data_pending_reads": 0, + "innodb_data_pending_writes": 0, + "innodb_data_read": 2801664, + "innodb_data_reads": 185, + "innodb_data_writes": 16, + "innodb_data_written": 0, + "innodb_deadlocks": 0, + "innodb_log_waits": 0, + "innodb_log_write_requests": 109, + "innodb_log_writes": 15, + "innodb_os_log_written": 6097, + "innodb_row_lock_current_waits": 0, + "innodb_rows_deleted": 0, + "innodb_rows_inserted": 0, + "innodb_rows_read": 0, + "innodb_rows_updated": 0, + "key_blocks_not_flushed": 0, + "key_blocks_unused": 107163, + "key_blocks_used": 0, + "key_read_requests": 0, + "key_reads": 0, + "key_write_requests": 0, + "key_writes": 0, + "max_connections": 151, + "max_used_connections": 1, + "open_files": 29, + "open_tables": 10, + "opened_files": 100, + "opened_tables": 16, + "process_list_fetch_query_duration": 0, + "process_list_longest_query_duration": 9, + "process_list_queries_count_system": 0, + "process_list_queries_count_user": 2, + "qcache_free_blocks": 1, + "qcache_free_memory": 1031272, + "qcache_hits": 0, + "qcache_inserts": 0, + "qcache_lowmem_prunes": 0, + "qcache_not_cached": 0, + "qcache_queries_in_cache": 0, + "qcache_total_blocks": 1, + "queries": 33, + "questions": 24, + "seconds_behind_master": 0, + "select_full_join": 0, + "select_full_range_join": 0, + "select_range": 0, + "select_range_check": 0, + "select_scan": 2, + "slave_io_running": 1, + "slave_sql_running": 1, + "slow_queries": 0, + "sort_merge_passes": 0, + "sort_range": 0, + "sort_scan": 0, + "table_locks_immediate": 60, + "table_locks_waited": 0, + "table_open_cache": 2000, + "table_open_cache_overflows": 0, + "thread_cache_misses": 1666, + "threads_cached": 0, + "threads_connected": 1, + "threads_created": 2, + "threads_running": 3, + "userstats_netdata_access_denied": 33, + "userstats_netdata_binlog_bytes_written": 0, + "userstats_netdata_commit_transactions": 0, + "userstats_netdata_cpu_time": 77, + "userstats_netdata_denied_connections": 49698, + "userstats_netdata_empty_queries": 66, + "userstats_netdata_lost_connections": 0, + "userstats_netdata_other_commands": 0, + "userstats_netdata_rollback_transactions": 0, + "userstats_netdata_rows_deleted": 0, + "userstats_netdata_rows_inserted": 0, + "userstats_netdata_rows_read": 0, + "userstats_netdata_rows_sent": 99, + "userstats_netdata_rows_updated": 0, + "userstats_netdata_select_commands": 33, + "userstats_netdata_total_connections": 1, + "userstats_netdata_update_commands": 0, + "userstats_root_access_denied": 0, + "userstats_root_binlog_bytes_written": 0, + "userstats_root_commit_transactions": 0, + "userstats_root_cpu_time": 0, + "userstats_root_denied_connections": 0, + "userstats_root_empty_queries": 0, + "userstats_root_lost_connections": 0, + "userstats_root_other_commands": 0, + "userstats_root_rollback_transactions": 0, + "userstats_root_rows_deleted": 0, + "userstats_root_rows_inserted": 0, + "userstats_root_rows_read": 0, + "userstats_root_rows_sent": 2, + "userstats_root_rows_updated": 0, + "userstats_root_select_commands": 0, + "userstats_root_total_connections": 1, + "userstats_root_update_commands": 0, + "wsrep_cluster_size": 0, + "wsrep_cluster_status_disconnected": 1, + "wsrep_cluster_status_non_primary": 0, + "wsrep_cluster_status_primary": 0, + "wsrep_connected": 0, + "wsrep_local_bf_aborts": 0, + "wsrep_ready": 0, + "wsrep_thread_count": 0, + } + + copyProcessListQueryDuration(mx, expected) + require.Equal(t, expected, mx) + ensureCollectedHasAllChartsDimsVarsIDs(t, my, mx) + }, + }, + }, + "MariaDB-MultiSourceReplication[v10.8.4]: success on all queries": { + { + prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { + mockExpect(t, m, queryShowVersion, dataMariaVer1084Version) + mockExpect(t, m, queryShowSessionVariables, dataSessionVariables) + mockExpect(t, m, queryDisableSessionQueryLog, nil) + mockExpect(t, m, queryDisableSessionSlowQueryLog, nil) + mockExpect(t, m, queryShowGlobalStatus, dataMariaVer1084GlobalStatus) + mockExpect(t, m, queryShowGlobalVariables, dataMariaVer1084GlobalVariables) + mockExpect(t, m, queryShowAllSlavesStatus, dataMariaVer1084AllSlavesStatusMultiSource) + mockExpect(t, m, queryShowUserStatistics, dataMariaVer1084UserStatistics) + mockExpect(t, m, queryShowProcessList, dataMariaVer1084ProcessList) + }, + check: func(t *testing.T, my *MySQL) { + mx := my.Collect() + + expected := map[string]int64{ + "aborted_connects": 2, + "binlog_cache_disk_use": 0, + "binlog_cache_use": 0, + "binlog_stmt_cache_disk_use": 0, + "binlog_stmt_cache_use": 0, + "bytes_received": 81392, + "bytes_sent": 56794, + "com_delete": 0, + "com_insert": 0, + "com_replace": 0, + "com_select": 6, + "com_update": 0, + "connection_errors_accept": 0, + "connection_errors_internal": 0, + "connection_errors_max_connections": 0, + "connection_errors_peer_address": 0, + "connection_errors_select": 0, + "connection_errors_tcpwrap": 0, + "connections": 12, + "created_tmp_disk_tables": 0, + "created_tmp_files": 5, + "created_tmp_tables": 2, + "handler_commit": 30, + "handler_delete": 0, + "handler_prepare": 0, + "handler_read_first": 7, + "handler_read_key": 7, + "handler_read_next": 3, + "handler_read_prev": 0, + "handler_read_rnd": 0, + "handler_read_rnd_next": 626, + "handler_rollback": 0, + "handler_savepoint": 0, + "handler_savepoint_rollback": 0, + "handler_update": 3, + "handler_write": 13, + "innodb_buffer_pool_bytes_data": 5062656, + "innodb_buffer_pool_bytes_dirty": 475136, + "innodb_buffer_pool_pages_data": 309, + "innodb_buffer_pool_pages_dirty": 29, + "innodb_buffer_pool_pages_flushed": 0, + "innodb_buffer_pool_pages_free": 7755, + "innodb_buffer_pool_pages_misc": 0, + "innodb_buffer_pool_pages_total": 8064, + "innodb_buffer_pool_read_ahead": 0, + "innodb_buffer_pool_read_ahead_evicted": 0, + "innodb_buffer_pool_read_ahead_rnd": 0, + "innodb_buffer_pool_read_requests": 1911, + "innodb_buffer_pool_reads": 171, + "innodb_buffer_pool_wait_free": 0, + "innodb_buffer_pool_write_requests": 148, + "innodb_data_fsyncs": 17, + "innodb_data_pending_fsyncs": 0, + "innodb_data_pending_reads": 0, + "innodb_data_pending_writes": 0, + "innodb_data_read": 2801664, + "innodb_data_reads": 185, + "innodb_data_writes": 16, + "innodb_data_written": 0, + "innodb_deadlocks": 0, + "innodb_log_waits": 0, + "innodb_log_write_requests": 109, + "innodb_log_writes": 15, + "innodb_os_log_written": 6097, + "innodb_row_lock_current_waits": 0, + "innodb_rows_deleted": 0, + "innodb_rows_inserted": 0, + "innodb_rows_read": 0, + "innodb_rows_updated": 0, + "key_blocks_not_flushed": 0, + "key_blocks_unused": 107163, + "key_blocks_used": 0, + "key_read_requests": 0, + "key_reads": 0, + "key_write_requests": 0, + "key_writes": 0, + "max_connections": 151, + "max_used_connections": 1, + "open_files": 29, + "open_tables": 10, + "opened_files": 100, + "opened_tables": 16, + "process_list_fetch_query_duration": 0, + "process_list_longest_query_duration": 9, + "process_list_queries_count_system": 0, + "process_list_queries_count_user": 2, + "qcache_free_blocks": 1, + "qcache_free_memory": 1031272, + "qcache_hits": 0, + "qcache_inserts": 0, + "qcache_lowmem_prunes": 0, + "qcache_not_cached": 0, + "qcache_queries_in_cache": 0, + "qcache_total_blocks": 1, + "queries": 33, + "questions": 24, + "seconds_behind_master_master1": 0, + "seconds_behind_master_master2": 0, + "select_full_join": 0, + "select_full_range_join": 0, + "select_range": 0, + "select_range_check": 0, + "select_scan": 2, + "slave_io_running_master1": 1, + "slave_io_running_master2": 1, + "slave_sql_running_master1": 1, + "slave_sql_running_master2": 1, + "slow_queries": 0, + "sort_merge_passes": 0, + "sort_range": 0, + "sort_scan": 0, + "table_locks_immediate": 60, + "table_locks_waited": 0, + "table_open_cache": 2000, + "table_open_cache_overflows": 0, + "thread_cache_misses": 1666, + "threads_cached": 0, + "threads_connected": 1, + "threads_created": 2, + "threads_running": 3, + "userstats_netdata_access_denied": 33, + "userstats_netdata_binlog_bytes_written": 0, + "userstats_netdata_commit_transactions": 0, + "userstats_netdata_cpu_time": 77, + "userstats_netdata_denied_connections": 49698, + "userstats_netdata_empty_queries": 66, + "userstats_netdata_lost_connections": 0, + "userstats_netdata_other_commands": 0, + "userstats_netdata_rollback_transactions": 0, + "userstats_netdata_rows_deleted": 0, + "userstats_netdata_rows_inserted": 0, + "userstats_netdata_rows_read": 0, + "userstats_netdata_rows_sent": 99, + "userstats_netdata_rows_updated": 0, + "userstats_netdata_select_commands": 33, + "userstats_netdata_total_connections": 1, + "userstats_netdata_update_commands": 0, + "userstats_root_access_denied": 0, + "userstats_root_binlog_bytes_written": 0, + "userstats_root_commit_transactions": 0, + "userstats_root_cpu_time": 0, + "userstats_root_denied_connections": 0, + "userstats_root_empty_queries": 0, + "userstats_root_lost_connections": 0, + "userstats_root_other_commands": 0, + "userstats_root_rollback_transactions": 0, + "userstats_root_rows_deleted": 0, + "userstats_root_rows_inserted": 0, + "userstats_root_rows_read": 0, + "userstats_root_rows_sent": 2, + "userstats_root_rows_updated": 0, + "userstats_root_select_commands": 0, + "userstats_root_total_connections": 1, + "userstats_root_update_commands": 0, + "wsrep_cluster_size": 0, + "wsrep_cluster_status_disconnected": 1, + "wsrep_cluster_status_non_primary": 0, + "wsrep_cluster_status_primary": 0, + "wsrep_connected": 0, + "wsrep_local_bf_aborts": 0, + "wsrep_ready": 0, + "wsrep_thread_count": 0, + } + + copyProcessListQueryDuration(mx, expected) + require.Equal(t, expected, mx) + ensureCollectedHasAllChartsDimsVarsIDs(t, my, mx) + }, + }, + }, + "MariaDB-MultiSourceReplication[v10.8.4]: error on slaves status (no permissions)": { + { + prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { + mockExpect(t, m, queryShowVersion, dataMariaVer1084Version) + mockExpect(t, m, queryShowSessionVariables, dataSessionVariables) + mockExpect(t, m, queryDisableSessionQueryLog, nil) + mockExpect(t, m, queryDisableSessionSlowQueryLog, nil) + mockExpect(t, m, queryShowGlobalStatus, dataMariaVer1084GlobalStatus) + mockExpect(t, m, queryShowGlobalVariables, dataMariaVer1084GlobalVariables) + mockExpectErr(m, queryShowAllSlavesStatus) + mockExpect(t, m, queryShowUserStatistics, dataMariaVer1084UserStatistics) + mockExpect(t, m, queryShowProcessList, dataMariaVer1084ProcessList) + }, + check: func(t *testing.T, my *MySQL) { + mx := my.Collect() + + expected := map[string]int64{ + "aborted_connects": 2, + "binlog_cache_disk_use": 0, + "binlog_cache_use": 0, + "binlog_stmt_cache_disk_use": 0, + "binlog_stmt_cache_use": 0, + "bytes_received": 81392, + "bytes_sent": 56794, + "com_delete": 0, + "com_insert": 0, + "com_replace": 0, + "com_select": 6, + "com_update": 0, + "connection_errors_accept": 0, + "connection_errors_internal": 0, + "connection_errors_max_connections": 0, + "connection_errors_peer_address": 0, + "connection_errors_select": 0, + "connection_errors_tcpwrap": 0, + "connections": 12, + "created_tmp_disk_tables": 0, + "created_tmp_files": 5, + "created_tmp_tables": 2, + "handler_commit": 30, + "handler_delete": 0, + "handler_prepare": 0, + "handler_read_first": 7, + "handler_read_key": 7, + "handler_read_next": 3, + "handler_read_prev": 0, + "handler_read_rnd": 0, + "handler_read_rnd_next": 626, + "handler_rollback": 0, + "handler_savepoint": 0, + "handler_savepoint_rollback": 0, + "handler_update": 3, + "handler_write": 13, + "innodb_buffer_pool_bytes_data": 5062656, + "innodb_buffer_pool_bytes_dirty": 475136, + "innodb_buffer_pool_pages_data": 309, + "innodb_buffer_pool_pages_dirty": 29, + "innodb_buffer_pool_pages_flushed": 0, + "innodb_buffer_pool_pages_free": 7755, + "innodb_buffer_pool_pages_misc": 0, + "innodb_buffer_pool_pages_total": 8064, + "innodb_buffer_pool_read_ahead": 0, + "innodb_buffer_pool_read_ahead_evicted": 0, + "innodb_buffer_pool_read_ahead_rnd": 0, + "innodb_buffer_pool_read_requests": 1911, + "innodb_buffer_pool_reads": 171, + "innodb_buffer_pool_wait_free": 0, + "innodb_buffer_pool_write_requests": 148, + "innodb_data_fsyncs": 17, + "innodb_data_pending_fsyncs": 0, + "innodb_data_pending_reads": 0, + "innodb_data_pending_writes": 0, + "innodb_data_read": 2801664, + "innodb_data_reads": 185, + "innodb_data_writes": 16, + "innodb_data_written": 0, + "innodb_deadlocks": 0, + "innodb_log_waits": 0, + "innodb_log_write_requests": 109, + "innodb_log_writes": 15, + "innodb_os_log_written": 6097, + "innodb_row_lock_current_waits": 0, + "innodb_rows_deleted": 0, + "innodb_rows_inserted": 0, + "innodb_rows_read": 0, + "innodb_rows_updated": 0, + "key_blocks_not_flushed": 0, + "key_blocks_unused": 107163, + "key_blocks_used": 0, + "key_read_requests": 0, + "key_reads": 0, + "key_write_requests": 0, + "key_writes": 0, + "max_connections": 151, + "max_used_connections": 1, + "open_files": 29, + "open_tables": 10, + "opened_files": 100, + "opened_tables": 16, + "process_list_fetch_query_duration": 0, + "process_list_longest_query_duration": 9, + "process_list_queries_count_system": 0, + "process_list_queries_count_user": 2, + "qcache_free_blocks": 1, + "qcache_free_memory": 1031272, + "qcache_hits": 0, + "qcache_inserts": 0, + "qcache_lowmem_prunes": 0, + "qcache_not_cached": 0, + "qcache_queries_in_cache": 0, + "qcache_total_blocks": 1, + "queries": 33, + "questions": 24, + "select_full_join": 0, + "select_full_range_join": 0, + "select_range": 0, + "select_range_check": 0, + "select_scan": 2, + "slow_queries": 0, + "sort_merge_passes": 0, + "sort_range": 0, + "sort_scan": 0, + "table_locks_immediate": 60, + "table_locks_waited": 0, + "table_open_cache": 2000, + "table_open_cache_overflows": 0, + "thread_cache_misses": 1666, + "threads_cached": 0, + "threads_connected": 1, + "threads_created": 2, + "threads_running": 3, + "userstats_netdata_access_denied": 33, + "userstats_netdata_binlog_bytes_written": 0, + "userstats_netdata_commit_transactions": 0, + "userstats_netdata_cpu_time": 77, + "userstats_netdata_denied_connections": 49698, + "userstats_netdata_empty_queries": 66, + "userstats_netdata_lost_connections": 0, + "userstats_netdata_other_commands": 0, + "userstats_netdata_rollback_transactions": 0, + "userstats_netdata_rows_deleted": 0, + "userstats_netdata_rows_inserted": 0, + "userstats_netdata_rows_read": 0, + "userstats_netdata_rows_sent": 99, + "userstats_netdata_rows_updated": 0, + "userstats_netdata_select_commands": 33, + "userstats_netdata_total_connections": 1, + "userstats_netdata_update_commands": 0, + "userstats_root_access_denied": 0, + "userstats_root_binlog_bytes_written": 0, + "userstats_root_commit_transactions": 0, + "userstats_root_cpu_time": 0, + "userstats_root_denied_connections": 0, + "userstats_root_empty_queries": 0, + "userstats_root_lost_connections": 0, + "userstats_root_other_commands": 0, + "userstats_root_rollback_transactions": 0, + "userstats_root_rows_deleted": 0, + "userstats_root_rows_inserted": 0, + "userstats_root_rows_read": 0, + "userstats_root_rows_sent": 2, + "userstats_root_rows_updated": 0, + "userstats_root_select_commands": 0, + "userstats_root_total_connections": 1, + "userstats_root_update_commands": 0, + "wsrep_cluster_size": 0, + "wsrep_cluster_status_disconnected": 1, + "wsrep_cluster_status_non_primary": 0, + "wsrep_cluster_status_primary": 0, + "wsrep_connected": 0, + "wsrep_local_bf_aborts": 0, + "wsrep_ready": 0, + "wsrep_thread_count": 0, + } + + copyProcessListQueryDuration(mx, expected) + require.Equal(t, expected, mx) + ensureCollectedHasAllChartsDimsVarsIDs(t, my, mx) + }, + }, + }, + "MariaDB-GaleraCluster[v10.8.4]: success on all queries": { + { + prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { + mockExpect(t, m, queryShowVersion, dataMariaGaleraClusterVer1084Version) + mockExpect(t, m, queryShowSessionVariables, dataSessionVariables) + mockExpect(t, m, queryDisableSessionQueryLog, nil) + mockExpect(t, m, queryDisableSessionSlowQueryLog, nil) + mockExpect(t, m, queryShowGlobalStatus, dataMariaGaleraClusterVer1084GlobalStatus) + mockExpect(t, m, queryShowGlobalVariables, dataMariaGaleraClusterVer1084GlobalVariables) + mockExpect(t, m, queryShowAllSlavesStatus, nil) + mockExpect(t, m, queryShowUserStatistics, dataMariaGaleraClusterVer1084UserStatistics) + mockExpect(t, m, queryShowProcessList, dataMariaGaleraClusterVer1084ProcessList) + }, + check: func(t *testing.T, my *MySQL) { + mx := my.Collect() + + expected := map[string]int64{ + "aborted_connects": 0, + "binlog_cache_disk_use": 0, + "binlog_cache_use": 0, + "binlog_stmt_cache_disk_use": 0, + "binlog_stmt_cache_use": 0, + "bytes_received": 3009, + "bytes_sent": 228856, + "com_delete": 6, + "com_insert": 0, + "com_replace": 0, + "com_select": 12, + "com_update": 0, + "connection_errors_accept": 0, + "connection_errors_internal": 0, + "connection_errors_max_connections": 0, + "connection_errors_peer_address": 0, + "connection_errors_select": 0, + "connection_errors_tcpwrap": 0, + "connections": 15, + "created_tmp_disk_tables": 4, + "created_tmp_files": 5, + "created_tmp_tables": 17, + "handler_commit": 37, + "handler_delete": 7, + "handler_prepare": 0, + "handler_read_first": 3, + "handler_read_key": 9, + "handler_read_next": 1, + "handler_read_prev": 0, + "handler_read_rnd": 0, + "handler_read_rnd_next": 6222, + "handler_rollback": 0, + "handler_savepoint": 0, + "handler_savepoint_rollback": 0, + "handler_update": 0, + "handler_write": 9, + "innodb_buffer_pool_bytes_data": 5193728, + "innodb_buffer_pool_bytes_dirty": 2260992, + "innodb_buffer_pool_pages_data": 317, + "innodb_buffer_pool_pages_dirty": 138, + "innodb_buffer_pool_pages_flushed": 0, + "innodb_buffer_pool_pages_free": 7747, + "innodb_buffer_pool_pages_misc": 0, + "innodb_buffer_pool_pages_total": 8064, + "innodb_buffer_pool_read_ahead": 0, + "innodb_buffer_pool_read_ahead_evicted": 0, + "innodb_buffer_pool_read_ahead_rnd": 0, + "innodb_buffer_pool_read_requests": 2298, + "innodb_buffer_pool_reads": 184, + "innodb_buffer_pool_wait_free": 0, + "innodb_buffer_pool_write_requests": 203, + "innodb_data_fsyncs": 15, + "innodb_data_pending_fsyncs": 0, + "innodb_data_pending_reads": 0, + "innodb_data_pending_writes": 0, + "innodb_data_read": 3014656, + "innodb_data_reads": 201, + "innodb_data_writes": 14, + "innodb_data_written": 0, + "innodb_deadlocks": 0, + "innodb_log_waits": 0, + "innodb_log_write_requests": 65, + "innodb_log_writes": 13, + "innodb_os_log_written": 4785, + "innodb_row_lock_current_waits": 0, + "innodb_rows_deleted": 0, + "innodb_rows_inserted": 0, + "innodb_rows_read": 0, + "innodb_rows_updated": 0, + "key_blocks_not_flushed": 0, + "key_blocks_unused": 107163, + "key_blocks_used": 0, + "key_read_requests": 0, + "key_reads": 0, + "key_write_requests": 0, + "key_writes": 0, + "max_connections": 151, + "max_used_connections": 1, + "open_files": 7, + "open_tables": 0, + "opened_files": 125, + "opened_tables": 24, + "process_list_fetch_query_duration": 0, + "process_list_longest_query_duration": 9, + "process_list_queries_count_system": 0, + "process_list_queries_count_user": 2, + "qcache_free_blocks": 1, + "qcache_free_memory": 1031272, + "qcache_hits": 0, + "qcache_inserts": 0, + "qcache_lowmem_prunes": 0, + "qcache_not_cached": 0, + "qcache_queries_in_cache": 0, + "qcache_total_blocks": 1, + "queries": 75, + "questions": 62, + "select_full_join": 0, + "select_full_range_join": 0, + "select_range": 0, + "select_range_check": 0, + "select_scan": 17, + "slow_queries": 0, + "sort_merge_passes": 0, + "sort_range": 0, + "sort_scan": 0, + "table_locks_immediate": 17, + "table_locks_waited": 0, + "table_open_cache": 2000, + "table_open_cache_overflows": 0, + "thread_cache_misses": 4000, + "threads_cached": 0, + "threads_connected": 1, + "threads_created": 6, + "threads_running": 1, + "userstats_netdata_access_denied": 33, + "userstats_netdata_binlog_bytes_written": 0, + "userstats_netdata_commit_transactions": 0, + "userstats_netdata_cpu_time": 77, + "userstats_netdata_denied_connections": 49698, + "userstats_netdata_empty_queries": 66, + "userstats_netdata_lost_connections": 0, + "userstats_netdata_other_commands": 0, + "userstats_netdata_rollback_transactions": 0, + "userstats_netdata_rows_deleted": 0, + "userstats_netdata_rows_inserted": 0, + "userstats_netdata_rows_read": 0, + "userstats_netdata_rows_sent": 99, + "userstats_netdata_rows_updated": 0, + "userstats_netdata_select_commands": 33, + "userstats_netdata_total_connections": 1, + "userstats_netdata_update_commands": 0, + "userstats_root_access_denied": 0, + "userstats_root_binlog_bytes_written": 0, + "userstats_root_commit_transactions": 0, + "userstats_root_cpu_time": 0, + "userstats_root_denied_connections": 0, + "userstats_root_empty_queries": 0, + "userstats_root_lost_connections": 0, + "userstats_root_other_commands": 0, + "userstats_root_rollback_transactions": 0, + "userstats_root_rows_deleted": 0, + "userstats_root_rows_inserted": 0, + "userstats_root_rows_read": 0, + "userstats_root_rows_sent": 2, + "userstats_root_rows_updated": 0, + "userstats_root_select_commands": 0, + "userstats_root_total_connections": 1, + "userstats_root_update_commands": 0, + "wsrep_cluster_size": 3, + "wsrep_cluster_status_disconnected": 0, + "wsrep_cluster_status_non_primary": 0, + "wsrep_cluster_status_primary": 1, + "wsrep_cluster_weight": 3, + "wsrep_connected": 1, + "wsrep_flow_control_paused_ns": 0, + "wsrep_local_bf_aborts": 0, + "wsrep_local_cert_failures": 0, + "wsrep_local_recv_queue": 0, + "wsrep_local_send_queue": 0, + "wsrep_local_state_donor": 0, + "wsrep_local_state_error": 0, + "wsrep_local_state_joined": 0, + "wsrep_local_state_joiner": 0, + "wsrep_local_state_synced": 1, + "wsrep_local_state_undefined": 0, + "wsrep_open_transactions": 0, + "wsrep_ready": 1, + "wsrep_received": 11, + "wsrep_received_bytes": 1410, + "wsrep_replicated": 0, + "wsrep_replicated_bytes": 0, + "wsrep_thread_count": 5, + } + + copyProcessListQueryDuration(mx, expected) + require.Equal(t, expected, mx) + ensureCollectedHasAllChartsDimsVarsIDs(t, my, mx) + }, + }, + }, + "MySQL-MultiSourceReplication[v8.0.30]: success on all queries": { + { + prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { + mockExpect(t, m, queryShowVersion, dataMySQLVer8030Version) + mockExpect(t, m, queryShowSessionVariables, dataSessionVariables) + mockExpect(t, m, queryDisableSessionQueryLog, nil) + mockExpect(t, m, queryDisableSessionSlowQueryLog, nil) + mockExpect(t, m, queryShowGlobalStatus, dataMySQLVer8030GlobalStatus) + mockExpect(t, m, queryShowGlobalVariables, dataMySQLVer8030GlobalVariables) + mockExpect(t, m, queryShowReplicaStatus, dataMySQLVer8030ReplicaStatusMultiSource) + mockExpect(t, m, queryShowProcessListPS, dataMySQLVer8030ProcessList) + }, + check: func(t *testing.T, my *MySQL) { + mx := my.Collect() + + expected := map[string]int64{ + "aborted_connects": 0, + "binlog_cache_disk_use": 0, + "binlog_cache_use": 6, + "binlog_stmt_cache_disk_use": 0, + "binlog_stmt_cache_use": 0, + "bytes_received": 5584, + "bytes_sent": 70700, + "com_delete": 0, + "com_insert": 0, + "com_replace": 0, + "com_select": 2, + "com_update": 0, + "connection_errors_accept": 0, + "connection_errors_internal": 0, + "connection_errors_max_connections": 0, + "connection_errors_peer_address": 0, + "connection_errors_select": 0, + "connection_errors_tcpwrap": 0, + "connections": 25, + "created_tmp_disk_tables": 0, + "created_tmp_files": 5, + "created_tmp_tables": 6, + "handler_commit": 720, + "handler_delete": 8, + "handler_prepare": 24, + "handler_read_first": 50, + "handler_read_key": 1914, + "handler_read_next": 4303, + "handler_read_prev": 0, + "handler_read_rnd": 0, + "handler_read_rnd_next": 4723, + "handler_rollback": 1, + "handler_savepoint": 0, + "handler_savepoint_rollback": 0, + "handler_update": 373, + "handler_write": 1966, + "innodb_buffer_pool_bytes_data": 17121280, + "innodb_buffer_pool_bytes_dirty": 0, + "innodb_buffer_pool_pages_data": 1045, + "innodb_buffer_pool_pages_dirty": 0, + "innodb_buffer_pool_pages_flushed": 361, + "innodb_buffer_pool_pages_free": 7143, + "innodb_buffer_pool_pages_misc": 4, + "innodb_buffer_pool_pages_total": 8192, + "innodb_buffer_pool_read_ahead": 0, + "innodb_buffer_pool_read_ahead_evicted": 0, + "innodb_buffer_pool_read_ahead_rnd": 0, + "innodb_buffer_pool_read_requests": 16723, + "innodb_buffer_pool_reads": 878, + "innodb_buffer_pool_wait_free": 0, + "innodb_buffer_pool_write_requests": 2377, + "innodb_data_fsyncs": 255, + "innodb_data_pending_fsyncs": 0, + "innodb_data_pending_reads": 0, + "innodb_data_pending_writes": 0, + "innodb_data_read": 14453760, + "innodb_data_reads": 899, + "innodb_data_writes": 561, + "innodb_data_written": 6128128, + "innodb_log_waits": 0, + "innodb_log_write_requests": 1062, + "innodb_log_writes": 116, + "innodb_os_log_fsyncs": 69, + "innodb_os_log_pending_fsyncs": 0, + "innodb_os_log_pending_writes": 0, + "innodb_os_log_written": 147968, + "innodb_row_lock_current_waits": 0, + "innodb_rows_deleted": 0, + "innodb_rows_inserted": 0, + "innodb_rows_read": 0, + "innodb_rows_updated": 0, + "key_blocks_not_flushed": 0, + "key_blocks_unused": 6698, + "key_blocks_used": 0, + "key_read_requests": 0, + "key_reads": 0, + "key_write_requests": 0, + "key_writes": 0, + "max_connections": 151, + "max_used_connections": 2, + "open_files": 8, + "open_tables": 127, + "opened_files": 8, + "opened_tables": 208, + "process_list_fetch_query_duration": 0, + "process_list_longest_query_duration": 9, + "process_list_queries_count_system": 0, + "process_list_queries_count_user": 2, + "queries": 27, + "questions": 15, + "seconds_behind_master_master1": 0, + "seconds_behind_master_master2": 0, + "select_full_join": 0, + "select_full_range_join": 0, + "select_range": 0, + "select_range_check": 0, + "select_scan": 12, + "slave_io_running_master1": 1, + "slave_io_running_master2": 1, + "slave_sql_running_master1": 1, + "slave_sql_running_master2": 1, + "slow_queries": 0, + "sort_merge_passes": 0, + "sort_range": 0, + "sort_scan": 0, + "table_locks_immediate": 6, + "table_locks_waited": 0, + "table_open_cache": 4000, + "table_open_cache_overflows": 0, + "thread_cache_misses": 800, + "threads_cached": 1, + "threads_connected": 1, + "threads_created": 2, + "threads_running": 2, + } + + copyProcessListQueryDuration(mx, expected) + require.Equal(t, expected, mx) + ensureCollectedHasAllChartsDimsVarsIDs(t, my, mx) + }, + }, + }, + "Percona-Standalone[v8.0.29]: success on all queries": { + { + prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { + mockExpect(t, m, queryShowVersion, dataPerconaVer8029Version) + mockExpect(t, m, queryShowSessionVariables, dataSessionVariables) + mockExpect(t, m, queryDisableSessionQueryLog, nil) + mockExpect(t, m, queryDisableSessionSlowQueryLog, nil) + mockExpect(t, m, queryShowGlobalStatus, dataPerconaVer8029GlobalStatus) + mockExpect(t, m, queryShowGlobalVariables, dataPerconaVer8029GlobalVariables) + mockExpect(t, m, queryShowReplicaStatus, nil) + mockExpect(t, m, queryShowUserStatistics, dataPerconaVer8029UserStatistics) + mockExpect(t, m, queryShowProcessListPS, dataPerconaV8029ProcessList) + }, + check: func(t *testing.T, my *MySQL) { + mx := my.Collect() + + expected := map[string]int64{ + "aborted_connects": 1, + "binlog_cache_disk_use": 0, + "binlog_cache_use": 0, + "binlog_stmt_cache_disk_use": 0, + "binlog_stmt_cache_use": 0, + "bytes_received": 682970, + "bytes_sent": 33668405, + "com_delete": 0, + "com_insert": 0, + "com_replace": 0, + "com_select": 1687, + "com_update": 0, + "connection_errors_accept": 0, + "connection_errors_internal": 0, + "connection_errors_max_connections": 0, + "connection_errors_peer_address": 0, + "connection_errors_select": 0, + "connection_errors_tcpwrap": 0, + "connections": 13, + "created_tmp_disk_tables": 1683, + "created_tmp_files": 5, + "created_tmp_tables": 5054, + "handler_commit": 576, + "handler_delete": 0, + "handler_prepare": 0, + "handler_read_first": 1724, + "handler_read_key": 3439, + "handler_read_next": 4147, + "handler_read_prev": 0, + "handler_read_rnd": 0, + "handler_read_rnd_next": 2983285, + "handler_rollback": 0, + "handler_savepoint": 0, + "handler_savepoint_rollback": 0, + "handler_update": 317, + "handler_write": 906501, + "innodb_buffer_pool_bytes_data": 18399232, + "innodb_buffer_pool_bytes_dirty": 49152, + "innodb_buffer_pool_pages_data": 1123, + "innodb_buffer_pool_pages_dirty": 3, + "innodb_buffer_pool_pages_flushed": 205, + "innodb_buffer_pool_pages_free": 7064, + "innodb_buffer_pool_pages_misc": 5, + "innodb_buffer_pool_pages_total": 8192, + "innodb_buffer_pool_read_ahead": 0, + "innodb_buffer_pool_read_ahead_evicted": 0, + "innodb_buffer_pool_read_ahead_rnd": 0, + "innodb_buffer_pool_read_requests": 109817, + "innodb_buffer_pool_reads": 978, + "innodb_buffer_pool_wait_free": 0, + "innodb_buffer_pool_write_requests": 77412, + "innodb_data_fsyncs": 50, + "innodb_data_pending_fsyncs": 0, + "innodb_data_pending_reads": 0, + "innodb_data_pending_writes": 0, + "innodb_data_read": 16094208, + "innodb_data_reads": 1002, + "innodb_data_writes": 288, + "innodb_data_written": 3420160, + "innodb_log_waits": 0, + "innodb_log_write_requests": 651, + "innodb_log_writes": 47, + "innodb_os_log_fsyncs": 13, + "innodb_os_log_pending_fsyncs": 0, + "innodb_os_log_pending_writes": 0, + "innodb_os_log_written": 45568, + "innodb_row_lock_current_waits": 0, + "innodb_rows_deleted": 0, + "innodb_rows_inserted": 5055, + "innodb_rows_read": 5055, + "innodb_rows_updated": 0, + "key_blocks_not_flushed": 0, + "key_blocks_unused": 6698, + "key_blocks_used": 0, + "key_read_requests": 0, + "key_reads": 0, + "key_write_requests": 0, + "key_writes": 0, + "max_connections": 151, + "max_used_connections": 3, + "open_files": 2, + "open_tables": 77, + "opened_files": 2, + "opened_tables": 158, + "process_list_fetch_query_duration": 0, + "process_list_longest_query_duration": 9, + "process_list_queries_count_system": 0, + "process_list_queries_count_user": 2, + "queries": 6748, + "questions": 6746, + "select_full_join": 0, + "select_full_range_join": 0, + "select_range": 0, + "select_range_check": 0, + "select_scan": 8425, + "slow_queries": 0, + "sort_merge_passes": 0, + "sort_range": 0, + "sort_scan": 1681, + "table_locks_immediate": 3371, + "table_locks_waited": 0, + "table_open_cache": 4000, + "table_open_cache_overflows": 0, + "thread_cache_misses": 2307, + "threads_cached": 1, + "threads_connected": 2, + "threads_created": 3, + "threads_running": 2, + "userstats_netdata_access_denied": 0, + "userstats_netdata_binlog_bytes_written": 0, + "userstats_netdata_commit_transactions": 0, + "userstats_netdata_cpu_time": 0, + "userstats_netdata_denied_connections": 0, + "userstats_netdata_empty_queries": 0, + "userstats_netdata_lost_connections": 0, + "userstats_netdata_other_commands": 1, + "userstats_netdata_rollback_transactions": 0, + "userstats_netdata_rows_fetched": 1, + "userstats_netdata_rows_updated": 0, + "userstats_netdata_select_commands": 1, + "userstats_netdata_total_connections": 1, + "userstats_netdata_update_commands": 0, + "userstats_root_access_denied": 0, + "userstats_root_binlog_bytes_written": 0, + "userstats_root_commit_transactions": 0, + "userstats_root_cpu_time": 151, + "userstats_root_denied_connections": 1, + "userstats_root_empty_queries": 36, + "userstats_root_lost_connections": 0, + "userstats_root_other_commands": 110, + "userstats_root_rollback_transactions": 0, + "userstats_root_rows_fetched": 1, + "userstats_root_rows_updated": 0, + "userstats_root_select_commands": 37, + "userstats_root_total_connections": 2, + "userstats_root_update_commands": 0, + } + + copyProcessListQueryDuration(mx, expected) + require.Equal(t, expected, mx) + ensureCollectedHasAllChartsDimsVarsIDs(t, my, 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 ensureCollectedHasAllChartsDimsVarsIDs(t *testing.T, mySQL *MySQL, collected map[string]int64) { + for _, chart := range *mySQL.Charts() { + if mySQL.isMariaDB { + // https://mariadb.com/kb/en/server-status-variables/#connection_errors_accept + if mySQL.version.LT(semver.Version{Major: 10, Minor: 0, Patch: 4}) && chart.ID == "connection_errors" { + continue + } + } + for _, dim := range chart.Dims { + _, ok := collected[dim.ID] + assert.Truef(t, ok, "collected metrics has no data for dim '%s' chart '%s'", dim.ID, chart.ID) + } + for _, v := range chart.Vars { + _, ok := collected[v.ID] + assert.Truef(t, ok, "collected metrics has no data for var '%s' chart '%s'", v.ID, chart.ID) + } + } +} + +func copyProcessListQueryDuration(dst, src map[string]int64) { + if _, ok := dst["process_list_fetch_query_duration"]; !ok { + return + } + if _, ok := src["process_list_fetch_query_duration"]; !ok { + return + } + dst["process_list_fetch_query_duration"] = src["process_list_fetch_query_duration"] +} + +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() +} |