]> git.ipfire.org Git - thirdparty/squid.git/blame - src/stat.cc
Cleaned up the "null" FS by removing all unused "junk", and merging it into
[thirdparty/squid.git] / src / stat.cc
CommitLineData
e5f6c5c2 1
30a4f2a8 2/*
2b6662ba 3 * $Id: stat.cc,v 1.343 2001/01/12 00:37:21 wessels Exp $
30a4f2a8 4 *
5 * DEBUG: section 18 Cache Manager Statistics
6 * AUTHOR: Harvest Derived
7 *
2b6662ba 8 * SQUID Web Proxy Cache http://www.squid-cache.org/
e25c139f 9 * ----------------------------------------------------------
30a4f2a8 10 *
2b6662ba 11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
30a4f2a8 19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
cbdec147 32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 33 *
019dd986 34 */
ed43818f 35
234967c9 36
44a47c6e 37#include "squid.h"
090089c4 38
ae94d28e 39#define DEBUG_OPENFD 1
40
1da3b90b 41typedef int STOBJFLT(const StoreEntry *);
42typedef struct {
43 StoreEntry *sentry;
44 int bucket;
45 STOBJFLT *filter;
46} StatObjectsState;
47
67508012 48/* LOCALS */
f5b8bbc4 49static const char *describeStatuses(const StoreEntry *);
f5b8bbc4 50static const char *describeTimestamps(const StoreEntry *);
f2908497 51static void statAvgTick(void *notused);
a0f32775 52static void statAvgDump(StoreEntry *, int minutes, int hours);
01aebf31 53#if STAT_GRAPHS
54static void statGraphDump(StoreEntry *);
55#endif
12cf1be2 56static void statCountersInit(StatCounters *);
1d803566 57static void statCountersInitSpecial(StatCounters *);
12cf1be2 58static void statCountersClean(StatCounters *);
2ac76861 59static void statCountersCopy(StatCounters * dest, const StatCounters * orig);
7d94ae33 60static double statMedianSvc(int, int);
a5a5de87 61static void statStoreEntry(StoreEntry * s, StoreEntry * e);
49ad0a8c 62static double statCPUUsage(int minutes);
ed7f5615 63static OBJH stat_io_get;
64static OBJH stat_objects_get;
65static OBJH stat_vmobjects_get;
ae94d28e 66#if DEBUG_OPENFD
67static OBJH statOpenfdObj;
68#endif
1da3b90b 69static EVH statObjects;
ed7f5615 70static OBJH info_get;
71static OBJH statFiledescriptors;
071a3ae7 72static OBJH statCountersDump;
a1e927f6 73static OBJH statPeerSelect;
26b164ac 74static OBJH statDigestBlob;
ed7f5615 75static OBJH statAvg5min;
45eb7f49 76static OBJH statAvg60min;
e9b5ead4 77static OBJH statUtilization;
ba4f8e5a 78static OBJH statCountersHistograms;
0f1bc304 79static OBJH statClientRequests;
20882fb1 80
20882fb1 81#ifdef XMALLOC_STATISTICS
58cd5bbd 82static void info_get_mallstat(int, int, int, void *);
83static double xm_time;
84static double xm_deltat;
20882fb1 85#endif
30a4f2a8 86
a9113eb0 87StatCounters CountHist[N_COUNT_HIST];
d5649d9f 88static int NCountHist = 0;
a0f32775 89static StatCounters CountHourHist[N_COUNT_HOUR_HIST];
90static int NCountHourHist = 0;
28c60158 91CBDATA_TYPE(StatObjectsState);
a0f32775 92
d480bbc0 93extern unsigned int mem_pool_alloc_calls;
94extern unsigned int mem_pool_free_calls;
95
5e29a294 96static void
e9b5ead4 97statUtilization(StoreEntry * e)
a0f32775 98{
99 storeAppendPrintf(e, "Cache Utilisation:\n");
100 storeAppendPrintf(e, "\n");
101 storeAppendPrintf(e, "Last 5 minutes:\n");
102 if (NCountHist >= 5)
103 statAvgDump(e, 5, 0);
104 else
105 storeAppendPrintf(e, "(no values recorded yet)\n");
106 storeAppendPrintf(e, "\n");
107 storeAppendPrintf(e, "Last 15 minutes:\n");
108 if (NCountHist >= 15)
109 statAvgDump(e, 15, 0);
110 else
111 storeAppendPrintf(e, "(no values recorded yet)\n");
112 storeAppendPrintf(e, "\n");
113 storeAppendPrintf(e, "Last hour:\n");
114 if (NCountHist >= 60)
115 statAvgDump(e, 60, 0);
116 else
117 storeAppendPrintf(e, "(no values recorded yet)\n");
118 storeAppendPrintf(e, "\n");
119 storeAppendPrintf(e, "Last 8 hours:\n");
120 if (NCountHourHist >= 8)
121 statAvgDump(e, 0, 8);
122 else
123 storeAppendPrintf(e, "(no values recorded yet)\n");
124 storeAppendPrintf(e, "\n");
125 storeAppendPrintf(e, "Last day:\n");
126 if (NCountHourHist >= 24)
127 statAvgDump(e, 0, 24);
128 else
129 storeAppendPrintf(e, "(no values recorded yet)\n");
130 storeAppendPrintf(e, "\n");
131 storeAppendPrintf(e, "Last 3 days:\n");
132 if (NCountHourHist >= 72)
133 statAvgDump(e, 0, 72);
134 else
135 storeAppendPrintf(e, "(no values recorded yet)\n");
136 storeAppendPrintf(e, "\n");
137 storeAppendPrintf(e, "Totals since cache startup:\n");
138 statCountersDump(e);
139}
f2908497 140
5e29a294 141static void
b8d8561b 142stat_io_get(StoreEntry * sentry)
30a4f2a8 143{
144 int i;
145
15576b6a 146 storeAppendPrintf(sentry, "HTTP I/O\n");
147 storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Http.reads);
15576b6a 148 storeAppendPrintf(sentry, "Read Histogram:\n");
30a4f2a8 149 for (i = 0; i < 16; i++) {
15576b6a 150 storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
30a4f2a8 151 i ? (1 << (i - 1)) + 1 : 1,
152 1 << i,
153 IOStats.Http.read_hist[i],
154 percent(IOStats.Http.read_hist[i], IOStats.Http.reads));
155 }
156
15576b6a 157 storeAppendPrintf(sentry, "\n");
158 storeAppendPrintf(sentry, "FTP I/O\n");
159 storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Ftp.reads);
15576b6a 160 storeAppendPrintf(sentry, "Read Histogram:\n");
30a4f2a8 161 for (i = 0; i < 16; i++) {
15576b6a 162 storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
30a4f2a8 163 i ? (1 << (i - 1)) + 1 : 1,
164 1 << i,
165 IOStats.Ftp.read_hist[i],
166 percent(IOStats.Ftp.read_hist[i], IOStats.Ftp.reads));
167 }
168
15576b6a 169 storeAppendPrintf(sentry, "\n");
170 storeAppendPrintf(sentry, "Gopher I/O\n");
171 storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Gopher.reads);
15576b6a 172 storeAppendPrintf(sentry, "Read Histogram:\n");
56fa4cad 173 for (i = 0; i < 16; i++) {
15576b6a 174 storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
56fa4cad 175 i ? (1 << (i - 1)) + 1 : 1,
176 1 << i,
177 IOStats.Gopher.read_hist[i],
178 percent(IOStats.Gopher.read_hist[i], IOStats.Gopher.reads));
179 }
180
15576b6a 181 storeAppendPrintf(sentry, "\n");
182 storeAppendPrintf(sentry, "WAIS I/O\n");
183 storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Wais.reads);
15576b6a 184 storeAppendPrintf(sentry, "Read Histogram:\n");
56fa4cad 185 for (i = 0; i < 16; i++) {
15576b6a 186 storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
56fa4cad 187 i ? (1 << (i - 1)) + 1 : 1,
188 1 << i,
189 IOStats.Wais.read_hist[i],
190 percent(IOStats.Wais.read_hist[i], IOStats.Wais.reads));
191 }
090089c4 192}
193
0ee4272b 194static const char *
fe4e214f 195describeStatuses(const StoreEntry * entry)
d1a43e28 196{
197 LOCAL_ARRAY(char, buf, 256);
56878878 198 snprintf(buf, 256, "%-13s %-13s %-12s %-12s",
d1a43e28 199 storeStatusStr[entry->store_status],
200 memStatusStr[entry->mem_status],
201 swapStatusStr[entry->swap_status],
202 pingStatusStr[entry->ping_status]);
203 return buf;
204}
205
415e0dd2 206const char *
207storeEntryFlags(const StoreEntry * entry)
d1a43e28 208{
209 LOCAL_ARRAY(char, buf, 256);
315005bd 210 int flags = (int) entry->flags;
d1a43e28 211 char *t;
212 buf[0] = '\0';
7d94ae33 213 if (EBIT_TEST(flags, ENTRY_SPECIAL))
977c1c5b 214 strcat(buf, "SPECIAL,");
7d94ae33 215 if (EBIT_TEST(flags, ENTRY_REVALIDATE))
977c1c5b 216 strcat(buf, "REVALIDATE,");
7d94ae33 217 if (EBIT_TEST(flags, DELAY_SENDING))
977c1c5b 218 strcat(buf, "DELAY_SENDING,");
7d94ae33 219 if (EBIT_TEST(flags, RELEASE_REQUEST))
977c1c5b 220 strcat(buf, "RELEASE_REQUEST,");
7d94ae33 221 if (EBIT_TEST(flags, REFRESH_REQUEST))
977c1c5b 222 strcat(buf, "REFRESH_REQUEST,");
7d94ae33 223 if (EBIT_TEST(flags, ENTRY_CACHABLE))
977c1c5b 224 strcat(buf, "CACHABLE,");
7d94ae33 225 if (EBIT_TEST(flags, ENTRY_DISPATCHED))
977c1c5b 226 strcat(buf, "DISPATCHED,");
7d94ae33 227 if (EBIT_TEST(flags, KEY_PRIVATE))
977c1c5b 228 strcat(buf, "PRIVATE,");
05b0ef8a 229 if (EBIT_TEST(flags, ENTRY_FWD_HDR_WAIT))
230 strcat(buf, "FWD_HDR_WAIT,");
7d94ae33 231 if (EBIT_TEST(flags, ENTRY_NEGCACHED))
977c1c5b 232 strcat(buf, "NEGCACHED,");
7d94ae33 233 if (EBIT_TEST(flags, ENTRY_VALIDATED))
977c1c5b 234 strcat(buf, "VALIDATED,");
7d94ae33 235 if (EBIT_TEST(flags, ENTRY_BAD_LENGTH))
977c1c5b 236 strcat(buf, "BAD_LENGTH,");
d2e002d1 237 if (EBIT_TEST(flags, ENTRY_ABORTED))
238 strcat(buf, "ABORTED,");
d1a43e28 239 if ((t = strrchr(buf, ',')))
240 *t = '\0';
241 return buf;
242}
243
0ee4272b 244static const char *
fe4e214f 245describeTimestamps(const StoreEntry * entry)
d1a43e28 246{
247 LOCAL_ARRAY(char, buf, 256);
56878878 248 snprintf(buf, 256, "LV:%-9d LU:%-9d LM:%-9d EX:%-9d",
d1a43e28 249 (int) entry->timestamp,
250 (int) entry->lastref,
251 (int) entry->lastmod,
252 (int) entry->expires);
253 return buf;
254}
255
b8d8561b 256static void
a5a5de87 257statStoreEntry(StoreEntry * s, StoreEntry * e)
090089c4 258{
a5a5de87 259 MemObject *mem = e->mem_obj;
637ed800 260 int i;
261 struct _store_client *sc;
06d2839d 262 dlink_node *node;
186477c1 263 storeAppendPrintf(s, "KEY %s\n", storeKeyText(e->hash.key));
a5a5de87 264 if (mem)
265 storeAppendPrintf(s, "\t%s %s\n",
266 RequestMethodStr[mem->method], mem->log_url);
267 storeAppendPrintf(s, "\t%s\n", describeStatuses(e));
415e0dd2 268 storeAppendPrintf(s, "\t%s\n", storeEntryFlags(e));
a5a5de87 269 storeAppendPrintf(s, "\t%s\n", describeTimestamps(e));
270 storeAppendPrintf(s, "\t%d locks, %d clients, %d refs\n",
271 (int) e->lock_count,
272 storePendingNClients(e),
273 (int) e->refcount);
cd748f27 274 storeAppendPrintf(s, "\tSwap Dir %d, File %#08X\n",
275 e->swap_dirn, e->swap_filen);
a5a5de87 276 if (mem != NULL) {
277 storeAppendPrintf(s, "\tinmem_lo: %d\n", (int) mem->inmem_lo);
278 storeAppendPrintf(s, "\tinmem_hi: %d\n", (int) mem->inmem_hi);
2391a162 279 storeAppendPrintf(s, "\tswapout: %d bytes queued\n",
280 (int) mem->swapout.queue_offset);
281 if (mem->swapout.sio)
282 storeAppendPrintf(s, "\tswapout: %d bytes written\n",
60df005c 283 (int) storeOffset(mem->swapout.sio));
a4b8110e 284 for (i = 0, node = mem->clients.head; node; node = node->next, i++) {
285 sc = (store_client *) node->data;
637ed800 286 if (sc->callback_data == NULL)
287 continue;
0f1bc304 288 storeAppendPrintf(s, "\tClient #%d, %p\n", i, sc->callback_data);
a5a5de87 289 storeAppendPrintf(s, "\t\tcopy_offset: %d\n",
637ed800 290 (int) sc->copy_offset);
a5a5de87 291 storeAppendPrintf(s, "\t\tseen_offset: %d\n",
637ed800 292 (int) sc->seen_offset);
a5a5de87 293 storeAppendPrintf(s, "\t\tcopy_size: %d\n",
637ed800 294 (int) sc->copy_size);
b8890359 295 storeAppendPrintf(s, "\t\tflags:");
296 if (sc->flags.disk_io_pending)
297 storeAppendPrintf(s, " disk_io_pending");
298 if (sc->flags.store_copying)
299 storeAppendPrintf(s, " store_copying");
300 if (sc->flags.copy_event_pending)
301 storeAppendPrintf(s, " copy_event_pending");
302 storeAppendPrintf(s, "\n");
637ed800 303 }
a5a5de87 304 }
305 storeAppendPrintf(s, "\n");
306}
307
308/* process objects list */
309static void
1da3b90b 310statObjects(void *data)
a5a5de87 311{
1da3b90b 312 StatObjectsState *state = data;
313 StoreEntry *e;
314 hash_link *link_ptr = NULL;
315 hash_link *link_next = NULL;
634b97dc 316 if (state->bucket >= store_hash_buckets) {
1da3b90b 317 storeComplete(state->sentry);
318 storeUnlockObject(state->sentry);
319 cbdataFree(state);
320 return;
b7fe0ab0 321 } else if (EBIT_TEST(state->sentry->flags, ENTRY_ABORTED)) {
7d9e8f15 322 storeUnlockObject(state->sentry);
323 cbdataFree(state);
324 return;
562b34ae 325 } else if (fwdCheckDeferRead(-1, state->sentry)) {
48a0f016 326 eventAdd("statObjects", statObjects, state, 0.1, 1);
562b34ae 327 return;
1da3b90b 328 }
329 storeBuffer(state->sentry);
330 debug(49, 3) ("statObjects: Bucket #%d\n", state->bucket);
331 link_next = hash_get_bucket(store_table, state->bucket);
332 while (NULL != (link_ptr = link_next)) {
333 link_next = link_ptr->next;
334 e = (StoreEntry *) link_ptr;
335 if (state->filter && 0 == state->filter(e))
a5a5de87 336 continue;
1da3b90b 337 statStoreEntry(state->sentry, e);
a5a5de87 338 }
634b97dc 339 state->bucket++;
1da3b90b 340 eventAdd("statObjects", statObjects, state, 0.0, 1);
341 storeBufferFlush(state->sentry);
a5a5de87 342}
343
5e29a294 344static void
1da3b90b 345statObjectsStart(StoreEntry * sentry, STOBJFLT * filter)
346{
28c60158 347 StatObjectsState *state;
348 state = CBDATA_ALLOC(StatObjectsState, NULL);
1da3b90b 349 state->sentry = sentry;
350 state->filter = filter;
351 storeLockObject(sentry);
1da3b90b 352 eventAdd("statObjects", statObjects, state, 0.0, 1);
353}
354
355static void
356stat_objects_get(StoreEntry * sentry)
357{
358 statObjectsStart(sentry, NULL);
359}
360
361static int
362statObjectsVmFilter(const StoreEntry * e)
090089c4 363{
1da3b90b 364 return e->mem_obj ? 1 : 0;
6684fec0 365}
090089c4 366
5e29a294 367static void
1da3b90b 368stat_vmobjects_get(StoreEntry * sentry)
6684fec0 369{
1da3b90b 370 statObjectsStart(sentry, statObjectsVmFilter);
090089c4 371}
372
ae94d28e 373#if DEBUG_OPENFD
1da3b90b 374static int
375statObjectsOpenfdFilter(const StoreEntry * e)
376{
377 if (e->mem_obj == NULL)
378 return 0;
2391a162 379 if (e->mem_obj->swapout.sio == NULL)
380 return 0;
1da3b90b 381 return 1;
382}
383
ae94d28e 384static void
385statOpenfdObj(StoreEntry * sentry)
386{
1da3b90b 387 statObjectsStart(sentry, statObjectsOpenfdFilter);
ae94d28e 388}
1da3b90b 389
ae94d28e 390#endif
391
0a0bf5db 392#ifdef XMALLOC_STATISTICS
b8d8561b 393static void
58cd5bbd 394info_get_mallstat(int size, int number, int oldnum, void *data)
30a4f2a8 395{
7e3ce7b9 396 StoreEntry *sentry = data;
30a4f2a8 397 if (number > 0)
186477c1 398 storeAppendPrintf(sentry, "%d\t %d\t %d\t %.1f\n", size, number, number - oldnum, xdiv((number - oldnum), xm_deltat));
30a4f2a8 399}
400#endif
090089c4 401
0ee4272b 402static const char *
f1dc9b30 403fdRemoteAddr(const fde * f)
d51e52f5 404{
95d659f0 405 LOCAL_ARRAY(char, buf, 32);
4f92c80c 406 if (f->type != FD_SOCKET)
407 return null_string;
042461c3 408 snprintf(buf, 32, "%s.%d", f->ipaddr, (int) f->remote_port);
d2af9477 409 return buf;
d51e52f5 410}
411
5e29a294 412static void
b8d8561b 413statFiledescriptors(StoreEntry * sentry)
d51e52f5 414{
415 int i;
f1dc9b30 416 fde *f;
15576b6a 417 storeAppendPrintf(sentry, "Active file descriptors:\n");
b6a2f15e 418 storeAppendPrintf(sentry, "%-4s %-6s %-4s %-7s* %-7s* %-21s %s\n",
d51e52f5 419 "File",
420 "Type",
d51e52f5 421 "Tout",
4f92c80c 422 "Nread",
423 "Nwrite",
d51e52f5 424 "Remote Address",
425 "Description");
b6a2f15e 426 storeAppendPrintf(sentry, "---- ------ ---- -------- -------- --------------------- ------------------------------\n");
e83892e9 427 for (i = 0; i < Squid_MaxFD; i++) {
429fdbec 428 f = &fd_table[i];
60c0b5a2 429 if (!f->flags.open)
d51e52f5 430 continue;
b6a2f15e 431 storeAppendPrintf(sentry, "%4d %-6.6s %4d %7d%c %7d%c %-21s %s\n",
d2af9477 432 i,
22f5d1ca 433 fdTypeStr[f->type],
5f6ac48b 434 f->timeout_handler ? (int) (f->timeout - squid_curtime) / 60 : 0,
4f92c80c 435 f->bytes_read,
b6a2f15e 436 f->read_handler ? '*' : ' ',
4f92c80c 437 f->bytes_written,
b6a2f15e 438 f->write_handler ? '*' : ' ',
4f92c80c 439 fdRemoteAddr(f),
440 f->desc);
d51e52f5 441 }
d51e52f5 442}
443
5e29a294 444static void
03eb2f01 445info_get(StoreEntry * sentry)
090089c4 446{
090089c4 447 struct rusage rusage;
f2908497 448 double cputime;
449 double runtime;
88738790 450#if HAVE_MSTATS && HAVE_GNUMALLOC_H
451 struct mstats ms;
eb824054 452#elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
090089c4 453 struct mallinfo mp;
88738790 454 int t;
090089c4 455#endif
456
f2908497 457 runtime = tvSubDsec(squid_start, current_time);
458 if (runtime == 0.0)
459 runtime = 1.0;
15576b6a 460 storeAppendPrintf(sentry, "Squid Object Cache: Version %s\n",
d51e52f5 461 version_string);
15576b6a 462 storeAppendPrintf(sentry, "Start Time:\t%s\n",
f2908497 463 mkrfc1123(squid_start.tv_sec));
15576b6a 464 storeAppendPrintf(sentry, "Current Time:\t%s\n",
f2908497 465 mkrfc1123(current_time.tv_sec));
15576b6a 466 storeAppendPrintf(sentry, "Connection information for %s:\n",
d51e52f5 467 appname);
98829f69 468 storeAppendPrintf(sentry, "\tNumber of clients accessing cache:\t%u\n",
83704487 469 statCounter.client_http.clients);
15576b6a 470 storeAppendPrintf(sentry, "\tNumber of HTTP requests received:\t%u\n",
83704487 471 statCounter.client_http.requests);
15576b6a 472 storeAppendPrintf(sentry, "\tNumber of ICP messages received:\t%u\n",
83704487 473 statCounter.icp.pkts_recv);
15576b6a 474 storeAppendPrintf(sentry, "\tNumber of ICP messages sent:\t%u\n",
83704487 475 statCounter.icp.pkts_sent);
2e8e29b8 476 storeAppendPrintf(sentry, "\tNumber of queued ICP replies:\t%u\n",
83704487 477 statCounter.icp.replies_queued);
15576b6a 478 storeAppendPrintf(sentry, "\tRequest failure ratio:\t%5.2f%%\n",
88aad2e5 479 request_failure_ratio);
f2908497 480
15576b6a 481 storeAppendPrintf(sentry, "\tHTTP requests per minute:\t%.1f\n",
83704487 482 statCounter.client_http.requests / (runtime / 60.0));
15576b6a 483 storeAppendPrintf(sentry, "\tICP messages per minute:\t%.1f\n",
83704487 484 (statCounter.icp.pkts_sent + statCounter.icp.pkts_recv) / (runtime / 60.0));
15576b6a 485 storeAppendPrintf(sentry, "\tSelect loop called: %d times, %0.3f ms avg\n",
83704487 486 statCounter.select_loops, 1000.0 * runtime / statCounter.select_loops);
090089c4 487
15576b6a 488 storeAppendPrintf(sentry, "Cache information for %s:\n",
30a4f2a8 489 appname);
491a980b 490 storeAppendPrintf(sentry, "\tRequest Hit Ratios:\t5min: %3.1f%%, 60min: %3.1f%%\n",
491 statRequestHitRatio(5),
492 statRequestHitRatio(60));
493 storeAppendPrintf(sentry, "\tByte Hit Ratios:\t5min: %3.1f%%, 60min: %3.1f%%\n",
494 statByteHitRatio(5),
495 statByteHitRatio(60));
4f4d1d6e 496 storeAppendPrintf(sentry, "\tRequest Memory Hit Ratios:\t5min: %3.1f%%, 60min: %3.1f%%\n",
497 statRequestHitMemoryRatio(5),
498 statRequestHitMemoryRatio(60));
499 storeAppendPrintf(sentry, "\tRequest Disk Hit Ratios:\t5min: %3.1f%%, 60min: %3.1f%%\n",
500 statRequestHitDiskRatio(5),
501 statRequestHitDiskRatio(60));
15576b6a 502 storeAppendPrintf(sentry, "\tStorage Swap size:\t%d KB\n",
c932b107 503 store_swap_size);
15576b6a 504 storeAppendPrintf(sentry, "\tStorage Mem size:\t%d KB\n",
5f6ac48b 505 (int) (store_mem_size >> 10));
0faf70d0 506 storeAppendPrintf(sentry, "\tMean Object Size:\t%0.2f KB\n",
507 n_disk_objects ? (double) store_swap_size / n_disk_objects : 0.0);
15576b6a 508 storeAppendPrintf(sentry, "\tRequests given to unlinkd:\t%d\n",
83704487 509 statCounter.unlink.requests);
090089c4 510
b87b92fb 511 storeAppendPrintf(sentry, "Median Service Times (seconds) 5 min 60 min:\n");
512 storeAppendPrintf(sentry, "\tHTTP Requests (All): %8.5f %8.5f\n",
513 statMedianSvc(5, MEDIAN_HTTP) / 1000.0,
514 statMedianSvc(60, MEDIAN_HTTP) / 1000.0);
515 storeAppendPrintf(sentry, "\tCache Misses: %8.5f %8.5f\n",
516 statMedianSvc(5, MEDIAN_MISS) / 1000.0,
517 statMedianSvc(60, MEDIAN_MISS) / 1000.0);
518 storeAppendPrintf(sentry, "\tCache Hits: %8.5f %8.5f\n",
519 statMedianSvc(5, MEDIAN_HIT) / 1000.0,
520 statMedianSvc(60, MEDIAN_HIT) / 1000.0);
7c9c84ad 521 storeAppendPrintf(sentry, "\tNear Hits: %8.5f %8.5f\n",
522 statMedianSvc(5, MEDIAN_NH) / 1000.0,
523 statMedianSvc(60, MEDIAN_NH) / 1000.0);
b87b92fb 524 storeAppendPrintf(sentry, "\tNot-Modified Replies: %8.5f %8.5f\n",
525 statMedianSvc(5, MEDIAN_NM) / 1000.0,
526 statMedianSvc(60, MEDIAN_NM) / 1000.0);
527 storeAppendPrintf(sentry, "\tDNS Lookups: %8.5f %8.5f\n",
528 statMedianSvc(5, MEDIAN_DNS) / 1000.0,
529 statMedianSvc(60, MEDIAN_DNS) / 1000.0);
530 storeAppendPrintf(sentry, "\tICP Queries: %8.5f %8.5f\n",
531 statMedianSvc(5, MEDIAN_ICP_QUERY) / 1000000.0,
532 statMedianSvc(60, MEDIAN_ICP_QUERY) / 1000000.0);
533
f2908497 534 squid_getrusage(&rusage);
535 cputime = rusage_cputime(&rusage);
15576b6a 536 storeAppendPrintf(sentry, "Resource usage for %s:\n", appname);
537 storeAppendPrintf(sentry, "\tUP Time:\t%.3f seconds\n", runtime);
538 storeAppendPrintf(sentry, "\tCPU Time:\t%.3f seconds\n", cputime);
539 storeAppendPrintf(sentry, "\tCPU Usage:\t%.2f%%\n",
f2908497 540 dpercent(cputime, runtime));
979533fa 541 storeAppendPrintf(sentry, "\tCPU Usage, 5 minute avg:\t%.2f%%\n",
49ad0a8c 542 statCPUUsage(5));
543 storeAppendPrintf(sentry, "\tCPU Usage, 60 minute avg:\t%.2f%%\n",
544 statCPUUsage(60));
5f6ac48b 545 storeAppendPrintf(sentry, "\tMaximum Resident Size: %d KB\n",
f2908497 546 rusage_maxrss(&rusage));
5f6ac48b 547 storeAppendPrintf(sentry, "\tPage faults with physical i/o: %d\n",
f2908497 548 rusage_pagefaults(&rusage));
090089c4 549
88738790 550#if HAVE_MSTATS && HAVE_GNUMALLOC_H
551 ms = mstats();
15576b6a 552 storeAppendPrintf(sentry, "Memory usage for %s via mstats():\n",
88738790 553 appname);
15576b6a 554 storeAppendPrintf(sentry, "\tTotal space in arena: %6d KB\n",
88738790 555 ms.bytes_total >> 10);
15576b6a 556 storeAppendPrintf(sentry, "\tTotal free: %6d KB %d%%\n",
88738790 557 ms.bytes_free >> 10, percent(ms.bytes_free, ms.bytes_total));
eb824054 558#elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
090089c4 559 mp = mallinfo();
15576b6a 560 storeAppendPrintf(sentry, "Memory usage for %s via mallinfo():\n",
d51e52f5 561 appname);
15576b6a 562 storeAppendPrintf(sentry, "\tTotal space in arena: %6d KB\n",
b560dd20 563 mp.arena >> 10);
15576b6a 564 storeAppendPrintf(sentry, "\tOrdinary blocks: %6d KB %6d blks\n",
30a4f2a8 565 mp.uordblks >> 10, mp.ordblks);
15576b6a 566 storeAppendPrintf(sentry, "\tSmall blocks: %6d KB %6d blks\n",
30a4f2a8 567 mp.usmblks >> 10, mp.smblks);
15576b6a 568 storeAppendPrintf(sentry, "\tHolding blocks: %6d KB %6d blks\n",
30a4f2a8 569 mp.hblkhd >> 10, mp.hblks);
15576b6a 570 storeAppendPrintf(sentry, "\tFree Small blocks: %6d KB\n",
30a4f2a8 571 mp.fsmblks >> 10);
15576b6a 572 storeAppendPrintf(sentry, "\tFree Ordinary blocks: %6d KB\n",
30a4f2a8 573 mp.fordblks >> 10);
574 t = mp.uordblks + mp.usmblks + mp.hblkhd;
15576b6a 575 storeAppendPrintf(sentry, "\tTotal in use: %6d KB %d%%\n",
30a4f2a8 576 t >> 10, percent(t, mp.arena));
577 t = mp.fsmblks + mp.fordblks;
15576b6a 578 storeAppendPrintf(sentry, "\tTotal free: %6d KB %d%%\n",
30a4f2a8 579 t >> 10, percent(t, mp.arena));
46c883ed 580#if HAVE_EXT_MALLINFO
15576b6a 581 storeAppendPrintf(sentry, "\tmax size of small blocks:\t%d\n", mp.mxfast);
582 storeAppendPrintf(sentry, "\tnumber of small blocks in a holding block:\t%d\n",
090089c4 583 mp.nlblks);
15576b6a 584 storeAppendPrintf(sentry, "\tsmall block rounding factor:\t%d\n", mp.grain);
585 storeAppendPrintf(sentry, "\tspace (including overhead) allocated in ord. blks:\t%d\n"
090089c4 586 ,mp.uordbytes);
15576b6a 587 storeAppendPrintf(sentry, "\tnumber of ordinary blocks allocated:\t%d\n",
090089c4 588 mp.allocated);
15576b6a 589 storeAppendPrintf(sentry, "\tbytes used in maintaining the free tree:\t%d\n",
090089c4 590 mp.treeoverhead);
46c883ed 591#endif /* HAVE_EXT_MALLINFO */
50bc2565 592#endif /* HAVE_MALLINFO */
5d1f3c82 593 storeAppendPrintf(sentry, "Memory accounted for:\n");
979533fa 594 storeAppendPrintf(sentry, "\tTotal accounted: %6d KB\n",
48a0f016 595 memTotalAllocated() >> 10);
d480bbc0 596 storeAppendPrintf(sentry, "\tmemPoolAlloc calls: %d\n",
597 mem_pool_alloc_calls);
598 storeAppendPrintf(sentry, "\tmemPoolFree calls: %d\n",
599 mem_pool_free_calls);
090089c4 600
15576b6a 601 storeAppendPrintf(sentry, "File descriptor usage for %s:\n", appname);
602 storeAppendPrintf(sentry, "\tMaximum number of file descriptors: %4d\n",
e83892e9 603 Squid_MaxFD);
15576b6a 604 storeAppendPrintf(sentry, "\tLargest file desc currently in use: %4d\n",
429fdbec 605 Biggest_FD);
15576b6a 606 storeAppendPrintf(sentry, "\tNumber of file desc currently in use: %4d\n",
88738790 607 Number_FD);
b6a2f15e 608 storeAppendPrintf(sentry, "\tFiles queued for open: %4d\n",
609 Opening_FD);
15576b6a 610 storeAppendPrintf(sentry, "\tAvailable number of file descriptors: %4d\n",
83a29c95 611 fdNFree());
15576b6a 612 storeAppendPrintf(sentry, "\tReserved number of file descriptors: %4d\n",
090089c4 613 RESERVED_FD);
83a29c95 614 storeAppendPrintf(sentry, "\tStore Disk files open: %4d\n",
615 store_open_disk_fd);
090089c4 616
15576b6a 617 storeAppendPrintf(sentry, "Internal Data Structures:\n");
618 storeAppendPrintf(sentry, "\t%6d StoreEntries\n",
3f6c0fb2 619 memInUse(MEM_STOREENTRY));
15576b6a 620 storeAppendPrintf(sentry, "\t%6d StoreEntries with MemObjects\n",
3f6c0fb2 621 memInUse(MEM_MEMOBJECT));
15576b6a 622 storeAppendPrintf(sentry, "\t%6d Hot Object Cache Items\n",
59c4d35b 623 hot_obj_count);
0b2e785a 624 storeAppendPrintf(sentry, "\t%6d on-disk objects\n",
625 n_disk_objects);
30a4f2a8 626
627#if XMALLOC_STATISTICS
58cd5bbd 628 xm_deltat = current_dtime - xm_time;
629 xm_time = current_dtime;
630 storeAppendPrintf(sentry, "\nMemory allocation statistics\n");
631 storeAppendPrintf(sentry, "Allocation Size\t Alloc Count\t Alloc Delta\t Allocs/sec \n");
30a4f2a8 632 malloc_statistics(info_get_mallstat, sentry);
633#endif
090089c4 634}
635
a7c05555 636#define XAVG(X) (dt ? (double) (f->X - l->X) / dt : 0.0)
b8d8561b 637static void
a0f32775 638statAvgDump(StoreEntry * sentry, int minutes, int hours)
090089c4 639{
a7c05555 640 StatCounters *f;
641 StatCounters *l;
642 double dt;
643 double ct;
7ae52c25 644 double x;
a7c05555 645 assert(N_COUNT_HIST > 1);
a0f32775 646 assert(minutes > 0 || hours > 0);
a7c05555 647 f = &CountHist[0];
a0f32775 648 l = f;
649 if (minutes > 0 && hours == 0) {
650 /* checking minute readings ... */
651 if (minutes > N_COUNT_HIST - 1)
652 minutes = N_COUNT_HIST - 1;
653 l = &CountHist[minutes];
654 } else if (minutes == 0 && hours > 0) {
655 /* checking hour readings ... */
656 if (hours > N_COUNT_HOUR_HIST - 1)
657 hours = N_COUNT_HOUR_HIST - 1;
658 l = &CountHourHist[hours];
659 } else {
399e85ea 660 debug(18, 1) ("statAvgDump: Invalid args, minutes=%d, hours=%d\n",
661 minutes, hours);
a0f32775 662 return;
663 }
a7c05555 664 dt = tvSubDsec(l->timestamp, f->timestamp);
665 ct = f->cputime - l->cputime;
ee1679df 666
399e85ea 667 storeAppendPrintf(sentry, "sample_start_time = %d.%d (%s)\n",
5f6ac48b 668 (int) l->timestamp.tv_sec,
669 (int) l->timestamp.tv_usec,
cc1ae888 670 mkrfc1123(l->timestamp.tv_sec));
5843f24a 671 storeAppendPrintf(sentry, "sample_end_time = %d.%d (%s)\n",
672 (int) f->timestamp.tv_sec,
673 (int) f->timestamp.tv_usec,
cc1ae888 674 mkrfc1123(f->timestamp.tv_sec));
a0f32775 675
a7c05555 676 storeAppendPrintf(sentry, "client_http.requests = %f/sec\n",
677 XAVG(client_http.requests));
678 storeAppendPrintf(sentry, "client_http.hits = %f/sec\n",
679 XAVG(client_http.hits));
680 storeAppendPrintf(sentry, "client_http.errors = %f/sec\n",
681 XAVG(client_http.errors));
682 storeAppendPrintf(sentry, "client_http.kbytes_in = %f/sec\n",
683 XAVG(client_http.kbytes_in.kb));
684 storeAppendPrintf(sentry, "client_http.kbytes_out = %f/sec\n",
685 XAVG(client_http.kbytes_out.kb));
ee1679df 686
12cf1be2 687 x = statHistDeltaMedian(&l->client_http.all_svc_time,
ee1679df 688 &f->client_http.all_svc_time);
689 storeAppendPrintf(sentry, "client_http.all_median_svc_time = %f seconds\n",
690 x / 1000.0);
12cf1be2 691 x = statHistDeltaMedian(&l->client_http.miss_svc_time,
ee1679df 692 &f->client_http.miss_svc_time);
693 storeAppendPrintf(sentry, "client_http.miss_median_svc_time = %f seconds\n",
694 x / 1000.0);
12cf1be2 695 x = statHistDeltaMedian(&l->client_http.nm_svc_time,
ee1679df 696 &f->client_http.nm_svc_time);
697 storeAppendPrintf(sentry, "client_http.nm_median_svc_time = %f seconds\n",
698 x / 1000.0);
7c9c84ad 699 x = statHistDeltaMedian(&l->client_http.nh_svc_time,
700 &f->client_http.nh_svc_time);
701 storeAppendPrintf(sentry, "client_http.nh_median_svc_time = %f seconds\n",
702 x / 1000.0);
12cf1be2 703 x = statHistDeltaMedian(&l->client_http.hit_svc_time,
ee1679df 704 &f->client_http.hit_svc_time);
705 storeAppendPrintf(sentry, "client_http.hit_median_svc_time = %f seconds\n",
7ae52c25 706 x / 1000.0);
071a3ae7 707
a0f32775 708 storeAppendPrintf(sentry, "server.all.requests = %f/sec\n",
709 XAVG(server.all.requests));
710 storeAppendPrintf(sentry, "server.all.errors = %f/sec\n",
711 XAVG(server.all.errors));
712 storeAppendPrintf(sentry, "server.all.kbytes_in = %f/sec\n",
713 XAVG(server.all.kbytes_in.kb));
714 storeAppendPrintf(sentry, "server.all.kbytes_out = %f/sec\n",
715 XAVG(server.all.kbytes_out.kb));
716
717 storeAppendPrintf(sentry, "server.http.requests = %f/sec\n",
718 XAVG(server.http.requests));
719 storeAppendPrintf(sentry, "server.http.errors = %f/sec\n",
720 XAVG(server.http.errors));
721 storeAppendPrintf(sentry, "server.http.kbytes_in = %f/sec\n",
722 XAVG(server.http.kbytes_in.kb));
723 storeAppendPrintf(sentry, "server.http.kbytes_out = %f/sec\n",
724 XAVG(server.http.kbytes_out.kb));
725
726 storeAppendPrintf(sentry, "server.ftp.requests = %f/sec\n",
727 XAVG(server.ftp.requests));
728 storeAppendPrintf(sentry, "server.ftp.errors = %f/sec\n",
729 XAVG(server.ftp.errors));
730 storeAppendPrintf(sentry, "server.ftp.kbytes_in = %f/sec\n",
731 XAVG(server.ftp.kbytes_in.kb));
732 storeAppendPrintf(sentry, "server.ftp.kbytes_out = %f/sec\n",
733 XAVG(server.ftp.kbytes_out.kb));
734
735 storeAppendPrintf(sentry, "server.other.requests = %f/sec\n",
736 XAVG(server.other.requests));
737 storeAppendPrintf(sentry, "server.other.errors = %f/sec\n",
738 XAVG(server.other.errors));
739 storeAppendPrintf(sentry, "server.other.kbytes_in = %f/sec\n",
740 XAVG(server.other.kbytes_in.kb));
741 storeAppendPrintf(sentry, "server.other.kbytes_out = %f/sec\n",
742 XAVG(server.other.kbytes_out.kb));
ee1679df 743
a7c05555 744 storeAppendPrintf(sentry, "icp.pkts_sent = %f/sec\n",
745 XAVG(icp.pkts_sent));
746 storeAppendPrintf(sentry, "icp.pkts_recv = %f/sec\n",
747 XAVG(icp.pkts_recv));
071a3ae7 748 storeAppendPrintf(sentry, "icp.queries_sent = %f/sec\n",
749 XAVG(icp.queries_sent));
750 storeAppendPrintf(sentry, "icp.replies_sent = %f/sec\n",
751 XAVG(icp.replies_sent));
752 storeAppendPrintf(sentry, "icp.queries_recv = %f/sec\n",
753 XAVG(icp.queries_recv));
754 storeAppendPrintf(sentry, "icp.replies_recv = %f/sec\n",
755 XAVG(icp.replies_recv));
2e8e29b8 756 storeAppendPrintf(sentry, "icp.replies_queued = %f/sec\n",
757 XAVG(icp.replies_queued));
071a3ae7 758 storeAppendPrintf(sentry, "icp.query_timeouts = %f/sec\n",
759 XAVG(icp.query_timeouts));
a7c05555 760 storeAppendPrintf(sentry, "icp.kbytes_sent = %f/sec\n",
761 XAVG(icp.kbytes_sent.kb));
762 storeAppendPrintf(sentry, "icp.kbytes_recv = %f/sec\n",
763 XAVG(icp.kbytes_recv.kb));
071a3ae7 764 storeAppendPrintf(sentry, "icp.q_kbytes_sent = %f/sec\n",
765 XAVG(icp.q_kbytes_sent.kb));
766 storeAppendPrintf(sentry, "icp.r_kbytes_sent = %f/sec\n",
767 XAVG(icp.r_kbytes_sent.kb));
768 storeAppendPrintf(sentry, "icp.q_kbytes_recv = %f/sec\n",
769 XAVG(icp.q_kbytes_recv.kb));
770 storeAppendPrintf(sentry, "icp.r_kbytes_recv = %f/sec\n",
771 XAVG(icp.r_kbytes_recv.kb));
12cf1be2 772 x = statHistDeltaMedian(&l->icp.query_svc_time, &f->icp.query_svc_time);
ee1679df 773 storeAppendPrintf(sentry, "icp.query_median_svc_time = %f seconds\n",
774 x / 1000000.0);
12cf1be2 775 x = statHistDeltaMedian(&l->icp.reply_svc_time, &f->icp.reply_svc_time);
ee1679df 776 storeAppendPrintf(sentry, "icp.reply_median_svc_time = %f seconds\n",
7ae52c25 777 x / 1000000.0);
12cf1be2 778 x = statHistDeltaMedian(&l->dns.svc_time, &f->dns.svc_time);
9973e9fe 779 storeAppendPrintf(sentry, "dns.median_svc_time = %f seconds\n",
901d8c30 780 x / 1000.0);
a7c05555 781 storeAppendPrintf(sentry, "unlink.requests = %f/sec\n",
782 XAVG(unlink.requests));
783 storeAppendPrintf(sentry, "page_faults = %f/sec\n",
784 XAVG(page_faults));
785 storeAppendPrintf(sentry, "select_loops = %f/sec\n",
786 XAVG(select_loops));
d239c2f5 787 storeAppendPrintf(sentry, "select_fds = %f/sec\n",
788 XAVG(select_fds));
789 storeAppendPrintf(sentry, "average_select_fd_period = %f/fd\n",
5942e8d4 790 f->select_fds > l->select_fds ?
d239c2f5 791 (f->select_time - l->select_time) / (f->select_fds - l->select_fds)
792 : 0.0);
26d6ee93 793 x = statHistDeltaMedian(&l->select_fds_hist, &f->select_fds_hist);
794 storeAppendPrintf(sentry, "median_select_fds = %f\n", x);
23dc8aca 795 storeAppendPrintf(sentry, "swap.outs = %f/sec\n",
796 XAVG(swap.outs));
797 storeAppendPrintf(sentry, "swap.ins = %f/sec\n",
798 XAVG(swap.ins));
799 storeAppendPrintf(sentry, "swap.files_cleaned = %f/sec\n",
800 XAVG(swap.files_cleaned));
bfae3379 801 storeAppendPrintf(sentry, "aborted_requests = %f/sec\n",
802 XAVG(aborted_requests));
886f2785 803
804#if HAVE_POLL
805 storeAppendPrintf(sentry, "syscalls.polls = %f/sec\n", XAVG(syscalls.polls));
806#else
807 storeAppendPrintf(sentry, "syscalls.selects = %f/sec\n", XAVG(syscalls.selects));
808#endif
809 storeAppendPrintf(sentry, "syscalls.disk.opens = %f/sec\n", XAVG(syscalls.disk.opens));
810 storeAppendPrintf(sentry, "syscalls.disk.closes = %f/sec\n", XAVG(syscalls.disk.closes));
811 storeAppendPrintf(sentry, "syscalls.disk.reads = %f/sec\n", XAVG(syscalls.disk.reads));
812 storeAppendPrintf(sentry, "syscalls.disk.writes = %f/sec\n", XAVG(syscalls.disk.writes));
813 storeAppendPrintf(sentry, "syscalls.disk.seeks = %f/sec\n", XAVG(syscalls.disk.seeks));
bfae3379 814 storeAppendPrintf(sentry, "syscalls.disk.unlinks = %f/sec\n", XAVG(syscalls.disk.unlinks));
886f2785 815 storeAppendPrintf(sentry, "syscalls.sock.accepts = %f/sec\n", XAVG(syscalls.sock.accepts));
816 storeAppendPrintf(sentry, "syscalls.sock.sockets = %f/sec\n", XAVG(syscalls.sock.sockets));
817 storeAppendPrintf(sentry, "syscalls.sock.connects = %f/sec\n", XAVG(syscalls.sock.connects));
818 storeAppendPrintf(sentry, "syscalls.sock.binds = %f/sec\n", XAVG(syscalls.sock.binds));
819 storeAppendPrintf(sentry, "syscalls.sock.closes = %f/sec\n", XAVG(syscalls.sock.closes));
820 storeAppendPrintf(sentry, "syscalls.sock.reads = %f/sec\n", XAVG(syscalls.sock.reads));
821 storeAppendPrintf(sentry, "syscalls.sock.writes = %f/sec\n", XAVG(syscalls.sock.writes));
822 storeAppendPrintf(sentry, "syscalls.sock.recvfroms = %f/sec\n", XAVG(syscalls.sock.recvfroms));
823 storeAppendPrintf(sentry, "syscalls.sock.sendtos = %f/sec\n", XAVG(syscalls.sock.sendtos));
824
a7c05555 825 storeAppendPrintf(sentry, "cpu_time = %f seconds\n", ct);
826 storeAppendPrintf(sentry, "wall_time = %f seconds\n", dt);
0e473d70 827 storeAppendPrintf(sentry, "cpu_usage = %f%%\n", dpercent(ct, dt));
090089c4 828}
829
979533fa 830
b8d8561b 831void
a7c05555 832statInit(void)
090089c4 833{
090089c4 834 int i;
a7c05555 835 debug(18, 5) ("statInit: Initializing...\n");
28c60158 836 CBDATA_INIT_TYPE(StatObjectsState);
0e473d70 837 for (i = 0; i < N_COUNT_HIST; i++)
12cf1be2 838 statCountersInit(&CountHist[i]);
a0f32775 839 for (i = 0; i < N_COUNT_HOUR_HIST; i++)
840 statCountersInit(&CountHourHist[i]);
83704487 841 statCountersInit(&statCounter);
52040193 842 eventAdd("statAvgTick", statAvgTick, NULL, (double) COUNT_INTERVAL, 1);
22f3fd98 843 cachemgrRegister("info",
844 "General Runtime Information",
1da3b90b 845 info_get, 0, 1);
22f3fd98 846 cachemgrRegister("filedescriptors",
847 "Process Filedescriptor Allocation",
1da3b90b 848 statFiledescriptors, 0, 1);
22f3fd98 849 cachemgrRegister("objects",
850 "All Cache Objects",
1da3b90b 851 stat_objects_get, 0, 0);
22f3fd98 852 cachemgrRegister("vm_objects",
853 "In-Memory and In-Transit Objects",
1da3b90b 854 stat_vmobjects_get, 0, 0);
ae94d28e 855#if DEBUG_OPENFD
856 cachemgrRegister("openfd_objects",
857 "Objects with Swapout files open",
1da3b90b 858 statOpenfdObj, 0, 0);
ae94d28e 859#endif
22f3fd98 860 cachemgrRegister("io",
861 "Server-side network read() size histograms",
1da3b90b 862 stat_io_get, 0, 1);
22f3fd98 863 cachemgrRegister("counters",
864 "Traffic and Resource Counters",
1da3b90b 865 statCountersDump, 0, 1);
a1e927f6 866 cachemgrRegister("peer_select",
867 "Peer Selection Algorithms",
1da3b90b 868 statPeerSelect, 0, 1);
26b164ac 869 cachemgrRegister("digest_stats",
870 "Cache Digest and ICP blob",
1da3b90b 871 statDigestBlob, 0, 1);
22f3fd98 872 cachemgrRegister("5min",
873 "5 Minute Average of Counters",
1da3b90b 874 statAvg5min, 0, 1);
45eb7f49 875 cachemgrRegister("60min",
876 "60 Minute Average of Counters",
1da3b90b 877 statAvg60min, 0, 1);
e9b5ead4 878 cachemgrRegister("utilization",
879 "Cache Utilization",
1da3b90b 880 statUtilization, 0, 1);
01aebf31 881#if STAT_GRAPHS
882 cachemgrRegister("graph_variables",
883 "Display cache metrics graphically",
1da3b90b 884 statGraphDump, 0, 1);
01aebf31 885#endif
ba4f8e5a 886 cachemgrRegister("histograms",
887 "Full Histogram Counts",
1da3b90b 888 statCountersHistograms, 0, 1);
0f1bc304 889 ClientActiveRequests.head = NULL;
890 ClientActiveRequests.tail = NULL;
891 cachemgrRegister("active_requests",
892 "Client-side Active Requests",
893 statClientRequests, 0, 1);
090089c4 894}
f2908497 895
f2908497 896static void
897statAvgTick(void *notused)
898{
d5649d9f 899 StatCounters *t = &CountHist[0];
900 StatCounters *p = &CountHist[1];
83704487 901 StatCounters *c = &statCounter;
f2908497 902 struct rusage rusage;
b6a2f15e 903 eventAdd("statAvgTick", statAvgTick, NULL, (double) COUNT_INTERVAL, 1);
20903cac 904 squid_getrusage(&rusage);
905 c->page_faults = rusage_pagefaults(&rusage);
906 c->cputime = rusage_cputime(&rusage);
d5649d9f 907 c->timestamp = current_time;
12cf1be2 908 /* even if NCountHist is small, we already Init()ed the tail */
2ac76861 909 statCountersClean(CountHist + N_COUNT_HIST - 1);
dbfed404 910 xmemmove(p, t, (N_COUNT_HIST - 1) * sizeof(StatCounters));
12cf1be2 911 statCountersCopy(t, c);
d5649d9f 912 NCountHist++;
a0f32775 913
914 if ((NCountHist % COUNT_INTERVAL) == 0) {
915 /* we have an hours worth of readings. store previous hour */
ffb245b5 916 StatCounters *t = &CountHourHist[0];
917 StatCounters *p = &CountHourHist[1];
e82d6d21 918 StatCounters *c = &CountHist[N_COUNT_HIST - 1];
ffb245b5 919 statCountersClean(CountHourHist + N_COUNT_HOUR_HIST - 1);
a0f32775 920 xmemmove(p, t, (N_COUNT_HOUR_HIST - 1) * sizeof(StatCounters));
a887b8fa 921 statCountersCopy(t, c);
a0f32775 922 NCountHourHist++;
923 }
b8a46de0 924 if (Config.warnings.high_rptm > 0) {
7fb4e2d1 925 int i = (int) statMedianSvc(20, MEDIAN_HTTP);
b8a46de0 926 if (Config.warnings.high_rptm < i)
927 debug(18, 0) ("WARNING: Median response time is %d milliseconds\n", i);
928 }
929 if (Config.warnings.high_pf) {
930 int i = (CountHist[0].page_faults - CountHist[1].page_faults);
931 double dt = tvSubDsec(CountHist[0].timestamp, CountHist[1].timestamp);
16516f66 932 if (i > 0 && dt > 0.0) {
b8a46de0 933 i /= (int) dt;
16516f66 934 if (Config.warnings.high_pf < i)
935 debug(18, 0) ("WARNING: Page faults occuring at %d/sec\n", i);
936 }
b8a46de0 937 }
938 if (Config.warnings.high_memory) {
939 int i = 0;
940#if HAVE_MSTATS && HAVE_GNUMALLOC_H
941 struct mstats ms = mstats();
942 i = ms.bytes_total;
943#elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
944 struct mallinfo mp = mallinfo();
945 i = mp.arena;
946#endif
2a5a6521 947 if (Config.warnings.high_memory < i)
b8a46de0 948 debug(18, 0) ("WARNING: Memory usage at %d MB\n", i >> 20);
949 }
20903cac 950}
951
12cf1be2 952static void
2ac76861 953statCountersInit(StatCounters * C)
20903cac 954{
12cf1be2 955 assert(C);
1d803566 956 memset(C, 0, sizeof(*C));
12cf1be2 957 C->timestamp = current_time;
1d803566 958 statCountersInitSpecial(C);
959}
960
961/* add special cases here as they arrive */
962static void
2ac76861 963statCountersInitSpecial(StatCounters * C)
1d803566 964{
12cf1be2 965 /*
966 * HTTP svc_time hist is kept in milli-seconds; max of 3 hours.
967 */
968 statHistLogInit(&C->client_http.all_svc_time, 300, 0.0, 3600000.0 * 3.0);
969 statHistLogInit(&C->client_http.miss_svc_time, 300, 0.0, 3600000.0 * 3.0);
970 statHistLogInit(&C->client_http.nm_svc_time, 300, 0.0, 3600000.0 * 3.0);
7c9c84ad 971 statHistLogInit(&C->client_http.nh_svc_time, 300, 0.0, 3600000.0 * 3.0);
12cf1be2 972 statHistLogInit(&C->client_http.hit_svc_time, 300, 0.0, 3600000.0 * 3.0);
973 /*
974 * ICP svc_time hist is kept in micro-seconds; max of 1 minute.
975 */
976 statHistLogInit(&C->icp.query_svc_time, 300, 0.0, 1000000.0 * 60.0);
977 statHistLogInit(&C->icp.reply_svc_time, 300, 0.0, 1000000.0 * 60.0);
978 /*
979 * DNS svc_time hist is kept in milli-seconds; max of 10 minutes.
980 */
981 statHistLogInit(&C->dns.svc_time, 300, 0.0, 60000.0 * 10.0);
a1e927f6 982 /*
69c95dd3 983 * Cache Digest Stuff
a1e927f6 984 */
0c511722 985 statHistEnumInit(&C->cd.on_xition_count, CacheDigestHashFuncCount);
c6ecdbc3 986 statHistEnumInit(&C->comm_icp_incoming, INCOMING_ICP_MAX);
ef523f99 987 statHistEnumInit(&C->comm_dns_incoming, INCOMING_DNS_MAX);
c6ecdbc3 988 statHistEnumInit(&C->comm_http_incoming, INCOMING_HTTP_MAX);
26d6ee93 989 statHistIntInit(&C->select_fds_hist, SQUID_MAXFD);
0f5607d9 990}
991
12cf1be2 992/* add special cases here as they arrive */
5e29a294 993static void
2ac76861 994statCountersClean(StatCounters * C)
0f5607d9 995{
12cf1be2 996 assert(C);
997 statHistClean(&C->client_http.all_svc_time);
998 statHistClean(&C->client_http.miss_svc_time);
999 statHistClean(&C->client_http.nm_svc_time);
7c9c84ad 1000 statHistClean(&C->client_http.nh_svc_time);
12cf1be2 1001 statHistClean(&C->client_http.hit_svc_time);
1002 statHistClean(&C->icp.query_svc_time);
1003 statHistClean(&C->icp.reply_svc_time);
1004 statHistClean(&C->dns.svc_time);
c135694e 1005 statHistClean(&C->cd.on_xition_count);
c6ecdbc3 1006 statHistClean(&C->comm_icp_incoming);
1007 statHistClean(&C->comm_http_incoming);
26d6ee93 1008 statHistClean(&C->select_fds_hist);
a7c05555 1009}
1010
12cf1be2 1011/* add special cases here as they arrive */
5e29a294 1012static void
2ac76861 1013statCountersCopy(StatCounters * dest, const StatCounters * orig)
45eb7f49 1014{
12cf1be2 1015 assert(dest && orig);
1d803566 1016 /* this should take care of all the fields, but "special" ones */
cac03dd2 1017 xmemcpy(dest, orig, sizeof(*dest));
1d803566 1018 /* prepare space where to copy special entries */
1019 statCountersInitSpecial(dest);
1020 /* now handle special cases */
1021 /* note: we assert that histogram capacities do not change */
12cf1be2 1022 statHistCopy(&dest->client_http.all_svc_time, &orig->client_http.all_svc_time);
1023 statHistCopy(&dest->client_http.miss_svc_time, &orig->client_http.miss_svc_time);
1024 statHistCopy(&dest->client_http.nm_svc_time, &orig->client_http.nm_svc_time);
7c9c84ad 1025 statHistCopy(&dest->client_http.nh_svc_time, &orig->client_http.nh_svc_time);
12cf1be2 1026 statHistCopy(&dest->client_http.hit_svc_time, &orig->client_http.hit_svc_time);
1027 statHistCopy(&dest->icp.query_svc_time, &orig->icp.query_svc_time);
1028 statHistCopy(&dest->icp.reply_svc_time, &orig->icp.reply_svc_time);
1029 statHistCopy(&dest->dns.svc_time, &orig->dns.svc_time);
c135694e 1030 statHistCopy(&dest->cd.on_xition_count, &orig->cd.on_xition_count);
c6ecdbc3 1031 statHistCopy(&dest->comm_icp_incoming, &orig->comm_icp_incoming);
1032 statHistCopy(&dest->comm_http_incoming, &orig->comm_http_incoming);
26d6ee93 1033 statHistCopy(&dest->select_fds_hist, &orig->select_fds_hist);
45eb7f49 1034}
1035
071a3ae7 1036static void
5d406e78 1037statCountersHistograms(StoreEntry * sentry)
071a3ae7 1038{
83704487 1039 StatCounters *f = &statCounter;
071a3ae7 1040 storeAppendPrintf(sentry, "client_http.all_svc_time histogram:\n");
1041 statHistDump(&f->client_http.all_svc_time, sentry, NULL);
1042 storeAppendPrintf(sentry, "client_http.miss_svc_time histogram:\n");
1043 statHistDump(&f->client_http.miss_svc_time, sentry, NULL);
1044 storeAppendPrintf(sentry, "client_http.nm_svc_time histogram:\n");
1045 statHistDump(&f->client_http.nm_svc_time, sentry, NULL);
7c9c84ad 1046 storeAppendPrintf(sentry, "client_http.nh_svc_time histogram:\n");
1047 statHistDump(&f->client_http.nh_svc_time, sentry, NULL);
071a3ae7 1048 storeAppendPrintf(sentry, "client_http.hit_svc_time histogram:\n");
1049 statHistDump(&f->client_http.hit_svc_time, sentry, NULL);
071a3ae7 1050 storeAppendPrintf(sentry, "icp.query_svc_time histogram:\n");
1051 statHistDump(&f->icp.query_svc_time, sentry, NULL);
1052 storeAppendPrintf(sentry, "icp.reply_svc_time histogram:\n");
1053 statHistDump(&f->icp.reply_svc_time, sentry, NULL);
1054 storeAppendPrintf(sentry, "dns.svc_time histogram:\n");
1055 statHistDump(&f->dns.svc_time, sentry, NULL);
071a3ae7 1056}
1057
12cf1be2 1058static void
1059statCountersDump(StoreEntry * sentry)
7ae52c25 1060{
83704487 1061 StatCounters *f = &statCounter;
12cf1be2 1062 struct rusage rusage;
1063 squid_getrusage(&rusage);
1064 f->page_faults = rusage_pagefaults(&rusage);
1065 f->cputime = rusage_cputime(&rusage);
1066
a0f32775 1067 storeAppendPrintf(sentry, "sample_time = %d.%d (%s)\n",
5f6ac48b 1068 (int) f->timestamp.tv_sec,
1069 (int) f->timestamp.tv_usec,
a0f32775 1070 mkrfc1123(f->timestamp.tv_sec));
12cf1be2 1071 storeAppendPrintf(sentry, "client_http.requests = %d\n",
1072 f->client_http.requests);
1073 storeAppendPrintf(sentry, "client_http.hits = %d\n",
1074 f->client_http.hits);
1075 storeAppendPrintf(sentry, "client_http.errors = %d\n",
1076 f->client_http.errors);
1077 storeAppendPrintf(sentry, "client_http.kbytes_in = %d\n",
1078 (int) f->client_http.kbytes_in.kb);
1079 storeAppendPrintf(sentry, "client_http.kbytes_out = %d\n",
1080 (int) f->client_http.kbytes_out.kb);
c68e9c6b 1081 storeAppendPrintf(sentry, "client_http.hit_kbytes_out = %d\n",
1082 (int) f->client_http.hit_kbytes_out.kb);
0567f2a6 1083
a0f32775 1084 storeAppendPrintf(sentry, "server.all.requests = %d\n",
1085 (int) f->server.all.requests);
1086 storeAppendPrintf(sentry, "server.all.errors = %d\n",
1087 (int) f->server.all.errors);
1088 storeAppendPrintf(sentry, "server.all.kbytes_in = %d\n",
1089 (int) f->server.all.kbytes_in.kb);
1090 storeAppendPrintf(sentry, "server.all.kbytes_out = %d\n",
1091 (int) f->server.all.kbytes_out.kb);
1092
1093 storeAppendPrintf(sentry, "server.http.requests = %d\n",
1094 (int) f->server.http.requests);
1095 storeAppendPrintf(sentry, "server.http.errors = %d\n",
1096 (int) f->server.http.errors);
1097 storeAppendPrintf(sentry, "server.http.kbytes_in = %d\n",
1098 (int) f->server.http.kbytes_in.kb);
1099 storeAppendPrintf(sentry, "server.http.kbytes_out = %d\n",
1100 (int) f->server.http.kbytes_out.kb);
1101
1102 storeAppendPrintf(sentry, "server.ftp.requests = %d\n",
1103 (int) f->server.ftp.requests);
1104 storeAppendPrintf(sentry, "server.ftp.errors = %d\n",
1105 (int) f->server.ftp.errors);
1106 storeAppendPrintf(sentry, "server.ftp.kbytes_in = %d\n",
1107 (int) f->server.ftp.kbytes_in.kb);
1108 storeAppendPrintf(sentry, "server.ftp.kbytes_out = %d\n",
1109 (int) f->server.ftp.kbytes_out.kb);
1110
1111 storeAppendPrintf(sentry, "server.other.requests = %d\n",
1112 (int) f->server.other.requests);
1113 storeAppendPrintf(sentry, "server.other.errors = %d\n",
1114 (int) f->server.other.errors);
1115 storeAppendPrintf(sentry, "server.other.kbytes_in = %d\n",
1116 (int) f->server.other.kbytes_in.kb);
1117 storeAppendPrintf(sentry, "server.other.kbytes_out = %d\n",
1118 (int) f->server.other.kbytes_out.kb);
12cf1be2 1119
1120 storeAppendPrintf(sentry, "icp.pkts_sent = %d\n",
1121 f->icp.pkts_sent);
1122 storeAppendPrintf(sentry, "icp.pkts_recv = %d\n",
1123 f->icp.pkts_recv);
071a3ae7 1124 storeAppendPrintf(sentry, "icp.queries_sent = %d\n",
1125 f->icp.queries_sent);
1126 storeAppendPrintf(sentry, "icp.replies_sent = %d\n",
1127 f->icp.replies_sent);
1128 storeAppendPrintf(sentry, "icp.queries_recv = %d\n",
1129 f->icp.queries_recv);
1130 storeAppendPrintf(sentry, "icp.replies_recv = %d\n",
1131 f->icp.replies_recv);
1132 storeAppendPrintf(sentry, "icp.query_timeouts = %d\n",
1133 f->icp.query_timeouts);
2e8e29b8 1134 storeAppendPrintf(sentry, "icp.replies_queued = %d\n",
1135 f->icp.replies_queued);
12cf1be2 1136 storeAppendPrintf(sentry, "icp.kbytes_sent = %d\n",
1137 (int) f->icp.kbytes_sent.kb);
1138 storeAppendPrintf(sentry, "icp.kbytes_recv = %d\n",
1139 (int) f->icp.kbytes_recv.kb);
071a3ae7 1140 storeAppendPrintf(sentry, "icp.q_kbytes_sent = %d\n",
1141 (int) f->icp.q_kbytes_sent.kb);
1142 storeAppendPrintf(sentry, "icp.r_kbytes_sent = %d\n",
1143 (int) f->icp.r_kbytes_sent.kb);
1144 storeAppendPrintf(sentry, "icp.q_kbytes_recv = %d\n",
1145 (int) f->icp.q_kbytes_recv.kb);
1146 storeAppendPrintf(sentry, "icp.r_kbytes_recv = %d\n",
1147 (int) f->icp.r_kbytes_recv.kb);
0567f2a6 1148
6cfa8966 1149#if USE_CACHE_DIGESTS
071a3ae7 1150 storeAppendPrintf(sentry, "icp.times_used = %d\n",
5d406e78 1151 f->icp.times_used);
071a3ae7 1152 storeAppendPrintf(sentry, "cd.times_used = %d\n",
5d406e78 1153 f->cd.times_used);
00485c29 1154 storeAppendPrintf(sentry, "cd.msgs_sent = %d\n",
1155 f->cd.msgs_sent);
1156 storeAppendPrintf(sentry, "cd.msgs_recv = %d\n",
1157 f->cd.msgs_recv);
071a3ae7 1158 storeAppendPrintf(sentry, "cd.memory = %d\n",
5d406e78 1159 (int) f->cd.memory.kb);
522b517b 1160 storeAppendPrintf(sentry, "cd.local_memory = %d\n",
5d406e78 1161 (int) (store_digest ? store_digest->mask_size / 1024 : 0));
00485c29 1162 storeAppendPrintf(sentry, "cd.kbytes_sent = %d\n",
1163 (int) f->cd.kbytes_sent.kb);
1164 storeAppendPrintf(sentry, "cd.kbytes_recv = %d\n",
1165 (int) f->cd.kbytes_recv.kb);
0567f2a6 1166#endif
1167
12cf1be2 1168 storeAppendPrintf(sentry, "unlink.requests = %d\n",
1169 f->unlink.requests);
1170 storeAppendPrintf(sentry, "page_faults = %d\n",
1171 f->page_faults);
1172 storeAppendPrintf(sentry, "select_loops = %d\n",
1173 f->select_loops);
1174 storeAppendPrintf(sentry, "cpu_time = %f\n",
1175 f->cputime);
1176 storeAppendPrintf(sentry, "wall_time = %f\n",
1177 tvSubDsec(f->timestamp, current_time));
23dc8aca 1178 storeAppendPrintf(sentry, "swap.outs = %d\n",
1179 f->swap.outs);
1180 storeAppendPrintf(sentry, "swap.ins = %d\n",
1181 f->swap.ins);
1182 storeAppendPrintf(sentry, "swap.files_cleaned = %d\n",
1183 f->swap.files_cleaned);
bfae3379 1184 storeAppendPrintf(sentry, "aborted_requests = %d\n",
1185 f->aborted_requests);
7ae52c25 1186}
1187
d2db411c 1188void
1189statFreeMemory(void)
1190{
1191 int i;
1192 for (i = 0; i < N_COUNT_HIST; i++)
1193 statCountersClean(&CountHist[i]);
1194 for (i = 0; i < N_COUNT_HOUR_HIST; i++)
1195 statCountersClean(&CountHourHist[i]);
1196}
1197
5e29a294 1198static void
a1e927f6 1199statPeerSelect(StoreEntry * sentry)
1200{
6cfa8966 1201#if USE_CACHE_DIGESTS
83704487 1202 StatCounters *f = &statCounter;
a1e927f6 1203 peer *peer;
1204 const int tot_used = f->cd.times_used + f->icp.times_used;
1205
1206 /* totals */
1207 cacheDigestGuessStatsReport(&f->cd.guess, sentry, "all peers");
1208 /* per-peer */
1209 storeAppendPrintf(sentry, "\nPer-peer statistics:\n");
1210 for (peer = getFirstPeer(); peer; peer = getNextPeer(peer)) {
e13ee7ad 1211 if (peer->digest)
1212 peerDigestStatsReport(peer->digest, sentry);
1543ab6c 1213 else
e13ee7ad 1214 storeAppendPrintf(sentry, "\nNo peer digest from %s\n", peer->host);
7ea5d333 1215 storeAppendPrintf(sentry, "\n");
a1e927f6 1216 }
1217
1218 storeAppendPrintf(sentry, "\nAlgorithm usage:\n");
1219 storeAppendPrintf(sentry, "Cache Digest: %7d (%3d%%)\n",
1220 f->cd.times_used, xpercentInt(f->cd.times_used, tot_used));
1221 storeAppendPrintf(sentry, "Icp: %7d (%3d%%)\n",
1222 f->icp.times_used, xpercentInt(f->icp.times_used, tot_used));
1223 storeAppendPrintf(sentry, "Total: %7d (%3d%%)\n",
1224 tot_used, xpercentInt(tot_used, tot_used));
1225#else
1226 storeAppendPrintf(sentry, "peer digests are disabled; no stats is available.\n");
1227#endif
1228}
1229
1230static void
26b164ac 1231statDigestBlob(StoreEntry * sentry)
1232{
071a3ae7 1233 storeAppendPrintf(sentry, "\nCounters:\n");
1234 statCountersDump(sentry);
86e2a291 1235 storeAppendPrintf(sentry, "\n5 Min Averages:\n");
1236 statAvgDump(sentry, 5, 0);
071a3ae7 1237 storeAppendPrintf(sentry, "\nHistograms:\n");
1238 statCountersHistograms(sentry);
1239 storeAppendPrintf(sentry, "\nPeer Digests:\n");
26b164ac 1240 statPeerSelect(sentry);
588d9545 1241 storeAppendPrintf(sentry, "\nLocal Digest:\n");
26b164ac 1242 storeDigestReport(sentry);
1243}
1244
5e29a294 1245static void
12cf1be2 1246statAvg5min(StoreEntry * e)
7ae52c25 1247{
a0f32775 1248 statAvgDump(e, 5, 0);
7ae52c25 1249}
1250
5e29a294 1251static void
12cf1be2 1252statAvg60min(StoreEntry * e)
7ae52c25 1253{
a0f32775 1254 statAvgDump(e, 60, 0);
7ae52c25 1255}
1256
7d94ae33 1257static double
b87b92fb 1258statMedianSvc(int interval, int which)
a9113eb0 1259{
1260 StatCounters *f;
1261 StatCounters *l;
1262 double x;
f8d264b8 1263 assert(interval > 0);
1264 if (interval > N_COUNT_HIST - 1)
1265 interval = N_COUNT_HIST - 1;
a9113eb0 1266 f = &CountHist[0];
1267 l = &CountHist[interval];
ee1679df 1268 assert(f);
1269 assert(l);
a9113eb0 1270 switch (which) {
b87b92fb 1271 case MEDIAN_HTTP:
12cf1be2 1272 x = statHistDeltaMedian(&l->client_http.all_svc_time, &f->client_http.all_svc_time);
ee1679df 1273 break;
b87b92fb 1274 case MEDIAN_HIT:
1275 x = statHistDeltaMedian(&l->client_http.hit_svc_time, &f->client_http.hit_svc_time);
1276 break;
1277 case MEDIAN_MISS:
1278 x = statHistDeltaMedian(&l->client_http.miss_svc_time, &f->client_http.miss_svc_time);
1279 break;
1280 case MEDIAN_NM:
1281 x = statHistDeltaMedian(&l->client_http.nm_svc_time, &f->client_http.nm_svc_time);
1282 break;
7c9c84ad 1283 case MEDIAN_NH:
1284 x = statHistDeltaMedian(&l->client_http.nh_svc_time, &f->client_http.nh_svc_time);
1285 break;
b87b92fb 1286 case MEDIAN_ICP_QUERY:
12cf1be2 1287 x = statHistDeltaMedian(&l->icp.query_svc_time, &f->icp.query_svc_time);
ee1679df 1288 break;
b87b92fb 1289 case MEDIAN_DNS:
12cf1be2 1290 x = statHistDeltaMedian(&l->dns.svc_time, &f->dns.svc_time);
ee1679df 1291 break;
a9113eb0 1292 default:
ee1679df 1293 debug(49, 5) ("get_median_val: unknown type.\n");
1294 x = 0;
a9113eb0 1295 }
b87b92fb 1296 return x;
1297}
1298
1299/*
1300 * SNMP wants ints, ick
1301 */
1302int
1303get_median_svc(int interval, int which)
1304{
b644367b 1305 return (int) statMedianSvc(interval, which);
a9113eb0 1306}
451b07c5 1307
1308StatCounters *
1309snmpStatGet(int minutes)
1310{
2ac76861 1311 return &CountHist[minutes];
451b07c5 1312}
01aebf31 1313
1f3c4622 1314int
1315stat5minClientRequests(void)
1316{
5999b776 1317 assert(N_COUNT_HIST > 5);
83704487 1318 return statCounter.client_http.requests - CountHist[5].client_http.requests;
1f3c4622 1319}
1320
49ad0a8c 1321static double
1322statCPUUsage(int minutes)
979533fa 1323{
49ad0a8c 1324 assert(minutes < N_COUNT_HIST);
1325 return dpercent(CountHist[0].cputime - CountHist[minutes].cputime,
1326 tvSubDsec(CountHist[minutes].timestamp, CountHist[0].timestamp));
979533fa 1327}
01aebf31 1328
1d5b6d43 1329extern double
491a980b 1330statRequestHitRatio(int minutes)
1331{
1332 assert(minutes < N_COUNT_HIST);
1333 return dpercent(CountHist[0].client_http.hits -
1334 CountHist[minutes].client_http.hits,
1335 CountHist[0].client_http.requests -
1336 CountHist[minutes].client_http.requests);
1337}
1338
4f4d1d6e 1339extern double
1340statRequestHitMemoryRatio(int minutes)
1341{
1342 assert(minutes < N_COUNT_HIST);
1343 return dpercent(CountHist[0].client_http.mem_hits -
1344 CountHist[minutes].client_http.mem_hits,
1345 CountHist[0].client_http.hits -
1346 CountHist[minutes].client_http.hits);
1347}
1348
1349extern double
1350statRequestHitDiskRatio(int minutes)
1351{
1352 assert(minutes < N_COUNT_HIST);
1353 return dpercent(CountHist[0].client_http.disk_hits -
1354 CountHist[minutes].client_http.disk_hits,
1355 CountHist[0].client_http.hits -
1356 CountHist[minutes].client_http.hits);
1357}
1358
1d5b6d43 1359extern double
491a980b 1360statByteHitRatio(int minutes)
1361{
1362 size_t s;
1363 size_t c;
ac342231 1364#if USE_CACHE_DIGESTS
1365 size_t cd;
1366#endif
1367 /* size_t might be unsigned */
491a980b 1368 assert(minutes < N_COUNT_HIST);
1369 c = CountHist[0].client_http.kbytes_out.kb - CountHist[minutes].client_http.kbytes_out.kb;
1370 s = CountHist[0].server.all.kbytes_in.kb - CountHist[minutes].server.all.kbytes_in.kb;
ac342231 1371#if USE_CACHE_DIGESTS
1372 /*
1373 * This ugly hack is here to prevent the user from seeing a
1374 * negative byte hit ratio. When we fetch a cache digest from
1375 * a neighbor, it gets treated like a cache miss because the
1376 * object is consumed internally. Thus, we subtract cache
1377 * digest bytes out before calculating the byte hit ratio.
1378 */
1379 cd = CountHist[0].cd.kbytes_recv.kb - CountHist[minutes].cd.kbytes_recv.kb;
49d7ce5f 1380 if (s < cd)
1381 debug(18, 1) ("STRANGE: srv_kbytes=%d, cd_kbytes=%d\n", s, cd);
ac342231 1382 s -= cd;
1383#endif
94e56ef7 1384 if (c > s)
7d47d8e6 1385 return dpercent(c - s, c);
94e56ef7 1386 else
7d47d8e6 1387 return (-1.0 * dpercent(s - c, c));
491a980b 1388}
1389
0f1bc304 1390static void
1391statClientRequests(StoreEntry * s)
1392{
1393 dlink_node *i;
1394 clientHttpRequest *http;
1395 ConnStateData *conn;
1396 StoreEntry *e;
1397 int fd;
1398 for (i = ClientActiveRequests.head; i; i = i->next) {
1399 http = i->data;
1400 assert(http);
1401 conn = http->conn;
1402 storeAppendPrintf(s, "Connection: %p\n", conn);
1403 if (conn) {
1404 fd = conn->fd;
1405 storeAppendPrintf(s, "\tFD %d, read %d, wrote %d\n", fd,
1406 fd_table[fd].bytes_read, fd_table[fd].bytes_written);
1407 storeAppendPrintf(s, "\tFD desc: %s\n", fd_table[fd].desc);
1408 storeAppendPrintf(s, "\tin: buf %p, offset %d, size %d\n",
1409 conn->in.buf, conn->in.offset, conn->in.size);
1410 storeAppendPrintf(s, "\tpeer: %s:%d\n",
1411 inet_ntoa(conn->peer.sin_addr),
1412 ntohs(conn->peer.sin_port));
1413 storeAppendPrintf(s, "\tme: %s:%d\n",
1414 inet_ntoa(conn->me.sin_addr),
1415 ntohs(conn->me.sin_port));
1416 storeAppendPrintf(s, "\tnrequests: %d\n",
1417 conn->nrequests);
0f1bc304 1418 storeAppendPrintf(s, "\tdefer: n %d, until %d\n",
1419 conn->defer.n, conn->defer.until);
1420 }
1421 storeAppendPrintf(s, "uri %s\n", http->uri);
ba781fe7 1422 storeAppendPrintf(s, "log_type %s\n", log_tags[http->log_type]);
0f1bc304 1423 storeAppendPrintf(s, "out.offset %d, out.size %d\n",
1424 http->out.offset, http->out.size);
1425 storeAppendPrintf(s, "req_sz %d\n", http->req_sz);
1426 e = http->entry;
186477c1 1427 storeAppendPrintf(s, "entry %p/%s\n", e, e ? storeKeyText(e->hash.key) : "N/A");
0f1bc304 1428 e = http->old_entry;
186477c1 1429 storeAppendPrintf(s, "old_entry %p/%s\n", e, e ? storeKeyText(e->hash.key) : "N/A");
0f1bc304 1430 storeAppendPrintf(s, "start %d.%06d (%f seconds ago)\n", http->start.tv_sec,
1431 http->start.tv_usec,
1432 tvSubDsec(http->start, current_time));
1433 storeAppendPrintf(s, "\n");
1434 }
1435}
1436
01aebf31 1437#if STAT_GRAPHS
1438/*
1439 * urgh, i don't like these, but they do cut the amount of code down immensely
1440 */
1441
1442#define GRAPH_PER_MIN(Y) \
1443 for (i=0;i<(N_COUNT_HIST-2);i++) { \
1444 dt = tvSubDsec(CountHist[i].timestamp, CountHist[i+1].timestamp); \
1445 if (dt <= 0.0) \
1446 break; \
1447 storeAppendPrintf(e, "%lu,%0.2f:", \
1448 CountHist[i].timestamp.tv_sec, \
1449 ((CountHist[i].Y - CountHist[i+1].Y) / dt)); \
1450 }
1451
1452#define GRAPH_PER_HOUR(Y) \
1453 for (i=0;i<(N_COUNT_HOUR_HIST-2);i++) { \
1454 dt = tvSubDsec(CountHourHist[i].timestamp, CountHourHist[i+1].timestamp); \
1455 if (dt <= 0.0) \
1456 break; \
1457 storeAppendPrintf(e, "%lu,%0.2f:", \
1458 CountHourHist[i].timestamp.tv_sec, \
1459 ((CountHourHist[i].Y - CountHourHist[i+1].Y) / dt)); \
1460 }
1461
1462#define GRAPH_TITLE(X,Y) storeAppendPrintf(e,"%s\t%s\t",X,Y);
1463#define GRAPH_END storeAppendPrintf(e,"\n");
1464
1465#define GENGRAPH(X,Y,Z) \
1466 GRAPH_TITLE(Y,Z) \
1467 GRAPH_PER_MIN(X) \
1468 GRAPH_PER_HOUR(X) \
1469 GRAPH_END
1470
1471static void
1472statGraphDump(StoreEntry * e)
1473{
1474 int i;
1475 double dt;
1476
1477 GENGRAPH(client_http.requests, "client_http.requests", "Client HTTP requests/sec");
1478 GENGRAPH(client_http.hits, "client_http.hits", "Client HTTP hits/sec");
1479 GENGRAPH(client_http.errors, "client_http.errors", "Client HTTP errors/sec");
1480 GENGRAPH(client_http.kbytes_in.kb, "client_http.kbytes_in", "Client HTTP kbytes_in/sec");
1481 GENGRAPH(client_http.kbytes_out.kb, "client_http.kbytes_out", "Client HTTP kbytes_out/sec");
1482
1483 /* XXX todo: http median service times */
1484
1485 GENGRAPH(server.all.requests, "server.all.requests", "Server requests/sec");
1486 GENGRAPH(server.all.errors, "server.all.errors", "Server errors/sec");
1487 GENGRAPH(server.all.kbytes_in.kb, "server.all.kbytes_in", "Server total kbytes_in/sec");
1488 GENGRAPH(server.all.kbytes_out.kb, "server.all.kbytes_out", "Server total kbytes_out/sec");
1489
1490 GENGRAPH(server.http.requests, "server.http.requests", "Server HTTP requests/sec");
1491 GENGRAPH(server.http.errors, "server.http.errors", "Server HTTP errors/sec");
1492 GENGRAPH(server.http.kbytes_in.kb, "server.http.kbytes_in", "Server HTTP kbytes_in/sec");
1493 GENGRAPH(server.http.kbytes_out.kb, "server.http.kbytes_out", "Server HTTP kbytes_out/sec");
1494
1495 GENGRAPH(server.ftp.requests, "server.ftp.requests", "Server FTP requests/sec");
1496 GENGRAPH(server.ftp.errors, "server.ftp.errors", "Server FTP errors/sec");
1497 GENGRAPH(server.ftp.kbytes_in.kb, "server.ftp.kbytes_in", "Server FTP kbytes_in/sec");
1498 GENGRAPH(server.ftp.kbytes_out.kb, "server.ftp.kbytes_out", "Server FTP kbytes_out/sec");
1499
1500 GENGRAPH(server.other.requests, "server.other.requests", "Server other requests/sec");
1501 GENGRAPH(server.other.errors, "server.other.errors", "Server other errors/sec");
1502 GENGRAPH(server.other.kbytes_in.kb, "server.other.kbytes_in", "Server other kbytes_in/sec");
1503 GENGRAPH(server.other.kbytes_out.kb, "server.other.kbytes_out", "Server other kbytes_out/sec");
1504
1505 GENGRAPH(icp.pkts_sent, "icp.pkts_sent", "ICP packets sent/sec");
1506 GENGRAPH(icp.pkts_recv, "icp.pkts_recv", "ICP packets received/sec");
1507 GENGRAPH(icp.kbytes_sent.kb, "icp.kbytes_sent", "ICP kbytes_sent/sec");
1508 GENGRAPH(icp.kbytes_recv.kb, "icp.kbytes_recv", "ICP kbytes_received/sec");
1509
1510 /* XXX todo: icp median service times */
1511 /* XXX todo: dns median service times */
1512
1513 GENGRAPH(unlink.requests, "unlink.requests", "Cache File unlink requests/sec");
1514 GENGRAPH(page_faults, "page_faults", "System Page Faults/sec");
1515 GENGRAPH(select_loops, "select_loops", "System Select Loop calls/sec");
1516 GENGRAPH(cputime, "cputime", "CPU utilisation");
1517}
1afe05c5 1518
01aebf31 1519#endif /* STAT_GRAPHS */