]> git.ipfire.org Git - thirdparty/squid.git/blame - src/stat.cc
Changed storeClientCopy() calls to copy directly into the bloom filter
[thirdparty/squid.git] / src / stat.cc
CommitLineData
e5f6c5c2 1
30a4f2a8 2/*
071a3ae7 3 * $Id: stat.cc,v 1.231 1998/04/09 21:32:11 wessels Exp $
30a4f2a8 4 *
5 * DEBUG: section 18 Cache Manager Statistics
6 * AUTHOR: Harvest Derived
7 *
42c04c16 8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
30a4f2a8 9 * --------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by
14 * the National Science Foundation.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 *
30 */
019dd986 31
32/*
30a4f2a8 33 * Copyright (c) 1994, 1995. All rights reserved.
34 *
35 * The Harvest software was developed by the Internet Research Task
36 * Force Research Group on Resource Discovery (IRTF-RD):
37 *
38 * Mic Bowman of Transarc Corporation.
39 * Peter Danzig of the University of Southern California.
40 * Darren R. Hardy of the University of Colorado at Boulder.
41 * Udi Manber of the University of Arizona.
42 * Michael F. Schwartz of the University of Colorado at Boulder.
43 * Duane Wessels of the University of Colorado at Boulder.
44 *
45 * This copyright notice applies to software in the Harvest
46 * ``src/'' directory only. Users should consult the individual
47 * copyright notices in the ``components/'' subdirectories for
48 * copyright information about other software bundled with the
49 * Harvest source code distribution.
50 *
51 * TERMS OF USE
52 *
53 * The Harvest software may be used and re-distributed without
54 * charge, provided that the software origin and research team are
55 * cited in any use of the system. Most commonly this is
56 * accomplished by including a link to the Harvest Home Page
57 * (http://harvest.cs.colorado.edu/) from the query page of any
58 * Broker you deploy, as well as in the query result pages. These
59 * links are generated automatically by the standard Broker
60 * software distribution.
61 *
62 * The Harvest software is provided ``as is'', without express or
63 * implied warranty, and with no support nor obligation to assist
64 * in its use, correction, modification or enhancement. We assume
65 * no liability with respect to the infringement of copyrights,
66 * trade secrets, or any patents, and are not responsible for
67 * consequential damages. Proper use of the Harvest software is
68 * entirely the responsibility of the user.
69 *
70 * DERIVATIVE WORKS
71 *
72 * Users may make derivative works from the Harvest software, subject
73 * to the following constraints:
74 *
75 * - You must include the above copyright notice and these
76 * accompanying paragraphs in all forms of derivative works,
77 * and any documentation and other materials related to such
78 * distribution and use acknowledge that the software was
79 * developed at the above institutions.
80 *
81 * - You must notify IRTF-RD regarding your distribution of
82 * the derivative work.
83 *
84 * - You must clearly notify users that your are distributing
85 * a modified version and not the original Harvest software.
86 *
87 * - Any derivative product is also subject to these copyright
88 * and use restrictions.
89 *
90 * Note that the Harvest software is NOT in the public domain. We
91 * retain copyright, as specified above.
92 *
93 * HISTORY OF FREE SOFTWARE STATUS
94 *
95 * Originally we required sites to license the software in cases
96 * where they were going to build commercial products/services
97 * around Harvest. In June 1995 we changed this policy. We now
98 * allow people to use the core Harvest software (the code found in
99 * the Harvest ``src/'' directory) for free. We made this change
100 * in the interest of encouraging the widest possible deployment of
101 * the technology. The Harvest software is really a reference
102 * implementation of a set of protocols and formats, some of which
103 * we intend to standardize. We encourage commercial
104 * re-implementations of code complying to this set of standards.
019dd986 105 */
ed43818f 106
234967c9 107
44a47c6e 108#include "squid.h"
090089c4 109
67508012 110/* LOCALS */
f5b8bbc4 111static const char *describeStatuses(const StoreEntry *);
112static const char *describeFlags(const StoreEntry *);
113static const char *describeTimestamps(const StoreEntry *);
f2908497 114static void statAvgTick(void *notused);
a0f32775 115static void statAvgDump(StoreEntry *, int minutes, int hours);
01aebf31 116#if STAT_GRAPHS
117static void statGraphDump(StoreEntry *);
118#endif
12cf1be2 119static void statCountersInit(StatCounters *);
1d803566 120static void statCountersInitSpecial(StatCounters *);
12cf1be2 121static void statCountersClean(StatCounters *);
2ac76861 122static void statCountersCopy(StatCounters * dest, const StatCounters * orig);
b87b92fb 123static double statMedianSvc(int, int);
ed7f5615 124static OBJH stat_io_get;
125static OBJH stat_objects_get;
126static OBJH stat_vmobjects_get;
127static OBJH info_get;
128static OBJH statFiledescriptors;
071a3ae7 129static OBJH statCountersDump;
a1e927f6 130static OBJH statPeerSelect;
26b164ac 131static OBJH statDigestBlob;
ed7f5615 132static OBJH statAvg5min;
45eb7f49 133static OBJH statAvg60min;
e9b5ead4 134static OBJH statUtilization;
20882fb1 135
20882fb1 136#ifdef XMALLOC_STATISTICS
f5b8bbc4 137static void info_get_mallstat(int, int, StoreEntry *);
20882fb1 138#endif
30a4f2a8 139
a9113eb0 140StatCounters CountHist[N_COUNT_HIST];
d5649d9f 141static int NCountHist = 0;
a0f32775 142static StatCounters CountHourHist[N_COUNT_HOUR_HIST];
143static int NCountHourHist = 0;
144
5e29a294 145static void
e9b5ead4 146statUtilization(StoreEntry * e)
a0f32775 147{
148 storeAppendPrintf(e, "Cache Utilisation:\n");
149 storeAppendPrintf(e, "\n");
150 storeAppendPrintf(e, "Last 5 minutes:\n");
151 if (NCountHist >= 5)
152 statAvgDump(e, 5, 0);
153 else
154 storeAppendPrintf(e, "(no values recorded yet)\n");
155 storeAppendPrintf(e, "\n");
156 storeAppendPrintf(e, "Last 15 minutes:\n");
157 if (NCountHist >= 15)
158 statAvgDump(e, 15, 0);
159 else
160 storeAppendPrintf(e, "(no values recorded yet)\n");
161 storeAppendPrintf(e, "\n");
162 storeAppendPrintf(e, "Last hour:\n");
163 if (NCountHist >= 60)
164 statAvgDump(e, 60, 0);
165 else
166 storeAppendPrintf(e, "(no values recorded yet)\n");
167 storeAppendPrintf(e, "\n");
168 storeAppendPrintf(e, "Last 8 hours:\n");
169 if (NCountHourHist >= 8)
170 statAvgDump(e, 0, 8);
171 else
172 storeAppendPrintf(e, "(no values recorded yet)\n");
173 storeAppendPrintf(e, "\n");
174 storeAppendPrintf(e, "Last day:\n");
175 if (NCountHourHist >= 24)
176 statAvgDump(e, 0, 24);
177 else
178 storeAppendPrintf(e, "(no values recorded yet)\n");
179 storeAppendPrintf(e, "\n");
180 storeAppendPrintf(e, "Last 3 days:\n");
181 if (NCountHourHist >= 72)
182 statAvgDump(e, 0, 72);
183 else
184 storeAppendPrintf(e, "(no values recorded yet)\n");
185 storeAppendPrintf(e, "\n");
186 storeAppendPrintf(e, "Totals since cache startup:\n");
187 statCountersDump(e);
188}
f2908497 189
5e29a294 190static void
b8d8561b 191stat_io_get(StoreEntry * sentry)
30a4f2a8 192{
193 int i;
194
15576b6a 195 storeAppendPrintf(sentry, "HTTP I/O\n");
196 storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Http.reads);
197 storeAppendPrintf(sentry, "deferred reads: %d (%d%%)\n",
30a4f2a8 198 IOStats.Http.reads_deferred,
199 percent(IOStats.Http.reads_deferred, IOStats.Http.reads));
15576b6a 200 storeAppendPrintf(sentry, "Read Histogram:\n");
30a4f2a8 201 for (i = 0; i < 16; i++) {
15576b6a 202 storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
30a4f2a8 203 i ? (1 << (i - 1)) + 1 : 1,
204 1 << i,
205 IOStats.Http.read_hist[i],
206 percent(IOStats.Http.read_hist[i], IOStats.Http.reads));
207 }
208
15576b6a 209 storeAppendPrintf(sentry, "\n");
210 storeAppendPrintf(sentry, "FTP I/O\n");
211 storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Ftp.reads);
212 storeAppendPrintf(sentry, "deferred reads: %d (%d%%)\n",
30a4f2a8 213 IOStats.Ftp.reads_deferred,
214 percent(IOStats.Ftp.reads_deferred, IOStats.Ftp.reads));
15576b6a 215 storeAppendPrintf(sentry, "Read Histogram:\n");
30a4f2a8 216 for (i = 0; i < 16; i++) {
15576b6a 217 storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
30a4f2a8 218 i ? (1 << (i - 1)) + 1 : 1,
219 1 << i,
220 IOStats.Ftp.read_hist[i],
221 percent(IOStats.Ftp.read_hist[i], IOStats.Ftp.reads));
222 }
223
15576b6a 224 storeAppendPrintf(sentry, "\n");
225 storeAppendPrintf(sentry, "Gopher I/O\n");
226 storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Gopher.reads);
227 storeAppendPrintf(sentry, "deferred reads: %d (%d%%)\n",
56fa4cad 228 IOStats.Gopher.reads_deferred,
229 percent(IOStats.Gopher.reads_deferred, IOStats.Gopher.reads));
15576b6a 230 storeAppendPrintf(sentry, "Read Histogram:\n");
56fa4cad 231 for (i = 0; i < 16; i++) {
15576b6a 232 storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
56fa4cad 233 i ? (1 << (i - 1)) + 1 : 1,
234 1 << i,
235 IOStats.Gopher.read_hist[i],
236 percent(IOStats.Gopher.read_hist[i], IOStats.Gopher.reads));
237 }
238
15576b6a 239 storeAppendPrintf(sentry, "\n");
240 storeAppendPrintf(sentry, "WAIS I/O\n");
241 storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Wais.reads);
242 storeAppendPrintf(sentry, "deferred reads: %d (%d%%)\n",
56fa4cad 243 IOStats.Wais.reads_deferred,
244 percent(IOStats.Wais.reads_deferred, IOStats.Wais.reads));
15576b6a 245 storeAppendPrintf(sentry, "Read Histogram:\n");
56fa4cad 246 for (i = 0; i < 16; i++) {
15576b6a 247 storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
56fa4cad 248 i ? (1 << (i - 1)) + 1 : 1,
249 1 << i,
250 IOStats.Wais.read_hist[i],
251 percent(IOStats.Wais.read_hist[i], IOStats.Wais.reads));
252 }
090089c4 253}
254
0ee4272b 255static const char *
fe4e214f 256describeStatuses(const StoreEntry * entry)
d1a43e28 257{
258 LOCAL_ARRAY(char, buf, 256);
56878878 259 snprintf(buf, 256, "%-13s %-13s %-12s %-12s",
d1a43e28 260 storeStatusStr[entry->store_status],
261 memStatusStr[entry->mem_status],
262 swapStatusStr[entry->swap_status],
263 pingStatusStr[entry->ping_status]);
264 return buf;
265}
266
0ee4272b 267static const char *
fe4e214f 268describeFlags(const StoreEntry * entry)
d1a43e28 269{
270 LOCAL_ARRAY(char, buf, 256);
271 int flags = (int) entry->flag;
272 char *t;
273 buf[0] = '\0';
79a15e0a 274 if (EBIT_TEST(flags, DELAY_SENDING))
d1a43e28 275 strcat(buf, "DS,");
79a15e0a 276 if (EBIT_TEST(flags, RELEASE_REQUEST))
d1a43e28 277 strcat(buf, "RL,");
79a15e0a 278 if (EBIT_TEST(flags, REFRESH_REQUEST))
d1a43e28 279 strcat(buf, "RF,");
79a15e0a 280 if (EBIT_TEST(flags, ENTRY_CACHABLE))
d1a43e28 281 strcat(buf, "EC,");
79a15e0a 282 if (EBIT_TEST(flags, ENTRY_DISPATCHED))
d1a43e28 283 strcat(buf, "ED,");
79a15e0a 284 if (EBIT_TEST(flags, KEY_PRIVATE))
d1a43e28 285 strcat(buf, "KP,");
79a15e0a 286 if (EBIT_TEST(flags, HIERARCHICAL))
d1a43e28 287 strcat(buf, "HI,");
79a15e0a 288 if (EBIT_TEST(flags, ENTRY_NEGCACHED))
d1a43e28 289 strcat(buf, "NG,");
d1a43e28 290 if ((t = strrchr(buf, ',')))
291 *t = '\0';
292 return buf;
293}
294
0ee4272b 295static const char *
fe4e214f 296describeTimestamps(const StoreEntry * entry)
d1a43e28 297{
298 LOCAL_ARRAY(char, buf, 256);
56878878 299 snprintf(buf, 256, "LV:%-9d LU:%-9d LM:%-9d EX:%-9d",
d1a43e28 300 (int) entry->timestamp,
301 (int) entry->lastref,
302 (int) entry->lastmod,
303 (int) entry->expires);
304 return buf;
305}
306
090089c4 307/* process objects list */
b8d8561b 308static void
6684fec0 309statObjects(StoreEntry * sentry, int vm_or_not)
090089c4 310{
09610784 311 StoreEntry *entry = NULL;
f09f5b26 312 StoreEntry *next = NULL;
d1a43e28 313 MemObject *mem;
090089c4 314 int N = 0;
637ed800 315 int i;
316 struct _store_client *sc;
f09f5b26 317 next = (StoreEntry *) hash_first(store_table);
a200bbd2 318 while ((entry = next) != NULL) {
f09f5b26 319 next = (StoreEntry *) hash_next(store_table);
d1a43e28 320 mem = entry->mem_obj;
321 if (vm_or_not && mem == NULL)
090089c4 322 continue;
323 if ((++N & 0xFF) == 0) {
22f3fd98 324 debug(18, 3) ("statObjects: Processed %d objects...\n", N);
090089c4 325 }
438fc1e3 326 storeBuffer(sentry);
24ffafb4 327 storeAppendPrintf(sentry, "KEY %s\n", storeKeyText(entry->key));
2ac237e2 328 if (mem)
329 storeAppendPrintf(sentry, "\t%s %s\n",
785c2dc3 330 RequestMethodStr[mem->method], mem->log_url);
637ed800 331 storeAppendPrintf(sentry, "\t%s\n", describeStatuses(entry));
332 storeAppendPrintf(sentry, "\t%s\n", describeFlags(entry));
333 storeAppendPrintf(sentry, "\t%s\n", describeTimestamps(entry));
334 storeAppendPrintf(sentry, "\t%d locks, %d clients, %d refs\n",
335 (int) entry->lock_count,
336 storePendingNClients(entry),
337 (int) entry->refcount);
338 storeAppendPrintf(sentry, "\tSwap File %#08X\n",
339 entry->swap_file_number);
340 if (mem == NULL)
341 continue;
342 storeAppendPrintf(sentry, "\tinmem_lo: %d\n", (int) mem->inmem_lo);
343 storeAppendPrintf(sentry, "\tinmem_hi: %d\n", (int) mem->inmem_hi);
344 storeAppendPrintf(sentry, "\tswapout: %d bytes done, %d queued, FD %d\n",
5f6ac48b 345 (int) mem->swapout.done_offset,
346 (int) mem->swapout.queue_offset,
637ed800 347 mem->swapout.fd);
348 for (i = 0; i < mem->nclients; i++) {
349 sc = &mem->clients[i];
350 if (sc->callback_data == NULL)
351 continue;
352 storeAppendPrintf(sentry, "\tClient #%d\n", i);
353 storeAppendPrintf(sentry, "\t\tcopy_offset: %d\n",
354 (int) sc->copy_offset);
355 storeAppendPrintf(sentry, "\t\tseen_offset: %d\n",
356 (int) sc->seen_offset);
357 storeAppendPrintf(sentry, "\t\tcopy_size: %d\n",
358 (int) sc->copy_size);
359 storeAppendPrintf(sentry, "\t\tswapin_fd: %d\n",
360 (int) sc->swapin_fd);
361 }
24ffafb4 362 storeAppendPrintf(sentry, "\n");
438fc1e3 363 storeBufferFlush(sentry);
090089c4 364 }
090089c4 365}
366
5e29a294 367static void
603a02fd 368stat_objects_get(StoreEntry * e)
090089c4 369{
603a02fd 370 statObjects(e, 0);
6684fec0 371}
090089c4 372
5e29a294 373static void
603a02fd 374stat_vmobjects_get(StoreEntry * e)
6684fec0 375{
603a02fd 376 statObjects(e, 1);
090089c4 377}
378
0a0bf5db 379#ifdef XMALLOC_STATISTICS
b8d8561b 380static void
0a0bf5db 381info_get_mallstat(int size, int number, StoreEntry * sentry)
30a4f2a8 382{
30a4f2a8 383 if (number > 0)
15576b6a 384 storeAppendPrintf(sentry, "\t%d = %d\n", size, number);
30a4f2a8 385}
386#endif
090089c4 387
0ee4272b 388static const char *
f1dc9b30 389fdRemoteAddr(const fde * f)
d51e52f5 390{
95d659f0 391 LOCAL_ARRAY(char, buf, 32);
4f92c80c 392 if (f->type != FD_SOCKET)
393 return null_string;
042461c3 394 snprintf(buf, 32, "%s.%d", f->ipaddr, (int) f->remote_port);
d2af9477 395 return buf;
d51e52f5 396}
397
5e29a294 398static void
b8d8561b 399statFiledescriptors(StoreEntry * sentry)
d51e52f5 400{
401 int i;
f1dc9b30 402 fde *f;
15576b6a 403 storeAppendPrintf(sentry, "Active file descriptors:\n");
404 storeAppendPrintf(sentry, "%-4s %-6s %-4s %-7s %-7s %-21s %s\n",
d51e52f5 405 "File",
406 "Type",
d51e52f5 407 "Tout",
4f92c80c 408 "Nread",
409 "Nwrite",
d51e52f5 410 "Remote Address",
411 "Description");
15576b6a 412 storeAppendPrintf(sentry, "---- ------ ---- ------- ------- --------------------- ------------------------------\n");
e83892e9 413 for (i = 0; i < Squid_MaxFD; i++) {
429fdbec 414 f = &fd_table[i];
5c5783a2 415 if (!f->open)
d51e52f5 416 continue;
15576b6a 417 storeAppendPrintf(sentry, "%4d %-6.6s %4d %7d %7d %-21s %s\n",
d2af9477 418 i,
22f5d1ca 419 fdTypeStr[f->type],
5f6ac48b 420 f->timeout_handler ? (int) (f->timeout - squid_curtime) / 60 : 0,
4f92c80c 421 f->bytes_read,
422 f->bytes_written,
423 fdRemoteAddr(f),
424 f->desc);
d51e52f5 425 }
d51e52f5 426}
427
5e29a294 428static void
03eb2f01 429info_get(StoreEntry * sentry)
090089c4 430{
090089c4 431 struct rusage rusage;
f2908497 432 double cputime;
433 double runtime;
88738790 434#if HAVE_MSTATS && HAVE_GNUMALLOC_H
435 struct mstats ms;
436#elif HAVE_MALLINFO
090089c4 437 struct mallinfo mp;
88738790 438 int t;
090089c4 439#endif
440
f2908497 441 runtime = tvSubDsec(squid_start, current_time);
442 if (runtime == 0.0)
443 runtime = 1.0;
15576b6a 444 storeAppendPrintf(sentry, "Squid Object Cache: Version %s\n",
d51e52f5 445 version_string);
15576b6a 446 storeAppendPrintf(sentry, "Start Time:\t%s\n",
f2908497 447 mkrfc1123(squid_start.tv_sec));
15576b6a 448 storeAppendPrintf(sentry, "Current Time:\t%s\n",
f2908497 449 mkrfc1123(current_time.tv_sec));
15576b6a 450 storeAppendPrintf(sentry, "Connection information for %s:\n",
d51e52f5 451 appname);
15576b6a 452 storeAppendPrintf(sentry, "\tNumber of HTTP requests received:\t%u\n",
f2908497 453 Counter.client_http.requests);
15576b6a 454 storeAppendPrintf(sentry, "\tNumber of ICP messages received:\t%u\n",
f2908497 455 Counter.icp.pkts_recv);
15576b6a 456 storeAppendPrintf(sentry, "\tNumber of ICP messages sent:\t%u\n",
f2908497 457 Counter.icp.pkts_sent);
2e8e29b8 458 storeAppendPrintf(sentry, "\tNumber of queued ICP replies:\t%u\n",
459 Counter.icp.replies_queued);
15576b6a 460 storeAppendPrintf(sentry, "\tRequest failure ratio:\t%5.2f%%\n",
88aad2e5 461 request_failure_ratio);
f2908497 462
15576b6a 463 storeAppendPrintf(sentry, "\tHTTP requests per minute:\t%.1f\n",
f2908497 464 Counter.client_http.requests / (runtime / 60.0));
15576b6a 465 storeAppendPrintf(sentry, "\tICP messages per minute:\t%.1f\n",
f2908497 466 (Counter.icp.pkts_sent + Counter.icp.pkts_recv) / (runtime / 60.0));
15576b6a 467 storeAppendPrintf(sentry, "\tSelect loop called: %d times, %0.3f ms avg\n",
f2908497 468 Counter.select_loops, 1000.0 * runtime / Counter.select_loops);
090089c4 469
15576b6a 470 storeAppendPrintf(sentry, "Cache information for %s:\n",
30a4f2a8 471 appname);
15576b6a 472 storeAppendPrintf(sentry, "\tStorage Swap size:\t%d KB\n",
c932b107 473 store_swap_size);
15576b6a 474 storeAppendPrintf(sentry, "\tStorage Mem size:\t%d KB\n",
5f6ac48b 475 (int) (store_mem_size >> 10));
15576b6a 476 storeAppendPrintf(sentry, "\tStorage LRU Expiration Age:\t%6.2f days\n",
52cd89fd 477 (double) storeExpiredReferenceAge() / 86400.0);
15576b6a 478 storeAppendPrintf(sentry, "\tRequests given to unlinkd:\t%d\n",
f2908497 479 Counter.unlink.requests);
090089c4 480
b87b92fb 481 storeAppendPrintf(sentry, "Median Service Times (seconds) 5 min 60 min:\n");
482 storeAppendPrintf(sentry, "\tHTTP Requests (All): %8.5f %8.5f\n",
483 statMedianSvc(5, MEDIAN_HTTP) / 1000.0,
484 statMedianSvc(60, MEDIAN_HTTP) / 1000.0);
485 storeAppendPrintf(sentry, "\tCache Misses: %8.5f %8.5f\n",
486 statMedianSvc(5, MEDIAN_MISS) / 1000.0,
487 statMedianSvc(60, MEDIAN_MISS) / 1000.0);
488 storeAppendPrintf(sentry, "\tCache Hits: %8.5f %8.5f\n",
489 statMedianSvc(5, MEDIAN_HIT) / 1000.0,
490 statMedianSvc(60, MEDIAN_HIT) / 1000.0);
491 storeAppendPrintf(sentry, "\tNot-Modified Replies: %8.5f %8.5f\n",
492 statMedianSvc(5, MEDIAN_NM) / 1000.0,
493 statMedianSvc(60, MEDIAN_NM) / 1000.0);
494 storeAppendPrintf(sentry, "\tDNS Lookups: %8.5f %8.5f\n",
495 statMedianSvc(5, MEDIAN_DNS) / 1000.0,
496 statMedianSvc(60, MEDIAN_DNS) / 1000.0);
497 storeAppendPrintf(sentry, "\tICP Queries: %8.5f %8.5f\n",
498 statMedianSvc(5, MEDIAN_ICP_QUERY) / 1000000.0,
499 statMedianSvc(60, MEDIAN_ICP_QUERY) / 1000000.0);
500
f2908497 501 squid_getrusage(&rusage);
502 cputime = rusage_cputime(&rusage);
15576b6a 503 storeAppendPrintf(sentry, "Resource usage for %s:\n", appname);
504 storeAppendPrintf(sentry, "\tUP Time:\t%.3f seconds\n", runtime);
505 storeAppendPrintf(sentry, "\tCPU Time:\t%.3f seconds\n", cputime);
506 storeAppendPrintf(sentry, "\tCPU Usage:\t%.2f%%\n",
f2908497 507 dpercent(cputime, runtime));
5f6ac48b 508 storeAppendPrintf(sentry, "\tMaximum Resident Size: %d KB\n",
f2908497 509 rusage_maxrss(&rusage));
5f6ac48b 510 storeAppendPrintf(sentry, "\tPage faults with physical i/o: %d\n",
f2908497 511 rusage_pagefaults(&rusage));
090089c4 512
88738790 513#if HAVE_MSTATS && HAVE_GNUMALLOC_H
514 ms = mstats();
15576b6a 515 storeAppendPrintf(sentry, "Memory usage for %s via mstats():\n",
88738790 516 appname);
15576b6a 517 storeAppendPrintf(sentry, "\tTotal space in arena: %6d KB\n",
88738790 518 ms.bytes_total >> 10);
15576b6a 519 storeAppendPrintf(sentry, "\tTotal free: %6d KB %d%%\n",
88738790 520 ms.bytes_free >> 10, percent(ms.bytes_free, ms.bytes_total));
521#elif HAVE_MALLINFO
090089c4 522 mp = mallinfo();
15576b6a 523 storeAppendPrintf(sentry, "Memory usage for %s via mallinfo():\n",
d51e52f5 524 appname);
15576b6a 525 storeAppendPrintf(sentry, "\tTotal space in arena: %6d KB\n",
b560dd20 526 mp.arena >> 10);
15576b6a 527 storeAppendPrintf(sentry, "\tOrdinary blocks: %6d KB %6d blks\n",
30a4f2a8 528 mp.uordblks >> 10, mp.ordblks);
15576b6a 529 storeAppendPrintf(sentry, "\tSmall blocks: %6d KB %6d blks\n",
30a4f2a8 530 mp.usmblks >> 10, mp.smblks);
15576b6a 531 storeAppendPrintf(sentry, "\tHolding blocks: %6d KB %6d blks\n",
30a4f2a8 532 mp.hblkhd >> 10, mp.hblks);
15576b6a 533 storeAppendPrintf(sentry, "\tFree Small blocks: %6d KB\n",
30a4f2a8 534 mp.fsmblks >> 10);
15576b6a 535 storeAppendPrintf(sentry, "\tFree Ordinary blocks: %6d KB\n",
30a4f2a8 536 mp.fordblks >> 10);
537 t = mp.uordblks + mp.usmblks + mp.hblkhd;
15576b6a 538 storeAppendPrintf(sentry, "\tTotal in use: %6d KB %d%%\n",
30a4f2a8 539 t >> 10, percent(t, mp.arena));
540 t = mp.fsmblks + mp.fordblks;
15576b6a 541 storeAppendPrintf(sentry, "\tTotal free: %6d KB %d%%\n",
30a4f2a8 542 t >> 10, percent(t, mp.arena));
46c883ed 543#if HAVE_EXT_MALLINFO
15576b6a 544 storeAppendPrintf(sentry, "\tmax size of small blocks:\t%d\n", mp.mxfast);
545 storeAppendPrintf(sentry, "\tnumber of small blocks in a holding block:\t%d\n",
090089c4 546 mp.nlblks);
15576b6a 547 storeAppendPrintf(sentry, "\tsmall block rounding factor:\t%d\n", mp.grain);
548 storeAppendPrintf(sentry, "\tspace (including overhead) allocated in ord. blks:\t%d\n"
090089c4 549 ,mp.uordbytes);
15576b6a 550 storeAppendPrintf(sentry, "\tnumber of ordinary blocks allocated:\t%d\n",
090089c4 551 mp.allocated);
15576b6a 552 storeAppendPrintf(sentry, "\tbytes used in maintaining the free tree:\t%d\n",
090089c4 553 mp.treeoverhead);
46c883ed 554#endif /* HAVE_EXT_MALLINFO */
50bc2565 555#endif /* HAVE_MALLINFO */
090089c4 556
15576b6a 557 storeAppendPrintf(sentry, "File descriptor usage for %s:\n", appname);
558 storeAppendPrintf(sentry, "\tMaximum number of file descriptors: %4d\n",
e83892e9 559 Squid_MaxFD);
15576b6a 560 storeAppendPrintf(sentry, "\tLargest file desc currently in use: %4d\n",
429fdbec 561 Biggest_FD);
15576b6a 562 storeAppendPrintf(sentry, "\tNumber of file desc currently in use: %4d\n",
88738790 563 Number_FD);
15576b6a 564 storeAppendPrintf(sentry, "\tAvailable number of file descriptors: %4d\n",
88738790 565 Squid_MaxFD - Number_FD);
15576b6a 566 storeAppendPrintf(sentry, "\tReserved number of file descriptors: %4d\n",
090089c4 567 RESERVED_FD);
090089c4 568
15576b6a 569 storeAppendPrintf(sentry, "Internal Data Structures:\n");
570 storeAppendPrintf(sentry, "\t%6d StoreEntries\n",
3f6c0fb2 571 memInUse(MEM_STOREENTRY));
15576b6a 572 storeAppendPrintf(sentry, "\t%6d StoreEntries with MemObjects\n",
3f6c0fb2 573 memInUse(MEM_MEMOBJECT));
15576b6a 574 storeAppendPrintf(sentry, "\t%6d StoreEntries with MemObject Data\n",
3f6c0fb2 575 memInUse(MEM_MEM_HDR));
15576b6a 576 storeAppendPrintf(sentry, "\t%6d Hot Object Cache Items\n",
59c4d35b 577 hot_obj_count);
30a4f2a8 578
579#if XMALLOC_STATISTICS
15576b6a 580 storeAppendPrintf(sentry, "Memory allocation statistics\n");
30a4f2a8 581 malloc_statistics(info_get_mallstat, sentry);
582#endif
090089c4 583}
584
a7c05555 585#define XAVG(X) (dt ? (double) (f->X - l->X) / dt : 0.0)
b8d8561b 586static void
a0f32775 587statAvgDump(StoreEntry * sentry, int minutes, int hours)
090089c4 588{
a7c05555 589 StatCounters *f;
590 StatCounters *l;
591 double dt;
592 double ct;
7ae52c25 593 double x;
a7c05555 594 assert(N_COUNT_HIST > 1);
a0f32775 595 assert(minutes > 0 || hours > 0);
a7c05555 596 f = &CountHist[0];
a0f32775 597 l = f;
598 if (minutes > 0 && hours == 0) {
599 /* checking minute readings ... */
600 if (minutes > N_COUNT_HIST - 1)
601 minutes = N_COUNT_HIST - 1;
602 l = &CountHist[minutes];
603 } else if (minutes == 0 && hours > 0) {
604 /* checking hour readings ... */
605 if (hours > N_COUNT_HOUR_HIST - 1)
606 hours = N_COUNT_HOUR_HIST - 1;
607 l = &CountHourHist[hours];
608 } else {
399e85ea 609 debug(18, 1) ("statAvgDump: Invalid args, minutes=%d, hours=%d\n",
610 minutes, hours);
a0f32775 611 return;
612 }
a7c05555 613 dt = tvSubDsec(l->timestamp, f->timestamp);
614 ct = f->cputime - l->cputime;
ee1679df 615
399e85ea 616 storeAppendPrintf(sentry, "sample_start_time = %d.%d (%s)\n",
5f6ac48b 617 (int) f->timestamp.tv_sec,
618 (int) f->timestamp.tv_usec,
a0f32775 619 mkrfc1123(f->timestamp.tv_sec));
399e85ea 620 storeAppendPrintf(sentry, "sample_end_time = %d.%d (%s)\n",
5f6ac48b 621 (int) l->timestamp.tv_sec,
622 (int) l->timestamp.tv_usec,
a0f32775 623 mkrfc1123(l->timestamp.tv_sec));
624
a7c05555 625 storeAppendPrintf(sentry, "client_http.requests = %f/sec\n",
626 XAVG(client_http.requests));
627 storeAppendPrintf(sentry, "client_http.hits = %f/sec\n",
628 XAVG(client_http.hits));
629 storeAppendPrintf(sentry, "client_http.errors = %f/sec\n",
630 XAVG(client_http.errors));
631 storeAppendPrintf(sentry, "client_http.kbytes_in = %f/sec\n",
632 XAVG(client_http.kbytes_in.kb));
633 storeAppendPrintf(sentry, "client_http.kbytes_out = %f/sec\n",
634 XAVG(client_http.kbytes_out.kb));
ee1679df 635
12cf1be2 636 x = statHistDeltaMedian(&l->client_http.all_svc_time,
ee1679df 637 &f->client_http.all_svc_time);
638 storeAppendPrintf(sentry, "client_http.all_median_svc_time = %f seconds\n",
639 x / 1000.0);
12cf1be2 640 x = statHistDeltaMedian(&l->client_http.miss_svc_time,
ee1679df 641 &f->client_http.miss_svc_time);
642 storeAppendPrintf(sentry, "client_http.miss_median_svc_time = %f seconds\n",
643 x / 1000.0);
12cf1be2 644 x = statHistDeltaMedian(&l->client_http.nm_svc_time,
ee1679df 645 &f->client_http.nm_svc_time);
646 storeAppendPrintf(sentry, "client_http.nm_median_svc_time = %f seconds\n",
647 x / 1000.0);
12cf1be2 648 x = statHistDeltaMedian(&l->client_http.hit_svc_time,
ee1679df 649 &f->client_http.hit_svc_time);
650 storeAppendPrintf(sentry, "client_http.hit_median_svc_time = %f seconds\n",
7ae52c25 651 x / 1000.0);
071a3ae7 652
a1e927f6 653#if SQUID_PEER_DIGEST
00485c29 654 storeAppendPrintf(sentry, "cd.msgs_sent = %f/sec\n",
655 XAVG(cd.msgs_sent));
656 storeAppendPrintf(sentry, "cd.msgs_recv = %f/sec\n",
657 XAVG(cd.msgs_recv));
658 storeAppendPrintf(sentry, "cd.kbytes_sent = %f/sec\n",
659 XAVG(cd.kbytes_sent.kb));
660 storeAppendPrintf(sentry, "cd.kbytes_recv = %f/sec\n",
661 XAVG(cd.kbytes_recv.kb));
a1e927f6 662 x = statHistDeltaMedian(&l->cd.client_svc_time,
663 &f->cd.client_svc_time);
664 storeAppendPrintf(sentry, "cd.client_median_svc_time = %f seconds\n",
665 x / 1000.0);
39edba21 666 x = statHistDeltaMedian(&l->cd.server_svc_time,
667 &f->cd.server_svc_time);
668 storeAppendPrintf(sentry, "cd.server_median_svc_time = %f seconds\n",
669 x / 1000.0);
a1e927f6 670 x = statHistDeltaMedian(&l->icp.client_svc_time,
671 &f->icp.client_svc_time);
672 storeAppendPrintf(sentry, "icp.client_median_svc_time = %f seconds\n",
673 x / 1000.0);
39edba21 674 x = statHistDeltaMedian(&l->icp.server_svc_time,
675 &f->icp.server_svc_time);
676 storeAppendPrintf(sentry, "icp.server_median_svc_time = %f seconds\n",
677 x / 1000.0);
a1e927f6 678#endif
ee1679df 679
a0f32775 680 storeAppendPrintf(sentry, "server.all.requests = %f/sec\n",
681 XAVG(server.all.requests));
682 storeAppendPrintf(sentry, "server.all.errors = %f/sec\n",
683 XAVG(server.all.errors));
684 storeAppendPrintf(sentry, "server.all.kbytes_in = %f/sec\n",
685 XAVG(server.all.kbytes_in.kb));
686 storeAppendPrintf(sentry, "server.all.kbytes_out = %f/sec\n",
687 XAVG(server.all.kbytes_out.kb));
688
689 storeAppendPrintf(sentry, "server.http.requests = %f/sec\n",
690 XAVG(server.http.requests));
691 storeAppendPrintf(sentry, "server.http.errors = %f/sec\n",
692 XAVG(server.http.errors));
693 storeAppendPrintf(sentry, "server.http.kbytes_in = %f/sec\n",
694 XAVG(server.http.kbytes_in.kb));
695 storeAppendPrintf(sentry, "server.http.kbytes_out = %f/sec\n",
696 XAVG(server.http.kbytes_out.kb));
697
698 storeAppendPrintf(sentry, "server.ftp.requests = %f/sec\n",
699 XAVG(server.ftp.requests));
700 storeAppendPrintf(sentry, "server.ftp.errors = %f/sec\n",
701 XAVG(server.ftp.errors));
702 storeAppendPrintf(sentry, "server.ftp.kbytes_in = %f/sec\n",
703 XAVG(server.ftp.kbytes_in.kb));
704 storeAppendPrintf(sentry, "server.ftp.kbytes_out = %f/sec\n",
705 XAVG(server.ftp.kbytes_out.kb));
706
707 storeAppendPrintf(sentry, "server.other.requests = %f/sec\n",
708 XAVG(server.other.requests));
709 storeAppendPrintf(sentry, "server.other.errors = %f/sec\n",
710 XAVG(server.other.errors));
711 storeAppendPrintf(sentry, "server.other.kbytes_in = %f/sec\n",
712 XAVG(server.other.kbytes_in.kb));
713 storeAppendPrintf(sentry, "server.other.kbytes_out = %f/sec\n",
714 XAVG(server.other.kbytes_out.kb));
ee1679df 715
a7c05555 716 storeAppendPrintf(sentry, "icp.pkts_sent = %f/sec\n",
717 XAVG(icp.pkts_sent));
718 storeAppendPrintf(sentry, "icp.pkts_recv = %f/sec\n",
719 XAVG(icp.pkts_recv));
071a3ae7 720 storeAppendPrintf(sentry, "icp.queries_sent = %f/sec\n",
721 XAVG(icp.queries_sent));
722 storeAppendPrintf(sentry, "icp.replies_sent = %f/sec\n",
723 XAVG(icp.replies_sent));
724 storeAppendPrintf(sentry, "icp.queries_recv = %f/sec\n",
725 XAVG(icp.queries_recv));
726 storeAppendPrintf(sentry, "icp.replies_recv = %f/sec\n",
727 XAVG(icp.replies_recv));
2e8e29b8 728 storeAppendPrintf(sentry, "icp.replies_queued = %f/sec\n",
729 XAVG(icp.replies_queued));
071a3ae7 730 storeAppendPrintf(sentry, "icp.query_timeouts = %f/sec\n",
731 XAVG(icp.query_timeouts));
a7c05555 732 storeAppendPrintf(sentry, "icp.kbytes_sent = %f/sec\n",
733 XAVG(icp.kbytes_sent.kb));
734 storeAppendPrintf(sentry, "icp.kbytes_recv = %f/sec\n",
735 XAVG(icp.kbytes_recv.kb));
071a3ae7 736 storeAppendPrintf(sentry, "icp.q_kbytes_sent = %f/sec\n",
737 XAVG(icp.q_kbytes_sent.kb));
738 storeAppendPrintf(sentry, "icp.r_kbytes_sent = %f/sec\n",
739 XAVG(icp.r_kbytes_sent.kb));
740 storeAppendPrintf(sentry, "icp.q_kbytes_recv = %f/sec\n",
741 XAVG(icp.q_kbytes_recv.kb));
742 storeAppendPrintf(sentry, "icp.r_kbytes_recv = %f/sec\n",
743 XAVG(icp.r_kbytes_recv.kb));
12cf1be2 744 x = statHistDeltaMedian(&l->icp.query_svc_time, &f->icp.query_svc_time);
ee1679df 745 storeAppendPrintf(sentry, "icp.query_median_svc_time = %f seconds\n",
746 x / 1000000.0);
12cf1be2 747 x = statHistDeltaMedian(&l->icp.reply_svc_time, &f->icp.reply_svc_time);
ee1679df 748 storeAppendPrintf(sentry, "icp.reply_median_svc_time = %f seconds\n",
7ae52c25 749 x / 1000000.0);
12cf1be2 750 x = statHistDeltaMedian(&l->dns.svc_time, &f->dns.svc_time);
9973e9fe 751 storeAppendPrintf(sentry, "dns.median_svc_time = %f seconds\n",
901d8c30 752 x / 1000.0);
a7c05555 753 storeAppendPrintf(sentry, "unlink.requests = %f/sec\n",
754 XAVG(unlink.requests));
755 storeAppendPrintf(sentry, "page_faults = %f/sec\n",
756 XAVG(page_faults));
757 storeAppendPrintf(sentry, "select_loops = %f/sec\n",
758 XAVG(select_loops));
759 storeAppendPrintf(sentry, "cpu_time = %f seconds\n", ct);
760 storeAppendPrintf(sentry, "wall_time = %f seconds\n", dt);
0e473d70 761 storeAppendPrintf(sentry, "cpu_usage = %f%%\n", dpercent(ct, dt));
090089c4 762}
763
b8d8561b 764void
a7c05555 765statInit(void)
090089c4 766{
090089c4 767 int i;
a7c05555 768 debug(18, 5) ("statInit: Initializing...\n");
0e473d70 769 for (i = 0; i < N_COUNT_HIST; i++)
12cf1be2 770 statCountersInit(&CountHist[i]);
a0f32775 771 for (i = 0; i < N_COUNT_HOUR_HIST; i++)
772 statCountersInit(&CountHourHist[i]);
12cf1be2 773 statCountersInit(&Counter);
a0f32775 774 eventAdd("statAvgTick", statAvgTick, NULL, COUNT_INTERVAL);
22f3fd98 775 cachemgrRegister("info",
776 "General Runtime Information",
777 info_get, 0);
778 cachemgrRegister("filedescriptors",
779 "Process Filedescriptor Allocation",
780 statFiledescriptors, 0);
781 cachemgrRegister("objects",
782 "All Cache Objects",
783 stat_objects_get, 0);
784 cachemgrRegister("vm_objects",
785 "In-Memory and In-Transit Objects",
786 stat_vmobjects_get, 0);
787 cachemgrRegister("io",
788 "Server-side network read() size histograms",
789 stat_io_get, 0);
790 cachemgrRegister("counters",
791 "Traffic and Resource Counters",
071a3ae7 792 statCountersDump, 0);
a1e927f6 793 cachemgrRegister("peer_select",
794 "Peer Selection Algorithms",
795 statPeerSelect, 0);
26b164ac 796 cachemgrRegister("digest_stats",
797 "Cache Digest and ICP blob",
798 statDigestBlob, 0);
22f3fd98 799 cachemgrRegister("5min",
800 "5 Minute Average of Counters",
801 statAvg5min, 0);
45eb7f49 802 cachemgrRegister("60min",
803 "60 Minute Average of Counters",
804 statAvg60min, 0);
e9b5ead4 805 cachemgrRegister("utilization",
806 "Cache Utilization",
807 statUtilization, 0);
01aebf31 808#if STAT_GRAPHS
809 cachemgrRegister("graph_variables",
810 "Display cache metrics graphically",
811 statGraphDump, 0);
812#endif
090089c4 813}
f2908497 814
f2908497 815static void
816statAvgTick(void *notused)
817{
d5649d9f 818 StatCounters *t = &CountHist[0];
819 StatCounters *p = &CountHist[1];
f2908497 820 StatCounters *c = &Counter;
821 struct rusage rusage;
a0f32775 822 eventAdd("statAvgTick", statAvgTick, NULL, COUNT_INTERVAL);
20903cac 823 squid_getrusage(&rusage);
824 c->page_faults = rusage_pagefaults(&rusage);
825 c->cputime = rusage_cputime(&rusage);
d5649d9f 826 c->timestamp = current_time;
12cf1be2 827 /* even if NCountHist is small, we already Init()ed the tail */
2ac76861 828 statCountersClean(CountHist + N_COUNT_HIST - 1);
dbfed404 829 xmemmove(p, t, (N_COUNT_HIST - 1) * sizeof(StatCounters));
12cf1be2 830 statCountersCopy(t, c);
d5649d9f 831 NCountHist++;
a0f32775 832
833 if ((NCountHist % COUNT_INTERVAL) == 0) {
834 /* we have an hours worth of readings. store previous hour */
835 StatCounters *p = &CountHourHist[0];
836 StatCounters *t = &CountHourHist[1];
837 StatCounters *c = &CountHist[N_COUNT_HIST];
838 xmemmove(p, t, (N_COUNT_HOUR_HIST - 1) * sizeof(StatCounters));
839 memcpy(t, c, sizeof(StatCounters));
840 NCountHourHist++;
841 }
20903cac 842}
843
12cf1be2 844static void
2ac76861 845statCountersInit(StatCounters * C)
20903cac 846{
12cf1be2 847 assert(C);
1d803566 848 memset(C, 0, sizeof(*C));
12cf1be2 849 C->timestamp = current_time;
1d803566 850 statCountersInitSpecial(C);
851}
852
853/* add special cases here as they arrive */
854static void
2ac76861 855statCountersInitSpecial(StatCounters * C)
1d803566 856{
12cf1be2 857 /*
858 * HTTP svc_time hist is kept in milli-seconds; max of 3 hours.
859 */
860 statHistLogInit(&C->client_http.all_svc_time, 300, 0.0, 3600000.0 * 3.0);
861 statHistLogInit(&C->client_http.miss_svc_time, 300, 0.0, 3600000.0 * 3.0);
862 statHistLogInit(&C->client_http.nm_svc_time, 300, 0.0, 3600000.0 * 3.0);
863 statHistLogInit(&C->client_http.hit_svc_time, 300, 0.0, 3600000.0 * 3.0);
864 /*
865 * ICP svc_time hist is kept in micro-seconds; max of 1 minute.
866 */
867 statHistLogInit(&C->icp.query_svc_time, 300, 0.0, 1000000.0 * 60.0);
868 statHistLogInit(&C->icp.reply_svc_time, 300, 0.0, 1000000.0 * 60.0);
869 /*
870 * DNS svc_time hist is kept in milli-seconds; max of 10 minutes.
871 */
872 statHistLogInit(&C->dns.svc_time, 300, 0.0, 60000.0 * 10.0);
df819896 873#if SQUID_PEER_DIGEST
a1e927f6 874 /*
875 * Digested and ICPed cvs times in milli-seconds; max of 3 hours.
876 */
df819896 877 statHistLogInit(&C->cd.client_svc_time, 300, 0.0, 3600000.0 * 30.0);
878 statHistLogInit(&C->icp.client_svc_time, 300, 0.0, 3600000.0 * 30.0);
39edba21 879 statHistLogInit(&C->cd.server_svc_time, 300, 0.0, 3600000.0 * 30.0);
880 statHistLogInit(&C->icp.server_svc_time, 300, 0.0, 3600000.0 * 30.0);
df819896 881#endif
0f5607d9 882}
883
12cf1be2 884/* add special cases here as they arrive */
5e29a294 885static void
2ac76861 886statCountersClean(StatCounters * C)
0f5607d9 887{
12cf1be2 888 assert(C);
889 statHistClean(&C->client_http.all_svc_time);
890 statHistClean(&C->client_http.miss_svc_time);
891 statHistClean(&C->client_http.nm_svc_time);
892 statHistClean(&C->client_http.hit_svc_time);
893 statHistClean(&C->icp.query_svc_time);
894 statHistClean(&C->icp.reply_svc_time);
895 statHistClean(&C->dns.svc_time);
df819896 896#if SQUID_PEER_DIGEST
897 statHistClean(&C->cd.client_svc_time);
898 statHistClean(&C->icp.client_svc_time);
39edba21 899 statHistClean(&C->cd.server_svc_time);
900 statHistClean(&C->icp.server_svc_time);
df819896 901#endif
a7c05555 902}
903
12cf1be2 904/* add special cases here as they arrive */
5e29a294 905static void
2ac76861 906statCountersCopy(StatCounters * dest, const StatCounters * orig)
45eb7f49 907{
12cf1be2 908 assert(dest && orig);
1d803566 909 /* this should take care of all the fields, but "special" ones */
12cf1be2 910 memcpy(dest, orig, sizeof(*dest));
1d803566 911 /* prepare space where to copy special entries */
912 statCountersInitSpecial(dest);
913 /* now handle special cases */
914 /* note: we assert that histogram capacities do not change */
12cf1be2 915 statHistCopy(&dest->client_http.all_svc_time, &orig->client_http.all_svc_time);
916 statHistCopy(&dest->client_http.miss_svc_time, &orig->client_http.miss_svc_time);
917 statHistCopy(&dest->client_http.nm_svc_time, &orig->client_http.nm_svc_time);
918 statHistCopy(&dest->client_http.hit_svc_time, &orig->client_http.hit_svc_time);
919 statHistCopy(&dest->icp.query_svc_time, &orig->icp.query_svc_time);
920 statHistCopy(&dest->icp.reply_svc_time, &orig->icp.reply_svc_time);
921 statHistCopy(&dest->dns.svc_time, &orig->dns.svc_time);
df819896 922#if SQUID_PEER_DIGEST
923 statHistCopy(&dest->cd.client_svc_time, &orig->cd.client_svc_time);
924 statHistCopy(&dest->icp.client_svc_time, &orig->icp.client_svc_time);
39edba21 925 statHistCopy(&dest->cd.server_svc_time, &orig->cd.server_svc_time);
926 statHistCopy(&dest->icp.server_svc_time, &orig->icp.server_svc_time);
df819896 927#endif
45eb7f49 928}
929
071a3ae7 930static void
931statCountersHistograms(StoreEntry *sentry)
932{
933 StatCounters *f = &Counter;
934#if TOO_MUCH_OUTPUT
935 storeAppendPrintf(sentry, "client_http.all_svc_time histogram:\n");
936 statHistDump(&f->client_http.all_svc_time, sentry, NULL);
937 storeAppendPrintf(sentry, "client_http.miss_svc_time histogram:\n");
938 statHistDump(&f->client_http.miss_svc_time, sentry, NULL);
939 storeAppendPrintf(sentry, "client_http.nm_svc_time histogram:\n");
940 statHistDump(&f->client_http.nm_svc_time, sentry, NULL);
941 storeAppendPrintf(sentry, "client_http.hit_svc_time histogram:\n");
942 statHistDump(&f->client_http.hit_svc_time, sentry, NULL);
943#endif
944#if SQUID_PEER_DIGEST
945 storeAppendPrintf(sentry, "\nicp.query_svc_time histogram:\n");
946 statHistDump(&f->icp.query_svc_time, sentry, NULL);
947 storeAppendPrintf(sentry, "\nicp.reply_svc_time histogram:\n");
948 statHistDump(&f->icp.reply_svc_time, sentry, NULL);
949 storeAppendPrintf(sentry, "\nicp.client_svc_time histogram:\n");
950 statHistDump(&f->icp.client_svc_time, sentry, NULL);
951 storeAppendPrintf(sentry, "\ncd.client_svc_time histogram:\n");
952 statHistDump(&f->cd.client_svc_time, sentry, NULL);
953#endif
954#if TOO_MUCH_OUTPUT
955 storeAppendPrintf(sentry, "icp.query_svc_time histogram:\n");
956 statHistDump(&f->icp.query_svc_time, sentry, NULL);
957 storeAppendPrintf(sentry, "icp.reply_svc_time histogram:\n");
958 statHistDump(&f->icp.reply_svc_time, sentry, NULL);
959 storeAppendPrintf(sentry, "dns.svc_time histogram:\n");
960 statHistDump(&f->dns.svc_time, sentry, NULL);
961#endif
962}
963
12cf1be2 964static void
965statCountersDump(StoreEntry * sentry)
7ae52c25 966{
12cf1be2 967 StatCounters *f = &Counter;
968 struct rusage rusage;
969 squid_getrusage(&rusage);
970 f->page_faults = rusage_pagefaults(&rusage);
971 f->cputime = rusage_cputime(&rusage);
972
a0f32775 973 storeAppendPrintf(sentry, "sample_time = %d.%d (%s)\n",
5f6ac48b 974 (int) f->timestamp.tv_sec,
975 (int) f->timestamp.tv_usec,
a0f32775 976 mkrfc1123(f->timestamp.tv_sec));
12cf1be2 977 storeAppendPrintf(sentry, "client_http.requests = %d\n",
978 f->client_http.requests);
979 storeAppendPrintf(sentry, "client_http.hits = %d\n",
980 f->client_http.hits);
981 storeAppendPrintf(sentry, "client_http.errors = %d\n",
982 f->client_http.errors);
983 storeAppendPrintf(sentry, "client_http.kbytes_in = %d\n",
984 (int) f->client_http.kbytes_in.kb);
985 storeAppendPrintf(sentry, "client_http.kbytes_out = %d\n",
986 (int) f->client_http.kbytes_out.kb);
0567f2a6 987
a0f32775 988 storeAppendPrintf(sentry, "server.all.requests = %d\n",
989 (int) f->server.all.requests);
990 storeAppendPrintf(sentry, "server.all.errors = %d\n",
991 (int) f->server.all.errors);
992 storeAppendPrintf(sentry, "server.all.kbytes_in = %d\n",
993 (int) f->server.all.kbytes_in.kb);
994 storeAppendPrintf(sentry, "server.all.kbytes_out = %d\n",
995 (int) f->server.all.kbytes_out.kb);
996
997 storeAppendPrintf(sentry, "server.http.requests = %d\n",
998 (int) f->server.http.requests);
999 storeAppendPrintf(sentry, "server.http.errors = %d\n",
1000 (int) f->server.http.errors);
1001 storeAppendPrintf(sentry, "server.http.kbytes_in = %d\n",
1002 (int) f->server.http.kbytes_in.kb);
1003 storeAppendPrintf(sentry, "server.http.kbytes_out = %d\n",
1004 (int) f->server.http.kbytes_out.kb);
1005
1006 storeAppendPrintf(sentry, "server.ftp.requests = %d\n",
1007 (int) f->server.ftp.requests);
1008 storeAppendPrintf(sentry, "server.ftp.errors = %d\n",
1009 (int) f->server.ftp.errors);
1010 storeAppendPrintf(sentry, "server.ftp.kbytes_in = %d\n",
1011 (int) f->server.ftp.kbytes_in.kb);
1012 storeAppendPrintf(sentry, "server.ftp.kbytes_out = %d\n",
1013 (int) f->server.ftp.kbytes_out.kb);
1014
1015 storeAppendPrintf(sentry, "server.other.requests = %d\n",
1016 (int) f->server.other.requests);
1017 storeAppendPrintf(sentry, "server.other.errors = %d\n",
1018 (int) f->server.other.errors);
1019 storeAppendPrintf(sentry, "server.other.kbytes_in = %d\n",
1020 (int) f->server.other.kbytes_in.kb);
1021 storeAppendPrintf(sentry, "server.other.kbytes_out = %d\n",
1022 (int) f->server.other.kbytes_out.kb);
12cf1be2 1023
1024 storeAppendPrintf(sentry, "icp.pkts_sent = %d\n",
1025 f->icp.pkts_sent);
1026 storeAppendPrintf(sentry, "icp.pkts_recv = %d\n",
1027 f->icp.pkts_recv);
071a3ae7 1028 storeAppendPrintf(sentry, "icp.queries_sent = %d\n",
1029 f->icp.queries_sent);
1030 storeAppendPrintf(sentry, "icp.replies_sent = %d\n",
1031 f->icp.replies_sent);
1032 storeAppendPrintf(sentry, "icp.queries_recv = %d\n",
1033 f->icp.queries_recv);
1034 storeAppendPrintf(sentry, "icp.replies_recv = %d\n",
1035 f->icp.replies_recv);
1036 storeAppendPrintf(sentry, "icp.query_timeouts = %d\n",
1037 f->icp.query_timeouts);
2e8e29b8 1038 storeAppendPrintf(sentry, "icp.replies_queued = %d\n",
1039 f->icp.replies_queued);
12cf1be2 1040 storeAppendPrintf(sentry, "icp.kbytes_sent = %d\n",
1041 (int) f->icp.kbytes_sent.kb);
1042 storeAppendPrintf(sentry, "icp.kbytes_recv = %d\n",
1043 (int) f->icp.kbytes_recv.kb);
071a3ae7 1044 storeAppendPrintf(sentry, "icp.q_kbytes_sent = %d\n",
1045 (int) f->icp.q_kbytes_sent.kb);
1046 storeAppendPrintf(sentry, "icp.r_kbytes_sent = %d\n",
1047 (int) f->icp.r_kbytes_sent.kb);
1048 storeAppendPrintf(sentry, "icp.q_kbytes_recv = %d\n",
1049 (int) f->icp.q_kbytes_recv.kb);
1050 storeAppendPrintf(sentry, "icp.r_kbytes_recv = %d\n",
1051 (int) f->icp.r_kbytes_recv.kb);
0567f2a6 1052
00485c29 1053#if SQUID_PEER_DIGEST
071a3ae7 1054 storeAppendPrintf(sentry, "icp.times_used = %d\n",
1055 f->icp.times_used);
1056 storeAppendPrintf(sentry, "cd.times_used = %d\n",
1057 f->cd.times_used);
00485c29 1058 storeAppendPrintf(sentry, "cd.msgs_sent = %d\n",
1059 f->cd.msgs_sent);
1060 storeAppendPrintf(sentry, "cd.msgs_recv = %d\n",
1061 f->cd.msgs_recv);
071a3ae7 1062 storeAppendPrintf(sentry, "cd.memory = %d\n",
1063 (int)f->cd.memory.kb);
1064 storeAppendPrintf(sentry, "cd.store_memory = %d\n",
1065 (int) (store_digest ? store_digest->mask_size/1024 : 0));
00485c29 1066 storeAppendPrintf(sentry, "cd.kbytes_sent = %d\n",
1067 (int) f->cd.kbytes_sent.kb);
1068 storeAppendPrintf(sentry, "cd.kbytes_recv = %d\n",
1069 (int) f->cd.kbytes_recv.kb);
0567f2a6 1070#endif
1071
12cf1be2 1072 storeAppendPrintf(sentry, "unlink.requests = %d\n",
1073 f->unlink.requests);
1074 storeAppendPrintf(sentry, "page_faults = %d\n",
1075 f->page_faults);
1076 storeAppendPrintf(sentry, "select_loops = %d\n",
1077 f->select_loops);
1078 storeAppendPrintf(sentry, "cpu_time = %f\n",
1079 f->cputime);
1080 storeAppendPrintf(sentry, "wall_time = %f\n",
1081 tvSubDsec(f->timestamp, current_time));
7ae52c25 1082}
1083
5e29a294 1084static void
a1e927f6 1085statPeerSelect(StoreEntry * sentry)
1086{
1087#if SQUID_PEER_DIGEST
1088 StatCounters *f = &Counter;
1089 peer *peer;
1090 const int tot_used = f->cd.times_used + f->icp.times_used;
1091
1092 /* totals */
1093 cacheDigestGuessStatsReport(&f->cd.guess, sentry, "all peers");
1094 /* per-peer */
1095 storeAppendPrintf(sentry, "\nPer-peer statistics:\n");
1096 for (peer = getFirstPeer(); peer; peer = getNextPeer(peer)) {
1097 cacheDigestGuessStatsReport(&peer->digest.stats.guess, sentry, peer->host);
ddc0f170 1098 storeAppendPrintf(sentry, "peer.msgs_sent = %d\n",
1099 peer->digest.stats.msgs_sent);
1100 storeAppendPrintf(sentry, "peer.msgs_recv = %d\n",
1101 peer->digest.stats.msgs_recv);
1102 storeAppendPrintf(sentry, "peer.kbytes_sent = %d\n",
1103 (int) peer->digest.stats.kbytes_sent.kb);
1104 storeAppendPrintf(sentry, "peer.kbytes_recv = %d\n",
1105 (int) peer->digest.stats.kbytes_recv.kb);
1106 storeAppendPrintf(sentry, "peer.local_memory = %d\n",
1107 peer->digest.cd ? peer->digest.cd->mask_size/1024 : 0);
a1e927f6 1108 storeAppendPrintf(sentry, "\n");
1109 }
1110
1111 storeAppendPrintf(sentry, "\nAlgorithm usage:\n");
1112 storeAppendPrintf(sentry, "Cache Digest: %7d (%3d%%)\n",
1113 f->cd.times_used, xpercentInt(f->cd.times_used, tot_used));
1114 storeAppendPrintf(sentry, "Icp: %7d (%3d%%)\n",
1115 f->icp.times_used, xpercentInt(f->icp.times_used, tot_used));
1116 storeAppendPrintf(sentry, "Total: %7d (%3d%%)\n",
1117 tot_used, xpercentInt(tot_used, tot_used));
1118#else
1119 storeAppendPrintf(sentry, "peer digests are disabled; no stats is available.\n");
1120#endif
1121}
1122
1123static void
26b164ac 1124statDigestBlob(StoreEntry * sentry)
1125{
071a3ae7 1126 storeAppendPrintf(sentry, "\nCounters:\n");
1127 statCountersDump(sentry);
1128 storeAppendPrintf(sentry, "\nHistograms:\n");
1129 statCountersHistograms(sentry);
1130 storeAppendPrintf(sentry, "\nPeer Digests:\n");
26b164ac 1131 statPeerSelect(sentry);
071a3ae7 1132 storeAppendPrintf(sentry, "\nDigest Report:\n");
26b164ac 1133 storeDigestReport(sentry);
1134}
1135
5e29a294 1136static void
12cf1be2 1137statAvg5min(StoreEntry * e)
7ae52c25 1138{
a0f32775 1139 statAvgDump(e, 5, 0);
7ae52c25 1140}
1141
5e29a294 1142static void
12cf1be2 1143statAvg60min(StoreEntry * e)
7ae52c25 1144{
a0f32775 1145 statAvgDump(e, 60, 0);
7ae52c25 1146}
1147
b87b92fb 1148static double
1149statMedianSvc(int interval, int which)
a9113eb0 1150{
1151 StatCounters *f;
1152 StatCounters *l;
1153 double x;
f8d264b8 1154 assert(interval > 0);
1155 if (interval > N_COUNT_HIST - 1)
1156 interval = N_COUNT_HIST - 1;
a9113eb0 1157 f = &CountHist[0];
1158 l = &CountHist[interval];
ee1679df 1159 assert(f);
1160 assert(l);
a9113eb0 1161 switch (which) {
b87b92fb 1162 case MEDIAN_HTTP:
12cf1be2 1163 x = statHistDeltaMedian(&l->client_http.all_svc_time, &f->client_http.all_svc_time);
ee1679df 1164 break;
b87b92fb 1165 case MEDIAN_HIT:
1166 x = statHistDeltaMedian(&l->client_http.hit_svc_time, &f->client_http.hit_svc_time);
1167 break;
1168 case MEDIAN_MISS:
1169 x = statHistDeltaMedian(&l->client_http.miss_svc_time, &f->client_http.miss_svc_time);
1170 break;
1171 case MEDIAN_NM:
1172 x = statHistDeltaMedian(&l->client_http.nm_svc_time, &f->client_http.nm_svc_time);
1173 break;
1174 case MEDIAN_ICP_QUERY:
12cf1be2 1175 x = statHistDeltaMedian(&l->icp.query_svc_time, &f->icp.query_svc_time);
ee1679df 1176 break;
b87b92fb 1177 case MEDIAN_DNS:
12cf1be2 1178 x = statHistDeltaMedian(&l->dns.svc_time, &f->dns.svc_time);
ee1679df 1179 break;
a9113eb0 1180 default:
ee1679df 1181 debug(49, 5) ("get_median_val: unknown type.\n");
1182 x = 0;
a9113eb0 1183 }
b87b92fb 1184 return x;
1185}
1186
1187/*
1188 * SNMP wants ints, ick
1189 */
1190int
1191get_median_svc(int interval, int which)
1192{
b644367b 1193 return (int) statMedianSvc(interval, which);
a9113eb0 1194}
451b07c5 1195
1196StatCounters *
1197snmpStatGet(int minutes)
1198{
2ac76861 1199 return &CountHist[minutes];
451b07c5 1200}
01aebf31 1201
1202
1203#if STAT_GRAPHS
1204/*
1205 * urgh, i don't like these, but they do cut the amount of code down immensely
1206 */
1207
1208#define GRAPH_PER_MIN(Y) \
1209 for (i=0;i<(N_COUNT_HIST-2);i++) { \
1210 dt = tvSubDsec(CountHist[i].timestamp, CountHist[i+1].timestamp); \
1211 if (dt <= 0.0) \
1212 break; \
1213 storeAppendPrintf(e, "%lu,%0.2f:", \
1214 CountHist[i].timestamp.tv_sec, \
1215 ((CountHist[i].Y - CountHist[i+1].Y) / dt)); \
1216 }
1217
1218#define GRAPH_PER_HOUR(Y) \
1219 for (i=0;i<(N_COUNT_HOUR_HIST-2);i++) { \
1220 dt = tvSubDsec(CountHourHist[i].timestamp, CountHourHist[i+1].timestamp); \
1221 if (dt <= 0.0) \
1222 break; \
1223 storeAppendPrintf(e, "%lu,%0.2f:", \
1224 CountHourHist[i].timestamp.tv_sec, \
1225 ((CountHourHist[i].Y - CountHourHist[i+1].Y) / dt)); \
1226 }
1227
1228#define GRAPH_TITLE(X,Y) storeAppendPrintf(e,"%s\t%s\t",X,Y);
1229#define GRAPH_END storeAppendPrintf(e,"\n");
1230
1231#define GENGRAPH(X,Y,Z) \
1232 GRAPH_TITLE(Y,Z) \
1233 GRAPH_PER_MIN(X) \
1234 GRAPH_PER_HOUR(X) \
1235 GRAPH_END
1236
1237static void
1238statGraphDump(StoreEntry * e)
1239{
1240 int i;
1241 double dt;
1242
1243 GENGRAPH(client_http.requests, "client_http.requests", "Client HTTP requests/sec");
1244 GENGRAPH(client_http.hits, "client_http.hits", "Client HTTP hits/sec");
1245 GENGRAPH(client_http.errors, "client_http.errors", "Client HTTP errors/sec");
1246 GENGRAPH(client_http.kbytes_in.kb, "client_http.kbytes_in", "Client HTTP kbytes_in/sec");
1247 GENGRAPH(client_http.kbytes_out.kb, "client_http.kbytes_out", "Client HTTP kbytes_out/sec");
1248
1249 /* XXX todo: http median service times */
1250
1251 GENGRAPH(server.all.requests, "server.all.requests", "Server requests/sec");
1252 GENGRAPH(server.all.errors, "server.all.errors", "Server errors/sec");
1253 GENGRAPH(server.all.kbytes_in.kb, "server.all.kbytes_in", "Server total kbytes_in/sec");
1254 GENGRAPH(server.all.kbytes_out.kb, "server.all.kbytes_out", "Server total kbytes_out/sec");
1255
1256 GENGRAPH(server.http.requests, "server.http.requests", "Server HTTP requests/sec");
1257 GENGRAPH(server.http.errors, "server.http.errors", "Server HTTP errors/sec");
1258 GENGRAPH(server.http.kbytes_in.kb, "server.http.kbytes_in", "Server HTTP kbytes_in/sec");
1259 GENGRAPH(server.http.kbytes_out.kb, "server.http.kbytes_out", "Server HTTP kbytes_out/sec");
1260
1261 GENGRAPH(server.ftp.requests, "server.ftp.requests", "Server FTP requests/sec");
1262 GENGRAPH(server.ftp.errors, "server.ftp.errors", "Server FTP errors/sec");
1263 GENGRAPH(server.ftp.kbytes_in.kb, "server.ftp.kbytes_in", "Server FTP kbytes_in/sec");
1264 GENGRAPH(server.ftp.kbytes_out.kb, "server.ftp.kbytes_out", "Server FTP kbytes_out/sec");
1265
1266 GENGRAPH(server.other.requests, "server.other.requests", "Server other requests/sec");
1267 GENGRAPH(server.other.errors, "server.other.errors", "Server other errors/sec");
1268 GENGRAPH(server.other.kbytes_in.kb, "server.other.kbytes_in", "Server other kbytes_in/sec");
1269 GENGRAPH(server.other.kbytes_out.kb, "server.other.kbytes_out", "Server other kbytes_out/sec");
1270
1271 GENGRAPH(icp.pkts_sent, "icp.pkts_sent", "ICP packets sent/sec");
1272 GENGRAPH(icp.pkts_recv, "icp.pkts_recv", "ICP packets received/sec");
1273 GENGRAPH(icp.kbytes_sent.kb, "icp.kbytes_sent", "ICP kbytes_sent/sec");
1274 GENGRAPH(icp.kbytes_recv.kb, "icp.kbytes_recv", "ICP kbytes_received/sec");
1275
1276 /* XXX todo: icp median service times */
1277 /* XXX todo: dns median service times */
1278
1279 GENGRAPH(unlink.requests, "unlink.requests", "Cache File unlink requests/sec");
1280 GENGRAPH(page_faults, "page_faults", "System Page Faults/sec");
1281 GENGRAPH(select_loops, "select_loops", "System Select Loop calls/sec");
1282 GENGRAPH(cputime, "cputime", "CPU utilisation");
1283}
1afe05c5 1284
01aebf31 1285#endif /* STAT_GRAPHS */