statsd adding default copyright template to source code file
[sip-router] / src / modules / statsd / statsd.c
1 /**
2  *
3  * This file is part of Kamailio, a free SIP server.
4  *
5  * This file is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version
9  *
10  *
11  * This file is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21 #include <sys/time.h>
22 #include <stdlib.h>
23
24 #include "../../core/sr_module.h"
25 #include "../../core/usr_avp.h"
26 #include "../../core/pvar.h"
27 #include "../../core/lvalue.h"
28 #include "lib_statsd.h"
29
30
31 MODULE_VERSION
32
33 static int mod_init(void);
34 static int mod_destroy(void);
35 static int func_gauge(struct sip_msg *msg, char *key, char* val);
36 static int func_set(struct sip_msg *msg, char *key, char* val);
37 static int func_time_start(struct sip_msg *msg, char *key);
38 static int func_time_end(struct sip_msg *msg, char *key);
39 static int func_incr(struct sip_msg *msg, char *key);
40 static int func_decr(struct sip_msg *msg, char *key);
41 static char* get_milliseconds(char *dst);
42
43 typedef struct StatsdParams{
44     char *ip;
45     char *port;
46 } StatsdParams;
47
48 static StatsdParams statsd_params= {};
49
50 static cmd_export_t commands[] = {
51         {"statsd_gauge", (cmd_function)func_gauge, 2, 0, 0, ANY_ROUTE},
52         {"statsd_start", (cmd_function)func_time_start, 1, 0, 0, ANY_ROUTE},
53         {"statsd_stop", (cmd_function)func_time_end, 1, 0, 0, ANY_ROUTE},
54         {"statsd_incr", (cmd_function)func_incr, 1, 0, 0, ANY_ROUTE},
55         {"statsd_decr", (cmd_function)func_decr, 1, 0, 0, ANY_ROUTE},
56         {"statsd_set", (cmd_function)func_set, 2, 0, 0, ANY_ROUTE},
57     {0, 0, 0, 0, 0, 0}
58 };
59
60 static param_export_t parameters[] = {
61     {"ip", STR_PARAM, &(statsd_params.ip)},
62     {"port", STR_PARAM, &(statsd_params.port)},
63     {0, 0, 0}
64 };
65
66 struct module_exports exports = {
67     "statsd",    // module name
68     DEFAULT_DLFLAGS, // dlopen flags
69     commands,        // exported functions
70     parameters,      // exported parameters
71     NULL,            // exported statistics
72     NULL,            // exported MI functions
73     NULL,            // exported seudo-variables
74     NULL,            // extra processes
75     mod_init,        // module init function (before fork. kids will inherit)
76     NULL,            // reply processing function
77     (destroy_function) mod_destroy,     // destroy function
78     NULL       // child init function
79 };
80
81
82 static int mod_init(void)
83 {
84     int rc = 0;
85     if(!statsd_params.ip){
86         LM_INFO("Statsd init ip value is null. use default 127.0.0.1\r\n");
87     }else{
88         LM_INFO("Statsd init ip value %s \r\n", statsd_params.ip);
89     }
90
91     if(!statsd_params.port){
92         LM_INFO("Statsd init port value is null. use default 8125\r\n");
93     } else {
94         LM_INFO("Statsd init port value %s\r\n", statsd_params.port);
95     }
96
97     rc = statsd_init(statsd_params.ip, statsd_params.port);
98     if (rc < 0){
99         LM_ERR("Statsd connection failed (ERROR_CODE: %i) \n",rc);
100         return -1;
101     }else{
102         LM_INFO("Statsd: success connection to statsd server\n");
103     }
104     return 0;
105 }
106
107 /**
108 * destroy module function
109 */
110 static int mod_destroy(void)
111 {
112     statsd_destroy();
113     return 0;
114 }
115
116 static int func_gauge(struct sip_msg* msg, char* key, char* val)
117 {
118     return statsd_gauge(key, val);
119 }
120
121 static int func_set(struct sip_msg* msg, char* key, char* val)
122 {
123     return statsd_set(key, val);
124 }
125
126 static int func_time_start(struct sip_msg *msg, char *key)
127 {
128     int_str avp_key, avp_val;
129     char unix_time[24];
130     get_milliseconds(unix_time);
131     avp_key.s.s = key;
132     avp_key.s.len = strlen(avp_key.s.s);
133
134     avp_val.s.s = unix_time;
135     avp_val.s.len = strlen(avp_val.s.s);
136
137         if (add_avp(AVP_NAME_STR|AVP_VAL_STR, avp_key, avp_val) < 0) {
138         LM_ERR("Statsd: time start failed to create AVP\n");
139         return -1;
140     }
141     return 1;
142 }
143
144
145 static int func_time_end(struct sip_msg *msg, char *key)
146 {
147     char unix_time[24];
148     char *endptr;
149     long int start_time;
150     int result;
151
152     struct search_state st;
153
154     get_milliseconds(unix_time);
155     LM_DBG("Statsd: statsd_stop at %s\n",unix_time);
156     avp_t* prev_avp;
157
158     int_str avp_value, avp_name;
159     avp_name.s.s = key;
160     avp_name.s.len = strlen(avp_name.s.s);
161
162     prev_avp = search_first_avp(
163         AVP_NAME_STR|AVP_VAL_STR, avp_name, &avp_value, &st);
164     if(avp_value.s.len == 0){
165         LM_ERR("Statsd: statsd_stop not valid key(%s)\n",key);
166         return 1;
167     }
168
169     start_time = strtol(avp_value.s.s, &endptr,10);
170     if(strlen(endptr) >0){
171       LM_DBG(
172           "Statsd:statsd_stop not valid key(%s) it's not a number value=%s\n",
173           key, avp_value.s.s);
174       return 0;
175     }
176
177     result = atol(unix_time) - start_time;
178     LM_DBG(
179         "Statsd: statsd_stop Start_time=%ld unix_time=%ld (%i)\n",
180         start_time, atol(unix_time), result);
181     destroy_avp(prev_avp);
182     return statsd_timing(key, result);
183 }
184
185
186 static int func_incr(struct sip_msg *msg, char *key)
187 {
188     return statsd_count(key, "+1");
189 }
190
191
192 static int func_decr(struct sip_msg *msg, char *key)
193 {
194     return statsd_count(key, "-1");
195 }
196
197
198 char* get_milliseconds(char *dst){
199     struct timeval tv;
200     long int millis;
201
202     gettimeofday(&tv, NULL);
203     millis = (tv.tv_sec * (int)1000) + (tv.tv_usec / 1000);
204     snprintf(dst, 21, "%ld", millis);
205     return dst;
206 }