]> git.ipfire.org Git - thirdparty/squid.git/blame - src/stat.cc
rusage hacks if its not defined
[thirdparty/squid.git] / src / stat.cc
CommitLineData
e5f6c5c2 1
30a4f2a8 2/*
f2908497 3 * $Id: stat.cc,v 1.172 1997/11/15 00:14:51 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 *);
114static void proto_count(cacheinfo *, protocol_t, log_type);
115static void proto_newobject(cacheinfo *, protocol_t, int, int);
116static void proto_purgeobject(cacheinfo *, protocol_t, int);
117static void proto_touchobject(cacheinfo *, protocol_t, int);
118static int memoryAccounted(void);
f2908497 119static void statAvgTick(void *notused);
20882fb1 120
20882fb1 121#ifdef XMALLOC_STATISTICS
f5b8bbc4 122static void info_get_mallstat(int, int, StoreEntry *);
20882fb1 123#endif
30a4f2a8 124
6605655c 125#define PCONN_HIST_SZ 256
126int client_pconn_hist[PCONN_HIST_SZ];
b716a8ad 127int server_pconn_hist[PCONN_HIST_SZ];
6605655c 128
f2908497 129#define N_DELTAS 5
130static StatCounters Deltas[N_DELTAS];
131
090089c4 132/* process utilization information */
b8d8561b 133static void
6684fec0 134statUtilization(cacheinfo * obj, StoreEntry * sentry, const char *desc)
090089c4 135{
8213067d 136 protocol_t proto_id;
137 proto_stat *p = &obj->proto_stat_data[PROTO_MAX];
090089c4 138 proto_stat *q = NULL;
139 int secs = 0;
f2908497 140 secs = (int) (squid_curtime - squid_start.tv_sec);
a528eb87 141 storeAppendPrintf(sentry, "{ %s\n", desc); /* } */
234967c9 142 strcpy(p->protoname, "TOTAL");
090089c4 143 p->object_count = 0;
144 p->kb.max = 0;
145 p->kb.min = 0;
146 p->kb.avg = 0;
147 p->kb.now = 0;
148 p->hit = 0;
149 p->miss = 0;
150 p->refcount = 0;
151 p->transferbyte = 0;
090089c4 152 /* find the total */
30a4f2a8 153 for (proto_id = PROTO_NONE; proto_id < PROTO_MAX; ++proto_id) {
090089c4 154 q = &obj->proto_stat_data[proto_id];
090089c4 155 p->object_count += q->object_count;
156 p->kb.max += q->kb.max;
157 p->kb.min += q->kb.min;
158 p->kb.avg += q->kb.avg;
159 p->kb.now += q->kb.now;
160 p->hit += q->hit;
161 p->miss += q->miss;
162 p->refcount += q->refcount;
163 p->transferbyte += q->transferbyte;
164 }
090089c4 165 /* dump it */
30a4f2a8 166 for (proto_id = PROTO_NONE; proto_id <= PROTO_MAX; ++proto_id) {
090089c4 167 p = &obj->proto_stat_data[proto_id];
168 if (p->hit != 0) {
169 p->hitratio =
170 (float) p->hit /
171 ((float) p->hit +
172 (float) p->miss);
173 }
30a4f2a8 174 storeAppendPrintf(sentry, "{%8.8s %d %d %d %d %4.2f %d %d %d}\n",
090089c4 175 p->protoname,
176 p->object_count,
177 p->kb.max,
178 p->kb.now,
179 p->kb.min,
180 p->hitratio,
181 (secs ? p->transferbyte / secs : 0),
182 p->refcount,
183 p->transferbyte);
090089c4 184 }
30a4f2a8 185 storeAppendPrintf(sentry, close_bracket);
186}
187
6684fec0 188void
603a02fd 189stat_utilization_get(StoreEntry * e)
6684fec0 190{
603a02fd 191 statUtilization(HTTPCacheInfo, e, "HTTP");
192 statUtilization(ICPCacheInfo, e, "ICP");
6684fec0 193}
194
195void
b8d8561b 196stat_io_get(StoreEntry * sentry)
30a4f2a8 197{
198 int i;
199
200 storeAppendPrintf(sentry, open_bracket);
201 storeAppendPrintf(sentry, "{HTTP I/O}\n");
202 storeAppendPrintf(sentry, "{number of reads: %d}\n", IOStats.Http.reads);
203 storeAppendPrintf(sentry, "{deferred reads: %d (%d%%)}\n",
204 IOStats.Http.reads_deferred,
205 percent(IOStats.Http.reads_deferred, IOStats.Http.reads));
206 storeAppendPrintf(sentry, "{Read Histogram:}\n");
207 for (i = 0; i < 16; i++) {
208 storeAppendPrintf(sentry, "{%5d-%5d: %9d %2d%%}\n",
209 i ? (1 << (i - 1)) + 1 : 1,
210 1 << i,
211 IOStats.Http.read_hist[i],
212 percent(IOStats.Http.read_hist[i], IOStats.Http.reads));
213 }
214
215 storeAppendPrintf(sentry, "{}\n");
216 storeAppendPrintf(sentry, "{FTP I/O}\n");
217 storeAppendPrintf(sentry, "{number of reads: %d}\n", IOStats.Ftp.reads);
218 storeAppendPrintf(sentry, "{deferred reads: %d (%d%%)}\n",
219 IOStats.Ftp.reads_deferred,
220 percent(IOStats.Ftp.reads_deferred, IOStats.Ftp.reads));
221 storeAppendPrintf(sentry, "{Read Histogram:}\n");
222 for (i = 0; i < 16; i++) {
223 storeAppendPrintf(sentry, "{%5d-%5d: %9d %2d%%}\n",
224 i ? (1 << (i - 1)) + 1 : 1,
225 1 << i,
226 IOStats.Ftp.read_hist[i],
227 percent(IOStats.Ftp.read_hist[i], IOStats.Ftp.reads));
228 }
229
56fa4cad 230 storeAppendPrintf(sentry, "{}\n");
231 storeAppendPrintf(sentry, "{Gopher I/O}\n");
232 storeAppendPrintf(sentry, "{number of reads: %d}\n", IOStats.Gopher.reads);
233 storeAppendPrintf(sentry, "{deferred reads: %d (%d%%)}\n",
234 IOStats.Gopher.reads_deferred,
235 percent(IOStats.Gopher.reads_deferred, IOStats.Gopher.reads));
236 storeAppendPrintf(sentry, "{Read Histogram:}\n");
237 for (i = 0; i < 16; i++) {
238 storeAppendPrintf(sentry, "{%5d-%5d: %9d %2d%%}\n",
239 i ? (1 << (i - 1)) + 1 : 1,
240 1 << i,
241 IOStats.Gopher.read_hist[i],
242 percent(IOStats.Gopher.read_hist[i], IOStats.Gopher.reads));
243 }
244
245 storeAppendPrintf(sentry, "{}\n");
246 storeAppendPrintf(sentry, "{WAIS I/O}\n");
247 storeAppendPrintf(sentry, "{number of reads: %d}\n", IOStats.Wais.reads);
248 storeAppendPrintf(sentry, "{deferred reads: %d (%d%%)}\n",
249 IOStats.Wais.reads_deferred,
250 percent(IOStats.Wais.reads_deferred, IOStats.Wais.reads));
251 storeAppendPrintf(sentry, "{Read Histogram:}\n");
252 for (i = 0; i < 16; i++) {
253 storeAppendPrintf(sentry, "{%5d-%5d: %9d %2d%%}\n",
254 i ? (1 << (i - 1)) + 1 : 1,
255 1 << i,
256 IOStats.Wais.read_hist[i],
257 percent(IOStats.Wais.read_hist[i], IOStats.Wais.reads));
258 }
259
30a4f2a8 260 storeAppendPrintf(sentry, close_bracket);
090089c4 261}
262
0ee4272b 263static const char *
fe4e214f 264describeStatuses(const StoreEntry * entry)
d1a43e28 265{
266 LOCAL_ARRAY(char, buf, 256);
56878878 267 snprintf(buf, 256, "%-13s %-13s %-12s %-12s",
d1a43e28 268 storeStatusStr[entry->store_status],
269 memStatusStr[entry->mem_status],
270 swapStatusStr[entry->swap_status],
271 pingStatusStr[entry->ping_status]);
272 return buf;
273}
274
0ee4272b 275static const char *
fe4e214f 276describeFlags(const StoreEntry * entry)
d1a43e28 277{
278 LOCAL_ARRAY(char, buf, 256);
279 int flags = (int) entry->flag;
280 char *t;
281 buf[0] = '\0';
79a15e0a 282 if (EBIT_TEST(flags, DELAY_SENDING))
d1a43e28 283 strcat(buf, "DS,");
79a15e0a 284 if (EBIT_TEST(flags, RELEASE_REQUEST))
d1a43e28 285 strcat(buf, "RL,");
79a15e0a 286 if (EBIT_TEST(flags, REFRESH_REQUEST))
d1a43e28 287 strcat(buf, "RF,");
79a15e0a 288 if (EBIT_TEST(flags, ENTRY_CACHABLE))
d1a43e28 289 strcat(buf, "EC,");
79a15e0a 290 if (EBIT_TEST(flags, ENTRY_DISPATCHED))
d1a43e28 291 strcat(buf, "ED,");
79a15e0a 292 if (EBIT_TEST(flags, KEY_PRIVATE))
d1a43e28 293 strcat(buf, "KP,");
79a15e0a 294 if (EBIT_TEST(flags, HIERARCHICAL))
d1a43e28 295 strcat(buf, "HI,");
79a15e0a 296 if (EBIT_TEST(flags, ENTRY_NEGCACHED))
d1a43e28 297 strcat(buf, "NG,");
d1a43e28 298 if ((t = strrchr(buf, ',')))
299 *t = '\0';
300 return buf;
301}
302
0ee4272b 303static const char *
fe4e214f 304describeTimestamps(const StoreEntry * entry)
d1a43e28 305{
306 LOCAL_ARRAY(char, buf, 256);
56878878 307 snprintf(buf, 256, "LV:%-9d LU:%-9d LM:%-9d EX:%-9d",
d1a43e28 308 (int) entry->timestamp,
309 (int) entry->lastref,
310 (int) entry->lastmod,
311 (int) entry->expires);
312 return buf;
313}
314
090089c4 315/* process objects list */
b8d8561b 316static void
6684fec0 317statObjects(StoreEntry * sentry, int vm_or_not)
090089c4 318{
09610784 319 StoreEntry *entry = NULL;
d1a43e28 320 MemObject *mem;
090089c4 321 int N = 0;
637ed800 322 int i;
323 struct _store_client *sc;
d1a43e28 324 for (entry = storeGetFirst(); entry != NULL; entry = storeGetNext()) {
325 mem = entry->mem_obj;
326 if (vm_or_not && mem == NULL)
090089c4 327 continue;
328 if ((++N & 0xFF) == 0) {
a3d5953d 329 debug(18, 3) ("stat_objects_get: Processed %d objects...\n", N);
090089c4 330 }
79a15e0a 331 EBIT_SET(sentry->flag, DELAY_SENDING);
24ffafb4 332 storeAppendPrintf(sentry, "KEY %s\n", storeKeyText(entry->key));
333 storeAppendPrintf(sentry, "\t%s %s\n",
9fb13bb6 334 RequestMethodStr[entry->method], storeUrl(entry));
637ed800 335 storeAppendPrintf(sentry, "\t%s\n", describeStatuses(entry));
336 storeAppendPrintf(sentry, "\t%s\n", describeFlags(entry));
337 storeAppendPrintf(sentry, "\t%s\n", describeTimestamps(entry));
338 storeAppendPrintf(sentry, "\t%d locks, %d clients, %d refs\n",
339 (int) entry->lock_count,
340 storePendingNClients(entry),
341 (int) entry->refcount);
342 storeAppendPrintf(sentry, "\tSwap File %#08X\n",
343 entry->swap_file_number);
344 if (mem == NULL)
345 continue;
346 storeAppendPrintf(sentry, "\tinmem_lo: %d\n", (int) mem->inmem_lo);
347 storeAppendPrintf(sentry, "\tinmem_hi: %d\n", (int) mem->inmem_hi);
348 storeAppendPrintf(sentry, "\tswapout: %d bytes done, %d queued, FD %d\n",
349 mem->swapout.done_offset,
350 mem->swapout.queue_offset,
351 mem->swapout.fd);
352 for (i = 0; i < mem->nclients; i++) {
353 sc = &mem->clients[i];
354 if (sc->callback_data == NULL)
355 continue;
356 storeAppendPrintf(sentry, "\tClient #%d\n", i);
357 storeAppendPrintf(sentry, "\t\tcopy_offset: %d\n",
358 (int) sc->copy_offset);
359 storeAppendPrintf(sentry, "\t\tseen_offset: %d\n",
360 (int) sc->seen_offset);
361 storeAppendPrintf(sentry, "\t\tcopy_size: %d\n",
362 (int) sc->copy_size);
363 storeAppendPrintf(sentry, "\t\tswapin_fd: %d\n",
364 (int) sc->swapin_fd);
365 }
79a15e0a 366 EBIT_CLR(sentry->flag, DELAY_SENDING);
24ffafb4 367 storeAppendPrintf(sentry, "\n");
090089c4 368 }
090089c4 369}
370
03eb2f01 371void
603a02fd 372stat_objects_get(StoreEntry * e)
090089c4 373{
603a02fd 374 statObjects(e, 0);
6684fec0 375}
090089c4 376
6684fec0 377void
603a02fd 378stat_vmobjects_get(StoreEntry * e)
6684fec0 379{
603a02fd 380 statObjects(e, 1);
090089c4 381}
382
03eb2f01 383void
384server_list(StoreEntry * sentry)
e102ebda 385{
386 dump_peers(sentry, Config.peers);
387}
388
389void
390dump_peers(StoreEntry * sentry, peer * peers)
090089c4 391{
deb79f06 392 peer *e = NULL;
b012353a 393 struct _domain_ping *d = NULL;
30a4f2a8 394 icp_opcode op;
30a4f2a8 395 storeAppendPrintf(sentry, open_bracket);
e102ebda 396 if (peers == NULL)
c30c5a73 397 storeAppendPrintf(sentry, "{There are no neighbors installed.}\n");
e102ebda 398 for (e = peers; e; e = e->next) {
399 assert(e->host != NULL);
30a4f2a8 400 storeAppendPrintf(sentry, "\n{%-11.11s: %s/%d/%d}\n",
0c77d853 401 neighborTypeStr(e),
30a4f2a8 402 e->host,
403 e->http_port,
404 e->icp_port);
405 storeAppendPrintf(sentry, "{Status : %s}\n",
5269d0bd 406 neighborUp(e) ? "Up" : "Down");
30a4f2a8 407 storeAppendPrintf(sentry, "{AVG RTT : %d msec}\n", e->stats.rtt);
408 storeAppendPrintf(sentry, "{ACK DEFICIT: %8d}\n", e->stats.ack_deficit);
409 storeAppendPrintf(sentry, "{PINGS SENT : %8d}\n", e->stats.pings_sent);
410 storeAppendPrintf(sentry, "{PINGS ACKED: %8d %3d%%}\n",
411 e->stats.pings_acked,
412 percent(e->stats.pings_acked, e->stats.pings_sent));
0c77d853 413 storeAppendPrintf(sentry, "{FETCHES : %8d %3d%%}\n",
414 e->stats.fetches,
415 percent(e->stats.fetches, e->stats.pings_acked));
a7e59001 416 storeAppendPrintf(sentry, "{IGNORED : %8d %3d%%}\n",
417 e->stats.ignored_replies,
418 percent(e->stats.ignored_replies, e->stats.pings_acked));
30a4f2a8 419 storeAppendPrintf(sentry, "{Histogram of PINGS ACKED:}\n");
420 for (op = ICP_OP_INVALID; op < ICP_OP_END; op++) {
421 if (e->stats.counts[op] == 0)
422 continue;
0c77d853 423 storeAppendPrintf(sentry, "{ %12.12s : %8d %3d%%}\n",
30a4f2a8 424 IcpOpcodeStr[op],
425 e->stats.counts[op],
426 percent(e->stats.counts[op], e->stats.pings_acked));
427 }
090089c4 428 if (e->last_fail_time) {
c30c5a73 429 storeAppendPrintf(sentry, "{Last failed connect() at: %s}\n",
090089c4 430 mkhttpdlogtime(&(e->last_fail_time)));
090089c4 431 }
c30c5a73 432 storeAppendPrintf(sentry, "{DOMAIN LIST: ");
b012353a 433 for (d = e->pinglist; d; d = d->next) {
090089c4 434 if (d->do_ping)
c30c5a73 435 storeAppendPrintf(sentry, "%s ", d->domain);
090089c4 436 else
c30c5a73 437 storeAppendPrintf(sentry, "!%s ", d->domain);
090089c4 438 }
30a4f2a8 439 storeAppendPrintf(sentry, close_bracket); /* } */
9a75cc4d 440 storeAppendPrintf(sentry, "{Keep-Alive Ratio: %d%%}\n",
79d39a72 441 percent(e->stats.n_keepalives_recv, e->stats.n_keepalives_sent));
090089c4 442 }
30a4f2a8 443 storeAppendPrintf(sentry, close_bracket);
090089c4 444}
445
0a0bf5db 446#ifdef XMALLOC_STATISTICS
b8d8561b 447static void
0a0bf5db 448info_get_mallstat(int size, int number, StoreEntry * sentry)
30a4f2a8 449{
30a4f2a8 450 if (number > 0)
451 storeAppendPrintf(sentry, "{\t%d = %d}\n", size, number);
452}
453#endif
090089c4 454
0ee4272b 455static const char *
f1dc9b30 456fdRemoteAddr(const fde * f)
d51e52f5 457{
95d659f0 458 LOCAL_ARRAY(char, buf, 32);
4f92c80c 459 if (f->type != FD_SOCKET)
460 return null_string;
042461c3 461 snprintf(buf, 32, "%s.%d", f->ipaddr, (int) f->remote_port);
d2af9477 462 return buf;
d51e52f5 463}
464
6684fec0 465void
b8d8561b 466statFiledescriptors(StoreEntry * sentry)
d51e52f5 467{
468 int i;
f1dc9b30 469 fde *f;
d51e52f5 470 storeAppendPrintf(sentry, open_bracket);
471 storeAppendPrintf(sentry, "{Active file descriptors:}\n");
4f92c80c 472 storeAppendPrintf(sentry, "{%-4s %-6s %-4s %-7s %-7s %-21s %s}\n",
d51e52f5 473 "File",
474 "Type",
d51e52f5 475 "Tout",
4f92c80c 476 "Nread",
477 "Nwrite",
d51e52f5 478 "Remote Address",
479 "Description");
4f92c80c 480 storeAppendPrintf(sentry, "{---- ------ ---- ------- ------- --------------------- ------------------------------}\n");
e83892e9 481 for (i = 0; i < Squid_MaxFD; i++) {
429fdbec 482 f = &fd_table[i];
5c5783a2 483 if (!f->open)
d51e52f5 484 continue;
4f92c80c 485 storeAppendPrintf(sentry, "{%4d %-6.6s %4d %7d %7d %-21s %s}\n",
d2af9477 486 i,
4f92c80c 487 fdstatTypeStr[f->type],
488 f->timeout_handler ? (f->timeout - squid_curtime) / 60 : 0,
489 f->bytes_read,
490 f->bytes_written,
491 fdRemoteAddr(f),
492 f->desc);
d51e52f5 493 }
494 storeAppendPrintf(sentry, close_bracket);
495}
496
b8d8561b 497static int
0673c0ba 498memoryAccounted(void)
1a082686 499{
92a8c005 500 return (int)
501 meta_data.store_entries * sizeof(StoreEntry) +
9fb13bb6 502 meta_data.store_keys +
92a8c005 503 meta_data.ipcache_count * sizeof(ipcache_entry) +
f88bb09c 504 meta_data.fqdncache_count * sizeof(fqdncache_entry) +
b15fe823 505 hash_links_allocated * sizeof(hash_link) +
92a8c005 506 sm_stats.total_pages_allocated * sm_stats.page_size +
507 disk_stats.total_pages_allocated * disk_stats.page_size +
508 request_pool.total_pages_allocated * request_pool.page_size +
509 mem_obj_pool.total_pages_allocated * mem_obj_pool.page_size +
3e12e062 510 meta_data.netdb_addrs * sizeof(netdbEntry) +
511 meta_data.netdb_hosts * sizeof(struct _net_db_name) +
429fdbec 512 meta_data.netdb_peers * sizeof(struct _net_db_peer) +
f6c78bd2 513 meta_data.client_info * client_info_sz +
f6610c4e 514 meta_data.misc;
1a082686 515}
516
03eb2f01 517void
518info_get(StoreEntry * sentry)
090089c4 519{
090089c4 520 struct rusage rusage;
f2908497 521 double cputime;
522 double runtime;
88738790 523#if HAVE_MSTATS && HAVE_GNUMALLOC_H
524 struct mstats ms;
525#elif HAVE_MALLINFO
090089c4 526 struct mallinfo mp;
88738790 527 int t;
090089c4 528#endif
529
f2908497 530 runtime = tvSubDsec(squid_start, current_time);
531 if (runtime == 0.0)
532 runtime = 1.0;
30a4f2a8 533 storeAppendPrintf(sentry, open_bracket);
d51e52f5 534 storeAppendPrintf(sentry, "{Squid Object Cache: Version %s}\n",
535 version_string);
f2908497 536 storeAppendPrintf(sentry, "{Start Time:\t%s}\n",
537 mkrfc1123(squid_start.tv_sec));
538 storeAppendPrintf(sentry, "{Current Time:\t%s}\n",
539 mkrfc1123(current_time.tv_sec));
d51e52f5 540 storeAppendPrintf(sentry, "{Connection information for %s:}\n",
541 appname);
f2908497 542 storeAppendPrintf(sentry, "{\tNumber of HTTP requests received:\t%u}\n",
543 Counter.client_http.requests);
544 storeAppendPrintf(sentry, "{\tNumber of ICP messages received:\t%u}\n",
545 Counter.icp.pkts_recv);
546 storeAppendPrintf(sentry, "{\tNumber of ICP messages sent:\t%u}\n",
547 Counter.icp.pkts_sent);
548
549 storeAppendPrintf(sentry, "{\tHTTP requests per minute:\t%.1f}\n",
550 Counter.client_http.requests / (runtime / 60.0));
551 storeAppendPrintf(sentry, "{\tICP messages per minute:\t%.1f}\n",
552 (Counter.icp.pkts_sent + Counter.icp.pkts_recv) / (runtime / 60.0));
429fdbec 553 storeAppendPrintf(sentry, "{\tSelect loop called: %d times, %0.3f ms avg}\n",
f2908497 554 Counter.select_loops, 1000.0 * runtime / Counter.select_loops);
090089c4 555
30a4f2a8 556 storeAppendPrintf(sentry, "{Cache information for %s:}\n",
557 appname);
c932b107 558 storeAppendPrintf(sentry, "{\tStorage Swap size:\t%d KB}\n",
559 store_swap_size);
30a4f2a8 560 storeAppendPrintf(sentry, "{\tStorage Mem size:\t%d KB}\n",
e954773d 561 store_mem_size >> 10);
10cab007 562 storeAppendPrintf(sentry, "{\tStorage LRU Expiration Age:\t%6.2f days}\n",
52cd89fd 563 (double) storeExpiredReferenceAge() / 86400.0);
429fdbec 564 storeAppendPrintf(sentry, "{\tRequests given to unlinkd:\t%d}\n",
f2908497 565 Counter.unlink.requests);
429fdbec 566 storeAppendPrintf(sentry, "{\tUnused fileno stack count:\t%d}\n",
567 fileno_stack_count);
090089c4 568
f2908497 569 squid_getrusage(&rusage);
570 cputime = rusage_cputime(&rusage);
c30c5a73 571 storeAppendPrintf(sentry, "{Resource usage for %s:}\n", appname);
f2908497 572 storeAppendPrintf(sentry, "{\tUP Time:\t%.3f seconds}\n", runtime);
573 storeAppendPrintf(sentry, "{\tCPU Time:\t%.3f seconds}\n", cputime);
574 storeAppendPrintf(sentry, "{\tCPU Usage:\t%d%%}\n",
575 dpercent(cputime, runtime));
1fe4a4e1 576 storeAppendPrintf(sentry, "{\tMaximum Resident Size: %ld KB}\n",
f2908497 577 rusage_maxrss(&rusage));
30a4f2a8 578 storeAppendPrintf(sentry, "{\tPage faults with physical i/o: %ld}\n",
f2908497 579 rusage_pagefaults(&rusage));
090089c4 580
88738790 581#if HAVE_MSTATS && HAVE_GNUMALLOC_H
582 ms = mstats();
583 storeAppendPrintf(sentry, "{Memory usage for %s via mstats():}\n",
584 appname);
585 storeAppendPrintf(sentry, "{\tTotal space in arena: %6d KB}\n",
586 ms.bytes_total >> 10);
587 storeAppendPrintf(sentry, "{\tTotal free: %6d KB %d%%}\n",
588 ms.bytes_free >> 10, percent(ms.bytes_free, ms.bytes_total));
589#elif HAVE_MALLINFO
090089c4 590 mp = mallinfo();
d51e52f5 591 storeAppendPrintf(sentry, "{Memory usage for %s via mallinfo():}\n",
592 appname);
30a4f2a8 593 storeAppendPrintf(sentry, "{\tTotal space in arena: %6d KB}\n",
b560dd20 594 mp.arena >> 10);
30a4f2a8 595 storeAppendPrintf(sentry, "{\tOrdinary blocks: %6d KB %6d blks}\n",
596 mp.uordblks >> 10, mp.ordblks);
597 storeAppendPrintf(sentry, "{\tSmall blocks: %6d KB %6d blks}\n",
598 mp.usmblks >> 10, mp.smblks);
599 storeAppendPrintf(sentry, "{\tHolding blocks: %6d KB %6d blks}\n",
600 mp.hblkhd >> 10, mp.hblks);
601 storeAppendPrintf(sentry, "{\tFree Small blocks: %6d KB}\n",
602 mp.fsmblks >> 10);
603 storeAppendPrintf(sentry, "{\tFree Ordinary blocks: %6d KB}\n",
604 mp.fordblks >> 10);
605 t = mp.uordblks + mp.usmblks + mp.hblkhd;
606 storeAppendPrintf(sentry, "{\tTotal in use: %6d KB %d%%}\n",
607 t >> 10, percent(t, mp.arena));
608 t = mp.fsmblks + mp.fordblks;
609 storeAppendPrintf(sentry, "{\tTotal free: %6d KB %d%%}\n",
610 t >> 10, percent(t, mp.arena));
46c883ed 611#if HAVE_EXT_MALLINFO
c30c5a73 612 storeAppendPrintf(sentry, "{\tmax size of small blocks:\t%d}\n", mp.mxfast);
613 storeAppendPrintf(sentry, "{\tnumber of small blocks in a holding block:\t%d}\n",
090089c4 614 mp.nlblks);
c30c5a73 615 storeAppendPrintf(sentry, "{\tsmall block rounding factor:\t%d}\n", mp.grain);
616 storeAppendPrintf(sentry, "{\tspace (including overhead) allocated in ord. blks:\t%d}\n"
090089c4 617 ,mp.uordbytes);
c30c5a73 618 storeAppendPrintf(sentry, "{\tnumber of ordinary blocks allocated:\t%d}\n",
090089c4 619 mp.allocated);
c30c5a73 620 storeAppendPrintf(sentry, "{\tbytes used in maintaining the free tree:\t%d}\n",
090089c4 621 mp.treeoverhead);
46c883ed 622#endif /* HAVE_EXT_MALLINFO */
50bc2565 623#endif /* HAVE_MALLINFO */
090089c4 624
c30c5a73 625 storeAppendPrintf(sentry, "{File descriptor usage for %s:}\n", appname);
88738790 626 storeAppendPrintf(sentry, "{\tMaximum number of file descriptors: %4d}\n",
e83892e9 627 Squid_MaxFD);
30a4f2a8 628 storeAppendPrintf(sentry, "{\tLargest file desc currently in use: %4d}\n",
429fdbec 629 Biggest_FD);
88738790 630 storeAppendPrintf(sentry, "{\tNumber of file desc currently in use: %4d}\n",
631 Number_FD);
30a4f2a8 632 storeAppendPrintf(sentry, "{\tAvailable number of file descriptors: %4d}\n",
88738790 633 Squid_MaxFD - Number_FD);
30a4f2a8 634 storeAppendPrintf(sentry, "{\tReserved number of file descriptors: %4d}\n",
090089c4 635 RESERVED_FD);
090089c4 636
c30c5a73 637 storeAppendPrintf(sentry, "{Internal Data Structures:}\n");
c31201c6 638 storeAppendPrintf(sentry, "{\t%6d StoreEntries}\n",
639 meta_data.store_entries);
640 storeAppendPrintf(sentry, "{\t%6d StoreEntries with MemObjects}\n",
641 meta_data.mem_obj_count);
642 storeAppendPrintf(sentry, "{\t%6d StoreEntries with MemObject Data}\n",
643 meta_data.mem_data_count);
644 storeAppendPrintf(sentry, "{\t%6d Hot Object Cache Items}\n",
30a4f2a8 645 meta_data.hot_vm);
30a4f2a8 646
c31201c6 647 storeAppendPrintf(sentry, "{Accounted Memory Usage:}\n");
30a4f2a8 648 storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB}\n",
649 "StoreEntry",
cff333e8 650 meta_data.store_entries,
651 (int) sizeof(StoreEntry),
0d5fc38a 652 (int) (meta_data.store_entries * sizeof(StoreEntry) >> 10));
cff333e8 653
a6f3a003 654 storeAppendPrintf(sentry, "{\t%-25.25s = %6d KB}\n",
9fb13bb6 655 "StoreEntry Keys",
656 meta_data.store_keys >> 10);
a6f3a003 657
30a4f2a8 658 storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB}\n",
659 "IPCacheEntry",
cff333e8 660 meta_data.ipcache_count,
661 (int) sizeof(ipcache_entry),
0d5fc38a 662 (int) (meta_data.ipcache_count * sizeof(ipcache_entry) >> 10));
cff333e8 663
f88bb09c 664 storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB}\n",
665 "FQDNCacheEntry",
666 meta_data.fqdncache_count,
667 (int) sizeof(fqdncache_entry),
668 (int) (meta_data.fqdncache_count * sizeof(fqdncache_entry) >> 10));
669
30a4f2a8 670 storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB}\n",
671 "Hash link",
b15fe823 672 hash_links_allocated,
cff333e8 673 (int) sizeof(hash_link),
b15fe823 674 (int) (hash_links_allocated * sizeof(hash_link) >> 10));
cff333e8 675
30a4f2a8 676 storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB (%6d free)}\n",
677 "Pool MemObject structures",
678 mem_obj_pool.total_pages_allocated,
679 mem_obj_pool.page_size,
680 mem_obj_pool.total_pages_allocated * mem_obj_pool.page_size >> 10,
681 (mem_obj_pool.total_pages_allocated - mem_obj_pool.n_pages_in_use) * mem_obj_pool.page_size >> 10);
682
683 storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB (%6d free)}\n",
684 "Pool for Request structures",
685 request_pool.total_pages_allocated,
686 request_pool.page_size,
687 request_pool.total_pages_allocated * request_pool.page_size >> 10,
688 (request_pool.total_pages_allocated - request_pool.n_pages_in_use) * request_pool.page_size >> 10);
689
690 storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB (%6d free)}\n",
691 "Pool for in-memory object data",
692 sm_stats.total_pages_allocated,
693 sm_stats.page_size,
694 sm_stats.total_pages_allocated * sm_stats.page_size >> 10,
695 (sm_stats.total_pages_allocated - sm_stats.n_pages_in_use) * sm_stats.page_size >> 10);
cff333e8 696
30a4f2a8 697 storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB (%6d free)}\n",
698 "Pool for disk I/O",
699 disk_stats.total_pages_allocated,
700 disk_stats.page_size,
cff333e8 701 disk_stats.total_pages_allocated * disk_stats.page_size >> 10,
702 (disk_stats.total_pages_allocated - disk_stats.n_pages_in_use) * disk_stats.page_size >> 10);
cff333e8 703
82696127 704 storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB}\n",
3e12e062 705 "NetDB Address Entries",
706 meta_data.netdb_addrs,
82696127 707 (int) sizeof(netdbEntry),
3e12e062 708 (int) (meta_data.netdb_addrs * sizeof(netdbEntry) >> 10));
709
710 storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB}\n",
711 "NetDB Host Entries",
712 meta_data.netdb_hosts,
713 (int) sizeof(struct _net_db_name),
f6610c4e 714 (int) (meta_data.netdb_hosts * sizeof(struct _net_db_name) >> 10));
e97f40f4 715
429fdbec 716 storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB}\n",
717 "NetDB Peer Entries",
718 meta_data.netdb_peers,
719 (int) sizeof(struct _net_db_peer),
720 (int) (meta_data.netdb_peers * sizeof(struct _net_db_peer) >> 10));
721
5ecceaa4 722 storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB}\n",
723 "ClientDB Entries",
724 meta_data.client_info,
725 client_info_sz,
726 (int) (meta_data.client_info * client_info_sz >> 10));
82696127 727
30a4f2a8 728 storeAppendPrintf(sentry, "{\t%-25.25s = %6d KB}\n",
729 "Miscellaneous",
730 meta_data.misc >> 10);
cff333e8 731
30a4f2a8 732 storeAppendPrintf(sentry, "{\t%-25.25s = %6d KB}\n",
733 "Total Accounted",
1a082686 734 memoryAccounted() >> 10);
30a4f2a8 735
736#if XMALLOC_STATISTICS
737 storeAppendPrintf(sentry, "{Memory allocation statistics}\n");
738 malloc_statistics(info_get_mallstat, sentry);
739#endif
090089c4 740
30a4f2a8 741 storeAppendPrintf(sentry, close_bracket);
090089c4 742}
743
b8d8561b 744static void
745proto_newobject(cacheinfo * obj, protocol_t proto_id, int size, int restart)
090089c4 746{
747 proto_stat *p = &obj->proto_stat_data[proto_id];
748
749 p->object_count++;
750
751 /* Account for 1KB granularity */
752 p->kb.now += ((size + 1023) >> 10);
753
754 if (p->kb.now > p->kb.max)
755 p->kb.max = p->kb.now;
756 if (restart)
757 p->kb.min = p->kb.now;
758}
759
760
b8d8561b 761static void
762proto_purgeobject(cacheinfo * obj, protocol_t proto_id, int size)
090089c4 763{
764 proto_stat *p = &obj->proto_stat_data[proto_id];
765
766 p->object_count--;
767
768 /* Scale down to KB */
769 p->kb.now -= ((size + 1023) >> 10);
770
771 if (p->kb.now < p->kb.min)
772 p->kb.min = p->kb.now;
773}
774
775/* update stat for each particular protocol when an object is fetched */
b8d8561b 776static void
777proto_touchobject(cacheinfo * obj, protocol_t proto_id, int size)
090089c4 778{
779 obj->proto_stat_data[proto_id].refcount++;
780 obj->proto_stat_data[proto_id].transferbyte += (1023 + size) >> 10;
781}
782
b8d8561b 783static void
784proto_count(cacheinfo * obj, protocol_t proto_id, log_type type)
090089c4 785{
a528eb87 786 switch (type) {
787 case LOG_TCP_HIT:
788 case LOG_TCP_IMS_HIT:
38792624 789 case LOG_TCP_REFRESH_HIT:
790 case LOG_TCP_REFRESH_FAIL_HIT:
a528eb87 791 case LOG_UDP_HIT:
792 case LOG_UDP_HIT_OBJ:
793 obj->proto_stat_data[proto_id].hit++;
794 break;
795 default:
796 obj->proto_stat_data[proto_id].miss++;
797 break;
798 }
090089c4 799}
800
090089c4 801
b8d8561b 802void
fe4e214f 803stat_init(cacheinfo ** object, const char *logfilename)
090089c4 804{
805 cacheinfo *obj = NULL;
806 int i;
a3d5953d 807 debug(18, 5) ("stat_init: Initializing...\n");
30a4f2a8 808 obj = xcalloc(1, sizeof(cacheinfo));
a4394ebd 809 if (logfilename)
365e5b34 810 accessLogOpen(logfilename);
92a6f4b1 811 obj->proto_id = urlParseProtocol;
090089c4 812 obj->proto_newobject = proto_newobject;
813 obj->proto_purgeobject = proto_purgeobject;
814 obj->proto_touchobject = proto_touchobject;
a528eb87 815 obj->proto_count = proto_count;
30a4f2a8 816 for (i = PROTO_NONE; i <= PROTO_MAX; i++) {
090089c4 817 switch (i) {
8213067d 818 case PROTO_HTTP:
090089c4 819 strcpy(obj->proto_stat_data[i].protoname, "HTTP");
820 break;
8213067d 821 case PROTO_GOPHER:
090089c4 822 strcpy(obj->proto_stat_data[i].protoname, "GOPHER");
823 break;
8213067d 824 case PROTO_FTP:
090089c4 825 strcpy(obj->proto_stat_data[i].protoname, "FTP");
826 break;
234967c9 827 case PROTO_WAIS:
828 strcpy(obj->proto_stat_data[i].protoname, "WAIS");
829 break;
8213067d 830 case PROTO_CACHEOBJ:
831 strcpy(obj->proto_stat_data[i].protoname, "CACHE_OBJ");
090089c4 832 break;
8213067d 833 case PROTO_MAX:
834 strcpy(obj->proto_stat_data[i].protoname, "TOTAL");
090089c4 835 break;
8213067d 836 case PROTO_NONE:
090089c4 837 default:
8213067d 838 strcpy(obj->proto_stat_data[i].protoname, "OTHER");
090089c4 839 break;
840 }
090089c4 841 obj->proto_stat_data[i].object_count = 0;
842 obj->proto_stat_data[i].hit = 0;
843 obj->proto_stat_data[i].miss = 0;
844 obj->proto_stat_data[i].hitratio = 0.0;
845 obj->proto_stat_data[i].transferrate = 0;
846 obj->proto_stat_data[i].refcount = 0;
847 obj->proto_stat_data[i].transferbyte = 0;
090089c4 848 obj->proto_stat_data[i].kb.max = 0;
849 obj->proto_stat_data[i].kb.min = 0;
850 obj->proto_stat_data[i].kb.avg = 0;
851 obj->proto_stat_data[i].kb.now = 0;
090089c4 852 }
090089c4 853 *object = obj;
b716a8ad 854 for (i = 0; i < PCONN_HIST_SZ; i++) {
603a02fd 855 client_pconn_hist[i] = 0;
b716a8ad 856 server_pconn_hist[i] = 0;
857 }
6605655c 858}
859
860void
861pconnHistCount(int what, int i)
862{
863 if (i >= PCONN_HIST_SZ)
864 i = PCONN_HIST_SZ - 1;
865 /* what == 0 for client, 1 for server */
866 if (what == 0)
867 client_pconn_hist[i]++;
b716a8ad 868 else if (what == 1)
869 server_pconn_hist[i]++;
870 else
ce66013b 871 assert(0);
6605655c 872}
873
874void
875pconnHistDump(StoreEntry * e)
876{
877 int i;
878 storeAppendPrintf(e,
879 "Client-side persistent connection counts:\n"
880 "\n"
b716a8ad 881 "\treq/\n"
882 "\tconn count\n"
883 "\t---- ---------\n");
6605655c 884 for (i = 0; i < PCONN_HIST_SZ; i++) {
885 if (client_pconn_hist[i] == 0)
886 continue;
b716a8ad 887 storeAppendPrintf(e, "\t%4d %9d\n", i, client_pconn_hist[i]);
888 }
889 storeAppendPrintf(e,
890 "\n"
891 "Server-side persistent connection counts:\n"
892 "\n"
893 "\treq/\n"
894 "\tconn count\n"
895 "\t---- ---------\n");
896 for (i = 0; i < PCONN_HIST_SZ; i++) {
897 if (server_pconn_hist[i] == 0)
898 continue;
899 storeAppendPrintf(e, "\t%4d %9d\n", i, server_pconn_hist[i]);
6605655c 900 }
090089c4 901}
f2908497 902
903void
904statAvgInit(void)
905{
906 memset(Deltas, '\0', N_DELTAS * sizeof(StatCounters));
907 eventAdd("statAvgTick", statAvgTick, NULL, 60);
908}
909
910static void
911statAvgTick(void *notused)
912{
913 StatCounters *t = &Deltas[0];
914 StatCounters *p = &Deltas[1];
915 StatCounters *c = &Counter;
916 struct rusage rusage;
917 eventAdd("statAvgTick", statAvgTick, NULL, 60);
918 memmove(p, t, (N_DELTAS - 1) * sizeof(StatCounters));
919 t->client_http.requests = c->client_http.requests - p->client_http.requests;
920 t->client_http.hits = c->client_http.hits - p->client_http.hits;
921 t->client_http.errors = c->client_http.errors - p->client_http.errors;
922 t->client_http.bytes_in = c->client_http.bytes_in - p->client_http.bytes_in;
923 t->client_http.bytes_out = c->client_http.bytes_out - p->client_http.bytes_out;
924 t->icp.pkts_sent = c->icp.pkts_sent - p->icp.pkts_sent;
925 t->icp.pkts_recv = c->icp.pkts_recv - p->icp.pkts_recv;
926 t->icp.bytes_sent = c->icp.bytes_sent - p->icp.bytes_sent;
927 t->icp.bytes_recv = c->icp.bytes_recv - p->icp.bytes_recv;
928 t->unlink.requests = c->unlink.requests - p->unlink.requests;
929 t->page_faults = c->page_faults - p->page_faults;
930 t->select_loops = c->select_loops - p->select_loops;
931 t->cputime = c->cputime - p->cputime;
932 squid_getrusage(&rusage);
933 c->page_faults = rusage_pagefaults(&rusage);
934 c->cputime = rusage_cputime(&rusage);
935}