1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-07 00:04:31 +03:00

MDEV-26519: Improved histograms

Save extra information in the histogram:

    "target_histogram_size": nnn,
    "collected_at": "(date and time)",
    "collected_by": "(server version)",
This commit is contained in:
Sergei Petrunia
2021-12-03 18:08:10 +03:00
parent a0916cf5a2
commit c2d2c1e727
8 changed files with 579 additions and 54 deletions

View File

@@ -22,7 +22,13 @@
/*
Un-escape a JSON string and save it into *out.
@brief
Un-escape a JSON string and save it into *out.
@detail
There's no way to tell how much space is needed for the output.
Start with a small string and increase its size until json_unescape()
succeeds.
*/
static bool json_unescape_to_string(const char *val, int val_len, String* out)
@@ -55,7 +61,13 @@ static bool json_unescape_to_string(const char *val, int val_len, String* out)
/*
Escape a JSON string and save it into *out.
@brief
Escape a JSON string and save it into *out.
@detail
There's no way to tell how much space is needed for the output.
Start with a small string and increase its size until json_escape()
succeeds.
*/
static bool json_escape_to_string(const String *str, String* out)
@@ -145,6 +157,8 @@ public:
bucket.size= 0;
writer.start_object();
append_histogram_params();
writer.add_member(Histogram_json_hb::JSON_NAME).start_array();
}
@@ -153,6 +167,27 @@ public:
private:
bool bucket_is_empty() { return bucket.ndv == 0; }
void append_histogram_params()
{
char buf[128];
time_t cur_time_t= my_time(0);
struct tm curtime;
localtime_r(&cur_time_t, &curtime);
my_snprintf(buf, sizeof(buf), "%d-%02d-%02d %2d:%02d:%02d %s",
curtime.tm_year + 1900,
curtime.tm_mon+1,
curtime.tm_mday,
curtime.tm_hour,
curtime.tm_min,
curtime.tm_sec,
system_time_zone);
writer.add_member("target_histogram_size").add_ull(hist_width);
writer.add_member("collected_at").add_str(buf);
writer.add_member("collected_by").add_str(server_version);
}
/*
Flush the current bucket out (to JSON output), and set it to be empty.
*/
@@ -423,6 +458,15 @@ public:
};
/*
@brief
Read a constant from JSON document and save it in *out.
@detail
The JSON document stores constant in text form, we need to save it in
KeyTupleFormat. String constants in JSON may be escaped.
*/
bool read_bucket_endpoint(json_engine_t *je, Field *field, String *out,
const char **err)
{
@@ -508,8 +552,9 @@ int Histogram_json_hb::parse_bucket(json_engine_t *je, Field *field,
double size_d;
longlong ndv_ll;
StringBuffer<128> value_buf;
int rc;
while (!json_scan_next(je) && je->state != JST_OBJ_END)
while (!(rc= json_scan_next(je)) && je->state != JST_OBJ_END)
{
Json_saved_parser_state save1(je);
Json_string start_str("start");
@@ -579,6 +624,9 @@ int Histogram_json_hb::parse_bucket(json_engine_t *je, Field *field,
return 1;
}
if (rc)
return 1;
if (!have_start)
{
*err= "\"start\" element not present";
@@ -625,13 +673,12 @@ bool Histogram_json_hb::parse(MEM_ROOT *mem_root, const char *db_name,
json_engine_t je;
int rc;
const char *err= "JSON parse error";
double total_size= 0.0;
int end_element= -1;
double total_size;
int end_element;
bool end_assigned;
DBUG_ENTER("Histogram_json_hb::parse");
DBUG_ASSERT(type_arg == JSON_HB);
Json_string hist_key_name(JSON_NAME);
json_scan_start(&je, &my_charset_utf8mb4_bin,
(const uchar*)hist_data,
(const uchar*)hist_data+hist_data_len);
@@ -645,33 +692,46 @@ bool Histogram_json_hb::parse(MEM_ROOT *mem_root, const char *db_name,
goto err;
}
if (json_scan_next(&je))
goto err;
if (je.state != JST_KEY || !json_key_matches(&je, hist_key_name.get()))
while (1)
{
err= "Root element must be histogram_hb";
goto err;
if (json_scan_next(&je))
goto err;
if (je.state == JST_OBJ_END)
break; // End of object
if (je.state != JST_KEY)
goto err; // Can' really have this: JSON object has keys in it
Json_string hist_key_name(JSON_NAME);
if (json_key_matches(&je, hist_key_name.get()))
{
total_size= 0.0;
end_element= -1;
if (json_scan_next(&je))
goto err;
if (je.state != JST_ARRAY_START)
{
err= "histogram_hb must contain an array";
goto err;
}
while (!(rc= parse_bucket(&je, field, &total_size, &end_assigned, &err)))
{
if (end_assigned && end_element != -1)
end_element= (int)buckets.size();
}
if (rc > 0) // Got error other than EOF
goto err;
}
else
{
// Some unknown member. Skip it.
if (json_skip_key(&je))
return 1;
}
}
if (json_scan_next(&je))
goto err;
if (je.state != JST_ARRAY_START)
{
err= "histogram_hb must contain an array";
goto err;
}
while (!(rc= parse_bucket(&je, field, &total_size, &end_assigned, &err)))
{
if (end_assigned && end_element != -1)
end_element= (int)buckets.size();
}
if (rc > 0) // Got error other than EOF
goto err;
if (buckets.size() < 1)
{
err= "Histogram must have at least one bucket";