Skip to content

Commit 3c4eaa7

Browse files
authored
Merge pull request #4854 from sysown/v2.7-pmm_runtime_servers_metrics
Add PMM compatible 'runtime_mysql_servers_*' metrics to Prometheus exporter
2 parents 69b0dd4 + a5cb3cb commit 3c4eaa7

File tree

3 files changed

+334
-2
lines changed

3 files changed

+334
-2
lines changed

include/MySQL_HostGroups_Manager.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,16 @@ struct p_hg_dyn_gauge {
532532
connection_pool_conn_used,
533533
connection_pool_latency_us,
534534
connection_pool_status,
535+
// PMM-Compatibility metrics
536+
///////////////////////////////////////////////////////////////////////
537+
runtime_servers_status,
538+
runtime_servers_weight,
539+
runtime_servers_compression,
540+
runtime_servers_max_connections,
541+
runtime_servers_max_replication_lag,
542+
runtime_servers_use_ssl,
543+
runtime_servers_max_latency_ms,
544+
///////////////////////////////////////////////////////////////////////
535545
__size
536546
};
537547
};
@@ -914,6 +924,16 @@ class MySQL_HostGroups_Manager {
914924
std::map<std::string, prometheus::Gauge*> p_connection_pool_latency_us_map {};
915925
std::map<std::string, prometheus::Counter*> p_connection_pool_queries_map {};
916926
std::map<std::string, prometheus::Gauge*> p_connection_pool_status_map {};
927+
// PMM-Compatibility metrics
928+
///////////////////////////////////////////////////////////////////////
929+
std::map<std::string, prometheus::Gauge*> p_runtime_servers_status_map {};
930+
std::map<std::string, prometheus::Gauge*> p_runtime_servers_weight_map {};
931+
std::map<std::string, prometheus::Gauge*> p_runtime_servers_compress_map {};
932+
std::map<std::string, prometheus::Gauge*> p_runtime_servers_max_conns_map {};
933+
std::map<std::string, prometheus::Gauge*> p_runtime_servers_max_repl_lag_map {};
934+
std::map<std::string, prometheus::Gauge*> p_runtime_servers_use_ssl_map {};
935+
std::map<std::string, prometheus::Gauge*> p_runtime_servers_max_lat_map {};
936+
///////////////////////////////////////////////////////////////////////
917937

918938
/// Prometheus gtid_executed metrics
919939
std::map<std::string, prometheus::Counter*> p_gtid_executed_map {};

lib/MySQL_HostGroups_Manager.cpp

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,52 @@ hg_metrics_map = std::make_tuple(
572572
"proxysql_connpool_conns_status",
573573
"The status of the backend server (1 - ONLINE, 2 - SHUNNED, 3 - OFFLINE_SOFT, 4 - OFFLINE_HARD, 5 - SHUNNED_REPLICATION_LAG).",
574574
metric_tags {}
575+
),
576+
// PMM-Compatibility metrics
577+
////////////////////////////////////////////////////////////////////////
578+
std::make_tuple (
579+
p_hg_dyn_gauge::runtime_servers_status,
580+
"proxysql_runtime_mysql_servers_status",
581+
"The status of the backend server (1 - ONLINE, 2 - SHUNNED, 3 - OFFLINE_SOFT, 4 - OFFLINE_HARD, 5 - SHUNNED_REPLICATION_LAG).",
582+
metric_tags {}
583+
),
584+
std::make_tuple (
585+
p_hg_dyn_gauge::runtime_servers_weight,
586+
"proxysql_runtime_mysql_servers_weight",
587+
"Configured 'weight' for the backend server.",
588+
metric_tags {}
589+
),
590+
std::make_tuple (
591+
p_hg_dyn_gauge::runtime_servers_compression,
592+
"proxysql_runtime_mysql_servers_compression",
593+
"If 'compression' is enabled for the backend server.",
594+
metric_tags {}
595+
),
596+
std::make_tuple (
597+
p_hg_dyn_gauge::runtime_servers_max_connections,
598+
"proxysql_runtime_mysql_servers_max_connections",
599+
"Configured 'max_connections' for the backend server.",
600+
metric_tags {}
601+
),
602+
std::make_tuple (
603+
p_hg_dyn_gauge::runtime_servers_max_replication_lag,
604+
"proxysql_runtime_mysql_servers_max_replication_lag",
605+
"Configured 'max_replication_lag' for the backend server.",
606+
metric_tags {}
607+
),
608+
std::make_tuple (
609+
p_hg_dyn_gauge::runtime_servers_use_ssl,
610+
"proxysql_runtime_mysql_servers_use_ssl",
611+
"If 'ssl' is enabled for the backend server.",
612+
metric_tags {}
613+
),
614+
std::make_tuple (
615+
p_hg_dyn_gauge::runtime_servers_max_latency_ms,
616+
"proxysql_runtime_mysql_servers_max_latency_ms",
617+
"Configured 'max_latency_ms' for the backend server.",
618+
metric_tags {}
575619
)
620+
////////////////////////////////////////////////////////////////////////
576621
}
577622
);
578623

