summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfumingwei <[email protected]>2023-09-07 18:38:18 +0800
committerfumingwei <[email protected]>2023-09-07 18:38:18 +0800
commit6b814df254290b8d24fac50d8040441807c8e80b (patch)
tree28420ceb9ee6d5994f3bd38a2759ac9abf9a7830
parent7509a711cf291cebb9340258f564f0e470ba4640 (diff)
temp commit 8
-rw-r--r--include/fieldstat/fieldstat.h2
-rw-r--r--include/fieldstat/fieldstat_exporter.h2
-rw-r--r--src/exporter/exporter.c7
-rw-r--r--src/exporter/exporter_internal.h2
-rw-r--r--src/exporter/prometheus_exporter.c244
-rw-r--r--src/fieldstat.c20
-rw-r--r--src/metrics/metric.c30
-rw-r--r--src/metrics/metric.h3
-rw-r--r--test/test_exporter_prometheus.cpp294
9 files changed, 447 insertions, 157 deletions
diff --git a/include/fieldstat/fieldstat.h b/include/fieldstat/fieldstat.h
index 6d078c0..9ea2d5f 100644
--- a/include/fieldstat/fieldstat.h
+++ b/include/fieldstat/fieldstat.h
@@ -243,6 +243,8 @@ int fieldstat_get_max_cell_num(const struct fieldstat *instance, int cube_id);
long long fieldstat_counter_get(const struct fieldstat *instance, int cube_id, int metric_id, int cell_id);
double fieldstat_hll_get(const struct fieldstat *instance, int cube_id, int metric_id, int cell_id);
long long fieldstat_hist_value_at_percentile(const struct fieldstat *instance, int cube_id, int metric_id, int cell_id, double percentile);
+long long fieldstat_hist_value_total_count(const struct fieldstat *instance, int cube_id, int metric_id, int cell_id);
+long long fieldstat_hist_value_sum(const struct fieldstat *instance, int cube_id, int metric_id, int cell_id);
long long fieldstat_hist_count_le_value(const struct fieldstat *instance, int cube_id, int metric_id, int cell_id, long long value);
// get the base 64 encoded string of the serialized blob of a cell
diff --git a/include/fieldstat/fieldstat_exporter.h b/include/fieldstat/fieldstat_exporter.h
index 2f2b69c..784e932 100644
--- a/include/fieldstat/fieldstat_exporter.h
+++ b/include/fieldstat/fieldstat_exporter.h
@@ -77,8 +77,6 @@ int fieldstat_exporter_merge_fieldstat(struct fieldstat_exporter *exporter,
int fieldstat_exporter_local_export(struct fieldstat_exporter *exporter,
struct fieldstat *instance);
-int fieldstat_exporter_prometheus_export(struct fieldstat_exporter *exporter,
- struct fieldstat *instance);
/* -------------------------------------------------------------------------- */
/* fieldstat_json_exporter */
/* -------------------------------------------------------------------------- */
diff --git a/src/exporter/exporter.c b/src/exporter/exporter.c
index d1b8398..36d5173 100644
--- a/src/exporter/exporter.c
+++ b/src/exporter/exporter.c
@@ -91,6 +91,8 @@ struct fieldstat_exporter *fieldstat_exporter_new(const char *name,
memcpy((void *)exporter->tags, (const void *)tags, sizeof(struct fieldstat_tag) * n_tags);
exporter->n_tags = n_tags;
+ pthread_spin_init(&(exporter->lock), PTHREAD_PROCESS_SHARED);
+
return exporter;
}
@@ -120,6 +122,8 @@ void fieldstat_exporter_free(struct fieldstat_exporter *exporter)
exporter->n_tags = 0;
}
+ pthread_spin_destroy(&(exporter->lock));
+
free(exporter);
exporter = NULL;
}
@@ -236,8 +240,9 @@ int fieldstat_exporter_merge_fieldstat(struct fieldstat_exporter *exporter,
return -1;
}
}
-
+ pthread_spin_lock(&(exporter->lock));
ret = fieldstat_merge(exporter->accumulated, exporter->changing);
+ pthread_spin_unlock(&(exporter->lock));
if(ret == -1)
{
fieldstat_reset(exporter->changing);
diff --git a/src/exporter/exporter_internal.h b/src/exporter/exporter_internal.h
index eddb81d..e3e06bb 100644
--- a/src/exporter/exporter_internal.h
+++ b/src/exporter/exporter_internal.h
@@ -35,6 +35,8 @@ struct fieldstat_exporter
struct fieldstat *changing;
struct fieldstat *accumulated;
+ pthread_spinlock_t lock;
+
char local_exporter_filename[MAX_PATH_LEN];
int enable_local_exporter;
diff --git a/src/exporter/prometheus_exporter.c b/src/exporter/prometheus_exporter.c
index 28588bf..911844f 100644
--- a/src/exporter/prometheus_exporter.c
+++ b/src/exporter/prometheus_exporter.c
@@ -177,8 +177,8 @@ static char* str_unescape(char* s, char *d, int d_len)
}
-static int build_payload_append_metric_name(char *metric_name, char *exporter_name,
- char *buf, size_t size)
+static int build_metric_name_buf(char *metric_name, char *exporter_name,
+ char *buf, size_t size)
{
char unescape[256] = {0};
int used = 0;
@@ -199,54 +199,44 @@ static int covert_tags_to_string(struct fieldstat_tag *tags, size_t n_tags,
for(int i = 0; i < n_tags; i++)
{
memset(unescape, 0, sizeof(unescape));
-
+ str_unescape((char *)tags[i].key, unescape, sizeof(unescape));
switch(tags[i].type)
{
case TAG_INTEGER:
- used += snprintf(buf + used, size - used, "%s=\"%lld\",",
- tags[i].key, tags[i].value_longlong);
+ used += snprintf(buf + used, size - used, ",%s=\"%lld\"",
+ unescape, tags[i].value_longlong);
break;
case TAG_DOUBLE:
- used += snprintf(buf + used, size - used, "%s=\"%lf\",",
- tags[i].key, tags[i].value_double);
+ used += snprintf(buf + used, size - used, ",%s=\"%lf\"",
+ unescape, tags[i].value_double);
break;
case TAG_CSTRING:
- used += snprintf(buf + used, size - used, "%s=\"%s\",",
- tags[i].key, tags[i].value_str);
+ used += snprintf(buf + used, size - used, ",%s=\"%s\"",
+ unescape, tags[i].value_str);
break;
default:
assert(0);
}
}
- // if(used > 0)
- // {
- // buf[used- 1] = '\0';
- // used --;
- // }
-
return used;
}
-static int build_payload_append_global_tags(struct fieldstat_exporter *exporter,
- char *buf,
- size_t size)
+static int build_global_tags_buf(struct fieldstat_exporter *exporter, char *buf,
+ size_t size)
{
int used = 0;
- used += snprintf(buf, size - used, "app_name=\"%s\",", exporter->name);
- used += covert_tags_to_string(exporter->tags, exporter->n_tags,
- buf + used, size - used);
-
+ used += snprintf(buf, size - used, "app_name=\"%s\"", exporter->name);
+ used += covert_tags_to_string(exporter->tags, exporter->n_tags, buf + used,
+ size - used);
return used;
}
-static int build_payload_append_cube_tags(struct fieldstat *instance,
- int cube_id,
- char *buf,
- size_t size)
+static int build_cube_tags_buf(struct fieldstat *instance, int cube_id,
+ char *buf, size_t size)
{
int used = 0;
struct fieldstat_tag_list *tags_list = NULL;
@@ -258,10 +248,8 @@ static int build_payload_append_cube_tags(struct fieldstat *instance,
}
-static int build_payload_append_cell_tags(struct fieldstat_tag *tags,
- size_t n_tags,
- char *buf,
- size_t size)
+static int build_cell_tags_buf(struct fieldstat_tag *tags, size_t n_tags,
+ char *buf, size_t size)
{
int used = 0;
@@ -271,151 +259,98 @@ static int build_payload_append_cell_tags(struct fieldstat_tag *tags,
}
-static int build_payload_append_metric_value(const struct fieldstat *instance,
- enum metric_type metric_type,
- int cube_id,
- int metric_id,
- int cell_id,
- char *buf,
- size_t size)
-{
- int used = 0;
- long long value = 0;
- const char *quantiles = "0.1,0.5,0.8,0.9,0.95,0.99";
- const double quantiles[] = {0.1,0.5,0.8,0.9,0.95,0.99};
- 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";
-
- switch(metric_type)
- {
- case METRIC_TYPE_COUNTER:
- value = fieldstat_counter_get(instance, cube_id, metric_id, cell_id);
- used += snprintf(buf, size - used, "%lld\n", value);
- break;
- case METRIC_TYPE_HLL:
- break;
- case METRIC_TYPE_HISTOGRAM:
- for(int i = 0; i < sizeof(quantiles)/sizeof(quantiles[0]); i++)
- {
- value =
- fieldstat_hist_value_at_percentile(instance, cube_id, metric_id,
- cube_id, quantiles[i] * 100);
-
- used += snprintf(buf + used, size - used, "%lld\n", value);
- }
- break;
- default:
- assert(0);
- break;
- }
-
- return used;
-}
-
-
-int build_fieldstat_exporter_payload(struct fieldstat_exporter *exporter,
- char **payload,
- int *payload_size,
+int build_fieldstat_exporter_payload(struct fieldstat_exporter *exporter, char **payload_buf, int *payload_size,
int *payload_offset)
{
- int *cube_ids = NULL;
- int n_cube = 0;
+ double quantiles[6] = {0.1, 0.5, 0.8, 0.9, 0.95, 0.99};
- int max_metric_id = 0;
- char *metric_name = NULL;
- enum metric_type metric_type;
+ pthread_spin_lock(&(exporter->lock));
struct fieldstat *instance = exporter->accumulated;
- char *new_payload = *payload;
- int new_payload_size = *payload_size;
- int new_payload_offset = *payload_offset;
+ char *buf = *payload_buf;
+ int size = *payload_size;
+ int offset = *payload_offset;
- char global_buf[512] = {0};
- int global_buf_offset = 0;
+ int *cube_ids = NULL;
+ int n_cube_ids = 0;
- global_buf_offset += build_payload_append_global_tags(exporter, global_buf,
- sizeof(global_buf));
-
- fieldstat_get_cubes(instance, &cube_ids, &n_cube);
-
- if(n_cube == 0)
+ fieldstat_get_cubes(instance, &cube_ids, &n_cube_ids);
+ if(n_cube_ids == 0)
{
return -1;
}
-
- for(int i = 0; i < n_cube; i++)
+ //part of one metric
+ char global_buf[512] = {0};
+ build_global_tags_buf(exporter, global_buf, sizeof(global_buf));
+
+ for(int i = 0; i < n_cube_ids; i++)
{
- max_metric_id = fieldstat_get_max_metric_id(instance, cube_ids[i]);
+ int max_metric_id = fieldstat_get_max_metric_id(instance, cube_ids[i]);
+ //part of one metric
+ char cube_buf[512] = {0};
+ build_cube_tags_buf(instance, cube_ids[i], cube_buf, sizeof(cube_buf));
for(int j = 0; j <= max_metric_id; j++)
{
int *cell_ids = NULL;
size_t n_cell = 0;
+
+ char name_buf[256] = {0};
+ char cell_buf[512] = {0};
+
struct fieldstat_tag_list *tags_list = NULL;
+ enum metric_type metric_type = fieldstat_get_metric_type(instance, cube_ids[i], j);
- fieldstat_get_cells(instance, cube_ids[i], j, &cell_ids, &tags_list,
- &n_cell);
+ char *metric_name = (char *)fieldstat_get_metric_name(instance, cube_ids[i], j);
+ //part of one metric
+ build_metric_name_buf(metric_name, exporter->name, name_buf, sizeof(name_buf));
+ fieldstat_get_cells(instance, cube_ids[i], j, &cell_ids, &tags_list, &n_cell);
+ //part of one metric
+ build_cell_tags_buf(tags_list->tag, tags_list->n_tag, cell_buf, sizeof(cell_buf));
+
for(int k = 0; k < n_cell; k++)
{
- payload_realloc(&new_payload, &new_payload_size, new_payload_offset);
-
- metric_name = (char *)fieldstat_get_metric_name(instance, cube_ids[i], j);
- metric_type = fieldstat_get_metric_type(instance, cube_ids[i], j);
+ long long value = 0;
+ double hll_value = 0.0;
+ payload_realloc(&buf, &size, offset);
- new_payload_offset += build_payload_append_metric_name(
- metric_name,
- exporter->name,
- new_payload + new_payload_offset,
- new_payload_size - new_payload_offset);
-
- new_payload_offset += snprintf(
- new_payload + new_payload_offset,
- new_payload_size - new_payload_offset,
- "{");
-
- new_payload_offset += build_payload_append_global_tags(
- exporter,
- new_payload + new_payload_offset,
- new_payload_size - new_payload_offset);
-
- new_payload_offset += snprintf(new_payload + new_payload_offset,new_payload_size - new_payload_offset, "%s",
-
-
- new_payload_offset += build_payload_append_cube_tags(
- instance,
- cube_ids[i],
- new_payload + new_payload_offset,
- new_payload_size - new_payload_offset);
-
- new_payload_offset += build_payload_append_cell_tags(
- tags_list->tag,
- tags_list->n_tag,
- new_payload + new_payload_offset,
- new_payload_size - new_payload_offset);
-
- if(new_payload[new_payload_offset - 1] == ',')
+ switch(metric_type)
{
- new_payload_offset--;
+ case METRIC_TYPE_COUNTER:
+ value = fieldstat_counter_get(instance, i, j, k);
+ offset += snprintf(buf + offset, size - offset, "%s{%s%s%s} %lld\n",
+ name_buf, global_buf, cube_buf, cell_buf, value);
+ break;
+
+ case METRIC_TYPE_HLL:
+ hll_value = fieldstat_hll_get(instance, i, j, k);
+ offset += snprintf(buf + offset, size - offset, "%s_total_count{%s%s%s} %.0f\n",
+ name_buf, global_buf, cube_buf, cell_buf, hll_value);
+ break;
+
+ case METRIC_TYPE_HISTOGRAM:
+
+ for(int m = 0; m < sizeof(quantiles)/sizeof(quantiles[0]); m++)
+ {
+ value = fieldstat_hist_value_at_percentile(instance, i, j, k, quantiles[m] * 100);
+ offset += snprintf(buf + offset, size - offset,
+ "%s{%s%s%s,quantile=\"%0.2f\"} %lld\n",
+ name_buf, global_buf, cube_buf, cell_buf, quantiles[m], value);
+ }
+
+ value = fieldstat_hist_value_total_count(instance, i, j, k);
+ offset += snprintf(buf + offset, size - offset, "%s_count{%s%s%s} %lld\n",
+ name_buf, global_buf, cube_buf, cell_buf, value);
+
+ value = fieldstat_hist_value_sum(instance, i, j, k);
+ offset += snprintf(buf + offset, size - offset, "%s_sum{%s%s%s} %lld\n",
+ name_buf, global_buf, cube_buf, cell_buf, value);
+ break;
+ default:
+ assert(0);
+ break;
}
-
- new_payload_offset += snprintf(
- new_payload + new_payload_offset,
- new_payload_size - new_payload_offset,
- "} ");
-
- new_payload_offset += build_payload_append_metric_value(
- instance,
- metric_type,
- i, j, k,
- new_payload + new_payload_offset,
- new_payload_size - new_payload_offset);
}
if(cell_ids)
@@ -433,10 +368,11 @@ int build_fieldstat_exporter_payload(struct fieldstat_exporter *exporter,
free(cube_ids);
cube_ids = NULL;
}
+ pthread_spin_unlock(&(exporter->lock));
- *payload = new_payload;
- *payload_size = new_payload_size;
- *payload_offset = new_payload_offset;
+ *payload_buf = buf;
+ *payload_size = size;
+ *payload_offset = offset;
return 0;
}
diff --git a/src/fieldstat.c b/src/fieldstat.c
index 19846d5..12ab2ed 100644
--- a/src/fieldstat.c
+++ b/src/fieldstat.c
@@ -1029,6 +1029,26 @@ long long fieldstat_hist_value_at_percentile(const struct fieldstat *instance, i
return metric_histogram_value_at_percentile(metric, cell_id, percentile);
}
+long long fieldstat_hist_value_total_count(const struct fieldstat *instance, int cube_id, int metric_id, int cell_id)
+{
+ const struct metric *metric = fieldstat_find_metric(instance, cube_id, metric_id);
+ if (metric == NULL || metric_get_type(metric) != METRIC_TYPE_HISTOGRAM) {
+ return -1;
+ }
+
+ return metric_histogram_value_total_count(metric, cell_id);
+}
+
+long long fieldstat_hist_value_sum(const struct fieldstat *instance, int cube_id, int metric_id, int cell_id)
+{
+ const struct metric *metric = fieldstat_find_metric(instance, cube_id, metric_id);
+ if (metric == NULL || metric_get_type(metric) != METRIC_TYPE_HISTOGRAM) {
+ return -1;
+ }
+
+ return metric_histogram_value_sum(metric, cell_id);
+}
+
long long fieldstat_hist_count_le_value(const struct fieldstat *instance, int cube_id, int metric_id, int cell_id, long long value)
{
const struct metric *metric = fieldstat_find_metric(instance, cube_id, metric_id);
diff --git a/src/metrics/metric.c b/src/metrics/metric.c
index 0b6c025..335ee2b 100644
--- a/src/metrics/metric.c
+++ b/src/metrics/metric.c
@@ -815,6 +815,36 @@ long long metric_histogram_value_at_percentile(const struct metric *pthis, int c
return hdr_value_at_percentile(data->hdr, percentile);
}
+
+long long metric_histogram_value_total_count(const struct metric *pthis, int cell_id)
+{
+ const struct metric_measure_data *data = metric_find_one_cell(pthis, cell_id);
+ if (data == NULL) {
+ return -1;
+ }
+ return (long long)data->hdr->total_count;
+}
+
+long long metric_histogram_value_sum(const struct metric *pthis, int cell_id)
+{
+ const struct metric_measure_data *data = metric_find_one_cell(pthis, cell_id);
+ if (data == NULL) {
+ return -1;
+ }
+
+ struct hdr_iter iter;
+ long long sum = 0;
+
+ hdr_iter_recorded_init(&iter, data->hdr);
+ while (hdr_iter_next(&iter))
+ {
+ sum+=(long long)iter.value;
+ }
+ return sum;
+}
+
+
+
static long long hdr_count_le_value(const struct hdr_histogram* h, long long value)
{
struct hdr_iter iter;
diff --git a/src/metrics/metric.h b/src/metrics/metric.h
index 6122746..17da701 100644
--- a/src/metrics/metric.h
+++ b/src/metrics/metric.h
@@ -33,6 +33,9 @@ struct metric *metric_histogram_new(const char *name, long long lowest_trackable
int metric_histogram_record(struct metric *pthis, int cell_id, long long value);
// for the meaning of these two query method, refer to https://prometheus.io/docs/concepts/metric_types/, and search for "histogram" and "summary"
long long metric_histogram_value_at_percentile(const struct metric *pthis, int cell_id, double percentile);
+long long metric_histogram_value_total_count(const struct metric *pthis, int cell_id);
+long long metric_histogram_value_sum(const struct metric *pthis, int cell_id);
+
long long metric_histogram_count_le_value(const struct metric *pthis, int cell_id, long long value);
diff --git a/test/test_exporter_prometheus.cpp b/test/test_exporter_prometheus.cpp
index c19466d..656a1f3 100644
--- a/test/test_exporter_prometheus.cpp
+++ b/test/test_exporter_prometheus.cpp
@@ -548,6 +548,300 @@ TEST(ExporterPrometheus, AllTags)
}
+/*******************************************************************************
+ * case: MetricTypeCounter
+*******************************************************************************/
+static struct fieldstat *test_new_exporter_MetricTypeCounter()
+{
+ struct fieldstat *instance = fieldstat_new();
+ EXPECT_NE(nullptr, instance);
+
+ int cube_id = fieldstat_register_cube(instance, NULL, 0,
+ SAMPLING_MODE_COMPREHENSIVE, 3);
+ EXPECT_EQ(0, cube_id);
+
+ int counter_id = fieldstat_register_counter(instance, cube_id, "Traffic_bytes",
+ COUNTER_MERGE_BY_SUM);
+
+ int cell_id = fieldstat_cube_add(instance, cube_id, NULL, 0, 1);
+ EXPECT_EQ(0, cell_id);
+
+ if(cell_id >= 0)
+ {
+ fieldstat_counter_incrby(instance, cube_id, counter_id, cell_id, 1);
+ }
+
+ return instance;
+}
+
+static void test_analyze_MetricTypeCounter()
+{
+ int n_line = 0;
+ char buffer[512];
+ const char *desired = "firewall_Traffic_bytes{app_name=\"firewall\"} 1\n";
+
+ FILE *fp = fopen("/tmp/prometheus.txt", "r");
+ EXPECT_NE(nullptr, fp);
+
+ while(fgets(buffer, sizeof(buffer), fp) != NULL)
+ {
+ n_line++;
+ }
+ fclose(fp);
+
+ EXPECT_EQ(1, n_line);
+ EXPECT_STREQ(desired, buffer);
+
+ return;
+}
+
+
+TEST(ExporterPrometheus, MetricTypeCounter)
+{
+ int ret = 0;
+ unsigned short port = 40009;
+ struct fieldstat_exporter *exporter = NULL;
+ struct fieldstat *instance = NULL;
+ // input start
+ const char *exporter_name = "firewall";
+
+ exporter = fieldstat_exporter_new(exporter_name, NULL, 0);
+ EXPECT_NE(nullptr, exporter);
+
+ ret = fieldstat_exporter_enable_prometheus_exporter(exporter);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_exporter_global_enable_prometheus_endpoint(port, "/metrics");
+ EXPECT_EQ(0, ret);
+
+ fieldstat_exporter_start(exporter);
+
+ instance = test_new_exporter_MetricTypeCounter();
+
+ ret = fieldstat_exporter_merge_fieldstat(exporter, &instance, 1);
+ EXPECT_EQ(0, ret);
+
+ //test function start
+ sleep(1);
+ test_pull_metrics_request(port, "/metrics");
+ test_analyze_MetricTypeCounter();
+ sleep(1);
+ //test function end
+
+ fieldstat_exporter_free(exporter);
+ fieldstat_free(instance);
+ fieldstat_exporter_global_disable_prometheus_endpoint();
+}
+
+/*******************************************************************************
+ * case: MetricTypeHistogram
+*******************************************************************************/
+
+//maat_hit_rate{app_name=\"maat\",quantile=\"0.10\"} 20\n
+static struct fieldstat *test_new_exporter_MetricTypeHistogram()
+{
+ struct fieldstat *instance = fieldstat_new();
+ EXPECT_NE(nullptr, instance);
+
+ int cube_id = fieldstat_register_cube(instance, NULL, 0,
+ SAMPLING_MODE_COMPREHENSIVE, 3);
+ EXPECT_EQ(0, cube_id);
+
+ int metric_id = fieldstat_register_hist(instance, cube_id, "hit_rate", 1, 100, 3);
+ EXPECT_EQ(metric_id, 0);
+
+ int cell_id = fieldstat_cube_add(instance, cube_id, NULL, 0, 1);
+ EXPECT_EQ(0, cell_id);
+
+ for(int i = 0; i < 100; i++)
+ {
+ fieldstat_hist_record(instance, cube_id, metric_id, cell_id, i + 1);
+ }
+
+ return instance;
+}
+
+static void test_analyze_MetricTypeHistogram()
+{
+ int n_line = 0;
+ char buffer[512];
+
+ const char *desired_p10 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.10\"} 10\n";
+ const char *desired_p50 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.50\"} 50\n";
+ const char *desired_p80 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.80\"} 80\n";
+ const char *desired_p90 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.90\"} 90\n";
+ const char *desired_p95 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.95\"} 95\n";
+ const char *desired_p99 = "maat_hit_rate{app_name=\"maat\",quantile=\"0.99\"} 99\n";
+ const char *desired_cnt = "maat_hit_rate_count{app_name=\"maat\"} 100\n";
+ const char *desired_sum = "maat_hit_rate_sum{app_name=\"maat\"} 5050\n";
+
+ FILE *fp = fopen("/tmp/prometheus.txt", "r");
+ EXPECT_NE(nullptr, fp);
+
+ while(fgets(buffer, sizeof(buffer), fp) != NULL)
+ {
+ switch(n_line)
+ {
+ case 0:
+ EXPECT_STREQ(desired_p10, buffer);
+ break;
+ case 1:
+ EXPECT_STREQ(desired_p50, buffer);
+ break;
+ case 2:
+ EXPECT_STREQ(desired_p80, buffer);
+ break;
+ case 3:
+ EXPECT_STREQ(desired_p90, buffer);
+ break;
+ case 4:
+ EXPECT_STREQ(desired_p95, buffer);
+ break;
+ case 5:
+ EXPECT_STREQ(desired_p99, buffer);
+ break;
+ case 6:
+ EXPECT_STREQ(desired_cnt, buffer);
+ break;
+ case 7:
+ EXPECT_STREQ(desired_sum, buffer);
+ break;
+ default:
+ break;
+ }
+ n_line++;
+ }
+ fclose(fp);
+
+ EXPECT_EQ(8, n_line);
+
+ return;
+}
+
+
+TEST(ExporterPrometheus, MetricTypeHistogram)
+{
+ int ret = 0;
+ unsigned short port = 40010;
+ struct fieldstat_exporter *exporter = NULL;
+ struct fieldstat *instance = NULL;
+ // input start
+ const char *exporter_name = "maat";
+
+ exporter = fieldstat_exporter_new(exporter_name, NULL, 0);
+ EXPECT_NE(nullptr, exporter);
+
+ ret = fieldstat_exporter_enable_prometheus_exporter(exporter);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_exporter_global_enable_prometheus_endpoint(port, "/metrics");
+ EXPECT_EQ(0, ret);
+
+ fieldstat_exporter_start(exporter);
+
+ instance = test_new_exporter_MetricTypeHistogram();
+
+ ret = fieldstat_exporter_merge_fieldstat(exporter, &instance, 1);
+ EXPECT_EQ(0, ret);
+
+ //test function start
+ sleep(1);
+ test_pull_metrics_request(port, "/metrics");
+ test_analyze_MetricTypeHistogram();
+ sleep(1);
+ //test function end
+
+ fieldstat_exporter_free(exporter);
+ fieldstat_free(instance);
+ fieldstat_exporter_global_disable_prometheus_endpoint();
+}
+
+/*******************************************************************************
+ * case: MetricTypeHyperloglog
+*******************************************************************************/
+
+static struct fieldstat *test_new_exporter_MetricTypeHyperloglog()
+{
+ struct fieldstat *instance = fieldstat_new();
+ EXPECT_NE(nullptr, instance);
+
+ int cube_id = fieldstat_register_cube(instance, NULL, 0,
+ SAMPLING_MODE_COMPREHENSIVE, 3);
+ EXPECT_EQ(0, cube_id);
+
+ int metric_id = fieldstat_register_hll(instance, cube_id, "hit_policy", 10);
+ EXPECT_EQ(metric_id, 0);
+
+ int cell_id = fieldstat_cube_add(instance, cube_id, NULL, 0, 1);
+ EXPECT_EQ(0, cell_id);
+
+ fieldstat_hll_add(instance, cube_id, metric_id, cell_id, "192.168.1.1", 11);
+ fieldstat_hll_add(instance, cube_id, metric_id, cell_id, "192.168.1.2", 11);
+ fieldstat_hll_add(instance, cube_id, metric_id, cell_id, "192.168.1.3", 11);
+ fieldstat_hll_add(instance, cube_id, metric_id, cell_id, "192.168.1.4", 11);
+ fieldstat_hll_add(instance, cube_id, metric_id, cell_id, "192.168.1.5", 11);
+
+ return instance;
+}
+
+static void test_analyze_MetricTypeHyperloglog()
+{
+ int n_line = 0;
+ char buffer[512];
+ const char *desired = "firewall_hit_policy_total_count{app_name=\"firewall\"} 5\n";
+ FILE *fp = fopen("/tmp/prometheus.txt", "r");
+ EXPECT_NE(nullptr, fp);
+
+ while(fgets(buffer, sizeof(buffer), fp) != NULL)
+ {
+ n_line++;
+ }
+ fclose(fp);
+
+ EXPECT_EQ(1, n_line);
+ EXPECT_STREQ(desired, buffer);
+ return;
+}
+
+
+TEST(ExporterPrometheus, MetricTypeHyperloglog)
+{
+ int ret = 0;
+ unsigned short port = 40011;
+ struct fieldstat_exporter *exporter = NULL;
+ struct fieldstat *instance = NULL;
+ // input start
+ const char *exporter_name = "firewall";
+
+ exporter = fieldstat_exporter_new(exporter_name, NULL, 0);
+ EXPECT_NE(nullptr, exporter);
+
+ ret = fieldstat_exporter_enable_prometheus_exporter(exporter);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_exporter_global_enable_prometheus_endpoint(port, "/metrics");
+ EXPECT_EQ(0, ret);
+
+ fieldstat_exporter_start(exporter);
+
+ instance = test_new_exporter_MetricTypeHyperloglog();
+
+ ret = fieldstat_exporter_merge_fieldstat(exporter, &instance, 1);
+ EXPECT_EQ(0, ret);
+
+ //test function start
+ sleep(1);
+ test_pull_metrics_request(port, "/metrics");
+ test_analyze_MetricTypeHyperloglog();
+ sleep(1);
+ //test function end
+
+ fieldstat_exporter_free(exporter);
+ fieldstat_free(instance);
+ fieldstat_exporter_global_disable_prometheus_endpoint();
+}
+
+
int main(int argc, char *argv[])
{
testing::InitGoogleTest(&argc, argv);