]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: http: add support for action "set-log-level" in http-request/http-response
authorWilly Tarreau <w@1wt.eu>
Tue, 11 Jun 2013 15:45:46 +0000 (17:45 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 11 Jun 2013 15:50:26 +0000 (17:50 +0200)
Some users want to disable logging for certain non-important requests such as
stats requests or health-checks coming from another equipment. Other users want
to log with a higher importance (eg: notice) some special traffic (POST requests,
authenticated requests, requests coming from suspicious IPs) or some abnormally
large responses.

This patch responds to all these needs at once by adding a "set-log-level" action
to http-request/http-response. The 8 syslog levels are supported, as well as "silent"
to disable logging.

doc/configuration.txt
include/types/proto_http.h
src/proto_http.c
src/session.c

index 93d2f2cbfd12ef964b6a9ada1cfe2da2a25242bd..ef80690d5ecd761aaadc017096ea5c2528b976d3 100644 (file)
@@ -2669,7 +2669,7 @@ http-check send-state
 
 http-request { allow | deny | tarpit | auth [realm <realm>] | redirect <rule> |
               add-header <name> <fmt> | set-header <name> <fmt> |
-              set-nice <nice> }
+              set-nice <nice> | set-log-level <level> }
              [ { if | unless } <condition> ]
   Access control for Layer 7 requests
 
@@ -2736,6 +2736,13 @@ http-request { allow | deny | tarpit | auth [realm <realm>] | redirect <rule> |
       some requests, or lower the priority of non-important requests. Using
       this setting without prior experimentation can cause some major slowdown.
 
+    - "set-log-level" is used to change the log level of the current request
+      when a certain condition is met. Valid levels are the 8 syslog levels
+      (see the "log" keyword) plus the special level "silent" which disables
+      logging for this request. This rule is not final so the last matching
+      rule wins. This rule can be useful to disable health checks coming from
+      another equipment.
+
   There is no limit to the number of http-request statements per instance.
 
   It is important to know that http-request rules are processed very early in
@@ -2772,7 +2779,8 @@ http-request { allow | deny | tarpit | auth [realm <realm>] | redirect <rule> |
              about ACL usage.
 
 http-response { allow | deny | add-header <name> <fmt> | set-nice <nice> |
-                set-header <name> <fmt> } [ { if | unless } <condition> ]
+                set-header <name> <fmt> | set-log-level <level> }
+                [ { if | unless } <condition> ]
   Access control for Layer 7 responses
 
   May be used in sections:   defaults | frontend | listen | backend
@@ -2816,6 +2824,13 @@ http-response { allow | deny | add-header <name> <fmt> | set-nice <nice> |
       some requests, or lower the priority of non-important requests. Using
       this setting without prior experimentation can cause some major slowdown.
 
+    - "set-log-level" is used to change the log level of the current request
+      when a certain condition is met. Valid levels are the 8 syslog levels
+      (see the "log" keyword) plus the special level "silent" which disables
+      logging for this request. This rule is not final so the last matching
+      rule wins. This rule can be useful to disable health checks coming from
+      another equipment.
+
   There is no limit to the number of http-response statements per instance.
 
   It is important to know that http-reqsponse rules are processed very early in
index b50375f79092fbebb5d545e966d0a9c1a8eb48c9..b2010552958afc4581fd9545a0bcd082cdbd4d3a 100644 (file)
@@ -247,6 +247,7 @@ enum {
        HTTP_REQ_ACT_SET_HDR,
        HTTP_REQ_ACT_REDIR,
        HTTP_REQ_ACT_SET_NICE,
+       HTTP_REQ_ACT_SET_LOGL,
        HTTP_REQ_ACT_MAX /* must always be last */
 };
 
@@ -258,6 +259,7 @@ enum {
        HTTP_RES_ACT_ADD_HDR,
        HTTP_RES_ACT_SET_HDR,
        HTTP_RES_ACT_SET_NICE,
+       HTTP_RES_ACT_SET_LOGL,
        HTTP_RES_ACT_MAX /* must always be last */
 };
 
@@ -371,6 +373,7 @@ struct http_req_rule {
                } hdr_add;                     /* args used by "add-header" and "set-header" */
                struct redirect_rule *redir;   /* redirect rule or "http-request redirect" */
                int nice;                      /* nice value for HTTP_REQ_ACT_SET_NICE */
+               int loglevel;                  /* log-level value for HTTP_REQ_ACT_SET_LOGL */
        } arg;                                 /* arguments used by some actions */
 };
 
@@ -385,6 +388,7 @@ struct http_res_rule {
                        struct list fmt;       /* log-format compatible expression */
                } hdr_add;                     /* args used by "add-header" and "set-header" */
                int nice;                      /* nice value for HTTP_RES_ACT_SET_NICE */
+               int loglevel;                  /* log-level value for HTTP_RES_ACT_SET_LOGL */
        } arg;                                 /* arguments used by some actions */
 };
 
