[STATS] add support for "show info" on the unix socket

It is sometimes required to know some informations such as the
process uptime when consulting statistics. This patch adds the
"show info" command to query those informations on the UNIX
socket.
This commit is contained in:
Willy Tarreau 2008-01-03 10:19:15 +01:00
parent 9f2b73064b
commit a8efd362b2
4 changed files with 75 additions and 24 deletions

View File

@ -145,14 +145,16 @@ stats socket <path> [{uid | user} <uid>] [{gid | group} <gid>] [mode <mode>]
Creates a UNIX socket in stream mode at location <path>. Any previously Creates a UNIX socket in stream mode at location <path>. Any previously
existing socket will be backed up then replaced. Connections to this socket existing socket will be backed up then replaced. Connections to this socket
will get a CSV-formated output of the process statistics in response to the will get a CSV-formated output of the process statistics in response to the
"show stat" command followed by a line feed. On platforms which support it, "show stat" command followed by a line feed, and more general process
it is possible to restrict access to this socket by specifying numerical IDs information in response to the "show info" command followed by a line feed.
after "uid" and "gid", or valid user and group names after the "user" and
"group" keywords. It is also possible to restrict permissions on the socket On platforms which support it, it is possible to restrict access to this
by passing an octal value after the "mode" keyword (same syntax as chmod). socket by specifying numerical IDs after "uid" and "gid", or valid user and
Depending on the platform, the permissions on the socket will be inherited group names after the "user" and "group" keywords. It is also possible to
from the directory which hosts it, or from the user the process is started restrict permissions on the socket by passing an octal value after the "mode"
with. keyword (same syntax as chmod). Depending on the platform, the permissions on
the socket will be inherited from the directory which hosts it, or from the
user the process is started with.
stats timeout <timeout, in milliseconds> stats timeout <timeout, in milliseconds>
The default timeout on the stats socket is set to 10 seconds. It is possible The default timeout on the stats socket is set to 10 seconds. It is possible

View File

@ -27,7 +27,9 @@
#include <types/buffers.h> #include <types/buffers.h>
#include <types/session.h> #include <types/session.h>
#define STAT_FMT_HTML 0x1 #define STAT_FMT_HTML 0x1
#define STAT_SHOW_STAT 0x2
#define STAT_SHOW_INFO 0x4
int stats_parse_global(const char **args, char *err, int errlen); int stats_parse_global(const char **args, char *err, int errlen);
int stats_dump_raw(struct session *s, struct uri_auth *uri, int flags); int stats_dump_raw(struct session *s, struct uri_auth *uri, int flags);

View File

