diff options
| author | fumingwei <[email protected]> | 2023-03-17 23:53:11 +0800 |
|---|---|---|
| committer | fumingwei <[email protected]> | 2023-03-22 20:15:51 +0800 |
| commit | 1b3d40eaa3db4867d71b0908f6121f1f21b8b448 (patch) | |
| tree | 99f4831310ffc66d373151a4ef6cbc7ef8825e3e | |
| parent | ea4c2b9c11ef8a02f745b514f4a54f07512a7e8b (diff) | |
feature:1.新增dynamic metric接口测试用例. 2.新增instance free接口.
| -rw-r--r-- | inc/fieldstat.h | 110 | ||||
| -rw-r--r-- | src/fieldstat.cpp | 213 | ||||
| -rw-r--r-- | src/fieldstat_dynamic.cpp | 168 | ||||
| -rw-r--r-- | src/fieldstat_internal.h | 80 | ||||
| -rw-r--r-- | src/file_output.cpp | 20 | ||||
| -rw-r--r-- | src/line_protocol_output.cpp | 21 | ||||
| -rw-r--r-- | src/prometheus_output.cpp | 64 | ||||
| -rw-r--r-- | test/src/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | test/src/gtest_dynamic_fieldstat.cpp | 2263 | ||||
| -rw-r--r-- | test/src/gtest_fieldstat.cpp | 46 |
10 files changed, 2873 insertions, 115 deletions
diff --git a/inc/fieldstat.h b/inc/fieldstat.h index 4c0f7f7..64aff47 100644 --- a/inc/fieldstat.h +++ b/inc/fieldstat.h @@ -214,53 +214,125 @@ struct fieldstat_dynamic_instance * fieldstat_dynamic_instance_new(const char *n */ int fieldstat_dynamic_set_line_protocol_server(struct fieldstat_dynamic_instance *instance, const char *ip, unsigned short port); /** - * Disable the background thread. + * Disable the dynamic metric output background thread. * The operation should be executed in single-threaded fashion. * @param instance The fieldstat instance. * @return -1 is failed. 0 is success. */ int fieldstat_dynamic_disable_background_thread(struct fieldstat_dynamic_instance *instance); /** - * Set the output interval in milliseconds + * Set the dynamic metric output interval in milliseconds * The operation should be executed in single-threaded fashion. * @param seconds In milliseconds. * @return -1 is failed. 0 is success. */ int fieldstat_dynamic_set_output_interval(struct fieldstat_dynamic_instance *instance, int milliseconds); /** - * Passive output + * Dynamic metrics passive output * @param instance The fieldstat instance. */ void fieldstat_dynamic_passive_output(struct fieldstat_dynamic_instance *instance); /** - * Make the fieldstat instance affect. + * Make the fieldstat dynamic instance affect. * @param instance The fieldstat instance. */ void fieldstat_dynamic_instance_start(struct fieldstat_dynamic_instance *instance); /** - * Set the output interval in milliseconds - * The operation should be executed in single-threaded fashion. - * @param seconds In milliseconds. - * @return -1 is failed. 0 is success. + * Register table. Max table num is 64. Max table columns is 64. + * @param instance The fieldstat dynamic instance. + * @param table_name The table name. + * @param column_name column name array. + * @param column_type column type array. Type in [counter, gauge] + * @param n_column size of column_type[] and column_name[] + * @param out_column_ids output metric id in table row. + * @return table id. -1 is failed. >=0 is success. */ - int fieldstat_register_dynamic_table(struct fieldstat_dynamic_instance *instance, const char *table_name, const char *column_name[], enum field_type column_type[], size_t n_column, unsigned int out_column_ids[]); - +/** + * fieldstat dynamic instance metric value increment operate. metirc type in[gauge, counter] + * @param instance The fieldstat dynamic instance. + * @param type The metric type. + * @param field_name The metric field name. + * @param value The increment value. + * @param tags The tag array. + * @param n_tag Size of tags[] + * @param thread_id The thread id of the call. + * @return -1 is failed. 0 is success. + */ int fieldstat_dynamic_metric_value_incrby(struct fieldstat_dynamic_instance *instance, enum field_type type, const char *field_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id); - +/** + * fieldstat dynamic instance metric value set operate. metirc type in[gauge, counter] + * @param instance The fieldstat dynamic instance. + * @param type The metric type. + * @param field_name The metric field name. + * @param value The set value. + * @param tags The tag array. + * @param n_tag Size of tags[] + * @param thread_id The thread id of the call. + * @return -1 is failed. 0 is success. + */ int fieldstat_dynamic_metric_value_set(struct fieldstat_dynamic_instance *instance, enum field_type type, const char *field_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id); - +/** + * fieldstat dynamic instance metric value decrment operate. metirc type in[gauge, counter] + * @param instance The fieldstat dynamic instance. + * @param type The metric type. + * @param field_name The metric field name. + * @param value The decrment value. + * @param tags The tag array. + * @param n_tag Size of tags[] + * @param thread_id The thread id of the call. + * @return -1 is failed. 0 is success. + */ int fieldstat_dynamic_metric_value_decrby(struct fieldstat_dynamic_instance *instance, enum field_type type, const char *field_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id); - - +/** + * fieldstat dynamic instance table metric value incrment operate. + * @param instance The fieldstat dynamic instance. + * @param table_id The table id. + * @param column_id The column id. + * @param row_name The row name of table. + * @param value The incrment value. + * @param tags The tag array. + * @param n_tag Size of tags[] + * @param thread_id The thread id of the call. + * @return -1 is failed. 0 is success. + */ int fieldstat_dynamic_table_metric_value_incrby(struct fieldstat_dynamic_instance *instance, int table_id, unsigned int column_id, const char *row_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id); - +/** + * fieldstat dynamic instance table metric value set operate. + * @param instance The fieldstat dynamic instance. + * @param table_id The table id. + * @param column_id The column id. + * @param row_name The row name of table. + * @param value The set value. + * @param tags The tag array. + * @param n_tag Size of tags[] + * @param thread_id The thread id of the call. + * @return -1 is failed. 0 is success. + */ int fieldstat_dynamic_table_metric_value_set(struct fieldstat_dynamic_instance *instance, int table_id, unsigned int column_id, const char *row_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id); - +/** + * fieldstat dynamic instance table metric value decrment operate. + * @param instance The fieldstat dynamic instance. + * @param table_id The table id. + * @param column_id The column id. + * @param row_name The row name of table. + * @param value The decrment value. + * @param tags The tag array. + * @param n_tag Size of tags[] + * @param thread_id The thread id of the call. + * @return -1 is failed. 0 is success. + */ int fieldstat_dynamic_table_metric_value_decrby(struct fieldstat_dynamic_instance *instance, int table_id, unsigned int column_id, const char *row_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id); - - - +/** + * fieldstat instance free. + * @param instance The fieldstat instance need to free. + */ +void fieldstat_instance_free(struct fieldstat_instance *instance); +/** + * fieldstat dynamic instance free. + * @param instance The fieldstat dynamic instance need to free. + */ +void fieldstat_dynamic_instance_free(struct fieldstat_dynamic_instance *instance); #ifdef __cplusplus } #endif
\ No newline at end of file diff --git a/src/fieldstat.cpp b/src/fieldstat.cpp index b67e8a5..3a8747c 100644 --- a/src/fieldstat.cpp +++ b/src/fieldstat.cpp @@ -48,6 +48,45 @@ int is_valid_field_name(const char* name) return 1; } +int is_valid_tag_value(const char* value) +{ + const char* reserverd="|:\n\r \t<>[]#!@"; + unsigned int i=0,j=0; + for(i=0;i<strlen(value);i++) + { + for(j=0;j<strlen(reserverd);j++) + if(value[i]==reserverd[j]) + { + return 0; + } + } + return 1; +} + + +int is_valid_tags(const struct fieldstat_tag *tags, size_t n_tags) +{ + int i = 0; + struct fieldstat_tag *tag = NULL; + + for(i = 0; i < (int)n_tags; i++) + { + tag = (struct fieldstat_tag *)&tags[i]; + if (0 == is_valid_field_name(tag->key)) + { + return 0; + } + + if(tag->value_type == 2) + { + if (0 == is_valid_tag_value(tag->value_str)) + { + return 0; + } + } + } + return 1; +} void get_current_table_line_cnt(struct fieldstat_instance *instance, int n_table, int *tables_line_cnt) { @@ -145,6 +184,11 @@ void metric_free(struct metric *metric) } metric->n_tag = 0; + if(metric->table) + { + metric->table = NULL; + } + free(metric); return; @@ -353,6 +397,11 @@ int fieldstat_register(struct fieldstat_instance *instance, enum field_type type return -1; } + if(0 == is_valid_tags(tags, n_tag)) + { + 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); @@ -477,7 +526,7 @@ void fieldstat_instance_start(struct fieldstat_instance *instance) clock_gettime(CLOCK_MONOTONIC,&(instance->last_output_time)); if(instance->background_thread_disable == 0) { - pthread_create(&(instance->cfg_mon_t), NULL, fieldstat_thread_schema_output, (void*)instance); + pthread_create(&(instance->background_thread), NULL, fieldstat_thread_schema_output, (void*)instance); } //append instance to prometheus output } @@ -490,6 +539,10 @@ struct fieldstat_instance * fieldstat_instance_new(const char *name) { return NULL; } + if(!is_valid_field_name(name)) + { + return NULL; + } instance = (struct fieldstat_instance *)calloc(sizeof(struct fieldstat_instance),1); strcpy(instance->name, name); @@ -500,6 +553,65 @@ struct fieldstat_instance * fieldstat_instance_new(const char *name) return instance; } +void fieldstat_instance_free(struct fieldstat_instance *instance) +{ + int i = 0; + void *pthread_ret; + struct metric *metric = NULL; + if(instance == NULL) + { + return; + } + + if(instance->background_thread_is_created == 1) + { + pthread_cancel(instance->background_thread); + pthread_join(instance->background_thread, &pthread_ret); + instance->background_thread_is_created = 0; + instance->running = 0; + } + + if(instance->local_output_fp) + { + fclose(instance->local_output_fp); + instance->local_output_fp = NULL; + instance->local_output_enable = 0; + } + + if(instance->line_protocol_socket != -1) + { + close(instance->line_protocol_socket); + instance->line_protocol_socket = -1; + } + + for(i = 0; i < instance->metric_cnt; i++) + { + metric = get_metric(instance, i); + metric_free(metric); + } + + for(i = 0; i < instance->table_num; i++) + { + table_metric_free(instance->table_metrics[i]); + instance->table_metrics[i] = NULL; + } + + if(instance->metric_block_list != NULL) + { + for(i = 0; i < BLOCK_LIST_SIZE; i++) + { + if(instance->metric_block_list[i] != NULL) + { + free(instance->metric_block_list[i]); + instance->metric_block_list[i] = NULL; + } + } + } + free(instance); + return; +} + + struct table_metric* table_metric_new(const char *name, const char *column_name[], enum field_type column_type[], size_t n_column) { int i = 0; @@ -516,12 +628,70 @@ struct table_metric* table_metric_new(const char *name, const char *column_name[ return table_metric; } +void table_metric_free(struct table_metric *table) +{ + int i = 0; + struct table_line *table_line = NULL; + + if(table == NULL) + { + return; + } + free(table->name); + table->name = NULL; + for(i = 0; i < (int)table->column_cnt; i++) + { + if(table->column_name[i] == NULL) + { + continue; + } + free(table->column_name[i]); + table->column_name[i] = NULL; + } + + for(i = 0; i < table->line_cnt; i++) + { + table_line = read_table_line(table, i); + table_line_free(table_line); + } + + if(table->line_block != NULL) + { + for(i = 0; i < BLOCK_LIST_SIZE; i++) + { + if(table->line_block[i] == NULL) + { + continue; + } + free(table->line_block[i]); + table->line_block[i] = NULL; + } + } + table->column_cnt = 0; + free(table); + return; +} + + int fieldstat_register_table(struct fieldstat_instance *instance, const char *table_name, const char *column_name[], enum field_type column_type[], size_t n_column) { int table_id = 0; struct table_metric *table_metric = NULL; + if(!is_valid_field_name(table_name)) + { + return -1; + } + + for(int i = 0; i < (int)n_column; i++) + { + if(!is_valid_field_name(column_name[i])) + { + return -1; + } + } + if(n_column <= 0 || n_column > TABLE_COLUMN_SIZE) { return -1; @@ -539,7 +709,7 @@ struct table_metric* table_metric_new(const char *name, const char *column_name[ return table_id; } -static struct table_line ** read_table_line_slot(struct table_metric *table, int line_id) +struct table_line ** read_table_line_slot(struct table_metric *table, int line_id) { int block_index = 0; int in_block_index = 0; @@ -561,7 +731,7 @@ static struct table_line ** read_table_line_slot(struct table_metric *table, int return (struct table_line **)&(line[in_block_index]); } -static struct table_line *table_line_new(const char *name, const struct fieldstat_tag tags[],size_t n_tag) +struct table_line *table_line_new(const char *name, const struct fieldstat_tag tags[],size_t n_tag) { struct table_line *table_line = (struct table_line *)calloc(sizeof(struct table_line), 1); @@ -574,6 +744,32 @@ static struct table_line *table_line_new(const char *name, const struct fieldsta } +void table_line_free(struct table_line *table_line) +{ + if(table_line == NULL) + { + return; + } + + free(table_line->name); + + table_line->name = NULL; + + for(int i = 0; i < (int)table_line->n_tag; i++) + { + free(table_line->tag_key[i]); + table_line->tag_key[i] = NULL; + + free(table_line->tag_value[i]); + table_line->tag_value[i] = NULL; + } + table_line->n_tag = 0; + + free(table_line); +} + + + int fieldstat_register_table_row(struct fieldstat_instance * instance, int table_id, const char *row_name, const struct fieldstat_tag tags[], size_t n_tag, int output_metric_ids[]) { int metric_id = 0; @@ -595,6 +791,11 @@ int fieldstat_register_table_row(struct fieldstat_instance * instance, int table return -1; } + if(0 == is_valid_tags(tags, n_tag)) + { + return -1; + } + table = instance->table_metrics[table_id]; line_id = atomic_inc(&(table->line_cnt)) - 1; line_slot = read_table_line_slot(table, line_id); @@ -607,11 +808,15 @@ int fieldstat_register_table_row(struct fieldstat_instance * instance, int table table_line->metric_id_belong_to_line[i] = metric_id; metric = get_metric(instance, metric_id); + + metric->table = table; + metric->table_column_id = i; +/* metric->table_id = table_id; metric->table_column_name = __str_dup(table->column_name[i]); metric->table_name = __str_dup(table->name); metric->belong_to_table = 1; - +*/ output_metric_ids[i] = metric_id; } *line_slot = table_line; diff --git a/src/fieldstat_dynamic.cpp b/src/fieldstat_dynamic.cpp index b9f163a..72f3155 100644 --- a/src/fieldstat_dynamic.cpp +++ b/src/fieldstat_dynamic.cpp @@ -8,6 +8,11 @@ struct fieldstat_dynamic_instance * fieldstat_dynamic_instance_new(const char *n { return NULL; } + + if(!is_valid_field_name(name)) + { + return NULL; + } instance = (struct fieldstat_dynamic_instance *)calloc(sizeof(struct fieldstat_dynamic_instance), 1); @@ -22,9 +27,81 @@ struct fieldstat_dynamic_instance * fieldstat_dynamic_instance_new(const char *n return instance; } +void fieldstat_dynamic_instance_free(struct fieldstat_dynamic_instance *instance) +{ + int i = 0; + struct dynamic_metric **head = NULL; + struct dynamic_metric *dyn_metric, *tmp_dyn_metric; + void *pthread_ret; + + if(instance == NULL) + { + return; + } + + if(instance->background_thread_is_created == 1) + { + pthread_cancel(instance->background_thread); + pthread_join(instance->background_thread, &pthread_ret); + instance->background_thread_is_created = 0; + instance->running = 0; + } + + if(instance->line_protocol_socket != -1) + { + close(instance->line_protocol_socket); + instance->line_protocol_socket = -1; + } + + for(i = 0; i < instance->n_thread; i++) + { + head = &instance->n_thread_dynamic_metric[i]; + HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric) + { + HASH_DEL(*head, dyn_metric); + if(dyn_metric->metrics) + { + int n_loop = 0; + struct metric *metric = dyn_metric->metrics[0]; + if(metric->table) + { + n_loop = metric->table->column_cnt; + } + else + { + n_loop = 1; + } + for(int j = 0; j < n_loop; j ++) + { + metric_free(dyn_metric->metrics[j]); + dyn_metric->metrics[j] = NULL; + } + free(dyn_metric->metrics); + dyn_metric->metrics = NULL; + } + free(dyn_metric); + } + instance->n_thread_dynamic_metric[i] = NULL; + } + + for(i = 0; i < instance->table_num; i++) + { + table_metric_free(instance->table_metrics[i]); + instance->table_metrics[i] = NULL; + } + + free(instance->n_thread_dynamic_metric); + instance->n_thread_dynamic_metric = NULL; + free(instance); + + return; +} + + + int fieldstat_dynamic_set_line_protocol_server(struct fieldstat_dynamic_instance *instance, const char *ip, unsigned short port) { - if(instance->running == 1) + if(instance == NULL || instance->running == 1) { return -1; } @@ -85,6 +162,7 @@ void fieldstat_dynamic_passive_output(struct fieldstat_dynamic_instance *instanc } if(ret == -1) { + printf("Passive return: output ret -1\n"); return; } memcpy(&(instance->last_output_time),&this_output_time, sizeof(this_output_time)); @@ -107,7 +185,8 @@ void fieldstat_dynamic_instance_start(struct fieldstat_dynamic_instance *instanc clock_gettime(CLOCK_MONOTONIC, &(instance->last_output_time)); if(instance->background_thread_disable == 0) { - pthread_create(&(instance->cfg_mon_t), NULL, fieldstat_dynamic_thread_schema_output, (void*)instance); + pthread_create(&(instance->background_thread), NULL, fieldstat_dynamic_thread_schema_output, (void*)instance); + instance->background_thread_is_created = 1; } } @@ -118,6 +197,19 @@ int fieldstat_register_dynamic_table(struct fieldstat_dynamic_instance *instance struct table_metric *table_metric = NULL; + if(!is_valid_field_name(table_name)) + { + return -1; + } + + for(i = 0; i < (int)n_column; i++) + { + if(!is_valid_field_name(column_name[i])) + { + return -1; + } + } + if(n_column <= 0 || n_column > TABLE_COLUMN_SIZE) { return -1; @@ -226,11 +318,15 @@ static struct metric * create_dynamic_table_metric(struct fieldstat_dynamic_inst assert(0); break; } + metric->table = table; + metric->table_column_id = i; +/* metric->table_id = table_id; metric->table_column_name = __str_dup(table->column_name[i]); metric->table_name = __str_dup(table->name); metric->belong_to_table = 1; - + metric->table_column_cnt = table->column_cnt; +*/ value->metrics[i] = metric; } @@ -297,21 +393,48 @@ static int fieldstat_dynamic_metric_value_operate(struct fieldstat_dynamic_insta int fieldstat_dynamic_metric_value_incrby(struct fieldstat_dynamic_instance *instance, enum field_type type, const char *field_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id) { int ret = 0; - fieldstat_dynamic_metric_value_operate(instance, FS_OP_ADD, type, field_name, value, tags, n_tags, thread_id); + if(!is_valid_field_name(field_name)) + { + return -1; + } + + if(0 == is_valid_tags(tags, n_tags)) + { + return -1; + } + ret = fieldstat_dynamic_metric_value_operate(instance, FS_OP_ADD, type, field_name, value, tags, n_tags, thread_id); return ret; } int fieldstat_dynamic_metric_value_set(struct fieldstat_dynamic_instance *instance, enum field_type type, const char *field_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id) { int ret = 0; - fieldstat_dynamic_metric_value_operate(instance, FS_OP_SET, type, field_name, value, tags, n_tags, thread_id); + if(!is_valid_field_name(field_name)) + { + return -1; + } + if(0 == is_valid_tags(tags, n_tags)) + { + return -1; + } + + ret = fieldstat_dynamic_metric_value_operate(instance, FS_OP_SET, type, field_name, value, tags, n_tags, thread_id); return ret; } int fieldstat_dynamic_metric_value_decrby(struct fieldstat_dynamic_instance *instance, enum field_type type, const char *field_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id) { int ret = 0; - fieldstat_dynamic_metric_value_operate(instance, FS_OP_SUB, type, field_name, value, tags, n_tags, thread_id); + if(!is_valid_field_name(field_name)) + { + return -1; + } + if(0 == is_valid_tags(tags, n_tags)) + { + return -1; + } + + ret = fieldstat_dynamic_metric_value_operate(instance, FS_OP_SUB, type, field_name, value, tags, n_tags, thread_id); return ret; } @@ -336,21 +459,48 @@ int fieldstat_dynamic_table_metric_value_operate(struct fieldstat_dynamic_instan int fieldstat_dynamic_table_metric_value_incrby(struct fieldstat_dynamic_instance *instance, int table_id, unsigned int column_id, const char *row_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id) { int ret = 0; - fieldstat_dynamic_table_metric_value_operate( instance, FS_OP_ADD, table_id, column_id, row_name, value, tags, n_tags, thread_id); + if(!is_valid_field_name(row_name)) + { + return -1; + } + if(0 == is_valid_tags(tags, n_tags)) + { + return -1; + } + + ret = fieldstat_dynamic_table_metric_value_operate( instance, FS_OP_ADD, table_id, column_id, row_name, value, tags, n_tags, thread_id); return ret; } int fieldstat_dynamic_table_metric_value_set(struct fieldstat_dynamic_instance *instance, int table_id, unsigned int column_id, const char *row_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id) { int ret = 0; - fieldstat_dynamic_table_metric_value_operate( instance, FS_OP_SET, table_id, column_id, row_name, value, tags, n_tags, thread_id); + if(!is_valid_field_name(row_name)) + { + return -1; + } + if(0 == is_valid_tags(tags, n_tags)) + { + return -1; + } + + ret = fieldstat_dynamic_table_metric_value_operate( instance, FS_OP_SET, table_id, column_id, row_name, value, tags, n_tags, thread_id); return ret; } int fieldstat_dynamic_table_metric_value_decrby(struct fieldstat_dynamic_instance *instance, int table_id, unsigned int column_id, const char *row_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id) { int ret = 0; - fieldstat_dynamic_table_metric_value_operate( instance, FS_OP_SUB, table_id, column_id, row_name, value, tags, n_tags, thread_id); + if(!is_valid_field_name(row_name)) + { + return -1; + } + if(0 == is_valid_tags(tags, n_tags)) + { + return -1; + } + + ret = fieldstat_dynamic_table_metric_value_operate( instance, FS_OP_SUB, table_id, column_id, row_name, value, tags, n_tags, thread_id); return ret; } diff --git a/src/fieldstat_internal.h b/src/fieldstat_internal.h index 1e8fc34..97171e5 100644 --- a/src/fieldstat_internal.h +++ b/src/fieldstat_internal.h @@ -100,6 +100,27 @@ struct histogram_t double *bins; }; +struct table_line +{ + char *name; + size_t n_tag; + char *tag_key[N_TAG_MAX]; + char *tag_value[N_TAG_MAX]; + + int metric_id_belong_to_line[TABLE_COLUMN_SIZE]; +}; + +struct table_metric +{ + char *name; + char *column_name[TABLE_COLUMN_SIZE]; + enum field_type column_type[TABLE_COLUMN_SIZE]; + int column_cnt; + + int line_cnt; + struct table_line **line_block[BLOCK_LIST_SIZE]; +}; + struct metric { @@ -115,13 +136,15 @@ struct metric int not_send_to_server; int numerator_id; int denominator_id; - +/* int belong_to_table; int table_id; - size_t line_seq; - int table_column_id; char *table_column_name; char *table_name; + int table_column_cnt; +*/ + struct table_metric *table; + int table_column_id; union { @@ -131,28 +154,6 @@ struct metric }; }; -struct table_line -{ - char *name; - size_t n_tag; - char *tag_key[N_TAG_MAX]; - char *tag_value[N_TAG_MAX]; - - int metric_id_belong_to_line[TABLE_COLUMN_SIZE]; -}; - -struct table_metric -{ - char *name; - char *column_name[TABLE_COLUMN_SIZE]; - enum field_type column_type[TABLE_COLUMN_SIZE]; - int column_cnt; - - int line_cnt; - struct table_line **line_block[BLOCK_LIST_SIZE]; -}; - - struct fieldstat_instance { char name[INSTANCE_NAME_LEN]; @@ -161,6 +162,7 @@ struct fieldstat_instance unsigned int statsd_server_ip; unsigned short statsd_server_port; int statsd_output_enable; + int line_protocol_socket; //char line_protocol_server_str_ip[LEN_IP_MAX]; unsigned int line_protocol_server_ip; @@ -170,8 +172,12 @@ struct fieldstat_instance char local_output_filename[LEN_PATH_MAX]; char local_output_format[LEN_FORMAT_MAX]; int local_output_enable; + FILE* local_output_fp; int background_thread_disable; + pthread_t background_thread; + int background_thread_is_created; + int output_interval_ms; int running; @@ -182,10 +188,7 @@ struct fieldstat_instance struct table_metric *table_metrics[TABLE_MAX_NUM]; - int *index_table[TABLE_MAX_NUM][TABLE_COLUMN_SIZE]; - int table_num; - int line_seq; int prometheus_output_enable; @@ -194,14 +197,9 @@ struct fieldstat_instance struct timespec last_output_time; - pthread_t cfg_mon_t; char line_protocol_send_buff[UDP_PAYLOAD_SIZE]; size_t line_protocol_send_buff_offset; - int line_protocol_socket; - pthread_mutex_t output_lock; - - FILE* fp; }; struct prometheus_endpoint_instance @@ -209,6 +207,7 @@ struct prometheus_endpoint_instance unsigned short port; char *url_path; pthread_t tid; + int thread_created; int running; struct http_server_s *server_handle; int fs_instance_cnt; @@ -238,7 +237,8 @@ struct fieldstat_dynamic_instance int table_num; struct timespec last_output_time; - pthread_t cfg_mon_t; + pthread_t background_thread; + int background_thread_is_created; char line_protocol_send_buff[UDP_PAYLOAD_SIZE]; size_t line_protocol_send_buff_offset; int line_protocol_socket; @@ -255,8 +255,10 @@ long long hdr_count_le_value(const struct hdr_histogram* h, long long value); struct metric * get_metric(struct fieldstat_instance *instance, int metric_id); long long get_metric_unit_val(struct metric *metric,enum field_calc_algo calc_type,int is_refer); int is_valid_field_name(const char* name); +int is_valid_tags(const struct fieldstat_tag *tags, size_t n_tags); struct metric ** read_metric_slot(struct fieldstat_instance *instance, int metric_id); struct metric * metric_new(enum field_type type, const char *field_name, const struct fieldstat_tag tags[], size_t n_tag); +void metric_free(struct metric *metric); int fieldstat_output_file(struct fieldstat_instance *instance,long long interval_ms); struct table_line * read_table_line(struct table_metric *table, int line_id); int send_udp(int sd, unsigned int dest_ip, unsigned short dest_port, const char * data, int len); @@ -266,4 +268,12 @@ int startup_udp(); void metric_value_operate(struct metric *metric, enum field_op op, long long value); struct table_metric* table_metric_new(const char *name, const char *column_name[], enum field_type column_type[], size_t n_column); -int line_protocol_dynamic_metric_output(struct fieldstat_dynamic_instance *instance);
\ No newline at end of file +void table_metric_free(struct table_metric *table); + +struct table_line *table_line_new(const char *name, const struct fieldstat_tag tags[],size_t n_tag); +void table_line_free(struct table_line *table_line); +int line_protocol_dynamic_metric_output(struct fieldstat_dynamic_instance *instance); + +struct table_line ** read_table_line_slot(struct table_metric *table, int line_id); + +void fieldstat_global_disable_prometheus_endpoint();
\ No newline at end of file diff --git a/src/file_output.cpp b/src/file_output.cpp index 3c4c921..40d28a1 100644 --- a/src/file_output.cpp +++ b/src/file_output.cpp @@ -64,7 +64,7 @@ static int output_file_format_default_type_gauge(struct fieldstat_instance *inst { continue; } - if(metric->belong_to_table == 1) + if(metric->table) { continue; } @@ -137,7 +137,7 @@ static int output_file_format_default_type_counter(struct fieldstat_instance *in { continue; } - if(metric->belong_to_table == 1) + if(metric->table) { continue; } @@ -403,8 +403,8 @@ static int output_file_format_default_type_histogram_and_summary(struct fieldsta char *pos = print_buf; //display_manifest_t* p=NULL; struct metric *metric = NULL; - struct metric *metric_array[current_metric_cnt] = {NULL}; - int metric_is_print[current_metric_cnt] = {0}; + struct metric *metric_array[current_metric_cnt]; + int metric_is_print[current_metric_cnt]; if(instance->histogram_cnt == 0 && instance->summary_cnt == 0) @@ -476,10 +476,10 @@ int fieldstat_output_file(struct fieldstat_instance *instance,long long interval time_t current = 0; char ctime_buff[STR_LEN_32]={0}; - if(instance->fp == NULL) + if(instance->local_output_fp == NULL) { - instance->fp = fopen(instance->local_output_filename, "w"); - if(instance->fp == NULL) + instance->local_output_fp = fopen(instance->local_output_filename, "w"); + if(instance->local_output_fp == NULL) { printf("Field Stat: open %s failed.\n",instance->local_output_filename); assert(0); @@ -511,10 +511,10 @@ int fieldstat_output_file(struct fieldstat_instance *instance,long long interval //TODO from json output } - fseek(instance->fp,0,SEEK_SET); - fwrite(print_buf,append_pos - print_buf,1,instance->fp); + fseek(instance->local_output_fp, 0, SEEK_SET); + fwrite(print_buf,append_pos - print_buf,1,instance->local_output_fp); - fflush(instance->fp); + fflush(instance->local_output_fp); if(print_buf) { diff --git a/src/line_protocol_output.cpp b/src/line_protocol_output.cpp index 3f4e86c..f1b2c16 100644 --- a/src/line_protocol_output.cpp +++ b/src/line_protocol_output.cpp @@ -121,7 +121,7 @@ static void output_line_protocol_table(struct fieldstat_instance *instance,int t field_pos += snprintf(field_pos, sizeof(field_set_buff) - (field_set_buff - field_set_buff), "%s=%lld,", - metric->table_column_name, + metric->table->column_name[metric->table_column_id], value ); @@ -178,7 +178,7 @@ int line_protocol_output(struct fieldstat_instance *instance) continue; } - if(metric->belong_to_table == 1) + if(metric->table) { continue; } @@ -258,7 +258,7 @@ static void append_line_protocol_dynamic_row(struct fieldstat_dynamic_instance * { flush_line_protocol_dynamic_metric(instance); } - printf("Line_protocol metric: %s%s %s\n",measurement,tag_set,field_set); + //printf("Line_protocol metric: %s:%s %s\n",measurement,tag_set,field_set); instance->line_protocol_send_buff_offset += snprintf(instance->line_protocol_send_buff + instance->line_protocol_send_buff_offset, sizeof(instance->line_protocol_send_buff) - instance->line_protocol_send_buff_offset, "%s%s %s\n", @@ -294,16 +294,16 @@ int line_protocol_dynamic_metric_output(struct fieldstat_dynamic_instance *insta metrics = dyn_metric->metrics; metric = metrics[0]; memset(tag_set_buff, 0, sizeof(tag_set_buff)); - memset(field_set_buff, 0 ,sizeof(field_set_buff)); + memset(field_set_buff, 0,sizeof(field_set_buff)); field_used_len = 0; tag_used_len = 0; - if(metric->belong_to_table == 1) + if(metric->table) { - table = instance->table_metrics[metric->table_id]; + table = metric->table; for(j = 0; j < table->column_cnt; j++) { - metric = metrics[i]; + metric = metrics[j]; value = metric->field_type == FIELD_TYPE_GAUGE ? get_metric_unit_val(metric, FS_CALC_CURRENT, 0): get_metric_unit_val(metric, FS_CALC_SPEED, 0); @@ -314,15 +314,18 @@ int line_protocol_dynamic_metric_output(struct fieldstat_dynamic_instance *insta field_used_len += snprintf(field_set_buff + field_used_len, sizeof(field_set_buff) - field_used_len, "%s=%lld,", - metric->table_column_name, + metric->table->column_name[metric->table_column_id], value ); } - if(row_value_is_not_zero == 1) + if(row_value_is_not_zero != 1) { continue; } + metric = metrics[0]; + field_used_len--; + field_set_buff[field_used_len] = '\0'; tag_used_len += snprintf(tag_set_buff + tag_used_len, sizeof(tag_set_buff) - tag_used_len, ",app_name=%s,table_name=%s", diff --git a/src/prometheus_output.cpp b/src/prometheus_output.cpp index 151bfba..8b31ae3 100644 --- a/src/prometheus_output.cpp +++ b/src/prometheus_output.cpp @@ -8,6 +8,7 @@ struct prometheus_endpoint_instance g_prometheus_endpoint_instance = NULL, 0, 0, + 0, NULL, 0, NULL, @@ -98,17 +99,24 @@ static void prometheus_output_uri_list(struct prometheus_endpoint_instance *prom fs_instance = prometheus_output->fs_instance; + if(prometheus_output->fs_instance_cnt > 0) + { + payload_len = prometheus_output->fs_instance_cnt * 128; //TODO using marco, len? + printf("payload_len =%d\n, n_instance =%d\n", payload_len, prometheus_output->fs_instance_cnt); + payload = (char *)calloc(1,payload_len); + payload_append_position = payload; + payload_append_position += snprintf(payload_append_position, payload_len - (payload_append_position - payload),"url_path:\n\t%s\n", prometheus_output->url_path); - payload_len = prometheus_output->fs_instance_cnt * 128; //TODO using marco, len? - payload_append_position = payload = (char *)calloc(1,payload_len); - - payload_append_position += snprintf(payload_append_position, payload_len - (payload_append_position - payload),"url_path:\n\t%s\n", prometheus_output->url_path); - - for(i = 0; i < prometheus_output->fs_instance_cnt; i++) + for(i = 0; i < prometheus_output->fs_instance_cnt; i++) + { + payload_append_position += snprintf(payload_append_position, payload_len - (payload_append_position - payload),"\t/%s\n", fs_instance[i]->name); + } + } + else { - payload_append_position += snprintf(payload_append_position, payload_len - (payload_append_position - payload),"\t/%s\n", fs_instance[i]->name); + payload = (char *)calloc(1, 128); + strncpy(payload, "Not Invaild instance\n", 128); } - response = http_response_init(); http_response_status(response, 404); http_response_header(response, "Content-Type", "text/plain; charset=utf-8"); @@ -130,7 +138,7 @@ static int prometheus_output_read_metric_tags(struct metric *metric, char *insta append_pos += snprintf(append_pos, size - (append_pos - tags_buff), "app_name=\"%s\"", instance_name); - if(metric->belong_to_table == 1) + if(metric->table) { append_pos += snprintf(append_pos, size - (append_pos - tags_buff), ",line_name=\"%s\"", metric->field_name); } @@ -149,9 +157,9 @@ static int prometheus_output_read_metric_name(struct metric *metric, char *insta { char unescape[256] = {0}; char *append_pos = name_buff; - if(metric->belong_to_table == 1) + if(metric->table) { - str_unescape(metric->table_column_name, unescape, sizeof(unescape)); + str_unescape(metric->table->column_name[metric->table_column_id], unescape, sizeof(unescape)); } else { @@ -417,9 +425,8 @@ int fieldstat_global_enable_prometheus_endpoint(unsigned short listen_port, cons g_prometheus_endpoint_instance.port = listen_port; g_prometheus_endpoint_instance.running = 1; g_prometheus_endpoint_instance.fs_instance = (struct fieldstat_instance **)calloc( sizeof(struct fieldstat_instance *), g_prometheus_endpoint_instance.fs_instance_size); - pthread_create(&g_prometheus_endpoint_instance.tid, NULL, prometheus_endpoint_listen_thread_entry, (void *)&g_prometheus_endpoint_instance); - + g_prometheus_endpoint_instance.thread_created = 1; return 0; } @@ -444,3 +451,34 @@ int fieldstat_enable_prometheus_output(struct fieldstat_instance *instance) } +void fieldstat_global_disable_prometheus_endpoint() +{ + void *pthread_ret; + + if(g_prometheus_endpoint_instance.thread_created == 1) + { + pthread_cancel(g_prometheus_endpoint_instance.tid); + pthread_join(g_prometheus_endpoint_instance.tid, &pthread_ret); + g_prometheus_endpoint_instance.running = 0; + g_prometheus_endpoint_instance.thread_created = 0; + free(g_prometheus_endpoint_instance.server_handle); + g_prometheus_endpoint_instance.server_handle = NULL; + } + + if(g_prometheus_endpoint_instance.url_path) + { + free(g_prometheus_endpoint_instance.url_path); + g_prometheus_endpoint_instance.url_path = NULL; + } + + if(g_prometheus_endpoint_instance.fs_instance) + { + free(g_prometheus_endpoint_instance.fs_instance); + g_prometheus_endpoint_instance.fs_instance = NULL; + g_prometheus_endpoint_instance.fs_instance_cnt = 0; + g_prometheus_endpoint_instance.fs_instance_size = 0; + } + + return; +} + diff --git a/test/src/CMakeLists.txt b/test/src/CMakeLists.txt index aa1250b..fa02909 100644 --- a/test/src/CMakeLists.txt +++ b/test/src/CMakeLists.txt @@ -2,8 +2,7 @@ cmake_minimum_required(VERSION 2.8) include_directories(${PROJECT_SOURCE_DIR}/inc/) include_directories(${PROJECT_SOURCE_DIR}/src/) - - +add_definitions(-std=c++11) #add_executable(gtest_rule ${PROJECT_SOURCE_DIR}/src/tsg_rule.cpp ${PROJECT_SOURCE_DIR}/src/tsg_bridge.cpp ${PROJECT_SOURCE_DIR}/src/tsg_leaky_bucket.cpp gtest_common.cpp gtest_rule.cpp) #target_link_libraries(gtest_rule gtest-static ctemplate-static cjson MESA_prof_load MESA_handle_logger MESA_jump_layer MESA_field_stat2 maatframe) diff --git a/test/src/gtest_dynamic_fieldstat.cpp b/test/src/gtest_dynamic_fieldstat.cpp index 4fe76e2..7c3aa09 100644 --- a/test/src/gtest_dynamic_fieldstat.cpp +++ b/test/src/gtest_dynamic_fieldstat.cpp @@ -4,12 +4,14 @@ #include <gtest/gtest.h> #include "fieldstat.h" #include "fieldstat_internal.h" +#include "cJSON.h" extern struct prometheus_endpoint_instance g_prometheus_endpoint_instance; TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceNew) { - struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", 16); + struct fieldstat_dynamic_instance *instance = NULL; + instance = fieldstat_dynamic_instance_new("firewall", 16); EXPECT_NE(nullptr, instance); EXPECT_STREQ("firewall", instance->name); @@ -19,6 +21,53 @@ TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceNew) { EXPECT_EQ(nullptr, instance->n_thread_dynamic_metric[i]); } + fieldstat_dynamic_instance_free(instance); + + instance = fieldstat_dynamic_instance_new("firewall-name-length-more-than-32", 16); + EXPECT_EQ(nullptr, instance); + + instance = fieldstat_dynamic_instance_new("firewall", 0); + EXPECT_EQ(nullptr, instance); + + instance = fieldstat_dynamic_instance_new("firewall\n", 16); + EXPECT_EQ(nullptr, instance); + + instance = fieldstat_dynamic_instance_new("firewall|", 16); + EXPECT_EQ(nullptr, instance); + + instance = fieldstat_dynamic_instance_new("firewall:", 16); + EXPECT_EQ(nullptr, instance); + + instance = fieldstat_dynamic_instance_new("firewall.", 16); + EXPECT_EQ(nullptr, instance); + + instance = fieldstat_dynamic_instance_new("firewall ", 16); + EXPECT_EQ(nullptr, instance); + + instance = fieldstat_dynamic_instance_new("firewall\t", 16); + EXPECT_EQ(nullptr, instance); + + instance = fieldstat_dynamic_instance_new("firewall<", 16); + EXPECT_EQ(nullptr, instance); + + instance = fieldstat_dynamic_instance_new("firewall>", 16); + EXPECT_EQ(nullptr, instance); + + instance = fieldstat_dynamic_instance_new("firewall[", 16); + EXPECT_EQ(nullptr, instance); + + instance = fieldstat_dynamic_instance_new("firewall]", 16); + EXPECT_EQ(nullptr, instance); + + instance = fieldstat_dynamic_instance_new("firewall#", 16); + EXPECT_EQ(nullptr, instance); + + instance = fieldstat_dynamic_instance_new("firewall!", 16); + EXPECT_EQ(nullptr, instance); + + instance = fieldstat_dynamic_instance_new("firewall@", 16); + EXPECT_EQ(nullptr, instance); + } TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceSetPara) @@ -44,6 +93,7 @@ TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceSetPara) ret = fieldstat_dynamic_set_output_interval(instance, 5000); EXPECT_EQ(0, ret); EXPECT_EQ(5000, instance->output_interval_ms); + fieldstat_dynamic_instance_free(instance); } @@ -56,8 +106,9 @@ TEST(FeildStatDynamicAPI, FieldStatDynamicStart) fieldstat_dynamic_instance_start(instance); EXPECT_EQ(1, instance->running); - ret = pthread_kill(instance->cfg_mon_t, 0); + ret = pthread_kill(instance->background_thread, 0); EXPECT_EQ(0, ret); + fieldstat_dynamic_instance_free(instance); } TEST(FeildStatDynamicAPI, FieldStatDynamicPassiveOutput) @@ -85,7 +136,7 @@ TEST(FeildStatDynamicAPI, FieldStatDynamicPassiveOutput) fieldstat_dynamic_passive_output(instance); EXPECT_NE(0, instance->last_output_time.tv_sec); EXPECT_NE(0, instance->last_output_time.tv_nsec); - + fieldstat_dynamic_instance_free(instance); } TEST(FeildStatDynamicAPI, FieldStatRegisterDynamicTable) @@ -130,7 +181,7 @@ TEST(FeildStatDynamicAPI, FieldStatRegisterDynamicTable) } } - + fieldstat_dynamic_instance_free(instance); } @@ -192,7 +243,7 @@ TEST(FeildStatDynamicAPI, FieldStatDynamicMetricValueIncrby) } } - + fieldstat_dynamic_instance_free(instance); } @@ -253,6 +304,7 @@ TEST(FeildStatDynamicAPI, FieldStatDynamicMetricValueSet) } } } + fieldstat_dynamic_instance_free(instance); } TEST(FeildStatDynamicAPI, FieldStatDynamicMetricValueDecrby) @@ -312,8 +364,2209 @@ TEST(FeildStatDynamicAPI, FieldStatDynamicMetricValueDecrby) } } } + fieldstat_dynamic_instance_free(instance); +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicTableMetricValueIncrby) +{ + int ret = 0; + int n_thread = 64; + struct fieldstat_tag tags[3]; + + tags[0].key = "policy_id"; + tags[0].value_int = 1; + tags[0].value_type = 0; + + tags[1].key = "quanlity"; + tags[1].value_double = 0.50; + tags[1].value_type = 1; + + tags[2].key = "device_id"; + tags[2].value_str = "test_device"; + tags[2].value_type = 2; + + struct dynamic_metric *dyn_metric, *tmp_dyn_metric; + struct dynamic_metric **head = NULL; + struct metric **metrics = NULL; + struct metric *metric = NULL; + long long value = 0; + + const char *column_name[] = {"packages", "bytes"}; + enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER}; + unsigned int out_column_ids[2]; + int table_id = -1; + + + struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread); + + table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids); + + EXPECT_EQ(0, table_id); + for(int i = 0; i < n_thread; i++) + { + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 20 + i, tags, sizeof(tags)/sizeof(tags[0]), i); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 200 + i, tags, sizeof(tags)/sizeof(tags[0]), i); + EXPECT_EQ(0, ret); + } + //EXPECT Per thread add one value. + for(int i = 0; i < n_thread; i++) + { + head = &instance->n_thread_dynamic_metric[i]; + HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric) + { + metrics = dyn_metric->metrics; + for(int j = 0; j < 2; j++) + { + metric = metrics[j]; + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + switch(j) + { + case 0: + EXPECT_EQ(value, 20 + i); + break; + case 1: + EXPECT_EQ(value, 200 + i); + break; + default: + FAIL() << "Field type should be in {counter, gauge}"; + } + } + } + } + fieldstat_dynamic_instance_free(instance); +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicTableMetricValueSet) +{ + int ret = 0; + int n_thread = 64; + struct fieldstat_tag tags[3]; + + tags[0].key = "policy_id"; + tags[0].value_int = 1; + tags[0].value_type = 0; + + tags[1].key = "quanlity"; + tags[1].value_double = 0.50; + tags[1].value_type = 1; + + tags[2].key = "device_id"; + tags[2].value_str = "test_device"; + tags[2].value_type = 2; + + struct dynamic_metric *dyn_metric, *tmp_dyn_metric; + struct dynamic_metric **head = NULL; + struct metric **metrics = NULL; + struct metric *metric = NULL; + long long value = 0; + + const char *column_name[] = {"packages", "bytes"}; + enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER}; + unsigned int out_column_ids[2]; + int table_id = -1; + + + struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread); + + table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids); + + EXPECT_EQ(0, table_id); + + for(int i = 0; i < n_thread; i++) + { + ret = fieldstat_dynamic_table_metric_value_set(instance, table_id, out_column_ids[0], "security_rule_hits", 20 + i, tags, sizeof(tags)/sizeof(tags[0]), i); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_table_metric_value_set(instance, table_id, out_column_ids[1], "security_rule_hits", 200 + i, tags, sizeof(tags)/sizeof(tags[0]), i); + EXPECT_EQ(0, ret); + } + + for(int i = 0; i < n_thread; i++) + { + head = &instance->n_thread_dynamic_metric[i]; + HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric) + { + metrics = dyn_metric->metrics; + for(int j = 0; j < 2; j++) + { + metric = metrics[j]; + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + switch(j) + { + case 0: + EXPECT_EQ(value, 20 + i); + break; + case 1: + EXPECT_EQ(value, 200 + i); + break; + default: + FAIL() << "Field type should be in {counter, gauge}"; + } + } + } + } + fieldstat_dynamic_instance_free(instance); +} + +TEST(FeildStatDynamicAPI, FieldStatDynamicTableMetricValueDecrby) +{ + int ret = 0; + int n_thread = 64; + struct fieldstat_tag tags[3]; + + tags[0].key = "policy_id"; + tags[0].value_int = 1; + tags[0].value_type = 0; + + tags[1].key = "quanlity"; + tags[1].value_double = 0.50; + tags[1].value_type = 1; + + tags[2].key = "device_id"; + tags[2].value_str = "test_device"; + tags[2].value_type = 2; + + struct dynamic_metric *dyn_metric, *tmp_dyn_metric; + struct dynamic_metric **head = NULL; + struct metric **metrics = NULL; + struct metric *metric = NULL; + long long value = 0; + + const char *column_name[] = {"packages", "bytes"}; + enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER}; + unsigned int out_column_ids[2]; + int table_id = -1; + + + struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread); + + table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids); + + EXPECT_EQ(0, table_id); + + for(int i = 0; i < n_thread; i++) + { + ret = fieldstat_dynamic_table_metric_value_decrby(instance, table_id, out_column_ids[0], "security_rule_hits", 20 + i, tags, sizeof(tags)/sizeof(tags[0]), i); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_table_metric_value_decrby(instance, table_id, out_column_ids[1], "security_rule_hits", 200 + i, tags, sizeof(tags)/sizeof(tags[0]), i); + EXPECT_EQ(0, ret); + } + + for(int i = 0; i < n_thread; i++) + { + head = &instance->n_thread_dynamic_metric[i]; + HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric) + { + metrics = dyn_metric->metrics; + for(int j = 0; j < 2; j++) + { + metric = metrics[j]; + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + switch(j) + { + case 0: + EXPECT_EQ(value, -(20 + i)); + break; + case 1: + EXPECT_EQ(value, -(200 + i)); + break; + default: + FAIL() << "Field type should be in {counter, gauge}"; + } + } + } + } + fieldstat_dynamic_instance_free(instance); +} + + +void parse_telegraf_cjson_output(const char *compare) +{ + const char *telegraf_output_file = "/tmp/metrics.out"; + FILE *fp; + char line[1024] = {0}; + char *cjson_metric_str = NULL; + int ret = 0; + + fp = fopen(telegraf_output_file, "r"); + EXPECT_NE(nullptr, fp); + + while(!feof(fp)) + { + fgets(line, sizeof(line), fp); + } + fclose(fp); + +//{"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"}} + + cJSON *cjson_metric = NULL; + cJSON *cjson_tags = NULL; + + cjson_metric = cJSON_Parse(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); + ret = strcmp(cjson_metric_str, compare); + EXPECT_EQ(0, ret); + cJSON_Delete(cjson_metric); + if(cjson_metric_str) + { + free(cjson_metric_str); + cjson_metric_str = NULL; + } + return; +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolNoTag) +{ + int n_thread = 48; + int ret = 0; + struct fieldstat_dynamic_instance *instance = NULL; + + instance = fieldstat_dynamic_instance_new("firewall", n_thread); + const char *compare_zero_tag = "{\"fields\":{\"Active_sessions\":10},\"name\":\"Active_sessions\",\"tags\":{\"app_name\":\"firewall\"}}"; + + + EXPECT_NE(nullptr, instance); + + ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600); + EXPECT_EQ(0, ret); + + ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_GAUGE, "Active_sessions", 10, NULL, 0, 0); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output(compare_zero_tag); + fieldstat_dynamic_instance_free(instance); +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolOneTag) +{ + int n_thread = 48; + int ret = 0; + struct fieldstat_dynamic_instance *instance = NULL; + struct fieldstat_tag tags[1]; + instance = fieldstat_dynamic_instance_new("firewall", n_thread); + const char *compare_one_tag = "{\"fields\":{\"Active_sessions\":11},\"name\":\"Active_sessions\",\"tags\":{\"app_name\":\"firewall\",\"policy_id\":\"1\"}}"; + + tags[0].key = "policy_id"; + tags[0].value_int = 1; + tags[0].value_type = 0; + + EXPECT_NE(nullptr, instance); + + ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_GAUGE, "Active_sessions", 11, tags, 1, 0); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output(compare_one_tag); + fieldstat_dynamic_instance_free(instance); + +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolTwoTags) +{ + int n_thread = 48; + int ret = 0; + struct fieldstat_dynamic_instance *instance = NULL; + struct fieldstat_tag tags[2]; + instance = fieldstat_dynamic_instance_new("firewall", n_thread); + const char *compare_two_tags = "{\"fields\":{\"Active_sessions\":12},\"name\":\"Active_sessions\",\"tags\":{\"app_name\":\"firewall\",\"policy_id\":\"1\",\"quanlity\":\"0.500000\"}}"; + + tags[0].key = "policy_id"; + tags[0].value_int = 1; + tags[0].value_type = 0; + + tags[1].key = "quanlity"; + tags[1].value_double = 0.50; + tags[1].value_type = 1; + + EXPECT_NE(nullptr, instance); + + ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600); + EXPECT_EQ(0, ret); + + ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_GAUGE, "Active_sessions", 12, tags, 2, 0); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output(compare_two_tags); + fieldstat_dynamic_instance_free(instance); +} + +TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolTableMetricNoTag) +{ + int n_thread = 48; + int ret = 0; + struct fieldstat_dynamic_instance *instance = NULL; + const char *column_name[] = {"packages", "bytes"}; + enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER}; + unsigned int out_column_ids[2]; + int table_id = -1; + const char *compare_zero_tag = "{\"fields\":{\"bytes\":30,\"packages\":30},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}"; + + + + instance = fieldstat_dynamic_instance_new("firewall", n_thread); + EXPECT_NE(nullptr, instance); + + table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids); + EXPECT_EQ(0, table_id); + + ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600); + EXPECT_EQ(0, ret); + + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, NULL, 0, 0); + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 30, NULL, 0, 0); + EXPECT_EQ(0, ret); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output(compare_zero_tag); + fieldstat_dynamic_instance_free(instance); + //parse_telegraf_cjson_output(compare_zero_tag_column1); +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolTableMetricOneTag) +{ + int n_thread = 48; + int ret = 0; + struct fieldstat_dynamic_instance *instance = NULL; + const char *column_name[] = {"packages", "bytes"}; + enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER}; + unsigned int out_column_ids[2]; + int table_id = -1; + struct fieldstat_tag tags[1]; + + const char *compare_one_tag = "{\"fields\":{\"bytes\":30,\"packages\":30},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"policy_id\":\"1\",\"table_name\":\"shaping\"}}"; + + tags[0].key = "policy_id"; + tags[0].value_int = 1; + tags[0].value_type = 0; + + + instance = fieldstat_dynamic_instance_new("firewall", n_thread); + EXPECT_NE(nullptr, instance); + + table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids); + EXPECT_EQ(0, table_id); + + ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600); + EXPECT_EQ(0, ret); + + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, tags, sizeof(tags)/sizeof(tags[0]), 0); + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 30, tags, sizeof(tags)/sizeof(tags[0]), 0); + EXPECT_EQ(0, ret); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output(compare_one_tag); + fieldstat_dynamic_instance_free(instance); + //parse_telegraf_cjson_output(compare_zero_tag_column1); +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolTableMetricTowTags) +{ + int n_thread = 48; + int ret = 0; + struct fieldstat_dynamic_instance *instance = NULL; + const char *column_name[] = {"packages", "bytes"}; + enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER}; + unsigned int out_column_ids[2]; + int table_id = -1; + struct fieldstat_tag tags[2]; + + const char *compare_two_tags = "{\"fields\":{\"bytes\":30,\"packages\":30},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"policy_id\":\"1\",\"quanlity\":\"0.500000\",\"table_name\":\"shaping\"}}"; + + tags[0].key = "policy_id"; + tags[0].value_int = 1; + tags[0].value_type = 0; + + tags[1].key = "quanlity"; + tags[1].value_double = 0.50; + tags[1].value_type = 1; + + + instance = fieldstat_dynamic_instance_new("firewall", n_thread); + EXPECT_NE(nullptr, instance); + + table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids); + EXPECT_EQ(0, table_id); + + ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600); + EXPECT_EQ(0, ret); + + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, tags, sizeof(tags)/sizeof(tags[0]), 0); + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 30, tags, sizeof(tags)/sizeof(tags[0]), 0); + EXPECT_EQ(0, ret); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output(compare_two_tags); + fieldstat_dynamic_instance_free(instance); +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolTypeGauge) +{ + int n_thread = 48; + int ret = 0; + struct fieldstat_dynamic_instance *instance = NULL; + + const char *compare_first_output = "{\"fields\":{\"Active_sessions\":12},\"name\":\"Active_sessions\",\"tags\":{\"app_name\":\"firewall\"}}"; + const char *compare_second_output = "{\"fields\":{\"Active_sessions\":24},\"name\":\"Active_sessions\",\"tags\":{\"app_name\":\"firewall\"}}"; + + instance = fieldstat_dynamic_instance_new("firewall", n_thread); + EXPECT_NE(nullptr, instance); + + ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600); + EXPECT_EQ(0, ret); + + ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_GAUGE, "Active_sessions", 12, NULL, 0, 0); + EXPECT_EQ(0, ret); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output(compare_first_output); + + ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_GAUGE, "Active_sessions", 12, NULL, 0, 0); + EXPECT_EQ(0, ret); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output(compare_second_output); + fieldstat_dynamic_instance_free(instance); + +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolTypeCounter) +{ + int n_thread = 48; + int ret = 0; + struct fieldstat_dynamic_instance *instance = NULL; + + const char *compare_first_output = "{\"fields\":{\"Active_sessions\":12},\"name\":\"Active_sessions\",\"tags\":{\"app_name\":\"firewall\"}}"; + const char *compare_second_output = "{\"fields\":{\"Active_sessions\":12},\"name\":\"Active_sessions\",\"tags\":{\"app_name\":\"firewall\"}}"; + + instance = fieldstat_dynamic_instance_new("firewall", n_thread); + EXPECT_NE(nullptr, instance); + + ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600); + EXPECT_EQ(0, ret); + + ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_COUNTER, "Active_sessions", 12, NULL, 0, 0); + EXPECT_EQ(0, ret); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output(compare_first_output); + + ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_COUNTER, "Active_sessions", 12, NULL, 0, 0); + EXPECT_EQ(0, ret); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output(compare_second_output); + fieldstat_dynamic_instance_free(instance); +} + +TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolTableMetricTypeAllCounter) +{ + int n_thread = 48; + int ret = 0; + struct fieldstat_dynamic_instance *instance = NULL; + const char *column_name[] = {"packages", "bytes"}; + enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER}; + unsigned int out_column_ids[2]; + int table_id = -1; + const char *compare_update_column_0 = "{\"fields\":{\"bytes\":0,\"packages\":30},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}"; + const char *compare_update_column_1 = "{\"fields\":{\"bytes\":30,\"packages\":0},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}"; + const char *compare_update_column_all = "{\"fields\":{\"bytes\":30,\"packages\":30},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}"; + + instance = fieldstat_dynamic_instance_new("firewall", n_thread); + EXPECT_NE(nullptr, instance); + + table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids); + EXPECT_EQ(0, table_id); + + ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600); + EXPECT_EQ(0, ret); + + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, NULL, 0, 0); + EXPECT_EQ(0, ret); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output(compare_update_column_0); + + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 30, NULL, 0, 0); + EXPECT_EQ(0, ret); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output(compare_update_column_1); + + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, NULL, 0, 0); + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 30, NULL, 0, 0); + EXPECT_EQ(0, ret); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output(compare_update_column_all); + fieldstat_dynamic_instance_free(instance); +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolTableMetricTypeAllGauge) +{ + int n_thread = 48; + int ret = 0; + struct fieldstat_dynamic_instance *instance = NULL; + const char *column_name[] = {"packages", "bytes"}; + enum field_type column_type[] = {FIELD_TYPE_GAUGE, FIELD_TYPE_GAUGE}; + unsigned int out_column_ids[2]; + int table_id = -1; + const char *compare_update_column_0 = "{\"fields\":{\"bytes\":0,\"packages\":30},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}"; + const char *compare_update_column_1 = "{\"fields\":{\"bytes\":30,\"packages\":30},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}"; + const char *compare_update_column_all = "{\"fields\":{\"bytes\":60,\"packages\":60},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}"; + + instance = fieldstat_dynamic_instance_new("firewall", n_thread); + EXPECT_NE(nullptr, instance); + + table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids); + EXPECT_EQ(0, table_id); + + ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600); + EXPECT_EQ(0, ret); + + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, NULL, 0, 0); + EXPECT_EQ(0, ret); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output(compare_update_column_0); + + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 30, NULL, 0, 0); + EXPECT_EQ(0, ret); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output(compare_update_column_1); + + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, NULL, 0, 0); + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 30, NULL, 0, 0); + EXPECT_EQ(0, ret); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output(compare_update_column_all); + fieldstat_dynamic_instance_free(instance); +} + +TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolTableMetricTypeOneCounterOneGauge) +{ + int n_thread = 48; + int ret = 0; + struct fieldstat_dynamic_instance *instance = NULL; + const char *column_name[] = {"packages", "bytes"}; + enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_GAUGE}; + unsigned int out_column_ids[2]; + int table_id = -1; + const char *compare_update_column_0 = "{\"fields\":{\"bytes\":0,\"packages\":30},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}"; + const char *compare_update_column_1 = "{\"fields\":{\"bytes\":30,\"packages\":0},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}"; + const char *compare_update_column_all = "{\"fields\":{\"bytes\":60,\"packages\":30},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}"; + + instance = fieldstat_dynamic_instance_new("firewall", n_thread); + EXPECT_NE(nullptr, instance); + + table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids); + EXPECT_EQ(0, table_id); + + ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600); + EXPECT_EQ(0, ret); + + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, NULL, 0, 0); + EXPECT_EQ(0, ret); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output(compare_update_column_0); + + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 30, NULL, 0, 0); + EXPECT_EQ(0, ret); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output(compare_update_column_1); + + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, NULL, 0, 0); + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 30, NULL, 0, 0); + EXPECT_EQ(0, ret); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output(compare_update_column_all); + fieldstat_dynamic_instance_free(instance); +} + +void parse_telegraf_cjson_output_not_equal(const char *compare) +{ + const char *telegraf_output_file = "/tmp/metrics.out"; + FILE *fp; + char line[1024] = {0}; + char *cjson_metric_str = NULL; + int ret = 0; + + fp = fopen(telegraf_output_file, "r"); + EXPECT_NE(nullptr, fp); + + while(!feof(fp)) + { + fgets(line, sizeof(line), fp); + } + fclose(fp); + + + cJSON *cjson_metric = NULL; + cJSON *cjson_tags = NULL; + + cjson_metric = cJSON_Parse(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); + ret = strcmp(cjson_metric_str, compare); + EXPECT_NE(0, ret); + cJSON_Delete(cjson_metric); + if(cjson_metric_str) + { + free(cjson_metric_str); + cjson_metric_str = NULL; + } + return; +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolValueZero) +{ + int n_thread = 48; + int ret = 0; + struct fieldstat_dynamic_instance *instance = NULL; + + const char *compare_output = "{\"fields\":{\"Active_sessions\":0},\"name\":\"Active_sessions\",\"tags\":{\"app_name\":\"firewall\"}}"; + + instance = fieldstat_dynamic_instance_new("firewall", n_thread); + EXPECT_NE(nullptr, instance); + + ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600); + EXPECT_EQ(0, ret); + + ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_GAUGE, "Active_sessions", 0, NULL, 0, 0); + EXPECT_EQ(0, ret); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output_not_equal(compare_output); + fieldstat_dynamic_instance_free(instance); +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolTableMetricValueZero) +{ + int n_thread = 48; + int ret = 0; + struct fieldstat_dynamic_instance *instance = NULL; + const char *column_name[] = {"packages", "bytes"}; + enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER}; + unsigned int out_column_ids[2]; + int table_id = -1; + const char *compare_column = "{\"fields\":{\"bytes\":0,\"packages\":0},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}"; + + + instance = fieldstat_dynamic_instance_new("firewall", n_thread); + EXPECT_NE(nullptr, instance); + + table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids); + EXPECT_EQ(0, table_id); + + ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600); + EXPECT_EQ(0, ret); + + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 0, NULL, 0, 0); + EXPECT_EQ(0, ret); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output_not_equal(compare_column); + + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 0, NULL, 0, 0); + EXPECT_EQ(0, ret); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output_not_equal(compare_column); + + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 0, NULL, 0, 0); + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 0, NULL, 0, 0); + EXPECT_EQ(0, ret); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(1); + parse_telegraf_cjson_output_not_equal(compare_column); + fieldstat_dynamic_instance_free(instance); +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolMultiMetric) +{ + int n_thread = 48; + int ret = 0; + int loops = 5000; + struct fieldstat_dynamic_instance *instance = NULL; + char field_name[32]; + const char *telegraf_output_file = "/tmp/metrics.out"; + FILE *fp; + char line[1024] = {0}; + cJSON *cjson_metric = NULL; + cJSON *cjson_tags = NULL; + char compare[1024]; + char *cjson_metric_str = NULL; + + instance = fieldstat_dynamic_instance_new("firewall", n_thread); + EXPECT_NE(nullptr, instance); + ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600); + EXPECT_EQ(0, ret); + for(int i = 0; i < loops; i++) + { + memset(field_name, 0, sizeof(field_name)); + snprintf(field_name, sizeof(field_name), "Active_sessions_%d", i); + ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_GAUGE, (const char *)field_name, 12, NULL, 0, 0); + EXPECT_EQ(0, ret); + } + ret = system("cat /dev/null > /tmp/metrics.out"); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(5); + + fp = fopen(telegraf_output_file, "r"); + EXPECT_NE(nullptr, fp); + int n_line = 0; + + while(!feof(fp)) + { + if(NULL == fgets(line, sizeof(line), fp)) + { + continue; + } + cjson_metric = cJSON_Parse(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"); + memset(compare, 0, sizeof(compare)); + snprintf(compare, sizeof(compare), "{\"fields\":{\"Active_sessions_%d\":12},\"name\":\"Active_sessions_%d\",\"tags\":{\"app_name\":\"firewall\"}}", n_line, n_line); + cjson_metric_str = cJSON_PrintUnformatted(cjson_metric); + EXPECT_STREQ(compare, cjson_metric_str); + cJSON_Delete(cjson_metric); + if(cjson_metric_str) + { + free(cjson_metric_str); + cjson_metric_str = NULL; + } + n_line++; + } + fclose(fp); + EXPECT_EQ(n_line, loops); + fieldstat_dynamic_instance_free(instance); +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolMultiTableRow) +{ + int n_thread = 48; + int ret = 0; + int loops = 5000; + struct fieldstat_dynamic_instance *instance = NULL; + char row_name[32]; + const char *telegraf_output_file = "/tmp/metrics.out"; + FILE *fp; + char line[1024] = {0}; + cJSON *cjson_metric = NULL; + cJSON *cjson_tags = NULL; + char compare[1024]; + char *cjson_metric_str = NULL; + + + const char *column_name[] = {"packages", "bytes"}; + enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER}; + unsigned int out_column_ids[2]; + int table_id = -1; + + instance = fieldstat_dynamic_instance_new("firewall", n_thread); + EXPECT_NE(nullptr, instance); + ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600); + EXPECT_EQ(0, ret); + table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids); + EXPECT_EQ(0, table_id); + for(int i = 0; i < loops; i++) + { + memset(row_name, 0, sizeof(row_name)); + snprintf(row_name, sizeof(row_name), "security_rule_hits_%d", i); + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], row_name, 30, NULL, 0, 0); + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], row_name, 30, NULL, 0, 0); + EXPECT_EQ(0, ret); + } + ret = system("cat /dev/null > /tmp/metrics.out"); + ret = line_protocol_dynamic_metric_output(instance); + EXPECT_EQ(0, ret); + sleep(5); + + fp = fopen(telegraf_output_file, "r"); + EXPECT_NE(nullptr, fp); + int n_line = 0; + + while(!feof(fp)) + { + if(NULL == fgets(line, sizeof(line), fp)) + { + continue; + } + cjson_metric = cJSON_Parse(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"); + memset(compare, 0, sizeof(compare)); + + snprintf(compare, sizeof(compare), "{\"fields\":{\"bytes\":30,\"packages\":30},\"name\":\"security_rule_hits_%d\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}", n_line); + cjson_metric_str = cJSON_PrintUnformatted(cjson_metric); + EXPECT_STREQ(compare, cjson_metric_str); + cJSON_Delete(cjson_metric); + if(cjson_metric_str) + { + free(cjson_metric_str); + cjson_metric_str = NULL; + } + n_line++; + } + fclose(fp); + EXPECT_EQ(n_line, loops); + + fieldstat_dynamic_instance_free(instance); +} + + + +struct thread_para +{ + int loops; + struct fieldstat_dynamic_instance * instance; + int thread_id; + int table_id; + unsigned int *out_column_ids; +}; + +void _worker_thread_multi_incrby(void *arg) +{ + + struct thread_para *para = (struct thread_para*)arg; + int loops = para->loops; + int thread_id = para->thread_id; + int table_id = para->table_id; + unsigned int *out_column_ids = para->out_column_ids; + + struct fieldstat_dynamic_instance *instance = para->instance; + int ret = 0; + struct fieldstat_tag tags[3]; + + int i = 0; + + tags[0].key = "policy_id"; + tags[0].value_int = 1; + tags[0].value_type = 0; + + tags[1].key = "quanlity"; + tags[1].value_double = 0.50; + tags[1].value_type = 1; + + tags[2].key = "device_id"; + tags[2].value_str = "test_device"; + tags[2].value_type = 2; + + for(i = 0; i < loops; i++) + { + ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_GAUGE, "Active_sessions", 10, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_COUNTER, "Traffic_bytes", 20, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 31, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + } + return; +} +void * worker_thread_multi_incrby(void *arg) +{ + _worker_thread_multi_incrby(arg); + return NULL; +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceMultiIncrby) +{ + int ret = 0; + int n_thread = 64; + int n_loops = 50000; + + struct dynamic_metric *dyn_metric, *tmp_dyn_metric; + struct dynamic_metric **head = NULL; + struct metric **metrics = NULL; + struct metric *metric = NULL; + long long value = 0; + + const char *column_name[] = {"packages", "bytes"}; + enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER}; + unsigned int out_column_ids[2]; + int table_id = -1; + + struct thread_para para[n_thread]; + pthread_t thread_ids[n_thread]; + + + struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread); + + table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids); + + EXPECT_EQ(0, table_id); + + for(int i = 0; i < n_thread; i++) + { + para[i].loops = n_loops; + para[i].instance = instance; + para[i].thread_id = i; + para[i].table_id = table_id; + para[i].out_column_ids = out_column_ids; + } + + for(int i = 0; i < n_thread; i++) + { + ret = pthread_create(&(thread_ids[i]), NULL, worker_thread_multi_incrby, &(para[i])); + EXPECT_EQ(0, ret); + } + + void *temp; + for(int i = 0; i < n_thread; i++) + { + pthread_join(thread_ids[i], (void**)&temp); + } + + for(int i = 0; i < n_thread; i++) + { + int n_metrics = 0; + head = &instance->n_thread_dynamic_metric[i]; + HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric) + { + metrics = dyn_metric->metrics; + metric = metrics[0]; + if(metric->table) + { + metric = metrics[0]; + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ((30 * n_loops), value); + metric = metrics[1]; + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ((31 * n_loops), value); + } + else + { + switch(metric->field_type) + { + case FIELD_TYPE_GAUGE: + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ((10 * n_loops), value); + break; + case FIELD_TYPE_COUNTER: + value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0); + EXPECT_EQ((20 * n_loops), value); + break; + default: + FAIL() << "Field type should be in {counter, gauge}"; + } + } + n_metrics++; + } + EXPECT_EQ(3, n_metrics); + } + fieldstat_dynamic_instance_free(instance); +} + + +void _worker_thread_multi_decrby(void *arg) +{ + + struct thread_para *para = (struct thread_para*)arg; + int loops = para->loops; + int thread_id = para->thread_id; + int table_id = para->table_id; + unsigned int *out_column_ids = para->out_column_ids; + + struct fieldstat_dynamic_instance *instance = para->instance; + int ret = 0; + struct fieldstat_tag tags[3]; + + int i = 0; + + tags[0].key = "policy_id"; + tags[0].value_int = 1; + tags[0].value_type = 0; + + tags[1].key = "quanlity"; + tags[1].value_double = 0.50; + tags[1].value_type = 1; + + tags[2].key = "device_id"; + tags[2].value_str = "test_device"; + tags[2].value_type = 2; + + for(i = 0; i < loops; i++) + { + ret = fieldstat_dynamic_metric_value_decrby(instance, FIELD_TYPE_GAUGE, "Active_sessions", 10, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_metric_value_decrby(instance, FIELD_TYPE_COUNTER, "Traffic_bytes", 20, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + + ret = fieldstat_dynamic_table_metric_value_decrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_table_metric_value_decrby(instance, table_id, out_column_ids[1], "security_rule_hits", 31, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + } + return; } +void * worker_thread_multi_decrby(void *arg) +{ + _worker_thread_multi_decrby(arg); + return NULL; +} + +TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceMultiDecrby) +{ + int ret = 0; + int n_thread = 64; + int n_loops = 50000; + + struct dynamic_metric *dyn_metric, *tmp_dyn_metric; + struct dynamic_metric **head = NULL; + struct metric **metrics = NULL; + struct metric *metric = NULL; + long long value = 0; + + const char *column_name[] = {"packages", "bytes"}; + enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER}; + unsigned int out_column_ids[2]; + int table_id = -1; + + struct thread_para para[n_thread]; + pthread_t thread_ids[n_thread]; + + + struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread); + + table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids); + + EXPECT_EQ(0, table_id); + + for(int i = 0; i < n_thread; i++) + { + para[i].loops = n_loops; + para[i].instance = instance; + para[i].thread_id = i; + para[i].table_id = table_id; + para[i].out_column_ids = out_column_ids; + } + + for(int i = 0; i < n_thread; i++) + { + ret = pthread_create(&(thread_ids[i]), NULL, worker_thread_multi_decrby, &(para[i])); + EXPECT_EQ(0, ret); + } + + void *temp; + for(int i = 0; i < n_thread; i++) + { + pthread_join(thread_ids[i], (void**)&temp); + } + + for(int i = 0; i < n_thread; i++) + { + int n_metrics = 0; + head = &instance->n_thread_dynamic_metric[i]; + HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric) + { + metrics = dyn_metric->metrics; + metric = metrics[0]; + if(metric->table) + { + metric = metrics[0]; + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ((-30 * n_loops), value); + metric = metrics[1]; + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ((-31 * n_loops), value); + } + else + { + switch(metric->field_type) + { + case FIELD_TYPE_GAUGE: + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ((-10 * n_loops), value); + break; + case FIELD_TYPE_COUNTER: + value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0); + EXPECT_EQ((-20 * n_loops), value); + break; + default: + FAIL() << "Field type should be in {counter, gauge}"; + } + } + n_metrics++; + } + EXPECT_EQ(3, n_metrics); + } + fieldstat_dynamic_instance_free(instance); +} + + +void _worker_thread_multi_set(void *arg) +{ + + struct thread_para *para = (struct thread_para*)arg; + int loops = para->loops; + int thread_id = para->thread_id; + int table_id = para->table_id; + unsigned int *out_column_ids = para->out_column_ids; + + struct fieldstat_dynamic_instance *instance = para->instance; + int ret = 0; + struct fieldstat_tag tags[3]; + + int i = 0; + + tags[0].key = "policy_id"; + tags[0].value_int = 1; + tags[0].value_type = 0; + + tags[1].key = "quanlity"; + tags[1].value_double = 0.50; + tags[1].value_type = 1; + + tags[2].key = "device_id"; + tags[2].value_str = "test_device"; + tags[2].value_type = 2; + + for(i = 0; i < loops; i++) + { + ret = fieldstat_dynamic_metric_value_set(instance, FIELD_TYPE_GAUGE, "Active_sessions", 10, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_metric_value_set(instance, FIELD_TYPE_COUNTER, "Traffic_bytes", 20, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + + ret = fieldstat_dynamic_table_metric_value_set(instance, table_id, out_column_ids[0], "security_rule_hits", 30, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_table_metric_value_set(instance, table_id, out_column_ids[1], "security_rule_hits", 31, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + } + return; +} +void * worker_thread_multi_set(void *arg) +{ + _worker_thread_multi_set(arg); + return NULL; +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceMultiSet) +{ + int ret = 0; + int n_thread = 64; + int n_loops = 50000; + + struct dynamic_metric *dyn_metric, *tmp_dyn_metric; + struct dynamic_metric **head = NULL; + struct metric **metrics = NULL; + struct metric *metric = NULL; + long long value = 0; + + const char *column_name[] = {"packages", "bytes"}; + enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER}; + unsigned int out_column_ids[2]; + int table_id = -1; + + struct thread_para para[n_thread]; + pthread_t thread_ids[n_thread]; + + + struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread); + + table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids); + + EXPECT_EQ(0, table_id); + + for(int i = 0; i < n_thread; i++) + { + para[i].loops = n_loops; + para[i].instance = instance; + para[i].thread_id = i; + para[i].table_id = table_id; + para[i].out_column_ids = out_column_ids; + } + + for(int i = 0; i < n_thread; i++) + { + ret = pthread_create(&(thread_ids[i]), NULL, worker_thread_multi_set, &(para[i])); + EXPECT_EQ(0, ret); + } + + void *temp; + for(int i = 0; i < n_thread; i++) + { + pthread_join(thread_ids[i], (void**)&temp); + } + + for(int i = 0; i < n_thread; i++) + { + int n_metrics = 0; + head = &instance->n_thread_dynamic_metric[i]; + HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric) + { + metrics = dyn_metric->metrics; + metric = metrics[0]; + if(metric->table) + { + metric = metrics[0]; + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ(30, value); + metric = metrics[1]; + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ(31, value); + } + else + { + switch(metric->field_type) + { + case FIELD_TYPE_GAUGE: + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ(10, value); + break; + case FIELD_TYPE_COUNTER: + value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0); + EXPECT_EQ(20, value); + break; + default: + FAIL() << "Field type should be in {counter, gauge}"; + } + } + n_metrics++; + } + EXPECT_EQ(3, n_metrics); + } + fieldstat_dynamic_instance_free(instance); +} + + +void _worker_thread_incrby_multi_metric(void *arg) +{ + + struct thread_para *para = (struct thread_para*)arg; + int loops = para->loops; + int thread_id = para->thread_id; + int table_id = para->table_id; + unsigned int *out_column_ids = para->out_column_ids; + + struct fieldstat_dynamic_instance *instance = para->instance; + int ret = 0; + struct fieldstat_tag tags[3]; + + int i = 0; + + tags[0].key = "policy_id"; + tags[0].value_int = 1; + tags[0].value_type = 0; + + tags[1].key = "quanlity"; + tags[1].value_double = 0.50; + tags[1].value_type = 1; + + tags[2].key = "device_id"; + tags[2].value_str = "test_device"; + tags[2].value_type = 2; + + for(i = 0; i < loops; i++) + { + char gauge_name[32]; + char counter_name[32]; + char table_column_name[32]; + snprintf(gauge_name, sizeof(gauge_name), "Active_sessions_%d", i); + snprintf(counter_name, sizeof(gauge_name), "Traffic_bytes_%d", i); + snprintf(table_column_name, sizeof(gauge_name), "security_rule_hits_%d", i); + ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_GAUGE, gauge_name, 10, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_COUNTER, counter_name, 20, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], table_column_name, 30, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], table_column_name, 31, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + } +} +void * worker_thread_incrby_multi_metric(void *arg) +{ + _worker_thread_incrby_multi_metric(arg); + return NULL; +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceIncrbyMultiMetric) +{ + int ret = 0; + int n_thread = 64; + int n_loops = 1000; + + struct dynamic_metric *dyn_metric, *tmp_dyn_metric; + struct dynamic_metric **head = NULL; + struct metric **metrics = NULL; + struct metric *metric = NULL; + long long value = 0; + + const char *column_name[] = {"packages", "bytes"}; + enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER}; + unsigned int out_column_ids[2]; + int table_id = -1; + + struct thread_para para[n_thread]; + pthread_t thread_ids[n_thread]; + + + struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread); + + table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids); + + EXPECT_EQ(0, table_id); + + for(int i = 0; i < n_thread; i++) + { + para[i].loops = n_loops; + para[i].instance = instance; + para[i].thread_id = i; + para[i].table_id = table_id; + para[i].out_column_ids = out_column_ids; + } + + for(int i = 0; i < n_thread; i++) + { + ret = pthread_create(&(thread_ids[i]), NULL, worker_thread_incrby_multi_metric, &(para[i])); + EXPECT_EQ(0, ret); + } + + void *temp; + for(int i = 0; i < n_thread; i++) + { + pthread_join(thread_ids[i], (void**)&temp); + } + + for(int i = 0; i < n_thread; i++) + { + int n_metrics = 0; + head = &instance->n_thread_dynamic_metric[i]; + HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric) + { + metrics = dyn_metric->metrics; + metric = metrics[0]; + if(metric->table) + { + metric = metrics[0]; + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ(30, value); + metric = metrics[1]; + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ(31, value); + } + else + { + switch(metric->field_type) + { + case FIELD_TYPE_GAUGE: + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ(10, value); + break; + case FIELD_TYPE_COUNTER: + value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0); + EXPECT_EQ(20, value); + break; + default: + FAIL() << "Field type should be in {counter, gauge}"; + } + } + n_metrics++; + } + EXPECT_EQ((3 * n_loops), n_metrics); + } + fieldstat_dynamic_instance_free(instance); +} + + +void _worker_thread_decrby_multi_metric(void *arg) +{ + + struct thread_para *para = (struct thread_para*)arg; + int loops = para->loops; + int thread_id = para->thread_id; + int table_id = para->table_id; + unsigned int *out_column_ids = para->out_column_ids; + + struct fieldstat_dynamic_instance *instance = para->instance; + int ret = 0; + struct fieldstat_tag tags[3]; + + int i = 0; + + tags[0].key = "policy_id"; + tags[0].value_int = 1; + tags[0].value_type = 0; + + tags[1].key = "quanlity"; + tags[1].value_double = 0.50; + tags[1].value_type = 1; + + tags[2].key = "device_id"; + tags[2].value_str = "test_device"; + tags[2].value_type = 2; + + for(i = 0; i < loops; i++) + { + char gauge_name[32]; + char counter_name[32]; + char table_column_name[32]; + snprintf(gauge_name, sizeof(gauge_name), "Active_sessions_%d", i); + snprintf(counter_name, sizeof(gauge_name), "Traffic_bytes_%d", i); + snprintf(table_column_name, sizeof(gauge_name), "security_rule_hits_%d", i); + ret = fieldstat_dynamic_metric_value_decrby(instance, FIELD_TYPE_GAUGE, gauge_name, 10, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_metric_value_decrby(instance, FIELD_TYPE_COUNTER, counter_name, 20, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + + ret = fieldstat_dynamic_table_metric_value_decrby(instance, table_id, out_column_ids[0], table_column_name, 30, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_table_metric_value_decrby(instance, table_id, out_column_ids[1], table_column_name, 31, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + } + return; +} +void * worker_thread_decrby_multi_metric(void *arg) +{ + _worker_thread_decrby_multi_metric(arg); + return NULL; +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceDecrbyMultiMetric) +{ + int ret = 0; + int n_thread = 64; + int n_loops = 1000; + + struct dynamic_metric *dyn_metric, *tmp_dyn_metric; + struct dynamic_metric **head = NULL; + struct metric **metrics = NULL; + struct metric *metric = NULL; + long long value = 0; + + const char *column_name[] = {"packages", "bytes"}; + enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER}; + unsigned int out_column_ids[2]; + int table_id = -1; + + struct thread_para para[n_thread]; + pthread_t thread_ids[n_thread]; + + + struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread); + + table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids); + + EXPECT_EQ(0, table_id); + + for(int i = 0; i < n_thread; i++) + { + para[i].loops = n_loops; + para[i].instance = instance; + para[i].thread_id = i; + para[i].table_id = table_id; + para[i].out_column_ids = out_column_ids; + } + + for(int i = 0; i < n_thread; i++) + { + ret = pthread_create(&(thread_ids[i]), NULL, worker_thread_decrby_multi_metric, &(para[i])); + EXPECT_EQ(0, ret); + } + + void *temp; + for(int i = 0; i < n_thread; i++) + { + pthread_join(thread_ids[i], (void**)&temp); + } + + for(int i = 0; i < n_thread; i++) + { + int n_metrics = 0; + head = &instance->n_thread_dynamic_metric[i]; + HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric) + { + metrics = dyn_metric->metrics; + metric = metrics[0]; + if(metric->table) + { + metric = metrics[0]; + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ(-30, value); + metric = metrics[1]; + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ(-31, value); + } + else + { + switch(metric->field_type) + { + case FIELD_TYPE_GAUGE: + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ(-10, value); + break; + case FIELD_TYPE_COUNTER: + value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0); + EXPECT_EQ(-20, value); + break; + default: + FAIL() << "Field type should be in {counter, gauge}"; + } + } + n_metrics++; + } + EXPECT_EQ((3 * n_loops), n_metrics); + } + fieldstat_dynamic_instance_free(instance); +} + + + +void _worker_thread_set_multi_metric(void *arg) +{ + + struct thread_para *para = (struct thread_para*)arg; + int loops = para->loops; + int thread_id = para->thread_id; + int table_id = para->table_id; + unsigned int *out_column_ids = para->out_column_ids; + + struct fieldstat_dynamic_instance *instance = para->instance; + int ret = 0; + struct fieldstat_tag tags[3]; + + int i = 0; + + tags[0].key = "policy_id"; + tags[0].value_int = 1; + tags[0].value_type = 0; + + tags[1].key = "quanlity"; + tags[1].value_double = 0.50; + tags[1].value_type = 1; + + tags[2].key = "device_id"; + tags[2].value_str = "test_device"; + tags[2].value_type = 2; + + for(i = 0; i < loops; i++) + { + char gauge_name[32]; + char counter_name[32]; + char table_column_name[32]; + snprintf(gauge_name, sizeof(gauge_name), "Active_sessions_%d", i); + snprintf(counter_name, sizeof(gauge_name), "Traffic_bytes_%d", i); + snprintf(table_column_name, sizeof(gauge_name), "security_rule_hits_%d", i); + ret = fieldstat_dynamic_metric_value_set(instance, FIELD_TYPE_GAUGE, gauge_name, 10, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_metric_value_set(instance, FIELD_TYPE_COUNTER, counter_name, 20, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + + ret = fieldstat_dynamic_table_metric_value_set(instance, table_id, out_column_ids[0], table_column_name, 30, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_table_metric_value_set(instance, table_id, out_column_ids[1], table_column_name, 31, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + } + return; +} +void * worker_thread_set_multi_metric(void *arg) +{ + _worker_thread_set_multi_metric(arg); + return NULL; +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceSetMultiMetric) +{ + int ret = 0; + int n_thread = 64; + int n_loops = 1000; + + struct dynamic_metric *dyn_metric, *tmp_dyn_metric; + struct dynamic_metric **head = NULL; + struct metric **metrics = NULL; + struct metric *metric = NULL; + long long value = 0; + + const char *column_name[] = {"packages", "bytes"}; + enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER}; + unsigned int out_column_ids[2]; + int table_id = -1; + + struct thread_para para[n_thread]; + pthread_t thread_ids[n_thread]; + + + struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread); + + table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids); + + EXPECT_EQ(0, table_id); + + for(int i = 0; i < n_thread; i++) + { + para[i].loops = n_loops; + para[i].instance = instance; + para[i].thread_id = i; + para[i].table_id = table_id; + para[i].out_column_ids = out_column_ids; + } + + for(int i = 0; i < n_thread; i++) + { + ret = pthread_create(&(thread_ids[i]), NULL, worker_thread_set_multi_metric, &(para[i])); + EXPECT_EQ(0, ret); + } + + void *temp; + for(int i = 0; i < n_thread; i++) + { + pthread_join(thread_ids[i], (void**)&temp); + } + + for(int i = 0; i < n_thread; i++) + { + int n_metrics = 0; + head = &instance->n_thread_dynamic_metric[i]; + HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric) + { + metrics = dyn_metric->metrics; + metric = metrics[0]; + if(metric->table) + { + metric = metrics[0]; + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ(30, value); + metric = metrics[1]; + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ(31, value); + } + else + { + switch(metric->field_type) + { + case FIELD_TYPE_GAUGE: + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ(10, value); + break; + case FIELD_TYPE_COUNTER: + value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0); + EXPECT_EQ(20, value); + break; + default: + FAIL() << "Field type should be in {counter, gauge}"; + } + } + n_metrics++; + } + EXPECT_EQ((3 * n_loops), n_metrics); + } + fieldstat_dynamic_instance_free(instance); +} + + + + + +void _worker_thread_multi_incrby_multi_metric(void *arg) +{ + struct thread_para *para = (struct thread_para*)arg; + int loops = para->loops; + int thread_id = para->thread_id; + int table_id = para->table_id; + unsigned int *out_column_ids = para->out_column_ids; + + struct fieldstat_dynamic_instance *instance = para->instance; + int ret = 0; + struct fieldstat_tag tags[3]; + + int i = 0; + + tags[0].key = "policy_id"; + tags[0].value_int = 1; + tags[0].value_type = 0; + + tags[1].key = "quanlity"; + tags[1].value_double = 0.50; + tags[1].value_type = 1; + + tags[2].key = "device_id"; + tags[2].value_str = "test_device"; + tags[2].value_type = 2; + + for(i = 0; i < loops; i++) + { + char gauge_name[32]; + char counter_name[32]; + char table_column_name[32]; + snprintf(gauge_name, sizeof(gauge_name), "Active_sessions_%d", i); + snprintf(counter_name, sizeof(gauge_name), "Traffic_bytes_%d", i); + snprintf(table_column_name, sizeof(gauge_name), "security_rule_hits_%d", i); + + for(int j = 0; j < loops; j++) + { + ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_GAUGE, (const char *)gauge_name, 10, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_COUNTER, (const char *)counter_name, 20, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], (const char *)table_column_name, 30, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], (const char *)table_column_name, 31, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + } + } + return; +} +void * worker_thread_multi_incrby_multi_metric(void *arg) +{ + _worker_thread_multi_incrby_multi_metric(arg); + return NULL; +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceMultiIncrbyMultiMetric) +{ + int ret = 0; + int n_thread = 64; + int n_loops = 1000; + + struct dynamic_metric *dyn_metric, *tmp_dyn_metric; + struct dynamic_metric **head = NULL; + struct metric **metrics = NULL; + struct metric *metric = NULL; + long long value = 0; + + const char *column_name[] = {"packages", "bytes"}; + enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER}; + unsigned int out_column_ids[2]; + int table_id = -1; + + struct thread_para para[n_thread]; + pthread_t thread_ids[n_thread]; + + + struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread); + + table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids); + + EXPECT_EQ(0, table_id); + + for(int i = 0; i < n_thread; i++) + { + para[i].loops = n_loops; + para[i].instance = instance; + para[i].thread_id = i; + para[i].table_id = table_id; + para[i].out_column_ids = out_column_ids; + } + + for(int i = 0; i < n_thread; i++) + { + ret = pthread_create(&(thread_ids[i]), NULL, worker_thread_multi_incrby_multi_metric, &(para[i])); + EXPECT_EQ(0, ret); + } + + void *temp; + for(int i = 0; i < n_thread; i++) + { + pthread_join(thread_ids[i], (void**)&temp); + } + + for(int i = 0; i < n_thread; i++) + { + int n_metrics = 0; + head = &instance->n_thread_dynamic_metric[i]; + HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric) + { + metrics = dyn_metric->metrics; + metric = metrics[0]; + if(metric->table) + { + metric = metrics[0]; + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ((30 * n_loops), value); + metric = metrics[1]; + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ((31 * n_loops), value); + } + else + { + switch(metric->field_type) + { + case FIELD_TYPE_GAUGE: + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ((10 * n_loops), value); + break; + case FIELD_TYPE_COUNTER: + value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0); + EXPECT_EQ((20 * n_loops), value); + break; + default: + FAIL() << "Field type should be in {counter, gauge}"; + } + } + n_metrics++; + } + EXPECT_EQ((3 * n_loops), n_metrics); + } + fieldstat_dynamic_instance_free(instance); +} + + +void _worker_thread_multi_decrby_multi_metric(void *arg) +{ + struct thread_para *para = (struct thread_para*)arg; + int loops = para->loops; + int thread_id = para->thread_id; + int table_id = para->table_id; + unsigned int *out_column_ids = para->out_column_ids; + + struct fieldstat_dynamic_instance *instance = para->instance; + int ret = 0; + struct fieldstat_tag tags[3]; + + int i = 0; + + tags[0].key = "policy_id"; + tags[0].value_int = 1; + tags[0].value_type = 0; + + tags[1].key = "quanlity"; + tags[1].value_double = 0.50; + tags[1].value_type = 1; + + tags[2].key = "device_id"; + tags[2].value_str = "test_device"; + tags[2].value_type = 2; + + for(i = 0; i < loops; i++) + { + char gauge_name[32]; + char counter_name[32]; + char table_column_name[32]; + snprintf(gauge_name, sizeof(gauge_name), "Active_sessions_%d", i); + snprintf(counter_name, sizeof(gauge_name), "Traffic_bytes_%d", i); + snprintf(table_column_name, sizeof(gauge_name), "security_rule_hits_%d", i); + + for(int j = 0; j < loops; j++) + { + ret = fieldstat_dynamic_metric_value_decrby(instance, FIELD_TYPE_GAUGE, (const char *)gauge_name, 10, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_metric_value_decrby(instance, FIELD_TYPE_COUNTER, (const char *)counter_name, 20, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + + ret = fieldstat_dynamic_table_metric_value_decrby(instance, table_id, out_column_ids[0], (const char *)table_column_name, 30, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_table_metric_value_decrby(instance, table_id, out_column_ids[1], (const char *)table_column_name, 31, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + } + } + return; +} +void * worker_thread_multi_decrby_multi_metric(void *arg) +{ + _worker_thread_multi_decrby_multi_metric(arg); + return NULL; +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceMultiDecrbyMultiMetric) +{ + int ret = 0; + int n_thread = 64; + int n_loops = 1000; + + struct dynamic_metric *dyn_metric, *tmp_dyn_metric; + struct dynamic_metric **head = NULL; + struct metric **metrics = NULL; + struct metric *metric = NULL; + long long value = 0; + + const char *column_name[] = {"packages", "bytes"}; + enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER}; + unsigned int out_column_ids[2]; + int table_id = -1; + + struct thread_para para[n_thread]; + pthread_t thread_ids[n_thread]; + + + struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread); + + table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids); + + EXPECT_EQ(0, table_id); + + for(int i = 0; i < n_thread; i++) + { + para[i].loops = n_loops; + para[i].instance = instance; + para[i].thread_id = i; + para[i].table_id = table_id; + para[i].out_column_ids = out_column_ids; + } + + for(int i = 0; i < n_thread; i++) + { + ret = pthread_create(&(thread_ids[i]), NULL, worker_thread_multi_decrby_multi_metric, &(para[i])); + EXPECT_EQ(0, ret); + } + + void *temp; + for(int i = 0; i < n_thread; i++) + { + pthread_join(thread_ids[i], (void**)&temp); + } + + for(int i = 0; i < n_thread; i++) + { + int n_metrics = 0; + head = &instance->n_thread_dynamic_metric[i]; + HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric) + { + metrics = dyn_metric->metrics; + metric = metrics[0]; + if(metric->table) + { + metric = metrics[0]; + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ((-1 * 30 * n_loops), value); + metric = metrics[1]; + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ((-1 * 31 * n_loops), value); + } + else + { + switch(metric->field_type) + { + case FIELD_TYPE_GAUGE: + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ((-1 * 10 * n_loops), value); + break; + case FIELD_TYPE_COUNTER: + value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0); + EXPECT_EQ((-1 * 20 * n_loops), value); + break; + default: + FAIL() << "Field type should be in {counter, gauge}"; + } + } + n_metrics++; + } + EXPECT_EQ((3 * n_loops), n_metrics); + } + fieldstat_dynamic_instance_free(instance); +} + +void _worker_thread_multi_set_multi_metric(void *arg) +{ + struct thread_para *para = (struct thread_para*)arg; + int loops = para->loops; + int thread_id = para->thread_id; + int table_id = para->table_id; + unsigned int *out_column_ids = para->out_column_ids; + + struct fieldstat_dynamic_instance *instance = para->instance; + int ret = 0; + struct fieldstat_tag tags[3]; + + int i = 0; + + tags[0].key = "policy_id"; + tags[0].value_int = 1; + tags[0].value_type = 0; + + tags[1].key = "quanlity"; + tags[1].value_double = 0.50; + tags[1].value_type = 1; + + tags[2].key = "device_id"; + tags[2].value_str = "test_device"; + tags[2].value_type = 2; + + for(i = 0; i < loops; i++) + { + char gauge_name[32]; + char counter_name[32]; + char table_column_name[32]; + snprintf(gauge_name, sizeof(gauge_name), "Active_sessions_%d", i); + snprintf(counter_name, sizeof(gauge_name), "Traffic_bytes_%d", i); + snprintf(table_column_name, sizeof(gauge_name), "security_rule_hits_%d", i); + + for(int j = 0; j < loops; j++) + { + ret = fieldstat_dynamic_metric_value_set(instance, FIELD_TYPE_GAUGE, (const char *)gauge_name, 10, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_metric_value_set(instance, FIELD_TYPE_COUNTER, (const char *)counter_name, 20, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + + ret = fieldstat_dynamic_table_metric_value_set(instance, table_id, out_column_ids[0], (const char *)table_column_name, 30, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + ret = fieldstat_dynamic_table_metric_value_set(instance, table_id, out_column_ids[1], (const char *)table_column_name, 31, tags, sizeof(tags)/sizeof(tags[0]), thread_id); + EXPECT_EQ(0, ret); + } + } + return; +} +void * worker_thread_multi_set_multi_metric(void *arg) +{ + _worker_thread_multi_set_multi_metric(arg); + return NULL; +} + + +TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceMultiSetMultiMetric) +{ + int ret = 0; + int n_thread = 64; + int n_loops = 1000; + + struct dynamic_metric *dyn_metric, *tmp_dyn_metric; + struct dynamic_metric **head = NULL; + struct metric **metrics = NULL; + struct metric *metric = NULL; + long long value = 0; + + const char *column_name[] = {"packages", "bytes"}; + enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER}; + unsigned int out_column_ids[2]; + int table_id = -1; + + struct thread_para para[n_thread]; + pthread_t thread_ids[n_thread]; + + + struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread); + + table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids); + + EXPECT_EQ(0, table_id); + + for(int i = 0; i < n_thread; i++) + { + para[i].loops = n_loops; + para[i].instance = instance; + para[i].thread_id = i; + para[i].table_id = table_id; + para[i].out_column_ids = out_column_ids; + } + + for(int i = 0; i < n_thread; i++) + { + ret = pthread_create(&(thread_ids[i]), NULL, worker_thread_multi_set_multi_metric, &(para[i])); + EXPECT_EQ(0, ret); + } + + void *temp; + for(int i = 0; i < n_thread; i++) + { + pthread_join(thread_ids[i], (void**)&temp); + } + + for(int i = 0; i < n_thread; i++) + { + int n_metrics = 0; + head = &instance->n_thread_dynamic_metric[i]; + HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric) + { + metrics = dyn_metric->metrics; + metric = metrics[0]; + if(metric->table) + { + metric = metrics[0]; + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ(30, value); + metric = metrics[1]; + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ(31, value); + } + else + { + switch(metric->field_type) + { + case FIELD_TYPE_GAUGE: + value = get_metric_unit_val(metric, FS_CALC_SPEED, 0); + EXPECT_EQ(10, value); + break; + case FIELD_TYPE_COUNTER: + value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0); + EXPECT_EQ(20, value); + break; + default: + FAIL() << "Field type should be in {counter, gauge}"; + } + } + n_metrics++; + } + EXPECT_EQ((3 * n_loops), n_metrics); + } + fieldstat_dynamic_instance_free(instance); +} diff --git a/test/src/gtest_fieldstat.cpp b/test/src/gtest_fieldstat.cpp index ee69475..2434539 100644 --- a/test/src/gtest_fieldstat.cpp +++ b/test/src/gtest_fieldstat.cpp @@ -7,25 +7,30 @@ extern struct prometheus_endpoint_instance g_prometheus_endpoint_instance; -TEST(FeildStatAPI, CreateFieldStatInstance) +TEST(FeildStatAPI, FieldStatInstanceNew) { struct fieldstat_instance *instance = fieldstat_instance_new("test"); EXPECT_NE(nullptr, instance); EXPECT_STREQ("test", instance->name); + fieldstat_instance_free(instance); } +/* TEST(FeildStatAPI, FieldStatEnablePrometheusEndpoint) { int ret_enable_prometheus_endpoint = 0; int ret_req_prometheus_endpoint = 0; + const char *request_cmd = "curl -s -o /dev/null http://127.0.0.1:9020/metrics"; ret_enable_prometheus_endpoint = fieldstat_global_enable_prometheus_endpoint(9020, "/metrcis"); EXPECT_EQ(0, ret_enable_prometheus_endpoint); - - ret_req_prometheus_endpoint = system("curl -s -o /dev/null http://127.0.0.1:9020/metrics"); + usleep(500 * 1000); + ret_req_prometheus_endpoint = system(request_cmd); EXPECT_EQ(0,ret_req_prometheus_endpoint); + usleep(500 * 1000); + fieldstat_global_disable_prometheus_endpoint(); } - +*/ TEST(FeildStatAPI, FieldStatSetPrometheusOutput) { struct fieldstat_instance *instance = NULL; @@ -35,7 +40,7 @@ TEST(FeildStatAPI, FieldStatSetPrometheusOutput) instance = fieldstat_instance_new("test"); EXPECT_STREQ("test", instance->name); - ret_enable_prometheus_endpoint = fieldstat_global_enable_prometheus_endpoint(9020, "/metrcis"); + ret_enable_prometheus_endpoint = fieldstat_global_enable_prometheus_endpoint(9020, "/metrics"); EXPECT_EQ(0, ret_enable_prometheus_endpoint); ret_set_prometheus_output = fieldstat_enable_prometheus_output(instance); @@ -44,8 +49,13 @@ TEST(FeildStatAPI, FieldStatSetPrometheusOutput) EXPECT_EQ(1, g_prometheus_endpoint_instance.running); EXPECT_EQ(instance, g_prometheus_endpoint_instance.fs_instance[0]); EXPECT_EQ(1, g_prometheus_endpoint_instance.fs_instance_cnt); + + usleep(500 * 1000); + fieldstat_global_disable_prometheus_endpoint(); + fieldstat_instance_free(instance); } + TEST(FeildStatAPI, FieldStatSetLineProtocolServer) { struct fieldstat_instance *instance = NULL; @@ -59,6 +69,7 @@ TEST(FeildStatAPI, FieldStatSetLineProtocolServer) EXPECT_EQ(0, ret_set_line_protocol_server); EXPECT_EQ(1, instance->line_protocol_output_enable); EXPECT_NE(-1, instance->line_protocol_socket); + fieldstat_instance_free(instance); } TEST(FeildStatAPI, FieldStatSetLocalOutput) @@ -74,10 +85,9 @@ TEST(FeildStatAPI, FieldStatSetLocalOutput) EXPECT_STREQ("test.fs", instance->local_output_filename); EXPECT_STREQ("default", instance->local_output_format); EXPECT_EQ(1, instance->local_output_enable); + fieldstat_instance_free(instance); } -int fieldstat_disable_background_thread(struct fieldstat_instance *instance); - TEST(FeildStatAPI, FieldStatBackgroundThreadDisable) { struct fieldstat_instance *instance = NULL; @@ -88,6 +98,7 @@ TEST(FeildStatAPI, FieldStatBackgroundThreadDisable) ret_background_thread_disable = fieldstat_disable_background_thread(instance); EXPECT_EQ(0, ret_background_thread_disable); EXPECT_EQ(1, instance->background_thread_disable); + fieldstat_instance_free(instance); } TEST(FeildStatAPI, FieldStatSetOutputInterval) @@ -101,6 +112,19 @@ TEST(FeildStatAPI, FieldStatSetOutputInterval) ret_set_output_interval = fieldstat_set_output_interval(instance, 1); EXPECT_EQ(0, ret_set_output_interval); EXPECT_EQ(1, instance->output_interval_ms); + fieldstat_instance_free(instance); +} + +TEST(FeildStatAPI, FieldStatInstanceStart) +{ + struct fieldstat_instance *instance = NULL; + + instance = fieldstat_instance_new("test"); + EXPECT_STREQ("test", instance->name); + + fieldstat_instance_start(instance); + usleep(500 * 1000); + fieldstat_instance_free(instance); } TEST(FeildStatAPI, FieldStatRegister) @@ -137,6 +161,7 @@ TEST(FeildStatAPI, FieldStatRegister) EXPECT_EQ(2, metric_id); EXPECT_EQ(3, instance->metric_cnt); EXPECT_NE(nullptr, in_block_metric[2]); + fieldstat_instance_free(instance); } TEST(FieldStatAPI, FieldStatRegisterTable) @@ -164,6 +189,7 @@ TEST(FieldStatAPI, FieldStatRegisterTable) EXPECT_EQ(0, table->line_cnt); EXPECT_EQ(nullptr, table->line_block[0]); + 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(1, table_id); @@ -172,6 +198,8 @@ TEST(FieldStatAPI, FieldStatRegisterTable) EXPECT_EQ(4, table->column_cnt); EXPECT_EQ(0, table->line_cnt); EXPECT_EQ(nullptr, table->line_block[0]); + + fieldstat_instance_free(instance); } @@ -179,7 +207,6 @@ TEST(FieldStatAPI, FieldStatRegisterTableMetrics) { struct fieldstat_instance * instance = NULL; int table_id = -1; - struct table_metric *table = NULL; const char *sc_column_name[] = {"sent_pkts", "send_bytes", "recv_pkts", "recv_bytes"}; enum field_type sc_column_type[] = {FIELD_TYPE_COUNTER,FIELD_TYPE_COUNTER,FIELD_TYPE_COUNTER,FIELD_TYPE_COUNTER}; @@ -190,7 +217,8 @@ TEST(FieldStatAPI, FieldStatRegisterTableMetrics) 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); } |
