diff options
| author | fumingwei <[email protected]> | 2023-03-24 14:10:59 +0800 |
|---|---|---|
| committer | fumingwei <[email protected]> | 2023-03-24 14:10:59 +0800 |
| commit | e09e7f397145613f1776622a2219047b9066f3a5 (patch) | |
| tree | 57529534a861fffe98637fcd734b084bda8a7e0b | |
| parent | a52d18031284607d4c75878b14fdb7aff0396665 (diff) | |
feature:summay和histogram注册接口新增output_window参数
| -rw-r--r-- | inc/fieldstat.h | 6 | ||||
| -rw-r--r-- | src/fieldstat.cpp | 16 | ||||
| -rw-r--r-- | src/fieldstat_internal.h | 8 | ||||
| -rw-r--r-- | src/file_output.cpp | 133 | ||||
| -rw-r--r-- | test/fieldstat_test.cpp | 8 | ||||
| -rw-r--r-- | test/src/gtest_dynamic_fieldstat.cpp | 12 | ||||
| -rw-r--r-- | test/src/gtest_fieldstat.cpp | 30 |
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); |
