]> git.ipfire.org Git - thirdparty/squid.git/blame - src/stat.cc
Simplify appending SBuf to String (#2108)
[thirdparty/squid.git] / src / stat.cc
CommitLineData
30a4f2a8 1/*
1f7b830e 2 * Copyright (C) 1996-2025 The Squid Software Foundation and contributors
e25c139f 3 *
bbc27441
AJ
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
019dd986 7 */
ed43818f 8
bbc27441
AJ
9/* DEBUG: section 18 Cache Manager Statistics */
10
582c2af2 11#include "squid.h"
63ed9e8e 12#include "AccessLogEntry.h"
b814e8d4 13#include "CacheDigest.h"
a011edee 14#include "CachePeer.h"
2e24d0bf 15#include "CachePeers.h"
582c2af2 16#include "client_side.h"
602d9612 17#include "client_side_request.h"
582c2af2 18#include "comm/Connection.h"
65d448bc 19#include "comm/Loops.h"
a553a5a3 20#include "event.h"
582c2af2 21#include "fde.h"
31971e6a 22#include "format/Token.h"
582c2af2 23#include "globals.h"
d3dddfb5 24#include "http/Stream.h"
d3f603c8 25#include "HttpRequest.h"
9ce629cf 26#include "IoStats.h"
ed6e9fb9 27#include "mem/Pool.h"
a7508376 28#include "mem/Stats.h"
528b2c61 29#include "mem_node.h"
0eb49b6d 30#include "MemBuf.h"
602d9612 31#include "MemObject.h"
8822ebee
AR
32#include "mgr/CountersAction.h"
33#include "mgr/FunAction.h"
34#include "mgr/InfoAction.h"
35#include "mgr/IntervalAction.h"
36#include "mgr/IoAction.h"
582c2af2 37#include "mgr/Registration.h"
8822ebee 38#include "mgr/ServiceTimesAction.h"
f0ba2534 39#include "neighbors.h"
e35609f5 40#include "PeerDigest.h"
4d5904f7 41#include "SquidConfig.h"
582c2af2 42#include "SquidMath.h"
6ea5959e 43#include "stat.h"
602d9612 44#include "StatCounters.h"
582c2af2 45#include "Store.h"
35a28a37 46#include "store_digest.h"
602d9612 47#include "StoreClient.h"
5bed43d6 48#include "tools.h"
582c2af2
FC
49#if USE_AUTH
50#include "auth/UserRequest.h"
51#endif
52#if USE_DELAY_POOLS
53#include "DelayId.h"
54#endif
cb4f4424 55#if USE_OPENSSL
4db984be
CT
56#include "ssl/support.h"
57#endif
528b2c61 58
59/* these are included because they expose stats calls */
60/* TODO: provide a self registration mechanism for those classes
61 * to use during static construction
62 */
63#include "comm.h"
c8f4eac4 64#include "StoreSearch.h"
090089c4 65
1da3b90b 66typedef int STOBJFLT(const StoreEntry *);
62e76326 67
c8f4eac4 68class StatObjectsState
62e76326 69{
5c2f68b7 70 CBDATA_CLASS(StatObjectsState);
c8f4eac4 71
72public:
1da3b90b 73 StoreEntry *sentry;
1da3b90b 74 STOBJFLT *filter;
c8f4eac4 75 StoreSearchPointer theSearch;
c8f4eac4 76};
62e76326 77
67508012 78/* LOCALS */
f5b8bbc4 79static const char *describeStatuses(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
04a28d46 85static double statPctileSvc(double, int, int);
fcc35180 86static void statStoreEntry(MemBuf * mb, StoreEntry * e);
49ad0a8c 87static double statCPUUsage(int minutes);
ed7f5615 88static OBJH stat_objects_get;
89static OBJH stat_vmobjects_get;
ae94d28e 90static OBJH statOpenfdObj;
1da3b90b 91static EVH statObjects;
071a3ae7 92static OBJH statCountersDump;
a1e927f6 93static OBJH statPeerSelect;
26b164ac 94static OBJH statDigestBlob;
e9b5ead4 95static OBJH statUtilization;
ba4f8e5a 96static OBJH statCountersHistograms;
0f1bc304 97static OBJH statClientRequests;
8822ebee
AR
98void GetAvgStat(Mgr::IntervalActionData& stats, int minutes, int hours);
99void DumpAvgStat(Mgr::IntervalActionData& stats, StoreEntry* sentry);
100void GetInfo(Mgr::InfoActionData& stats);
101void DumpInfo(Mgr::InfoActionData& stats, StoreEntry* sentry);
102void DumpMallocStatistics(StoreEntry* sentry);
103void GetCountersStats(Mgr::CountersActionData& stats);
104void DumpCountersStats(Mgr::CountersActionData& stats, StoreEntry* sentry);
105void GetServiceTimesStats(Mgr::ServiceTimesActionData& stats);
106void DumpServiceTimesStats(Mgr::ServiceTimesActionData& stats, StoreEntry* sentry);
107void GetIoStats(Mgr::IoActionData& stats);
108void DumpIoStats(Mgr::IoActionData& stats, StoreEntry* sentry);
20882fb1 109
32d002cb 110#if XMALLOC_STATISTICS
58cd5bbd 111static void info_get_mallstat(int, int, int, void *);
112static double xm_time;
113static double xm_deltat;
20882fb1 114#endif
30a4f2a8 115
a9113eb0 116StatCounters CountHist[N_COUNT_HIST];
d5649d9f 117static int NCountHist = 0;
a0f32775 118static StatCounters CountHourHist[N_COUNT_HOUR_HIST];
119static int NCountHourHist = 0;
c8f4eac4 120CBDATA_CLASS_INIT(StatObjectsState);
a0f32775 121
d480bbc0 122extern unsigned int mem_pool_alloc_calls;
123extern unsigned int mem_pool_free_calls;
124
5e29a294 125static void
e9b5ead4 126statUtilization(StoreEntry * e)
a0f32775 127{
128 storeAppendPrintf(e, "Cache Utilisation:\n");
129 storeAppendPrintf(e, "\n");
130 storeAppendPrintf(e, "Last 5 minutes:\n");
62e76326 131
a0f32775 132 if (NCountHist >= 5)
62e76326 133 statAvgDump(e, 5, 0);
a0f32775 134 else
62e76326 135 storeAppendPrintf(e, "(no values recorded yet)\n");
136
a0f32775 137 storeAppendPrintf(e, "\n");
62e76326 138
a0f32775 139 storeAppendPrintf(e, "Last 15 minutes:\n");
62e76326 140
a0f32775 141 if (NCountHist >= 15)
62e76326 142 statAvgDump(e, 15, 0);
a0f32775 143 else
62e76326 144 storeAppendPrintf(e, "(no values recorded yet)\n");
145
a0f32775 146 storeAppendPrintf(e, "\n");
62e76326 147
a0f32775 148 storeAppendPrintf(e, "Last hour:\n");
62e76326 149
a0f32775 150 if (NCountHist >= 60)
62e76326 151 statAvgDump(e, 60, 0);
a0f32775 152 else
62e76326 153 storeAppendPrintf(e, "(no values recorded yet)\n");
154
a0f32775 155 storeAppendPrintf(e, "\n");
62e76326 156
a0f32775 157 storeAppendPrintf(e, "Last 8 hours:\n");
62e76326 158
a0f32775 159 if (NCountHourHist >= 8)
62e76326 160 statAvgDump(e, 0, 8);
a0f32775 161 else
62e76326 162 storeAppendPrintf(e, "(no values recorded yet)\n");
163
a0f32775 164 storeAppendPrintf(e, "\n");
62e76326 165
a0f32775 166 storeAppendPrintf(e, "Last day:\n");
62e76326 167
a0f32775 168 if (NCountHourHist >= 24)
62e76326 169 statAvgDump(e, 0, 24);
a0f32775 170 else
62e76326 171 storeAppendPrintf(e, "(no values recorded yet)\n");
172
a0f32775 173 storeAppendPrintf(e, "\n");
62e76326 174
a0f32775 175 storeAppendPrintf(e, "Last 3 days:\n");
62e76326 176
a0f32775 177 if (NCountHourHist >= 72)
62e76326 178 statAvgDump(e, 0, 72);
a0f32775 179 else
62e76326 180 storeAppendPrintf(e, "(no values recorded yet)\n");
181
a0f32775 182 storeAppendPrintf(e, "\n");
62e76326 183
a0f32775 184 storeAppendPrintf(e, "Totals since cache startup:\n");
62e76326 185
a0f32775 186 statCountersDump(e);
187}
f2908497 188
8822ebee
AR
189void
190GetIoStats(Mgr::IoActionData& stats)
191{
192 int i;
193
194 stats.http_reads = IOStats.Http.reads;
195
9ce629cf 196 for (i = 0; i < IoStats::histSize; ++i) {
8822ebee
AR
197 stats.http_read_hist[i] = IOStats.Http.read_hist[i];
198 }
199
200 stats.ftp_reads = IOStats.Ftp.reads;
201
9ce629cf 202 for (i = 0; i < IoStats::histSize; ++i) {
8822ebee
AR
203 stats.ftp_read_hist[i] = IOStats.Ftp.read_hist[i];
204 }
8822ebee
AR
205}
206
207void
208DumpIoStats(Mgr::IoActionData& stats, StoreEntry* sentry)
30a4f2a8 209{
210 int i;
211
15576b6a 212 storeAppendPrintf(sentry, "HTTP I/O\n");
8822ebee 213 storeAppendPrintf(sentry, "number of reads: %.0f\n", stats.http_reads);
15576b6a 214 storeAppendPrintf(sentry, "Read Histogram:\n");
62e76326 215
9ce629cf 216 for (i = 0; i < IoStats::histSize; ++i) {
8822ebee 217 storeAppendPrintf(sentry, "%5d-%5d: %9.0f %2.0f%%\n",
d9fc6862
A
218 i ? (1 << (i - 1)) + 1 : 1,
219 1 << i,
220 stats.http_read_hist[i],
221 Math::doublePercent(stats.http_read_hist[i], stats.http_reads));
30a4f2a8 222 }
223
15576b6a 224 storeAppendPrintf(sentry, "\n");
225 storeAppendPrintf(sentry, "FTP I/O\n");
8822ebee 226 storeAppendPrintf(sentry, "number of reads: %.0f\n", stats.ftp_reads);
15576b6a 227 storeAppendPrintf(sentry, "Read Histogram:\n");
62e76326 228
9ce629cf 229 for (i = 0; i < IoStats::histSize; ++i) {
8822ebee 230 storeAppendPrintf(sentry, "%5d-%5d: %9.0f %2.0f%%\n",
d9fc6862
A
231 i ? (1 << (i - 1)) + 1 : 1,
232 1 << i,
233 stats.ftp_read_hist[i],
234 Math::doublePercent(stats.ftp_read_hist[i], stats.ftp_reads));
30a4f2a8 235 }
236
15576b6a 237 storeAppendPrintf(sentry, "\n");
090089c4 238}
239
0ee4272b 240static const char *
fe4e214f 241describeStatuses(const StoreEntry * entry)
d1a43e28 242{
243 LOCAL_ARRAY(char, buf, 256);
56878878 244 snprintf(buf, 256, "%-13s %-13s %-12s %-12s",
62e76326 245 storeStatusStr[entry->store_status],
246 memStatusStr[entry->mem_status],
247 swapStatusStr[entry->swap_status],
248 pingStatusStr[entry->ping_status]);
d1a43e28 249 return buf;
250}
251
415e0dd2 252const char *
253storeEntryFlags(const StoreEntry * entry)
d1a43e28 254{
255 LOCAL_ARRAY(char, buf, 256);
315005bd 256 int flags = (int) entry->flags;
d1a43e28 257 char *t;
258 buf[0] = '\0';
62e76326 259
7d94ae33 260 if (EBIT_TEST(flags, ENTRY_SPECIAL))
62e76326 261 strcat(buf, "SPECIAL,");
262
fa83b766
EB
263 if (EBIT_TEST(flags, ENTRY_REVALIDATE_ALWAYS))
264 strcat(buf, "REVALIDATE_ALWAYS,");
62e76326 265
7d94ae33 266 if (EBIT_TEST(flags, DELAY_SENDING))
62e76326 267 strcat(buf, "DELAY_SENDING,");
268
7d94ae33 269 if (EBIT_TEST(flags, RELEASE_REQUEST))
62e76326 270 strcat(buf, "RELEASE_REQUEST,");
271
7d94ae33 272 if (EBIT_TEST(flags, REFRESH_REQUEST))
62e76326 273 strcat(buf, "REFRESH_REQUEST,");
274
fa83b766
EB
275 if (EBIT_TEST(flags, ENTRY_REVALIDATE_STALE))
276 strcat(buf, "REVALIDATE_STALE,");
277
7d94ae33 278 if (EBIT_TEST(flags, ENTRY_DISPATCHED))
62e76326 279 strcat(buf, "DISPATCHED,");
280
7d94ae33 281 if (EBIT_TEST(flags, KEY_PRIVATE))
62e76326 282 strcat(buf, "PRIVATE,");
283
05b0ef8a 284 if (EBIT_TEST(flags, ENTRY_FWD_HDR_WAIT))
62e76326 285 strcat(buf, "FWD_HDR_WAIT,");
286
7d94ae33 287 if (EBIT_TEST(flags, ENTRY_NEGCACHED))
62e76326 288 strcat(buf, "NEGCACHED,");
289
7d94ae33 290 if (EBIT_TEST(flags, ENTRY_VALIDATED))
62e76326 291 strcat(buf, "VALIDATED,");
292
7d94ae33 293 if (EBIT_TEST(flags, ENTRY_BAD_LENGTH))
62e76326 294 strcat(buf, "BAD_LENGTH,");
295
d2e002d1 296 if (EBIT_TEST(flags, ENTRY_ABORTED))
62e76326 297 strcat(buf, "ABORTED,");
298
d1a43e28 299 if ((t = strrchr(buf, ',')))
62e76326 300 *t = '\0';
301
d1a43e28 302 return buf;
303}
304
b8d8561b 305static void
fcc35180 306statStoreEntry(MemBuf * mb, StoreEntry * e)
090089c4 307{
a5a5de87 308 MemObject *mem = e->mem_obj;
4391cd15
AJ
309 mb->appendf("KEY %s\n", e->getMD5Text());
310 mb->appendf("\t%s\n", describeStatuses(e));
311 mb->appendf("\t%s\n", storeEntryFlags(e));
438b41ba 312 mb->appendf("\t%s\n", e->describeTimestamps());
4391cd15
AJ
313 mb->appendf("\t%d locks, %d clients, %d refs\n", (int) e->locks(), storePendingNClients(e), (int) e->refcount);
314 mb->appendf("\tSwap Dir %d, File %#08X\n", e->swap_dirn, e->swap_filen);
62e76326 315
aee3523a 316 if (mem != nullptr)
fcc35180 317 mem->stat (mb);
62e76326 318
4391cd15 319 mb->append("\n", 1);
a5a5de87 320}
321
322/* process objects list */
323static void
1da3b90b 324statObjects(void *data)
a5a5de87 325{
e6ccf245 326 StatObjectsState *state = static_cast<StatObjectsState *>(data);
1da3b90b 327 StoreEntry *e;
62e76326 328
c8f4eac4 329 if (state->theSearch->isDone()) {
99572608 330 Mgr::CloseKidSection(state->sentry, Mgr::Format::informal);
62e76326 331 state->sentry->complete();
1bfe9ade 332 state->sentry->unlock("statObjects+isDone");
bd6e2f16 333 delete state;
62e76326 334 return;
b7fe0ab0 335 } else if (EBIT_TEST(state->sentry->flags, ENTRY_ABORTED)) {
1bfe9ade 336 state->sentry->unlock("statObjects+aborted");
bd6e2f16 337 delete state;
62e76326 338 return;
a46d2c0e 339 } else if (state->sentry->checkDeferRead(-1)) {
3f783384 340 state->sentry->flush();
62e76326 341 eventAdd("statObjects", statObjects, state, 0.1, 1);
342 return;
1da3b90b 343 }
62e76326 344
3900307b 345 state->sentry->buffer();
c8f4eac4 346 size_t statCount = 0;
347 MemBuf mb;
2fe7eff9 348 mb.init();
62e76326 349
c8f4eac4 350 while (statCount++ < static_cast<size_t>(Config.Store.objectsPerBucket) && state->
351 theSearch->next()) {
352 e = state->theSearch->currentItem();
62e76326 353
c8f4eac4 354 if (state->filter && 0 == state->filter(e))
355 continue;
62e76326 356
c8f4eac4 357 statStoreEntry(&mb, e);
358 }
fcc35180 359
c8f4eac4 360 if (mb.size)
3900307b 361 state->sentry->append(mb.buf, mb.size);
2fe7eff9 362 mb.clean();
62e76326 363
1da3b90b 364 eventAdd("statObjects", statObjects, state, 0.0, 1);
a5a5de87 365}
366
5e29a294 367static void
1da3b90b 368statObjectsStart(StoreEntry * sentry, STOBJFLT * filter)
369{
c8f4eac4 370 StatObjectsState *state = new StatObjectsState;
1da3b90b 371 state->sentry = sentry;
372 state->filter = filter;
34266cde 373
1bfe9ade 374 sentry->lock("statObjects");
2745fea5 375 state->theSearch = Store::Root().search();
34266cde 376
1da3b90b 377 eventAdd("statObjects", statObjects, state, 0.0, 1);
378}
379
380static void
381stat_objects_get(StoreEntry * sentry)
382{
aee3523a 383 statObjectsStart(sentry, nullptr);
1da3b90b 384}
385
386static int
387statObjectsVmFilter(const StoreEntry * e)
090089c4 388{
1da3b90b 389 return e->mem_obj ? 1 : 0;
6684fec0 390}
090089c4 391
5e29a294 392static void
1da3b90b 393stat_vmobjects_get(StoreEntry * sentry)
6684fec0 394{
1da3b90b 395 statObjectsStart(sentry, statObjectsVmFilter);
090089c4 396}
397
1da3b90b 398static int
399statObjectsOpenfdFilter(const StoreEntry * e)
400{
aee3523a 401 if (e->mem_obj == nullptr)
62e76326 402 return 0;
403
aee3523a 404 if (e->mem_obj->swapout.sio == nullptr)
62e76326 405 return 0;
406
1da3b90b 407 return 1;
408}
409
ae94d28e 410static void
411statOpenfdObj(StoreEntry * sentry)
412{
1da3b90b 413 statObjectsStart(sentry, statObjectsOpenfdFilter);
ae94d28e 414}
1da3b90b 415
32d002cb 416#if XMALLOC_STATISTICS
b8d8561b 417static void
58cd5bbd 418info_get_mallstat(int size, int number, int oldnum, void *data)
30a4f2a8 419{
18f2f920 420 StoreEntry *sentry = (StoreEntry *)data;
62e76326 421
77b88b59 422// format: "%12s %15s %6s %12s\n","Alloc Size","Count","Delta","Alloc/sec"
30a4f2a8 423 if (number > 0)
77b88b59 424 storeAppendPrintf(sentry, "%12d %15d %6d %.1f\n", size, number, number - oldnum, xdiv((number - oldnum), xm_deltat));
30a4f2a8 425}
62e76326 426
30a4f2a8 427#endif
090089c4 428
8822ebee
AR
429void
430GetInfo(Mgr::InfoActionData& stats)
090089c4 431{
62e76326 432
090089c4 433 struct rusage rusage;
f2908497 434 double cputime;
435 double runtime;
88738790 436#if HAVE_MSTATS && HAVE_GNUMALLOC_H
437 struct mstats ms;
090089c4 438#endif
439
f2908497 440 runtime = tvSubDsec(squid_start, current_time);
62e76326 441
f2908497 442 if (runtime == 0.0)
62e76326 443 runtime = 1.0;
444
8822ebee
AR
445 stats.squid_start = squid_start;
446
447 stats.current_time = current_time;
448
449 stats.client_http_clients = statCounter.client_http.clients;
450
451 stats.client_http_requests = statCounter.client_http.requests;
452
453 stats.icp_pkts_recv = statCounter.icp.pkts_recv;
454
455 stats.icp_pkts_sent = statCounter.icp.pkts_sent;
456
457 stats.icp_replies_queued = statCounter.icp.replies_queued;
458
459#if USE_HTCP
460
461 stats.htcp_pkts_recv = statCounter.htcp.pkts_recv;
462
463 stats.htcp_pkts_sent = statCounter.htcp.pkts_sent;
464
465#endif
466
467 stats.request_failure_ratio = request_failure_ratio;
468
469 stats.avg_client_http_requests = statCounter.client_http.requests / (runtime / 60.0);
470
471 stats.avg_icp_messages = (statCounter.icp.pkts_sent + statCounter.icp.pkts_recv) / (runtime / 60.0);
472
473 stats.select_loops = statCounter.select_loops;
474 stats.avg_loop_time = 1000.0 * runtime / statCounter.select_loops;
475
476 stats.request_hit_ratio5 = statRequestHitRatio(5);
477 stats.request_hit_ratio60 = statRequestHitRatio(60);
478
479 stats.byte_hit_ratio5 = statByteHitRatio(5);
480 stats.byte_hit_ratio60 = statByteHitRatio(60);
481
482 stats.request_hit_mem_ratio5 = statRequestHitMemoryRatio(5);
483 stats.request_hit_mem_ratio60 = statRequestHitMemoryRatio(60);
484
485 stats.request_hit_disk_ratio5 = statRequestHitDiskRatio(5);
486 stats.request_hit_disk_ratio60 = statRequestHitDiskRatio(60);
487
93bc1434 488 Store::Root().getStats(stats.store);
8822ebee
AR
489
490 stats.unlink_requests = statCounter.unlink.requests;
491
492 stats.http_requests5 = statPctileSvc(0.5, 5, PCTILE_HTTP);
493 stats.http_requests60 = statPctileSvc(0.5, 60, PCTILE_HTTP);
494
495 stats.cache_misses5 = statPctileSvc(0.5, 5, PCTILE_MISS);
496 stats.cache_misses60 = statPctileSvc(0.5, 60, PCTILE_MISS);
497
498 stats.cache_hits5 = statPctileSvc(0.5, 5, PCTILE_HIT);
499 stats.cache_hits60 = statPctileSvc(0.5, 60, PCTILE_HIT);
500
501 stats.near_hits5 = statPctileSvc(0.5, 5, PCTILE_NH);
502 stats.near_hits60 = statPctileSvc(0.5, 60, PCTILE_NH);
503
504 stats.not_modified_replies5 = statPctileSvc(0.5, 5, PCTILE_NM);
505 stats.not_modified_replies60 = statPctileSvc(0.5, 60, PCTILE_NM);
506
507 stats.dns_lookups5 = statPctileSvc(0.5, 5, PCTILE_DNS);
508 stats.dns_lookups60 = statPctileSvc(0.5, 60, PCTILE_DNS);
509
510 stats.icp_queries5 = statPctileSvc(0.5, 5, PCTILE_ICP_QUERY);
511 stats.icp_queries60 = statPctileSvc(0.5, 60, PCTILE_ICP_QUERY);
512
513 squid_getrusage(&rusage);
514 cputime = rusage_cputime(&rusage);
515
516 stats.up_time = runtime;
517 stats.cpu_time = cputime;
518 stats.cpu_usage = Math::doublePercent(cputime, runtime);
519 stats.cpu_usage5 = statCPUUsage(5);
520 stats.cpu_usage60 = statCPUUsage(60);
521
8822ebee
AR
522 stats.maxrss = rusage_maxrss(&rusage);
523
524 stats.page_faults = rusage_pagefaults(&rusage);
525
526#if HAVE_MSTATS && HAVE_GNUMALLOC_H
527
528 ms = mstats();
529
530 stats.ms_bytes_total = ms.bytes_total;
531
532 stats.ms_bytes_free = ms.bytes_free;
533
4572073a 534#endif
8822ebee 535
8822ebee 536 {
a7508376
AJ
537 Mem::PoolStats mp_stats;
538 Mem::GlobalStats(mp_stats);
539 stats.gb_saved_count = mp_stats.meter->gb_saved.count;
540 stats.gb_freed_count = mp_stats.meter->gb_freed.count;
541 stats.total_accounted = mp_stats.meter->alloc.currentLevel();
8822ebee
AR
542 }
543
544 stats.max_fd = Squid_MaxFD;
545 stats.biggest_fd = Biggest_FD;
546 stats.number_fd = Number_FD;
547 stats.opening_fd = Opening_FD;
548 stats.num_fd_free = fdNFree();
549 stats.reserved_fd = RESERVED_FD;
8822ebee
AR
550}
551
552void
553DumpInfo(Mgr::InfoActionData& stats, StoreEntry* sentry)
554{
15576b6a 555 storeAppendPrintf(sentry, "Squid Object Cache: Version %s\n",
62e76326 556 version_string);
557
397d2d61
AJ
558 storeAppendPrintf(sentry, "Build Info: " SQUID_BUILD_INFO "\n");
559
be266cb2 560#if _SQUID_WINDOWS_
1a774556 561 if (WIN32_run_mode == _WIN_SQUID_RUN_MODE_SERVICE) {
d5f21615 562 storeAppendPrintf(sentry,"\nRunning as " SQUIDSBUFPH " Windows System Service on %s\n",
e802a427 563 SQUIDSBUFPRINT(service_name), WIN32_OS_string);
1a774556 564 storeAppendPrintf(sentry,"Service command line is: %s\n", WIN32_Service_Command_Line);
565 } else
566 storeAppendPrintf(sentry,"Running on %s\n",WIN32_OS_string);
cf2155f2 567#else
d5f21615 568 storeAppendPrintf(sentry,"Service Name: " SQUIDSBUFPH "\n", SQUIDSBUFPRINT(service_name));
1a774556 569#endif
570
15576b6a 571 storeAppendPrintf(sentry, "Start Time:\t%s\n",
98cacedb 572 Time::FormatRfc1123(stats.squid_start.tv_sec));
62e76326 573
15576b6a 574 storeAppendPrintf(sentry, "Current Time:\t%s\n",
98cacedb 575 Time::FormatRfc1123(stats.current_time.tv_sec));
62e76326 576
7dbca7a4 577 storeAppendPrintf(sentry, "Connection information for %s:\n",APP_SHORTNAME);
62e76326 578
154df539
AJ
579 if (Config.onoff.client_db)
580 storeAppendPrintf(sentry, "\tNumber of clients accessing cache:\t%.0f\n", stats.client_http_clients);
581 else
582 sentry->append("\tNumber of clients accessing cache:\t(client_db off)\n", 52);
62e76326 583
8822ebee
AR
584 storeAppendPrintf(sentry, "\tNumber of HTTP requests received:\t%.0f\n",
585 stats.client_http_requests);
62e76326 586
8822ebee
AR
587 storeAppendPrintf(sentry, "\tNumber of ICP messages received:\t%.0f\n",
588 stats.icp_pkts_recv);
62e76326 589
8822ebee
AR
590 storeAppendPrintf(sentry, "\tNumber of ICP messages sent:\t%.0f\n",
591 stats.icp_pkts_sent);
62e76326 592
8822ebee
AR
593 storeAppendPrintf(sentry, "\tNumber of queued ICP replies:\t%.0f\n",
594 stats.icp_replies_queued);
62e76326 595
c4ebc830 596#if USE_HTCP
597
8822ebee
AR
598 storeAppendPrintf(sentry, "\tNumber of HTCP messages received:\t%.0f\n",
599 stats.htcp_pkts_recv);
c4ebc830 600
8822ebee
AR
601 storeAppendPrintf(sentry, "\tNumber of HTCP messages sent:\t%.0f\n",
602 stats.htcp_pkts_sent);
c4ebc830 603
604#endif
605
8822ebee 606 double fct = stats.count > 1 ? stats.count : 1.0;
a4ba1105 607 storeAppendPrintf(sentry, "\tRequest failure ratio:\t%5.2f\n",
8822ebee 608 stats.request_failure_ratio / fct);
f2908497 609
b51b0e13 610 storeAppendPrintf(sentry, "\tAverage HTTP requests per minute since start:\t%.1f\n",
61564333 611 stats.avg_client_http_requests);
62e76326 612
b51b0e13 613 storeAppendPrintf(sentry, "\tAverage ICP messages per minute since start:\t%.1f\n",
61564333 614 stats.avg_icp_messages);
62e76326 615
8822ebee
AR
616 storeAppendPrintf(sentry, "\tSelect loop called: %.0f times, %0.3f ms avg\n",
617 stats.select_loops, stats.avg_loop_time / fct);
090089c4 618
7dbca7a4 619 storeAppendPrintf(sentry, "Cache information for %s:\n",APP_SHORTNAME);
62e76326 620
5bf79e53 621 storeAppendPrintf(sentry, "\tHits as %% of all requests:\t5min: %3.1f%%, 60min: %3.1f%%\n",
8822ebee
AR
622 stats.request_hit_ratio5 / fct,
623 stats.request_hit_ratio60 / fct);
62e76326 624
5bf79e53 625 storeAppendPrintf(sentry, "\tHits as %% of bytes sent:\t5min: %3.1f%%, 60min: %3.1f%%\n",
8822ebee
AR
626 stats.byte_hit_ratio5 / fct,
627 stats.byte_hit_ratio60 / fct);
62e76326 628
5bf79e53 629 storeAppendPrintf(sentry, "\tMemory hits as %% of hit requests:\t5min: %3.1f%%, 60min: %3.1f%%\n",
8822ebee
AR
630 stats.request_hit_mem_ratio5 / fct,
631 stats.request_hit_mem_ratio60 / fct);
62e76326 632
5bf79e53 633 storeAppendPrintf(sentry, "\tDisk hits as %% of hit requests:\t5min: %3.1f%%, 60min: %3.1f%%\n",
8822ebee
AR
634 stats.request_hit_disk_ratio5 / fct,
635 stats.request_hit_disk_ratio60 / fct);
62e76326 636
8822ebee 637 storeAppendPrintf(sentry, "\tStorage Swap size:\t%.0f KB\n",
93bc1434 638 stats.store.swap.size / 1024);
62e76326 639
6a52823b 640 storeAppendPrintf(sentry, "\tStorage Swap capacity:\t%4.1f%% used, %4.1f%% free\n",
93bc1434
AR
641 Math::doublePercent(stats.store.swap.size, stats.store.swap.capacity),
642 Math::doublePercent(stats.store.swap.available(), stats.store.swap.capacity));
6a52823b 643
8822ebee 644 storeAppendPrintf(sentry, "\tStorage Mem size:\t%.0f KB\n",
93bc1434 645 stats.store.mem.size / 1024);
62e76326 646
6a52823b 647 storeAppendPrintf(sentry, "\tStorage Mem capacity:\t%4.1f%% used, %4.1f%% free\n",
93bc1434
AR
648 Math::doublePercent(stats.store.mem.size, stats.store.mem.capacity),
649 Math::doublePercent(stats.store.mem.available(), stats.store.mem.capacity));
6a52823b 650
0faf70d0 651 storeAppendPrintf(sentry, "\tMean Object Size:\t%0.2f KB\n",
93bc1434 652 stats.store.swap.meanObjectSize() / 1024);
62e76326 653
8822ebee
AR
654 storeAppendPrintf(sentry, "\tRequests given to unlinkd:\t%.0f\n",
655 stats.unlink_requests);
090089c4 656
b87b92fb 657 storeAppendPrintf(sentry, "Median Service Times (seconds) 5 min 60 min:\n");
62e76326 658
8822ebee 659 fct = stats.count > 1 ? stats.count * 1000.0 : 1000.0;
b87b92fb 660 storeAppendPrintf(sentry, "\tHTTP Requests (All): %8.5f %8.5f\n",
8822ebee
AR
661 stats.http_requests5 / fct,
662 stats.http_requests60 / fct);
62e76326 663
b87b92fb 664 storeAppendPrintf(sentry, "\tCache Misses: %8.5f %8.5f\n",
8822ebee
AR
665 stats.cache_misses5 / fct,
666 stats.cache_misses60 / fct);
62e76326 667
b87b92fb 668 storeAppendPrintf(sentry, "\tCache Hits: %8.5f %8.5f\n",
8822ebee
AR
669 stats.cache_hits5 / fct,
670 stats.cache_hits60 / fct);
62e76326 671
7c9c84ad 672 storeAppendPrintf(sentry, "\tNear Hits: %8.5f %8.5f\n",
8822ebee
AR
673 stats.near_hits5 / fct,
674 stats.near_hits60 / fct);
62e76326 675
b87b92fb 676 storeAppendPrintf(sentry, "\tNot-Modified Replies: %8.5f %8.5f\n",
8822ebee
AR
677 stats.not_modified_replies5 / fct,
678 stats.not_modified_replies60 / fct);
62e76326 679
b87b92fb 680 storeAppendPrintf(sentry, "\tDNS Lookups: %8.5f %8.5f\n",
8822ebee
AR
681 stats.dns_lookups5 / fct,
682 stats.dns_lookups60 / fct);
62e76326 683
8822ebee 684 fct = stats.count > 1 ? stats.count * 1000000.0 : 1000000.0;
b87b92fb 685 storeAppendPrintf(sentry, "\tICP Queries: %8.5f %8.5f\n",
8822ebee
AR
686 stats.icp_queries5 / fct,
687 stats.icp_queries60 / fct);
62e76326 688
7dbca7a4 689 storeAppendPrintf(sentry, "Resource usage for %s:\n", APP_SHORTNAME);
62e76326 690
8822ebee 691 storeAppendPrintf(sentry, "\tUP Time:\t%.3f seconds\n", stats.up_time);
62e76326 692
8822ebee 693 storeAppendPrintf(sentry, "\tCPU Time:\t%.3f seconds\n", stats.cpu_time);
62e76326 694
15576b6a 695 storeAppendPrintf(sentry, "\tCPU Usage:\t%.2f%%\n",
8822ebee 696 stats.cpu_usage);
62e76326 697
979533fa 698 storeAppendPrintf(sentry, "\tCPU Usage, 5 minute avg:\t%.2f%%\n",
8822ebee 699 stats.cpu_usage5);
62e76326 700
49ad0a8c 701 storeAppendPrintf(sentry, "\tCPU Usage, 60 minute avg:\t%.2f%%\n",
8822ebee 702 stats.cpu_usage60);
62e76326 703
8822ebee
AR
704 storeAppendPrintf(sentry, "\tMaximum Resident Size: %.0f KB\n",
705 stats.maxrss);
62e76326 706
8822ebee
AR
707 storeAppendPrintf(sentry, "\tPage faults with physical i/o: %.0f\n",
708 stats.page_faults);
090089c4 709
88738790 710#if HAVE_MSTATS && HAVE_GNUMALLOC_H
62e76326 711
7dbca7a4 712 storeAppendPrintf(sentry, "Memory usage for %s via mstats():\n",APP_SHORTNAME);
62e76326 713
8822ebee
AR
714 storeAppendPrintf(sentry, "\tTotal space in arena: %6.0f KB\n",
715 stats.ms_bytes_total / 1024);
62e76326 716
8822ebee
AR
717 storeAppendPrintf(sentry, "\tTotal free: %6.0f KB %.0f%%\n",
718 stats.ms_bytes_free / 1024,
719 Math::doublePercent(stats.ms_bytes_free, stats.ms_bytes_total));
62e76326 720
4572073a 721#endif
62e76326 722
5d1f3c82 723 storeAppendPrintf(sentry, "Memory accounted for:\n");
8822ebee
AR
724 storeAppendPrintf(sentry, "\tTotal accounted: %6.0f KB\n",
725 stats.total_accounted / 1024);
d96ceb8e 726 {
a7508376
AJ
727 Mem::PoolStats mp_stats;
728 Mem::GlobalStats(mp_stats); // XXX: called just for its side effects
62e76326 729 storeAppendPrintf(sentry, "\tmemPoolAlloc calls: %9.0f\n",
8822ebee 730 stats.gb_saved_count);
62e76326 731 storeAppendPrintf(sentry, "\tmemPoolFree calls: %9.0f\n",
8822ebee 732 stats.gb_freed_count);
d96ceb8e 733 }
62e76326 734
7dbca7a4 735 storeAppendPrintf(sentry, "File descriptor usage for %s:\n", APP_SHORTNAME);
8822ebee
AR
736 storeAppendPrintf(sentry, "\tMaximum number of file descriptors: %4.0f\n",
737 stats.max_fd);
738 storeAppendPrintf(sentry, "\tLargest file desc currently in use: %4.0f\n",
739 stats.biggest_fd);
740 storeAppendPrintf(sentry, "\tNumber of file desc currently in use: %4.0f\n",
741 stats.number_fd);
742 storeAppendPrintf(sentry, "\tFiles queued for open: %4.0f\n",
743 stats.opening_fd);
744 storeAppendPrintf(sentry, "\tAvailable number of file descriptors: %4.0f\n",
745 stats.num_fd_free);
746 storeAppendPrintf(sentry, "\tReserved number of file descriptors: %4.0f\n",
747 stats.reserved_fd);
748 storeAppendPrintf(sentry, "\tStore Disk files open: %4.0f\n",
93bc1434 749 stats.store.swap.open_disk_fd);
090089c4 750
15576b6a 751 storeAppendPrintf(sentry, "Internal Data Structures:\n");
8822ebee 752 storeAppendPrintf(sentry, "\t%6.0f StoreEntries\n",
93bc1434 753 stats.store.store_entry_count);
8822ebee 754 storeAppendPrintf(sentry, "\t%6.0f StoreEntries with MemObjects\n",
93bc1434 755 stats.store.mem_object_count);
8822ebee 756 storeAppendPrintf(sentry, "\t%6.0f Hot Object Cache Items\n",
93bc1434 757 stats.store.mem.count);
8822ebee 758 storeAppendPrintf(sentry, "\t%6.0f on-disk objects\n",
93bc1434 759 stats.store.swap.count);
8822ebee 760}
30a4f2a8 761
8822ebee
AR
762void
763DumpMallocStatistics(StoreEntry* sentry)
764{
30a4f2a8 765#if XMALLOC_STATISTICS
58cd5bbd 766 xm_deltat = current_dtime - xm_time;
767 xm_time = current_dtime;
768 storeAppendPrintf(sentry, "\nMemory allocation statistics\n");
77b88b59 769 storeAppendPrintf(sentry, "%12s %15s %6s %12s\n","Alloc Size","Count","Delta","Alloc/sec");
30a4f2a8 770 malloc_statistics(info_get_mallstat, sentry);
8b082ed9
FC
771#else
772 (void)sentry;
30a4f2a8 773#endif
090089c4 774}
775
8822ebee
AR
776void
777GetServiceTimesStats(Mgr::ServiceTimesActionData& stats)
778{
779 for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) {
780 double p = (i + 1) * 5 / 100.0;
781 stats.http_requests5[i] = statPctileSvc(p, 5, PCTILE_HTTP);
782 stats.http_requests60[i] = statPctileSvc(p, 60, PCTILE_HTTP);
783
784 stats.cache_misses5[i] = statPctileSvc(p, 5, PCTILE_MISS);
785 stats.cache_misses60[i] = statPctileSvc(p, 60, PCTILE_MISS);
786
787 stats.cache_hits5[i] = statPctileSvc(p, 5, PCTILE_HIT);
788 stats.cache_hits60[i] = statPctileSvc(p, 60, PCTILE_HIT);
789
790 stats.near_hits5[i] = statPctileSvc(p, 5, PCTILE_NH);
791 stats.near_hits60[i] = statPctileSvc(p, 60, PCTILE_NH);
792
793 stats.not_modified_replies5[i] = statPctileSvc(p, 5, PCTILE_NM);
794 stats.not_modified_replies60[i] = statPctileSvc(p, 60, PCTILE_NM);
795
796 stats.dns_lookups5[i] = statPctileSvc(p, 5, PCTILE_DNS);
797 stats.dns_lookups60[i] = statPctileSvc(p, 60, PCTILE_DNS);
798
799 stats.icp_queries5[i] = statPctileSvc(p, 5, PCTILE_ICP_QUERY);
800 stats.icp_queries60[i] = statPctileSvc(p, 60, PCTILE_ICP_QUERY);
801 }
802}
803
804void
805DumpServiceTimesStats(Mgr::ServiceTimesActionData& stats, StoreEntry* sentry)
04a28d46 806{
04a28d46 807 storeAppendPrintf(sentry, "Service Time Percentiles 5 min 60 min:\n");
8822ebee
AR
808 double fct = stats.count > 1 ? stats.count * 1000.0 : 1000.0;
809 for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) {
26ac0430 810 storeAppendPrintf(sentry, "\tHTTP Requests (All): %2d%% %8.5f %8.5f\n",
8822ebee
AR
811 (i + 1) * 5,
812 stats.http_requests5[i] / fct,
813 stats.http_requests60[i] / fct);
04a28d46 814 }
8822ebee 815 for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) {
26ac0430 816 storeAppendPrintf(sentry, "\tCache Misses: %2d%% %8.5f %8.5f\n",
8822ebee
AR
817 (i + 1) * 5,
818 stats.cache_misses5[i] / fct,
819 stats.cache_misses60[i] / fct);
04a28d46 820 }
8822ebee 821 for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) {
26ac0430 822 storeAppendPrintf(sentry, "\tCache Hits: %2d%% %8.5f %8.5f\n",
8822ebee
AR
823 (i + 1) * 5,
824 stats.cache_hits5[i] / fct,
825 stats.cache_hits60[i] / fct);
04a28d46 826 }
8822ebee 827 for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) {
26ac0430 828 storeAppendPrintf(sentry, "\tNear Hits: %2d%% %8.5f %8.5f\n",
8822ebee
AR
829 (i + 1) * 5,
830 stats.near_hits5[i] / fct,
831 stats.near_hits60[i] / fct);
04a28d46 832 }
8822ebee 833 for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) {
26ac0430 834 storeAppendPrintf(sentry, "\tNot-Modified Replies: %2d%% %8.5f %8.5f\n",
8822ebee
AR
835 (i + 1) * 5,
836 stats.not_modified_replies5[i] / fct,
837 stats.not_modified_replies60[i] / fct);
04a28d46 838 }
8822ebee 839 for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) {
26ac0430 840 storeAppendPrintf(sentry, "\tDNS Lookups: %2d%% %8.5f %8.5f\n",
8822ebee
AR
841 (i + 1) * 5,
842 stats.dns_lookups5[i] / fct,
843 stats.dns_lookups60[i] / fct);
04a28d46 844 }
8822ebee
AR
845 fct = stats.count > 1 ? stats.count * 1000000.0 : 1000000.0;
846 for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) {
26ac0430 847 storeAppendPrintf(sentry, "\tICP Queries: %2d%% %8.5f %8.5f\n",
8822ebee
AR
848 (i + 1) * 5,
849 stats.icp_queries5[i] / fct,
850 stats.icp_queries60[i] / fct);
04a28d46 851 }
852}
853
b8d8561b 854static void
a0f32775 855statAvgDump(StoreEntry * sentry, int minutes, int hours)
8822ebee
AR
856{
857 Mgr::IntervalActionData stats;
858 GetAvgStat(stats, minutes, hours);
859 DumpAvgStat(stats, sentry);
860}
861
862#define XAVG(X) (dt ? (double) (f->X - l->X) / dt : 0.0)
863void
864GetAvgStat(Mgr::IntervalActionData& stats, int minutes, int hours)
090089c4 865{
a7c05555 866 StatCounters *f;
867 StatCounters *l;
868 double dt;
869 double ct;
870 assert(N_COUNT_HIST > 1);
a0f32775 871 assert(minutes > 0 || hours > 0);
a7c05555 872 f = &CountHist[0];
a0f32775 873 l = f;
62e76326 874
a0f32775 875 if (minutes > 0 && hours == 0) {
62e76326 876 /* checking minute readings ... */
877
878 if (minutes > N_COUNT_HIST - 1)
879 minutes = N_COUNT_HIST - 1;
880
881 l = &CountHist[minutes];
a0f32775 882 } else if (minutes == 0 && hours > 0) {
62e76326 883 /* checking hour readings ... */
884
885 if (hours > N_COUNT_HOUR_HIST - 1)
886 hours = N_COUNT_HOUR_HIST - 1;
887
888 l = &CountHourHist[hours];
a0f32775 889 } else {
d816f28d 890 debugs(18, DBG_IMPORTANT, "ERROR: statAvgDump: Invalid args, minutes=" << minutes << ", hours=" << hours);
62e76326 891 return;
a0f32775 892 }
62e76326 893
a7c05555 894 dt = tvSubDsec(l->timestamp, f->timestamp);
895 ct = f->cputime - l->cputime;
ee1679df 896
8822ebee
AR
897 stats.sample_start_time = l->timestamp;
898 stats.sample_end_time = f->timestamp;
899
900 stats.client_http_requests = XAVG(client_http.requests);
901 stats.client_http_hits = XAVG(client_http.hits);
902 stats.client_http_errors = XAVG(client_http.errors);
903 stats.client_http_kbytes_in = XAVG(client_http.kbytes_in.kb);
904 stats.client_http_kbytes_out = XAVG(client_http.kbytes_out.kb);
905
e8baef82
FC
906 stats.client_http_all_median_svc_time = statHistDeltaMedian(l->client_http.allSvcTime,
907 f->client_http.allSvcTime) / 1000.0;
908 stats.client_http_miss_median_svc_time = statHistDeltaMedian(l->client_http.missSvcTime,
909 f->client_http.missSvcTime) / 1000.0;
910 stats.client_http_nm_median_svc_time = statHistDeltaMedian(l->client_http.nearMissSvcTime,
911 f->client_http.nearMissSvcTime) / 1000.0;
912 stats.client_http_nh_median_svc_time = statHistDeltaMedian(l->client_http.nearHitSvcTime,
913 f->client_http.nearHitSvcTime) / 1000.0;
914 stats.client_http_hit_median_svc_time = statHistDeltaMedian(l->client_http.hitSvcTime,
915 f->client_http.hitSvcTime) / 1000.0;
8822ebee
AR
916
917 stats.server_all_requests = XAVG(server.all.requests);
918 stats.server_all_errors = XAVG(server.all.errors);
919 stats.server_all_kbytes_in = XAVG(server.all.kbytes_in.kb);
920 stats.server_all_kbytes_out = XAVG(server.all.kbytes_out.kb);
921
922 stats.server_http_requests = XAVG(server.http.requests);
923 stats.server_http_errors = XAVG(server.http.errors);
924 stats.server_http_kbytes_in = XAVG(server.http.kbytes_in.kb);
925 stats.server_http_kbytes_out = XAVG(server.http.kbytes_out.kb);
926
927 stats.server_ftp_requests = XAVG(server.ftp.requests);
928 stats.server_ftp_errors = XAVG(server.ftp.errors);
929 stats.server_ftp_kbytes_in = XAVG(server.ftp.kbytes_in.kb);
930 stats.server_ftp_kbytes_out = XAVG(server.ftp.kbytes_out.kb);
931
932 stats.server_other_requests = XAVG(server.other.requests);
933 stats.server_other_errors = XAVG(server.other.errors);
934 stats.server_other_kbytes_in = XAVG(server.other.kbytes_in.kb);
935 stats.server_other_kbytes_out = XAVG(server.other.kbytes_out.kb);
936
937 stats.icp_pkts_sent = XAVG(icp.pkts_sent);
938 stats.icp_pkts_recv = XAVG(icp.pkts_recv);
939 stats.icp_queries_sent = XAVG(icp.queries_sent);
940 stats.icp_replies_sent = XAVG(icp.replies_sent);
941 stats.icp_queries_recv = XAVG(icp.queries_recv);
942 stats.icp_replies_recv = XAVG(icp.replies_recv);
943 stats.icp_replies_queued = XAVG(icp.replies_queued);
944 stats.icp_query_timeouts = XAVG(icp.query_timeouts);
945 stats.icp_kbytes_sent = XAVG(icp.kbytes_sent.kb);
946 stats.icp_kbytes_recv = XAVG(icp.kbytes_recv.kb);
947 stats.icp_q_kbytes_sent = XAVG(icp.q_kbytes_sent.kb);
948 stats.icp_r_kbytes_sent = XAVG(icp.r_kbytes_sent.kb);
949 stats.icp_q_kbytes_recv = XAVG(icp.q_kbytes_recv.kb);
950 stats.icp_r_kbytes_recv = XAVG(icp.r_kbytes_recv.kb);
951
e8baef82
FC
952 stats.icp_query_median_svc_time = statHistDeltaMedian(l->icp.querySvcTime,
953 f->icp.querySvcTime) / 1000000.0;
954 stats.icp_reply_median_svc_time = statHistDeltaMedian(l->icp.replySvcTime,
955 f->icp.replySvcTime) / 1000000.0;
956 stats.dns_median_svc_time = statHistDeltaMedian(l->dns.svcTime,
957 f->dns.svcTime) / 1000.0;
8822ebee
AR
958
959 stats.unlink_requests = XAVG(unlink.requests);
960 stats.page_faults = XAVG(page_faults);
961 stats.select_loops = XAVG(select_loops);
962 stats.select_fds = XAVG(select_fds);
963 stats.average_select_fd_period = f->select_fds > l->select_fds ?
d9fc6862 964 (f->select_time - l->select_time) / (f->select_fds - l->select_fds) : 0.0;
8822ebee 965
3888201e 966 stats.median_select_fds = statHistDeltaMedian(l->select_fds_hist, f->select_fds_hist);
8822ebee
AR
967 stats.swap_outs = XAVG(swap.outs);
968 stats.swap_ins = XAVG(swap.ins);
969 stats.swap_files_cleaned = XAVG(swap.files_cleaned);
970 stats.aborted_requests = XAVG(aborted_requests);
971
b2aca62a
EB
972 stats.hitValidationAttempts = XAVG(hitValidation.attempts);
973 stats.hitValidationRefusalsDueToLocking = XAVG(hitValidation.refusalsDueToLocking);
974 stats.hitValidationRefusalsDueToZeroSize = XAVG(hitValidation.refusalsDueToZeroSize);
975 stats.hitValidationRefusalsDueToTimeLimit = XAVG(hitValidation.refusalsDueToTimeLimit);
976 stats.hitValidationFailures = XAVG(hitValidation.failures);
977
8822ebee
AR
978 stats.syscalls_disk_opens = XAVG(syscalls.disk.opens);
979 stats.syscalls_disk_closes = XAVG(syscalls.disk.closes);
980 stats.syscalls_disk_reads = XAVG(syscalls.disk.reads);
981 stats.syscalls_disk_writes = XAVG(syscalls.disk.writes);
982 stats.syscalls_disk_seeks = XAVG(syscalls.disk.seeks);
983 stats.syscalls_disk_unlinks = XAVG(syscalls.disk.unlinks);
984 stats.syscalls_sock_accepts = XAVG(syscalls.sock.accepts);
985 stats.syscalls_sock_sockets = XAVG(syscalls.sock.sockets);
986 stats.syscalls_sock_connects = XAVG(syscalls.sock.connects);
987 stats.syscalls_sock_binds = XAVG(syscalls.sock.binds);
988 stats.syscalls_sock_closes = XAVG(syscalls.sock.closes);
989 stats.syscalls_sock_reads = XAVG(syscalls.sock.reads);
990 stats.syscalls_sock_writes = XAVG(syscalls.sock.writes);
991 stats.syscalls_sock_recvfroms = XAVG(syscalls.sock.recvfroms);
992 stats.syscalls_sock_sendtos = XAVG(syscalls.sock.sendtos);
993 stats.syscalls_selects = XAVG(syscalls.selects);
994
995 stats.cpu_time = ct;
996 stats.wall_time = dt;
997}
998
999void
1000DumpAvgStat(Mgr::IntervalActionData& stats, StoreEntry* sentry)
1001{
399e85ea 1002 storeAppendPrintf(sentry, "sample_start_time = %d.%d (%s)\n",
8822ebee
AR
1003 (int)stats.sample_start_time.tv_sec,
1004 (int)stats.sample_start_time.tv_usec,
98cacedb 1005 Time::FormatRfc1123(stats.sample_start_time.tv_sec));
5843f24a 1006 storeAppendPrintf(sentry, "sample_end_time = %d.%d (%s)\n",
8822ebee
AR
1007 (int)stats.sample_end_time.tv_sec,
1008 (int)stats.sample_end_time.tv_usec,
98cacedb 1009 Time::FormatRfc1123(stats.sample_end_time.tv_sec));
a0f32775 1010
a7c05555 1011 storeAppendPrintf(sentry, "client_http.requests = %f/sec\n",
8822ebee 1012 stats.client_http_requests);
a7c05555 1013 storeAppendPrintf(sentry, "client_http.hits = %f/sec\n",
8822ebee 1014 stats.client_http_hits);
a7c05555 1015 storeAppendPrintf(sentry, "client_http.errors = %f/sec\n",
8822ebee 1016 stats.client_http_errors);
a7c05555 1017 storeAppendPrintf(sentry, "client_http.kbytes_in = %f/sec\n",
8822ebee 1018 stats.client_http_kbytes_in);
a7c05555 1019 storeAppendPrintf(sentry, "client_http.kbytes_out = %f/sec\n",
8822ebee 1020 stats.client_http_kbytes_out);
ee1679df 1021
8822ebee 1022 double fct = stats.count > 1 ? stats.count : 1.0;
ee1679df 1023 storeAppendPrintf(sentry, "client_http.all_median_svc_time = %f seconds\n",
8822ebee 1024 stats.client_http_all_median_svc_time / fct);
ee1679df 1025 storeAppendPrintf(sentry, "client_http.miss_median_svc_time = %f seconds\n",
8822ebee 1026 stats.client_http_miss_median_svc_time / fct);
ee1679df 1027 storeAppendPrintf(sentry, "client_http.nm_median_svc_time = %f seconds\n",
8822ebee 1028 stats.client_http_nm_median_svc_time / fct);
7c9c84ad 1029 storeAppendPrintf(sentry, "client_http.nh_median_svc_time = %f seconds\n",
8822ebee 1030 stats.client_http_nh_median_svc_time / fct);
ee1679df 1031 storeAppendPrintf(sentry, "client_http.hit_median_svc_time = %f seconds\n",
8822ebee 1032 stats.client_http_hit_median_svc_time / fct);
071a3ae7 1033
a0f32775 1034 storeAppendPrintf(sentry, "server.all.requests = %f/sec\n",
8822ebee 1035 stats.server_all_requests);
a0f32775 1036 storeAppendPrintf(sentry, "server.all.errors = %f/sec\n",
8822ebee 1037 stats.server_all_errors);
a0f32775 1038 storeAppendPrintf(sentry, "server.all.kbytes_in = %f/sec\n",
8822ebee 1039 stats.server_all_kbytes_in);
a0f32775 1040 storeAppendPrintf(sentry, "server.all.kbytes_out = %f/sec\n",
8822ebee 1041 stats.server_all_kbytes_out);
a0f32775 1042
1043 storeAppendPrintf(sentry, "server.http.requests = %f/sec\n",
8822ebee 1044 stats.server_http_requests);
a0f32775 1045 storeAppendPrintf(sentry, "server.http.errors = %f/sec\n",
8822ebee 1046 stats.server_http_errors);
a0f32775 1047 storeAppendPrintf(sentry, "server.http.kbytes_in = %f/sec\n",
8822ebee 1048 stats.server_http_kbytes_in);
a0f32775 1049 storeAppendPrintf(sentry, "server.http.kbytes_out = %f/sec\n",
8822ebee 1050 stats.server_http_kbytes_out);
a0f32775 1051
1052 storeAppendPrintf(sentry, "server.ftp.requests = %f/sec\n",
8822ebee 1053 stats.server_ftp_requests);
a0f32775 1054 storeAppendPrintf(sentry, "server.ftp.errors = %f/sec\n",
8822ebee 1055 stats.server_ftp_errors);
a0f32775 1056 storeAppendPrintf(sentry, "server.ftp.kbytes_in = %f/sec\n",
8822ebee 1057 stats.server_ftp_kbytes_in);
a0f32775 1058 storeAppendPrintf(sentry, "server.ftp.kbytes_out = %f/sec\n",
8822ebee 1059 stats.server_ftp_kbytes_out);
a0f32775 1060
1061 storeAppendPrintf(sentry, "server.other.requests = %f/sec\n",
8822ebee 1062 stats.server_other_requests);
a0f32775 1063 storeAppendPrintf(sentry, "server.other.errors = %f/sec\n",
8822ebee 1064 stats.server_other_errors);
a0f32775 1065 storeAppendPrintf(sentry, "server.other.kbytes_in = %f/sec\n",
8822ebee 1066 stats.server_other_kbytes_in);
a0f32775 1067 storeAppendPrintf(sentry, "server.other.kbytes_out = %f/sec\n",
8822ebee 1068 stats.server_other_kbytes_out);
ee1679df 1069
a7c05555 1070 storeAppendPrintf(sentry, "icp.pkts_sent = %f/sec\n",
8822ebee 1071 stats.icp_pkts_sent);
a7c05555 1072 storeAppendPrintf(sentry, "icp.pkts_recv = %f/sec\n",
8822ebee 1073 stats.icp_pkts_recv);
071a3ae7 1074 storeAppendPrintf(sentry, "icp.queries_sent = %f/sec\n",
8822ebee 1075 stats.icp_queries_sent);
071a3ae7 1076 storeAppendPrintf(sentry, "icp.replies_sent = %f/sec\n",
8822ebee 1077 stats.icp_replies_sent);
071a3ae7 1078 storeAppendPrintf(sentry, "icp.queries_recv = %f/sec\n",
8822ebee 1079 stats.icp_queries_recv);
071a3ae7 1080 storeAppendPrintf(sentry, "icp.replies_recv = %f/sec\n",
8822ebee 1081 stats.icp_replies_recv);
2e8e29b8 1082 storeAppendPrintf(sentry, "icp.replies_queued = %f/sec\n",
8822ebee 1083 stats.icp_replies_queued);
071a3ae7 1084 storeAppendPrintf(sentry, "icp.query_timeouts = %f/sec\n",
8822ebee 1085 stats.icp_query_timeouts);
a7c05555 1086 storeAppendPrintf(sentry, "icp.kbytes_sent = %f/sec\n",
8822ebee 1087 stats.icp_kbytes_sent);
a7c05555 1088 storeAppendPrintf(sentry, "icp.kbytes_recv = %f/sec\n",
8822ebee 1089 stats.icp_kbytes_recv);
071a3ae7 1090 storeAppendPrintf(sentry, "icp.q_kbytes_sent = %f/sec\n",
8822ebee 1091 stats.icp_q_kbytes_sent);
071a3ae7 1092 storeAppendPrintf(sentry, "icp.r_kbytes_sent = %f/sec\n",
8822ebee 1093 stats.icp_r_kbytes_sent);
071a3ae7 1094 storeAppendPrintf(sentry, "icp.q_kbytes_recv = %f/sec\n",
8822ebee 1095 stats.icp_q_kbytes_recv);
071a3ae7 1096 storeAppendPrintf(sentry, "icp.r_kbytes_recv = %f/sec\n",
8822ebee 1097 stats.icp_r_kbytes_recv);
ee1679df 1098 storeAppendPrintf(sentry, "icp.query_median_svc_time = %f seconds\n",
8822ebee 1099 stats.icp_query_median_svc_time / fct);
ee1679df 1100 storeAppendPrintf(sentry, "icp.reply_median_svc_time = %f seconds\n",
8822ebee 1101 stats.icp_reply_median_svc_time / fct);
9973e9fe 1102 storeAppendPrintf(sentry, "dns.median_svc_time = %f seconds\n",
8822ebee 1103 stats.dns_median_svc_time / fct);
a7c05555 1104 storeAppendPrintf(sentry, "unlink.requests = %f/sec\n",
8822ebee 1105 stats.unlink_requests);
a7c05555 1106 storeAppendPrintf(sentry, "page_faults = %f/sec\n",
8822ebee 1107 stats.page_faults);
a7c05555 1108 storeAppendPrintf(sentry, "select_loops = %f/sec\n",
8822ebee 1109 stats.select_loops);
d239c2f5 1110 storeAppendPrintf(sentry, "select_fds = %f/sec\n",
8822ebee 1111 stats.select_fds);
d239c2f5 1112 storeAppendPrintf(sentry, "average_select_fd_period = %f/fd\n",
8822ebee
AR
1113 stats.average_select_fd_period / fct);
1114 storeAppendPrintf(sentry, "median_select_fds = %f\n",
1115 stats.median_select_fds / fct);
23dc8aca 1116 storeAppendPrintf(sentry, "swap.outs = %f/sec\n",
8822ebee 1117 stats.swap_outs);
23dc8aca 1118 storeAppendPrintf(sentry, "swap.ins = %f/sec\n",
8822ebee 1119 stats.swap_ins);
23dc8aca 1120 storeAppendPrintf(sentry, "swap.files_cleaned = %f/sec\n",
8822ebee 1121 stats.swap_files_cleaned);
bfae3379 1122 storeAppendPrintf(sentry, "aborted_requests = %f/sec\n",
8822ebee 1123 stats.aborted_requests);
886f2785 1124
b2aca62a
EB
1125 storeAppendPrintf(sentry, "hit_validation.attempts = %f/sec\n",
1126 stats.hitValidationAttempts);
1127 storeAppendPrintf(sentry, "hit_validation.refusals.due_to_locking = %f/sec\n",
1128 stats.hitValidationRefusalsDueToLocking);
1129 storeAppendPrintf(sentry, "hit_validation.refusals.due_to_zeroSize = %f/sec\n",
1130 stats.hitValidationRefusalsDueToZeroSize);
1131 storeAppendPrintf(sentry, "hit_validation.refusals.due_to_timeLimit = %f/sec\n",
1132 stats.hitValidationRefusalsDueToTimeLimit);
1133 storeAppendPrintf(sentry, "hit_validation.failures = %f/sec\n",
1134 stats.hitValidationFailures);
1135
1b3db6d9 1136#if USE_POLL
8822ebee 1137 storeAppendPrintf(sentry, "syscalls.polls = %f/sec\n", stats.syscalls_selects);
91a04222 1138#elif USE_SELECT
8822ebee 1139 storeAppendPrintf(sentry, "syscalls.selects = %f/sec\n", stats.syscalls_selects);
886f2785 1140#endif
62e76326 1141
8822ebee
AR
1142 storeAppendPrintf(sentry, "syscalls.disk.opens = %f/sec\n", stats.syscalls_disk_opens);
1143 storeAppendPrintf(sentry, "syscalls.disk.closes = %f/sec\n", stats.syscalls_disk_closes);
1144 storeAppendPrintf(sentry, "syscalls.disk.reads = %f/sec\n", stats.syscalls_disk_reads);
1145 storeAppendPrintf(sentry, "syscalls.disk.writes = %f/sec\n", stats.syscalls_disk_writes);
1146 storeAppendPrintf(sentry, "syscalls.disk.seeks = %f/sec\n", stats.syscalls_disk_seeks);
1147 storeAppendPrintf(sentry, "syscalls.disk.unlinks = %f/sec\n", stats.syscalls_disk_unlinks);
1148 storeAppendPrintf(sentry, "syscalls.sock.accepts = %f/sec\n", stats.syscalls_sock_accepts);
1149 storeAppendPrintf(sentry, "syscalls.sock.sockets = %f/sec\n", stats.syscalls_sock_sockets);
1150 storeAppendPrintf(sentry, "syscalls.sock.connects = %f/sec\n", stats.syscalls_sock_connects);
1151 storeAppendPrintf(sentry, "syscalls.sock.binds = %f/sec\n", stats.syscalls_sock_binds);
1152 storeAppendPrintf(sentry, "syscalls.sock.closes = %f/sec\n", stats.syscalls_sock_closes);
1153 storeAppendPrintf(sentry, "syscalls.sock.reads = %f/sec\n", stats.syscalls_sock_reads);
1154 storeAppendPrintf(sentry, "syscalls.sock.writes = %f/sec\n", stats.syscalls_sock_writes);
1155 storeAppendPrintf(sentry, "syscalls.sock.recvfroms = %f/sec\n", stats.syscalls_sock_recvfroms);
1156 storeAppendPrintf(sentry, "syscalls.sock.sendtos = %f/sec\n", stats.syscalls_sock_sendtos);
1157
1158 storeAppendPrintf(sentry, "cpu_time = %f seconds\n", stats.cpu_time);
1159 storeAppendPrintf(sentry, "wall_time = %f seconds\n", stats.wall_time);
1160 storeAppendPrintf(sentry, "cpu_usage = %f%%\n", Math::doublePercent(stats.cpu_time, stats.wall_time));
090089c4 1161}
1162
5f5e883f 1163static void
b8083b1c 1164statRegisterWithCacheManager(void)
62ee09ca 1165{
8822ebee 1166 Mgr::RegisterAction("info", "General Runtime Information",
d9fc6862 1167 &Mgr::InfoAction::Create, 0, 1);
8822ebee 1168 Mgr::RegisterAction("service_times", "Service Times (Percentiles)",
d9fc6862 1169 &Mgr::ServiceTimesAction::Create, 0, 1);
8822ebee 1170 Mgr::RegisterAction("filedescriptors", "Process Filedescriptor Allocation",
d9fc6862 1171 fde::DumpStats, 0, 1);
8822ebee
AR
1172 Mgr::RegisterAction("objects", "All Cache Objects", stat_objects_get, 0, 0);
1173 Mgr::RegisterAction("vm_objects", "In-Memory and In-Transit Objects",
d9fc6862 1174 stat_vmobjects_get, 0, 0);
8822ebee 1175 Mgr::RegisterAction("io", "Server-side network read() size histograms",
d9fc6862 1176 &Mgr::IoAction::Create, 0, 1);
8822ebee 1177 Mgr::RegisterAction("counters", "Traffic and Resource Counters",
d9fc6862 1178 &Mgr::CountersAction::Create, 0, 1);
8822ebee 1179 Mgr::RegisterAction("peer_select", "Peer Selection Algorithms",
d9fc6862 1180 statPeerSelect, 0, 1);
8822ebee 1181 Mgr::RegisterAction("digest_stats", "Cache Digest and ICP blob",
d9fc6862 1182 statDigestBlob, 0, 1);
8822ebee 1183 Mgr::RegisterAction("5min", "5 Minute Average of Counters",
d9fc6862 1184 &Mgr::IntervalAction::Create5min, 0, 1);
8822ebee 1185 Mgr::RegisterAction("60min", "60 Minute Average of Counters",
d9fc6862 1186 &Mgr::IntervalAction::Create60min, 0, 1);
8822ebee 1187 Mgr::RegisterAction("utilization", "Cache Utilization",
d9fc6862 1188 statUtilization, 0, 1);
8822ebee 1189 Mgr::RegisterAction("histograms", "Full Histogram Counts",
d9fc6862 1190 statCountersHistograms, 0, 1);
8822ebee 1191 Mgr::RegisterAction("active_requests",
d9fc6862
A
1192 "Client-side Active Requests",
1193 statClientRequests, 0, 1);
2f1431ea 1194#if USE_AUTH
8822ebee 1195 Mgr::RegisterAction("username_cache",
d9fc6862 1196 "Active Cached Usernames",
638cfbc4 1197 Auth::User::CredentialsCacheStats, 0, 1);
2f1431ea 1198#endif
8822ebee 1199 Mgr::RegisterAction("openfd_objects", "Objects with Swapout files open",
d9fc6862 1200 statOpenfdObj, 0, 0);
b8083b1c 1201#if STAT_GRAPHS
8822ebee 1202 Mgr::RegisterAction("graph_variables", "Display cache metrics graphically",
d9fc6862 1203 statGraphDump, 0, 1);
b8083b1c 1204#endif
090089c4 1205}
f2908497 1206
b56b37cf
AJ
1207/* add special cases here as they arrive */
1208static void
1209statCountersInitSpecial(StatCounters * C)
1210{
1211 /*
1212 * HTTP svc_time hist is kept in milli-seconds; max of 3 hours.
1213 */
1214 C->client_http.allSvcTime.logInit(300, 0.0, 3600000.0 * 3.0);
1215 C->client_http.missSvcTime.logInit(300, 0.0, 3600000.0 * 3.0);
1216 C->client_http.nearMissSvcTime.logInit(300, 0.0, 3600000.0 * 3.0);
1217 C->client_http.nearHitSvcTime.logInit(300, 0.0, 3600000.0 * 3.0);
1218 C->client_http.hitSvcTime.logInit(300, 0.0, 3600000.0 * 3.0);
1219 /*
1220 * ICP svc_time hist is kept in micro-seconds; max of 1 minute.
1221 */
1222 C->icp.querySvcTime.logInit(300, 0.0, 1000000.0 * 60.0);
1223 C->icp.replySvcTime.logInit(300, 0.0, 1000000.0 * 60.0);
1224 /*
1225 * DNS svc_time hist is kept in milli-seconds; max of 10 minutes.
1226 */
1227 C->dns.svcTime.logInit(300, 0.0, 60000.0 * 10.0);
1228 /*
1229 * Cache Digest Stuff
1230 */
1231 C->cd.on_xition_count.enumInit(CacheDigestHashFuncCount);
17c0af35
AJ
1232#if USE_POLL || USE_SELECT
1233 C->comm_udp.init(INCOMING_UDP_MAX);
1234 C->comm_dns.init(INCOMING_DNS_MAX);
1235 C->comm_tcp.init(INCOMING_TCP_MAX);
1236#endif
b56b37cf
AJ
1237 C->select_fds_hist.enumInit(256); /* was SQUID_MAXFD, but it is way too much. It is OK to crop this statistics */
1238}
1239
1240static void
1241statCountersInit(StatCounters * C)
1242{
1243 assert(C);
1244 *C = StatCounters();
1245 statCountersInitSpecial(C);
1246}
1247
5f5e883f
FC
1248void
1249statInit(void)
1250{
1251 int i;
1252 debugs(18, 5, "statInit: Initializing...");
1253
5db6bf73 1254 for (i = 0; i < N_COUNT_HIST; ++i)
5f5e883f
FC
1255 statCountersInit(&CountHist[i]);
1256
5db6bf73 1257 for (i = 0; i < N_COUNT_HOUR_HIST; ++i)
5f5e883f
FC
1258 statCountersInit(&CountHourHist[i]);
1259
1260 statCountersInit(&statCounter);
1261
aee3523a 1262 eventAdd("statAvgTick", statAvgTick, nullptr, (double) COUNT_INTERVAL, 1);
5f5e883f 1263
aee3523a 1264 ClientActiveRequests.head = nullptr;
5f5e883f 1265
aee3523a 1266 ClientActiveRequests.tail = nullptr;
5f5e883f
FC
1267
1268 statRegisterWithCacheManager();
1269}
1270
f2908497 1271static void
ced8def3 1272statAvgTick(void *)
f2908497 1273{
f2908497 1274 struct rusage rusage;
aee3523a 1275 eventAdd("statAvgTick", statAvgTick, nullptr, (double) COUNT_INTERVAL, 1);
20903cac 1276 squid_getrusage(&rusage);
b56b37cf
AJ
1277 statCounter.page_faults = rusage_pagefaults(&rusage);
1278 statCounter.cputime = rusage_cputime(&rusage);
1279 statCounter.timestamp = current_time;
1280 // shift all elements right and prepend statCounter
1281 for(int i = N_COUNT_HIST-1; i > 0; --i)
1282 CountHist[i] = CountHist[i-1];
1283 CountHist[0] = statCounter;
5db6bf73 1284 ++NCountHist;
a0f32775 1285
1286 if ((NCountHist % COUNT_INTERVAL) == 0) {
62e76326 1287 /* we have an hours worth of readings. store previous hour */
b56b37cf
AJ
1288 // shift all elements right and prepend final CountHist element
1289 for(int i = N_COUNT_HOUR_HIST-1; i > 0; --i)
1290 CountHourHist[i] = CountHourHist[i-1];
1291 CountHourHist[0] = CountHist[N_COUNT_HIST - 1];
5db6bf73 1292 ++NCountHourHist;
a0f32775 1293 }
62e76326 1294
b8a46de0 1295 if (Config.warnings.high_rptm > 0) {
04a28d46 1296 int i = (int) statPctileSvc(0.5, 20, PCTILE_HTTP);
62e76326 1297
1298 if (Config.warnings.high_rptm < i)
fa84c01d 1299 debugs(18, DBG_CRITICAL, "WARNING: Median response time is " << i << " milliseconds");
b8a46de0 1300 }
62e76326 1301
b8a46de0 1302 if (Config.warnings.high_pf) {
62e76326 1303 int i = (CountHist[0].page_faults - CountHist[1].page_faults);
1304 double dt = tvSubDsec(CountHist[0].timestamp, CountHist[1].timestamp);
1305
1306 if (i > 0 && dt > 0.0) {
1307 i /= (int) dt;
1308
1309 if (Config.warnings.high_pf < i)
61beade2 1310 debugs(18, DBG_CRITICAL, "WARNING: Page faults occurring at " << i << "/sec");
62e76326 1311 }
b8a46de0 1312 }
62e76326 1313
b8a46de0 1314 if (Config.warnings.high_memory) {
62e76326 1315 size_t i = 0;
b8a46de0 1316#if HAVE_MSTATS && HAVE_GNUMALLOC_H
62e76326 1317 struct mstats ms = mstats();
1318 i = ms.bytes_total;
b8a46de0 1319#endif
62e76326 1320 if (Config.warnings.high_memory < i)
fa84c01d 1321 debugs(18, DBG_CRITICAL, "WARNING: Memory usage at " << ((unsigned long int)(i >> 20)) << " MB");
b8a46de0 1322 }
20903cac 1323}
1324
071a3ae7 1325static void
5d406e78 1326statCountersHistograms(StoreEntry * sentry)
071a3ae7 1327{
e8baef82 1328 storeAppendPrintf(sentry, "client_http.allSvcTime histogram:\n");
aee3523a 1329 statCounter.client_http.allSvcTime.dump(sentry, nullptr);
e8baef82 1330 storeAppendPrintf(sentry, "client_http.missSvcTime histogram:\n");
aee3523a 1331 statCounter.client_http.missSvcTime.dump(sentry, nullptr);
e8baef82 1332 storeAppendPrintf(sentry, "client_http.nearMissSvcTime histogram:\n");
aee3523a 1333 statCounter.client_http.nearMissSvcTime.dump(sentry, nullptr);
e8baef82 1334 storeAppendPrintf(sentry, "client_http.nearHitSvcTime histogram:\n");
aee3523a 1335 statCounter.client_http.nearHitSvcTime.dump(sentry, nullptr);
e8baef82 1336 storeAppendPrintf(sentry, "client_http.hitSvcTime histogram:\n");
aee3523a 1337 statCounter.client_http.hitSvcTime.dump(sentry, nullptr);
e8baef82 1338 storeAppendPrintf(sentry, "icp.querySvcTime histogram:\n");
aee3523a 1339 statCounter.icp.querySvcTime.dump(sentry, nullptr);
e8baef82 1340 storeAppendPrintf(sentry, "icp.replySvcTime histogram:\n");
aee3523a 1341 statCounter.icp.replySvcTime.dump(sentry, nullptr);
071a3ae7 1342 storeAppendPrintf(sentry, "dns.svc_time histogram:\n");
aee3523a 1343 statCounter.dns.svcTime.dump(sentry, nullptr);
2a73b7cb 1344 storeAppendPrintf(sentry, "select_fds_hist histogram:\n");
aee3523a 1345 statCounter.select_fds_hist.dump(sentry, nullptr);
071a3ae7 1346}
1347
12cf1be2 1348static void
1349statCountersDump(StoreEntry * sentry)
8822ebee
AR
1350{
1351 Mgr::CountersActionData stats;
1352 GetCountersStats(stats);
1353 DumpCountersStats(stats, sentry);
1354}
1355
1356void
1357GetCountersStats(Mgr::CountersActionData& stats)
7ae52c25 1358{
83704487 1359 StatCounters *f = &statCounter;
62e76326 1360
12cf1be2 1361 struct rusage rusage;
1362 squid_getrusage(&rusage);
1363 f->page_faults = rusage_pagefaults(&rusage);
1364 f->cputime = rusage_cputime(&rusage);
1365
8822ebee
AR
1366 stats.sample_time = f->timestamp;
1367 stats.client_http_requests = f->client_http.requests;
1368 stats.client_http_hits = f->client_http.hits;
1369 stats.client_http_errors = f->client_http.errors;
1370 stats.client_http_kbytes_in = f->client_http.kbytes_in.kb;
1371 stats.client_http_kbytes_out = f->client_http.kbytes_out.kb;
1372 stats.client_http_hit_kbytes_out = f->client_http.hit_kbytes_out.kb;
1373
1374 stats.server_all_requests = f->server.all.requests;
1375 stats.server_all_errors = f->server.all.errors;
1376 stats.server_all_kbytes_in = f->server.all.kbytes_in.kb;
1377 stats.server_all_kbytes_out = f->server.all.kbytes_out.kb;
1378
1379 stats.server_http_requests = f->server.http.requests;
1380 stats.server_http_errors = f->server.http.errors;
1381 stats.server_http_kbytes_in = f->server.http.kbytes_in.kb;
1382 stats.server_http_kbytes_out = f->server.http.kbytes_out.kb;
1383
1384 stats.server_ftp_requests = f->server.ftp.requests;
1385 stats.server_ftp_errors = f->server.ftp.errors;
1386 stats.server_ftp_kbytes_in = f->server.ftp.kbytes_in.kb;
1387 stats.server_ftp_kbytes_out = f->server.ftp.kbytes_out.kb;
1388
1389 stats.server_other_requests = f->server.other.requests;
1390 stats.server_other_errors = f->server.other.errors;
1391 stats.server_other_kbytes_in = f->server.other.kbytes_in.kb;
1392 stats.server_other_kbytes_out = f->server.other.kbytes_out.kb;
1393
1394 stats.icp_pkts_sent = f->icp.pkts_sent;
1395 stats.icp_pkts_recv = f->icp.pkts_recv;
1396 stats.icp_queries_sent = f->icp.queries_sent;
1397 stats.icp_replies_sent = f->icp.replies_sent;
1398 stats.icp_queries_recv = f->icp.queries_recv;
1399 stats.icp_replies_recv = f->icp.replies_recv;
1400 stats.icp_query_timeouts = f->icp.query_timeouts;
1401 stats.icp_replies_queued = f->icp.replies_queued;
1402 stats.icp_kbytes_sent = f->icp.kbytes_sent.kb;
1403 stats.icp_kbytes_recv = f->icp.kbytes_recv.kb;
1404 stats.icp_q_kbytes_sent = f->icp.q_kbytes_sent.kb;
1405 stats.icp_r_kbytes_sent = f->icp.r_kbytes_sent.kb;
1406 stats.icp_q_kbytes_recv = f->icp.q_kbytes_recv.kb;
1407 stats.icp_r_kbytes_recv = f->icp.r_kbytes_recv.kb;
1408
1409#if USE_CACHE_DIGESTS
1410
1411 stats.icp_times_used = f->icp.times_used;
1412 stats.cd_times_used = f->cd.times_used;
1413 stats.cd_msgs_sent = f->cd.msgs_sent;
1414 stats.cd_msgs_recv = f->cd.msgs_recv;
1415 stats.cd_memory = f->cd.memory.kb;
1416 stats.cd_local_memory = store_digest ? store_digest->mask_size / 1024 : 0;
1417 stats.cd_kbytes_sent = f->cd.kbytes_sent.kb;
1418 stats.cd_kbytes_recv = f->cd.kbytes_recv.kb;
1419#endif
1420
1421 stats.unlink_requests = f->unlink.requests;
1422 stats.page_faults = f->page_faults;
1423 stats.select_loops = f->select_loops;
1424 stats.cpu_time = f->cputime;
1425 stats.wall_time = tvSubDsec(f->timestamp, current_time);
1426 stats.swap_outs = f->swap.outs;
1427 stats.swap_ins = f->swap.ins;
1428 stats.swap_files_cleaned = f->swap.files_cleaned;
1429 stats.aborted_requests = f->aborted_requests;
b2aca62a
EB
1430
1431 stats.hitValidationAttempts = f->hitValidation.attempts;
1432 stats.hitValidationRefusalsDueToLocking = f->hitValidation.refusalsDueToLocking;
1433 stats.hitValidationRefusalsDueToZeroSize = f->hitValidation.refusalsDueToZeroSize;
1434 stats.hitValidationRefusalsDueToTimeLimit = f->hitValidation.refusalsDueToTimeLimit;
1435 stats.hitValidationFailures = f->hitValidation.failures;
8822ebee
AR
1436}
1437
1438void
1439DumpCountersStats(Mgr::CountersActionData& stats, StoreEntry* sentry)
1440{
a0f32775 1441 storeAppendPrintf(sentry, "sample_time = %d.%d (%s)\n",
8822ebee
AR
1442 (int) stats.sample_time.tv_sec,
1443 (int) stats.sample_time.tv_usec,
98cacedb 1444 Time::FormatRfc1123(stats.sample_time.tv_sec));
8822ebee
AR
1445 storeAppendPrintf(sentry, "client_http.requests = %.0f\n",
1446 stats.client_http_requests);
1447 storeAppendPrintf(sentry, "client_http.hits = %.0f\n",
1448 stats.client_http_hits);
1449 storeAppendPrintf(sentry, "client_http.errors = %.0f\n",
1450 stats.client_http_errors);
1451 storeAppendPrintf(sentry, "client_http.kbytes_in = %.0f\n",
1452 stats.client_http_kbytes_in);
1453 storeAppendPrintf(sentry, "client_http.kbytes_out = %.0f\n",
1454 stats.client_http_kbytes_out);
1455 storeAppendPrintf(sentry, "client_http.hit_kbytes_out = %.0f\n",
1456 stats.client_http_hit_kbytes_out);
1457
1458 storeAppendPrintf(sentry, "server.all.requests = %.0f\n",
1459 stats.server_all_requests);
1460 storeAppendPrintf(sentry, "server.all.errors = %.0f\n",
1461 stats.server_all_errors);
1462 storeAppendPrintf(sentry, "server.all.kbytes_in = %.0f\n",
1463 stats.server_all_kbytes_in);
1464 storeAppendPrintf(sentry, "server.all.kbytes_out = %.0f\n",
1465 stats.server_all_kbytes_out);
1466
1467 storeAppendPrintf(sentry, "server.http.requests = %.0f\n",
1468 stats.server_http_requests);
1469 storeAppendPrintf(sentry, "server.http.errors = %.0f\n",
1470 stats.server_http_errors);
1471 storeAppendPrintf(sentry, "server.http.kbytes_in = %.0f\n",
1472 stats.server_http_kbytes_in);
1473 storeAppendPrintf(sentry, "server.http.kbytes_out = %.0f\n",
1474 stats.server_http_kbytes_out);
1475
1476 storeAppendPrintf(sentry, "server.ftp.requests = %.0f\n",
1477 stats.server_ftp_requests);
1478 storeAppendPrintf(sentry, "server.ftp.errors = %.0f\n",
1479 stats.server_ftp_errors);
1480 storeAppendPrintf(sentry, "server.ftp.kbytes_in = %.0f\n",
1481 stats.server_ftp_kbytes_in);
1482 storeAppendPrintf(sentry, "server.ftp.kbytes_out = %.0f\n",
1483 stats.server_ftp_kbytes_out);
1484
1485 storeAppendPrintf(sentry, "server.other.requests = %.0f\n",
1486 stats.server_other_requests);
1487 storeAppendPrintf(sentry, "server.other.errors = %.0f\n",
1488 stats.server_other_errors);
1489 storeAppendPrintf(sentry, "server.other.kbytes_in = %.0f\n",
1490 stats.server_other_kbytes_in);
1491 storeAppendPrintf(sentry, "server.other.kbytes_out = %.0f\n",
1492 stats.server_other_kbytes_out);
1493
1494 storeAppendPrintf(sentry, "icp.pkts_sent = %.0f\n",
1495 stats.icp_pkts_sent);
1496 storeAppendPrintf(sentry, "icp.pkts_recv = %.0f\n",
1497 stats.icp_pkts_recv);
1498 storeAppendPrintf(sentry, "icp.queries_sent = %.0f\n",
1499 stats.icp_queries_sent);
1500 storeAppendPrintf(sentry, "icp.replies_sent = %.0f\n",
1501 stats.icp_replies_sent);
1502 storeAppendPrintf(sentry, "icp.queries_recv = %.0f\n",
1503 stats.icp_queries_recv);
1504 storeAppendPrintf(sentry, "icp.replies_recv = %.0f\n",
1505 stats.icp_replies_recv);
1506 storeAppendPrintf(sentry, "icp.query_timeouts = %.0f\n",
1507 stats.icp_query_timeouts);
1508 storeAppendPrintf(sentry, "icp.replies_queued = %.0f\n",
1509 stats.icp_replies_queued);
1510 storeAppendPrintf(sentry, "icp.kbytes_sent = %.0f\n",
1511 stats.icp_kbytes_sent);
1512 storeAppendPrintf(sentry, "icp.kbytes_recv = %.0f\n",
1513 stats.icp_kbytes_recv);
1514 storeAppendPrintf(sentry, "icp.q_kbytes_sent = %.0f\n",
1515 stats.icp_q_kbytes_sent);
1516 storeAppendPrintf(sentry, "icp.r_kbytes_sent = %.0f\n",
1517 stats.icp_r_kbytes_sent);
1518 storeAppendPrintf(sentry, "icp.q_kbytes_recv = %.0f\n",
1519 stats.icp_q_kbytes_recv);
1520 storeAppendPrintf(sentry, "icp.r_kbytes_recv = %.0f\n",
1521 stats.icp_r_kbytes_recv);
0567f2a6 1522
6cfa8966 1523#if USE_CACHE_DIGESTS
62e76326 1524
8822ebee
AR
1525 storeAppendPrintf(sentry, "icp.times_used = %.0f\n",
1526 stats.icp_times_used);
1527 storeAppendPrintf(sentry, "cd.times_used = %.0f\n",
1528 stats.cd_times_used);
1529 storeAppendPrintf(sentry, "cd.msgs_sent = %.0f\n",
1530 stats.cd_msgs_sent);
1531 storeAppendPrintf(sentry, "cd.msgs_recv = %.0f\n",
1532 stats.cd_msgs_recv);
1533 storeAppendPrintf(sentry, "cd.memory = %.0f\n",
1534 stats.cd_memory);
1535 storeAppendPrintf(sentry, "cd.local_memory = %.0f\n",
1536 stats.cd_local_memory);
1537 storeAppendPrintf(sentry, "cd.kbytes_sent = %.0f\n",
1538 stats.cd_kbytes_sent);
1539 storeAppendPrintf(sentry, "cd.kbytes_recv = %.0f\n",
1540 stats.cd_kbytes_recv);
0567f2a6 1541#endif
1542
8822ebee
AR
1543 storeAppendPrintf(sentry, "unlink.requests = %.0f\n",
1544 stats.unlink_requests);
1545 storeAppendPrintf(sentry, "page_faults = %.0f\n",
1546 stats.page_faults);
1547 storeAppendPrintf(sentry, "select_loops = %.0f\n",
1548 stats.select_loops);
12cf1be2 1549 storeAppendPrintf(sentry, "cpu_time = %f\n",
8822ebee 1550 stats.cpu_time);
12cf1be2 1551 storeAppendPrintf(sentry, "wall_time = %f\n",
8822ebee
AR
1552 stats.wall_time);
1553 storeAppendPrintf(sentry, "swap.outs = %.0f\n",
1554 stats.swap_outs);
1555 storeAppendPrintf(sentry, "swap.ins = %.0f\n",
1556 stats.swap_ins);
1557 storeAppendPrintf(sentry, "swap.files_cleaned = %.0f\n",
1558 stats.swap_files_cleaned);
1559 storeAppendPrintf(sentry, "aborted_requests = %.0f\n",
1560 stats.aborted_requests);
b2aca62a
EB
1561
1562 storeAppendPrintf(sentry, "hit_validation.attempts = %.0f\n",
1563 stats.hitValidationAttempts);
1564 storeAppendPrintf(sentry, "hit_validation.refusals.due_to_locking = %.0f\n",
1565 stats.hitValidationRefusalsDueToLocking);
1566 storeAppendPrintf(sentry, "hit_validation.refusals.due_to_zeroSize = %.0f\n",
1567 stats.hitValidationRefusalsDueToZeroSize);
1568 storeAppendPrintf(sentry, "hit_validation.refusals.due_to_timeLimit = %.0f\n",
1569 stats.hitValidationRefusalsDueToTimeLimit);
1570 storeAppendPrintf(sentry, "hit_validation.failures = %.0f\n",
1571 stats.hitValidationFailures);
7ae52c25 1572}
1573
5e29a294 1574static void
a1e927f6 1575statPeerSelect(StoreEntry * sentry)
1576{
6cfa8966 1577#if USE_CACHE_DIGESTS
83704487 1578 StatCounters *f = &statCounter;
a1e927f6 1579 const int tot_used = f->cd.times_used + f->icp.times_used;
1580
1581 /* totals */
0e3b8c9f
AJ
1582 static const SBuf label("all peers");
1583 cacheDigestGuessStatsReport(&f->cd.guess, sentry, label);
a1e927f6 1584 /* per-peer */
1585 storeAppendPrintf(sentry, "\nPer-peer statistics:\n");
62e76326 1586
2e24d0bf 1587 for (const auto &peer: CurrentCachePeers()) {
62e76326 1588 if (peer->digest)
1589 peerDigestStatsReport(peer->digest, sentry);
1590 else
1591 storeAppendPrintf(sentry, "\nNo peer digest from %s\n", peer->host);
1592
1593 storeAppendPrintf(sentry, "\n");
a1e927f6 1594 }
1595
1596 storeAppendPrintf(sentry, "\nAlgorithm usage:\n");
1597 storeAppendPrintf(sentry, "Cache Digest: %7d (%3d%%)\n",
62e76326 1598 f->cd.times_used, xpercentInt(f->cd.times_used, tot_used));
a1e927f6 1599 storeAppendPrintf(sentry, "Icp: %7d (%3d%%)\n",
62e76326 1600 f->icp.times_used, xpercentInt(f->icp.times_used, tot_used));
a1e927f6 1601 storeAppendPrintf(sentry, "Total: %7d (%3d%%)\n",
62e76326 1602 tot_used, xpercentInt(tot_used, tot_used));
a1e927f6 1603#else
62e76326 1604
a1e927f6 1605 storeAppendPrintf(sentry, "peer digests are disabled; no stats is available.\n");
1606#endif
1607}
1608
1609static void
26b164ac 1610statDigestBlob(StoreEntry * sentry)
1611{
071a3ae7 1612 storeAppendPrintf(sentry, "\nCounters:\n");
1613 statCountersDump(sentry);
86e2a291 1614 storeAppendPrintf(sentry, "\n5 Min Averages:\n");
1615 statAvgDump(sentry, 5, 0);
071a3ae7 1616 storeAppendPrintf(sentry, "\nHistograms:\n");
1617 statCountersHistograms(sentry);
1618 storeAppendPrintf(sentry, "\nPeer Digests:\n");
26b164ac 1619 statPeerSelect(sentry);
588d9545 1620 storeAppendPrintf(sentry, "\nLocal Digest:\n");
26b164ac 1621 storeDigestReport(sentry);
1622}
1623
7d94ae33 1624static double
04a28d46 1625statPctileSvc(double pctile, int interval, int which)
a9113eb0 1626{
1627 StatCounters *f;
1628 StatCounters *l;
1629 double x;
f8d264b8 1630 assert(interval > 0);
62e76326 1631
f8d264b8 1632 if (interval > N_COUNT_HIST - 1)
62e76326 1633 interval = N_COUNT_HIST - 1;
1634
a9113eb0 1635 f = &CountHist[0];
62e76326 1636
a9113eb0 1637 l = &CountHist[interval];
62e76326 1638
ee1679df 1639 assert(f);
62e76326 1640
ee1679df 1641 assert(l);
62e76326 1642
a9113eb0 1643 switch (which) {
62e76326 1644
04a28d46 1645 case PCTILE_HTTP:
e8baef82 1646 x = statHistDeltaPctile(l->client_http.allSvcTime,f->client_http.allSvcTime, pctile);
62e76326 1647 break;
1648
04a28d46 1649 case PCTILE_HIT:
e8baef82 1650 x = statHistDeltaPctile(l->client_http.hitSvcTime,f->client_http.hitSvcTime, pctile);
62e76326 1651 break;
1652
04a28d46 1653 case PCTILE_MISS:
e8baef82 1654 x = statHistDeltaPctile(l->client_http.missSvcTime,f->client_http.missSvcTime, pctile);
62e76326 1655 break;
1656
04a28d46 1657 case PCTILE_NM:
e8baef82 1658 x = statHistDeltaPctile(l->client_http.nearMissSvcTime,f->client_http.nearMissSvcTime, pctile);
62e76326 1659 break;
1660
04a28d46 1661 case PCTILE_NH:
e8baef82 1662 x = statHistDeltaPctile(l->client_http.nearHitSvcTime,f->client_http.nearHitSvcTime, pctile);
62e76326 1663 break;
1664
04a28d46 1665 case PCTILE_ICP_QUERY:
e8baef82 1666 x = statHistDeltaPctile(l->icp.querySvcTime,f->icp.querySvcTime, pctile);
62e76326 1667 break;
1668
04a28d46 1669 case PCTILE_DNS:
e8baef82 1670 x = statHistDeltaPctile(l->dns.svcTime,f->dns.svcTime, pctile);
62e76326 1671 break;
1672
a9113eb0 1673 default:
bf8fe701 1674 debugs(49, 5, "statPctileSvc: unknown type.");
62e76326 1675 x = 0;
a9113eb0 1676 }
62e76326 1677
b87b92fb 1678 return x;
1679}
1680
451b07c5 1681StatCounters *
1682snmpStatGet(int minutes)
1683{
2ac76861 1684 return &CountHist[minutes];
451b07c5 1685}
01aebf31 1686
72f2eff8
EB
1687bool
1688statSawRecentRequests()
1f3c4622 1689{
72f2eff8
EB
1690 const auto recentMinutes = 5;
1691 assert(N_COUNT_HIST > recentMinutes);
1692
1693 // Math below computes the number of requests during the last 0-6 minutes.
1694 // CountHist is based on "minutes passed since Squid start" periods. It cannot
1695 // deliver precise info for "last N minutes", but we do not need to be precise.
1696 const auto oldRequests = (NCountHist > recentMinutes) ? CountHist[recentMinutes].client_http.requests : 0;
1697 return statCounter.client_http.requests - oldRequests;
1f3c4622 1698}
1699
49ad0a8c 1700static double
1701statCPUUsage(int minutes)
979533fa 1702{
49ad0a8c 1703 assert(minutes < N_COUNT_HIST);
a98bcbee 1704 return Math::doublePercent(CountHist[0].cputime - CountHist[minutes].cputime,
f9afa4fb 1705 tvSubDsec(CountHist[minutes].timestamp, CountHist[0].timestamp));
979533fa 1706}
01aebf31 1707
82afb125 1708double
e1381638 1709statRequestHitRatio(int minutes)
491a980b 1710{
1711 assert(minutes < N_COUNT_HIST);
a98bcbee 1712 return Math::doublePercent(CountHist[0].client_http.hits -
f9afa4fb
A
1713 CountHist[minutes].client_http.hits,
1714 CountHist[0].client_http.requests -
1715 CountHist[minutes].client_http.requests);
491a980b 1716}
1717
82afb125 1718double
e1381638 1719statRequestHitMemoryRatio(int minutes)
4f4d1d6e 1720{
1721 assert(minutes < N_COUNT_HIST);
a98bcbee 1722 return Math::doublePercent(CountHist[0].client_http.mem_hits -
f9afa4fb
A
1723 CountHist[minutes].client_http.mem_hits,
1724 CountHist[0].client_http.hits -
1725 CountHist[minutes].client_http.hits);
4f4d1d6e 1726}
1727
82afb125 1728double
e1381638 1729statRequestHitDiskRatio(int minutes)
4f4d1d6e 1730{
1731 assert(minutes < N_COUNT_HIST);
a98bcbee 1732 return Math::doublePercent(CountHist[0].client_http.disk_hits -
f9afa4fb
A
1733 CountHist[minutes].client_http.disk_hits,
1734 CountHist[0].client_http.hits -
1735 CountHist[minutes].client_http.hits);
4f4d1d6e 1736}
1737
82afb125 1738double
e1381638 1739statByteHitRatio(int minutes)
491a980b 1740{
1741 size_t s;
1742 size_t c;
ac342231 1743#if USE_CACHE_DIGESTS
62e76326 1744
ac342231 1745 size_t cd;
1746#endif
1747 /* size_t might be unsigned */
491a980b 1748 assert(minutes < N_COUNT_HIST);
1749 c = CountHist[0].client_http.kbytes_out.kb - CountHist[minutes].client_http.kbytes_out.kb;
1750 s = CountHist[0].server.all.kbytes_in.kb - CountHist[minutes].server.all.kbytes_in.kb;
ac342231 1751#if USE_CACHE_DIGESTS
1752 /*
1753 * This ugly hack is here to prevent the user from seeing a
1754 * negative byte hit ratio. When we fetch a cache digest from
1755 * a neighbor, it gets treated like a cache miss because the
1756 * object is consumed internally. Thus, we subtract cache
1757 * digest bytes out before calculating the byte hit ratio.
1758 */
1759 cd = CountHist[0].cd.kbytes_recv.kb - CountHist[minutes].cd.kbytes_recv.kb;
62e76326 1760
49d7ce5f 1761 if (s < cd)
e0236918 1762 debugs(18, DBG_IMPORTANT, "STRANGE: srv_kbytes=" << s << ", cd_kbytes=" << cd);
62e76326 1763
ac342231 1764 s -= cd;
62e76326 1765
ac342231 1766#endif
62e76326 1767
94e56ef7 1768 if (c > s)
a98bcbee 1769 return Math::doublePercent(c - s, c);
94e56ef7 1770 else
a98bcbee 1771 return (-1.0 * Math::doublePercent(s - c, c));
491a980b 1772}
1773
0f1bc304 1774static void
1775statClientRequests(StoreEntry * s)
1776{
1777 dlink_node *i;
59a1efb2 1778 ClientHttpRequest *http;
0f1bc304 1779 StoreEntry *e;
cc192b50 1780 char buf[MAX_IPSTRLEN];
62e76326 1781
0f1bc304 1782 for (i = ClientActiveRequests.head; i; i = i->next) {
aee3523a 1783 const char *p = nullptr;
59a1efb2 1784 http = static_cast<ClientHttpRequest *>(i->data);
62e76326 1785 assert(http);
9512de47 1786 ConnStateData * conn = http->getConn();
1787 storeAppendPrintf(s, "Connection: %p\n", conn);
62e76326 1788
aee3523a 1789 if (conn != nullptr) {
73c36fd9 1790 const int fd = conn->clientConnection->fd;
c91ca3ce 1791 storeAppendPrintf(s, "\tFD %d, read %" PRId64 ", wrote %" PRId64 "\n", fd,
62e76326 1792 fd_table[fd].bytes_read, fd_table[fd].bytes_written);
1793 storeAppendPrintf(s, "\tFD desc: %s\n", fd_table[fd].desc);
e7287625 1794 storeAppendPrintf(s, "\tin: buf %p, used %ld, free %ld\n",
fcc444e3 1795 conn->inBuf.rawContent(), (long int) conn->inBuf.length(), (long int) conn->inBuf.spaceSize());
be364179 1796 storeAppendPrintf(s, "\tremote: %s\n",
4dd643d5 1797 conn->clientConnection->remote.toUrl(buf,MAX_IPSTRLEN));
be364179 1798 storeAppendPrintf(s, "\tlocal: %s\n",
4dd643d5 1799 conn->clientConnection->local.toUrl(buf,MAX_IPSTRLEN));
9dde3c2a 1800 storeAppendPrintf(s, "\tnrequests: %u\n", conn->pipeline.nrequests);
62e76326 1801 }
1802
1803 storeAppendPrintf(s, "uri %s\n", http->uri);
12f5a662 1804 storeAppendPrintf(s, "logType %s\n", http->loggingTags().c_str());
62e76326 1805 storeAppendPrintf(s, "out.offset %ld, out.size %lu\n",
1806 (long int) http->out.offset, (unsigned long int) http->out.size);
1807 storeAppendPrintf(s, "req_sz %ld\n", (long int) http->req_sz);
86a2f789 1808 e = http->storeEntry();
62e76326 1809 storeAppendPrintf(s, "entry %p/%s\n", e, e ? e->getMD5Text() : "N/A");
62e76326 1810 storeAppendPrintf(s, "start %ld.%06d (%f seconds ago)\n",
af0ded40
CT
1811 (long int) http->al->cache.start_time.tv_sec,
1812 (int) http->al->cache.start_time.tv_usec,
1813 tvSubDsec(http->al->cache.start_time, current_time));
2f1431ea 1814#if USE_AUTH
aee3523a 1815 if (http->request->auth_user_request != nullptr)
d3f603c8 1816 p = http->request->auth_user_request->username();
2f1431ea
AJ
1817 else
1818#endif
b38b26cb 1819 if (http->request->extacl_user.size() > 0) {
74174c03
A
1820 p = http->request->extacl_user.termedBuf();
1821 }
d3f603c8 1822
cb4f4424 1823#if USE_OPENSSL
aee3523a 1824 if (!p && conn != nullptr && Comm::IsConnOpen(conn->clientConnection))
33cc0629 1825 p = sslGetUserEmail(fd_table[conn->clientConnection->fd].ssl.get());
f4bd6296 1826#endif
1827
1828 if (!p)
1829 p = dash_str;
1830
1831 storeAppendPrintf(s, "username %s\n", p);
d3f603c8 1832
9a0a18de 1833#if USE_DELAY_POOLS
65a29f29 1834 storeAppendPrintf(s, "delay_pool %d\n", DelayId::DelayClient(http).pool());
8faa78e6 1835#endif
1836
62e76326 1837 storeAppendPrintf(s, "\n");
0f1bc304 1838 }
1839}
1840
01aebf31 1841#if STAT_GRAPHS
1842/*
1843 * urgh, i don't like these, but they do cut the amount of code down immensely
1844 */
1845
1846#define GRAPH_PER_MIN(Y) \
5db6bf73 1847 for (i=0;i<(N_COUNT_HIST-2);++i) { \
f53969cc
SM
1848 dt = tvSubDsec(CountHist[i+1].timestamp, CountHist[i].timestamp); \
1849 if (dt <= 0.0) \
1850 break; \
1851 storeAppendPrintf(e, "%lu,%0.2f:", \
1852 CountHist[i].timestamp.tv_sec, \
1853 ((CountHist[i].Y - CountHist[i+1].Y) / dt)); \
01aebf31 1854 }
1855
1856#define GRAPH_PER_HOUR(Y) \
5db6bf73 1857 for (i=0;i<(N_COUNT_HOUR_HIST-2);++i) { \
f53969cc
SM
1858 dt = tvSubDsec(CountHourHist[i+1].timestamp, CountHourHist[i].timestamp); \
1859 if (dt <= 0.0) \
1860 break; \
1861 storeAppendPrintf(e, "%lu,%0.2f:", \
1862 CountHourHist[i].timestamp.tv_sec, \
1863 ((CountHourHist[i].Y - CountHourHist[i+1].Y) / dt)); \
01aebf31 1864 }
1865
1866#define GRAPH_TITLE(X,Y) storeAppendPrintf(e,"%s\t%s\t",X,Y);
1867#define GRAPH_END storeAppendPrintf(e,"\n");
1868
1869#define GENGRAPH(X,Y,Z) \
1870 GRAPH_TITLE(Y,Z) \
1871 GRAPH_PER_MIN(X) \
1872 GRAPH_PER_HOUR(X) \
1873 GRAPH_END
1874
1875static void
1876statGraphDump(StoreEntry * e)
1877{
1878 int i;
1879 double dt;
1880
1881 GENGRAPH(client_http.requests, "client_http.requests", "Client HTTP requests/sec");
1882 GENGRAPH(client_http.hits, "client_http.hits", "Client HTTP hits/sec");
1883 GENGRAPH(client_http.errors, "client_http.errors", "Client HTTP errors/sec");
1884 GENGRAPH(client_http.kbytes_in.kb, "client_http.kbytes_in", "Client HTTP kbytes_in/sec");
1885 GENGRAPH(client_http.kbytes_out.kb, "client_http.kbytes_out", "Client HTTP kbytes_out/sec");
1886
9837567d 1887 // TODO: http median service times
01aebf31 1888
1889 GENGRAPH(server.all.requests, "server.all.requests", "Server requests/sec");
1890 GENGRAPH(server.all.errors, "server.all.errors", "Server errors/sec");
1891 GENGRAPH(server.all.kbytes_in.kb, "server.all.kbytes_in", "Server total kbytes_in/sec");
1892 GENGRAPH(server.all.kbytes_out.kb, "server.all.kbytes_out", "Server total kbytes_out/sec");
1893
1894 GENGRAPH(server.http.requests, "server.http.requests", "Server HTTP requests/sec");
1895 GENGRAPH(server.http.errors, "server.http.errors", "Server HTTP errors/sec");
1896 GENGRAPH(server.http.kbytes_in.kb, "server.http.kbytes_in", "Server HTTP kbytes_in/sec");
1897 GENGRAPH(server.http.kbytes_out.kb, "server.http.kbytes_out", "Server HTTP kbytes_out/sec");
1898
1899 GENGRAPH(server.ftp.requests, "server.ftp.requests", "Server FTP requests/sec");
1900 GENGRAPH(server.ftp.errors, "server.ftp.errors", "Server FTP errors/sec");
1901 GENGRAPH(server.ftp.kbytes_in.kb, "server.ftp.kbytes_in", "Server FTP kbytes_in/sec");
1902 GENGRAPH(server.ftp.kbytes_out.kb, "server.ftp.kbytes_out", "Server FTP kbytes_out/sec");
1903
1904 GENGRAPH(server.other.requests, "server.other.requests", "Server other requests/sec");
1905 GENGRAPH(server.other.errors, "server.other.errors", "Server other errors/sec");
1906 GENGRAPH(server.other.kbytes_in.kb, "server.other.kbytes_in", "Server other kbytes_in/sec");
1907 GENGRAPH(server.other.kbytes_out.kb, "server.other.kbytes_out", "Server other kbytes_out/sec");
1908
1909 GENGRAPH(icp.pkts_sent, "icp.pkts_sent", "ICP packets sent/sec");
1910 GENGRAPH(icp.pkts_recv, "icp.pkts_recv", "ICP packets received/sec");
1911 GENGRAPH(icp.kbytes_sent.kb, "icp.kbytes_sent", "ICP kbytes_sent/sec");
1912 GENGRAPH(icp.kbytes_recv.kb, "icp.kbytes_recv", "ICP kbytes_received/sec");
1913
9837567d
AJ
1914 // TODO: icp median service times
1915 // TODO: dns median service times
01aebf31 1916
1917 GENGRAPH(unlink.requests, "unlink.requests", "Cache File unlink requests/sec");
1918 GENGRAPH(page_faults, "page_faults", "System Page Faults/sec");
1919 GENGRAPH(select_loops, "select_loops", "System Select Loop calls/sec");
1920 GENGRAPH(cputime, "cputime", "CPU utilisation");
1921}
1afe05c5 1922
d96ceb8e 1923#endif /* STAT_GRAPHS */
1924