@@ -3408,6 +3453,69 @@ void MySQL_HostGroups_Manager::p_update_connection_pool() {
34083453
// proxysql_connection_pool_status metric
34093454
p_update_connection_pool_update_gauge(endpoint_id, common_labels,
34103455
status.p_connection_pool_status_map, ((int)mysrvc->get_status()) + 1, p_hg_dyn_gauge::connection_pool_status);
3456+
3457+
// PMM-Compatibility metrics
3458+
////////////////////////////////////////////////////////////////////
3459+
std::map<std::string, std::string> srvs_common_labels = common_labels;
3460+
srvs_common_labels.insert({"gtid_port", std::to_string(mysrvc->gtid_port)});
3461+
3462+
p_update_connection_pool_update_gauge(
3463+
endpoint_id,
3464+
srvs_common_labels,
3465+
status.p_runtime_servers_status_map,
3466+
((int)mysrvc->get_status()) + 1,
3467+
p_hg_dyn_gauge::runtime_servers_status
3468+
);
3469+
3470+
p_update_connection_pool_update_gauge(
3471+
endpoint_id,
3472+
srvs_common_labels,
3473+
status.p_runtime_servers_weight_map,
3474+
mysrvc->weight,
3475+
p_hg_dyn_gauge::runtime_servers_weight
3476+
);
3477+
3478+
p_update_connection_pool_update_gauge(
3479+
endpoint_id,
3480+
srvs_common_labels,
3481+
status.p_runtime_servers_compress_map,
3482+
mysrvc->compression,
3483+
p_hg_dyn_gauge::runtime_servers_compression
3484+
);
3485+
3486+
p_update_connection_pool_update_gauge(
3487+
endpoint_id,
3488+
srvs_common_labels,
3489+
status.p_runtime_servers_max_conns_map,
3490+
mysrvc->max_connections,
3491+
p_hg_dyn_gauge::runtime_servers_max_connections
3492+
);
3493+
3494+
p_update_connection_pool_update_gauge(
3495+
endpoint_id,
3496+
srvs_common_labels,
3497+
status.p_runtime_servers_max_repl_lag_map,
3498+
mysrvc->max_replication_lag,
3499+
p_hg_dyn_gauge::runtime_servers_max_replication_lag
3500+
);
3501+
3502+
p_update_connection_pool_update_gauge(
3503+
endpoint_id,
3504+
srvs_common_labels,
3505+
status.p_runtime_servers_use_ssl_map,
3506+
mysrvc->use_ssl,
3507+
p_hg_dyn_gauge::runtime_servers_use_ssl
3508+
);
3509+
3510+
p_update_connection_pool_update_gauge(
3511+
endpoint_id,
3512+
srvs_common_labels,
3513+
status.p_runtime_servers_max_lat_map,
3514+
mysrvc->max_latency_us / 1000,
3515+
p_hg_dyn_gauge::runtime_servers_max_latency_ms
3516+
);
3517+
3518+
////////////////////////////////////////////////////////////////////
34113519
}
34123520
}
34133521

@@ -3436,6 +3544,37 @@ void MySQL_HostGroups_Manager::p_update_connection_pool() {
34363544
gauge = status.p_connection_pool_latency_us_map[key];
34373545
status.p_dyn_gauge_array[p_hg_dyn_gauge::connection_pool_latency_us]->Remove(gauge);
34383546
status.p_connection_pool_latency_us_map.erase(key);
3547+
3548+
// PMM-Compatibility metrics
3549+
////////////////////////////////////////////////////////////////////
3550+
gauge = status.p_runtime_servers_status_map[key];
3551+
status.p_dyn_gauge_array[p_hg_dyn_gauge::runtime_servers_status]->Remove(gauge);
3552+
status.p_runtime_servers_status_map.erase(key);
3553+
3554+
gauge = status.p_runtime_servers_weight_map[key];
3555+
status.p_dyn_gauge_array[p_hg_dyn_gauge::runtime_servers_weight]->Remove(gauge);
3556+
status.p_runtime_servers_weight_map.erase(key);
3557+
3558+
gauge = status.p_runtime_servers_compress_map[key];
3559+
status.p_dyn_gauge_array[p_hg_dyn_gauge::runtime_servers_compression]->Remove(gauge);
3560+
status.p_runtime_servers_compress_map.erase(key);
3561+
3562+
gauge = status.p_runtime_servers_max_conns_map[key];
3563+
status.p_dyn_gauge_array[p_hg_dyn_gauge::runtime_servers_max_connections]->Remove(gauge);
3564+
status.p_runtime_servers_max_conns_map.erase(key);
3565+
3566+
gauge = status.p_runtime_servers_max_repl_lag_map[key];
3567+
status.p_dyn_gauge_array[p_hg_dyn_gauge::runtime_servers_max_replication_lag]->Remove(gauge);
3568+
status.p_runtime_servers_max_repl_lag_map.erase(key);
3569+
3570+
gauge = status.p_runtime_servers_use_ssl_map[key];
3571+
status.p_dyn_gauge_array[p_hg_dyn_gauge::runtime_servers_use_ssl]->Remove(gauge);
3572+
status.p_runtime_servers_use_ssl_map.erase(key);
3573+
3574+
gauge = status.p_runtime_servers_max_lat_map[key];
3575+
status.p_dyn_gauge_array[p_hg_dyn_gauge::runtime_servers_max_latency_ms]->Remove(gauge);
3576+
status.p_runtime_servers_max_lat_map.erase(key);
3577+
////////////////////////////////////////////////////////////////////
34393578
}
34403579

