Merge pull request #5484 from sysown/v3.0-issue5483

Fix TSDB TAP tests for Docker-based CI
private/multi-group-runner
René Cannaò 2 months ago committed by GitHub
commit 5129d55d00
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -95,65 +95,140 @@ int main() {
curl_global_init(CURL_GLOBAL_ALL);
plan(10);
diag("TSDB API Test Configuration:");
diag(" ProxySQL host: %s", cl.host);
diag(" Admin port: %d", cl.admin_port);
diag(" Admin username: %s", cl.admin_username);
MYSQL* admin = mysql_init(NULL);
if (!mysql_real_connect(admin, cl.host, cl.admin_username, cl.admin_password, NULL, cl.admin_port, NULL, 0)) {
diag("Connection failed: %s", mysql_error(admin));
return EXIT_FAILURE;
}
diag("Connected to ProxySQL admin interface");
// 1. Enable TSDB and REST API
diag("Enabling TSDB, Web, and REST API...");
mysql_query(admin, "SET tsdb-enabled='1'"); drain_results(admin);
mysql_query(admin, "SET tsdb-sample_interval='1'"); drain_results(admin);
mysql_query(admin, "SET admin-restapi_enabled='1'"); drain_results(admin);
mysql_query(admin, "SET admin-web_enabled='1'"); drain_results(admin);
mysql_query(admin, "LOAD TSDB VARIABLES TO RUNTIME"); drain_results(admin);
mysql_query(admin, "LOAD ADMIN VARIABLES TO RUNTIME"); drain_results(admin);
int rc;
rc = mysql_query(admin, "SET tsdb-enabled='1'");
if (rc) {
diag("SET tsdb-enabled failed: %s", mysql_error(admin));
return EXIT_FAILURE;
}
drain_results(admin);
rc = mysql_query(admin, "SET tsdb-sample_interval='1'");
if (rc) {
diag("SET tsdb-sample_interval failed: %s", mysql_error(admin));
return EXIT_FAILURE;
}
drain_results(admin);
rc = mysql_query(admin, "SET admin-restapi_enabled='1'");
if (rc) {
diag("SET admin-restapi_enabled failed: %s", mysql_error(admin));
return EXIT_FAILURE;
}
drain_results(admin);
rc = mysql_query(admin, "SET admin-web_enabled='1'");
if (rc) {
diag("SET admin-web_enabled failed: %s", mysql_error(admin));
return EXIT_FAILURE;
}
drain_results(admin);
rc = mysql_query(admin, "LOAD TSDB VARIABLES TO RUNTIME");
if (rc) {
diag("LOAD TSDB VARIABLES failed: %s", mysql_error(admin));
return EXIT_FAILURE;
}
drain_results(admin);
rc = mysql_query(admin, "LOAD ADMIN VARIABLES TO RUNTIME");
if (rc) {
diag("LOAD ADMIN VARIABLES failed: %s", mysql_error(admin));
return EXIT_FAILURE;
}
drain_results(admin);
// Verify the settings were applied
MYSQL_RES* res;
rc = mysql_query(admin, "SELECT variable_name, variable_value FROM runtime_global_variables WHERE variable_name IN ('admin-restapi_enabled', 'admin-web_enabled', 'tsdb-enabled')");
if (rc == 0) {
res = mysql_store_result(admin);
if (res) {
diag("Runtime variable status:");
MYSQL_ROW row;
while ((row = mysql_fetch_row(res))) {
diag(" %s = %s", row[0], row[1]);
}
mysql_free_result(res);
}
}
drain_results(admin);
// 2. Wait for background loops to collect data and HTTP server to start
diag("Waiting for initialization and data collection (7s)...");
sleep(7);
string base_url = "https://127.0.0.1:6080";
string rest_url = "http://127.0.0.1:6070";
// Use admin interface host for HTTP endpoints
string base_url = string("https://") + cl.admin_host + ":6080";
string rest_url = string("http://") + cl.admin_host + ":6070";
diag("Web dashboard URL: %s", base_url.c_str());
diag("REST API URL: %s", rest_url.c_str());
string response;
long rc;
long http_rc;
// 3. Test /tsdb Dashboard (HTML)
diag("Testing GET /tsdb");
// Retry once if server returned nothing
for (int i=0; i<3; i++) {
rc = http_get((base_url + "/tsdb").c_str(), response);
if (rc != 0) break;
diag("Retry %d for /tsdb...", i+1);
response.clear();
// Retry multiple times if server returned nothing
for (int i=0; i<5; i++) {
http_rc = http_get((base_url + "/tsdb").c_str(), response);
if (http_rc != 0) break;
diag("Retry %d for /tsdb (got response code 0, connection likely failed)...", i+1);
sleep(2);
}
ok(rc == 200, "Dashboard /tsdb returns 200 (got %ld)", rc);
ok(http_rc == 200, "Dashboard /tsdb returns 200 (got %ld)", http_rc);
if (http_rc != 200) {
diag("Dashboard response code: %ld", http_rc);
diag("This may indicate web interface is not enabled or not accessible at %s", base_url.c_str());
}
ok(response.find("ProxySQL TSDB Dashboard") != string::npos, "Dashboard contains title");
ok(response.find("tsdbChart") != string::npos, "Dashboard contains canvas element");
// 4. Test /api/tsdb/status
diag("Testing GET /api/tsdb/status");
rc = http_get((rest_url + "/api/tsdb/status").c_str(), response, "admin:admin");
ok(rc == 200, "API /api/tsdb/status returns 200");
response.clear();
string auth_creds = string(cl.admin_username) + ":" + string(cl.admin_password);
diag("Using authentication with username: %s", cl.admin_username);
http_rc = http_get((rest_url + "/api/tsdb/status").c_str(), response, auth_creds.c_str());
ok(http_rc == 200, "API /api/tsdb/status returns 200 (got %ld)", http_rc);
if (http_rc != 200) {
diag("REST API may not be enabled or not accessible at %s", rest_url.c_str());
}
ok(response.find("total_datapoints") != string::npos, "Status contains total_datapoints");
diag("Status response: %s", response.c_str());
diag("Status response (first 200 chars): %s", response.substr(0, 200).c_str());
// 5. Test /api/tsdb/metrics
diag("Testing GET /api/tsdb/metrics");
rc = http_get((rest_url + "/api/tsdb/metrics").c_str(), response, "admin:admin");
ok(rc == 200, "API /api/tsdb/metrics returns 200");
ok(response.length() > 2, "Metrics list is not empty");
response.clear();
http_rc = http_get((rest_url + "/api/tsdb/metrics").c_str(), response, auth_creds.c_str());
ok(http_rc == 200, "API /api/tsdb/metrics returns 200 (got %ld)", http_rc);
ok(response.length() > 2, "Metrics list is not empty (length: %zu)", response.length());
diag("Metrics response (first 200 chars): %s", response.substr(0, 200).c_str());
// 6. Test /api/tsdb/query
diag("Testing GET /api/tsdb/query for proxysql_uptime_seconds_total");
rc = http_get((rest_url + "/api/tsdb/query?metric=proxysql_uptime_seconds_total").c_str(), response, "admin:admin");
ok(rc == 200, "API /api/tsdb/query returns 200");
response.clear();
http_rc = http_get((rest_url + "/api/tsdb/query?metric=proxysql_uptime_seconds_total").c_str(), response, auth_creds.c_str());
ok(http_rc == 200, "API /api/tsdb/query returns 200 (got %ld)", http_rc);
ok(response.find("\"metric\":\"proxysql_uptime_seconds_total\"") != string::npos, "Query result contains metric name");
ok(response.find("\"value\":") != string::npos, "Query result contains data values");
diag("Query response (first 100 chars): %s", response.substr(0, 100).c_str());
diag("Query response (first 200 chars): %s", response.substr(0, 200).c_str());
mysql_close(admin);
return exit_status();

@ -1,6 +1,7 @@
#include <map>
#include <string>
#include <cstdlib>
#include <ctime>
#include <unistd.h>
#include "mysql.h"
@ -193,15 +194,76 @@ int main() {
ok(dp_ok && atoi(count.c_str()) > 0, "SHOW TSDB STATUS reports datapoints > 0 (found %s)", count.c_str());
// 12. Test Downsampling command
// NOTE: Downsampling only processes COMPLETED hours (data with timestamps before current_hour).
// Since we only have a few seconds of data, we need to insert test data with timestamps
// from at least 1 hour ago for the downsample to produce results.
diag("Testing TSDB downsampling via command...");
// Get current timestamp and calculate timestamp from 2 hours ago
time_t now = time(NULL);
time_t two_hours_ago = ((now - 7200) / 3600) * 3600; // Start of the hour, 2 hours ago
diag("Current time: %ld, Two hours ago (hour boundary): %ld", now, two_hours_ago);
// Insert test data with timestamps from 2 hours ago (completed hour)
diag("Inserting test metrics data with timestamps from completed hour...");
char insert_query[512];
snprintf(insert_query, sizeof(insert_query),
"INSERT OR REPLACE INTO stats_history.tsdb_metrics (timestamp, metric_name, labels, value) "
"VALUES (%ld, 'test_downsample_metric', '{\"test\":\"true\"}', 42.0)",
two_hours_ago);
rc = mysql_query(admin, insert_query);
if (rc != 0) {
diag("Failed to insert test data: %s", mysql_error(admin));
}
drain_results(admin);
diag("Inserted test metric at timestamp %ld", two_hours_ago);
// Also insert a few more data points in the same hour for realistic test
for (int i = 1; i <= 3; i++) {
snprintf(insert_query, sizeof(insert_query),
"INSERT OR REPLACE INTO stats_history.tsdb_metrics (timestamp, metric_name, labels, value) "
"VALUES (%ld, 'test_downsample_metric', '{\"test\":\"true\"}', %f)",
two_hours_ago + i * 60, 42.0 + i); // Add data points every minute
mysql_query(admin, insert_query);
drain_results(admin);
}
diag("Inserted 4 total test data points in the completed hour");
// Check metrics count before downsampling
string before_count;
fetch_single_string(admin, "SELECT COUNT(*) FROM stats_history.tsdb_metrics WHERE metric_name='test_downsample_metric'", before_count);
diag("Test metrics in tsdb_metrics before downsample: %s", before_count.c_str());
// Run the downsample command
rc = mysql_query(admin, "PROXYSQL TSDB DOWNSAMPLE");
ok(rc == 0, "PROXYSQL TSDB DOWNSAMPLE command is supported");
drain_results(admin);
// Check hourly table after downsampling
diag("Verifying downsampled data...");
string ds_count;
bool ds_ok = fetch_single_string(admin, "SELECT COUNT(*) FROM stats_history.tsdb_metrics_hour", ds_count);
ok(ds_ok && atoi(ds_count.c_str()) > 0, "Downsample produced rows in tsdb_metrics_hour (count: %s)", ds_count.c_str());
diag("Rows in tsdb_metrics_hour after downsample: %s", ds_count.c_str());
// Also check for our specific test metric
string test_metric_count;
bool test_metric_ok = fetch_single_string(admin,
"SELECT COUNT(*) FROM stats_history.tsdb_metrics_hour WHERE metric_name='test_downsample_metric'",
test_metric_count);
diag("Test metric rows in tsdb_metrics_hour: %s", test_metric_count.c_str());
ok(
ds_ok && test_metric_ok && atoi(test_metric_count.c_str()) > 0,
"Downsample produced rows for test_downsample_metric (metric rows: %s, total rows: %s)",
test_metric_count.c_str(), ds_count.c_str()
);
// Cleanup: remove test data
diag("Cleaning up test data...");
mysql_query(admin, "DELETE FROM stats_history.tsdb_metrics WHERE metric_name='test_downsample_metric'");
drain_results(admin);
mysql_query(admin, "DELETE FROM stats_history.tsdb_metrics_hour WHERE metric_name='test_downsample_metric'");
drain_results(admin);
mysql_close(admin);
return exit_status();

Loading…
Cancel
Save