summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfumingwei <[email protected]>2023-02-27 09:56:06 +0800
committerfumingwei <[email protected]>2023-02-27 10:56:42 +0800
commit5d0e57fe9b820805cfaf08eef278aa5a62ebb7b8 (patch)
tree503d91372845fbf635730ee4a936a6965ee40505
parentb2095aa2c9ade769c4772ec0fcc2f61e54e5f265 (diff)
feature:实现类型为counter和gauge的本地文件输出
-rw-r--r--inc/field_stat2.h120
-rw-r--r--inc/fieldstat.h108
-rw-r--r--src/MESA_field_stat.cpp1567
-rw-r--r--src/fieldstat.cpp596
-rw-r--r--src/fieldstat_internal.h82
-rw-r--r--test/fs2_test.cpp255
6 files changed, 851 insertions, 1877 deletions
diff --git a/inc/field_stat2.h b/inc/field_stat2.h
deleted file mode 100644
index 1d4e79f..0000000
--- a/inc/field_stat2.h
+++ /dev/null
@@ -1,120 +0,0 @@
-#ifndef H_SCREEN_STAT_H_INCLUDE
-#define H_SCREEN_STAT_H_INCLUDE
-#include <stdio.h>
-#include <time.h>
-#ifndef __cplusplus
-#error("This file should be compiled with C++ compiler")
-#endif
-
-enum field_dsp_style_t
-{
- FS_STYLE_FIELD=0,
- FS_STYLE_COLUMN,
- FS_STYLE_LINE,
- FS_STYLE_STATUS,
- FS_STYLE_HISTOGRAM
-};
-enum field_calc_algo
-{
- FS_CALC_CURRENT=0,
- FS_CALC_SPEED
-};
-enum field_op
-{
- FS_OP_ADD=1,
- FS_OP_SET,
- FS_OP_SUB
-};
-
-enum stats_output_format
-{
- FS_OUTPUT_STATSD=1,
- FS_OUTPUT_INFLUX_LINE=2
-};
-
-enum metris_output_format
-{
- FS_METRIS_OUTPUT_DEFAULT=0,
- FS_METRIS_OUTPUT_JSON=1
-};
-
-typedef void* screen_stat_handle_t;
-
-enum FS_option
-{
- OUTPUT_DEVICE, //VALUE is a const char*, indicate a file path string, SIZE = strlen(string+'\0')+1.DEFAULT:output to stdout.
- PRINT_MODE, //VALUE is an interger,1:Rewrite ,2: Append. SIZE=4,DEFALUT:REWRITE.
- STAT_CYCLE, //VALUE is an interger idicate interval seconds of every output, SIZE=4 ,DEFUALT:2 seconds.
- PRINT_TRIGGER, //VALUE is an interger,1:Do print,0: Don't print.SIZE=4.DEFAULT:1.
- CREATE_THREAD, //VALUE is an interger,1: Create a print thread,0:not create,output by call passive_output function,
- //and the STAT_CYCLE is meaningless.SIZE=4,DEFAULT:0.
- ID_INVISBLE, //value is field_id/status_id/column_id, not output this string, SIZE=4,DEFAULT: shutdown NO one.
- FLUSH_BY_DATE, //value is 1(true) or 0(false),SIZE=4,DEFAULT: Do not flush by date.
- APP_NAME, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. DEFAULT is "?".
- STATS_SERVER_IP, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. No DEFAULT.
- STATS_SERVER_PORT, //VALUE is a unsigned short or a signed int, host order, SIZE= sizeof(unsigned short) or sizeof(int). No DEFAULT.
- STATS_FORMAT, //VALUE is enum stats_output_format, STATSD or INFLUX_LINE, SIZE=sizeof(int), DEFAULT:STATSD.
- MAX_STAT_FIELD_NUM, //VALUE is an interger, SIZE=sizeof(int), DEFAULT:1024.
- HISTOGRAM_GLOBAL_BINS, //VALUE is a const char*, define a histogram bins for default field, SIZE = strlen(string+'\0')+1. DEFAULT: "0.5,0.8,0.9,0.95,0.99“.
- NOT_SEND_METRIC_TO_SERVER, //value is field_id/status_id/column_id, not output this string, SIZE=4,DEFAULT:Send.
- METRIS_FORMAT, //VALUE is enum metris_output_format, DEFAULT or JSON, SIZE=sizeof(int).
- OUTPUT_PROMETHEUS //VALUE is an interger,1:output prometheus ,0: not output. SIZE=4,DEFALUT: 0.
-};
-
-//Always success.
-screen_stat_handle_t FS_create_handle(void);
-
-int FS_set_para(screen_stat_handle_t handle, enum FS_option type,const void* value,int size);
-void FS_start(screen_stat_handle_t handle);
-void FS_stop(screen_stat_handle_t* handle);
-
-//return field_id/line_id/column_id greater than zero if success,return an interger less than zero if failed.
-//should NOT include "|:\n\r.\t<>[]#!@"or space in the parameter name.
-//Runtime rregister column is NOT allowed.
-int FS_register(screen_stat_handle_t handle,enum field_dsp_style_t style,enum field_calc_algo calc_type,const char* name);
-
-//numerator_id and denominator_id must be column/field/status style.
-//scaling: negative value: zoom in; positive value: zoom out;
-int FS_register_ratio(screen_stat_handle_t handle,int numerator_id,int denominator_id,int scaling,enum field_dsp_style_t style,enum field_calc_algo calc_type,const char* name);
-
-inline void record_time_start(struct timespec *start)
-{
- clock_gettime(CLOCK_MONOTONIC, start);
-}
-inline long record_time_elapse_us(struct timespec *start)
-{
- struct timespec end;
- long elapsed = 0;
- clock_gettime(CLOCK_MONOTONIC, &end);
- elapsed = (end.tv_sec - start->tv_sec)*1000000 + (end.tv_nsec - start->tv_nsec)/1000;
- return elapsed;
-}
-
-//@param bins format is comma spited number, e.g."0.1,0.5,0.8,0.9,0.95,0.99"
-//return 0 on success, <0 on failed.
-int FS_histogram_set_bins(screen_stat_handle_t handle, int id, const char* bins);
-
-//@param lowest_trackable_value >1
-//@param highest_trackable_value>lowest_trackable_value * 2
-//@param 1<significant_figures<4
-int FS_register_histogram(screen_stat_handle_t handle, enum field_calc_algo calc_type, const char* name,
- long long lowest_trackable_value,
- long long highest_trackable_value,
- int significant_figures);
-
-//id: when id's type is FIELD , column_id is ignored.
-int FS_operate(screen_stat_handle_t handle,int id,int column_id,enum field_op op,long long value);
-
-void FS_passive_output(screen_stat_handle_t handle);
-
-//@param default port is 9273
-//return 1 on success, 0 on failed.
-int FS_library_set_prometheus_port(unsigned short port);
-//@param default url_path is "/metrics"
-//return 1 on success, 0 on failed.
-int FS_library_set_prometheus_url_path(const char *url_path);
-int FS_library_init(void);
-void FS_library_destroy(void);
-
-#endif
-
diff --git a/inc/fieldstat.h b/inc/fieldstat.h
new file mode 100644
index 0000000..8746645
--- /dev/null
+++ b/inc/fieldstat.h
@@ -0,0 +1,108 @@
+#ifndef H_SCHEMA_STAT_H_INCLUDE
+#define H_SCHEMA_STAT_H_INCLUDE
+#include <stdio.h>
+#include <time.h>
+#include <pthread.h>
+#ifndef __cplusplus
+#error("This file should be compiled with C++ compiler")
+#endif
+
+
+#define URL_MAX_LEN 2048
+#define LEN_IP_MAX 32 //?????? 32 from document
+#define LEN_APP_NAME 32
+#define LEN_FORMAT_MAX 32
+#define LEN_PATH_MAX 256
+
+
+struct fieldstat_global_prometheus
+{
+ unsigned short port;
+ char *url_path;
+};
+
+struct fieldstat_instance
+{
+ //char *statsd_server_ip;
+ char statsd_server_str_ip[LEN_IP_MAX];
+ unsigned int statsd_server_ip;
+ unsigned short statsd_server_port;
+ int statsd_output_enable;
+
+ char line_protocol_server_str_ip[LEN_IP_MAX];
+ unsigned int line_protocol_server_ip;
+ unsigned short line_protocol_server_port;
+ int line_protocol_output_enable;
+
+ char local_output_filename[LEN_PATH_MAX];
+ char local_output_format[LEN_FORMAT_MAX];
+ int local_output_enable;
+
+ int background_thread_disable; //default:1
+ int output_interval_s; //default:2
+ char app_name[LEN_APP_NAME];
+ int running;
+
+ int metric_cnt;
+ int metric_size;
+ struct metric_t **metric;
+
+ int prometheus_output_enable;
+
+ int counter_cnt;
+ int gauge_cnt;
+ int histogram_cnt;
+ int summary_cnt;
+
+ struct timespec last_output_time;
+
+ pthread_t cfg_mon_t;
+
+ FILE* fp;
+};
+
+enum field_type
+{
+ FIELD_TYPE_COUNTER,
+ FIELD_TYPE_GAUGE,
+ FILED_TYPE_HISTOGRAM,
+ FIELD_TYPE_SUMMARY
+};
+
+/*
+ * @param listen_port
+ * @param url if NULL use "/metrics" default
+ * */
+struct fieldstat_instance * fieldstat_instance_create(void);
+int fieldstat_global_enable_prometheus_endpoint(unsigned short listen_port, const char *url); //TODO
+int fieldstat_prometheus_output_enable(struct fieldstat_instance *instance);
+int fieldstat_set_statsd_server(struct fieldstat_instance *instance, const char *ip, unsigned short port);
+int fieldstat_set_line_protocol_server(struct fieldstat_instance *instance, const char *ip, unsigned short port);
+int fieldstat_set_local_output(struct fieldstat_instance *instance, const char *filename, const char *format);//format could be "json" or "default"
+int fieldstat_backgroud_thead_disable(struct fieldstat_instance *instance);
+int fieldstat_set_output_interval(struct fieldstat_instance *instance, int seconds);//default is 2 seconds
+int fieldstat_set_app_name(struct fieldstat_instance *instance, const char *app_name);
+
+
+/*
+ * @param field_name the name of the field
+ * @type counter, gauge summary and histogram
+ * @n_tag size of tag_key[] and tag_value[]
+ * return field_id to be used in fieldstat_value_xxx(),
+ * -1 if an error occured.
+ * example field_name=packets, tag=[{"policy_id", "101"},{"profile_id", "a"}]
+ * ouput: accumulate value or delta value
+ * counter or histogram
+ * */
+int fieldstat_register(struct fieldstat_instance *instance, enum field_type type, const char *field_name, const char *tag_key[], const char *tag_value[], size_t n_tag);
+//int fieldstat_register_table(struct fieldstat_instance *instance, enum file_type table_type[], consul char *field_list[], size_t n_field);
+//int fieldstat_register_table_metrics(struct fieldstat_instance * instance, const char *tag_key[], const char *tag_value[]);
+
+int fieldstat_value_incrby(struct fieldstat_instance *instance, int field_id, long long increment);
+int fieldstat_value_set(struct fieldstat_instance *instance, int field_id, long long increment);
+int fieldstat_value_decrby(struct fieldstat_instance *instance, int field_id, long long decrment);
+
+void fieldstat_instance_start(struct fieldstat_instance *instance);
+void fieldstat_passive_output(struct fieldstat_instance *instance);
+
+#endif
diff --git a/src/MESA_field_stat.cpp b/src/MESA_field_stat.cpp
deleted file mode 100644
index 6528a94..0000000
--- a/src/MESA_field_stat.cpp
+++ /dev/null
@@ -1,1567 +0,0 @@
-#include "field_stat2.h"
-#include "field_stat_internal.h"
-#include "threadsafe_counter.h"
-#include "hdr_histogram.h"
-#include "cJSON.h"
-
-#include <sys/socket.h>//socket
-#include <sys/types.h>//socket
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <string.h> //strerror
-#include <errno.h>//strerror
-#include <fcntl.h>//fcntl
-#include <unistd.h>//fcntl
-#include <net/if.h>//fcntl
-#include <sys/ioctl.h>//ioctl
-#include <stdio.h>
-#include <time.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <pthread.h>
-#include <assert.h>
-#include <sys/time.h>
-
-double HISTOGRAM_DEFAULT_BINS[]={50.0, 80.0, 90.0, 95.0, 99.0};
-
-int FIELD_STAT_VERSION_2_8_20200805_fix_outOfBound=0;
-
-//Automatically generate the version number
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#define GIT_VERSION_CATTER(v) __attribute__((__used__)) const char * GIT_VERSION_##v = NULL
-#define GIT_VERSION_EXPEND(v) GIT_VERSION_CATTER(v)
-
-/* VERSION TAG */
-#ifdef GIT_VERSION
-GIT_VERSION_EXPEND(GIT_VERSION);
-#else
-static __attribute__((__used__)) const char * GIT_VERSION_UNKNOWN = NULL;
-#endif
-#undef GIT_VERSION_CATTER
-#undef GIT_VERSION_EXPEND
-
-#ifdef __cplusplus
-}
-#endif
-//endof Automatically generate the version number
-
-const char* draw_line="________________________________________________________________________________________________________________________________________________";
-const char* draw_boundary="============================================================";
-
-static char* __str_dup(const char* str)
-{
- char* dup=NULL;
- dup=(char*)calloc(sizeof(char),strlen(str)+1);
- memcpy(dup, str, strlen(str));
- return dup;
-}
-//histogram bins format example: "10,100,1000,2000" will return 4 bins which indicate 5 interval.
-static int parse_histogram_bin_format(const char* format, double **output_bins)
-{
- char *token=NULL,*sub_token=NULL,*saveptr;
- size_t i=0;
- int comma_num=0,ret=0;
- double *bins;
- char* dup_format=__str_dup(format);
- for(i=0;i<strlen(dup_format);i++)
- {
- if(dup_format[i]==',')
- {
- comma_num++;
- }
- }
- bins=(double*)calloc(sizeof(double),comma_num+1);
- for (token = dup_format,i=0; ; token= NULL, i++)
- {
- sub_token= strtok_r(token,",", &saveptr);
- if (sub_token == NULL)
- break;
- ret=sscanf(sub_token,"%lf",bins+i);
- if(bins[i]>1.0)
- {
- goto error_out;
- }
- bins[i] *= 100;
- if(ret!=1)
- {
- goto error_out;
- }
- }
- free(dup_format);
- *output_bins=bins;
- return i;
-error_out:
- free(dup_format);
- free(bins);
- return -1;
-}
-
-struct display_manifest_t* display_manifest_new(const char* name, enum field_dsp_style_t style,enum field_calc_algo calc_type)
-{
- struct display_manifest_t* p=(struct display_manifest_t*)calloc(sizeof(struct display_manifest_t),1);
- p->calc_type=calc_type;
- p->style=style;
- p->is_ratio=0;
- p->output_scaling=1;
- p->name=__str_dup(name);
- return p;
-}
-void display_manifest_free(struct display_manifest_t* p)
-{
- free(p->name);
- p->name=NULL;
- free(p);
- return;
-}
-
-static int send_udp(int sd, unsigned int dest_ip, unsigned short dest_port, const char * data, int len)
-{
- int to_send_len=len;
- int already_sended_len=0,this_sended_len=0;
- struct sockaddr_in addr;
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr =dest_ip;
- addr.sin_port = htons(dest_port);
-
- while(to_send_len>already_sended_len)
- {
- this_sended_len=sendto(sd,(void*)(data+already_sended_len),
- to_send_len-already_sended_len,
- 0,
- (struct sockaddr *)&(addr),
- sizeof(addr));
- if(this_sended_len==-1)
- {
- if((EAGAIN == errno)||( EINTR == errno )|| (EWOULDBLOCK==errno))
- {
- continue;
- }
- else
- {
- printf("FS2: at send,socket error: %d %s", errno, strerror(errno));
- return -1;
- }
- }
- already_sended_len=+this_sended_len;
- }
-
- return 0;
-}
-void flush_metric(struct FS_space_t* _handle)
-{
- if(_handle->snd_buf_off==0)
- {
- return;
- }
-
- if(_handle->server_port>0)
- {
- send_udp(_handle->statsd_socket, _handle->server_ip,(unsigned short) _handle->server_port, _handle->send_buff, _handle->snd_buf_off);
- }
-
- _handle->snd_buf_off=0;
- memset(_handle->send_buff,0,sizeof(_handle->send_buff));
- return;
-}
-void append_statsd_counter(struct FS_space_t* _handle,const char* name, long long value)
-{
- if(value==0)
- {
- return;
- }
-
- size_t max_output_len=strlen(name)+strlen(name)+20+14+strlen(_handle->app_name); //14: ,app_name=:|c\n;
- if(UDP_PAYLOAD_SIZE-_handle->snd_buf_off<max_output_len)
- {
- flush_metric(_handle);
- }
- _handle->snd_buf_off+=snprintf(_handle->send_buff+_handle->snd_buf_off,UDP_PAYLOAD_SIZE-_handle->snd_buf_off,
- "%s,app_name=%s:%lld|c\n",
- name,_handle->app_name,value);
- assert(_handle->snd_buf_off<=UDP_PAYLOAD_SIZE && _handle->snd_buf_off>=0);
- return;
-}
-void append_statsd_histogram(struct FS_space_t* _handle,const char* name, long long value, long long count)
-{
- if(count==0)
- {
- return;
- }
- size_t max_output_len=strlen(name)+strlen(name)+20+3+16+strlen(_handle->app_name); //20: %lld; 3: .%f; 16: ,app_name=:|h|@\n;
- if(UDP_PAYLOAD_SIZE-_handle->snd_buf_off<max_output_len)
- {
- flush_metric(_handle);
- }
-
- if(count==1)
- {
- _handle->snd_buf_off+=snprintf(_handle->send_buff+_handle->snd_buf_off,UDP_PAYLOAD_SIZE-_handle->snd_buf_off,
- "%s,app_name=%s:%lld|h\n",
- name,_handle->app_name,value);
- }
- else
- {
- _handle->snd_buf_off+=snprintf(_handle->send_buff+_handle->snd_buf_off,UDP_PAYLOAD_SIZE-_handle->snd_buf_off,
- "%s,app_name=%s:%lld|h|@%f\n",
- name,_handle->app_name,value, (double)1/count);
- }
- assert(_handle->snd_buf_off<=UDP_PAYLOAD_SIZE && _handle->snd_buf_off>=0);
- return;
-}
-
-
-void appen_influx_line(struct FS_space_t* _handle,const char* measurement, char *field_set)
-{
- if(field_set==NULL)
- {
- return;
- }
- if(UDP_PAYLOAD_SIZE-(unsigned int)_handle->snd_buf_off<strlen(measurement)+strlen(field_set)+strlen(_handle->app_name)+12)
- {
- flush_metric(_handle);
- }
- _handle->snd_buf_off+=snprintf(_handle->send_buff+_handle->snd_buf_off,UDP_PAYLOAD_SIZE-_handle->snd_buf_off,
- "%s,app_name=%s %s\n",
- measurement, _handle->app_name,field_set);
- return;
-}
-
-int is_valid_fs_name(const char* name)
-{
- const char* reserverd="|:\n\r. \t<>[]#!@";
- unsigned int i=0,j=0;
- for(i=0;i<strlen(name);i++)
- {
- for(j=0;j<strlen(reserverd);j++)
- if(name[i]==reserverd[j])
- {
- return 0;
- }
- }
- return 1;
-}
-int current_day(char* day_buff,int size)
-{
-
- int current_day;
- int year;
- int month;
- int day;
-
- time_t t;
- struct tm *local_time;
-
- t = time(NULL);
- local_time=localtime(&t);
-
- snprintf(day_buff, size,"%04d-%02d-%02d", (local_time->tm_year + 1900), (local_time->tm_mon + 1), local_time->tm_mday);
-
- year = local_time->tm_year + 1900;
- month = local_time->tm_mon + 1;
- day = local_time->tm_mday;
- current_day = year*10000 + month*100 + day;
-
- return current_day;
-}
-static int startup_udp()
-{
- int sd_udp=-1;
- int flags;
- if(-1==(sd_udp = socket(AF_INET, SOCK_DGRAM, 0)))
- {
- printf("FS2: socket error: %d %s, restart socket.", errno, strerror(errno));
- sd_udp=-1;
- }
- flags=fcntl(sd_udp,F_GETFL);
- flags|=O_NONBLOCK;
- if(fcntl(sd_udp,F_SETFL,flags)==-1)
- {
- printf("FS2: socket error: %d %s, restart socket.", errno, strerror(errno));
- sd_udp=-1;
- }
- int opt=1;
- if (setsockopt (sd_udp, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt) ) < 0) {
- printf("FS2:setsockopt error: %d %s, restart socket.", errno, strerror(errno));
- close (sd_udp);
- sd_udp=-1;
- return sd_udp;
- }
-
- return sd_udp;
-}
-
-void *fs2_thread_screen_print(void *arg);
-
-screen_stat_handle_t __attribute__((visibility("default"))) FS_create_handle(void)
-{
- struct FS_space_t* handle=(struct FS_space_t*)calloc(sizeof(struct FS_space_t),1);
- handle->screen_print_trigger=1;
- handle->print_mode=1;
- handle->write_mode="w";
- handle->stat_cycle=2;
- handle->create_thread=1;
- handle->display_size=INIT_STAT_FIELD_NUM;
- handle->running=0;
- handle->fp=stdout;
- strcpy(handle->app_name,"?");
- memset(handle->appoint_output_file,0,sizeof(handle->appoint_output_file));
- memset(handle->current_output_file,0,sizeof(handle->current_output_file));
- pthread_mutex_init(&(handle->reg_lock),NULL);
- handle->histogram_bin_num=sizeof(HISTOGRAM_DEFAULT_BINS)/sizeof(HISTOGRAM_DEFAULT_BINS[0]);
- handle->histogram_bins=(double*)calloc(sizeof(double), handle->histogram_bin_num);
- memcpy(handle->histogram_bins, HISTOGRAM_DEFAULT_BINS, sizeof(HISTOGRAM_DEFAULT_BINS));
- handle->display=(struct display_manifest_t **)calloc(sizeof(struct display_manifest_t *),handle->display_size);
- return handle;
-}
-
-int FS_set_para(screen_stat_handle_t handle, enum FS_option type,const void* value,int size)
-{
- struct FS_space_t* _handle=(struct FS_space_t*)handle;
- int int_val=0,ret=0;
- if(_handle->running==1 && type!=ID_INVISBLE)
- {
- return -1;
- }
-
- switch(type)
- {
- case OUTPUT_DEVICE:
- assert((unsigned int)size<sizeof(_handle->appoint_output_file));
- memcpy(_handle->appoint_output_file,value,size);
- break;
- case PRINT_MODE:
- int_val = *(const int *)value;
- if (size != 4 || (int_val != 1 && int_val != 2))
- {
- return -1;
- }
- _handle->print_mode=int_val;
- if(_handle->print_mode==1)
- {
- _handle->write_mode="w";
- }
- else
- {
- _handle->write_mode="a+";
- }
- break;
- case STAT_CYCLE:
- int_val = *(const int *)value;
- if(size!=4||(int_val==0))
- {
- return -1;
- }
- _handle->stat_cycle=int_val;
- break;
- case PRINT_TRIGGER:
- int_val = *(const int *)value;
- if(size!=4||(int_val!=0&&int_val!=1))
- {
- return -1;
- }
- _handle->screen_print_trigger=int_val;
- break;
- case CREATE_THREAD:
- int_val = *(const int *)value;
- if(size!=4||(int_val!=0&&int_val!=1))
- {
- return -1;
- }
- _handle->create_thread=int_val;
- break;
- case ID_INVISBLE:
- int_val = *(const int *)value;
- if(int_val<0||int_val>=_handle->display_cnt)
- {
- return -1;
- }
- _handle->display[int_val]->is_invisible=1;
- break;
- case NOT_SEND_METRIC_TO_SERVER:
- int_val = *(const int *)value;
- if(int_val<0||int_val>=_handle->display_cnt)
- {
- return -1;
- }
- _handle->display[int_val]->not_send_to_server=1;
- break;
- case FLUSH_BY_DATE:
- int_val = *(const int *)value;
- if(int_val==1)
- {
- _handle->flush_by_date=1;
- }
- break;
- case APP_NAME:
- if((unsigned int)size>sizeof(_handle->app_name)-1)
- {
- return -1;
- }
- strncpy(_handle->app_name,(char*)value, size);
- break;
- case STATS_SERVER_IP:
- if((unsigned int)size>sizeof(_handle->str_ip)-1)
- {
- return -1;
- }
- strncpy(_handle->str_ip,(char*)value, size);
- ret=inet_pton(AF_INET, _handle->str_ip, &(_handle->server_ip));
- if(ret<0)
- {
- return -1;
- }
- _handle->statsd_switch=FS_OUTPUT_STATSD;
- break;
- case STATS_SERVER_PORT:
- if((size_t)size==sizeof(unsigned short))
- {
- _handle->server_port=*((unsigned short *)value);
- }
- else if((size_t)size==sizeof(int))
- {
- _handle->server_port=*((int*)value);
- }
- else
- {
- return -1;
- }
- break;
- case STATS_FORMAT:
- int_val = *(const int *)value;
- if(size!=4||(int_val!=FS_OUTPUT_STATSD&&int_val!=FS_OUTPUT_INFLUX_LINE))
- {
- return -1;
- }
- _handle->statsd_switch=int_val;
- break;
- case MAX_STAT_FIELD_NUM:
- if((size_t)size!=sizeof(int))
- {
- return -1;
- }
- _handle->display_size=*((int*)value);
- _handle->display=(struct display_manifest_t **)realloc(_handle->display,sizeof(struct display_manifest_t *)*_handle->display_size);
- break;
- case HISTOGRAM_GLOBAL_BINS:
- if(_handle->histogram_bins!=NULL)
- {
- free(_handle->histogram_bins);
- _handle->histogram_bins=NULL;
- }
- _handle->histogram_bin_num=parse_histogram_bin_format((const char*)value, &_handle->histogram_bins);
- assert(_handle->histogram_bin_num>0);
- case METRIS_FORMAT:
- int_val = *(const int *)value;
- if(size!=4||(int_val!=FS_METRIS_OUTPUT_DEFAULT&&int_val!=FS_METRIS_OUTPUT_JSON))
- {
- return -1;
- }
- _handle->metris_format=int_val;
- break;
- case OUTPUT_PROMETHEUS:
- int_val = *(const int *)value;
- if(size==sizeof(int))
- {
- _handle->output_prometheus=*(int *)value;
- }
- break;
- default:
- return -1;
- }
- return 0;
-}
-void FS_start(screen_stat_handle_t handle)
-{
- struct FS_space_t* _handle=(struct FS_space_t*)handle;
- int i=0,j=0;
- char date_buff[32]={0};
-
- struct display_manifest_t *p=NULL;
- for(i=0;i<_handle->display_cnt;i++)
- {
- p=_handle->display[i];
- switch(p->style)
- {
- case FS_STYLE_FIELD:
- case FS_STYLE_STATUS:
- case FS_STYLE_HISTOGRAM:
- break;
- case FS_STYLE_COLUMN:
- _handle->cloumn_id[j]=i;
- p->column_seq=j;
- j++;
- break;
- case FS_STYLE_LINE:
- p->line=(struct stat_unit_t*)realloc(p->line,sizeof(struct stat_unit_t)*_handle->column_cnt);
- memset(p->line,0,sizeof(struct stat_unit_t)*_handle->column_cnt);
- break;
- default:
- assert(0);
- break;
- }
- }
- assert(j==_handle->column_cnt);
- _handle->running=1;
- if(strlen(_handle->appoint_output_file)>0)//otherwise use stdout;
- {
- if(_handle->flush_by_date==1)
- {
- _handle->current_date=current_day(date_buff, sizeof(date_buff));
- snprintf(_handle->current_output_file,sizeof(_handle->current_output_file)
- ,"%s.%s",_handle->appoint_output_file,date_buff);
- }
- else
- {
- snprintf(_handle->current_output_file,sizeof(_handle->current_output_file)
- ,"%s",_handle->appoint_output_file);
- }
-
- _handle->fp=fopen(_handle->current_output_file,_handle->write_mode);
- if(_handle->fp==NULL)
- {
- printf("Field Stat: open %s failed.\n",_handle->appoint_output_file);
- assert(0);
- return;
- }
- }
- if(_handle->statsd_switch > 0)
- {
- _handle->statsd_socket=startup_udp();
- if(_handle->statsd_switch == FS_OUTPUT_STATSD)
- {
- append_statsd_counter(_handle, "RESTART", 1);
- flush_metric(_handle);
- }
- }
- clock_gettime(CLOCK_MONOTONIC,&(_handle->last_display_time));
- if(_handle->create_thread==1)
- {
- pthread_create(&(_handle->cfg_mon_t), NULL, fs2_thread_screen_print, (void*)handle);
- }
-
- FS_library_promethues_register(handle);
-
- return;
-}
-void FS_stop(screen_stat_handle_t* handle)
-{
- int i=0;
- void * ret=NULL;
- struct FS_space_t* _handle=*(struct FS_space_t**)handle;
- if(_handle->create_thread==1 && _handle->cfg_mon_t!=0)
- {
- _handle->create_thread=0;
- pthread_join(_handle->cfg_mon_t, &ret);
- }
- struct display_manifest_t * p=NULL;
- for(i=0;i<_handle->display_cnt;i++)
- {
- p=_handle->display[i];
- switch (p->style)
- {
- case FS_STYLE_LINE:
- free(p->line);
- p->line=NULL;
- break;
- case FS_STYLE_HISTOGRAM:
- if(p->histogram.previous_changed!=NULL)
- {
- hdr_close(p->histogram.previous_changed);
- p->histogram.previous_changed=NULL;
- }
- if(p->histogram.changing!=NULL)
- {
- hdr_close(p->histogram.changing);
- p->histogram.changing=NULL;
- }
- if(p->histogram.accumulated!=NULL)
- {
- hdr_close(p->histogram.accumulated);
- p->histogram.accumulated=NULL;
- }
- default:
- break;
- }
- free(p->name);
- p->name=NULL;
- free(p);
- _handle->display[i]=NULL;
- }
- if(strlen(_handle->appoint_output_file)>0)
- {
- fclose(_handle->fp);
- _handle->fp=NULL;
- }
- free(_handle->display);
- if(_handle->fp!=NULL)
- {
- fclose(_handle->fp);
- _handle->fp=NULL;
- }
- free(_handle->histogram_bins);
- _handle->histogram_bins=NULL;
-
- if(_handle->statsd_switch > 0)
- {
- close(_handle->statsd_socket);
- }
-
-
- free(_handle);
-
- *handle=NULL;
- return;
-}
-int FS_register(screen_stat_handle_t handle,enum field_dsp_style_t style,enum field_calc_algo calc_type,const char* name)
-{
- struct FS_space_t* _handle=(struct FS_space_t*)handle;
- struct display_manifest_t * choosen=NULL;
- int id=0;
- if(!is_valid_fs_name(name))
- {
- return -1;
- }
- if(_handle->running==1&&style==FS_STYLE_COLUMN)
- {
- return -1;
- }
- pthread_mutex_lock(&(_handle->reg_lock));
- id=_handle->display_cnt;
- _handle->display_cnt++;
- assert(_handle->display_cnt<_handle->display_size);
- choosen=_handle->display[id]=display_manifest_new(name, style, calc_type);
-
- switch(style)
- {
- case FS_STYLE_FIELD:
- case FS_STYLE_STATUS:
- _handle->single_cnt++;
- memset(&(choosen->single), 0, sizeof(choosen->single));
- break;
- case FS_STYLE_LINE:
- choosen->line=(struct stat_unit_t*)calloc(sizeof(struct stat_unit_t), _handle->column_cnt);
- _handle->line_cnt++;
- break;
- case FS_STYLE_COLUMN:
- _handle->column_cnt++;
- break;
- case FS_STYLE_HISTOGRAM:
- default:
- assert(0);
- }
- pthread_mutex_unlock(&(_handle->reg_lock));
- return id;
-}
-int FS_register_histogram(screen_stat_handle_t handle, enum field_calc_algo calc_type, const char* name,
- long long lowest_trackable_value,
- long long highest_trackable_value,
- int significant_figures)
-{
- struct FS_space_t* _handle=(struct FS_space_t*)handle;
- struct display_manifest_t * choosen=NULL;
- int id=0;
- if(!is_valid_fs_name(name))
- {
- return -1;
- }
- if (lowest_trackable_value < 1 ||
- significant_figures < 1 || 5 < significant_figures)
- {
- return -1;
- }
- else if (lowest_trackable_value * 2 > highest_trackable_value)
- {
- return -1;
- }
-
- pthread_mutex_lock(&(_handle->reg_lock));
- id=_handle->display_cnt;
- _handle->display_cnt++;
- assert(_handle->display_cnt<_handle->display_size);
- choosen=_handle->display[id]=display_manifest_new(name, FS_STYLE_HISTOGRAM, calc_type);
- choosen->histogram.highest_trackable_value=(int64_t)highest_trackable_value;
- choosen->histogram.lowest_trackable_value=(int64_t)lowest_trackable_value;
- choosen->histogram.significant_figures=significant_figures;
-
- int ret=hdr_init((int64_t)lowest_trackable_value, (int64_t)highest_trackable_value, significant_figures, &(choosen->histogram.changing));
- assert(ret==0);
- ret=hdr_init((int64_t)lowest_trackable_value, (int64_t)highest_trackable_value, significant_figures, &(choosen->histogram.accumulated));
- assert(ret==0);
- _handle->histogram_cnt++;
- pthread_mutex_unlock(&(_handle->reg_lock));
- return id;
-}
-
-
-int FS_register_ratio(screen_stat_handle_t handle,int numerator_id,int denominator_id,int scaling,enum field_dsp_style_t style,enum field_calc_algo calc_type,const char* name)
-{
- struct FS_space_t* _handle=(struct FS_space_t*)handle;
- struct display_manifest_t * choosen=NULL;
- int id=0;
- if(_handle->running==1&&(style==FS_STYLE_LINE||style==FS_STYLE_COLUMN))
- {
- return -1;
- }
- if(!is_valid_fs_name(name))
- {
- return -1;
- }
- if(numerator_id>=_handle->display_cnt||denominator_id>=_handle->display_cnt)
- {
- return -1;
- }
- if(_handle->display[denominator_id]->is_ratio==1||_handle->display[numerator_id]->is_ratio==1)
- {
- return -1;
- }
- if(_handle->display[denominator_id]->style==FS_STYLE_LINE||_handle->display[numerator_id]->style==FS_STYLE_LINE)
- {
- return -1;
- }
- if(style==FS_STYLE_LINE||scaling==0)
- {
- return -1;
- }
- pthread_mutex_lock(&(_handle->reg_lock));
-
- switch(style)
- {
- case FS_STYLE_FIELD:
- case FS_STYLE_STATUS:
- _handle->single_cnt++;
- break;
- case FS_STYLE_LINE:
- _handle->line_cnt++;
- break;
- case FS_STYLE_COLUMN:
- _handle->column_cnt++;
- break;
- default:
- pthread_mutex_unlock(&(_handle->reg_lock));
- assert(0);
- return -1;
- }
-
- id=_handle->display_cnt;
- _handle->display_cnt++;
- assert(_handle->display_cnt<_handle->display_size);
- choosen=_handle->display[id]=display_manifest_new(name, style, calc_type);
- choosen->is_ratio=1;
- choosen->output_scaling=scaling;
- choosen->denominator_id=denominator_id;
- choosen->numerator_id=numerator_id;
- pthread_mutex_unlock(&(_handle->reg_lock));
-
- return id;
-}
-
-int FS_operate(screen_stat_handle_t handle,int id,int column_id,enum field_op op,long long value)
-{
- struct FS_space_t* _handle=(struct FS_space_t*)handle;
- int i=0;
- struct display_manifest_t* p=NULL;
- struct stat_unit_t* target=NULL;
- if(id>=_handle->display_cnt)
- {
- return -1;
- }
- p=_handle->display[id];
- switch(p->style)
- {
- case FS_STYLE_LINE:
- if(column_id>=_handle->display_cnt||column_id>=_handle->display_cnt||_handle->display[column_id]->style!=FS_STYLE_COLUMN)
- {
- return -1;
- }
- i=_handle->display[column_id]->column_seq;
- target=&(p->line[i]);
- break;
- case FS_STYLE_HISTOGRAM:
- hdr_record_value(p->histogram.changing, (int64_t) value);
- return 0;
- default:
- target=&(p->single);
- break;
- }
- switch(op)
- {
- case FS_OP_ADD:
- threadsafe_counter_add(&(target->changing), value);
- break;
- case FS_OP_SET:
- threadsafe_counter_set(&(target->changing), value-target->accumulated);
- break;
- case FS_OP_SUB:
- threadsafe_counter_sub(&(target->changing), value);
- break;
- default:
- assert(0);
- break;
- }
- return 0;
-}
-long long get_stat_unit_val(display_manifest_t* p, int column_seq,enum field_calc_algo calc_type,int is_refer)
-{
- stat_unit_t* target=NULL;
- long long value=0;
- switch(p->style)
- {
- case FS_STYLE_FIELD:
- case FS_STYLE_STATUS:
- target=&(p->single);
- break;
- case FS_STYLE_LINE:
- target=&(p->line[column_seq]);
- break;
- case FS_STYLE_HISTOGRAM:
- case FS_STYLE_COLUMN:
- default:
- break;
- }
- value= threadsafe_counter_read(&(target->changing));
- if(is_refer==0)
- {
- target->previous_changed=value;
- target->accumulated+=value;
- threadsafe_counter_set(&(target->changing), 0);
- }
- switch(calc_type)
- {
- case FS_CALC_CURRENT:
- value=target->accumulated;
- break;
- case FS_CALC_SPEED:
- value=target->previous_changed;
- break;
- default:
- assert(0);
- }
-
- return value;
-}
-static double get_stat_ratio(struct display_manifest_t* numerator, struct display_manifest_t* denominator, struct display_manifest_t* line, int scaling,enum field_calc_algo calc_type)
-{
- long long value_n=0,value_d=0;
- double ratio=0.0;
-
- if(numerator->style==FS_STYLE_COLUMN)
- {
- assert(denominator->style==FS_STYLE_COLUMN);
- value_n=get_stat_unit_val(line, numerator->column_seq,calc_type,1);
- value_d=get_stat_unit_val(line, denominator->column_seq,calc_type,1);
- }
- else
- {
- value_n=get_stat_unit_val(numerator,0,calc_type,1);
- value_d=get_stat_unit_val(denominator,0,calc_type,1);
- }
- if(value_d==0)
- {
- ratio=0.0;
- }
- else
- {
- if(scaling>0)
- {
- ratio=((double)value_n*scaling/value_d);
- }
- else
- {
- ratio=((double)value_n/(value_d*scaling*-1));
- }
- }
- return ratio;
-}
-
-void influx_output(struct FS_space_t* _handle)
-{
- display_manifest_t* p=NULL,*p_column=NULL;
- long long value=0;
- int i=0,j=0;
- char field_buff[UDP_PAYLOAD_SIZE];
- int buff_off = 0, not_zero_column_cnt = 0;
-
- memset(field_buff, 0, UDP_PAYLOAD_SIZE);
-
- for(i=0;i<_handle->display_cnt;i++)
- {
- p=_handle->display[i];
- if(p->not_send_to_server==1||p->is_ratio==1)
- {
- continue;
- }
- switch(p->style)
- {
- case FS_STYLE_STATUS:
- if (p->calc_type == FS_CALC_CURRENT)
- {
- value=get_stat_unit_val(p, 0, FS_CALC_CURRENT, 1);
- if(value != 0)
- {
- snprintf(field_buff, UDP_PAYLOAD_SIZE, "%s=%lld", p->name, value);
- appen_influx_line(_handle, p->name, field_buff);
- }
- break;
- }
- //not break
- case FS_STYLE_FIELD:
- value=get_stat_unit_val(p, 0, FS_CALC_SPEED, 1);
- if(value != 0)
- {
- snprintf(field_buff, UDP_PAYLOAD_SIZE, "%s=%lld", p->name, value);
- appen_influx_line(_handle, p->name, field_buff);
- }
- break;
- case FS_STYLE_LINE:
- for(j=0;j<_handle->column_cnt;j++)
- {
- p_column=_handle->display[_handle->cloumn_id[j]];
- if(p_column->not_send_to_server==1||p_column->is_ratio==1)
- {
- continue;
- }
- if(p_column->calc_type==FS_CALC_SPEED)
- {
- value = get_stat_unit_val(p, p_column->column_seq, FS_CALC_SPEED, 1);
- }
- if(p_column->calc_type==FS_CALC_CURRENT)
- {
- value = get_stat_unit_val(p, p_column->column_seq, FS_CALC_CURRENT, 1);
- }
- buff_off+=snprintf(field_buff+buff_off, UDP_PAYLOAD_SIZE-buff_off,"%s=%lld,",p_column->name, value);
- if(value != 0)
- {
- not_zero_column_cnt += 1;
- }
- if(buff_off >= UDP_PAYLOAD_SIZE)continue;
- }
- if(not_zero_column_cnt > 0)
- {
- field_buff[buff_off-1] = '\0';
- appen_influx_line(_handle, p->name, field_buff);
- }
- buff_off=0;
- not_zero_column_cnt = 0;
- break;
- case FS_STYLE_HISTOGRAM:
- //
- break;
- default:
- break;
- }
-
- }
- flush_metric(_handle);
-}
-
-void StatsD_output(struct FS_space_t* _handle)
-{
- display_manifest_t* p=NULL,*p_column=NULL;
- long long value=0;
- int i=0,j=0;
- char name_buff[UDP_PAYLOAD_SIZE];
- struct hdr_iter iter;
- int index=0;
-
- for(i=0;i<_handle->display_cnt;i++)
- {
- p=_handle->display[i];
- if(p->not_send_to_server==1||p->is_ratio==1)
- {
- continue;
- }
- switch(p->style)
- {
- case FS_STYLE_STATUS:
- if(p->calc_type==FS_CALC_CURRENT)
- {
- value=get_stat_unit_val(p, 0, FS_CALC_CURRENT, 1);
- append_statsd_counter(_handle, p->name, value);
- break;
- }
- //not break;
- case FS_STYLE_FIELD:
- value=get_stat_unit_val(p, 0, FS_CALC_SPEED, 1);
- append_statsd_counter(_handle, p->name, value);
- break;
- case FS_STYLE_LINE:
- for(j=0;j<_handle->column_cnt;j++)
- {
- p_column=_handle->display[_handle->cloumn_id[j]];
- if(p_column->not_send_to_server==1||p_column->is_ratio==1)
- {
- continue;
- }
- snprintf(name_buff,sizeof(name_buff),"%s#%s",p->name,p_column->name);
- value=get_stat_unit_val(p, p_column->column_seq, FS_CALC_SPEED, 1);
- append_statsd_counter(_handle, name_buff, value);
- }
- break;
- case FS_STYLE_HISTOGRAM:
- // Raw Histogram
- if(p->histogram.previous_changed!=NULL)
- {
- hdr_iter_recorded_init(&iter, p->histogram.previous_changed);
- while (hdr_iter_next(&iter))
- {
- append_statsd_histogram(_handle, p->name, (long long)iter.value, (long long)iter.count);
- index++;
- }
- }
- break;
- default:
- break;
- }
-
- }
- flush_metric(_handle);
-}
-
-static int output_style_status(struct FS_space_t* _handle,long long interval_ms,char*print_buf, unsigned int size)
-{
- int i=0,j=0;
- display_manifest_t* p=NULL;
- long long value=0;
- double ratio=0.0;
- char* pos=print_buf;
-
- for(i=0;i<_handle->display_cnt;i++)
- {
- p=_handle->display[i];
- if(p->style!=FS_STYLE_STATUS)
- {
- continue;
- }
- if(p->is_invisible==1)
- {
- value=get_stat_unit_val(p, 0, p->calc_type, 0);
- continue;
- }
- if(p->is_ratio==1)
- {
- ratio=get_stat_ratio(_handle->display[p->numerator_id], _handle->display[p->denominator_id], NULL,
- p->output_scaling, p->calc_type);
- pos+=snprintf(pos,size-(pos-print_buf),"%s: %10.2e\t",p->name,ratio);
- }
- else
- {
- value=get_stat_unit_val(p, 0, p->calc_type, 0);
- if(p->calc_type==FS_CALC_SPEED)
- {
- value=value*p->output_scaling*1000/interval_ms;
- }
- pos+=snprintf(pos,size-(pos-print_buf),"%s: %-10lld\t",p->name,value);
- }
- j++;
- if(j==STATUS_PER_LINE)
- {
- pos+=snprintf(pos,sizeof(print_buf)-(pos-print_buf),"\n");
- j=0;
- }
- }
- if(pos-print_buf>0)
- {
- if(*(pos-1)=='\n')
- {
- pos--;
- }
- pos+=snprintf(pos,sizeof(print_buf)-(pos-print_buf),"\n%s\n",draw_line);
- }
- return pos-print_buf;
-}
-static int output_style_field(struct FS_space_t* _handle,long long interval_ms,char*print_buf, unsigned int size)
-{
- int i=0,j=0;
- display_manifest_t* p=NULL;
- long long value=0;
- double ratio=0.0;
- char* pos=print_buf;
- int field_id[INIT_STAT_FIELD_NUM]={0};
- int field_cnt=0;
-
- for(i=0;i<_handle->display_cnt;i++)
- {
- p=_handle->display[i];
- if(p->style!=FS_STYLE_FIELD)
- {
- continue;
- }
- if(p->is_invisible==1)
- {
- //for update last_output
- get_stat_unit_val(p, 0,FS_CALC_CURRENT, 0);
- continue;
- }
- field_id[field_cnt]=i;
- field_cnt++;
- }
- for(i=0;i<field_cnt;i++)
- {
- pos+=snprintf(pos,size-(pos-print_buf),"\t");
- for(j=0;j<FIELD_PER_LINE&&i+j<field_cnt;j++)
- {
- p=_handle->display[field_id[i+j]];
- pos+=snprintf(pos,size-(pos-print_buf),"%10s\t",p->name);
- }
- pos+=snprintf(pos,size-(pos-print_buf),"\nsum\t");
- for(j=0;j<FIELD_PER_LINE&&i+j<field_cnt;j++)
- {
- p=_handle->display[field_id[i+j]];
- if(p->is_ratio==1)
- {
- ratio=get_stat_ratio(_handle->display[p->numerator_id], _handle->display[p->denominator_id], NULL,
- p->output_scaling, FS_CALC_CURRENT);
- pos+=snprintf(pos,size-(pos-print_buf),"%f\t",ratio);
- }
- else
- {
- value=get_stat_unit_val(p, 0,FS_CALC_CURRENT, 1);
- pos+=snprintf(pos,sizeof(print_buf)-(pos-print_buf),"%10lld\t",value);
- }
- }
- pos+=snprintf(pos,sizeof(print_buf)-(pos-print_buf),"\nspeed/s\t");
- for(j=0;j<FIELD_PER_LINE&&i+j<field_cnt;j++)
- {
- p=_handle->display[field_id[i+j]];
- if(p->is_ratio==1)
- {
- ratio=get_stat_ratio(_handle->display[p->numerator_id],_handle->display[p->denominator_id],NULL,
- p->output_scaling, FS_CALC_SPEED);
- pos+=snprintf(pos,size-(pos-print_buf),"%10.2e\t",ratio);
- }
- else
- {
- value=get_stat_unit_val(p,0,FS_CALC_SPEED, 0);
- pos+=snprintf(pos,size-(pos-print_buf),"%10lld\t",value*1000/interval_ms);
- }
- }
- i+=(j-1);
- pos+=snprintf(pos,size-(pos-print_buf),"\n");
- }
- if(pos-print_buf>0)
- {
- if(*(pos-1)=='\n')
- {
- pos--;
- }
- pos+=snprintf(pos,size-(pos-print_buf),"\n%s\n",draw_line);
- }
- return pos-print_buf;
-}
-static int output_style_table(struct FS_space_t* _handle,long long interval_ms,char*print_buf, unsigned int size)
-{
- int i=0,j=0;
- char* pos=print_buf;
- display_manifest_t* p_column=NULL,*p_line=NULL;
- double ratio=0.0,speed=0.0;
- long long value=0;
- if(_handle->column_cnt==0)
- {
- return 0;
- }
- for(i=0;i<_handle->column_cnt;i++)
- {
- if(i==0)
- {
- pos+=snprintf(pos,size-(pos-print_buf),"\t\t");
- }
- p_column=_handle->display[_handle->cloumn_id[i]];
- if(p_column->is_invisible==1)
- {
- continue;
- }
- pos+=snprintf(pos,size-(pos-print_buf),"\t%10s",p_column->name);
- }
- pos+=snprintf(pos,sizeof(print_buf)-(pos-print_buf),"\n");
- for(i=0;i<_handle->display_cnt;i++)
- {
- p_line=_handle->display[i];
- if(p_line->style!=FS_STYLE_LINE)
- {
- continue;
- }
- pos+=snprintf(pos,size-(pos-print_buf),"%-20s\t",p_line->name);
- for(j=0;j<_handle->column_cnt;j++)
- {
- p_column=_handle->display[_handle->cloumn_id[j]];
- if(p_column->is_invisible==1)
- {
- //for flush last_output_value
- get_stat_unit_val(p_line, p_column->column_seq, p_column->calc_type, 0);
- continue;
- }
- if(p_column->is_ratio==1)
- {
- ratio=get_stat_ratio(_handle->display[p_column->numerator_id], _handle->display[p_column->denominator_id], p_line,
- p_column->output_scaling, p_column->calc_type);
- pos+=snprintf(pos,size-(pos-print_buf),"%10.2e\t",ratio);
- }
- else
- {
- value=get_stat_unit_val(p_line,p_column->column_seq, p_column->calc_type, 0);
- if(p_column->calc_type==FS_CALC_SPEED)
- {
- speed=(double)value*1000/interval_ms;
- pos+=snprintf(pos,size-(pos-print_buf),"%10.2e\t",speed);
-
- }
- else
- {
- pos+=snprintf(pos,size-(pos-print_buf),"%10lld\t",value);
- }
- }
- }
- pos+=snprintf(pos,size-(pos-print_buf),"\n");
-
- }
- if(pos-print_buf>0)
- {
- if(*(pos-1)=='\n')
- {
- pos--;
- }
- pos+=snprintf(pos,size-(pos-print_buf),"\n%s\n",draw_line);
- }
- return pos-print_buf;
-}
-#define HISTOGRAM_WIDTH 10
-static int print_histogram_head(double * bins, int bin_num, char*print_buf, size_t size)
-{
- char* pos=print_buf;
- char bin_format[256], str_format[256];
- const char* extra[]={"MAX", "MIN", "AVG", "STDDEV", "CNT"};
- char buff[32];
- int i=0;
- snprintf(bin_format, sizeof(bin_format), "%%%d.2lf%%%%", HISTOGRAM_WIDTH-1);
- snprintf(str_format, sizeof(str_format), "%%%ds", HISTOGRAM_WIDTH);
- pos+=snprintf(pos,size-(pos-print_buf),"%-8s\t","histogram");
- for(i=0;i<bin_num;i++)
- {
- snprintf(buff,sizeof(buff),bin_format,bins[i]);
- pos+=snprintf(pos,size-(pos-print_buf),str_format, buff);
- }
- for(i=0;(unsigned int)i<sizeof(extra)/sizeof(extra[0]);i++)
- {
- pos+=snprintf(pos,size-(pos-print_buf),str_format, extra[i]);
- }
- pos+=snprintf(pos,size-(pos-print_buf),"\n");
- return pos-print_buf;
-}
-static int print_histogram_unit(display_manifest_t* p, double * bins, int bin_num, char*print_buf, size_t size)
-{
- char* pos=print_buf;
- long long value=0;
- int i=0;
- struct histogram_t* h=&(p->histogram);
- struct hdr_histogram* h_out=NULL, *h_tmp=NULL;
- char int_format[256], double_format[256];
- snprintf(int_format, sizeof(int_format), "%%%dlld",HISTOGRAM_WIDTH);
- snprintf(double_format, sizeof(double_format), "%%%d.2lf",HISTOGRAM_WIDTH);
-
- hdr_init(h->lowest_trackable_value, h->highest_trackable_value, h->significant_figures, &(h_tmp));
- if(h->previous_changed!=NULL) hdr_close(h->previous_changed);
-
- h->previous_changed=atomic_read(&(h->changing));
- h_tmp=atomic_set(&(h->changing), h_tmp);// left h_tmp is used to avoid warining [-Wunused-value]
-
- hdr_add(h->accumulated, h->previous_changed);
- if(p->calc_type==FS_CALC_SPEED)
- {
- h_out=h->previous_changed;
- }
- else
- {
- h_out=h->accumulated;
- }
- pos+=snprintf(pos,size-(pos-print_buf),"%-10s\t",p->name);
-
- for(i=0;i<bin_num;i++)
- {
- value=(long long)hdr_value_at_percentile(h_out, bins[i]);
- pos+=snprintf(pos,size-(pos-print_buf),int_format, value);
- }
- pos+=snprintf(pos,size-(pos-print_buf),int_format,h_out->total_count==0?0:(long long)hdr_max(h_out));
- pos+=snprintf(pos,size-(pos-print_buf),int_format,h_out->total_count==0?0:(long long)hdr_min(h_out));
- pos+=snprintf(pos,size-(pos-print_buf),double_format,h_out->total_count==0?0:hdr_mean(h_out));
- pos+=snprintf(pos,size-(pos-print_buf),double_format,h_out->total_count==0?0:hdr_stddev(h_out));
- pos+=snprintf(pos,size-(pos-print_buf),int_format,(long long)h_out->total_count);
-
- pos+=snprintf(pos,size-(pos-print_buf),"\n");
-
- h_tmp=NULL;
-
- return pos-print_buf;
-}
-static int output_style_histogram(struct FS_space_t* _handle, long long interval_ms, char*print_buf, size_t size)
-{
- int i=0;
- char* pos=print_buf;
- display_manifest_t* p=NULL;
- if(_handle->histogram_cnt==0)
- {
- return 0;
- }
- pos+=print_histogram_head(_handle->histogram_bins, _handle->histogram_bin_num, pos, size-(pos-print_buf));
-
- for(i=0;i<_handle->display_cnt;i++)
- {
- p=_handle->display[i];
- if(p->style!=FS_STYLE_HISTOGRAM)
- {
- continue;
- }
- pos+=print_histogram_unit(p, _handle->histogram_bins, _handle->histogram_bin_num, pos, size-(pos-print_buf));
-
- }
- if(pos-print_buf>0)
- {
- if(*(pos-1)=='\n')
- {
- pos--;
- }
- pos+=snprintf(pos,size-(pos-print_buf),"\n%s\n", draw_line);
- }
- return pos-print_buf;
-}
-
-cJSON *fs2_metrics_to_json(FS_space_t* _handle, long long timestamp)
-{
- if(_handle == NULL)
- {
- return NULL;
- }
- display_manifest_t* p=NULL, *p_column=NULL;;
- long long value=0;
- cJSON *root_obj = cJSON_CreateObject();
- cJSON_AddNumberToObject(root_obj, "unix timestamp", timestamp);
- cJSON_AddNumberToObject(root_obj, "output interval", _handle->stat_cycle);
- cJSON *metrics_array_obj = cJSON_CreateArray();
- cJSON *tmp_obj = NULL;
- char tmp_output_name[64];
- const char* extra[]={"MAX", "MIN", "AVG", "STDDEV", "CNT"};
- long long tmp_histogram_values[sizeof(extra)/sizeof(char*)];
- for(int i=0;i<_handle->display_cnt;i++)
- {
- p=_handle->display[i];
- if(p->not_send_to_server==1||p->is_ratio==1)
- {
- continue;
- }
- switch(p->style)
- {
- case FS_STYLE_STATUS:
- if(p->calc_type==FS_CALC_SPEED)
- {
- //value=get_stat_unit_val(p, 0, FS_CALC_CURRENT, 1);
- tmp_obj = cJSON_CreateObject();
- cJSON_AddStringToObject(tmp_obj, "name", p->name);
- cJSON_AddStringToObject(tmp_obj, "type", "single");
- cJSON_AddNumberToObject(tmp_obj, "acc", p->single.accumulated);
- value=threadsafe_counter_read(&p->single.changing);
- cJSON_AddNumberToObject(tmp_obj, "diff", value);
- cJSON_AddItemToArray(metrics_array_obj, tmp_obj);
- //cJSON_Delete(tmp_obj);
- break;
- }
- //not break
- case FS_STYLE_FIELD:
- //value=get_stat_unit_val(p, 0, FS_CALC_SPEED, 1);
- tmp_obj = cJSON_CreateObject();
- cJSON_AddStringToObject(tmp_obj, "name", p->name);
- cJSON_AddStringToObject(tmp_obj, "type", "single");
- cJSON_AddNumberToObject(tmp_obj, "acc", p->single.accumulated);
- value=threadsafe_counter_read(&p->single.changing);
- cJSON_AddNumberToObject(tmp_obj, "diff", value);
- cJSON_AddItemToArray(metrics_array_obj, tmp_obj);
- //cJSON_Delete(tmp_obj);
- break;
- case FS_STYLE_LINE:
- for(int j=0;j<_handle->column_cnt;j++)
- {
- p_column=_handle->display[_handle->cloumn_id[j]];
- if(p_column->not_send_to_server==1||p_column->is_ratio==1)
- {
- continue;
- }
- //value=get_stat_unit_val(p, p_column->column_seq, FS_CALC_SPEED, 1);
- tmp_obj = cJSON_CreateObject();
- snprintf(tmp_output_name, sizeof(tmp_output_name), "%s.%s", p->name, p_column->name);
- cJSON_AddStringToObject(tmp_obj, "name", tmp_output_name);
- //cJSON_AddStringToObject(tmp_obj, "type", "line");
- cJSON_AddNumberToObject(tmp_obj, "acc", p_column->single.accumulated);
- value=threadsafe_counter_read(&p->single.changing);
- cJSON_AddNumberToObject(tmp_obj, "diff", value);
- cJSON_AddItemToArray(metrics_array_obj, tmp_obj);
- //cJSON_Delete(tmp_obj);
- }
- break;
- case FS_STYLE_HISTOGRAM:
- {
- struct histogram_t* h=&(p->histogram);
- struct hdr_histogram* h_out=NULL, *h_tmp=NULL;
- hdr_init(h->lowest_trackable_value, h->highest_trackable_value, h->significant_figures, &(h_tmp));
- if(h->previous_changed!=NULL) hdr_close(h->previous_changed);
-
- h->previous_changed=atomic_read(&(h->changing));
- h_tmp=atomic_set(&(h->changing), h_tmp);// left h_tmp is used to avoid warining [-Wunused-value]
-
- hdr_add(h->accumulated, h->previous_changed);
- if(p->calc_type==FS_CALC_SPEED)
- {
- h_out=h->previous_changed;
- }
- else
- {
- h_out=h->accumulated;
- }
-
- for(int j=0;j<_handle->histogram_bin_num;j++)
- {
- value=(long long)hdr_value_at_percentile(h_out, _handle->histogram_bins[j]);
- tmp_obj = cJSON_CreateObject();
- snprintf(tmp_output_name, sizeof(tmp_output_name), "%s.p%.2f", p->name,
- _handle->histogram_bins[j]);
- cJSON_AddStringToObject(tmp_obj, "name", tmp_output_name);
- cJSON_AddNumberToObject(tmp_obj, "acc", value);
- cJSON_AddNumberToObject(tmp_obj, "diff", value);
- cJSON_AddItemToArray(metrics_array_obj, tmp_obj);
- }
- tmp_histogram_values[0] = h_out->total_count==0?0:(long long)hdr_max(h_out);
- tmp_histogram_values[1] = h_out->total_count==0?0:(long long)hdr_min(h_out);
- tmp_histogram_values[2] = h_out->total_count==0?0:hdr_mean(h_out);
- tmp_histogram_values[3] = h_out->total_count==0?0:hdr_stddev(h_out);
- tmp_histogram_values[4] = (long long)h_out->total_count;
- for(unsigned int j = 0; j < sizeof(extra)/sizeof(char*); j++)
- {
- tmp_obj = cJSON_CreateObject();
- snprintf(tmp_output_name, sizeof(tmp_output_name), "%s.%s", p->name, extra[j]);
- cJSON_AddStringToObject(tmp_obj, "name", tmp_output_name);
- cJSON_AddNumberToObject(tmp_obj, "acc", tmp_histogram_values[j]);
- cJSON_AddNumberToObject(tmp_obj, "diff", tmp_histogram_values[j]);
- cJSON_AddItemToArray(metrics_array_obj, tmp_obj);
- }
- }
- break;
- default:
- break;
- }
-
- }
- cJSON_AddItemToObject(root_obj, "metrics", metrics_array_obj);
- //cJSON_Delete(metrics_array_obj);
- return root_obj;
-}
-
-void FS_passive_output(screen_stat_handle_t handle)
-{
- struct FS_space_t* _handle=(struct FS_space_t*)handle;
- struct timespec now;
- time_t current=0;
- char date_buff[32];
- //he reentrant version ctime_r() does the same, but stores the string in a user-supplied buffer which should have room for at least 26 bytes.
- char ctime_buff[32]={0};
- char* print_buf=NULL;
- size_t print_buf_sz=_handle->display_cnt*1024;
- char*pos=NULL;
- int today=0;
- time(&current);
- if(_handle->running==0)
- {
- return;
- }
- if(_handle->screen_print_trigger==0)
- {
- return;
- }
- if(strlen(_handle->appoint_output_file)>0&&_handle->flush_by_date==1)
- {
- today=current_day(date_buff, sizeof(date_buff));
- if(today!=_handle->current_date)
- {
- snprintf(_handle->current_output_file,sizeof(_handle->current_output_file)
- ,"%s.%s",_handle->appoint_output_file,date_buff);
- _handle->current_date=today;
- fclose(_handle->fp);
- _handle->fp=fopen(_handle->current_output_file,_handle->write_mode);
- }
- }
- if(_handle->fp==NULL)
- {
- printf("Field Stat: open %s failed.\n",_handle->appoint_output_file);
- return;
- }
- clock_gettime(CLOCK_MONOTONIC,&now);
- long long interval_ms=(now.tv_sec-_handle->last_display_time.tv_sec)*1000+(now.tv_nsec-_handle->last_display_time.tv_nsec)/1000000;
- if(interval_ms<1)
- {
- return;
- }
- if(_handle->metris_format == FS_METRIS_OUTPUT_DEFAULT)
- {
- print_buf=(char*)calloc(sizeof(char), print_buf_sz);
- pos=print_buf;
- ctime_r(&current, ctime_buff);
- pos+=snprintf(pos, print_buf_sz-(pos-print_buf), "%s%s", draw_boundary, ctime_buff);
- pos--;//jump '\n' generate by ctime()
- pos+=snprintf(pos, print_buf_sz-(pos-print_buf),"%s\n",draw_boundary);
-
- pthread_mutex_lock(&(_handle->reg_lock));
- pos+=output_style_status(_handle, interval_ms, pos, print_buf_sz-(pos-print_buf));
- pos+=output_style_field(_handle, interval_ms, pos, print_buf_sz-(pos-print_buf));
- pos+=output_style_table(_handle, interval_ms, pos, print_buf_sz-(pos-print_buf));
- pos+=output_style_histogram(_handle, interval_ms, pos, print_buf_sz-(pos-print_buf));
- pthread_mutex_unlock(&(_handle->reg_lock));
- }
- if(_handle->metris_format == FS_METRIS_OUTPUT_JSON)
- {
- pthread_mutex_lock(&(_handle->reg_lock));
- cJSON *output_obj = fs2_metrics_to_json(_handle, now.tv_sec);
- pthread_mutex_unlock(&(_handle->reg_lock));
- if(output_obj != NULL)
- {
- print_buf = cJSON_PrintUnformatted(output_obj);
- cJSON_Delete(output_obj);
- pos = print_buf+strlen(print_buf)+1;
- }
- }
-
- if(_handle->print_mode==1)
- {
- fseek(_handle->fp,0,SEEK_SET);
- }
- fwrite(print_buf,pos-print_buf,1,_handle->fp);
- fflush(_handle->fp);
- memcpy(&(_handle->last_display_time),&now,sizeof(now));
- if(_handle->statsd_switch > 0)
- {
- pthread_mutex_lock(&(_handle->reg_lock));
- if(_handle->statsd_switch == FS_OUTPUT_STATSD)
- {
- StatsD_output(_handle);
- }
- if(_handle->statsd_switch == FS_OUTPUT_INFLUX_LINE)
- {
- influx_output(_handle);
- }
- pthread_mutex_unlock(&(_handle->reg_lock));
- }
- free(print_buf);
- print_buf=NULL;
-}
-
-void *fs2_thread_screen_print(void *arg)
-{
- struct FS_space_t* handle=(struct FS_space_t*)arg;
- while(handle->create_thread)
- {
- FS_passive_output(handle);
- sleep(handle->stat_cycle);
- }
- return NULL;
-}
-
-
diff --git a/src/fieldstat.cpp b/src/fieldstat.cpp
new file mode 100644
index 0000000..a277559
--- /dev/null
+++ b/src/fieldstat.cpp
@@ -0,0 +1,596 @@
+#include "fieldstat.h"
+#include "fieldstat_internal.h"
+#include "threadsafe_counter.h"
+#include "hdr_histogram.h"
+#include "cJSON.h"
+
+#include <sys/socket.h>//socket
+#include <sys/types.h>//socket
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h> //strerror
+#include <errno.h>//strerror
+#include <fcntl.h>//fcntl
+#include <unistd.h>//fcntl
+#include <net/if.h>//fcntl
+#include <sys/ioctl.h>//ioctl
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <assert.h>
+#include <sys/time.h>
+
+double HISTOGRAM_DEFAULT_BINS[]={50.0, 80.0, 90.0, 95.0, 99.0};
+
+int FIELD_STAT_VERSION_2_8_20200805_fix_outOfBound=0;
+
+//Automatically generate the version number
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define GIT_VERSION_CATTER(v) __attribute__((__used__)) const char * GIT_VERSION_##v = NULL
+#define GIT_VERSION_EXPEND(v) GIT_VERSION_CATTER(v)
+
+/* VERSION TAG */
+#ifdef GIT_VERSION
+GIT_VERSION_EXPEND(GIT_VERSION);
+#else
+static __attribute__((__used__)) const char * GIT_VERSION_UNKNOWN = NULL;
+#endif
+#undef GIT_VERSION_CATTER
+#undef GIT_VERSION_EXPEND
+
+#ifdef __cplusplus
+}
+#endif
+//endof Automatically generate the version number
+
+const char* draw_line="________________________________________________________________________________________________________________________________________________";
+const char* draw_boundary="============================================================";
+
+static char* __str_dup(const char* str)
+{
+ char* dup=NULL;
+ dup=(char*)calloc(sizeof(char),strlen(str)+1);
+ memcpy(dup, str, strlen(str));
+ return dup;
+}
+
+int is_valid_field_name(const char* name)
+{
+ const char* reserverd="|:\n\r. \t<>[]#!@";
+ unsigned int i=0,j=0;
+ for(i=0;i<strlen(name);i++)
+ {
+ for(j=0;j<strlen(reserverd);j++)
+ if(name[i]==reserverd[j])
+ {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
+
+struct metric_t* metric_new(enum field_type type, const char *field_name, const char *tag_key[], const char *tag_value[], size_t n_tag)
+{
+ int i = 0;
+ struct metric_t* metric=(struct metric_t*)calloc(sizeof(struct metric_t),1);
+ metric->field_name =__str_dup(field_name);
+ metric->field_type = type;
+ metric->is_ratio = 0;
+ metric->output_scaling = 1;
+ metric->n_tag = n_tag;
+
+ for(i = 0; i < (int)n_tag; i++)
+ {
+ metric->tag_key[i] = strdup(tag_key[i]);
+ metric->tag_value[i] = strdup(tag_value[i]);
+ }
+ return metric;
+}
+
+void metric_free(struct metric_t* metric)
+{
+ int i = 0;
+
+ free(metric->field_name);
+ metric->field_name = NULL;
+
+ for(i = 0; i < (int)metric->n_tag; i++)
+ {
+ free(metric->tag_key[i]);
+ metric->tag_key[i] = NULL;
+
+ free(metric->tag_value[i]);
+ metric->tag_value[i] = NULL;
+ }
+ metric->n_tag = 0;
+
+ free(metric);
+
+ return;
+}
+
+
+
+
+int fieldstat_set_app_name(struct fieldstat_instance *instance, const char *app_name)
+{
+ int len_app_name = strlen(app_name);
+ if(instance->running == 1)
+ {
+ return -1;
+ }
+ if(len_app_name <= 0 && len_app_name >= LEN_APP_NAME )
+ {
+ return -1;
+ }
+ strncpy(instance->app_name,(char*)app_name, len_app_name);
+ return 0;
+}
+
+int fieldstat_set_output_interval(struct fieldstat_instance *instance, int seconds)
+{
+ if(instance->running == 1 || seconds <= 0 )
+ {
+ return -1;
+ }
+ instance->output_interval_s = seconds;
+ return 0;
+}
+
+int fieldstat_backgroud_thead_disable(struct fieldstat_instance *instance)
+{
+ if(instance->running == 1)
+ {
+ return -1;
+ }
+ instance->background_thread_disable = 1;
+ return 0;
+}
+
+int fieldstat_prometheus_output_enable(struct fieldstat_instance *instance)
+{
+ if(instance->running == 1)
+ {
+ return -1;
+ }
+ instance->prometheus_output_enable = 1;
+ return 0;
+}
+
+int fieldstat_set_local_output(struct fieldstat_instance *instance, const char *filename, const char *format)
+{
+ int len_filename = strlen(filename);
+ int len_format = strlen(format);
+
+ if(instance->running == 1)
+ {
+ return -1;
+ }
+ if(strcmp(format,"default") != 0 && strcmp(format,"json") != 0)
+ {
+ return -1;
+ }
+ if(len_filename <= 0 || len_filename >= LEN_PATH_MAX)
+ {
+ return -1;
+ }
+ if(len_format <= 0 || len_format >= LEN_FORMAT_MAX)
+ {
+ return -1;
+ }
+
+ strncpy(instance->local_output_filename, (char *)filename, len_filename);
+ strncpy(instance->local_output_format, (char *)format, len_format);
+ instance->local_output_enable = 1;
+
+ return 0;
+}
+
+int fieldstat_set_line_protocol_server(struct fieldstat_instance *instance, const char *ip, unsigned short port)
+{
+ int len_ip = strlen(ip);
+
+ if(instance->running == 1)
+ {
+ return -1;
+ }
+ if(len_ip <= 0 || len_ip >= LEN_IP_MAX)
+ {
+ return -1;
+ }
+ if(1 != inet_pton(AF_INET, ip, (void *)&(instance->line_protocol_server_ip)))
+ {
+ return -1;
+ }
+
+ strncpy(instance->line_protocol_server_str_ip,(char *)ip,len_ip);
+ instance->line_protocol_server_port = port;
+ instance->line_protocol_output_enable = 1;
+
+ return 0;
+}
+
+int fieldstat_set_statsd_server(struct fieldstat_instance *instance, const char *ip, unsigned short port)
+{
+ int len_ip = strlen(ip);
+ if(instance->running == 1)
+ {
+ return -1;
+ }
+ if(len_ip <= 0 || len_ip >= LEN_IP_MAX)
+ {
+ return -1;
+ }
+
+ if(1 != inet_pton(AF_INET, ip, (void *)&(instance->statsd_server_ip)))
+ {
+ return -1;
+ }
+
+ strncpy(instance->statsd_server_str_ip,(char *)ip,len_ip);
+ instance->statsd_server_port = port;
+ instance->statsd_output_enable = 1;
+ return 0;
+}
+
+int fieldstat_register(struct fieldstat_instance *instance, enum field_type type, const char *field_name, const char *tag_key[], const char *tag_value[], size_t n_tag)
+{
+ int metric_id = 0;
+ struct metric_t * metric_choosen = NULL;
+ if(!is_valid_field_name(field_name))
+ {
+ return -1;
+ }
+ if(n_tag > N_TAG_MAX)
+ {
+ return -1;
+ }
+ //TODO not block
+ metric_id = instance->metric_cnt++;
+ assert(instance->metric_cnt < instance->metric_size);
+ metric_choosen = instance->metric[metric_id] = metric_new(type,field_name,tag_key,tag_value,n_tag);
+ switch(type)
+ {
+ case FIELD_TYPE_COUNTER:
+ instance->counter_cnt++;
+ memset(&(metric_choosen->counter), 0, sizeof(metric_choosen->counter));
+ break;
+ case FIELD_TYPE_GAUGE:
+ instance->gauge_cnt++;
+ memset(&(metric_choosen->gauge), 0, sizeof(metric_choosen->gauge));
+ break;
+ case FILED_TYPE_HISTOGRAM:
+ //instance->histogram_cnt++;
+ // TODO what?
+ break;
+ case FIELD_TYPE_SUMMARY:
+ //instance->summary_cnt++;
+ //TODO what ?
+ break;
+ default:
+ assert(0);
+ }
+ return metric_id;
+}
+
+
+//long long get_metric_unit_val(display_manifest_t* p, int column_seq,enum field_calc_algo calc_type,int is_refer)
+long long get_metric_unit_val(struct metric_t *metric,enum field_calc_algo calc_type,int is_refer)
+{
+ 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;
+ case FILED_TYPE_HISTOGRAM:
+ case FIELD_TYPE_SUMMARY:
+ default:
+ break;
+ }
+ value = threadsafe_counter_read(&(target->changing));
+ //value= threadsafe_counter_read(&(target->changing));
+ if(is_refer == 0)
+ {
+ target->previous_changed = value;
+ target->accumulated += value;
+ threadsafe_counter_set(&(target->changing), 0);
+ }
+ switch(calc_type)
+ {
+ case FS_CALC_CURRENT:
+ value=target->accumulated;
+ break;
+ case FS_CALC_SPEED:
+ value=target->previous_changed;
+ break;
+ default:
+ assert(0);
+ }
+ return value;
+}
+
+static int print_buf_tag_append_position(metric_t *metric, char *print_buf_tags, unsigned int size)
+{
+ int i = 0;
+ char *print_buf_tags_append_position = print_buf_tags;
+
+ print_buf_tags_append_position += snprintf(print_buf_tags_append_position, size - (print_buf_tags_append_position - print_buf_tags),"{");
+ for(; i < metric->n_tag; i++)
+ {
+ if(i == 0)
+ {
+ print_buf_tags_append_position += snprintf(print_buf_tags_append_position, size - (print_buf_tags_append_position - print_buf_tags),"%s=\"%s\"", metric->tag_key[i],metric->tag_value[i]);
+ }
+ else
+ {
+ print_buf_tags_append_position += snprintf(print_buf_tags_append_position, size - (print_buf_tags_append_position - print_buf_tags),",%s=\"%s\"", metric->tag_key[i],metric->tag_value[i]);
+ }
+ }
+ print_buf_tags_append_position += snprintf(print_buf_tags_append_position, size - (print_buf_tags_append_position - print_buf_tags),"}");
+
+ return print_buf_tags_append_position - print_buf_tags;
+}
+
+
+static int output_file_format_default_type_gauge(struct fieldstat_instance *instance,long long interval_ms,char *print_buf, unsigned int size)
+{
+ int i = 0, j = 0;
+ //display_manifest_t* p = NULL;
+ metric_t *metric = NULL;
+ long long value = 0;
+ //double ratio = 0.0;
+ //char* pos=print_buf;
+ char *print_buf_append_position = print_buf;
+ char print_buf_tags[1024];
+
+ for(i = 0; i < instance->metric_cnt; i++)
+ {
+ metric = instance->metric[i];
+ if(metric->field_type != FIELD_TYPE_GAUGE)
+ {
+ continue;
+ }
+ if(metric->is_invisible == 1)
+ {
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ continue;
+ }
+ /*
+ if(metric->is_ratio==1)
+ {
+ ratio=get_stat_ratio(_handle->display[p->numerator_id], _handle->display[p->denominator_id], NULL,
+ p->output_scaling, p->calc_type);
+ pos+=snprintf(pos,size-(pos-print_buf),"%s: %10.2e\t",p->name,ratio);
+ }
+ */
+ value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0);
+ //value=value * metric->output_scaling * 1000 / interval_ms;
+ memset(print_buf_tags,0, sizeof(print_buf_tags));
+ print_buf_tag_append_position(metric, print_buf_tags, sizeof(print_buf_tags));
+ print_buf_append_position += snprintf(print_buf_append_position, size - (print_buf_append_position - print_buf), "%s %s: %-10lld\t", metric->field_name, print_buf_tags, value);
+ j++;
+ if(j == STATUS_PER_LINE)
+ {
+ print_buf_append_position += snprintf(print_buf_append_position, size - (print_buf_append_position - print_buf),"\n");
+ j=0;
+ }
+ }
+
+ if(print_buf_append_position - print_buf > 0)
+ {
+ if(*(print_buf_append_position - 1) == '\n')
+ {
+ print_buf_append_position --;
+ }
+ print_buf_append_position += snprintf(print_buf_append_position, size - (print_buf_append_position-print_buf),"\n%s\n",draw_line);
+ }
+ return print_buf_append_position - print_buf;
+}
+
+
+static int output_file_format_default_type_counter(struct fieldstat_instance *instance,long long interval_ms,char*print_buf, unsigned int size)
+{
+ int i=0,j=0;
+ //display_manifest_t* p=NULL;
+ metric_t *metric = NULL;
+ long long value = 0;
+ //double ratio = 0.0;
+ char* print_buf_append_position = print_buf;
+ int metric_id[INIT_STAT_FIELD_NUM] = {0};
+ int metric_cnt = 0;
+ char print_buf_tags[1024];
+
+ for(i = 0;i < instance->metric_cnt; i++)
+ {
+ //p=_handle->display[i];
+ metric = instance->metric[i];
+ if(metric->field_type != FIELD_TYPE_COUNTER)
+ {
+ continue;
+ }
+ if(metric->is_invisible == 1)
+ {
+ get_metric_unit_val(metric,FS_CALC_CURRENT,0);
+ continue;
+ }
+ metric_id[metric_cnt] = i;
+ metric_cnt++;
+ }
+
+ for(i = 0; i < metric_cnt; i++)
+ {
+ print_buf_append_position += snprintf(print_buf_append_position, size - (print_buf_append_position - print_buf),"\t");
+
+ for(j = 0; j < FIELD_PER_LINE && i+j < metric_cnt; j++)
+ {
+ metric = instance->metric[metric_id[i+j]];
+ memset(print_buf_tags,0, sizeof(print_buf_tags));
+ print_buf_tag_append_position(metric, print_buf_tags, sizeof(print_buf_tags));
+ print_buf_append_position += snprintf(print_buf_append_position, size - (print_buf_append_position - print_buf), "%10s %s\t", metric->field_name, print_buf_tags);
+ }
+ print_buf_append_position += snprintf(print_buf_append_position, size - (print_buf_append_position-print_buf), "\nsum\t");
+
+ for(j=0; j < FIELD_PER_LINE && i+j < metric_cnt; j++)
+ {
+ metric = instance->metric[metric_id[i+j]];
+ value = get_metric_unit_val(metric,FS_CALC_CURRENT, 1);
+ print_buf_append_position += snprintf(print_buf_append_position, sizeof(print_buf) - (print_buf_append_position - print_buf), "%10lld\t", value);
+ }
+ print_buf_append_position += snprintf(print_buf_append_position, sizeof(print_buf) - (print_buf_append_position - print_buf), "\nspeed/s\t");
+
+ for(j=0;j<FIELD_PER_LINE&&i+j<metric_cnt;j++)
+ {
+ metric = instance->metric[metric_id[i+j]];
+ value = get_metric_unit_val(metric,FS_CALC_SPEED, 0);
+ print_buf_append_position += snprintf(print_buf_append_position, size - (print_buf_append_position - print_buf), "%10lld\t", value*1000/interval_ms);
+ }
+ i += (j-1);
+ print_buf_append_position += snprintf(print_buf_append_position, size - (print_buf_append_position - print_buf), "\n");
+ }
+
+ if(print_buf_append_position - print_buf > 0)
+ {
+ if(*(print_buf_append_position - 1)=='\n')
+ {
+ print_buf_append_position--;
+ }
+ print_buf_append_position += snprintf(print_buf_append_position, size - (print_buf_append_position - print_buf),"\n%s\n", draw_line);
+ }
+
+ return print_buf_append_position - print_buf;
+}
+
+
+int fieldstat_output_file(struct fieldstat_instance *instance,long long interval_ms)
+{
+ size_t print_buf_sz = instance->metric_cnt*1024;
+ char *print_buf = NULL;
+ char *print_buf_append_position = NULL;
+ time_t current = 0;
+ char ctime_buff[32]={0};
+
+ if(instance->fp == NULL)
+ {
+ instance->fp = fopen(instance->local_output_filename, "w");
+ if(instance->fp == NULL)
+ {
+ printf("Field Stat: open %s failed.\n",instance->local_output_filename);
+ assert(0);
+ return -1;
+ }
+ }
+
+ if(!strcmp(instance->local_output_format, "default"))
+ {
+ time(&current);
+ ctime_r(&current, ctime_buff);
+ print_buf = (char*)calloc(sizeof(char), print_buf_sz);
+ print_buf_append_position = print_buf;
+ print_buf_append_position += snprintf(print_buf_append_position, print_buf_sz - (print_buf_append_position - print_buf), "%s%s", draw_boundary, ctime_buff);
+ print_buf_append_position --;//jump '\n' generate by ctime()
+ print_buf_append_position += snprintf(print_buf_append_position, print_buf_sz - (print_buf_append_position - print_buf),"%s\n",draw_boundary);
+
+ //pthread_mutex_lock(&(_handle->reg_lock)); //TODO
+ print_buf_append_position += output_file_format_default_type_gauge(instance, interval_ms, print_buf_append_position, print_buf_sz - (print_buf_append_position - print_buf));
+ print_buf_append_position += output_file_format_default_type_counter(instance, interval_ms, print_buf_append_position, print_buf_sz - (print_buf_append_position - print_buf));
+ //TODO output table,output histogram,output summary
+ //pthread_mutex_unlock(&(_handle->reg_lock));//TODO
+ }
+
+ if(!strcmp(instance->local_output_format, "json"))
+ {
+ //TODO from json output
+ }
+
+ fseek(instance->fp,0,SEEK_SET);
+ fwrite(print_buf,print_buf_append_position - print_buf,1,instance->fp);
+
+ fflush(instance->fp);
+
+ if(print_buf)
+ {
+ free(print_buf);
+ print_buf = NULL;
+ }
+ return 0;
+}
+
+
+void fieldstat_passive_output(struct fieldstat_instance *instance)
+{
+ struct timespec this_output_time;
+ long long interval_ms = 0;
+ int ret = 0;
+
+ if(instance->running == 0)
+ {
+ return;
+ }
+
+ clock_gettime(CLOCK_MONOTONIC ,&this_output_time);
+ interval_ms = (this_output_time.tv_sec - instance->last_output_time.tv_sec) * 1000 + (this_output_time.tv_nsec - instance->last_output_time.tv_nsec) / 1000000;
+ if(interval_ms < 1)
+ {
+ printf("Passive return\n");
+ return;
+ }
+
+ if(instance->local_output_enable)
+ {
+ ret = fieldstat_output_file(instance, interval_ms);
+ }
+ if(ret == -1)
+ {
+ return;
+ }
+ memcpy(&(instance->last_output_time),&this_output_time, sizeof(this_output_time));
+}
+
+void *fieldstat_thread_schema_output(void *arg)
+{
+ struct fieldstat_instance *instance=(struct fieldstat_instance *)arg;
+ while(instance->background_thread_disable == 0)
+ {
+ fieldstat_passive_output(instance);
+ sleep(instance->output_interval_s);
+ }
+ return NULL;
+}
+
+
+void fieldstat_instance_start(struct fieldstat_instance *instance)
+{
+ instance->running = 1;
+ 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);
+ }
+ //append instance to prometheus output
+}
+
+struct fieldstat_instance * fieldstat_instance_create(void)
+{
+ struct fieldstat_instance *instance = (struct fieldstat_instance *)calloc(sizeof(struct fieldstat_instance),1);
+
+ strcpy(instance->app_name, "?");
+ instance->running = 0;
+ instance->output_interval_s = 2; //default 2s
+ instance->background_thread_disable = 0;
+ instance->metric_size = NUM_INIT_METRICS;
+ instance->metric =(struct metric_t **)calloc(sizeof(struct metric *), instance->metric_size);
+ return instance;
+}
diff --git a/src/fieldstat_internal.h b/src/fieldstat_internal.h
new file mode 100644
index 0000000..c9baf1d
--- /dev/null
+++ b/src/fieldstat_internal.h
@@ -0,0 +1,82 @@
+#ifndef __FIELD_STAT2_INTERNAL_H__
+#define __FIELD_STAT2_INTERNAL_H__
+
+#include <pthread.h>
+#include "hdr_histogram.h"
+#include "threadsafe_counter.h"
+
+#define INIT_STAT_FIELD_NUM 1024
+#define MAX_STAT_COLUMN_NUM 64
+#define MAX_PATH_LEN 256
+#define UDP_PAYLOAD_SIZE 1460
+
+#define STATUS_PER_LINE 6
+#define FIELD_PER_LINE 8
+
+
+
+#define HISOTGRAM_EXTRA_INF 0
+#define HISTOGRAM_EXTRA_SUM 1
+#define HISTOGRAM_EXTRA_MAXVAL 2
+#define HISTOGRAM_EXTRA_SIZE 3
+
+
+
+#define N_TAG_MAX 32
+#define NUM_INIT_METRICS 1024
+
+enum field_calc_algo
+{
+ FS_CALC_CURRENT=0,
+ FS_CALC_SPEED
+};
+
+struct stat_unit_t
+{
+ struct threadsafe_counter changing;
+ long long accumulated;
+ long long previous_changed;
+};
+struct histogram_t
+{
+ struct hdr_histogram* changing;
+ struct hdr_histogram* accumulated;
+ struct hdr_histogram* previous_changed;
+ int64_t lowest_trackable_value;
+ int64_t highest_trackable_value;
+ int significant_figures;
+
+};
+
+
+struct metric_t
+{
+ char *field_name;
+ enum field_type field_type;
+ size_t n_tag;
+ char *tag_key[N_TAG_MAX];
+ char *tag_value[N_TAG_MAX];
+ int output_scaling;
+
+ int is_invisible;
+ int is_ratio;
+ int not_send_to_server;
+ int numerator_id;
+ int denominator_id;
+
+ union
+ {
+ struct stat_unit_t counter;
+ struct stat_unit_t gauge;
+ struct stat_unit_t single;//for status and field
+ struct stat_unit_t* line; //for line
+ struct histogram_t histogram;
+ int column_seq; //for column
+ };
+};
+
+
+
+
+
+#endif
diff --git a/test/fs2_test.cpp b/test/fs2_test.cpp
index 5b4af3f..b049059 100644
--- a/test/fs2_test.cpp
+++ b/test/fs2_test.cpp
@@ -1,4 +1,4 @@
-#include "../inc/field_stat2.h"
+#include "../inc/fieldstat.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
@@ -15,201 +15,76 @@
#define TEST_RUNTIME_REG_NUM 32
#define TEST_RUNTIME_REG_LINE_NUM 6
-int status_ids[TEST_STATUS_NUM], field_ids[TEST_FIELD_NUM], line_ids[TEST_LINE_NUM + TEST_RUNTIME_REG_LINE_NUM], column_ids[TEST_COLUMN_NUM];
-int histogram_ids[TEST_HISTOGRAM_NUM];
-int runtime_status_ids[TEST_RUNTIME_REG_NUM];
-int runtime_reg_num = 0, runtime_reg_line_num = 0;
-struct thread_para
-{
- int loops;
- screen_stat_handle_t handle;
- int thread_id;
-};
-static void* worker_thread(void* arg)
+
+int main(int argc, char *argv[])
{
-
- struct thread_para* para=(struct thread_para*)arg;
- int loops = para->loops, i=0, j=0;
- screen_stat_handle_t handle=para->handle;
- char buff[128];
- int ret=0;
- while (loops > 0)
+ int ret = 0;
+ struct fieldstat_instance * test_instance = NULL;
+ const char *tag_key[] = {"A","B","C"};
+ const char *tag_value[] = {"a1","b1","c1"};
+
+ test_instance = fieldstat_instance_create();
+ ret = fieldstat_set_app_name(test_instance, "test");
+ if(ret == -1)
{
- loops--;
- for (i = 0; i < TEST_STATUS_NUM; i++)
- {
- FS_operate(handle, status_ids[i], 0, FS_OP_SET, i * 10);
- }
- for (i = 0; i < TEST_FIELD_NUM; i++)
- {
- FS_operate(handle, field_ids[i], 0, FS_OP_ADD, i * 100);
- }
- for (i = 0; i < TEST_LINE_NUM + runtime_reg_line_num; i++)
- {
- for (j = 0; j < TEST_COLUMN_NUM; j++)
- {
- FS_operate(handle, line_ids[i], column_ids[j], FS_OP_ADD, (j + 1) * 30);
- }
- }
- for (i = 0; i < runtime_reg_num; i++)
- {
- FS_operate(handle, runtime_status_ids[i], 0, FS_OP_ADD, i * 1000);
- }
- if (runtime_reg_num < TEST_RUNTIME_REG_NUM)
- {
- snprintf(buff, sizeof(buff), "rt_reg_%02d", runtime_reg_num);
- ret = FS_register(handle, FS_STYLE_STATUS, FS_CALC_SPEED, buff);
- assert(ret >= 0);
- runtime_status_ids[runtime_reg_num] = ret;
- runtime_reg_num++;
- ret = FS_register(handle, FS_STYLE_COLUMN, FS_CALC_SPEED, buff);
- assert(ret == -1); //always failed
- }
- if (runtime_reg_line_num < TEST_RUNTIME_REG_LINE_NUM)
- {
- snprintf(buff, sizeof(buff), "line_rt_%02d", runtime_reg_line_num);
- ret = FS_register(handle, FS_STYLE_LINE, FS_CALC_SPEED, buff);
- assert(ret >= 0);
- line_ids[TEST_LINE_NUM + runtime_reg_line_num] = ret;
- runtime_reg_line_num++;
- }
- long long preset[] = {1, 10, 20, 30, 40, 200, 300, 400, 600, 1000, 2000, 4000, 5000, 8000, 100000};
- for (i = 0; i < TEST_HISTOGRAM_NUM; i++)
- {
- for (j = 0; (size_t)j < sizeof(preset) / sizeof(long long); j++)
- {
- FS_operate(handle, histogram_ids[i], 0, FS_OP_SET, preset[j]);
- }
- }
- sleep(1);
+ printf("set fieldstat app_name failed!\n");
}
- return NULL;
-}
-int main(int argc, char *argv[])
-{
- screen_stat_handle_t handle = NULL;
- const char *stat_path = "./fs2_test.status";
- const char *app_name = "fs2_test";
- char buff[128];
- int value = 0, i = 0;
-
- srand(171);
-
- unsigned short port = 9001;
- FS_library_set_prometheus_port(port);
- char *url_path = (char *)"/prometheus";
- FS_library_set_prometheus_url_path(url_path);
- FS_library_init();
- struct timespec start;
- long time_use;
- for (int repeat_cnt = 0; repeat_cnt < 2; repeat_cnt++)
+ ret = fieldstat_set_local_output(test_instance, "./test.fs", "default");
+ if(ret == -1)
{
- record_time_start(&start);
-
- handle = FS_create_handle();
-
- FS_set_para(handle, APP_NAME, app_name, strlen(app_name) + 1);
- value = 0;
- FS_set_para(handle, FLUSH_BY_DATE, &value, sizeof(value));
- FS_set_para(handle, OUTPUT_DEVICE, stat_path, strlen(stat_path) + 1);
- value = 1;
- FS_set_para(handle, PRINT_MODE, &value, sizeof(value));
- value = 1;
- FS_set_para(handle, CREATE_THREAD, &value, sizeof(value));
- value = 0;
- FS_set_para(handle, METRIS_FORMAT, &value, sizeof(value));
- value = 2;
- FS_set_para(handle, STAT_CYCLE, &value, sizeof(value));
- value = 4096;
- FS_set_para(handle, MAX_STAT_FIELD_NUM, &value, sizeof(value));
-
- FS_set_para(handle, STATS_SERVER_IP, "127.0.0.1", strlen("127.0.0.1"));
- value = 8100;
- FS_set_para(handle, STATS_SERVER_PORT, &value, sizeof(value));
-
- //value=FS_OUTPUT_INFLUX_LINE;
- value = FS_OUTPUT_STATSD;
- FS_set_para(handle, STATS_FORMAT, &value, sizeof(value));
-
- value = 1;
- FS_set_para(handle, OUTPUT_PROMETHEUS, &value, sizeof(value));
-
- const char *histogram_format = "0.1,0.5,0.8,0.9,0.95,0.99";
- FS_set_para(handle, HISTOGRAM_GLOBAL_BINS, histogram_format, strlen(histogram_format) + 1);
-
-
- for (i = 0; i < TEST_STATUS_NUM; i++)
- {
- snprintf(buff, sizeof(buff), "(status_%02d)/\\-,;%%$*", i);
- status_ids[i] = FS_register(handle, FS_STYLE_STATUS, FS_CALC_CURRENT, buff);
- }
- for (i = 0; i < TEST_FIELD_NUM; i++)
- {
- snprintf(buff, sizeof(buff), "(field_%02d)", i);
- field_ids[i] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, buff);
- }
- for (i = 0; i < TEST_LINE_NUM; i++)
- {
- snprintf(buff, sizeof(buff), "line_%d", i);
- line_ids[i] = FS_register(handle, FS_STYLE_LINE, FS_CALC_CURRENT, buff);
- }
- for (i = 0; i < TEST_COLUMN_NUM; i++)
- {
- snprintf(buff, sizeof(buff), "column_%d", i);
- column_ids[i] = FS_register(handle, FS_STYLE_COLUMN, FS_CALC_SPEED, buff);
- }
- for (i = 0; i < TEST_HISTOGRAM_NUM; i++)
- {
- snprintf(buff, sizeof(buff), "{rpc_%d}", i);
- if (i == 1)
- {
- histogram_ids[i] = FS_register_histogram(handle, FS_CALC_SPEED, buff, 1, 100000, 3);
- }
- else
- {
- histogram_ids[i] = FS_register_histogram(handle, FS_CALC_CURRENT, buff, 1, 100000, 3);
- }
- }
- value = column_ids[2];
- FS_set_para(handle, ID_INVISBLE, &value, sizeof(value));
- snprintf(buff, sizeof(buff), "c0/c1");
- FS_register_ratio(handle,
- column_ids[0],
- column_ids[1],
- 1,
- FS_STYLE_COLUMN,
- FS_CALC_SPEED,
- buff);
- value = line_ids[1];
- FS_set_para(handle, NOT_SEND_METRIC_TO_SERVER, &value, sizeof(value));
-
- FS_start(handle);
- int thread_num=16;
- pthread_t threads[thread_num];
- struct thread_para para;
- para.loops=10;
- para.handle=handle;
- for(i=0; i<thread_num; i++)
- {
- pthread_create(&(threads[i]), NULL, worker_thread, &para);
- }
- void *temp;
- for(i=0; i<thread_num; i++)
- {
- pthread_join(threads[i], (void**)&temp);
- }
-
-
- FS_stop(&handle);
- time_use = record_time_elapse_us(&start);
- printf("fs2 stoped cnt = %d, cost %ld us, will sleep 1s\n", repeat_cnt, time_use);
- sleep(1);
+ printf("set fieldstat local_outpud failed!\n");
}
- printf("Start FS library destoryed ...\n");
- FS_library_destroy();
- printf("FS library destoryed, will sleep 30s\n");
- sleep(30);
+
+ ret = fieldstat_set_output_interval(test_instance, 5);
+ if(ret == -1)
+ {
+ printf("Set output_interval failed!\n");
+ }
+
+ ret = fieldstat_backgroud_thead_disable(test_instance);
+ if(ret == -1)
+ {
+ printf("Set backgroud thread disable failed!\n");
+ }
+
+ ret = fieldstat_set_line_protocol_server(test_instance, "127.0.0.1", 8001);
+ if(ret == -1)
+ {
+ printf("Failed to set line_protocol server\n");
+ }
+
+ ret = fieldstat_set_statsd_server(test_instance, "192.168.100.1", 8002);
+ if(ret == -1)
+ {
+ printf("Failed to set statsd_server!\n");
+ }
+
+ ret = fieldstat_prometheus_output_enable(test_instance);
+ if(ret == -1)
+ {
+ printf("Failed to set prometheus_output_enable!\n");
+ }
+
+ ret = fieldstat_register(test_instance, FIELD_TYPE_COUNTER, "metric_0", tag_key, tag_value, sizeof(tag_key)/sizeof(tag_key[0]));
+ if(ret == -1)
+ {
+ printf("Failed to register metric!\n");
+ }
+
+
+ ret = fieldstat_register(test_instance, FIELD_TYPE_COUNTER, "metric_1", tag_key, tag_value, sizeof(tag_key)/sizeof(tag_key[0]));
+ if(ret == -1)
+ {
+ printf("Failed to register metric!\n");
+ }
+
+ ret = fieldstat_register(test_instance, FIELD_TYPE_GAUGE, "gauge_0",tag_key, tag_value, sizeof(tag_key)/sizeof(tag_key[0]));
+
+ fieldstat_instance_start(test_instance);
+ sleep(1);
+ fieldstat_passive_output(test_instance);
+ printf("Testing for fieldstat\n");
return 0;
}