github.com/netdata/go.d.plugin@v0.58.1/modules/proxysql/charts.go (about)

     1  // SPDX-License-Identifier: GPL-3.0-or-later
     2  
     3  package proxysql
     4  
     5  import (
     6  	"fmt"
     7  	"strings"
     8  
     9  	"github.com/netdata/go.d.plugin/agent/module"
    10  )
    11  
    12  // TODO: check https://github.com/ProxySQL/proxysql-grafana-prometheus/blob/main/grafana/provisioning/dashboards/ProxySQL-Host-Statistics.json
    13  
    14  const (
    15  	prioClientConnectionsCount = module.Priority + iota
    16  	prioClientConnectionsRate
    17  	prioServerConnectionsCount
    18  	prioServerConnectionsRate
    19  	prioBackendsTraffic
    20  	prioFrontendsTraffic
    21  	prioActiveTransactionsCount
    22  	prioQuestionsRate
    23  	prioSlowQueriesRate
    24  	prioQueriesRate
    25  	prioBackendStatementsCount
    26  	prioBackendStatementsRate
    27  	prioFrontendStatementsCount
    28  	prioFrontendStatementsRate
    29  	prioCachedStatementsCount
    30  	prioQueryCacheEntriesCount
    31  	prioQueryCacheIO
    32  	prioQueryCacheRequestsRate
    33  	prioQueryCacheMemoryUsed
    34  	prioMySQLMonitorWorkersCount
    35  	prioMySQLMonitorWorkersRate
    36  	prioMySQLMonitorConnectChecksRate
    37  	prioMySQLMonitorPingChecksRate
    38  	prioMySQLMonitorReadOnlyChecksRate
    39  	prioMySQLMonitorReplicationLagChecksRate
    40  	prioJemallocMemoryUsed
    41  	prioMemoryUsed
    42  	prioMySQLCommandExecutionsRate
    43  	prioMySQLCommandExecutionTime
    44  	prioMySQLCommandExecutionDurationHistogram
    45  	prioMySQLUserConnectionsUtilization
    46  	prioMySQLUserConnectionsCount
    47  	prioBackendStatus
    48  	prioBackendConnectionsUsage
    49  	prioBackendConnectionsRate
    50  	prioBackendQueriesRateRate
    51  	prioBackendTraffic
    52  	prioBackendLatency
    53  	prioUptime
    54  )
    55  
    56  var (
    57  	baseCharts = module.Charts{
    58  		clientConnectionsCountChart.Copy(),
    59  		clientConnectionsRateChart.Copy(),
    60  		serverConnectionsCountChart.Copy(),
    61  		serverConnectionsRateChart.Copy(),
    62  		backendsTrafficChart.Copy(),
    63  		frontendsTrafficChart.Copy(),
    64  		activeTransactionsCountChart.Copy(),
    65  		questionsRateChart.Copy(),
    66  		slowQueriesRateChart.Copy(),
    67  		queriesRateChart.Copy(),
    68  		backendStatementsCountChart.Copy(),
    69  		backendStatementsRateChart.Copy(),
    70  		clientStatementsCountChart.Copy(),
    71  		clientStatementsRateChart.Copy(),
    72  		cachedStatementsCountChart.Copy(),
    73  		queryCacheEntriesCountChart.Copy(),
    74  		queryCacheIOChart.Copy(),
    75  		queryCacheRequestsRateChart.Copy(),
    76  		queryCacheMemoryUsedChart.Copy(),
    77  		mySQLMonitorWorkersCountChart.Copy(),
    78  		mySQLMonitorWorkersRateChart.Copy(),
    79  		mySQLMonitorConnectChecksRateChart.Copy(),
    80  		mySQLMonitorPingChecksRateChart.Copy(),
    81  		mySQLMonitorReadOnlyChecksRateChart.Copy(),
    82  		mySQLMonitorReplicationLagChecksRateChart.Copy(),
    83  		jemallocMemoryUsedChart.Copy(),
    84  		memoryUsedCountChart.Copy(),
    85  		uptimeChart.Copy(),
    86  	}
    87  
    88  	clientConnectionsCountChart = module.Chart{
    89  		ID:       "client_connections_count",
    90  		Title:    "Client connections",
    91  		Units:    "connections",
    92  		Fam:      "connections",
    93  		Ctx:      "proxysql.client_connections_count",
    94  		Priority: prioClientConnectionsCount,
    95  		Dims: module.Dims{
    96  			{ID: "Client_Connections_connected", Name: "connected"},
    97  			{ID: "Client_Connections_non_idle", Name: "non_idle"},
    98  			{ID: "Client_Connections_hostgroup_locked", Name: "hostgroup_locked"},
    99  		},
   100  	}
   101  	clientConnectionsRateChart = module.Chart{
   102  		ID:       "client_connections_rate",
   103  		Title:    "Client connections rate",
   104  		Units:    "connections/s",
   105  		Fam:      "connections",
   106  		Ctx:      "proxysql.client_connections_rate",
   107  		Priority: prioClientConnectionsRate,
   108  		Dims: module.Dims{
   109  			{ID: "Client_Connections_created", Name: "created", Algo: module.Incremental},
   110  			{ID: "Client_Connections_aborted", Name: "aborted", Algo: module.Incremental},
   111  		},
   112  	}
   113  
   114  	serverConnectionsCountChart = module.Chart{
   115  		ID:       "server_connections_count",
   116  		Title:    "Server connections",
   117  		Units:    "connections",
   118  		Fam:      "connections",
   119  		Ctx:      "proxysql.server_connections_count",
   120  		Priority: prioServerConnectionsCount,
   121  		Dims: module.Dims{
   122  			{ID: "Server_Connections_connected", Name: "connected"},
   123  		},
   124  	}
   125  	serverConnectionsRateChart = module.Chart{
   126  		ID:       "server_connections_rate",
   127  		Title:    "Server connections rate",
   128  		Units:    "connections/s",
   129  		Fam:      "connections",
   130  		Ctx:      "proxysql.server_connections_rate",
   131  		Priority: prioServerConnectionsRate,
   132  		Dims: module.Dims{
   133  			{ID: "Server_Connections_created", Name: "created", Algo: module.Incremental},
   134  			{ID: "Server_Connections_aborted", Name: "aborted", Algo: module.Incremental},
   135  			{ID: "Server_Connections_delayed", Name: "delayed", Algo: module.Incremental},
   136  		},
   137  	}
   138  
   139  	backendsTrafficChart = module.Chart{
   140  		ID:       "backends_traffic",
   141  		Title:    "Backends traffic",
   142  		Units:    "B/s",
   143  		Fam:      "traffic",
   144  		Ctx:      "proxysql.backends_traffic",
   145  		Priority: prioBackendsTraffic,
   146  		Dims: module.Dims{
   147  			{ID: "Queries_backends_bytes_recv", Name: "recv", Algo: module.Incremental},
   148  			{ID: "Queries_backends_bytes_sent", Name: "sent", Algo: module.Incremental},
   149  		},
   150  	}
   151  	frontendsTrafficChart = module.Chart{
   152  		ID:       "clients_traffic",
   153  		Title:    "Clients traffic",
   154  		Units:    "B/s",
   155  		Fam:      "traffic",
   156  		Ctx:      "proxysql.clients_traffic",
   157  		Priority: prioFrontendsTraffic,
   158  		Dims: module.Dims{
   159  			{ID: "Queries_frontends_bytes_recv", Name: "recv", Algo: module.Incremental},
   160  			{ID: "Queries_frontends_bytes_sent", Name: "sent", Algo: module.Incremental},
   161  		},
   162  	}
   163  
   164  	activeTransactionsCountChart = module.Chart{
   165  		ID:       "active_transactions_count",
   166  		Title:    "Client connections that are currently processing a transaction",
   167  		Units:    "transactions",
   168  		Fam:      "transactions",
   169  		Ctx:      "proxysql.active_transactions_count",
   170  		Priority: prioActiveTransactionsCount,
   171  		Dims: module.Dims{
   172  			{ID: "Active_Transactions", Name: "active"},
   173  		},
   174  	}
   175  	questionsRateChart = module.Chart{
   176  		ID:       "questions_rate",
   177  		Title:    "Client requests / statements executed",
   178  		Units:    "questions/s",
   179  		Fam:      "queries",
   180  		Ctx:      "proxysql.questions_rate",
   181  		Priority: prioQuestionsRate,
   182  		Dims: module.Dims{
   183  			{ID: "Questions", Name: "questions", Algo: module.Incremental},
   184  		},
   185  	}
   186  	slowQueriesRateChart = module.Chart{
   187  		ID:       "slow_queries_rate",
   188  		Title:    "Slow queries",
   189  		Units:    "queries/s",
   190  		Fam:      "queries",
   191  		Ctx:      "proxysql.slow_queries_rate",
   192  		Priority: prioSlowQueriesRate,
   193  		Dims: module.Dims{
   194  			{ID: "Slow_queries", Name: "slow", Algo: module.Incremental},
   195  		},
   196  	}
   197  	queriesRateChart = module.Chart{
   198  		ID:       "queries_rate",
   199  		Title:    "Queries rate",
   200  		Units:    "queries/s",
   201  		Fam:      "queries",
   202  		Ctx:      "proxysql.queries_rate",
   203  		Priority: prioQueriesRate,
   204  		Type:     module.Stacked,
   205  		Dims: module.Dims{
   206  			{ID: "Com_autocommit", Name: "autocommit", Algo: module.Incremental},
   207  			{ID: "Com_autocommit_filtered", Name: "autocommit_filtered", Algo: module.Incremental},
   208  			{ID: "Com_commit", Name: "commit", Algo: module.Incremental},
   209  			{ID: "Com_commit_filtered", Name: "commit_filtered", Algo: module.Incremental},
   210  			{ID: "Com_rollback", Name: "rollback", Algo: module.Incremental},
   211  			{ID: "Com_rollback_filtered", Name: "rollback_filtered", Algo: module.Incremental},
   212  			{ID: "Com_backend_change_user", Name: "backend_change_user", Algo: module.Incremental},
   213  			{ID: "Com_backend_init_db", Name: "backend_init_db", Algo: module.Incremental},
   214  			{ID: "Com_backend_set_names", Name: "backend_set_names", Algo: module.Incremental},
   215  			{ID: "Com_frontend_init_db", Name: "frontend_init_db", Algo: module.Incremental},
   216  			{ID: "Com_frontend_set_names", Name: "frontend_set_names", Algo: module.Incremental},
   217  			{ID: "Com_frontend_use_db", Name: "frontend_use_db", Algo: module.Incremental},
   218  		},
   219  	}
   220  
   221  	backendStatementsCountChart = module.Chart{
   222  		ID:       "backend_statements_count",
   223  		Title:    "Statements available across all backend connections",
   224  		Units:    "statements",
   225  		Fam:      "statements",
   226  		Ctx:      "proxysql.backend_statements_count",
   227  		Priority: prioBackendStatementsCount,
   228  		Dims: module.Dims{
   229  			{ID: "Stmt_Server_Active_Total", Name: "total"},
   230  			{ID: "Stmt_Server_Active_Unique", Name: "unique"},
   231  		},
   232  	}
   233  	backendStatementsRateChart = module.Chart{
   234  		ID:       "backend_statements_rate",
   235  		Title:    "Statements executed against the backends",
   236  		Units:    "statements/s",
   237  		Fam:      "statements",
   238  		Ctx:      "proxysql.backend_statements_rate",
   239  		Priority: prioBackendStatementsRate,
   240  		Type:     module.Stacked,
   241  		Dims: module.Dims{
   242  			{ID: "Com_backend_stmt_prepare", Name: "prepare", Algo: module.Incremental},
   243  			{ID: "Com_backend_stmt_execute", Name: "execute", Algo: module.Incremental},
   244  			{ID: "Com_backend_stmt_close", Name: "close", Algo: module.Incremental},
   245  		},
   246  	}
   247  	clientStatementsCountChart = module.Chart{
   248  		ID:       "client_statements_count",
   249  		Title:    "Statements that are in use by clients",
   250  		Units:    "statements",
   251  		Fam:      "statements",
   252  		Ctx:      "proxysql.client_statements_count",
   253  		Priority: prioFrontendStatementsCount,
   254  		Dims: module.Dims{
   255  			{ID: "Stmt_Client_Active_Total", Name: "total"},
   256  			{ID: "Stmt_Client_Active_Unique", Name: "unique"},
   257  		},
   258  	}
   259  	clientStatementsRateChart = module.Chart{
   260  		ID:       "client_statements_rate",
   261  		Title:    "Statements executed by clients",
   262  		Units:    "statements/s",
   263  		Fam:      "statements",
   264  		Ctx:      "proxysql.client_statements_rate",
   265  		Priority: prioFrontendStatementsRate,
   266  		Type:     module.Stacked,
   267  		Dims: module.Dims{
   268  			{ID: "Com_frontend_stmt_prepare", Name: "prepare", Algo: module.Incremental},
   269  			{ID: "Com_frontend_stmt_execute", Name: "execute", Algo: module.Incremental},
   270  			{ID: "Com_frontend_stmt_close", Name: "close", Algo: module.Incremental},
   271  		},
   272  	}
   273  	cachedStatementsCountChart = module.Chart{
   274  		ID:       "cached_statements_count",
   275  		Title:    "Global prepared statements",
   276  		Units:    "statements",
   277  		Fam:      "statements",
   278  		Ctx:      "proxysql.cached_statements_count",
   279  		Priority: prioCachedStatementsCount,
   280  		Dims: module.Dims{
   281  			{ID: "Stmt_Cached", Name: "cached"},
   282  		},
   283  	}
   284  
   285  	queryCacheEntriesCountChart = module.Chart{
   286  		ID:       "query_cache_entries_count",
   287  		Title:    "Query Cache entries",
   288  		Units:    "entries",
   289  		Fam:      "query cache",
   290  		Ctx:      "proxysql.query_cache_entries_count",
   291  		Priority: prioQueryCacheEntriesCount,
   292  		Dims: module.Dims{
   293  			{ID: "Query_Cache_Entries", Name: "entries"},
   294  		},
   295  	}
   296  	queryCacheMemoryUsedChart = module.Chart{
   297  		ID:       "query_cache_memory_used",
   298  		Title:    "Query Cache memory used",
   299  		Units:    "B",
   300  		Fam:      "query cache",
   301  		Ctx:      "proxysql.query_cache_memory_used",
   302  		Priority: prioQueryCacheMemoryUsed,
   303  		Dims: module.Dims{
   304  			{ID: "Query_Cache_Memory_bytes", Name: "used"},
   305  		},
   306  	}
   307  	queryCacheIOChart = module.Chart{
   308  		ID:       "query_cache_io",
   309  		Title:    "Query Cache I/O",
   310  		Units:    "B/s",
   311  		Fam:      "query cache",
   312  		Ctx:      "proxysql.query_cache_io",
   313  		Priority: prioQueryCacheIO,
   314  		Dims: module.Dims{
   315  			{ID: "Query_Cache_bytes_IN", Name: "in", Algo: module.Incremental},
   316  			{ID: "Query_Cache_bytes_OUT", Name: "out", Algo: module.Incremental},
   317  		},
   318  	}
   319  	queryCacheRequestsRateChart = module.Chart{
   320  		ID:       "query_cache_requests_rate",
   321  		Title:    "Query Cache requests",
   322  		Units:    "requests/s",
   323  		Fam:      "query cache",
   324  		Ctx:      "proxysql.query_cache_requests_rate",
   325  		Priority: prioQueryCacheRequestsRate,
   326  		Dims: module.Dims{
   327  			{ID: "Query_Cache_count_GET", Name: "read", Algo: module.Incremental},
   328  			{ID: "Query_Cache_count_SET", Name: "write", Algo: module.Incremental},
   329  			{ID: "Query_Cache_count_GET_OK", Name: "read_success", Algo: module.Incremental},
   330  		},
   331  	}
   332  
   333  	mySQLMonitorWorkersCountChart = module.Chart{
   334  		ID:       "mysql_monitor_workers_count",
   335  		Title:    "MySQL monitor workers",
   336  		Units:    "threads",
   337  		Fam:      "monitor",
   338  		Ctx:      "proxysql.mysql_monitor_workers_count",
   339  		Priority: prioMySQLMonitorWorkersCount,
   340  		Dims: module.Dims{
   341  			{ID: "MySQL_Monitor_Workers", Name: "workers"},
   342  			{ID: "MySQL_Monitor_Workers_Aux", Name: "auxiliary"},
   343  		},
   344  	}
   345  	mySQLMonitorWorkersRateChart = module.Chart{
   346  		ID:       "mysql_monitor_workers_rate",
   347  		Title:    "MySQL monitor workers rate",
   348  		Units:    "workers/s",
   349  		Fam:      "monitor",
   350  		Ctx:      "proxysql.mysql_monitor_workers_rate",
   351  		Priority: prioMySQLMonitorWorkersRate,
   352  		Dims: module.Dims{
   353  			{ID: "MySQL_Monitor_Workers_Started", Name: "started", Algo: module.Incremental},
   354  		},
   355  	}
   356  	mySQLMonitorConnectChecksRateChart = module.Chart{
   357  		ID:       "mysql_monitor_connect_checks_rate",
   358  		Title:    "MySQL monitor connect checks",
   359  		Units:    "checks/s",
   360  		Fam:      "monitor",
   361  		Ctx:      "proxysql.mysql_monitor_connect_checks_rate",
   362  		Priority: prioMySQLMonitorConnectChecksRate,
   363  		Dims: module.Dims{
   364  			{ID: "MySQL_Monitor_connect_check_OK", Name: "succeed", Algo: module.Incremental},
   365  			{ID: "MySQL_Monitor_connect_check_ERR", Name: "failed", Algo: module.Incremental},
   366  		},
   367  	}
   368  	mySQLMonitorPingChecksRateChart = module.Chart{
   369  		ID:       "mysql_monitor_ping_checks_rate",
   370  		Title:    "MySQL monitor ping checks",
   371  		Units:    "checks/s",
   372  		Fam:      "monitor",
   373  		Ctx:      "proxysql.mysql_monitor_ping_checks_rate",
   374  		Priority: prioMySQLMonitorPingChecksRate,
   375  		Dims: module.Dims{
   376  			{ID: "MySQL_Monitor_ping_check_OK", Name: "succeed", Algo: module.Incremental},
   377  			{ID: "MySQL_Monitor_ping_check_ERR", Name: "failed", Algo: module.Incremental},
   378  		},
   379  	}
   380  	mySQLMonitorReadOnlyChecksRateChart = module.Chart{
   381  		ID:       "mysql_monitor_read_only_checks_rate",
   382  		Title:    "MySQL monitor read only checks",
   383  		Units:    "checks/s",
   384  		Fam:      "monitor",
   385  		Ctx:      "proxysql.mysql_monitor_read_only_checks_rate",
   386  		Priority: prioMySQLMonitorReadOnlyChecksRate,
   387  		Dims: module.Dims{
   388  			{ID: "MySQL_Monitor_read_only_check_OK", Name: "succeed", Algo: module.Incremental},
   389  			{ID: "MySQL_Monitor_read_only_check_ERR", Name: "failed", Algo: module.Incremental},
   390  		},
   391  	}
   392  	mySQLMonitorReplicationLagChecksRateChart = module.Chart{
   393  		ID:       "mysql_monitor_replication_lag_checks_rate",
   394  		Title:    "MySQL monitor replication lag checks",
   395  		Units:    "checks/s",
   396  		Fam:      "monitor",
   397  		Ctx:      "proxysql.mysql_monitor_replication_lag_checks_rate",
   398  		Priority: prioMySQLMonitorReplicationLagChecksRate,
   399  		Dims: module.Dims{
   400  			{ID: "MySQL_Monitor_replication_lag_check_OK", Name: "succeed", Algo: module.Incremental},
   401  			{ID: "MySQL_Monitor_replication_lag_check_ERR", Name: "failed", Algo: module.Incremental},
   402  		},
   403  	}
   404  
   405  	jemallocMemoryUsedChart = module.Chart{
   406  		ID:       "jemalloc_memory_used",
   407  		Title:    "Jemalloc used memory",
   408  		Units:    "bytes",
   409  		Fam:      "memory",
   410  		Ctx:      "proxysql.jemalloc_memory_used",
   411  		Type:     module.Stacked,
   412  		Priority: prioJemallocMemoryUsed,
   413  		Dims: module.Dims{
   414  			{ID: "jemalloc_active", Name: "active"},
   415  			{ID: "jemalloc_allocated", Name: "allocated"},
   416  			{ID: "jemalloc_mapped", Name: "mapped"},
   417  			{ID: "jemalloc_metadata", Name: "metadata"},
   418  			{ID: "jemalloc_resident", Name: "resident"},
   419  			{ID: "jemalloc_retained", Name: "retained"},
   420  		},
   421  	}
   422  	memoryUsedCountChart = module.Chart{
   423  		ID:       "memory_used",
   424  		Title:    "Memory used",
   425  		Units:    "bytes",
   426  		Fam:      "memory",
   427  		Ctx:      "proxysql.memory_used",
   428  		Priority: prioMemoryUsed,
   429  		Type:     module.Stacked,
   430  		Dims: module.Dims{
   431  			{ID: "Auth_memory", Name: "auth"},
   432  			{ID: "SQLite3_memory_bytes", Name: "sqlite3"},
   433  			{ID: "query_digest_memory", Name: "query_digest"},
   434  			{ID: "mysql_query_rules_memory", Name: "query_rules"},
   435  			{ID: "mysql_firewall_users_table", Name: "firewall_users_table"},
   436  			{ID: "mysql_firewall_users_config", Name: "firewall_users_config"},
   437  			{ID: "mysql_firewall_rules_table", Name: "firewall_rules_table"},
   438  			{ID: "mysql_firewall_rules_config", Name: "firewall_rules_config"},
   439  			{ID: "stack_memory_mysql_threads", Name: "mysql_threads"},
   440  			{ID: "stack_memory_admin_threads", Name: "admin_threads"},
   441  			{ID: "stack_memory_cluster_threads", Name: "cluster_threads"},
   442  		},
   443  	}
   444  	uptimeChart = module.Chart{
   445  		ID:       "proxysql_uptime",
   446  		Title:    "Uptime",
   447  		Units:    "seconds",
   448  		Fam:      "uptime",
   449  		Ctx:      "proxysql.uptime",
   450  		Priority: prioUptime,
   451  		Dims: module.Dims{
   452  			{ID: "ProxySQL_Uptime", Name: "uptime"},
   453  		},
   454  	}
   455  )
   456  
   457  var (
   458  	mySQLCommandChartsTmpl = module.Charts{
   459  		mySQLCommandExecutionRateChartTmpl.Copy(),
   460  		mySQLCommandExecutionTimeChartTmpl.Copy(),
   461  		mySQLCommandExecutionDurationHistogramChartTmpl.Copy(),
   462  	}
   463  
   464  	mySQLCommandExecutionRateChartTmpl = module.Chart{
   465  		ID:       "mysql_command_%s_execution_rate",
   466  		Title:    "MySQL command execution",
   467  		Units:    "commands/s",
   468  		Fam:      "command exec",
   469  		Ctx:      "proxysql.mysql_command_execution_rate",
   470  		Priority: prioMySQLCommandExecutionsRate,
   471  		Dims: module.Dims{
   472  			{ID: "mysql_command_%s_Total_cnt", Name: "commands", Algo: module.Incremental},
   473  		},
   474  	}
   475  	mySQLCommandExecutionTimeChartTmpl = module.Chart{
   476  		ID:       "mysql_command_%s_execution_time",
   477  		Title:    "MySQL command execution time",
   478  		Units:    "microseconds",
   479  		Fam:      "command exec time",
   480  		Ctx:      "proxysql.mysql_command_execution_time",
   481  		Priority: prioMySQLCommandExecutionTime,
   482  		Dims: module.Dims{
   483  			{ID: "mysql_command_%s_Total_Time_us", Name: "time", Algo: module.Incremental},
   484  		},
   485  	}
   486  	mySQLCommandExecutionDurationHistogramChartTmpl = module.Chart{
   487  		ID:       "mysql_command_%s_execution_duration",
   488  		Title:    "MySQL command execution duration histogram",
   489  		Units:    "commands/s",
   490  		Fam:      "command exec duration",
   491  		Ctx:      "proxysql.mysql_command_execution_duration",
   492  		Type:     module.Stacked,
   493  		Priority: prioMySQLCommandExecutionDurationHistogram,
   494  		Dims: module.Dims{
   495  			{ID: "mysql_command_%s_cnt_100us", Name: "100us", Algo: module.Incremental},
   496  			{ID: "mysql_command_%s_cnt_500us", Name: "500us", Algo: module.Incremental},
   497  			{ID: "mysql_command_%s_cnt_1ms", Name: "1ms", Algo: module.Incremental},
   498  			{ID: "mysql_command_%s_cnt_5ms", Name: "5ms", Algo: module.Incremental},
   499  			{ID: "mysql_command_%s_cnt_10ms", Name: "10ms", Algo: module.Incremental},
   500  			{ID: "mysql_command_%s_cnt_50ms", Name: "50ms", Algo: module.Incremental},
   501  			{ID: "mysql_command_%s_cnt_100ms", Name: "100ms", Algo: module.Incremental},
   502  			{ID: "mysql_command_%s_cnt_500ms", Name: "500ms", Algo: module.Incremental},
   503  			{ID: "mysql_command_%s_cnt_1s", Name: "1s", Algo: module.Incremental},
   504  			{ID: "mysql_command_%s_cnt_5s", Name: "5s", Algo: module.Incremental},
   505  			{ID: "mysql_command_%s_cnt_10s", Name: "10s", Algo: module.Incremental},
   506  			{ID: "mysql_command_%s_cnt_INFs", Name: "+Inf", Algo: module.Incremental},
   507  		},
   508  	}
   509  )
   510  
   511  func newMySQLCommandCountersCharts(command string) *module.Charts {
   512  	charts := mySQLCommandChartsTmpl.Copy()
   513  
   514  	for _, chart := range *charts {
   515  		chart.ID = fmt.Sprintf(chart.ID, strings.ToLower(command))
   516  		chart.Labels = []module.Label{{Key: "command", Value: command}}
   517  		for _, dim := range chart.Dims {
   518  			dim.ID = fmt.Sprintf(dim.ID, command)
   519  		}
   520  	}
   521  
   522  	return charts
   523  }
   524  
   525  func (p *ProxySQL) addMySQLCommandCountersCharts(command string) {
   526  	charts := newMySQLCommandCountersCharts(command)
   527  
   528  	if err := p.Charts().Add(*charts...); err != nil {
   529  		p.Warning(err)
   530  	}
   531  }
   532  
   533  func (p *ProxySQL) removeMySQLCommandCountersCharts(command string) {
   534  	prefix := "mysql_command_" + strings.ToLower(command)
   535  
   536  	for _, chart := range *p.Charts() {
   537  		if strings.HasPrefix(chart.ID, prefix) {
   538  			chart.MarkRemove()
   539  			chart.MarkNotCreated()
   540  		}
   541  	}
   542  }
   543  
   544  var (
   545  	mySQLUserChartsTmpl = module.Charts{
   546  		mySQLUserConnectionsUtilizationChartTmpl.Copy(),
   547  		mySQLUserConnectionsCountChartTmpl.Copy(),
   548  	}
   549  
   550  	mySQLUserConnectionsUtilizationChartTmpl = module.Chart{
   551  		ID:       "mysql_user_%s_connections_utilization",
   552  		Title:    "MySQL user connections utilization",
   553  		Units:    "percentage",
   554  		Fam:      "user conns",
   555  		Ctx:      "proxysql.mysql_user_connections_utilization",
   556  		Priority: prioMySQLUserConnectionsUtilization,
   557  		Dims: module.Dims{
   558  			{ID: "mysql_user_%s_frontend_connections_utilization", Name: "used"},
   559  		},
   560  	}
   561  	mySQLUserConnectionsCountChartTmpl = module.Chart{
   562  		ID:       "mysql_user_%s_connections_count",
   563  		Title:    "MySQL user connections used",
   564  		Units:    "connections",
   565  		Fam:      "user conns",
   566  		Ctx:      "proxysql.mysql_user_connections_count",
   567  		Priority: prioMySQLUserConnectionsCount,
   568  		Dims: module.Dims{
   569  			{ID: "mysql_user_%s_frontend_connections", Name: "used"},
   570  		},
   571  	}
   572  )
   573  
   574  func newMySQLUserCharts(username string) *module.Charts {
   575  	charts := mySQLUserChartsTmpl.Copy()
   576  
   577  	for _, chart := range *charts {
   578  		chart.ID = fmt.Sprintf(chart.ID, username)
   579  		chart.Labels = []module.Label{{Key: "user", Value: username}}
   580  		for _, dim := range chart.Dims {
   581  			dim.ID = fmt.Sprintf(dim.ID, username)
   582  		}
   583  	}
   584  
   585  	return charts
   586  }
   587  
   588  func (p *ProxySQL) addMySQLUsersCharts(username string) {
   589  	charts := newMySQLUserCharts(username)
   590  
   591  	if err := p.Charts().Add(*charts...); err != nil {
   592  		p.Warning(err)
   593  	}
   594  }
   595  
   596  func (p *ProxySQL) removeMySQLUserCharts(user string) {
   597  	prefix := "mysql_user_" + user
   598  
   599  	for _, chart := range *p.Charts() {
   600  		if strings.HasPrefix(chart.ID, prefix) {
   601  			chart.MarkRemove()
   602  			chart.MarkNotCreated()
   603  		}
   604  	}
   605  }
   606  
   607  var (
   608  	backendChartsTmpl = module.Charts{
   609  		backendStatusChartTmpl.Copy(),
   610  		backendConnectionsUsageChartTmpl.Copy(),
   611  		backendConnectionsRateChartTmpl.Copy(),
   612  		backendQueriesRateRateChartTmpl.Copy(),
   613  		backendTrafficChartTmpl.Copy(),
   614  		backendLatencyChartTmpl.Copy(),
   615  	}
   616  
   617  	backendStatusChartTmpl = module.Chart{
   618  		ID:       "backend_%s_status",
   619  		Title:    "Backend status",
   620  		Units:    "status",
   621  		Fam:      "backend status",
   622  		Ctx:      "proxysql.backend_status",
   623  		Priority: prioBackendStatus,
   624  		Dims: module.Dims{
   625  			{ID: "backend_%s_status_ONLINE", Name: "online"},
   626  			{ID: "backend_%s_status_SHUNNED", Name: "shunned"},
   627  			{ID: "backend_%s_status_OFFLINE_SOFT", Name: "offline_soft"},
   628  			{ID: "backend_%s_status_OFFLINE_HARD", Name: "offline_hard"},
   629  		},
   630  	}
   631  	backendConnectionsUsageChartTmpl = module.Chart{
   632  		ID:       "backend_%s_connections_usage",
   633  		Title:    "Backend connections usage",
   634  		Units:    "connections",
   635  		Fam:      "backend conns usage",
   636  		Ctx:      "proxysql.backend_connections_usage",
   637  		Type:     module.Stacked,
   638  		Priority: prioBackendConnectionsUsage,
   639  		Dims: module.Dims{
   640  			{ID: "backend_%s_ConnFree", Name: "free"},
   641  			{ID: "backend_%s_ConnUsed", Name: "used"},
   642  		},
   643  	}
   644  	backendConnectionsRateChartTmpl = module.Chart{
   645  		ID:       "backend_%s_connections_rate",
   646  		Title:    "Backend connections established",
   647  		Units:    "connections/s",
   648  		Fam:      "backend conns established",
   649  		Ctx:      "proxysql.backend_connections_rate",
   650  		Priority: prioBackendConnectionsRate,
   651  		Dims: module.Dims{
   652  			{ID: "backend_%s_ConnOK", Name: "succeed", Algo: module.Incremental},
   653  			{ID: "backend_%s_ConnERR", Name: "failed", Algo: module.Incremental},
   654  		},
   655  	}
   656  	backendQueriesRateRateChartTmpl = module.Chart{
   657  		ID:       "backend_%s_queries_rate",
   658  		Title:    "Backend queries",
   659  		Units:    "queries/s",
   660  		Fam:      "backend queries",
   661  		Ctx:      "proxysql.backend_queries_rate",
   662  		Priority: prioBackendQueriesRateRate,
   663  		Dims: module.Dims{
   664  			{ID: "backend_%s_Queries", Name: "queries", Algo: module.Incremental},
   665  		},
   666  	}
   667  	backendTrafficChartTmpl = module.Chart{
   668  		ID:       "backend_%s_traffic",
   669  		Title:    "Backend traffic",
   670  		Units:    "B/s",
   671  		Fam:      "backend traffic",
   672  		Ctx:      "proxysql.backend_traffic",
   673  		Priority: prioBackendTraffic,
   674  		Dims: module.Dims{
   675  			{ID: "backend_%s_Bytes_data_recv", Name: "recv", Algo: module.Incremental},
   676  			{ID: "backend_%s_Bytes_data_sent", Name: "sent", Algo: module.Incremental},
   677  		},
   678  	}
   679  	backendLatencyChartTmpl = module.Chart{
   680  		ID:       "backend_%s_latency",
   681  		Title:    "Backend latency",
   682  		Units:    "microseconds",
   683  		Fam:      "backend latency",
   684  		Ctx:      "proxysql.backend_latency",
   685  		Priority: prioBackendLatency,
   686  		Dims: module.Dims{
   687  			{ID: "backend_%s_Latency_us", Name: "latency"},
   688  		},
   689  	}
   690  )
   691  
   692  func newBackendCharts(hg, host, port string) *module.Charts {
   693  	charts := backendChartsTmpl.Copy()
   694  
   695  	for _, chart := range *charts {
   696  		chart.ID = fmt.Sprintf(chart.ID, backendID(hg, host, port))
   697  		chart.Labels = []module.Label{
   698  			{Key: "host", Value: host},
   699  			{Key: "port", Value: port},
   700  		}
   701  		for _, dim := range chart.Dims {
   702  			dim.ID = fmt.Sprintf(dim.ID, backendID(hg, host, port))
   703  		}
   704  	}
   705  
   706  	return charts
   707  }
   708  
   709  func (p *ProxySQL) addBackendCharts(hg, host, port string) {
   710  	charts := newBackendCharts(hg, host, port)
   711  
   712  	if err := p.Charts().Add(*charts...); err != nil {
   713  		p.Warning(err)
   714  	}
   715  }
   716  
   717  func (p *ProxySQL) removeBackendCharts(hg, host, port string) {
   718  	prefix := "backend_" + backendID(hg, host, port)
   719  
   720  	for _, chart := range *p.Charts() {
   721  		if strings.HasPrefix(chart.ID, prefix) {
   722  			chart.MarkRemove()
   723  			chart.MarkNotCreated()
   724  		}
   725  	}
   726  }