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: 372f342441e2f56d007bfb546c8865cce5aeae9c $
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: 372f342441e2f56d007bfb546c8865cce5aeae9c $")
25 
26 #include <freeradius-devel/server/client.h>
27 #include <freeradius-devel/server/request.h>
28 #include <freeradius-devel/server/stats.h>
29 #include <freeradius-devel/util/debug.h>
30 
31 #include <freeradius-devel/util/misc.h>
32 #include <freeradius-devel/util/time.h>
33 #include <freeradius-devel/radius/defs.h>
34 
35 
36 #ifdef WITH_STATS
37 
38 #define EMA_SCALE (100)
39 #define F_EMA_SCALE (1000000)
40 
43 
44 #define FR_STATS_INIT { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
45  { 0, 0, 0, 0, 0, 0, 0, 0 }}
46 
49 
51 {
52  if (request->counted) return;
53 
54 #if 0
55  if (!request->listener) return;
56  if (!request->client) return;
57  if (!request->packet) return;
58 #endif
59 
60 #if 0
61  if ((request->listener->type != RAD_LISTEN_NONE) &&
62  (request->listener->type != RAD_LISTEN_ACCT) &&
63  (request->listener->type != RAD_LISTEN_AUTH)) return;
64 #endif
65  /* don't count statistic requests */
66  if (request->packet->code == FR_RADIUS_CODE_STATUS_SERVER)
67  return;
68 
69 #undef INC_AUTH
70 #define INC_AUTH(_x) do { radius_auth_stats._x++;request->client->auth._x++; } while (0)
71 
72 #undef INC_ACCT
73 #define INC_ACCT(_x) do { radius_acct_stats._x++;request->client->acct._x++; } while (0)
74 
75  /*
76  * Update the statistics.
77  *
78  * Note that we do NOT do this in a child thread.
79  * Instead, we update the stats when a request is
80  * deleted, because only the main server thread calls
81  * this function, which makes it thread-safe.
82  */
83  if (request->reply && (request->packet->code != FR_RADIUS_CODE_STATUS_SERVER)) switch (request->reply->code) {
85  INC_AUTH(total_access_accepts);
86 
87  auth_stats:
88  INC_AUTH(total_responses);
89 
90  /*
91  * FIXME: Do the time calculations once...
92  */
94  request->packet->timestamp,
95  request->reply->timestamp);
96  fr_stats_bins(&request->client->auth,
97  request->packet->timestamp,
98  request->reply->timestamp);
99  break;
100 
102  INC_AUTH(total_access_rejects);
103  goto auth_stats;
104 
106  INC_AUTH(total_access_challenges);
107  goto auth_stats;
108 
110  INC_ACCT(total_responses);
112  request->packet->timestamp,
113  request->reply->timestamp);
114  break;
115 
116  /*
117  * No response, it must have been a bad
118  * authenticator.
119  */
120  case 0:
121  switch (request->packet->code) {
123  if (request->reply->id == -1) {
124  INC_AUTH(total_bad_authenticators);
125  } else {
126  INC_AUTH(total_packets_dropped);
127  }
128  break;
129 
130 
132  if (request->reply->id == -1) {
133  INC_ACCT(total_bad_authenticators);
134  } else {
135  INC_ACCT(total_packets_dropped);
136  }
137  break;
138 
139  default:
140  break;
141  }
142  break;
143 
144  default:
145  break;
146  }
147 
148  request->counted = true;
149 }
150 
151 void radius_stats_init(int flag)
152 {
153  if (!flag) {
154  start_time = fr_time();
155  hup_time = start_time; /* it's just nicer this way */
156  } else {
157  hup_time = fr_time();
158  }
159 }
160 
162 {
163  int64_t tdiff;
164 #ifdef WITH_STATS_DEBUG
165  static int n = 0;
166 #endif
167  if (ema->window == 0) return;
168 
169  fr_assert(fr_time_lteq(start, end));
170 
171  /*
172  * Initialize it.
173  */
174  if (ema->f1 == 0) {
175  if (ema->window > 10000) ema->window = 10000;
176 
177  ema->f1 = (2 * F_EMA_SCALE) / (ema->window + 1);
178  ema->f10 = (2 * F_EMA_SCALE) / ((10 * ema->window) + 1);
179  }
180 
181  tdiff = fr_time_delta_to_usec(fr_time_sub(start, end));
182  tdiff *= EMA_SCALE;
183 
184  if (ema->ema1 == 0) {
185  ema->ema1 = tdiff;
186  ema->ema10 = tdiff;
187  } else {
188  int diff;
189 
190  diff = ema->f1 * (tdiff - ema->ema1);
191  ema->ema1 += (diff / 1000000);
192 
193  diff = ema->f10 * (tdiff - ema->ema10);
194  ema->ema10 += (diff / 1000000);
195  }
196 
197 
198 #ifdef WITH_STATS_DEBUG
199  DEBUG("time %d %d.%06d\t%d.%06d\t%d.%06d\n",
200  n, tdiff / PREC, (tdiff / EMA_SCALE) % USEC,
201  ema->ema1 / PREC, (ema->ema1 / EMA_SCALE) % USEC,
202  ema->ema10 / PREC, (ema->ema10 / EMA_SCALE) % USEC);
203  n++;
204 #endif
205 }
206 
207 /** Sort latency times into bins
208  *
209  * This solves the problem of attempting to keep min/max/avg latencies, whilst
210  * not knowing what the polling frequency will be.
211  *
212  * @param[out] stats Holding monotonically increasing stats bins.
213  * @param[in] start of the request.
214  * @param[in] end of the request.
215  */
217 {
218  fr_time_delta_t diff;
219  uint32_t delay;
220 
221  if (fr_time_lt(end, start)) return; /* bad data */
222  diff = fr_time_sub(end, start);
223 
225  stats->elapsed[7]++;
226  } else {
227  int i;
228  uint32_t cmp;
229 
230  delay = fr_time_delta_to_usec(diff);
231 
232  cmp = 10;
233  for (i = 0; i < 7; i++) {
234  if (delay < cmp) {
235  stats->elapsed[i]++;
236  break;
237  }
238  cmp *= 10;
239  }
240  }
241 }
242 
243 #endif /* WITH_STATS */
int n
Definition: acutest.h:577
#define RCSID(id)
Definition: build.h:481
@ 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:74
@ 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:39
#define EMA_SCALE
Definition: stats.c:38
static fr_time_t start_time
Definition: stats.c:41
static fr_time_t hup_time
Definition: stats.c:42
void radius_stats_ema(fr_stats_ema_t *ema, fr_time_t start, fr_time_t end)
Definition: stats.c:161
void fr_stats_bins(fr_stats_t *stats, fr_time_t start, fr_time_t end)
Sort latency times into bins.
Definition: stats.c:216
void request_stats_final(request_t *request)
Definition: stats.c:50
fr_stats_t radius_auth_stats
Definition: stats.c:47
void radius_stats_init(int flag)
Definition: stats.c:151
#define FR_STATS_INIT
Definition: stats.c:44
fr_stats_t radius_acct_stats
Definition: stats.c:48
#define INC_AUTH(_x)
#define INC_ACCT(_x)
uint32_t f1
Definition: stats.h:62
uint32_t ema1
Definition: stats.h:63
uint32_t window
Definition: stats.h:60
uint32_t f10
Definition: stats.h:62
uint32_t ema10
Definition: stats.h:63
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:590
#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:632
#define USEC
Definition: time.h:380
#define fr_time_delta_gteq(_a, _b)
Definition: time.h:284
#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