index de9b331300d86a1338ddf293dab979f7a735ee4a..fe79c15730757bd32723a73b28f9f70e98d8cdd2 100644 (file)
@@ -3211,6 +3211,10 @@ http_req_get_intercept_rule(struct proxy *px, struct list *rules, struct session
                        s->task->nice = rule->arg.nice;
                        break;
 
+               case HTTP_REQ_ACT_SET_LOGL:
+                       s->logs.level = rule->arg.loglevel;
+                       break;
+
                case HTTP_REQ_ACT_SET_HDR:
                        ctx.idx = 0;
                        /* remove all occurrences of the header */
@@ -3280,6 +3284,10 @@ http_res_get_intercept_rule(struct proxy *px, struct list *rules, struct session
                        s->task->nice = rule->arg.nice;
                        break;
 
+               case HTTP_RES_ACT_SET_LOGL:
+                       s->logs.level = rule->arg.loglevel;
+                       break;
+
                case HTTP_RES_ACT_SET_HDR:
                        ctx.idx = 0;
                        /* remove all occurrences of the header */
@@ -8412,6 +8420,22 @@ struct http_req_rule *parse_http_req_cond(const char **args, const char *file, i
                else if (rule->arg.nice > 1024)
                        rule->arg.nice = 1024;
                cur_arg++;
+       } else if (!strcmp(args[0], "set-log-level")) {
+               rule->action = HTTP_REQ_ACT_SET_LOGL;
+               cur_arg = 1;
+
+               if (!*args[cur_arg] ||
+                   (*args[cur_arg + 1] && strcmp(args[cur_arg + 1], "if") != 0 && strcmp(args[cur_arg + 1], "unless") != 0)) {
+               bad_log_level:
+                       Alert("parsing [%s:%d]: 'http-request %s' expects exactly 1 argument (log level name or 'silent').\n",
+                             file, linenum, args[0]);
+                       goto out_err;
+               }
+               if (strcmp(args[cur_arg], "silent") == 0)
+                       rule->arg.loglevel = -1;
+               else if ((rule->arg.loglevel = get_log_level(args[cur_arg]) + 1) == 0)
+                       goto bad_log_level;
+               cur_arg++;
        } else if (strcmp(args[0], "add-header") == 0 || strcmp(args[0], "set-header") == 0) {
                rule->action = *args[0] == 'a' ? HTTP_REQ_ACT_ADD_HDR : HTTP_REQ_ACT_SET_HDR;
                cur_arg = 1;
@@ -8451,7 +8475,7 @@ struct http_req_rule *parse_http_req_cond(const char **args, const char *file, i
                cur_arg = 2;
                return rule;
        } else {
-               Alert("parsing [%s:%d]: 'http-request' expects 'allow', 'deny', 'auth', 'redirect', 'tarpit', 'add-header', 'set-header', 'set-nice', but got '%s'%s.\n",
+               Alert("parsing [%s:%d]: 'http-request' expects 'allow', 'deny', 'auth', 'redirect', 'tarpit', 'add-header', 'set-header', 'set-nice', 'set-log-level', but got '%s'%s.\n",
                      file, linenum, args[0], *args[0] ? "" : " (missing argument)");
                goto out_err;
        }
@@ -8515,6 +8539,22 @@ struct http_res_rule *parse_http_res_cond(const char **args, const char *file, i
                else if (rule->arg.nice > 1024)
                        rule->arg.nice = 1024;
                cur_arg++;
+       } else if (!strcmp(args[0], "set-log-level")) {
+               rule->action = HTTP_RES_ACT_SET_LOGL;
+               cur_arg = 1;
+
+               if (!*args[cur_arg] ||
+                   (*args[cur_arg + 1] && strcmp(args[cur_arg + 1], "if") != 0 && strcmp(args[cur_arg + 1], "unless") != 0)) {
+               bad_log_level:
+                       Alert("parsing [%s:%d]: 'http-response %s' expects exactly 1 argument (log level name or 'silent').\n",
+                             file, linenum, args[0]);
+                       goto out_err;
+               }
+               if (strcmp(args[cur_arg], "silent") == 0)
+                       rule->arg.loglevel = -1;
+               else if ((rule->arg.loglevel = get_log_level(args[cur_arg] + 1)) == 0)
+                       goto bad_log_level;
+               cur_arg++;
        } else if (strcmp(args[0], "add-header") == 0 || strcmp(args[0], "set-header") == 0) {
                rule->action = *args[0] == 'a' ? HTTP_RES_ACT_ADD_HDR : HTTP_RES_ACT_SET_HDR;
                cur_arg = 1;
@@ -8535,7 +8575,7 @@ struct http_res_rule *parse_http_res_cond(const char **args, const char *file, i
                                       (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR);
                cur_arg += 2;
        } else {
-               Alert("parsing [%s:%d]: 'http-response' expects 'allow', 'deny', 'redirect', 'add-header', 'set-header', 'set-nice', but got '%s'%s.\n",
+               Alert("parsing [%s:%d]: 'http-response' expects 'allow', 'deny', 'redirect', 'add-header', 'set-header', 'set-nice', 'set-log-level', but got '%s'%s.\n",
                      file, linenum, args[0], *args[0] ? "" : " (missing argument)");
                goto out_err;
        }
index 7309af00b8b77a3bebcfcba0e67c5cbe434ca44b..5e0da25ab25580b37770eb4be5eef907476a9707 100644 (file)
@@ -97,6 +97,7 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
         */
        s->flags = 0;
        s->logs.logwait = p->to_log;
+       s->logs.level = 0;
 
        memset(s->stkctr, 0, sizeof(s->stkctr));