summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfumingwei <[email protected]>2023-04-06 20:55:12 +0800
committerfumingwei <[email protected]>2023-04-11 18:40:50 +0800
commita31d2c750f1b3fa2a0b718505ae528232cab19a3 (patch)
tree832fc745e1f3c61e60849c22772f06b47f133b98
parent1e22236b3fdce7446422fedb03594cf09c3d4cfb (diff)
bugfix:TSG-14523:修复单独输出prometheus和line protocol数据异常的bugv3.0.2bugfix-promethues-output-zero-value
-rw-r--r--ctest/CMakeLists.txt8
-rw-r--r--src/fieldstat.cpp27
-rw-r--r--src/fieldstat_dynamic.cpp6
-rw-r--r--src/fieldstat_internal.h6
-rw-r--r--src/file_output.cpp16
-rw-r--r--src/line_protocol_output.cpp30
-rw-r--r--src/prometheus_output.cpp9
-rw-r--r--test/src/CMakeLists.txt9
-rw-r--r--test/src/gtest_dynamic_fieldstat_output.cpp126
-rw-r--r--test/src/gtest_fieldstat_interface.cpp (renamed from test/src/gtest_fieldstat.cpp)1
-rw-r--r--test/src/gtest_fieldstat_output.cpp694
11 files changed, 893 insertions, 39 deletions
diff --git a/ctest/CMakeLists.txt b/ctest/CMakeLists.txt
index d9a7c17..c25ad35 100644
--- a/ctest/CMakeLists.txt
+++ b/ctest/CMakeLists.txt
@@ -4,11 +4,15 @@ project(fieldstat_ctest)
add_test(NAME COPY_CREATE_DIR COMMAND sh -c "mkdir -p ${CMAKE_BINARY_DIR}/testing/ ")
-add_test(NAME COPY_GTEST_BINARY COMMAND sh -c "cp ${CMAKE_BINARY_DIR}/test/src/gtest_fieldstat ${CMAKE_BINARY_DIR}/testing/")
+add_test(NAME COPY_GTEST_INTERFACE_BINARY COMMAND sh -c "cp ${CMAKE_BINARY_DIR}/test/src/gtest_fieldstat_interface ${CMAKE_BINARY_DIR}/testing/")
+add_test(NAME COPY_GTEST_OUTPUT_BINARY COMMAND sh -c "cp ${CMAKE_BINARY_DIR}/test/src/gtest_fieldstat_output ${CMAKE_BINARY_DIR}/testing/")
add_test(NAME COPY_GTEST_DYNAMIC_BINARY COMMAND sh -c "cp ${CMAKE_BINARY_DIR}/test/src/gtest_dynamic_fieldstat ${CMAKE_BINARY_DIR}/testing/")
+add_test(NAME COPY_GTEST_DYNAMIC_OUTPUT_BINARY COMMAND sh -c "cp ${CMAKE_BINARY_DIR}/test/src/gtest_dynamic_fieldstat_output ${CMAKE_BINARY_DIR}/testing/")
set(GTEST_RUN_DIR ${CMAKE_BINARY_DIR}/testing)
#add_test(NAME GTEST_RULE COMMAND gtest_rule WORKING_DIRECTORY ${GTEST_RUN_DIR})
-add_test(NAME GTEST_FIELDSTAT COMMAND gtest_fieldstat WORKING_DIRECTORY ${GTEST_RUN_DIR})
+add_test(NAME GTEST_FIELDSTAT_INTERFACE COMMAND gtest_fieldstat_interface WORKING_DIRECTORY ${GTEST_RUN_DIR})
+add_test(NAME GTEST_FIELDSTAT_OUTPUT COMMAND gtest_fieldstat_output WORKING_DIRECTORY ${GTEST_RUN_DIR})
add_test(NAME GTEST_DYNAMIC_FIELDSTAT COMMAND gtest_dynamic_fieldstat WORKING_DIRECTORY ${GTEST_RUN_DIR})
+add_test(NAME GTEST_DYNAMIC_FIELDSTAT_OUTPUT COMMAND gtest_dynamic_fieldstat_output WORKING_DIRECTORY ${GTEST_RUN_DIR})
diff --git a/src/fieldstat.cpp b/src/fieldstat.cpp
index 0ad0e67..6014600 100644
--- a/src/fieldstat.cpp
+++ b/src/fieldstat.cpp
@@ -344,6 +344,7 @@ int fieldstat_set_local_output(struct fieldstat_instance *instance, const char *
strncpy(instance->local_output_filename, (char *)filename, len_filename);
strncpy(instance->local_output_format, (char *)format, len_format);
instance->local_output_enable = 1;
+ instance->output_type |= 8;
return 0;
}
@@ -360,6 +361,7 @@ int fieldstat_set_line_protocol_server(struct fieldstat_instance *instance, cons
if(ret == 0)
{
instance->line_protocol_output_enable = 1;
+ instance->output_type |= 4;
}
return ret;
@@ -379,6 +381,7 @@ int fieldstat_set_statsd_server(struct fieldstat_instance *instance, const char
instance->statsd_server_port = port;
instance->statsd_output_enable = 1;
+ instance->output_type |= 2;
return 0;
}
@@ -460,6 +463,28 @@ long long get_metric_unit_val(struct metric *metric,enum field_calc_algo calc_ty
return value;
}
+long long read_metric_current_value(struct metric *metric)
+{
+ stat_unit_t* target = NULL;
+ long long value = 0;
+ switch(metric->field_type)
+ {
+ case FIELD_TYPE_COUNTER:
+ target = &(metric->counter);
+ break;
+ case FIELD_TYPE_GAUGE:
+ target = &(metric->gauge);
+ break;
+ default:
+ break;
+ }
+
+ value = threadsafe_counter_read(&(target->changing));
+ value += target->accumulated;
+
+ return value;
+}
+
long long hdr_count_le_value(const struct hdr_histogram* h, long long value)
{
struct hdr_iter iter;
@@ -494,7 +519,7 @@ void fieldstat_passive_output(struct fieldstat_instance *instance)
if(instance->local_output_enable)
{
- ret = fieldstat_output_file(instance, interval_ms);
+ ret = file_output(instance, interval_ms);
}
if(instance->line_protocol_output_enable)
{
diff --git a/src/fieldstat_dynamic.cpp b/src/fieldstat_dynamic.cpp
index 5a0609e..c10dc56 100644
--- a/src/fieldstat_dynamic.cpp
+++ b/src/fieldstat_dynamic.cpp
@@ -111,6 +111,7 @@ int fieldstat_dynamic_set_line_protocol_server(struct fieldstat_dynamic_instance
if(ret == 0)
{
instance->line_protocol_output_enable = 1;
+ instance->output_type |= 4;
}
return ret;
@@ -513,9 +514,8 @@ static long long dynamic_metric_value_read(struct fieldstat_dynamic_instance *in
{
return 0;
}
- metric->field_type == FIELD_TYPE_GAUGE
- ?value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0)
- :value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ value = read_metric_current_value(metric);
+
return value;
}
diff --git a/src/fieldstat_internal.h b/src/fieldstat_internal.h
index 58bd58c..eb3b5d0 100644
--- a/src/fieldstat_internal.h
+++ b/src/fieldstat_internal.h
@@ -194,7 +194,7 @@ struct fieldstat_instance
int summary_cnt;
struct timespec last_output_time;
-
+ int output_type; // 0b0000:not output, 0b1000:output file, 0b0100:output line_protocol, 0b0010: output statsd, 0b0001: output prometheus
};
struct prometheus_endpoint_instance
@@ -236,6 +236,7 @@ struct fieldstat_dynamic_instance
struct dynamic_metric **n_thread_dynamic_metric;
int n_thread;
+ int output_type; // 0b0000:not output, 0b1000:output file, 0b0100:output line_protocol, 0b0010: output statsd, 0b0001: output prometheus
};
@@ -245,12 +246,13 @@ char* __str_dup(const char* str);
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);
+long long read_metric_current_value(struct metric *metric);
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);
+int file_output(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);
int line_protocol_output(struct fieldstat_instance *instance);
diff --git a/src/file_output.cpp b/src/file_output.cpp
index 3ffea17..d585160 100644
--- a/src/file_output.cpp
+++ b/src/file_output.cpp
@@ -53,11 +53,6 @@ static int output_file_format_default_type_gauge(struct fieldstat_instance *inst
{
continue;
}
- if(metric->is_invisible == 1)
- {
- value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
- continue;
- }
value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0);
memset(tags_buf, 0, sizeof(tags_buf));
@@ -115,11 +110,6 @@ static int output_file_format_default_type_counter(struct fieldstat_instance *in
{
continue;
}
- if(metric->is_invisible == 1)
- {
- get_metric_unit_val(metric, FS_CALC_CURRENT, 0);
- continue;
- }
metric_id[metric_cnt] = i;
metric_cnt++;
}
@@ -481,8 +471,8 @@ int output_file_format_json(struct fieldstat_instance *instance, int n_cur_metri
cJSON_AddStringToObject(tmp_obj, "column_name", metric->table->column_name[metric->table_column_id]);
}
metric->field_type == FIELD_TYPE_COUNTER
- ?cJSON_AddStringToObject(tmp_obj, "type", "gauge")
- :cJSON_AddStringToObject(tmp_obj, "type", "counter");
+ ?cJSON_AddStringToObject(tmp_obj, "type", "counter")
+ :cJSON_AddStringToObject(tmp_obj, "type", "gauge");
value = get_metric_unit_val(metric, FS_CALC_CURRENT, 1);
cJSON_AddNumberToObject(tmp_obj, "acc", value);
value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
@@ -560,7 +550,7 @@ int output_file_format_json(struct fieldstat_instance *instance, int n_cur_metri
}
-int fieldstat_output_file(struct fieldstat_instance *instance,long long interval_ms)
+int file_output(struct fieldstat_instance *instance,long long interval_ms)
{
int used_len = 0;
int current_table_cnt = 0;
diff --git a/src/line_protocol_output.cpp b/src/line_protocol_output.cpp
index bead3ca..372db3d 100644
--- a/src/line_protocol_output.cpp
+++ b/src/line_protocol_output.cpp
@@ -84,12 +84,16 @@ static int add_user_tag_set(struct metric *metric, char *line_buf, unsigned int
return used_len;
}
-static long long read_single_metric_value(struct metric *metric)
+static long long read_single_metric_value(struct metric *metric, int output_type)
{
long long value = 0;
+ int is_refer = 1;
+ (output_type >= 4 && output_type < 8)
+ ?is_refer = 0
+ :is_refer = 1;
metric->field_type == FIELD_TYPE_GAUGE
- ?value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0)
- :value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ ?value = get_metric_unit_val(metric, FS_CALC_CURRENT, is_refer)
+ :value = get_metric_unit_val(metric, FS_CALC_SPEED, is_refer);
return value;
}
@@ -141,12 +145,12 @@ static int add_table_row_field_set(char *column_name[], long long *row_value, in
-static int build_single_metric_line_buf(char *instance_name, struct metric *metric, char *line_buf, int line_buf_size)
+static int build_single_metric_line_buf(char *instance_name, int output_type, struct metric *metric, char *line_buf, int line_buf_size)
{
int used_len = 0;
long long value = 0;
- value = read_single_metric_value(metric);
+ value = read_single_metric_value(metric, output_type);
if(value == 0)
{
@@ -169,7 +173,7 @@ static int build_single_metric_line_buf(char *instance_name, struct metric *metr
}
-static int read_table_row_value(struct metric **row_metric, int n_column, long long *out_row_value)
+static int read_table_row_value(struct metric **row_metric, int output_type, int n_column, long long *out_row_value)
{
int i = 0;
struct metric *metric = NULL;
@@ -182,13 +186,13 @@ static int read_table_row_value(struct metric **row_metric, int n_column, long l
for(i = 0; i < n_column; i++)
{
metric = row_metric[i];
- out_row_value[i] = read_single_metric_value(metric);
+ out_row_value[i] = read_single_metric_value(metric, output_type);
}
return 0;
}
-static int build_table_row_line_buf(char *instance_name, struct table_metric *table, struct metric **row_metric, char *line_buf, int line_buf_size)
+static int build_table_row_line_buf(char *instance_name, int output_type, struct table_metric *table, struct metric **row_metric, char *line_buf, int line_buf_size)
{
int used_len = 0;
struct metric *metric = NULL;
@@ -199,7 +203,7 @@ static int build_table_row_line_buf(char *instance_name, struct table_metric *ta
}
long long row_value[table->column_cnt];
- if(-1 == read_table_row_value(row_metric, table->column_cnt, row_value))
+ if(-1 == read_table_row_value(row_metric, output_type, table->column_cnt, row_value))
{
return 0;
}
@@ -245,7 +249,7 @@ static void output_line_protocol_single_metric(struct fieldstat_instance *instan
}
memset(line_buf, 0, sizeof(line_buf));
- used_len = build_single_metric_line_buf(instance->name, metric, line_buf, sizeof(line_buf));
+ used_len = build_single_metric_line_buf(instance->name, instance->output_type, metric, line_buf, sizeof(line_buf));
send_line_buf(&instance->line_protocol_output, line_buf, used_len);
}
@@ -280,7 +284,7 @@ static void output_line_protocol_table_row(struct fieldstat_instance *instance,
row_metrics[k] = get_metric(instance, row->metric_id_belong_to_line[k]);
}
- used_len = build_table_row_line_buf(instance->name, table, row_metrics, line_buf, sizeof(line_buf));
+ used_len = build_table_row_line_buf(instance->name, instance->output_type, table, row_metrics, line_buf, sizeof(line_buf));
send_line_buf(&instance->line_protocol_output, line_buf, used_len);
}
@@ -330,11 +334,11 @@ int line_protocol_dynamic_metric_output(struct fieldstat_dynamic_instance *insta
memset(line_buf, 0, sizeof(line_buf));
if(metric->table)
{
- used_len = build_table_row_line_buf(instance->name, metric->table, metrics, line_buf, sizeof(line_buf));
+ used_len = build_table_row_line_buf(instance->name, instance->output_type, metric->table, metrics, line_buf, sizeof(line_buf));
}
else
{
- used_len = build_single_metric_line_buf(instance->name, metric, line_buf, sizeof(line_buf));
+ used_len = build_single_metric_line_buf(instance->name, instance->output_type, metric, line_buf, sizeof(line_buf));
}
send_line_buf(&instance->line_protocol_output, line_buf, used_len);
}
diff --git a/src/prometheus_output.cpp b/src/prometheus_output.cpp
index 2b605e8..a4e4d88 100644
--- a/src/prometheus_output.cpp
+++ b/src/prometheus_output.cpp
@@ -129,14 +129,14 @@ static void prometheus_output_uri_list(struct prometheus_endpoint_instance *prom
static int prometheus_output_read_metric_tags(struct metric *metric, char *instance_name, char *tags_buf, unsigned int size)
{
int i = 0;//used_len = 0;
- char unescape[STR_LEN_256] = {0};
+ char unescape[256] = {0};
int used_len = 0;
used_len += snprintf(tags_buf + used_len, size - used_len, "app_name=\"%s\"", instance_name);
if(metric->table)
{
- used_len += snprintf(tags_buf + used_len, size - used_len, ",line_name=\"%s\"", metric->field_name);
+ used_len += snprintf(tags_buf + used_len, size - used_len, ",table_name=\"%s\",line_name=\"%s\"", metric->table->name, metric->field_name);
}
for(i = 0; i < (int)metric->n_tag; i++)
@@ -322,7 +322,9 @@ static int prometheus_get_instance_metric_playload(struct fieldstat_instance *in
{
case FIELD_TYPE_COUNTER:
case FIELD_TYPE_GAUGE:
- value = get_metric_unit_val(metric, FS_CALC_CURRENT, 1);
+ instance->output_type == 1
+ ?value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0)
+ :value = get_metric_unit_val(metric, FS_CALC_CURRENT, 1);
append_offset += snprintf(new_payload + append_offset,
new_payload_size - append_offset,
"%s{%s} %lld\n",
@@ -443,6 +445,7 @@ int fieldstat_enable_prometheus_output(struct fieldstat_instance *instance)
fs_instance_id = g_prometheus_endpoint_instance.fs_instance_cnt++;
g_prometheus_endpoint_instance.fs_instance[fs_instance_id] = instance;
+ instance->output_type |= 1;
return 0;
}
diff --git a/test/src/CMakeLists.txt b/test/src/CMakeLists.txt
index fa02909..044eb5d 100644
--- a/test/src/CMakeLists.txt
+++ b/test/src/CMakeLists.txt
@@ -6,9 +6,14 @@ 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)
-add_executable(gtest_fieldstat ${SRC} gtest_fieldstat.cpp)
-target_link_libraries(gtest_fieldstat gtest-static)
+add_executable(gtest_fieldstat_interface ${SRC} gtest_fieldstat_interface.cpp)
+target_link_libraries(gtest_fieldstat_interface gtest-static)
+add_executable(gtest_fieldstat_output ${SRC} gtest_fieldstat_output.cpp)
+target_link_libraries(gtest_fieldstat_output gtest-static)
add_executable(gtest_dynamic_fieldstat ${SRC} gtest_dynamic_fieldstat.cpp)
target_link_libraries(gtest_dynamic_fieldstat gtest-static)
+
+add_executable(gtest_dynamic_fieldstat_output ${SRC} gtest_dynamic_fieldstat_output.cpp)
+target_link_libraries(gtest_dynamic_fieldstat_output gtest-static) \ No newline at end of file
diff --git a/test/src/gtest_dynamic_fieldstat_output.cpp b/test/src/gtest_dynamic_fieldstat_output.cpp
new file mode 100644
index 0000000..fb066c4
--- /dev/null
+++ b/test/src/gtest_dynamic_fieldstat_output.cpp
@@ -0,0 +1,126 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <gtest/gtest.h>
+#include "fieldstat.h"
+#include "fieldstat_internal.h"
+#include "cJSON.h"
+
+extern struct prometheus_endpoint_instance g_prometheus_endpoint_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);
+ usleep(1000);
+ }
+ return;
+}
+void * worker_thread_multi_incrby(void *arg)
+{
+ _worker_thread_multi_incrby(arg);
+ usleep(1000 * 100);
+ return NULL;
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceMultiIncrby)
+{
+ int ret = 0;
+ int n_thread = 64;
+ int n_loops = 100000;
+
+ 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);
+ 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);
+ system("cat /dev/null > /tmp/metrics.out");
+ fieldstat_dynamic_instance_start(instance);
+
+ 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);
+ }
+ sleep(6);
+ fieldstat_dynamic_instance_free(instance);
+}
+
+int main(int argc, char *argv[])
+{
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+} \ No newline at end of file
diff --git a/test/src/gtest_fieldstat.cpp b/test/src/gtest_fieldstat_interface.cpp
index 6683a31..558f267 100644
--- a/test/src/gtest_fieldstat.cpp
+++ b/test/src/gtest_fieldstat_interface.cpp
@@ -291,6 +291,7 @@ TEST(FeildStatAPI, FieldStatLineProtocolOutputTableMetric)
ret = fieldstat_set_line_protocol_server(instance, "127.0.0.1", 8600);
EXPECT_EQ(0, ret);
+ EXPECT_EQ(4, instance->output_type);
ret = fieldstat_disable_background_thread(instance);
EXPECT_EQ(0, ret);
fieldstat_instance_start(instance);
diff --git a/test/src/gtest_fieldstat_output.cpp b/test/src/gtest_fieldstat_output.cpp
new file mode 100644
index 0000000..9ae18de
--- /dev/null
+++ b/test/src/gtest_fieldstat_output.cpp
@@ -0,0 +1,694 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <gtest/gtest.h>
+#include "fieldstat.h"
+#include "fieldstat_internal.h"
+
+extern struct prometheus_endpoint_instance g_prometheus_endpoint_instance;
+
+TEST(FeildStatOutput, OutputFile)
+{
+ int ret = 0;
+ int n_loops = 4;
+ struct fieldstat_instance * instance = NULL;
+ int table_id = -1;
+ FILE *fp;
+ char read_line_buf[2048] = {0};
+
+ int output_metric_ids[54] = {0};
+
+ const char *output_file_path = "/tmp/fieldstat.txt";
+ const char *table_column = "network_activity new_conn_num established_conn_num"
+ " close_conn_num total_in_bytes total_out_bytes total_in_packets "
+ "total_out_packets default_conn_num default_in_bytes default_out_bytes "
+ "default_in_packets default_out_packets allow_conn_num allow_in_bytes "
+ "allow_out_bytes allow_in_packets allow_out_packets deny_conn_num "
+ "deny_in_bytes deny_out_bytes deny_in_packets deny_out_packets monitor_conn_num "
+ "monitor_in_bytes monitor_out_bytes monitor_in_packets monitor_out_packets intercept_conn_num "
+ "intercept_in_bytes intercept_out_bytes intercept_in_packets intercept_out_packets "
+ "ipv4_in_packets ipv4_in_bytes ipv4_out_packetsipv4_out_bytes ipv6_in_packets ipv6_in_bytes "
+ "ipv6_out_packets ipv6_out_bytes tcp_conn_num tcp_in_packets tcp_in_bytes tcp_out_packets "
+ "tcp_out_bytes udp_conn_num udp_in_packets udp_in_bytes udp_out_packets udp_out_bytes "
+ "alert_bytes block_bytes pinning_num maybe_pinning_num not_pinning_num\n";
+
+ const char *table_row_value = "TRAFFIC 1000 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 \n";
+
+ const char *table_column_name[] = {"new_conn_num", "established_conn_num", "close_conn_num", "total_in_bytes", "total_out_bytes", "total_in_packets",
+ "total_out_packets", "default_conn_num", "default_in_bytes", "default_out_bytes", "default_in_packets", "default_out_packets", "allow_conn_num",
+ "allow_in_bytes", "allow_out_bytes", "allow_in_packets", "allow_out_packets", "deny_conn_num", "deny_in_bytes", "deny_out_bytes", "deny_in_packets",
+ "deny_out_packets", "monitor_conn_num", "monitor_in_bytes", "monitor_out_bytes", "monitor_in_packets", "monitor_out_packets", "intercept_conn_num",
+ "intercept_in_bytes", "intercept_out_bytes", "intercept_in_packets", "intercept_out_packets", "ipv4_in_packets", "ipv4_in_bytes", "ipv4_out_packets"
+ "ipv4_out_bytes", "ipv6_in_packets", "ipv6_in_bytes", "ipv6_out_packets", "ipv6_out_bytes", "tcp_conn_num", "tcp_in_packets", "tcp_in_bytes",
+ "tcp_out_packets", "tcp_out_bytes", "udp_conn_num", "udp_in_packets", "udp_in_bytes", "udp_out_packets", "udp_out_bytes", "alert_bytes", "block_bytes",
+ "pinning_num", "maybe_pinning_num", "not_pinning_num"};
+ enum field_type table_column_type[54] = {FIELD_TYPE_COUNTER};
+
+ instance = fieldstat_instance_new("tsg_statistic");
+ EXPECT_STREQ("tsg_statistic", instance->name);
+
+ table_id = fieldstat_register_table(instance, "network_activity", table_column_name, table_column_type, sizeof(table_column_name)/sizeof(table_column_name[0]));
+ EXPECT_EQ(0, table_id);
+ ret = fieldstat_register_table_row(instance, table_id, "TRAFFIC", NULL, 0, output_metric_ids);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_set_local_output(instance, output_file_path, "default");
+ EXPECT_EQ(0, ret);
+ fieldstat_instance_start(instance);
+ fieldstat_value_incrby(instance, output_metric_ids[0], 1000);
+ sleep(3);
+ fp = fopen(output_file_path, "r");
+ EXPECT_NE(nullptr, fp);
+ int n_line = 0;
+
+ while(!feof(fp))
+ {
+ if(NULL == fgets(read_line_buf, sizeof(read_line_buf), fp))
+ {
+ continue;
+ }
+ if(n_line == 1)
+ {
+ EXPECT_STREQ(table_column, read_line_buf);
+ }
+ if(n_line == 2)
+ {
+ EXPECT_STREQ(table_row_value, read_line_buf);
+ }
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(n_line, n_loops);
+ fieldstat_instance_free(instance);
+
+}
+
+
+TEST(FeildStatOutput, OutputLineProtocol)
+{
+ int ret = 0;
+ int n_loops = 1;
+ struct fieldstat_instance * instance = NULL;
+ int table_id = -1;
+ int output_metric_ids[54] = {0};
+ const char *telegraf_output_file = "/tmp/metrics.out";
+ FILE *fp;
+ char line[2048] = {0};
+ cJSON *cjson_metric = NULL;
+ cJSON *cjson_tags = NULL;
+ const char *compare = "{\"fields\":{\"alert_bytes\":0,\"allow_conn_num\":0,\"allow_in_bytes\":0,\"allow_in_packets\":0,\"allow_out_bytes\":0,"\
+ "\"allow_out_packets\":0,\"block_bytes\":0,\"close_conn_num\":0,\"default_conn_num\":0,\"default_in_bytes\":0,"\
+ "\"default_in_packets\":0,\"default_out_bytes\":0,\"default_out_packets\":0,\"deny_conn_num\":0,\"deny_in_bytes\":0,"\
+ "\"deny_in_packets\":0,\"deny_out_bytes\":0,\"deny_out_packets\":0,\"established_conn_num\":0,\"intercept_conn_num\":0,"\
+ "\"intercept_in_bytes\":0,\"intercept_in_packets\":0,\"intercept_out_bytes\":0,\"intercept_out_packets\":0,"\
+ "\"ipv4_in_bytes\":0,\"ipv4_in_packets\":0,\"ipv4_out_packetsipv4_out_bytes\":0,\"ipv6_in_bytes\":0,\"ipv6_in_packets\":0,"\
+ "\"ipv6_out_bytes\":0,\"ipv6_out_packets\":0,\"maybe_pinning_num\":0,\"monitor_conn_num\":0,\"monitor_in_bytes\":0,"\
+ "\"monitor_in_packets\":0,\"monitor_out_bytes\":0,\"monitor_out_packets\":0,\"new_conn_num\":1000,\"not_pinning_num\":0,"\
+ "\"pinning_num\":0,\"tcp_conn_num\":0,\"tcp_in_bytes\":0,\"tcp_in_packets\":0,\"tcp_out_bytes\":0,\"tcp_out_packets\":0,"\
+ "\"total_in_bytes\":0,\"total_in_packets\":0,\"total_out_bytes\":0,\"total_out_packets\":0,\"udp_conn_num\":0,"\
+ "\"udp_in_bytes\":0,\"udp_in_packets\":0,\"udp_out_bytes\":0,\"udp_out_packets\":0},\"name\":\"TRAFFIC\","\
+ "\"tags\":{\"app_name\":\"tsg_statistic\",\"table_name\":\"network_activity\"}}";
+ char *cjson_metric_str = NULL;
+
+ const char *table_column_name[] = {"new_conn_num", "established_conn_num", "close_conn_num", "total_in_bytes", "total_out_bytes", "total_in_packets",
+ "total_out_packets", "default_conn_num", "default_in_bytes", "default_out_bytes", "default_in_packets", "default_out_packets", "allow_conn_num",
+ "allow_in_bytes", "allow_out_bytes", "allow_in_packets", "allow_out_packets", "deny_conn_num", "deny_in_bytes", "deny_out_bytes", "deny_in_packets",
+ "deny_out_packets", "monitor_conn_num", "monitor_in_bytes", "monitor_out_bytes", "monitor_in_packets", "monitor_out_packets", "intercept_conn_num",
+ "intercept_in_bytes", "intercept_out_bytes", "intercept_in_packets", "intercept_out_packets", "ipv4_in_packets", "ipv4_in_bytes", "ipv4_out_packets"
+ "ipv4_out_bytes", "ipv6_in_packets", "ipv6_in_bytes", "ipv6_out_packets", "ipv6_out_bytes", "tcp_conn_num", "tcp_in_packets", "tcp_in_bytes",
+ "tcp_out_packets", "tcp_out_bytes", "udp_conn_num", "udp_in_packets", "udp_in_bytes", "udp_out_packets", "udp_out_bytes", "alert_bytes", "block_bytes",
+ "pinning_num", "maybe_pinning_num", "not_pinning_num"};
+ enum field_type table_column_type[54] = {FIELD_TYPE_COUNTER};
+
+ instance = fieldstat_instance_new("tsg_statistic");
+ EXPECT_STREQ("tsg_statistic", instance->name);
+
+ table_id = fieldstat_register_table(instance, "network_activity", table_column_name, table_column_type, sizeof(table_column_name)/sizeof(table_column_name[0]));
+ EXPECT_EQ(0, table_id);
+ ret = fieldstat_register_table_row(instance, table_id, "TRAFFIC", NULL, 0, output_metric_ids);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_set_line_protocol_server(instance, "127.0.0.1", 8600);
+ EXPECT_EQ(0, ret);
+ EXPECT_EQ(4, instance->output_type);
+ fieldstat_instance_start(instance);
+ fieldstat_value_incrby(instance, output_metric_ids[0], 1000);
+ ret = system("cat /dev/null > /tmp/metrics.out");
+ sleep(3);
+ 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");
+ cjson_metric_str = cJSON_PrintUnformatted(cjson_metric);
+ EXPECT_NE(nullptr, cjson_metric_str);
+ if(cjson_metric_str)
+ {
+ EXPECT_STREQ(compare, cjson_metric_str);
+ free(cjson_metric_str);
+ cjson_metric_str = NULL;
+ }
+ cJSON_Delete(cjson_metric);
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(n_line, n_loops);
+
+ fieldstat_instance_free(instance);
+
+}
+
+TEST(FeildStatOutput, OutputPrometheus)
+{
+ int ret = 0;
+ int table_id = -1;
+ int n_loops = 54;
+ int output_metric_ids[54] = {0};
+ struct fieldstat_instance * instance = NULL;
+ FILE *fp;
+ const char *prometheus_output_file = "/tmp/prometheus.txt";
+ char line[2048] = {0};
+ const char *compare = "tsg_statistic_new_conn_num{app_name=\"tsg_statistic\",table_name=\"network_activity\",line_name=\"TRAFFIC\"} 1000\n";
+
+ const char *table_column_name[] = {"new_conn_num", "established_conn_num", "close_conn_num", "total_in_bytes", "total_out_bytes", "total_in_packets",
+ "total_out_packets", "default_conn_num", "default_in_bytes", "default_out_bytes", "default_in_packets", "default_out_packets", "allow_conn_num",
+ "allow_in_bytes", "allow_out_bytes", "allow_in_packets", "allow_out_packets", "deny_conn_num", "deny_in_bytes", "deny_out_bytes", "deny_in_packets",
+ "deny_out_packets", "monitor_conn_num", "monitor_in_bytes", "monitor_out_bytes", "monitor_in_packets", "monitor_out_packets", "intercept_conn_num",
+ "intercept_in_bytes", "intercept_out_bytes", "intercept_in_packets", "intercept_out_packets", "ipv4_in_packets", "ipv4_in_bytes", "ipv4_out_packets"
+ "ipv4_out_bytes", "ipv6_in_packets", "ipv6_in_bytes", "ipv6_out_packets", "ipv6_out_bytes", "tcp_conn_num", "tcp_in_packets", "tcp_in_bytes",
+ "tcp_out_packets", "tcp_out_bytes", "udp_conn_num", "udp_in_packets", "udp_in_bytes", "udp_out_packets", "udp_out_bytes", "alert_bytes", "block_bytes",
+ "pinning_num", "maybe_pinning_num", "not_pinning_num"};
+ enum field_type table_column_type[54] = {FIELD_TYPE_COUNTER};
+
+ instance = fieldstat_instance_new("tsg_statistic");
+ EXPECT_STREQ("tsg_statistic", instance->name);
+
+ table_id = fieldstat_register_table(instance, "network_activity", table_column_name, table_column_type, sizeof(table_column_name)/sizeof(table_column_name[0]));
+ EXPECT_EQ(0, table_id);
+ ret = fieldstat_register_table_row(instance, table_id, "TRAFFIC", NULL, 0, output_metric_ids);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_global_enable_prometheus_endpoint(9020, NULL);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_enable_prometheus_output(instance);
+ EXPECT_EQ(0, ret);
+ fieldstat_instance_start(instance);
+ fieldstat_value_incrby(instance, output_metric_ids[0], 1000);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ system("cat /dev/null > /tmp/prometheus.txt");
+ system("curl -s http://127.0.0.1:9020/metrics -o /tmp/prometheus.txt");
+
+ int n_line = 0;
+ fp = fopen(prometheus_output_file, "r");
+ EXPECT_NE(nullptr, fp);
+ while(!feof(fp))
+ {
+ if(NULL == fgets(line, sizeof(line), fp))
+ {
+ continue;
+ }
+ if(n_line == 0)
+ {
+ EXPECT_STREQ(compare, line);
+ }
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(n_line, n_loops);
+
+ fieldstat_global_disable_prometheus_endpoint();
+ fieldstat_instance_free(instance);
+}
+
+TEST(FeildStatOutput, OutputFileAndLineProtocol)
+{
+ int ret = 0;
+ int n_loops = 1;
+ struct fieldstat_instance * instance = NULL;
+ int table_id = -1;
+ int output_metric_ids[54] = {0};
+ const char *telegraf_output_file = "/tmp/metrics.out";
+ FILE *fp;
+ char line[2048] = {0};
+ char read_line_buf[2048] = {0};
+ cJSON *cjson_metric = NULL;
+ cJSON *cjson_tags = NULL;
+
+ const char *output_file_path = "/tmp/fieldstat.txt";
+ const char *table_column = "network_activity new_conn_num established_conn_num"
+ " close_conn_num total_in_bytes total_out_bytes total_in_packets "
+ "total_out_packets default_conn_num default_in_bytes default_out_bytes "
+ "default_in_packets default_out_packets allow_conn_num allow_in_bytes "
+ "allow_out_bytes allow_in_packets allow_out_packets deny_conn_num "
+ "deny_in_bytes deny_out_bytes deny_in_packets deny_out_packets monitor_conn_num "
+ "monitor_in_bytes monitor_out_bytes monitor_in_packets monitor_out_packets intercept_conn_num "
+ "intercept_in_bytes intercept_out_bytes intercept_in_packets intercept_out_packets "
+ "ipv4_in_packets ipv4_in_bytes ipv4_out_packetsipv4_out_bytes ipv6_in_packets ipv6_in_bytes "
+ "ipv6_out_packets ipv6_out_bytes tcp_conn_num tcp_in_packets tcp_in_bytes tcp_out_packets "
+ "tcp_out_bytes udp_conn_num udp_in_packets udp_in_bytes udp_out_packets udp_out_bytes "
+ "alert_bytes block_bytes pinning_num maybe_pinning_num not_pinning_num\n";
+
+ const char *table_row_value = "TRAFFIC 1000 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 \n";
+
+
+ const char *compare = "{\"fields\":{\"alert_bytes\":0,\"allow_conn_num\":0,\"allow_in_bytes\":0,\"allow_in_packets\":0,\"allow_out_bytes\":0,"\
+ "\"allow_out_packets\":0,\"block_bytes\":0,\"close_conn_num\":0,\"default_conn_num\":0,\"default_in_bytes\":0,"\
+ "\"default_in_packets\":0,\"default_out_bytes\":0,\"default_out_packets\":0,\"deny_conn_num\":0,\"deny_in_bytes\":0,"\
+ "\"deny_in_packets\":0,\"deny_out_bytes\":0,\"deny_out_packets\":0,\"established_conn_num\":0,\"intercept_conn_num\":0,"\
+ "\"intercept_in_bytes\":0,\"intercept_in_packets\":0,\"intercept_out_bytes\":0,\"intercept_out_packets\":0,"\
+ "\"ipv4_in_bytes\":0,\"ipv4_in_packets\":0,\"ipv4_out_packetsipv4_out_bytes\":0,\"ipv6_in_bytes\":0,\"ipv6_in_packets\":0,"\
+ "\"ipv6_out_bytes\":0,\"ipv6_out_packets\":0,\"maybe_pinning_num\":0,\"monitor_conn_num\":0,\"monitor_in_bytes\":0,"\
+ "\"monitor_in_packets\":0,\"monitor_out_bytes\":0,\"monitor_out_packets\":0,\"new_conn_num\":1000,\"not_pinning_num\":0,"\
+ "\"pinning_num\":0,\"tcp_conn_num\":0,\"tcp_in_bytes\":0,\"tcp_in_packets\":0,\"tcp_out_bytes\":0,\"tcp_out_packets\":0,"\
+ "\"total_in_bytes\":0,\"total_in_packets\":0,\"total_out_bytes\":0,\"total_out_packets\":0,\"udp_conn_num\":0,"\
+ "\"udp_in_bytes\":0,\"udp_in_packets\":0,\"udp_out_bytes\":0,\"udp_out_packets\":0},\"name\":\"TRAFFIC\","\
+ "\"tags\":{\"app_name\":\"tsg_statistic\",\"table_name\":\"network_activity\"}}";
+ char *cjson_metric_str = NULL;
+
+ const char *table_column_name[] = {"new_conn_num", "established_conn_num", "close_conn_num", "total_in_bytes", "total_out_bytes", "total_in_packets",
+ "total_out_packets", "default_conn_num", "default_in_bytes", "default_out_bytes", "default_in_packets", "default_out_packets", "allow_conn_num",
+ "allow_in_bytes", "allow_out_bytes", "allow_in_packets", "allow_out_packets", "deny_conn_num", "deny_in_bytes", "deny_out_bytes", "deny_in_packets",
+ "deny_out_packets", "monitor_conn_num", "monitor_in_bytes", "monitor_out_bytes", "monitor_in_packets", "monitor_out_packets", "intercept_conn_num",
+ "intercept_in_bytes", "intercept_out_bytes", "intercept_in_packets", "intercept_out_packets", "ipv4_in_packets", "ipv4_in_bytes", "ipv4_out_packets"
+ "ipv4_out_bytes", "ipv6_in_packets", "ipv6_in_bytes", "ipv6_out_packets", "ipv6_out_bytes", "tcp_conn_num", "tcp_in_packets", "tcp_in_bytes",
+ "tcp_out_packets", "tcp_out_bytes", "udp_conn_num", "udp_in_packets", "udp_in_bytes", "udp_out_packets", "udp_out_bytes", "alert_bytes", "block_bytes",
+ "pinning_num", "maybe_pinning_num", "not_pinning_num"};
+ enum field_type table_column_type[54] = {FIELD_TYPE_COUNTER};
+
+ instance = fieldstat_instance_new("tsg_statistic");
+ EXPECT_STREQ("tsg_statistic", instance->name);
+
+ table_id = fieldstat_register_table(instance, "network_activity", table_column_name, table_column_type, sizeof(table_column_name)/sizeof(table_column_name[0]));
+ EXPECT_EQ(0, table_id);
+ ret = fieldstat_register_table_row(instance, table_id, "TRAFFIC", NULL, 0, output_metric_ids);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_set_line_protocol_server(instance, "127.0.0.1", 8600);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_set_local_output(instance, output_file_path, "default");
+ EXPECT_EQ(0, ret);
+
+ EXPECT_EQ(12, instance->output_type);
+ ret = system("cat /dev/null > /tmp/metrics.out");
+ ret = system("cat /dev/null > /tmp/fieldstat.txt");
+ fieldstat_instance_start(instance);
+ fieldstat_value_incrby(instance, output_metric_ids[0], 1000);
+ sleep(3);
+ int n_line = 0;
+ fp = fopen(telegraf_output_file, "r");
+ EXPECT_NE(nullptr, fp);
+ 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");
+ cjson_metric_str = cJSON_PrintUnformatted(cjson_metric);
+ EXPECT_NE(nullptr, cjson_metric_str);
+ if(cjson_metric_str)
+ {
+ EXPECT_STREQ(compare, cjson_metric_str);
+ free(cjson_metric_str);
+ cjson_metric_str = NULL;
+ }
+ cJSON_Delete(cjson_metric);
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(n_line, n_loops);
+
+ fp = fopen("/tmp/fieldstat.txt", "r");
+ EXPECT_NE(nullptr, fp);
+ n_line = 0;
+ n_loops = 4;
+
+ while(!feof(fp))
+ {
+ if(NULL == fgets(read_line_buf, sizeof(read_line_buf), fp))
+ {
+ continue;
+ }
+ if(n_line == 1)
+ {
+ EXPECT_STREQ(table_column, read_line_buf);
+ }
+ if(n_line == 2)
+ {
+ EXPECT_STREQ(table_row_value, read_line_buf);
+ }
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(n_line, n_loops);
+
+
+ fieldstat_instance_free(instance);
+
+}
+
+
+TEST(FeildStatOutput, OutputFileAndPrometheus)
+{
+ int ret = 0;
+ int n_loops = 0;
+ struct fieldstat_instance * instance = NULL;
+ int table_id = -1;
+ int output_metric_ids[54] = {0};
+ FILE *fp;
+ char line[2048] = {0};
+
+ const char *prometheus_output_path = "/tmp/prometheus.txt";
+ const char *file_output_path = "/tmp/fieldstat.txt";
+ const char *prometheus_output_result = "tsg_statistic_new_conn_num{app_name=\"tsg_statistic\",table_name=\"network_activity\",line_name=\"TRAFFIC\"} 1000\n";
+ const char *table_column = "network_activity new_conn_num established_conn_num"
+ " close_conn_num total_in_bytes total_out_bytes total_in_packets "
+ "total_out_packets default_conn_num default_in_bytes default_out_bytes "
+ "default_in_packets default_out_packets allow_conn_num allow_in_bytes "
+ "allow_out_bytes allow_in_packets allow_out_packets deny_conn_num "
+ "deny_in_bytes deny_out_bytes deny_in_packets deny_out_packets monitor_conn_num "
+ "monitor_in_bytes monitor_out_bytes monitor_in_packets monitor_out_packets intercept_conn_num "
+ "intercept_in_bytes intercept_out_bytes intercept_in_packets intercept_out_packets "
+ "ipv4_in_packets ipv4_in_bytes ipv4_out_packetsipv4_out_bytes ipv6_in_packets ipv6_in_bytes "
+ "ipv6_out_packets ipv6_out_bytes tcp_conn_num tcp_in_packets tcp_in_bytes tcp_out_packets "
+ "tcp_out_bytes udp_conn_num udp_in_packets udp_in_bytes udp_out_packets udp_out_bytes "
+ "alert_bytes block_bytes pinning_num maybe_pinning_num not_pinning_num\n";
+
+ const char *table_row_value = "TRAFFIC 1000 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 \n";
+
+
+
+ const char *table_column_name[] = {"new_conn_num", "established_conn_num", "close_conn_num", "total_in_bytes", "total_out_bytes", "total_in_packets",
+ "total_out_packets", "default_conn_num", "default_in_bytes", "default_out_bytes", "default_in_packets", "default_out_packets", "allow_conn_num",
+ "allow_in_bytes", "allow_out_bytes", "allow_in_packets", "allow_out_packets", "deny_conn_num", "deny_in_bytes", "deny_out_bytes", "deny_in_packets",
+ "deny_out_packets", "monitor_conn_num", "monitor_in_bytes", "monitor_out_bytes", "monitor_in_packets", "monitor_out_packets", "intercept_conn_num",
+ "intercept_in_bytes", "intercept_out_bytes", "intercept_in_packets", "intercept_out_packets", "ipv4_in_packets", "ipv4_in_bytes", "ipv4_out_packets"
+ "ipv4_out_bytes", "ipv6_in_packets", "ipv6_in_bytes", "ipv6_out_packets", "ipv6_out_bytes", "tcp_conn_num", "tcp_in_packets", "tcp_in_bytes",
+ "tcp_out_packets", "tcp_out_bytes", "udp_conn_num", "udp_in_packets", "udp_in_bytes", "udp_out_packets", "udp_out_bytes", "alert_bytes", "block_bytes",
+ "pinning_num", "maybe_pinning_num", "not_pinning_num"};
+ enum field_type table_column_type[54] = {FIELD_TYPE_COUNTER};
+
+ instance = fieldstat_instance_new("tsg_statistic");
+ EXPECT_STREQ("tsg_statistic", instance->name);
+
+ table_id = fieldstat_register_table(instance, "network_activity", table_column_name, table_column_type, sizeof(table_column_name)/sizeof(table_column_name[0]));
+ EXPECT_EQ(0, table_id);
+ ret = fieldstat_register_table_row(instance, table_id, "TRAFFIC", NULL, 0, output_metric_ids);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_set_local_output(instance, file_output_path, "default");
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_global_enable_prometheus_endpoint(9021, NULL);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_enable_prometheus_output(instance);
+ EXPECT_EQ(0, ret);
+
+ EXPECT_EQ(9, instance->output_type);
+ ret = system("cat /dev/null > /tmp/prometheus.txt");
+ ret = system("cat /dev/null > /tmp/fieldstat.txt");
+ fieldstat_instance_start(instance);
+ fieldstat_value_incrby(instance, output_metric_ids[0], 1000);
+ sleep(3);
+ system("curl -s http://127.0.0.1:9021/metrics -o /tmp/prometheus.txt");
+ int n_line = 0;
+
+ fp = fopen("/tmp/fieldstat.txt", "r");
+ EXPECT_NE(nullptr, fp);
+ n_line = 0;
+ n_loops = 4;
+
+ while(!feof(fp))
+ {
+ if(NULL == fgets(line, sizeof(line), fp))
+ {
+ continue;
+ }
+ if(n_line == 1)
+ {
+ EXPECT_STREQ(table_column, line);
+ }
+ if(n_line == 2)
+ {
+ EXPECT_STREQ(table_row_value, line);
+ }
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(n_line, n_loops);
+ n_loops = 54;
+ n_line = 0;
+ fp = fopen(prometheus_output_path, "r");
+ EXPECT_NE(nullptr, fp);
+ while(!feof(fp))
+ {
+ if(NULL == fgets(line, sizeof(line), fp))
+ {
+ continue;
+ }
+ if(n_line == 0)
+ {
+ EXPECT_STREQ(prometheus_output_result, line);
+ }
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(n_line, n_loops);
+ fieldstat_global_disable_prometheus_endpoint();
+ fieldstat_instance_free(instance);
+
+}
+
+TEST(FeildStatOutput, OutputFileAndPrometheusAndLineProtocol)
+{
+ int ret = 0;
+ int n_loops = 0;
+ struct fieldstat_instance * instance = NULL;
+ int table_id = -1;
+ int output_metric_ids[54] = {0};
+ FILE *fp;
+ char line[2048] = {0};
+
+ const char *prometheus_output_path = "/tmp/prometheus.txt";
+ const char *file_output_path = "/tmp/fieldstat.txt";
+ const char *telegraf_output_file = "/tmp/metrics.out";
+ const char *prometheus_output_result = "tsg_statistic_new_conn_num{app_name=\"tsg_statistic\",table_name=\"network_activity\",line_name=\"TRAFFIC\"} 1000\n";
+ const char *table_column = "network_activity new_conn_num established_conn_num"
+ " close_conn_num total_in_bytes total_out_bytes total_in_packets "
+ "total_out_packets default_conn_num default_in_bytes default_out_bytes "
+ "default_in_packets default_out_packets allow_conn_num allow_in_bytes "
+ "allow_out_bytes allow_in_packets allow_out_packets deny_conn_num "
+ "deny_in_bytes deny_out_bytes deny_in_packets deny_out_packets monitor_conn_num "
+ "monitor_in_bytes monitor_out_bytes monitor_in_packets monitor_out_packets intercept_conn_num "
+ "intercept_in_bytes intercept_out_bytes intercept_in_packets intercept_out_packets "
+ "ipv4_in_packets ipv4_in_bytes ipv4_out_packetsipv4_out_bytes ipv6_in_packets ipv6_in_bytes "
+ "ipv6_out_packets ipv6_out_bytes tcp_conn_num tcp_in_packets tcp_in_bytes tcp_out_packets "
+ "tcp_out_bytes udp_conn_num udp_in_packets udp_in_bytes udp_out_packets udp_out_bytes "
+ "alert_bytes block_bytes pinning_num maybe_pinning_num not_pinning_num\n";
+
+ const char *table_row_value = "TRAFFIC 1000 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 "
+ "0 0 0 0 \n";
+
+
+
+ const char *table_column_name[] = {"new_conn_num", "established_conn_num", "close_conn_num", "total_in_bytes", "total_out_bytes", "total_in_packets",
+ "total_out_packets", "default_conn_num", "default_in_bytes", "default_out_bytes", "default_in_packets", "default_out_packets", "allow_conn_num",
+ "allow_in_bytes", "allow_out_bytes", "allow_in_packets", "allow_out_packets", "deny_conn_num", "deny_in_bytes", "deny_out_bytes", "deny_in_packets",
+ "deny_out_packets", "monitor_conn_num", "monitor_in_bytes", "monitor_out_bytes", "monitor_in_packets", "monitor_out_packets", "intercept_conn_num",
+ "intercept_in_bytes", "intercept_out_bytes", "intercept_in_packets", "intercept_out_packets", "ipv4_in_packets", "ipv4_in_bytes", "ipv4_out_packets"
+ "ipv4_out_bytes", "ipv6_in_packets", "ipv6_in_bytes", "ipv6_out_packets", "ipv6_out_bytes", "tcp_conn_num", "tcp_in_packets", "tcp_in_bytes",
+ "tcp_out_packets", "tcp_out_bytes", "udp_conn_num", "udp_in_packets", "udp_in_bytes", "udp_out_packets", "udp_out_bytes", "alert_bytes", "block_bytes",
+ "pinning_num", "maybe_pinning_num", "not_pinning_num"};
+
+ cJSON *cjson_metric = NULL;
+ cJSON *cjson_tags = NULL;
+ const char *compare = "{\"fields\":{\"alert_bytes\":0,\"allow_conn_num\":0,\"allow_in_bytes\":0,\"allow_in_packets\":0,\"allow_out_bytes\":0,"\
+ "\"allow_out_packets\":0,\"block_bytes\":0,\"close_conn_num\":0,\"default_conn_num\":0,\"default_in_bytes\":0,"\
+ "\"default_in_packets\":0,\"default_out_bytes\":0,\"default_out_packets\":0,\"deny_conn_num\":0,\"deny_in_bytes\":0,"\
+ "\"deny_in_packets\":0,\"deny_out_bytes\":0,\"deny_out_packets\":0,\"established_conn_num\":0,\"intercept_conn_num\":0,"\
+ "\"intercept_in_bytes\":0,\"intercept_in_packets\":0,\"intercept_out_bytes\":0,\"intercept_out_packets\":0,"\
+ "\"ipv4_in_bytes\":0,\"ipv4_in_packets\":0,\"ipv4_out_packetsipv4_out_bytes\":0,\"ipv6_in_bytes\":0,\"ipv6_in_packets\":0,"\
+ "\"ipv6_out_bytes\":0,\"ipv6_out_packets\":0,\"maybe_pinning_num\":0,\"monitor_conn_num\":0,\"monitor_in_bytes\":0,"\
+ "\"monitor_in_packets\":0,\"monitor_out_bytes\":0,\"monitor_out_packets\":0,\"new_conn_num\":1000,\"not_pinning_num\":0,"\
+ "\"pinning_num\":0,\"tcp_conn_num\":0,\"tcp_in_bytes\":0,\"tcp_in_packets\":0,\"tcp_out_bytes\":0,\"tcp_out_packets\":0,"\
+ "\"total_in_bytes\":0,\"total_in_packets\":0,\"total_out_bytes\":0,\"total_out_packets\":0,\"udp_conn_num\":0,"\
+ "\"udp_in_bytes\":0,\"udp_in_packets\":0,\"udp_out_bytes\":0,\"udp_out_packets\":0},\"name\":\"TRAFFIC\","\
+ "\"tags\":{\"app_name\":\"tsg_statistic\",\"table_name\":\"network_activity\"}}";
+ char *cjson_metric_str = NULL;
+
+ enum field_type table_column_type[54] = {FIELD_TYPE_COUNTER};
+
+ instance = fieldstat_instance_new("tsg_statistic");
+ EXPECT_STREQ("tsg_statistic", instance->name);
+
+ table_id = fieldstat_register_table(instance, "network_activity", table_column_name, table_column_type, sizeof(table_column_name)/sizeof(table_column_name[0]));
+ EXPECT_EQ(0, table_id);
+ ret = fieldstat_register_table_row(instance, table_id, "TRAFFIC", NULL, 0, output_metric_ids);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_set_local_output(instance, file_output_path, "default");
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_global_enable_prometheus_endpoint(9022, NULL);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_enable_prometheus_output(instance);
+ EXPECT_EQ(0, ret);
+
+ EXPECT_EQ(9, instance->output_type);
+ ret = system("cat /dev/null > /tmp/prometheus.txt");
+ ret = system("cat /dev/null > /tmp/fieldstat.txt");
+ fieldstat_instance_start(instance);
+ fieldstat_value_incrby(instance, output_metric_ids[0], 1000);
+ sleep(3);
+ system("curl -s http://127.0.0.1:9022/metrics -o /tmp/prometheus.txt");
+ int n_line = 0;
+
+ fp = fopen("/tmp/fieldstat.txt", "r");
+ EXPECT_NE(nullptr, fp);
+ n_line = 0;
+ n_loops = 4;
+
+ while(!feof(fp))
+ {
+ if(NULL == fgets(line, sizeof(line), fp))
+ {
+ continue;
+ }
+ if(n_line == 1)
+ {
+ EXPECT_STREQ(table_column, line);
+ }
+ if(n_line == 2)
+ {
+ EXPECT_STREQ(table_row_value, line);
+ }
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(n_line, n_loops);
+ n_loops = 54;
+ n_line = 0;
+ fp = fopen(prometheus_output_path, "r");
+ EXPECT_NE(nullptr, fp);
+ while(!feof(fp))
+ {
+ if(NULL == fgets(line, sizeof(line), fp))
+ {
+ continue;
+ }
+ if(n_line == 0)
+ {
+ EXPECT_STREQ(prometheus_output_result, line);
+ }
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(n_line, n_loops);
+
+ n_loops = 1;
+ n_line = 0;
+ fp = fopen(telegraf_output_file, "r");
+ EXPECT_NE(nullptr, fp);
+
+ 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");
+ cjson_metric_str = cJSON_PrintUnformatted(cjson_metric);
+ EXPECT_NE(nullptr, cjson_metric_str);
+ if(cjson_metric_str)
+ {
+ EXPECT_STREQ(compare, cjson_metric_str);
+ free(cjson_metric_str);
+ cjson_metric_str = NULL;
+ }
+ cJSON_Delete(cjson_metric);
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(n_line, n_loops);
+
+ fieldstat_global_disable_prometheus_endpoint();
+ fieldstat_instance_free(instance);
+
+}
+
+
+int main(int argc, char *argv[])
+{
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+} \ No newline at end of file