mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-22 06:11:32 +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
|
||||
#define MAX_LINE_ARGS 64
|
||||
|
||||
// max # args on a uxts socket
|
||||
#define MAX_UXST_ARGS 16
|
||||
// max # args on a stats socket
|
||||
#define MAX_STATS_ARGS 16
|
||||
|
||||
// max # of added headers per request
|
||||
#define MAX_NEWHDR 10
|
||||
|
@ -44,6 +44,8 @@
|
||||
#define STATS_ST_REP 2
|
||||
#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);
|
||||
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);
|
||||
|
@ -113,7 +113,7 @@
|
||||
#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_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_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/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
|
||||
* -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
|
||||
@ -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.accept = uxst_event_accept;
|
||||
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_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");
|
||||
}
|
||||
|
||||
/* 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
|
||||
* 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/backend.h>
|
||||
#include <proto/buffers.h>
|
||||
#include <proto/dumpstats.h>
|
||||
#include <proto/fd.h>
|
||||
#include <proto/log.h>
|
||||
#include <proto/protocols.h>
|
||||
@ -78,19 +77,6 @@ static struct protocol proto_unix = {
|
||||
.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
|
||||
********************************/
|
||||
@ -572,148 +558,6 @@ int uxst_event_accept(int fd) {
|
||||
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))
|
||||
static void __uxst_protocol_init(void)
|
||||
{
|
||||
|
@ -22,13 +22,13 @@
|
||||
#include <proto/acl.h>
|
||||
#include <proto/backend.h>
|
||||
#include <proto/buffers.h>
|
||||
#include <proto/dumpstats.h>
|
||||
#include <proto/hdr_idx.h>
|
||||
#include <proto/log.h>
|
||||
#include <proto/session.h>
|
||||
#include <proto/pipe.h>
|
||||
#include <proto/proto_http.h>
|
||||
#include <proto/proto_tcp.h>
|
||||
#include <proto/proto_uxst.h>
|
||||
#include <proto/proxy.h>
|
||||
#include <proto/queue.h>
|
||||
#include <proto/server.h>
|
||||
@ -841,9 +841,9 @@ resync_stream_interface:
|
||||
break;
|
||||
}
|
||||
|
||||
if (s->req->analysers & AN_REQ_UNIX_STATS) {
|
||||
last_ana |= AN_REQ_UNIX_STATS;
|
||||
if (!uxst_req_analyser_stats(s, s->req, AN_REQ_UNIX_STATS))
|
||||
if (s->req->analysers & AN_REQ_STATS_SOCK) {
|
||||
last_ana |= AN_REQ_STATS_SOCK;
|
||||
if (!stats_sock_req_analyser(s, s->req, AN_REQ_STATS_SOCK))
|
||||
break;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user