4 * DEBUG: section 18 Cache Manager Statistics
5 * AUTHOR: Harvest Derived
7 * SQUID Web Proxy Cache http://www.squid-cache.org/
8 * ----------------------------------------------------------
10 * Squid is the result of efforts by numerous individuals from
11 * the Internet community; see the CONTRIBUTORS file for full
12 * details. Many organizations have provided support for Squid's
13 * development; see the SPONSORS file for full details. Squid is
14 * Copyrighted (C) 2001 by the Regents of the University of
15 * California; see the COPYRIGHT file for full details. Squid
16 * incorporates software developed and/or copyrighted by other
17 * sources; see the CREDITS file for full details.
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
37 #include "StoreClient.h"
38 #include "auth/UserRequest.h"
39 #include "CacheManager.h"
41 #include "HttpRequest.h"
42 #include "MemObject.h"
48 #include "client_side_request.h"
49 #include "client_side.h"
51 #include "SquidTime.h"
53 /* these are included because they expose stats calls */
54 /* TODO: provide a self registration mechanism for those classes
55 * to use during static construction
58 #include "StoreSearch.h"
60 #define DEBUG_OPENFD 1
62 typedef int STOBJFLT(const StoreEntry
*);
64 class StatObjectsState
70 StoreSearchPointer theSearch
;
73 CBDATA_CLASS2(StatObjectsState
);
78 static const char *describeStatuses(const StoreEntry
*);
79 static const char *describeTimestamps(const StoreEntry
*);
80 static void statAvgTick(void *notused
);
81 static void statAvgDump(StoreEntry
*, int minutes
, int hours
);
83 static void statGraphDump(StoreEntry
*);
85 static void statCountersInit(StatCounters
*);
86 static void statCountersInitSpecial(StatCounters
*);
87 static void statCountersClean(StatCounters
*);
88 static void statCountersCopy(StatCounters
* dest
, const StatCounters
* orig
);
89 static double statPctileSvc(double, int, int);
90 static void statStoreEntry(MemBuf
* mb
, StoreEntry
* e
);
91 static double statCPUUsage(int minutes
);
92 static OBJH stat_io_get
;
93 static OBJH stat_objects_get
;
94 static OBJH stat_vmobjects_get
;
96 static OBJH statOpenfdObj
;
98 static EVH statObjects
;
100 static OBJH statCountersDump
;
101 static OBJH statPeerSelect
;
102 static OBJH statDigestBlob
;
103 static OBJH statAvg5min
;
104 static OBJH statAvg60min
;
105 static OBJH statUtilization
;
106 static OBJH statCountersHistograms
;
107 static OBJH statClientRequests
;
109 #ifdef XMALLOC_STATISTICS
110 static void info_get_mallstat(int, int, int, void *);
111 static double xm_time
;
112 static double xm_deltat
;
115 StatCounters CountHist
[N_COUNT_HIST
];
116 static int NCountHist
= 0;
117 static StatCounters CountHourHist
[N_COUNT_HOUR_HIST
];
118 static int NCountHourHist
= 0;
119 CBDATA_CLASS_INIT(StatObjectsState
);
121 extern unsigned int mem_pool_alloc_calls
;
122 extern unsigned int mem_pool_free_calls
;
125 statUtilization(StoreEntry
* e
)
127 storeAppendPrintf(e
, "Cache Utilisation:\n");
128 storeAppendPrintf(e
, "\n");
129 storeAppendPrintf(e
, "Last 5 minutes:\n");
132 statAvgDump(e
, 5, 0);
134 storeAppendPrintf(e
, "(no values recorded yet)\n");
136 storeAppendPrintf(e
, "\n");
138 storeAppendPrintf(e
, "Last 15 minutes:\n");
140 if (NCountHist
>= 15)
141 statAvgDump(e
, 15, 0);
143 storeAppendPrintf(e
, "(no values recorded yet)\n");
145 storeAppendPrintf(e
, "\n");
147 storeAppendPrintf(e
, "Last hour:\n");
149 if (NCountHist
>= 60)
150 statAvgDump(e
, 60, 0);
152 storeAppendPrintf(e
, "(no values recorded yet)\n");
154 storeAppendPrintf(e
, "\n");
156 storeAppendPrintf(e
, "Last 8 hours:\n");
158 if (NCountHourHist
>= 8)
159 statAvgDump(e
, 0, 8);
161 storeAppendPrintf(e
, "(no values recorded yet)\n");
163 storeAppendPrintf(e
, "\n");
165 storeAppendPrintf(e
, "Last day:\n");
167 if (NCountHourHist
>= 24)
168 statAvgDump(e
, 0, 24);
170 storeAppendPrintf(e
, "(no values recorded yet)\n");
172 storeAppendPrintf(e
, "\n");
174 storeAppendPrintf(e
, "Last 3 days:\n");
176 if (NCountHourHist
>= 72)
177 statAvgDump(e
, 0, 72);
179 storeAppendPrintf(e
, "(no values recorded yet)\n");
181 storeAppendPrintf(e
, "\n");
183 storeAppendPrintf(e
, "Totals since cache startup:\n");
189 stat_io_get(StoreEntry
* sentry
)
193 storeAppendPrintf(sentry
, "HTTP I/O\n");
194 storeAppendPrintf(sentry
, "number of reads: %d\n", IOStats
.Http
.reads
);
195 storeAppendPrintf(sentry
, "Read Histogram:\n");
197 for (i
= 0; i
< 16; i
++) {
198 storeAppendPrintf(sentry
, "%5d-%5d: %9d %2d%%\n",
199 i
? (1 << (i
- 1)) + 1 : 1,
201 IOStats
.Http
.read_hist
[i
],
202 percent(IOStats
.Http
.read_hist
[i
], IOStats
.Http
.reads
));
205 storeAppendPrintf(sentry
, "\n");
206 storeAppendPrintf(sentry
, "FTP I/O\n");
207 storeAppendPrintf(sentry
, "number of reads: %d\n", IOStats
.Ftp
.reads
);
208 storeAppendPrintf(sentry
, "Read Histogram:\n");
210 for (i
= 0; i
< 16; i
++) {
211 storeAppendPrintf(sentry
, "%5d-%5d: %9d %2d%%\n",
212 i
? (1 << (i
- 1)) + 1 : 1,
214 IOStats
.Ftp
.read_hist
[i
],
215 percent(IOStats
.Ftp
.read_hist
[i
], IOStats
.Ftp
.reads
));
218 storeAppendPrintf(sentry
, "\n");
219 storeAppendPrintf(sentry
, "Gopher I/O\n");
220 storeAppendPrintf(sentry
, "number of reads: %d\n", IOStats
.Gopher
.reads
);
221 storeAppendPrintf(sentry
, "Read Histogram:\n");
223 for (i
= 0; i
< 16; i
++) {
224 storeAppendPrintf(sentry
, "%5d-%5d: %9d %2d%%\n",
225 i
? (1 << (i
- 1)) + 1 : 1,
227 IOStats
.Gopher
.read_hist
[i
],
228 percent(IOStats
.Gopher
.read_hist
[i
], IOStats
.Gopher
.reads
));
231 storeAppendPrintf(sentry
, "\n");
235 describeStatuses(const StoreEntry
* entry
)
237 LOCAL_ARRAY(char, buf
, 256);
238 snprintf(buf
, 256, "%-13s %-13s %-12s %-12s",
239 storeStatusStr
[entry
->store_status
],
240 memStatusStr
[entry
->mem_status
],
241 swapStatusStr
[entry
->swap_status
],
242 pingStatusStr
[entry
->ping_status
]);
247 storeEntryFlags(const StoreEntry
* entry
)
249 LOCAL_ARRAY(char, buf
, 256);
250 int flags
= (int) entry
->flags
;
254 if (EBIT_TEST(flags
, ENTRY_SPECIAL
))
255 strcat(buf
, "SPECIAL,");
257 if (EBIT_TEST(flags
, ENTRY_REVALIDATE
))
258 strcat(buf
, "REVALIDATE,");
260 if (EBIT_TEST(flags
, DELAY_SENDING
))
261 strcat(buf
, "DELAY_SENDING,");
263 if (EBIT_TEST(flags
, RELEASE_REQUEST
))
264 strcat(buf
, "RELEASE_REQUEST,");
266 if (EBIT_TEST(flags
, REFRESH_REQUEST
))
267 strcat(buf
, "REFRESH_REQUEST,");
269 if (EBIT_TEST(flags
, ENTRY_CACHABLE
))
270 strcat(buf
, "CACHABLE,");
272 if (EBIT_TEST(flags
, ENTRY_DISPATCHED
))
273 strcat(buf
, "DISPATCHED,");
275 if (EBIT_TEST(flags
, KEY_PRIVATE
))
276 strcat(buf
, "PRIVATE,");
278 if (EBIT_TEST(flags
, ENTRY_FWD_HDR_WAIT
))
279 strcat(buf
, "FWD_HDR_WAIT,");
281 if (EBIT_TEST(flags
, ENTRY_NEGCACHED
))
282 strcat(buf
, "NEGCACHED,");
284 if (EBIT_TEST(flags
, ENTRY_VALIDATED
))
285 strcat(buf
, "VALIDATED,");
287 if (EBIT_TEST(flags
, ENTRY_BAD_LENGTH
))
288 strcat(buf
, "BAD_LENGTH,");
290 if (EBIT_TEST(flags
, ENTRY_ABORTED
))
291 strcat(buf
, "ABORTED,");
293 if ((t
= strrchr(buf
, ',')))
300 describeTimestamps(const StoreEntry
* entry
)
302 LOCAL_ARRAY(char, buf
, 256);
303 snprintf(buf
, 256, "LV:%-9d LU:%-9d LM:%-9d EX:%-9d",
304 (int) entry
->timestamp
,
305 (int) entry
->lastref
,
306 (int) entry
->lastmod
,
307 (int) entry
->expires
);
312 statStoreEntry(MemBuf
* mb
, StoreEntry
* e
)
314 MemObject
*mem
= e
->mem_obj
;
315 mb
->Printf("KEY %s\n", e
->getMD5Text());
316 mb
->Printf("\t%s\n", describeStatuses(e
));
317 mb
->Printf("\t%s\n", storeEntryFlags(e
));
318 mb
->Printf("\t%s\n", describeTimestamps(e
));
319 mb
->Printf("\t%d locks, %d clients, %d refs\n",
321 storePendingNClients(e
),
323 mb
->Printf("\tSwap Dir %d, File %#08X\n",
324 e
->swap_dirn
, e
->swap_filen
);
332 /* process objects list */
334 statObjects(void *data
)
336 StatObjectsState
*state
= static_cast<StatObjectsState
*>(data
);
339 if (state
->theSearch
->isDone()) {
340 state
->sentry
->complete();
341 state
->sentry
->unlock();
344 } else if (EBIT_TEST(state
->sentry
->flags
, ENTRY_ABORTED
)) {
345 state
->sentry
->unlock();
348 } else if (state
->sentry
->checkDeferRead(-1)) {
349 eventAdd("statObjects", statObjects
, state
, 0.1, 1);
353 state
->sentry
->buffer();
354 size_t statCount
= 0;
358 while (statCount
++ < static_cast<size_t>(Config
.Store
.objectsPerBucket
) && state
->
360 e
= state
->theSearch
->currentItem();
362 if (state
->filter
&& 0 == state
->filter(e
))
365 statStoreEntry(&mb
, e
);
369 state
->sentry
->append(mb
.buf
, mb
.size
);
372 eventAdd("statObjects", statObjects
, state
, 0.0, 1);
376 statObjectsStart(StoreEntry
* sentry
, STOBJFLT
* filter
)
378 StatObjectsState
*state
= new StatObjectsState
;
379 state
->sentry
= sentry
;
380 state
->filter
= filter
;
383 state
->theSearch
= Store::Root().search(NULL
, NULL
);
385 eventAdd("statObjects", statObjects
, state
, 0.0, 1);
389 stat_objects_get(StoreEntry
* sentry
)
391 statObjectsStart(sentry
, NULL
);
395 statObjectsVmFilter(const StoreEntry
* e
)
397 return e
->mem_obj
? 1 : 0;
401 stat_vmobjects_get(StoreEntry
* sentry
)
403 statObjectsStart(sentry
, statObjectsVmFilter
);
408 statObjectsOpenfdFilter(const StoreEntry
* e
)
410 if (e
->mem_obj
== NULL
)
413 if (e
->mem_obj
->swapout
.sio
== NULL
)
420 statOpenfdObj(StoreEntry
* sentry
)
422 statObjectsStart(sentry
, statObjectsOpenfdFilter
);
427 #ifdef XMALLOC_STATISTICS
429 info_get_mallstat(int size
, int number
, int oldnum
, void *data
)
431 StoreEntry
*sentry
= (StoreEntry
*)data
;
433 // format: "%12s %15s %6s %12s\n","Alloc Size","Count","Delta","Alloc/sec"
435 storeAppendPrintf(sentry
, "%12d %15d %6d %.1f\n", size
, number
, number
- oldnum
, xdiv((number
- oldnum
), xm_deltat
));
441 info_get(StoreEntry
* sentry
)
444 struct rusage rusage
;
447 #if HAVE_MSTATS && HAVE_GNUMALLOC_H
450 #elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
456 runtime
= tvSubDsec(squid_start
, current_time
);
461 storeAppendPrintf(sentry
, "Squid Object Cache: Version %s\n",
466 if (WIN32_run_mode
== _WIN_SQUID_RUN_MODE_SERVICE
) {
467 storeAppendPrintf(sentry
,"\nRunning as %s Windows System Service on %s\n",
468 WIN32_Service_name
, WIN32_OS_string
);
469 storeAppendPrintf(sentry
,"Service command line is: %s\n", WIN32_Service_Command_Line
);
471 storeAppendPrintf(sentry
,"Running on %s\n",WIN32_OS_string
);
475 storeAppendPrintf(sentry
, "Start Time:\t%s\n",
476 mkrfc1123(squid_start
.tv_sec
));
478 storeAppendPrintf(sentry
, "Current Time:\t%s\n",
479 mkrfc1123(current_time
.tv_sec
));
481 storeAppendPrintf(sentry
, "Connection information for %s:\n",APP_SHORTNAME
);
483 storeAppendPrintf(sentry
, "\tNumber of clients accessing cache:\t%u\n",
484 statCounter
.client_http
.clients
);
486 storeAppendPrintf(sentry
, "\tNumber of HTTP requests received:\t%u\n",
487 statCounter
.client_http
.requests
);
489 storeAppendPrintf(sentry
, "\tNumber of ICP messages received:\t%u\n",
490 statCounter
.icp
.pkts_recv
);
492 storeAppendPrintf(sentry
, "\tNumber of ICP messages sent:\t%u\n",
493 statCounter
.icp
.pkts_sent
);
495 storeAppendPrintf(sentry
, "\tNumber of queued ICP replies:\t%u\n",
496 statCounter
.icp
.replies_queued
);
500 storeAppendPrintf(sentry
, "\tNumber of HTCP messages received:\t%u\n",
501 statCounter
.htcp
.pkts_recv
);
503 storeAppendPrintf(sentry
, "\tNumber of HTCP messages sent:\t%u\n",
504 statCounter
.htcp
.pkts_sent
);
508 storeAppendPrintf(sentry
, "\tRequest failure ratio:\t%5.2f\n",
509 request_failure_ratio
);
511 storeAppendPrintf(sentry
, "\tAverage HTTP requests per minute since start:\t%.1f\n",
512 statCounter
.client_http
.requests
/ (runtime
/ 60.0));
514 storeAppendPrintf(sentry
, "\tAverage ICP messages per minute since start:\t%.1f\n",
515 (statCounter
.icp
.pkts_sent
+ statCounter
.icp
.pkts_recv
) / (runtime
/ 60.0));
517 storeAppendPrintf(sentry
, "\tSelect loop called: %ld times, %0.3f ms avg\n",
518 statCounter
.select_loops
, 1000.0 * runtime
/ statCounter
.select_loops
);
520 storeAppendPrintf(sentry
, "Cache information for %s:\n",APP_SHORTNAME
);
522 storeAppendPrintf(sentry
, "\tHits as %% of all requests:\t5min: %3.1f%%, 60min: %3.1f%%\n",
523 statRequestHitRatio(5),
524 statRequestHitRatio(60));
526 storeAppendPrintf(sentry
, "\tHits as %% of bytes sent:\t5min: %3.1f%%, 60min: %3.1f%%\n",
528 statByteHitRatio(60));
530 storeAppendPrintf(sentry
, "\tMemory hits as %% of hit requests:\t5min: %3.1f%%, 60min: %3.1f%%\n",
531 statRequestHitMemoryRatio(5),
532 statRequestHitMemoryRatio(60));
534 storeAppendPrintf(sentry
, "\tDisk hits as %% of hit requests:\t5min: %3.1f%%, 60min: %3.1f%%\n",
535 statRequestHitDiskRatio(5),
536 statRequestHitDiskRatio(60));
538 storeAppendPrintf(sentry
, "\tStorage Swap size:\t%lu KB\n",
541 storeAppendPrintf(sentry
, "\tStorage Swap capacity:\t%4.1f%% used, %4.1f%% free\n",
542 dpercent(store_swap_size
, Store::Root().maxSize()),
543 dpercent((Store::Root().maxSize() - store_swap_size
), Store::Root().maxSize()));
546 storeAppendPrintf(sentry
, "\tStorage Mem size:\t%lu KB\n",
547 (unsigned long)mem_node::StoreMemSize() >> 10);
549 storeAppendPrintf(sentry
, "\tStorage Mem capacity:\t%4.1f%% used, %4.1f%% free\n",
550 dpercent(mem_node::InUseCount(), store_pages_max
),
551 dpercent((store_pages_max
- mem_node::InUseCount()), store_pages_max
));
553 storeAppendPrintf(sentry
, "\tMean Object Size:\t%0.2f KB\n",
554 n_disk_objects
? (double) store_swap_size
/ n_disk_objects
: 0.0);
556 storeAppendPrintf(sentry
, "\tRequests given to unlinkd:\t%d\n",
557 statCounter
.unlink
.requests
);
559 storeAppendPrintf(sentry
, "Median Service Times (seconds) 5 min 60 min:\n");
561 storeAppendPrintf(sentry
, "\tHTTP Requests (All): %8.5f %8.5f\n",
562 statPctileSvc(0.5, 5, PCTILE_HTTP
) / 1000.0,
563 statPctileSvc(0.5, 60, PCTILE_HTTP
) / 1000.0);
565 storeAppendPrintf(sentry
, "\tCache Misses: %8.5f %8.5f\n",
566 statPctileSvc(0.5, 5, PCTILE_MISS
) / 1000.0,
567 statPctileSvc(0.5, 60, PCTILE_MISS
) / 1000.0);
569 storeAppendPrintf(sentry
, "\tCache Hits: %8.5f %8.5f\n",
570 statPctileSvc(0.5, 5, PCTILE_HIT
) / 1000.0,
571 statPctileSvc(0.5, 60, PCTILE_HIT
) / 1000.0);
573 storeAppendPrintf(sentry
, "\tNear Hits: %8.5f %8.5f\n",
574 statPctileSvc(0.5, 5, PCTILE_NH
) / 1000.0,
575 statPctileSvc(0.5, 60, PCTILE_NH
) / 1000.0);
577 storeAppendPrintf(sentry
, "\tNot-Modified Replies: %8.5f %8.5f\n",
578 statPctileSvc(0.5, 5, PCTILE_NM
) / 1000.0,
579 statPctileSvc(0.5, 60, PCTILE_NM
) / 1000.0);
581 storeAppendPrintf(sentry
, "\tDNS Lookups: %8.5f %8.5f\n",
582 statPctileSvc(0.5, 5, PCTILE_DNS
) / 1000.0,
583 statPctileSvc(0.5, 60, PCTILE_DNS
) / 1000.0);
585 storeAppendPrintf(sentry
, "\tICP Queries: %8.5f %8.5f\n",
586 statPctileSvc(0.5, 5, PCTILE_ICP_QUERY
) / 1000000.0,
587 statPctileSvc(0.5, 60, PCTILE_ICP_QUERY
) / 1000000.0);
589 squid_getrusage(&rusage
);
591 cputime
= rusage_cputime(&rusage
);
593 storeAppendPrintf(sentry
, "Resource usage for %s:\n", APP_SHORTNAME
);
595 storeAppendPrintf(sentry
, "\tUP Time:\t%.3f seconds\n", runtime
);
597 storeAppendPrintf(sentry
, "\tCPU Time:\t%.3f seconds\n", cputime
);
599 storeAppendPrintf(sentry
, "\tCPU Usage:\t%.2f%%\n",
600 dpercent(cputime
, runtime
));
602 storeAppendPrintf(sentry
, "\tCPU Usage, 5 minute avg:\t%.2f%%\n",
605 storeAppendPrintf(sentry
, "\tCPU Usage, 60 minute avg:\t%.2f%%\n",
610 storeAppendPrintf(sentry
, "\tProcess Data Segment Size via sbrk(): %lu KB\n",
611 (unsigned long) (((char *) sbrk(0) - (char *) sbrk_start
) >> 10));
615 storeAppendPrintf(sentry
, "\tMaximum Resident Size: %d KB\n",
616 rusage_maxrss(&rusage
));
618 storeAppendPrintf(sentry
, "\tPage faults with physical i/o: %d\n",
619 rusage_pagefaults(&rusage
));
621 #if HAVE_MSTATS && HAVE_GNUMALLOC_H
625 storeAppendPrintf(sentry
, "Memory usage for %s via mstats():\n",APP_SHORTNAME
);
627 storeAppendPrintf(sentry
, "\tTotal space in arena: %6d KB\n",
628 ms
.bytes_total
>> 10);
630 storeAppendPrintf(sentry
, "\tTotal free: %6d KB %d%%\n",
631 ms
.bytes_free
>> 10, percent(ms
.bytes_free
, ms
.bytes_total
));
633 #elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
637 storeAppendPrintf(sentry
, "Memory usage for %s via mallinfo():\n",APP_SHORTNAME
);
639 storeAppendPrintf(sentry
, "\tTotal space in arena: %6ld KB\n",
640 (long)mp
.arena
>> 10);
642 storeAppendPrintf(sentry
, "\tOrdinary blocks: %6ld KB %6ld blks\n",
643 (long)mp
.uordblks
>> 10, (long)mp
.ordblks
);
645 storeAppendPrintf(sentry
, "\tSmall blocks: %6ld KB %6ld blks\n",
646 (long)mp
.usmblks
>> 10, (long)mp
.smblks
);
648 storeAppendPrintf(sentry
, "\tHolding blocks: %6ld KB %6ld blks\n",
649 (long)mp
.hblkhd
>> 10, (long)mp
.hblks
);
651 storeAppendPrintf(sentry
, "\tFree Small blocks: %6ld KB\n",
652 (long)mp
.fsmblks
>> 10);
654 storeAppendPrintf(sentry
, "\tFree Ordinary blocks: %6ld KB\n",
655 (long)mp
.fordblks
>> 10);
657 t
= mp
.uordblks
+ mp
.usmblks
+ mp
.hblkhd
;
659 storeAppendPrintf(sentry
, "\tTotal in use: %6d KB %d%%\n",
660 t
>> 10, percent(t
, mp
.arena
+ mp
.hblkhd
));
662 t
= mp
.fsmblks
+ mp
.fordblks
;
664 storeAppendPrintf(sentry
, "\tTotal free: %6d KB %d%%\n",
665 t
>> 10, percent(t
, mp
.arena
+ mp
.hblkhd
));
667 t
= mp
.arena
+ mp
.hblkhd
;
669 storeAppendPrintf(sentry
, "\tTotal size: %6d KB\n",
672 #if HAVE_STRUCT_MALLINFO_MXFAST
674 storeAppendPrintf(sentry
, "\tmax size of small blocks:\t%d\n", mp
.mxfast
);
676 storeAppendPrintf(sentry
, "\tnumber of small blocks in a holding block:\t%d\n",
679 storeAppendPrintf(sentry
, "\tsmall block rounding factor:\t%d\n", mp
.grain
);
681 storeAppendPrintf(sentry
, "\tspace (including overhead) allocated in ord. blks:\t%d\n"
684 storeAppendPrintf(sentry
, "\tnumber of ordinary blocks allocated:\t%d\n",
687 storeAppendPrintf(sentry
, "\tbytes used in maintaining the free tree:\t%d\n",
690 #endif /* HAVE_STRUCT_MALLINFO_MXFAST */
691 #endif /* HAVE_MALLINFO */
693 storeAppendPrintf(sentry
, "Memory accounted for:\n");
695 #if !(HAVE_MSTATS && HAVE_GNUMALLOC_H) && HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
697 storeAppendPrintf(sentry
, "\tTotal accounted: %6d KB %3d%%\n",
698 statMemoryAccounted() >> 10, percent(statMemoryAccounted(), t
));
702 storeAppendPrintf(sentry
, "\tTotal accounted: %6d KB\n",
703 statMemoryAccounted() >> 10);
707 MemPoolGlobalStats mp_stats
;
708 memPoolGetGlobalStats(&mp_stats
);
709 #if !(HAVE_MSTATS && HAVE_GNUMALLOC_H) && HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
711 storeAppendPrintf(sentry
, "\tmemPool accounted: %6d KB %3d%%\n",
712 (int) mp_stats
.TheMeter
->alloc
.level
>> 10,
713 percent(mp_stats
.TheMeter
->alloc
.level
, t
));
714 storeAppendPrintf(sentry
, "\tmemPool unaccounted: %6d KB %3d%%\n",
715 (t
- (int) mp_stats
.TheMeter
->alloc
.level
) >> 10,
716 percent((t
- mp_stats
.TheMeter
->alloc
.level
), t
));
719 storeAppendPrintf(sentry
, "\tmemPoolAlloc calls: %9.0f\n",
720 mp_stats
.TheMeter
->gb_saved
.count
);
721 storeAppendPrintf(sentry
, "\tmemPoolFree calls: %9.0f\n",
722 mp_stats
.TheMeter
->gb_freed
.count
);
725 storeAppendPrintf(sentry
, "File descriptor usage for %s:\n", APP_SHORTNAME
);
726 storeAppendPrintf(sentry
, "\tMaximum number of file descriptors: %4d\n",
728 storeAppendPrintf(sentry
, "\tLargest file desc currently in use: %4d\n",
730 storeAppendPrintf(sentry
, "\tNumber of file desc currently in use: %4d\n",
732 storeAppendPrintf(sentry
, "\tFiles queued for open: %4d\n",
734 storeAppendPrintf(sentry
, "\tAvailable number of file descriptors: %4d\n",
736 storeAppendPrintf(sentry
, "\tReserved number of file descriptors: %4d\n",
738 storeAppendPrintf(sentry
, "\tStore Disk files open: %4d\n",
741 storeAppendPrintf(sentry
, "Internal Data Structures:\n");
742 storeAppendPrintf(sentry
, "\t%6lu StoreEntries\n",
743 (unsigned long)StoreEntry::inUseCount());
744 storeAppendPrintf(sentry
, "\t%6lu StoreEntries with MemObjects\n",
745 (unsigned long)MemObject::inUseCount());
746 storeAppendPrintf(sentry
, "\t%6d Hot Object Cache Items\n",
748 storeAppendPrintf(sentry
, "\t%6d on-disk objects\n",
751 #if XMALLOC_STATISTICS
753 xm_deltat
= current_dtime
- xm_time
;
754 xm_time
= current_dtime
;
755 storeAppendPrintf(sentry
, "\nMemory allocation statistics\n");
756 storeAppendPrintf(sentry
, "%12s %15s %6s %12s\n","Alloc Size","Count","Delta","Alloc/sec");
757 malloc_statistics(info_get_mallstat
, sentry
);
762 service_times(StoreEntry
* sentry
)
765 storeAppendPrintf(sentry
, "Service Time Percentiles 5 min 60 min:\n");
766 for (p
= 5; p
< 100; p
+= 5) {
767 storeAppendPrintf(sentry
, "\tHTTP Requests (All): %2d%% %8.5f %8.5f\n",
769 statPctileSvc((double) p
/ 100.0, 5, PCTILE_HTTP
) / 1000.0,
770 statPctileSvc((double) p
/ 100.0, 60, PCTILE_HTTP
) / 1000.0);
772 for (p
= 5; p
< 100; p
+= 5) {
773 storeAppendPrintf(sentry
, "\tCache Misses: %2d%% %8.5f %8.5f\n",
775 statPctileSvc((double) p
/ 100.0, 5, PCTILE_MISS
) / 1000.0,
776 statPctileSvc((double) p
/ 100.0, 60, PCTILE_MISS
) / 1000.0);
778 for (p
= 5; p
< 100; p
+= 5) {
779 storeAppendPrintf(sentry
, "\tCache Hits: %2d%% %8.5f %8.5f\n",
781 statPctileSvc((double) p
/ 100.0, 5, PCTILE_HIT
) / 1000.0,
782 statPctileSvc((double) p
/ 100.0, 60, PCTILE_HIT
) / 1000.0);
784 for (p
= 5; p
< 100; p
+= 5) {
785 storeAppendPrintf(sentry
, "\tNear Hits: %2d%% %8.5f %8.5f\n",
787 statPctileSvc((double) p
/ 100.0, 5, PCTILE_NH
) / 1000.0,
788 statPctileSvc((double) p
/ 100.0, 60, PCTILE_NH
) / 1000.0);
790 for (p
= 5; p
< 100; p
+= 5) {
791 storeAppendPrintf(sentry
, "\tNot-Modified Replies: %2d%% %8.5f %8.5f\n",
793 statPctileSvc((double) p
/ 100.0, 5, PCTILE_NM
) / 1000.0,
794 statPctileSvc((double) p
/ 100.0, 60, PCTILE_NM
) / 1000.0);
796 for (p
= 5; p
< 100; p
+= 5) {
797 storeAppendPrintf(sentry
, "\tDNS Lookups: %2d%% %8.5f %8.5f\n",
799 statPctileSvc((double) p
/ 100.0, 5, PCTILE_DNS
) / 1000.0,
800 statPctileSvc((double) p
/ 100.0, 60, PCTILE_DNS
) / 1000.0);
802 for (p
= 5; p
< 100; p
+= 5) {
803 storeAppendPrintf(sentry
, "\tICP Queries: %2d%% %8.5f %8.5f\n",
805 statPctileSvc((double) p
/ 100.0, 5, PCTILE_ICP_QUERY
) / 1000000.0,
806 statPctileSvc((double) p
/ 100.0, 60, PCTILE_ICP_QUERY
) / 1000000.0);
810 #define XAVG(X) (dt ? (double) (f->X - l->X) / dt : 0.0)
812 statAvgDump(StoreEntry
* sentry
, int minutes
, int hours
)
819 assert(N_COUNT_HIST
> 1);
820 assert(minutes
> 0 || hours
> 0);
824 if (minutes
> 0 && hours
== 0) {
825 /* checking minute readings ... */
827 if (minutes
> N_COUNT_HIST
- 1)
828 minutes
= N_COUNT_HIST
- 1;
830 l
= &CountHist
[minutes
];
831 } else if (minutes
== 0 && hours
> 0) {
832 /* checking hour readings ... */
834 if (hours
> N_COUNT_HOUR_HIST
- 1)
835 hours
= N_COUNT_HOUR_HIST
- 1;
837 l
= &CountHourHist
[hours
];
839 debugs(18, 1, "statAvgDump: Invalid args, minutes=" << minutes
<< ", hours=" << hours
);
843 dt
= tvSubDsec(l
->timestamp
, f
->timestamp
);
844 ct
= f
->cputime
- l
->cputime
;
846 storeAppendPrintf(sentry
, "sample_start_time = %d.%d (%s)\n",
847 (int) l
->timestamp
.tv_sec
,
848 (int) l
->timestamp
.tv_usec
,
849 mkrfc1123(l
->timestamp
.tv_sec
));
850 storeAppendPrintf(sentry
, "sample_end_time = %d.%d (%s)\n",
851 (int) f
->timestamp
.tv_sec
,
852 (int) f
->timestamp
.tv_usec
,
853 mkrfc1123(f
->timestamp
.tv_sec
));
855 storeAppendPrintf(sentry
, "client_http.requests = %f/sec\n",
856 XAVG(client_http
.requests
));
857 storeAppendPrintf(sentry
, "client_http.hits = %f/sec\n",
858 XAVG(client_http
.hits
));
859 storeAppendPrintf(sentry
, "client_http.errors = %f/sec\n",
860 XAVG(client_http
.errors
));
861 storeAppendPrintf(sentry
, "client_http.kbytes_in = %f/sec\n",
862 XAVG(client_http
.kbytes_in
.kb
));
863 storeAppendPrintf(sentry
, "client_http.kbytes_out = %f/sec\n",
864 XAVG(client_http
.kbytes_out
.kb
));
866 x
= statHistDeltaMedian(&l
->client_http
.all_svc_time
,
867 &f
->client_http
.all_svc_time
);
868 storeAppendPrintf(sentry
, "client_http.all_median_svc_time = %f seconds\n",
870 x
= statHistDeltaMedian(&l
->client_http
.miss_svc_time
,
871 &f
->client_http
.miss_svc_time
);
872 storeAppendPrintf(sentry
, "client_http.miss_median_svc_time = %f seconds\n",
874 x
= statHistDeltaMedian(&l
->client_http
.nm_svc_time
,
875 &f
->client_http
.nm_svc_time
);
876 storeAppendPrintf(sentry
, "client_http.nm_median_svc_time = %f seconds\n",
878 x
= statHistDeltaMedian(&l
->client_http
.nh_svc_time
,
879 &f
->client_http
.nh_svc_time
);
880 storeAppendPrintf(sentry
, "client_http.nh_median_svc_time = %f seconds\n",
882 x
= statHistDeltaMedian(&l
->client_http
.hit_svc_time
,
883 &f
->client_http
.hit_svc_time
);
884 storeAppendPrintf(sentry
, "client_http.hit_median_svc_time = %f seconds\n",
887 storeAppendPrintf(sentry
, "server.all.requests = %f/sec\n",
888 XAVG(server
.all
.requests
));
889 storeAppendPrintf(sentry
, "server.all.errors = %f/sec\n",
890 XAVG(server
.all
.errors
));
891 storeAppendPrintf(sentry
, "server.all.kbytes_in = %f/sec\n",
892 XAVG(server
.all
.kbytes_in
.kb
));
893 storeAppendPrintf(sentry
, "server.all.kbytes_out = %f/sec\n",
894 XAVG(server
.all
.kbytes_out
.kb
));
896 storeAppendPrintf(sentry
, "server.http.requests = %f/sec\n",
897 XAVG(server
.http
.requests
));
898 storeAppendPrintf(sentry
, "server.http.errors = %f/sec\n",
899 XAVG(server
.http
.errors
));
900 storeAppendPrintf(sentry
, "server.http.kbytes_in = %f/sec\n",
901 XAVG(server
.http
.kbytes_in
.kb
));
902 storeAppendPrintf(sentry
, "server.http.kbytes_out = %f/sec\n",
903 XAVG(server
.http
.kbytes_out
.kb
));
905 storeAppendPrintf(sentry
, "server.ftp.requests = %f/sec\n",
906 XAVG(server
.ftp
.requests
));
907 storeAppendPrintf(sentry
, "server.ftp.errors = %f/sec\n",
908 XAVG(server
.ftp
.errors
));
909 storeAppendPrintf(sentry
, "server.ftp.kbytes_in = %f/sec\n",
910 XAVG(server
.ftp
.kbytes_in
.kb
));
911 storeAppendPrintf(sentry
, "server.ftp.kbytes_out = %f/sec\n",
912 XAVG(server
.ftp
.kbytes_out
.kb
));
914 storeAppendPrintf(sentry
, "server.other.requests = %f/sec\n",
915 XAVG(server
.other
.requests
));
916 storeAppendPrintf(sentry
, "server.other.errors = %f/sec\n",
917 XAVG(server
.other
.errors
));
918 storeAppendPrintf(sentry
, "server.other.kbytes_in = %f/sec\n",
919 XAVG(server
.other
.kbytes_in
.kb
));
920 storeAppendPrintf(sentry
, "server.other.kbytes_out = %f/sec\n",
921 XAVG(server
.other
.kbytes_out
.kb
));
923 storeAppendPrintf(sentry
, "icp.pkts_sent = %f/sec\n",
924 XAVG(icp
.pkts_sent
));
925 storeAppendPrintf(sentry
, "icp.pkts_recv = %f/sec\n",
926 XAVG(icp
.pkts_recv
));
927 storeAppendPrintf(sentry
, "icp.queries_sent = %f/sec\n",
928 XAVG(icp
.queries_sent
));
929 storeAppendPrintf(sentry
, "icp.replies_sent = %f/sec\n",
930 XAVG(icp
.replies_sent
));
931 storeAppendPrintf(sentry
, "icp.queries_recv = %f/sec\n",
932 XAVG(icp
.queries_recv
));
933 storeAppendPrintf(sentry
, "icp.replies_recv = %f/sec\n",
934 XAVG(icp
.replies_recv
));
935 storeAppendPrintf(sentry
, "icp.replies_queued = %f/sec\n",
936 XAVG(icp
.replies_queued
));
937 storeAppendPrintf(sentry
, "icp.query_timeouts = %f/sec\n",
938 XAVG(icp
.query_timeouts
));
939 storeAppendPrintf(sentry
, "icp.kbytes_sent = %f/sec\n",
940 XAVG(icp
.kbytes_sent
.kb
));
941 storeAppendPrintf(sentry
, "icp.kbytes_recv = %f/sec\n",
942 XAVG(icp
.kbytes_recv
.kb
));
943 storeAppendPrintf(sentry
, "icp.q_kbytes_sent = %f/sec\n",
944 XAVG(icp
.q_kbytes_sent
.kb
));
945 storeAppendPrintf(sentry
, "icp.r_kbytes_sent = %f/sec\n",
946 XAVG(icp
.r_kbytes_sent
.kb
));
947 storeAppendPrintf(sentry
, "icp.q_kbytes_recv = %f/sec\n",
948 XAVG(icp
.q_kbytes_recv
.kb
));
949 storeAppendPrintf(sentry
, "icp.r_kbytes_recv = %f/sec\n",
950 XAVG(icp
.r_kbytes_recv
.kb
));
951 x
= statHistDeltaMedian(&l
->icp
.query_svc_time
, &f
->icp
.query_svc_time
);
952 storeAppendPrintf(sentry
, "icp.query_median_svc_time = %f seconds\n",
954 x
= statHistDeltaMedian(&l
->icp
.reply_svc_time
, &f
->icp
.reply_svc_time
);
955 storeAppendPrintf(sentry
, "icp.reply_median_svc_time = %f seconds\n",
957 x
= statHistDeltaMedian(&l
->dns
.svc_time
, &f
->dns
.svc_time
);
958 storeAppendPrintf(sentry
, "dns.median_svc_time = %f seconds\n",
960 storeAppendPrintf(sentry
, "unlink.requests = %f/sec\n",
961 XAVG(unlink
.requests
));
962 storeAppendPrintf(sentry
, "page_faults = %f/sec\n",
964 storeAppendPrintf(sentry
, "select_loops = %f/sec\n",
966 storeAppendPrintf(sentry
, "select_fds = %f/sec\n",
968 storeAppendPrintf(sentry
, "average_select_fd_period = %f/fd\n",
969 f
->select_fds
> l
->select_fds
?
970 (f
->select_time
- l
->select_time
) / (f
->select_fds
- l
->select_fds
)
972 x
= statHistDeltaMedian(&l
->select_fds_hist
, &f
->select_fds_hist
);
973 storeAppendPrintf(sentry
, "median_select_fds = %f\n", x
);
974 storeAppendPrintf(sentry
, "swap.outs = %f/sec\n",
976 storeAppendPrintf(sentry
, "swap.ins = %f/sec\n",
978 storeAppendPrintf(sentry
, "swap.files_cleaned = %f/sec\n",
979 XAVG(swap
.files_cleaned
));
980 storeAppendPrintf(sentry
, "aborted_requests = %f/sec\n",
981 XAVG(aborted_requests
));
984 storeAppendPrintf(sentry
, "syscalls.polls = %f/sec\n", XAVG(syscalls
.selects
));
985 #elif defined(USE_SELECT) || defined(USE_SELECT_WIN32)
986 storeAppendPrintf(sentry
, "syscalls.selects = %f/sec\n", XAVG(syscalls
.selects
));
989 storeAppendPrintf(sentry
, "syscalls.disk.opens = %f/sec\n", XAVG(syscalls
.disk
.opens
));
990 storeAppendPrintf(sentry
, "syscalls.disk.closes = %f/sec\n", XAVG(syscalls
.disk
.closes
));
991 storeAppendPrintf(sentry
, "syscalls.disk.reads = %f/sec\n", XAVG(syscalls
.disk
.reads
));
992 storeAppendPrintf(sentry
, "syscalls.disk.writes = %f/sec\n", XAVG(syscalls
.disk
.writes
));
993 storeAppendPrintf(sentry
, "syscalls.disk.seeks = %f/sec\n", XAVG(syscalls
.disk
.seeks
));
994 storeAppendPrintf(sentry
, "syscalls.disk.unlinks = %f/sec\n", XAVG(syscalls
.disk
.unlinks
));
995 storeAppendPrintf(sentry
, "syscalls.sock.accepts = %f/sec\n", XAVG(syscalls
.sock
.accepts
));
996 storeAppendPrintf(sentry
, "syscalls.sock.sockets = %f/sec\n", XAVG(syscalls
.sock
.sockets
));
997 storeAppendPrintf(sentry
, "syscalls.sock.connects = %f/sec\n", XAVG(syscalls
.sock
.connects
));
998 storeAppendPrintf(sentry
, "syscalls.sock.binds = %f/sec\n", XAVG(syscalls
.sock
.binds
));
999 storeAppendPrintf(sentry
, "syscalls.sock.closes = %f/sec\n", XAVG(syscalls
.sock
.closes
));
1000 storeAppendPrintf(sentry
, "syscalls.sock.reads = %f/sec\n", XAVG(syscalls
.sock
.reads
));
1001 storeAppendPrintf(sentry
, "syscalls.sock.writes = %f/sec\n", XAVG(syscalls
.sock
.writes
));
1002 storeAppendPrintf(sentry
, "syscalls.sock.recvfroms = %f/sec\n", XAVG(syscalls
.sock
.recvfroms
));
1003 storeAppendPrintf(sentry
, "syscalls.sock.sendtos = %f/sec\n", XAVG(syscalls
.sock
.sendtos
));
1005 storeAppendPrintf(sentry
, "cpu_time = %f seconds\n", ct
);
1006 storeAppendPrintf(sentry
, "wall_time = %f seconds\n", dt
);
1007 storeAppendPrintf(sentry
, "cpu_usage = %f%%\n", dpercent(ct
, dt
));
1011 statRegisterWithCacheManager(void)
1013 CacheManager
*manager
= CacheManager::GetInstance();
1014 manager
->registerAction("info", "General Runtime Information",
1016 manager
->registerAction("service_times", "Service Times (Percentiles)",
1017 service_times
, 0, 1);
1018 manager
->registerAction("filedescriptors", "Process Filedescriptor Allocation",
1019 fde::DumpStats
, 0, 1);
1020 manager
->registerAction("objects", "All Cache Objects", stat_objects_get
, 0, 0);
1021 manager
->registerAction("vm_objects", "In-Memory and In-Transit Objects",
1022 stat_vmobjects_get
, 0, 0);
1023 manager
->registerAction("io", "Server-side network read() size histograms",
1025 manager
->registerAction("counters", "Traffic and Resource Counters",
1026 statCountersDump
, 0, 1);
1027 manager
->registerAction("peer_select", "Peer Selection Algorithms",
1028 statPeerSelect
, 0, 1);
1029 manager
->registerAction("digest_stats", "Cache Digest and ICP blob",
1030 statDigestBlob
, 0, 1);
1031 manager
->registerAction("5min", "5 Minute Average of Counters",
1033 manager
->registerAction("60min", "60 Minute Average of Counters",
1034 statAvg60min
, 0, 1);
1035 manager
->registerAction("utilization", "Cache Utilization",
1036 statUtilization
, 0, 1);
1037 manager
->registerAction("histograms", "Full Histogram Counts",
1038 statCountersHistograms
, 0, 1);
1039 manager
->registerAction("active_requests",
1040 "Client-side Active Requests",
1041 statClientRequests
, 0, 1);
1043 manager
->registerAction("openfd_objects", "Objects with Swapout files open",
1044 statOpenfdObj
, 0, 0);
1047 manager
->registerAction("graph_variables", "Display cache metrics graphically",
1048 statGraphDump
, 0, 1);
1057 debugs(18, 5, "statInit: Initializing...");
1059 for (i
= 0; i
< N_COUNT_HIST
; i
++)
1060 statCountersInit(&CountHist
[i
]);
1062 for (i
= 0; i
< N_COUNT_HOUR_HIST
; i
++)
1063 statCountersInit(&CountHourHist
[i
]);
1065 statCountersInit(&statCounter
);
1067 eventAdd("statAvgTick", statAvgTick
, NULL
, (double) COUNT_INTERVAL
, 1);
1069 ClientActiveRequests
.head
= NULL
;
1071 ClientActiveRequests
.tail
= NULL
;
1073 statRegisterWithCacheManager();
1077 statAvgTick(void *notused
)
1079 StatCounters
*t
= &CountHist
[0];
1080 StatCounters
*p
= &CountHist
[1];
1081 StatCounters
*c
= &statCounter
;
1083 struct rusage rusage
;
1084 eventAdd("statAvgTick", statAvgTick
, NULL
, (double) COUNT_INTERVAL
, 1);
1085 squid_getrusage(&rusage
);
1086 c
->page_faults
= rusage_pagefaults(&rusage
);
1087 c
->cputime
= rusage_cputime(&rusage
);
1088 c
->timestamp
= current_time
;
1089 /* even if NCountHist is small, we already Init()ed the tail */
1090 statCountersClean(CountHist
+ N_COUNT_HIST
- 1);
1091 xmemmove(p
, t
, (N_COUNT_HIST
- 1) * sizeof(StatCounters
));
1092 statCountersCopy(t
, c
);
1095 if ((NCountHist
% COUNT_INTERVAL
) == 0) {
1096 /* we have an hours worth of readings. store previous hour */
1097 StatCounters
*t
= &CountHourHist
[0];
1098 StatCounters
*p
= &CountHourHist
[1];
1099 StatCounters
*c
= &CountHist
[N_COUNT_HIST
- 1];
1100 statCountersClean(CountHourHist
+ N_COUNT_HOUR_HIST
- 1);
1101 xmemmove(p
, t
, (N_COUNT_HOUR_HIST
- 1) * sizeof(StatCounters
));
1102 statCountersCopy(t
, c
);
1106 if (Config
.warnings
.high_rptm
> 0) {
1107 int i
= (int) statPctileSvc(0.5, 20, PCTILE_HTTP
);
1109 if (Config
.warnings
.high_rptm
< i
)
1110 debugs(18, 0, "WARNING: Median response time is " << i
<< " milliseconds");
1113 if (Config
.warnings
.high_pf
) {
1114 int i
= (CountHist
[0].page_faults
- CountHist
[1].page_faults
);
1115 double dt
= tvSubDsec(CountHist
[0].timestamp
, CountHist
[1].timestamp
);
1117 if (i
> 0 && dt
> 0.0) {
1120 if (Config
.warnings
.high_pf
< i
)
1121 debugs(18, 0, "WARNING: Page faults occuring at " << i
<< "/sec");
1125 if (Config
.warnings
.high_memory
) {
1127 #if HAVE_MSTATS && HAVE_GNUMALLOC_H
1129 struct mstats ms
= mstats();
1131 #elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
1133 struct mallinfo mp
= mallinfo();
1137 i
= (size_t) ((char *) sbrk(0) - (char *) sbrk_start
);
1140 if (Config
.warnings
.high_memory
< i
)
1141 debugs(18, 0, "WARNING: Memory usage at " << ((unsigned long int)(i
>> 20)) << " MB");
1146 statCountersInit(StatCounters
* C
)
1149 memset(C
, 0, sizeof(*C
));
1150 C
->timestamp
= current_time
;
1151 statCountersInitSpecial(C
);
1154 /* add special cases here as they arrive */
1156 statCountersInitSpecial(StatCounters
* C
)
1159 * HTTP svc_time hist is kept in milli-seconds; max of 3 hours.
1161 statHistLogInit(&C
->client_http
.all_svc_time
, 300, 0.0, 3600000.0 * 3.0);
1162 statHistLogInit(&C
->client_http
.miss_svc_time
, 300, 0.0, 3600000.0 * 3.0);
1163 statHistLogInit(&C
->client_http
.nm_svc_time
, 300, 0.0, 3600000.0 * 3.0);
1164 statHistLogInit(&C
->client_http
.nh_svc_time
, 300, 0.0, 3600000.0 * 3.0);
1165 statHistLogInit(&C
->client_http
.hit_svc_time
, 300, 0.0, 3600000.0 * 3.0);
1167 * ICP svc_time hist is kept in micro-seconds; max of 1 minute.
1169 statHistLogInit(&C
->icp
.query_svc_time
, 300, 0.0, 1000000.0 * 60.0);
1170 statHistLogInit(&C
->icp
.reply_svc_time
, 300, 0.0, 1000000.0 * 60.0);
1172 * DNS svc_time hist is kept in milli-seconds; max of 10 minutes.
1174 statHistLogInit(&C
->dns
.svc_time
, 300, 0.0, 60000.0 * 10.0);
1176 * Cache Digest Stuff
1178 statHistEnumInit(&C
->cd
.on_xition_count
, CacheDigestHashFuncCount
);
1179 statHistEnumInit(&C
->comm_icp_incoming
, INCOMING_ICP_MAX
);
1180 statHistEnumInit(&C
->comm_dns_incoming
, INCOMING_DNS_MAX
);
1181 statHistEnumInit(&C
->comm_http_incoming
, INCOMING_HTTP_MAX
);
1182 statHistIntInit(&C
->select_fds_hist
, 256); /* was SQUID_MAXFD, but it is way too much. It is OK to crop this statistics */
1185 /* add special cases here as they arrive */
1187 statCountersClean(StatCounters
* C
)
1190 statHistClean(&C
->client_http
.all_svc_time
);
1191 statHistClean(&C
->client_http
.miss_svc_time
);
1192 statHistClean(&C
->client_http
.nm_svc_time
);
1193 statHistClean(&C
->client_http
.nh_svc_time
);
1194 statHistClean(&C
->client_http
.hit_svc_time
);
1195 statHistClean(&C
->icp
.query_svc_time
);
1196 statHistClean(&C
->icp
.reply_svc_time
);
1197 statHistClean(&C
->dns
.svc_time
);
1198 statHistClean(&C
->cd
.on_xition_count
);
1199 statHistClean(&C
->comm_icp_incoming
);
1200 statHistClean(&C
->comm_dns_incoming
);
1201 statHistClean(&C
->comm_http_incoming
);
1202 statHistClean(&C
->select_fds_hist
);
1205 /* add special cases here as they arrive */
1207 statCountersCopy(StatCounters
* dest
, const StatCounters
* orig
)
1209 assert(dest
&& orig
);
1210 /* this should take care of all the fields, but "special" ones */
1211 xmemcpy(dest
, orig
, sizeof(*dest
));
1212 /* prepare space where to copy special entries */
1213 statCountersInitSpecial(dest
);
1214 /* now handle special cases */
1215 /* note: we assert that histogram capacities do not change */
1216 statHistCopy(&dest
->client_http
.all_svc_time
, &orig
->client_http
.all_svc_time
);
1217 statHistCopy(&dest
->client_http
.miss_svc_time
, &orig
->client_http
.miss_svc_time
);
1218 statHistCopy(&dest
->client_http
.nm_svc_time
, &orig
->client_http
.nm_svc_time
);
1219 statHistCopy(&dest
->client_http
.nh_svc_time
, &orig
->client_http
.nh_svc_time
);
1220 statHistCopy(&dest
->client_http
.hit_svc_time
, &orig
->client_http
.hit_svc_time
);
1221 statHistCopy(&dest
->icp
.query_svc_time
, &orig
->icp
.query_svc_time
);
1222 statHistCopy(&dest
->icp
.reply_svc_time
, &orig
->icp
.reply_svc_time
);
1223 statHistCopy(&dest
->dns
.svc_time
, &orig
->dns
.svc_time
);
1224 statHistCopy(&dest
->cd
.on_xition_count
, &orig
->cd
.on_xition_count
);
1225 statHistCopy(&dest
->comm_icp_incoming
, &orig
->comm_icp_incoming
);
1226 statHistCopy(&dest
->comm_http_incoming
, &orig
->comm_http_incoming
);
1227 statHistCopy(&dest
->select_fds_hist
, &orig
->select_fds_hist
);
1231 statCountersHistograms(StoreEntry
* sentry
)
1233 StatCounters
*f
= &statCounter
;
1234 storeAppendPrintf(sentry
, "client_http.all_svc_time histogram:\n");
1235 statHistDump(&f
->client_http
.all_svc_time
, sentry
, NULL
);
1236 storeAppendPrintf(sentry
, "client_http.miss_svc_time histogram:\n");
1237 statHistDump(&f
->client_http
.miss_svc_time
, sentry
, NULL
);
1238 storeAppendPrintf(sentry
, "client_http.nm_svc_time histogram:\n");
1239 statHistDump(&f
->client_http
.nm_svc_time
, sentry
, NULL
);
1240 storeAppendPrintf(sentry
, "client_http.nh_svc_time histogram:\n");
1241 statHistDump(&f
->client_http
.nh_svc_time
, sentry
, NULL
);
1242 storeAppendPrintf(sentry
, "client_http.hit_svc_time histogram:\n");
1243 statHistDump(&f
->client_http
.hit_svc_time
, sentry
, NULL
);
1244 storeAppendPrintf(sentry
, "icp.query_svc_time histogram:\n");
1245 statHistDump(&f
->icp
.query_svc_time
, sentry
, NULL
);
1246 storeAppendPrintf(sentry
, "icp.reply_svc_time histogram:\n");
1247 statHistDump(&f
->icp
.reply_svc_time
, sentry
, NULL
);
1248 storeAppendPrintf(sentry
, "dns.svc_time histogram:\n");
1249 statHistDump(&f
->dns
.svc_time
, sentry
, NULL
);
1250 storeAppendPrintf(sentry
, "select_fds_hist histogram:\n");
1251 statHistDump(&f
->select_fds_hist
, sentry
, NULL
);
1255 statCountersDump(StoreEntry
* sentry
)
1257 StatCounters
*f
= &statCounter
;
1259 struct rusage rusage
;
1260 squid_getrusage(&rusage
);
1261 f
->page_faults
= rusage_pagefaults(&rusage
);
1262 f
->cputime
= rusage_cputime(&rusage
);
1264 storeAppendPrintf(sentry
, "sample_time = %d.%d (%s)\n",
1265 (int) f
->timestamp
.tv_sec
,
1266 (int) f
->timestamp
.tv_usec
,
1267 mkrfc1123(f
->timestamp
.tv_sec
));
1268 storeAppendPrintf(sentry
, "client_http.requests = %d\n",
1269 f
->client_http
.requests
);
1270 storeAppendPrintf(sentry
, "client_http.hits = %d\n",
1271 f
->client_http
.hits
);
1272 storeAppendPrintf(sentry
, "client_http.errors = %d\n",
1273 f
->client_http
.errors
);
1274 storeAppendPrintf(sentry
, "client_http.kbytes_in = %d\n",
1275 (int) f
->client_http
.kbytes_in
.kb
);
1276 storeAppendPrintf(sentry
, "client_http.kbytes_out = %d\n",
1277 (int) f
->client_http
.kbytes_out
.kb
);
1278 storeAppendPrintf(sentry
, "client_http.hit_kbytes_out = %d\n",
1279 (int) f
->client_http
.hit_kbytes_out
.kb
);
1281 storeAppendPrintf(sentry
, "server.all.requests = %d\n",
1282 (int) f
->server
.all
.requests
);
1283 storeAppendPrintf(sentry
, "server.all.errors = %d\n",
1284 (int) f
->server
.all
.errors
);
1285 storeAppendPrintf(sentry
, "server.all.kbytes_in = %d\n",
1286 (int) f
->server
.all
.kbytes_in
.kb
);
1287 storeAppendPrintf(sentry
, "server.all.kbytes_out = %d\n",
1288 (int) f
->server
.all
.kbytes_out
.kb
);
1290 storeAppendPrintf(sentry
, "server.http.requests = %d\n",
1291 (int) f
->server
.http
.requests
);
1292 storeAppendPrintf(sentry
, "server.http.errors = %d\n",
1293 (int) f
->server
.http
.errors
);
1294 storeAppendPrintf(sentry
, "server.http.kbytes_in = %d\n",
1295 (int) f
->server
.http
.kbytes_in
.kb
);
1296 storeAppendPrintf(sentry
, "server.http.kbytes_out = %d\n",
1297 (int) f
->server
.http
.kbytes_out
.kb
);
1299 storeAppendPrintf(sentry
, "server.ftp.requests = %d\n",
1300 (int) f
->server
.ftp
.requests
);
1301 storeAppendPrintf(sentry
, "server.ftp.errors = %d\n",
1302 (int) f
->server
.ftp
.errors
);
1303 storeAppendPrintf(sentry
, "server.ftp.kbytes_in = %d\n",
1304 (int) f
->server
.ftp
.kbytes_in
.kb
);
1305 storeAppendPrintf(sentry
, "server.ftp.kbytes_out = %d\n",
1306 (int) f
->server
.ftp
.kbytes_out
.kb
);
1308 storeAppendPrintf(sentry
, "server.other.requests = %d\n",
1309 (int) f
->server
.other
.requests
);
1310 storeAppendPrintf(sentry
, "server.other.errors = %d\n",
1311 (int) f
->server
.other
.errors
);
1312 storeAppendPrintf(sentry
, "server.other.kbytes_in = %d\n",
1313 (int) f
->server
.other
.kbytes_in
.kb
);
1314 storeAppendPrintf(sentry
, "server.other.kbytes_out = %d\n",
1315 (int) f
->server
.other
.kbytes_out
.kb
);
1317 storeAppendPrintf(sentry
, "icp.pkts_sent = %d\n",
1319 storeAppendPrintf(sentry
, "icp.pkts_recv = %d\n",
1321 storeAppendPrintf(sentry
, "icp.queries_sent = %d\n",
1322 f
->icp
.queries_sent
);
1323 storeAppendPrintf(sentry
, "icp.replies_sent = %d\n",
1324 f
->icp
.replies_sent
);
1325 storeAppendPrintf(sentry
, "icp.queries_recv = %d\n",
1326 f
->icp
.queries_recv
);
1327 storeAppendPrintf(sentry
, "icp.replies_recv = %d\n",
1328 f
->icp
.replies_recv
);
1329 storeAppendPrintf(sentry
, "icp.query_timeouts = %d\n",
1330 f
->icp
.query_timeouts
);
1331 storeAppendPrintf(sentry
, "icp.replies_queued = %d\n",
1332 f
->icp
.replies_queued
);
1333 storeAppendPrintf(sentry
, "icp.kbytes_sent = %d\n",
1334 (int) f
->icp
.kbytes_sent
.kb
);
1335 storeAppendPrintf(sentry
, "icp.kbytes_recv = %d\n",
1336 (int) f
->icp
.kbytes_recv
.kb
);
1337 storeAppendPrintf(sentry
, "icp.q_kbytes_sent = %d\n",
1338 (int) f
->icp
.q_kbytes_sent
.kb
);
1339 storeAppendPrintf(sentry
, "icp.r_kbytes_sent = %d\n",
1340 (int) f
->icp
.r_kbytes_sent
.kb
);
1341 storeAppendPrintf(sentry
, "icp.q_kbytes_recv = %d\n",
1342 (int) f
->icp
.q_kbytes_recv
.kb
);
1343 storeAppendPrintf(sentry
, "icp.r_kbytes_recv = %d\n",
1344 (int) f
->icp
.r_kbytes_recv
.kb
);
1346 #if USE_CACHE_DIGESTS
1348 storeAppendPrintf(sentry
, "icp.times_used = %d\n",
1350 storeAppendPrintf(sentry
, "cd.times_used = %d\n",
1352 storeAppendPrintf(sentry
, "cd.msgs_sent = %d\n",
1354 storeAppendPrintf(sentry
, "cd.msgs_recv = %d\n",
1356 storeAppendPrintf(sentry
, "cd.memory = %d\n",
1357 (int) f
->cd
.memory
.kb
);
1358 storeAppendPrintf(sentry
, "cd.local_memory = %d\n",
1359 (int) (store_digest
? store_digest
->mask_size
/ 1024 : 0));
1360 storeAppendPrintf(sentry
, "cd.kbytes_sent = %d\n",
1361 (int) f
->cd
.kbytes_sent
.kb
);
1362 storeAppendPrintf(sentry
, "cd.kbytes_recv = %d\n",
1363 (int) f
->cd
.kbytes_recv
.kb
);
1366 storeAppendPrintf(sentry
, "unlink.requests = %d\n",
1367 f
->unlink
.requests
);
1368 storeAppendPrintf(sentry
, "page_faults = %d\n",
1370 storeAppendPrintf(sentry
, "select_loops = %ld\n",
1372 storeAppendPrintf(sentry
, "cpu_time = %f\n",
1374 storeAppendPrintf(sentry
, "wall_time = %f\n",
1375 tvSubDsec(f
->timestamp
, current_time
));
1376 storeAppendPrintf(sentry
, "swap.outs = %d\n",
1378 storeAppendPrintf(sentry
, "swap.ins = %d\n",
1380 storeAppendPrintf(sentry
, "swap.files_cleaned = %d\n",
1381 f
->swap
.files_cleaned
);
1382 storeAppendPrintf(sentry
, "aborted_requests = %d\n",
1383 f
->aborted_requests
);
1387 statFreeMemory(void)
1391 for (i
= 0; i
< N_COUNT_HIST
; i
++)
1392 statCountersClean(&CountHist
[i
]);
1394 for (i
= 0; i
< N_COUNT_HOUR_HIST
; i
++)
1395 statCountersClean(&CountHourHist
[i
]);
1399 statPeerSelect(StoreEntry
* sentry
)
1401 #if USE_CACHE_DIGESTS
1402 StatCounters
*f
= &statCounter
;
1404 const int tot_used
= f
->cd
.times_used
+ f
->icp
.times_used
;
1407 cacheDigestGuessStatsReport(&f
->cd
.guess
, sentry
, "all peers");
1409 storeAppendPrintf(sentry
, "\nPer-peer statistics:\n");
1411 for (peer
= getFirstPeer(); peer
; peer
= getNextPeer(peer
)) {
1413 peerDigestStatsReport(peer
->digest
, sentry
);
1415 storeAppendPrintf(sentry
, "\nNo peer digest from %s\n", peer
->host
);
1417 storeAppendPrintf(sentry
, "\n");
1420 storeAppendPrintf(sentry
, "\nAlgorithm usage:\n");
1421 storeAppendPrintf(sentry
, "Cache Digest: %7d (%3d%%)\n",
1422 f
->cd
.times_used
, xpercentInt(f
->cd
.times_used
, tot_used
));
1423 storeAppendPrintf(sentry
, "Icp: %7d (%3d%%)\n",
1424 f
->icp
.times_used
, xpercentInt(f
->icp
.times_used
, tot_used
));
1425 storeAppendPrintf(sentry
, "Total: %7d (%3d%%)\n",
1426 tot_used
, xpercentInt(tot_used
, tot_used
));
1429 storeAppendPrintf(sentry
, "peer digests are disabled; no stats is available.\n");
1434 statDigestBlob(StoreEntry
* sentry
)
1436 storeAppendPrintf(sentry
, "\nCounters:\n");
1437 statCountersDump(sentry
);
1438 storeAppendPrintf(sentry
, "\n5 Min Averages:\n");
1439 statAvgDump(sentry
, 5, 0);
1440 storeAppendPrintf(sentry
, "\nHistograms:\n");
1441 statCountersHistograms(sentry
);
1442 storeAppendPrintf(sentry
, "\nPeer Digests:\n");
1443 statPeerSelect(sentry
);
1444 storeAppendPrintf(sentry
, "\nLocal Digest:\n");
1445 storeDigestReport(sentry
);
1449 statAvg5min(StoreEntry
* e
)
1451 statAvgDump(e
, 5, 0);
1455 statAvg60min(StoreEntry
* e
)
1457 statAvgDump(e
, 60, 0);
1461 statPctileSvc(double pctile
, int interval
, int which
)
1466 assert(interval
> 0);
1468 if (interval
> N_COUNT_HIST
- 1)
1469 interval
= N_COUNT_HIST
- 1;
1473 l
= &CountHist
[interval
];
1482 x
= statHistDeltaPctile(&l
->client_http
.all_svc_time
, &f
->client_http
.all_svc_time
, pctile
);
1486 x
= statHistDeltaPctile(&l
->client_http
.hit_svc_time
, &f
->client_http
.hit_svc_time
, pctile
);
1490 x
= statHistDeltaPctile(&l
->client_http
.miss_svc_time
, &f
->client_http
.miss_svc_time
, pctile
);
1494 x
= statHistDeltaPctile(&l
->client_http
.nm_svc_time
, &f
->client_http
.nm_svc_time
, pctile
);
1498 x
= statHistDeltaPctile(&l
->client_http
.nh_svc_time
, &f
->client_http
.nh_svc_time
, pctile
);
1501 case PCTILE_ICP_QUERY
:
1502 x
= statHistDeltaPctile(&l
->icp
.query_svc_time
, &f
->icp
.query_svc_time
, pctile
);
1506 x
= statHistDeltaPctile(&l
->dns
.svc_time
, &f
->dns
.svc_time
, pctile
);
1510 debugs(49, 5, "statPctileSvc: unknown type.");
1518 snmpStatGet(int minutes
)
1520 return &CountHist
[minutes
];
1524 stat5minClientRequests(void)
1526 assert(N_COUNT_HIST
> 5);
1527 return statCounter
.client_http
.requests
- CountHist
[5].client_http
.requests
;
1531 statCPUUsage(int minutes
)
1533 assert(minutes
< N_COUNT_HIST
);
1534 return dpercent(CountHist
[0].cputime
- CountHist
[minutes
].cputime
,
1535 tvSubDsec(CountHist
[minutes
].timestamp
, CountHist
[0].timestamp
));
1539 statRequestHitRatio(int minutes
)
1541 assert(minutes
< N_COUNT_HIST
);
1542 return dpercent(CountHist
[0].client_http
.hits
-
1543 CountHist
[minutes
].client_http
.hits
,
1544 CountHist
[0].client_http
.requests
-
1545 CountHist
[minutes
].client_http
.requests
);
1549 statRequestHitMemoryRatio(int minutes
)
1551 assert(minutes
< N_COUNT_HIST
);
1552 return dpercent(CountHist
[0].client_http
.mem_hits
-
1553 CountHist
[minutes
].client_http
.mem_hits
,
1554 CountHist
[0].client_http
.hits
-
1555 CountHist
[minutes
].client_http
.hits
);
1559 statRequestHitDiskRatio(int minutes
)
1561 assert(minutes
< N_COUNT_HIST
);
1562 return dpercent(CountHist
[0].client_http
.disk_hits
-
1563 CountHist
[minutes
].client_http
.disk_hits
,
1564 CountHist
[0].client_http
.hits
-
1565 CountHist
[minutes
].client_http
.hits
);
1569 statByteHitRatio(int minutes
)
1573 #if USE_CACHE_DIGESTS
1577 /* size_t might be unsigned */
1578 assert(minutes
< N_COUNT_HIST
);
1579 c
= CountHist
[0].client_http
.kbytes_out
.kb
- CountHist
[minutes
].client_http
.kbytes_out
.kb
;
1580 s
= CountHist
[0].server
.all
.kbytes_in
.kb
- CountHist
[minutes
].server
.all
.kbytes_in
.kb
;
1581 #if USE_CACHE_DIGESTS
1583 * This ugly hack is here to prevent the user from seeing a
1584 * negative byte hit ratio. When we fetch a cache digest from
1585 * a neighbor, it gets treated like a cache miss because the
1586 * object is consumed internally. Thus, we subtract cache
1587 * digest bytes out before calculating the byte hit ratio.
1589 cd
= CountHist
[0].cd
.kbytes_recv
.kb
- CountHist
[minutes
].cd
.kbytes_recv
.kb
;
1592 debugs(18, 1, "STRANGE: srv_kbytes=" << s
<< ", cd_kbytes=" << cd
);
1599 return dpercent(c
- s
, c
);
1601 return (-1.0 * dpercent(s
- c
, c
));
1605 statClientRequests(StoreEntry
* s
)
1608 ClientHttpRequest
*http
;
1611 char buf
[MAX_IPSTRLEN
];
1613 for (i
= ClientActiveRequests
.head
; i
; i
= i
->next
) {
1614 const char *p
= NULL
;
1615 http
= static_cast<ClientHttpRequest
*>(i
->data
);
1617 ConnStateData
* conn
= http
->getConn();
1618 storeAppendPrintf(s
, "Connection: %p\n", conn
);
1622 storeAppendPrintf(s
, "\tFD %d, read %"PRId64
", wrote %"PRId64
"\n", fd
,
1623 fd_table
[fd
].bytes_read
, fd_table
[fd
].bytes_written
);
1624 storeAppendPrintf(s
, "\tFD desc: %s\n", fd_table
[fd
].desc
);
1625 storeAppendPrintf(s
, "\tin: buf %p, offset %ld, size %ld\n",
1626 conn
->in
.buf
, (long int) conn
->in
.notYetUsed
, (long int) conn
->in
.allocatedSize
);
1627 storeAppendPrintf(s
, "\tpeer: %s:%d\n",
1628 conn
->peer
.NtoA(buf
,MAX_IPSTRLEN
),
1629 conn
->peer
.GetPort());
1630 storeAppendPrintf(s
, "\tme: %s:%d\n",
1631 conn
->me
.NtoA(buf
,MAX_IPSTRLEN
),
1632 conn
->me
.GetPort());
1633 storeAppendPrintf(s
, "\tnrequests: %d\n",
1637 storeAppendPrintf(s
, "uri %s\n", http
->uri
);
1638 storeAppendPrintf(s
, "logType %s\n", log_tags
[http
->logType
]);
1639 storeAppendPrintf(s
, "out.offset %ld, out.size %lu\n",
1640 (long int) http
->out
.offset
, (unsigned long int) http
->out
.size
);
1641 storeAppendPrintf(s
, "req_sz %ld\n", (long int) http
->req_sz
);
1642 e
= http
->storeEntry();
1643 storeAppendPrintf(s
, "entry %p/%s\n", e
, e
? e
->getMD5Text() : "N/A");
1645 /* Not a member anymore */
1646 e
= http
->old_entry
;
1647 storeAppendPrintf(s
, "old_entry %p/%s\n", e
, e
? e
->getMD5Text() : "N/A");
1650 storeAppendPrintf(s
, "start %ld.%06d (%f seconds ago)\n",
1651 (long int) http
->start_time
.tv_sec
,
1652 (int) http
->start_time
.tv_usec
,
1653 tvSubDsec(http
->start_time
, current_time
));
1655 if (http
->request
->auth_user_request
)
1656 p
= http
->request
->auth_user_request
->username();
1657 else if (http
->request
->extacl_user
.defined()) {
1658 p
= http
->request
->extacl_user
.termedBuf();
1661 if (!p
&& (conn
!= NULL
&& conn
->rfc931
[0]))
1666 if (!p
&& conn
!= NULL
)
1667 p
= sslGetUserEmail(fd_table
[conn
->fd
].ssl
);
1674 storeAppendPrintf(s
, "username %s\n", p
);
1678 storeAppendPrintf(s
, "delay_pool %d\n", DelayId::DelayClient(http
).pool());
1682 storeAppendPrintf(s
, "\n");
1688 * urgh, i don't like these, but they do cut the amount of code down immensely
1691 #define GRAPH_PER_MIN(Y) \
1692 for (i=0;i<(N_COUNT_HIST-2);i++) { \
1693 dt = tvSubDsec(CountHist[i+1].timestamp, CountHist[i].timestamp); \
1696 storeAppendPrintf(e, "%lu,%0.2f:", \
1697 CountHist[i].timestamp.tv_sec, \
1698 ((CountHist[i].Y - CountHist[i+1].Y) / dt)); \
1701 #define GRAPH_PER_HOUR(Y) \
1702 for (i=0;i<(N_COUNT_HOUR_HIST-2);i++) { \
1703 dt = tvSubDsec(CountHourHist[i+1].timestamp, CountHourHist[i].timestamp); \
1706 storeAppendPrintf(e, "%lu,%0.2f:", \
1707 CountHourHist[i].timestamp.tv_sec, \
1708 ((CountHourHist[i].Y - CountHourHist[i+1].Y) / dt)); \
1711 #define GRAPH_TITLE(X,Y) storeAppendPrintf(e,"%s\t%s\t",X,Y);
1712 #define GRAPH_END storeAppendPrintf(e,"\n");
1714 #define GENGRAPH(X,Y,Z) \
1721 statGraphDump(StoreEntry
* e
)
1726 GENGRAPH(client_http
.requests
, "client_http.requests", "Client HTTP requests/sec");
1727 GENGRAPH(client_http
.hits
, "client_http.hits", "Client HTTP hits/sec");
1728 GENGRAPH(client_http
.errors
, "client_http.errors", "Client HTTP errors/sec");
1729 GENGRAPH(client_http
.kbytes_in
.kb
, "client_http.kbytes_in", "Client HTTP kbytes_in/sec");
1730 GENGRAPH(client_http
.kbytes_out
.kb
, "client_http.kbytes_out", "Client HTTP kbytes_out/sec");
1732 /* XXX todo: http median service times */
1734 GENGRAPH(server
.all
.requests
, "server.all.requests", "Server requests/sec");
1735 GENGRAPH(server
.all
.errors
, "server.all.errors", "Server errors/sec");
1736 GENGRAPH(server
.all
.kbytes_in
.kb
, "server.all.kbytes_in", "Server total kbytes_in/sec");
1737 GENGRAPH(server
.all
.kbytes_out
.kb
, "server.all.kbytes_out", "Server total kbytes_out/sec");
1739 GENGRAPH(server
.http
.requests
, "server.http.requests", "Server HTTP requests/sec");
1740 GENGRAPH(server
.http
.errors
, "server.http.errors", "Server HTTP errors/sec");
1741 GENGRAPH(server
.http
.kbytes_in
.kb
, "server.http.kbytes_in", "Server HTTP kbytes_in/sec");
1742 GENGRAPH(server
.http
.kbytes_out
.kb
, "server.http.kbytes_out", "Server HTTP kbytes_out/sec");
1744 GENGRAPH(server
.ftp
.requests
, "server.ftp.requests", "Server FTP requests/sec");
1745 GENGRAPH(server
.ftp
.errors
, "server.ftp.errors", "Server FTP errors/sec");
1746 GENGRAPH(server
.ftp
.kbytes_in
.kb
, "server.ftp.kbytes_in", "Server FTP kbytes_in/sec");
1747 GENGRAPH(server
.ftp
.kbytes_out
.kb
, "server.ftp.kbytes_out", "Server FTP kbytes_out/sec");
1749 GENGRAPH(server
.other
.requests
, "server.other.requests", "Server other requests/sec");
1750 GENGRAPH(server
.other
.errors
, "server.other.errors", "Server other errors/sec");
1751 GENGRAPH(server
.other
.kbytes_in
.kb
, "server.other.kbytes_in", "Server other kbytes_in/sec");
1752 GENGRAPH(server
.other
.kbytes_out
.kb
, "server.other.kbytes_out", "Server other kbytes_out/sec");
1754 GENGRAPH(icp
.pkts_sent
, "icp.pkts_sent", "ICP packets sent/sec");
1755 GENGRAPH(icp
.pkts_recv
, "icp.pkts_recv", "ICP packets received/sec");
1756 GENGRAPH(icp
.kbytes_sent
.kb
, "icp.kbytes_sent", "ICP kbytes_sent/sec");
1757 GENGRAPH(icp
.kbytes_recv
.kb
, "icp.kbytes_recv", "ICP kbytes_received/sec");
1759 /* XXX todo: icp median service times */
1760 /* XXX todo: dns median service times */
1762 GENGRAPH(unlink
.requests
, "unlink.requests", "Cache File unlink requests/sec");
1763 GENGRAPH(page_faults
, "page_faults", "System Page Faults/sec");
1764 GENGRAPH(select_loops
, "select_loops", "System Select Loop calls/sec");
1765 GENGRAPH(cputime
, "cputime", "CPU utilisation");
1768 #endif /* STAT_GRAPHS */
1771 statMemoryAccounted(void)
1773 return memPoolsTotalAllocated();