statsd: one more increase for milliseconds buffer
[sip-router] / modules / statsd / statsd.c
1
2 #include <sys/time.h>
3 #include <stdlib.h>
4
5 #include "../../sr_module.h"
6 #include "../../usr_avp.c"
7 #include "../../pvar.h"
8 #include "../../lvalue.h"
9 #include "lib_statsd.h"
10
11
12 MODULE_VERSION
13
14 static int mod_init(void);
15 static int mod_destroy(void);
16 static int func_gauge(struct sip_msg *msg, char *key, char* val);
17 static int func_set(struct sip_msg *msg, char *key, char* val);
18 static int func_time_start(struct sip_msg *msg, char *key);
19 static int func_time_end(struct sip_msg *msg, char *key);
20 static int func_incr(struct sip_msg *msg, char *key);
21 static int func_decr(struct sip_msg *msg, char *key);
22 static char* get_milliseconds(char *dst);
23
24 typedef struct StatsdParams{
25     char *ip;
26     char *port;
27 } StatsdParams;
28
29 static StatsdParams statsd_params= {};
30
31 static cmd_export_t commands[] = {
32         {"statsd_gauge", (cmd_function)func_gauge, 2, 0, 0, ANY_ROUTE},
33         {"statsd_start", (cmd_function)func_time_start, 1, 0, 0, ANY_ROUTE},
34         {"statsd_stop", (cmd_function)func_time_end, 1, 0, 0, ANY_ROUTE},
35         {"statsd_incr", (cmd_function)func_incr, 1, 0, 0, ANY_ROUTE},
36         {"statsd_decr", (cmd_function)func_decr, 1, 0, 0, ANY_ROUTE},
37         {"statsd_set", (cmd_function)func_set, 2, 0, 0, ANY_ROUTE},
38     {0, 0, 0, 0, 0, 0}
39 };
40
41 static param_export_t parameters[] = {
42     {"ip", STR_PARAM, &(statsd_params.ip)},
43     {"port", STR_PARAM, &(statsd_params.port)},
44     {0, 0, 0}
45 };
46
47 struct module_exports exports = {
48     "statsd",    // module name
49     DEFAULT_DLFLAGS, // dlopen flags
50     commands,        // exported functions
51     parameters,      // exported parameters
52     NULL,            // exported statistics
53     NULL,            // exported MI functions
54     NULL,            // exported seudo-variables
55     NULL,            // extra processes
56     mod_init,        // module init function (before fork. kids will inherit)
57     NULL,            // reply processing function
58     (destroy_function) mod_destroy,     // destroy function
59     NULL       // child init function
60 };
61
62
63 static int mod_init(void)
64 {
65     int rc = 0;
66     if(!statsd_params.ip){
67         LM_INFO("Statsd init ip value is null. use default 127.0.0.1\r\n");
68     }else{
69         LM_INFO("Statsd init ip value %s \r\n", statsd_params.ip);
70     }
71
72     if(!statsd_params.port){
73         LM_INFO("Statsd init port value is null. use default 8125\r\n");
74     } else {
75         LM_INFO("Statsd init port value %s\r\n", statsd_params.port);
76     }
77
78     rc = statsd_init(statsd_params.ip, statsd_params.port);
79     if (rc < 0){
80         LM_ERR("Statsd connection failed (ERROR_CODE: %i) \n",rc);
81         return -1;
82     }else{
83         LM_INFO("Statsd: success connection to statsd server\n");
84     }
85     return 0;
86 }
87
88 /**
89 * destroy module function
90 */
91 static int mod_destroy(void)
92 {
93     statsd_destroy();
94     return 0;
95 }
96
97 static int func_gauge(struct sip_msg* msg, char* key, char* val)
98 {
99     return statsd_gauge(key, val);
100 }
101
102 static int func_set(struct sip_msg* msg, char* key, char* val)
103 {
104     return statsd_set(key, val);
105 }
106
107 static int func_time_start(struct sip_msg *msg, char *key)
108 {
109     int_str avp_key, avp_val;
110     char unix_time[24];
111     get_milliseconds(unix_time);
112     avp_key.s.s = key;
113     avp_key.s.len = strlen(avp_key.s.s);
114
115     avp_val.s.s = unix_time;
116     avp_val.s.len = strlen(avp_val.s.s);
117
118         if (add_avp(AVP_NAME_STR|AVP_VAL_STR, avp_key, avp_val) < 0) {
119         LM_ERR("Statsd: time start failed to create AVP\n");
120         return -1;
121     }
122     return 1;
123 }
124
125
126 static int func_time_end(struct sip_msg *msg, char *key)
127 {
128     char unix_time[24];
129     char *endptr;
130     long int start_time;
131     int result;
132
133     struct search_state st;
134
135     get_milliseconds(unix_time);
136     LM_DBG("Statsd: statsd_stop at %s\n",unix_time);
137     avp_t* prev_avp;
138
139     int_str avp_value, avp_name;
140     avp_name.s.s = key;
141     avp_name.s.len = strlen(avp_name.s.s);
142
143     prev_avp = search_first_avp(
144         AVP_NAME_STR|AVP_VAL_STR, avp_name, &avp_value, &st);
145     if(avp_value.s.len == 0){
146         LM_ERR("Statsd: statsd_stop not valid key(%s)\n",key);
147         return 1;
148     }
149
150     start_time = strtol(avp_value.s.s, &endptr,10);
151     if(strlen(endptr) >0){
152       LM_DBG(
153           "Statsd:statsd_stop not valid key(%s) it's not a number value=%s\n",
154           key, avp_value.s.s);
155       return 0;
156     }
157
158     result = atol(unix_time) - start_time;
159     LM_DBG(
160         "Statsd: statsd_stop Start_time=%ld unix_time=%ld (%i)\n",
161         start_time, atol(unix_time), result);
162     destroy_avp(prev_avp);
163     return statsd_timing(key, result);
164 }
165
166
167 static int func_incr(struct sip_msg *msg, char *key)
168 {
169     return statsd_count(key, "+1");
170 }
171
172
173 static int func_decr(struct sip_msg *msg, char *key)
174 {
175     return statsd_count(key, "-1");
176 }
177
178
179 char* get_milliseconds(char *dst){
180     struct timeval tv;
181     long int millis;
182
183     gettimeofday(&tv, NULL);
184     millis = (tv.tv_sec * (int)1000) + (tv.tv_usec / 1000);
185     snprintf(dst, 21, "%ld", millis);
186     return dst;
187 }