blob: 655cb4dfe2a42cc851a83863a5b7b288e452cb52 [file] [log] [blame]
Willy Tarreau91861262007-10-17 17:06:05 +02001/*
2 * Functions dedicated to statistics output
3 *
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004 * Copyright 2000-2008 Willy Tarreau <w@1wt.eu>
Willy Tarreau91861262007-10-17 17:06:05 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <ctype.h>
14#include <errno.h>
15#include <fcntl.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020019#include <pwd.h>
20#include <grp.h>
Willy Tarreau91861262007-10-17 17:06:05 +020021
22#include <sys/socket.h>
23#include <sys/stat.h>
24#include <sys/types.h>
25
Willy Tarreau10522fd2008-07-09 20:12:41 +020026#include <common/cfgparse.h>
Willy Tarreau91861262007-10-17 17:06:05 +020027#include <common/compat.h>
28#include <common/config.h>
29#include <common/debug.h>
30#include <common/memory.h>
31#include <common/mini-clist.h>
32#include <common/standard.h>
Willy Tarreau0c303ee2008-07-07 00:09:58 +020033#include <common/ticks.h>
Willy Tarreau91861262007-10-17 17:06:05 +020034#include <common/time.h>
35#include <common/uri_auth.h>
36#include <common/version.h>
37
38#include <types/client.h>
39#include <types/global.h>
40#include <types/polling.h>
41#include <types/proxy.h>
42#include <types/server.h>
43
44#include <proto/backend.h>
45#include <proto/buffers.h>
46#include <proto/dumpstats.h>
47#include <proto/fd.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020048#include <proto/proto_uxst.h>
Willy Tarreau91861262007-10-17 17:06:05 +020049#include <proto/senddata.h>
50#include <proto/session.h>
Krzysztof Oledzki85130942007-10-22 16:21:10 +020051#include <proto/server.h>
Willy Tarreau91861262007-10-17 17:06:05 +020052
Willy Tarreaufbee7132007-10-18 13:53:22 +020053/* This function parses a "stats" statement in the "global" section. It returns
54 * -1 if there is any error, otherwise zero. If it returns -1, it may write an
55 * error message into ther <err> buffer, for at most <errlen> bytes, trailing
56 * zero included. The trailing '\n' must not be written. The function must be
57 * called with <args> pointing to the first word after "stats".
58 */
Willy Tarreau10522fd2008-07-09 20:12:41 +020059static int stats_parse_global(char **args, int section_type, struct proxy *curpx,
60 struct proxy *defpx, char *err, int errlen)
Willy Tarreaufbee7132007-10-18 13:53:22 +020061{
Willy Tarreau10522fd2008-07-09 20:12:41 +020062 args++;
Willy Tarreaufbee7132007-10-18 13:53:22 +020063 if (!strcmp(args[0], "socket")) {
64 struct sockaddr_un su;
65 int cur_arg;
66
67 if (*args[1] == 0) {
68 snprintf(err, errlen, "'stats socket' in global section expects a path to a UNIX socket");
69 return -1;
70 }
71
72 if (global.stats_sock.state != LI_NEW) {
73 snprintf(err, errlen, "'stats socket' already specified in global section");
74 return -1;
75 }
76
77 su.sun_family = AF_UNIX;
78 strncpy(su.sun_path, args[1], sizeof(su.sun_path));
79 su.sun_path[sizeof(su.sun_path) - 1] = 0;
80 memcpy(&global.stats_sock.addr, &su, sizeof(su)); // guaranteed to fit
81
82 global.stats_sock.state = LI_INIT;
Willy Tarreau6fb42e02007-10-28 17:02:33 +010083 global.stats_sock.options = LI_O_NONE;
Willy Tarreaufbee7132007-10-18 13:53:22 +020084 global.stats_sock.accept = uxst_event_accept;
85 global.stats_sock.handler = process_uxst_stats;
86 global.stats_sock.private = NULL;
87
88 cur_arg = 2;
89 while (*args[cur_arg]) {
90 if (!strcmp(args[cur_arg], "uid")) {
91 global.stats_sock.perm.ux.uid = atol(args[cur_arg + 1]);
92 cur_arg += 2;
93 }
94 else if (!strcmp(args[cur_arg], "gid")) {
95 global.stats_sock.perm.ux.gid = atol(args[cur_arg + 1]);
96 cur_arg += 2;
97 }
98 else if (!strcmp(args[cur_arg], "mode")) {
99 global.stats_sock.perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
100 cur_arg += 2;
101 }
102 else if (!strcmp(args[cur_arg], "user")) {
103 struct passwd *user;
104 user = getpwnam(args[cur_arg + 1]);
105 if (!user) {
106 snprintf(err, errlen, "unknown user '%s' in 'global' section ('stats user')",
107 args[cur_arg + 1]);
108 return -1;
109 }
110 global.stats_sock.perm.ux.uid = user->pw_uid;
111 cur_arg += 2;
112 }
113 else if (!strcmp(args[cur_arg], "group")) {
114 struct group *group;
115 group = getgrnam(args[cur_arg + 1]);
116 if (!group) {
117 snprintf(err, errlen, "unknown group '%s' in 'global' section ('stats group')",
118 args[cur_arg + 1]);
119 return -1;
120 }
121 global.stats_sock.perm.ux.gid = group->gr_gid;
122 cur_arg += 2;
123 }
124 else {
125 snprintf(err, errlen, "'stats socket' only supports 'user', 'uid', 'group', 'gid', and 'mode'");
126 return -1;
127 }
128 }
129
130 uxst_add_listener(&global.stats_sock);
131 global.maxsock++;
132 }
133 else if (!strcmp(args[0], "timeout")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100134 unsigned timeout;
135 const char *res = parse_time_err(args[1], &timeout, TIME_UNIT_MS);
136
137 if (res) {
138 snprintf(err, errlen, "unexpected character '%c' in 'stats timeout' in 'global' section", *res);
139 return -1;
140 }
Willy Tarreaufbee7132007-10-18 13:53:22 +0200141
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100142 if (!timeout) {
Willy Tarreaufbee7132007-10-18 13:53:22 +0200143 snprintf(err, errlen, "a positive value is expected for 'stats timeout' in 'global section'");
144 return -1;
145 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200146 global.stats_timeout = MS_TO_TICKS(timeout);
Willy Tarreaufbee7132007-10-18 13:53:22 +0200147 }
148 else if (!strcmp(args[0], "maxconn")) {
149 int maxconn = atol(args[1]);
150
151 if (maxconn <= 0) {
152 snprintf(err, errlen, "a positive value is expected for 'stats maxconn' in 'global section'");
153 return -1;
154 }
155 global.maxsock -= global.stats_sock.maxconn;
156 global.stats_sock.maxconn = maxconn;
157 global.maxsock += global.stats_sock.maxconn;
158 }
159 else {
160 snprintf(err, errlen, "'stats' only supports 'socket', 'maxconn' and 'timeout' in 'global' section");
161 return -1;
162 }
163 return 0;
164}
165
Willy Tarreau4bab24d2007-11-30 18:16:29 +0100166int print_csv_header(struct chunk *msg, int size)
167{
168 return chunk_printf(msg, size,
169 "# pxname,svname,"
170 "qcur,qmax,"
171 "scur,smax,slim,stot,"
172 "bin,bout,"
173 "dreq,dresp,"
174 "ereq,econ,eresp,"
175 "wretr,wredis,"
176 "status,weight,act,bck,"
177 "chkfail,chkdown,lastchg,downtime,qlimit,"
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100178 "pid,iid,sid,throttle,lbtot,tracked,type,"
Willy Tarreau4bab24d2007-11-30 18:16:29 +0100179 "\n");
180}
181
Willy Tarreau91861262007-10-17 17:06:05 +0200182/*
183 * Produces statistics data for the session <s>. Expects to be called with
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100184 * s->cli_state == CL_STSHUTR. It *may* make use of informations from <uri>.
185 * s->data_ctx must have been zeroed first, and the flags properly set.
Willy Tarreau3e76e722007-10-17 18:57:38 +0200186 * It returns 0 if it had to stop writing data and an I/O is needed, 1 if the
187 * dump is finished and the session must be closed, or -1 in case of any error.
188 */
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100189int stats_dump_raw(struct session *s, struct uri_auth *uri)
Willy Tarreau3e76e722007-10-17 18:57:38 +0200190{
191 struct buffer *rep = s->rep;
192 struct proxy *px;
193 struct chunk msg;
Willy Tarreaua8efd362008-01-03 10:19:15 +0100194 unsigned int up;
Willy Tarreau3e76e722007-10-17 18:57:38 +0200195
196 msg.len = 0;
197 msg.str = trash;
198
199 switch (s->data_state) {
200 case DATA_ST_INIT:
201 /* the function had not been called yet, let's prepare the
202 * buffer for a response.
203 */
204 client_retnclose(s, &msg);
205 s->data_state = DATA_ST_HEAD;
206 /* fall through */
207
208 case DATA_ST_HEAD:
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100209 if (s->data_ctx.stats.flags & STAT_SHOW_STAT) {
Willy Tarreaua8efd362008-01-03 10:19:15 +0100210 print_csv_header(&msg, sizeof(trash));
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +0200211 if (buffer_write_chunk(rep, &msg) >= 0)
Willy Tarreaua8efd362008-01-03 10:19:15 +0100212 return 0;
213 }
Willy Tarreau3e76e722007-10-17 18:57:38 +0200214
215 s->data_state = DATA_ST_INFO;
216 /* fall through */
217
218 case DATA_ST_INFO:
Willy Tarreaua8efd362008-01-03 10:19:15 +0100219 up = (now.tv_sec - start_date.tv_sec);
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100220 if (s->data_ctx.stats.flags & STAT_SHOW_INFO) {
Willy Tarreaua8efd362008-01-03 10:19:15 +0100221 chunk_printf(&msg, sizeof(trash),
222 "Name: " PRODUCT_NAME "\n"
223 "Version: " HAPROXY_VERSION "\n"
224 "Release_date: " HAPROXY_DATE "\n"
225 "Nbproc: %d\n"
226 "Process_num: %d\n"
227 "Pid: %d\n"
228 "Uptime: %dd %dh%02dm%02ds\n"
229 "Uptime_sec: %d\n"
230 "Memmax_MB: %d\n"
231 "Ulimit-n: %d\n"
232 "Maxsock: %d\n"
233 "Maxconn: %d\n"
234 "CurrConns: %d\n"
235 "",
236 global.nbproc,
237 relative_pid,
238 pid,
239 up / 86400, (up % 86400) / 3600, (up % 3600) / 60, (up % 60),
240 up,
241 global.rlimit_memmax,
242 global.rlimit_nofile,
243 global.maxsock,
244 global.maxconn,
245 actconn
246 );
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +0200247 if (buffer_write_chunk(rep, &msg) >= 0)
Willy Tarreaua8efd362008-01-03 10:19:15 +0100248 return 0;
249 }
250
Willy Tarreau3e76e722007-10-17 18:57:38 +0200251 s->data_ctx.stats.px = proxy;
252 s->data_ctx.stats.px_st = DATA_ST_PX_INIT;
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100253
254 s->data_ctx.stats.sv = NULL;
255 s->data_ctx.stats.sv_st = 0;
256
Willy Tarreau3e76e722007-10-17 18:57:38 +0200257 s->data_state = DATA_ST_LIST;
258 /* fall through */
259
260 case DATA_ST_LIST:
261 /* dump proxies */
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100262 if (s->data_ctx.stats.flags & STAT_SHOW_STAT) {
Willy Tarreaua8efd362008-01-03 10:19:15 +0100263 while (s->data_ctx.stats.px) {
264 px = s->data_ctx.stats.px;
265 /* skip the disabled proxies and non-networked ones */
266 if (px->state != PR_STSTOPPED &&
267 (px->cap & (PR_CAP_FE | PR_CAP_BE)))
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100268 if (stats_dump_proxy(s, px, NULL) == 0)
Willy Tarreaua8efd362008-01-03 10:19:15 +0100269 return 0;
Willy Tarreau3e76e722007-10-17 18:57:38 +0200270
Willy Tarreaua8efd362008-01-03 10:19:15 +0100271 s->data_ctx.stats.px = px->next;
272 s->data_ctx.stats.px_st = DATA_ST_PX_INIT;
273 }
274 /* here, we just have reached the last proxy */
Willy Tarreau3e76e722007-10-17 18:57:38 +0200275 }
Willy Tarreau3e76e722007-10-17 18:57:38 +0200276
277 s->data_state = DATA_ST_END;
278 /* fall through */
279
280 case DATA_ST_END:
281 s->data_state = DATA_ST_FIN;
282 return 1;
283
284 case DATA_ST_FIN:
285 return 1;
286
287 default:
288 /* unknown state ! */
289 return -1;
290 }
291}
292
293
294/*
295 * Produces statistics data for the session <s>. Expects to be called with
Willy Tarreau91861262007-10-17 17:06:05 +0200296 * s->cli_state == CL_STSHUTR. It stops by itself by unsetting the SN_SELF_GEN
297 * flag from the session, which it uses to keep on being called when there is
298 * free space in the buffer, of simply by letting an empty buffer upon return.
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100299 * s->data_ctx must have been zeroed before the first call, and the flags set.
Willy Tarreau91861262007-10-17 17:06:05 +0200300 * It returns 0 if it had to stop writing data and an I/O is needed, 1 if the
301 * dump is finished and the session must be closed, or -1 in case of any error.
302 */
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100303int stats_dump_http(struct session *s, struct uri_auth *uri)
Willy Tarreau91861262007-10-17 17:06:05 +0200304{
305 struct buffer *rep = s->rep;
306 struct proxy *px;
307 struct chunk msg;
308 unsigned int up;
309
310 msg.len = 0;
311 msg.str = trash;
312
313 switch (s->data_state) {
314 case DATA_ST_INIT:
315 /* the function had not been called yet */
316 s->flags |= SN_SELF_GEN; // more data will follow
317
318 chunk_printf(&msg, sizeof(trash),
319 "HTTP/1.0 200 OK\r\n"
320 "Cache-Control: no-cache\r\n"
321 "Connection: close\r\n"
Willy Tarreau55bb8452007-10-17 18:44:57 +0200322 "Content-Type: %s\r\n",
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100323 (s->data_ctx.stats.flags & STAT_FMT_CSV) ? "text/plain" : "text/html");
Willy Tarreau91861262007-10-17 17:06:05 +0200324
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100325 if (uri->refresh > 0 && !(s->data_ctx.stats.flags & STAT_NO_REFRESH))
Willy Tarreau91861262007-10-17 17:06:05 +0200326 chunk_printf(&msg, sizeof(trash), "Refresh: %d\r\n",
327 uri->refresh);
328
329 chunk_printf(&msg, sizeof(trash), "\r\n");
330
331 s->txn.status = 200;
332 client_retnclose(s, &msg); // send the start of the response.
333 msg.len = 0;
334
335 if (!(s->flags & SN_ERR_MASK)) // this is not really an error but it is
336 s->flags |= SN_ERR_PRXCOND; // to mark that it comes from the proxy
337 if (!(s->flags & SN_FINST_MASK))
338 s->flags |= SN_FINST_R;
339
340 if (s->txn.meth == HTTP_METH_HEAD) {
341 /* that's all we return in case of HEAD request */
342 s->data_state = DATA_ST_FIN;
343 s->flags &= ~SN_SELF_GEN;
344 return 1;
345 }
346
347 s->data_state = DATA_ST_HEAD; /* let's start producing data */
348 /* fall through */
349
350 case DATA_ST_HEAD:
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100351 if (!(s->data_ctx.stats.flags & STAT_FMT_CSV)) {
Willy Tarreau55bb8452007-10-17 18:44:57 +0200352 /* WARNING! This must fit in the first buffer !!! */
353 chunk_printf(&msg, sizeof(trash),
Willy Tarreau91861262007-10-17 17:06:05 +0200354 "<html><head><title>Statistics Report for " PRODUCT_NAME "</title>\n"
355 "<meta http-equiv=\"content-type\" content=\"text/html; charset=iso-8859-1\">\n"
356 "<style type=\"text/css\"><!--\n"
357 "body {"
358 " font-family: helvetica, arial;"
359 " font-size: 12px;"
360 " font-weight: normal;"
361 " color: black;"
362 " background: white;"
363 "}\n"
364 "th,td {"
365 " font-size: 0.8em;"
366 " align: center;"
367 "}\n"
368 "h1 {"
369 " font-size: xx-large;"
370 " margin-bottom: 0.5em;"
371 "}\n"
372 "h2 {"
373 " font-family: helvetica, arial;"
374 " font-size: x-large;"
375 " font-weight: bold;"
376 " font-style: italic;"
377 " color: #6020a0;"
378 " margin-top: 0em;"
379 " margin-bottom: 0em;"
380 "}\n"
381 "h3 {"
382 " font-family: helvetica, arial;"
383 " font-size: 16px;"
384 " font-weight: bold;"
385 " color: #b00040;"
386 " background: #e8e8d0;"
387 " margin-top: 0em;"
388 " margin-bottom: 0em;"
389 "}\n"
390 "li {"
391 " margin-top: 0.25em;"
392 " margin-right: 2em;"
393 "}\n"
394 ".hr {margin-top: 0.25em;"
395 " border-color: black;"
396 " border-bottom-style: solid;"
397 "}\n"
398 ".pxname {background: #b00040;color: #ffff40;font-weight: bold;}\n"
399 ".titre {background: #20D0D0;color: #000000;font-weight: bold;}\n"
400 ".total {background: #20D0D0;color: #ffff80;}\n"
401 ".frontend {background: #e8e8d0;}\n"
402 ".backend {background: #e8e8d0;}\n"
403 ".active0 {background: #ff9090;}\n"
404 ".active1 {background: #ffd020;}\n"
405 ".active2 {background: #ffffa0;}\n"
406 ".active3 {background: #c0ffc0;}\n"
Willy Tarreau2ea81932007-11-30 12:04:38 +0100407 ".active4 {background: #ffffa0;}\n" /* NOLB state shows same as going down */
408 ".active5 {background: #a0e0a0;}\n" /* NOLB state shows darker than up */
409 ".active6 {background: #e0e0e0;}\n"
Willy Tarreau91861262007-10-17 17:06:05 +0200410 ".backup0 {background: #ff9090;}\n"
411 ".backup1 {background: #ff80ff;}\n"
412 ".backup2 {background: #c060ff;}\n"
413 ".backup3 {background: #b0d0ff;}\n"
Willy Tarreau2ea81932007-11-30 12:04:38 +0100414 ".backup4 {background: #c060ff;}\n" /* NOLB state shows same as going down */
415 ".backup5 {background: #90b0e0;}\n" /* NOLB state shows same as going down */
416 ".backup6 {background: #e0e0e0;}\n"
Willy Tarreau91861262007-10-17 17:06:05 +0200417 "table.tbl { border-collapse: collapse; border-style: none;}\n"
418 "table.tbl td { border-width: 1px 1px 1px 1px; border-style: solid solid solid solid; padding: 2px 3px; border-color: gray;}\n"
419 "table.tbl th { border-width: 1px; border-style: solid solid solid solid; border-color: gray;}\n"
420 "table.tbl th.empty { border-style: none; empty-cells: hide;}\n"
421 "table.lgd { border-collapse: collapse; border-width: 1px; border-style: none none none solid; border-color: black;}\n"
422 "table.lgd td { border-width: 1px; border-style: solid solid solid solid; border-color: gray; padding: 2px;}\n"
423 "table.lgd td.noborder { border-style: none; padding: 2px; white-space: nowrap;}\n"
424 "-->\n"
425 "</style></head>\n");
Willy Tarreau55bb8452007-10-17 18:44:57 +0200426 } else {
Willy Tarreau4bab24d2007-11-30 18:16:29 +0100427 print_csv_header(&msg, sizeof(trash));
Willy Tarreau55bb8452007-10-17 18:44:57 +0200428 }
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +0200429 if (buffer_write_chunk(rep, &msg) >= 0)
Willy Tarreau91861262007-10-17 17:06:05 +0200430 return 0;
431
432 s->data_state = DATA_ST_INFO;
433 /* fall through */
434
435 case DATA_ST_INFO:
436 up = (now.tv_sec - start_date.tv_sec);
437
438 /* WARNING! this has to fit the first packet too.
439 * We are around 3.5 kB, add adding entries will
440 * become tricky if we want to support 4kB buffers !
441 */
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100442 if (!(s->data_ctx.stats.flags & STAT_FMT_CSV)) {
Willy Tarreau55bb8452007-10-17 18:44:57 +0200443 chunk_printf(&msg, sizeof(trash),
Willy Tarreau91861262007-10-17 17:06:05 +0200444 "<body><h1><a href=\"" PRODUCT_URL "\" style=\"text-decoration: none;\">"
445 PRODUCT_NAME "%s</a></h1>\n"
446 "<h2>Statistics Report for pid %d</h2>\n"
447 "<hr width=\"100%%\" class=\"hr\">\n"
448 "<h3>&gt; General process information</h3>\n"
449 "<table border=0 cols=4><tr><td align=\"left\" nowrap width=\"1%%\">\n"
Willy Tarreaua8efd362008-01-03 10:19:15 +0100450 "<p><b>pid = </b> %d (process #%d, nbproc = %d)<br>\n"
Willy Tarreau91861262007-10-17 17:06:05 +0200451 "<b>uptime = </b> %dd %dh%02dm%02ds<br>\n"
452 "<b>system limits :</b> memmax = %s%s ; ulimit-n = %d<br>\n"
453 "<b>maxsock = </b> %d<br>\n"
454 "<b>maxconn = </b> %d (current conns = %d)<br>\n"
455 "</td><td align=\"center\" nowrap>\n"
456 "<table class=\"lgd\"><tr>\n"
457 "<td class=\"active3\">&nbsp;</td><td class=\"noborder\">active UP </td>"
458 "<td class=\"backup3\">&nbsp;</td><td class=\"noborder\">backup UP </td>"
459 "</tr><tr>\n"
460 "<td class=\"active2\"></td><td class=\"noborder\">active UP, going down </td>"
461 "<td class=\"backup2\"></td><td class=\"noborder\">backup UP, going down </td>"
462 "</tr><tr>\n"
463 "<td class=\"active1\"></td><td class=\"noborder\">active DOWN, going up </td>"
464 "<td class=\"backup1\"></td><td class=\"noborder\">backup DOWN, going up </td>"
465 "</tr><tr>\n"
466 "<td class=\"active0\"></td><td class=\"noborder\">active or backup DOWN &nbsp;</td>"
Willy Tarreau2ea81932007-11-30 12:04:38 +0100467 "<td class=\"active6\"></td><td class=\"noborder\">not checked </td>"
Willy Tarreau91861262007-10-17 17:06:05 +0200468 "</tr></table>\n"
Willy Tarreau2ea81932007-11-30 12:04:38 +0100469 "Note: UP with load-balancing disabled is reported as \"NOLB\"."
Willy Tarreau91861262007-10-17 17:06:05 +0200470 "</td>"
471 "<td align=\"left\" valign=\"top\" nowrap width=\"1%%\">"
472 "<b>Display option:</b><ul style=\"margin-top: 0.25em;\">"
473 "",
474 (uri->flags&ST_HIDEVER)?"":(STATS_VERSION_STRING),
Willy Tarreaua8efd362008-01-03 10:19:15 +0100475 pid, pid,
476 relative_pid, global.nbproc,
Willy Tarreau91861262007-10-17 17:06:05 +0200477 up / 86400, (up % 86400) / 3600,
478 (up % 3600) / 60, (up % 60),
479 global.rlimit_memmax ? ultoa(global.rlimit_memmax) : "unlimited",
480 global.rlimit_memmax ? " MB" : "",
481 global.rlimit_nofile,
482 global.maxsock,
483 global.maxconn,
484 actconn
485 );
486
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100487 if (s->data_ctx.stats.flags & STAT_HIDE_DOWN)
Willy Tarreau55bb8452007-10-17 18:44:57 +0200488 chunk_printf(&msg, sizeof(trash),
Willy Tarreau91861262007-10-17 17:06:05 +0200489 "<li><a href=\"%s%s%s\">Show all servers</a><br>\n",
490 uri->uri_prefix,
491 "",
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100492 (s->data_ctx.stats.flags & STAT_NO_REFRESH) ? ";norefresh" : "");
Willy Tarreau55bb8452007-10-17 18:44:57 +0200493 else
494 chunk_printf(&msg, sizeof(trash),
Willy Tarreau91861262007-10-17 17:06:05 +0200495 "<li><a href=\"%s%s%s\">Hide 'DOWN' servers</a><br>\n",
496 uri->uri_prefix,
497 ";up",
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100498 (s->data_ctx.stats.flags & STAT_NO_REFRESH) ? ";norefresh" : "");
Willy Tarreau91861262007-10-17 17:06:05 +0200499
Willy Tarreau55bb8452007-10-17 18:44:57 +0200500 if (uri->refresh > 0) {
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100501 if (s->data_ctx.stats.flags & STAT_NO_REFRESH)
Willy Tarreau55bb8452007-10-17 18:44:57 +0200502 chunk_printf(&msg, sizeof(trash),
Willy Tarreau91861262007-10-17 17:06:05 +0200503 "<li><a href=\"%s%s%s\">Enable refresh</a><br>\n",
504 uri->uri_prefix,
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100505 (s->data_ctx.stats.flags & STAT_HIDE_DOWN) ? ";up" : "",
Willy Tarreau91861262007-10-17 17:06:05 +0200506 "");
Willy Tarreau55bb8452007-10-17 18:44:57 +0200507 else
508 chunk_printf(&msg, sizeof(trash),
Willy Tarreau91861262007-10-17 17:06:05 +0200509 "<li><a href=\"%s%s%s\">Disable refresh</a><br>\n",
510 uri->uri_prefix,
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100511 (s->data_ctx.stats.flags & STAT_HIDE_DOWN) ? ";up" : "",
Willy Tarreau91861262007-10-17 17:06:05 +0200512 ";norefresh");
Willy Tarreau55bb8452007-10-17 18:44:57 +0200513 }
Willy Tarreau91861262007-10-17 17:06:05 +0200514
Willy Tarreau55bb8452007-10-17 18:44:57 +0200515 chunk_printf(&msg, sizeof(trash),
Willy Tarreau91861262007-10-17 17:06:05 +0200516 "<li><a href=\"%s%s%s\">Refresh now</a><br>\n",
517 uri->uri_prefix,
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100518 (s->data_ctx.stats.flags & STAT_HIDE_DOWN) ? ";up" : "",
519 (s->data_ctx.stats.flags & STAT_NO_REFRESH) ? ";norefresh" : "");
Willy Tarreau91861262007-10-17 17:06:05 +0200520
Willy Tarreau55bb8452007-10-17 18:44:57 +0200521 chunk_printf(&msg, sizeof(trash),
Willy Tarreau5031e6a2007-10-18 11:05:48 +0200522 "<li><a href=\"%s;csv%s\">CSV export</a><br>\n",
523 uri->uri_prefix,
524 (uri->refresh > 0) ? ";norefresh" : "");
525
526 chunk_printf(&msg, sizeof(trash),
Willy Tarreau91861262007-10-17 17:06:05 +0200527 "</td>"
528 "<td align=\"left\" valign=\"top\" nowrap width=\"1%%\">"
529 "<b>External ressources:</b><ul style=\"margin-top: 0.25em;\">\n"
530 "<li><a href=\"" PRODUCT_URL "\">Primary site</a><br>\n"
531 "<li><a href=\"" PRODUCT_URL_UPD "\">Updates (v" PRODUCT_BRANCH ")</a><br>\n"
532 "<li><a href=\"" PRODUCT_URL_DOC "\">Online manual</a><br>\n"
533 "</ul>"
534 "</td>"
535 "</tr></table>\n"
536 ""
537 );
538
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +0200539 if (buffer_write_chunk(rep, &msg) >= 0)
Willy Tarreau55bb8452007-10-17 18:44:57 +0200540 return 0;
541 }
Willy Tarreau91861262007-10-17 17:06:05 +0200542
Willy Tarreau91861262007-10-17 17:06:05 +0200543 s->data_ctx.stats.px = proxy;
544 s->data_ctx.stats.px_st = DATA_ST_PX_INIT;
545 s->data_state = DATA_ST_LIST;
546 /* fall through */
547
548 case DATA_ST_LIST:
549 /* dump proxies */
550 while (s->data_ctx.stats.px) {
551 px = s->data_ctx.stats.px;
552 /* skip the disabled proxies and non-networked ones */
553 if (px->state != PR_STSTOPPED && (px->cap & (PR_CAP_FE | PR_CAP_BE)))
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100554 if (stats_dump_proxy(s, px, uri) == 0)
Willy Tarreau91861262007-10-17 17:06:05 +0200555 return 0;
556
557 s->data_ctx.stats.px = px->next;
558 s->data_ctx.stats.px_st = DATA_ST_PX_INIT;
559 }
560 /* here, we just have reached the last proxy */
561
562 s->data_state = DATA_ST_END;
563 /* fall through */
564
565 case DATA_ST_END:
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100566 if (!(s->data_ctx.stats.flags & STAT_FMT_CSV)) {
Willy Tarreau55bb8452007-10-17 18:44:57 +0200567 chunk_printf(&msg, sizeof(trash), "</body></html>\n");
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +0200568 if (buffer_write_chunk(rep, &msg) >= 0)
Willy Tarreau55bb8452007-10-17 18:44:57 +0200569 return 0;
570 }
Willy Tarreau91861262007-10-17 17:06:05 +0200571
572 s->data_state = DATA_ST_FIN;
573 /* fall through */
574
575 case DATA_ST_FIN:
576 s->flags &= ~SN_SELF_GEN;
577 return 1;
578
579 default:
580 /* unknown state ! */
581 s->flags &= ~SN_SELF_GEN;
582 return -1;
583 }
584}
585
586
587/*
588 * Dumps statistics for a proxy.
589 * Returns 0 if it had to stop dumping data because of lack of buffer space,
590 * ot non-zero if everything completed.
591 */
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100592int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri)
Willy Tarreau91861262007-10-17 17:06:05 +0200593{
594 struct buffer *rep = s->rep;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +0100595 struct server *sv, *svs; /* server and server-state, server-state=server or server->tracked */
Willy Tarreau91861262007-10-17 17:06:05 +0200596 struct chunk msg;
597
598 msg.len = 0;
599 msg.str = trash;
600
601 switch (s->data_ctx.stats.px_st) {
602 case DATA_ST_PX_INIT:
603 /* we are on a new proxy */
604
605 if (uri && uri->scope) {
606 /* we have a limited scope, we have to check the proxy name */
607 struct stat_scope *scope;
608 int len;
609
610 len = strlen(px->id);
611 scope = uri->scope;
612
613 while (scope) {
614 /* match exact proxy name */
615 if (scope->px_len == len && !memcmp(px->id, scope->px_id, len))
616 break;
617
618 /* match '.' which means 'self' proxy */
Willy Tarreau1388a3a2007-10-18 16:38:37 +0200619 if (!strcmp(scope->px_id, ".") && px == s->be)
Willy Tarreau91861262007-10-17 17:06:05 +0200620 break;
621 scope = scope->next;
622 }
623
624 /* proxy name not found : don't dump anything */
625 if (scope == NULL)
626 return 1;
627 }
628
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100629 if ((s->data_ctx.stats.flags & STAT_BOUND) && (s->data_ctx.stats.iid != -1) &&
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100630 (px->uuid != s->data_ctx.stats.iid))
631 return 1;
632
Willy Tarreau91861262007-10-17 17:06:05 +0200633 s->data_ctx.stats.px_st = DATA_ST_PX_TH;
634 /* fall through */
635
636 case DATA_ST_PX_TH:
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100637 if (!(s->data_ctx.stats.flags & STAT_FMT_CSV)) {
Willy Tarreau55bb8452007-10-17 18:44:57 +0200638 /* print a new table */
639 chunk_printf(&msg, sizeof(trash),
Willy Tarreauddbb82f2007-12-05 10:34:49 +0100640 "<table cols=\"26\" class=\"tbl\" width=\"100%%\">\n"
Willy Tarreau55bb8452007-10-17 18:44:57 +0200641 "<tr align=\"center\" class=\"titre\">"
642 "<th colspan=2 class=\"pxname\">%s</th>"
Willy Tarreauddbb82f2007-12-05 10:34:49 +0100643 "<th colspan=24 class=\"empty\"></th>"
Willy Tarreau55bb8452007-10-17 18:44:57 +0200644 "</tr>\n"
645 "<tr align=\"center\" class=\"titre\">"
646 "<th rowspan=2></th>"
Willy Tarreauddbb82f2007-12-05 10:34:49 +0100647 "<th colspan=3>Queue</th><th colspan=5>Sessions</th>"
Willy Tarreau55bb8452007-10-17 18:44:57 +0200648 "<th colspan=2>Bytes</th><th colspan=2>Denied</th>"
Krzysztof Oledzki1cf36ba2007-10-18 19:12:30 +0200649 "<th colspan=3>Errors</th><th colspan=2>Warnings</th>"
Willy Tarreau4bab24d2007-11-30 18:16:29 +0100650 "<th colspan=8>Server</th>"
Willy Tarreau55bb8452007-10-17 18:44:57 +0200651 "</tr>\n"
652 "<tr align=\"center\" class=\"titre\">"
Elijah Epifanovacafc5f2007-10-25 20:15:38 +0200653 "<th>Cur</th><th>Max</th><th>Limit</th><th>Cur</th><th>Max</th>"
Willy Tarreauddbb82f2007-12-05 10:34:49 +0100654 "<th>Limit</th><th>Total</th><th>LbTot</th><th>In</th><th>Out</th>"
Willy Tarreau55bb8452007-10-17 18:44:57 +0200655 "<th>Req</th><th>Resp</th><th>Req</th><th>Conn</th>"
Krzysztof Oledzki1cf36ba2007-10-18 19:12:30 +0200656 "<th>Resp</th><th>Retr</th><th>Redis</th>"
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200657 "<th>Status</th><th>Wght</th><th>Act</th>"
Willy Tarreau4bab24d2007-11-30 18:16:29 +0100658 "<th>Bck</th><th>Chk</th><th>Dwn</th><th>Dwntme</th>"
659 "<th>Thrtle</th>\n"
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200660 "</tr>",
Willy Tarreau55bb8452007-10-17 18:44:57 +0200661 px->id);
662
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +0200663 if (buffer_write_chunk(rep, &msg) >= 0)
Willy Tarreau55bb8452007-10-17 18:44:57 +0200664 return 0;
665 }
Willy Tarreau91861262007-10-17 17:06:05 +0200666
667 s->data_ctx.stats.px_st = DATA_ST_PX_FE;
668 /* fall through */
669
670 case DATA_ST_PX_FE:
671 /* print the frontend */
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100672 if ((px->cap & PR_CAP_FE) &&
673 (!(s->data_ctx.stats.flags & STAT_BOUND) || (s->data_ctx.stats.type & (1 << STATS_TYPE_FE)))) {
674 if (!(s->data_ctx.stats.flags & STAT_FMT_CSV)) {
Willy Tarreau55bb8452007-10-17 18:44:57 +0200675 chunk_printf(&msg, sizeof(trash),
Willy Tarreau91861262007-10-17 17:06:05 +0200676 /* name, queue */
Elijah Epifanovacafc5f2007-10-25 20:15:38 +0200677 "<tr align=center class=\"frontend\"><td>Frontend</td><td colspan=3></td>"
Willy Tarreauddbb82f2007-12-05 10:34:49 +0100678 /* sessions : current, max, limit, total, lbtot */
Willy Tarreau55bb8452007-10-17 18:44:57 +0200679 "<td align=right>%d</td><td align=right>%d</td>"
680 "<td align=right>%d</td><td align=right>%d</td>"
Willy Tarreauddbb82f2007-12-05 10:34:49 +0100681 "<td align=right></td>"
Willy Tarreau91861262007-10-17 17:06:05 +0200682 /* bytes : in, out */
683 "<td align=right>%lld</td><td align=right>%lld</td>"
684 /* denied: req, resp */
685 "<td align=right>%d</td><td align=right>%d</td>"
686 /* errors : request, connect, response */
687 "<td align=right>%d</td><td align=right></td><td align=right></td>"
Krzysztof Oledzki1cf36ba2007-10-18 19:12:30 +0200688 /* warnings: retries, redispatches */
689 "<td align=right></td><td align=right></td>"
Willy Tarreau55bb8452007-10-17 18:44:57 +0200690 /* server status : reflect frontend status */
Willy Tarreau91861262007-10-17 17:06:05 +0200691 "<td align=center>%s</td>"
692 /* rest of server: nothing */
Willy Tarreau4bab24d2007-11-30 18:16:29 +0100693 "<td align=center colspan=7></td></tr>"
Willy Tarreau91861262007-10-17 17:06:05 +0200694 "",
695 px->feconn, px->feconn_max, px->maxconn, px->cum_feconn,
696 px->bytes_in, px->bytes_out,
697 px->denied_req, px->denied_resp,
698 px->failed_req,
699 px->state == PR_STRUN ? "OPEN" :
700 px->state == PR_STIDLE ? "FULL" : "STOP");
Willy Tarreau55bb8452007-10-17 18:44:57 +0200701 } else {
702 chunk_printf(&msg, sizeof(trash),
703 /* pxid, name, queue cur, queue max, */
704 "%s,FRONTEND,,,"
Willy Tarreauddbb82f2007-12-05 10:34:49 +0100705 /* sessions : current, max, limit, total */
Willy Tarreau55bb8452007-10-17 18:44:57 +0200706 "%d,%d,%d,%d,"
707 /* bytes : in, out */
708 "%lld,%lld,"
709 /* denied: req, resp */
710 "%d,%d,"
711 /* errors : request, connect, response */
712 "%d,,,"
Krzysztof Oledzki1cf36ba2007-10-18 19:12:30 +0200713 /* warnings: retries, redispatches */
714 ",,"
Willy Tarreau55bb8452007-10-17 18:44:57 +0200715 /* server status : reflect frontend status */
716 "%s,"
717 /* rest of server: nothing */
Elijah Epifanovacafc5f2007-10-25 20:15:38 +0200718 ",,,,,,,,"
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100719 /* pid, iid, sid, throttle, lbtot, tracked, type */
720 "%d,%d,0,,,,%d,"
Willy Tarreau55bb8452007-10-17 18:44:57 +0200721 "\n",
722 px->id,
723 px->feconn, px->feconn_max, px->maxconn, px->cum_feconn,
724 px->bytes_in, px->bytes_out,
725 px->denied_req, px->denied_resp,
726 px->failed_req,
727 px->state == PR_STRUN ? "OPEN" :
Willy Tarreaudcd47712007-11-04 23:35:08 +0100728 px->state == PR_STIDLE ? "FULL" : "STOP",
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100729 relative_pid, px->uuid, STATS_TYPE_FE);
Willy Tarreau55bb8452007-10-17 18:44:57 +0200730 }
Willy Tarreau91861262007-10-17 17:06:05 +0200731
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +0200732 if (buffer_write_chunk(rep, &msg) >= 0)
Willy Tarreau91861262007-10-17 17:06:05 +0200733 return 0;
734 }
735
736 s->data_ctx.stats.sv = px->srv; /* may be NULL */
737 s->data_ctx.stats.px_st = DATA_ST_PX_SV;
738 /* fall through */
739
740 case DATA_ST_PX_SV:
741 /* stats.sv has been initialized above */
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100742 for (; s->data_ctx.stats.sv != NULL; s->data_ctx.stats.sv = sv->next) {
743
Willy Tarreau2ea81932007-11-30 12:04:38 +0100744 int sv_state; /* 0=DOWN, 1=going up, 2=going down, 3=UP, 4,5=NOLB, 6=unchecked */
Willy Tarreau91861262007-10-17 17:06:05 +0200745
746 sv = s->data_ctx.stats.sv;
747
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100748 if (s->data_ctx.stats.flags & STAT_BOUND) {
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100749 if (!(s->data_ctx.stats.type & (1 << STATS_TYPE_SV)))
750 break;
751
752 if (s->data_ctx.stats.sid != -1 && sv->puid != s->data_ctx.stats.sid)
753 continue;
754 }
755
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +0100756 if (sv->tracked)
757 svs = sv->tracked;
758 else
759 svs = sv;
760
Willy Tarreau91861262007-10-17 17:06:05 +0200761 /* FIXME: produce some small strings for "UP/DOWN x/y &#xxxx;" */
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +0100762 if (!(svs->state & SRV_CHECKED))
Willy Tarreau2ea81932007-11-30 12:04:38 +0100763 sv_state = 6;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +0100764 else if (svs->state & SRV_RUNNING) {
765 if (svs->health == svs->rise + svs->fall - 1)
Willy Tarreau91861262007-10-17 17:06:05 +0200766 sv_state = 3; /* UP */
767 else
768 sv_state = 2; /* going down */
Willy Tarreau2ea81932007-11-30 12:04:38 +0100769
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +0100770 if (svs->state & SRV_GOINGDOWN)
Willy Tarreau2ea81932007-11-30 12:04:38 +0100771 sv_state += 2;
772 }
Willy Tarreau91861262007-10-17 17:06:05 +0200773 else
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +0100774 if (svs->health)
Willy Tarreau91861262007-10-17 17:06:05 +0200775 sv_state = 1; /* going up */
776 else
777 sv_state = 0; /* DOWN */
778
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100779 if ((sv_state == 0) && (s->data_ctx.stats.flags & STAT_HIDE_DOWN)) {
Willy Tarreau91861262007-10-17 17:06:05 +0200780 /* do not report servers which are DOWN */
781 s->data_ctx.stats.sv = sv->next;
782 continue;
783 }
784
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100785 if (!(s->data_ctx.stats.flags & STAT_FMT_CSV)) {
Willy Tarreau2ea81932007-11-30 12:04:38 +0100786 static char *srv_hlt_st[7] = { "DOWN", "DN %d/%d &uarr;",
787 "UP %d/%d &darr;", "UP",
788 "NOLB %d/%d &darr;", "NOLB",
789 "<i>no check</i>" };
Willy Tarreau55bb8452007-10-17 18:44:57 +0200790 chunk_printf(&msg, sizeof(trash),
Willy Tarreau91861262007-10-17 17:06:05 +0200791 /* name */
792 "<tr align=\"center\" class=\"%s%d\"><td>%s</td>"
Elijah Epifanovacafc5f2007-10-25 20:15:38 +0200793 /* queue : current, max, limit */
794 "<td align=right>%d</td><td align=right>%d</td><td align=right>%s</td>"
Willy Tarreauddbb82f2007-12-05 10:34:49 +0100795 /* sessions : current, max, limit, total, lbtot */
Willy Tarreau55bb8452007-10-17 18:44:57 +0200796 "<td align=right>%d</td><td align=right>%d</td>"
797 "<td align=right>%s</td><td align=right>%d</td>"
Willy Tarreauddbb82f2007-12-05 10:34:49 +0100798 "<td align=right>%d</td>"
Willy Tarreau91861262007-10-17 17:06:05 +0200799 /* bytes : in, out */
800 "<td align=right>%lld</td><td align=right>%lld</td>"
801 /* denied: req, resp */
802 "<td align=right></td><td align=right>%d</td>"
803 /* errors : request, connect, response */
804 "<td align=right></td><td align=right>%d</td><td align=right>%d</td>\n"
Krzysztof Oledzki1cf36ba2007-10-18 19:12:30 +0200805 /* warnings: retries, redispatches */
Krzysztof Piotr Oledzki25b501a2008-01-06 16:36:16 +0100806 "<td align=right>%u</td><td align=right>%u</td>"
Willy Tarreau91861262007-10-17 17:06:05 +0200807 "",
808 (sv->state & SRV_BACKUP) ? "backup" : "active",
809 sv_state, sv->id,
Elijah Epifanovacafc5f2007-10-25 20:15:38 +0200810 sv->nbpend, sv->nbpend_max, LIM2A0(sv->maxqueue, "-"),
Willy Tarreauddbb82f2007-12-05 10:34:49 +0100811 sv->cur_sess, sv->cur_sess_max, LIM2A1(sv->maxconn, "-"),
812 sv->cum_sess, sv->cum_lbconn,
Willy Tarreau91861262007-10-17 17:06:05 +0200813 sv->bytes_in, sv->bytes_out,
814 sv->failed_secu,
Krzysztof Oledzki1cf36ba2007-10-18 19:12:30 +0200815 sv->failed_conns, sv->failed_resp,
Krzysztof Piotr Oledzki25b501a2008-01-06 16:36:16 +0100816 sv->retries, sv->redispatches);
Willy Tarreau91861262007-10-17 17:06:05 +0200817
Willy Tarreau55bb8452007-10-17 18:44:57 +0200818 /* status */
819 chunk_printf(&msg, sizeof(trash), "<td nowrap>");
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200820
821 if (sv->state & SRV_CHECKED)
822 chunk_printf(&msg, sizeof(trash), "%s ",
823 human_time(now.tv_sec - sv->last_change, 1));
824
Willy Tarreau55bb8452007-10-17 18:44:57 +0200825 chunk_printf(&msg, sizeof(trash),
Willy Tarreau91861262007-10-17 17:06:05 +0200826 srv_hlt_st[sv_state],
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +0100827 (svs->state & SRV_RUNNING) ? (svs->health - svs->rise + 1) : (svs->health),
828 (svs->state & SRV_RUNNING) ? (svs->fall) : (svs->rise));
Willy Tarreau91861262007-10-17 17:06:05 +0200829
Willy Tarreau55bb8452007-10-17 18:44:57 +0200830 chunk_printf(&msg, sizeof(trash),
Willy Tarreau91861262007-10-17 17:06:05 +0200831 /* weight */
832 "</td><td>%d</td>"
833 /* act, bck */
834 "<td>%s</td><td>%s</td>"
835 "",
Willy Tarreau5542af62007-12-03 02:04:00 +0100836 (sv->eweight * px->lbprm.wmult + px->lbprm.wdiv - 1) / px->lbprm.wdiv,
Willy Tarreau91861262007-10-17 17:06:05 +0200837 (sv->state & SRV_BACKUP) ? "-" : "Y",
838 (sv->state & SRV_BACKUP) ? "Y" : "-");
839
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200840 /* check failures: unique, fatal, down time */
Willy Tarreau55bb8452007-10-17 18:44:57 +0200841 if (sv->state & SRV_CHECKED)
842 chunk_printf(&msg, sizeof(trash),
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200843 "<td align=right>%d</td><td align=right>%d</td>"
844 "<td nowrap align=right>%s</td>"
Willy Tarreau4bab24d2007-11-30 18:16:29 +0100845 "",
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +0100846 svs->failed_checks, svs->down_trans,
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200847 human_time(srv_downtime(sv), 1));
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +0100848 else if (sv != svs)
849 chunk_printf(&msg, sizeof(trash),
850 "<td nowrap colspan=3>via %s/%s</td>", svs->proxy->id, svs->id );
Willy Tarreau55bb8452007-10-17 18:44:57 +0200851 else
852 chunk_printf(&msg, sizeof(trash),
Willy Tarreau4bab24d2007-11-30 18:16:29 +0100853 "<td colspan=3></td>");
854
855 /* throttle */
856 if ((sv->state & SRV_WARMINGUP) &&
857 now.tv_sec < sv->last_change + sv->slowstart &&
858 now.tv_sec >= sv->last_change) {
859 unsigned int ratio;
860 ratio = MAX(1, 100 * (now.tv_sec - sv->last_change) / sv->slowstart);
861 chunk_printf(&msg, sizeof(trash),
862 "<td>%d %%</td></tr>\n", ratio);
863 } else {
864 chunk_printf(&msg, sizeof(trash),
865 "<td>-</td></tr>\n");
866 }
Willy Tarreau55bb8452007-10-17 18:44:57 +0200867 } else {
Willy Tarreau2ea81932007-11-30 12:04:38 +0100868 static char *srv_hlt_st[7] = { "DOWN,", "DOWN %d/%d,",
869 "UP %d/%d,", "UP,",
870 "NOLB %d/%d,", "NOLB,",
871 "no check," };
Willy Tarreau55bb8452007-10-17 18:44:57 +0200872 chunk_printf(&msg, sizeof(trash),
873 /* pxid, name */
874 "%s,%s,"
875 /* queue : current, max */
876 "%d,%d,"
Willy Tarreauddbb82f2007-12-05 10:34:49 +0100877 /* sessions : current, max, limit, total */
Willy Tarreau55bb8452007-10-17 18:44:57 +0200878 "%d,%d,%s,%d,"
879 /* bytes : in, out */
880 "%lld,%lld,"
881 /* denied: req, resp */
882 ",%d,"
883 /* errors : request, connect, response */
884 ",%d,%d,"
Krzysztof Oledzki1cf36ba2007-10-18 19:12:30 +0200885 /* warnings: retries, redispatches */
Krzysztof Piotr Oledzki25b501a2008-01-06 16:36:16 +0100886 "%u,%u,"
Willy Tarreau55bb8452007-10-17 18:44:57 +0200887 "",
888 px->id, sv->id,
889 sv->nbpend, sv->nbpend_max,
Willy Tarreaudcd47712007-11-04 23:35:08 +0100890 sv->cur_sess, sv->cur_sess_max, LIM2A0(sv->maxconn, ""), sv->cum_sess,
Willy Tarreau55bb8452007-10-17 18:44:57 +0200891 sv->bytes_in, sv->bytes_out,
892 sv->failed_secu,
Krzysztof Oledzki1cf36ba2007-10-18 19:12:30 +0200893 sv->failed_conns, sv->failed_resp,
Krzysztof Piotr Oledzki25b501a2008-01-06 16:36:16 +0100894 sv->retries, sv->redispatches);
Willy Tarreau55bb8452007-10-17 18:44:57 +0200895
896 /* status */
897 chunk_printf(&msg, sizeof(trash),
898 srv_hlt_st[sv_state],
899 (sv->state & SRV_RUNNING) ? (sv->health - sv->rise + 1) : (sv->health),
900 (sv->state & SRV_RUNNING) ? (sv->fall) : (sv->rise));
Willy Tarreau91861262007-10-17 17:06:05 +0200901
Willy Tarreau55bb8452007-10-17 18:44:57 +0200902 chunk_printf(&msg, sizeof(trash),
903 /* weight, active, backup */
904 "%d,%d,%d,"
905 "",
Willy Tarreau5542af62007-12-03 02:04:00 +0100906 (sv->eweight * px->lbprm.wmult + px->lbprm.wdiv - 1) / px->lbprm.wdiv,
Willy Tarreau55bb8452007-10-17 18:44:57 +0200907 (sv->state & SRV_BACKUP) ? 0 : 1,
908 (sv->state & SRV_BACKUP) ? 1 : 0);
909
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200910 /* check failures: unique, fatal; last change, total downtime */
Willy Tarreau55bb8452007-10-17 18:44:57 +0200911 if (sv->state & SRV_CHECKED)
912 chunk_printf(&msg, sizeof(trash),
Elijah Epifanovacafc5f2007-10-25 20:15:38 +0200913 "%d,%d,%d,%d,",
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200914 sv->failed_checks, sv->down_trans,
915 now.tv_sec - sv->last_change, srv_downtime(sv));
Willy Tarreau55bb8452007-10-17 18:44:57 +0200916 else
917 chunk_printf(&msg, sizeof(trash),
Elijah Epifanovacafc5f2007-10-25 20:15:38 +0200918 ",,,,");
919
Willy Tarreau4bab24d2007-11-30 18:16:29 +0100920 /* queue limit, pid, iid, sid, */
Elijah Epifanovacafc5f2007-10-25 20:15:38 +0200921 chunk_printf(&msg, sizeof(trash),
Willy Tarreaudcd47712007-11-04 23:35:08 +0100922 "%s,"
Willy Tarreau4bab24d2007-11-30 18:16:29 +0100923 "%d,%d,%d,",
Willy Tarreaudcd47712007-11-04 23:35:08 +0100924 LIM2A0(sv->maxqueue, ""),
925 relative_pid, px->uuid, sv->puid);
Willy Tarreau4bab24d2007-11-30 18:16:29 +0100926
927 /* throttle */
928 if ((sv->state & SRV_WARMINGUP) &&
929 now.tv_sec < sv->last_change + sv->slowstart &&
930 now.tv_sec >= sv->last_change) {
931 unsigned int ratio;
932 ratio = MAX(1, 100 * (now.tv_sec - sv->last_change) / sv->slowstart);
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100933 chunk_printf(&msg, sizeof(trash), "%d", ratio);
Willy Tarreau4bab24d2007-11-30 18:16:29 +0100934 }
935
Willy Tarreauddbb82f2007-12-05 10:34:49 +0100936 /* sessions: lbtot */
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100937 chunk_printf(&msg, sizeof(trash), ",%d,", sv->cum_lbconn);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +0100938
939 /* tracked */
940 if (sv->tracked)
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100941 chunk_printf(&msg, sizeof(trash), "%s/%s,",
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +0100942 sv->tracked->proxy->id, sv->tracked->id);
943 else
944 chunk_printf(&msg, sizeof(trash), ",");
945
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100946 /* type, then EOL */
947 chunk_printf(&msg, sizeof(trash), "%d,\n", STATS_TYPE_SV);
Willy Tarreau55bb8452007-10-17 18:44:57 +0200948 }
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +0200949 if (buffer_write_chunk(rep, &msg) >= 0)
Willy Tarreau91861262007-10-17 17:06:05 +0200950 return 0;
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100951 } /* for sv */
Willy Tarreau91861262007-10-17 17:06:05 +0200952
953 s->data_ctx.stats.px_st = DATA_ST_PX_BE;
954 /* fall through */
955
956 case DATA_ST_PX_BE:
957 /* print the backend */
Willy Tarreau39f7e6d2008-03-17 21:38:24 +0100958 if ((px->cap & PR_CAP_BE) &&
959 (!(s->data_ctx.stats.flags & STAT_BOUND) || (s->data_ctx.stats.type & (1 << STATS_TYPE_BE)))) {
960 if (!(s->data_ctx.stats.flags & STAT_FMT_CSV)) {
Willy Tarreau55bb8452007-10-17 18:44:57 +0200961 chunk_printf(&msg, sizeof(trash),
Willy Tarreau91861262007-10-17 17:06:05 +0200962 /* name */
963 "<tr align=center class=\"backend\"><td>Backend</td>"
964 /* queue : current, max */
Elijah Epifanovacafc5f2007-10-25 20:15:38 +0200965 "<td align=right>%d</td><td align=right>%d</td><td></td>"
Willy Tarreauddbb82f2007-12-05 10:34:49 +0100966 /* sessions : current, max, limit, total, lbtot */
967 "<td align=right>%d</td><td align=right>%d</td>"
968 "<td align=right>%d</td><td align=right>%d</td>"
969 "<td align=right>%d</td>"
Willy Tarreau91861262007-10-17 17:06:05 +0200970 /* bytes : in, out */
971 "<td align=right>%lld</td><td align=right>%lld</td>"
972 /* denied: req, resp */
973 "<td align=right>%d</td><td align=right>%d</td>"
974 /* errors : request, connect, response */
975 "<td align=right></td><td align=right>%d</td><td align=right>%d</td>\n"
Krzysztof Oledzki1cf36ba2007-10-18 19:12:30 +0200976 /* warnings: retries, redispatches */
Krzysztof Piotr Oledzki25b501a2008-01-06 16:36:16 +0100977 "<td align=right>%u</td><td align=right>%u</td>"
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200978 /* backend status: reflect backend status (up/down): we display UP
Willy Tarreau91861262007-10-17 17:06:05 +0200979 * if the backend has known working servers or if it has no server at
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200980 * all (eg: for stats). Then we display the total weight, number of
Willy Tarreau91861262007-10-17 17:06:05 +0200981 * active and backups. */
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200982 "<td align=center nowrap>%s %s</td><td align=center>%d</td>"
983 "<td align=center>%d</td><td align=center>%d</td>",
Willy Tarreau91861262007-10-17 17:06:05 +0200984 px->nbpend /* or px->totpend ? */, px->nbpend_max,
Willy Tarreauddbb82f2007-12-05 10:34:49 +0100985 px->beconn, px->beconn_max, px->fullconn, px->cum_beconn, px->cum_lbconn,
Willy Tarreau91861262007-10-17 17:06:05 +0200986 px->bytes_in, px->bytes_out,
987 px->denied_req, px->denied_resp,
988 px->failed_conns, px->failed_resp,
Krzysztof Oledzki1cf36ba2007-10-18 19:12:30 +0200989 px->retries, px->redispatches,
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200990 human_time(now.tv_sec - px->last_change, 1),
Willy Tarreau2ea81932007-11-30 12:04:38 +0100991 (px->lbprm.tot_weight > 0 || !px->srv) ? "UP" :
992 "<font color=\"red\"><b>DOWN</b></font>",
Willy Tarreau5542af62007-12-03 02:04:00 +0100993 (px->lbprm.tot_weight * px->lbprm.wmult + px->lbprm.wdiv - 1) / px->lbprm.wdiv,
Willy Tarreau20697042007-11-15 23:26:18 +0100994 px->srv_act, px->srv_bck);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200995
996 chunk_printf(&msg, sizeof(trash),
Willy Tarreau4bab24d2007-11-30 18:16:29 +0100997 /* rest of backend: nothing, down transitions, total downtime, throttle */
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200998 "<td align=center>&nbsp;</td><td align=\"right\">%d</td>"
999 "<td align=\"right\" nowrap>%s</td>"
Willy Tarreau4bab24d2007-11-30 18:16:29 +01001000 "<td></td>"
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001001 "</tr>",
1002 px->down_trans,
1003 px->srv?human_time(be_downtime(px), 1):"&nbsp;");
Willy Tarreau55bb8452007-10-17 18:44:57 +02001004 } else {
1005 chunk_printf(&msg, sizeof(trash),
1006 /* pxid, name */
1007 "%s,BACKEND,"
1008 /* queue : current, max */
1009 "%d,%d,"
Willy Tarreauddbb82f2007-12-05 10:34:49 +01001010 /* sessions : current, max, limit, total */
Willy Tarreau55bb8452007-10-17 18:44:57 +02001011 "%d,%d,%d,%d,"
1012 /* bytes : in, out */
1013 "%lld,%lld,"
1014 /* denied: req, resp */
1015 "%d,%d,"
1016 /* errors : request, connect, response */
1017 ",%d,%d,"
Krzysztof Oledzki1cf36ba2007-10-18 19:12:30 +02001018 /* warnings: retries, redispatches */
Krzysztof Piotr Oledzki25b501a2008-01-06 16:36:16 +01001019 "%u,%u,"
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001020 /* backend status: reflect backend status (up/down): we display UP
Willy Tarreau55bb8452007-10-17 18:44:57 +02001021 * if the backend has known working servers or if it has no server at
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001022 * all (eg: for stats). Then we display the total weight, number of
Willy Tarreau55bb8452007-10-17 18:44:57 +02001023 * active and backups. */
1024 "%s,"
1025 "%d,%d,%d,"
Willy Tarreau4bab24d2007-11-30 18:16:29 +01001026 /* rest of backend: nothing, down transitions, last change, total downtime */
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001027 ",%d,%d,%d,,"
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +01001028 /* pid, iid, sid, throttle, lbtot, tracked, type */
1029 "%d,%d,0,,%d,,%d,"
Willy Tarreau55bb8452007-10-17 18:44:57 +02001030 "\n",
1031 px->id,
1032 px->nbpend /* or px->totpend ? */, px->nbpend_max,
1033 px->beconn, px->beconn_max, px->fullconn, px->cum_beconn,
1034 px->bytes_in, px->bytes_out,
1035 px->denied_req, px->denied_resp,
1036 px->failed_conns, px->failed_resp,
Krzysztof Oledzki1cf36ba2007-10-18 19:12:30 +02001037 px->retries, px->redispatches,
Willy Tarreau20697042007-11-15 23:26:18 +01001038 (px->lbprm.tot_weight > 0 || !px->srv) ? "UP" : "DOWN",
Willy Tarreau5542af62007-12-03 02:04:00 +01001039 (px->lbprm.tot_weight * px->lbprm.wmult + px->lbprm.wdiv - 1) / px->lbprm.wdiv,
Willy Tarreau20697042007-11-15 23:26:18 +01001040 px->srv_act, px->srv_bck,
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001041 px->down_trans, now.tv_sec - px->last_change,
Willy Tarreau20697042007-11-15 23:26:18 +01001042 px->srv?be_downtime(px):0,
Willy Tarreauddbb82f2007-12-05 10:34:49 +01001043 relative_pid, px->uuid,
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +01001044 px->cum_lbconn, STATS_TYPE_BE);
Willy Tarreau55bb8452007-10-17 18:44:57 +02001045 }
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +02001046 if (buffer_write_chunk(rep, &msg) >= 0)
Willy Tarreau91861262007-10-17 17:06:05 +02001047 return 0;
1048 }
1049
1050 s->data_ctx.stats.px_st = DATA_ST_PX_END;
1051 /* fall through */
1052
1053 case DATA_ST_PX_END:
Willy Tarreau39f7e6d2008-03-17 21:38:24 +01001054 if (!(s->data_ctx.stats.flags & STAT_FMT_CSV)) {
Willy Tarreau55bb8452007-10-17 18:44:57 +02001055 chunk_printf(&msg, sizeof(trash), "</table><p>\n");
Willy Tarreau91861262007-10-17 17:06:05 +02001056
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +02001057 if (buffer_write_chunk(rep, &msg) >= 0)
Willy Tarreau55bb8452007-10-17 18:44:57 +02001058 return 0;
1059 }
Willy Tarreau91861262007-10-17 17:06:05 +02001060
1061 s->data_ctx.stats.px_st = DATA_ST_PX_FIN;
1062 /* fall through */
1063
1064 case DATA_ST_PX_FIN:
1065 return 1;
1066
1067 default:
1068 /* unknown state, we should put an abort() here ! */
1069 return 1;
1070 }
1071}
1072
Willy Tarreau10522fd2008-07-09 20:12:41 +02001073static struct cfg_kw_list cfg_kws = {{ },{
1074 { CFG_GLOBAL, "stats", stats_parse_global },
1075 { 0, NULL, NULL },
1076}};
1077
1078__attribute__((constructor))
1079static void __dumpstats_module_init(void)
1080{
1081 cfg_register_keywords(&cfg_kws);
1082}
1083
Willy Tarreau91861262007-10-17 17:06:05 +02001084/*
1085 * Local variables:
1086 * c-indent-level: 8
1087 * c-basic-offset: 8
1088 * End:
1089 */