]> git.ipfire.org Git - thirdparty/squid.git/blame - src/stat.cc
- many cache digest related deletions and additions
[thirdparty/squid.git] / src / stat.cc
CommitLineData
e5f6c5c2 1
30a4f2a8 2/*
b644367b 3 * $Id: stat.cc,v 1.224 1998/04/06 22:32:20 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);
a7c05555 123static void statCountersDump(StoreEntry * sentry);
b87b92fb 124static double statMedianSvc(int, int);
ed7f5615 125static OBJH stat_io_get;
126static OBJH stat_objects_get;
127static OBJH stat_vmobjects_get;
128static OBJH info_get;
129static OBJH statFiledescriptors;
130static OBJH statCounters;
131static OBJH statAvg5min;
45eb7f49 132static OBJH statAvg60min;
e9b5ead4 133static OBJH statUtilization;
20882fb1 134
20882fb1 135#ifdef XMALLOC_STATISTICS
f5b8bbc4 136static void info_get_mallstat(int, int, StoreEntry *);
20882fb1 137#endif
30a4f2a8 138
a9113eb0 139StatCounters CountHist[N_COUNT_HIST];
d5649d9f 140static int NCountHist = 0;
a0f32775 141static StatCounters CountHourHist[N_COUNT_HOUR_HIST];
142static int NCountHourHist = 0;
143
5e29a294 144static void
e9b5ead4 145statUtilization(StoreEntry * e)
a0f32775 146{
147 storeAppendPrintf(e, "Cache Utilisation:\n");
148 storeAppendPrintf(e, "\n");
149 storeAppendPrintf(e, "Last 5 minutes:\n");
150 if (NCountHist >= 5)
151 statAvgDump(e, 5, 0);
152 else
153 storeAppendPrintf(e, "(no values recorded yet)\n");
154 storeAppendPrintf(e, "\n");
155 storeAppendPrintf(e, "Last 15 minutes:\n");
156 if (NCountHist >= 15)
157 statAvgDump(e, 15, 0);
158 else
159 storeAppendPrintf(e, "(no values recorded yet)\n");
160 storeAppendPrintf(e, "\n");
161 storeAppendPrintf(e, "Last hour:\n");
162 if (NCountHist >= 60)
163 statAvgDump(e, 60, 0);
164 else
165 storeAppendPrintf(e, "(no values recorded yet)\n");
166 storeAppendPrintf(e, "\n");
167 storeAppendPrintf(e, "Last 8 hours:\n");
168 if (NCountHourHist >= 8)
169 statAvgDump(e, 0, 8);
170 else
171 storeAppendPrintf(e, "(no values recorded yet)\n");
172 storeAppendPrintf(e, "\n");
173 storeAppendPrintf(e, "Last day:\n");
174 if (NCountHourHist >= 24)
175 statAvgDump(e, 0, 24);
176 else
177 storeAppendPrintf(e, "(no values recorded yet)\n");
178 storeAppendPrintf(e, "\n");
179 storeAppendPrintf(e, "Last 3 days:\n");
180 if (NCountHourHist >= 72)
181 statAvgDump(e, 0, 72);
182 else
183 storeAppendPrintf(e, "(no values recorded yet)\n");
184 storeAppendPrintf(e, "\n");
185 storeAppendPrintf(e, "Totals since cache startup:\n");
186 statCountersDump(e);
187}
f2908497 188
5e29a294 189static void
b8d8561b 190stat_io_get(StoreEntry * sentry)
30a4f2a8 191{
192 int i;
193
15576b6a 194 storeAppendPrintf(sentry, "HTTP I/O\n");
195 storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Http.reads);
196 storeAppendPrintf(sentry, "deferred reads: %d (%d%%)\n",
30a4f2a8 197 IOStats.Http.reads_deferred,
198 percent(IOStats.Http.reads_deferred, IOStats.Http.reads));
15576b6a 199 storeAppendPrintf(sentry, "Read Histogram:\n");
30a4f2a8 200 for (i = 0; i < 16; i++) {
15576b6a 201 storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
30a4f2a8 202 i ? (1 << (i - 1)) + 1 : 1,
203 1 << i,
204 IOStats.Http.read_hist[i],
205 percent(IOStats.Http.read_hist[i], IOStats.Http.reads));
206 }
207
15576b6a 208 storeAppendPrintf(sentry, "\n");
209 storeAppendPrintf(sentry, "FTP I/O\n");
210 storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Ftp.reads);
211 storeAppendPrintf(sentry, "deferred reads: %d (%d%%)\n",
30a4f2a8 212 IOStats.Ftp.reads_deferred,
213 percent(IOStats.Ftp.reads_deferred, IOStats.Ftp.reads));
15576b6a 214 storeAppendPrintf(sentry, "Read Histogram:\n");
30a4f2a8 215 for (i = 0; i < 16; i++) {
15576b6a 216 storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
30a4f2a8 217 i ? (1 << (i - 1)) + 1 : 1,
218 1 << i,
219 IOStats.Ftp.read_hist[i],
220 percent(IOStats.Ftp.read_hist[i], IOStats.Ftp.reads));
221 }
222
15576b6a 223 storeAppendPrintf(sentry, "\n");
224 storeAppendPrintf(sentry, "Gopher I/O\n");
225 storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Gopher.reads);
226 storeAppendPrintf(sentry, "deferred reads: %d (%d%%)\n",
56fa4cad 227 IOStats.Gopher.reads_deferred,
228 percent(IOStats.Gopher.reads_deferred, IOStats.Gopher.reads));
15576b6a 229 storeAppendPrintf(sentry, "Read Histogram:\n");
56fa4cad 230 for (i = 0; i < 16; i++) {
15576b6a 231 storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
56fa4cad 232 i ? (1 << (i - 1)) + 1 : 1,
233 1 << i,
234 IOStats.Gopher.read_hist[i],
235 percent(IOStats.Gopher.read_hist[i], IOStats.Gopher.reads));
236 }
237
15576b6a 238 storeAppendPrintf(sentry, "\n");
239 storeAppendPrintf(sentry, "WAIS I/O\n");
240 storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Wais.reads);
241 storeAppendPrintf(sentry, "deferred reads: %d (%d%%)\n",
56fa4cad 242 IOStats.Wais.reads_deferred,
243 percent(IOStats.Wais.reads_deferred, IOStats.Wais.reads));
15576b6a 244 storeAppendPrintf(sentry, "Read Histogram:\n");
56fa4cad 245 for (i = 0; i < 16; i++) {
15576b6a 246 storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n",
56fa4cad 247 i ? (1 << (i - 1)) + 1 : 1,
248 1 << i,
249 IOStats.Wais.read_hist[i],
250 percent(IOStats.Wais.read_hist[i], IOStats.Wais.reads));
251 }
090089c4 252}
253
0ee4272b 254static const char *
fe4e214f 255describeStatuses(const StoreEntry * entry)
d1a43e28 256{
257 LOCAL_ARRAY(char, buf, 256);
56878878 258 snprintf(buf, 256, "%-13s %-13s %-12s %-12s",
d1a43e28 259 storeStatusStr[entry->store_status],
260 memStatusStr[entry->mem_status],
261 swapStatusStr[entry->swap_status],
262 pingStatusStr[entry->ping_status]);
263 return buf;
264}
265
0ee4272b 266static const char *
fe4e214f 267describeFlags(const StoreEntry * entry)
d1a43e28 268{
269 LOCAL_ARRAY(char, buf, 256);
270 int flags = (int) entry->flag;
271 char *t;
272 buf[0] = '\0';
79a15e0a 273 if (EBIT_TEST(flags, DELAY_SENDING))
d1a43e28 274 strcat(buf, "DS,");
79a15e0a 275 if (EBIT_TEST(flags, RELEASE_REQUEST))
d1a43e28 276 strcat(buf, "RL,");
79a15e0a 277 if (EBIT_TEST(flags, REFRESH_REQUEST))
d1a43e28 278 strcat(buf, "RF,");
79a15e0a 279 if (EBIT_TEST(flags, ENTRY_CACHABLE))
d1a43e28 280 strcat(buf, "EC,");
79a15e0a 281 if (EBIT_TEST(flags, ENTRY_DISPATCHED))
d1a43e28 282 strcat(buf, "ED,");
79a15e0a 283 if (EBIT_TEST(flags, KEY_PRIVATE))
d1a43e28 284 strcat(buf, "KP,");
79a15e0a 285 if (EBIT_TEST(flags, HIERARCHICAL))
d1a43e28 286 strcat(buf, "HI,");
79a15e0a 287 if (EBIT_TEST(flags, ENTRY_NEGCACHED))
d1a43e28 288 strcat(buf, "NG,");
d1a43e28 289 if ((t = strrchr(buf, ',')))
290 *t = '\0';
291 return buf;
292}
293
0ee4272b 294static const char *
fe4e214f 295describeTimestamps(const StoreEntry * entry)
d1a43e28 296{
297 LOCAL_ARRAY(char, buf, 256);
56878878 298 snprintf(buf, 256, "LV:%-9d LU:%-9d LM:%-9d EX:%-9d",
d1a43e28 299 (int) entry->timestamp,
300 (int) entry->lastref,
301 (int) entry->lastmod,
302 (int) entry->expires);
303 return buf;
304}
305
090089c4 306/* process objects list */
b8d8561b 307static void
6684fec0 308statObjects(StoreEntry * sentry, int vm_or_not)
090089c4 309{
09610784 310 StoreEntry *entry = NULL;
f09f5b26 311 StoreEntry *next = NULL;
d1a43e28 312 MemObject *mem;
090089c4 313 int N = 0;
637ed800 314 int i;
315 struct _store_client *sc;
f09f5b26 316 next = (StoreEntry *) hash_first(store_table);
a200bbd2 317 while ((entry = next) != NULL) {
f09f5b26 318 next = (StoreEntry *) hash_next(store_table);
d1a43e28 319 mem = entry->mem_obj;
320 if (vm_or_not && mem == NULL)
090089c4 321 continue;
322 if ((++N & 0xFF) == 0) {
22f3fd98 323 debug(18, 3) ("statObjects: Processed %d objects...\n", N);
090089c4 324 }
438fc1e3 325 storeBuffer(sentry);
24ffafb4 326 storeAppendPrintf(sentry, "KEY %s\n", storeKeyText(entry->key));
2ac237e2 327 if (mem)
328 storeAppendPrintf(sentry, "\t%s %s\n",
785c2dc3 329 RequestMethodStr[mem->method], mem->log_url);
637ed800 330 storeAppendPrintf(sentry, "\t%s\n", describeStatuses(entry));
331 storeAppendPrintf(sentry, "\t%s\n", describeFlags(entry));
332 storeAppendPrintf(sentry, "\t%s\n", describeTimestamps(entry));
333 storeAppendPrintf(sentry, "\t%d locks, %d clients, %d refs\n",
334 (int) entry->lock_count,
335 storePendingNClients(entry),
336 (int) entry->refcount);
337 storeAppendPrintf(sentry, "\tSwap File %#08X\n",
338 entry->swap_file_number);
339 if (mem == NULL)
340 continue;
341 storeAppendPrintf(sentry, "\tinmem_lo: %d\n", (int) mem->inmem_lo);
342 storeAppendPrintf(sentry, "\tinmem_hi: %d\n", (int) mem->inmem_hi);
343 storeAppendPrintf(sentry, "\tswapout: %d bytes done, %d queued, FD %d\n",
5f6ac48b 344 (int) mem->swapout.done_offset,
345 (int) mem->swapout.queue_offset,
637ed800 346 mem->swapout.fd);
347 for (i = 0; i < mem->nclients; i++) {
348 sc = &mem->clients[i];
349 if (sc->callback_data == NULL)
350 continue;
351 storeAppendPrintf(sentry, "\tClient #%d\n", i);
352 storeAppendPrintf(sentry, "\t\tcopy_offset: %d\n",
353 (int) sc->copy_offset);
354 storeAppendPrintf(sentry, "\t\tseen_offset: %d\n",
355 (int) sc->seen_offset);
356 storeAppendPrintf(sentry, "\t\tcopy_size: %d\n",
357 (int) sc->copy_size);
358 storeAppendPrintf(sentry, "\t\tswapin_fd: %d\n",
359 (int) sc->swapin_fd);
360 }
24ffafb4 361 storeAppendPrintf(sentry, "\n");
438fc1e3 362 storeBufferFlush(sentry);
090089c4 363 }
090089c4 364}
365
5e29a294 366static void
603a02fd 367stat_objects_get(StoreEntry * e)
090089c4 368{
603a02fd 369 statObjects(e, 0);
6684fec0 370}
090089c4 371
5e29a294 372static void
603a02fd 373stat_vmobjects_get(StoreEntry * e)
6684fec0 374{
603a02fd 375 statObjects(e, 1);
090089c4 376}
377
0a0bf5db 378#ifdef XMALLOC_STATISTICS
b8d8561b 379static void
0a0bf5db 380info_get_mallstat(int size, int number, StoreEntry * sentry)
30a4f2a8 381{
30a4f2a8 382 if (number > 0)
15576b6a 383 storeAppendPrintf(sentry, "\t%d = %d\n", size, number);
30a4f2a8 384}
385#endif
090089c4 386
0ee4272b 387static const char *
f1dc9b30 388fdRemoteAddr(const fde * f)
d51e52f5 389{
95d659f0 390 LOCAL_ARRAY(char, buf, 32);
4f92c80c 391 if (f->type != FD_SOCKET)
392 return null_string;
042461c3 393 snprintf(buf, 32, "%s.%d", f->ipaddr, (int) f->remote_port);
d2af9477 394 return buf;
d51e52f5 395}
396
5e29a294 397static void
b8d8561b 398statFiledescriptors(StoreEntry * sentry)
d51e52f5 399{
400 int i;
f1dc9b30 401 fde *f;
15576b6a 402 storeAppendPrintf(sentry, "Active file descriptors:\n");
403 storeAppendPrintf(sentry, "%-4s %-6s %-4s %-7s %-7s %-21s %s\n",
d51e52f5 404 "File",
405 "Type",
d51e52f5 406 "Tout",
4f92c80c 407 "Nread",
408 "Nwrite",
d51e52f5 409 "Remote Address",
410 "Description");
15576b6a 411 storeAppendPrintf(sentry, "---- ------ ---- ------- ------- --------------------- ------------------------------\n");
e83892e9 412 for (i = 0; i < Squid_MaxFD; i++) {
429fdbec 413 f = &fd_table[i];
5c5783a2 414 if (!f->open)
d51e52f5 415 continue;
15576b6a 416 storeAppendPrintf(sentry, "%4d %-6.6s %4d %7d %7d %-21s %s\n",
d2af9477 417 i,
22f5d1ca 418 fdTypeStr[f->type],
5f6ac48b 419 f->timeout_handler ? (int) (f->timeout - squid_curtime) / 60 : 0,
4f92c80c 420 f->bytes_read,
421 f->bytes_written,
422 fdRemoteAddr(f),
423 f->desc);
d51e52f5 424 }
d51e52f5 425}
426
5e29a294 427static void
03eb2f01 428info_get(StoreEntry * sentry)
090089c4 429{
090089c4 430 struct rusage rusage;
f2908497 431 double cputime;
432 double runtime;
88738790 433#if HAVE_MSTATS && HAVE_GNUMALLOC_H
434 struct mstats ms;
435#elif HAVE_MALLINFO
090089c4 436 struct mallinfo mp;
88738790 437 int t;
090089c4 438#endif
439
f2908497 440 runtime = tvSubDsec(squid_start, current_time);
441 if (runtime == 0.0)
442 runtime = 1.0;
15576b6a 443 storeAppendPrintf(sentry, "Squid Object Cache: Version %s\n",
d51e52f5 444 version_string);
15576b6a 445 storeAppendPrintf(sentry, "Start Time:\t%s\n",
f2908497 446 mkrfc1123(squid_start.tv_sec));
15576b6a 447 storeAppendPrintf(sentry, "Current Time:\t%s\n",
f2908497 448 mkrfc1123(current_time.tv_sec));
15576b6a 449 storeAppendPrintf(sentry, "Connection information for %s:\n",
d51e52f5 450 appname);
15576b6a 451 storeAppendPrintf(sentry, "\tNumber of HTTP requests received:\t%u\n",
f2908497 452 Counter.client_http.requests);
15576b6a 453 storeAppendPrintf(sentry, "\tNumber of ICP messages received:\t%u\n",
f2908497 454 Counter.icp.pkts_recv);
15576b6a 455 storeAppendPrintf(sentry, "\tNumber of ICP messages sent:\t%u\n",
f2908497 456 Counter.icp.pkts_sent);
2e8e29b8 457 storeAppendPrintf(sentry, "\tNumber of queued ICP replies:\t%u\n",
458 Counter.icp.replies_queued);
15576b6a 459 storeAppendPrintf(sentry, "\tRequest failure ratio:\t%5.2f%%\n",
88aad2e5 460 request_failure_ratio);
f2908497 461
15576b6a 462 storeAppendPrintf(sentry, "\tHTTP requests per minute:\t%.1f\n",
f2908497 463 Counter.client_http.requests / (runtime / 60.0));
15576b6a 464 storeAppendPrintf(sentry, "\tICP messages per minute:\t%.1f\n",
f2908497 465 (Counter.icp.pkts_sent + Counter.icp.pkts_recv) / (runtime / 60.0));
15576b6a 466 storeAppendPrintf(sentry, "\tSelect loop called: %d times, %0.3f ms avg\n",
f2908497 467 Counter.select_loops, 1000.0 * runtime / Counter.select_loops);
090089c4 468
15576b6a 469 storeAppendPrintf(sentry, "Cache information for %s:\n",
30a4f2a8 470 appname);
15576b6a 471 storeAppendPrintf(sentry, "\tStorage Swap size:\t%d KB\n",
c932b107 472 store_swap_size);
15576b6a 473 storeAppendPrintf(sentry, "\tStorage Mem size:\t%d KB\n",
5f6ac48b 474 (int) (store_mem_size >> 10));
15576b6a 475 storeAppendPrintf(sentry, "\tStorage LRU Expiration Age:\t%6.2f days\n",
52cd89fd 476 (double) storeExpiredReferenceAge() / 86400.0);
15576b6a 477 storeAppendPrintf(sentry, "\tRequests given to unlinkd:\t%d\n",
f2908497 478 Counter.unlink.requests);
090089c4 479
b87b92fb 480 storeAppendPrintf(sentry, "Median Service Times (seconds) 5 min 60 min:\n");
481 storeAppendPrintf(sentry, "\tHTTP Requests (All): %8.5f %8.5f\n",
482 statMedianSvc(5, MEDIAN_HTTP) / 1000.0,
483 statMedianSvc(60, MEDIAN_HTTP) / 1000.0);
484 storeAppendPrintf(sentry, "\tCache Misses: %8.5f %8.5f\n",
485 statMedianSvc(5, MEDIAN_MISS) / 1000.0,
486 statMedianSvc(60, MEDIAN_MISS) / 1000.0);
487 storeAppendPrintf(sentry, "\tCache Hits: %8.5f %8.5f\n",
488 statMedianSvc(5, MEDIAN_HIT) / 1000.0,
489 statMedianSvc(60, MEDIAN_HIT) / 1000.0);
490 storeAppendPrintf(sentry, "\tNot-Modified Replies: %8.5f %8.5f\n",
491 statMedianSvc(5, MEDIAN_NM) / 1000.0,
492 statMedianSvc(60, MEDIAN_NM) / 1000.0);
493 storeAppendPrintf(sentry, "\tDNS Lookups: %8.5f %8.5f\n",
494 statMedianSvc(5, MEDIAN_DNS) / 1000.0,
495 statMedianSvc(60, MEDIAN_DNS) / 1000.0);
496 storeAppendPrintf(sentry, "\tICP Queries: %8.5f %8.5f\n",
497 statMedianSvc(5, MEDIAN_ICP_QUERY) / 1000000.0,
498 statMedianSvc(60, MEDIAN_ICP_QUERY) / 1000000.0);
499
f2908497 500 squid_getrusage(&rusage);
501 cputime = rusage_cputime(&rusage);
15576b6a 502 storeAppendPrintf(sentry, "Resource usage for %s:\n", appname);
503 storeAppendPrintf(sentry, "\tUP Time:\t%.3f seconds\n", runtime);
504 storeAppendPrintf(sentry, "\tCPU Time:\t%.3f seconds\n", cputime);
505 storeAppendPrintf(sentry, "\tCPU Usage:\t%.2f%%\n",
f2908497 506 dpercent(cputime, runtime));
5f6ac48b 507 storeAppendPrintf(sentry, "\tMaximum Resident Size: %d KB\n",
f2908497 508 rusage_maxrss(&rusage));
5f6ac48b 509 storeAppendPrintf(sentry, "\tPage faults with physical i/o: %d\n",
f2908497 510 rusage_pagefaults(&rusage));
090089c4 511
88738790 512#if HAVE_MSTATS && HAVE_GNUMALLOC_H
513 ms = mstats();
15576b6a 514 storeAppendPrintf(sentry, "Memory usage for %s via mstats():\n",
88738790 515 appname);
15576b6a 516 storeAppendPrintf(sentry, "\tTotal space in arena: %6d KB\n",
88738790 517 ms.bytes_total >> 10);
15576b6a 518 storeAppendPrintf(sentry, "\tTotal free: %6d KB %d%%\n",
88738790 519 ms.bytes_free >> 10, percent(ms.bytes_free, ms.bytes_total));
520#elif HAVE_MALLINFO
090089c4 521 mp = mallinfo();
15576b6a 522 storeAppendPrintf(sentry, "Memory usage for %s via mallinfo():\n",
d51e52f5 523 appname);
15576b6a 524 storeAppendPrintf(sentry, "\tTotal space in arena: %6d KB\n",
b560dd20 525 mp.arena >> 10);
15576b6a 526 storeAppendPrintf(sentry, "\tOrdinary blocks: %6d KB %6d blks\n",
30a4f2a8 527 mp.uordblks >> 10, mp.ordblks);
15576b6a 528 storeAppendPrintf(sentry, "\tSmall blocks: %6d KB %6d blks\n",
30a4f2a8 529 mp.usmblks >> 10, mp.smblks);
15576b6a 530 storeAppendPrintf(sentry, "\tHolding blocks: %6d KB %6d blks\n",
30a4f2a8 531 mp.hblkhd >> 10, mp.hblks);
15576b6a 532 storeAppendPrintf(sentry, "\tFree Small blocks: %6d KB\n",
30a4f2a8 533 mp.fsmblks >> 10);
15576b6a 534 storeAppendPrintf(sentry, "\tFree Ordinary blocks: %6d KB\n",
30a4f2a8 535 mp.fordblks >> 10);
536 t = mp.uordblks + mp.usmblks + mp.hblkhd;
15576b6a 537 storeAppendPrintf(sentry, "\tTotal in use: %6d KB %d%%\n",
30a4f2a8 538 t >> 10, percent(t, mp.arena));
539 t = mp.fsmblks + mp.fordblks;
15576b6a 540 storeAppendPrintf(sentry, "\tTotal free: %6d KB %d%%\n",
30a4f2a8 541 t >> 10, percent(t, mp.arena));
46c883ed 542#if HAVE_EXT_MALLINFO
15576b6a 543 storeAppendPrintf(sentry, "\tmax size of small blocks:\t%d\n", mp.mxfast);
544 storeAppendPrintf(sentry, "\tnumber of small blocks in a holding block:\t%d\n",
090089c4 545 mp.nlblks);
15576b6a 546 storeAppendPrintf(sentry, "\tsmall block rounding factor:\t%d\n", mp.grain);
547 storeAppendPrintf(sentry, "\tspace (including overhead) allocated in ord. blks:\t%d\n"
090089c4 548 ,mp.uordbytes);
15576b6a 549 storeAppendPrintf(sentry, "\tnumber of ordinary blocks allocated:\t%d\n",
090089c4 550 mp.allocated);
15576b6a 551 storeAppendPrintf(sentry, "\tbytes used in maintaining the free tree:\t%d\n",
090089c4 552 mp.treeoverhead);
46c883ed 553#endif /* HAVE_EXT_MALLINFO */
50bc2565 554#endif /* HAVE_MALLINFO */
090089c4 555
15576b6a 556 storeAppendPrintf(sentry, "File descriptor usage for %s:\n", appname);
557 storeAppendPrintf(sentry, "\tMaximum number of file descriptors: %4d\n",
e83892e9 558 Squid_MaxFD);
15576b6a 559 storeAppendPrintf(sentry, "\tLargest file desc currently in use: %4d\n",
429fdbec 560 Biggest_FD);
15576b6a 561 storeAppendPrintf(sentry, "\tNumber of file desc currently in use: %4d\n",
88738790 562 Number_FD);
15576b6a 563 storeAppendPrintf(sentry, "\tAvailable number of file descriptors: %4d\n",
88738790 564 Squid_MaxFD - Number_FD);
15576b6a 565 storeAppendPrintf(sentry, "\tReserved number of file descriptors: %4d\n",
090089c4 566 RESERVED_FD);
090089c4 567
15576b6a 568 storeAppendPrintf(sentry, "Internal Data Structures:\n");
569 storeAppendPrintf(sentry, "\t%6d StoreEntries\n",
3f6c0fb2 570 memInUse(MEM_STOREENTRY));
15576b6a 571 storeAppendPrintf(sentry, "\t%6d StoreEntries with MemObjects\n",
3f6c0fb2 572 memInUse(MEM_MEMOBJECT));
15576b6a 573 storeAppendPrintf(sentry, "\t%6d StoreEntries with MemObject Data\n",
3f6c0fb2 574 memInUse(MEM_MEM_HDR));
15576b6a 575 storeAppendPrintf(sentry, "\t%6d Hot Object Cache Items\n",
59c4d35b 576 hot_obj_count);
30a4f2a8 577
578#if XMALLOC_STATISTICS
15576b6a 579 storeAppendPrintf(sentry, "Memory allocation statistics\n");
30a4f2a8 580 malloc_statistics(info_get_mallstat, sentry);
581#endif
090089c4 582}
583
a7c05555 584#define XAVG(X) (dt ? (double) (f->X - l->X) / dt : 0.0)
b8d8561b 585static void
a0f32775 586statAvgDump(StoreEntry * sentry, int minutes, int hours)
090089c4 587{
a7c05555 588 StatCounters *f;
589 StatCounters *l;
590 double dt;
591 double ct;
7ae52c25 592 double x;
a7c05555 593 assert(N_COUNT_HIST > 1);
a0f32775 594 assert(minutes > 0 || hours > 0);
a7c05555 595 f = &CountHist[0];
a0f32775 596 l = f;
597 if (minutes > 0 && hours == 0) {
598 /* checking minute readings ... */
599 if (minutes > N_COUNT_HIST - 1)
600 minutes = N_COUNT_HIST - 1;
601 l = &CountHist[minutes];
602 } else if (minutes == 0 && hours > 0) {
603 /* checking hour readings ... */
604 if (hours > N_COUNT_HOUR_HIST - 1)
605 hours = N_COUNT_HOUR_HIST - 1;
606 l = &CountHourHist[hours];
607 } else {
399e85ea 608 debug(18, 1) ("statAvgDump: Invalid args, minutes=%d, hours=%d\n",
609 minutes, hours);
a0f32775 610 return;
611 }
a7c05555 612 dt = tvSubDsec(l->timestamp, f->timestamp);
613 ct = f->cputime - l->cputime;
ee1679df 614
399e85ea 615 storeAppendPrintf(sentry, "sample_start_time = %d.%d (%s)\n",
5f6ac48b 616 (int) f->timestamp.tv_sec,
617 (int) f->timestamp.tv_usec,
a0f32775 618 mkrfc1123(f->timestamp.tv_sec));
399e85ea 619 storeAppendPrintf(sentry, "sample_end_time = %d.%d (%s)\n",
5f6ac48b 620 (int) l->timestamp.tv_sec,
621 (int) l->timestamp.tv_usec,
a0f32775 622 mkrfc1123(l->timestamp.tv_sec));
623
a7c05555 624 storeAppendPrintf(sentry, "client_http.requests = %f/sec\n",
625 XAVG(client_http.requests));
626 storeAppendPrintf(sentry, "client_http.hits = %f/sec\n",
627 XAVG(client_http.hits));
628 storeAppendPrintf(sentry, "client_http.errors = %f/sec\n",
629 XAVG(client_http.errors));
630 storeAppendPrintf(sentry, "client_http.kbytes_in = %f/sec\n",
631 XAVG(client_http.kbytes_in.kb));
632 storeAppendPrintf(sentry, "client_http.kbytes_out = %f/sec\n",
633 XAVG(client_http.kbytes_out.kb));
ee1679df 634
12cf1be2 635 x = statHistDeltaMedian(&l->client_http.all_svc_time,
ee1679df 636 &f->client_http.all_svc_time);
637 storeAppendPrintf(sentry, "client_http.all_median_svc_time = %f seconds\n",
638 x / 1000.0);
12cf1be2 639 x = statHistDeltaMedian(&l->client_http.miss_svc_time,
ee1679df 640 &f->client_http.miss_svc_time);
641 storeAppendPrintf(sentry, "client_http.miss_median_svc_time = %f seconds\n",
642 x / 1000.0);
12cf1be2 643 x = statHistDeltaMedian(&l->client_http.nm_svc_time,
ee1679df 644 &f->client_http.nm_svc_time);
645 storeAppendPrintf(sentry, "client_http.nm_median_svc_time = %f seconds\n",
646 x / 1000.0);
12cf1be2 647 x = statHistDeltaMedian(&l->client_http.hit_svc_time,
ee1679df 648 &f->client_http.hit_svc_time);
649 storeAppendPrintf(sentry, "client_http.hit_median_svc_time = %f seconds\n",
7ae52c25 650 x / 1000.0);
ee1679df 651
a0f32775 652 storeAppendPrintf(sentry, "server.all.requests = %f/sec\n",
653 XAVG(server.all.requests));
654 storeAppendPrintf(sentry, "server.all.errors = %f/sec\n",
655 XAVG(server.all.errors));
656 storeAppendPrintf(sentry, "server.all.kbytes_in = %f/sec\n",
657 XAVG(server.all.kbytes_in.kb));
658 storeAppendPrintf(sentry, "server.all.kbytes_out = %f/sec\n",
659 XAVG(server.all.kbytes_out.kb));
660
661 storeAppendPrintf(sentry, "server.http.requests = %f/sec\n",
662 XAVG(server.http.requests));
663 storeAppendPrintf(sentry, "server.http.errors = %f/sec\n",
664 XAVG(server.http.errors));
665 storeAppendPrintf(sentry, "server.http.kbytes_in = %f/sec\n",
666 XAVG(server.http.kbytes_in.kb));
667 storeAppendPrintf(sentry, "server.http.kbytes_out = %f/sec\n",
668 XAVG(server.http.kbytes_out.kb));
669
670 storeAppendPrintf(sentry, "server.ftp.requests = %f/sec\n",
671 XAVG(server.ftp.requests));
672 storeAppendPrintf(sentry, "server.ftp.errors = %f/sec\n",
673 XAVG(server.ftp.errors));
674 storeAppendPrintf(sentry, "server.ftp.kbytes_in = %f/sec\n",
675 XAVG(server.ftp.kbytes_in.kb));
676 storeAppendPrintf(sentry, "server.ftp.kbytes_out = %f/sec\n",
677 XAVG(server.ftp.kbytes_out.kb));
678
679 storeAppendPrintf(sentry, "server.other.requests = %f/sec\n",
680 XAVG(server.other.requests));
681 storeAppendPrintf(sentry, "server.other.errors = %f/sec\n",
682 XAVG(server.other.errors));
683 storeAppendPrintf(sentry, "server.other.kbytes_in = %f/sec\n",
684 XAVG(server.other.kbytes_in.kb));
685 storeAppendPrintf(sentry, "server.other.kbytes_out = %f/sec\n",
686 XAVG(server.other.kbytes_out.kb));
ee1679df 687
a7c05555 688 storeAppendPrintf(sentry, "icp.pkts_sent = %f/sec\n",
689 XAVG(icp.pkts_sent));
690 storeAppendPrintf(sentry, "icp.pkts_recv = %f/sec\n",
691 XAVG(icp.pkts_recv));
2e8e29b8 692 storeAppendPrintf(sentry, "icp.replies_queued = %f/sec\n",
693 XAVG(icp.replies_queued));
a7c05555 694 storeAppendPrintf(sentry, "icp.kbytes_sent = %f/sec\n",
695 XAVG(icp.kbytes_sent.kb));
696 storeAppendPrintf(sentry, "icp.kbytes_recv = %f/sec\n",
697 XAVG(icp.kbytes_recv.kb));
12cf1be2 698 x = statHistDeltaMedian(&l->icp.query_svc_time, &f->icp.query_svc_time);
ee1679df 699 storeAppendPrintf(sentry, "icp.query_median_svc_time = %f seconds\n",
700 x / 1000000.0);
12cf1be2 701 x = statHistDeltaMedian(&l->icp.reply_svc_time, &f->icp.reply_svc_time);
ee1679df 702 storeAppendPrintf(sentry, "icp.reply_median_svc_time = %f seconds\n",
7ae52c25 703 x / 1000000.0);
12cf1be2 704 x = statHistDeltaMedian(&l->dns.svc_time, &f->dns.svc_time);
9973e9fe 705 storeAppendPrintf(sentry, "dns.median_svc_time = %f seconds\n",
901d8c30 706 x / 1000.0);
a7c05555 707 storeAppendPrintf(sentry, "unlink.requests = %f/sec\n",
708 XAVG(unlink.requests));
709 storeAppendPrintf(sentry, "page_faults = %f/sec\n",
710 XAVG(page_faults));
711 storeAppendPrintf(sentry, "select_loops = %f/sec\n",
712 XAVG(select_loops));
713 storeAppendPrintf(sentry, "cpu_time = %f seconds\n", ct);
714 storeAppendPrintf(sentry, "wall_time = %f seconds\n", dt);
0e473d70 715 storeAppendPrintf(sentry, "cpu_usage = %f%%\n", dpercent(ct, dt));
090089c4 716}
717
b8d8561b 718void
a7c05555 719statInit(void)
090089c4 720{
090089c4 721 int i;
a7c05555 722 debug(18, 5) ("statInit: Initializing...\n");
0e473d70 723 for (i = 0; i < N_COUNT_HIST; i++)
12cf1be2 724 statCountersInit(&CountHist[i]);
a0f32775 725 for (i = 0; i < N_COUNT_HOUR_HIST; i++)
726 statCountersInit(&CountHourHist[i]);
12cf1be2 727 statCountersInit(&Counter);
a0f32775 728 eventAdd("statAvgTick", statAvgTick, NULL, COUNT_INTERVAL);
22f3fd98 729 cachemgrRegister("info",
730 "General Runtime Information",
731 info_get, 0);
732 cachemgrRegister("filedescriptors",
733 "Process Filedescriptor Allocation",
734 statFiledescriptors, 0);
735 cachemgrRegister("objects",
736 "All Cache Objects",
737 stat_objects_get, 0);
738 cachemgrRegister("vm_objects",
739 "In-Memory and In-Transit Objects",
740 stat_vmobjects_get, 0);
741 cachemgrRegister("io",
742 "Server-side network read() size histograms",
743 stat_io_get, 0);
744 cachemgrRegister("counters",
745 "Traffic and Resource Counters",
746 statCounters, 0);
747 cachemgrRegister("5min",
748 "5 Minute Average of Counters",
749 statAvg5min, 0);
45eb7f49 750 cachemgrRegister("60min",
751 "60 Minute Average of Counters",
752 statAvg60min, 0);
e9b5ead4 753 cachemgrRegister("utilization",
754 "Cache Utilization",
755 statUtilization, 0);
01aebf31 756#if STAT_GRAPHS
757 cachemgrRegister("graph_variables",
758 "Display cache metrics graphically",
759 statGraphDump, 0);
760#endif
090089c4 761}
f2908497 762
f2908497 763static void
764statAvgTick(void *notused)
765{
d5649d9f 766 StatCounters *t = &CountHist[0];
767 StatCounters *p = &CountHist[1];
f2908497 768 StatCounters *c = &Counter;
769 struct rusage rusage;
a0f32775 770 eventAdd("statAvgTick", statAvgTick, NULL, COUNT_INTERVAL);
20903cac 771 squid_getrusage(&rusage);
772 c->page_faults = rusage_pagefaults(&rusage);
773 c->cputime = rusage_cputime(&rusage);
d5649d9f 774 c->timestamp = current_time;
12cf1be2 775 /* even if NCountHist is small, we already Init()ed the tail */
2ac76861 776 statCountersClean(CountHist + N_COUNT_HIST - 1);
dbfed404 777 xmemmove(p, t, (N_COUNT_HIST - 1) * sizeof(StatCounters));
12cf1be2 778 statCountersCopy(t, c);
d5649d9f 779 NCountHist++;
a0f32775 780
781 if ((NCountHist % COUNT_INTERVAL) == 0) {
782 /* we have an hours worth of readings. store previous hour */
783 StatCounters *p = &CountHourHist[0];
784 StatCounters *t = &CountHourHist[1];
785 StatCounters *c = &CountHist[N_COUNT_HIST];
786 xmemmove(p, t, (N_COUNT_HOUR_HIST - 1) * sizeof(StatCounters));
787 memcpy(t, c, sizeof(StatCounters));
788 NCountHourHist++;
789 }
20903cac 790}
791
12cf1be2 792static void
2ac76861 793statCountersInit(StatCounters * C)
20903cac 794{
12cf1be2 795 assert(C);
1d803566 796 memset(C, 0, sizeof(*C));
12cf1be2 797 C->timestamp = current_time;
1d803566 798 statCountersInitSpecial(C);
799}
800
801/* add special cases here as they arrive */
802static void
2ac76861 803statCountersInitSpecial(StatCounters * C)
1d803566 804{
12cf1be2 805 /*
806 * HTTP svc_time hist is kept in milli-seconds; max of 3 hours.
807 */
808 statHistLogInit(&C->client_http.all_svc_time, 300, 0.0, 3600000.0 * 3.0);
809 statHistLogInit(&C->client_http.miss_svc_time, 300, 0.0, 3600000.0 * 3.0);
810 statHistLogInit(&C->client_http.nm_svc_time, 300, 0.0, 3600000.0 * 3.0);
811 statHistLogInit(&C->client_http.hit_svc_time, 300, 0.0, 3600000.0 * 3.0);
812 /*
813 * ICP svc_time hist is kept in micro-seconds; max of 1 minute.
814 */
815 statHistLogInit(&C->icp.query_svc_time, 300, 0.0, 1000000.0 * 60.0);
816 statHistLogInit(&C->icp.reply_svc_time, 300, 0.0, 1000000.0 * 60.0);
817 /*
818 * DNS svc_time hist is kept in milli-seconds; max of 10 minutes.
819 */
820 statHistLogInit(&C->dns.svc_time, 300, 0.0, 60000.0 * 10.0);
df819896 821#if SQUID_PEER_DIGEST
822 statHistLogInit(&C->cd.client_svc_time, 300, 0.0, 3600000.0 * 30.0);
823 statHistLogInit(&C->icp.client_svc_time, 300, 0.0, 3600000.0 * 30.0);
824#endif
0f5607d9 825}
826
12cf1be2 827/* add special cases here as they arrive */
5e29a294 828static void
2ac76861 829statCountersClean(StatCounters * C)
0f5607d9 830{
12cf1be2 831 assert(C);
832 statHistClean(&C->client_http.all_svc_time);
833 statHistClean(&C->client_http.miss_svc_time);
834 statHistClean(&C->client_http.nm_svc_time);
835 statHistClean(&C->client_http.hit_svc_time);
836 statHistClean(&C->icp.query_svc_time);
837 statHistClean(&C->icp.reply_svc_time);
838 statHistClean(&C->dns.svc_time);
df819896 839#if SQUID_PEER_DIGEST
840 statHistClean(&C->cd.client_svc_time);
841 statHistClean(&C->icp.client_svc_time);
842#endif
a7c05555 843}
844
12cf1be2 845/* add special cases here as they arrive */
5e29a294 846static void
2ac76861 847statCountersCopy(StatCounters * dest, const StatCounters * orig)
45eb7f49 848{
12cf1be2 849 assert(dest && orig);
1d803566 850 /* this should take care of all the fields, but "special" ones */
12cf1be2 851 memcpy(dest, orig, sizeof(*dest));
1d803566 852 /* prepare space where to copy special entries */
853 statCountersInitSpecial(dest);
854 /* now handle special cases */
855 /* note: we assert that histogram capacities do not change */
12cf1be2 856 statHistCopy(&dest->client_http.all_svc_time, &orig->client_http.all_svc_time);
857 statHistCopy(&dest->client_http.miss_svc_time, &orig->client_http.miss_svc_time);
858 statHistCopy(&dest->client_http.nm_svc_time, &orig->client_http.nm_svc_time);
859 statHistCopy(&dest->client_http.hit_svc_time, &orig->client_http.hit_svc_time);
860 statHistCopy(&dest->icp.query_svc_time, &orig->icp.query_svc_time);
861 statHistCopy(&dest->icp.reply_svc_time, &orig->icp.reply_svc_time);
862 statHistCopy(&dest->dns.svc_time, &orig->dns.svc_time);
df819896 863#if SQUID_PEER_DIGEST
864 statHistCopy(&dest->cd.client_svc_time, &orig->cd.client_svc_time);
865 statHistCopy(&dest->icp.client_svc_time, &orig->icp.client_svc_time);
866#endif
45eb7f49 867}
868
12cf1be2 869static void
870statCountersDump(StoreEntry * sentry)
7ae52c25 871{
12cf1be2 872 StatCounters *f = &Counter;
873 struct rusage rusage;
874 squid_getrusage(&rusage);
875 f->page_faults = rusage_pagefaults(&rusage);
876 f->cputime = rusage_cputime(&rusage);
877
a0f32775 878 storeAppendPrintf(sentry, "sample_time = %d.%d (%s)\n",
5f6ac48b 879 (int) f->timestamp.tv_sec,
880 (int) f->timestamp.tv_usec,
a0f32775 881 mkrfc1123(f->timestamp.tv_sec));
12cf1be2 882 storeAppendPrintf(sentry, "client_http.requests = %d\n",
883 f->client_http.requests);
884 storeAppendPrintf(sentry, "client_http.hits = %d\n",
885 f->client_http.hits);
886 storeAppendPrintf(sentry, "client_http.errors = %d\n",
887 f->client_http.errors);
888 storeAppendPrintf(sentry, "client_http.kbytes_in = %d\n",
889 (int) f->client_http.kbytes_in.kb);
890 storeAppendPrintf(sentry, "client_http.kbytes_out = %d\n",
891 (int) f->client_http.kbytes_out.kb);
0567f2a6 892
893#if TOO_MUCH_OUTPUT
12cf1be2 894 storeAppendPrintf(sentry, "client_http.all_svc_time histogram:\n");
895 statHistDump(&f->client_http.all_svc_time, sentry, NULL);
896 storeAppendPrintf(sentry, "client_http.miss_svc_time histogram:\n");
897 statHistDump(&f->client_http.miss_svc_time, sentry, NULL);
898 storeAppendPrintf(sentry, "client_http.nm_svc_time histogram:\n");
899 statHistDump(&f->client_http.nm_svc_time, sentry, NULL);
900 storeAppendPrintf(sentry, "client_http.hit_svc_time histogram:\n");
901 statHistDump(&f->client_http.hit_svc_time, sentry, NULL);
0567f2a6 902#endif
12cf1be2 903
a0f32775 904 storeAppendPrintf(sentry, "server.all.requests = %d\n",
905 (int) f->server.all.requests);
906 storeAppendPrintf(sentry, "server.all.errors = %d\n",
907 (int) f->server.all.errors);
908 storeAppendPrintf(sentry, "server.all.kbytes_in = %d\n",
909 (int) f->server.all.kbytes_in.kb);
910 storeAppendPrintf(sentry, "server.all.kbytes_out = %d\n",
911 (int) f->server.all.kbytes_out.kb);
912
913 storeAppendPrintf(sentry, "server.http.requests = %d\n",
914 (int) f->server.http.requests);
915 storeAppendPrintf(sentry, "server.http.errors = %d\n",
916 (int) f->server.http.errors);
917 storeAppendPrintf(sentry, "server.http.kbytes_in = %d\n",
918 (int) f->server.http.kbytes_in.kb);
919 storeAppendPrintf(sentry, "server.http.kbytes_out = %d\n",
920 (int) f->server.http.kbytes_out.kb);
921
922 storeAppendPrintf(sentry, "server.ftp.requests = %d\n",
923 (int) f->server.ftp.requests);
924 storeAppendPrintf(sentry, "server.ftp.errors = %d\n",
925 (int) f->server.ftp.errors);
926 storeAppendPrintf(sentry, "server.ftp.kbytes_in = %d\n",
927 (int) f->server.ftp.kbytes_in.kb);
928 storeAppendPrintf(sentry, "server.ftp.kbytes_out = %d\n",
929 (int) f->server.ftp.kbytes_out.kb);
930
931 storeAppendPrintf(sentry, "server.other.requests = %d\n",
932 (int) f->server.other.requests);
933 storeAppendPrintf(sentry, "server.other.errors = %d\n",
934 (int) f->server.other.errors);
935 storeAppendPrintf(sentry, "server.other.kbytes_in = %d\n",
936 (int) f->server.other.kbytes_in.kb);
937 storeAppendPrintf(sentry, "server.other.kbytes_out = %d\n",
938 (int) f->server.other.kbytes_out.kb);
12cf1be2 939
940 storeAppendPrintf(sentry, "icp.pkts_sent = %d\n",
941 f->icp.pkts_sent);
942 storeAppendPrintf(sentry, "icp.pkts_recv = %d\n",
943 f->icp.pkts_recv);
2e8e29b8 944 storeAppendPrintf(sentry, "icp.replies_queued = %d\n",
945 f->icp.replies_queued);
12cf1be2 946 storeAppendPrintf(sentry, "icp.kbytes_sent = %d\n",
947 (int) f->icp.kbytes_sent.kb);
948 storeAppendPrintf(sentry, "icp.kbytes_recv = %d\n",
949 (int) f->icp.kbytes_recv.kb);
0567f2a6 950
951#if TOO_MUCH_OUTPUT
12cf1be2 952 storeAppendPrintf(sentry, "icp.query_svc_time histogram:\n");
953 statHistDump(&f->icp.query_svc_time, sentry, NULL);
954 storeAppendPrintf(sentry, "icp.reply_svc_time histogram:\n");
955 statHistDump(&f->icp.reply_svc_time, sentry, NULL);
12cf1be2 956 storeAppendPrintf(sentry, "dns.svc_time histogram:\n");
957 statHistDump(&f->dns.svc_time, sentry, NULL);
0567f2a6 958#endif
959
12cf1be2 960 storeAppendPrintf(sentry, "unlink.requests = %d\n",
961 f->unlink.requests);
962 storeAppendPrintf(sentry, "page_faults = %d\n",
963 f->page_faults);
964 storeAppendPrintf(sentry, "select_loops = %d\n",
965 f->select_loops);
966 storeAppendPrintf(sentry, "cpu_time = %f\n",
967 f->cputime);
968 storeAppendPrintf(sentry, "wall_time = %f\n",
969 tvSubDsec(f->timestamp, current_time));
7ae52c25 970}
971
5e29a294 972static void
12cf1be2 973statCounters(StoreEntry * e)
7ae52c25 974{
12cf1be2 975 statCountersDump(e);
7ae52c25 976}
977
5e29a294 978static void
12cf1be2 979statAvg5min(StoreEntry * e)
7ae52c25 980{
a0f32775 981 statAvgDump(e, 5, 0);
7ae52c25 982}
983
5e29a294 984static void
12cf1be2 985statAvg60min(StoreEntry * e)
7ae52c25 986{
a0f32775 987 statAvgDump(e, 60, 0);
7ae52c25 988}
989
b87b92fb 990static double
991statMedianSvc(int interval, int which)
a9113eb0 992{
993 StatCounters *f;
994 StatCounters *l;
995 double x;
f8d264b8 996 assert(interval > 0);
997 if (interval > N_COUNT_HIST - 1)
998 interval = N_COUNT_HIST - 1;
a9113eb0 999 f = &CountHist[0];
1000 l = &CountHist[interval];
ee1679df 1001 assert(f);
1002 assert(l);
a9113eb0 1003 switch (which) {
b87b92fb 1004 case MEDIAN_HTTP:
12cf1be2 1005 x = statHistDeltaMedian(&l->client_http.all_svc_time, &f->client_http.all_svc_time);
ee1679df 1006 break;
b87b92fb 1007 case MEDIAN_HIT:
1008 x = statHistDeltaMedian(&l->client_http.hit_svc_time, &f->client_http.hit_svc_time);
1009 break;
1010 case MEDIAN_MISS:
1011 x = statHistDeltaMedian(&l->client_http.miss_svc_time, &f->client_http.miss_svc_time);
1012 break;
1013 case MEDIAN_NM:
1014 x = statHistDeltaMedian(&l->client_http.nm_svc_time, &f->client_http.nm_svc_time);
1015 break;
1016 case MEDIAN_ICP_QUERY:
12cf1be2 1017 x = statHistDeltaMedian(&l->icp.query_svc_time, &f->icp.query_svc_time);
ee1679df 1018 break;
b87b92fb 1019 case MEDIAN_DNS:
12cf1be2 1020 x = statHistDeltaMedian(&l->dns.svc_time, &f->dns.svc_time);
ee1679df 1021 break;
a9113eb0 1022 default:
ee1679df 1023 debug(49, 5) ("get_median_val: unknown type.\n");
1024 x = 0;
a9113eb0 1025 }
b87b92fb 1026 return x;
1027}
1028
1029/*
1030 * SNMP wants ints, ick
1031 */
1032int
1033get_median_svc(int interval, int which)
1034{
b644367b 1035 return (int) statMedianSvc(interval, which);
a9113eb0 1036}
451b07c5 1037
1038StatCounters *
1039snmpStatGet(int minutes)
1040{
2ac76861 1041 return &CountHist[minutes];
451b07c5 1042}
01aebf31 1043
1044
1045#if STAT_GRAPHS
1046/*
1047 * urgh, i don't like these, but they do cut the amount of code down immensely
1048 */
1049
1050#define GRAPH_PER_MIN(Y) \
1051 for (i=0;i<(N_COUNT_HIST-2);i++) { \
1052 dt = tvSubDsec(CountHist[i].timestamp, CountHist[i+1].timestamp); \
1053 if (dt <= 0.0) \
1054 break; \
1055 storeAppendPrintf(e, "%lu,%0.2f:", \
1056 CountHist[i].timestamp.tv_sec, \
1057 ((CountHist[i].Y - CountHist[i+1].Y) / dt)); \
1058 }
1059
1060#define GRAPH_PER_HOUR(Y) \
1061 for (i=0;i<(N_COUNT_HOUR_HIST-2);i++) { \
1062 dt = tvSubDsec(CountHourHist[i].timestamp, CountHourHist[i+1].timestamp); \
1063 if (dt <= 0.0) \
1064 break; \
1065 storeAppendPrintf(e, "%lu,%0.2f:", \
1066 CountHourHist[i].timestamp.tv_sec, \
1067 ((CountHourHist[i].Y - CountHourHist[i+1].Y) / dt)); \
1068 }
1069
1070#define GRAPH_TITLE(X,Y) storeAppendPrintf(e,"%s\t%s\t",X,Y);
1071#define GRAPH_END storeAppendPrintf(e,"\n");
1072
1073#define GENGRAPH(X,Y,Z) \
1074 GRAPH_TITLE(Y,Z) \
1075 GRAPH_PER_MIN(X) \
1076 GRAPH_PER_HOUR(X) \
1077 GRAPH_END
1078
1079static void
1080statGraphDump(StoreEntry * e)
1081{
1082 int i;
1083 double dt;
1084
1085 GENGRAPH(client_http.requests, "client_http.requests", "Client HTTP requests/sec");
1086 GENGRAPH(client_http.hits, "client_http.hits", "Client HTTP hits/sec");
1087 GENGRAPH(client_http.errors, "client_http.errors", "Client HTTP errors/sec");
1088 GENGRAPH(client_http.kbytes_in.kb, "client_http.kbytes_in", "Client HTTP kbytes_in/sec");
1089 GENGRAPH(client_http.kbytes_out.kb, "client_http.kbytes_out", "Client HTTP kbytes_out/sec");
1090
1091 /* XXX todo: http median service times */
1092
1093 GENGRAPH(server.all.requests, "server.all.requests", "Server requests/sec");
1094 GENGRAPH(server.all.errors, "server.all.errors", "Server errors/sec");
1095 GENGRAPH(server.all.kbytes_in.kb, "server.all.kbytes_in", "Server total kbytes_in/sec");
1096 GENGRAPH(server.all.kbytes_out.kb, "server.all.kbytes_out", "Server total kbytes_out/sec");
1097
1098 GENGRAPH(server.http.requests, "server.http.requests", "Server HTTP requests/sec");
1099 GENGRAPH(server.http.errors, "server.http.errors", "Server HTTP errors/sec");
1100 GENGRAPH(server.http.kbytes_in.kb, "server.http.kbytes_in", "Server HTTP kbytes_in/sec");
1101 GENGRAPH(server.http.kbytes_out.kb, "server.http.kbytes_out", "Server HTTP kbytes_out/sec");
1102
1103 GENGRAPH(server.ftp.requests, "server.ftp.requests", "Server FTP requests/sec");
1104 GENGRAPH(server.ftp.errors, "server.ftp.errors", "Server FTP errors/sec");
1105 GENGRAPH(server.ftp.kbytes_in.kb, "server.ftp.kbytes_in", "Server FTP kbytes_in/sec");
1106 GENGRAPH(server.ftp.kbytes_out.kb, "server.ftp.kbytes_out", "Server FTP kbytes_out/sec");
1107
1108 GENGRAPH(server.other.requests, "server.other.requests", "Server other requests/sec");
1109 GENGRAPH(server.other.errors, "server.other.errors", "Server other errors/sec");
1110 GENGRAPH(server.other.kbytes_in.kb, "server.other.kbytes_in", "Server other kbytes_in/sec");
1111 GENGRAPH(server.other.kbytes_out.kb, "server.other.kbytes_out", "Server other kbytes_out/sec");
1112
1113 GENGRAPH(icp.pkts_sent, "icp.pkts_sent", "ICP packets sent/sec");
1114 GENGRAPH(icp.pkts_recv, "icp.pkts_recv", "ICP packets received/sec");
1115 GENGRAPH(icp.kbytes_sent.kb, "icp.kbytes_sent", "ICP kbytes_sent/sec");
1116 GENGRAPH(icp.kbytes_recv.kb, "icp.kbytes_recv", "ICP kbytes_received/sec");
1117
1118 /* XXX todo: icp median service times */
1119 /* XXX todo: dns median service times */
1120
1121 GENGRAPH(unlink.requests, "unlink.requests", "Cache File unlink requests/sec");
1122 GENGRAPH(page_faults, "page_faults", "System Page Faults/sec");
1123 GENGRAPH(select_loops, "select_loops", "System Select Loop calls/sec");
1124 GENGRAPH(cputime, "cputime", "CPU utilisation");
1125}
1afe05c5 1126
01aebf31 1127#endif /* STAT_GRAPHS */