@ -187,6 +187,7 @@ int stats_dump_raw(struct session *s, struct uri_auth *uri, int flags)
struct buffer *rep = s->rep; struct buffer *rep = s->rep;
struct proxy *px; struct proxy *px;
struct chunk msg; struct chunk msg;
unsigned int up;
msg.len = 0; msg.len = 0;
msg.str = trash; msg.str = trash;
@ -201,16 +202,50 @@ int stats_dump_raw(struct session *s, struct uri_auth *uri, int flags)
/* fall through */ /* fall through */
case DATA_ST_HEAD: case DATA_ST_HEAD:
print_csv_header(&msg, sizeof(trash)); if (flags & STAT_SHOW_STAT) {
if (buffer_write_chunk(rep, &msg) != 0) print_csv_header(&msg, sizeof(trash));
return 0; if (buffer_write_chunk(rep, &msg) != 0)
return 0;
}
s->data_state = DATA_ST_INFO; s->data_state = DATA_ST_INFO;
/* fall through */ /* fall through */
case DATA_ST_INFO: case DATA_ST_INFO:
up = (now.tv_sec - start_date.tv_sec);
memset(&s->data_ctx, 0, sizeof(s->data_ctx)); memset(&s->data_ctx, 0, sizeof(s->data_ctx));
if (flags & STAT_SHOW_INFO) {
chunk_printf(&msg, sizeof(trash),
"Name: " PRODUCT_NAME "\n"
"Version: " HAPROXY_VERSION "\n"
"Release_date: " HAPROXY_DATE "\n"
"Nbproc: %d\n"
"Process_num: %d\n"
"Pid: %d\n"
"Uptime: %dd %dh%02dm%02ds\n"
"Uptime_sec: %d\n"
"Memmax_MB: %d\n"
"Ulimit-n: %d\n"
"Maxsock: %d\n"
"Maxconn: %d\n"
"CurrConns: %d\n"
"",
global.nbproc,
relative_pid,
pid,
up / 86400, (up % 86400) / 3600, (up % 3600) / 60, (up % 60),
up,
global.rlimit_memmax,
global.rlimit_nofile,
global.maxsock,
global.maxconn,
actconn
);
if (buffer_write_chunk(rep, &msg) != 0)
return 0;
}
s->data_ctx.stats.px = proxy; s->data_ctx.stats.px = proxy;
s->data_ctx.stats.px_st = DATA_ST_PX_INIT; s->data_ctx.stats.px_st = DATA_ST_PX_INIT;
s->data_state = DATA_ST_LIST; s->data_state = DATA_ST_LIST;
@ -218,17 +253,20 @@ int stats_dump_raw(struct session *s, struct uri_auth *uri, int flags)
case DATA_ST_LIST: case DATA_ST_LIST:
/* dump proxies */ /* dump proxies */
while (s->data_ctx.stats.px) { if (flags & STAT_SHOW_STAT) {
px = s->data_ctx.stats.px; while (s->data_ctx.stats.px) {
/* skip the disabled proxies and non-networked ones */ px = s->data_ctx.stats.px;
if (px->state != PR_STSTOPPED && (px->cap & (PR_CAP_FE | PR_CAP_BE))) /* skip the disabled proxies and non-networked ones */
if (stats_dump_proxy(s, px, NULL, 0) == 0) if (px->state != PR_STSTOPPED &&
return 0; (px->cap & (PR_CAP_FE | PR_CAP_BE)))
if (stats_dump_proxy(s, px, NULL, 0) == 0)
return 0;
s->data_ctx.stats.px = px->next; s->data_ctx.stats.px = px->next;
s->data_ctx.stats.px_st = DATA_ST_PX_INIT; s->data_ctx.stats.px_st = DATA_ST_PX_INIT;
}
/* here, we just have reached the last proxy */
} }
/* here, we just have reached the last proxy */
s->data_state = DATA_ST_END; s->data_state = DATA_ST_END;
/* fall through */ /* fall through */
@ -402,7 +440,7 @@ int stats_dump_http(struct session *s, struct uri_auth *uri, int flags)
"<hr width=\"100%%\" class=\"hr\">\n" "<hr width=\"100%%\" class=\"hr\">\n"
"<h3>&gt; General process information</h3>\n" "<h3>&gt; General process information</h3>\n"
"<table border=0 cols=4><tr><td align=\"left\" nowrap width=\"1%%\">\n" "<table border=0 cols=4><tr><td align=\"left\" nowrap width=\"1%%\">\n"
"<p><b>pid = </b> %d (nbproc = %d)<br>\n" "<p><b>pid = </b> %d (process #%d, nbproc = %d)<br>\n"
"<b>uptime = </b> %dd %dh%02dm%02ds<br>\n" "<b>uptime = </b> %dd %dh%02dm%02ds<br>\n"
"<b>system limits :</b> memmax = %s%s ; ulimit-n = %d<br>\n" "<b>system limits :</b> memmax = %s%s ; ulimit-n = %d<br>\n"
"<b>maxsock = </b> %d<br>\n" "<b>maxsock = </b> %d<br>\n"
@ -427,7 +465,8 @@ int stats_dump_http(struct session *s, struct uri_auth *uri, int flags)
"<b>Display option:</b><ul style=\"margin-top: 0.25em;\">" "<b>Display option:</b><ul style=\"margin-top: 0.25em;\">"
"", "",
(uri->flags&ST_HIDEVER)?"":(STATS_VERSION_STRING), (uri->flags&ST_HIDEVER)?"":(STATS_VERSION_STRING),
pid, pid, global.nbproc, pid, pid,
relative_pid, global.nbproc,
up / 86400, (up % 86400) / 3600, up / 86400, (up % 86400) / 3600,
(up % 3600) / 60, (up % 60), (up % 3600) / 60, (up % 60),
global.rlimit_memmax ? ultoa(global.rlimit_memmax) : "unlimited", global.rlimit_memmax ? ultoa(global.rlimit_memmax) : "unlimited",

View File

@ -1386,7 +1386,15 @@ void process_uxst_stats(struct task *t, struct timeval *next)
if (s->data_state == DATA_ST_INIT) { if (s->data_state == DATA_ST_INIT) {
if ((s->req->l >= 10) && (memcmp(s->req->data, "show stat\n", 10) == 0)) { if ((s->req->l >= 10) && (memcmp(s->req->data, "show stat\n", 10) == 0)) {
/* send the stats, and changes the data_state */ /* send the stats, and changes the data_state */
if (stats_dump_raw(s, NULL, 0) != 0) { if (stats_dump_raw(s, NULL, STAT_SHOW_STAT) != 0) {
s->srv_state = SV_STCLOSE;
fsm_resync |= 1;
continue;
}
}
if ((s->req->l >= 10) && (memcmp(s->req->data, "show info\n", 10) == 0)) {
/* send the stats, and changes the data_state */
if (stats_dump_raw(s, NULL, STAT_SHOW_INFO) != 0) {
s->srv_state = SV_STCLOSE; s->srv_state = SV_STCLOSE;
fsm_resync |= 1; fsm_resync |= 1;
continue; continue;