]> git.ipfire.org Git - thirdparty/squid.git/blame - src/stat.cc
Break out the comm code into a more "modular" format - poll code
[thirdparty/squid.git] / src / stat.cc
CommitLineData
e5f6c5c2 1
30a4f2a8 2/*
1b3db6d9 3 * $Id: stat.cc,v 1.352 2001/12/24 15:33:44 adrian 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;
72711e31 348 state = cbdataAlloc(StatObjectsState);
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",
2d72d4fd 595 statMemoryAccounted() >> 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
1b3db6d9 804#if USE_POLL
886f2785 805 storeAppendPrintf(sentry, "syscalls.polls = %f/sec\n", XAVG(syscalls.polls));
1b3db6d9 806#endif
807#if USE_SELECT
886f2785 808 storeAppendPrintf(sentry, "syscalls.selects = %f/sec\n", XAVG(syscalls.selects));
809#endif
810 storeAppendPrintf(sentry, "syscalls.disk.opens = %f/sec\n", XAVG(syscalls.disk.opens));
811 storeAppendPrintf(sentry, "syscalls.disk.closes = %f/sec\n", XAVG(syscalls.disk.closes));
812 storeAppendPrintf(sentry, "syscalls.disk.reads = %f/sec\n", XAVG(syscalls.disk.reads));
813 storeAppendPrintf(sentry, "syscalls.disk.writes = %f/sec\n", XAVG(syscalls.disk.writes));
814 storeAppendPrintf(sentry, "syscalls.disk.seeks = %f/sec\n", XAVG(syscalls.disk.seeks));
bfae3379 815 storeAppendPrintf(sentry, "syscalls.disk.unlinks = %f/sec\n", XAVG(syscalls.disk.unlinks));
886f2785 816 storeAppendPrintf(sentry, "syscalls.sock.accepts = %f/sec\n", XAVG(syscalls.sock.accepts));
817 storeAppendPrintf(sentry, "syscalls.sock.sockets = %f/sec\n", XAVG(syscalls.sock.sockets));
818 storeAppendPrintf(sentry, "syscalls.sock.connects = %f/sec\n", XAVG(syscalls.sock.connects));
819 storeAppendPrintf(sentry, "syscalls.sock.binds = %f/sec\n", XAVG(syscalls.sock.binds));
820 storeAppendPrintf(sentry, "syscalls.sock.closes = %f/sec\n", XAVG(syscalls.sock.closes));
821 storeAppendPrintf(sentry, "syscalls.sock.reads = %f/sec\n", XAVG(syscalls.sock.reads));
822 storeAppendPrintf(sentry, "syscalls.sock.writes = %f/sec\n", XAVG(syscalls.sock.writes));
823 storeAppendPrintf(sentry, "syscalls.sock.recvfroms = %f/sec\n", XAVG(syscalls.sock.recvfroms));
824 storeAppendPrintf(sentry, "syscalls.sock.sendtos = %f/sec\n", XAVG(syscalls.sock.sendtos));
825
a7c05555 826 storeAppendPrintf(sentry, "cpu_time = %f seconds\n", ct);
827 storeAppendPrintf(sentry, "wall_time = %f seconds\n", dt);
0e473d70 828 storeAppendPrintf(sentry, "cpu_usage = %f%%\n", dpercent(ct, dt));
090089c4 829}
830
979533fa 831
b8d8561b 832void
a7c05555 833statInit(void)
090089c4 834{
090089c4 835 int i;
a7c05555 836 debug(18, 5) ("statInit: Initializing...\n");
28c60158 837 CBDATA_INIT_TYPE(StatObjectsState);
0e473d70 838 for (i = 0; i < N_COUNT_HIST; i++)
12cf1be2 839 statCountersInit(&CountHist[i]);
a0f32775 840 for (i = 0; i < N_COUNT_HOUR_HIST; i++)
841 statCountersInit(&CountHourHist[i]);
83704487 842 statCountersInit(&statCounter);
52040193 843 eventAdd("statAvgTick", statAvgTick, NULL, (double) COUNT_INTERVAL, 1);
22f3fd98 844 cachemgrRegister("info",
845 "General Runtime Information",
1da3b90b 846 info_get, 0, 1);
22f3fd98 847 cachemgrRegister("filedescriptors",
848 "Process Filedescriptor Allocation",
1da3b90b 849 statFiledescriptors, 0, 1);
22f3fd98 850 cachemgrRegister("objects",
851 "All Cache Objects",
1da3b90b 852 stat_objects_get, 0, 0);
22f3fd98 853 cachemgrRegister("vm_objects",
854 "In-Memory and In-Transit Objects",
1da3b90b 855 stat_vmobjects_get, 0, 0);
ae94d28e 856#if DEBUG_OPENFD
857 cachemgrRegister("openfd_objects",
858 "Objects with Swapout files open",
1da3b90b 859 statOpenfdObj, 0, 0);
ae94d28e 860#endif
22f3fd98 861 cachemgrRegister("io",
862 "Server-side network read() size histograms",
1da3b90b 863 stat_io_get, 0, 1);
22f3fd98 864 cachemgrRegister("counters",
865 "Traffic and Resource Counters",
1da3b90b 866 statCountersDump, 0, 1);
a1e927f6 867 cachemgrRegister("peer_select",
868 "Peer Selection Algorithms",
1da3b90b 869 statPeerSelect, 0, 1);
26b164ac 870 cachemgrRegister("digest_stats",
871 "Cache Digest and ICP blob",
1da3b90b 872 statDigestBlob, 0, 1);
22f3fd98 873 cachemgrRegister("5min",
874 "5 Minute Average of Counters",
1da3b90b 875 statAvg5min, 0, 1);
45eb7f49 876 cachemgrRegister("60min",
877 "60 Minute Average of Counters",
1da3b90b 878 statAvg60min, 0, 1);
e9b5ead4 879 cachemgrRegister("utilization",
880 "Cache Utilization",
1da3b90b 881 statUtilization, 0, 1);
01aebf31 882#if STAT_GRAPHS
883 cachemgrRegister("graph_variables",
884 "Display cache metrics graphically",
1da3b90b 885 statGraphDump, 0, 1);
01aebf31 886#endif
ba4f8e5a 887 cachemgrRegister("histograms",
888 "Full Histogram Counts",
1da3b90b 889 statCountersHistograms, 0, 1);
0f1bc304 890 ClientActiveRequests.head = NULL;
891 ClientActiveRequests.tail = NULL;
892 cachemgrRegister("active_requests",
893 "Client-side Active Requests",
894 statClientRequests, 0, 1);
090089c4 895}
f2908497 896
f2908497 897static void
898statAvgTick(void *notused)
899{
d5649d9f 900 StatCounters *t = &CountHist[0];
901 StatCounters *p = &CountHist[1];
83704487 902 StatCounters *c = &statCounter;
f2908497 903 struct rusage rusage;
b6a2f15e 904 eventAdd("statAvgTick", statAvgTick, NULL, (double) COUNT_INTERVAL, 1);
20903cac 905 squid_getrusage(&rusage);
906 c->page_faults = rusage_pagefaults(&rusage);
907 c->cputime = rusage_cputime(&rusage);
d5649d9f 908 c->timestamp = current_time;
12cf1be2 909 /* even if NCountHist is small, we already Init()ed the tail */
2ac76861 910 statCountersClean(CountHist + N_COUNT_HIST - 1);
dbfed404 911 xmemmove(p, t, (N_COUNT_HIST - 1) * sizeof(StatCounters));
12cf1be2 912 statCountersCopy(t, c);
d5649d9f 913 NCountHist++;
a0f32775 914
915 if ((NCountHist % COUNT_INTERVAL) == 0) {
916 /* we have an hours worth of readings. store previous hour */
ffb245b5 917 StatCounters *t = &CountHourHist[0];
918 StatCounters *p = &CountHourHist[1];
e82d6d21 919 StatCounters *c = &CountHist[N_COUNT_HIST - 1];
ffb245b5 920 statCountersClean(CountHourHist + N_COUNT_HOUR_HIST - 1);
a0f32775 921 xmemmove(p, t, (N_COUNT_HOUR_HIST - 1) * sizeof(StatCounters));
a887b8fa 922 statCountersCopy(t, c);
a0f32775 923 NCountHourHist++;
924 }
b8a46de0 925 if (Config.warnings.high_rptm > 0) {
7fb4e2d1 926 int i = (int) statMedianSvc(20, MEDIAN_HTTP);
b8a46de0 927 if (Config.warnings.high_rptm < i)
928 debug(18, 0) ("WARNING: Median response time is %d milliseconds\n", i);
929 }
930 if (Config.warnings.high_pf) {
931 int i = (CountHist[0].page_faults - CountHist[1].page_faults);
932 double dt = tvSubDsec(CountHist[0].timestamp, CountHist[1].timestamp);
16516f66 933 if (i > 0 && dt > 0.0) {
b8a46de0 934 i /= (int) dt;
16516f66 935 if (Config.warnings.high_pf < i)
936 debug(18, 0) ("WARNING: Page faults occuring at %d/sec\n", i);
937 }
b8a46de0 938 }
939 if (Config.warnings.high_memory) {
940 int i = 0;
941#if HAVE_MSTATS && HAVE_GNUMALLOC_H
942 struct mstats ms = mstats();
943 i = ms.bytes_total;
944#elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
945 struct mallinfo mp = mallinfo();
946 i = mp.arena;
947#endif
2a5a6521 948 if (Config.warnings.high_memory < i)
b8a46de0 949 debug(18, 0) ("WARNING: Memory usage at %d MB\n", i >> 20);
950 }
20903cac 951}
952
12cf1be2 953static void
2ac76861 954statCountersInit(StatCounters * C)
20903cac 955{
12cf1be2 956 assert(C);
1d803566 957 memset(C, 0, sizeof(*C));
12cf1be2 958 C->timestamp = current_time;
1d803566 959 statCountersInitSpecial(C);
960}
961
962/* add special cases here as they arrive */
963static void
2ac76861 964statCountersInitSpecial(StatCounters * C)
1d803566 965{
12cf1be2 966 /*
967 * HTTP svc_time hist is kept in milli-seconds; max of 3 hours.
968 */
969 statHistLogInit(&C->client_http.all_svc_time, 300, 0.0, 3600000.0 * 3.0);
970 statHistLogInit(&C->client_http.miss_svc_time, 300, 0.0, 3600000.0 * 3.0);
971 statHistLogInit(&C->client_http.nm_svc_time, 300, 0.0, 3600000.0 * 3.0);
7c9c84ad 972 statHistLogInit(&C->client_http.nh_svc_time, 300, 0.0, 3600000.0 * 3.0);
12cf1be2 973 statHistLogInit(&C->client_http.hit_svc_time, 300, 0.0, 3600000.0 * 3.0);
974 /*
975 * ICP svc_time hist is kept in micro-seconds; max of 1 minute.
976 */
977 statHistLogInit(&C->icp.query_svc_time, 300, 0.0, 1000000.0 * 60.0);
978 statHistLogInit(&C->icp.reply_svc_time, 300, 0.0, 1000000.0 * 60.0);
979 /*
980 * DNS svc_time hist is kept in milli-seconds; max of 10 minutes.
981 */
982 statHistLogInit(&C->dns.svc_time, 300, 0.0, 60000.0 * 10.0);
a1e927f6 983 /*
69c95dd3 984 * Cache Digest Stuff
a1e927f6 985 */
0c511722 986 statHistEnumInit(&C->cd.on_xition_count, CacheDigestHashFuncCount);
c6ecdbc3 987 statHistEnumInit(&C->comm_icp_incoming, INCOMING_ICP_MAX);
ef523f99 988 statHistEnumInit(&C->comm_dns_incoming, INCOMING_DNS_MAX);
c6ecdbc3 989 statHistEnumInit(&C->comm_http_incoming, INCOMING_HTTP_MAX);
b671cc68 990 statHistIntInit(&C->select_fds_hist, 256); /* was SQUID_MAXFD, but it is way too much. It is OK to crop this statistics */
0f5607d9 991}
992
12cf1be2 993/* add special cases here as they arrive */
5e29a294 994static void
2ac76861 995statCountersClean(StatCounters * C)
0f5607d9 996{
12cf1be2 997 assert(C);
998 statHistClean(&C->client_http.all_svc_time);
999 statHistClean(&C->client_http.miss_svc_time);
1000 statHistClean(&C->client_http.nm_svc_time);
7c9c84ad 1001 statHistClean(&C->client_http.nh_svc_time);
12cf1be2 1002 statHistClean(&C->client_http.hit_svc_time);
1003 statHistClean(&C->icp.query_svc_time);
1004 statHistClean(&C->icp.reply_svc_time);
1005 statHistClean(&C->dns.svc_time);
c135694e 1006 statHistClean(&C->cd.on_xition_count);
c6ecdbc3 1007 statHistClean(&C->comm_icp_incoming);
a56906d4 1008 statHistClean(&C->comm_dns_incoming);
c6ecdbc3 1009 statHistClean(&C->comm_http_incoming);
26d6ee93 1010 statHistClean(&C->select_fds_hist);
a7c05555 1011}
1012
12cf1be2 1013/* add special cases here as they arrive */
5e29a294 1014static void
2ac76861 1015statCountersCopy(StatCounters * dest, const StatCounters * orig)
45eb7f49 1016{
12cf1be2 1017 assert(dest && orig);
1d803566 1018 /* this should take care of all the fields, but "special" ones */
cac03dd2 1019 xmemcpy(dest, orig, sizeof(*dest));
1d803566 1020 /* prepare space where to copy special entries */
1021 statCountersInitSpecial(dest);
1022 /* now handle special cases */
1023 /* note: we assert that histogram capacities do not change */
12cf1be2 1024 statHistCopy(&dest->client_http.all_svc_time, &orig->client_http.all_svc_time);
1025 statHistCopy(&dest->client_http.miss_svc_time, &orig->client_http.miss_svc_time);
1026 statHistCopy(&dest->client_http.nm_svc_time, &orig->client_http.nm_svc_time);
7c9c84ad 1027 statHistCopy(&dest->client_http.nh_svc_time, &orig->client_http.nh_svc_time);
12cf1be2 1028 statHistCopy(&dest->client_http.hit_svc_time, &orig->client_http.hit_svc_time);
1029 statHistCopy(&dest->icp.query_svc_time, &orig->icp.query_svc_time);
1030 statHistCopy(&dest->icp.reply_svc_time, &orig->icp.reply_svc_time);
1031 statHistCopy(&dest->dns.svc_time, &orig->dns.svc_time);
c135694e 1032 statHistCopy(&dest->cd.on_xition_count, &orig->cd.on_xition_count);
c6ecdbc3 1033 statHistCopy(&dest->comm_icp_incoming, &orig->comm_icp_incoming);
1034 statHistCopy(&dest->comm_http_incoming, &orig->comm_http_incoming);
26d6ee93 1035 statHistCopy(&dest->select_fds_hist, &orig->select_fds_hist);
45eb7f49 1036}
1037
071a3ae7 1038static void
5d406e78 1039statCountersHistograms(StoreEntry * sentry)
071a3ae7 1040{
83704487 1041 StatCounters *f = &statCounter;
071a3ae7 1042 storeAppendPrintf(sentry, "client_http.all_svc_time histogram:\n");
1043 statHistDump(&f->client_http.all_svc_time, sentry, NULL);
1044 storeAppendPrintf(sentry, "client_http.miss_svc_time histogram:\n");
1045 statHistDump(&f->client_http.miss_svc_time, sentry, NULL);
1046 storeAppendPrintf(sentry, "client_http.nm_svc_time histogram:\n");
1047 statHistDump(&f->client_http.nm_svc_time, sentry, NULL);
7c9c84ad 1048 storeAppendPrintf(sentry, "client_http.nh_svc_time histogram:\n");
1049 statHistDump(&f->client_http.nh_svc_time, sentry, NULL);
071a3ae7 1050 storeAppendPrintf(sentry, "client_http.hit_svc_time histogram:\n");
1051 statHistDump(&f->client_http.hit_svc_time, sentry, NULL);
071a3ae7 1052 storeAppendPrintf(sentry, "icp.query_svc_time histogram:\n");
1053 statHistDump(&f->icp.query_svc_time, sentry, NULL);
1054 storeAppendPrintf(sentry, "icp.reply_svc_time histogram:\n");
1055 statHistDump(&f->icp.reply_svc_time, sentry, NULL);
1056 storeAppendPrintf(sentry, "dns.svc_time histogram:\n");
1057 statHistDump(&f->dns.svc_time, sentry, NULL);
071a3ae7 1058}
1059
12cf1be2 1060static void
1061statCountersDump(StoreEntry * sentry)
7ae52c25 1062{
83704487 1063 StatCounters *f = &statCounter;
12cf1be2 1064 struct rusage rusage;
1065 squid_getrusage(&rusage);
1066 f->page_faults = rusage_pagefaults(&rusage);
1067 f->cputime = rusage_cputime(&rusage);
1068
a0f32775 1069 storeAppendPrintf(sentry, "sample_time = %d.%d (%s)\n",
5f6ac48b 1070 (int) f->timestamp.tv_sec,
1071 (int) f->timestamp.tv_usec,
a0f32775 1072 mkrfc1123(f->timestamp.tv_sec));
12cf1be2 1073 storeAppendPrintf(sentry, "client_http.requests = %d\n",
1074 f->client_http.requests);
1075 storeAppendPrintf(sentry, "client_http.hits = %d\n",
1076 f->client_http.hits);
1077 storeAppendPrintf(sentry, "client_http.errors = %d\n",
1078 f->client_http.errors);
1079 storeAppendPrintf(sentry, "client_http.kbytes_in = %d\n",
1080 (int) f->client_http.kbytes_in.kb);
1081 storeAppendPrintf(sentry, "client_http.kbytes_out = %d\n",
1082 (int) f->client_http.kbytes_out.kb);
c68e9c6b 1083 storeAppendPrintf(sentry, "client_http.hit_kbytes_out = %d\n",
1084 (int) f->client_http.hit_kbytes_out.kb);
0567f2a6 1085
a0f32775 1086 storeAppendPrintf(sentry, "server.all.requests = %d\n",
1087 (int) f->server.all.requests);
1088 storeAppendPrintf(sentry, "server.all.errors = %d\n",
1089 (int) f->server.all.errors);
1090 storeAppendPrintf(sentry, "server.all.kbytes_in = %d\n",
1091 (int) f->server.all.kbytes_in.kb);
1092 storeAppendPrintf(sentry, "server.all.kbytes_out = %d\n",
1093 (int) f->server.all.kbytes_out.kb);
1094
1095 storeAppendPrintf(sentry, "server.http.requests = %d\n",
1096 (int) f->server.http.requests);
1097 storeAppendPrintf(sentry, "server.http.errors = %d\n",
1098 (int) f->server.http.errors);
1099 storeAppendPrintf(sentry, "server.http.kbytes_in = %d\n",
1100 (int) f->server.http.kbytes_in.kb);
1101 storeAppendPrintf(sentry, "server.http.kbytes_out = %d\n",
1102 (int) f->server.http.kbytes_out.kb);
1103
1104 storeAppendPrintf(sentry, "server.ftp.requests = %d\n",
1105 (int) f->server.ftp.requests);
1106 storeAppendPrintf(sentry, "server.ftp.errors = %d\n",
1107 (int) f->server.ftp.errors);
1108 storeAppendPrintf(sentry, "server.ftp.kbytes_in = %d\n",
1109 (int) f->server.ftp.kbytes_in.kb);
1110 storeAppendPrintf(sentry, "server.ftp.kbytes_out = %d\n",
1111 (int) f->server.ftp.kbytes_out.kb);
1112
1113 storeAppendPrintf(sentry, "server.other.requests = %d\n",
1114 (int) f->server.other.requests);
1115 storeAppendPrintf(sentry, "server.other.errors = %d\n",
1116 (int) f->server.other.errors);
1117 storeAppendPrintf(sentry, "server.other.kbytes_in = %d\n",
1118 (int) f->server.other.kbytes_in.kb);
1119 storeAppendPrintf(sentry, "server.other.kbytes_out = %d\n",
1120 (int) f->server.other.kbytes_out.kb);
12cf1be2 1121
1122 storeAppendPrintf(sentry, "icp.pkts_sent = %d\n",
1123 f->icp.pkts_sent);
1124 storeAppendPrintf(sentry, "icp.pkts_recv = %d\n",
1125 f->icp.pkts_recv);
071a3ae7 1126 storeAppendPrintf(sentry, "icp.queries_sent = %d\n",
1127 f->icp.queries_sent);
1128 storeAppendPrintf(sentry, "icp.replies_sent = %d\n",
1129 f->icp.replies_sent);
1130 storeAppendPrintf(sentry, "icp.queries_recv = %d\n",
1131 f->icp.queries_recv);
1132 storeAppendPrintf(sentry, "icp.replies_recv = %d\n",
1133 f->icp.replies_recv);
1134 storeAppendPrintf(sentry, "icp.query_timeouts = %d\n",
1135 f->icp.query_timeouts);
2e8e29b8 1136 storeAppendPrintf(sentry, "icp.replies_queued = %d\n",
1137 f->icp.replies_queued);
12cf1be2 1138 storeAppendPrintf(sentry, "icp.kbytes_sent = %d\n",
1139 (int) f->icp.kbytes_sent.kb);
1140 storeAppendPrintf(sentry, "icp.kbytes_recv = %d\n",
1141 (int) f->icp.kbytes_recv.kb);
071a3ae7 1142 storeAppendPrintf(sentry, "icp.q_kbytes_sent = %d\n",
1143 (int) f->icp.q_kbytes_sent.kb);
1144 storeAppendPrintf(sentry, "icp.r_kbytes_sent = %d\n",
1145 (int) f->icp.r_kbytes_sent.kb);
1146 storeAppendPrintf(sentry, "icp.q_kbytes_recv = %d\n",
1147 (int) f->icp.q_kbytes_recv.kb);
1148 storeAppendPrintf(sentry, "icp.r_kbytes_recv = %d\n",
1149 (int) f->icp.r_kbytes_recv.kb);
0567f2a6 1150
6cfa8966 1151#if USE_CACHE_DIGESTS
071a3ae7 1152 storeAppendPrintf(sentry, "icp.times_used = %d\n",
5d406e78 1153 f->icp.times_used);
071a3ae7 1154 storeAppendPrintf(sentry, "cd.times_used = %d\n",
5d406e78 1155 f->cd.times_used);
00485c29 1156 storeAppendPrintf(sentry, "cd.msgs_sent = %d\n",
1157 f->cd.msgs_sent);
1158 storeAppendPrintf(sentry, "cd.msgs_recv = %d\n",
1159 f->cd.msgs_recv);
071a3ae7 1160 storeAppendPrintf(sentry, "cd.memory = %d\n",
5d406e78 1161 (int) f->cd.memory.kb);
522b517b 1162 storeAppendPrintf(sentry, "cd.local_memory = %d\n",
5d406e78 1163 (int) (store_digest ? store_digest->mask_size / 1024 : 0));
00485c29 1164 storeAppendPrintf(sentry, "cd.kbytes_sent = %d\n",
1165 (int) f->cd.kbytes_sent.kb);
1166 storeAppendPrintf(sentry, "cd.kbytes_recv = %d\n",
1167 (int) f->cd.kbytes_recv.kb);
0567f2a6 1168#endif
1169
12cf1be2 1170 storeAppendPrintf(sentry, "unlink.requests = %d\n",
1171 f->unlink.requests);
1172 storeAppendPrintf(sentry, "page_faults = %d\n",
1173 f->page_faults);
1174 storeAppendPrintf(sentry, "select_loops = %d\n",
1175 f->select_loops);
1176 storeAppendPrintf(sentry, "cpu_time = %f\n",
1177 f->cputime);
1178 storeAppendPrintf(sentry, "wall_time = %f\n",
1179 tvSubDsec(f->timestamp, current_time));
23dc8aca 1180 storeAppendPrintf(sentry, "swap.outs = %d\n",
1181 f->swap.outs);
1182 storeAppendPrintf(sentry, "swap.ins = %d\n",
1183 f->swap.ins);
1184 storeAppendPrintf(sentry, "swap.files_cleaned = %d\n",
1185 f->swap.files_cleaned);
bfae3379 1186 storeAppendPrintf(sentry, "aborted_requests = %d\n",
1187 f->aborted_requests);
7ae52c25 1188}
1189
d2db411c 1190void
1191statFreeMemory(void)
1192{
1193 int i;
1194 for (i = 0; i < N_COUNT_HIST; i++)
1195 statCountersClean(&CountHist[i]);
1196 for (i = 0; i < N_COUNT_HOUR_HIST; i++)
1197 statCountersClean(&CountHourHist[i]);
1198}
1199
5e29a294 1200static void
a1e927f6 1201statPeerSelect(StoreEntry * sentry)
1202{
6cfa8966 1203#if USE_CACHE_DIGESTS
83704487 1204 StatCounters *f = &statCounter;
a1e927f6 1205 peer *peer;
1206 const int tot_used = f->cd.times_used + f->icp.times_used;
1207
1208 /* totals */
1209 cacheDigestGuessStatsReport(&f->cd.guess, sentry, "all peers");
1210 /* per-peer */
1211 storeAppendPrintf(sentry, "\nPer-peer statistics:\n");
1212 for (peer = getFirstPeer(); peer; peer = getNextPeer(peer)) {
e13ee7ad 1213 if (peer->digest)
1214 peerDigestStatsReport(peer->digest, sentry);
1543ab6c 1215 else
e13ee7ad 1216 storeAppendPrintf(sentry, "\nNo peer digest from %s\n", peer->host);
7ea5d333 1217 storeAppendPrintf(sentry, "\n");
a1e927f6 1218 }
1219
1220 storeAppendPrintf(sentry, "\nAlgorithm usage:\n");
1221 storeAppendPrintf(sentry, "Cache Digest: %7d (%3d%%)\n",
1222 f->cd.times_used, xpercentInt(f->cd.times_used, tot_used));
1223 storeAppendPrintf(sentry, "Icp: %7d (%3d%%)\n",
1224 f->icp.times_used, xpercentInt(f->icp.times_used, tot_used));
1225 storeAppendPrintf(sentry, "Total: %7d (%3d%%)\n",
1226 tot_used, xpercentInt(tot_used, tot_used));
1227#else
1228 storeAppendPrintf(sentry, "peer digests are disabled; no stats is available.\n");
1229#endif
1230}
1231
1232static void
26b164ac 1233statDigestBlob(StoreEntry * sentry)
1234{
071a3ae7 1235 storeAppendPrintf(sentry, "\nCounters:\n");
1236 statCountersDump(sentry);
86e2a291 1237 storeAppendPrintf(sentry, "\n5 Min Averages:\n");
1238 statAvgDump(sentry, 5, 0);
071a3ae7 1239 storeAppendPrintf(sentry, "\nHistograms:\n");
1240 statCountersHistograms(sentry);
1241 storeAppendPrintf(sentry, "\nPeer Digests:\n");
26b164ac 1242 statPeerSelect(sentry);
588d9545 1243 storeAppendPrintf(sentry, "\nLocal Digest:\n");
26b164ac 1244 storeDigestReport(sentry);
1245}
1246
5e29a294 1247static void
12cf1be2 1248statAvg5min(StoreEntry * e)
7ae52c25 1249{
a0f32775 1250 statAvgDump(e, 5, 0);
7ae52c25 1251}
1252
5e29a294 1253static void
12cf1be2 1254statAvg60min(StoreEntry * e)
7ae52c25 1255{
a0f32775 1256 statAvgDump(e, 60, 0);
7ae52c25 1257}
1258
7d94ae33 1259static double
b87b92fb 1260statMedianSvc(int interval, int which)
a9113eb0 1261{
1262 StatCounters *f;
1263 StatCounters *l;
1264 double x;
f8d264b8 1265 assert(interval > 0);
1266 if (interval > N_COUNT_HIST - 1)
1267 interval = N_COUNT_HIST - 1;
a9113eb0 1268 f = &CountHist[0];
1269 l = &CountHist[interval];
ee1679df 1270 assert(f);
1271 assert(l);
a9113eb0 1272 switch (which) {
b87b92fb 1273 case MEDIAN_HTTP:
12cf1be2 1274 x = statHistDeltaMedian(&l->client_http.all_svc_time, &f->client_http.all_svc_time);
ee1679df 1275 break;
b87b92fb 1276 case MEDIAN_HIT:
1277 x = statHistDeltaMedian(&l->client_http.hit_svc_time, &f->client_http.hit_svc_time);
1278 break;
1279 case MEDIAN_MISS:
1280 x = statHistDeltaMedian(&l->client_http.miss_svc_time, &f->client_http.miss_svc_time);
1281 break;
1282 case MEDIAN_NM:
1283 x = statHistDeltaMedian(&l->client_http.nm_svc_time, &f->client_http.nm_svc_time);
1284 break;
7c9c84ad 1285 case MEDIAN_NH:
1286 x = statHistDeltaMedian(&l->client_http.nh_svc_time, &f->client_http.nh_svc_time);
1287 break;
b87b92fb 1288 case MEDIAN_ICP_QUERY:
12cf1be2 1289 x = statHistDeltaMedian(&l->icp.query_svc_time, &f->icp.query_svc_time);
ee1679df 1290 break;
b87b92fb 1291 case MEDIAN_DNS:
12cf1be2 1292 x = statHistDeltaMedian(&l->dns.svc_time, &f->dns.svc_time);
ee1679df 1293 break;
a9113eb0 1294 default:
ee1679df 1295 debug(49, 5) ("get_median_val: unknown type.\n");
1296 x = 0;
a9113eb0 1297 }
b87b92fb 1298 return x;
1299}
1300
1301/*
1302 * SNMP wants ints, ick
1303 */
2d72d4fd 1304#if UNUSED_CODE
b87b92fb 1305int
1306get_median_svc(int interval, int which)
1307{
b644367b 1308 return (int) statMedianSvc(interval, which);
a9113eb0 1309}
451b07c5 1310
2d72d4fd 1311#endif
1312
451b07c5 1313StatCounters *
1314snmpStatGet(int minutes)
1315{
2ac76861 1316 return &CountHist[minutes];
451b07c5 1317}
01aebf31 1318
1f3c4622 1319int
1320stat5minClientRequests(void)
1321{
5999b776 1322 assert(N_COUNT_HIST > 5);
83704487 1323 return statCounter.client_http.requests - CountHist[5].client_http.requests;
1f3c4622 1324}
1325
49ad0a8c 1326static double
1327statCPUUsage(int minutes)
979533fa 1328{
49ad0a8c 1329 assert(minutes < N_COUNT_HIST);
1330 return dpercent(CountHist[0].cputime - CountHist[minutes].cputime,
1331 tvSubDsec(CountHist[minutes].timestamp, CountHist[0].timestamp));
979533fa 1332}
01aebf31 1333
1d5b6d43 1334extern double
491a980b 1335statRequestHitRatio(int minutes)
1336{
1337 assert(minutes < N_COUNT_HIST);
1338 return dpercent(CountHist[0].client_http.hits -
1339 CountHist[minutes].client_http.hits,
1340 CountHist[0].client_http.requests -
1341 CountHist[minutes].client_http.requests);
1342}
1343
4f4d1d6e 1344extern double
1345statRequestHitMemoryRatio(int minutes)
1346{
1347 assert(minutes < N_COUNT_HIST);
1348 return dpercent(CountHist[0].client_http.mem_hits -
1349 CountHist[minutes].client_http.mem_hits,
1350 CountHist[0].client_http.hits -
1351 CountHist[minutes].client_http.hits);
1352}
1353
1354extern double
1355statRequestHitDiskRatio(int minutes)
1356{
1357 assert(minutes < N_COUNT_HIST);
1358 return dpercent(CountHist[0].client_http.disk_hits -
1359 CountHist[minutes].client_http.disk_hits,
1360 CountHist[0].client_http.hits -
1361 CountHist[minutes].client_http.hits);
1362}
1363
1d5b6d43 1364extern double
491a980b 1365statByteHitRatio(int minutes)
1366{
1367 size_t s;
1368 size_t c;
ac342231 1369#if USE_CACHE_DIGESTS
1370 size_t cd;
1371#endif
1372 /* size_t might be unsigned */
491a980b 1373 assert(minutes < N_COUNT_HIST);
1374 c = CountHist[0].client_http.kbytes_out.kb - CountHist[minutes].client_http.kbytes_out.kb;
1375 s = CountHist[0].server.all.kbytes_in.kb - CountHist[minutes].server.all.kbytes_in.kb;
ac342231 1376#if USE_CACHE_DIGESTS
1377 /*
1378 * This ugly hack is here to prevent the user from seeing a
1379 * negative byte hit ratio. When we fetch a cache digest from
1380 * a neighbor, it gets treated like a cache miss because the
1381 * object is consumed internally. Thus, we subtract cache
1382 * digest bytes out before calculating the byte hit ratio.
1383 */
1384 cd = CountHist[0].cd.kbytes_recv.kb - CountHist[minutes].cd.kbytes_recv.kb;
49d7ce5f 1385 if (s < cd)
1386 debug(18, 1) ("STRANGE: srv_kbytes=%d, cd_kbytes=%d\n", s, cd);
ac342231 1387 s -= cd;
1388#endif
94e56ef7 1389 if (c > s)
7d47d8e6 1390 return dpercent(c - s, c);
94e56ef7 1391 else
7d47d8e6 1392 return (-1.0 * dpercent(s - c, c));
491a980b 1393}
1394
0f1bc304 1395static void
1396statClientRequests(StoreEntry * s)
1397{
1398 dlink_node *i;
1399 clientHttpRequest *http;
1400 ConnStateData *conn;
1401 StoreEntry *e;
1402 int fd;
1403 for (i = ClientActiveRequests.head; i; i = i->next) {
1404 http = i->data;
1405 assert(http);
1406 conn = http->conn;
1407 storeAppendPrintf(s, "Connection: %p\n", conn);
1408 if (conn) {
1409 fd = conn->fd;
1410 storeAppendPrintf(s, "\tFD %d, read %d, wrote %d\n", fd,
1411 fd_table[fd].bytes_read, fd_table[fd].bytes_written);
1412 storeAppendPrintf(s, "\tFD desc: %s\n", fd_table[fd].desc);
38650cc8 1413 storeAppendPrintf(s, "\tin: buf %p, offset %ld, size %ld\n",
84f2d773 1414 conn->in.buf, (long int) conn->in.offset, (long int) conn->in.size);
0f1bc304 1415 storeAppendPrintf(s, "\tpeer: %s:%d\n",
1416 inet_ntoa(conn->peer.sin_addr),
1417 ntohs(conn->peer.sin_port));
1418 storeAppendPrintf(s, "\tme: %s:%d\n",
1419 inet_ntoa(conn->me.sin_addr),
1420 ntohs(conn->me.sin_port));
1421 storeAppendPrintf(s, "\tnrequests: %d\n",
1422 conn->nrequests);
38650cc8 1423 storeAppendPrintf(s, "\tdefer: n %d, until %ld\n",
84f2d773 1424 conn->defer.n, (long int) conn->defer.until);
0f1bc304 1425 }
1426 storeAppendPrintf(s, "uri %s\n", http->uri);
ba781fe7 1427 storeAppendPrintf(s, "log_type %s\n", log_tags[http->log_type]);
38650cc8 1428 storeAppendPrintf(s, "out.offset %ld, out.size %lu\n",
84f2d773 1429 (long int) http->out.offset, (unsigned long int) http->out.size);
ed19251a 1430 storeAppendPrintf(s, "req_sz %ld\n", (long int) http->req_sz);
0f1bc304 1431 e = http->entry;
186477c1 1432 storeAppendPrintf(s, "entry %p/%s\n", e, e ? storeKeyText(e->hash.key) : "N/A");
0f1bc304 1433 e = http->old_entry;
186477c1 1434 storeAppendPrintf(s, "old_entry %p/%s\n", e, e ? storeKeyText(e->hash.key) : "N/A");
38650cc8 1435 storeAppendPrintf(s, "start %ld.%06d (%f seconds ago)\n",
84f2d773 1436 (long int) http->start.tv_sec,
1437 (int) http->start.tv_usec,
0f1bc304 1438 tvSubDsec(http->start, current_time));
1439 storeAppendPrintf(s, "\n");
1440 }
1441}
1442
01aebf31 1443#if STAT_GRAPHS
1444/*
1445 * urgh, i don't like these, but they do cut the amount of code down immensely
1446 */
1447
1448#define GRAPH_PER_MIN(Y) \
1449 for (i=0;i<(N_COUNT_HIST-2);i++) { \
1450 dt = tvSubDsec(CountHist[i].timestamp, CountHist[i+1].timestamp); \
1451 if (dt <= 0.0) \
1452 break; \
1453 storeAppendPrintf(e, "%lu,%0.2f:", \
1454 CountHist[i].timestamp.tv_sec, \
1455 ((CountHist[i].Y - CountHist[i+1].Y) / dt)); \
1456 }
1457
1458#define GRAPH_PER_HOUR(Y) \
1459 for (i=0;i<(N_COUNT_HOUR_HIST-2);i++) { \
1460 dt = tvSubDsec(CountHourHist[i].timestamp, CountHourHist[i+1].timestamp); \
1461 if (dt <= 0.0) \
1462 break; \
1463 storeAppendPrintf(e, "%lu,%0.2f:", \
1464 CountHourHist[i].timestamp.tv_sec, \
1465 ((CountHourHist[i].Y - CountHourHist[i+1].Y) / dt)); \
1466 }
1467
1468#define GRAPH_TITLE(X,Y) storeAppendPrintf(e,"%s\t%s\t",X,Y);
1469#define GRAPH_END storeAppendPrintf(e,"\n");
1470
1471#define GENGRAPH(X,Y,Z) \
1472 GRAPH_TITLE(Y,Z) \
1473 GRAPH_PER_MIN(X) \
1474 GRAPH_PER_HOUR(X) \
1475 GRAPH_END
1476
1477static void
1478statGraphDump(StoreEntry * e)
1479{
1480 int i;
1481 double dt;
1482
1483 GENGRAPH(client_http.requests, "client_http.requests", "Client HTTP requests/sec");
1484 GENGRAPH(client_http.hits, "client_http.hits", "Client HTTP hits/sec");
1485 GENGRAPH(client_http.errors, "client_http.errors", "Client HTTP errors/sec");
1486 GENGRAPH(client_http.kbytes_in.kb, "client_http.kbytes_in", "Client HTTP kbytes_in/sec");
1487 GENGRAPH(client_http.kbytes_out.kb, "client_http.kbytes_out", "Client HTTP kbytes_out/sec");
1488
1489 /* XXX todo: http median service times */
1490
1491 GENGRAPH(server.all.requests, "server.all.requests", "Server requests/sec");
1492 GENGRAPH(server.all.errors, "server.all.errors", "Server errors/sec");
1493 GENGRAPH(server.all.kbytes_in.kb, "server.all.kbytes_in", "Server total kbytes_in/sec");
1494 GENGRAPH(server.all.kbytes_out.kb, "server.all.kbytes_out", "Server total kbytes_out/sec");
1495
1496 GENGRAPH(server.http.requests, "server.http.requests", "Server HTTP requests/sec");
1497 GENGRAPH(server.http.errors, "server.http.errors", "Server HTTP errors/sec");
1498 GENGRAPH(server.http.kbytes_in.kb, "server.http.kbytes_in", "Server HTTP kbytes_in/sec");
1499 GENGRAPH(server.http.kbytes_out.kb, "server.http.kbytes_out", "Server HTTP kbytes_out/sec");
1500
1501 GENGRAPH(server.ftp.requests, "server.ftp.requests", "Server FTP requests/sec");
1502 GENGRAPH(server.ftp.errors, "server.ftp.errors", "Server FTP errors/sec");
1503 GENGRAPH(server.ftp.kbytes_in.kb, "server.ftp.kbytes_in", "Server FTP kbytes_in/sec");
1504 GENGRAPH(server.ftp.kbytes_out.kb, "server.ftp.kbytes_out", "Server FTP kbytes_out/sec");
1505
1506 GENGRAPH(server.other.requests, "server.other.requests", "Server other requests/sec");
1507 GENGRAPH(server.other.errors, "server.other.errors", "Server other errors/sec");
1508 GENGRAPH(server.other.kbytes_in.kb, "server.other.kbytes_in", "Server other kbytes_in/sec");
1509 GENGRAPH(server.other.kbytes_out.kb, "server.other.kbytes_out", "Server other kbytes_out/sec");
1510
1511 GENGRAPH(icp.pkts_sent, "icp.pkts_sent", "ICP packets sent/sec");
1512 GENGRAPH(icp.pkts_recv, "icp.pkts_recv", "ICP packets received/sec");
1513 GENGRAPH(icp.kbytes_sent.kb, "icp.kbytes_sent", "ICP kbytes_sent/sec");
1514 GENGRAPH(icp.kbytes_recv.kb, "icp.kbytes_recv", "ICP kbytes_received/sec");
1515
1516 /* XXX todo: icp median service times */
1517 /* XXX todo: dns median service times */
1518
1519 GENGRAPH(unlink.requests, "unlink.requests", "Cache File unlink requests/sec");
1520 GENGRAPH(page_faults, "page_faults", "System Page Faults/sec");
1521 GENGRAPH(select_loops, "select_loops", "System Select Loop calls/sec");
1522 GENGRAPH(cputime, "cputime", "CPU utilisation");
1523}
1afe05c5 1524
2d72d4fd 1525int
1526statMemoryAccounted(void)
1527{
1528 memTotalAllocated();
1529}
1530
01aebf31 1531#endif /* STAT_GRAPHS */