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