[MINOR] implement per-logger log level limitation

Some people are using haproxy in a shared environment where the
system logger by default sends alert and emerg messages to all
consoles, which happens when all servers go down on a backend for
instance. These people can not always change the system configuration
and would like to limit the outgoing messages level in order not to
disturb the local users.

The addition of an optional 4th field on the "log" line permits
exactly this. The minimal log level ensures that all outgoing logs
will have at least this level. So the logs are not filtered out,
just set to this level.
This commit is contained in:
Willy Tarreau 2009-05-10 17:20:05 +02:00
parent affb481f1a
commit f7edefa413
5 changed files with 51 additions and 10 deletions

View File

@ -415,7 +415,7 @@ group <group name>
Similar to "gid" but uses the GID of group name <group name> from /etc/group.
See also "gid" and "user".
log <address> <facility> [max level]
log <address> <facility> [max level [min level]]
Adds a global syslog server. Up to two global servers can be defined. They
will receive logs for startups and exits, as well as all logs from proxies
configured with "log global".
@ -438,8 +438,12 @@ log <address> <facility> [max level]
local0 local1 local2 local3 local4 local5 local6 local7
An optional level can be specified to filter outgoing messages. By default,
all messages are sent. If a level is specified, only messages with a severity
at least as important as this level will be sent. 8 levels are known :
all messages are sent. If a maximum level is specified, only messages with a
severity at least as important as this level will be sent. An optional minimum
level can be specified. If it is set, logs emitted with a more severe level
than this one will be capped to this level. This is used to avoid sending
"emerg" messages on all terminals on some default syslog configurations.
Eight levels are known :
emerg alert crit err warning notice info debug
@ -1640,7 +1644,7 @@ id <value>
log global
log <address> <facility> [<level>]
log <address> <facility> [<level> [<minlevel>]]
Enable per-instance logging of events and traffic.
May be used in sections : defaults | frontend | listen | backend
yes | yes | yes | yes
@ -1673,7 +1677,11 @@ log <address> <facility> [<level>]
<level> is optional and can be specified to filter outgoing messages. By
default, all messages are sent. If a level is specified, only
messages with a severity at least as important as this level
will be sent. 8 levels are known :
will be sent. An optional minimum level can be specified. If it
is set, logs emitted with a more severe level than this one will
be capped to this level. This is used to avoid sending "emerg"
messages on all terminals on some default syslog configurations.
Eight levels are known :
emerg alert crit err warning notice info debug
@ -1696,7 +1704,8 @@ log <address> <facility> [<level>]
Example :
log global
log 127.0.0.1:514 local0 notice
log 127.0.0.1:514 local0 notice # only send important events
log 127.0.0.1:514 local0 notice notice # same but limit output level
maxconn <conns>

View File

