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