Coverage Report

Created: 2026-05-04 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensips/core_stats.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2006 Voice Sistem SRL
3
 *
4
 * This file is part of opensips, a free SIP server.
5
 *
6
 * opensips is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * opensips 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
 * History:
21
 * ---------
22
 *  2006-01-23  first version (bogdan)
23
 *  2006-11-28  Added statistics for the number of bad URI's, methods, and
24
 *              proxy requests (Jeffrey Magder - SOMA Networks)
25
 *  2009-04-23  NET and PKG statistics added (bogdan)
26
 */
27
28
/*!
29
 * \file
30
 * \brief OpenSIPS Core statistics
31
 */
32
33
34
#include <string.h>
35
36
#include "statistics.h"
37
#include "globals.h"
38
#include "pt.h"
39
#include "timer.h"
40
#include <sys/types.h>
41
#include <signal.h>
42
#include "socket_info.h"
43
#include "ipc.h"
44
45
46
#ifdef STATISTICS
47
48
/*************************** SIP statistics *********************************/
49
stat_var* rcv_reqs;
50
stat_var* rcv_rpls;
51
stat_var* fwd_reqs;
52
stat_var* fwd_rpls;
53
stat_var* drp_reqs;
54
stat_var* drp_rpls;
55
stat_var* err_reqs;
56
stat_var* err_rpls;
57
stat_var* bad_URIs;
58
stat_var* bad_msg_hdr;
59
stat_var* slow_msgs;
60
61
62
const stat_export_t core_stats[] = {
63
  {"rcv_requests" ,         0,  &rcv_reqs              },
64
  {"rcv_replies" ,          0,  &rcv_rpls              },
65
  {"fwd_requests" ,         0,  &fwd_reqs              },
66
  {"fwd_replies" ,          0,  &fwd_rpls              },
67
  {"drop_requests" ,        0,  &drp_reqs              },
68
  {"drop_replies" ,         0,  &drp_rpls              },
69
  {"err_requests" ,         0,  &err_reqs              },
70
  {"err_replies" ,          0,  &err_rpls              },
71
  {"bad_URIs_rcvd",         0,  &bad_URIs              },
72
  {"bad_msg_hdr",           0,  &bad_msg_hdr           },
73
  {"slow_messages" ,        0,  &slow_msgs             },
74
  {"timestamp",  STAT_IS_FUNC, (stat_var**)get_ticks   },
75
  {0,0,0}
76
};
77
78
79
80
/*************************** NET statistics *********************************/
81
82
static unsigned long net_get_wb_udp(unsigned short foo)
83
0
{
84
0
  return get_total_bytes_waiting(PROTO_UDP);
85
0
}
86
87
static unsigned long net_get_wb_tcp(unsigned short foo)
88
0
{
89
0
  return get_total_bytes_waiting(PROTO_TCP);
90
0
}
91
92
static unsigned long net_get_wb_tls(unsigned short foo)
93
0
{
94
0
  return get_total_bytes_waiting(PROTO_TLS);
95
0
}
96
97
const stat_export_t net_stats[] = {
98
  {"waiting_udp" ,    STAT_IS_FUNC,  (stat_var**)net_get_wb_udp    },
99
  {"waiting_tcp" ,    STAT_IS_FUNC,  (stat_var**)net_get_wb_tcp    },
100
  {"waiting_tls" ,    STAT_IS_FUNC,  (stat_var**)net_get_wb_tls    },
101
  {0,0,0}
102
};
103
104
105
106
/*************************** PKG statistics *********************************/
107
108
#ifdef PKG_MALLOC
109
static pkg_status_holder *pkg_status = NULL;
110
static time_t *marker_t = NULL;
111
static int no_pkg_status = 0;
112
113
static void rpc_get_pkg_stats(int sender_id, void *foo)
114
{
115
#ifdef PKG_MALLOC
116
  pkg_status_holder *holder;
117
118
  holder = (pkg_status && process_no<no_pkg_status)?
119
    &(pkg_status[process_no]) : NULL ;
120
121
  set_pkg_stats( holder );
122
#endif
123
  return;
124
}
125
126
static inline void signal_pkg_status(unsigned long proc_id)
127
{
128
  time_t t;
129
130
  if (IPC_FD_WRITE(proc_id)<=0)
131
    return;
132
133
  t = time(NULL);
134
  if (t>marker_t[proc_id]+1) {
135
136
    if (proc_id==process_no) {
137
      /* avoid sending IPC to ourselves, as it will get executed
138
       * after we ar done with pkg_status job; better do it inline */
139
      rpc_get_pkg_stats(process_no, NULL);
140
    } else {
141
      if (ipc_send_rpc( proc_id, rpc_get_pkg_stats, NULL)<0) {
142
        LM_ERR("failed to trigger pkg stats for process %ld\n",
143
          proc_id );
144
        return;
145
      }
146
    }
147
148
    marker_t[proc_id] = t;
149
    usleep(20);
150
  }
151
}
152
153
static unsigned long get_pkg_total_size( void* proc_id)
154
{
155
  signal_pkg_status((unsigned long)proc_id);
156
  return pkg_status[(unsigned long)proc_id][PKG_TOTAL_SIZE_IDX];
157
}
158
159
static unsigned long get_pkg_used_size( void* proc_id)
160
{
161
  signal_pkg_status((unsigned long)proc_id);
162
  return pkg_status[(unsigned long)proc_id][PKG_USED_SIZE_IDX];
163
}
164
165
static unsigned long get_pkg_real_used_size( void* proc_id)
166
{
167
  signal_pkg_status((unsigned long)proc_id);
168
  return pkg_status[(unsigned long)proc_id][PKG_REAL_USED_SIZE_IDX];
169
}
170
171
static unsigned long get_pkg_max_used_size( void* proc_id)
172
{
173
  signal_pkg_status((unsigned long)proc_id);
174
  return pkg_status[(unsigned long)proc_id][PKG_MAX_USED_SIZE_IDX];
175
}
176
177
static unsigned long get_pkg_free_size( void* proc_id)
178
{
179
  signal_pkg_status((unsigned long)proc_id);
180
  return pkg_status[(unsigned long)proc_id][PKG_FREE_SIZE_IDX];
181
}
182
183
static unsigned long get_pkg_fragments( void*proc_id)
184
{
185
  signal_pkg_status((unsigned long)proc_id);
186
  return pkg_status[(unsigned long)proc_id][PKG_FRAGMENTS_SIZE_IDX];
187
}
188
189
190
int init_pkg_stats(int procs_no)
191
{
192
  int n;
193
  str n_str;
194
  char *name;
195
  str sname;
196
  group_stats *total_size_grp, *used_size_grp, *real_used_size_grp,
197
        *max_used_size_grp, *free_size_grp, *frags_grp;
198
199
  LM_DBG("setting stats for %d processes\n",procs_no);
200
201
  pkg_status = shm_malloc(procs_no*sizeof(pkg_status_holder));
202
  marker_t = shm_malloc(procs_no*sizeof(time_t));
203
  if (pkg_status==NULL || marker_t==NULL) {
204
    LM_ERR("no more pkg mem for stats\n");
205
    return -1;
206
  }
207
  memset( pkg_status, 0, procs_no*sizeof(pkg_status_holder));
208
  memset( marker_t, 0, procs_no*sizeof(time_t));
209
  no_pkg_status = procs_no;
210
211
212
  total_size_grp = register_stats_group("proc_total_size");
213
  if (!total_size_grp) {
214
    LM_ERR("could not register stats group proc_total_size");
215
    return -1;
216
  }
217
  used_size_grp = register_stats_group("proc_used_size");
218
  if (!used_size_grp) {
219
    LM_ERR("could not register stats group proc_used_size");
220
    return -1;
221
  }
222
  real_used_size_grp = register_stats_group("proc_real_used_size");
223
  if (!real_used_size_grp) {
224
    LM_ERR("could not register stats group proc_real_used_size");
225
    return -1;
226
  }
227
  max_used_size_grp = register_stats_group("proc_max_used_size");
228
  if (!max_used_size_grp) {
229
    LM_ERR("could not register stats group proc_max_used_size");
230
    return -1;
231
  }
232
  free_size_grp = register_stats_group("proc_free_size");
233
  if (!free_size_grp) {
234
    LM_ERR("could not register stats group proc_free_size");
235
    return -1;
236
  }
237
  frags_grp = register_stats_group("proc_fragments");
238
  if (!frags_grp) {
239
    LM_ERR("could not register stats group proc_fragments");
240
    return -1;
241
  }
242
243
  /* build the stats and register them */
244
  for( n=0 ; n<procs_no ; n++) {
245
    n_str.s = int2str( n, &n_str.len);
246
247
    if ( (name=build_stat_name( &n_str,"total_size"))==0 ||
248
    register_stat2("pkmem", name, (stat_var**)get_pkg_total_size,
249
    STAT_NO_RESET|STAT_SHM_NAME|STAT_IS_FUNC|STAT_PER_PROC,
250
    (void*)(long)n, 0)!=0 ) {
251
      LM_ERR("failed to add stat variable\n");
252
      return -1;
253
    }
254
    sname.s = name;
255
    sname.len = strlen(name);
256
    pt[n].pkg_total = get_stat(&sname);
257
    pt[n].pkg_total->flags |= STAT_HIDDEN;
258
    add_stats_group(total_size_grp, pt[n].pkg_total);
259
260
    if ( (name=build_stat_name( &n_str,"used_size"))==0 ||
261
    register_stat2("pkmem", name, (stat_var**)get_pkg_used_size,
262
    STAT_NO_RESET|STAT_SHM_NAME|STAT_IS_FUNC|STAT_PER_PROC,
263
    (void*)(long)n, 0)!=0 ) {
264
      LM_ERR("failed to add stat variable\n");
265
      return -1;
266
    }
267
    sname.s = name;
268
    sname.len = strlen(name);
269
    pt[n].pkg_used = get_stat(&sname);
270
    pt[n].pkg_used->flags |= STAT_HIDDEN;
271
    add_stats_group(used_size_grp, pt[n].pkg_used);
272
273
    if ( (name=build_stat_name( &n_str,"real_used_size"))==0 ||
274
    register_stat2("pkmem", name, (stat_var**)get_pkg_real_used_size,
275
    STAT_NO_RESET|STAT_SHM_NAME|STAT_IS_FUNC|STAT_PER_PROC,
276
    (void*)(long)n, 0)!=0 ) {
277
      LM_ERR("failed to add stat variable\n");
278
      return -1;
279
    }
280
    sname.s = name;
281
    sname.len = strlen(name);
282
    pt[n].pkg_rused = get_stat(&sname);
283
    pt[n].pkg_rused->flags |= STAT_HIDDEN;
284
    add_stats_group(real_used_size_grp, pt[n].pkg_rused);
285
286
    if ( (name=build_stat_name( &n_str,"max_used_size"))==0 ||
287
    register_stat2("pkmem", name, (stat_var**)get_pkg_max_used_size,
288
    STAT_NO_RESET|STAT_SHM_NAME|STAT_IS_FUNC|STAT_PER_PROC,
289
    (void*)(long)n, 0)!=0 ) {
290
      LM_ERR("failed to add stat variable\n");
291
      return -1;
292
    }
293
    sname.s = name;
294
    sname.len = strlen(name);
295
    pt[n].pkg_mused = get_stat(&sname);
296
    pt[n].pkg_mused->flags |= STAT_HIDDEN;
297
    add_stats_group(max_used_size_grp, pt[n].pkg_mused);
298
299
    if ( (name=build_stat_name( &n_str,"free_size"))==0 ||
300
    register_stat2("pkmem", name, (stat_var**)get_pkg_free_size,
301
    STAT_NO_RESET|STAT_SHM_NAME|STAT_IS_FUNC|STAT_PER_PROC,
302
    (void*)(long)n, 0)!=0 ) {
303
      LM_ERR("failed to add stat variable\n");
304
      return -1;
305
    }
306
    sname.s = name;
307
    sname.len = strlen(name);
308
    pt[n].pkg_free = get_stat(&sname);
309
    pt[n].pkg_free->flags |= STAT_HIDDEN;
310
    add_stats_group(free_size_grp, pt[n].pkg_free);
311
312
    if ( (name=build_stat_name( &n_str,"fragments"))==0 ||
313
    register_stat2("pkmem", name, (stat_var**)get_pkg_fragments,
314
    STAT_NO_RESET|STAT_SHM_NAME|STAT_IS_FUNC|STAT_PER_PROC,
315
    (void*)(long)n, 0)!=0 ) {
316
      LM_ERR("failed to add stat variable\n");
317
      return -1;
318
    }
319
    sname.s = name;
320
    sname.len = strlen(name);
321
    pt[n].pkg_frags = get_stat(&sname);
322
    pt[n].pkg_frags->flags |= STAT_HIDDEN;
323
    add_stats_group(frags_grp, pt[n].pkg_frags);
324
  }
325
326
  return 0;
327
}
328
#endif /* PKG */
329
330
#endif /* STATISTICS */