summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfumingwei <[email protected]>2023-05-29 14:04:57 +0800
committerfumingwei <[email protected]>2023-06-02 10:41:12 +0800
commit2b6a1bfd1a6c41fb71b59dd50f62d2c3f4688fa8 (patch)
treea4bc90b8a752dee1f42bfda1b313cb824d1ed0ff
parentd5389fb9f1cf48f413eb6cd7baad27a57efe2274 (diff)
bugfix:新增historgam和summary line protocol输出
-rw-r--r--src/fieldstat.cpp33
-rw-r--r--src/fieldstat_dynamic.cpp19
-rw-r--r--src/file_output.cpp55
-rw-r--r--src/line_protocol_output.cpp131
-rw-r--r--src/prometheus_output.cpp2
-rw-r--r--test/src/gtest_fieldstat_interface.cpp52
-rw-r--r--test/src/gtest_fieldstat_output.cpp951
7 files changed, 1205 insertions, 38 deletions
diff --git a/src/fieldstat.cpp b/src/fieldstat.cpp
index 4bdaa39..4be0ce2 100644
--- a/src/fieldstat.cpp
+++ b/src/fieldstat.cpp
@@ -170,6 +170,7 @@ struct metric * metric_new(enum field_type type, const char *field_name, const s
void metric_free(struct metric *metric)
{
int i = 0;
+ struct histogram_t *h = NULL;
free(metric->field_name);
metric->field_name = NULL;
@@ -188,6 +189,31 @@ void metric_free(struct metric *metric)
{
metric->table = NULL;
}
+ if(metric->field_type == FIELD_TYPE_SUMMARY ||
+ metric->field_type == FILED_TYPE_HISTOGRAM)
+ {
+ h = &metric->histogram;
+ if(h->changing != NULL)
+ {
+ hdr_close(h->changing);
+ h->changing = NULL;
+ }
+ if(h->accumulated != NULL)
+ {
+ hdr_close(h->accumulated);
+ h->accumulated = NULL;
+ }
+ if(h->previous_changed != NULL)
+ {
+ hdr_close(h->previous_changed);
+ h->previous_changed = NULL;
+ }
+ if(h->bins != NULL)
+ {
+ free(h->bins);
+ h->bins = NULL;
+ }
+ }
free(metric);
@@ -436,7 +462,8 @@ long long get_metric_unit_val(struct metric *metric,enum field_calc_algo calc_ty
target = &(metric->gauge);
break;
default:
- break;
+ assert(0);
+ return 0;
}
value = threadsafe_counter_read(&(target->changing));
@@ -715,6 +742,10 @@ void table_metric_free(struct table_metric *table)
{
return -1;
}
+ if(column_type[i] != FIELD_TYPE_GAUGE && column_type[i] != FIELD_TYPE_COUNTER)
+ {
+ return -1;
+ }
}
if(n_column <= 0 || n_column > TABLE_COLUMN_SIZE)
diff --git a/src/fieldstat_dynamic.cpp b/src/fieldstat_dynamic.cpp
index c10dc56..597ee3b 100644
--- a/src/fieldstat_dynamic.cpp
+++ b/src/fieldstat_dynamic.cpp
@@ -208,6 +208,10 @@ int fieldstat_register_dynamic_table(struct fieldstat_dynamic_instance *instance
{
return -1;
}
+ if(column_type[i] != FIELD_TYPE_GAUGE && column_type[i] != FIELD_TYPE_COUNTER)
+ {
+ return -1;
+ }
}
if(n_column <= 0 || n_column > TABLE_COLUMN_SIZE)
@@ -402,6 +406,12 @@ int fieldstat_dynamic_metric_value_incrby(struct fieldstat_dynamic_instance *ins
{
return -1;
}
+
+ if(type != FIELD_TYPE_GAUGE && type != FIELD_TYPE_COUNTER)
+ {
+ return -1;
+ }
+
ret = fieldstat_dynamic_metric_value_operate(instance, FS_OP_ADD, type, field_name, value, tags, n_tags, thread_id);
return ret;
}
@@ -417,6 +427,10 @@ int fieldstat_dynamic_metric_value_set(struct fieldstat_dynamic_instance *instan
{
return -1;
}
+ if(type != FIELD_TYPE_GAUGE && type != FIELD_TYPE_COUNTER)
+ {
+ return -1;
+ }
ret = fieldstat_dynamic_metric_value_operate(instance, FS_OP_SET, type, field_name, value, tags, n_tags, thread_id);
return ret;
@@ -434,6 +448,11 @@ int fieldstat_dynamic_metric_value_decrby(struct fieldstat_dynamic_instance *ins
return -1;
}
+ if(type != FIELD_TYPE_GAUGE && type != FIELD_TYPE_COUNTER)
+ {
+ return -1;
+ }
+
ret = fieldstat_dynamic_metric_value_operate(instance, FS_OP_SUB, type, field_name, value, tags, n_tags, thread_id);
return ret;
}
diff --git a/src/file_output.cpp b/src/file_output.cpp
index 9b29ad4..a6ae655 100644
--- a/src/file_output.cpp
+++ b/src/file_output.cpp
@@ -390,6 +390,27 @@ static int output_file_print_hdr_head(struct metric *metric, char *print_buf, si
return used_len;
}
+static struct hdr_histogram *read_hdr_unit_output(struct metric *metric)
+{
+ struct histogram_t *h = &(metric->histogram);
+ struct hdr_histogram *h_out = NULL, *h_tmp = NULL;
+ hdr_init(h->lowest_trackable_value, h->highest_trackable_value,
+ h->significant_figures, &(h_tmp));
+
+ if(h->previous_changed != NULL)
+ {
+ hdr_close(h->previous_changed);
+ }
+
+ h->previous_changed = atomic_read(&(h->changing));
+ h_tmp=atomic_set(&(h->changing), h_tmp);
+ hdr_add(h->accumulated, h->previous_changed);
+
+ h_out = (metric->output_window == 0)?h->accumulated:h->previous_changed;
+
+ return h_out;
+}
+
static int output_file_print_hdr_unit(struct metric *metric, char *print_buf, size_t size)
{
int used_len = 0;
@@ -397,28 +418,13 @@ static int output_file_print_hdr_unit(struct metric *metric, char *print_buf, si
int bins_num = metric->histogram.bins_num;
long long value = 0;
int i = 0;
- struct histogram_t *h=&(metric->histogram);
- struct hdr_histogram *h_out=NULL, *h_tmp=NULL;
+ struct hdr_histogram *h_out=NULL;
char int_format[STR_LEN_256], double_format[STR_LEN_256];
snprintf(int_format, sizeof(int_format), "%%%dlld",HISTOGRAM_WIDTH);
snprintf(double_format, sizeof(double_format), "%%%d.2lf",HISTOGRAM_WIDTH);
- hdr_init(h->lowest_trackable_value, h->highest_trackable_value, h->significant_figures, &(h_tmp));
-
- if(h->previous_changed != NULL)
- {
- hdr_close(h->previous_changed);
- }
-
- h->previous_changed=atomic_read(&(h->changing));
- h_tmp=atomic_set(&(h->changing), h_tmp);// left h_tmp is used to avoid warining [-Wunused-value]
-
- hdr_add(h->accumulated, h->previous_changed);
-
- metric->output_window == 0
- ?h_out = h->accumulated
- :h_out = h->previous_changed;
+ h_out = read_hdr_unit_output(metric);
used_len += snprintf(print_buf + used_len, size - used_len, "%-10s\t", metric->field_name);
@@ -443,8 +449,6 @@ static int output_file_print_hdr_unit(struct metric *metric, char *print_buf, si
used_len += snprintf(print_buf + used_len, size - used_len,"\n");
- h_tmp = NULL;
-
return used_len;
}
@@ -592,18 +596,7 @@ int output_file_format_json(struct fieldstat_instance *instance, int n_cur_metri
break;
case FIELD_TYPE_SUMMARY:
case FILED_TYPE_HISTOGRAM:
- struct histogram_t* h=&(metric->histogram);
- struct hdr_histogram* h_out=NULL, *h_tmp=NULL;
- hdr_init(h->lowest_trackable_value, h->highest_trackable_value, h->significant_figures, &(h_tmp));
- if(h->previous_changed!=NULL) hdr_close(h->previous_changed);
-
- h->previous_changed=atomic_read(&(h->changing));
- h_tmp=atomic_set(&(h->changing), h_tmp);// left h_tmp is used to avoid warining [-Wunused-value]
-
- hdr_add(h->accumulated, h->previous_changed);
- metric->output_window == 0
- ?h_out = h->accumulated
- :h_out = h->previous_changed;
+ struct hdr_histogram *h_out = read_hdr_unit_output(metric);
tmp_obj = cJSON_CreateObject();
for(int j = 0; j < metric->histogram.bins_num; j++)
diff --git a/src/line_protocol_output.cpp b/src/line_protocol_output.cpp
index 3b8ef00..bbc6974 100644
--- a/src/line_protocol_output.cpp
+++ b/src/line_protocol_output.cpp
@@ -23,7 +23,7 @@ static void flush_send_buf(struct line_protocol_output *line_protocol_output)
static void send_line_buf(struct line_protocol_output *line_protocol_output, char *line_buf, unsigned int line_buf_len)
{
- if(line_protocol_output == NULL || line_buf == NULL)
+ if(line_protocol_output == NULL || line_buf == NULL || line_buf_len == 0)
{
return;
}
@@ -91,9 +91,18 @@ static long long read_single_metric_value(struct metric *metric, int output_type
(output_type >= 4 && output_type < 8)
?is_refer = 0
:is_refer = 1;
- metric->field_type == FIELD_TYPE_GAUGE
- ?value = get_metric_unit_val(metric, FS_CALC_CURRENT, is_refer)
- :value = get_metric_unit_val(metric, FS_CALC_SPEED, is_refer);
+ switch(metric->field_type)
+ {
+ case FIELD_TYPE_GAUGE:
+ value = get_metric_unit_val(metric, FS_CALC_CURRENT, is_refer);
+ break;
+ case FIELD_TYPE_COUNTER:
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, is_refer);
+ break;
+ default:
+ assert(0);
+ break;
+ }
return value;
}
@@ -123,6 +132,49 @@ static int add_field_set(char *field_key, long long field_value, char *line_buf,
return used_len;
}
+static int add_hdr_field_set(struct metric *metric, struct hdr_histogram *h_out,
+ char *line_buf, int line_buf_size)
+{
+
+ int used_len = 0;
+ long long value = 0;
+ double * bins = metric->histogram.bins;
+ int bins_num = metric->histogram.bins_num;
+
+ for(int i = 0; i < bins_num; i++)
+ {
+ switch(metric->field_type)
+ {
+ case FIELD_TYPE_SUMMARY:
+ value = (long long)hdr_value_at_percentile(h_out, bins[i]*100);
+ used_len += snprintf(line_buf + used_len, line_buf_size - used_len,
+ "P%d=%lld,", (int)(bins[i]*100), value);
+ break;
+ case FILED_TYPE_HISTOGRAM:
+ value = hdr_count_le_value(h_out, (long long)bins[i]);
+ used_len += snprintf(line_buf + used_len, line_buf_size - used_len,
+ "le%d=%lld,", (int)bins[i], value);
+ break;
+ default:
+ assert(0);
+ return 0;
+ }
+ }
+
+ used_len += snprintf(line_buf + used_len, line_buf_size - used_len, "max=%lld,",
+ h_out->total_count==0?0:(long long)hdr_max(h_out));
+ used_len += snprintf(line_buf + used_len, line_buf_size - used_len, "min=%lld,",
+ h_out->total_count==0?0:(long long)hdr_min(h_out));
+ used_len += snprintf(line_buf + used_len, line_buf_size - used_len, "avg=%0.2f,",
+ h_out->total_count==0?0:hdr_mean(h_out));
+ used_len += snprintf(line_buf + used_len, line_buf_size - used_len, "stddev=%0.2f,",
+ h_out->total_count==0?0:hdr_stddev(h_out));
+ used_len += snprintf(line_buf + used_len, line_buf_size - used_len, "cnt=%lld",
+ (long long)h_out->total_count);
+
+ return used_len;
+}
+
static int add_table_row_field_set(char *column_name[], long long *row_value, int n_column, char *line_buf, int line_buf_size)
{
@@ -172,6 +224,60 @@ static int build_single_metric_line_buf(char *instance_name, int output_type, st
return used_len;
}
+static struct hdr_histogram *read_hdr_metric_value(struct metric *metric, int output_type)
+{
+ struct histogram_t *h=&(metric->histogram);
+ struct hdr_histogram *h_out = NULL, *h_tmp = NULL;
+
+ if(output_type >= 4 && output_type < 8)
+ {
+ hdr_init(h->lowest_trackable_value, h->highest_trackable_value,
+ h->significant_figures, &(h_tmp));
+
+ if(h->previous_changed != NULL)
+ {
+ hdr_close(h->previous_changed);
+ }
+ h->previous_changed = atomic_read(&(h->changing));
+ h_tmp = atomic_set(&(h->changing), h_tmp);
+ hdr_add(h->accumulated, h->previous_changed);
+ }
+ h_out = (metric->output_window == 0) ? h->accumulated : h->previous_changed;
+
+ return h_out;
+}
+
+static int build_hdr_metric_line_buf(char *instance_name, int output_type, struct metric *metric,
+ char *line_buf, int line_buf_size)
+{
+ int used_len = 0;
+ struct hdr_histogram *h_out = NULL;
+
+ h_out = read_hdr_metric_value(metric, output_type);
+
+ if(h_out == NULL)
+ {
+ return 0;
+ }
+
+ used_len += add_measurement(metric->field_name, line_buf, line_buf_size);
+
+ used_len += add_default_tag_set(instance_name, NULL, line_buf + used_len,
+ line_buf_size - used_len);
+
+ used_len += add_user_tag_set(metric, line_buf + used_len,
+ line_buf_size - used_len);
+
+ used_len += snprintf(line_buf + used_len, line_buf_size - used_len, " ");
+
+ used_len += add_hdr_field_set(metric, h_out, line_buf + used_len,
+ line_buf_size - used_len);
+
+ used_len += snprintf(line_buf + used_len, line_buf_size - used_len, "\n");
+
+ return used_len;
+}
+
static int read_table_row(struct metric **row_metric, char *column_name[], int output_type, int n_column, char *out_column_name[], long long *out_row_value)
{
@@ -263,7 +369,22 @@ static void output_line_protocol_single_metric(struct fieldstat_instance *instan
}
memset(line_buf, 0, sizeof(line_buf));
- used_len = build_single_metric_line_buf(instance->name, instance->output_type, metric, line_buf, sizeof(line_buf));
+ switch(metric->field_type)
+ {
+ case FIELD_TYPE_GAUGE:
+ case FIELD_TYPE_COUNTER:
+ used_len = build_single_metric_line_buf(instance->name, instance->output_type,
+ metric, line_buf, sizeof(line_buf));
+ break;
+ case FIELD_TYPE_SUMMARY:
+ case FILED_TYPE_HISTOGRAM:
+ used_len = build_hdr_metric_line_buf(instance->name, instance->output_type,
+ metric, line_buf, sizeof(line_buf));
+ break;
+ default:
+ assert(0);
+ break;
+ }
send_line_buf(&instance->line_protocol_output, line_buf, used_len);
}
diff --git a/src/prometheus_output.cpp b/src/prometheus_output.cpp
index a4e4d88..7a25822 100644
--- a/src/prometheus_output.cpp
+++ b/src/prometheus_output.cpp
@@ -206,7 +206,7 @@ static int prometheus_output_histogram_and_summary(struct metric *metric, char *
}
if(metric->field_type == FIELD_TYPE_SUMMARY)
{
- value=(long long)hdr_value_at_percentile(h_out, bins[i]);
+ value=(long long)hdr_value_at_percentile(h_out, bins[i]*100);
}
used_len+=snprintf(payload+used_len,
diff --git a/test/src/gtest_fieldstat_interface.cpp b/test/src/gtest_fieldstat_interface.cpp
index 600314f..48ebb9a 100644
--- a/test/src/gtest_fieldstat_interface.cpp
+++ b/test/src/gtest_fieldstat_interface.cpp
@@ -564,6 +564,58 @@ TEST(FeildStatAPI, SetMetricInvisible)
fieldstat_instance_free(instance);
}
+TEST(FeildStatAPI, RegisterSummary)
+{
+ int ret = 0;
+ struct fieldstat_instance * instance = NULL;
+ const char * quantiles = "0.1,0.5,0.8,0.9,0.95,0.99";
+
+ instance = fieldstat_instance_new("maat");
+
+ ret = fieldstat_register_summary(instance, "latency", NULL, 0, quantiles, 1, 5, 2, 0);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_register_summary(instance, "latency", NULL, 0, quantiles, -1, 5, 2, 0);
+ EXPECT_EQ(-1, ret);
+
+ ret = fieldstat_register_summary(instance, "latency", NULL, 0, quantiles, 2, 3, 2, 0);
+ EXPECT_EQ(-1, ret);
+
+ ret = fieldstat_register_summary(instance, "latency", NULL, 0, quantiles, 1, 5, 10, 0);
+ EXPECT_EQ(-1, ret);
+
+ ret = fieldstat_register_summary(instance, "latency", NULL, 0, quantiles, 1, 5, 2, 2);
+ EXPECT_EQ(-1, ret);
+
+ fieldstat_instance_free(instance);
+}
+
+TEST(FeildStatAPI, RegisterHistogram)
+{
+ int ret = 0;
+ struct fieldstat_instance * instance = NULL;
+ const char * quantiles = "0.1,0.5,0.8,0.9,0.95,0.99";
+
+ instance = fieldstat_instance_new("maat");
+
+ ret = fieldstat_register_histogram(instance, "latency", NULL, 0, quantiles, 1, 5, 2, 0);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_register_histogram(instance, "latency", NULL, 0, quantiles, -1, 5, 2, 0);
+ EXPECT_EQ(-1, ret);
+
+ ret = fieldstat_register_histogram(instance, "latency", NULL, 0, quantiles, 2, 3, 2, 0);
+ EXPECT_EQ(-1, ret);
+
+ ret = fieldstat_register_histogram(instance, "latency", NULL, 0, quantiles, 1, 5, 10, 0);
+ EXPECT_EQ(-1, ret);
+
+ ret = fieldstat_register_histogram(instance, "latency", NULL, 0, quantiles, 1, 5, 2, 2);
+ EXPECT_EQ(-1, ret);
+
+ fieldstat_instance_free(instance);
+}
+
int main(int argc, char *argv[])
{
diff --git a/test/src/gtest_fieldstat_output.cpp b/test/src/gtest_fieldstat_output.cpp
index 634017d..a7e92d0 100644
--- a/test/src/gtest_fieldstat_output.cpp
+++ b/test/src/gtest_fieldstat_output.cpp
@@ -718,6 +718,957 @@ TEST(FeildStatOutput, OutputFileAndPrometheusAndLineProtocol)
}
+TEST(FeildStatOutput, SummaryOutputFile)
+{
+ int metric_id = -1;
+ const char *quantiles = "0.1,0.5,0.8,0.9,0.95,0.99";
+ const char *output_file = "/tmp/fieldstat.txt";
+ const char *compared_data_line = "hit_rate 10 50"
+ " 80 90 95"
+ " 99 100 1"
+ " 50.50 28.87 100\n";
+ FILE *fp;
+ char read_line[2048] = {0};
+ int n_line = 0;
+
+ struct fieldstat_instance *instance = fieldstat_instance_new("maat");
+ fieldstat_set_local_output(instance, "/tmp/fieldstat.txt", "default");
+
+ metric_id = fieldstat_register_summary(instance, "hit_rate", NULL, 0,
+ quantiles, 1, 100, 2, 0);
+ EXPECT_EQ(0, metric_id);
+ fieldstat_instance_start(instance);
+ sleep(1);
+ for(int i = 0; i < 100; i ++)
+ {
+ fieldstat_value_set(instance, metric_id, i + 1);
+ }
+ sleep(2);
+
+ fp = fopen(output_file, "r");
+ EXPECT_NE(nullptr, fp);
+ while(!feof(fp))
+ {
+ if(NULL == fgets(read_line, sizeof(read_line), fp))
+ {
+ continue;
+ }
+ if(n_line == 2)
+ {
+ EXPECT_STREQ(compared_data_line, read_line);
+ }
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(4, n_line);
+ fieldstat_instance_free(instance);
+}
+
+TEST(FeildStatOutput, SummaryOutputLineProtocol)
+{
+ int metric_id = -1;
+ const char * quantiles = "0.1,0.5,0.8,0.9,0.95,0.99";
+
+ const char *telegraf_file = "/tmp/metrics.out";
+ FILE *fp;
+ char read_line[2048] = {0};
+ int n_line = 0;
+ cJSON *cjson_metric = NULL;
+ cJSON *cjson_tags = NULL;
+ char *cjson_metric_str = NULL;
+ const char *compared_data = "{\"fields\":{\"P10\":10,\"P50\":50,"
+ "\"P80\":80,\"P90\":90,\"P95\":95,"
+ "\"P99\":99,\"avg\":50.500000,\"cnt\":100,"
+ "\"max\":100,\"min\":1,\"stddev\":28.870000},"
+ "\"name\":\"hit_rate\",\"tags\":"
+ "{\"app_name\":\"maat\"}}";
+
+ struct fieldstat_instance * instance = NULL;
+
+ instance = fieldstat_instance_new("maat");
+ fieldstat_set_line_protocol_server(instance, "127.0.0.1", 8700);
+
+ metric_id = fieldstat_register_summary(instance, "hit_rate", NULL, 0,
+ quantiles, 1, 100, 2, 0);
+ EXPECT_EQ(0, metric_id);
+ fieldstat_instance_start(instance);
+ system("cat /dev/null > /tmp/metrics.out");
+ sleep(1);
+ for(int i = 0; i < 100; i ++)
+ {
+ fieldstat_value_set(instance, metric_id, i + 1);
+ }
+ sleep(2);
+
+ fp = fopen(telegraf_file, "r");
+ EXPECT_NE(nullptr, fp);
+ while(!feof(fp))
+ {
+ if(NULL == fgets(read_line, sizeof(read_line), fp))
+ {
+ continue;
+ }
+ cjson_metric = cJSON_Parse(read_line);
+ EXPECT_NE(nullptr, cjson_metric);
+ cJSON_DeleteItemFromObject(cjson_metric, "timestamp");
+
+ cjson_tags = cJSON_GetObjectItem(cjson_metric, "tags");
+ EXPECT_NE(nullptr, cjson_tags);
+ cJSON_DeleteItemFromObject(cjson_tags, "host");
+ cjson_metric_str = cJSON_PrintUnformatted(cjson_metric);
+ EXPECT_NE(nullptr, cjson_metric_str);
+ if(cjson_metric_str)
+ {
+ EXPECT_STREQ(compared_data, cjson_metric_str);
+ free(cjson_metric_str);
+ cjson_metric_str = NULL;
+ }
+ cJSON_Delete(cjson_metric);
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(1, n_line);
+
+ fieldstat_instance_free(instance);
+}
+
+TEST(FeildStatOutput, SummaryOutputPrometheus)
+{
+ int metric_id = -1;
+ const char * quantiles = "0.1,0.5,0.8,0.9,0.95,0.99";
+
+
+ const char *prometheus_file = "/tmp/prometheus.txt";
+ FILE *fp;
+ char read_line[2048] = {0};
+ int n_line = 0;
+ const char *compared_p10 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.10\"} 10\n";
+ const char *compared_p50 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.50\"} 50\n";
+ const char *compared_p80 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.80\"} 80\n";
+ const char *compared_p90 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.90\"} 90\n";
+ const char *compared_p95 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.95\"} 95\n";
+ const char *compared_p99 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.99\"} 99\n";
+ const char *compared_cnt = "maat_hit_rate_count{app_name=\"maat\"} 100\n";
+ const char *compared_sum = "maat_hit_rate_sum{app_name=\"maat\"} 5050\n";
+
+ struct fieldstat_instance * instance = NULL;
+
+ instance = fieldstat_instance_new("maat");
+ fieldstat_global_enable_prometheus_endpoint(9023, NULL);
+ fieldstat_enable_prometheus_output(instance);
+ metric_id = fieldstat_register_summary(instance, "hit_rate", NULL, 0,
+ quantiles, 1, 100, 2, 0);
+ EXPECT_EQ(0, metric_id);
+ fieldstat_instance_start(instance);
+ system("cat /dev/null > /tmp/prometheus.txt");
+ for(int i = 0; i < 100; i ++)
+ {
+ fieldstat_value_set(instance, metric_id, i + 1);
+ }
+ system("curl -s http://127.0.0.1:9023/metrics -o /tmp/prometheus.txt");
+
+
+ fp = fopen(prometheus_file, "r");
+ EXPECT_NE(nullptr, fp);
+ while(!feof(fp))
+ {
+ if(NULL == fgets(read_line, sizeof(read_line), fp))
+ {
+ continue;
+ }
+ switch(n_line)
+ {
+ case 0:
+ EXPECT_STREQ(compared_p10, read_line);
+ break;
+ case 1:
+ EXPECT_STREQ(compared_p50, read_line);
+ break;
+ case 2:
+ EXPECT_STREQ(compared_p80, read_line);
+ break;
+ case 3:
+ EXPECT_STREQ(compared_p90, read_line);
+ break;
+ case 4:
+ EXPECT_STREQ(compared_p95, read_line);
+ break;
+ case 5:
+ EXPECT_STREQ(compared_p99, read_line);
+ break;
+ case 6:
+ EXPECT_STREQ(compared_cnt, read_line);
+ break;
+ case 7:
+ EXPECT_STREQ(compared_sum, read_line);
+ break;
+ default:
+ break;
+ }
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(8, n_line);
+ fieldstat_global_disable_prometheus_endpoint();
+ fieldstat_instance_free(instance);
+}
+
+TEST(FeildStatOutput, HistogramOutputFile)
+{
+ int metric_id = -1;
+ const char *upper_inclusive_bounds = "10,50,80,90,95,99";
+ const char *output_file = "/tmp/fieldstat.txt";
+ const char *compared_data_line = "hit_rate 10 50"
+ " 80 90 95"
+ " 99 100 1"
+ " 50.50 28.87 100\n";
+ FILE *fp;
+ char read_line[2048] = {0};
+ int n_line = 0;
+
+ struct fieldstat_instance *instance = fieldstat_instance_new("maat");
+ fieldstat_set_local_output(instance, "/tmp/fieldstat.txt", "default");
+
+ metric_id = fieldstat_register_histogram(instance, "hit_rate", NULL, 0,
+ upper_inclusive_bounds, 1, 100, 2, 0);
+ EXPECT_EQ(0, metric_id);
+ fieldstat_instance_start(instance);
+ sleep(1);
+ for(int i = 0; i < 100; i ++)
+ {
+ fieldstat_value_set(instance, metric_id, i + 1);
+ }
+ sleep(2);
+
+ fp = fopen(output_file, "r");
+ EXPECT_NE(nullptr, fp);
+ while(!feof(fp))
+ {
+ if(NULL == fgets(read_line, sizeof(read_line), fp))
+ {
+ continue;
+ }
+ if(n_line == 2)
+ {
+ EXPECT_STREQ(compared_data_line, read_line);
+ }
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(4, n_line);
+ fieldstat_instance_free(instance);
+}
+
+TEST(FeildStatOutput, HistogramOutputLineProtocol)
+{
+ int metric_id = -1;
+ const char *upper_inclusive_bounds = "10,50,80,90,95,99";
+
+ const char *telegraf_file = "/tmp/metrics.out";
+ FILE *fp;
+ char read_line[2048] = {0};
+ int n_line = 0;
+ cJSON *cjson_metric = NULL;
+ cJSON *cjson_tags = NULL;
+ char *cjson_metric_str = NULL;
+ const char *compared_data = "{\"fields\":{\"avg\":50.500000,\"cnt\":100,"
+ "\"le10\":10,\"le50\":50,\"le80\":80,"
+ "\"le90\":90,\"le95\":95,\"le99\":99,"
+ "\"max\":100,\"min\":1,\"stddev\":28.870000},"
+ "\"name\":\"hit_rate\",\"tags\":"
+ "{\"app_name\":\"maat\"}}";
+
+ struct fieldstat_instance * instance = NULL;
+
+ instance = fieldstat_instance_new("maat");
+ fieldstat_set_line_protocol_server(instance, "127.0.0.1", 8700);
+
+ metric_id = fieldstat_register_histogram(instance, "hit_rate", NULL, 0,
+ upper_inclusive_bounds, 1, 100, 2, 0);
+ EXPECT_EQ(0, metric_id);
+ fieldstat_instance_start(instance);
+ system("cat /dev/null > /tmp/metrics.out");
+ sleep(1);
+ for(int i = 0; i < 100; i ++)
+ {
+ fieldstat_value_set(instance, metric_id, i + 1);
+ }
+ sleep(2);
+
+ fp = fopen(telegraf_file, "r");
+ EXPECT_NE(nullptr, fp);
+ while(!feof(fp))
+ {
+ if(NULL == fgets(read_line, sizeof(read_line), fp))
+ {
+ continue;
+ }
+ cjson_metric = cJSON_Parse(read_line);
+ EXPECT_NE(nullptr, cjson_metric);
+ cJSON_DeleteItemFromObject(cjson_metric, "timestamp");
+
+ cjson_tags = cJSON_GetObjectItem(cjson_metric, "tags");
+ EXPECT_NE(nullptr, cjson_tags);
+ cJSON_DeleteItemFromObject(cjson_tags, "host");
+ cjson_metric_str = cJSON_PrintUnformatted(cjson_metric);
+ EXPECT_NE(nullptr, cjson_metric_str);
+ if(cjson_metric_str)
+ {
+ EXPECT_STREQ(compared_data, cjson_metric_str);
+ free(cjson_metric_str);
+ cjson_metric_str = NULL;
+ }
+ cJSON_Delete(cjson_metric);
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(1, n_line);
+
+ fieldstat_instance_free(instance);
+}
+
+
+TEST(FeildStatOutput, HistogramOutputPrometheus)
+{
+ int metric_id = -1;
+ const char *upper_inclusive_bounds = "10,50,80,90,95,99";
+
+ const char *prometheus_file = "/tmp/prometheus.txt";
+ FILE *fp;
+ char read_line[2048] = {0};
+ int n_line = 0;
+ const char *compared_le10 = "maat_hit_rate_bucket{app_name=\"maat\",le=\"10.00\"} 10\n";
+ const char *compared_le50 = "maat_hit_rate_bucket{app_name=\"maat\",le=\"50.00\"} 50\n";
+ const char *compared_le80 = "maat_hit_rate_bucket{app_name=\"maat\",le=\"80.00\"} 80\n";
+ const char *compared_le90 = "maat_hit_rate_bucket{app_name=\"maat\",le=\"90.00\"} 90\n";
+ const char *compared_le95 = "maat_hit_rate_bucket{app_name=\"maat\",le=\"95.00\"} 95\n";
+ const char *compared_le99 = "maat_hit_rate_bucket{app_name=\"maat\",le=\"99.00\"} 99\n";
+ const char *compared_cnt = "maat_hit_rate_count{app_name=\"maat\"} 100\n";
+ const char *compared_sum = "maat_hit_rate_sum{app_name=\"maat\"} 5050\n";
+
+ struct fieldstat_instance * instance = NULL;
+
+ instance = fieldstat_instance_new("maat");
+ fieldstat_global_enable_prometheus_endpoint(9024, NULL);
+ fieldstat_enable_prometheus_output(instance);
+ metric_id = fieldstat_register_histogram(instance, "hit_rate", NULL, 0,
+ upper_inclusive_bounds, 1, 100, 2, 0);
+ EXPECT_EQ(0, metric_id);
+ fieldstat_instance_start(instance);
+ sleep(1);
+ system("cat /dev/null > /tmp/prometheus.txt");
+ for(int i = 0; i < 100; i ++)
+ {
+ fieldstat_value_set(instance, metric_id, i + 1);
+ }
+ system("curl -s http://127.0.0.1:9024/metrics -o /tmp/prometheus.txt");
+
+
+ fp = fopen(prometheus_file, "r");
+ EXPECT_NE(nullptr, fp);
+ while(!feof(fp))
+ {
+ if(NULL == fgets(read_line, sizeof(read_line), fp))
+ {
+ continue;
+ }
+ switch(n_line)
+ {
+ case 0:
+ EXPECT_STREQ(compared_le10, read_line);
+ break;
+ case 1:
+ EXPECT_STREQ(compared_le50, read_line);
+ break;
+ case 2:
+ EXPECT_STREQ(compared_le80, read_line);
+ break;
+ case 3:
+ EXPECT_STREQ(compared_le90, read_line);
+ break;
+ case 4:
+ EXPECT_STREQ(compared_le95, read_line);
+ break;
+ case 5:
+ EXPECT_STREQ(compared_le99, read_line);
+ break;
+ case 6:
+ EXPECT_STREQ(compared_cnt, read_line);
+ break;
+ case 7:
+ EXPECT_STREQ(compared_sum, read_line);
+ break;
+ default:
+ break;
+ }
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(8, n_line);
+ fieldstat_global_disable_prometheus_endpoint();
+ fieldstat_instance_free(instance);
+}
+
+
+TEST(FeildStatOutput, SummaryOutputFileCurrent)
+{
+ int metric_id = -1;
+ const char *quantiles = "0.1,0.5,0.8,0.9,0.95,0.99";
+ const char *output_file = "/tmp/fieldstat.txt";
+ const char *compared_data_line = "hit_rate 20 100"
+ " 160 180 190"
+ " 198 200 1"
+ " 100.50 57.73 200\n";
+ FILE *fp;
+ char read_line[2048] = {0};
+ int n_line = 0;
+
+ struct fieldstat_instance *instance = fieldstat_instance_new("maat");
+ fieldstat_set_local_output(instance, "/tmp/fieldstat.txt", "default");
+
+ metric_id = fieldstat_register_summary(instance, "hit_rate", NULL, 0,
+ quantiles, 1, 200, 2, 0);
+ EXPECT_EQ(0, metric_id);
+ fieldstat_instance_start(instance);
+ sleep(1);
+ for(int i = 0; i < 100; i ++)
+ {
+ fieldstat_value_set(instance, metric_id, i + 1);
+ }
+ sleep(2);
+ for(int i = 0; i < 100; i++)
+ {
+ fieldstat_value_set(instance, metric_id, i + 101);
+ }
+ sleep(2);
+ fp = fopen(output_file, "r");
+ EXPECT_NE(nullptr, fp);
+ while(!feof(fp))
+ {
+ if(NULL == fgets(read_line, sizeof(read_line), fp))
+ {
+ continue;
+ }
+ if(n_line == 2)
+ {
+ EXPECT_STREQ(compared_data_line, read_line);
+ }
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(4, n_line);
+ fieldstat_instance_free(instance);
+}
+
+TEST(FeildStatOutput, SummaryOutputFileChange)
+{
+ int metric_id = -1;
+ const char *quantiles = "0.1,0.5,0.8,0.9,0.95,0.99";
+ const char *output_file = "/tmp/fieldstat.txt";
+ const char *compared_data_line = "hit_rate 110 150"
+ " 180 190 195"
+ " 199 200 101"
+ " 150.50 28.87 100\n";
+ FILE *fp;
+ char read_line[2048] = {0};
+ int n_line = 0;
+
+ struct fieldstat_instance *instance = fieldstat_instance_new("maat");
+ fieldstat_set_local_output(instance, "/tmp/fieldstat.txt", "default");
+
+ metric_id = fieldstat_register_summary(instance, "hit_rate", NULL, 0,
+ quantiles, 1, 200, 2, 1);
+ EXPECT_EQ(0, metric_id);
+ fieldstat_instance_start(instance);
+ sleep(1);
+ for(int i = 0; i < 100; i ++)
+ {
+ fieldstat_value_set(instance, metric_id, i + 1);
+ }
+ sleep(2);
+ for(int i = 0; i < 100; i++)
+ {
+ fieldstat_value_set(instance, metric_id, i + 101);
+ }
+ sleep(2);
+ fp = fopen(output_file, "r");
+ EXPECT_NE(nullptr, fp);
+ while(!feof(fp))
+ {
+ if(NULL == fgets(read_line, sizeof(read_line), fp))
+ {
+ continue;
+ }
+ if(n_line == 2)
+ {
+ EXPECT_STREQ(compared_data_line, read_line);
+ }
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(4, n_line);
+ fieldstat_instance_free(instance);
+}
+
+TEST(FeildStatOutput, SummaryOutputLineProtocolCurrent)
+{
+ int metric_id = -1;
+ const char * quantiles = "0.1,0.5,0.8,0.9,0.95,0.99";
+
+ const char *telegraf_file = "/tmp/metrics.out";
+ FILE *fp;
+ char read_line[2048] = {0};
+ int n_line = 0;
+ cJSON *cjson_metric = NULL;
+ cJSON *cjson_tags = NULL;
+ char *cjson_metric_str = NULL;
+
+ const char *compared_line0 = "{\"fields\":{\"P10\":10,\"P50\":50,"
+ "\"P80\":80,\"P90\":90,\"P95\":95,"
+ "\"P99\":99,\"avg\":50.500000,"
+ "\"cnt\":100,\"max\":100,\"min\":1,"
+ "\"stddev\":28.870000},\"name\":"
+ "\"hit_rate\",\"tags\":{\"app_name\""
+ ":\"maat\"}}";
+
+ const char *compared_line1 = "{\"fields\":{\"P10\":20,\"P50\":100,"
+ "\"P80\":160,\"P90\":180,\"P95\":190,"
+ "\"P99\":198,\"avg\":100.500000,"
+ "\"cnt\":200,\"max\":200,\"min\":1,"
+ "\"stddev\":57.730000},\"name\":"
+ "\"hit_rate\",\"tags\":{\"app_name\""
+ ":\"maat\"}}";
+
+
+
+ struct fieldstat_instance * instance = NULL;
+
+ instance = fieldstat_instance_new("maat");
+ fieldstat_set_line_protocol_server(instance, "127.0.0.1", 8700);
+
+ metric_id = fieldstat_register_summary(instance, "hit_rate", NULL, 0,
+ quantiles, 1, 100, 2, 0);
+ EXPECT_EQ(0, metric_id);
+ fieldstat_instance_start(instance);
+ system("cat /dev/null > /tmp/metrics.out");
+ sleep(1);
+ for(int i = 0; i < 100; i ++)
+ {
+ fieldstat_value_set(instance, metric_id, i + 1);
+ }
+ sleep(2);
+
+ for(int i = 0; i < 100; i ++)
+ {
+ fieldstat_value_set(instance, metric_id, i + 101);
+ }
+ sleep(2);
+
+ fp = fopen(telegraf_file, "r");
+ EXPECT_NE(nullptr, fp);
+ while(!feof(fp))
+ {
+ if(NULL == fgets(read_line, sizeof(read_line), fp))
+ {
+ continue;
+ }
+ cjson_metric = cJSON_Parse(read_line);
+ EXPECT_NE(nullptr, cjson_metric);
+ cJSON_DeleteItemFromObject(cjson_metric, "timestamp");
+
+ cjson_tags = cJSON_GetObjectItem(cjson_metric, "tags");
+ EXPECT_NE(nullptr, cjson_tags);
+ cJSON_DeleteItemFromObject(cjson_tags, "host");
+ cjson_metric_str = cJSON_PrintUnformatted(cjson_metric);
+ EXPECT_NE(nullptr, cjson_metric_str);
+ if(cjson_metric_str)
+ {
+ if(n_line == 0)
+ {
+ EXPECT_STREQ(compared_line0, cjson_metric_str);
+ }
+ if(n_line == 1)
+ {
+ EXPECT_STREQ(compared_line1, cjson_metric_str);
+ }
+ free(cjson_metric_str);
+ cjson_metric_str = NULL;
+ }
+ cJSON_Delete(cjson_metric);
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(2, n_line);
+
+ fieldstat_instance_free(instance);
+}
+
+TEST(FeildStatOutput, SummaryOutputLineProtocolChange)
+{
+ int metric_id = -1;
+ const char * quantiles = "0.1,0.5,0.8,0.9,0.95,0.99";
+
+ const char *telegraf_file = "/tmp/metrics.out";
+ FILE *fp;
+ char read_line[2048] = {0};
+ int n_line = 0;
+ cJSON *cjson_metric = NULL;
+ cJSON *cjson_tags = NULL;
+ char *cjson_metric_str = NULL;
+
+ const char *compared_line0 = "{\"fields\":{\"P10\":10,\"P50\":50,"
+ "\"P80\":80,\"P90\":90,\"P95\":95,"
+ "\"P99\":99,\"avg\":50.500000,"
+ "\"cnt\":100,\"max\":100,\"min\":1,"
+ "\"stddev\":28.870000},\"name\":"
+ "\"hit_rate\",\"tags\":{\"app_name\""
+ ":\"maat\"}}";
+
+ const char *compared_line1 = "{\"fields\":{\"P10\":110,\"P50\":150,"
+ "\"P80\":180,\"P90\":190,\"P95\":195,"
+ "\"P99\":199,\"avg\":150.500000,"
+ "\"cnt\":100,\"max\":200,\"min\":101,"
+ "\"stddev\":28.870000},\"name\":"
+ "\"hit_rate\",\"tags\":{\"app_name\""
+ ":\"maat\"}}";
+
+
+
+ struct fieldstat_instance * instance = NULL;
+
+ instance = fieldstat_instance_new("maat");
+ fieldstat_set_line_protocol_server(instance, "127.0.0.1", 8700);
+
+ metric_id = fieldstat_register_summary(instance, "hit_rate", NULL, 0,
+ quantiles, 1, 100, 2, 1);
+ EXPECT_EQ(0, metric_id);
+ fieldstat_instance_start(instance);
+ system("cat /dev/null > /tmp/metrics.out");
+ sleep(1);
+ for(int i = 0; i < 100; i ++)
+ {
+ fieldstat_value_set(instance, metric_id, i + 1);
+ }
+ sleep(2);
+
+ for(int i = 0; i < 100; i ++)
+ {
+ fieldstat_value_set(instance, metric_id, i + 101);
+ }
+ sleep(2);
+
+ fp = fopen(telegraf_file, "r");
+ EXPECT_NE(nullptr, fp);
+ while(!feof(fp))
+ {
+ if(NULL == fgets(read_line, sizeof(read_line), fp))
+ {
+ continue;
+ }
+ cjson_metric = cJSON_Parse(read_line);
+ EXPECT_NE(nullptr, cjson_metric);
+ cJSON_DeleteItemFromObject(cjson_metric, "timestamp");
+
+ cjson_tags = cJSON_GetObjectItem(cjson_metric, "tags");
+ EXPECT_NE(nullptr, cjson_tags);
+ cJSON_DeleteItemFromObject(cjson_tags, "host");
+ cjson_metric_str = cJSON_PrintUnformatted(cjson_metric);
+ EXPECT_NE(nullptr, cjson_metric_str);
+ if(cjson_metric_str)
+ {
+ if(n_line == 0)
+ {
+ EXPECT_STREQ(compared_line0, cjson_metric_str);
+ }
+ if(n_line == 1)
+ {
+ EXPECT_STREQ(compared_line1, cjson_metric_str);
+ }
+ free(cjson_metric_str);
+ cjson_metric_str = NULL;
+ }
+ cJSON_Delete(cjson_metric);
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(2, n_line);
+
+ fieldstat_instance_free(instance);
+}
+
+TEST(FeildStatOutput, SummaryOutputPrometheusCurrent)
+{
+ int metric_id = -1;
+ const char * quantiles = "0.1,0.5,0.8,0.9,0.95,0.99";
+
+ const char *prometheus_file = "/tmp/prometheus.txt";
+ FILE *fp;
+ char read_line[2048] = {0};
+ int n_line = 0;
+ const char *compared_p10_0 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.10\"} 10\n";
+ const char *compared_p50_0 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.50\"} 50\n";
+ const char *compared_p80_0 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.80\"} 80\n";
+ const char *compared_p90_0 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.90\"} 90\n";
+ const char *compared_p95_0 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.95\"} 95\n";
+ const char *compared_p99_0 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.99\"} 99\n";
+ const char *compared_cnt_0 = "maat_hit_rate_count{app_name=\"maat\"} 100\n";
+ const char *compared_sum_0 = "maat_hit_rate_sum{app_name=\"maat\"} 5050\n";
+ const char *compared_p10_1 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.10\"} 20\n";
+ const char *compared_p50_1 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.50\"} 100\n";
+ const char *compared_p80_1 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.80\"} 160\n";
+ const char *compared_p90_1 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.90\"} 180\n";
+ const char *compared_p95_1 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.95\"} 190\n";
+ const char *compared_p99_1 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.99\"} 198\n";
+ const char *compared_cnt_1 = "maat_hit_rate_count{app_name=\"maat\"} 200\n";
+ const char *compared_sum_1 = "maat_hit_rate_sum{app_name=\"maat\"} 20100\n";
+
+ struct fieldstat_instance * instance = NULL;
+
+ instance = fieldstat_instance_new("maat");
+ fieldstat_global_enable_prometheus_endpoint(9026, NULL);
+ fieldstat_enable_prometheus_output(instance);
+ metric_id = fieldstat_register_summary(instance, "hit_rate", NULL, 0,
+ quantiles, 1, 100, 2, 0);
+ EXPECT_EQ(0, metric_id);
+ fieldstat_instance_start(instance);
+ system("cat /dev/null > /tmp/prometheus.txt");
+ for(int i = 0; i < 100; i ++)
+ {
+ fieldstat_value_set(instance, metric_id, i + 1);
+ }
+ system("curl -s http://127.0.0.1:9026/metrics -o /tmp/prometheus.txt");
+
+ fp = fopen(prometheus_file, "r");
+ EXPECT_NE(nullptr, fp);
+ while(!feof(fp))
+ {
+ if(NULL == fgets(read_line, sizeof(read_line), fp))
+ {
+ continue;
+ }
+ switch(n_line)
+ {
+ case 0:
+ EXPECT_STREQ(compared_p10_0, read_line);
+ break;
+ case 1:
+ EXPECT_STREQ(compared_p50_0, read_line);
+ break;
+ case 2:
+ EXPECT_STREQ(compared_p80_0, read_line);
+ break;
+ case 3:
+ EXPECT_STREQ(compared_p90_0, read_line);
+ break;
+ case 4:
+ EXPECT_STREQ(compared_p95_0, read_line);
+ break;
+ case 5:
+ EXPECT_STREQ(compared_p99_0, read_line);
+ break;
+ case 6:
+ EXPECT_STREQ(compared_cnt_0, read_line);
+ break;
+ case 7:
+ EXPECT_STREQ(compared_sum_0, read_line);
+ break;
+ default:
+ break;
+ }
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(8, n_line);
+
+ for(int i = 0; i < 100; i ++)
+ {
+ fieldstat_value_set(instance, metric_id, i + 101);
+ }
+ sleep(1);
+ n_line = 0;
+ system("curl -s http://127.0.0.1:9026/metrics -o /tmp/prometheus.txt");
+ fp = fopen(prometheus_file, "r");
+ EXPECT_NE(nullptr, fp);
+ while(!feof(fp))
+ {
+ if(NULL == fgets(read_line, sizeof(read_line), fp))
+ {
+ continue;
+ }
+ switch(n_line)
+ {
+ case 0:
+ EXPECT_STREQ(compared_p10_1, read_line);
+ break;
+ case 1:
+ EXPECT_STREQ(compared_p50_1, read_line);
+ break;
+ case 2:
+ EXPECT_STREQ(compared_p80_1, read_line);
+ break;
+ case 3:
+ EXPECT_STREQ(compared_p90_1, read_line);
+ break;
+ case 4:
+ EXPECT_STREQ(compared_p95_1, read_line);
+ break;
+ case 5:
+ EXPECT_STREQ(compared_p99_1, read_line);
+ break;
+ case 6:
+ EXPECT_STREQ(compared_cnt_1, read_line);
+ break;
+ case 7:
+ EXPECT_STREQ(compared_sum_1, read_line);
+ break;
+ default:
+ break;
+ }
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(8, n_line);
+
+ fieldstat_global_disable_prometheus_endpoint();
+ fieldstat_instance_free(instance);
+}
+
+TEST(FeildStatOutput, SummaryOutputPrometheusChange)
+{
+ int metric_id = -1;
+ const char * quantiles = "0.1,0.5,0.8,0.9,0.95,0.99";
+
+ const char *prometheus_file = "/tmp/prometheus.txt";
+ FILE *fp;
+ char read_line[2048] = {0};
+ int n_line = 0;
+ const char *compared_p10_0 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.10\"} 10\n";
+ const char *compared_p50_0 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.50\"} 50\n";
+ const char *compared_p80_0 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.80\"} 80\n";
+ const char *compared_p90_0 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.90\"} 90\n";
+ const char *compared_p95_0 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.95\"} 95\n";
+ const char *compared_p99_0 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.99\"} 99\n";
+ const char *compared_cnt_0 = "maat_hit_rate_count{app_name=\"maat\"} 100\n";
+ const char *compared_sum_0 = "maat_hit_rate_sum{app_name=\"maat\"} 5050\n";
+ const char *compared_p10_1 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.10\"} 20\n";
+ const char *compared_p50_1 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.50\"} 100\n";
+ const char *compared_p80_1 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.80\"} 160\n";
+ const char *compared_p90_1 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.90\"} 180\n";
+ const char *compared_p95_1 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.95\"} 190\n";
+ const char *compared_p99_1 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.99\"} 198\n";
+ const char *compared_cnt_1 = "maat_hit_rate_count{app_name=\"maat\"} 200\n";
+ const char *compared_sum_1 = "maat_hit_rate_sum{app_name=\"maat\"} 20100\n";
+
+ struct fieldstat_instance * instance = NULL;
+
+ instance = fieldstat_instance_new("maat");
+ fieldstat_global_enable_prometheus_endpoint(9027, NULL);
+ fieldstat_enable_prometheus_output(instance);
+ metric_id = fieldstat_register_summary(instance, "hit_rate", NULL, 0,
+ quantiles, 1, 100, 2, 1);
+ EXPECT_EQ(0, metric_id);
+ fieldstat_instance_start(instance);
+ system("cat /dev/null > /tmp/prometheus.txt");
+ for(int i = 0; i < 100; i ++)
+ {
+ fieldstat_value_set(instance, metric_id, i + 1);
+ }
+ system("curl -s http://127.0.0.1:9027/metrics -o /tmp/prometheus.txt");
+
+ fp = fopen(prometheus_file, "r");
+ EXPECT_NE(nullptr, fp);
+ while(!feof(fp))
+ {
+ if(NULL == fgets(read_line, sizeof(read_line), fp))
+ {
+ continue;
+ }
+ switch(n_line)
+ {
+ case 0:
+ EXPECT_STREQ(compared_p10_0, read_line);
+ break;
+ case 1:
+ EXPECT_STREQ(compared_p50_0, read_line);
+ break;
+ case 2:
+ EXPECT_STREQ(compared_p80_0, read_line);
+ break;
+ case 3:
+ EXPECT_STREQ(compared_p90_0, read_line);
+ break;
+ case 4:
+ EXPECT_STREQ(compared_p95_0, read_line);
+ break;
+ case 5:
+ EXPECT_STREQ(compared_p99_0, read_line);
+ break;
+ case 6:
+ EXPECT_STREQ(compared_cnt_0, read_line);
+ break;
+ case 7:
+ EXPECT_STREQ(compared_sum_0, read_line);
+ break;
+ default:
+ break;
+ }
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(8, n_line);
+
+ for(int i = 0; i < 100; i ++)
+ {
+ fieldstat_value_set(instance, metric_id, i + 101);
+ }
+ sleep(1);
+ n_line = 0;
+ system("curl -s http://127.0.0.1:9027/metrics -o /tmp/prometheus.txt");
+ fp = fopen(prometheus_file, "r");
+ EXPECT_NE(nullptr, fp);
+ while(!feof(fp))
+ {
+ if(NULL == fgets(read_line, sizeof(read_line), fp))
+ {
+ continue;
+ }
+ switch(n_line)
+ {
+ case 0:
+ EXPECT_STREQ(compared_p10_1, read_line);
+ break;
+ case 1:
+ EXPECT_STREQ(compared_p50_1, read_line);
+ break;
+ case 2:
+ EXPECT_STREQ(compared_p80_1, read_line);
+ break;
+ case 3:
+ EXPECT_STREQ(compared_p90_1, read_line);
+ break;
+ case 4:
+ EXPECT_STREQ(compared_p95_1, read_line);
+ break;
+ case 5:
+ EXPECT_STREQ(compared_p99_1, read_line);
+ break;
+ case 6:
+ EXPECT_STREQ(compared_cnt_1, read_line);
+ break;
+ case 7:
+ EXPECT_STREQ(compared_sum_1, read_line);
+ break;
+ default:
+ break;
+ }
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(8, n_line);
+
+ fieldstat_global_disable_prometheus_endpoint();
+ fieldstat_instance_free(instance);
+}
int main(int argc, char *argv[])
{