MINOR: logs: add a new per-proxy "log-tag" directive

This is equivalent to what was done in commit 48936af ("[MINOR] log:
ability to override the syslog tag") but this time instead of doing
this globally, it does it per proxy. The purpose is to be able to use
a separate log tag for various proxies (eg: make it easier to route
log messages depending on the customer).
This commit is contained in:
Willy Tarreau 2015-01-07 15:03:42 +01:00
parent fb4e7ea307
commit 094af4e16e
4 changed files with 43 additions and 9 deletions

View File

@ -629,7 +629,7 @@ log-tag <string>
Sets the tag field in the syslog header to this string. It defaults to the Sets the tag field in the syslog header to this string. It defaults to the
program name as launched from the command line, which usually is "haproxy". program name as launched from the command line, which usually is "haproxy".
Sometimes it can be useful to differentiate between multiple processes Sometimes it can be useful to differentiate between multiple processes
running on the same host. running on the same host. See also the per-proxy "log-tag" directive.
nbproc <number> nbproc <number>
Creates <number> processes when going daemon. This requires the "daemon" Creates <number> processes when going daemon. This requires the "daemon"
@ -1353,6 +1353,7 @@ id - X X X
ignore-persist - X X X ignore-persist - X X X
log (*) X X X X log (*) X X X X
log-format X X X - log-format X X X -
log-tag X X X X
max-keep-alive-queue X - X X max-keep-alive-queue X - X X
maxconn X X X - maxconn X X X -
mode X X X X mode X X X X
@ -3558,6 +3559,20 @@ log-format <string>
the same log format. Please see section 8.2.4 which covers the log format the same log format. Please see section 8.2.4 which covers the log format
string in depth. string in depth.
log-tag <string>
Specifies the log tag to use for all outgoing logs
May be used in sections: defaults | frontend | listen | backend
yes | yes | yes | yes
Sets the tag field in the syslog header to this string. It defaults to the
log-tag set in the global section, otherwise the program name as launched
from the command line, which usually is "haproxy". Sometimes it can be useful
to differentiate between multiple processes running on the same host, or to
differentiate customer instances running in the same process. In the backend,
logs about servers up/down will use this tag. As a hint, it can be convenient
to set a log-tag related to a hosted customer in a defaults section then put
all the frontends and backends for that customer, then start another customer
in a new defaults section. See also the global "log-tag" directive.
max-keep-alive-queue <value> max-keep-alive-queue <value>
Set the maximum server queue size for maintaining keep-alive connections Set the maximum server queue size for maintaining keep-alive connections

View File

@ -320,6 +320,7 @@ struct proxy {
unsigned int log_count; /* number of logs produced by the frontend */ unsigned int log_count; /* number of logs produced by the frontend */
struct list logsrvs; struct list logsrvs;
struct list logformat; /* log_format linked list */ struct list logformat; /* log_format linked list */
char *log_tag; /* override default syslog tag */
char *header_unique_id; /* unique-id header */ char *header_unique_id; /* unique-id header */
struct list format_unique_id; /* unique-id format */ struct list format_unique_id; /* unique-id format */
int to_log; /* things to be logged (LW_*) */ int to_log; /* things to be logged (LW_*) */

View File

@ -2184,6 +2184,9 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
if (curproxy->conf.uniqueid_format_string) if (curproxy->conf.uniqueid_format_string)
curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string); curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
if (defproxy.log_tag)
curproxy->log_tag = strdup(defproxy.log_tag);
if (defproxy.conf.uif_file) { if (defproxy.conf.uif_file) {
curproxy->conf.uif_file = strdup(defproxy.conf.uif_file); curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
curproxy->conf.uif_line = defproxy.conf.uif_line; curproxy->conf.uif_line = defproxy.conf.uif_line;
@ -2249,6 +2252,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
free(defproxy.conf.uniqueid_format_string); free(defproxy.conf.uniqueid_format_string);
free(defproxy.conf.lfs_file); free(defproxy.conf.lfs_file);
free(defproxy.conf.uif_file); free(defproxy.conf.uif_file);
free(defproxy.log_tag);
for (rc = 0; rc < HTTP_ERR_SIZE; rc++) for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
chunk_destroy(&defproxy.errmsg[rc]); chunk_destroy(&defproxy.errmsg[rc]);
@ -4911,7 +4915,15 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
err_code |= ERR_WARN; err_code |= ERR_WARN;
} }
} }
else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
if (*(args[1]) == 0) {
Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
free(curproxy->log_tag);
curproxy->log_tag = strdup(args[1]);
}
else if (!strcmp(args[0], "log") && kwm == KWM_NO) { else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
/* delete previous herited or defined syslog servers */ /* delete previous herited or defined syslog servers */
struct logsrv *back; struct logsrv *back;

View File

@ -724,10 +724,11 @@ char *lf_port(char *dst, struct sockaddr *sockaddr, size_t size, struct logforma
/* Re-generate the syslog header at the beginning of logline once a second and /* Re-generate the syslog header at the beginning of logline once a second and
* return the pointer to the first character after the header. * return the pointer to the first character after the header.
*/ */
static char *update_log_hdr() static char *update_log_hdr(const char *log_tag)
{ {
static long tvsec; static long tvsec;
static char *dataptr = NULL; /* backup of last end of header, NULL first time */ static char *dataptr = NULL; /* backup of last end of header, NULL first time */
int tag_len;
if (unlikely(date.tv_sec != tvsec || dataptr == NULL)) { if (unlikely(date.tv_sec != tvsec || dataptr == NULL)) {
/* this string is rebuild only once a second */ /* this string is rebuild only once a second */
@ -738,11 +739,10 @@ static char *update_log_hdr()
get_localtime(tvsec, &tm); get_localtime(tvsec, &tm);
hdr_len = snprintf(logline, global.max_syslog_len, hdr_len = snprintf(logline, global.max_syslog_len,
"<<<<>%s %2d %02d:%02d:%02d %s%s[%d]: ", "<<<<>%s %2d %02d:%02d:%02d %s",
monthname[tm.tm_mon], monthname[tm.tm_mon],
tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
global.log_send_hostname ? global.log_send_hostname : "", global.log_send_hostname ? global.log_send_hostname : "");
global.log_tag, pid);
/* WARNING: depending upon implementations, snprintf may return /* WARNING: depending upon implementations, snprintf may return
* either -1 or the number of bytes that would be needed to store * either -1 or the number of bytes that would be needed to store
* the total message. In both cases, we must adjust it. * the total message. In both cases, we must adjust it.
@ -753,7 +753,13 @@ static char *update_log_hdr()
dataptr = logline + hdr_len; dataptr = logline + hdr_len;
} }
return dataptr; dataptr[0] = 0; // ensure we get rid of any previous attempt
tag_len = snprintf(dataptr, logline + global.max_syslog_len - dataptr, "%s[%d]: ", log_tag, pid);
if (tag_len < 0 || tag_len > logline + global.max_syslog_len - dataptr)
tag_len = logline + global.max_syslog_len - dataptr;
return dataptr + tag_len;
} }
/* /*
@ -769,7 +775,7 @@ void send_log(struct proxy *p, int level, const char *format, ...)
if (level < 0 || format == NULL) if (level < 0 || format == NULL)
return; return;
dataptr = update_log_hdr(); /* update log header and skip it */ dataptr = update_log_hdr(p->log_tag ? p->log_tag : global.log_tag); /* update log header and skip it */
data_len = dataptr - logline; data_len = dataptr - logline;
va_start(argp, format); va_start(argp, format);
@ -1633,7 +1639,7 @@ void sess_log(struct session *s)
build_logline(s, s->unique_id, UNIQUEID_LEN, &s->fe->format_unique_id); build_logline(s, s->unique_id, UNIQUEID_LEN, &s->fe->format_unique_id);
} }
tmplog = update_log_hdr(); tmplog = update_log_hdr(s->fe->log_tag ? s->fe->log_tag : global.log_tag);
size = tmplog - logline; size = tmplog - logline;
size += build_logline(s, tmplog, global.max_syslog_len - size, &s->fe->logformat); size += build_logline(s, tmplog, global.max_syslog_len - size, &s->fe->logformat);
if (size > 0) { if (size > 0) {