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.
This commit is contained in:
Willy Tarreau 2013-06-11 17:45:46 +02:00
parent abcd5145f8
commit 9a355ec257
4 changed files with 64 additions and 4 deletions

View 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

View 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 */
};

View 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;
}

View 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));