[MEDIUM] store a complete dump of request and response errors in proxies

Each proxy instance, either frontend or backend, now has some room
dedicated to storing a complete dated request or response in case
of parsing error. This will make it possible to consult errors in
order to find the exact cause, which is particularly important for
troubleshooting faulty applications.
This commit is contained in:
Willy Tarreau 2009-03-01 23:21:47 +01:00
parent 7552c031c0
commit f073a83b1d
2 changed files with 42 additions and 1 deletions

View File

@ -123,6 +123,17 @@ struct fwrr_group {
int next_weight; /* total weight of the next time range */
};
struct error_snapshot {
struct timeval when; /* date of this event, (tv_sec == 0) means "never" */
unsigned int len; /* original length of the last invalid request/response */
unsigned int pos; /* position of the first invalid character */
unsigned int sid; /* ID of the faulty session */
struct server *srv; /* server associated with the error (or NULL) */
struct proxy *oe; /* other end = frontend or backend involved */
struct sockaddr_storage src; /* client's address */
char buf[BUFSIZE]; /* copy of the beginning of the message */
};
struct proxy {
struct listener *listen; /* the listen addresses and sockets */
struct in_addr mon_net, mon_mask; /* don't forward connections from this net (network order) FIXME: should support IPv6 */
@ -259,6 +270,7 @@ struct proxy {
int next_svid; /* next server-id, used for SNMP */
unsigned int backlog; /* force the frontend's listen backlog */
unsigned int bind_proc; /* bitmask of processes using this proxy. 0 = all. */
struct error_snapshot invalid_req, invalid_rep; /* captures of last errors */
};
struct switching_rule {

View File

@ -1538,7 +1538,7 @@ int http_process_request(struct session *s, struct buffer *req)
* For the parsing, we use a 28 states FSM.
*
* Here is the information we currently have :
* req->data + req->som = beginning of request
* req->data + msg->som = beginning of request
* req->data + req->eoh = end of processed headers / start of current one
* req->data + req->eol = end of current header or line (LF or CRLF)
* req->lr = first non-visited byte
@ -2317,6 +2317,21 @@ int http_process_request(struct session *s, struct buffer *req)
return 1;
return_bad_req: /* let's centralize all bad requests */
if (unlikely(msg->msg_state == HTTP_MSG_ERROR)) {
/* we detected a parsing error. We want to archive this request
* in the dedicated proxy area for later troubleshooting.
*/
struct error_snapshot *es = &s->fe->invalid_req;
int maxlen = MIN(req->r - req->data + msg->som, sizeof(es->buf));
memcpy(es->buf, req->data + msg->som, maxlen);
es->pos = req->lr - req->data + msg->som;
es->len = req->r - req->data + msg->som;
es->when = now;
es->sid = s->uniq_id;
es->srv = s->srv;
es->oe = s->be;
es->src = s->cli_addr;
}
txn->req.msg_state = HTTP_MSG_ERROR;
txn->status = 400;
req->analysers = 0;
@ -2539,6 +2554,20 @@ int process_response(struct session *t)
if (unlikely(msg->msg_state != HTTP_MSG_BODY)) {
/* Invalid response */
if (unlikely(msg->msg_state == HTTP_MSG_ERROR)) {
/* we detected a parsing error. We want to archive this response
* in the dedicated proxy area for later troubleshooting.
*/
struct error_snapshot *es = &t->be->invalid_rep;
int maxlen = MIN(rep->r - rep->data + msg->som, sizeof(es->buf));
memcpy(es->buf, rep->data + msg->som, maxlen);
es->pos = rep->lr - rep->data + msg->som;
es->len = rep->r - rep->data + msg->som;
es->when = now;
es->sid = t->uniq_id;
es->srv = t->srv;
es->oe = t->fe;
es->src = t->cli_addr;
hdr_response_bad:
//buffer_shutr(rep);
//buffer_shutw(req);