summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfumingwei <[email protected]>2023-03-24 14:10:59 +0800
committerfumingwei <[email protected]>2023-03-24 14:10:59 +0800
commite09e7f397145613f1776622a2219047b9066f3a5 (patch)
tree57529534a861fffe98637fcd734b084bda8a7e0b
parenta52d18031284607d4c75878b14fdb7aff0396665 (diff)
feature:summay和histogram注册接口新增output_window参数
-rw-r--r--inc/fieldstat.h6
-rw-r--r--src/fieldstat.cpp16
-rw-r--r--src/fieldstat_internal.h8
-rw-r--r--src/file_output.cpp133
-rw-r--r--test/fieldstat_test.cpp8
-rw-r--r--test/src/gtest_dynamic_fieldstat.cpp12
-rw-r--r--test/src/gtest_fieldstat.cpp30
7 files changed, 189 insertions, 24 deletions
diff --git a/inc/fieldstat.h b/inc/fieldstat.h
index 64aff47..4c64ea8 100644
--- a/inc/fieldstat.h
+++ b/inc/fieldstat.h
@@ -170,10 +170,11 @@ void fieldstat_passive_output(struct fieldstat_instance *instance);
* of figures in a decimal number that will be maintained. E.g. a value of 3 will mean
* the results from the histogram will be accurate up to the first three digits. Must
* be a value between 1 and 5 (inclusive).
+ * @param output_window The of output data. 1: output the data in the time interval window, 0: output data all the time.
* @return metric id: -1 is failed, >= 0 is success
*/
int fieldstat_register_histogram(struct fieldstat_instance *instance, const char *field_name, const struct fieldstat_tag tags[], size_t n_tag,
- const char *upper_inclusive_bounds, const long long lowest_trackable_value, long long highest_trackable_value, int significant_figures);
+ const char *upper_inclusive_bounds, const long long lowest_trackable_value, long long highest_trackable_value, int significant_figures, int output_window);
/**
* Register summary metric
@@ -190,10 +191,11 @@ int fieldstat_register_histogram(struct fieldstat_instance *instance, const char
* of figures in a decimal number that will be maintained. E.g. a value of 3 will mean
* the results from the histogram will be accurate up to the first three digits. Must
* be a value between 1 and 5 (inclusive).
+ * @param output_window The of output data. 1: output the data in the time interval window, 0: output data all the time.
* @return metric id: -1 is failed, >= 0 is success
*/
int fieldstat_register_summary(struct fieldstat_instance *instance, const char *field_name, const struct fieldstat_tag tags[], size_t n_tag,
- const char *quantiles, const long long lowest_trackable_value, long long highest_trackable_value, int significant_figures);
+ const char *quantiles, const long long lowest_trackable_value, long long highest_trackable_value, int significant_figures, int output_window);
/**
* Register dynamic fieldstat instance.
diff --git a/src/fieldstat.cpp b/src/fieldstat.cpp
index ddbe054..65a0c15 100644
--- a/src/fieldstat.cpp
+++ b/src/fieldstat.cpp
@@ -941,7 +941,7 @@ error_out:
static int fieldstat_register_histogram_and_summary(struct fieldstat_instance *instance, enum field_type type, const char *field_name, const struct fieldstat_tag tags[], size_t n_tag,
- const char * bins, long long lowest_trackable_value, long long highest_trackable_value, int significant_figures)
+ const char * bins, long long lowest_trackable_value, long long highest_trackable_value, int significant_figures, int output_window)
{
struct metric *metric = NULL;
struct metric **metric_slot = NULL;
@@ -967,9 +967,15 @@ static int fieldstat_register_histogram_and_summary(struct fieldstat_instance *i
return -1;
}
+ if(output_window != 0 && output_window != 1)
+ {
+ return -1;
+ }
+
metric_id = atomic_inc(&instance->metric_cnt) - 1;
metric_slot = read_metric_slot(instance, metric_id);
metric = metric_new(type, field_name, tags, n_tag);
+ metric->output_window = output_window;
metric->histogram.highest_trackable_value = (int64_t)highest_trackable_value;
metric->histogram.lowest_trackable_value = (int64_t)lowest_trackable_value;
@@ -998,16 +1004,16 @@ static int fieldstat_register_histogram_and_summary(struct fieldstat_instance *i
int fieldstat_register_histogram(struct fieldstat_instance *instance, const char *field_name,const struct fieldstat_tag tags[], size_t n_tag,
- const char * bins, long long lowest_trackable_value, long long highest_trackable_value, int significant_figures)
+ const char * bins, long long lowest_trackable_value, long long highest_trackable_value, int significant_figures, int output_window)
{
return fieldstat_register_histogram_and_summary(instance, FILED_TYPE_HISTOGRAM, field_name, tags, n_tag,
- bins, lowest_trackable_value, highest_trackable_value, significant_figures);
+ bins, lowest_trackable_value, highest_trackable_value, significant_figures, output_window);
}
int fieldstat_register_summary(struct fieldstat_instance *instance, const char *field_name, const struct fieldstat_tag tags[], size_t n_tag,
- const char * bins, long long lowest_trackable_value, long long highest_trackable_value, int significant_figures)
+ const char * bins, long long lowest_trackable_value, long long highest_trackable_value, int significant_figures, int output_window)
{
return fieldstat_register_histogram_and_summary(instance, FIELD_TYPE_SUMMARY, field_name, tags, n_tag,
- bins, lowest_trackable_value, highest_trackable_value, significant_figures);
+ bins, lowest_trackable_value, highest_trackable_value, significant_figures, output_window);
}
diff --git a/src/fieldstat_internal.h b/src/fieldstat_internal.h
index 97171e5..2cb888e 100644
--- a/src/fieldstat_internal.h
+++ b/src/fieldstat_internal.h
@@ -136,15 +136,9 @@ struct metric
int not_send_to_server;
int numerator_id;
int denominator_id;
-/*
- int belong_to_table;
- int table_id;
- char *table_column_name;
- char *table_name;
- int table_column_cnt;
-*/
struct table_metric *table;
int table_column_id;
+ int output_window;
union
{
diff --git a/src/file_output.cpp b/src/file_output.cpp
index d66e235..3ffea17 100644
--- a/src/file_output.cpp
+++ b/src/file_output.cpp
@@ -314,7 +314,10 @@ static int output_file_print_hdr_unit(struct metric *metric, char *print_buf, si
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);
- h_out = h->accumulated; //TODO
+
+ metric->output_window == 0
+ ?h_out = h->accumulated
+ :h_out = h->previous_changed;
used_len += snprintf(print_buf + used_len, size - used_len, "%-10s\t", metric->field_name);
@@ -431,6 +434,132 @@ static int output_file_format_default_type_histogram_and_summary(struct fieldsta
}
+int output_file_format_json(struct fieldstat_instance *instance, int n_cur_metric, char **print_buf)
+{
+ int i = 0;
+ long long value = 0;
+ struct metric *metric = NULL;
+ cJSON *root_obj = NULL;
+ cJSON *metrics_array_obj = NULL;
+ cJSON *tmp_obj = NULL;
+ char tmp_output_name[64];
+ const char* extra[]={"MAX", "MIN", "AVG", "STDDEV", "CNT"};
+ long long tmp_histogram_values[sizeof(extra)/sizeof(char*)];
+
+ if(instance == NULL || n_cur_metric <= 0)
+ {
+ return 0;
+ }
+ struct timespec this_output_time;
+
+ clock_gettime(CLOCK_MONOTONIC ,&this_output_time);
+
+
+
+ root_obj = cJSON_CreateObject();
+ cJSON_AddNumberToObject(root_obj, "unix timestamp", this_output_time.tv_sec);
+ cJSON_AddNumberToObject(root_obj, "output interval", (double)instance->output_interval_ms/1000);
+ metrics_array_obj = cJSON_CreateArray();
+
+ for(i = 0; i < n_cur_metric; i++)
+ {
+ metric = get_metric(instance, i);
+ if(metric == NULL)
+ {
+ continue;
+ }
+
+ switch(metric->field_type)
+ {
+ case FIELD_TYPE_COUNTER:
+ case FIELD_TYPE_GAUGE:
+ tmp_obj = cJSON_CreateObject();
+ cJSON_AddStringToObject(tmp_obj, "name", metric->field_name);
+ if(metric->table)
+ {
+ cJSON_AddStringToObject(tmp_obj, "table_name", metric->table->name);
+ cJSON_AddStringToObject(tmp_obj, "column_name", metric->table->column_name[metric->table_column_id]);
+ }
+ metric->field_type == FIELD_TYPE_COUNTER
+ ?cJSON_AddStringToObject(tmp_obj, "type", "gauge")
+ :cJSON_AddStringToObject(tmp_obj, "type", "counter");
+ value = get_metric_unit_val(metric, FS_CALC_CURRENT, 1);
+ cJSON_AddNumberToObject(tmp_obj, "acc", value);
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ cJSON_AddNumberToObject(tmp_obj, "diff", value);
+ cJSON_AddItemToArray(metrics_array_obj, tmp_obj);
+ 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;
+ tmp_obj = cJSON_CreateObject();
+
+ for(int j = 0; j < metric->histogram.bins_num; j++)
+ {
+ if(metric->field_type == FIELD_TYPE_SUMMARY)
+ {
+ value = (long long)hdr_value_at_percentile(h_out, metric->histogram.bins[j]);
+ cJSON_AddStringToObject(tmp_obj, "type", "summary");
+ snprintf(tmp_output_name, sizeof(tmp_output_name), "%s.p%.2f", metric->field_name, metric->histogram.bins[j]);
+ }
+ if(metric->field_type == FILED_TYPE_HISTOGRAM)
+ {
+ value = hdr_count_le_value(h_out, (long long)metric->histogram.bins[j]);
+ cJSON_AddStringToObject(tmp_obj, "type", "histogram");
+ snprintf(tmp_output_name, sizeof(tmp_output_name), "%s.le=%.2f", metric->field_name, metric->histogram.bins[j]);
+ }
+ cJSON_AddStringToObject(tmp_obj, "name", tmp_output_name);
+
+ cJSON_AddNumberToObject(tmp_obj, "acc", value);
+ cJSON_AddNumberToObject(tmp_obj, "diff", value);
+ cJSON_AddItemToArray(metrics_array_obj, tmp_obj);
+ }
+ tmp_histogram_values[0] = h_out->total_count==0?0:(long long)hdr_max(h_out);
+ tmp_histogram_values[1] = h_out->total_count==0?0:(long long)hdr_min(h_out);
+ tmp_histogram_values[2] = h_out->total_count==0?0:hdr_mean(h_out);
+ tmp_histogram_values[3] = h_out->total_count==0?0:hdr_stddev(h_out);
+ tmp_histogram_values[4] = (long long)h_out->total_count;
+ for(unsigned int j = 0; j < sizeof(extra)/sizeof(char*); j++)
+ {
+ tmp_obj = cJSON_CreateObject();
+ snprintf(tmp_output_name, sizeof(tmp_output_name), "%s.%s", metric->field_name, extra[j]);
+ cJSON_AddStringToObject(tmp_obj, "name", tmp_output_name);
+ if(metric->field_type == FIELD_TYPE_SUMMARY)
+ {
+ cJSON_AddStringToObject(tmp_obj, "type", "summary");
+ }
+ if(metric->field_type == FILED_TYPE_HISTOGRAM)
+ {
+ cJSON_AddStringToObject(tmp_obj, "type", "histogram");
+ }
+ cJSON_AddNumberToObject(tmp_obj, "acc", tmp_histogram_values[j]);
+ cJSON_AddNumberToObject(tmp_obj, "diff", tmp_histogram_values[j]);
+ cJSON_AddItemToArray(metrics_array_obj, tmp_obj);
+ }
+ break;
+ }
+
+ }
+ cJSON_AddItemToObject(root_obj, "metrics", metrics_array_obj);
+
+ *print_buf = cJSON_PrintUnformatted(root_obj);
+ cJSON_Delete(root_obj);
+ //cJSON_Delete(metrics_array_obj);
+ return strlen(*print_buf) + 1;
+}
+
+
int fieldstat_output_file(struct fieldstat_instance *instance,long long interval_ms)
{
int used_len = 0;
@@ -482,7 +611,7 @@ int fieldstat_output_file(struct fieldstat_instance *instance,long long interval
if(!strcmp(instance->local_output_format, "json"))
{
- //TODO from json output
+ used_len = output_file_format_json(instance, current_metric_cnt, &print_buf);
}
fseek(instance->local_output_fp, 0, SEEK_SET);
diff --git a/test/fieldstat_test.cpp b/test/fieldstat_test.cpp
index 311f461..003d367 100644
--- a/test/fieldstat_test.cpp
+++ b/test/fieldstat_test.cpp
@@ -98,11 +98,11 @@ static void* dynamic_register(void* arg)
memset(name, 0, sizeof(name));
snprintf(name, sizeof(name), "summary_%d_%d", loops, rand()%10000);
- fieldstat_register_histogram(instance, name, tags, 1, bins_htr, 1, 10000, 2);
+ fieldstat_register_histogram(instance, name, tags, 1, bins_htr, 1, 10000, 2, 0);
memset(name, 0, sizeof(name));
snprintf(name, sizeof(name), "histogram_%d_%d", loops, rand()%10000);
- fieldstat_register_summary(instance, name, tags, 1, bins_sar,1,10000,2);
+ fieldstat_register_summary(instance, name, tags, 1, bins_sar,1,10000,2, 1);
memset(name, 0, sizeof(name));
snprintf(name, sizeof(name), "shp_%d_%d", loops, rand()%10000);
@@ -266,7 +266,7 @@ int test_register_by_fieldstat_type(struct fieldstat_instance *instance)
//Register histogram and summary start
const char * bins_htr = "10,20,30,40,50,60,70,80,90";
- ret = fieldstat_register_histogram(instance, "htr", NULL, 0, bins_htr, 1, 1000, 2);
+ ret = fieldstat_register_histogram(instance, "htr", NULL, 0, bins_htr, 1, 1000, 2, 0);
if(ret == -1)
{
printf("Failed ot register htr, type = histogram\n");
@@ -274,7 +274,7 @@ int test_register_by_fieldstat_type(struct fieldstat_instance *instance)
}
g_histogram_id = ret;
const char * bins_sar = "0.1,0.5,0.8,0.9,0.95,0.99";
- ret = fieldstat_register_summary(instance, "sar", NULL, 0, bins_sar, 1, 1000, 2);
+ ret = fieldstat_register_summary(instance, "sar", NULL, 0, bins_sar, 1, 1000, 2, 0);
if(ret == -1)
{
printf("Failed ot register sar, type = summary\n");
diff --git a/test/src/gtest_dynamic_fieldstat.cpp b/test/src/gtest_dynamic_fieldstat.cpp
index 994df26..6bdf643 100644
--- a/test/src/gtest_dynamic_fieldstat.cpp
+++ b/test/src/gtest_dynamic_fieldstat.cpp
@@ -601,13 +601,15 @@ void parse_telegraf_cjson_output(const char *compare)
//{"fields":{"Active_sessions":10},"name":"Active_sessions","tags":{"app_name":"firewall","host":"developer-testing-41.22"},"timestamp":1679308196}
//{"fields":{"Active_sessions":10},"name":"Active_sessions","tags":{"app_name":"firewall"}}
-
+ if(strlen(line) == 0)
+ {
+ return;
+ }
cJSON *cjson_metric = NULL;
cJSON *cjson_tags = NULL;
-
cjson_metric = cJSON_Parse(line);
EXPECT_NE(nullptr, cjson_metric);
- cJSON_DeleteItemFromObject(cjson_metric ,"timestamp");
+ cJSON_DeleteItemFromObject(cjson_metric, "timestamp");
cjson_tags = cJSON_GetObjectItem(cjson_metric, "tags");
EXPECT_NE(nullptr, cjson_tags);
@@ -1043,6 +1045,10 @@ void parse_telegraf_cjson_output_not_equal(const char *compare)
}
fclose(fp);
+ if(strlen(line) == 0)
+ {
+ return;
+ }
cJSON *cjson_metric = NULL;
cJSON *cjson_tags = NULL;
diff --git a/test/src/gtest_fieldstat.cpp b/test/src/gtest_fieldstat.cpp
index cf99443..da1e8a5 100644
--- a/test/src/gtest_fieldstat.cpp
+++ b/test/src/gtest_fieldstat.cpp
@@ -215,13 +215,41 @@ TEST(FieldStatAPI, FieldStatRegisterTableMetrics)
instance = fieldstat_instance_new("test");
EXPECT_STREQ("test", instance->name);
-
table_id = fieldstat_register_table(instance, sc_table_name, sc_column_name, sc_column_type, sizeof(sc_column_name)/sizeof(sc_column_name[0]));
EXPECT_EQ(0, table_id);
fieldstat_instance_free(instance);
}
+TEST(FeildStatAPI, FieldStatLocalOutputFormatJson)
+{
+ int metric_id = -1;
+ int ret_set_local_output = 0;
+ struct fieldstat_instance * instance = NULL;
+ int ret = 0;
+
+ instance = fieldstat_instance_new("test");
+ EXPECT_STREQ("test", instance->name);
+
+ metric_id = fieldstat_register(instance, FIELD_TYPE_COUNTER, "Traffic_bytes",NULL,0);
+ EXPECT_EQ(0, metric_id);
+
+ ret_set_local_output = fieldstat_set_local_output(instance,"test.json","json");
+ EXPECT_EQ(0, ret_set_local_output);
+ instance->running = 1;
+
+ ret = fieldstat_value_incrby(instance, metric_id, 10);
+ EXPECT_EQ(0, ret);
+ fieldstat_passive_output(instance);
+ sleep(1);
+ ret = fieldstat_value_incrby(instance, metric_id, 10);
+ sleep(1);
+ fieldstat_passive_output(instance);
+ EXPECT_EQ(0, ret);
+ instance->running = 0;
+ fieldstat_instance_free(instance);
+}
+
int main(int argc, char *argv[])
{
testing::InitGoogleTest(&argc, argv);