The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
stats.c
Go to the documentation of this file.
1 /*
2  * stats.c Internal statistics handling.
3  *
4  * Version: $Id: 82c71e75b6322481954196ad80d02b6159bce15e $
5  *
6  * This program 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  * This program 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 St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * @copyright 2008 The FreeRADIUS server project
21  * @copyright 2008 Alan DeKok (aland@deployingradius.com)
22  */
23 
24 RCSID("$Id: 82c71e75b6322481954196ad80d02b6159bce15e $")
25 
26 #include <freeradius-devel/server/base.h>
27 #include <freeradius-devel/util/debug.h>
28 
29 #include <freeradius-devel/util/misc.h>
30 #include <freeradius-devel/util/time.h>
31 #include <freeradius-devel/radius/defs.h>
32 
33 
34 #ifdef WITH_STATS
35 
36 #define EMA_SCALE (100)
37 #define F_EMA_SCALE (1000000)
38 
41 
42 #define FR_STATS_INIT { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
43  { 0, 0, 0, 0, 0, 0, 0, 0 }}
44 
47 
49 {
50  if (request->master_state == REQUEST_COUNTED) return;
51 
52 #if 0
53  if (!request->listener) return;
54  if (!request->client) return;
55  if (!request->packet) return;
56 #endif
57 
58 #if 0
59  if ((request->listener->type != RAD_LISTEN_NONE) &&
60  (request->listener->type != RAD_LISTEN_ACCT) &&
61  (request->listener->type != RAD_LISTEN_AUTH)) return;
62 #endif
63  /* don't count statistic requests */
64  if (request->packet->code == FR_RADIUS_CODE_STATUS_SERVER)
65  return;
66 
67 #undef INC_AUTH
68 #define INC_AUTH(_x) do { radius_auth_stats._x++;request->client->auth._x++; } while (0)
69 
70 #undef INC_ACCT
71 #define INC_ACCT(_x) do { radius_acct_stats._x++;request->client->acct._x++; } while (0)
72 
73  /*
74  * Update the statistics.
75  *
76  * Note that we do NOT do this in a child thread.
77  * Instead, we update the stats when a request is
78  * deleted, because only the main server thread calls
79  * this function, which makes it thread-safe.
80  */
81  if (request->reply && (request->packet->code != FR_RADIUS_CODE_STATUS_SERVER)) switch (request->reply->code) {
83  INC_AUTH(total_access_accepts);
84 
85  auth_stats:
86  INC_AUTH(total_responses);
87 
88  /*
89  * FIXME: Do the time calculations once...
90  */
92  request->packet->timestamp,
93  request->reply->timestamp);
94  fr_stats_bins(&request->client->auth,
95  request->packet->timestamp,
96  request->reply->timestamp);
97  break;
98 
100  INC_AUTH(total_access_rejects);
101  goto auth_stats;
102 
104  INC_AUTH(total_access_challenges);
105  goto auth_stats;
106 
108  INC_ACCT(total_responses);
110  request->packet->timestamp,
111  request->reply->timestamp);
112  break;
113 
114  /*
115  * No response, it must have been a bad
116  * authenticator.
117  */
118  case 0:
119  switch (request->packet->code) {
121  if (request->reply->id == -1) {
122  INC_AUTH(total_bad_authenticators);
123  } else {
124  INC_AUTH(total_packets_dropped);
125  }
126  break;
127 
128 
130  if (request->reply->id == -1) {
131  INC_ACCT(total_bad_authenticators);
132  } else {
133  INC_ACCT(total_packets_dropped);
134  }
135  break;
136 
137  default:
138  break;
139  }
140  break;
141 
142  default:
143  break;
144  }
145 
146  request->master_state = REQUEST_COUNTED;
147 }
148 
149 void radius_stats_init(int flag)
150 {
151  if (!flag) {
152  start_time = fr_time();
153  hup_time = start_time; /* it's just nicer this way */
154  } else {
155  hup_time = fr_time();
156  }
157 }
158 
160 {
161  int64_t tdiff;
162 #ifdef WITH_STATS_DEBUG
163  static int n = 0;
164 #endif
165  if (ema->window == 0) return;
166 
167  fr_assert(fr_time_lteq(start, end));
168 
169  /*
170  * Initialize it.
171  */
172  if (ema->f1 == 0) {
173  if (ema->window > 10000) ema->window = 10000;
174 
175  ema->f1 = (2 * F_EMA_SCALE) / (ema->window + 1);
176  ema->f10 = (2 * F_EMA_SCALE) / ((10 * ema->window) + 1);
177  }
178 
179  tdiff = fr_time_delta_to_usec(fr_time_sub(start, end));
180  tdiff *= EMA_SCALE;
181 
182  if (ema->ema1 == 0) {
183  ema->ema1 = tdiff;
184  ema->ema10 = tdiff;
185  } else {
186  int diff;
187 
188  diff = ema->f1 * (tdiff - ema->ema1);
189  ema->ema1 += (diff / 1000000);
190 
191  diff = ema->f10 * (tdiff - ema->ema10);
192  ema->ema10 += (diff / 1000000);
193  }
194 
195 
196 #ifdef WITH_STATS_DEBUG
197  DEBUG("time %d %d.%06d\t%d.%06d\t%d.%06d\n",
198  n, tdiff / PREC, (tdiff / EMA_SCALE) % USEC,
199  ema->ema1 / PREC, (ema->ema1 / EMA_SCALE) % USEC,
200  ema->ema10 / PREC, (ema->ema10 / EMA_SCALE) % USEC);
201  n++;
202 #endif
203 }
204 
205 /** Sort latency times into bins
206  *
207  * This solves the problem of attempting to keep min/max/avg latencies, whilst
208  * not knowing what the polling frequency will be.
209  *
210  * @param[out] stats Holding monotonically increasing stats bins.
211  * @param[in] start of the request.
212  * @param[in] end of the request.
213  */
215 {
216  fr_time_delta_t diff;
217  uint32_t delay;
218 
219  if (fr_time_lt(end, start)) return; /* bad data */
220  diff = fr_time_sub(end, start);
221 
223  stats->elapsed[7]++;
224  } else {
225  int i;
226  uint32_t cmp;
227 
228  delay = fr_time_delta_to_usec(diff);
229 
230  cmp = 10;
231  for (i = 0; i < 7; i++) {
232  if (delay < cmp) {
233  stats->elapsed[i]++;
234  break;
235  }
236  cmp *= 10;
237  }
238  }
239 }
240 
241 #endif /* WITH_STATS */
int n
Definition: acutest.h:577
#define RCSID(id)
Definition: build.h:444
@ FR_RADIUS_CODE_ACCESS_CHALLENGE
RFC2865 - Access-Challenge.
Definition: defs.h:43
@ FR_RADIUS_CODE_ACCESS_REQUEST
RFC2865 - Access-Request.
Definition: defs.h:33
@ FR_RADIUS_CODE_STATUS_SERVER
RFC2865/RFC5997 - Status Server (request)
Definition: defs.h:44
@ FR_RADIUS_CODE_ACCESS_ACCEPT
RFC2865 - Access-Accept.
Definition: defs.h:34
@ FR_RADIUS_CODE_ACCOUNTING_RESPONSE
RFC2866 - Accounting-Response.
Definition: defs.h:37
@ FR_RADIUS_CODE_ACCOUNTING_REQUEST
RFC2866 - Accounting-Request.
Definition: defs.h:36
@ FR_RADIUS_CODE_ACCESS_REJECT
RFC2865 - Access-Reject.
Definition: defs.h:35
#define DEBUG(fmt,...)
Definition: dhcpclient.c:39
unsigned int uint32_t
Definition: merged_model.c:33
static rc_stats_t stats
Definition: radclient-ng.c:72
@ REQUEST_COUNTED
Definition: request.h:63
@ RAD_LISTEN_ACCT
Definition: listen.h:48
@ RAD_LISTEN_AUTH
Definition: listen.h:47
@ RAD_LISTEN_NONE
Definition: listen.h:45
#define F_EMA_SCALE
Definition: stats.c:37
#define EMA_SCALE
Definition: stats.c:36
static fr_time_t start_time
Definition: stats.c:39
static fr_time_t hup_time
Definition: stats.c:40
void radius_stats_ema(fr_stats_ema_t *ema, fr_time_t start, fr_time_t end)
Definition: stats.c:159
void fr_stats_bins(fr_stats_t *stats, fr_time_t start, fr_time_t end)
Sort latency times into bins.
Definition: stats.c:214
void request_stats_final(request_t *request)
Definition: stats.c:48
fr_stats_t radius_auth_stats
Definition: stats.c:45
void radius_stats_init(int flag)
Definition: stats.c:149
#define FR_STATS_INIT
Definition: stats.c:42
fr_stats_t radius_acct_stats
Definition: stats.c:46
#define INC_AUTH(_x)
#define INC_ACCT(_x)
uint32_t f1
Definition: stats.h:60
uint32_t ema1
Definition: stats.h:61
uint32_t window
Definition: stats.h:58
uint32_t f10
Definition: stats.h:60
uint32_t ema10
Definition: stats.h:61
fr_assert(0)
#define fr_time()
Allow us to arbitrarily manipulate time.
Definition: state_test.c:8
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition: time.h:588
#define fr_time_lteq(_a, _b)
Definition: time.h:240
static int64_t fr_time_delta_to_usec(fr_time_delta_t delta)
Definition: time.h:630
#define USEC
Definition: time.h:378
#define fr_time_delta_gteq(_a, _b)
Definition: time.h:282
#define fr_time_sub(_a, _b)
Subtract one time from another.
Definition: time.h:229
#define fr_time_lt(_a, _b)
Definition: time.h:239
A time delta, a difference in time measured in nanoseconds.
Definition: time.h:80
"server local" time.
Definition: time.h:69