]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MINOR] implement per-logger log level limitation
authorWilly Tarreau <w@1wt.eu>
Sun, 10 May 2009 15:20:05 +0000 (17:20 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 10 May 2009 15:20:05 +0000 (17:20 +0200)
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.

doc/configuration.txt
include/types/global.h
include/types/proxy.h
src/cfgparse.c
src/log.c

index 454bbd395f3ada67637237304d67f61d9c08a874..43627b56550f1f829177db3c7c6191e504b7e952 100644 (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>
index d0c22bcb45705edec5719a6bc8bca5488b663805..1ba0b11804bb5750d56bd470043b002ab26f76e5 100644 (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 */
index 3cb60c0f41263eee2c903047199fd556b46a344c..7ef5fc89a26ab036dddecc25b08c7caa43a3d61c 100644 (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;
index 3a71df2506db5d41fe660b30c07a32d6ceb06046..e3c8b62958c7c4cf1c164e1463552a644c64d569 100644 (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);
index bc9fd0a4b8be33df23a2b87bc2294963cad33bbd..093accb28735e9b40389ab66559a24990b85db2b 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -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;