From: William Lallemand Date: Mon, 12 Mar 2012 11:46:41 +0000 (+0100) Subject: MEDIUM: log: split of log_format generation X-Git-Tag: v1.5-dev9~110 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1d7055675e79ec704b82a43cc937f67efaed51b1;p=thirdparty%2Fhaproxy.git MEDIUM: log: split of log_format generation * logformat functions now take a format linked list as argument * build_logline() build a logline using a format linked list * rename LOG_* by LOG_FMT_* in enum * improve error management in build_logline() --- diff --git a/include/proto/log.h b/include/proto/log.h index 0ee60a00dd..2efb539405 100644 --- a/include/proto/log.h +++ b/include/proto/log.h @@ -40,6 +40,8 @@ extern char default_http_log_format[]; extern char clf_http_log_format[]; +int build_logline(struct session *s, char *dst, size_t maxsize, struct list *list_format); + /* * send a log for the session when we have enough info about it. * Will not log if the frontend has no log defined. @@ -55,20 +57,19 @@ int parse_logformat_var_args(char *args, struct logformat_node *node); * Parse a variable '%varname' or '%{args}varname' in logformat * */ -int parse_logformat_var(char *str, size_t len, struct proxy *curproxy, int *options); +int parse_logformat_var(char *str, size_t len, struct proxy *curproxy, struct list *list_format, int *defoptions); /* * add to the logformat linked list */ -void add_to_logformat_list(char *start, char *end, int type, struct proxy *curproxy); +void add_to_logformat_list(char *start, char *end, int type, struct list *list_format); /* * Parse the log_format string and fill a linked list. * Variable name are preceded by % and composed by characters [a-zA-Z0-9]* : %varname * You can set arguments using { } : %{many arguments}varname */ -void parse_logformat_string(char *str, struct proxy *curproxy); - +void parse_logformat_string(char *str, struct proxy *curproxy, struct list *list_format, int capabilities); /* * Displays the message on stderr with the date and pid. Overrides the quiet * mode during startup. diff --git a/include/types/log.h b/include/types/log.h index 741fba935d..efb1d91f5f 100644 --- a/include/types/log.h +++ b/include/types/log.h @@ -35,49 +35,49 @@ /* lists of fields that can be logged */ enum { - LOG_TEXT = 0, /* raw text */ + LOG_FMT_TEXT = 0, /* raw text */ - LOG_SEPARATOR, /* separator replaced by one space */ - LOG_VARIABLE, + LOG_FMT_SEPARATOR, /* separator replaced by one space */ + LOG_FMT_VARIABLE, /* information fields */ - LOG_GLOBAL, - LOG_CLIENTIP, - LOG_CLIENTPORT, - LOG_SOURCEPORT, - LOG_SOURCEIP, - LOG_DATE, - LOG_DATEGMT, - LOG_MS, - LOG_FRONTEND, - LOG_BACKEND, - LOG_SERVER, - LOG_BYTES, - LOG_T, - LOG_TQ, - LOG_TW, - LOG_TC, - LOG_TR, - LOG_TT, - LOG_STATUS, - LOG_CCLIENT, - LOG_CSERVER, - LOG_TERMSTATE, - LOG_TERMSTATE_CK, - LOG_CONN, - LOG_ACTCONN, - LOG_FECONN, - LOG_BECONN, - LOG_SRVCONN, - LOG_RETRIES, - LOG_QUEUES, - LOG_SRVQUEUE, - LOG_BCKQUEUE, - LOG_HDRREQUEST, - LOG_HDRRESPONS, - LOG_HDRREQUESTLIST, - LOG_HDRRESPONSLIST, - LOG_REQ, + LOG_FMT_GLOBAL, + LOG_FMT_CLIENTIP, + LOG_FMT_CLIENTPORT, + LOG_FMT_BACKENDIP, + LOG_FMT_BACKENDPORT, + LOG_FMT_DATE, + LOG_FMT_DATEGMT, + LOG_FMT_MS, + LOG_FMT_FRONTEND, + LOG_FMT_BACKEND, + LOG_FMT_SERVER, + LOG_FMT_BYTES, + LOG_FMT_T, + LOG_FMT_TQ, + LOG_FMT_TW, + LOG_FMT_TC, + LOG_FMT_TR, + LOG_FMT_TT, + LOG_FMT_STATUS, + LOG_FMT_CCLIENT, + LOG_FMT_CSERVER, + LOG_FMT_TERMSTATE, + LOG_FMT_TERMSTATE_CK, + LOG_FMT_CONN, + LOG_FMT_ACTCONN, + LOG_FMT_FECONN, + LOG_FMT_BECONN, + LOG_FMT_SRVCONN, + LOG_FMT_RETRIES, + LOG_FMT_QUEUES, + LOG_FMT_SRVQUEUE, + LOG_FMT_BCKQUEUE, + LOG_FMT_HDRREQUEST, + LOG_FMT_HDRRESPONS, + LOG_FMT_HDRREQUESTLIST, + LOG_FMT_HDRRESPONSLIST, + LOG_FMT_REQ, }; /* enum for parse_logformat */ diff --git a/src/cfgparse.c b/src/cfgparse.c index d827d4c0fb..aa57b9b55a 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -3352,14 +3352,14 @@ stats_error_parsing: goto out; } } - parse_logformat_string(logformat, curproxy); + parse_logformat_string(logformat, curproxy, &curproxy->logformat, curproxy->mode); } else if (!strcmp(args[1], "tcplog")) { char *logformat; /* generate a detailed TCP log */ curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES; logformat = default_tcp_log_format; - parse_logformat_string(logformat, curproxy); + parse_logformat_string(logformat, curproxy, &curproxy->logformat, curproxy->mode); } else if (!strcmp(args[1], "tcpka")) { /* enable TCP keep-alives on client and server sessions */ @@ -4598,7 +4598,7 @@ stats_error_parsing: err_code |= ERR_ALERT | ERR_FATAL; goto out; } - parse_logformat_string(args[1], curproxy); + parse_logformat_string(args[1], curproxy, &curproxy->logformat, curproxy->mode); } else if (!strcmp(args[0], "log") && kwm == KWM_NO) { diff --git a/src/log.c b/src/log.c index 9065a5b38c..8a0912137f 100644 --- a/src/log.c +++ b/src/log.c @@ -64,40 +64,40 @@ int prepare_addrsource(struct logformat_node *node, struct proxy *curproxy); /* log_format variable names */ static const struct logformat_type logformat_keywords[] = { - { "o", LOG_GLOBAL, PR_MODE_TCP, NULL }, /* global option */ - { "Ci", LOG_CLIENTIP, PR_MODE_TCP, NULL }, /* client ip */ - { "Cp", LOG_CLIENTPORT, PR_MODE_TCP, NULL }, /* client port */ - { "Bp", LOG_SOURCEPORT, PR_MODE_TCP, prepare_addrsource }, /* backend source port */ - { "Bi", LOG_SOURCEIP, PR_MODE_TCP, prepare_addrsource }, /* backend source ip */ - { "t", LOG_DATE, PR_MODE_TCP, NULL }, /* date */ - { "T", LOG_DATEGMT, PR_MODE_TCP, NULL }, /* date GMT */ - { "ms", LOG_MS, PR_MODE_TCP, NULL }, /* accept date millisecond */ - { "f", LOG_FRONTEND, PR_MODE_TCP, NULL }, /* frontend */ - { "b", LOG_BACKEND, PR_MODE_TCP, NULL }, /* backend */ - { "s", LOG_SERVER, PR_MODE_TCP, NULL }, /* server */ - { "B", LOG_BYTES, PR_MODE_TCP, NULL }, /* bytes read */ - { "Tq", LOG_TQ, PR_MODE_HTTP, NULL }, /* Tq */ - { "Tw", LOG_TW, PR_MODE_TCP, NULL }, /* Tw */ - { "Tc", LOG_TC, PR_MODE_TCP, NULL }, /* Tc */ - { "Tr", LOG_TR, PR_MODE_HTTP, NULL }, /* Tr */ - { "Tt", LOG_TT, PR_MODE_TCP, NULL }, /* Tt */ - { "st", LOG_STATUS, PR_MODE_HTTP, NULL }, /* status code */ - { "cc", LOG_CCLIENT, PR_MODE_HTTP, NULL }, /* client cookie */ - { "cs", LOG_CSERVER, PR_MODE_HTTP, NULL }, /* server cookie */ - { "ts", LOG_TERMSTATE, PR_MODE_TCP, NULL },/* terminaison state */ - { "tsc", LOG_TERMSTATE_CK, PR_MODE_HTTP, NULL },/* terminaison state with cookie status */ - { "ac", LOG_ACTCONN, PR_MODE_TCP, NULL }, /* actconn */ - { "fc", LOG_FECONN, PR_MODE_TCP, NULL }, /* feconn */ - { "bc", LOG_BECONN, PR_MODE_TCP, NULL }, /* beconn */ - { "sc", LOG_SRVCONN, PR_MODE_TCP, NULL }, /* srv_conn */ - { "rc", LOG_RETRIES, PR_MODE_TCP, NULL }, /* retries */ - { "sq", LOG_SRVQUEUE, PR_MODE_TCP, NULL }, /* srv_queue */ - { "bq", LOG_BCKQUEUE, PR_MODE_TCP, NULL }, /* backend_queue */ - { "hr", LOG_HDRREQUEST, PR_MODE_HTTP, NULL }, /* header request */ - { "hs", LOG_HDRRESPONS, PR_MODE_HTTP, NULL }, /* header response */ - { "hrl", LOG_HDRREQUESTLIST, PR_MODE_HTTP, NULL }, /* header request list */ - { "hsl", LOG_HDRRESPONSLIST, PR_MODE_HTTP, NULL }, /* header response list */ - { "r", LOG_REQ, PR_MODE_HTTP, NULL }, /* request */ + { "o", LOG_FMT_GLOBAL, PR_MODE_TCP, NULL }, /* global option */ + { "Ci", LOG_FMT_CLIENTIP, PR_MODE_TCP, NULL }, /* client ip */ + { "Cp", LOG_FMT_CLIENTPORT, PR_MODE_TCP, NULL }, /* client port */ + { "Bp", LOG_FMT_BACKENDPORT, PR_MODE_TCP, prepare_addrsource }, /* backend source port */ + { "Bi", LOG_FMT_BACKENDIP, PR_MODE_TCP, prepare_addrsource }, /* backend source ip */ + { "t", LOG_FMT_DATE, PR_MODE_TCP, NULL }, /* date */ + { "T", LOG_FMT_DATEGMT, PR_MODE_TCP, NULL }, /* date GMT */ + { "ms", LOG_FMT_MS, PR_MODE_TCP, NULL }, /* accept date millisecond */ + { "f", LOG_FMT_FRONTEND, PR_MODE_TCP, NULL }, /* frontend */ + { "b", LOG_FMT_BACKEND, PR_MODE_TCP, NULL }, /* backend */ + { "s", LOG_FMT_SERVER, PR_MODE_TCP, NULL }, /* server */ + { "B", LOG_FMT_BYTES, PR_MODE_TCP, NULL }, /* bytes read */ + { "Tq", LOG_FMT_TQ, PR_MODE_HTTP, NULL }, /* Tq */ + { "Tw", LOG_FMT_TW, PR_MODE_TCP, NULL }, /* Tw */ + { "Tc", LOG_FMT_TC, PR_MODE_TCP, NULL }, /* Tc */ + { "Tr", LOG_FMT_TR, PR_MODE_HTTP, NULL }, /* Tr */ + { "Tt", LOG_FMT_TT, PR_MODE_TCP, NULL }, /* Tt */ + { "st", LOG_FMT_STATUS, PR_MODE_HTTP, NULL }, /* status code */ + { "cc", LOG_FMT_CCLIENT, PR_MODE_HTTP, NULL }, /* client cookie */ + { "cs", LOG_FMT_CSERVER, PR_MODE_HTTP, NULL }, /* server cookie */ + { "ts", LOG_FMT_TERMSTATE, PR_MODE_TCP, NULL },/* terminaison state */ + { "tsc", LOG_FMT_TERMSTATE_CK, PR_MODE_TCP, NULL },/* terminaison state */ + { "ac", LOG_FMT_ACTCONN, PR_MODE_TCP, NULL }, /* actconn */ + { "fc", LOG_FMT_FECONN, PR_MODE_TCP, NULL }, /* feconn */ + { "bc", LOG_FMT_BECONN, PR_MODE_TCP, NULL }, /* beconn */ + { "sc", LOG_FMT_SRVCONN, PR_MODE_TCP, NULL }, /* srv_conn */ + { "rc", LOG_FMT_RETRIES, PR_MODE_TCP, NULL }, /* retries */ + { "sq", LOG_FMT_SRVQUEUE, PR_MODE_TCP, NULL }, /* srv_queue */ + { "bq", LOG_FMT_BCKQUEUE, PR_MODE_TCP, NULL }, /* backend_queue */ + { "hr", LOG_FMT_HDRREQUEST, PR_MODE_HTTP, NULL }, /* header request */ + { "hs", LOG_FMT_HDRRESPONS, PR_MODE_HTTP, NULL }, /* header response */ + { "hrl", LOG_FMT_HDRREQUESTLIST, PR_MODE_HTTP, NULL }, /* header request list */ + { "hsl", LOG_FMT_HDRRESPONSLIST, PR_MODE_HTTP, NULL }, /* header response list */ + { "r", LOG_FMT_REQ, PR_MODE_HTTP, NULL }, /* request */ { 0, 0, 0, NULL } }; @@ -188,7 +188,7 @@ int parse_logformat_var_args(char *args, struct logformat_node *node) * Parse a variable '%varname' or '%{args}varname' in logformat * */ -int parse_logformat_var(char *str, size_t len, struct proxy *curproxy, int *defoptions) +int parse_logformat_var(char *str, size_t len, struct proxy *curproxy, struct list *list_format, int *defoptions) { int i, j; char *arg = NULL; // arguments @@ -218,7 +218,7 @@ int parse_logformat_var(char *str, size_t len, struct proxy *curproxy, int *defo node->options = *defoptions; node->arg = arg; parse_logformat_var_args(node->arg, node); - if (node->type == LOG_GLOBAL) { + if (node->type == LOG_FMT_GLOBAL) { *defoptions = node->options; free(node); } else { @@ -227,7 +227,7 @@ int parse_logformat_var(char *str, size_t len, struct proxy *curproxy, int *defo return -1; } } - LIST_ADDQ(&curproxy->logformat, &node->list); + LIST_ADDQ(list_format, &node->list); } return 0; } else { @@ -253,28 +253,27 @@ int parse_logformat_var(char *str, size_t len, struct proxy *curproxy, int *defo * start: start pointer * end: end text pointer * type: string type + * list_format: destination list * * LOG_TEXT: copy chars from start to end excluding end. * */ -void add_to_logformat_list(char *start, char *end, int type, struct proxy *curproxy) +void add_to_logformat_list(char *start, char *end, int type, struct list *list_format) { char *str; - if (type == LOG_TEXT) { /* type text */ + if (type == LOG_FMT_TEXT) { /* type text */ struct logformat_node *node = calloc(1, sizeof(struct logformat_node)); - str = calloc(end - start + 1, 1); strncpy(str, start, end - start); - str[end - start] = '\0'; node->arg = str; - node->type = LOG_TEXT; // type string - LIST_ADDQ(&curproxy->logformat, &node->list); - } else if (type == LOG_SEPARATOR) { + node->type = LOG_FMT_TEXT; // type string + LIST_ADDQ(list_format, &node->list); + } else if (type == LOG_FMT_SEPARATOR) { struct logformat_node *node = calloc(1, sizeof(struct logformat_node)); - node->type = LOG_SEPARATOR; - LIST_ADDQ(&curproxy->logformat, &node->list); + node->type = LOG_FMT_SEPARATOR; + LIST_ADDQ(list_format, &node->list); } } @@ -282,8 +281,13 @@ void add_to_logformat_list(char *start, char *end, int type, struct proxy *curpr * Parse the log_format string and fill a linked list. * Variable name are preceded by % and composed by characters [a-zA-Z0-9]* : %varname * You can set arguments using { } : %{many arguments}varname + * + * str: the string to parse + * curproxy: the proxy affected + * list_format: the destination list + * capabilities: PR_MODE_TCP_ | PR_MODE_HTTP */ -void parse_logformat_string(char *str, struct proxy *curproxy) +void parse_logformat_string(char *str, struct proxy *curproxy, struct list *list_format, int capabilities) { char *sp = str; /* start pointer */ int cformat = -1; /* current token format : LOG_TEXT, LOG_SEPARATOR, LOG_VARIABLE */ @@ -292,7 +296,7 @@ void parse_logformat_string(char *str, struct proxy *curproxy) int options = 0; /* flush the list first. */ - list_for_each_entry_safe(tmplf, back, &curproxy->logformat, list) { + list_for_each_entry_safe(tmplf, back, list_format, list) { LIST_DEL(&tmplf->list); free(tmplf); } @@ -308,9 +312,9 @@ void parse_logformat_string(char *str, struct proxy *curproxy) if (pformat > LF_VAR) // unfinished string pformat = LF_TEXT; if (pformat == LF_VAR) - parse_logformat_var(sp, str - sp, curproxy, &options); + parse_logformat_var(sp, str - sp, curproxy, list_format, &options); else - add_to_logformat_list(sp, str, pformat, curproxy); + add_to_logformat_list(sp, str, pformat, list_format); sp = str; if (*str == '\0') break; @@ -482,7 +486,6 @@ char *logformat_write_string(char *dst, char *src, size_t size, struct logformat *(dst++) = '"'; *(dst++) = '"'; *dst = '\0'; - node->options |= LOG_OPT_WRITTEN; } else { dst = NULL; return dst; @@ -491,7 +494,6 @@ char *logformat_write_string(char *dst, char *src, size_t size, struct logformat if (size > 1) { *(dst++) = '-'; *dst = '\0'; - node->options |= LOG_OPT_WRITTEN; } else { // error no space available dst = NULL; return dst; @@ -693,27 +695,26 @@ const char sess_set_cookie[8] = "NPDIRU67"; /* No set-cookie, Set-cookie found a Set-cookie Deleted, Set-Cookie Inserted, Set-cookie Rewritten, Set-cookie Updated, unknown, unknown */ +/* + * try to write a character if there is enough space, or goto out + */ #define LOGCHAR(x) do { \ - if (tmplog < logline + MAX_SYSLOG_LEN - 1) { \ + if (tmplog < dst + maxsize - 1) { \ *(tmplog++) = (x); \ } else { \ goto out; \ } \ } while(0) -/* - * send a log for the session when we have enough info about it. - * Will not log if the frontend has no log defined. - */ -void sess_log(struct session *s) + + +int build_logline(struct session *s, char *dst, size_t maxsize, struct list *list_format) { char pn[INET6_ADDRSTRLEN]; - char sn[INET6_ADDRSTRLEN]; struct proxy *fe = s->fe; struct proxy *be = s->be; - struct proxy *prx_log; struct http_txn *txn = &s->txn; - int tolog, level, err; + int tolog; char *uri; const char *svid; struct tm tm; @@ -721,27 +722,10 @@ void sess_log(struct session *s) int hdr; int last_isspace = 1; char *tmplog; + char *ret; + int iret; struct logformat_node *tmp; - /* if we don't want to log normal traffic, return now */ - err = (s->flags & (SN_ERR_MASK | SN_REDISP)) || - (s->req->cons->conn_retries != be->conn_retries) || - ((s->fe->mode == PR_MODE_HTTP) && txn->status >= 500); - if (!err && (fe->options2 & PR_O2_NOLOGNORM)) - return; - - if (LIST_ISEMPTY(&fe->logsrvs)) - return; - prx_log = fe; - - if (addr_to_str(&s->req->prod->addr.from, pn, sizeof(pn)) == AF_UNIX) - snprintf(pn, sizeof(pn), "unix:%d", s->listener->luid); - - if (be->options2 & PR_O2_SRC_ADDR) { - if (addr_to_str(&s->req->cons->addr.from, sn, sizeof(sn)) == AF_UNIX) - snprintf(sn, sizeof(sn), "unix:%d", s->listener->luid); - } - /* FIXME: let's limit ourselves to frontend logging for now. */ tolog = fe->to_log; @@ -763,85 +747,94 @@ void sess_log(struct session *s) if (tv_isge(&s->logs.tv_request, &s->logs.tv_accept)) t_request = tv_ms_elapsed(&s->logs.tv_accept, &s->logs.tv_request); - level = LOG_INFO; - if (err && (fe->options2 & PR_O2_LOGERRORS)) - level = LOG_ERR; + tmplog = dst; /* fill logbuffer */ + if (LIST_ISEMPTY(list_format)) + return 0; - tmplog = update_log_hdr(); /* update log header and skip it */ - - list_for_each_entry(tmp, &fe->logformat, list) { + list_for_each_entry(tmp, list_format, list) { char *src = NULL; switch (tmp->type) { - case LOG_SEPARATOR: + case LOG_FMT_SEPARATOR: if (!last_isspace) { LOGCHAR(' '); last_isspace = 1; - *tmplog = '\0'; } break; - case LOG_TEXT: // text + case LOG_FMT_TEXT: // text src = tmp->arg; - tmplog += strlcpy2(tmplog, src, MAX_SYSLOG_LEN - (tmplog - logline)); - if (tmplog > logline + MAX_SYSLOG_LEN - 2) + iret = strlcpy2(tmplog, src, maxsize - (tmplog - dst)); + if (iret == 0) goto out; + tmplog += iret; last_isspace = 0; break; - case LOG_CLIENTIP: // %Ci + case LOG_FMT_CLIENTIP: // %Ci + /* client addr */ + if (addr_to_str(&s->req->prod->addr.from, pn, sizeof(pn)) == AF_UNIX) + snprintf(pn, sizeof(pn), "unix:%d", s->listener->luid); src = (s->req->prod->addr.from.ss_family == AF_UNIX) ? "unix" : pn; - tmplog = logformat_write_string(tmplog, src, MAX_SYSLOG_LEN - (tmplog - logline), tmp); - if (!tmplog) + ret = logformat_write_string(tmplog, src, maxsize - (tmplog - dst), tmp); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_CLIENTPORT: // %Cp - tmplog = ltoa_o((s->req->prod->addr.from.ss_family == AF_UNIX) ? s->listener->luid : get_host_port(&s->req->prod->addr.from), - tmplog, MAX_SYSLOG_LEN - (tmplog - logline)); - if (!tmplog) + case LOG_FMT_CLIENTPORT: // %Cp + ret = ltoa_o((s->req->prod->addr.from.ss_family == AF_UNIX) ? + s->listener->luid : get_host_port(&s->req->prod->addr.from), + tmplog, maxsize - (tmplog - dst)); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_SOURCEIP: // Bi - src = (s->req->cons->addr.from.ss_family == AF_UNIX) ? "unix" : sn; - tmplog = logformat_write_string(tmplog, src, MAX_SYSLOG_LEN - (tmplog - logline), tmp); - if (!tmplog) + case LOG_FMT_BACKENDIP: // %Bi + /* backend addr */ + if (be->options2 & PR_O2_SRC_ADDR) + addr_to_str(&s->req->cons->addr.from, pn, sizeof(pn)); + ret = logformat_write_string(tmplog, pn, maxsize - (tmplog - dst), tmp); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_SOURCEPORT: // %Bp - tmplog = ltoa_o((s->req->cons->addr.from.ss_family == AF_UNIX) ? s->listener->luid : get_host_port(&s->req->cons->addr.from), - tmplog, MAX_SYSLOG_LEN - (tmplog - logline)); - if (!tmplog) + case LOG_FMT_BACKENDPORT: // %Bp + ret = ltoa_o(get_host_port(&s->req->cons->addr.from), + tmplog, maxsize - (tmplog - dst)); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_DATE: // %t + case LOG_FMT_DATE: // %t get_localtime(s->logs.accept_date.tv_sec, &tm); - tmplog = date2str_log(tmplog, &tm, &(s->logs.accept_date), MAX_SYSLOG_LEN - (tmplog - logline)); - if (!tmplog) + ret = date2str_log(tmplog, &tm, &(s->logs.accept_date), maxsize - (tmplog - dst)); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_DATEGMT: // %T + case LOG_FMT_DATEGMT: // %T get_gmtime(s->logs.accept_date.tv_sec, &tm); - tmplog = gmt2str_log(tmplog, &tm, MAX_SYSLOG_LEN - (tmplog - logline)); - if (!tmplog) + ret = gmt2str_log(tmplog, &tm, maxsize - (tmplog - dst)); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_MS: // %ms - if ((MAX_SYSLOG_LEN - (tmplog - logline)) < 4) { - tmplog = NULL; + case LOG_FMT_MS: // %ms + if ((maxsize - (tmplog - dst)) < 4) { goto out; } tmplog = utoa_pad((unsigned int)s->logs.accept_date.tv_usec/1000, @@ -851,167 +844,192 @@ void sess_log(struct session *s) last_isspace = 0; break; - case LOG_FRONTEND: // %f + case LOG_FMT_FRONTEND: // %f src = fe->id; - tmplog = logformat_write_string(tmplog, src, MAX_SYSLOG_LEN - (tmplog - logline), tmp); - if (!tmplog) + ret = logformat_write_string(tmplog, src, maxsize - (tmplog - dst), tmp); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_BACKEND: // %b + case LOG_FMT_BACKEND: // %b src = be->id; - tmplog = logformat_write_string(tmplog, src, MAX_SYSLOG_LEN - (tmplog - logline), tmp); - if (!tmplog) + ret = logformat_write_string(tmplog, src, maxsize - (tmplog - dst), tmp); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_SERVER: // %s + case LOG_FMT_SERVER: // %s src = (char *)svid; - tmplog = logformat_write_string(tmplog, src, MAX_SYSLOG_LEN - (tmplog - logline), tmp); - if (!tmplog) + ret = logformat_write_string(tmplog, src, maxsize - (tmplog - dst), tmp); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_TQ: // %Tq - tmplog = ltoa_o(t_request, tmplog, MAX_SYSLOG_LEN - (tmplog - logline)); - if (!tmplog) + case LOG_FMT_TQ: // %Tq + ret = ltoa_o(t_request, tmplog, maxsize - (tmplog - dst)); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_TW: // %Tw - tmplog = ltoa_o((s->logs.t_queue >= 0) ? s->logs.t_queue - t_request : -1, tmplog, MAX_SYSLOG_LEN - (tmplog - logline)); - if (!tmplog) + case LOG_FMT_TW: // %Tw + ret = ltoa_o((s->logs.t_queue >= 0) ? s->logs.t_queue - t_request : -1, + tmplog, maxsize - (tmplog - dst)); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_TC: // %Tc - tmplog = ltoa_o((s->logs.t_connect >= 0) ? s->logs.t_connect - s->logs.t_queue : -1, tmplog, MAX_SYSLOG_LEN - (tmplog - logline)); - if (!tmplog) + case LOG_FMT_TC: // %Tc + ret = ltoa_o((s->logs.t_connect >= 0) ? s->logs.t_connect - s->logs.t_queue : -1, + tmplog, maxsize - (tmplog - dst)); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_TR: // %Tr - tmplog = ltoa_o((s->logs.t_data >= 0) ? s->logs.t_data - s->logs.t_connect : -1, tmplog, MAX_SYSLOG_LEN - (tmplog - logline)); - if (!tmplog) + case LOG_FMT_TR: // %Tr + ret = ltoa_o((s->logs.t_data >= 0) ? s->logs.t_data - s->logs.t_connect : -1, + tmplog, maxsize - (tmplog - dst)); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_TT: // %Tt + case LOG_FMT_TT: // %Tt if (!(tolog & LW_BYTES)) - *(tmplog++) = '+'; - tmplog = ltoa_o(s->logs.t_close, tmplog, MAX_SYSLOG_LEN - (tmplog - logline)); - if (!tmplog) + LOGCHAR('+'); + ret = ltoa_o(s->logs.t_close, tmplog, maxsize - (tmplog - dst)); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_STATUS: // %st - tmplog = ltoa_o(txn->status, tmplog, MAX_SYSLOG_LEN - (tmplog - logline)); - if (!tmplog) + case LOG_FMT_STATUS: // %st + ret = ltoa_o(txn->status, tmplog, maxsize - (tmplog - dst)); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_BYTES: // %B + case LOG_FMT_BYTES: // %B if (!(tolog & LW_BYTES)) - *(tmplog++) = '+'; - tmplog = lltoa(s->logs.bytes_out, tmplog, MAX_SYSLOG_LEN - (tmplog - logline)); - if (!tmplog) + LOGCHAR('+'); + ret = lltoa(s->logs.bytes_out, tmplog, maxsize - (tmplog - dst)); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_CCLIENT: // %cc + case LOG_FMT_CCLIENT: // %cc src = txn->cli_cookie; - tmplog = logformat_write_string(tmplog, src, MAX_SYSLOG_LEN - (tmplog - logline), tmp); - if (!tmplog) + ret = logformat_write_string(tmplog, src, maxsize - (tmplog - dst), tmp); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_CSERVER: // %cs + case LOG_FMT_CSERVER: // %cs src = txn->srv_cookie; - tmplog = logformat_write_string(tmplog, src, MAX_SYSLOG_LEN - (tmplog - logline), tmp); - if (!tmplog) + ret = logformat_write_string(tmplog, src, maxsize - (tmplog - dst), tmp); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_TERMSTATE: // %ts + case LOG_FMT_TERMSTATE: // %ts LOGCHAR(sess_term_cond[(s->flags & SN_ERR_MASK) >> SN_ERR_SHIFT]); LOGCHAR(sess_fin_state[(s->flags & SN_FINST_MASK) >> SN_FINST_SHIFT]); *tmplog = '\0'; last_isspace = 0; break; - case LOG_TERMSTATE_CK: // %tsc, same as TS with cookie state (for mode HTTP) + case LOG_FMT_TERMSTATE_CK: // %tsc, same as TS with cookie state (for mode HTTP) LOGCHAR(sess_term_cond[(s->flags & SN_ERR_MASK) >> SN_ERR_SHIFT]); LOGCHAR(sess_fin_state[(s->flags & SN_FINST_MASK) >> SN_FINST_SHIFT]); LOGCHAR((be->options & PR_O_COOK_ANY) ? sess_cookie[(txn->flags & TX_CK_MASK) >> TX_CK_SHIFT] : '-'); LOGCHAR((be->options & PR_O_COOK_ANY) ? sess_set_cookie[(txn->flags & TX_SCK_MASK) >> TX_SCK_SHIFT] : '-'); - *tmplog = '\0'; last_isspace = 0; break; - case LOG_ACTCONN: // %ac - tmplog = ltoa_o(actconn, tmplog, MAX_SYSLOG_LEN - (tmplog - logline)); - if (!tmplog) + case LOG_FMT_ACTCONN: // %ac + ret = ltoa_o(actconn, tmplog, maxsize - (tmplog - dst)); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_FECONN: // %fc - tmplog = ltoa_o(fe->feconn, tmplog, MAX_SYSLOG_LEN - (tmplog - logline)); - if (!tmplog) + case LOG_FMT_FECONN: // %fc + ret = ltoa_o(fe->feconn, tmplog, maxsize - (tmplog - dst)); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_BECONN: // %bc - tmplog = ltoa_o(be->beconn, tmplog, MAX_SYSLOG_LEN - (tmplog - logline)); - if (!tmplog) + case LOG_FMT_BECONN: // %bc + ret = ltoa_o(be->beconn, tmplog, maxsize - (tmplog - dst)); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_SRVCONN: // %sc - tmplog = ultoa_o(target_srv(&s->target) ? target_srv(&s->target)->cur_sess : 0, tmplog, MAX_SYSLOG_LEN - (tmplog - logline)); - if (!tmplog) + case LOG_FMT_SRVCONN: // %sc + ret = ultoa_o(target_srv(&s->target) ? + target_srv(&s->target)->cur_sess : + 0, tmplog, maxsize - (tmplog - dst)); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_RETRIES: // %rq + case LOG_FMT_RETRIES: // %rq if (s->flags & SN_REDISP) - *(tmplog++) = '+'; - tmplog = ltoa_o((s->req->cons->conn_retries>0)?(be->conn_retries - s->req->cons->conn_retries):be->conn_retries, tmplog, MAX_SYSLOG_LEN - (tmplog - logline)); - if (!tmplog) + LOGCHAR('+'); + ret = ltoa_o((s->req->cons->conn_retries>0) ? + (be->conn_retries - s->req->cons->conn_retries) : + be->conn_retries, tmplog, maxsize - (tmplog - dst)); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_SRVQUEUE: // %sq - tmplog = ltoa_o(s->logs.srv_queue_size, tmplog, MAX_SYSLOG_LEN - (tmplog - logline)); - if (!tmplog) + case LOG_FMT_SRVQUEUE: // %sq + ret = ltoa_o(s->logs.srv_queue_size, tmplog, maxsize - (tmplog - dst)); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_BCKQUEUE: // %bq - tmplog = ltoa_o(s->logs.prx_queue_size, tmplog, MAX_SYSLOG_LEN - (tmplog - logline)); - if (!tmplog) + case LOG_FMT_BCKQUEUE: // %bq + ret = ltoa_o(s->logs.prx_queue_size, tmplog, maxsize - (tmplog - dst)); + if (ret == NULL) goto out; + tmplog = ret; last_isspace = 0; break; - case LOG_HDRREQUEST: // %hr + case LOG_FMT_HDRREQUEST: // %hr /* request header */ if (fe->to_log & LW_REQHDR && txn->req.cap) { if (tmp->options & LOG_OPT_QUOTE) @@ -1021,21 +1039,23 @@ void sess_log(struct session *s) if (hdr) LOGCHAR('|'); if (txn->req.cap[hdr] != NULL) { - tmplog = encode_string(tmplog, logline + MAX_SYSLOG_LEN, + ret = encode_string(tmplog, dst + maxsize, '#', hdr_encode_map, txn->req.cap[hdr]); - if (*tmplog != '\0') + if (ret == NULL || *ret != '\0') goto out; + tmplog = ret; } } LOGCHAR('}'); if (tmp->options & LOG_OPT_QUOTE) LOGCHAR('"'); last_isspace = 0; + if (tmp->options & LOG_OPT_QUOTE) + LOGCHAR('"'); } - *tmplog = '\0'; break; - case LOG_HDRREQUESTLIST: // %hrl + case LOG_FMT_HDRREQUESTLIST: // %hrl /* request header list */ if (fe->to_log & LW_REQHDR && txn->req.cap) { for (hdr = 0; hdr < fe->nb_req_cap; hdr++) { @@ -1044,22 +1064,22 @@ void sess_log(struct session *s) if (tmp->options & LOG_OPT_QUOTE) LOGCHAR('"'); if (txn->req.cap[hdr] != NULL) { - tmplog = encode_string(tmplog, logline + MAX_SYSLOG_LEN, + ret = encode_string(tmplog, dst + maxsize, '#', hdr_encode_map, txn->req.cap[hdr]); - if (*tmplog != '\0') + if (ret == NULL || *ret != '\0') goto out; - + tmplog = ret; } else if (!(tmp->options & LOG_OPT_QUOTE)) LOGCHAR('-'); if (tmp->options & LOG_OPT_QUOTE) LOGCHAR('"'); - *tmplog = '\0'; last_isspace = 0; } } break; - case LOG_HDRRESPONS: // %hs + + case LOG_FMT_HDRRESPONS: // %hs /* response header */ if (fe->to_log & LW_RSPHDR && txn->rsp.cap) { @@ -1070,10 +1090,11 @@ void sess_log(struct session *s) if (hdr) LOGCHAR('|'); if (txn->rsp.cap[hdr] != NULL) { - tmplog = encode_string(tmplog, logline + MAX_SYSLOG_LEN, - '#', hdr_encode_map, txn->rsp.cap[hdr]); - if (*tmplog != '\0') + ret = encode_string(tmplog, dst + maxsize, + '#', hdr_encode_map, txn->rsp.cap[hdr]); + if (ret == NULL || *ret != '\0') goto out; + tmplog = ret; } } LOGCHAR('}'); @@ -1081,10 +1102,9 @@ void sess_log(struct session *s) if (tmp->options & LOG_OPT_QUOTE) LOGCHAR('"'); } - *tmplog = '\0'; break; - case LOG_HDRRESPONSLIST: // %hsl + case LOG_FMT_HDRRESPONSLIST: // %hsl /* response header list */ if (fe->to_log & LW_RSPHDR && txn->rsp.cap) { for (hdr = 0; hdr < fe->nb_rsp_cap; hdr++) { @@ -1093,50 +1113,77 @@ void sess_log(struct session *s) if (tmp->options & LOG_OPT_QUOTE) LOGCHAR('"'); if (txn->rsp.cap[hdr] != NULL) { - tmplog = encode_string(tmplog, logline + MAX_SYSLOG_LEN, - '#', hdr_encode_map, txn->rsp.cap[hdr]); - if (*tmplog != '\0') + ret = encode_string(tmplog, dst + maxsize, + '#', hdr_encode_map, txn->rsp.cap[hdr]); + if (ret == NULL || *ret != '\0') goto out; + tmplog = ret; } else if (!(tmp->options & LOG_OPT_QUOTE)) LOGCHAR('-'); if (tmp->options & LOG_OPT_QUOTE) LOGCHAR('"'); - *tmplog = '\0'; last_isspace = 0; } } break; - case LOG_REQ: // %r + case LOG_FMT_REQ: // %r /* Request */ if (tmp->options & LOG_OPT_QUOTE) LOGCHAR('"'); uri = txn->uri ? txn->uri : ""; - tmplog = encode_string(tmplog, logline + MAX_SYSLOG_LEN, + ret = encode_string(tmplog, dst + maxsize, '#', url_encode_map, uri); - if (*tmplog != '\0') + if (ret == NULL || *ret != '\0') goto out; + tmplog = ret; if (tmp->options & LOG_OPT_QUOTE) LOGCHAR('"'); - *tmplog = '\0'; last_isspace = 0; break; } } out: + /* *tmplog is a unused character */ + *tmplog = '\0'; - if (tmplog == NULL) // if previous error - tmplog = logline + MAX_SYSLOG_LEN - 1; - - __send_log(prx_log, level, logline, tmplog - logline + 1); - s->logs.logwait = 0; + return tmplog - dst + 1; } +/* + * send a log for the session when we have enough info about it. + * Will not log if the frontend has no log defined. + */ +void sess_log(struct session *s) +{ + char *tmplog; + int size, err, level; + + /* if we don't want to log normal traffic, return now */ + err = (s->flags & (SN_ERR_MASK | SN_REDISP)) || + (s->req->cons->conn_retries != s->be->conn_retries) || + ((s->fe->mode == PR_MODE_HTTP) && s->txn.status >= 500); + if (!err && (s->fe->options2 & PR_O2_NOLOGNORM)) + return; + if (LIST_ISEMPTY(&s->fe->logsrvs)) + return; + level = LOG_INFO; + if (err && (s->fe->options2 & PR_O2_LOGERRORS)) + level = LOG_ERR; + + tmplog = update_log_hdr(); + size = tmplog - logline; + size += build_logline(s, tmplog, sizeof(logline) - size, &s->fe->logformat); + if (size > 0) { + __send_log(s->fe, level, logline, size); + s->logs.logwait = 0; + } +} /* * Local variables: