mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-22 14:21:25 +02:00
[CLEANUP] move remaining stats sockets code to dumpstats
The remains of the stats socket code has nothing to do in proto_uxst anymore and must move to dumpstats. The code is much cleaner and more structured. It was also an opportunity to rename AN_REQ_UNIX_STATS as AN_REQ_STATS_SOCK as the stats socket is no longer unix-specific either. The last item refering to stats in proto_uxst is the setting of the task's nice value which should in fact come from the listener.
This commit is contained in:
parent
8e13d7492d
commit
5ca791da8d
@ -64,8 +64,8 @@
|
|||||||
// max # args on a configuration line
|
// max # args on a configuration line
|
||||||
#define MAX_LINE_ARGS 64
|
#define MAX_LINE_ARGS 64
|
||||||
|
|
||||||
// max # args on a uxts socket
|
// max # args on a stats socket
|
||||||
#define MAX_UXST_ARGS 16
|
#define MAX_STATS_ARGS 16
|
||||||
|
|
||||||
// max # of added headers per request
|
// max # of added headers per request
|
||||||
#define MAX_NEWHDR 10
|
#define MAX_NEWHDR 10
|
||||||
|
@ -44,6 +44,8 @@
|
|||||||
#define STATS_ST_REP 2
|
#define STATS_ST_REP 2
|
||||||
#define STATS_ST_CLOSE 3
|
#define STATS_ST_CLOSE 3
|
||||||
|
|
||||||
|
int stats_sock_parse_request(struct session *s, char *line);
|
||||||
|
int stats_sock_req_analyser(struct session *s, struct buffer *req, int an_bit);
|
||||||
int stats_dump_raw(struct session *s, struct buffer *rep, struct uri_auth *uri);
|
int stats_dump_raw(struct session *s, struct buffer *rep, struct uri_auth *uri);
|
||||||
void stats_dump_raw_to_buffer(struct session *s, struct buffer *req);
|
void stats_dump_raw_to_buffer(struct session *s, struct buffer *req);
|
||||||
int stats_dump_http(struct session *s, struct buffer *rep, struct uri_auth *uri);
|
int stats_dump_http(struct session *s, struct buffer *rep, struct uri_auth *uri);
|
||||||
|
@ -113,7 +113,7 @@
|
|||||||
#define AN_REQ_HTTP_INNER 0x00000020 /* inner processing of HTTP request */
|
#define AN_REQ_HTTP_INNER 0x00000020 /* inner processing of HTTP request */
|
||||||
#define AN_REQ_HTTP_TARPIT 0x00000040 /* wait for end of HTTP tarpit */
|
#define AN_REQ_HTTP_TARPIT 0x00000040 /* wait for end of HTTP tarpit */
|
||||||
#define AN_REQ_HTTP_BODY 0x00000080 /* inspect HTTP request body */
|
#define AN_REQ_HTTP_BODY 0x00000080 /* inspect HTTP request body */
|
||||||
#define AN_REQ_UNIX_STATS 0x00000100 /* process unix stats socket request */
|
#define AN_REQ_STATS_SOCK 0x00000100 /* process stats socket request */
|
||||||
|
|
||||||
#define AN_RTR_HTTP_HDR 0x00000200 /* inspect HTTP response headers */
|
#define AN_RTR_HTTP_HDR 0x00000200 /* inspect HTTP response headers */
|
||||||
#define AN_REQ_PRST_RDP_COOKIE 0x00000400 /* persistence on rdp cookie */
|
#define AN_REQ_PRST_RDP_COOKIE 0x00000400 /* persistence on rdp cookie */
|
||||||
|
156
src/dumpstats.c
156
src/dumpstats.c
@ -50,6 +50,19 @@
|
|||||||
#include <proto/stream_interface.h>
|
#include <proto/stream_interface.h>
|
||||||
#include <proto/task.h>
|
#include <proto/task.h>
|
||||||
|
|
||||||
|
const char stats_sock_usage_msg[] =
|
||||||
|
"Unknown command. Please enter one of the following commands only :\n"
|
||||||
|
" show info : report information about the running process\n"
|
||||||
|
" show stat : report counters for each proxy and server\n"
|
||||||
|
" show errors : report last request and response errors for each proxy\n"
|
||||||
|
" show sess : report the list of current sessions\n"
|
||||||
|
"\n";
|
||||||
|
|
||||||
|
const struct chunk stats_sock_usage = {
|
||||||
|
.str = (char *)&stats_sock_usage_msg,
|
||||||
|
.len = sizeof(stats_sock_usage_msg)-1
|
||||||
|
};
|
||||||
|
|
||||||
/* This function parses a "stats" statement in the "global" section. It returns
|
/* This function parses a "stats" statement in the "global" section. It returns
|
||||||
* -1 if there is any error, otherwise zero. If it returns -1, it may write an
|
* -1 if there is any error, otherwise zero. If it returns -1, it may write an
|
||||||
* error message into ther <err> buffer, for at most <errlen> bytes, trailing
|
* error message into ther <err> buffer, for at most <errlen> bytes, trailing
|
||||||
@ -107,7 +120,7 @@ static int stats_parse_global(char **args, int section_type, struct proxy *curpx
|
|||||||
global.stats_sock.options = LI_O_NONE;
|
global.stats_sock.options = LI_O_NONE;
|
||||||
global.stats_sock.accept = uxst_event_accept;
|
global.stats_sock.accept = uxst_event_accept;
|
||||||
global.stats_sock.handler = process_session;
|
global.stats_sock.handler = process_session;
|
||||||
global.stats_sock.analysers = AN_REQ_UNIX_STATS;
|
global.stats_sock.analysers = AN_REQ_STATS_SOCK;
|
||||||
global.stats_sock.private = global.stats_fe; /* must point to the frontend */
|
global.stats_sock.private = global.stats_fe; /* must point to the frontend */
|
||||||
|
|
||||||
global.stats_fe->timeout.client = MS_TO_TICKS(10000); /* default timeout of 10 seconds */
|
global.stats_fe->timeout.client = MS_TO_TICKS(10000); /* default timeout of 10 seconds */
|
||||||
@ -211,6 +224,147 @@ int print_csv_header(struct chunk *msg, int size)
|
|||||||
"\n");
|
"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parses the request line in <cmd> and possibly starts dumping stats on
|
||||||
|
* s->rep with the hijack bit set. Returns 1 if OK, 0 in case of any error.
|
||||||
|
* The line is modified after parsing.
|
||||||
|
*/
|
||||||
|
int stats_sock_parse_request(struct session *s, char *line)
|
||||||
|
{
|
||||||
|
char *args[MAX_STATS_ARGS + 1];
|
||||||
|
int arg;
|
||||||
|
|
||||||
|
while (isspace((unsigned char)*line))
|
||||||
|
line++;
|
||||||
|
|
||||||
|
arg = 0;
|
||||||
|
args[arg] = line;
|
||||||
|
|
||||||
|
while (*line && arg < MAX_STATS_ARGS) {
|
||||||
|
if (isspace((unsigned char)*line)) {
|
||||||
|
*line++ = '\0';
|
||||||
|
|
||||||
|
while (isspace((unsigned char)*line))
|
||||||
|
line++;
|
||||||
|
|
||||||
|
args[++arg] = line;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
line++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (++arg <= MAX_STATS_ARGS)
|
||||||
|
args[arg] = line;
|
||||||
|
|
||||||
|
if (strcmp(args[0], "show") == 0) {
|
||||||
|
if (strcmp(args[1], "stat") == 0) {
|
||||||
|
if (*args[2] && *args[3] && *args[4]) {
|
||||||
|
s->data_ctx.stats.flags |= STAT_BOUND;
|
||||||
|
s->data_ctx.stats.iid = atoi(args[2]);
|
||||||
|
s->data_ctx.stats.type = atoi(args[3]);
|
||||||
|
s->data_ctx.stats.sid = atoi(args[4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
s->data_ctx.stats.flags |= STAT_SHOW_STAT;
|
||||||
|
s->data_ctx.stats.flags |= STAT_FMT_CSV;
|
||||||
|
s->ana_state = STATS_ST_REP;
|
||||||
|
buffer_install_hijacker(s, s->rep, stats_dump_raw_to_buffer);
|
||||||
|
}
|
||||||
|
else if (strcmp(args[1], "info") == 0) {
|
||||||
|
s->data_ctx.stats.flags |= STAT_SHOW_INFO;
|
||||||
|
s->data_ctx.stats.flags |= STAT_FMT_CSV;
|
||||||
|
s->ana_state = STATS_ST_REP;
|
||||||
|
buffer_install_hijacker(s, s->rep, stats_dump_raw_to_buffer);
|
||||||
|
}
|
||||||
|
else if (strcmp(args[1], "sess") == 0) {
|
||||||
|
s->ana_state = STATS_ST_REP;
|
||||||
|
buffer_install_hijacker(s, s->rep, stats_dump_sess_to_buffer);
|
||||||
|
}
|
||||||
|
else if (strcmp(args[1], "errors") == 0) {
|
||||||
|
if (*args[2])
|
||||||
|
s->data_ctx.errors.iid = atoi(args[2]);
|
||||||
|
else
|
||||||
|
s->data_ctx.errors.iid = -1;
|
||||||
|
s->data_ctx.errors.px = NULL;
|
||||||
|
s->ana_state = STATS_ST_REP;
|
||||||
|
buffer_install_hijacker(s, s->rep, stats_dump_errors_to_buffer);
|
||||||
|
}
|
||||||
|
else { /* neither "stat" nor "info" nor "sess" */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { /* not "show" */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Processes the stats interpreter on the statistics socket.
|
||||||
|
* In order to ease the transition, we simply simulate the server status
|
||||||
|
* for now. It only knows states STATS_ST_INIT, STATS_ST_REQ, STATS_ST_REP, and
|
||||||
|
* STATS_ST_CLOSE. It removes its analyser bit from req->analysers once done.
|
||||||
|
* It always returns 0.
|
||||||
|
*/
|
||||||
|
int stats_sock_req_analyser(struct session *s, struct buffer *req, int an_bit)
|
||||||
|
{
|
||||||
|
char *line, *p;
|
||||||
|
|
||||||
|
switch (s->ana_state) {
|
||||||
|
case STATS_ST_INIT:
|
||||||
|
/* Stats output not initialized yet */
|
||||||
|
memset(&s->data_ctx.stats, 0, sizeof(s->data_ctx.stats));
|
||||||
|
s->data_source = DATA_SRC_STATS;
|
||||||
|
s->ana_state = STATS_ST_REQ;
|
||||||
|
buffer_write_dis(s->req);
|
||||||
|
/* fall through */
|
||||||
|
|
||||||
|
case STATS_ST_REQ:
|
||||||
|
/* Now, stats are initialized, hijack is not set, and
|
||||||
|
* we are waiting for a complete request line.
|
||||||
|
*/
|
||||||
|
|
||||||
|
line = s->req->data;
|
||||||
|
p = memchr(line, '\n', s->req->l);
|
||||||
|
|
||||||
|
if (p) {
|
||||||
|
*p = '\0';
|
||||||
|
if (!stats_sock_parse_request(s, line)) {
|
||||||
|
/* invalid request */
|
||||||
|
stream_int_retnclose(s->req->prod, &stats_sock_usage);
|
||||||
|
s->ana_state = 0;
|
||||||
|
req->analysers = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* processing a valid or incomplete request */
|
||||||
|
if ((req->flags & BF_FULL) || /* invalid request */
|
||||||
|
(req->flags & BF_READ_ERROR) || /* input error */
|
||||||
|
(req->flags & BF_READ_TIMEOUT) || /* read timeout */
|
||||||
|
tick_is_expired(req->analyse_exp, now_ms) || /* request timeout */
|
||||||
|
(req->flags & BF_SHUTR)) { /* input closed */
|
||||||
|
buffer_shutw_now(s->rep);
|
||||||
|
s->ana_state = 0;
|
||||||
|
req->analysers = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* don't forward nor abort */
|
||||||
|
req->flags |= BF_READ_DONTWAIT; /* we plan to read small requests */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case STATS_ST_REP:
|
||||||
|
/* do nothing while response is being processed */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case STATS_ST_CLOSE:
|
||||||
|
/* end of dump */
|
||||||
|
s->req->analysers &= ~an_bit;
|
||||||
|
s->ana_state = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Produces statistics data for the session <s>. Expects to be called with
|
* Produces statistics data for the session <s>. Expects to be called with
|
||||||
* client socket shut down on input. It *may* make use of informations from
|
* client socket shut down on input. It *may* make use of informations from
|
||||||
|
156
src/proto_uxst.c
156
src/proto_uxst.c
@ -41,7 +41,6 @@
|
|||||||
#include <proto/acl.h>
|
#include <proto/acl.h>
|
||||||
#include <proto/backend.h>
|
#include <proto/backend.h>
|
||||||
#include <proto/buffers.h>
|
#include <proto/buffers.h>
|
||||||
#include <proto/dumpstats.h>
|
|
||||||
#include <proto/fd.h>
|
#include <proto/fd.h>
|
||||||
#include <proto/log.h>
|
#include <proto/log.h>
|
||||||
#include <proto/protocols.h>
|
#include <proto/protocols.h>
|
||||||
@ -78,19 +77,6 @@ static struct protocol proto_unix = {
|
|||||||
.nb_listeners = 0,
|
.nb_listeners = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const char unix_sock_usage_msg[] =
|
|
||||||
"Unknown command. Please enter one of the following commands only :\n"
|
|
||||||
" show info : report information about the running process\n"
|
|
||||||
" show stat : report counters for each proxy and server\n"
|
|
||||||
" show errors : report last request and response errors for each proxy\n"
|
|
||||||
" show sess : report the list of current sessions\n"
|
|
||||||
"\n";
|
|
||||||
|
|
||||||
const struct chunk unix_sock_usage = {
|
|
||||||
.str = (char *)&unix_sock_usage_msg,
|
|
||||||
.len = sizeof(unix_sock_usage_msg)-1
|
|
||||||
};
|
|
||||||
|
|
||||||
/********************************
|
/********************************
|
||||||
* 1) low-level socket functions
|
* 1) low-level socket functions
|
||||||
********************************/
|
********************************/
|
||||||
@ -572,148 +558,6 @@ int uxst_event_accept(int fd) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parses the request line in <cmd> and possibly starts dumping stats on
|
|
||||||
* s->rep with the hijack bit set. Returns 1 if OK, 0 in case of any error.
|
|
||||||
* The line is modified after parsing.
|
|
||||||
*/
|
|
||||||
int unix_sock_parse_request(struct session *s, char *line)
|
|
||||||
{
|
|
||||||
char *args[MAX_UXST_ARGS + 1];
|
|
||||||
int arg;
|
|
||||||
|
|
||||||
while (isspace((unsigned char)*line))
|
|
||||||
line++;
|
|
||||||
|
|
||||||
arg = 0;
|
|
||||||
args[arg] = line;
|
|
||||||
|
|
||||||
while (*line && arg < MAX_UXST_ARGS) {
|
|
||||||
if (isspace((unsigned char)*line)) {
|
|
||||||
*line++ = '\0';
|
|
||||||
|
|
||||||
while (isspace((unsigned char)*line))
|
|
||||||
line++;
|
|
||||||
|
|
||||||
args[++arg] = line;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
line++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (++arg <= MAX_UXST_ARGS)
|
|
||||||
args[arg] = line;
|
|
||||||
|
|
||||||
if (strcmp(args[0], "show") == 0) {
|
|
||||||
if (strcmp(args[1], "stat") == 0) {
|
|
||||||
if (*args[2] && *args[3] && *args[4]) {
|
|
||||||
s->data_ctx.stats.flags |= STAT_BOUND;
|
|
||||||
s->data_ctx.stats.iid = atoi(args[2]);
|
|
||||||
s->data_ctx.stats.type = atoi(args[3]);
|
|
||||||
s->data_ctx.stats.sid = atoi(args[4]);
|
|
||||||
}
|
|
||||||
|
|
||||||
s->data_ctx.stats.flags |= STAT_SHOW_STAT;
|
|
||||||
s->data_ctx.stats.flags |= STAT_FMT_CSV;
|
|
||||||
s->ana_state = STATS_ST_REP;
|
|
||||||
buffer_install_hijacker(s, s->rep, stats_dump_raw_to_buffer);
|
|
||||||
}
|
|
||||||
else if (strcmp(args[1], "info") == 0) {
|
|
||||||
s->data_ctx.stats.flags |= STAT_SHOW_INFO;
|
|
||||||
s->data_ctx.stats.flags |= STAT_FMT_CSV;
|
|
||||||
s->ana_state = STATS_ST_REP;
|
|
||||||
buffer_install_hijacker(s, s->rep, stats_dump_raw_to_buffer);
|
|
||||||
}
|
|
||||||
else if (strcmp(args[1], "sess") == 0) {
|
|
||||||
s->ana_state = STATS_ST_REP;
|
|
||||||
buffer_install_hijacker(s, s->rep, stats_dump_sess_to_buffer);
|
|
||||||
}
|
|
||||||
else if (strcmp(args[1], "errors") == 0) {
|
|
||||||
if (*args[2])
|
|
||||||
s->data_ctx.errors.iid = atoi(args[2]);
|
|
||||||
else
|
|
||||||
s->data_ctx.errors.iid = -1;
|
|
||||||
s->data_ctx.errors.px = NULL;
|
|
||||||
s->ana_state = STATS_ST_REP;
|
|
||||||
buffer_install_hijacker(s, s->rep, stats_dump_errors_to_buffer);
|
|
||||||
}
|
|
||||||
else { /* neither "stat" nor "info" nor "sess" */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { /* not "show" */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Processes the stats interpreter on the statistics socket.
|
|
||||||
* In order to ease the transition, we simply simulate the server status
|
|
||||||
* for now. It only knows states STATS_ST_INIT, STATS_ST_REQ, STATS_ST_REP, and
|
|
||||||
* STATS_ST_CLOSE. It removes the AN_REQ_UNIX_STATS bit from req->analysers
|
|
||||||
* once done. It always returns 0.
|
|
||||||
*/
|
|
||||||
int uxst_req_analyser_stats(struct session *s, struct buffer *req, int an_bit)
|
|
||||||
{
|
|
||||||
char *line, *p;
|
|
||||||
|
|
||||||
switch (s->ana_state) {
|
|
||||||
case STATS_ST_INIT:
|
|
||||||
/* Stats output not initialized yet */
|
|
||||||
memset(&s->data_ctx.stats, 0, sizeof(s->data_ctx.stats));
|
|
||||||
s->data_source = DATA_SRC_STATS;
|
|
||||||
s->ana_state = STATS_ST_REQ;
|
|
||||||
buffer_write_dis(s->req);
|
|
||||||
/* fall through */
|
|
||||||
|
|
||||||
case STATS_ST_REQ:
|
|
||||||
/* Now, stats are initialized, hijack is not set, and
|
|
||||||
* we are waiting for a complete request line.
|
|
||||||
*/
|
|
||||||
|
|
||||||
line = s->req->data;
|
|
||||||
p = memchr(line, '\n', s->req->l);
|
|
||||||
|
|
||||||
if (p) {
|
|
||||||
*p = '\0';
|
|
||||||
if (!unix_sock_parse_request(s, line)) {
|
|
||||||
/* invalid request */
|
|
||||||
stream_int_retnclose(s->req->prod, &unix_sock_usage);
|
|
||||||
s->ana_state = 0;
|
|
||||||
req->analysers = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* processing a valid or incomplete request */
|
|
||||||
if ((req->flags & BF_FULL) || /* invalid request */
|
|
||||||
(req->flags & BF_READ_ERROR) || /* input error */
|
|
||||||
(req->flags & BF_READ_TIMEOUT) || /* read timeout */
|
|
||||||
tick_is_expired(req->analyse_exp, now_ms) || /* request timeout */
|
|
||||||
(req->flags & BF_SHUTR)) { /* input closed */
|
|
||||||
buffer_shutw_now(s->rep);
|
|
||||||
s->ana_state = 0;
|
|
||||||
req->analysers = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* don't forward nor abort */
|
|
||||||
req->flags |= BF_READ_DONTWAIT; /* we plan to read small requests */
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case STATS_ST_REP:
|
|
||||||
/* do nothing while response is being processed */
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case STATS_ST_CLOSE:
|
|
||||||
/* end of dump */
|
|
||||||
s->req->analysers &= ~an_bit;
|
|
||||||
s->ana_state = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
__attribute__((constructor))
|
__attribute__((constructor))
|
||||||
static void __uxst_protocol_init(void)
|
static void __uxst_protocol_init(void)
|
||||||
{
|
{
|
||||||
|
@ -22,13 +22,13 @@
|
|||||||
#include <proto/acl.h>
|
#include <proto/acl.h>
|
||||||
#include <proto/backend.h>
|
#include <proto/backend.h>
|
||||||
#include <proto/buffers.h>
|
#include <proto/buffers.h>
|
||||||
|
#include <proto/dumpstats.h>
|
||||||
#include <proto/hdr_idx.h>
|
#include <proto/hdr_idx.h>
|
||||||
#include <proto/log.h>
|
#include <proto/log.h>
|
||||||
#include <proto/session.h>
|
#include <proto/session.h>
|
||||||
#include <proto/pipe.h>
|
#include <proto/pipe.h>
|
||||||
#include <proto/proto_http.h>
|
#include <proto/proto_http.h>
|
||||||
#include <proto/proto_tcp.h>
|
#include <proto/proto_tcp.h>
|
||||||
#include <proto/proto_uxst.h>
|
|
||||||
#include <proto/proxy.h>
|
#include <proto/proxy.h>
|
||||||
#include <proto/queue.h>
|
#include <proto/queue.h>
|
||||||
#include <proto/server.h>
|
#include <proto/server.h>
|
||||||
@ -841,9 +841,9 @@ resync_stream_interface:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->req->analysers & AN_REQ_UNIX_STATS) {
|
if (s->req->analysers & AN_REQ_STATS_SOCK) {
|
||||||
last_ana |= AN_REQ_UNIX_STATS;
|
last_ana |= AN_REQ_STATS_SOCK;
|
||||||
if (!uxst_req_analyser_stats(s, s->req, AN_REQ_UNIX_STATS))
|
if (!stats_sock_req_analyser(s, s->req, AN_REQ_STATS_SOCK))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user