]> git.ipfire.org Git - thirdparty/squid.git/blame - src/stat.cc
Author: wessels & Christos Tsantilas
[thirdparty/squid.git] / src / stat.cc
CommitLineData
30a4f2a8 1/*
47f6e231 2 * $Id: stat.cc,v 1.408 2007/08/13 17:20:51 hno Exp $
30a4f2a8 3 *
4 * DEBUG: section 18 Cache Manager Statistics
5 * AUTHOR: Harvest Derived
6 *
2b6662ba 7 * SQUID Web Proxy Cache http://www.squid-cache.org/
e25c139f 8 * ----------------------------------------------------------
30a4f2a8 9 *
2b6662ba 10 * Squid is the result of efforts by numerous individuals from
11 * the Internet community; see the CONTRIBUTORS file for full
12 * details. Many organizations have provided support for Squid's
13 * development; see the SPONSORS file for full details. Squid is
14 * Copyrighted (C) 2001 by the Regents of the University of
15 * California; see the COPYRIGHT file for full details. Squid
16 * incorporates software developed and/or copyrighted by other
17 * sources; see the CREDITS file for full details.
30a4f2a8 18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
cbdec147 31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 32 *
019dd986 33 */
ed43818f 34
44a47c6e 35#include "squid.h"
a553a5a3 36#include "event.h"
c8be6d7b 37#include "StoreClient.h"
d3f603c8 38#include "AuthUserRequest.h"
62ee09ca 39#include "CacheManager.h"
e6ccf245 40#include "Store.h"
d3f603c8 41#include "HttpRequest.h"
528b2c61 42#include "MemObject.h"
43#include "fde.h"
44#include "mem_node.h"
8faa78e6 45#if DELAY_POOLS
46#include "DelayId.h"
47#endif
528b2c61 48#include "client_side_request.h"
a46d2c0e 49#include "client_side.h"
0eb49b6d 50#include "MemBuf.h"
528b2c61 51
52/* these are included because they expose stats calls */
53/* TODO: provide a self registration mechanism for those classes
54 * to use during static construction
55 */
56#include "comm.h"
c8f4eac4 57#include "StoreSearch.h"
090089c4 58
ae94d28e 59#define DEBUG_OPENFD 1
60
1da3b90b 61typedef int STOBJFLT(const StoreEntry *);
62e76326 62
c8f4eac4 63class StatObjectsState
62e76326 64{
c8f4eac4 65
66public:
1da3b90b 67 StoreEntry *sentry;
1da3b90b 68 STOBJFLT *filter;
c8f4eac4 69 StoreSearchPointer theSearch;
70
71private:
72 CBDATA_CLASS2(StatObjectsState);
73};
62e76326 74
1da3b90b 75
67508012 76/* LOCALS */
f5b8bbc4 77static const char *describeStatuses(const StoreEntry *);
f5b8bbc4 78static const char *describeTimestamps(const StoreEntry *);
f2908497 79static void statAvgTick(void *notused);
a0f32775 80static void statAvgDump(StoreEntry *, int minutes, int hours);
01aebf31 81#if STAT_GRAPHS
82static void statGraphDump(StoreEntry *);
83#endif
12cf1be2 84static void statCountersInit(StatCounters *);
1d803566 85static void statCountersInitSpecial(StatCounters *);
12cf1be2 86static void statCountersClean(StatCounters *);
2ac76861 87static void statCountersCopy(StatCounters * dest, const StatCounters * orig);
04a28d46 88static double statPctileSvc(double, int, int);
fcc35180 89static void statStoreEntry(MemBuf * mb, StoreEntry * e);
49ad0a8c 90static double statCPUUsage(int minutes);
ed7f5615 91static OBJH stat_io_get;
92static OBJH stat_objects_get;
93static OBJH stat_vmobjects_get;
ae94d28e 94#if DEBUG_OPENFD
95static OBJH statOpenfdObj;
96#endif
1da3b90b 97static EVH statObjects;
ed7f5615 98static OBJH info_get;
071a3ae7 99static OBJH statCountersDump;
a1e927f6 100static OBJH statPeerSelect;
26b164ac 101static OBJH statDigestBlob;
ed7f5615 102static OBJH statAvg5min;
45eb7f49 103static OBJH statAvg60min;
e9b5ead4 104static OBJH statUtilization;
ba4f8e5a 105static OBJH statCountersHistograms;
0f1bc304 106static OBJH statClientRequests;
20882fb1 107
20882fb1 108#ifdef XMALLOC_STATISTICS
58cd5bbd 109static void info_get_mallstat(int, int, int, void *);
110static double xm_time;
111static double xm_deltat;
20882fb1 112#endif
30a4f2a8 113
a9113eb0 114StatCounters CountHist[N_COUNT_HIST];
d5649d9f 115static int NCountHist = 0;
a0f32775 116static StatCounters CountHourHist[N_COUNT_HOUR_HIST];
117static int NCountHourHist = 0;
c8f4eac4 118CBDATA_CLASS_INIT(StatObjectsState);
a0f32775 119
d480bbc0 120extern unsigned int mem_pool_alloc_calls;
121extern unsigned int mem_pool_free_calls;
122
5e29a294 123static void
e9b5ead4 124statUtilization(StoreEntry * e)
a0f32775 125{
126 storeAppendPrintf(e, "Cache Utilisation:\n");
127 storeAppendPrintf(e, "\n");
128 storeAppendPrintf(e, "Last 5 minutes:\n");
62e76326 129
a0f32775 130 if (NCountHist >= 5)
62e76326 131 statAvgDump(e, 5, 0);
a0f32775 132 else
62e76326 133 storeAppendPrintf(e, "(no values recorded yet)\n");
134
a0f32775 135 storeAppendPrintf(e, "\n");
62e76326 136
a0f32775 137 storeAppendPrintf(e, "Last 15 minutes:\n");
62e76326 138
a0f32775 139 if (NCountHist >= 15)
62e76326 140 statAvgDump(e, 15, 0);
a0f32775 141 else
62e76326 142 storeAppendPrintf(e, "(no values recorded yet)\n");
143
a0f32775 144 storeAppendPrintf(e, "\n");
62e76326 145
a0f32775 146 storeAppendPrintf(e, "Last hour:\n");
62e76326 147
a0f32775 148 if (NCountHist >= 60)
62e76326 149 statAvgDump(e, 60, 0);
a0f32775 150 else
62e76326 151 storeAppendPrintf(e, "(no values recorded yet)\n");
152
a0f32775 153 storeAppendPrintf(e, "\n");
62e76326 154
a0f32775 155 storeAppendPrintf(e, "Last 8 hours:\n");
62e76326 156
a0f32775 157 if (NCountHourHist >= 8)
62e76326 158 statAvgDump(e, 0, 8);
a0f32775 159 else
62e76326 160 storeAppendPrintf(e, "(no values recorded yet)\n");
161
a0f32775 162 storeAppendPrintf(e, "\n");
62e76326 163
a0f32775 164 storeAppendPrintf(e, "Last day:\n");
62e76326 165
a0f32775 166 if (NCountHourHist >= 24)
62e76326 167 statAvgDump(e, 0, 24);
a0f32775 168 else
62e76326 169 storeAppendPrintf(e, "(no values recorded yet)\n");
170
a0f32775 171 storeAppendPrintf(e, "\n");
62e76326 172
a0f32775 173 storeAppendPrintf(e, "Last 3 days:\n");
62e76326 174
a0f32775 175 if (NCountHourHist >= 72)
62e76326 176 statAvgDump(e, 0, 72);
a0f32775 177 else
62e76326 178 storeAppendPrintf(e, "(no values recorded yet)\n");
179
a0f32775 180 storeAppendPrintf(e, "\n");
62e76326 181
a0f32775 182 storeAppendPrintf(e, "Totals since cache startup:\n");
62e76326 183
a0f32775 184 statCountersDump(e);
185}
f2908497 186
5e29a294 187static void
b8d8561b 188stat_io_get(StoreEntry * sentry)
30a4f2a8 189{
190 int i;
191
15576b6a 192 storeAppendPrintf(sentry, "HTTP I/O\n");
193 storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Http.reads);
15576b6a 194 storeAppendPrintf(sentry, "Read Histogram:\n");
62e76326 195
30a4f2a8 196 for (i = 0; i < 16; i++) {
62e76326 197 storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
198 i ? (1 << (i - 1)) + 1 : 1,
199 1 << i,
200 IOStats.Http.read_hist[i],
201 percent(IOStats.Http.read_hist[i], IOStats.Http.reads));
30a4f2a8 202 }
203
15576b6a 204 storeAppendPrintf(sentry, "\n");
205 storeAppendPrintf(sentry, "FTP I/O\n");
206 storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Ftp.reads);
15576b6a 207 storeAppendPrintf(sentry, "Read Histogram:\n");
62e76326 208
30a4f2a8 209 for (i = 0; i < 16; i++) {
62e76326 210 storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
211 i ? (1 << (i - 1)) + 1 : 1,
212 1 << i,
213 IOStats.Ftp.read_hist[i],
214 percent(IOStats.Ftp.read_hist[i], IOStats.Ftp.reads));
30a4f2a8 215 }
216
15576b6a 217 storeAppendPrintf(sentry, "\n");
218 storeAppendPrintf(sentry, "Gopher I/O\n");
219 storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Gopher.reads);
15576b6a 220 storeAppendPrintf(sentry, "Read Histogram:\n");
62e76326 221
56fa4cad 222 for (i = 0; i < 16; i++) {
62e76326 223 storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
224 i ? (1 << (i - 1)) + 1 : 1,
225 1 << i,
226 IOStats.Gopher.read_hist[i],
227 percent(IOStats.Gopher.read_hist[i], IOStats.Gopher.reads));
56fa4cad 228 }
229
15576b6a 230 storeAppendPrintf(sentry, "\n");
090089c4 231}
232
0ee4272b 233static const char *
fe4e214f 234describeStatuses(const StoreEntry * entry)
d1a43e28 235{
236 LOCAL_ARRAY(char, buf, 256);
56878878 237 snprintf(buf, 256, "%-13s %-13s %-12s %-12s",
62e76326 238 storeStatusStr[entry->store_status],
239 memStatusStr[entry->mem_status],
240 swapStatusStr[entry->swap_status],
241 pingStatusStr[entry->ping_status]);
d1a43e28 242 return buf;
243}
244
415e0dd2 245const char *
246storeEntryFlags(const StoreEntry * entry)
d1a43e28 247{
248 LOCAL_ARRAY(char, buf, 256);
315005bd 249 int flags = (int) entry->flags;
d1a43e28 250 char *t;
251 buf[0] = '\0';
62e76326 252
7d94ae33 253 if (EBIT_TEST(flags, ENTRY_SPECIAL))
62e76326 254 strcat(buf, "SPECIAL,");
255
7d94ae33 256 if (EBIT_TEST(flags, ENTRY_REVALIDATE))
62e76326 257 strcat(buf, "REVALIDATE,");
258
7d94ae33 259 if (EBIT_TEST(flags, DELAY_SENDING))
62e76326 260 strcat(buf, "DELAY_SENDING,");
261
7d94ae33 262 if (EBIT_TEST(flags, RELEASE_REQUEST))
62e76326 263 strcat(buf, "RELEASE_REQUEST,");
264
7d94ae33 265 if (EBIT_TEST(flags, REFRESH_REQUEST))
62e76326 266 strcat(buf, "REFRESH_REQUEST,");
267
7d94ae33 268 if (EBIT_TEST(flags, ENTRY_CACHABLE))
62e76326 269 strcat(buf, "CACHABLE,");
270
7d94ae33 271 if (EBIT_TEST(flags, ENTRY_DISPATCHED))
62e76326 272 strcat(buf, "DISPATCHED,");
273
7d94ae33 274 if (EBIT_TEST(flags, KEY_PRIVATE))
62e76326 275 strcat(buf, "PRIVATE,");
276
05b0ef8a 277 if (EBIT_TEST(flags, ENTRY_FWD_HDR_WAIT))
62e76326 278 strcat(buf, "FWD_HDR_WAIT,");
279
7d94ae33 280 if (EBIT_TEST(flags, ENTRY_NEGCACHED))
62e76326 281 strcat(buf, "NEGCACHED,");
282
7d94ae33 283 if (EBIT_TEST(flags, ENTRY_VALIDATED))
62e76326 284 strcat(buf, "VALIDATED,");
285
7d94ae33 286 if (EBIT_TEST(flags, ENTRY_BAD_LENGTH))
62e76326 287 strcat(buf, "BAD_LENGTH,");
288
d2e002d1 289 if (EBIT_TEST(flags, ENTRY_ABORTED))
62e76326 290 strcat(buf, "ABORTED,");
291
d1a43e28 292 if ((t = strrchr(buf, ',')))
62e76326 293 *t = '\0';
294
d1a43e28 295 return buf;
296}
297
0ee4272b 298static const char *
fe4e214f 299describeTimestamps(const StoreEntry * entry)
d1a43e28 300{
301 LOCAL_ARRAY(char, buf, 256);
56878878 302 snprintf(buf, 256, "LV:%-9d LU:%-9d LM:%-9d EX:%-9d",
62e76326 303 (int) entry->timestamp,
304 (int) entry->lastref,
305 (int) entry->lastmod,
306 (int) entry->expires);
d1a43e28 307 return buf;
308}
309
b8d8561b 310static void
fcc35180 311statStoreEntry(MemBuf * mb, StoreEntry * e)
090089c4 312{
a5a5de87 313 MemObject *mem = e->mem_obj;
2fe7eff9 314 mb->Printf("KEY %s\n", e->getMD5Text());
315 mb->Printf("\t%s\n", describeStatuses(e));
316 mb->Printf("\t%s\n", storeEntryFlags(e));
317 mb->Printf("\t%s\n", describeTimestamps(e));
318 mb->Printf("\t%d locks, %d clients, %d refs\n",
319 (int) e->lock_count,
320 storePendingNClients(e),
321 (int) e->refcount);
322 mb->Printf("\tSwap Dir %d, File %#08X\n",
323 e->swap_dirn, e->swap_filen);
62e76326 324
528b2c61 325 if (mem != NULL)
fcc35180 326 mem->stat (mb);
62e76326 327
2fe7eff9 328 mb->Printf("\n");
a5a5de87 329}
330
331/* process objects list */
332static void
1da3b90b 333statObjects(void *data)
a5a5de87 334{
e6ccf245 335 StatObjectsState *state = static_cast<StatObjectsState *>(data);
1da3b90b 336 StoreEntry *e;
62e76326 337
c8f4eac4 338 if (state->theSearch->isDone()) {
62e76326 339 state->sentry->complete();
97b5e68f 340 state->sentry->unlock();
62e76326 341 cbdataFree(state);
342 return;
b7fe0ab0 343 } else if (EBIT_TEST(state->sentry->flags, ENTRY_ABORTED)) {
97b5e68f 344 state->sentry->unlock();
62e76326 345 cbdataFree(state);
346 return;
a46d2c0e 347 } else if (state->sentry->checkDeferRead(-1)) {
62e76326 348 eventAdd("statObjects", statObjects, state, 0.1, 1);
349 return;
1da3b90b 350 }
62e76326 351
3900307b 352 state->sentry->buffer();
c8f4eac4 353 size_t statCount = 0;
354 MemBuf mb;
2fe7eff9 355 mb.init();
62e76326 356
c8f4eac4 357 while (statCount++ < static_cast<size_t>(Config.Store.objectsPerBucket) && state->
358 theSearch->next()) {
359 e = state->theSearch->currentItem();
62e76326 360
c8f4eac4 361 if (state->filter && 0 == state->filter(e))
362 continue;
62e76326 363
c8f4eac4 364 statStoreEntry(&mb, e);
365 }
fcc35180 366
c8f4eac4 367 if (mb.size)
3900307b 368 state->sentry->append(mb.buf, mb.size);
2fe7eff9 369 mb.clean();
62e76326 370
1da3b90b 371 eventAdd("statObjects", statObjects, state, 0.0, 1);
a5a5de87 372}
373
5e29a294 374static void
1da3b90b 375statObjectsStart(StoreEntry * sentry, STOBJFLT * filter)
376{
c8f4eac4 377 StatObjectsState *state = new StatObjectsState;
1da3b90b 378 state->sentry = sentry;
379 state->filter = filter;
34266cde 380
381 sentry->lock()
382
383 ;
c8f4eac4 384 state->theSearch = Store::Root().search(NULL, NULL);
34266cde 385
1da3b90b 386 eventAdd("statObjects", statObjects, state, 0.0, 1);
387}
388
389static void
390stat_objects_get(StoreEntry * sentry)
391{
392 statObjectsStart(sentry, NULL);
393}
394
395static int
396statObjectsVmFilter(const StoreEntry * e)
090089c4 397{
1da3b90b 398 return e->mem_obj ? 1 : 0;
6684fec0 399}
090089c4 400
5e29a294 401static void
1da3b90b 402stat_vmobjects_get(StoreEntry * sentry)
6684fec0 403{
1da3b90b 404 statObjectsStart(sentry, statObjectsVmFilter);
090089c4 405}
406
ae94d28e 407#if DEBUG_OPENFD
1da3b90b 408static int
409statObjectsOpenfdFilter(const StoreEntry * e)
410{
411 if (e->mem_obj == NULL)
62e76326 412 return 0;
413
2391a162 414 if (e->mem_obj->swapout.sio == NULL)
62e76326 415 return 0;
416
1da3b90b 417 return 1;
418}
419
ae94d28e 420static void
421statOpenfdObj(StoreEntry * sentry)
422{
1da3b90b 423 statObjectsStart(sentry, statObjectsOpenfdFilter);
ae94d28e 424}
1da3b90b 425
ae94d28e 426#endif
427
0a0bf5db 428#ifdef XMALLOC_STATISTICS
b8d8561b 429static void
58cd5bbd 430info_get_mallstat(int size, int number, int oldnum, void *data)
30a4f2a8 431{
18f2f920 432 StoreEntry *sentry = (StoreEntry *)data;
62e76326 433
30a4f2a8 434 if (number > 0)
62e76326 435 storeAppendPrintf(sentry, "%d\t %d\t %d\t %.1f\n", size, number, number - oldnum, xdiv((number - oldnum), xm_deltat));
30a4f2a8 436}
62e76326 437
30a4f2a8 438#endif
090089c4 439
5e29a294 440static void
03eb2f01 441info_get(StoreEntry * sentry)
090089c4 442{
62e76326 443
090089c4 444 struct rusage rusage;
f2908497 445 double cputime;
446 double runtime;
88738790 447#if HAVE_MSTATS && HAVE_GNUMALLOC_H
62e76326 448
88738790 449 struct mstats ms;
eb824054 450#elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
62e76326 451
090089c4 452 struct mallinfo mp;
88738790 453 int t;
090089c4 454#endif
455
f2908497 456 runtime = tvSubDsec(squid_start, current_time);
62e76326 457
f2908497 458 if (runtime == 0.0)
62e76326 459 runtime = 1.0;
460
15576b6a 461 storeAppendPrintf(sentry, "Squid Object Cache: Version %s\n",
62e76326 462 version_string);
463
ec4daaa5 464#ifdef _SQUID_WIN32_
1a774556 465
466 if (WIN32_run_mode == _WIN_SQUID_RUN_MODE_SERVICE) {
467 storeAppendPrintf(sentry,"\nRunning as %s Windows System Service on %s\n",
468 WIN32_Service_name, WIN32_OS_string);
469 storeAppendPrintf(sentry,"Service command line is: %s\n", WIN32_Service_Command_Line);
470 } else
471 storeAppendPrintf(sentry,"Running on %s\n",WIN32_OS_string);
472
473#endif
474
15576b6a 475 storeAppendPrintf(sentry, "Start Time:\t%s\n",
62e76326 476 mkrfc1123(squid_start.tv_sec));
477
15576b6a 478 storeAppendPrintf(sentry, "Current Time:\t%s\n",
62e76326 479 mkrfc1123(current_time.tv_sec));
480
15576b6a 481 storeAppendPrintf(sentry, "Connection information for %s:\n",
62e76326 482 appname);
483
98829f69 484 storeAppendPrintf(sentry, "\tNumber of clients accessing cache:\t%u\n",
62e76326 485 statCounter.client_http.clients);
486
15576b6a 487 storeAppendPrintf(sentry, "\tNumber of HTTP requests received:\t%u\n",
62e76326 488 statCounter.client_http.requests);
489
15576b6a 490 storeAppendPrintf(sentry, "\tNumber of ICP messages received:\t%u\n",
62e76326 491 statCounter.icp.pkts_recv);
492
15576b6a 493 storeAppendPrintf(sentry, "\tNumber of ICP messages sent:\t%u\n",
62e76326 494 statCounter.icp.pkts_sent);
495
2e8e29b8 496 storeAppendPrintf(sentry, "\tNumber of queued ICP replies:\t%u\n",
62e76326 497 statCounter.icp.replies_queued);
498
c4ebc830 499#if USE_HTCP
500
501 storeAppendPrintf(sentry, "\tNumber of HTCP messages received:\t%u\n",
502 statCounter.htcp.pkts_recv);
503
504 storeAppendPrintf(sentry, "\tNumber of HTCP messages sent:\t%u\n",
505 statCounter.htcp.pkts_sent);
506
507#endif
508
a4ba1105 509 storeAppendPrintf(sentry, "\tRequest failure ratio:\t%5.2f\n",
62e76326 510 request_failure_ratio);
f2908497 511
b51b0e13 512 storeAppendPrintf(sentry, "\tAverage HTTP requests per minute since start:\t%.1f\n",
62e76326 513 statCounter.client_http.requests / (runtime / 60.0));
514
b51b0e13 515 storeAppendPrintf(sentry, "\tAverage ICP messages per minute since start:\t%.1f\n",
62e76326 516 (statCounter.icp.pkts_sent + statCounter.icp.pkts_recv) / (runtime / 60.0));
517
15576b6a 518 storeAppendPrintf(sentry, "\tSelect loop called: %d times, %0.3f ms avg\n",
62e76326 519 statCounter.select_loops, 1000.0 * runtime / statCounter.select_loops);
090089c4 520
15576b6a 521 storeAppendPrintf(sentry, "Cache information for %s:\n",
62e76326 522 appname);
523
5bf79e53 524 storeAppendPrintf(sentry, "\tHits as %% of all requests:\t5min: %3.1f%%, 60min: %3.1f%%\n",
62e76326 525 statRequestHitRatio(5),
526 statRequestHitRatio(60));
527
5bf79e53 528 storeAppendPrintf(sentry, "\tHits as %% of bytes sent:\t5min: %3.1f%%, 60min: %3.1f%%\n",
62e76326 529 statByteHitRatio(5),
530 statByteHitRatio(60));
531
5bf79e53 532 storeAppendPrintf(sentry, "\tMemory hits as %% of hit requests:\t5min: %3.1f%%, 60min: %3.1f%%\n",
62e76326 533 statRequestHitMemoryRatio(5),
534 statRequestHitMemoryRatio(60));
535
5bf79e53 536 storeAppendPrintf(sentry, "\tDisk hits as %% of hit requests:\t5min: %3.1f%%, 60min: %3.1f%%\n",
62e76326 537 statRequestHitDiskRatio(5),
538 statRequestHitDiskRatio(60));
539
e6ccf245 540 storeAppendPrintf(sentry, "\tStorage Swap size:\t%lu KB\n",
62e76326 541 store_swap_size);
542
6a52823b 543 storeAppendPrintf(sentry, "\tStorage Swap capacity:\t%4.1f%% used, %4.1f%% free\n",
544 dpercent((int) store_swap_size, (int) Store::Root().maxSize()),
545 dpercent((int) (Store::Root().maxSize() - store_swap_size), (int) Store::Root().maxSize()));
546
547
15576b6a 548 storeAppendPrintf(sentry, "\tStorage Mem size:\t%d KB\n",
62e76326 549 (int) (mem_node::store_mem_size >> 10));
550
6a52823b 551 storeAppendPrintf(sentry, "\tStorage Mem capacity:\t%4.1f%% used, %4.1f%% free\n",
552 dpercent(mem_node::InUseCount(), store_pages_max),
984ae844 553 dpercent(((double)store_pages_max - mem_node::InUseCount()), store_pages_max));
6a52823b 554
0faf70d0 555 storeAppendPrintf(sentry, "\tMean Object Size:\t%0.2f KB\n",
62e76326 556 n_disk_objects ? (double) store_swap_size / n_disk_objects : 0.0);
557
15576b6a 558 storeAppendPrintf(sentry, "\tRequests given to unlinkd:\t%d\n",
62e76326 559 statCounter.unlink.requests);
090089c4 560
b87b92fb 561 storeAppendPrintf(sentry, "Median Service Times (seconds) 5 min 60 min:\n");
62e76326 562
b87b92fb 563 storeAppendPrintf(sentry, "\tHTTP Requests (All): %8.5f %8.5f\n",
04a28d46 564 statPctileSvc(0.5, 5, PCTILE_HTTP) / 1000.0,
565 statPctileSvc(0.5, 60, PCTILE_HTTP) / 1000.0);
62e76326 566
b87b92fb 567 storeAppendPrintf(sentry, "\tCache Misses: %8.5f %8.5f\n",
04a28d46 568 statPctileSvc(0.5, 5, PCTILE_MISS) / 1000.0,
569 statPctileSvc(0.5, 60, PCTILE_MISS) / 1000.0);
62e76326 570
b87b92fb 571 storeAppendPrintf(sentry, "\tCache Hits: %8.5f %8.5f\n",
04a28d46 572 statPctileSvc(0.5, 5, PCTILE_HIT) / 1000.0,
573 statPctileSvc(0.5, 60, PCTILE_HIT) / 1000.0);
62e76326 574
7c9c84ad 575 storeAppendPrintf(sentry, "\tNear Hits: %8.5f %8.5f\n",
04a28d46 576 statPctileSvc(0.5, 5, PCTILE_NH) / 1000.0,
577 statPctileSvc(0.5, 60, PCTILE_NH) / 1000.0);
62e76326 578
b87b92fb 579 storeAppendPrintf(sentry, "\tNot-Modified Replies: %8.5f %8.5f\n",
04a28d46 580 statPctileSvc(0.5, 5, PCTILE_NM) / 1000.0,
581 statPctileSvc(0.5, 60, PCTILE_NM) / 1000.0);
62e76326 582
b87b92fb 583 storeAppendPrintf(sentry, "\tDNS Lookups: %8.5f %8.5f\n",
04a28d46 584 statPctileSvc(0.5, 5, PCTILE_DNS) / 1000.0,
585 statPctileSvc(0.5, 60, PCTILE_DNS) / 1000.0);
62e76326 586
b87b92fb 587 storeAppendPrintf(sentry, "\tICP Queries: %8.5f %8.5f\n",
04a28d46 588 statPctileSvc(0.5, 5, PCTILE_ICP_QUERY) / 1000000.0,
589 statPctileSvc(0.5, 60, PCTILE_ICP_QUERY) / 1000000.0);
b87b92fb 590
f2908497 591 squid_getrusage(&rusage);
62e76326 592
f2908497 593 cputime = rusage_cputime(&rusage);
62e76326 594
15576b6a 595 storeAppendPrintf(sentry, "Resource usage for %s:\n", appname);
62e76326 596
15576b6a 597 storeAppendPrintf(sentry, "\tUP Time:\t%.3f seconds\n", runtime);
62e76326 598
15576b6a 599 storeAppendPrintf(sentry, "\tCPU Time:\t%.3f seconds\n", cputime);
62e76326 600
15576b6a 601 storeAppendPrintf(sentry, "\tCPU Usage:\t%.2f%%\n",
62e76326 602 dpercent(cputime, runtime));
603
979533fa 604 storeAppendPrintf(sentry, "\tCPU Usage, 5 minute avg:\t%.2f%%\n",
62e76326 605 statCPUUsage(5));
606
49ad0a8c 607 storeAppendPrintf(sentry, "\tCPU Usage, 60 minute avg:\t%.2f%%\n",
62e76326 608 statCPUUsage(60));
609
a4ba1105 610#if HAVE_SBRK
62e76326 611
a4ba1105 612 storeAppendPrintf(sentry, "\tProcess Data Segment Size via sbrk(): %d KB\n",
62e76326 613 (int) (((char *) sbrk(0) - (char *) sbrk_start) >> 10));
614
a4ba1105 615#endif
62e76326 616
5f6ac48b 617 storeAppendPrintf(sentry, "\tMaximum Resident Size: %d KB\n",
62e76326 618 rusage_maxrss(&rusage));
619
5f6ac48b 620 storeAppendPrintf(sentry, "\tPage faults with physical i/o: %d\n",
62e76326 621 rusage_pagefaults(&rusage));
090089c4 622
88738790 623#if HAVE_MSTATS && HAVE_GNUMALLOC_H
62e76326 624
88738790 625 ms = mstats();
62e76326 626
15576b6a 627 storeAppendPrintf(sentry, "Memory usage for %s via mstats():\n",
62e76326 628 appname);
629
15576b6a 630 storeAppendPrintf(sentry, "\tTotal space in arena: %6d KB\n",
62e76326 631 ms.bytes_total >> 10);
632
15576b6a 633 storeAppendPrintf(sentry, "\tTotal free: %6d KB %d%%\n",
62e76326 634 ms.bytes_free >> 10, percent(ms.bytes_free, ms.bytes_total));
635
eb824054 636#elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
62e76326 637
090089c4 638 mp = mallinfo();
62e76326 639
15576b6a 640 storeAppendPrintf(sentry, "Memory usage for %s via mallinfo():\n",
62e76326 641 appname);
642
e4049756 643 storeAppendPrintf(sentry, "\tTotal space in arena: %6ld KB\n",
644 (long)mp.arena >> 10);
62e76326 645
e4049756 646 storeAppendPrintf(sentry, "\tOrdinary blocks: %6ld KB %6ld blks\n",
647 (long)mp.uordblks >> 10, (long)mp.ordblks);
62e76326 648
e4049756 649 storeAppendPrintf(sentry, "\tSmall blocks: %6ld KB %6ld blks\n",
650 (long)mp.usmblks >> 10, (long)mp.smblks);
62e76326 651
e4049756 652 storeAppendPrintf(sentry, "\tHolding blocks: %6ld KB %6ld blks\n",
653 (long)mp.hblkhd >> 10, (long)mp.hblks);
62e76326 654
e4049756 655 storeAppendPrintf(sentry, "\tFree Small blocks: %6ld KB\n",
656 (long)mp.fsmblks >> 10);
62e76326 657
e4049756 658 storeAppendPrintf(sentry, "\tFree Ordinary blocks: %6ld KB\n",
659 (long)mp.fordblks >> 10);
62e76326 660
30a4f2a8 661 t = mp.uordblks + mp.usmblks + mp.hblkhd;
62e76326 662
15576b6a 663 storeAppendPrintf(sentry, "\tTotal in use: %6d KB %d%%\n",
62e76326 664 t >> 10, percent(t, mp.arena + mp.hblkhd));
665
30a4f2a8 666 t = mp.fsmblks + mp.fordblks;
62e76326 667
15576b6a 668 storeAppendPrintf(sentry, "\tTotal free: %6d KB %d%%\n",
62e76326 669 t >> 10, percent(t, mp.arena + mp.hblkhd));
670
d96ceb8e 671 t = mp.arena + mp.hblkhd;
62e76326 672
d96ceb8e 673 storeAppendPrintf(sentry, "\tTotal size: %6d KB\n",
62e76326 674 t >> 10);
675
6a9f6389 676#if HAVE_STRUCT_MALLINFO_MXFAST
62e76326 677
15576b6a 678 storeAppendPrintf(sentry, "\tmax size of small blocks:\t%d\n", mp.mxfast);
62e76326 679
15576b6a 680 storeAppendPrintf(sentry, "\tnumber of small blocks in a holding block:\t%d\n",
62e76326 681 mp.nlblks);
682
15576b6a 683 storeAppendPrintf(sentry, "\tsmall block rounding factor:\t%d\n", mp.grain);
62e76326 684
15576b6a 685 storeAppendPrintf(sentry, "\tspace (including overhead) allocated in ord. blks:\t%d\n"
62e76326 686 ,mp.uordbytes);
687
15576b6a 688 storeAppendPrintf(sentry, "\tnumber of ordinary blocks allocated:\t%d\n",
62e76326 689 mp.allocated);
690
15576b6a 691 storeAppendPrintf(sentry, "\tbytes used in maintaining the free tree:\t%d\n",
62e76326 692 mp.treeoverhead);
693
6a9f6389 694#endif /* HAVE_STRUCT_MALLINFO_MXFAST */
50bc2565 695#endif /* HAVE_MALLINFO */
62e76326 696
5d1f3c82 697 storeAppendPrintf(sentry, "Memory accounted for:\n");
62e76326 698
d96ceb8e 699#if !(HAVE_MSTATS && HAVE_GNUMALLOC_H) && HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
62e76326 700
d96ceb8e 701 storeAppendPrintf(sentry, "\tTotal accounted: %6d KB %3d%%\n",
62e76326 702 statMemoryAccounted() >> 10, percent(statMemoryAccounted(), t));
703
d96ceb8e 704#else
62e76326 705
979533fa 706 storeAppendPrintf(sentry, "\tTotal accounted: %6d KB\n",
62e76326 707 statMemoryAccounted() >> 10);
708
d96ceb8e 709#endif
710 {
62e76326 711 MemPoolGlobalStats mp_stats;
712 memPoolGetGlobalStats(&mp_stats);
1ce8e204 713#if !(HAVE_MSTATS && HAVE_GNUMALLOC_H) && HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
62e76326 714
715 storeAppendPrintf(sentry, "\tmemPool accounted: %6d KB %3d%%\n",
e4049756 716 (int) mp_stats.TheMeter->alloc.level >> 10,
717 percent(mp_stats.TheMeter->alloc.level, t));
62e76326 718 storeAppendPrintf(sentry, "\tmemPool unaccounted: %6d KB %3d%%\n",
e4049756 719 (t - (int) mp_stats.TheMeter->alloc.level) >> 10,
720 percent((t - mp_stats.TheMeter->alloc.level), t));
1ce8e204 721#endif
62e76326 722
723 storeAppendPrintf(sentry, "\tmemPoolAlloc calls: %9.0f\n",
724 mp_stats.TheMeter->gb_saved.count);
725 storeAppendPrintf(sentry, "\tmemPoolFree calls: %9.0f\n",
726 mp_stats.TheMeter->gb_freed.count);
d96ceb8e 727 }
62e76326 728
15576b6a 729 storeAppendPrintf(sentry, "File descriptor usage for %s:\n", appname);
730 storeAppendPrintf(sentry, "\tMaximum number of file descriptors: %4d\n",
62e76326 731 Squid_MaxFD);
15576b6a 732 storeAppendPrintf(sentry, "\tLargest file desc currently in use: %4d\n",
62e76326 733 Biggest_FD);
15576b6a 734 storeAppendPrintf(sentry, "\tNumber of file desc currently in use: %4d\n",
62e76326 735 Number_FD);
b6a2f15e 736 storeAppendPrintf(sentry, "\tFiles queued for open: %4d\n",
62e76326 737 Opening_FD);
15576b6a 738 storeAppendPrintf(sentry, "\tAvailable number of file descriptors: %4d\n",
62e76326 739 fdNFree());
15576b6a 740 storeAppendPrintf(sentry, "\tReserved number of file descriptors: %4d\n",
62e76326 741 RESERVED_FD);
83a29c95 742 storeAppendPrintf(sentry, "\tStore Disk files open: %4d\n",
62e76326 743 store_open_disk_fd);
090089c4 744
15576b6a 745 storeAppendPrintf(sentry, "Internal Data Structures:\n");
08433d3c 746 storeAppendPrintf(sentry, "\t%6lu StoreEntries\n",
62e76326 747 (unsigned long)StoreEntry::inUseCount());
528b2c61 748 storeAppendPrintf(sentry, "\t%6lu StoreEntries with MemObjects\n",
62e76326 749 (unsigned long)MemObject::inUseCount());
15576b6a 750 storeAppendPrintf(sentry, "\t%6d Hot Object Cache Items\n",
62e76326 751 hot_obj_count);
0b2e785a 752 storeAppendPrintf(sentry, "\t%6d on-disk objects\n",
62e76326 753 n_disk_objects);
30a4f2a8 754
755#if XMALLOC_STATISTICS
62e76326 756
58cd5bbd 757 xm_deltat = current_dtime - xm_time;
758 xm_time = current_dtime;
759 storeAppendPrintf(sentry, "\nMemory allocation statistics\n");
760 storeAppendPrintf(sentry, "Allocation Size\t Alloc Count\t Alloc Delta\t Allocs/sec \n");
30a4f2a8 761 malloc_statistics(info_get_mallstat, sentry);
762#endif
090089c4 763}
764
04a28d46 765static void
766service_times(StoreEntry * sentry)
767{
768 int p;
769 storeAppendPrintf(sentry, "Service Time Percentiles 5 min 60 min:\n");
770 for (p = 5; p < 100; p += 5) {
771 storeAppendPrintf(sentry, "\tHTTP Requests (All): %2d%% %8.5f %8.5f\n",
772 p,
773 statPctileSvc((double) p / 100.0, 5, PCTILE_HTTP) / 1000.0,
774 statPctileSvc((double) p / 100.0, 60, PCTILE_HTTP) / 1000.0);
775 }
776 for (p = 5; p < 100; p += 5) {
777 storeAppendPrintf(sentry, "\tCache Misses: %2d%% %8.5f %8.5f\n",
778 p,
779 statPctileSvc((double) p / 100.0, 5, PCTILE_MISS) / 1000.0,
780 statPctileSvc((double) p / 100.0, 60, PCTILE_MISS) / 1000.0);
781 }
782 for (p = 5; p < 100; p += 5) {
783 storeAppendPrintf(sentry, "\tCache Hits: %2d%% %8.5f %8.5f\n",
784 p,
785 statPctileSvc((double) p / 100.0, 5, PCTILE_HIT) / 1000.0,
786 statPctileSvc((double) p / 100.0, 60, PCTILE_HIT) / 1000.0);
787 }
788 for (p = 5; p < 100; p += 5) {
789 storeAppendPrintf(sentry, "\tNear Hits: %2d%% %8.5f %8.5f\n",
790 p,
791 statPctileSvc((double) p / 100.0, 5, PCTILE_NH) / 1000.0,
792 statPctileSvc((double) p / 100.0, 60, PCTILE_NH) / 1000.0);
793 }
794 for (p = 5; p < 100; p += 5) {
795 storeAppendPrintf(sentry, "\tNot-Modified Replies: %2d%% %8.5f %8.5f\n",
796 p,
797 statPctileSvc((double) p / 100.0, 5, PCTILE_NM) / 1000.0,
798 statPctileSvc((double) p / 100.0, 60, PCTILE_NM) / 1000.0);
799 }
800 for (p = 5; p < 100; p += 5) {
801 storeAppendPrintf(sentry, "\tDNS Lookups: %2d%% %8.5f %8.5f\n",
802 p,
803 statPctileSvc((double) p / 100.0, 5, PCTILE_DNS) / 1000.0,
804 statPctileSvc((double) p / 100.0, 60, PCTILE_DNS) / 1000.0);
805 }
806 for (p = 5; p < 100; p += 5) {
807 storeAppendPrintf(sentry, "\tICP Queries: %2d%% %8.5f %8.5f\n",
808 p,
809 statPctileSvc((double) p / 100.0, 5, PCTILE_ICP_QUERY) / 1000000.0,
810 statPctileSvc((double) p / 100.0, 60, PCTILE_ICP_QUERY) / 1000000.0);
811 }
812}
813
a7c05555 814#define XAVG(X) (dt ? (double) (f->X - l->X) / dt : 0.0)
b8d8561b 815static void
a0f32775 816statAvgDump(StoreEntry * sentry, int minutes, int hours)
090089c4 817{
a7c05555 818 StatCounters *f;
819 StatCounters *l;
820 double dt;
821 double ct;
7ae52c25 822 double x;
a7c05555 823 assert(N_COUNT_HIST > 1);
a0f32775 824 assert(minutes > 0 || hours > 0);
a7c05555 825 f = &CountHist[0];
a0f32775 826 l = f;
62e76326 827
a0f32775 828 if (minutes > 0 && hours == 0) {
62e76326 829 /* checking minute readings ... */
830
831 if (minutes > N_COUNT_HIST - 1)
832 minutes = N_COUNT_HIST - 1;
833
834 l = &CountHist[minutes];
a0f32775 835 } else if (minutes == 0 && hours > 0) {
62e76326 836 /* checking hour readings ... */
837
838 if (hours > N_COUNT_HOUR_HIST - 1)
839 hours = N_COUNT_HOUR_HIST - 1;
840
841 l = &CountHourHist[hours];
a0f32775 842 } else {
bf8fe701 843 debugs(18, 1, "statAvgDump: Invalid args, minutes=" << minutes << ", hours=" << hours);
62e76326 844 return;
a0f32775 845 }
62e76326 846
a7c05555 847 dt = tvSubDsec(l->timestamp, f->timestamp);
848 ct = f->cputime - l->cputime;
ee1679df 849
399e85ea 850 storeAppendPrintf(sentry, "sample_start_time = %d.%d (%s)\n",
62e76326 851 (int) l->timestamp.tv_sec,
852 (int) l->timestamp.tv_usec,
853 mkrfc1123(l->timestamp.tv_sec));
5843f24a 854 storeAppendPrintf(sentry, "sample_end_time = %d.%d (%s)\n",
62e76326 855 (int) f->timestamp.tv_sec,
856 (int) f->timestamp.tv_usec,
857 mkrfc1123(f->timestamp.tv_sec));
a0f32775 858
a7c05555 859 storeAppendPrintf(sentry, "client_http.requests = %f/sec\n",
62e76326 860 XAVG(client_http.requests));
a7c05555 861 storeAppendPrintf(sentry, "client_http.hits = %f/sec\n",
62e76326 862 XAVG(client_http.hits));
a7c05555 863 storeAppendPrintf(sentry, "client_http.errors = %f/sec\n",
62e76326 864 XAVG(client_http.errors));
a7c05555 865 storeAppendPrintf(sentry, "client_http.kbytes_in = %f/sec\n",
62e76326 866 XAVG(client_http.kbytes_in.kb));
a7c05555 867 storeAppendPrintf(sentry, "client_http.kbytes_out = %f/sec\n",
62e76326 868 XAVG(client_http.kbytes_out.kb));
ee1679df 869
12cf1be2 870 x = statHistDeltaMedian(&l->client_http.all_svc_time,
62e76326 871 &f->client_http.all_svc_time);
ee1679df 872 storeAppendPrintf(sentry, "client_http.all_median_svc_time = %f seconds\n",
62e76326 873 x / 1000.0);
12cf1be2 874 x = statHistDeltaMedian(&l->client_http.miss_svc_time,
62e76326 875 &f->client_http.miss_svc_time);
ee1679df 876 storeAppendPrintf(sentry, "client_http.miss_median_svc_time = %f seconds\n",
62e76326 877 x / 1000.0);
12cf1be2 878 x = statHistDeltaMedian(&l->client_http.nm_svc_time,
62e76326 879 &f->client_http.nm_svc_time);
ee1679df 880 storeAppendPrintf(sentry, "client_http.nm_median_svc_time = %f seconds\n",
62e76326 881 x / 1000.0);
7c9c84ad 882 x = statHistDeltaMedian(&l->client_http.nh_svc_time,
62e76326 883 &f->client_http.nh_svc_time);
7c9c84ad 884 storeAppendPrintf(sentry, "client_http.nh_median_svc_time = %f seconds\n",
62e76326 885 x / 1000.0);
12cf1be2 886 x = statHistDeltaMedian(&l->client_http.hit_svc_time,
62e76326 887 &f->client_http.hit_svc_time);
ee1679df 888 storeAppendPrintf(sentry, "client_http.hit_median_svc_time = %f seconds\n",
62e76326 889 x / 1000.0);
071a3ae7 890
a0f32775 891 storeAppendPrintf(sentry, "server.all.requests = %f/sec\n",
62e76326 892 XAVG(server.all.requests));
a0f32775 893 storeAppendPrintf(sentry, "server.all.errors = %f/sec\n",
62e76326 894 XAVG(server.all.errors));
a0f32775 895 storeAppendPrintf(sentry, "server.all.kbytes_in = %f/sec\n",
62e76326 896 XAVG(server.all.kbytes_in.kb));
a0f32775 897 storeAppendPrintf(sentry, "server.all.kbytes_out = %f/sec\n",
62e76326 898 XAVG(server.all.kbytes_out.kb));
a0f32775 899
900 storeAppendPrintf(sentry, "server.http.requests = %f/sec\n",
62e76326 901 XAVG(server.http.requests));
a0f32775 902 storeAppendPrintf(sentry, "server.http.errors = %f/sec\n",
62e76326 903 XAVG(server.http.errors));
a0f32775 904 storeAppendPrintf(sentry, "server.http.kbytes_in = %f/sec\n",
62e76326 905 XAVG(server.http.kbytes_in.kb));
a0f32775 906 storeAppendPrintf(sentry, "server.http.kbytes_out = %f/sec\n",
62e76326 907 XAVG(server.http.kbytes_out.kb));
a0f32775 908
909 storeAppendPrintf(sentry, "server.ftp.requests = %f/sec\n",
62e76326 910 XAVG(server.ftp.requests));
a0f32775 911 storeAppendPrintf(sentry, "server.ftp.errors = %f/sec\n",
62e76326 912 XAVG(server.ftp.errors));
a0f32775 913 storeAppendPrintf(sentry, "server.ftp.kbytes_in = %f/sec\n",
62e76326 914 XAVG(server.ftp.kbytes_in.kb));
a0f32775 915 storeAppendPrintf(sentry, "server.ftp.kbytes_out = %f/sec\n",
62e76326 916 XAVG(server.ftp.kbytes_out.kb));
a0f32775 917
918 storeAppendPrintf(sentry, "server.other.requests = %f/sec\n",
62e76326 919 XAVG(server.other.requests));
a0f32775 920 storeAppendPrintf(sentry, "server.other.errors = %f/sec\n",
62e76326 921 XAVG(server.other.errors));
a0f32775 922 storeAppendPrintf(sentry, "server.other.kbytes_in = %f/sec\n",
62e76326 923 XAVG(server.other.kbytes_in.kb));
a0f32775 924 storeAppendPrintf(sentry, "server.other.kbytes_out = %f/sec\n",
62e76326 925 XAVG(server.other.kbytes_out.kb));
ee1679df 926
a7c05555 927 storeAppendPrintf(sentry, "icp.pkts_sent = %f/sec\n",
62e76326 928 XAVG(icp.pkts_sent));
a7c05555 929 storeAppendPrintf(sentry, "icp.pkts_recv = %f/sec\n",
62e76326 930 XAVG(icp.pkts_recv));
071a3ae7 931 storeAppendPrintf(sentry, "icp.queries_sent = %f/sec\n",
62e76326 932 XAVG(icp.queries_sent));
071a3ae7 933 storeAppendPrintf(sentry, "icp.replies_sent = %f/sec\n",
62e76326 934 XAVG(icp.replies_sent));
071a3ae7 935 storeAppendPrintf(sentry, "icp.queries_recv = %f/sec\n",
62e76326 936 XAVG(icp.queries_recv));
071a3ae7 937 storeAppendPrintf(sentry, "icp.replies_recv = %f/sec\n",
62e76326 938 XAVG(icp.replies_recv));
2e8e29b8 939 storeAppendPrintf(sentry, "icp.replies_queued = %f/sec\n",
62e76326 940 XAVG(icp.replies_queued));
071a3ae7 941 storeAppendPrintf(sentry, "icp.query_timeouts = %f/sec\n",
62e76326 942 XAVG(icp.query_timeouts));
a7c05555 943 storeAppendPrintf(sentry, "icp.kbytes_sent = %f/sec\n",
62e76326 944 XAVG(icp.kbytes_sent.kb));
a7c05555 945 storeAppendPrintf(sentry, "icp.kbytes_recv = %f/sec\n",
62e76326 946 XAVG(icp.kbytes_recv.kb));
071a3ae7 947 storeAppendPrintf(sentry, "icp.q_kbytes_sent = %f/sec\n",
62e76326 948 XAVG(icp.q_kbytes_sent.kb));
071a3ae7 949 storeAppendPrintf(sentry, "icp.r_kbytes_sent = %f/sec\n",
62e76326 950 XAVG(icp.r_kbytes_sent.kb));
071a3ae7 951 storeAppendPrintf(sentry, "icp.q_kbytes_recv = %f/sec\n",
62e76326 952 XAVG(icp.q_kbytes_recv.kb));
071a3ae7 953 storeAppendPrintf(sentry, "icp.r_kbytes_recv = %f/sec\n",
62e76326 954 XAVG(icp.r_kbytes_recv.kb));
12cf1be2 955 x = statHistDeltaMedian(&l->icp.query_svc_time, &f->icp.query_svc_time);
ee1679df 956 storeAppendPrintf(sentry, "icp.query_median_svc_time = %f seconds\n",
62e76326 957 x / 1000000.0);
12cf1be2 958 x = statHistDeltaMedian(&l->icp.reply_svc_time, &f->icp.reply_svc_time);
ee1679df 959 storeAppendPrintf(sentry, "icp.reply_median_svc_time = %f seconds\n",
62e76326 960 x / 1000000.0);
12cf1be2 961 x = statHistDeltaMedian(&l->dns.svc_time, &f->dns.svc_time);
9973e9fe 962 storeAppendPrintf(sentry, "dns.median_svc_time = %f seconds\n",
62e76326 963 x / 1000.0);
a7c05555 964 storeAppendPrintf(sentry, "unlink.requests = %f/sec\n",
62e76326 965 XAVG(unlink.requests));
a7c05555 966 storeAppendPrintf(sentry, "page_faults = %f/sec\n",
62e76326 967 XAVG(page_faults));
a7c05555 968 storeAppendPrintf(sentry, "select_loops = %f/sec\n",
62e76326 969 XAVG(select_loops));
d239c2f5 970 storeAppendPrintf(sentry, "select_fds = %f/sec\n",
62e76326 971 XAVG(select_fds));
d239c2f5 972 storeAppendPrintf(sentry, "average_select_fd_period = %f/fd\n",
62e76326 973 f->select_fds > l->select_fds ?
974 (f->select_time - l->select_time) / (f->select_fds - l->select_fds)
975 : 0.0);
26d6ee93 976 x = statHistDeltaMedian(&l->select_fds_hist, &f->select_fds_hist);
977 storeAppendPrintf(sentry, "median_select_fds = %f\n", x);
23dc8aca 978 storeAppendPrintf(sentry, "swap.outs = %f/sec\n",
62e76326 979 XAVG(swap.outs));
23dc8aca 980 storeAppendPrintf(sentry, "swap.ins = %f/sec\n",
62e76326 981 XAVG(swap.ins));
23dc8aca 982 storeAppendPrintf(sentry, "swap.files_cleaned = %f/sec\n",
62e76326 983 XAVG(swap.files_cleaned));
bfae3379 984 storeAppendPrintf(sentry, "aborted_requests = %f/sec\n",
62e76326 985 XAVG(aborted_requests));
886f2785 986
1b3db6d9 987#if USE_POLL
62e76326 988
886f2785 989 storeAppendPrintf(sentry, "syscalls.polls = %f/sec\n", XAVG(syscalls.polls));
1b3db6d9 990#endif
98348c69 991#if defined(USE_SELECT) || defined(USE_SELECT_WIN32)
62e76326 992
886f2785 993 storeAppendPrintf(sentry, "syscalls.selects = %f/sec\n", XAVG(syscalls.selects));
994#endif
62e76326 995
886f2785 996 storeAppendPrintf(sentry, "syscalls.disk.opens = %f/sec\n", XAVG(syscalls.disk.opens));
997 storeAppendPrintf(sentry, "syscalls.disk.closes = %f/sec\n", XAVG(syscalls.disk.closes));
998 storeAppendPrintf(sentry, "syscalls.disk.reads = %f/sec\n", XAVG(syscalls.disk.reads));
999 storeAppendPrintf(sentry, "syscalls.disk.writes = %f/sec\n", XAVG(syscalls.disk.writes));
1000 storeAppendPrintf(sentry, "syscalls.disk.seeks = %f/sec\n", XAVG(syscalls.disk.seeks));
bfae3379 1001 storeAppendPrintf(sentry, "syscalls.disk.unlinks = %f/sec\n", XAVG(syscalls.disk.unlinks));
886f2785 1002 storeAppendPrintf(sentry, "syscalls.sock.accepts = %f/sec\n", XAVG(syscalls.sock.accepts));
1003 storeAppendPrintf(sentry, "syscalls.sock.sockets = %f/sec\n", XAVG(syscalls.sock.sockets));
1004 storeAppendPrintf(sentry, "syscalls.sock.connects = %f/sec\n", XAVG(syscalls.sock.connects));
1005 storeAppendPrintf(sentry, "syscalls.sock.binds = %f/sec\n", XAVG(syscalls.sock.binds));
1006 storeAppendPrintf(sentry, "syscalls.sock.closes = %f/sec\n", XAVG(syscalls.sock.closes));
1007 storeAppendPrintf(sentry, "syscalls.sock.reads = %f/sec\n", XAVG(syscalls.sock.reads));
1008 storeAppendPrintf(sentry, "syscalls.sock.writes = %f/sec\n", XAVG(syscalls.sock.writes));
1009 storeAppendPrintf(sentry, "syscalls.sock.recvfroms = %f/sec\n", XAVG(syscalls.sock.recvfroms));
1010 storeAppendPrintf(sentry, "syscalls.sock.sendtos = %f/sec\n", XAVG(syscalls.sock.sendtos));
1011
a7c05555 1012 storeAppendPrintf(sentry, "cpu_time = %f seconds\n", ct);
1013 storeAppendPrintf(sentry, "wall_time = %f seconds\n", dt);
0e473d70 1014 storeAppendPrintf(sentry, "cpu_usage = %f%%\n", dpercent(ct, dt));
090089c4 1015}
1016
979533fa 1017
b8d8561b 1018void
a7c05555 1019statInit(void)
090089c4 1020{
090089c4 1021 int i;
bf8fe701 1022 debugs(18, 5, "statInit: Initializing...");
62e76326 1023
0e473d70 1024 for (i = 0; i < N_COUNT_HIST; i++)
62e76326 1025 statCountersInit(&CountHist[i]);
1026
a0f32775 1027 for (i = 0; i < N_COUNT_HOUR_HIST; i++)
62e76326 1028 statCountersInit(&CountHourHist[i]);
1029
83704487 1030 statCountersInit(&statCounter);
62e76326 1031
52040193 1032 eventAdd("statAvgTick", statAvgTick, NULL, (double) COUNT_INTERVAL, 1);
62e76326 1033
62ee09ca 1034 ClientActiveRequests.head = NULL;
1035
1036 ClientActiveRequests.tail = NULL;
1037}
62e76326 1038
62ee09ca 1039void
1040statRegisterWithCacheManager(CacheManager & manager)
1041{
1042 manager.registerAction("info",
1043 "General Runtime Information",
1044 info_get, 0, 1);
62e76326 1045
04a28d46 1046 manager.registerAction("service_times",
1047 "Service Times (Percentiles)",
1048 service_times, 0, 1);
1049
62ee09ca 1050 manager.registerAction("filedescriptors",
1051 "Process Filedescriptor Allocation",
1052 fde::DumpStats, 0, 1);
62e76326 1053
62ee09ca 1054 manager.registerAction("objects",
1055 "All Cache Objects",
1056 stat_objects_get, 0, 0);
1057
1058 manager.registerAction("vm_objects",
1059 "In-Memory and In-Transit Objects",
1060 stat_vmobjects_get, 0, 0);
62e76326 1061
ae94d28e 1062#if DEBUG_OPENFD
62e76326 1063
62ee09ca 1064 manager.registerAction("openfd_objects",
1065 "Objects with Swapout files open",
1066 statOpenfdObj, 0, 0);
62e76326 1067
ae94d28e 1068#endif
62e76326 1069
62ee09ca 1070 manager.registerAction("io",
1071 "Server-side network read() size histograms",
1072 stat_io_get, 0, 1);
62e76326 1073
62ee09ca 1074 manager.registerAction("counters",
1075 "Traffic and Resource Counters",
1076 statCountersDump, 0, 1);
62e76326 1077
62ee09ca 1078 manager.registerAction("peer_select",
1079 "Peer Selection Algorithms",
1080 statPeerSelect, 0, 1);
62e76326 1081
62ee09ca 1082 manager.registerAction("digest_stats",
1083 "Cache Digest and ICP blob",
1084 statDigestBlob, 0, 1);
62e76326 1085
62ee09ca 1086 manager.registerAction("5min",
1087 "5 Minute Average of Counters",
1088 statAvg5min, 0, 1);
62e76326 1089
62ee09ca 1090 manager.registerAction("60min",
1091 "60 Minute Average of Counters",
1092 statAvg60min, 0, 1);
62e76326 1093
62ee09ca 1094 manager.registerAction("utilization",
1095 "Cache Utilization",
1096 statUtilization, 0, 1);
62e76326 1097
01aebf31 1098#if STAT_GRAPHS
62e76326 1099
62ee09ca 1100 manager.registerAction("graph_variables",
1101 "Display cache metrics graphically",
1102 statGraphDump, 0, 1);
62e76326 1103
01aebf31 1104#endif
62e76326 1105
62ee09ca 1106 manager.registerAction("histograms",
1107 "Full Histogram Counts",
1108 statCountersHistograms, 0, 1);
62e76326 1109
62ee09ca 1110 manager.registerAction("active_requests",
1111 "Client-side Active Requests",
1112 statClientRequests, 0, 1);
090089c4 1113}
f2908497 1114
f2908497 1115static void
1116statAvgTick(void *notused)
1117{
d5649d9f 1118 StatCounters *t = &CountHist[0];
1119 StatCounters *p = &CountHist[1];
83704487 1120 StatCounters *c = &statCounter;
62e76326 1121
f2908497 1122 struct rusage rusage;
b6a2f15e 1123 eventAdd("statAvgTick", statAvgTick, NULL, (double) COUNT_INTERVAL, 1);
20903cac 1124 squid_getrusage(&rusage);
1125 c->page_faults = rusage_pagefaults(&rusage);
1126 c->cputime = rusage_cputime(&rusage);
d5649d9f 1127 c->timestamp = current_time;
12cf1be2 1128 /* even if NCountHist is small, we already Init()ed the tail */
2ac76861 1129 statCountersClean(CountHist + N_COUNT_HIST - 1);
dbfed404 1130 xmemmove(p, t, (N_COUNT_HIST - 1) * sizeof(StatCounters));
12cf1be2 1131 statCountersCopy(t, c);
d5649d9f 1132 NCountHist++;
a0f32775 1133
1134 if ((NCountHist % COUNT_INTERVAL) == 0) {
62e76326 1135 /* we have an hours worth of readings. store previous hour */
1136 StatCounters *t = &CountHourHist[0];
1137 StatCounters *p = &CountHourHist[1];
1138 StatCounters *c = &CountHist[N_COUNT_HIST - 1];
1139 statCountersClean(CountHourHist + N_COUNT_HOUR_HIST - 1);
1140 xmemmove(p, t, (N_COUNT_HOUR_HIST - 1) * sizeof(StatCounters));
1141 statCountersCopy(t, c);
1142 NCountHourHist++;
a0f32775 1143 }
62e76326 1144
b8a46de0 1145 if (Config.warnings.high_rptm > 0) {
04a28d46 1146 int i = (int) statPctileSvc(0.5, 20, PCTILE_HTTP);
62e76326 1147
1148 if (Config.warnings.high_rptm < i)
bf8fe701 1149 debugs(18, 0, "WARNING: Median response time is " << i << " milliseconds");
b8a46de0 1150 }
62e76326 1151
b8a46de0 1152 if (Config.warnings.high_pf) {
62e76326 1153 int i = (CountHist[0].page_faults - CountHist[1].page_faults);
1154 double dt = tvSubDsec(CountHist[0].timestamp, CountHist[1].timestamp);
1155
1156 if (i > 0 && dt > 0.0) {
1157 i /= (int) dt;
1158
1159 if (Config.warnings.high_pf < i)
bf8fe701 1160 debugs(18, 0, "WARNING: Page faults occuring at " << i << "/sec");
62e76326 1161 }
b8a46de0 1162 }
62e76326 1163
b8a46de0 1164 if (Config.warnings.high_memory) {
62e76326 1165 size_t i = 0;
b8a46de0 1166#if HAVE_MSTATS && HAVE_GNUMALLOC_H
62e76326 1167
1168 struct mstats ms = mstats();
1169 i = ms.bytes_total;
b8a46de0 1170#elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
62e76326 1171
1172 struct mallinfo mp = mallinfo();
1173 i = mp.arena;
703cc8e8 1174#elif HAVE_SBRK
1175
1176 i = (size_t) ((char *) sbrk(0) - (char *) sbrk_start);
b8a46de0 1177#endif
62e76326 1178
1179 if (Config.warnings.high_memory < i)
bf8fe701 1180 debugs(18, 0, "WARNING: Memory usage at " << ((unsigned long int)(i >> 20)) << " MB");
b8a46de0 1181 }
20903cac 1182}
1183
12cf1be2 1184static void
2ac76861 1185statCountersInit(StatCounters * C)
20903cac 1186{
12cf1be2 1187 assert(C);
1d803566 1188 memset(C, 0, sizeof(*C));
12cf1be2 1189 C->timestamp = current_time;
1d803566 1190 statCountersInitSpecial(C);
1191}
1192
1193/* add special cases here as they arrive */
1194static void
2ac76861 1195statCountersInitSpecial(StatCounters * C)
1d803566 1196{
12cf1be2 1197 /*
1198 * HTTP svc_time hist is kept in milli-seconds; max of 3 hours.
1199 */
1200 statHistLogInit(&C->client_http.all_svc_time, 300, 0.0, 3600000.0 * 3.0);
1201 statHistLogInit(&C->client_http.miss_svc_time, 300, 0.0, 3600000.0 * 3.0);
1202 statHistLogInit(&C->client_http.nm_svc_time, 300, 0.0, 3600000.0 * 3.0);
7c9c84ad 1203 statHistLogInit(&C->client_http.nh_svc_time, 300, 0.0, 3600000.0 * 3.0);
12cf1be2 1204 statHistLogInit(&C->client_http.hit_svc_time, 300, 0.0, 3600000.0 * 3.0);
1205 /*
1206 * ICP svc_time hist is kept in micro-seconds; max of 1 minute.
1207 */
1208 statHistLogInit(&C->icp.query_svc_time, 300, 0.0, 1000000.0 * 60.0);
1209 statHistLogInit(&C->icp.reply_svc_time, 300, 0.0, 1000000.0 * 60.0);
1210 /*
1211 * DNS svc_time hist is kept in milli-seconds; max of 10 minutes.
1212 */
1213 statHistLogInit(&C->dns.svc_time, 300, 0.0, 60000.0 * 10.0);
a1e927f6 1214 /*
69c95dd3 1215 * Cache Digest Stuff
a1e927f6 1216 */
0c511722 1217 statHistEnumInit(&C->cd.on_xition_count, CacheDigestHashFuncCount);
c6ecdbc3 1218 statHistEnumInit(&C->comm_icp_incoming, INCOMING_ICP_MAX);
ef523f99 1219 statHistEnumInit(&C->comm_dns_incoming, INCOMING_DNS_MAX);
c6ecdbc3 1220 statHistEnumInit(&C->comm_http_incoming, INCOMING_HTTP_MAX);
b671cc68 1221 statHistIntInit(&C->select_fds_hist, 256); /* was SQUID_MAXFD, but it is way too much. It is OK to crop this statistics */
0f5607d9 1222}
1223
12cf1be2 1224/* add special cases here as they arrive */
5e29a294 1225static void
2ac76861 1226statCountersClean(StatCounters * C)
0f5607d9 1227{
12cf1be2 1228 assert(C);
1229 statHistClean(&C->client_http.all_svc_time);
1230 statHistClean(&C->client_http.miss_svc_time);
1231 statHistClean(&C->client_http.nm_svc_time);
7c9c84ad 1232 statHistClean(&C->client_http.nh_svc_time);
12cf1be2 1233 statHistClean(&C->client_http.hit_svc_time);
1234 statHistClean(&C->icp.query_svc_time);
1235 statHistClean(&C->icp.reply_svc_time);
1236 statHistClean(&C->dns.svc_time);
c135694e 1237 statHistClean(&C->cd.on_xition_count);
c6ecdbc3 1238 statHistClean(&C->comm_icp_incoming);
a56906d4 1239 statHistClean(&C->comm_dns_incoming);
c6ecdbc3 1240 statHistClean(&C->comm_http_incoming);
26d6ee93 1241 statHistClean(&C->select_fds_hist);
a7c05555 1242}
1243
12cf1be2 1244/* add special cases here as they arrive */
5e29a294 1245static void
2ac76861 1246statCountersCopy(StatCounters * dest, const StatCounters * orig)
45eb7f49 1247{
12cf1be2 1248 assert(dest && orig);
1d803566 1249 /* this should take care of all the fields, but "special" ones */
cac03dd2 1250 xmemcpy(dest, orig, sizeof(*dest));
1d803566 1251 /* prepare space where to copy special entries */
1252 statCountersInitSpecial(dest);
1253 /* now handle special cases */
1254 /* note: we assert that histogram capacities do not change */
12cf1be2 1255 statHistCopy(&dest->client_http.all_svc_time, &orig->client_http.all_svc_time);
1256 statHistCopy(&dest->client_http.miss_svc_time, &orig->client_http.miss_svc_time);
1257 statHistCopy(&dest->client_http.nm_svc_time, &orig->client_http.nm_svc_time);
7c9c84ad 1258 statHistCopy(&dest->client_http.nh_svc_time, &orig->client_http.nh_svc_time);
12cf1be2 1259 statHistCopy(&dest->client_http.hit_svc_time, &orig->client_http.hit_svc_time);
1260 statHistCopy(&dest->icp.query_svc_time, &orig->icp.query_svc_time);
1261 statHistCopy(&dest->icp.reply_svc_time, &orig->icp.reply_svc_time);
1262 statHistCopy(&dest->dns.svc_time, &orig->dns.svc_time);
c135694e 1263 statHistCopy(&dest->cd.on_xition_count, &orig->cd.on_xition_count);
c6ecdbc3 1264 statHistCopy(&dest->comm_icp_incoming, &orig->comm_icp_incoming);
1265 statHistCopy(&dest->comm_http_incoming, &orig->comm_http_incoming);
26d6ee93 1266 statHistCopy(&dest->select_fds_hist, &orig->select_fds_hist);
45eb7f49 1267}
1268
071a3ae7 1269static void
5d406e78 1270statCountersHistograms(StoreEntry * sentry)
071a3ae7 1271{
83704487 1272 StatCounters *f = &statCounter;
071a3ae7 1273 storeAppendPrintf(sentry, "client_http.all_svc_time histogram:\n");
1274 statHistDump(&f->client_http.all_svc_time, sentry, NULL);
1275 storeAppendPrintf(sentry, "client_http.miss_svc_time histogram:\n");
1276 statHistDump(&f->client_http.miss_svc_time, sentry, NULL);
1277 storeAppendPrintf(sentry, "client_http.nm_svc_time histogram:\n");
1278 statHistDump(&f->client_http.nm_svc_time, sentry, NULL);
7c9c84ad 1279 storeAppendPrintf(sentry, "client_http.nh_svc_time histogram:\n");
1280 statHistDump(&f->client_http.nh_svc_time, sentry, NULL);
071a3ae7 1281 storeAppendPrintf(sentry, "client_http.hit_svc_time histogram:\n");
1282 statHistDump(&f->client_http.hit_svc_time, sentry, NULL);
071a3ae7 1283 storeAppendPrintf(sentry, "icp.query_svc_time histogram:\n");
1284 statHistDump(&f->icp.query_svc_time, sentry, NULL);
1285 storeAppendPrintf(sentry, "icp.reply_svc_time histogram:\n");
1286 statHistDump(&f->icp.reply_svc_time, sentry, NULL);
1287 storeAppendPrintf(sentry, "dns.svc_time histogram:\n");
1288 statHistDump(&f->dns.svc_time, sentry, NULL);
2a73b7cb 1289 storeAppendPrintf(sentry, "select_fds_hist histogram:\n");
1290 statHistDump(&f->select_fds_hist, sentry, NULL);
071a3ae7 1291}
1292
12cf1be2 1293static void
1294statCountersDump(StoreEntry * sentry)
7ae52c25 1295{
83704487 1296 StatCounters *f = &statCounter;
62e76326 1297
12cf1be2 1298 struct rusage rusage;
1299 squid_getrusage(&rusage);
1300 f->page_faults = rusage_pagefaults(&rusage);
1301 f->cputime = rusage_cputime(&rusage);
1302
a0f32775 1303 storeAppendPrintf(sentry, "sample_time = %d.%d (%s)\n",
62e76326 1304 (int) f->timestamp.tv_sec,
1305 (int) f->timestamp.tv_usec,
1306 mkrfc1123(f->timestamp.tv_sec));
12cf1be2 1307 storeAppendPrintf(sentry, "client_http.requests = %d\n",
62e76326 1308 f->client_http.requests);
12cf1be2 1309 storeAppendPrintf(sentry, "client_http.hits = %d\n",
62e76326 1310 f->client_http.hits);
12cf1be2 1311 storeAppendPrintf(sentry, "client_http.errors = %d\n",
62e76326 1312 f->client_http.errors);
12cf1be2 1313 storeAppendPrintf(sentry, "client_http.kbytes_in = %d\n",
62e76326 1314 (int) f->client_http.kbytes_in.kb);
12cf1be2 1315 storeAppendPrintf(sentry, "client_http.kbytes_out = %d\n",
62e76326 1316 (int) f->client_http.kbytes_out.kb);
c68e9c6b 1317 storeAppendPrintf(sentry, "client_http.hit_kbytes_out = %d\n",
62e76326 1318 (int) f->client_http.hit_kbytes_out.kb);
0567f2a6 1319
a0f32775 1320 storeAppendPrintf(sentry, "server.all.requests = %d\n",
62e76326 1321 (int) f->server.all.requests);
a0f32775 1322 storeAppendPrintf(sentry, "server.all.errors = %d\n",
62e76326 1323 (int) f->server.all.errors);
a0f32775 1324 storeAppendPrintf(sentry, "server.all.kbytes_in = %d\n",
62e76326 1325 (int) f->server.all.kbytes_in.kb);
a0f32775 1326 storeAppendPrintf(sentry, "server.all.kbytes_out = %d\n",
62e76326 1327 (int) f->server.all.kbytes_out.kb);
a0f32775 1328
1329 storeAppendPrintf(sentry, "server.http.requests = %d\n",
62e76326 1330 (int) f->server.http.requests);
a0f32775 1331 storeAppendPrintf(sentry, "server.http.errors = %d\n",
62e76326 1332 (int) f->server.http.errors);
a0f32775 1333 storeAppendPrintf(sentry, "server.http.kbytes_in = %d\n",
62e76326 1334 (int) f->server.http.kbytes_in.kb);
a0f32775 1335 storeAppendPrintf(sentry, "server.http.kbytes_out = %d\n",
62e76326 1336 (int) f->server.http.kbytes_out.kb);
a0f32775 1337
1338 storeAppendPrintf(sentry, "server.ftp.requests = %d\n",
62e76326 1339 (int) f->server.ftp.requests);
a0f32775 1340 storeAppendPrintf(sentry, "server.ftp.errors = %d\n",
62e76326 1341 (int) f->server.ftp.errors);
a0f32775 1342 storeAppendPrintf(sentry, "server.ftp.kbytes_in = %d\n",
62e76326 1343 (int) f->server.ftp.kbytes_in.kb);
a0f32775 1344 storeAppendPrintf(sentry, "server.ftp.kbytes_out = %d\n",
62e76326 1345 (int) f->server.ftp.kbytes_out.kb);
a0f32775 1346
1347 storeAppendPrintf(sentry, "server.other.requests = %d\n",
62e76326 1348 (int) f->server.other.requests);
a0f32775 1349 storeAppendPrintf(sentry, "server.other.errors = %d\n",
62e76326 1350 (int) f->server.other.errors);
a0f32775 1351 storeAppendPrintf(sentry, "server.other.kbytes_in = %d\n",
62e76326 1352 (int) f->server.other.kbytes_in.kb);
a0f32775 1353 storeAppendPrintf(sentry, "server.other.kbytes_out = %d\n",
62e76326 1354 (int) f->server.other.kbytes_out.kb);
12cf1be2 1355
1356 storeAppendPrintf(sentry, "icp.pkts_sent = %d\n",
62e76326 1357 f->icp.pkts_sent);
12cf1be2 1358 storeAppendPrintf(sentry, "icp.pkts_recv = %d\n",
62e76326 1359 f->icp.pkts_recv);
071a3ae7 1360 storeAppendPrintf(sentry, "icp.queries_sent = %d\n",
62e76326 1361 f->icp.queries_sent);
071a3ae7 1362 storeAppendPrintf(sentry, "icp.replies_sent = %d\n",
62e76326 1363 f->icp.replies_sent);
071a3ae7 1364 storeAppendPrintf(sentry, "icp.queries_recv = %d\n",
62e76326 1365 f->icp.queries_recv);
071a3ae7 1366 storeAppendPrintf(sentry, "icp.replies_recv = %d\n",
62e76326 1367 f->icp.replies_recv);
071a3ae7 1368 storeAppendPrintf(sentry, "icp.query_timeouts = %d\n",
62e76326 1369 f->icp.query_timeouts);
2e8e29b8 1370 storeAppendPrintf(sentry, "icp.replies_queued = %d\n",
62e76326 1371 f->icp.replies_queued);
12cf1be2 1372 storeAppendPrintf(sentry, "icp.kbytes_sent = %d\n",
62e76326 1373 (int) f->icp.kbytes_sent.kb);
12cf1be2 1374 storeAppendPrintf(sentry, "icp.kbytes_recv = %d\n",
62e76326 1375 (int) f->icp.kbytes_recv.kb);
071a3ae7 1376 storeAppendPrintf(sentry, "icp.q_kbytes_sent = %d\n",
62e76326 1377 (int) f->icp.q_kbytes_sent.kb);
071a3ae7 1378 storeAppendPrintf(sentry, "icp.r_kbytes_sent = %d\n",
62e76326 1379 (int) f->icp.r_kbytes_sent.kb);
071a3ae7 1380 storeAppendPrintf(sentry, "icp.q_kbytes_recv = %d\n",
62e76326 1381 (int) f->icp.q_kbytes_recv.kb);
071a3ae7 1382 storeAppendPrintf(sentry, "icp.r_kbytes_recv = %d\n",
62e76326 1383 (int) f->icp.r_kbytes_recv.kb);
0567f2a6 1384
6cfa8966 1385#if USE_CACHE_DIGESTS
62e76326 1386
071a3ae7 1387 storeAppendPrintf(sentry, "icp.times_used = %d\n",
62e76326 1388 f->icp.times_used);
071a3ae7 1389 storeAppendPrintf(sentry, "cd.times_used = %d\n",
62e76326 1390 f->cd.times_used);
00485c29 1391 storeAppendPrintf(sentry, "cd.msgs_sent = %d\n",
62e76326 1392 f->cd.msgs_sent);
00485c29 1393 storeAppendPrintf(sentry, "cd.msgs_recv = %d\n",
62e76326 1394 f->cd.msgs_recv);
071a3ae7 1395 storeAppendPrintf(sentry, "cd.memory = %d\n",
62e76326 1396 (int) f->cd.memory.kb);
522b517b 1397 storeAppendPrintf(sentry, "cd.local_memory = %d\n",
62e76326 1398 (int) (store_digest ? store_digest->mask_size / 1024 : 0));
00485c29 1399 storeAppendPrintf(sentry, "cd.kbytes_sent = %d\n",
62e76326 1400 (int) f->cd.kbytes_sent.kb);
00485c29 1401 storeAppendPrintf(sentry, "cd.kbytes_recv = %d\n",
62e76326 1402 (int) f->cd.kbytes_recv.kb);
0567f2a6 1403#endif
1404
12cf1be2 1405 storeAppendPrintf(sentry, "unlink.requests = %d\n",
62e76326 1406 f->unlink.requests);
12cf1be2 1407 storeAppendPrintf(sentry, "page_faults = %d\n",
62e76326 1408 f->page_faults);
12cf1be2 1409 storeAppendPrintf(sentry, "select_loops = %d\n",
62e76326 1410 f->select_loops);
12cf1be2 1411 storeAppendPrintf(sentry, "cpu_time = %f\n",
62e76326 1412 f->cputime);
12cf1be2 1413 storeAppendPrintf(sentry, "wall_time = %f\n",
62e76326 1414 tvSubDsec(f->timestamp, current_time));
23dc8aca 1415 storeAppendPrintf(sentry, "swap.outs = %d\n",
62e76326 1416 f->swap.outs);
23dc8aca 1417 storeAppendPrintf(sentry, "swap.ins = %d\n",
62e76326 1418 f->swap.ins);
23dc8aca 1419 storeAppendPrintf(sentry, "swap.files_cleaned = %d\n",
62e76326 1420 f->swap.files_cleaned);
bfae3379 1421 storeAppendPrintf(sentry, "aborted_requests = %d\n",
62e76326 1422 f->aborted_requests);
7ae52c25 1423}
1424
d2db411c 1425void
1426statFreeMemory(void)
1427{
1428 int i;
62e76326 1429
d2db411c 1430 for (i = 0; i < N_COUNT_HIST; i++)
62e76326 1431 statCountersClean(&CountHist[i]);
1432
d2db411c 1433 for (i = 0; i < N_COUNT_HOUR_HIST; i++)
62e76326 1434 statCountersClean(&CountHourHist[i]);
d2db411c 1435}
1436
5e29a294 1437static void
a1e927f6 1438statPeerSelect(StoreEntry * sentry)
1439{
6cfa8966 1440#if USE_CACHE_DIGESTS
83704487 1441 StatCounters *f = &statCounter;
a1e927f6 1442 peer *peer;
1443 const int tot_used = f->cd.times_used + f->icp.times_used;
1444
1445 /* totals */
1446 cacheDigestGuessStatsReport(&f->cd.guess, sentry, "all peers");
1447 /* per-peer */
1448 storeAppendPrintf(sentry, "\nPer-peer statistics:\n");
62e76326 1449
a1e927f6 1450 for (peer = getFirstPeer(); peer; peer = getNextPeer(peer)) {
62e76326 1451 if (peer->digest)
1452 peerDigestStatsReport(peer->digest, sentry);
1453 else
1454 storeAppendPrintf(sentry, "\nNo peer digest from %s\n", peer->host);
1455
1456 storeAppendPrintf(sentry, "\n");
a1e927f6 1457 }
1458
1459 storeAppendPrintf(sentry, "\nAlgorithm usage:\n");
1460 storeAppendPrintf(sentry, "Cache Digest: %7d (%3d%%)\n",
62e76326 1461 f->cd.times_used, xpercentInt(f->cd.times_used, tot_used));
a1e927f6 1462 storeAppendPrintf(sentry, "Icp: %7d (%3d%%)\n",
62e76326 1463 f->icp.times_used, xpercentInt(f->icp.times_used, tot_used));
a1e927f6 1464 storeAppendPrintf(sentry, "Total: %7d (%3d%%)\n",
62e76326 1465 tot_used, xpercentInt(tot_used, tot_used));
a1e927f6 1466#else
62e76326 1467
a1e927f6 1468 storeAppendPrintf(sentry, "peer digests are disabled; no stats is available.\n");
1469#endif
1470}
1471
1472static void
26b164ac 1473statDigestBlob(StoreEntry * sentry)
1474{
071a3ae7 1475 storeAppendPrintf(sentry, "\nCounters:\n");
1476 statCountersDump(sentry);
86e2a291 1477 storeAppendPrintf(sentry, "\n5 Min Averages:\n");
1478 statAvgDump(sentry, 5, 0);
071a3ae7 1479 storeAppendPrintf(sentry, "\nHistograms:\n");
1480 statCountersHistograms(sentry);
1481 storeAppendPrintf(sentry, "\nPeer Digests:\n");
26b164ac 1482 statPeerSelect(sentry);
588d9545 1483 storeAppendPrintf(sentry, "\nLocal Digest:\n");
26b164ac 1484 storeDigestReport(sentry);
1485}
1486
5e29a294 1487static void
12cf1be2 1488statAvg5min(StoreEntry * e)
7ae52c25 1489{
a0f32775 1490 statAvgDump(e, 5, 0);
7ae52c25 1491}
1492
5e29a294 1493static void
12cf1be2 1494statAvg60min(StoreEntry * e)
7ae52c25 1495{
a0f32775 1496 statAvgDump(e, 60, 0);
7ae52c25 1497}
1498
7d94ae33 1499static double
04a28d46 1500statPctileSvc(double pctile, int interval, int which)
a9113eb0 1501{
1502 StatCounters *f;
1503 StatCounters *l;
1504 double x;
f8d264b8 1505 assert(interval > 0);
62e76326 1506
f8d264b8 1507 if (interval > N_COUNT_HIST - 1)
62e76326 1508 interval = N_COUNT_HIST - 1;
1509
a9113eb0 1510 f = &CountHist[0];
62e76326 1511
a9113eb0 1512 l = &CountHist[interval];
62e76326 1513
ee1679df 1514 assert(f);
62e76326 1515
ee1679df 1516 assert(l);
62e76326 1517
a9113eb0 1518 switch (which) {
62e76326 1519
04a28d46 1520 case PCTILE_HTTP:
1521 x = statHistDeltaPctile(&l->client_http.all_svc_time, &f->client_http.all_svc_time, pctile);
62e76326 1522 break;
1523
04a28d46 1524 case PCTILE_HIT:
1525 x = statHistDeltaPctile(&l->client_http.hit_svc_time, &f->client_http.hit_svc_time, pctile);
62e76326 1526 break;
1527
04a28d46 1528 case PCTILE_MISS:
1529 x = statHistDeltaPctile(&l->client_http.miss_svc_time, &f->client_http.miss_svc_time, pctile);
62e76326 1530 break;
1531
04a28d46 1532 case PCTILE_NM:
1533 x = statHistDeltaPctile(&l->client_http.nm_svc_time, &f->client_http.nm_svc_time, pctile);
62e76326 1534 break;
1535
04a28d46 1536 case PCTILE_NH:
1537 x = statHistDeltaPctile(&l->client_http.nh_svc_time, &f->client_http.nh_svc_time, pctile);
62e76326 1538 break;
1539
04a28d46 1540 case PCTILE_ICP_QUERY:
1541 x = statHistDeltaPctile(&l->icp.query_svc_time, &f->icp.query_svc_time, pctile);
62e76326 1542 break;
1543
04a28d46 1544 case PCTILE_DNS:
1545 x = statHistDeltaPctile(&l->dns.svc_time, &f->dns.svc_time, pctile);
62e76326 1546 break;
1547
a9113eb0 1548 default:
bf8fe701 1549 debugs(49, 5, "statPctileSvc: unknown type.");
62e76326 1550 x = 0;
a9113eb0 1551 }
62e76326 1552
b87b92fb 1553 return x;
1554}
1555
451b07c5 1556StatCounters *
1557snmpStatGet(int minutes)
1558{
2ac76861 1559 return &CountHist[minutes];
451b07c5 1560}
01aebf31 1561
1f3c4622 1562int
1563stat5minClientRequests(void)
1564{
5999b776 1565 assert(N_COUNT_HIST > 5);
83704487 1566 return statCounter.client_http.requests - CountHist[5].client_http.requests;
1f3c4622 1567}
1568
49ad0a8c 1569static double
1570statCPUUsage(int minutes)
979533fa 1571{
49ad0a8c 1572 assert(minutes < N_COUNT_HIST);
1573 return dpercent(CountHist[0].cputime - CountHist[minutes].cputime,
62e76326 1574 tvSubDsec(CountHist[minutes].timestamp, CountHist[0].timestamp));
979533fa 1575}
01aebf31 1576
1d5b6d43 1577extern double
62e76326 1578 statRequestHitRatio(int minutes)
491a980b 1579{
1580 assert(minutes < N_COUNT_HIST);
1581 return dpercent(CountHist[0].client_http.hits -
62e76326 1582 CountHist[minutes].client_http.hits,
1583 CountHist[0].client_http.requests -
1584 CountHist[minutes].client_http.requests);
491a980b 1585}
1586
4f4d1d6e 1587extern double
62e76326 1588 statRequestHitMemoryRatio(int minutes)
4f4d1d6e 1589{
1590 assert(minutes < N_COUNT_HIST);
1591 return dpercent(CountHist[0].client_http.mem_hits -
62e76326 1592 CountHist[minutes].client_http.mem_hits,
1593 CountHist[0].client_http.hits -
1594 CountHist[minutes].client_http.hits);
4f4d1d6e 1595}
1596
1597extern double
62e76326 1598 statRequestHitDiskRatio(int minutes)
4f4d1d6e 1599{
1600 assert(minutes < N_COUNT_HIST);
1601 return dpercent(CountHist[0].client_http.disk_hits -
62e76326 1602 CountHist[minutes].client_http.disk_hits,
1603 CountHist[0].client_http.hits -
1604 CountHist[minutes].client_http.hits);
4f4d1d6e 1605}
1606
1d5b6d43 1607extern double
62e76326 1608 statByteHitRatio(int minutes)
491a980b 1609{
1610 size_t s;
1611 size_t c;
ac342231 1612#if USE_CACHE_DIGESTS
62e76326 1613
ac342231 1614 size_t cd;
1615#endif
1616 /* size_t might be unsigned */
491a980b 1617 assert(minutes < N_COUNT_HIST);
1618 c = CountHist[0].client_http.kbytes_out.kb - CountHist[minutes].client_http.kbytes_out.kb;
1619 s = CountHist[0].server.all.kbytes_in.kb - CountHist[minutes].server.all.kbytes_in.kb;
ac342231 1620#if USE_CACHE_DIGESTS
1621 /*
1622 * This ugly hack is here to prevent the user from seeing a
1623 * negative byte hit ratio. When we fetch a cache digest from
1624 * a neighbor, it gets treated like a cache miss because the
1625 * object is consumed internally. Thus, we subtract cache
1626 * digest bytes out before calculating the byte hit ratio.
1627 */
1628 cd = CountHist[0].cd.kbytes_recv.kb - CountHist[minutes].cd.kbytes_recv.kb;
62e76326 1629
49d7ce5f 1630 if (s < cd)
e4049756 1631 debugs(18, 1, "STRANGE: srv_kbytes=" << s << ", cd_kbytes=" << cd);
62e76326 1632
ac342231 1633 s -= cd;
62e76326 1634
ac342231 1635#endif
62e76326 1636
94e56ef7 1637 if (c > s)
62e76326 1638 return dpercent(c - s, c);
94e56ef7 1639 else
62e76326 1640 return (-1.0 * dpercent(s - c, c));
491a980b 1641}
1642
0f1bc304 1643static void
1644statClientRequests(StoreEntry * s)
1645{
1646 dlink_node *i;
59a1efb2 1647 ClientHttpRequest *http;
0f1bc304 1648 StoreEntry *e;
1649 int fd;
62e76326 1650
0f1bc304 1651 for (i = ClientActiveRequests.head; i; i = i->next) {
f4bd6296 1652 const char *p = NULL;
59a1efb2 1653 http = static_cast<ClientHttpRequest *>(i->data);
62e76326 1654 assert(http);
a2ac85d9 1655 ConnStateData::Pointer conn = http->getConn();
1656 storeAppendPrintf(s, "Connection: %p\n", conn.getRaw());
62e76326 1657
85a4b153 1658 if (conn != NULL) {
62e76326 1659 fd = conn->fd;
47f6e231 1660 storeAppendPrintf(s, "\tFD %d, read %"PRId64", wrote %"PRId64"\n", fd,
62e76326 1661 fd_table[fd].bytes_read, fd_table[fd].bytes_written);
1662 storeAppendPrintf(s, "\tFD desc: %s\n", fd_table[fd].desc);
1663 storeAppendPrintf(s, "\tin: buf %p, offset %ld, size %ld\n",
1664 conn->in.buf, (long int) conn->in.notYetUsed, (long int) conn->in.allocatedSize);
1665 storeAppendPrintf(s, "\tpeer: %s:%d\n",
1666 inet_ntoa(conn->peer.sin_addr),
1667 ntohs(conn->peer.sin_port));
1668 storeAppendPrintf(s, "\tme: %s:%d\n",
1669 inet_ntoa(conn->me.sin_addr),
1670 ntohs(conn->me.sin_port));
1671 storeAppendPrintf(s, "\tnrequests: %d\n",
1672 conn->nrequests);
62e76326 1673 }
1674
1675 storeAppendPrintf(s, "uri %s\n", http->uri);
1676 storeAppendPrintf(s, "logType %s\n", log_tags[http->logType]);
1677 storeAppendPrintf(s, "out.offset %ld, out.size %lu\n",
1678 (long int) http->out.offset, (unsigned long int) http->out.size);
1679 storeAppendPrintf(s, "req_sz %ld\n", (long int) http->req_sz);
86a2f789 1680 e = http->storeEntry();
62e76326 1681 storeAppendPrintf(s, "entry %p/%s\n", e, e ? e->getMD5Text() : "N/A");
0655fa4d 1682#if 0
1683 /* Not a member anymore */
62e76326 1684 e = http->old_entry;
1685 storeAppendPrintf(s, "old_entry %p/%s\n", e, e ? e->getMD5Text() : "N/A");
0655fa4d 1686#endif
1687
62e76326 1688 storeAppendPrintf(s, "start %ld.%06d (%f seconds ago)\n",
1689 (long int) http->start.tv_sec,
1690 (int) http->start.tv_usec,
1691 tvSubDsec(http->start, current_time));
8faa78e6 1692
f4bd6296 1693 if (http->request->auth_user_request)
d3f603c8 1694 p = http->request->auth_user_request->username();
30abd221 1695 else if (http->request->extacl_user.buf() != NULL) {
1696 p = http->request->extacl_user.buf();
f4bd6296 1697 }
d3f603c8 1698
85a4b153 1699 if (!p && (conn != NULL && conn->rfc931[0]))
f4bd6296 1700 p = conn->rfc931;
d3f603c8 1701
f4bd6296 1702#if USE_SSL
1703
85a4b153 1704 if (!p && conn != NULL)
f4bd6296 1705 p = sslGetUserEmail(fd_table[conn->fd].ssl);
1706
1707#endif
1708
1709 if (!p)
1710 p = dash_str;
1711
1712 storeAppendPrintf(s, "username %s\n", p);
d3f603c8 1713
1714#if DELAY_POOLS
f4bd6296 1715
8faa78e6 1716 storeAppendPrintf(s, "delay_pool %d\n", DelayId::DelayClient(http) >> 16);
d3f603c8 1717
8faa78e6 1718#endif
1719
62e76326 1720 storeAppendPrintf(s, "\n");
0f1bc304 1721 }
1722}
1723
01aebf31 1724#if STAT_GRAPHS
1725/*
1726 * urgh, i don't like these, but they do cut the amount of code down immensely
1727 */
1728
1729#define GRAPH_PER_MIN(Y) \
1730 for (i=0;i<(N_COUNT_HIST-2);i++) { \
79d15b05 1731 dt = tvSubDsec(CountHist[i+1].timestamp, CountHist[i].timestamp); \
01aebf31 1732 if (dt <= 0.0) \
1733 break; \
1734 storeAppendPrintf(e, "%lu,%0.2f:", \
1735 CountHist[i].timestamp.tv_sec, \
1736 ((CountHist[i].Y - CountHist[i+1].Y) / dt)); \
1737 }
1738
1739#define GRAPH_PER_HOUR(Y) \
1740 for (i=0;i<(N_COUNT_HOUR_HIST-2);i++) { \
79d15b05 1741 dt = tvSubDsec(CountHourHist[i+1].timestamp, CountHourHist[i].timestamp); \
01aebf31 1742 if (dt <= 0.0) \
1743 break; \
1744 storeAppendPrintf(e, "%lu,%0.2f:", \
1745 CountHourHist[i].timestamp.tv_sec, \
1746 ((CountHourHist[i].Y - CountHourHist[i+1].Y) / dt)); \
1747 }
1748
1749#define GRAPH_TITLE(X,Y) storeAppendPrintf(e,"%s\t%s\t",X,Y);
1750#define GRAPH_END storeAppendPrintf(e,"\n");
1751
1752#define GENGRAPH(X,Y,Z) \
1753 GRAPH_TITLE(Y,Z) \
1754 GRAPH_PER_MIN(X) \
1755 GRAPH_PER_HOUR(X) \
1756 GRAPH_END
1757
1758static void
1759statGraphDump(StoreEntry * e)
1760{
1761 int i;
1762 double dt;
1763
1764 GENGRAPH(client_http.requests, "client_http.requests", "Client HTTP requests/sec");
1765 GENGRAPH(client_http.hits, "client_http.hits", "Client HTTP hits/sec");
1766 GENGRAPH(client_http.errors, "client_http.errors", "Client HTTP errors/sec");
1767 GENGRAPH(client_http.kbytes_in.kb, "client_http.kbytes_in", "Client HTTP kbytes_in/sec");
1768 GENGRAPH(client_http.kbytes_out.kb, "client_http.kbytes_out", "Client HTTP kbytes_out/sec");
1769
1770 /* XXX todo: http median service times */
1771
1772 GENGRAPH(server.all.requests, "server.all.requests", "Server requests/sec");
1773 GENGRAPH(server.all.errors, "server.all.errors", "Server errors/sec");
1774 GENGRAPH(server.all.kbytes_in.kb, "server.all.kbytes_in", "Server total kbytes_in/sec");
1775 GENGRAPH(server.all.kbytes_out.kb, "server.all.kbytes_out", "Server total kbytes_out/sec");
1776
1777 GENGRAPH(server.http.requests, "server.http.requests", "Server HTTP requests/sec");
1778 GENGRAPH(server.http.errors, "server.http.errors", "Server HTTP errors/sec");
1779 GENGRAPH(server.http.kbytes_in.kb, "server.http.kbytes_in", "Server HTTP kbytes_in/sec");
1780 GENGRAPH(server.http.kbytes_out.kb, "server.http.kbytes_out", "Server HTTP kbytes_out/sec");
1781
1782 GENGRAPH(server.ftp.requests, "server.ftp.requests", "Server FTP requests/sec");
1783 GENGRAPH(server.ftp.errors, "server.ftp.errors", "Server FTP errors/sec");
1784 GENGRAPH(server.ftp.kbytes_in.kb, "server.ftp.kbytes_in", "Server FTP kbytes_in/sec");
1785 GENGRAPH(server.ftp.kbytes_out.kb, "server.ftp.kbytes_out", "Server FTP kbytes_out/sec");
1786
1787 GENGRAPH(server.other.requests, "server.other.requests", "Server other requests/sec");
1788 GENGRAPH(server.other.errors, "server.other.errors", "Server other errors/sec");
1789 GENGRAPH(server.other.kbytes_in.kb, "server.other.kbytes_in", "Server other kbytes_in/sec");
1790 GENGRAPH(server.other.kbytes_out.kb, "server.other.kbytes_out", "Server other kbytes_out/sec");
1791
1792 GENGRAPH(icp.pkts_sent, "icp.pkts_sent", "ICP packets sent/sec");
1793 GENGRAPH(icp.pkts_recv, "icp.pkts_recv", "ICP packets received/sec");
1794 GENGRAPH(icp.kbytes_sent.kb, "icp.kbytes_sent", "ICP kbytes_sent/sec");
1795 GENGRAPH(icp.kbytes_recv.kb, "icp.kbytes_recv", "ICP kbytes_received/sec");
1796
1797 /* XXX todo: icp median service times */
1798 /* XXX todo: dns median service times */
1799
1800 GENGRAPH(unlink.requests, "unlink.requests", "Cache File unlink requests/sec");
1801 GENGRAPH(page_faults, "page_faults", "System Page Faults/sec");
1802 GENGRAPH(select_loops, "select_loops", "System Select Loop calls/sec");
1803 GENGRAPH(cputime, "cputime", "CPU utilisation");
1804}
1afe05c5 1805
d96ceb8e 1806#endif /* STAT_GRAPHS */
1807
2d72d4fd 1808int
1809statMemoryAccounted(void)
1810{
d96ceb8e 1811 return memPoolsTotalAllocated();
2d72d4fd 1812}