[MEDIUM] splitted logs into two versions : TCP and HTTP
logs are handled better with dedicated functions. The HTTP implementation moved to proto_http.c. It has been cleaned up a bit. Now a frontend with option httplog and no log will not call the function anymore.
This commit is contained in:
parent
e2e27a5c8d
commit
422505801f
@ -58,7 +58,7 @@ void send_log(struct proxy *p, int level, char *message, ...);
|
|||||||
/*
|
/*
|
||||||
* send a log for the session when we have enough info about it
|
* send a log for the session when we have enough info about it
|
||||||
*/
|
*/
|
||||||
void sess_log(struct session *s);
|
void tcp_sess_log(struct session *s);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* returns log level for <lev> or -1 if not found.
|
* returns log level for <lev> or -1 if not found.
|
||||||
@ -70,11 +70,6 @@ int get_log_level(const char *lev);
|
|||||||
*/
|
*/
|
||||||
int get_log_facility(const char *fac);
|
int get_log_facility(const char *fac);
|
||||||
|
|
||||||
/*
|
|
||||||
* Initializes some data needed later.
|
|
||||||
*/
|
|
||||||
void init_log();
|
|
||||||
|
|
||||||
#endif /* _PROTO_LOG_H */
|
#endif /* _PROTO_LOG_H */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -275,7 +275,7 @@ int event_accept(int fd) {
|
|||||||
/* we have the client ip */
|
/* we have the client ip */
|
||||||
if (s->logs.logwait & LW_CLIP)
|
if (s->logs.logwait & LW_CLIP)
|
||||||
if (!(s->logs.logwait &= ~LW_CLIP))
|
if (!(s->logs.logwait &= ~LW_CLIP))
|
||||||
sess_log(s);
|
tcp_sess_log(s);
|
||||||
}
|
}
|
||||||
else if (s->cli_addr.ss_family == AF_INET) {
|
else if (s->cli_addr.ss_family == AF_INET) {
|
||||||
char pn[INET_ADDRSTRLEN], sn[INET_ADDRSTRLEN];
|
char pn[INET_ADDRSTRLEN], sn[INET_ADDRSTRLEN];
|
||||||
|
@ -362,7 +362,6 @@ void init(int argc, char **argv)
|
|||||||
localtime((time_t *)&now.tv_sec);
|
localtime((time_t *)&now.tv_sec);
|
||||||
start_date = now;
|
start_date = now;
|
||||||
|
|
||||||
init_log();
|
|
||||||
init_proto_http();
|
init_proto_http();
|
||||||
|
|
||||||
cfg_polling_mechanism = POLL_USE_SELECT; /* select() is always available */
|
cfg_polling_mechanism = POLL_USE_SELECT; /* select() is always available */
|
||||||
|
200
src/log.c
200
src/log.c
@ -27,8 +27,6 @@
|
|||||||
#include <types/backend.h>
|
#include <types/backend.h>
|
||||||
#include <types/global.h>
|
#include <types/global.h>
|
||||||
#include <types/log.h>
|
#include <types/log.h>
|
||||||
#include <types/proto_http.h>
|
|
||||||
#include <types/proxy.h>
|
|
||||||
#include <types/session.h>
|
#include <types/session.h>
|
||||||
|
|
||||||
|
|
||||||
@ -54,12 +52,6 @@ const char *monthname[12] = {
|
|||||||
|
|
||||||
const char sess_term_cond[8] = "-cCsSPRI"; /* normal, CliTo, CliErr, SrvTo, SrvErr, PxErr, Resource, Internal */
|
const char sess_term_cond[8] = "-cCsSPRI"; /* normal, CliTo, CliErr, SrvTo, SrvErr, PxErr, Resource, Internal */
|
||||||
const char sess_fin_state[8] = "-RCHDLQT"; /* cliRequest, srvConnect, srvHeader, Data, Last, Queue, Tarpit */
|
const char sess_fin_state[8] = "-RCHDLQT"; /* cliRequest, srvConnect, srvHeader, Data, Last, Queue, Tarpit */
|
||||||
const char sess_cookie[4] = "NIDV"; /* No cookie, Invalid cookie, cookie for a Down server, Valid cookie */
|
|
||||||
const char sess_set_cookie[8] = "N1I3PD5R"; /* No set-cookie, unknown, Set-Cookie Inserted, unknown,
|
|
||||||
Set-cookie seen and left unchanged (passive), Set-cookie Deleted,
|
|
||||||
unknown, Set-cookie Rewritten */
|
|
||||||
void **pool_requri = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Displays the message on stderr with the date and pid. Overrides the quiet
|
* Displays the message on stderr with the date and pid. Overrides the quiet
|
||||||
@ -148,22 +140,6 @@ int get_log_facility(const char *fac)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define FD_SETS_ARE_BITFIELDS
|
|
||||||
#ifdef FD_SETS_ARE_BITFIELDS
|
|
||||||
/*
|
|
||||||
* This map is used with all the FD_* macros to check whether a particular bit
|
|
||||||
* is set or not. Each bit represents an ACSII code. FD_SET() sets those bytes
|
|
||||||
* which should be encoded. When FD_ISSET() returns non-zero, it means that the
|
|
||||||
* byte should be encoded. Be careful to always pass bytes from 0 to 255
|
|
||||||
* exclusively to the macros.
|
|
||||||
*/
|
|
||||||
fd_set hdr_encode_map[(sizeof(fd_set) > (256/8)) ? 1 : ((256/8) / sizeof(fd_set))];
|
|
||||||
fd_set url_encode_map[(sizeof(fd_set) > (256/8)) ? 1 : ((256/8) / sizeof(fd_set))];
|
|
||||||
|
|
||||||
#else
|
|
||||||
#error "Check if your OS uses bitfields for fd_sets"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function sends a syslog message to both log servers of a proxy,
|
* This function sends a syslog message to both log servers of a proxy,
|
||||||
* or to global log servers if the proxy is NULL.
|
* or to global log servers if the proxy is NULL.
|
||||||
@ -288,30 +264,16 @@ void send_log(struct proxy *p, int level, const char *message, ...)
|
|||||||
/*
|
/*
|
||||||
* send a log for the session when we have enough info about it
|
* send a log for the session when we have enough info about it
|
||||||
*/
|
*/
|
||||||
void sess_log(struct session *s)
|
void tcp_sess_log(struct session *s)
|
||||||
{
|
{
|
||||||
char pn[INET6_ADDRSTRLEN + strlen(":65535")];
|
char pn[INET6_ADDRSTRLEN + strlen(":65535")];
|
||||||
struct proxy *fe = s->fe;
|
struct proxy *fe = s->fe;
|
||||||
struct proxy *be = s->be;
|
struct proxy *be = s->be;
|
||||||
struct proxy *prx_log;
|
struct proxy *prx_log;
|
||||||
struct http_txn *txn = &s->txn;
|
int tolog;
|
||||||
int log, tolog;
|
char *svid;
|
||||||
char *uri;
|
|
||||||
char *pxid;
|
|
||||||
char *srv;
|
|
||||||
struct tm *tm;
|
struct tm *tm;
|
||||||
|
|
||||||
/* This is a first attempt at a better logging system.
|
|
||||||
* For now, we rely on send_log() to provide the date, although it obviously
|
|
||||||
* is the date of the log and not of the request, and most fields are not
|
|
||||||
* computed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* FIXME: let's limit ourselves to frontend logging for now. */
|
|
||||||
tolog = (fe->to_log /*| be->to_log | be->to_log*/);
|
|
||||||
|
|
||||||
log = tolog & ~s->logs.logwait;
|
|
||||||
|
|
||||||
if (s->cli_addr.ss_family == AF_INET)
|
if (s->cli_addr.ss_family == AF_INET)
|
||||||
inet_ntop(AF_INET,
|
inet_ntop(AF_INET,
|
||||||
(const void *)&((struct sockaddr_in *)&s->cli_addr)->sin_addr,
|
(const void *)&((struct sockaddr_in *)&s->cli_addr)->sin_addr,
|
||||||
@ -321,12 +283,6 @@ void sess_log(struct session *s)
|
|||||||
(const void *)&((struct sockaddr_in6 *)(&s->cli_addr))->sin6_addr,
|
(const void *)&((struct sockaddr_in6 *)(&s->cli_addr))->sin6_addr,
|
||||||
pn, sizeof(pn));
|
pn, sizeof(pn));
|
||||||
|
|
||||||
uri = (log & LW_REQ) ? txn->uri ? txn->uri : "<BADREQ>" : "";
|
|
||||||
pxid = be->id;
|
|
||||||
srv = (tolog & LW_SVID) ?
|
|
||||||
(s->data_source != DATA_SRC_STATS) ?
|
|
||||||
(s->srv != NULL) ? s->srv->id : "<NOSRV>" : "<STATS>" : "-";
|
|
||||||
|
|
||||||
tm = localtime((time_t *)&s->logs.tv_accept.tv_sec);
|
tm = localtime((time_t *)&s->logs.tv_accept.tv_sec);
|
||||||
|
|
||||||
if (fe->logfac1 >= 0)
|
if (fe->logfac1 >= 0)
|
||||||
@ -342,141 +298,33 @@ void sess_log(struct session *s)
|
|||||||
else
|
else
|
||||||
prx_log = NULL; /* global */
|
prx_log = NULL; /* global */
|
||||||
|
|
||||||
if (tolog & LW_REQ) {
|
/* FIXME: let's limit ourselves to frontend logging for now. */
|
||||||
char tmpline[MAX_SYSLOG_LEN], *h;
|
tolog = fe->to_log;
|
||||||
int hdr;
|
svid = (tolog & LW_SVID) ? (s->srv != NULL) ? s->srv->id : "<NOSRV>" : "-";
|
||||||
|
|
||||||
h = tmpline;
|
send_log(prx_log, LOG_INFO, "%s:%d [%02d/%s/%04d:%02d:%02d:%02d.%03d]"
|
||||||
|
" %s %s/%s %d/%d/%s%d %s%lld"
|
||||||
/* right now, header capture is limited to the frontend only */
|
" %c%c %d/%d/%d/%d %d/%d\n",
|
||||||
if (fe->to_log & LW_REQHDR &&
|
pn,
|
||||||
txn->req.cap &&
|
(s->cli_addr.ss_family == AF_INET) ?
|
||||||
(h < tmpline + sizeof(tmpline) - 10)) {
|
ntohs(((struct sockaddr_in *)&s->cli_addr)->sin_port) :
|
||||||
*(h++) = ' ';
|
ntohs(((struct sockaddr_in6 *)&s->cli_addr)->sin6_port),
|
||||||
*(h++) = '{';
|
tm->tm_mday, monthname[tm->tm_mon], tm->tm_year+1900,
|
||||||
for (hdr = 0; hdr < fe->nb_req_cap; hdr++) {
|
tm->tm_hour, tm->tm_min, tm->tm_sec, s->logs.tv_accept.tv_usec/1000,
|
||||||
if (hdr)
|
fe->id, be->id, svid,
|
||||||
*(h++) = '|';
|
(s->logs.t_queue >= 0) ? s->logs.t_queue : -1,
|
||||||
if (txn->req.cap[hdr] != NULL)
|
(s->logs.t_connect >= 0) ? s->logs.t_connect - s->logs.t_queue : -1,
|
||||||
h = encode_string(h, tmpline + sizeof(tmpline) - 7,
|
(tolog & LW_BYTES) ? "" : "+", s->logs.t_close,
|
||||||
'#', hdr_encode_map, txn->req.cap[hdr]);
|
(tolog & LW_BYTES) ? "" : "+", s->logs.bytes_in,
|
||||||
}
|
sess_term_cond[(s->flags & SN_ERR_MASK) >> SN_ERR_SHIFT],
|
||||||
*(h++) = '}';
|
sess_fin_state[(s->flags & SN_FINST_MASK) >> SN_FINST_SHIFT],
|
||||||
}
|
actconn, fe->feconn, be->beconn, s->srv ? s->srv->cur_sess : 0,
|
||||||
|
s->logs.srv_queue_size, s->logs.prx_queue_size);
|
||||||
if (fe->to_log & LW_RSPHDR &&
|
|
||||||
txn->rsp.cap &&
|
|
||||||
(h < tmpline + sizeof(tmpline) - 7)) {
|
|
||||||
*(h++) = ' ';
|
|
||||||
*(h++) = '{';
|
|
||||||
for (hdr = 0; hdr < fe->nb_rsp_cap; hdr++) {
|
|
||||||
if (hdr)
|
|
||||||
*(h++) = '|';
|
|
||||||
if (txn->rsp.cap[hdr] != NULL)
|
|
||||||
h = encode_string(h, tmpline + sizeof(tmpline) - 4,
|
|
||||||
'#', hdr_encode_map, txn->rsp.cap[hdr]);
|
|
||||||
}
|
|
||||||
*(h++) = '}';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (h < tmpline + sizeof(tmpline) - 4) {
|
|
||||||
*(h++) = ' ';
|
|
||||||
*(h++) = '"';
|
|
||||||
h = encode_string(h, tmpline + sizeof(tmpline) - 1,
|
|
||||||
'#', url_encode_map, uri);
|
|
||||||
*(h++) = '"';
|
|
||||||
}
|
|
||||||
*h = '\0';
|
|
||||||
|
|
||||||
send_log(prx_log, LOG_INFO,
|
|
||||||
"%s:%d [%02d/%s/%04d:%02d:%02d:%02d.%03d]"
|
|
||||||
" %s %s/%s %d/%d/%d/%d/%s%d %d %s%lld"
|
|
||||||
" %s %s %c%c%c%c %d/%d/%d/%d %d/%d%s\n",
|
|
||||||
pn,
|
|
||||||
(s->cli_addr.ss_family == AF_INET) ?
|
|
||||||
ntohs(((struct sockaddr_in *)&s->cli_addr)->sin_port) :
|
|
||||||
ntohs(((struct sockaddr_in6 *)&s->cli_addr)->sin6_port),
|
|
||||||
tm->tm_mday, monthname[tm->tm_mon], tm->tm_year+1900,
|
|
||||||
tm->tm_hour, tm->tm_min, tm->tm_sec, s->logs.tv_accept.tv_usec/1000,
|
|
||||||
fe->id, pxid, srv,
|
|
||||||
s->logs.t_request,
|
|
||||||
(s->logs.t_queue >= 0) ? s->logs.t_queue - s->logs.t_request : -1,
|
|
||||||
(s->logs.t_connect >= 0) ? s->logs.t_connect - s->logs.t_queue : -1,
|
|
||||||
(s->logs.t_data >= 0) ? s->logs.t_data - s->logs.t_connect : -1,
|
|
||||||
(tolog & LW_BYTES) ? "" : "+", s->logs.t_close,
|
|
||||||
txn->status,
|
|
||||||
(tolog & LW_BYTES) ? "" : "+", s->logs.bytes_in,
|
|
||||||
txn->cli_cookie ? txn->cli_cookie : "-",
|
|
||||||
txn->srv_cookie ? txn->srv_cookie : "-",
|
|
||||||
sess_term_cond[(s->flags & SN_ERR_MASK) >> SN_ERR_SHIFT],
|
|
||||||
sess_fin_state[(s->flags & SN_FINST_MASK) >> SN_FINST_SHIFT],
|
|
||||||
(be->options & PR_O_COOK_ANY) ? sess_cookie[(txn->flags & TX_CK_MASK) >> TX_CK_SHIFT] : '-',
|
|
||||||
(be->options & PR_O_COOK_ANY) ? sess_set_cookie[(txn->flags & TX_SCK_MASK) >> TX_SCK_SHIFT] : '-',
|
|
||||||
actconn, fe->feconn, be->beconn, s->srv ? s->srv->cur_sess : 0,
|
|
||||||
s->logs.srv_queue_size, s->logs.prx_queue_size, tmpline);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
send_log(prx_log, LOG_INFO, "%s:%d [%02d/%s/%04d:%02d:%02d:%02d.%03d]"
|
|
||||||
" %s %s/%s %d/%d/%s%d %s%lld"
|
|
||||||
" %c%c %d/%d/%d/%d %d/%d\n",
|
|
||||||
pn,
|
|
||||||
(s->cli_addr.ss_family == AF_INET) ?
|
|
||||||
ntohs(((struct sockaddr_in *)&s->cli_addr)->sin_port) :
|
|
||||||
ntohs(((struct sockaddr_in6 *)&s->cli_addr)->sin6_port),
|
|
||||||
tm->tm_mday, monthname[tm->tm_mon], tm->tm_year+1900,
|
|
||||||
tm->tm_hour, tm->tm_min, tm->tm_sec, s->logs.tv_accept.tv_usec/1000,
|
|
||||||
fe->id, pxid, srv,
|
|
||||||
(s->logs.t_queue >= 0) ? s->logs.t_queue : -1,
|
|
||||||
(s->logs.t_connect >= 0) ? s->logs.t_connect - s->logs.t_queue : -1,
|
|
||||||
(tolog & LW_BYTES) ? "" : "+", s->logs.t_close,
|
|
||||||
(tolog & LW_BYTES) ? "" : "+", s->logs.bytes_in,
|
|
||||||
sess_term_cond[(s->flags & SN_ERR_MASK) >> SN_ERR_SHIFT],
|
|
||||||
sess_fin_state[(s->flags & SN_FINST_MASK) >> SN_FINST_SHIFT],
|
|
||||||
actconn, fe->feconn, be->beconn, s->srv ? s->srv->cur_sess : 0,
|
|
||||||
s->logs.srv_queue_size, s->logs.prx_queue_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
s->logs.logwait = 0;
|
s->logs.logwait = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Initializes some data needed later.
|
|
||||||
*/
|
|
||||||
void init_log()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char *tmp;
|
|
||||||
|
|
||||||
/* initialize the log header encoding map : '{|}"#' should be encoded with
|
|
||||||
* '#' as prefix, as well as non-printable characters ( <32 or >= 127 ).
|
|
||||||
* URL encoding only requires '"', '#' to be encoded as well as non-
|
|
||||||
* printable characters above.
|
|
||||||
*/
|
|
||||||
memset(hdr_encode_map, 0, sizeof(hdr_encode_map));
|
|
||||||
memset(url_encode_map, 0, sizeof(url_encode_map));
|
|
||||||
for (i = 0; i < 32; i++) {
|
|
||||||
FD_SET(i, hdr_encode_map);
|
|
||||||
FD_SET(i, url_encode_map);
|
|
||||||
}
|
|
||||||
for (i = 127; i < 256; i++) {
|
|
||||||
FD_SET(i, hdr_encode_map);
|
|
||||||
FD_SET(i, url_encode_map);
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp = "\"#{|}";
|
|
||||||
while (*tmp) {
|
|
||||||
FD_SET(*tmp, hdr_encode_map);
|
|
||||||
tmp++;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp = "\"#";
|
|
||||||
while (*tmp) {
|
|
||||||
FD_SET(*tmp, url_encode_map);
|
|
||||||
tmp++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local variables:
|
* Local variables:
|
||||||
* c-indent-level: 8
|
* c-indent-level: 8
|
||||||
|
217
src/proto_http.c
217
src/proto_http.c
@ -17,6 +17,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@ -181,9 +182,28 @@ static const char *http_err_msgs[HTTP_ERR_SIZE] = {
|
|||||||
*/
|
*/
|
||||||
struct chunk http_err_chunks[HTTP_ERR_SIZE];
|
struct chunk http_err_chunks[HTTP_ERR_SIZE];
|
||||||
|
|
||||||
|
#define FD_SETS_ARE_BITFIELDS
|
||||||
|
#ifdef FD_SETS_ARE_BITFIELDS
|
||||||
|
/*
|
||||||
|
* This map is used with all the FD_* macros to check whether a particular bit
|
||||||
|
* is set or not. Each bit represents an ACSII code. FD_SET() sets those bytes
|
||||||
|
* which should be encoded. When FD_ISSET() returns non-zero, it means that the
|
||||||
|
* byte should be encoded. Be careful to always pass bytes from 0 to 255
|
||||||
|
* exclusively to the macros.
|
||||||
|
*/
|
||||||
|
fd_set hdr_encode_map[(sizeof(fd_set) > (256/8)) ? 1 : ((256/8) / sizeof(fd_set))];
|
||||||
|
fd_set url_encode_map[(sizeof(fd_set) > (256/8)) ? 1 : ((256/8) / sizeof(fd_set))];
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "Check if your OS uses bitfields for fd_sets"
|
||||||
|
#endif
|
||||||
|
|
||||||
void init_proto_http()
|
void init_proto_http()
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
char *tmp;
|
||||||
int msg;
|
int msg;
|
||||||
|
|
||||||
for (msg = 0; msg < HTTP_ERR_SIZE; msg++) {
|
for (msg = 0; msg < HTTP_ERR_SIZE; msg++) {
|
||||||
if (!http_err_msgs[msg]) {
|
if (!http_err_msgs[msg]) {
|
||||||
Alert("Internal error: no message defined for HTTP return code %d. Aborting.\n", msg);
|
Alert("Internal error: no message defined for HTTP return code %d. Aborting.\n", msg);
|
||||||
@ -193,6 +213,34 @@ void init_proto_http()
|
|||||||
http_err_chunks[msg].str = (char *)http_err_msgs[msg];
|
http_err_chunks[msg].str = (char *)http_err_msgs[msg];
|
||||||
http_err_chunks[msg].len = strlen(http_err_msgs[msg]);
|
http_err_chunks[msg].len = strlen(http_err_msgs[msg]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* initialize the log header encoding map : '{|}"#' should be encoded with
|
||||||
|
* '#' as prefix, as well as non-printable characters ( <32 or >= 127 ).
|
||||||
|
* URL encoding only requires '"', '#' to be encoded as well as non-
|
||||||
|
* printable characters above.
|
||||||
|
*/
|
||||||
|
memset(hdr_encode_map, 0, sizeof(hdr_encode_map));
|
||||||
|
memset(url_encode_map, 0, sizeof(url_encode_map));
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
FD_SET(i, hdr_encode_map);
|
||||||
|
FD_SET(i, url_encode_map);
|
||||||
|
}
|
||||||
|
for (i = 127; i < 256; i++) {
|
||||||
|
FD_SET(i, hdr_encode_map);
|
||||||
|
FD_SET(i, url_encode_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = "\"#{|}";
|
||||||
|
while (*tmp) {
|
||||||
|
FD_SET(*tmp, hdr_encode_map);
|
||||||
|
tmp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = "\"#";
|
||||||
|
while (*tmp) {
|
||||||
|
FD_SET(*tmp, url_encode_map);
|
||||||
|
tmp++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -311,6 +359,8 @@ static char *cli_stnames[5] = {"HDR", "DAT", "SHR", "SHW", "CLS" };
|
|||||||
static char *srv_stnames[7] = {"IDL", "CON", "HDR", "DAT", "SHR", "SHW", "CLS" };
|
static char *srv_stnames[7] = {"IDL", "CON", "HDR", "DAT", "SHR", "SHW", "CLS" };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void http_sess_log(struct session *s);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adds a header and its CRLF at the tail of buffer <b>, just before the last
|
* Adds a header and its CRLF at the tail of buffer <b>, just before the last
|
||||||
* CRLF. Text length is measured first, so it cannot be NULL.
|
* CRLF. Text length is measured first, so it cannot be NULL.
|
||||||
@ -553,8 +603,12 @@ int process_session(struct task *t)
|
|||||||
/* let's do a final log if we need it */
|
/* let's do a final log if we need it */
|
||||||
if (s->logs.logwait &&
|
if (s->logs.logwait &&
|
||||||
!(s->flags & SN_MONITOR) &&
|
!(s->flags & SN_MONITOR) &&
|
||||||
(!(s->fe->options & PR_O_NULLNOLOG) || s->req->total))
|
(!(s->fe->options & PR_O_NULLNOLOG) || s->req->total)) {
|
||||||
sess_log(s);
|
if (s->fe->to_log & LW_REQ)
|
||||||
|
http_sess_log(s);
|
||||||
|
else
|
||||||
|
tcp_sess_log(s);
|
||||||
|
}
|
||||||
|
|
||||||
/* the task MUST not be in the run queue anymore */
|
/* the task MUST not be in the run queue anymore */
|
||||||
task_delete(t);
|
task_delete(t);
|
||||||
@ -564,22 +618,126 @@ int process_session(struct task *t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* either we find an LF at <ptr> or we jump to <bad>.
|
extern const char sess_term_cond[8];
|
||||||
*/
|
extern const char sess_fin_state[8];
|
||||||
#define EXPECT_LF_HERE(ptr, bad) do { if (unlikely(*(ptr) != '\n')) goto bad; } while (0)
|
extern const char *monthname[12];
|
||||||
|
const char sess_cookie[4] = "NIDV"; /* No cookie, Invalid cookie, cookie for a Down server, Valid cookie */
|
||||||
|
const char sess_set_cookie[8] = "N1I3PD5R"; /* No set-cookie, unknown, Set-Cookie Inserted, unknown,
|
||||||
|
Set-cookie seen and left unchanged (passive), Set-cookie Deleted,
|
||||||
|
unknown, Set-cookie Rewritten */
|
||||||
|
void **pool_requri = NULL;
|
||||||
|
|
||||||
/* plays with variables <ptr>, <end> and <state>. Jumps to <good> if OK,
|
/*
|
||||||
* otherwise to <http_msg_ood> with <state> set to <st>.
|
* send a log for the session when we have enough info about it.
|
||||||
|
* Will not log if the frontend has no log defined.
|
||||||
*/
|
*/
|
||||||
#define EAT_AND_JUMP_OR_RETURN(good, st) do { \
|
static void http_sess_log(struct session *s)
|
||||||
ptr++; \
|
{
|
||||||
if (likely(ptr < end)) \
|
char pn[INET6_ADDRSTRLEN + strlen(":65535")];
|
||||||
goto good; \
|
struct proxy *fe = s->fe;
|
||||||
else { \
|
struct proxy *be = s->be;
|
||||||
state = (st); \
|
struct proxy *prx_log;
|
||||||
goto http_msg_ood; \
|
struct http_txn *txn = &s->txn;
|
||||||
} \
|
int tolog;
|
||||||
} while (0)
|
char *uri, *h;
|
||||||
|
char *svid;
|
||||||
|
struct tm *tm;
|
||||||
|
static char tmpline[MAX_SYSLOG_LEN];
|
||||||
|
int hdr;
|
||||||
|
|
||||||
|
if (fe->logfac1 < 0 && fe->logfac2 < 0)
|
||||||
|
return;
|
||||||
|
prx_log = fe;
|
||||||
|
|
||||||
|
if (s->cli_addr.ss_family == AF_INET)
|
||||||
|
inet_ntop(AF_INET,
|
||||||
|
(const void *)&((struct sockaddr_in *)&s->cli_addr)->sin_addr,
|
||||||
|
pn, sizeof(pn));
|
||||||
|
else
|
||||||
|
inet_ntop(AF_INET6,
|
||||||
|
(const void *)&((struct sockaddr_in6 *)(&s->cli_addr))->sin6_addr,
|
||||||
|
pn, sizeof(pn));
|
||||||
|
|
||||||
|
tm = localtime((time_t *)&s->logs.tv_accept.tv_sec);
|
||||||
|
|
||||||
|
|
||||||
|
/* FIXME: let's limit ourselves to frontend logging for now. */
|
||||||
|
tolog = fe->to_log;
|
||||||
|
|
||||||
|
h = tmpline;
|
||||||
|
if (fe->to_log & LW_REQHDR &&
|
||||||
|
txn->req.cap &&
|
||||||
|
(h < tmpline + sizeof(tmpline) - 10)) {
|
||||||
|
*(h++) = ' ';
|
||||||
|
*(h++) = '{';
|
||||||
|
for (hdr = 0; hdr < fe->nb_req_cap; hdr++) {
|
||||||
|
if (hdr)
|
||||||
|
*(h++) = '|';
|
||||||
|
if (txn->req.cap[hdr] != NULL)
|
||||||
|
h = encode_string(h, tmpline + sizeof(tmpline) - 7,
|
||||||
|
'#', hdr_encode_map, txn->req.cap[hdr]);
|
||||||
|
}
|
||||||
|
*(h++) = '}';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fe->to_log & LW_RSPHDR &&
|
||||||
|
txn->rsp.cap &&
|
||||||
|
(h < tmpline + sizeof(tmpline) - 7)) {
|
||||||
|
*(h++) = ' ';
|
||||||
|
*(h++) = '{';
|
||||||
|
for (hdr = 0; hdr < fe->nb_rsp_cap; hdr++) {
|
||||||
|
if (hdr)
|
||||||
|
*(h++) = '|';
|
||||||
|
if (txn->rsp.cap[hdr] != NULL)
|
||||||
|
h = encode_string(h, tmpline + sizeof(tmpline) - 4,
|
||||||
|
'#', hdr_encode_map, txn->rsp.cap[hdr]);
|
||||||
|
}
|
||||||
|
*(h++) = '}';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h < tmpline + sizeof(tmpline) - 4) {
|
||||||
|
*(h++) = ' ';
|
||||||
|
*(h++) = '"';
|
||||||
|
uri = txn->uri ? txn->uri : "<BADREQ>";
|
||||||
|
h = encode_string(h, tmpline + sizeof(tmpline) - 1,
|
||||||
|
'#', url_encode_map, uri);
|
||||||
|
*(h++) = '"';
|
||||||
|
}
|
||||||
|
*h = '\0';
|
||||||
|
|
||||||
|
svid = (tolog & LW_SVID) ?
|
||||||
|
(s->data_source != DATA_SRC_STATS) ?
|
||||||
|
(s->srv != NULL) ? s->srv->id : "<NOSRV>" : "<STATS>" : "-";
|
||||||
|
|
||||||
|
send_log(prx_log, LOG_INFO,
|
||||||
|
"%s:%d [%02d/%s/%04d:%02d:%02d:%02d.%03d]"
|
||||||
|
" %s %s/%s %d/%d/%d/%d/%s%d %d %s%lld"
|
||||||
|
" %s %s %c%c%c%c %d/%d/%d/%d %d/%d%s\n",
|
||||||
|
pn,
|
||||||
|
(s->cli_addr.ss_family == AF_INET) ?
|
||||||
|
ntohs(((struct sockaddr_in *)&s->cli_addr)->sin_port) :
|
||||||
|
ntohs(((struct sockaddr_in6 *)&s->cli_addr)->sin6_port),
|
||||||
|
tm->tm_mday, monthname[tm->tm_mon], tm->tm_year+1900,
|
||||||
|
tm->tm_hour, tm->tm_min, tm->tm_sec, s->logs.tv_accept.tv_usec/1000,
|
||||||
|
fe->id, be->id, svid,
|
||||||
|
s->logs.t_request,
|
||||||
|
(s->logs.t_queue >= 0) ? s->logs.t_queue - s->logs.t_request : -1,
|
||||||
|
(s->logs.t_connect >= 0) ? s->logs.t_connect - s->logs.t_queue : -1,
|
||||||
|
(s->logs.t_data >= 0) ? s->logs.t_data - s->logs.t_connect : -1,
|
||||||
|
(tolog & LW_BYTES) ? "" : "+", s->logs.t_close,
|
||||||
|
txn->status,
|
||||||
|
(tolog & LW_BYTES) ? "" : "+", s->logs.bytes_in,
|
||||||
|
txn->cli_cookie ? txn->cli_cookie : "-",
|
||||||
|
txn->srv_cookie ? txn->srv_cookie : "-",
|
||||||
|
sess_term_cond[(s->flags & SN_ERR_MASK) >> SN_ERR_SHIFT],
|
||||||
|
sess_fin_state[(s->flags & SN_FINST_MASK) >> SN_FINST_SHIFT],
|
||||||
|
(be->options & PR_O_COOK_ANY) ? sess_cookie[(txn->flags & TX_CK_MASK) >> TX_CK_SHIFT] : '-',
|
||||||
|
(be->options & PR_O_COOK_ANY) ? sess_set_cookie[(txn->flags & TX_SCK_MASK) >> TX_SCK_SHIFT] : '-',
|
||||||
|
actconn, fe->feconn, be->beconn, s->srv ? s->srv->cur_sess : 0,
|
||||||
|
s->logs.srv_queue_size, s->logs.prx_queue_size, tmpline);
|
||||||
|
|
||||||
|
s->logs.logwait = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -634,6 +792,24 @@ void capture_headers(char *som, struct hdr_idx *idx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* either we find an LF at <ptr> or we jump to <bad>.
|
||||||
|
*/
|
||||||
|
#define EXPECT_LF_HERE(ptr, bad) do { if (unlikely(*(ptr) != '\n')) goto bad; } while (0)
|
||||||
|
|
||||||
|
/* plays with variables <ptr>, <end> and <state>. Jumps to <good> if OK,
|
||||||
|
* otherwise to <http_msg_ood> with <state> set to <st>.
|
||||||
|
*/
|
||||||
|
#define EAT_AND_JUMP_OR_RETURN(good, st) do { \
|
||||||
|
ptr++; \
|
||||||
|
if (likely(ptr < end)) \
|
||||||
|
goto good; \
|
||||||
|
else { \
|
||||||
|
state = (st); \
|
||||||
|
goto http_msg_ood; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function parses a status line between <ptr> and <end>, starting with
|
* This function parses a status line between <ptr> and <end>, starting with
|
||||||
* parser state <state>. Only states HTTP_MSG_RPVER, HTTP_MSG_RPVER_SP,
|
* parser state <state>. Only states HTTP_MSG_RPVER, HTTP_MSG_RPVER_SP,
|
||||||
@ -1425,7 +1601,7 @@ int process_cli(struct session *t)
|
|||||||
txn->uri[urilen] = 0;
|
txn->uri[urilen] = 0;
|
||||||
|
|
||||||
if (!(t->logs.logwait &= ~LW_REQ))
|
if (!(t->logs.logwait &= ~LW_REQ))
|
||||||
sess_log(t);
|
http_sess_log(t);
|
||||||
} else {
|
} else {
|
||||||
Alert("HTTP logging : out of memory.\n");
|
Alert("HTTP logging : out of memory.\n");
|
||||||
}
|
}
|
||||||
@ -2251,7 +2427,7 @@ int process_srv(struct session *t)
|
|||||||
bytes from the server, then this is the right moment. */
|
bytes from the server, then this is the right moment. */
|
||||||
if (t->fe->to_log && !(t->logs.logwait & LW_BYTES)) {
|
if (t->fe->to_log && !(t->logs.logwait & LW_BYTES)) {
|
||||||
t->logs.t_close = t->logs.t_connect; /* to get a valid end date */
|
t->logs.t_close = t->logs.t_connect; /* to get a valid end date */
|
||||||
sess_log(t);
|
tcp_sess_log(t);
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_HAP_TCPSPLICE
|
#ifdef CONFIG_HAP_TCPSPLICE
|
||||||
if ((t->fe->options & t->be->options) & PR_O_TCPSPLICE) {
|
if ((t->fe->options & t->be->options) & PR_O_TCPSPLICE) {
|
||||||
@ -2790,7 +2966,10 @@ int process_srv(struct session *t)
|
|||||||
if (t->fe->to_log && !(t->logs.logwait & LW_BYTES)) {
|
if (t->fe->to_log && !(t->logs.logwait & LW_BYTES)) {
|
||||||
t->logs.t_close = t->logs.t_data; /* to get a valid end date */
|
t->logs.t_close = t->logs.t_data; /* to get a valid end date */
|
||||||
t->logs.bytes_in = txn->rsp.eoh;
|
t->logs.bytes_in = txn->rsp.eoh;
|
||||||
sess_log(t);
|
if (t->fe->to_log & LW_REQ)
|
||||||
|
http_sess_log(t);
|
||||||
|
else
|
||||||
|
tcp_sess_log(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: we must not try to cheat by jumping directly to DATA,
|
/* Note: we must not try to cheat by jumping directly to DATA,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user