@ -72,6 +72,7 @@ struct global {
char *pidfile;
int logfac1, logfac2;
int loglev1, loglev2;
int minlvl1, minlvl2;
struct logsrv logsrv1, logsrv2;
struct {
int maxpollevents; /* max number of poll events at once */

View File

@ -266,6 +266,7 @@ struct proxy {
struct logsrv logsrv1, logsrv2; /* 2 syslog servers */
signed char logfac1, logfac2; /* log facility for both servers. -1 = disabled */
int loglev1, loglev2; /* log level for each server, 7 by default */
int minlvl1, minlvl2; /* minimum log level for each server, 0 by default */
int to_log; /* things to be logged (LW_*) */
int stop_time; /* date to stop listening, when stopping != 0 (int ticks) */
int nb_reqadd, nb_rspadd;

View File

@ -553,7 +553,7 @@ int cfg_parse_global(const char *file, int linenum, char **args, int inv)
}
else if (!strcmp(args[0], "log")) { /* syslog server address */
struct logsrv logsrv;
int facility, level;
int facility, level, minlvl;
if (*(args[1]) == 0 || *(args[2]) == 0) {
Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
@ -575,6 +575,15 @@ int cfg_parse_global(const char *file, int linenum, char **args, int inv)
}
}
minlvl = 0; /* limit syslog level to this level (emerg) */
if (*(args[4])) {
minlvl = get_log_level(args[4]);
if (level < 0) {
Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
exit(1);
}
}
if (args[1][0] == '/') {
logsrv.u.addr.sa_family = AF_UNIX;
logsrv.u.un = *str2sun(args[1]);
@ -589,11 +598,13 @@ int cfg_parse_global(const char *file, int linenum, char **args, int inv)
global.logsrv1 = logsrv;
global.logfac1 = facility;
global.loglev1 = level;
global.minlvl1 = minlvl;
}
else if (global.logfac2 == -1) {
global.logsrv2 = logsrv;
global.logfac2 = facility;
global.loglev2 = level;
global.minlvl2 = minlvl;
}
else {
Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
@ -847,9 +858,11 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
curproxy->logfac1 = defproxy.logfac1;
curproxy->logsrv1 = defproxy.logsrv1;
curproxy->loglev1 = defproxy.loglev1;
curproxy->minlvl1 = defproxy.minlvl1;
curproxy->logfac2 = defproxy.logfac2;
curproxy->logsrv2 = defproxy.logsrv2;
curproxy->loglev2 = defproxy.loglev2;
curproxy->minlvl2 = defproxy.minlvl2;
curproxy->grace = defproxy.grace;
curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
curproxy->next_svid = 1; /* server id 0 is reserved */
@ -2302,12 +2315,14 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
curproxy->logfac1 = global.logfac1;
curproxy->logsrv1 = global.logsrv1;
curproxy->loglev1 = global.loglev1;
curproxy->minlvl1 = global.minlvl1;
curproxy->logfac2 = global.logfac2;
curproxy->logsrv2 = global.logsrv2;
curproxy->loglev2 = global.loglev2;
curproxy->minlvl2 = global.minlvl2;
}
else if (*(args[1]) && *(args[2])) {
int level;
int level, minlvl;
facility = get_log_facility(args[2]);
if (facility < 0) {
@ -2324,6 +2339,15 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
}
}
minlvl = 0; /* limit syslog level to this level (emerg) */
if (*(args[4])) {
minlvl = get_log_level(args[4]);
if (level < 0) {
Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
exit(1);
}
}
if (args[1][0] == '/') {
logsrv.u.addr.sa_family = AF_UNIX;
logsrv.u.un = *str2sun(args[1]);
@ -2340,11 +2364,13 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
curproxy->logsrv1 = logsrv;
curproxy->logfac1 = facility;
curproxy->loglev1 = level;
curproxy->minlvl1 = minlvl;
}
else if (curproxy->logfac2 == -1) {
curproxy->logsrv2 = logsrv;
curproxy->logfac2 = facility;
curproxy->loglev2 = level;
curproxy->minlvl2 = minlvl;
}
else {
Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);

View File

@ -176,7 +176,7 @@ void send_log(struct proxy *p, int level, const char *message, ...)
int fac_level;
int hdr_len, data_len;
struct logsrv *logsrvs[2];
int facilities[2], loglevel[2];
int facilities[2], loglevel[2], minlvl[2];
int nblogger;
int nbloggers = 0;
char *log_ptr;
@ -222,12 +222,14 @@ void send_log(struct proxy *p, int level, const char *message, ...)
logsrvs[nbloggers] = &global.logsrv1;
facilities[nbloggers] = global.logfac1;
loglevel[nbloggers] = global.loglev1;
minlvl[nbloggers] = global.minlvl1;
nbloggers++;
}
if (global.logfac2 >= 0) {
logsrvs[nbloggers] = &global.logsrv2;
facilities[nbloggers] = global.logfac2;
loglevel[nbloggers] = global.loglev2;
minlvl[nbloggers] = global.minlvl2;
nbloggers++;
}
} else {
@ -235,12 +237,14 @@ void send_log(struct proxy *p, int level, const char *message, ...)
logsrvs[nbloggers] = &p->logsrv1;
facilities[nbloggers] = p->logfac1;
loglevel[nbloggers] = p->loglev1;
minlvl[nbloggers] = p->minlvl1;
nbloggers++;
}
if (p->logfac2 >= 0) {
logsrvs[nbloggers] = &p->logsrv2;
facilities[nbloggers] = p->logfac2;
loglevel[nbloggers] = p->loglev2;
minlvl[nbloggers] = p->minlvl2;
nbloggers++;
}
}
@ -292,7 +296,7 @@ void send_log(struct proxy *p, int level, const char *message, ...)
* time, we only change the facility in the pre-computed header,
* and we change the pointer to the header accordingly.
*/
fac_level = (facilities[nblogger] << 3) + level;
fac_level = (facilities[nblogger] << 3) + MAX(level, minlvl[nblogger]);
log_ptr = logmsg + 3; /* last digit of the log level */
do {
*log_ptr = '0' + fac_level % 10;