]> git.ipfire.org Git - thirdparty/squid.git/blame - src/stat.cc
memory free bug
[thirdparty/squid.git] / src / stat.cc
CommitLineData
e5f6c5c2 1
30a4f2a8 2/*
b23c4568 3 * $Id: stat.cc,v 1.277 1998/08/11 21:53:05 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
15 * Duane Wessels and the University of California San Diego. Please
16 * see the COPYRIGHT file for full details. Squid incorporates
17 * software developed and/or copyrighted by other sources. Please see
18 * 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 *);
50static const char *describeFlags(const StoreEntry *);
51static const char *describeTimestamps(const StoreEntry *);
f2908497 52static void statAvgTick(void *notused);
a0f32775 53static void statAvgDump(StoreEntry *, int minutes, int hours);
01aebf31 54#if STAT_GRAPHS
55static void statGraphDump(StoreEntry *);
56#endif
12cf1be2 57static void statCountersInit(StatCounters *);
1d803566 58static void statCountersInitSpecial(StatCounters *);
12cf1be2 59static void statCountersClean(StatCounters *);
2ac76861 60static void statCountersCopy(StatCounters * dest, const StatCounters * orig);
b87b92fb 61static double statMedianSvc(int, int);
a5a5de87 62static void statStoreEntry(StoreEntry * s, StoreEntry * e);
49ad0a8c 63static double statCPUUsage(int minutes);
ed7f5615 64static OBJH stat_io_get;
65static OBJH stat_objects_get;
66static OBJH stat_vmobjects_get;
ae94d28e 67#if DEBUG_OPENFD
68static OBJH statOpenfdObj;
69#endif
1da3b90b 70static EVH statObjects;
ed7f5615 71static OBJH info_get;
72static OBJH statFiledescriptors;
071a3ae7 73static OBJH statCountersDump;
a1e927f6 74static OBJH statPeerSelect;
26b164ac 75static OBJH statDigestBlob;
ed7f5615 76static OBJH statAvg5min;
45eb7f49 77static OBJH statAvg60min;
e9b5ead4 78static OBJH statUtilization;
ba4f8e5a 79static OBJH statCountersHistograms;
20882fb1 80
20882fb1 81#ifdef XMALLOC_STATISTICS
f5b8bbc4 82static void info_get_mallstat(int, int, StoreEntry *);
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
0ee4272b 200static const char *
fe4e214f 201describeFlags(const StoreEntry * entry)
d1a43e28 202{
203 LOCAL_ARRAY(char, buf, 256);
204 int flags = (int) entry->flag;
205 char *t;
206 buf[0] = '\0';
977c1c5b 207 if (EBIT_TEST(flags, ENTRY_SPECIAL))
208 strcat(buf, "SPECIAL,");
209 if (EBIT_TEST(flags, ENTRY_REVALIDATE))
210 strcat(buf, "REVALIDATE,");
79a15e0a 211 if (EBIT_TEST(flags, DELAY_SENDING))
977c1c5b 212 strcat(buf, "DELAY_SENDING,");
79a15e0a 213 if (EBIT_TEST(flags, RELEASE_REQUEST))
977c1c5b 214 strcat(buf, "RELEASE_REQUEST,");
79a15e0a 215 if (EBIT_TEST(flags, REFRESH_REQUEST))
977c1c5b 216 strcat(buf, "REFRESH_REQUEST,");
79a15e0a 217 if (EBIT_TEST(flags, ENTRY_CACHABLE))
977c1c5b 218 strcat(buf, "CACHABLE,");
79a15e0a 219 if (EBIT_TEST(flags, ENTRY_DISPATCHED))
977c1c5b 220 strcat(buf, "DISPATCHED,");
79a15e0a 221 if (EBIT_TEST(flags, KEY_PRIVATE))
977c1c5b 222 strcat(buf, "PRIVATE,");
79a15e0a 223 if (EBIT_TEST(flags, ENTRY_NEGCACHED))
977c1c5b 224 strcat(buf, "NEGCACHED,");
225 if (EBIT_TEST(flags, ENTRY_VALIDATED))
226 strcat(buf, "VALIDATED,");
227 if (EBIT_TEST(flags, ENTRY_BAD_LENGTH))
228 strcat(buf, "BAD_LENGTH,");
d1a43e28 229 if ((t = strrchr(buf, ',')))
230 *t = '\0';
231 return buf;
232}
233
0ee4272b 234static const char *
fe4e214f 235describeTimestamps(const StoreEntry * entry)
d1a43e28 236{
237 LOCAL_ARRAY(char, buf, 256);
56878878 238 snprintf(buf, 256, "LV:%-9d LU:%-9d LM:%-9d EX:%-9d",
d1a43e28 239 (int) entry->timestamp,
240 (int) entry->lastref,
241 (int) entry->lastmod,
242 (int) entry->expires);
243 return buf;
244}
245
b8d8561b 246static void
a5a5de87 247statStoreEntry(StoreEntry * s, StoreEntry * e)
090089c4 248{
a5a5de87 249 MemObject *mem = e->mem_obj;
637ed800 250 int i;
251 struct _store_client *sc;
a5a5de87 252 storeAppendPrintf(s, "KEY %s\n", storeKeyText(e->key));
253 if (mem)
254 storeAppendPrintf(s, "\t%s %s\n",
255 RequestMethodStr[mem->method], mem->log_url);
256 storeAppendPrintf(s, "\t%s\n", describeStatuses(e));
257 storeAppendPrintf(s, "\t%s\n", describeFlags(e));
258 storeAppendPrintf(s, "\t%s\n", describeTimestamps(e));
259 storeAppendPrintf(s, "\t%d locks, %d clients, %d refs\n",
260 (int) e->lock_count,
261 storePendingNClients(e),
262 (int) e->refcount);
263 storeAppendPrintf(s, "\tSwap File %#08X\n",
264 e->swap_file_number);
265 if (mem != NULL) {
266 storeAppendPrintf(s, "\tinmem_lo: %d\n", (int) mem->inmem_lo);
267 storeAppendPrintf(s, "\tinmem_hi: %d\n", (int) mem->inmem_hi);
268 storeAppendPrintf(s, "\tswapout: %d bytes done, %d queued, FD %d\n",
5f6ac48b 269 (int) mem->swapout.done_offset,
270 (int) mem->swapout.queue_offset,
637ed800 271 mem->swapout.fd);
272 for (i = 0; i < mem->nclients; i++) {
273 sc = &mem->clients[i];
274 if (sc->callback_data == NULL)
275 continue;
a5a5de87 276 storeAppendPrintf(s, "\tClient #%d\n", i);
277 storeAppendPrintf(s, "\t\tcopy_offset: %d\n",
637ed800 278 (int) sc->copy_offset);
a5a5de87 279 storeAppendPrintf(s, "\t\tseen_offset: %d\n",
637ed800 280 (int) sc->seen_offset);
a5a5de87 281 storeAppendPrintf(s, "\t\tcopy_size: %d\n",
637ed800 282 (int) sc->copy_size);
a5a5de87 283 storeAppendPrintf(s, "\t\tswapin_fd: %d\n",
637ed800 284 (int) sc->swapin_fd);
285 }
a5a5de87 286 }
287 storeAppendPrintf(s, "\n");
288}
289
290/* process objects list */
291static void
1da3b90b 292statObjects(void *data)
a5a5de87 293{
1da3b90b 294 StatObjectsState *state = data;
295 StoreEntry *e;
296 hash_link *link_ptr = NULL;
297 hash_link *link_next = NULL;
634b97dc 298 if (state->bucket >= store_hash_buckets) {
1da3b90b 299 storeComplete(state->sentry);
300 storeUnlockObject(state->sentry);
301 cbdataFree(state);
302 return;
7d9e8f15 303 } else if (state->sentry->store_status == STORE_ABORTED) {
304 storeUnlockObject(state->sentry);
305 cbdataFree(state);
306 return;
562b34ae 307 } else if (fwdCheckDeferRead(-1, state->sentry)) {
48a0f016 308 eventAdd("statObjects", statObjects, state, 0.1, 1);
562b34ae 309 return;
1da3b90b 310 }
311 storeBuffer(state->sentry);
312 debug(49, 3) ("statObjects: Bucket #%d\n", state->bucket);
313 link_next = hash_get_bucket(store_table, state->bucket);
314 while (NULL != (link_ptr = link_next)) {
315 link_next = link_ptr->next;
316 e = (StoreEntry *) link_ptr;
317 if (state->filter && 0 == state->filter(e))
a5a5de87 318 continue;
1da3b90b 319 statStoreEntry(state->sentry, e);
a5a5de87 320 }
634b97dc 321 state->bucket++;
1da3b90b 322 eventAdd("statObjects", statObjects, state, 0.0, 1);
323 storeBufferFlush(state->sentry);
a5a5de87 324}
325
5e29a294 326static void
1da3b90b 327statObjectsStart(StoreEntry * sentry, STOBJFLT * filter)
328{
329 StatObjectsState *state = xcalloc(1, sizeof(*state));
330 state->sentry = sentry;
331 state->filter = filter;
332 storeLockObject(sentry);
333 cbdataAdd(state, MEM_NONE);
334 eventAdd("statObjects", statObjects, state, 0.0, 1);
335}
336
337static void
338stat_objects_get(StoreEntry * sentry)
339{
340 statObjectsStart(sentry, NULL);
341}
342
343static int
344statObjectsVmFilter(const StoreEntry * e)
090089c4 345{
1da3b90b 346 return e->mem_obj ? 1 : 0;
6684fec0 347}
090089c4 348
5e29a294 349static void
1da3b90b 350stat_vmobjects_get(StoreEntry * sentry)
6684fec0 351{
1da3b90b 352 statObjectsStart(sentry, statObjectsVmFilter);
090089c4 353}
354
ae94d28e 355#if DEBUG_OPENFD
1da3b90b 356static int
357statObjectsOpenfdFilter(const StoreEntry * e)
358{
359 if (e->mem_obj == NULL)
360 return 0;
361 if (e->mem_obj->swapout.fd < 0)
362 return 0;;
363 return 1;
364}
365
ae94d28e 366static void
367statOpenfdObj(StoreEntry * sentry)
368{
1da3b90b 369 statObjectsStart(sentry, statObjectsOpenfdFilter);
ae94d28e 370}
1da3b90b 371
ae94d28e 372#endif
373
0a0bf5db 374#ifdef XMALLOC_STATISTICS
b8d8561b 375static void
0a0bf5db 376info_get_mallstat(int size, int number, StoreEntry * sentry)
30a4f2a8 377{
30a4f2a8 378 if (number > 0)
15576b6a 379 storeAppendPrintf(sentry, "\t%d = %d\n", size, number);
30a4f2a8 380}
381#endif
090089c4 382
0ee4272b 383static const char *
f1dc9b30 384fdRemoteAddr(const fde * f)
d51e52f5 385{
95d659f0 386 LOCAL_ARRAY(char, buf, 32);
4f92c80c 387 if (f->type != FD_SOCKET)
388 return null_string;
042461c3 389 snprintf(buf, 32, "%s.%d", f->ipaddr, (int) f->remote_port);
d2af9477 390 return buf;
d51e52f5 391}
392
5e29a294 393static void
b8d8561b 394statFiledescriptors(StoreEntry * sentry)
d51e52f5 395{
396 int i;
f1dc9b30 397 fde *f;
15576b6a 398 storeAppendPrintf(sentry, "Active file descriptors:\n");
399 storeAppendPrintf(sentry, "%-4s %-6s %-4s %-7s %-7s %-21s %s\n",
d51e52f5 400 "File",
401 "Type",
d51e52f5 402 "Tout",
4f92c80c 403 "Nread",
404 "Nwrite",
d51e52f5 405 "Remote Address",
406 "Description");
15576b6a 407 storeAppendPrintf(sentry, "---- ------ ---- ------- ------- --------------------- ------------------------------\n");
e83892e9 408 for (i = 0; i < Squid_MaxFD; i++) {
429fdbec 409 f = &fd_table[i];
5c5783a2 410 if (!f->open)
d51e52f5 411 continue;
15576b6a 412 storeAppendPrintf(sentry, "%4d %-6.6s %4d %7d %7d %-21s %s\n",
d2af9477 413 i,
22f5d1ca 414 fdTypeStr[f->type],
5f6ac48b 415 f->timeout_handler ? (int) (f->timeout - squid_curtime) / 60 : 0,
4f92c80c 416 f->bytes_read,
417 f->bytes_written,
418 fdRemoteAddr(f),
419 f->desc);
d51e52f5 420 }
d51e52f5 421}
422
5e29a294 423static void
03eb2f01 424info_get(StoreEntry * sentry)
090089c4 425{
090089c4 426 struct rusage rusage;
f2908497 427 double cputime;
428 double runtime;
88738790 429#if HAVE_MSTATS && HAVE_GNUMALLOC_H
430 struct mstats ms;
431#elif HAVE_MALLINFO
090089c4 432 struct mallinfo mp;
88738790 433 int t;
090089c4 434#endif
435
f2908497 436 runtime = tvSubDsec(squid_start, current_time);
437 if (runtime == 0.0)
438 runtime = 1.0;
15576b6a 439 storeAppendPrintf(sentry, "Squid Object Cache: Version %s\n",
d51e52f5 440 version_string);
15576b6a 441 storeAppendPrintf(sentry, "Start Time:\t%s\n",
f2908497 442 mkrfc1123(squid_start.tv_sec));
15576b6a 443 storeAppendPrintf(sentry, "Current Time:\t%s\n",
f2908497 444 mkrfc1123(current_time.tv_sec));
15576b6a 445 storeAppendPrintf(sentry, "Connection information for %s:\n",
d51e52f5 446 appname);
98829f69 447 storeAppendPrintf(sentry, "\tNumber of clients accessing cache:\t%u\n",
448 Counter.client_http.clients);
15576b6a 449 storeAppendPrintf(sentry, "\tNumber of HTTP requests received:\t%u\n",
f2908497 450 Counter.client_http.requests);
15576b6a 451 storeAppendPrintf(sentry, "\tNumber of ICP messages received:\t%u\n",
f2908497 452 Counter.icp.pkts_recv);
15576b6a 453 storeAppendPrintf(sentry, "\tNumber of ICP messages sent:\t%u\n",
f2908497 454 Counter.icp.pkts_sent);
2e8e29b8 455 storeAppendPrintf(sentry, "\tNumber of queued ICP replies:\t%u\n",
456 Counter.icp.replies_queued);
15576b6a 457 storeAppendPrintf(sentry, "\tRequest failure ratio:\t%5.2f%%\n",
88aad2e5 458 request_failure_ratio);
f2908497 459
15576b6a 460 storeAppendPrintf(sentry, "\tHTTP requests per minute:\t%.1f\n",
f2908497 461 Counter.client_http.requests / (runtime / 60.0));
15576b6a 462 storeAppendPrintf(sentry, "\tICP messages per minute:\t%.1f\n",
f2908497 463 (Counter.icp.pkts_sent + Counter.icp.pkts_recv) / (runtime / 60.0));
15576b6a 464 storeAppendPrintf(sentry, "\tSelect loop called: %d times, %0.3f ms avg\n",
f2908497 465 Counter.select_loops, 1000.0 * runtime / Counter.select_loops);
090089c4 466
15576b6a 467 storeAppendPrintf(sentry, "Cache information for %s:\n",
30a4f2a8 468 appname);
15576b6a 469 storeAppendPrintf(sentry, "\tStorage Swap size:\t%d KB\n",
c932b107 470 store_swap_size);
15576b6a 471 storeAppendPrintf(sentry, "\tStorage Mem size:\t%d KB\n",
5f6ac48b 472 (int) (store_mem_size >> 10));
15576b6a 473 storeAppendPrintf(sentry, "\tStorage LRU Expiration Age:\t%6.2f days\n",
52cd89fd 474 (double) storeExpiredReferenceAge() / 86400.0);
0faf70d0 475 storeAppendPrintf(sentry, "\tMean Object Size:\t%0.2f KB\n",
476 n_disk_objects ? (double) store_swap_size / n_disk_objects : 0.0);
15576b6a 477 storeAppendPrintf(sentry, "\tRequests given to unlinkd:\t%d\n",
f2908497 478 Counter.unlink.requests);
090089c4 479
b87b92fb 480 storeAppendPrintf(sentry, "Median Service Times (seconds) 5 min 60 min:\n");
481 storeAppendPrintf(sentry, "\tHTTP Requests (All): %8.5f %8.5f\n",
482 statMedianSvc(5, MEDIAN_HTTP) / 1000.0,
483 statMedianSvc(60, MEDIAN_HTTP) / 1000.0);
484 storeAppendPrintf(sentry, "\tCache Misses: %8.5f %8.5f\n",
485 statMedianSvc(5, MEDIAN_MISS) / 1000.0,
486 statMedianSvc(60, MEDIAN_MISS) / 1000.0);
487 storeAppendPrintf(sentry, "\tCache Hits: %8.5f %8.5f\n",
488 statMedianSvc(5, MEDIAN_HIT) / 1000.0,
489 statMedianSvc(60, MEDIAN_HIT) / 1000.0);
490 storeAppendPrintf(sentry, "\tNot-Modified Replies: %8.5f %8.5f\n",
491 statMedianSvc(5, MEDIAN_NM) / 1000.0,
492 statMedianSvc(60, MEDIAN_NM) / 1000.0);
493 storeAppendPrintf(sentry, "\tDNS Lookups: %8.5f %8.5f\n",
494 statMedianSvc(5, MEDIAN_DNS) / 1000.0,
495 statMedianSvc(60, MEDIAN_DNS) / 1000.0);
496 storeAppendPrintf(sentry, "\tICP Queries: %8.5f %8.5f\n",
497 statMedianSvc(5, MEDIAN_ICP_QUERY) / 1000000.0,
498 statMedianSvc(60, MEDIAN_ICP_QUERY) / 1000000.0);
499
f2908497 500 squid_getrusage(&rusage);
501 cputime = rusage_cputime(&rusage);
15576b6a 502 storeAppendPrintf(sentry, "Resource usage for %s:\n", appname);
503 storeAppendPrintf(sentry, "\tUP Time:\t%.3f seconds\n", runtime);
504 storeAppendPrintf(sentry, "\tCPU Time:\t%.3f seconds\n", cputime);
505 storeAppendPrintf(sentry, "\tCPU Usage:\t%.2f%%\n",
f2908497 506 dpercent(cputime, runtime));
979533fa 507 storeAppendPrintf(sentry, "\tCPU Usage, 5 minute avg:\t%.2f%%\n",
49ad0a8c 508 statCPUUsage(5));
509 storeAppendPrintf(sentry, "\tCPU Usage, 60 minute avg:\t%.2f%%\n",
510 statCPUUsage(60));
5f6ac48b 511 storeAppendPrintf(sentry, "\tMaximum Resident Size: %d KB\n",
f2908497 512 rusage_maxrss(&rusage));
5f6ac48b 513 storeAppendPrintf(sentry, "\tPage faults with physical i/o: %d\n",
f2908497 514 rusage_pagefaults(&rusage));
090089c4 515
88738790 516#if HAVE_MSTATS && HAVE_GNUMALLOC_H
517 ms = mstats();
15576b6a 518 storeAppendPrintf(sentry, "Memory usage for %s via mstats():\n",
88738790 519 appname);
15576b6a 520 storeAppendPrintf(sentry, "\tTotal space in arena: %6d KB\n",
88738790 521 ms.bytes_total >> 10);
15576b6a 522 storeAppendPrintf(sentry, "\tTotal free: %6d KB %d%%\n",
88738790 523 ms.bytes_free >> 10, percent(ms.bytes_free, ms.bytes_total));
524#elif HAVE_MALLINFO
090089c4 525 mp = mallinfo();
15576b6a 526 storeAppendPrintf(sentry, "Memory usage for %s via mallinfo():\n",
d51e52f5 527 appname);
15576b6a 528 storeAppendPrintf(sentry, "\tTotal space in arena: %6d KB\n",
b560dd20 529 mp.arena >> 10);
15576b6a 530 storeAppendPrintf(sentry, "\tOrdinary blocks: %6d KB %6d blks\n",
30a4f2a8 531 mp.uordblks >> 10, mp.ordblks);
15576b6a 532 storeAppendPrintf(sentry, "\tSmall blocks: %6d KB %6d blks\n",
30a4f2a8 533 mp.usmblks >> 10, mp.smblks);
15576b6a 534 storeAppendPrintf(sentry, "\tHolding blocks: %6d KB %6d blks\n",
30a4f2a8 535 mp.hblkhd >> 10, mp.hblks);
15576b6a 536 storeAppendPrintf(sentry, "\tFree Small blocks: %6d KB\n",
30a4f2a8 537 mp.fsmblks >> 10);
15576b6a 538 storeAppendPrintf(sentry, "\tFree Ordinary blocks: %6d KB\n",
30a4f2a8 539 mp.fordblks >> 10);
540 t = mp.uordblks + mp.usmblks + mp.hblkhd;
15576b6a 541 storeAppendPrintf(sentry, "\tTotal in use: %6d KB %d%%\n",
30a4f2a8 542 t >> 10, percent(t, mp.arena));
543 t = mp.fsmblks + mp.fordblks;
15576b6a 544 storeAppendPrintf(sentry, "\tTotal free: %6d KB %d%%\n",
30a4f2a8 545 t >> 10, percent(t, mp.arena));
46c883ed 546#if HAVE_EXT_MALLINFO
15576b6a 547 storeAppendPrintf(sentry, "\tmax size of small blocks:\t%d\n", mp.mxfast);
548 storeAppendPrintf(sentry, "\tnumber of small blocks in a holding block:\t%d\n",
090089c4 549 mp.nlblks);
15576b6a 550 storeAppendPrintf(sentry, "\tsmall block rounding factor:\t%d\n", mp.grain);
551 storeAppendPrintf(sentry, "\tspace (including overhead) allocated in ord. blks:\t%d\n"
090089c4 552 ,mp.uordbytes);
15576b6a 553 storeAppendPrintf(sentry, "\tnumber of ordinary blocks allocated:\t%d\n",
090089c4 554 mp.allocated);
15576b6a 555 storeAppendPrintf(sentry, "\tbytes used in maintaining the free tree:\t%d\n",
090089c4 556 mp.treeoverhead);
46c883ed 557#endif /* HAVE_EXT_MALLINFO */
50bc2565 558#endif /* HAVE_MALLINFO */
5d1f3c82 559 storeAppendPrintf(sentry, "Memory accounted for:\n");
979533fa 560 storeAppendPrintf(sentry, "\tTotal accounted: %6d KB\n",
48a0f016 561 memTotalAllocated() >> 10);
090089c4 562
15576b6a 563 storeAppendPrintf(sentry, "File descriptor usage for %s:\n", appname);
564 storeAppendPrintf(sentry, "\tMaximum number of file descriptors: %4d\n",
e83892e9 565 Squid_MaxFD);
15576b6a 566 storeAppendPrintf(sentry, "\tLargest file desc currently in use: %4d\n",
429fdbec 567 Biggest_FD);
15576b6a 568 storeAppendPrintf(sentry, "\tNumber of file desc currently in use: %4d\n",
88738790 569 Number_FD);
15576b6a 570 storeAppendPrintf(sentry, "\tAvailable number of file descriptors: %4d\n",
88738790 571 Squid_MaxFD - Number_FD);
15576b6a 572 storeAppendPrintf(sentry, "\tReserved number of file descriptors: %4d\n",
090089c4 573 RESERVED_FD);
090089c4 574
15576b6a 575 storeAppendPrintf(sentry, "Internal Data Structures:\n");
576 storeAppendPrintf(sentry, "\t%6d StoreEntries\n",
3f6c0fb2 577 memInUse(MEM_STOREENTRY));
15576b6a 578 storeAppendPrintf(sentry, "\t%6d StoreEntries with MemObjects\n",
3f6c0fb2 579 memInUse(MEM_MEMOBJECT));
15576b6a 580 storeAppendPrintf(sentry, "\t%6d Hot Object Cache Items\n",
59c4d35b 581 hot_obj_count);
5d406e78 582 storeAppendPrintf(sentry, "\t%6d Filemap bits set\n",
583 storeDirMapBitsInUse());
0b2e785a 584 storeAppendPrintf(sentry, "\t%6d on-disk objects\n",
585 n_disk_objects);
30a4f2a8 586
587#if XMALLOC_STATISTICS
15576b6a 588 storeAppendPrintf(sentry, "Memory allocation statistics\n");
30a4f2a8 589 malloc_statistics(info_get_mallstat, sentry);
590#endif
090089c4 591}
592
a7c05555 593#define XAVG(X) (dt ? (double) (f->X - l->X) / dt : 0.0)
b8d8561b 594static void
a0f32775 595statAvgDump(StoreEntry * sentry, int minutes, int hours)
090089c4 596{
a7c05555 597 StatCounters *f;
598 StatCounters *l;
599 double dt;
600 double ct;
7ae52c25 601 double x;
a7c05555 602 assert(N_COUNT_HIST > 1);
a0f32775 603 assert(minutes > 0 || hours > 0);
a7c05555 604 f = &CountHist[0];
a0f32775 605 l = f;
606 if (minutes > 0 && hours == 0) {
607 /* checking minute readings ... */
608 if (minutes > N_COUNT_HIST - 1)
609 minutes = N_COUNT_HIST - 1;
610 l = &CountHist[minutes];
611 } else if (minutes == 0 && hours > 0) {
612 /* checking hour readings ... */
613 if (hours > N_COUNT_HOUR_HIST - 1)
614 hours = N_COUNT_HOUR_HIST - 1;
615 l = &CountHourHist[hours];
616 } else {
399e85ea 617 debug(18, 1) ("statAvgDump: Invalid args, minutes=%d, hours=%d\n",
618 minutes, hours);
a0f32775 619 return;
620 }
a7c05555 621 dt = tvSubDsec(l->timestamp, f->timestamp);
622 ct = f->cputime - l->cputime;
ee1679df 623
399e85ea 624 storeAppendPrintf(sentry, "sample_start_time = %d.%d (%s)\n",
5f6ac48b 625 (int) l->timestamp.tv_sec,
626 (int) l->timestamp.tv_usec,
5843f24a 627 mkrfc1123(f->timestamp.tv_sec));
628 storeAppendPrintf(sentry, "sample_end_time = %d.%d (%s)\n",
629 (int) f->timestamp.tv_sec,
630 (int) f->timestamp.tv_usec,
a0f32775 631 mkrfc1123(l->timestamp.tv_sec));
632
a7c05555 633 storeAppendPrintf(sentry, "client_http.requests = %f/sec\n",
634 XAVG(client_http.requests));
635 storeAppendPrintf(sentry, "client_http.hits = %f/sec\n",
636 XAVG(client_http.hits));
637 storeAppendPrintf(sentry, "client_http.errors = %f/sec\n",
638 XAVG(client_http.errors));
639 storeAppendPrintf(sentry, "client_http.kbytes_in = %f/sec\n",
640 XAVG(client_http.kbytes_in.kb));
641 storeAppendPrintf(sentry, "client_http.kbytes_out = %f/sec\n",
642 XAVG(client_http.kbytes_out.kb));
ee1679df 643
12cf1be2 644 x = statHistDeltaMedian(&l->client_http.all_svc_time,
ee1679df 645 &f->client_http.all_svc_time);
646 storeAppendPrintf(sentry, "client_http.all_median_svc_time = %f seconds\n",
647 x / 1000.0);
12cf1be2 648 x = statHistDeltaMedian(&l->client_http.miss_svc_time,
ee1679df 649 &f->client_http.miss_svc_time);
650 storeAppendPrintf(sentry, "client_http.miss_median_svc_time = %f seconds\n",
651 x / 1000.0);
12cf1be2 652 x = statHistDeltaMedian(&l->client_http.nm_svc_time,
ee1679df 653 &f->client_http.nm_svc_time);
654 storeAppendPrintf(sentry, "client_http.nm_median_svc_time = %f seconds\n",
655 x / 1000.0);
12cf1be2 656 x = statHistDeltaMedian(&l->client_http.hit_svc_time,
ee1679df 657 &f->client_http.hit_svc_time);
658 storeAppendPrintf(sentry, "client_http.hit_median_svc_time = %f seconds\n",
7ae52c25 659 x / 1000.0);
071a3ae7 660
a0f32775 661 storeAppendPrintf(sentry, "server.all.requests = %f/sec\n",
662 XAVG(server.all.requests));
663 storeAppendPrintf(sentry, "server.all.errors = %f/sec\n",
664 XAVG(server.all.errors));
665 storeAppendPrintf(sentry, "server.all.kbytes_in = %f/sec\n",
666 XAVG(server.all.kbytes_in.kb));
667 storeAppendPrintf(sentry, "server.all.kbytes_out = %f/sec\n",
668 XAVG(server.all.kbytes_out.kb));
669
670 storeAppendPrintf(sentry, "server.http.requests = %f/sec\n",
671 XAVG(server.http.requests));
672 storeAppendPrintf(sentry, "server.http.errors = %f/sec\n",
673 XAVG(server.http.errors));
674 storeAppendPrintf(sentry, "server.http.kbytes_in = %f/sec\n",
675 XAVG(server.http.kbytes_in.kb));
676 storeAppendPrintf(sentry, "server.http.kbytes_out = %f/sec\n",
677 XAVG(server.http.kbytes_out.kb));
678
679 storeAppendPrintf(sentry, "server.ftp.requests = %f/sec\n",
680 XAVG(server.ftp.requests));
681 storeAppendPrintf(sentry, "server.ftp.errors = %f/sec\n",
682 XAVG(server.ftp.errors));
683 storeAppendPrintf(sentry, "server.ftp.kbytes_in = %f/sec\n",
684 XAVG(server.ftp.kbytes_in.kb));
685 storeAppendPrintf(sentry, "server.ftp.kbytes_out = %f/sec\n",
686 XAVG(server.ftp.kbytes_out.kb));
687
688 storeAppendPrintf(sentry, "server.other.requests = %f/sec\n",
689 XAVG(server.other.requests));
690 storeAppendPrintf(sentry, "server.other.errors = %f/sec\n",
691 XAVG(server.other.errors));
692 storeAppendPrintf(sentry, "server.other.kbytes_in = %f/sec\n",
693 XAVG(server.other.kbytes_in.kb));
694 storeAppendPrintf(sentry, "server.other.kbytes_out = %f/sec\n",
695 XAVG(server.other.kbytes_out.kb));
ee1679df 696
a7c05555 697 storeAppendPrintf(sentry, "icp.pkts_sent = %f/sec\n",
698 XAVG(icp.pkts_sent));
699 storeAppendPrintf(sentry, "icp.pkts_recv = %f/sec\n",
700 XAVG(icp.pkts_recv));
071a3ae7 701 storeAppendPrintf(sentry, "icp.queries_sent = %f/sec\n",
702 XAVG(icp.queries_sent));
703 storeAppendPrintf(sentry, "icp.replies_sent = %f/sec\n",
704 XAVG(icp.replies_sent));
705 storeAppendPrintf(sentry, "icp.queries_recv = %f/sec\n",
706 XAVG(icp.queries_recv));
707 storeAppendPrintf(sentry, "icp.replies_recv = %f/sec\n",
708 XAVG(icp.replies_recv));
2e8e29b8 709 storeAppendPrintf(sentry, "icp.replies_queued = %f/sec\n",
710 XAVG(icp.replies_queued));
071a3ae7 711 storeAppendPrintf(sentry, "icp.query_timeouts = %f/sec\n",
712 XAVG(icp.query_timeouts));
a7c05555 713 storeAppendPrintf(sentry, "icp.kbytes_sent = %f/sec\n",
714 XAVG(icp.kbytes_sent.kb));
715 storeAppendPrintf(sentry, "icp.kbytes_recv = %f/sec\n",
716 XAVG(icp.kbytes_recv.kb));
071a3ae7 717 storeAppendPrintf(sentry, "icp.q_kbytes_sent = %f/sec\n",
718 XAVG(icp.q_kbytes_sent.kb));
719 storeAppendPrintf(sentry, "icp.r_kbytes_sent = %f/sec\n",
720 XAVG(icp.r_kbytes_sent.kb));
721 storeAppendPrintf(sentry, "icp.q_kbytes_recv = %f/sec\n",
722 XAVG(icp.q_kbytes_recv.kb));
723 storeAppendPrintf(sentry, "icp.r_kbytes_recv = %f/sec\n",
724 XAVG(icp.r_kbytes_recv.kb));
12cf1be2 725 x = statHistDeltaMedian(&l->icp.query_svc_time, &f->icp.query_svc_time);
ee1679df 726 storeAppendPrintf(sentry, "icp.query_median_svc_time = %f seconds\n",
727 x / 1000000.0);
12cf1be2 728 x = statHistDeltaMedian(&l->icp.reply_svc_time, &f->icp.reply_svc_time);
ee1679df 729 storeAppendPrintf(sentry, "icp.reply_median_svc_time = %f seconds\n",
7ae52c25 730 x / 1000000.0);
12cf1be2 731 x = statHistDeltaMedian(&l->dns.svc_time, &f->dns.svc_time);
9973e9fe 732 storeAppendPrintf(sentry, "dns.median_svc_time = %f seconds\n",
901d8c30 733 x / 1000.0);
a7c05555 734 storeAppendPrintf(sentry, "unlink.requests = %f/sec\n",
735 XAVG(unlink.requests));
736 storeAppendPrintf(sentry, "page_faults = %f/sec\n",
737 XAVG(page_faults));
738 storeAppendPrintf(sentry, "select_loops = %f/sec\n",
739 XAVG(select_loops));
740 storeAppendPrintf(sentry, "cpu_time = %f seconds\n", ct);
741 storeAppendPrintf(sentry, "wall_time = %f seconds\n", dt);
0e473d70 742 storeAppendPrintf(sentry, "cpu_usage = %f%%\n", dpercent(ct, dt));
090089c4 743}
744
979533fa 745
b8d8561b 746void
a7c05555 747statInit(void)
090089c4 748{
090089c4 749 int i;
a7c05555 750 debug(18, 5) ("statInit: Initializing...\n");
0e473d70 751 for (i = 0; i < N_COUNT_HIST; i++)
12cf1be2 752 statCountersInit(&CountHist[i]);
a0f32775 753 for (i = 0; i < N_COUNT_HOUR_HIST; i++)
754 statCountersInit(&CountHourHist[i]);
12cf1be2 755 statCountersInit(&Counter);
52040193 756 eventAdd("statAvgTick", statAvgTick, NULL, (double) COUNT_INTERVAL, 1);
22f3fd98 757 cachemgrRegister("info",
758 "General Runtime Information",
1da3b90b 759 info_get, 0, 1);
22f3fd98 760 cachemgrRegister("filedescriptors",
761 "Process Filedescriptor Allocation",
1da3b90b 762 statFiledescriptors, 0, 1);
22f3fd98 763 cachemgrRegister("objects",
764 "All Cache Objects",
1da3b90b 765 stat_objects_get, 0, 0);
22f3fd98 766 cachemgrRegister("vm_objects",
767 "In-Memory and In-Transit Objects",
1da3b90b 768 stat_vmobjects_get, 0, 0);
ae94d28e 769#if DEBUG_OPENFD
770 cachemgrRegister("openfd_objects",
771 "Objects with Swapout files open",
1da3b90b 772 statOpenfdObj, 0, 0);
ae94d28e 773#endif
22f3fd98 774 cachemgrRegister("io",
775 "Server-side network read() size histograms",
1da3b90b 776 stat_io_get, 0, 1);
22f3fd98 777 cachemgrRegister("counters",
778 "Traffic and Resource Counters",
1da3b90b 779 statCountersDump, 0, 1);
a1e927f6 780 cachemgrRegister("peer_select",
781 "Peer Selection Algorithms",
1da3b90b 782 statPeerSelect, 0, 1);
26b164ac 783 cachemgrRegister("digest_stats",
784 "Cache Digest and ICP blob",
1da3b90b 785 statDigestBlob, 0, 1);
22f3fd98 786 cachemgrRegister("5min",
787 "5 Minute Average of Counters",
1da3b90b 788 statAvg5min, 0, 1);
45eb7f49 789 cachemgrRegister("60min",
790 "60 Minute Average of Counters",
1da3b90b 791 statAvg60min, 0, 1);
e9b5ead4 792 cachemgrRegister("utilization",
793 "Cache Utilization",
1da3b90b 794 statUtilization, 0, 1);
01aebf31 795#if STAT_GRAPHS
796 cachemgrRegister("graph_variables",
797 "Display cache metrics graphically",
1da3b90b 798 statGraphDump, 0, 1);
01aebf31 799#endif
ba4f8e5a 800 cachemgrRegister("histograms",
801 "Full Histogram Counts",
1da3b90b 802 statCountersHistograms, 0, 1);
090089c4 803}
f2908497 804
f2908497 805static void
806statAvgTick(void *notused)
807{
d5649d9f 808 StatCounters *t = &CountHist[0];
809 StatCounters *p = &CountHist[1];
f2908497 810 StatCounters *c = &Counter;
811 struct rusage rusage;
f720985e 812 eventAdd("statAvgTick", statAvgTick, NULL, COUNT_INTERVAL, 1);
20903cac 813 squid_getrusage(&rusage);
814 c->page_faults = rusage_pagefaults(&rusage);
815 c->cputime = rusage_cputime(&rusage);
d5649d9f 816 c->timestamp = current_time;
12cf1be2 817 /* even if NCountHist is small, we already Init()ed the tail */
2ac76861 818 statCountersClean(CountHist + N_COUNT_HIST - 1);
dbfed404 819 xmemmove(p, t, (N_COUNT_HIST - 1) * sizeof(StatCounters));
12cf1be2 820 statCountersCopy(t, c);
d5649d9f 821 NCountHist++;
a0f32775 822
823 if ((NCountHist % COUNT_INTERVAL) == 0) {
824 /* we have an hours worth of readings. store previous hour */
ffb245b5 825 StatCounters *t = &CountHourHist[0];
826 StatCounters *p = &CountHourHist[1];
b23c4568 827 StatCounters *c = &CountHist[N_COUNT_HIST-1];
ffb245b5 828 statCountersClean(CountHourHist + N_COUNT_HOUR_HIST - 1);
a0f32775 829 xmemmove(p, t, (N_COUNT_HOUR_HIST - 1) * sizeof(StatCounters));
a887b8fa 830 statCountersCopy(t, c);
a0f32775 831 NCountHourHist++;
832 }
20903cac 833}
834
12cf1be2 835static void
2ac76861 836statCountersInit(StatCounters * C)
20903cac 837{
12cf1be2 838 assert(C);
1d803566 839 memset(C, 0, sizeof(*C));
12cf1be2 840 C->timestamp = current_time;
1d803566 841 statCountersInitSpecial(C);
842}
843
844/* add special cases here as they arrive */
845static void
2ac76861 846statCountersInitSpecial(StatCounters * C)
1d803566 847{
12cf1be2 848 /*
849 * HTTP svc_time hist is kept in milli-seconds; max of 3 hours.
850 */
851 statHistLogInit(&C->client_http.all_svc_time, 300, 0.0, 3600000.0 * 3.0);
852 statHistLogInit(&C->client_http.miss_svc_time, 300, 0.0, 3600000.0 * 3.0);
853 statHistLogInit(&C->client_http.nm_svc_time, 300, 0.0, 3600000.0 * 3.0);
854 statHistLogInit(&C->client_http.hit_svc_time, 300, 0.0, 3600000.0 * 3.0);
855 /*
856 * ICP svc_time hist is kept in micro-seconds; max of 1 minute.
857 */
858 statHistLogInit(&C->icp.query_svc_time, 300, 0.0, 1000000.0 * 60.0);
859 statHistLogInit(&C->icp.reply_svc_time, 300, 0.0, 1000000.0 * 60.0);
860 /*
861 * DNS svc_time hist is kept in milli-seconds; max of 10 minutes.
862 */
863 statHistLogInit(&C->dns.svc_time, 300, 0.0, 60000.0 * 10.0);
a1e927f6 864 /*
69c95dd3 865 * Cache Digest Stuff
a1e927f6 866 */
0c511722 867 statHistEnumInit(&C->cd.on_xition_count, CacheDigestHashFuncCount);
c6ecdbc3 868 statHistEnumInit(&C->comm_icp_incoming, INCOMING_ICP_MAX);
869 statHistEnumInit(&C->comm_http_incoming, INCOMING_HTTP_MAX);
0f5607d9 870}
871
12cf1be2 872/* add special cases here as they arrive */
5e29a294 873static void
2ac76861 874statCountersClean(StatCounters * C)
0f5607d9 875{
12cf1be2 876 assert(C);
877 statHistClean(&C->client_http.all_svc_time);
878 statHistClean(&C->client_http.miss_svc_time);
879 statHistClean(&C->client_http.nm_svc_time);
880 statHistClean(&C->client_http.hit_svc_time);
881 statHistClean(&C->icp.query_svc_time);
882 statHistClean(&C->icp.reply_svc_time);
883 statHistClean(&C->dns.svc_time);
c135694e 884 statHistClean(&C->cd.on_xition_count);
c6ecdbc3 885 statHistClean(&C->comm_icp_incoming);
886 statHistClean(&C->comm_http_incoming);
a7c05555 887}
888
12cf1be2 889/* add special cases here as they arrive */
5e29a294 890static void
2ac76861 891statCountersCopy(StatCounters * dest, const StatCounters * orig)
45eb7f49 892{
12cf1be2 893 assert(dest && orig);
1d803566 894 /* this should take care of all the fields, but "special" ones */
12cf1be2 895 memcpy(dest, orig, sizeof(*dest));
1d803566 896 /* prepare space where to copy special entries */
897 statCountersInitSpecial(dest);
898 /* now handle special cases */
899 /* note: we assert that histogram capacities do not change */
12cf1be2 900 statHistCopy(&dest->client_http.all_svc_time, &orig->client_http.all_svc_time);
901 statHistCopy(&dest->client_http.miss_svc_time, &orig->client_http.miss_svc_time);
902 statHistCopy(&dest->client_http.nm_svc_time, &orig->client_http.nm_svc_time);
903 statHistCopy(&dest->client_http.hit_svc_time, &orig->client_http.hit_svc_time);
904 statHistCopy(&dest->icp.query_svc_time, &orig->icp.query_svc_time);
905 statHistCopy(&dest->icp.reply_svc_time, &orig->icp.reply_svc_time);
906 statHistCopy(&dest->dns.svc_time, &orig->dns.svc_time);
c135694e 907 statHistCopy(&dest->cd.on_xition_count, &orig->cd.on_xition_count);
c6ecdbc3 908 statHistCopy(&dest->comm_icp_incoming, &orig->comm_icp_incoming);
909 statHistCopy(&dest->comm_http_incoming, &orig->comm_http_incoming);
45eb7f49 910}
911
071a3ae7 912static void
5d406e78 913statCountersHistograms(StoreEntry * sentry)
071a3ae7 914{
ba4f8e5a 915 StatCounters *f = &Counter;
071a3ae7 916 storeAppendPrintf(sentry, "client_http.all_svc_time histogram:\n");
917 statHistDump(&f->client_http.all_svc_time, sentry, NULL);
918 storeAppendPrintf(sentry, "client_http.miss_svc_time histogram:\n");
919 statHistDump(&f->client_http.miss_svc_time, sentry, NULL);
920 storeAppendPrintf(sentry, "client_http.nm_svc_time histogram:\n");
921 statHistDump(&f->client_http.nm_svc_time, sentry, NULL);
922 storeAppendPrintf(sentry, "client_http.hit_svc_time histogram:\n");
923 statHistDump(&f->client_http.hit_svc_time, sentry, NULL);
071a3ae7 924 storeAppendPrintf(sentry, "icp.query_svc_time histogram:\n");
925 statHistDump(&f->icp.query_svc_time, sentry, NULL);
926 storeAppendPrintf(sentry, "icp.reply_svc_time histogram:\n");
927 statHistDump(&f->icp.reply_svc_time, sentry, NULL);
928 storeAppendPrintf(sentry, "dns.svc_time histogram:\n");
929 statHistDump(&f->dns.svc_time, sentry, NULL);
071a3ae7 930}
931
12cf1be2 932static void
933statCountersDump(StoreEntry * sentry)
7ae52c25 934{
12cf1be2 935 StatCounters *f = &Counter;
936 struct rusage rusage;
937 squid_getrusage(&rusage);
938 f->page_faults = rusage_pagefaults(&rusage);
939 f->cputime = rusage_cputime(&rusage);
940
a0f32775 941 storeAppendPrintf(sentry, "sample_time = %d.%d (%s)\n",
5f6ac48b 942 (int) f->timestamp.tv_sec,
943 (int) f->timestamp.tv_usec,
a0f32775 944 mkrfc1123(f->timestamp.tv_sec));
12cf1be2 945 storeAppendPrintf(sentry, "client_http.requests = %d\n",
946 f->client_http.requests);
947 storeAppendPrintf(sentry, "client_http.hits = %d\n",
948 f->client_http.hits);
949 storeAppendPrintf(sentry, "client_http.errors = %d\n",
950 f->client_http.errors);
951 storeAppendPrintf(sentry, "client_http.kbytes_in = %d\n",
952 (int) f->client_http.kbytes_in.kb);
953 storeAppendPrintf(sentry, "client_http.kbytes_out = %d\n",
954 (int) f->client_http.kbytes_out.kb);
0567f2a6 955
a0f32775 956 storeAppendPrintf(sentry, "server.all.requests = %d\n",
957 (int) f->server.all.requests);
958 storeAppendPrintf(sentry, "server.all.errors = %d\n",
959 (int) f->server.all.errors);
960 storeAppendPrintf(sentry, "server.all.kbytes_in = %d\n",
961 (int) f->server.all.kbytes_in.kb);
962 storeAppendPrintf(sentry, "server.all.kbytes_out = %d\n",
963 (int) f->server.all.kbytes_out.kb);
964
965 storeAppendPrintf(sentry, "server.http.requests = %d\n",
966 (int) f->server.http.requests);
967 storeAppendPrintf(sentry, "server.http.errors = %d\n",
968 (int) f->server.http.errors);
969 storeAppendPrintf(sentry, "server.http.kbytes_in = %d\n",
970 (int) f->server.http.kbytes_in.kb);
971 storeAppendPrintf(sentry, "server.http.kbytes_out = %d\n",
972 (int) f->server.http.kbytes_out.kb);
973
974 storeAppendPrintf(sentry, "server.ftp.requests = %d\n",
975 (int) f->server.ftp.requests);
976 storeAppendPrintf(sentry, "server.ftp.errors = %d\n",
977 (int) f->server.ftp.errors);
978 storeAppendPrintf(sentry, "server.ftp.kbytes_in = %d\n",
979 (int) f->server.ftp.kbytes_in.kb);
980 storeAppendPrintf(sentry, "server.ftp.kbytes_out = %d\n",
981 (int) f->server.ftp.kbytes_out.kb);
982
983 storeAppendPrintf(sentry, "server.other.requests = %d\n",
984 (int) f->server.other.requests);
985 storeAppendPrintf(sentry, "server.other.errors = %d\n",
986 (int) f->server.other.errors);
987 storeAppendPrintf(sentry, "server.other.kbytes_in = %d\n",
988 (int) f->server.other.kbytes_in.kb);
989 storeAppendPrintf(sentry, "server.other.kbytes_out = %d\n",
990 (int) f->server.other.kbytes_out.kb);
12cf1be2 991
992 storeAppendPrintf(sentry, "icp.pkts_sent = %d\n",
993 f->icp.pkts_sent);
994 storeAppendPrintf(sentry, "icp.pkts_recv = %d\n",
995 f->icp.pkts_recv);
071a3ae7 996 storeAppendPrintf(sentry, "icp.queries_sent = %d\n",
997 f->icp.queries_sent);
998 storeAppendPrintf(sentry, "icp.replies_sent = %d\n",
999 f->icp.replies_sent);
1000 storeAppendPrintf(sentry, "icp.queries_recv = %d\n",
1001 f->icp.queries_recv);
1002 storeAppendPrintf(sentry, "icp.replies_recv = %d\n",
1003 f->icp.replies_recv);
1004 storeAppendPrintf(sentry, "icp.query_timeouts = %d\n",
1005 f->icp.query_timeouts);
2e8e29b8 1006 storeAppendPrintf(sentry, "icp.replies_queued = %d\n",
1007 f->icp.replies_queued);
12cf1be2 1008 storeAppendPrintf(sentry, "icp.kbytes_sent = %d\n",
1009 (int) f->icp.kbytes_sent.kb);
1010 storeAppendPrintf(sentry, "icp.kbytes_recv = %d\n",
1011 (int) f->icp.kbytes_recv.kb);
071a3ae7 1012 storeAppendPrintf(sentry, "icp.q_kbytes_sent = %d\n",
1013 (int) f->icp.q_kbytes_sent.kb);
1014 storeAppendPrintf(sentry, "icp.r_kbytes_sent = %d\n",
1015 (int) f->icp.r_kbytes_sent.kb);
1016 storeAppendPrintf(sentry, "icp.q_kbytes_recv = %d\n",
1017 (int) f->icp.q_kbytes_recv.kb);
1018 storeAppendPrintf(sentry, "icp.r_kbytes_recv = %d\n",
1019 (int) f->icp.r_kbytes_recv.kb);
0567f2a6 1020
6cfa8966 1021#if USE_CACHE_DIGESTS
071a3ae7 1022 storeAppendPrintf(sentry, "icp.times_used = %d\n",
5d406e78 1023 f->icp.times_used);
071a3ae7 1024 storeAppendPrintf(sentry, "cd.times_used = %d\n",
5d406e78 1025 f->cd.times_used);
00485c29 1026 storeAppendPrintf(sentry, "cd.msgs_sent = %d\n",
1027 f->cd.msgs_sent);
1028 storeAppendPrintf(sentry, "cd.msgs_recv = %d\n",
1029 f->cd.msgs_recv);
071a3ae7 1030 storeAppendPrintf(sentry, "cd.memory = %d\n",
5d406e78 1031 (int) f->cd.memory.kb);
522b517b 1032 storeAppendPrintf(sentry, "cd.local_memory = %d\n",
5d406e78 1033 (int) (store_digest ? store_digest->mask_size / 1024 : 0));
00485c29 1034 storeAppendPrintf(sentry, "cd.kbytes_sent = %d\n",
1035 (int) f->cd.kbytes_sent.kb);
1036 storeAppendPrintf(sentry, "cd.kbytes_recv = %d\n",
1037 (int) f->cd.kbytes_recv.kb);
0567f2a6 1038#endif
1039
12cf1be2 1040 storeAppendPrintf(sentry, "unlink.requests = %d\n",
1041 f->unlink.requests);
1042 storeAppendPrintf(sentry, "page_faults = %d\n",
1043 f->page_faults);
1044 storeAppendPrintf(sentry, "select_loops = %d\n",
1045 f->select_loops);
1046 storeAppendPrintf(sentry, "cpu_time = %f\n",
1047 f->cputime);
1048 storeAppendPrintf(sentry, "wall_time = %f\n",
1049 tvSubDsec(f->timestamp, current_time));
7ae52c25 1050}
1051
d2db411c 1052void
1053statFreeMemory(void)
1054{
1055 int i;
1056 for (i = 0; i < N_COUNT_HIST; i++)
1057 statCountersClean(&CountHist[i]);
1058 for (i = 0; i < N_COUNT_HOUR_HIST; i++)
1059 statCountersClean(&CountHourHist[i]);
1060}
1061
5e29a294 1062static void
a1e927f6 1063statPeerSelect(StoreEntry * sentry)
1064{
6cfa8966 1065#if USE_CACHE_DIGESTS
a1e927f6 1066 StatCounters *f = &Counter;
1067 peer *peer;
1068 const int tot_used = f->cd.times_used + f->icp.times_used;
1069
1070 /* totals */
1071 cacheDigestGuessStatsReport(&f->cd.guess, sentry, "all peers");
1072 /* per-peer */
1073 storeAppendPrintf(sentry, "\nPer-peer statistics:\n");
1074 for (peer = getFirstPeer(); peer; peer = getNextPeer(peer)) {
1075 cacheDigestGuessStatsReport(&peer->digest.stats.guess, sentry, peer->host);
ddc0f170 1076 storeAppendPrintf(sentry, "peer.msgs_sent = %d\n",
1077 peer->digest.stats.msgs_sent);
1078 storeAppendPrintf(sentry, "peer.msgs_recv = %d\n",
1079 peer->digest.stats.msgs_recv);
1080 storeAppendPrintf(sentry, "peer.kbytes_sent = %d\n",
1081 (int) peer->digest.stats.kbytes_sent.kb);
1082 storeAppendPrintf(sentry, "peer.kbytes_recv = %d\n",
1083 (int) peer->digest.stats.kbytes_recv.kb);
1084 storeAppendPrintf(sentry, "peer.local_memory = %d\n",
5d406e78 1085 peer->digest.cd ? peer->digest.cd->mask_size / 1024 : 0);
1543ab6c 1086 storeAppendPrintf(sentry, "digest state: inited: %d, disabled: %d usable: %d requested: %d\n",
1087 0 < EBIT_TEST(peer->digest.flags, PD_INITED),
1088 0 < EBIT_TEST(peer->digest.flags, PD_DISABLED),
1089 0 < EBIT_TEST(peer->digest.flags, PD_USABLE),
1090 0 < EBIT_TEST(peer->digest.flags, PD_REQUESTED)
5d406e78 1091 );
1543ab6c 1092 if (peer->digest.cd)
7ea5d333 1093 cacheDigestReport(peer->digest.cd, peer->host, sentry);
1543ab6c 1094 else
1095 storeAppendPrintf(sentry, "no cache digest from peer %s\n", peer->host);
7ea5d333 1096 storeAppendPrintf(sentry, "\n");
a1e927f6 1097 }
1098
1099 storeAppendPrintf(sentry, "\nAlgorithm usage:\n");
1100 storeAppendPrintf(sentry, "Cache Digest: %7d (%3d%%)\n",
1101 f->cd.times_used, xpercentInt(f->cd.times_used, tot_used));
1102 storeAppendPrintf(sentry, "Icp: %7d (%3d%%)\n",
1103 f->icp.times_used, xpercentInt(f->icp.times_used, tot_used));
1104 storeAppendPrintf(sentry, "Total: %7d (%3d%%)\n",
1105 tot_used, xpercentInt(tot_used, tot_used));
1106#else
1107 storeAppendPrintf(sentry, "peer digests are disabled; no stats is available.\n");
1108#endif
1109}
1110
1111static void
26b164ac 1112statDigestBlob(StoreEntry * sentry)
1113{
071a3ae7 1114 storeAppendPrintf(sentry, "\nCounters:\n");
1115 statCountersDump(sentry);
86e2a291 1116 storeAppendPrintf(sentry, "\n5 Min Averages:\n");
1117 statAvgDump(sentry, 5, 0);
071a3ae7 1118 storeAppendPrintf(sentry, "\nHistograms:\n");
1119 statCountersHistograms(sentry);
1120 storeAppendPrintf(sentry, "\nPeer Digests:\n");
26b164ac 1121 statPeerSelect(sentry);
588d9545 1122 storeAppendPrintf(sentry, "\nLocal Digest:\n");
26b164ac 1123 storeDigestReport(sentry);
1124}
1125
5e29a294 1126static void
12cf1be2 1127statAvg5min(StoreEntry * e)
7ae52c25 1128{
a0f32775 1129 statAvgDump(e, 5, 0);
7ae52c25 1130}
1131
5e29a294 1132static void
12cf1be2 1133statAvg60min(StoreEntry * e)
7ae52c25 1134{
a0f32775 1135 statAvgDump(e, 60, 0);
7ae52c25 1136}
1137
b87b92fb 1138static double
1139statMedianSvc(int interval, int which)
a9113eb0 1140{
1141 StatCounters *f;
1142 StatCounters *l;
1143 double x;
f8d264b8 1144 assert(interval > 0);
1145 if (interval > N_COUNT_HIST - 1)
1146 interval = N_COUNT_HIST - 1;
a9113eb0 1147 f = &CountHist[0];
1148 l = &CountHist[interval];
ee1679df 1149 assert(f);
1150 assert(l);
a9113eb0 1151 switch (which) {
b87b92fb 1152 case MEDIAN_HTTP:
12cf1be2 1153 x = statHistDeltaMedian(&l->client_http.all_svc_time, &f->client_http.all_svc_time);
ee1679df 1154 break;
b87b92fb 1155 case MEDIAN_HIT:
1156 x = statHistDeltaMedian(&l->client_http.hit_svc_time, &f->client_http.hit_svc_time);
1157 break;
1158 case MEDIAN_MISS:
1159 x = statHistDeltaMedian(&l->client_http.miss_svc_time, &f->client_http.miss_svc_time);
1160 break;
1161 case MEDIAN_NM:
1162 x = statHistDeltaMedian(&l->client_http.nm_svc_time, &f->client_http.nm_svc_time);
1163 break;
1164 case MEDIAN_ICP_QUERY:
12cf1be2 1165 x = statHistDeltaMedian(&l->icp.query_svc_time, &f->icp.query_svc_time);
ee1679df 1166 break;
b87b92fb 1167 case MEDIAN_DNS:
12cf1be2 1168 x = statHistDeltaMedian(&l->dns.svc_time, &f->dns.svc_time);
ee1679df 1169 break;
a9113eb0 1170 default:
ee1679df 1171 debug(49, 5) ("get_median_val: unknown type.\n");
1172 x = 0;
a9113eb0 1173 }
b87b92fb 1174 return x;
1175}
1176
1177/*
1178 * SNMP wants ints, ick
1179 */
1180int
1181get_median_svc(int interval, int which)
1182{
b644367b 1183 return (int) statMedianSvc(interval, which);
a9113eb0 1184}
451b07c5 1185
1186StatCounters *
1187snmpStatGet(int minutes)
1188{
2ac76861 1189 return &CountHist[minutes];
451b07c5 1190}
01aebf31 1191
1f3c4622 1192int
1193stat5minClientRequests(void)
1194{
5999b776 1195 assert(N_COUNT_HIST > 5);
1196 return Counter.client_http.requests - CountHist[5].client_http.requests;
1f3c4622 1197}
1198
49ad0a8c 1199static double
1200statCPUUsage(int minutes)
979533fa 1201{
49ad0a8c 1202 assert(minutes < N_COUNT_HIST);
1203 return dpercent(CountHist[0].cputime - CountHist[minutes].cputime,
1204 tvSubDsec(CountHist[minutes].timestamp, CountHist[0].timestamp));
979533fa 1205}
01aebf31 1206
1207#if STAT_GRAPHS
1208/*
1209 * urgh, i don't like these, but they do cut the amount of code down immensely
1210 */
1211
1212#define GRAPH_PER_MIN(Y) \
1213 for (i=0;i<(N_COUNT_HIST-2);i++) { \
1214 dt = tvSubDsec(CountHist[i].timestamp, CountHist[i+1].timestamp); \
1215 if (dt <= 0.0) \
1216 break; \
1217 storeAppendPrintf(e, "%lu,%0.2f:", \
1218 CountHist[i].timestamp.tv_sec, \
1219 ((CountHist[i].Y - CountHist[i+1].Y) / dt)); \
1220 }
1221
1222#define GRAPH_PER_HOUR(Y) \
1223 for (i=0;i<(N_COUNT_HOUR_HIST-2);i++) { \
1224 dt = tvSubDsec(CountHourHist[i].timestamp, CountHourHist[i+1].timestamp); \
1225 if (dt <= 0.0) \
1226 break; \
1227 storeAppendPrintf(e, "%lu,%0.2f:", \
1228 CountHourHist[i].timestamp.tv_sec, \
1229 ((CountHourHist[i].Y - CountHourHist[i+1].Y) / dt)); \
1230 }
1231
1232#define GRAPH_TITLE(X,Y) storeAppendPrintf(e,"%s\t%s\t",X,Y);
1233#define GRAPH_END storeAppendPrintf(e,"\n");
1234
1235#define GENGRAPH(X,Y,Z) \
1236 GRAPH_TITLE(Y,Z) \
1237 GRAPH_PER_MIN(X) \
1238 GRAPH_PER_HOUR(X) \
1239 GRAPH_END
1240
1241static void
1242statGraphDump(StoreEntry * e)
1243{
1244 int i;
1245 double dt;
1246
1247 GENGRAPH(client_http.requests, "client_http.requests", "Client HTTP requests/sec");
1248 GENGRAPH(client_http.hits, "client_http.hits", "Client HTTP hits/sec");
1249 GENGRAPH(client_http.errors, "client_http.errors", "Client HTTP errors/sec");
1250 GENGRAPH(client_http.kbytes_in.kb, "client_http.kbytes_in", "Client HTTP kbytes_in/sec");
1251 GENGRAPH(client_http.kbytes_out.kb, "client_http.kbytes_out", "Client HTTP kbytes_out/sec");
1252
1253 /* XXX todo: http median service times */
1254
1255 GENGRAPH(server.all.requests, "server.all.requests", "Server requests/sec");
1256 GENGRAPH(server.all.errors, "server.all.errors", "Server errors/sec");
1257 GENGRAPH(server.all.kbytes_in.kb, "server.all.kbytes_in", "Server total kbytes_in/sec");
1258 GENGRAPH(server.all.kbytes_out.kb, "server.all.kbytes_out", "Server total kbytes_out/sec");
1259
1260 GENGRAPH(server.http.requests, "server.http.requests", "Server HTTP requests/sec");
1261 GENGRAPH(server.http.errors, "server.http.errors", "Server HTTP errors/sec");
1262 GENGRAPH(server.http.kbytes_in.kb, "server.http.kbytes_in", "Server HTTP kbytes_in/sec");
1263 GENGRAPH(server.http.kbytes_out.kb, "server.http.kbytes_out", "Server HTTP kbytes_out/sec");
1264
1265 GENGRAPH(server.ftp.requests, "server.ftp.requests", "Server FTP requests/sec");
1266 GENGRAPH(server.ftp.errors, "server.ftp.errors", "Server FTP errors/sec");
1267 GENGRAPH(server.ftp.kbytes_in.kb, "server.ftp.kbytes_in", "Server FTP kbytes_in/sec");
1268 GENGRAPH(server.ftp.kbytes_out.kb, "server.ftp.kbytes_out", "Server FTP kbytes_out/sec");
1269
1270 GENGRAPH(server.other.requests, "server.other.requests", "Server other requests/sec");
1271 GENGRAPH(server.other.errors, "server.other.errors", "Server other errors/sec");
1272 GENGRAPH(server.other.kbytes_in.kb, "server.other.kbytes_in", "Server other kbytes_in/sec");
1273 GENGRAPH(server.other.kbytes_out.kb, "server.other.kbytes_out", "Server other kbytes_out/sec");
1274
1275 GENGRAPH(icp.pkts_sent, "icp.pkts_sent", "ICP packets sent/sec");
1276 GENGRAPH(icp.pkts_recv, "icp.pkts_recv", "ICP packets received/sec");
1277 GENGRAPH(icp.kbytes_sent.kb, "icp.kbytes_sent", "ICP kbytes_sent/sec");
1278 GENGRAPH(icp.kbytes_recv.kb, "icp.kbytes_recv", "ICP kbytes_received/sec");
1279
1280 /* XXX todo: icp median service times */
1281 /* XXX todo: dns median service times */
1282
1283 GENGRAPH(unlink.requests, "unlink.requests", "Cache File unlink requests/sec");
1284 GENGRAPH(page_faults, "page_faults", "System Page Faults/sec");
1285 GENGRAPH(select_loops, "select_loops", "System Select Loop calls/sec");
1286 GENGRAPH(cputime, "cputime", "CPU utilisation");
1287}
1afe05c5 1288
01aebf31 1289#endif /* STAT_GRAPHS */