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> | http-request { allow | deny | tarpit | auth [realm <realm>] | redirect <rule> |
add-header <name> <fmt> | set-header <name> <fmt> | add-header <name> <fmt> | set-header <name> <fmt> |
set-nice <nice> } set-nice <nice> | set-log-level <level> }
[ { if | unless } <condition> ] [ { if | unless } <condition> ]
Access control for Layer 7 requests 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 some requests, or lower the priority of non-important requests. Using
this setting without prior experimentation can cause some major slowdown. 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. 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 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. about ACL usage.
http-response { allow | deny | add-header <name> <fmt> | set-nice <nice> | 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 Access control for Layer 7 responses
May be used in sections: defaults | frontend | listen | backend 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 some requests, or lower the priority of non-important requests. Using
this setting without prior experimentation can cause some major slowdown. 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. 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 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_SET_HDR,
HTTP_REQ_ACT_REDIR, HTTP_REQ_ACT_REDIR,
HTTP_REQ_ACT_SET_NICE, HTTP_REQ_ACT_SET_NICE,
HTTP_REQ_ACT_SET_LOGL,
HTTP_REQ_ACT_MAX /* must always be last */ HTTP_REQ_ACT_MAX /* must always be last */
}; };
@ -258,6 +259,7 @@ enum {
HTTP_RES_ACT_ADD_HDR, HTTP_RES_ACT_ADD_HDR,
HTTP_RES_ACT_SET_HDR, HTTP_RES_ACT_SET_HDR,
HTTP_RES_ACT_SET_NICE, HTTP_RES_ACT_SET_NICE,
HTTP_RES_ACT_SET_LOGL,
HTTP_RES_ACT_MAX /* must always be last */ 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" */ } hdr_add; /* args used by "add-header" and "set-header" */
struct redirect_rule *redir; /* redirect rule or "http-request redirect" */ struct redirect_rule *redir; /* redirect rule or "http-request redirect" */
int nice; /* nice value for HTTP_REQ_ACT_SET_NICE */ 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 */ } arg; /* arguments used by some actions */
}; };
@ -385,6 +388,7 @@ struct http_res_rule {
struct list fmt; /* log-format compatible expression */ struct list fmt; /* log-format compatible expression */
} hdr_add; /* args used by "add-header" and "set-header" */ } hdr_add; /* args used by "add-header" and "set-header" */
int nice; /* nice value for HTTP_RES_ACT_SET_NICE */ 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 */ } 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; s->task->nice = rule->arg.nice;
break; break;
case HTTP_REQ_ACT_SET_LOGL:
s->logs.level = rule->arg.loglevel;
break;
case HTTP_REQ_ACT_SET_HDR: case HTTP_REQ_ACT_SET_HDR:
ctx.idx = 0; ctx.idx = 0;
/* remove all occurrences of the header */ /* 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; s->task->nice = rule->arg.nice;
break; break;
case HTTP_RES_ACT_SET_LOGL:
s->logs.level = rule->arg.loglevel;
break;
case HTTP_RES_ACT_SET_HDR: case HTTP_RES_ACT_SET_HDR:
ctx.idx = 0; ctx.idx = 0;
/* remove all occurrences of the header */ /* 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) else if (rule->arg.nice > 1024)
rule->arg.nice = 1024; rule->arg.nice = 1024;
cur_arg++; 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) { } 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; rule->action = *args[0] == 'a' ? HTTP_REQ_ACT_ADD_HDR : HTTP_REQ_ACT_SET_HDR;
cur_arg = 1; 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; cur_arg = 2;
return rule; return rule;
} else { } 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)"); file, linenum, args[0], *args[0] ? "" : " (missing argument)");
goto out_err; 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) else if (rule->arg.nice > 1024)
rule->arg.nice = 1024; rule->arg.nice = 1024;
cur_arg++; 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) { } 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; rule->action = *args[0] == 'a' ? HTTP_RES_ACT_ADD_HDR : HTTP_RES_ACT_SET_HDR;
cur_arg = 1; 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); (proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR);
cur_arg += 2; cur_arg += 2;
} else { } 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)"); file, linenum, args[0], *args[0] ? "" : " (missing argument)");
goto out_err; 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->flags = 0;
s->logs.logwait = p->to_log; s->logs.logwait = p->to_log;
s->logs.level = 0;
memset(s->stkctr, 0, sizeof(s->stkctr)); memset(s->stkctr, 0, sizeof(s->stkctr));