]> git.ipfire.org Git - thirdparty/squid.git/blob - src/stat.cc
Merged from trunk
[thirdparty/squid.git] / src / stat.cc
1 /*
2 * DEBUG: section 18 Cache Manager Statistics
3 * AUTHOR: Harvest Derived
4 *
5 * SQUID Web Proxy Cache http://www.squid-cache.org/
6 * ----------------------------------------------------------
7 *
8 * Squid is the result of efforts by numerous individuals from
9 * the Internet community; see the CONTRIBUTORS file for full
10 * details. Many organizations have provided support for Squid's
11 * development; see the SPONSORS file for full details. Squid is
12 * Copyrighted (C) 2001 by the Regents of the University of
13 * California; see the COPYRIGHT file for full details. Squid
14 * incorporates software developed and/or copyrighted by other
15 * sources; see the CREDITS file for full details.
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
30 *
31 */
32
33 #include "squid.h"
34 #include "CacheDigest.h"
35 #include "CachePeer.h"
36 #include "client_side_request.h"
37 #include "client_side.h"
38 #include "comm/Connection.h"
39 #include "comm/Loops.h"
40 #include "event.h"
41 #include "fde.h"
42 #include "format/Token.h"
43 #include "globals.h"
44 #include "HttpRequest.h"
45 #include "IoStats.h"
46 #include "MemObject.h"
47 #include "mem_node.h"
48 #include "MemBuf.h"
49 #include "mgr/CountersAction.h"
50 #include "mgr/FunAction.h"
51 #include "mgr/InfoAction.h"
52 #include "mgr/IntervalAction.h"
53 #include "mgr/IoAction.h"
54 #include "mgr/Registration.h"
55 #include "mgr/ServiceTimesAction.h"
56 #include "neighbors.h"
57 #include "PeerDigest.h"
58 #include "SquidConfig.h"
59 #include "SquidMath.h"
60 #include "SquidTime.h"
61 #include "StatCounters.h"
62 #include "stat.h"
63 #include "StoreClient.h"
64 #include "Store.h"
65 #include "store_digest.h"
66 #include "tools.h"
67 #if USE_AUTH
68 #include "auth/UserRequest.h"
69 #endif
70 #if USE_DELAY_POOLS
71 #include "DelayId.h"
72 #endif
73 #if USE_SSL
74 #include "ssl/support.h"
75 #endif
76
77 /* these are included because they expose stats calls */
78 /* TODO: provide a self registration mechanism for those classes
79 * to use during static construction
80 */
81 #include "comm.h"
82 #include "StoreSearch.h"
83
84 #define DEBUG_OPENFD 1
85
86 typedef int STOBJFLT(const StoreEntry *);
87
88 class StatObjectsState
89 {
90
91 public:
92 StoreEntry *sentry;
93 STOBJFLT *filter;
94 StoreSearchPointer theSearch;
95
96 private:
97 CBDATA_CLASS2(StatObjectsState);
98 };
99
100 /* LOCALS */
101 static const char *describeStatuses(const StoreEntry *);
102 static const char *describeTimestamps(const StoreEntry *);
103 static void statAvgTick(void *notused);
104 static void statAvgDump(StoreEntry *, int minutes, int hours);
105 #if STAT_GRAPHS
106 static void statGraphDump(StoreEntry *);
107 #endif
108 static void statCountersInit(StatCounters *);
109 static void statCountersInitSpecial(StatCounters *);
110 static void statCountersClean(StatCounters *);
111 static void statCountersCopy(StatCounters * dest, const StatCounters * orig);
112 static double statPctileSvc(double, int, int);
113 static void statStoreEntry(MemBuf * mb, StoreEntry * e);
114 static double statCPUUsage(int minutes);
115 static OBJH stat_objects_get;
116 static OBJH stat_vmobjects_get;
117 #if DEBUG_OPENFD
118 static OBJH statOpenfdObj;
119 #endif
120 static EVH statObjects;
121 static OBJH statCountersDump;
122 static OBJH statPeerSelect;
123 static OBJH statDigestBlob;
124 static OBJH statUtilization;
125 static OBJH statCountersHistograms;
126 static OBJH statClientRequests;
127 void GetAvgStat(Mgr::IntervalActionData& stats, int minutes, int hours);
128 void DumpAvgStat(Mgr::IntervalActionData& stats, StoreEntry* sentry);
129 void GetInfo(Mgr::InfoActionData& stats);
130 void DumpInfo(Mgr::InfoActionData& stats, StoreEntry* sentry);
131 void DumpMallocStatistics(StoreEntry* sentry);
132 void GetCountersStats(Mgr::CountersActionData& stats);
133 void DumpCountersStats(Mgr::CountersActionData& stats, StoreEntry* sentry);
134 void GetServiceTimesStats(Mgr::ServiceTimesActionData& stats);
135 void DumpServiceTimesStats(Mgr::ServiceTimesActionData& stats, StoreEntry* sentry);
136 void GetIoStats(Mgr::IoActionData& stats);
137 void DumpIoStats(Mgr::IoActionData& stats, StoreEntry* sentry);
138
139 #if XMALLOC_STATISTICS
140 static void info_get_mallstat(int, int, int, void *);
141 static double xm_time;
142 static double xm_deltat;
143 #endif
144
145 StatCounters CountHist[N_COUNT_HIST];
146 static int NCountHist = 0;
147 static StatCounters CountHourHist[N_COUNT_HOUR_HIST];
148 static int NCountHourHist = 0;
149 CBDATA_CLASS_INIT(StatObjectsState);
150
151 extern unsigned int mem_pool_alloc_calls;
152 extern unsigned int mem_pool_free_calls;
153
154 static void
155 statUtilization(StoreEntry * e)
156 {
157 storeAppendPrintf(e, "Cache Utilisation:\n");
158 storeAppendPrintf(e, "\n");
159 storeAppendPrintf(e, "Last 5 minutes:\n");
160
161 if (NCountHist >= 5)
162 statAvgDump(e, 5, 0);
163 else
164 storeAppendPrintf(e, "(no values recorded yet)\n");
165
166 storeAppendPrintf(e, "\n");
167
168 storeAppendPrintf(e, "Last 15 minutes:\n");
169
170 if (NCountHist >= 15)
171 statAvgDump(e, 15, 0);
172 else
173 storeAppendPrintf(e, "(no values recorded yet)\n");
174
175 storeAppendPrintf(e, "\n");
176
177 storeAppendPrintf(e, "Last hour:\n");
178
179 if (NCountHist >= 60)
180 statAvgDump(e, 60, 0);
181 else
182 storeAppendPrintf(e, "(no values recorded yet)\n");
183
184 storeAppendPrintf(e, "\n");
185
186 storeAppendPrintf(e, "Last 8 hours:\n");
187
188 if (NCountHourHist >= 8)
189 statAvgDump(e, 0, 8);
190 else
191 storeAppendPrintf(e, "(no values recorded yet)\n");
192
193 storeAppendPrintf(e, "\n");
194
195 storeAppendPrintf(e, "Last day:\n");
196
197 if (NCountHourHist >= 24)
198 statAvgDump(e, 0, 24);
199 else
200 storeAppendPrintf(e, "(no values recorded yet)\n");
201
202 storeAppendPrintf(e, "\n");
203
204 storeAppendPrintf(e, "Last 3 days:\n");
205
206 if (NCountHourHist >= 72)
207 statAvgDump(e, 0, 72);
208 else
209 storeAppendPrintf(e, "(no values recorded yet)\n");
210
211 storeAppendPrintf(e, "\n");
212
213 storeAppendPrintf(e, "Totals since cache startup:\n");
214
215 statCountersDump(e);
216 }
217
218 void
219 GetIoStats(Mgr::IoActionData& stats)
220 {
221 int i;
222
223 stats.http_reads = IOStats.Http.reads;
224
225 for (i = 0; i < IoStats::histSize; ++i) {
226 stats.http_read_hist[i] = IOStats.Http.read_hist[i];
227 }
228
229 stats.ftp_reads = IOStats.Ftp.reads;
230
231 for (i = 0; i < IoStats::histSize; ++i) {
232 stats.ftp_read_hist[i] = IOStats.Ftp.read_hist[i];
233 }
234
235 stats.gopher_reads = IOStats.Gopher.reads;
236
237 for (i = 0; i < IoStats::histSize; ++i) {
238 stats.gopher_read_hist[i] = IOStats.Gopher.read_hist[i];
239 }
240 }
241
242 void
243 DumpIoStats(Mgr::IoActionData& stats, StoreEntry* sentry)
244 {
245 int i;
246
247 storeAppendPrintf(sentry, "HTTP I/O\n");
248 storeAppendPrintf(sentry, "number of reads: %.0f\n", stats.http_reads);
249 storeAppendPrintf(sentry, "Read Histogram:\n");
250
251 for (i = 0; i < IoStats::histSize; ++i) {
252 storeAppendPrintf(sentry, "%5d-%5d: %9.0f %2.0f%%\n",
253 i ? (1 << (i - 1)) + 1 : 1,
254 1 << i,
255 stats.http_read_hist[i],
256 Math::doublePercent(stats.http_read_hist[i], stats.http_reads));
257 }
258
259 storeAppendPrintf(sentry, "\n");
260 storeAppendPrintf(sentry, "FTP I/O\n");
261 storeAppendPrintf(sentry, "number of reads: %.0f\n", stats.ftp_reads);
262 storeAppendPrintf(sentry, "Read Histogram:\n");
263
264 for (i = 0; i < IoStats::histSize; ++i) {
265 storeAppendPrintf(sentry, "%5d-%5d: %9.0f %2.0f%%\n",
266 i ? (1 << (i - 1)) + 1 : 1,
267 1 << i,
268 stats.ftp_read_hist[i],
269 Math::doublePercent(stats.ftp_read_hist[i], stats.ftp_reads));
270 }
271
272 storeAppendPrintf(sentry, "\n");
273 storeAppendPrintf(sentry, "Gopher I/O\n");
274 storeAppendPrintf(sentry, "number of reads: %.0f\n", stats.gopher_reads);
275 storeAppendPrintf(sentry, "Read Histogram:\n");
276
277 for (i = 0; i < IoStats::histSize; ++i) {
278 storeAppendPrintf(sentry, "%5d-%5d: %9.0f %2.0f%%\n",
279 i ? (1 << (i - 1)) + 1 : 1,
280 1 << i,
281 stats.gopher_read_hist[i],
282 Math::doublePercent(stats.gopher_read_hist[i], stats.gopher_reads));
283 }
284
285 storeAppendPrintf(sentry, "\n");
286 }
287
288 static const char *
289 describeStatuses(const StoreEntry * entry)
290 {
291 LOCAL_ARRAY(char, buf, 256);
292 snprintf(buf, 256, "%-13s %-13s %-12s %-12s",
293 storeStatusStr[entry->store_status],
294 memStatusStr[entry->mem_status],
295 swapStatusStr[entry->swap_status],
296 pingStatusStr[entry->ping_status]);
297 return buf;
298 }
299
300 const char *
301 storeEntryFlags(const StoreEntry * entry)
302 {
303 LOCAL_ARRAY(char, buf, 256);
304 int flags = (int) entry->flags;
305 char *t;
306 buf[0] = '\0';
307
308 if (EBIT_TEST(flags, ENTRY_SPECIAL))
309 strcat(buf, "SPECIAL,");
310
311 if (EBIT_TEST(flags, ENTRY_REVALIDATE))
312 strcat(buf, "REVALIDATE,");
313
314 if (EBIT_TEST(flags, DELAY_SENDING))
315 strcat(buf, "DELAY_SENDING,");
316
317 if (EBIT_TEST(flags, RELEASE_REQUEST))
318 strcat(buf, "RELEASE_REQUEST,");
319
320 if (EBIT_TEST(flags, REFRESH_REQUEST))
321 strcat(buf, "REFRESH_REQUEST,");
322
323 if (EBIT_TEST(flags, ENTRY_CACHABLE))
324 strcat(buf, "CACHABLE,");
325
326 if (EBIT_TEST(flags, ENTRY_DISPATCHED))
327 strcat(buf, "DISPATCHED,");
328
329 if (EBIT_TEST(flags, KEY_PRIVATE))
330 strcat(buf, "PRIVATE,");
331
332 if (EBIT_TEST(flags, ENTRY_FWD_HDR_WAIT))
333 strcat(buf, "FWD_HDR_WAIT,");
334
335 if (EBIT_TEST(flags, ENTRY_NEGCACHED))
336 strcat(buf, "NEGCACHED,");
337
338 if (EBIT_TEST(flags, ENTRY_VALIDATED))
339 strcat(buf, "VALIDATED,");
340
341 if (EBIT_TEST(flags, ENTRY_BAD_LENGTH))
342 strcat(buf, "BAD_LENGTH,");
343
344 if (EBIT_TEST(flags, ENTRY_ABORTED))
345 strcat(buf, "ABORTED,");
346
347 if ((t = strrchr(buf, ',')))
348 *t = '\0';
349
350 return buf;
351 }
352
353 static const char *
354 describeTimestamps(const StoreEntry * entry)
355 {
356 LOCAL_ARRAY(char, buf, 256);
357 snprintf(buf, 256, "LV:%-9d LU:%-9d LM:%-9d EX:%-9d",
358 (int) entry->timestamp,
359 (int) entry->lastref,
360 (int) entry->lastmod,
361 (int) entry->expires);
362 return buf;
363 }
364
365 static void
366 statStoreEntry(MemBuf * mb, StoreEntry * e)
367 {
368 MemObject *mem = e->mem_obj;
369 mb->Printf("KEY %s\n", e->getMD5Text());
370 mb->Printf("\t%s\n", describeStatuses(e));
371 mb->Printf("\t%s\n", storeEntryFlags(e));
372 mb->Printf("\t%s\n", describeTimestamps(e));
373 mb->Printf("\t%d locks, %d clients, %d refs\n",
374 (int) e->lock_count,
375 storePendingNClients(e),
376 (int) e->refcount);
377 mb->Printf("\tSwap Dir %d, File %#08X\n",
378 e->swap_dirn, e->swap_filen);
379
380 if (mem != NULL)
381 mem->stat (mb);
382
383 mb->Printf("\n");
384 }
385
386 /* process objects list */
387 static void
388 statObjects(void *data)
389 {
390 StatObjectsState *state = static_cast<StatObjectsState *>(data);
391 StoreEntry *e;
392
393 if (state->theSearch->isDone()) {
394 if (UsingSmp())
395 storeAppendPrintf(state->sentry, "} by kid%d\n\n", KidIdentifier);
396 state->sentry->complete();
397 state->sentry->unlock();
398 cbdataFree(state);
399 return;
400 } else if (EBIT_TEST(state->sentry->flags, ENTRY_ABORTED)) {
401 state->sentry->unlock();
402 cbdataFree(state);
403 return;
404 } else if (state->sentry->checkDeferRead(-1)) {
405 state->sentry->flush();
406 eventAdd("statObjects", statObjects, state, 0.1, 1);
407 return;
408 }
409
410 state->sentry->buffer();
411 size_t statCount = 0;
412 MemBuf mb;
413 mb.init();
414
415 while (statCount++ < static_cast<size_t>(Config.Store.objectsPerBucket) && state->
416 theSearch->next()) {
417 e = state->theSearch->currentItem();
418
419 if (state->filter && 0 == state->filter(e))
420 continue;
421
422 statStoreEntry(&mb, e);
423 }
424
425 if (mb.size)
426 state->sentry->append(mb.buf, mb.size);
427 mb.clean();
428
429 eventAdd("statObjects", statObjects, state, 0.0, 1);
430 }
431
432 static void
433 statObjectsStart(StoreEntry * sentry, STOBJFLT * filter)
434 {
435 StatObjectsState *state = new StatObjectsState;
436 state->sentry = sentry;
437 state->filter = filter;
438
439 sentry->lock();
440 state->theSearch = Store::Root().search(NULL, NULL);
441
442 eventAdd("statObjects", statObjects, state, 0.0, 1);
443 }
444
445 static void
446 stat_objects_get(StoreEntry * sentry)
447 {
448 statObjectsStart(sentry, NULL);
449 }
450
451 static int
452 statObjectsVmFilter(const StoreEntry * e)
453 {
454 return e->mem_obj ? 1 : 0;
455 }
456
457 static void
458 stat_vmobjects_get(StoreEntry * sentry)
459 {
460 statObjectsStart(sentry, statObjectsVmFilter);
461 }
462
463 #if DEBUG_OPENFD
464 static int
465 statObjectsOpenfdFilter(const StoreEntry * e)
466 {
467 if (e->mem_obj == NULL)
468 return 0;
469
470 if (e->mem_obj->swapout.sio == NULL)
471 return 0;
472
473 return 1;
474 }
475
476 static void
477 statOpenfdObj(StoreEntry * sentry)
478 {
479 statObjectsStart(sentry, statObjectsOpenfdFilter);
480 }
481
482 #endif
483
484 #if XMALLOC_STATISTICS
485 static void
486 info_get_mallstat(int size, int number, int oldnum, void *data)
487 {
488 StoreEntry *sentry = (StoreEntry *)data;
489
490 // format: "%12s %15s %6s %12s\n","Alloc Size","Count","Delta","Alloc/sec"
491 if (number > 0)
492 storeAppendPrintf(sentry, "%12d %15d %6d %.1f\n", size, number, number - oldnum, xdiv((number - oldnum), xm_deltat));
493 }
494
495 #endif
496
497 void
498 GetInfo(Mgr::InfoActionData& stats)
499 {
500
501 struct rusage rusage;
502 double cputime;
503 double runtime;
504 #if HAVE_MSTATS && HAVE_GNUMALLOC_H
505
506 struct mstats ms;
507 #elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
508
509 struct mallinfo mp;
510 #endif
511
512 runtime = tvSubDsec(squid_start, current_time);
513
514 if (runtime == 0.0)
515 runtime = 1.0;
516
517 stats.squid_start = squid_start;
518
519 stats.current_time = current_time;
520
521 stats.client_http_clients = statCounter.client_http.clients;
522
523 stats.client_http_requests = statCounter.client_http.requests;
524
525 stats.icp_pkts_recv = statCounter.icp.pkts_recv;
526
527 stats.icp_pkts_sent = statCounter.icp.pkts_sent;
528
529 stats.icp_replies_queued = statCounter.icp.replies_queued;
530
531 #if USE_HTCP
532
533 stats.htcp_pkts_recv = statCounter.htcp.pkts_recv;
534
535 stats.htcp_pkts_sent = statCounter.htcp.pkts_sent;
536
537 #endif
538
539 stats.request_failure_ratio = request_failure_ratio;
540
541 stats.avg_client_http_requests = statCounter.client_http.requests / (runtime / 60.0);
542
543 stats.avg_icp_messages = (statCounter.icp.pkts_sent + statCounter.icp.pkts_recv) / (runtime / 60.0);
544
545 stats.select_loops = statCounter.select_loops;
546 stats.avg_loop_time = 1000.0 * runtime / statCounter.select_loops;
547
548 stats.request_hit_ratio5 = statRequestHitRatio(5);
549 stats.request_hit_ratio60 = statRequestHitRatio(60);
550
551 stats.byte_hit_ratio5 = statByteHitRatio(5);
552 stats.byte_hit_ratio60 = statByteHitRatio(60);
553
554 stats.request_hit_mem_ratio5 = statRequestHitMemoryRatio(5);
555 stats.request_hit_mem_ratio60 = statRequestHitMemoryRatio(60);
556
557 stats.request_hit_disk_ratio5 = statRequestHitDiskRatio(5);
558 stats.request_hit_disk_ratio60 = statRequestHitDiskRatio(60);
559
560 Store::Root().getStats(stats.store);
561
562 stats.unlink_requests = statCounter.unlink.requests;
563
564 stats.http_requests5 = statPctileSvc(0.5, 5, PCTILE_HTTP);
565 stats.http_requests60 = statPctileSvc(0.5, 60, PCTILE_HTTP);
566
567 stats.cache_misses5 = statPctileSvc(0.5, 5, PCTILE_MISS);
568 stats.cache_misses60 = statPctileSvc(0.5, 60, PCTILE_MISS);
569
570 stats.cache_hits5 = statPctileSvc(0.5, 5, PCTILE_HIT);
571 stats.cache_hits60 = statPctileSvc(0.5, 60, PCTILE_HIT);
572
573 stats.near_hits5 = statPctileSvc(0.5, 5, PCTILE_NH);
574 stats.near_hits60 = statPctileSvc(0.5, 60, PCTILE_NH);
575
576 stats.not_modified_replies5 = statPctileSvc(0.5, 5, PCTILE_NM);
577 stats.not_modified_replies60 = statPctileSvc(0.5, 60, PCTILE_NM);
578
579 stats.dns_lookups5 = statPctileSvc(0.5, 5, PCTILE_DNS);
580 stats.dns_lookups60 = statPctileSvc(0.5, 60, PCTILE_DNS);
581
582 stats.icp_queries5 = statPctileSvc(0.5, 5, PCTILE_ICP_QUERY);
583 stats.icp_queries60 = statPctileSvc(0.5, 60, PCTILE_ICP_QUERY);
584
585 squid_getrusage(&rusage);
586 cputime = rusage_cputime(&rusage);
587
588 stats.up_time = runtime;
589 stats.cpu_time = cputime;
590 stats.cpu_usage = Math::doublePercent(cputime, runtime);
591 stats.cpu_usage5 = statCPUUsage(5);
592 stats.cpu_usage60 = statCPUUsage(60);
593
594 #if HAVE_SBRK
595
596 stats.proc_data_seg = ((char *) sbrk(0) - (char *) sbrk_start);
597
598 #endif
599
600 stats.maxrss = rusage_maxrss(&rusage);
601
602 stats.page_faults = rusage_pagefaults(&rusage);
603
604 #if HAVE_MSTATS && HAVE_GNUMALLOC_H
605
606 ms = mstats();
607
608 stats.ms_bytes_total = ms.bytes_total;
609
610 stats.ms_bytes_free = ms.bytes_free;
611
612 #elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
613
614 mp = mallinfo();
615
616 stats.mp_arena = mp.arena;
617
618 stats.mp_uordblks = mp.uordblks;
619 stats.mp_ordblks = mp.ordblks;
620
621 stats.mp_usmblks = mp.usmblks;
622 stats.mp_smblks = mp.smblks;
623
624 stats.mp_hblkhd = mp.hblkhd;
625 stats.mp_hblks = mp.hblks;
626
627 stats.mp_fsmblks = mp.fsmblks;
628
629 stats.mp_fordblks = mp.fordblks;
630
631 #if HAVE_STRUCT_MALLINFO_MXFAST
632
633 stats.mp_mxfast = mp.mxfast;
634
635 stats.mp_nlblks = mp.nlblks;
636
637 stats.mp_grain = mp.grain;
638
639 stats.mp_uordbytes = mp.uordbytes;
640
641 stats.mp_allocated = mp.allocated;
642
643 stats.mp_treeoverhead = mp.treeoverhead;
644
645 #endif /* HAVE_STRUCT_MALLINFO_MXFAST */
646 #endif /* HAVE_MALLINFO */
647
648 stats.total_accounted = statMemoryAccounted();
649
650 {
651 MemPoolGlobalStats mp_stats;
652 memPoolGetGlobalStats(&mp_stats);
653 #if !(HAVE_MSTATS && HAVE_GNUMALLOC_H) && HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
654
655 stats.mem_pool_allocated = mp_stats.TheMeter->alloc.level;
656 #endif
657
658 stats.gb_saved_count = mp_stats.TheMeter->gb_saved.count;
659 stats.gb_freed_count = mp_stats.TheMeter->gb_freed.count;
660 }
661
662 stats.max_fd = Squid_MaxFD;
663 stats.biggest_fd = Biggest_FD;
664 stats.number_fd = Number_FD;
665 stats.opening_fd = Opening_FD;
666 stats.num_fd_free = fdNFree();
667 stats.reserved_fd = RESERVED_FD;
668 }
669
670 void
671 DumpInfo(Mgr::InfoActionData& stats, StoreEntry* sentry)
672 {
673 storeAppendPrintf(sentry, "Squid Object Cache: Version %s\n",
674 version_string);
675
676 storeAppendPrintf(sentry, "Build Info: " SQUID_BUILD_INFO "\n");
677
678 #if _SQUID_WINDOWS_
679 if (WIN32_run_mode == _WIN_SQUID_RUN_MODE_SERVICE) {
680 storeAppendPrintf(sentry,"\nRunning as %s Windows System Service on %s\n",
681 WIN32_Service_name, WIN32_OS_string);
682 storeAppendPrintf(sentry,"Service command line is: %s\n", WIN32_Service_Command_Line);
683 } else
684 storeAppendPrintf(sentry,"Running on %s\n",WIN32_OS_string);
685 #endif
686
687 storeAppendPrintf(sentry, "Start Time:\t%s\n",
688 mkrfc1123(stats.squid_start.tv_sec));
689
690 storeAppendPrintf(sentry, "Current Time:\t%s\n",
691 mkrfc1123(stats.current_time.tv_sec));
692
693 storeAppendPrintf(sentry, "Connection information for %s:\n",APP_SHORTNAME);
694
695 storeAppendPrintf(sentry, "\tNumber of clients accessing cache:\t%.0f\n",
696 stats.client_http_clients);
697
698 storeAppendPrintf(sentry, "\tNumber of HTTP requests received:\t%.0f\n",
699 stats.client_http_requests);
700
701 storeAppendPrintf(sentry, "\tNumber of ICP messages received:\t%.0f\n",
702 stats.icp_pkts_recv);
703
704 storeAppendPrintf(sentry, "\tNumber of ICP messages sent:\t%.0f\n",
705 stats.icp_pkts_sent);
706
707 storeAppendPrintf(sentry, "\tNumber of queued ICP replies:\t%.0f\n",
708 stats.icp_replies_queued);
709
710 #if USE_HTCP
711
712 storeAppendPrintf(sentry, "\tNumber of HTCP messages received:\t%.0f\n",
713 stats.htcp_pkts_recv);
714
715 storeAppendPrintf(sentry, "\tNumber of HTCP messages sent:\t%.0f\n",
716 stats.htcp_pkts_sent);
717
718 #endif
719
720 double fct = stats.count > 1 ? stats.count : 1.0;
721 storeAppendPrintf(sentry, "\tRequest failure ratio:\t%5.2f\n",
722 stats.request_failure_ratio / fct);
723
724 storeAppendPrintf(sentry, "\tAverage HTTP requests per minute since start:\t%.1f\n",
725 stats.avg_client_http_requests);
726
727 storeAppendPrintf(sentry, "\tAverage ICP messages per minute since start:\t%.1f\n",
728 stats.avg_icp_messages);
729
730 storeAppendPrintf(sentry, "\tSelect loop called: %.0f times, %0.3f ms avg\n",
731 stats.select_loops, stats.avg_loop_time / fct);
732
733 storeAppendPrintf(sentry, "Cache information for %s:\n",APP_SHORTNAME);
734
735 storeAppendPrintf(sentry, "\tHits as %% of all requests:\t5min: %3.1f%%, 60min: %3.1f%%\n",
736 stats.request_hit_ratio5 / fct,
737 stats.request_hit_ratio60 / fct);
738
739 storeAppendPrintf(sentry, "\tHits as %% of bytes sent:\t5min: %3.1f%%, 60min: %3.1f%%\n",
740 stats.byte_hit_ratio5 / fct,
741 stats.byte_hit_ratio60 / fct);
742
743 storeAppendPrintf(sentry, "\tMemory hits as %% of hit requests:\t5min: %3.1f%%, 60min: %3.1f%%\n",
744 stats.request_hit_mem_ratio5 / fct,
745 stats.request_hit_mem_ratio60 / fct);
746
747 storeAppendPrintf(sentry, "\tDisk hits as %% of hit requests:\t5min: %3.1f%%, 60min: %3.1f%%\n",
748 stats.request_hit_disk_ratio5 / fct,
749 stats.request_hit_disk_ratio60 / fct);
750
751 storeAppendPrintf(sentry, "\tStorage Swap size:\t%.0f KB\n",
752 stats.store.swap.size / 1024);
753
754 storeAppendPrintf(sentry, "\tStorage Swap capacity:\t%4.1f%% used, %4.1f%% free\n",
755 Math::doublePercent(stats.store.swap.size, stats.store.swap.capacity),
756 Math::doublePercent(stats.store.swap.available(), stats.store.swap.capacity));
757
758 storeAppendPrintf(sentry, "\tStorage Mem size:\t%.0f KB\n",
759 stats.store.mem.size / 1024);
760
761 storeAppendPrintf(sentry, "\tStorage Mem capacity:\t%4.1f%% used, %4.1f%% free\n",
762 Math::doublePercent(stats.store.mem.size, stats.store.mem.capacity),
763 Math::doublePercent(stats.store.mem.available(), stats.store.mem.capacity));
764
765 storeAppendPrintf(sentry, "\tMean Object Size:\t%0.2f KB\n",
766 stats.store.swap.meanObjectSize() / 1024);
767
768 storeAppendPrintf(sentry, "\tRequests given to unlinkd:\t%.0f\n",
769 stats.unlink_requests);
770
771 storeAppendPrintf(sentry, "Median Service Times (seconds) 5 min 60 min:\n");
772
773 fct = stats.count > 1 ? stats.count * 1000.0 : 1000.0;
774 storeAppendPrintf(sentry, "\tHTTP Requests (All): %8.5f %8.5f\n",
775 stats.http_requests5 / fct,
776 stats.http_requests60 / fct);
777
778 storeAppendPrintf(sentry, "\tCache Misses: %8.5f %8.5f\n",
779 stats.cache_misses5 / fct,
780 stats.cache_misses60 / fct);
781
782 storeAppendPrintf(sentry, "\tCache Hits: %8.5f %8.5f\n",
783 stats.cache_hits5 / fct,
784 stats.cache_hits60 / fct);
785
786 storeAppendPrintf(sentry, "\tNear Hits: %8.5f %8.5f\n",
787 stats.near_hits5 / fct,
788 stats.near_hits60 / fct);
789
790 storeAppendPrintf(sentry, "\tNot-Modified Replies: %8.5f %8.5f\n",
791 stats.not_modified_replies5 / fct,
792 stats.not_modified_replies60 / fct);
793
794 storeAppendPrintf(sentry, "\tDNS Lookups: %8.5f %8.5f\n",
795 stats.dns_lookups5 / fct,
796 stats.dns_lookups60 / fct);
797
798 fct = stats.count > 1 ? stats.count * 1000000.0 : 1000000.0;
799 storeAppendPrintf(sentry, "\tICP Queries: %8.5f %8.5f\n",
800 stats.icp_queries5 / fct,
801 stats.icp_queries60 / fct);
802
803 storeAppendPrintf(sentry, "Resource usage for %s:\n", APP_SHORTNAME);
804
805 storeAppendPrintf(sentry, "\tUP Time:\t%.3f seconds\n", stats.up_time);
806
807 storeAppendPrintf(sentry, "\tCPU Time:\t%.3f seconds\n", stats.cpu_time);
808
809 storeAppendPrintf(sentry, "\tCPU Usage:\t%.2f%%\n",
810 stats.cpu_usage);
811
812 storeAppendPrintf(sentry, "\tCPU Usage, 5 minute avg:\t%.2f%%\n",
813 stats.cpu_usage5);
814
815 storeAppendPrintf(sentry, "\tCPU Usage, 60 minute avg:\t%.2f%%\n",
816 stats.cpu_usage60);
817
818 #if HAVE_SBRK
819
820 storeAppendPrintf(sentry, "\tProcess Data Segment Size via sbrk(): %.0f KB\n",
821 stats.proc_data_seg / 1024);
822
823 #endif
824
825 storeAppendPrintf(sentry, "\tMaximum Resident Size: %.0f KB\n",
826 stats.maxrss);
827
828 storeAppendPrintf(sentry, "\tPage faults with physical i/o: %.0f\n",
829 stats.page_faults);
830
831 #if HAVE_MSTATS && HAVE_GNUMALLOC_H
832
833 storeAppendPrintf(sentry, "Memory usage for %s via mstats():\n",APP_SHORTNAME);
834
835 storeAppendPrintf(sentry, "\tTotal space in arena: %6.0f KB\n",
836 stats.ms_bytes_total / 1024);
837
838 storeAppendPrintf(sentry, "\tTotal free: %6.0f KB %.0f%%\n",
839 stats.ms_bytes_free / 1024,
840 Math::doublePercent(stats.ms_bytes_free, stats.ms_bytes_total));
841
842 #elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
843
844 storeAppendPrintf(sentry, "Memory usage for %s via mallinfo():\n",APP_SHORTNAME);
845
846 storeAppendPrintf(sentry, "\tTotal space in arena: %6.0f KB\n",
847 stats.mp_arena / 1024);
848
849 storeAppendPrintf(sentry, "\tOrdinary blocks: %6.0f KB %6.0f blks\n",
850 stats.mp_uordblks / 1024, stats.mp_ordblks);
851
852 storeAppendPrintf(sentry, "\tSmall blocks: %6.0f KB %6.0f blks\n",
853 stats.mp_usmblks / 1024, stats.mp_smblks);
854
855 storeAppendPrintf(sentry, "\tHolding blocks: %6.0f KB %6.0f blks\n",
856 stats.mp_hblkhd / 1024, stats.mp_hblks);
857
858 storeAppendPrintf(sentry, "\tFree Small blocks: %6.0f KB\n",
859 stats.mp_fsmblks / 1024);
860
861 storeAppendPrintf(sentry, "\tFree Ordinary blocks: %6.0f KB\n",
862 stats.mp_fordblks / 1024);
863
864 double t = stats.mp_fsmblks + stats.mp_fordblks;
865
866 storeAppendPrintf(sentry, "\tTotal in use: %6.0f KB %.0f%%\n",
867 t / 1024, Math::doublePercent(t, stats.mp_arena + stats.mp_hblkhd));
868
869 t = stats.mp_fsmblks + stats.mp_fordblks;
870
871 storeAppendPrintf(sentry, "\tTotal free: %6.0f KB %.0f%%\n",
872 t / 1024, Math::doublePercent(t, stats.mp_arena + stats.mp_hblkhd));
873
874 t = stats.mp_arena + stats.mp_hblkhd;
875
876 storeAppendPrintf(sentry, "\tTotal size: %6.0f KB\n",
877 t / 1024);
878
879 #if HAVE_STRUCT_MALLINFO_MXFAST
880
881 storeAppendPrintf(sentry, "\tmax size of small blocks:\t%.0f\n", stats.mp_mxfast);
882
883 storeAppendPrintf(sentry, "\tnumber of small blocks in a holding block:\t%.0f\n",
884 stats.mp_nlblks);
885
886 storeAppendPrintf(sentry, "\tsmall block rounding factor:\t%.0f\n", stats.mp_grain);
887
888 storeAppendPrintf(sentry, "\tspace (including overhead) allocated in ord. blks:\t%.0f\n"
889 ,stats.mp_uordbytes);
890
891 storeAppendPrintf(sentry, "\tnumber of ordinary blocks allocated:\t%.0f\n",
892 stats.mp_allocated);
893
894 storeAppendPrintf(sentry, "\tbytes used in maintaining the free tree:\t%.0f\n",
895 stats.mp_treeoverhead);
896
897 #endif /* HAVE_STRUCT_MALLINFO_MXFAST */
898 #endif /* HAVE_MALLINFO */
899
900 storeAppendPrintf(sentry, "Memory accounted for:\n");
901
902 #if !(HAVE_MSTATS && HAVE_GNUMALLOC_H) && HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
903
904 storeAppendPrintf(sentry, "\tTotal accounted: %6.0f KB %3.0f%%\n",
905 stats.total_accounted / 1024, Math::doublePercent(stats.total_accounted, t));
906
907 #else
908
909 storeAppendPrintf(sentry, "\tTotal accounted: %6.0f KB\n",
910 stats.total_accounted / 1024);
911
912 #endif
913 {
914 MemPoolGlobalStats mp_stats;
915 memPoolGetGlobalStats(&mp_stats);
916 #if !(HAVE_MSTATS && HAVE_GNUMALLOC_H) && HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
917
918 storeAppendPrintf(sentry, "\tmemPool accounted: %6.0f KB %3.0f%%\n",
919 stats.mem_pool_allocated / 1024,
920 Math::doublePercent(stats.mem_pool_allocated, t));
921
922 const double iFree = max(0.0, t - stats.mem_pool_allocated);
923 storeAppendPrintf(sentry, "\tmemPool unaccounted: %6.0f KB %3.0f%%\n",
924 (t - stats.mem_pool_allocated) / 1024,
925 Math::doublePercent(iFree, t));
926 #endif
927
928 storeAppendPrintf(sentry, "\tmemPoolAlloc calls: %9.0f\n",
929 stats.gb_saved_count);
930 storeAppendPrintf(sentry, "\tmemPoolFree calls: %9.0f\n",
931 stats.gb_freed_count);
932 }
933
934 storeAppendPrintf(sentry, "File descriptor usage for %s:\n", APP_SHORTNAME);
935 storeAppendPrintf(sentry, "\tMaximum number of file descriptors: %4.0f\n",
936 stats.max_fd);
937 storeAppendPrintf(sentry, "\tLargest file desc currently in use: %4.0f\n",
938 stats.biggest_fd);
939 storeAppendPrintf(sentry, "\tNumber of file desc currently in use: %4.0f\n",
940 stats.number_fd);
941 storeAppendPrintf(sentry, "\tFiles queued for open: %4.0f\n",
942 stats.opening_fd);
943 storeAppendPrintf(sentry, "\tAvailable number of file descriptors: %4.0f\n",
944 stats.num_fd_free);
945 storeAppendPrintf(sentry, "\tReserved number of file descriptors: %4.0f\n",
946 stats.reserved_fd);
947 storeAppendPrintf(sentry, "\tStore Disk files open: %4.0f\n",
948 stats.store.swap.open_disk_fd);
949
950 storeAppendPrintf(sentry, "Internal Data Structures:\n");
951 storeAppendPrintf(sentry, "\t%6.0f StoreEntries\n",
952 stats.store.store_entry_count);
953 storeAppendPrintf(sentry, "\t%6.0f StoreEntries with MemObjects\n",
954 stats.store.mem_object_count);
955 storeAppendPrintf(sentry, "\t%6.0f Hot Object Cache Items\n",
956 stats.store.mem.count);
957 storeAppendPrintf(sentry, "\t%6.0f on-disk objects\n",
958 stats.store.swap.count);
959 }
960
961 void
962 DumpMallocStatistics(StoreEntry* sentry)
963 {
964 #if XMALLOC_STATISTICS
965
966 xm_deltat = current_dtime - xm_time;
967 xm_time = current_dtime;
968 storeAppendPrintf(sentry, "\nMemory allocation statistics\n");
969 storeAppendPrintf(sentry, "%12s %15s %6s %12s\n","Alloc Size","Count","Delta","Alloc/sec");
970 malloc_statistics(info_get_mallstat, sentry);
971 #endif
972 }
973
974 void
975 GetServiceTimesStats(Mgr::ServiceTimesActionData& stats)
976 {
977 for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) {
978 double p = (i + 1) * 5 / 100.0;
979 stats.http_requests5[i] = statPctileSvc(p, 5, PCTILE_HTTP);
980 stats.http_requests60[i] = statPctileSvc(p, 60, PCTILE_HTTP);
981
982 stats.cache_misses5[i] = statPctileSvc(p, 5, PCTILE_MISS);
983 stats.cache_misses60[i] = statPctileSvc(p, 60, PCTILE_MISS);
984
985 stats.cache_hits5[i] = statPctileSvc(p, 5, PCTILE_HIT);
986 stats.cache_hits60[i] = statPctileSvc(p, 60, PCTILE_HIT);
987
988 stats.near_hits5[i] = statPctileSvc(p, 5, PCTILE_NH);
989 stats.near_hits60[i] = statPctileSvc(p, 60, PCTILE_NH);
990
991 stats.not_modified_replies5[i] = statPctileSvc(p, 5, PCTILE_NM);
992 stats.not_modified_replies60[i] = statPctileSvc(p, 60, PCTILE_NM);
993
994 stats.dns_lookups5[i] = statPctileSvc(p, 5, PCTILE_DNS);
995 stats.dns_lookups60[i] = statPctileSvc(p, 60, PCTILE_DNS);
996
997 stats.icp_queries5[i] = statPctileSvc(p, 5, PCTILE_ICP_QUERY);
998 stats.icp_queries60[i] = statPctileSvc(p, 60, PCTILE_ICP_QUERY);
999 }
1000 }
1001
1002 void
1003 DumpServiceTimesStats(Mgr::ServiceTimesActionData& stats, StoreEntry* sentry)
1004 {
1005 storeAppendPrintf(sentry, "Service Time Percentiles 5 min 60 min:\n");
1006 double fct = stats.count > 1 ? stats.count * 1000.0 : 1000.0;
1007 for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) {
1008 storeAppendPrintf(sentry, "\tHTTP Requests (All): %2d%% %8.5f %8.5f\n",
1009 (i + 1) * 5,
1010 stats.http_requests5[i] / fct,
1011 stats.http_requests60[i] / fct);
1012 }
1013 for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) {
1014 storeAppendPrintf(sentry, "\tCache Misses: %2d%% %8.5f %8.5f\n",
1015 (i + 1) * 5,
1016 stats.cache_misses5[i] / fct,
1017 stats.cache_misses60[i] / fct);
1018 }
1019 for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) {
1020 storeAppendPrintf(sentry, "\tCache Hits: %2d%% %8.5f %8.5f\n",
1021 (i + 1) * 5,
1022 stats.cache_hits5[i] / fct,
1023 stats.cache_hits60[i] / fct);
1024 }
1025 for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) {
1026 storeAppendPrintf(sentry, "\tNear Hits: %2d%% %8.5f %8.5f\n",
1027 (i + 1) * 5,
1028 stats.near_hits5[i] / fct,
1029 stats.near_hits60[i] / fct);
1030 }
1031 for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) {
1032 storeAppendPrintf(sentry, "\tNot-Modified Replies: %2d%% %8.5f %8.5f\n",
1033 (i + 1) * 5,
1034 stats.not_modified_replies5[i] / fct,
1035 stats.not_modified_replies60[i] / fct);
1036 }
1037 for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) {
1038 storeAppendPrintf(sentry, "\tDNS Lookups: %2d%% %8.5f %8.5f\n",
1039 (i + 1) * 5,
1040 stats.dns_lookups5[i] / fct,
1041 stats.dns_lookups60[i] / fct);
1042 }
1043 fct = stats.count > 1 ? stats.count * 1000000.0 : 1000000.0;
1044 for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) {
1045 storeAppendPrintf(sentry, "\tICP Queries: %2d%% %8.5f %8.5f\n",
1046 (i + 1) * 5,
1047 stats.icp_queries5[i] / fct,
1048 stats.icp_queries60[i] / fct);
1049 }
1050 }
1051
1052 static void
1053 statAvgDump(StoreEntry * sentry, int minutes, int hours)
1054 {
1055 Mgr::IntervalActionData stats;
1056 GetAvgStat(stats, minutes, hours);
1057 DumpAvgStat(stats, sentry);
1058 }
1059
1060 #define XAVG(X) (dt ? (double) (f->X - l->X) / dt : 0.0)
1061 void
1062 GetAvgStat(Mgr::IntervalActionData& stats, int minutes, int hours)
1063 {
1064 StatCounters *f;
1065 StatCounters *l;
1066 double dt;
1067 double ct;
1068 assert(N_COUNT_HIST > 1);
1069 assert(minutes > 0 || hours > 0);
1070 f = &CountHist[0];
1071 l = f;
1072
1073 if (minutes > 0 && hours == 0) {
1074 /* checking minute readings ... */
1075
1076 if (minutes > N_COUNT_HIST - 1)
1077 minutes = N_COUNT_HIST - 1;
1078
1079 l = &CountHist[minutes];
1080 } else if (minutes == 0 && hours > 0) {
1081 /* checking hour readings ... */
1082
1083 if (hours > N_COUNT_HOUR_HIST - 1)
1084 hours = N_COUNT_HOUR_HIST - 1;
1085
1086 l = &CountHourHist[hours];
1087 } else {
1088 debugs(18, DBG_IMPORTANT, "statAvgDump: Invalid args, minutes=" << minutes << ", hours=" << hours);
1089 return;
1090 }
1091
1092 dt = tvSubDsec(l->timestamp, f->timestamp);
1093 ct = f->cputime - l->cputime;
1094
1095 stats.sample_start_time = l->timestamp;
1096 stats.sample_end_time = f->timestamp;
1097
1098 stats.client_http_requests = XAVG(client_http.requests);
1099 stats.client_http_hits = XAVG(client_http.hits);
1100 stats.client_http_errors = XAVG(client_http.errors);
1101 stats.client_http_kbytes_in = XAVG(client_http.kbytes_in.kb);
1102 stats.client_http_kbytes_out = XAVG(client_http.kbytes_out.kb);
1103
1104 stats.client_http_all_median_svc_time = statHistDeltaMedian(l->client_http.allSvcTime,
1105 f->client_http.allSvcTime) / 1000.0;
1106 stats.client_http_miss_median_svc_time = statHistDeltaMedian(l->client_http.missSvcTime,
1107 f->client_http.missSvcTime) / 1000.0;
1108 stats.client_http_nm_median_svc_time = statHistDeltaMedian(l->client_http.nearMissSvcTime,
1109 f->client_http.nearMissSvcTime) / 1000.0;
1110 stats.client_http_nh_median_svc_time = statHistDeltaMedian(l->client_http.nearHitSvcTime,
1111 f->client_http.nearHitSvcTime) / 1000.0;
1112 stats.client_http_hit_median_svc_time = statHistDeltaMedian(l->client_http.hitSvcTime,
1113 f->client_http.hitSvcTime) / 1000.0;
1114
1115 stats.server_all_requests = XAVG(server.all.requests);
1116 stats.server_all_errors = XAVG(server.all.errors);
1117 stats.server_all_kbytes_in = XAVG(server.all.kbytes_in.kb);
1118 stats.server_all_kbytes_out = XAVG(server.all.kbytes_out.kb);
1119
1120 stats.server_http_requests = XAVG(server.http.requests);
1121 stats.server_http_errors = XAVG(server.http.errors);
1122 stats.server_http_kbytes_in = XAVG(server.http.kbytes_in.kb);
1123 stats.server_http_kbytes_out = XAVG(server.http.kbytes_out.kb);
1124
1125 stats.server_ftp_requests = XAVG(server.ftp.requests);
1126 stats.server_ftp_errors = XAVG(server.ftp.errors);
1127 stats.server_ftp_kbytes_in = XAVG(server.ftp.kbytes_in.kb);
1128 stats.server_ftp_kbytes_out = XAVG(server.ftp.kbytes_out.kb);
1129
1130 stats.server_other_requests = XAVG(server.other.requests);
1131 stats.server_other_errors = XAVG(server.other.errors);
1132 stats.server_other_kbytes_in = XAVG(server.other.kbytes_in.kb);
1133 stats.server_other_kbytes_out = XAVG(server.other.kbytes_out.kb);
1134
1135 stats.icp_pkts_sent = XAVG(icp.pkts_sent);
1136 stats.icp_pkts_recv = XAVG(icp.pkts_recv);
1137 stats.icp_queries_sent = XAVG(icp.queries_sent);
1138 stats.icp_replies_sent = XAVG(icp.replies_sent);
1139 stats.icp_queries_recv = XAVG(icp.queries_recv);
1140 stats.icp_replies_recv = XAVG(icp.replies_recv);
1141 stats.icp_replies_queued = XAVG(icp.replies_queued);
1142 stats.icp_query_timeouts = XAVG(icp.query_timeouts);
1143 stats.icp_kbytes_sent = XAVG(icp.kbytes_sent.kb);
1144 stats.icp_kbytes_recv = XAVG(icp.kbytes_recv.kb);
1145 stats.icp_q_kbytes_sent = XAVG(icp.q_kbytes_sent.kb);
1146 stats.icp_r_kbytes_sent = XAVG(icp.r_kbytes_sent.kb);
1147 stats.icp_q_kbytes_recv = XAVG(icp.q_kbytes_recv.kb);
1148 stats.icp_r_kbytes_recv = XAVG(icp.r_kbytes_recv.kb);
1149
1150 stats.icp_query_median_svc_time = statHistDeltaMedian(l->icp.querySvcTime,
1151 f->icp.querySvcTime) / 1000000.0;
1152 stats.icp_reply_median_svc_time = statHistDeltaMedian(l->icp.replySvcTime,
1153 f->icp.replySvcTime) / 1000000.0;
1154 stats.dns_median_svc_time = statHistDeltaMedian(l->dns.svcTime,
1155 f->dns.svcTime) / 1000.0;
1156
1157 stats.unlink_requests = XAVG(unlink.requests);
1158 stats.page_faults = XAVG(page_faults);
1159 stats.select_loops = XAVG(select_loops);
1160 stats.select_fds = XAVG(select_fds);
1161 stats.average_select_fd_period = f->select_fds > l->select_fds ?
1162 (f->select_time - l->select_time) / (f->select_fds - l->select_fds) : 0.0;
1163
1164 stats.median_select_fds = statHistDeltaMedian(l->select_fds_hist, f->select_fds_hist);
1165 stats.swap_outs = XAVG(swap.outs);
1166 stats.swap_ins = XAVG(swap.ins);
1167 stats.swap_files_cleaned = XAVG(swap.files_cleaned);
1168 stats.aborted_requests = XAVG(aborted_requests);
1169
1170 stats.syscalls_disk_opens = XAVG(syscalls.disk.opens);
1171 stats.syscalls_disk_closes = XAVG(syscalls.disk.closes);
1172 stats.syscalls_disk_reads = XAVG(syscalls.disk.reads);
1173 stats.syscalls_disk_writes = XAVG(syscalls.disk.writes);
1174 stats.syscalls_disk_seeks = XAVG(syscalls.disk.seeks);
1175 stats.syscalls_disk_unlinks = XAVG(syscalls.disk.unlinks);
1176 stats.syscalls_sock_accepts = XAVG(syscalls.sock.accepts);
1177 stats.syscalls_sock_sockets = XAVG(syscalls.sock.sockets);
1178 stats.syscalls_sock_connects = XAVG(syscalls.sock.connects);
1179 stats.syscalls_sock_binds = XAVG(syscalls.sock.binds);
1180 stats.syscalls_sock_closes = XAVG(syscalls.sock.closes);
1181 stats.syscalls_sock_reads = XAVG(syscalls.sock.reads);
1182 stats.syscalls_sock_writes = XAVG(syscalls.sock.writes);
1183 stats.syscalls_sock_recvfroms = XAVG(syscalls.sock.recvfroms);
1184 stats.syscalls_sock_sendtos = XAVG(syscalls.sock.sendtos);
1185 stats.syscalls_selects = XAVG(syscalls.selects);
1186
1187 stats.cpu_time = ct;
1188 stats.wall_time = dt;
1189 }
1190
1191 void
1192 DumpAvgStat(Mgr::IntervalActionData& stats, StoreEntry* sentry)
1193 {
1194 storeAppendPrintf(sentry, "sample_start_time = %d.%d (%s)\n",
1195 (int)stats.sample_start_time.tv_sec,
1196 (int)stats.sample_start_time.tv_usec,
1197 mkrfc1123(stats.sample_start_time.tv_sec));
1198 storeAppendPrintf(sentry, "sample_end_time = %d.%d (%s)\n",
1199 (int)stats.sample_end_time.tv_sec,
1200 (int)stats.sample_end_time.tv_usec,
1201 mkrfc1123(stats.sample_end_time.tv_sec));
1202
1203 storeAppendPrintf(sentry, "client_http.requests = %f/sec\n",
1204 stats.client_http_requests);
1205 storeAppendPrintf(sentry, "client_http.hits = %f/sec\n",
1206 stats.client_http_hits);
1207 storeAppendPrintf(sentry, "client_http.errors = %f/sec\n",
1208 stats.client_http_errors);
1209 storeAppendPrintf(sentry, "client_http.kbytes_in = %f/sec\n",
1210 stats.client_http_kbytes_in);
1211 storeAppendPrintf(sentry, "client_http.kbytes_out = %f/sec\n",
1212 stats.client_http_kbytes_out);
1213
1214 double fct = stats.count > 1 ? stats.count : 1.0;
1215 storeAppendPrintf(sentry, "client_http.all_median_svc_time = %f seconds\n",
1216 stats.client_http_all_median_svc_time / fct);
1217 storeAppendPrintf(sentry, "client_http.miss_median_svc_time = %f seconds\n",
1218 stats.client_http_miss_median_svc_time / fct);
1219 storeAppendPrintf(sentry, "client_http.nm_median_svc_time = %f seconds\n",
1220 stats.client_http_nm_median_svc_time / fct);
1221 storeAppendPrintf(sentry, "client_http.nh_median_svc_time = %f seconds\n",
1222 stats.client_http_nh_median_svc_time / fct);
1223 storeAppendPrintf(sentry, "client_http.hit_median_svc_time = %f seconds\n",
1224 stats.client_http_hit_median_svc_time / fct);
1225
1226 storeAppendPrintf(sentry, "server.all.requests = %f/sec\n",
1227 stats.server_all_requests);
1228 storeAppendPrintf(sentry, "server.all.errors = %f/sec\n",
1229 stats.server_all_errors);
1230 storeAppendPrintf(sentry, "server.all.kbytes_in = %f/sec\n",
1231 stats.server_all_kbytes_in);
1232 storeAppendPrintf(sentry, "server.all.kbytes_out = %f/sec\n",
1233 stats.server_all_kbytes_out);
1234
1235 storeAppendPrintf(sentry, "server.http.requests = %f/sec\n",
1236 stats.server_http_requests);
1237 storeAppendPrintf(sentry, "server.http.errors = %f/sec\n",
1238 stats.server_http_errors);
1239 storeAppendPrintf(sentry, "server.http.kbytes_in = %f/sec\n",
1240 stats.server_http_kbytes_in);
1241 storeAppendPrintf(sentry, "server.http.kbytes_out = %f/sec\n",
1242 stats.server_http_kbytes_out);
1243
1244 storeAppendPrintf(sentry, "server.ftp.requests = %f/sec\n",
1245 stats.server_ftp_requests);
1246 storeAppendPrintf(sentry, "server.ftp.errors = %f/sec\n",
1247 stats.server_ftp_errors);
1248 storeAppendPrintf(sentry, "server.ftp.kbytes_in = %f/sec\n",
1249 stats.server_ftp_kbytes_in);
1250 storeAppendPrintf(sentry, "server.ftp.kbytes_out = %f/sec\n",
1251 stats.server_ftp_kbytes_out);
1252
1253 storeAppendPrintf(sentry, "server.other.requests = %f/sec\n",
1254 stats.server_other_requests);
1255 storeAppendPrintf(sentry, "server.other.errors = %f/sec\n",
1256 stats.server_other_errors);
1257 storeAppendPrintf(sentry, "server.other.kbytes_in = %f/sec\n",
1258 stats.server_other_kbytes_in);
1259 storeAppendPrintf(sentry, "server.other.kbytes_out = %f/sec\n",
1260 stats.server_other_kbytes_out);
1261
1262 storeAppendPrintf(sentry, "icp.pkts_sent = %f/sec\n",
1263 stats.icp_pkts_sent);
1264 storeAppendPrintf(sentry, "icp.pkts_recv = %f/sec\n",
1265 stats.icp_pkts_recv);
1266 storeAppendPrintf(sentry, "icp.queries_sent = %f/sec\n",
1267 stats.icp_queries_sent);
1268 storeAppendPrintf(sentry, "icp.replies_sent = %f/sec\n",
1269 stats.icp_replies_sent);
1270 storeAppendPrintf(sentry, "icp.queries_recv = %f/sec\n",
1271 stats.icp_queries_recv);
1272 storeAppendPrintf(sentry, "icp.replies_recv = %f/sec\n",
1273 stats.icp_replies_recv);
1274 storeAppendPrintf(sentry, "icp.replies_queued = %f/sec\n",
1275 stats.icp_replies_queued);
1276 storeAppendPrintf(sentry, "icp.query_timeouts = %f/sec\n",
1277 stats.icp_query_timeouts);
1278 storeAppendPrintf(sentry, "icp.kbytes_sent = %f/sec\n",
1279 stats.icp_kbytes_sent);
1280 storeAppendPrintf(sentry, "icp.kbytes_recv = %f/sec\n",
1281 stats.icp_kbytes_recv);
1282 storeAppendPrintf(sentry, "icp.q_kbytes_sent = %f/sec\n",
1283 stats.icp_q_kbytes_sent);
1284 storeAppendPrintf(sentry, "icp.r_kbytes_sent = %f/sec\n",
1285 stats.icp_r_kbytes_sent);
1286 storeAppendPrintf(sentry, "icp.q_kbytes_recv = %f/sec\n",
1287 stats.icp_q_kbytes_recv);
1288 storeAppendPrintf(sentry, "icp.r_kbytes_recv = %f/sec\n",
1289 stats.icp_r_kbytes_recv);
1290 storeAppendPrintf(sentry, "icp.query_median_svc_time = %f seconds\n",
1291 stats.icp_query_median_svc_time / fct);
1292 storeAppendPrintf(sentry, "icp.reply_median_svc_time = %f seconds\n",
1293 stats.icp_reply_median_svc_time / fct);
1294 storeAppendPrintf(sentry, "dns.median_svc_time = %f seconds\n",
1295 stats.dns_median_svc_time / fct);
1296 storeAppendPrintf(sentry, "unlink.requests = %f/sec\n",
1297 stats.unlink_requests);
1298 storeAppendPrintf(sentry, "page_faults = %f/sec\n",
1299 stats.page_faults);
1300 storeAppendPrintf(sentry, "select_loops = %f/sec\n",
1301 stats.select_loops);
1302 storeAppendPrintf(sentry, "select_fds = %f/sec\n",
1303 stats.select_fds);
1304 storeAppendPrintf(sentry, "average_select_fd_period = %f/fd\n",
1305 stats.average_select_fd_period / fct);
1306 storeAppendPrintf(sentry, "median_select_fds = %f\n",
1307 stats.median_select_fds / fct);
1308 storeAppendPrintf(sentry, "swap.outs = %f/sec\n",
1309 stats.swap_outs);
1310 storeAppendPrintf(sentry, "swap.ins = %f/sec\n",
1311 stats.swap_ins);
1312 storeAppendPrintf(sentry, "swap.files_cleaned = %f/sec\n",
1313 stats.swap_files_cleaned);
1314 storeAppendPrintf(sentry, "aborted_requests = %f/sec\n",
1315 stats.aborted_requests);
1316
1317 #if USE_POLL
1318 storeAppendPrintf(sentry, "syscalls.polls = %f/sec\n", stats.syscalls_selects);
1319 #elif defined(USE_SELECT) || defined(USE_SELECT_WIN32)
1320 storeAppendPrintf(sentry, "syscalls.selects = %f/sec\n", stats.syscalls_selects);
1321 #endif
1322
1323 storeAppendPrintf(sentry, "syscalls.disk.opens = %f/sec\n", stats.syscalls_disk_opens);
1324 storeAppendPrintf(sentry, "syscalls.disk.closes = %f/sec\n", stats.syscalls_disk_closes);
1325 storeAppendPrintf(sentry, "syscalls.disk.reads = %f/sec\n", stats.syscalls_disk_reads);
1326 storeAppendPrintf(sentry, "syscalls.disk.writes = %f/sec\n", stats.syscalls_disk_writes);
1327 storeAppendPrintf(sentry, "syscalls.disk.seeks = %f/sec\n", stats.syscalls_disk_seeks);
1328 storeAppendPrintf(sentry, "syscalls.disk.unlinks = %f/sec\n", stats.syscalls_disk_unlinks);
1329 storeAppendPrintf(sentry, "syscalls.sock.accepts = %f/sec\n", stats.syscalls_sock_accepts);
1330 storeAppendPrintf(sentry, "syscalls.sock.sockets = %f/sec\n", stats.syscalls_sock_sockets);
1331 storeAppendPrintf(sentry, "syscalls.sock.connects = %f/sec\n", stats.syscalls_sock_connects);
1332 storeAppendPrintf(sentry, "syscalls.sock.binds = %f/sec\n", stats.syscalls_sock_binds);
1333 storeAppendPrintf(sentry, "syscalls.sock.closes = %f/sec\n", stats.syscalls_sock_closes);
1334 storeAppendPrintf(sentry, "syscalls.sock.reads = %f/sec\n", stats.syscalls_sock_reads);
1335 storeAppendPrintf(sentry, "syscalls.sock.writes = %f/sec\n", stats.syscalls_sock_writes);
1336 storeAppendPrintf(sentry, "syscalls.sock.recvfroms = %f/sec\n", stats.syscalls_sock_recvfroms);
1337 storeAppendPrintf(sentry, "syscalls.sock.sendtos = %f/sec\n", stats.syscalls_sock_sendtos);
1338
1339 storeAppendPrintf(sentry, "cpu_time = %f seconds\n", stats.cpu_time);
1340 storeAppendPrintf(sentry, "wall_time = %f seconds\n", stats.wall_time);
1341 storeAppendPrintf(sentry, "cpu_usage = %f%%\n", Math::doublePercent(stats.cpu_time, stats.wall_time));
1342 }
1343
1344 static void
1345 statRegisterWithCacheManager(void)
1346 {
1347 Mgr::RegisterAction("info", "General Runtime Information",
1348 &Mgr::InfoAction::Create, 0, 1);
1349 Mgr::RegisterAction("service_times", "Service Times (Percentiles)",
1350 &Mgr::ServiceTimesAction::Create, 0, 1);
1351 Mgr::RegisterAction("filedescriptors", "Process Filedescriptor Allocation",
1352 fde::DumpStats, 0, 1);
1353 Mgr::RegisterAction("objects", "All Cache Objects", stat_objects_get, 0, 0);
1354 Mgr::RegisterAction("vm_objects", "In-Memory and In-Transit Objects",
1355 stat_vmobjects_get, 0, 0);
1356 Mgr::RegisterAction("io", "Server-side network read() size histograms",
1357 &Mgr::IoAction::Create, 0, 1);
1358 Mgr::RegisterAction("counters", "Traffic and Resource Counters",
1359 &Mgr::CountersAction::Create, 0, 1);
1360 Mgr::RegisterAction("peer_select", "Peer Selection Algorithms",
1361 statPeerSelect, 0, 1);
1362 Mgr::RegisterAction("digest_stats", "Cache Digest and ICP blob",
1363 statDigestBlob, 0, 1);
1364 Mgr::RegisterAction("5min", "5 Minute Average of Counters",
1365 &Mgr::IntervalAction::Create5min, 0, 1);
1366 Mgr::RegisterAction("60min", "60 Minute Average of Counters",
1367 &Mgr::IntervalAction::Create60min, 0, 1);
1368 Mgr::RegisterAction("utilization", "Cache Utilization",
1369 statUtilization, 0, 1);
1370 Mgr::RegisterAction("histograms", "Full Histogram Counts",
1371 statCountersHistograms, 0, 1);
1372 Mgr::RegisterAction("active_requests",
1373 "Client-side Active Requests",
1374 statClientRequests, 0, 1);
1375 #if USE_AUTH
1376 Mgr::RegisterAction("username_cache",
1377 "Active Cached Usernames",
1378 Auth::User::UsernameCacheStats, 0, 1);
1379 #endif
1380 #if DEBUG_OPENFD
1381 Mgr::RegisterAction("openfd_objects", "Objects with Swapout files open",
1382 statOpenfdObj, 0, 0);
1383 #endif
1384 #if STAT_GRAPHS
1385 Mgr::RegisterAction("graph_variables", "Display cache metrics graphically",
1386 statGraphDump, 0, 1);
1387 #endif
1388 }
1389
1390 void
1391 statInit(void)
1392 {
1393 int i;
1394 debugs(18, 5, "statInit: Initializing...");
1395
1396 for (i = 0; i < N_COUNT_HIST; ++i)
1397 statCountersInit(&CountHist[i]);
1398
1399 for (i = 0; i < N_COUNT_HOUR_HIST; ++i)
1400 statCountersInit(&CountHourHist[i]);
1401
1402 statCountersInit(&statCounter);
1403
1404 eventAdd("statAvgTick", statAvgTick, NULL, (double) COUNT_INTERVAL, 1);
1405
1406 ClientActiveRequests.head = NULL;
1407
1408 ClientActiveRequests.tail = NULL;
1409
1410 statRegisterWithCacheManager();
1411 }
1412
1413 static void
1414 statAvgTick(void *notused)
1415 {
1416 StatCounters *t = &CountHist[0];
1417 StatCounters *p = &CountHist[1];
1418 StatCounters *c = &statCounter;
1419
1420 struct rusage rusage;
1421 eventAdd("statAvgTick", statAvgTick, NULL, (double) COUNT_INTERVAL, 1);
1422 squid_getrusage(&rusage);
1423 c->page_faults = rusage_pagefaults(&rusage);
1424 c->cputime = rusage_cputime(&rusage);
1425 c->timestamp = current_time;
1426 /* even if NCountHist is small, we already Init()ed the tail */
1427 statCountersClean(CountHist + N_COUNT_HIST - 1);
1428 memmove(p, t, (N_COUNT_HIST - 1) * sizeof(StatCounters));
1429 statCountersCopy(t, c);
1430 ++NCountHist;
1431
1432 if ((NCountHist % COUNT_INTERVAL) == 0) {
1433 /* we have an hours worth of readings. store previous hour */
1434 StatCounters *t2 = &CountHourHist[0];
1435 StatCounters *p2 = &CountHourHist[1];
1436 StatCounters *c2 = &CountHist[N_COUNT_HIST - 1];
1437 statCountersClean(CountHourHist + N_COUNT_HOUR_HIST - 1);
1438 memmove(p2, t2, (N_COUNT_HOUR_HIST - 1) * sizeof(StatCounters));
1439 statCountersCopy(t2, c2);
1440 ++NCountHourHist;
1441 }
1442
1443 if (Config.warnings.high_rptm > 0) {
1444 int i = (int) statPctileSvc(0.5, 20, PCTILE_HTTP);
1445
1446 if (Config.warnings.high_rptm < i)
1447 debugs(18, DBG_CRITICAL, "WARNING: Median response time is " << i << " milliseconds");
1448 }
1449
1450 if (Config.warnings.high_pf) {
1451 int i = (CountHist[0].page_faults - CountHist[1].page_faults);
1452 double dt = tvSubDsec(CountHist[0].timestamp, CountHist[1].timestamp);
1453
1454 if (i > 0 && dt > 0.0) {
1455 i /= (int) dt;
1456
1457 if (Config.warnings.high_pf < i)
1458 debugs(18, DBG_CRITICAL, "WARNING: Page faults occuring at " << i << "/sec");
1459 }
1460 }
1461
1462 if (Config.warnings.high_memory) {
1463 size_t i = 0;
1464 #if HAVE_MSTATS && HAVE_GNUMALLOC_H
1465
1466 struct mstats ms = mstats();
1467 i = ms.bytes_total;
1468 #elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
1469
1470 struct mallinfo mp = mallinfo();
1471 i = mp.arena;
1472 #elif HAVE_SBRK
1473
1474 i = (size_t) ((char *) sbrk(0) - (char *) sbrk_start);
1475 #endif
1476
1477 if (Config.warnings.high_memory < i)
1478 debugs(18, DBG_CRITICAL, "WARNING: Memory usage at " << ((unsigned long int)(i >> 20)) << " MB");
1479 }
1480 }
1481
1482 static void
1483 statCountersInit(StatCounters * C)
1484 {
1485 assert(C);
1486 memset(C, 0, sizeof(*C));
1487 C->timestamp = current_time;
1488 statCountersInitSpecial(C);
1489 }
1490
1491 /* add special cases here as they arrive */
1492 static void
1493 statCountersInitSpecial(StatCounters * C)
1494 {
1495 /*
1496 * HTTP svc_time hist is kept in milli-seconds; max of 3 hours.
1497 */
1498 C->client_http.allSvcTime.logInit(300, 0.0, 3600000.0 * 3.0);
1499 C->client_http.missSvcTime.logInit(300, 0.0, 3600000.0 * 3.0);
1500 C->client_http.nearMissSvcTime.logInit(300, 0.0, 3600000.0 * 3.0);
1501 C->client_http.nearHitSvcTime.logInit(300, 0.0, 3600000.0 * 3.0);
1502 C->client_http.hitSvcTime.logInit(300, 0.0, 3600000.0 * 3.0);
1503 /*
1504 * ICP svc_time hist is kept in micro-seconds; max of 1 minute.
1505 */
1506 C->icp.querySvcTime.logInit(300, 0.0, 1000000.0 * 60.0);
1507 C->icp.replySvcTime.logInit(300, 0.0, 1000000.0 * 60.0);
1508 /*
1509 * DNS svc_time hist is kept in milli-seconds; max of 10 minutes.
1510 */
1511 C->dns.svcTime.logInit(300, 0.0, 60000.0 * 10.0);
1512 /*
1513 * Cache Digest Stuff
1514 */
1515 C->cd.on_xition_count.enumInit(CacheDigestHashFuncCount);
1516 C->comm_udp_incoming.enumInit(INCOMING_UDP_MAX);
1517 C->comm_dns_incoming.enumInit(INCOMING_DNS_MAX);
1518 C->comm_tcp_incoming.enumInit(INCOMING_TCP_MAX);
1519 C->select_fds_hist.enumInit(256); /* was SQUID_MAXFD, but it is way too much. It is OK to crop this statistics */
1520 }
1521
1522 /* add special cases here as they arrive */
1523 static void
1524 statCountersClean(StatCounters * C)
1525 {
1526 assert(C);
1527 C->client_http.allSvcTime.clear();
1528 C->client_http.missSvcTime.clear();
1529 C->client_http.nearMissSvcTime.clear();
1530 C->client_http.nearHitSvcTime.clear();
1531 C->client_http.hitSvcTime.clear();
1532 C->icp.querySvcTime.clear();
1533 C->icp.replySvcTime.clear();
1534 C->dns.svcTime.clear();
1535 C->cd.on_xition_count.clear();
1536 C->comm_udp_incoming.clear();
1537 C->comm_dns_incoming.clear();
1538 C->comm_tcp_incoming.clear();
1539 C->select_fds_hist.clear();
1540 }
1541
1542 /* add special cases here as they arrive */
1543 static void
1544 statCountersCopy(StatCounters * dest, const StatCounters * orig)
1545 {
1546 assert(dest && orig);
1547 /* this should take care of all the fields, but "special" ones */
1548 memcpy(dest, orig, sizeof(*dest));
1549 /* prepare space where to copy special entries */
1550 statCountersInitSpecial(dest);
1551 /* now handle special cases */
1552 /* note: we assert that histogram capacities do not change */
1553 dest->client_http.allSvcTime=orig->client_http.allSvcTime;
1554 dest->client_http.missSvcTime=orig->client_http.missSvcTime;
1555 dest->client_http.nearMissSvcTime=orig->client_http.nearMissSvcTime;
1556 dest->client_http.nearHitSvcTime=orig->client_http.nearHitSvcTime;
1557
1558 dest->client_http.hitSvcTime=orig->client_http.hitSvcTime;
1559 dest->icp.querySvcTime=orig->icp.querySvcTime;
1560 dest->icp.replySvcTime=orig->icp.replySvcTime;
1561 dest->dns.svcTime=orig->dns.svcTime;
1562 dest->cd.on_xition_count=orig->cd.on_xition_count;
1563 dest->comm_udp_incoming=orig->comm_udp_incoming;
1564 dest->comm_dns_incoming=orig->comm_dns_incoming;
1565 dest->comm_tcp_incoming=orig->comm_tcp_incoming;
1566 dest->select_fds_hist=orig->select_fds_hist;
1567 }
1568
1569 static void
1570 statCountersHistograms(StoreEntry * sentry)
1571 {
1572 storeAppendPrintf(sentry, "client_http.allSvcTime histogram:\n");
1573 statCounter.client_http.allSvcTime.dump(sentry, NULL);
1574 storeAppendPrintf(sentry, "client_http.missSvcTime histogram:\n");
1575 statCounter.client_http.missSvcTime.dump(sentry, NULL);
1576 storeAppendPrintf(sentry, "client_http.nearMissSvcTime histogram:\n");
1577 statCounter.client_http.nearMissSvcTime.dump(sentry, NULL);
1578 storeAppendPrintf(sentry, "client_http.nearHitSvcTime histogram:\n");
1579 statCounter.client_http.nearHitSvcTime.dump(sentry, NULL);
1580 storeAppendPrintf(sentry, "client_http.hitSvcTime histogram:\n");
1581 statCounter.client_http.hitSvcTime.dump(sentry, NULL);
1582 storeAppendPrintf(sentry, "icp.querySvcTime histogram:\n");
1583 statCounter.icp.querySvcTime.dump(sentry, NULL);
1584 storeAppendPrintf(sentry, "icp.replySvcTime histogram:\n");
1585 statCounter.icp.replySvcTime.dump(sentry, NULL);
1586 storeAppendPrintf(sentry, "dns.svc_time histogram:\n");
1587 statCounter.dns.svcTime.dump(sentry, NULL);
1588 storeAppendPrintf(sentry, "select_fds_hist histogram:\n");
1589 statCounter.select_fds_hist.dump(sentry, NULL);
1590 }
1591
1592 static void
1593 statCountersDump(StoreEntry * sentry)
1594 {
1595 Mgr::CountersActionData stats;
1596 GetCountersStats(stats);
1597 DumpCountersStats(stats, sentry);
1598 }
1599
1600 void
1601 GetCountersStats(Mgr::CountersActionData& stats)
1602 {
1603 StatCounters *f = &statCounter;
1604
1605 struct rusage rusage;
1606 squid_getrusage(&rusage);
1607 f->page_faults = rusage_pagefaults(&rusage);
1608 f->cputime = rusage_cputime(&rusage);
1609
1610 stats.sample_time = f->timestamp;
1611 stats.client_http_requests = f->client_http.requests;
1612 stats.client_http_hits = f->client_http.hits;
1613 stats.client_http_errors = f->client_http.errors;
1614 stats.client_http_kbytes_in = f->client_http.kbytes_in.kb;
1615 stats.client_http_kbytes_out = f->client_http.kbytes_out.kb;
1616 stats.client_http_hit_kbytes_out = f->client_http.hit_kbytes_out.kb;
1617
1618 stats.server_all_requests = f->server.all.requests;
1619 stats.server_all_errors = f->server.all.errors;
1620 stats.server_all_kbytes_in = f->server.all.kbytes_in.kb;
1621 stats.server_all_kbytes_out = f->server.all.kbytes_out.kb;
1622
1623 stats.server_http_requests = f->server.http.requests;
1624 stats.server_http_errors = f->server.http.errors;
1625 stats.server_http_kbytes_in = f->server.http.kbytes_in.kb;
1626 stats.server_http_kbytes_out = f->server.http.kbytes_out.kb;
1627
1628 stats.server_ftp_requests = f->server.ftp.requests;
1629 stats.server_ftp_errors = f->server.ftp.errors;
1630 stats.server_ftp_kbytes_in = f->server.ftp.kbytes_in.kb;
1631 stats.server_ftp_kbytes_out = f->server.ftp.kbytes_out.kb;
1632
1633 stats.server_other_requests = f->server.other.requests;
1634 stats.server_other_errors = f->server.other.errors;
1635 stats.server_other_kbytes_in = f->server.other.kbytes_in.kb;
1636 stats.server_other_kbytes_out = f->server.other.kbytes_out.kb;
1637
1638 stats.icp_pkts_sent = f->icp.pkts_sent;
1639 stats.icp_pkts_recv = f->icp.pkts_recv;
1640 stats.icp_queries_sent = f->icp.queries_sent;
1641 stats.icp_replies_sent = f->icp.replies_sent;
1642 stats.icp_queries_recv = f->icp.queries_recv;
1643 stats.icp_replies_recv = f->icp.replies_recv;
1644 stats.icp_query_timeouts = f->icp.query_timeouts;
1645 stats.icp_replies_queued = f->icp.replies_queued;
1646 stats.icp_kbytes_sent = f->icp.kbytes_sent.kb;
1647 stats.icp_kbytes_recv = f->icp.kbytes_recv.kb;
1648 stats.icp_q_kbytes_sent = f->icp.q_kbytes_sent.kb;
1649 stats.icp_r_kbytes_sent = f->icp.r_kbytes_sent.kb;
1650 stats.icp_q_kbytes_recv = f->icp.q_kbytes_recv.kb;
1651 stats.icp_r_kbytes_recv = f->icp.r_kbytes_recv.kb;
1652
1653 #if USE_CACHE_DIGESTS
1654
1655 stats.icp_times_used = f->icp.times_used;
1656 stats.cd_times_used = f->cd.times_used;
1657 stats.cd_msgs_sent = f->cd.msgs_sent;
1658 stats.cd_msgs_recv = f->cd.msgs_recv;
1659 stats.cd_memory = f->cd.memory.kb;
1660 stats.cd_local_memory = store_digest ? store_digest->mask_size / 1024 : 0;
1661 stats.cd_kbytes_sent = f->cd.kbytes_sent.kb;
1662 stats.cd_kbytes_recv = f->cd.kbytes_recv.kb;
1663 #endif
1664
1665 stats.unlink_requests = f->unlink.requests;
1666 stats.page_faults = f->page_faults;
1667 stats.select_loops = f->select_loops;
1668 stats.cpu_time = f->cputime;
1669 stats.wall_time = tvSubDsec(f->timestamp, current_time);
1670 stats.swap_outs = f->swap.outs;
1671 stats.swap_ins = f->swap.ins;
1672 stats.swap_files_cleaned = f->swap.files_cleaned;
1673 stats.aborted_requests = f->aborted_requests;
1674 }
1675
1676 void
1677 DumpCountersStats(Mgr::CountersActionData& stats, StoreEntry* sentry)
1678 {
1679 storeAppendPrintf(sentry, "sample_time = %d.%d (%s)\n",
1680 (int) stats.sample_time.tv_sec,
1681 (int) stats.sample_time.tv_usec,
1682 mkrfc1123(stats.sample_time.tv_sec));
1683 storeAppendPrintf(sentry, "client_http.requests = %.0f\n",
1684 stats.client_http_requests);
1685 storeAppendPrintf(sentry, "client_http.hits = %.0f\n",
1686 stats.client_http_hits);
1687 storeAppendPrintf(sentry, "client_http.errors = %.0f\n",
1688 stats.client_http_errors);
1689 storeAppendPrintf(sentry, "client_http.kbytes_in = %.0f\n",
1690 stats.client_http_kbytes_in);
1691 storeAppendPrintf(sentry, "client_http.kbytes_out = %.0f\n",
1692 stats.client_http_kbytes_out);
1693 storeAppendPrintf(sentry, "client_http.hit_kbytes_out = %.0f\n",
1694 stats.client_http_hit_kbytes_out);
1695
1696 storeAppendPrintf(sentry, "server.all.requests = %.0f\n",
1697 stats.server_all_requests);
1698 storeAppendPrintf(sentry, "server.all.errors = %.0f\n",
1699 stats.server_all_errors);
1700 storeAppendPrintf(sentry, "server.all.kbytes_in = %.0f\n",
1701 stats.server_all_kbytes_in);
1702 storeAppendPrintf(sentry, "server.all.kbytes_out = %.0f\n",
1703 stats.server_all_kbytes_out);
1704
1705 storeAppendPrintf(sentry, "server.http.requests = %.0f\n",
1706 stats.server_http_requests);
1707 storeAppendPrintf(sentry, "server.http.errors = %.0f\n",
1708 stats.server_http_errors);
1709 storeAppendPrintf(sentry, "server.http.kbytes_in = %.0f\n",
1710 stats.server_http_kbytes_in);
1711 storeAppendPrintf(sentry, "server.http.kbytes_out = %.0f\n",
1712 stats.server_http_kbytes_out);
1713
1714 storeAppendPrintf(sentry, "server.ftp.requests = %.0f\n",
1715 stats.server_ftp_requests);
1716 storeAppendPrintf(sentry, "server.ftp.errors = %.0f\n",
1717 stats.server_ftp_errors);
1718 storeAppendPrintf(sentry, "server.ftp.kbytes_in = %.0f\n",
1719 stats.server_ftp_kbytes_in);
1720 storeAppendPrintf(sentry, "server.ftp.kbytes_out = %.0f\n",
1721 stats.server_ftp_kbytes_out);
1722
1723 storeAppendPrintf(sentry, "server.other.requests = %.0f\n",
1724 stats.server_other_requests);
1725 storeAppendPrintf(sentry, "server.other.errors = %.0f\n",
1726 stats.server_other_errors);
1727 storeAppendPrintf(sentry, "server.other.kbytes_in = %.0f\n",
1728 stats.server_other_kbytes_in);
1729 storeAppendPrintf(sentry, "server.other.kbytes_out = %.0f\n",
1730 stats.server_other_kbytes_out);
1731
1732 storeAppendPrintf(sentry, "icp.pkts_sent = %.0f\n",
1733 stats.icp_pkts_sent);
1734 storeAppendPrintf(sentry, "icp.pkts_recv = %.0f\n",
1735 stats.icp_pkts_recv);
1736 storeAppendPrintf(sentry, "icp.queries_sent = %.0f\n",
1737 stats.icp_queries_sent);
1738 storeAppendPrintf(sentry, "icp.replies_sent = %.0f\n",
1739 stats.icp_replies_sent);
1740 storeAppendPrintf(sentry, "icp.queries_recv = %.0f\n",
1741 stats.icp_queries_recv);
1742 storeAppendPrintf(sentry, "icp.replies_recv = %.0f\n",
1743 stats.icp_replies_recv);
1744 storeAppendPrintf(sentry, "icp.query_timeouts = %.0f\n",
1745 stats.icp_query_timeouts);
1746 storeAppendPrintf(sentry, "icp.replies_queued = %.0f\n",
1747 stats.icp_replies_queued);
1748 storeAppendPrintf(sentry, "icp.kbytes_sent = %.0f\n",
1749 stats.icp_kbytes_sent);
1750 storeAppendPrintf(sentry, "icp.kbytes_recv = %.0f\n",
1751 stats.icp_kbytes_recv);
1752 storeAppendPrintf(sentry, "icp.q_kbytes_sent = %.0f\n",
1753 stats.icp_q_kbytes_sent);
1754 storeAppendPrintf(sentry, "icp.r_kbytes_sent = %.0f\n",
1755 stats.icp_r_kbytes_sent);
1756 storeAppendPrintf(sentry, "icp.q_kbytes_recv = %.0f\n",
1757 stats.icp_q_kbytes_recv);
1758 storeAppendPrintf(sentry, "icp.r_kbytes_recv = %.0f\n",
1759 stats.icp_r_kbytes_recv);
1760
1761 #if USE_CACHE_DIGESTS
1762
1763 storeAppendPrintf(sentry, "icp.times_used = %.0f\n",
1764 stats.icp_times_used);
1765 storeAppendPrintf(sentry, "cd.times_used = %.0f\n",
1766 stats.cd_times_used);
1767 storeAppendPrintf(sentry, "cd.msgs_sent = %.0f\n",
1768 stats.cd_msgs_sent);
1769 storeAppendPrintf(sentry, "cd.msgs_recv = %.0f\n",
1770 stats.cd_msgs_recv);
1771 storeAppendPrintf(sentry, "cd.memory = %.0f\n",
1772 stats.cd_memory);
1773 storeAppendPrintf(sentry, "cd.local_memory = %.0f\n",
1774 stats.cd_local_memory);
1775 storeAppendPrintf(sentry, "cd.kbytes_sent = %.0f\n",
1776 stats.cd_kbytes_sent);
1777 storeAppendPrintf(sentry, "cd.kbytes_recv = %.0f\n",
1778 stats.cd_kbytes_recv);
1779 #endif
1780
1781 storeAppendPrintf(sentry, "unlink.requests = %.0f\n",
1782 stats.unlink_requests);
1783 storeAppendPrintf(sentry, "page_faults = %.0f\n",
1784 stats.page_faults);
1785 storeAppendPrintf(sentry, "select_loops = %.0f\n",
1786 stats.select_loops);
1787 storeAppendPrintf(sentry, "cpu_time = %f\n",
1788 stats.cpu_time);
1789 storeAppendPrintf(sentry, "wall_time = %f\n",
1790 stats.wall_time);
1791 storeAppendPrintf(sentry, "swap.outs = %.0f\n",
1792 stats.swap_outs);
1793 storeAppendPrintf(sentry, "swap.ins = %.0f\n",
1794 stats.swap_ins);
1795 storeAppendPrintf(sentry, "swap.files_cleaned = %.0f\n",
1796 stats.swap_files_cleaned);
1797 storeAppendPrintf(sentry, "aborted_requests = %.0f\n",
1798 stats.aborted_requests);
1799 }
1800
1801 void
1802 statFreeMemory(void)
1803 {
1804 int i;
1805
1806 for (i = 0; i < N_COUNT_HIST; ++i)
1807 statCountersClean(&CountHist[i]);
1808
1809 for (i = 0; i < N_COUNT_HOUR_HIST; ++i)
1810 statCountersClean(&CountHourHist[i]);
1811 }
1812
1813 static void
1814 statPeerSelect(StoreEntry * sentry)
1815 {
1816 #if USE_CACHE_DIGESTS
1817 StatCounters *f = &statCounter;
1818 CachePeer *peer;
1819 const int tot_used = f->cd.times_used + f->icp.times_used;
1820
1821 /* totals */
1822 cacheDigestGuessStatsReport(&f->cd.guess, sentry, "all peers");
1823 /* per-peer */
1824 storeAppendPrintf(sentry, "\nPer-peer statistics:\n");
1825
1826 for (peer = getFirstPeer(); peer; peer = getNextPeer(peer)) {
1827 if (peer->digest)
1828 peerDigestStatsReport(peer->digest, sentry);
1829 else
1830 storeAppendPrintf(sentry, "\nNo peer digest from %s\n", peer->host);
1831
1832 storeAppendPrintf(sentry, "\n");
1833 }
1834
1835 storeAppendPrintf(sentry, "\nAlgorithm usage:\n");
1836 storeAppendPrintf(sentry, "Cache Digest: %7d (%3d%%)\n",
1837 f->cd.times_used, xpercentInt(f->cd.times_used, tot_used));
1838 storeAppendPrintf(sentry, "Icp: %7d (%3d%%)\n",
1839 f->icp.times_used, xpercentInt(f->icp.times_used, tot_used));
1840 storeAppendPrintf(sentry, "Total: %7d (%3d%%)\n",
1841 tot_used, xpercentInt(tot_used, tot_used));
1842 #else
1843
1844 storeAppendPrintf(sentry, "peer digests are disabled; no stats is available.\n");
1845 #endif
1846 }
1847
1848 static void
1849 statDigestBlob(StoreEntry * sentry)
1850 {
1851 storeAppendPrintf(sentry, "\nCounters:\n");
1852 statCountersDump(sentry);
1853 storeAppendPrintf(sentry, "\n5 Min Averages:\n");
1854 statAvgDump(sentry, 5, 0);
1855 storeAppendPrintf(sentry, "\nHistograms:\n");
1856 statCountersHistograms(sentry);
1857 storeAppendPrintf(sentry, "\nPeer Digests:\n");
1858 statPeerSelect(sentry);
1859 storeAppendPrintf(sentry, "\nLocal Digest:\n");
1860 storeDigestReport(sentry);
1861 }
1862
1863 static double
1864 statPctileSvc(double pctile, int interval, int which)
1865 {
1866 StatCounters *f;
1867 StatCounters *l;
1868 double x;
1869 assert(interval > 0);
1870
1871 if (interval > N_COUNT_HIST - 1)
1872 interval = N_COUNT_HIST - 1;
1873
1874 f = &CountHist[0];
1875
1876 l = &CountHist[interval];
1877
1878 assert(f);
1879
1880 assert(l);
1881
1882 switch (which) {
1883
1884 case PCTILE_HTTP:
1885 x = statHistDeltaPctile(l->client_http.allSvcTime,f->client_http.allSvcTime, pctile);
1886 break;
1887
1888 case PCTILE_HIT:
1889 x = statHistDeltaPctile(l->client_http.hitSvcTime,f->client_http.hitSvcTime, pctile);
1890 break;
1891
1892 case PCTILE_MISS:
1893 x = statHistDeltaPctile(l->client_http.missSvcTime,f->client_http.missSvcTime, pctile);
1894 break;
1895
1896 case PCTILE_NM:
1897 x = statHistDeltaPctile(l->client_http.nearMissSvcTime,f->client_http.nearMissSvcTime, pctile);
1898 break;
1899
1900 case PCTILE_NH:
1901 x = statHistDeltaPctile(l->client_http.nearHitSvcTime,f->client_http.nearHitSvcTime, pctile);
1902 break;
1903
1904 case PCTILE_ICP_QUERY:
1905 x = statHistDeltaPctile(l->icp.querySvcTime,f->icp.querySvcTime, pctile);
1906 break;
1907
1908 case PCTILE_DNS:
1909 x = statHistDeltaPctile(l->dns.svcTime,f->dns.svcTime, pctile);
1910 break;
1911
1912 default:
1913 debugs(49, 5, "statPctileSvc: unknown type.");
1914 x = 0;
1915 }
1916
1917 return x;
1918 }
1919
1920 StatCounters *
1921 snmpStatGet(int minutes)
1922 {
1923 return &CountHist[minutes];
1924 }
1925
1926 int
1927 stat5minClientRequests(void)
1928 {
1929 assert(N_COUNT_HIST > 5);
1930 return statCounter.client_http.requests - CountHist[5].client_http.requests;
1931 }
1932
1933 static double
1934 statCPUUsage(int minutes)
1935 {
1936 assert(minutes < N_COUNT_HIST);
1937 return Math::doublePercent(CountHist[0].cputime - CountHist[minutes].cputime,
1938 tvSubDsec(CountHist[minutes].timestamp, CountHist[0].timestamp));
1939 }
1940
1941 double
1942 statRequestHitRatio(int minutes)
1943 {
1944 assert(minutes < N_COUNT_HIST);
1945 return Math::doublePercent(CountHist[0].client_http.hits -
1946 CountHist[minutes].client_http.hits,
1947 CountHist[0].client_http.requests -
1948 CountHist[minutes].client_http.requests);
1949 }
1950
1951 double
1952 statRequestHitMemoryRatio(int minutes)
1953 {
1954 assert(minutes < N_COUNT_HIST);
1955 return Math::doublePercent(CountHist[0].client_http.mem_hits -
1956 CountHist[minutes].client_http.mem_hits,
1957 CountHist[0].client_http.hits -
1958 CountHist[minutes].client_http.hits);
1959 }
1960
1961 double
1962 statRequestHitDiskRatio(int minutes)
1963 {
1964 assert(minutes < N_COUNT_HIST);
1965 return Math::doublePercent(CountHist[0].client_http.disk_hits -
1966 CountHist[minutes].client_http.disk_hits,
1967 CountHist[0].client_http.hits -
1968 CountHist[minutes].client_http.hits);
1969 }
1970
1971 double
1972 statByteHitRatio(int minutes)
1973 {
1974 size_t s;
1975 size_t c;
1976 #if USE_CACHE_DIGESTS
1977
1978 size_t cd;
1979 #endif
1980 /* size_t might be unsigned */
1981 assert(minutes < N_COUNT_HIST);
1982 c = CountHist[0].client_http.kbytes_out.kb - CountHist[minutes].client_http.kbytes_out.kb;
1983 s = CountHist[0].server.all.kbytes_in.kb - CountHist[minutes].server.all.kbytes_in.kb;
1984 #if USE_CACHE_DIGESTS
1985 /*
1986 * This ugly hack is here to prevent the user from seeing a
1987 * negative byte hit ratio. When we fetch a cache digest from
1988 * a neighbor, it gets treated like a cache miss because the
1989 * object is consumed internally. Thus, we subtract cache
1990 * digest bytes out before calculating the byte hit ratio.
1991 */
1992 cd = CountHist[0].cd.kbytes_recv.kb - CountHist[minutes].cd.kbytes_recv.kb;
1993
1994 if (s < cd)
1995 debugs(18, DBG_IMPORTANT, "STRANGE: srv_kbytes=" << s << ", cd_kbytes=" << cd);
1996
1997 s -= cd;
1998
1999 #endif
2000
2001 if (c > s)
2002 return Math::doublePercent(c - s, c);
2003 else
2004 return (-1.0 * Math::doublePercent(s - c, c));
2005 }
2006
2007 static void
2008 statClientRequests(StoreEntry * s)
2009 {
2010 dlink_node *i;
2011 ClientHttpRequest *http;
2012 StoreEntry *e;
2013 char buf[MAX_IPSTRLEN];
2014
2015 for (i = ClientActiveRequests.head; i; i = i->next) {
2016 const char *p = NULL;
2017 http = static_cast<ClientHttpRequest *>(i->data);
2018 assert(http);
2019 ConnStateData * conn = http->getConn();
2020 storeAppendPrintf(s, "Connection: %p\n", conn);
2021
2022 if (conn != NULL) {
2023 const int fd = conn->clientConnection->fd;
2024 storeAppendPrintf(s, "\tFD %d, read %" PRId64 ", wrote %" PRId64 "\n", fd,
2025 fd_table[fd].bytes_read, fd_table[fd].bytes_written);
2026 storeAppendPrintf(s, "\tFD desc: %s\n", fd_table[fd].desc);
2027 storeAppendPrintf(s, "\tin: buf %p, offset %ld, size %ld\n",
2028 conn->in.buf, (long int) conn->in.notYetUsed, (long int) conn->in.allocatedSize);
2029 storeAppendPrintf(s, "\tremote: %s\n",
2030 conn->clientConnection->remote.toUrl(buf,MAX_IPSTRLEN));
2031 storeAppendPrintf(s, "\tlocal: %s\n",
2032 conn->clientConnection->local.toUrl(buf,MAX_IPSTRLEN));
2033 storeAppendPrintf(s, "\tnrequests: %d\n",
2034 conn->nrequests);
2035 }
2036
2037 storeAppendPrintf(s, "uri %s\n", http->uri);
2038 storeAppendPrintf(s, "logType %s\n", LogTags_str[http->logType]);
2039 storeAppendPrintf(s, "out.offset %ld, out.size %lu\n",
2040 (long int) http->out.offset, (unsigned long int) http->out.size);
2041 storeAppendPrintf(s, "req_sz %ld\n", (long int) http->req_sz);
2042 e = http->storeEntry();
2043 storeAppendPrintf(s, "entry %p/%s\n", e, e ? e->getMD5Text() : "N/A");
2044 storeAppendPrintf(s, "start %ld.%06d (%f seconds ago)\n",
2045 (long int) http->start_time.tv_sec,
2046 (int) http->start_time.tv_usec,
2047 tvSubDsec(http->start_time, current_time));
2048 #if USE_AUTH
2049 if (http->request->auth_user_request != NULL)
2050 p = http->request->auth_user_request->username();
2051 else
2052 #endif
2053 if (http->request->extacl_user.defined()) {
2054 p = http->request->extacl_user.termedBuf();
2055 }
2056
2057 if (!p && conn != NULL && conn->clientConnection->rfc931[0])
2058 p = conn->clientConnection->rfc931;
2059
2060 #if USE_SSL
2061
2062 if (!p && conn != NULL && Comm::IsConnOpen(conn->clientConnection))
2063 p = sslGetUserEmail(fd_table[conn->clientConnection->fd].ssl);
2064
2065 #endif
2066
2067 if (!p)
2068 p = dash_str;
2069
2070 storeAppendPrintf(s, "username %s\n", p);
2071
2072 #if USE_DELAY_POOLS
2073 storeAppendPrintf(s, "delay_pool %d\n", DelayId::DelayClient(http).pool());
2074 #endif
2075
2076 storeAppendPrintf(s, "\n");
2077 }
2078 }
2079
2080 #if STAT_GRAPHS
2081 /*
2082 * urgh, i don't like these, but they do cut the amount of code down immensely
2083 */
2084
2085 #define GRAPH_PER_MIN(Y) \
2086 for (i=0;i<(N_COUNT_HIST-2);++i) { \
2087 dt = tvSubDsec(CountHist[i+1].timestamp, CountHist[i].timestamp); \
2088 if (dt <= 0.0) \
2089 break; \
2090 storeAppendPrintf(e, "%lu,%0.2f:", \
2091 CountHist[i].timestamp.tv_sec, \
2092 ((CountHist[i].Y - CountHist[i+1].Y) / dt)); \
2093 }
2094
2095 #define GRAPH_PER_HOUR(Y) \
2096 for (i=0;i<(N_COUNT_HOUR_HIST-2);++i) { \
2097 dt = tvSubDsec(CountHourHist[i+1].timestamp, CountHourHist[i].timestamp); \
2098 if (dt <= 0.0) \
2099 break; \
2100 storeAppendPrintf(e, "%lu,%0.2f:", \
2101 CountHourHist[i].timestamp.tv_sec, \
2102 ((CountHourHist[i].Y - CountHourHist[i+1].Y) / dt)); \
2103 }
2104
2105 #define GRAPH_TITLE(X,Y) storeAppendPrintf(e,"%s\t%s\t",X,Y);
2106 #define GRAPH_END storeAppendPrintf(e,"\n");
2107
2108 #define GENGRAPH(X,Y,Z) \
2109 GRAPH_TITLE(Y,Z) \
2110 GRAPH_PER_MIN(X) \
2111 GRAPH_PER_HOUR(X) \
2112 GRAPH_END
2113
2114 static void
2115 statGraphDump(StoreEntry * e)
2116 {
2117 int i;
2118 double dt;
2119
2120 GENGRAPH(client_http.requests, "client_http.requests", "Client HTTP requests/sec");
2121 GENGRAPH(client_http.hits, "client_http.hits", "Client HTTP hits/sec");
2122 GENGRAPH(client_http.errors, "client_http.errors", "Client HTTP errors/sec");
2123 GENGRAPH(client_http.kbytes_in.kb, "client_http.kbytes_in", "Client HTTP kbytes_in/sec");
2124 GENGRAPH(client_http.kbytes_out.kb, "client_http.kbytes_out", "Client HTTP kbytes_out/sec");
2125
2126 /* XXX todo: http median service times */
2127
2128 GENGRAPH(server.all.requests, "server.all.requests", "Server requests/sec");
2129 GENGRAPH(server.all.errors, "server.all.errors", "Server errors/sec");
2130 GENGRAPH(server.all.kbytes_in.kb, "server.all.kbytes_in", "Server total kbytes_in/sec");
2131 GENGRAPH(server.all.kbytes_out.kb, "server.all.kbytes_out", "Server total kbytes_out/sec");
2132
2133 GENGRAPH(server.http.requests, "server.http.requests", "Server HTTP requests/sec");
2134 GENGRAPH(server.http.errors, "server.http.errors", "Server HTTP errors/sec");
2135 GENGRAPH(server.http.kbytes_in.kb, "server.http.kbytes_in", "Server HTTP kbytes_in/sec");
2136 GENGRAPH(server.http.kbytes_out.kb, "server.http.kbytes_out", "Server HTTP kbytes_out/sec");
2137
2138 GENGRAPH(server.ftp.requests, "server.ftp.requests", "Server FTP requests/sec");
2139 GENGRAPH(server.ftp.errors, "server.ftp.errors", "Server FTP errors/sec");
2140 GENGRAPH(server.ftp.kbytes_in.kb, "server.ftp.kbytes_in", "Server FTP kbytes_in/sec");
2141 GENGRAPH(server.ftp.kbytes_out.kb, "server.ftp.kbytes_out", "Server FTP kbytes_out/sec");
2142
2143 GENGRAPH(server.other.requests, "server.other.requests", "Server other requests/sec");
2144 GENGRAPH(server.other.errors, "server.other.errors", "Server other errors/sec");
2145 GENGRAPH(server.other.kbytes_in.kb, "server.other.kbytes_in", "Server other kbytes_in/sec");
2146 GENGRAPH(server.other.kbytes_out.kb, "server.other.kbytes_out", "Server other kbytes_out/sec");
2147
2148 GENGRAPH(icp.pkts_sent, "icp.pkts_sent", "ICP packets sent/sec");
2149 GENGRAPH(icp.pkts_recv, "icp.pkts_recv", "ICP packets received/sec");
2150 GENGRAPH(icp.kbytes_sent.kb, "icp.kbytes_sent", "ICP kbytes_sent/sec");
2151 GENGRAPH(icp.kbytes_recv.kb, "icp.kbytes_recv", "ICP kbytes_received/sec");
2152
2153 /* XXX todo: icp median service times */
2154 /* XXX todo: dns median service times */
2155
2156 GENGRAPH(unlink.requests, "unlink.requests", "Cache File unlink requests/sec");
2157 GENGRAPH(page_faults, "page_faults", "System Page Faults/sec");
2158 GENGRAPH(select_loops, "select_loops", "System Select Loop calls/sec");
2159 GENGRAPH(cputime, "cputime", "CPU utilisation");
2160 }
2161
2162 #endif /* STAT_GRAPHS */
2163
2164 int
2165 statMemoryAccounted(void)
2166 {
2167 return memPoolsTotalAllocated();
2168 }