From 9a355ec257de12ec8ab6366d15ff59add8a8061f Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 11 Jun 2013 17:45:46 +0200 Subject: [PATCH] MEDIUM: http: add support for action "set-log-level" in http-request/http-response 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 | 19 ++++++++++++++-- include/types/proto_http.h | 4 ++++ src/proto_http.c | 44 ++++++++++++++++++++++++++++++++++++-- src/session.c | 1 + 4 files changed, 64 insertions(+), 4 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 93d2f2cbf..ef80690d5 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -2669,7 +2669,7 @@ http-check send-state http-request { allow | deny | tarpit | auth [realm ] | redirect | add-header | set-header | - set-nice } + set-nice | set-log-level } [ { if | unless } ] Access control for Layer 7 requests @@ -2736,6 +2736,13 @@ http-request { allow | deny | tarpit | auth [realm ] | redirect | 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 ] | redirect | about ACL usage. http-response { allow | deny | add-header | set-nice | - set-header } [ { if | unless } ] + set-header | set-log-level } + [ { if | unless } ] 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 | set-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 diff --git a/include/types/proto_http.h b/include/types/proto_http.h index b50375f79..b20105529 100644 --- a/include/types/proto_http.h +++ b/include/types/proto_http.h @@ -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 */ }; diff --git a/src/proto_http.c b/src/proto_http.c index de9b33130..fe79c1573 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -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; } diff --git a/src/session.c b/src/session.c index 7309af00b..5e0da25ab 100644 --- a/src/session.c +++ b/src/session.c @@ -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));