From 68d2e3a74216bd137cbfce25611e935067ee839b Mon Sep 17 00:00:00 2001 From: Dragan Dosen Date: Sat, 19 Sep 2015 22:35:44 +0200 Subject: [PATCH] MEDIUM: logs: remove the hostname, tag and pid part from the logheader At the moment we have to call snprintf() for every log line just to rebuild a constant. Thanks to sendmsg(), we send the message in 3 parts: time-based header, proxy-specific hostname+log-tag+pid, session-specific message. --- include/proto/log.h | 5 ++++ include/types/log.h | 2 +- include/types/proxy.h | 1 + src/cfgparse.c | 21 +++++++++++++++++ src/haproxy.c | 1 + src/log.c | 54 +++++++++++++++++++++++++++---------------- 6 files changed, 63 insertions(+), 21 deletions(-) diff --git a/include/proto/log.h b/include/proto/log.h index 14dfc5bcd..e8b57d867 100644 --- a/include/proto/log.h +++ b/include/proto/log.h @@ -138,6 +138,11 @@ char *lf_ip(char *dst, struct sockaddr *sockaddr, size_t size, struct logformat_ */ char *lf_port(char *dst, struct sockaddr *sockaddr, size_t size, struct logformat_node *node); +/* + * Write hostname, log_tag and pid to the log string + */ +char *lf_host_tag_pid(char *dst, const char *hostname, const char *log_tag, int pid, size_t size); + #endif /* _PROTO_LOG_H */ diff --git a/include/types/log.h b/include/types/log.h index 6707aa6b5..0214ae675 100644 --- a/include/types/log.h +++ b/include/types/log.h @@ -30,7 +30,7 @@ #define NB_LOG_FACILITIES 24 #define NB_LOG_LEVELS 8 -#define NB_MSG_IOVEC_ELEMENTS 2 +#define NB_MSG_IOVEC_ELEMENTS 3 #define SYSLOG_PORT 514 #define UNIQUEID_LEN 128 diff --git a/include/types/proxy.h b/include/types/proxy.h index 170e6f714..1400126de 100644 --- a/include/types/proxy.h +++ b/include/types/proxy.h @@ -346,6 +346,7 @@ struct proxy { struct list logsrvs; struct list logformat; /* log_format linked list */ char *log_tag; /* override default syslog tag */ + struct chunk log_htp; /* a syslog header part that contains hostname, log_tag and pid */ char *header_unique_id; /* unique-id header */ struct list format_unique_id; /* unique-id format */ int to_log; /* things to be logged (LW_*) */ diff --git a/src/cfgparse.c b/src/cfgparse.c index 39ee35988..fdbb462f6 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -7818,6 +7818,27 @@ int check_config_validity() } out_uri_auth_compat: + /* write a syslog header string that contains hostname, log_tag and pid */ + curproxy->log_htp.str = lf_host_tag_pid(logheader, + global.log_send_hostname ? global.log_send_hostname : "", + curproxy->log_tag ? curproxy->log_tag : global.log_tag, pid, + global.max_syslog_len); + + if ((curproxy->log_htp.str == NULL) || + (curproxy->log_htp.len = curproxy->log_htp.str - logheader) >= global.max_syslog_len) { + Alert("Proxy '%s': cannot write a syslog header string that contains " + "hostname, log_tag and pid.\n", + curproxy->id); + cfgerr++; + } + else { + curproxy->log_htp.str = (char *)malloc(curproxy->log_htp.len); + memcpy(curproxy->log_htp.str, logheader, curproxy->log_htp.len); + curproxy->log_htp.size = 0; + } + + logheader[0] = 0; + /* compile the log format */ if (!(curproxy->cap & PR_CAP_FE)) { if (curproxy->conf.logformat_string != default_http_log_format && diff --git a/src/haproxy.c b/src/haproxy.c index f6ba96b38..1edb823d7 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -1328,6 +1328,7 @@ void deinit(void) LIST_DEL(&log->list); free(log); } + chunk_destroy(&p->log_htp); list_for_each_entry_safe(lf, lfb, &p->logformat, list) { LIST_DEL(&lf->list); diff --git a/src/log.c b/src/log.c index 3724dd47e..ad25174d2 100644 --- a/src/log.c +++ b/src/log.c @@ -152,8 +152,7 @@ char default_tcp_log_format[] = "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/% char *log_format = NULL; /* This is a global syslog header, common to all outgoing messages. It - * begins with the syslog tag and the date that are updated by - * update_log_hdr(). + * begins with time-based part and is updated by update_log_hdr(). */ char *logheader = NULL; @@ -740,14 +739,26 @@ char *lf_port(char *dst, struct sockaddr *sockaddr, size_t size, struct logforma return ret; } +char *lf_host_tag_pid(char *dst, const char *hostname, const char *log_tag, int pid, size_t size) +{ + char *ret = dst; + int iret; + + iret = snprintf(dst, size, "%s%s[%d]: ", hostname, log_tag, pid); + if (iret < 0 || iret > size) + return NULL; + ret += iret; + + return ret; +} + /* Re-generate the syslog header at the beginning of logheader once a second and * return the pointer to the first character after the header. */ -static char *update_log_hdr(const char *log_tag) +char *update_log_hdr() { static long tvsec; static char *dataptr = NULL; /* backup of last end of header, NULL first time */ - int tag_len; if (unlikely(date.tv_sec != tvsec || dataptr == NULL)) { /* this string is rebuild only once a second */ @@ -758,10 +769,9 @@ static char *update_log_hdr(const char *log_tag) get_localtime(tvsec, &tm); hdr_len = snprintf(logheader, global.max_syslog_len, - "<<<<>%s %2d %02d:%02d:%02d %s", + "<<<<>%s %2d %02d:%02d:%02d ", monthname[tm.tm_mon], - tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, - global.log_send_hostname ? global.log_send_hostname : ""); + tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); /* WARNING: depending upon implementations, snprintf may return * either -1 or the number of bytes that would be needed to store * the total message. In both cases, we must adjust it. @@ -774,11 +784,7 @@ static char *update_log_hdr(const char *log_tag) dataptr[0] = 0; // ensure we get rid of any previous attempt - tag_len = snprintf(dataptr, logheader + global.max_syslog_len - dataptr, "%s[%d]: ", log_tag, pid); - if (tag_len < 0 || tag_len > logheader + global.max_syslog_len - dataptr) - tag_len = logheader + global.max_syslog_len - dataptr; - - return dataptr + tag_len; + return dataptr; } /* @@ -821,7 +827,6 @@ void __send_log(struct proxy *p, int level, char *message, size_t size) struct list *logsrvs = NULL; struct logsrv *tmp = NULL; int nblogger; - char *log_tag = global.log_tag; char *log_ptr; char *hdr_ptr; size_t hdr_size; @@ -836,15 +841,12 @@ void __send_log(struct proxy *p, int level, char *message, size_t size) if (!LIST_ISEMPTY(&p->logsrvs)) { logsrvs = &p->logsrvs; } - if (p->log_tag) { - log_tag = p->log_tag; - } } if (!logsrvs) return; - hdr_ptr = update_log_hdr(log_tag); + hdr_ptr = update_log_hdr(); hdr_size = hdr_ptr - logheader; /* Send log messages to syslog server. */ @@ -854,7 +856,9 @@ void __send_log(struct proxy *p, int level, char *message, size_t size) int *plogfd = logsrv->addr.ss_family == AF_UNIX ? &logfdunix : &logfdinet; int sent; + int maxlen; int hdr_max = 0; + int htp_max = 0; int max = 1; char backup; @@ -904,7 +908,15 @@ void __send_log(struct proxy *p, int level, char *message, size_t size) goto send; } - max = MIN(size, logsrv->maxlen - hdr_max); + maxlen = logsrv->maxlen - hdr_max; + htp_max = p->log_htp.len; + + if (unlikely(htp_max >= maxlen)) { + htp_max = maxlen - 1; + goto send; + } + + max = MIN(size, maxlen - htp_max); log_ptr += max - 1; @@ -918,8 +930,10 @@ send: iovec[0].iov_base = hdr_ptr; iovec[0].iov_len = hdr_max; - iovec[1].iov_base = dataptr; - iovec[1].iov_len = max; + iovec[1].iov_base = p->log_htp.str; + iovec[1].iov_len = htp_max; + iovec[2].iov_base = dataptr; + iovec[2].iov_len = max; msghdr.msg_name = (struct sockaddr *)&logsrv->addr; msghdr.msg_namelen = get_addr_len(&logsrv->addr);