34413580
wrunlock();

test/tap/tests/test_prometheus_metrics-t.cpp

Lines changed: 175 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ using std::vector;
2929
using std::pair;
3030
using std::string;
3131
using std::tuple;
32+
using std::map;
3233

3334
CommandLine cl;
3435

@@ -891,7 +892,157 @@ const vector<pair<string, tuple<setup, metric_trigger, metric_check>>> metric_te
891892
},
892893
};
893894

894-
using std::map;
895+
string status_to_string(int status) {
896+
if (status == 1) {
897+
return "ONLINE";
898+
} else if (status == 2) {
899+
return "SHUNNED";
900+
} else if (status == 3) {
901+
return "OFFLINE_SOFT";
902+
} else if (status == 4) {
903+
return "OFFLINE_HARD";
904+
} else if (status == 5) {
905+
return "SHUNNED_REPLICATION_LAG";
906+
} else {
907+
assert(0);
908+
}
909+
}
910+
911+
const char RUNTIME_SRVS[] {
912+
"SELECT"
913+
" hostgroup_id,"
914+
" (hostname || \":\" || port) AS endpoint,"
915+
" gtid_port,"
916+
" status,"
917+
" weight,"
918+
" compression,"
919+
" max_connections,"
920+
" max_replication_lag,"
921+
" use_ssl,"
922+
" max_latency_ms"
923+
" FROM"
924+
" runtime_mysql_servers"
925+
};
926+
927+
enum SRV_FLD {
928+
hosgroup_id = 0,
929+
endpoint,
930+
gtid_port,
931+
status,
932+
weight,
933+
compression,
934+
max_connections,
935+
max_replication_lag,
936+
use_ssl,
937+
max_latency_ms
938+
};
939+
940+
const map<string,int> m_srvs_metrics {
941+
{ "proxysql_runtime_mysql_servers_status", SRV_FLD::status },
942+
{ "proxysql_runtime_mysql_servers_weight", SRV_FLD::weight },
943+
{ "proxysql_runtime_mysql_servers_compression", SRV_FLD::compression },
944+
{ "proxysql_runtime_mysql_servers_max_connections", SRV_FLD::max_connections },
945+
{ "proxysql_runtime_mysql_servers_max_replication_lag", SRV_FLD::max_replication_lag },
946+
{ "proxysql_runtime_mysql_servers_use_ssl", SRV_FLD::use_ssl },
947+
{ "proxysql_runtime_mysql_servers_max_latency_ms", SRV_FLD::max_latency_ms },
948+
};
949+
950+
using p_srv_metrics = pair<mysql_row_t,vector<pair<string,double>>>;
951+
using nlohmann::json;
952+
953+
int check_srvs_metrics(
954+
const vector<mysql_row_t>& srvs, const map<string,double>& cur_metrics
955+
) {
956+
const auto match_start = [] (const string s1, const string s2) {
957+
return s1.rfind(s2) == 0;
958+
};
959+
960+
// 1. Find all defined metrics
961+
bool match = true;
962+
const uint32_t exp_checks = m_srvs_metrics.size() * srvs.size();
963+
uint32_t act_checks = 0;
964+
965+
// 2. Check all defined metrics match
966+
for (const mysql_row_t& row : srvs) {
967+
diag(
968+
"Checking matching ept metrics for server srv_row=\"%s\"",
969+
json(row).dump().c_str()
970+
);
971+
972+
for (const auto& p_id_val : cur_metrics) {
973+
auto metric_it {
974+
std::find_if(m_srvs_metrics.begin(), m_srvs_metrics.end(),
975+
[p_id_val] (const auto& p) { return p_id_val.first.rfind(p.first, 0) == 0; }
976+
)
977+
};
978+
979+
if (metric_it != std::end(m_srvs_metrics)) {
980+
const string& srv_ept { row[SRV_FLD::endpoint] };
981+
const string& srv_hg { row[SRV_FLD::hosgroup_id] };
982+
const auto& tags { extract_metric_tags(p_id_val.first) };
983+
984+
if (tags.at("endpoint") == srv_ept && tags.at("hostgroup") == srv_hg) {
985+
diag(
986+
"Checking matching ept metric ept=\"%s\" hg=%s metric=\"%s\" val=%lf",
987+
srv_ept.c_str(), srv_hg.c_str(), p_id_val.first.c_str(), p_id_val.second
988+
);
989+
990+
const string mval_str {
991+
metric_it->first.rfind("status") != std::string::npos ?
992+
status_to_string(int32_t(p_id_val.second))
993+
: std::to_string(int32_t(p_id_val.second))
994+
};
995+
996+
match = row[metric_it->second] == mval_str;
997+
match = row[SRV_FLD::gtid_port] == tags.at("gtid_port");
998+
act_checks += 1;
999+
1000+
if (!match) {
1001+
diag(
1002+
"FAIL - Mismatch found checking metric "
1003+
"exp_val=%s act_val=%s exp_gtid_port=%s act_gtid_port=%s",
1004+
row[metric_it->second].c_str(),
1005+
mval_str.c_str(),
1006+
row[SRV_FLD::gtid_port].c_str(),
1007+
tags.at("gtid_port").c_str()
1008+
);
1009+
}
1010+
}
1011+
}
1012+
}
1013+
}
1014+
1015+
ok(match, "Metrics values should match for Admin and Exporter");
1016+
ok(
1017+
exp_checks == act_checks,
1018+
"All supported metrics should be found for server entries exp_checks=%d act_checks=%d",
1019+
exp_checks, act_checks
1020+
);
1021+
1022+
return EXIT_SUCCESS;
1023+
}
1024+
1025+
int coherence_check_runtime_servers(MYSQL* admin) {
1026+
map<string,double> cur_metrics {};
1027+
int rc = get_cur_metrics(admin, cur_metrics);
1028+
if (rc) { return EXIT_FAILURE; }
1029+
1030+
auto srvs_rows { mysql_query_ext_rows(admin, RUNTIME_SRVS) };
1031+
if (srvs_rows.first) {
1032+
diag(
1033+
"Failed to fetch 'runtime_mysql_servers' rows errno=%d error=\"%s\" query=\"%s\"",
1034+
srvs_rows.first, mysql_error(admin), RUNTIME_SRVS
1035+
);
1036+
return EXIT_FAILURE;
1037+
}
1038+
1039+
return check_srvs_metrics(srvs_rows.second, cur_metrics);
1040+
}
1041+
1042+
const vector<pair<string, std::function<int(MYSQL*)>>> coherence_checks {
1043+
// Check current 'runtime_mysql_servers' values matches the ones exposed by its metrics
1044+
{ "proxysql_runtime_mysql_servers_{*} - Matching Admin Interface", coherence_check_runtime_servers },
1045+
};
8951046

8961047

8971048
int main(int argc, char** argv) {
@@ -901,7 +1052,10 @@ int main(int argc, char** argv) {
9011052
return EXIT_FAILURE;
9021053
}
9031054

904-
plan(metric_tests.size() * 4);
1055+
plan(
1056+
metric_tests.size() * 4
1057+
+ coherence_checks.size() * 2
1058+
);
9051059

9061060
for (const auto& metric_test : metric_tests) {
9071061
// Initialize Admin connection
@@ -959,5 +1113,24 @@ int main(int argc, char** argv) {
9591113
mysql_close(proxysql_admin);
9601114
}
9611115

1116+
{
1117+
MYSQL* admin = mysql_init(NULL);
1118+
1119+
if (!mysql_real_connect(admin, cl.host, cl.admin_username, cl.admin_password, NULL, cl.admin_port, NULL, 0)) {
1120+
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(admin));
1121+
return EXIT_FAILURE;
1122+
}
1123+
1124+
for (const auto& p_id_check : coherence_checks) {
1125+
const string& id { p_id_check.first.c_str() };
1126+
1127+
diag("Started metrics coherence check id=\"%s\"", id.c_str());
1128+
int rc = p_id_check.second(admin);
1129+
diag("Finished metric coherence check id=\"%s\" rc=%d", id.c_str(), rc);
1130+
}
1131+
1132+
mysql_close(admin);
1133+
}
1134+
9621135
return exit_status();
9631136
}

0 commit comments

Comments
 (0)