MINOR: lua: Add flags to configure logging behaviour

Until now, messages printed from LUA log functions were sent both to
the any logger configured for the current proxy, and additionally to
stderr (in most cases)

This introduces two flags to configure LUA log handling:
- tune.lua.log.loggers to use standard loggers or not
- tune.lua.log.stderr to use stderr, or not, or only conditionally

This addresses github feature request #2316

This can be backported to 2.8 as it doesn't change previous behaviour.
This commit is contained in:
Tristan 2023-10-23 13:07:39 +01:00 committed by Willy Tarreau
parent b12613f0ac
commit 97dacbbb86
4 changed files with 111 additions and 7 deletions

View File

@ -1196,6 +1196,8 @@ The following keywords are supported in the "global" section :
- tune.lua.service-timeout
- tune.lua.session-timeout
- tune.lua.task-timeout
- tune.lua.log.loggers
- tune.lua.log.stderr
- tune.max-checks-per-thread
- tune.maxaccept
- tune.maxpollevents
@ -3192,6 +3194,26 @@ tune.lua.task-timeout <timeout>
remain alive during of the lifetime of HAProxy. For example, a task used to
check servers.
tune.lua.log.loggers { on | off }
Enables ('on') or disables ('off') logging the output of LUA scripts via the
loggers applicable to the current proxy, if any.
Defaults to 'on'.
tune.lua.log.stderr { on | auto | off }
Enables ('on') or disables ('off') logging the output of LUA scripts via
stderr.
When set to 'auto', logging via stderr is conditionally 'on' if any of:
- tune.lua.log.loggers is set to 'off'
- the script is executed in a non-proxy context with no global logger
- the script is executed in a proxy context with no logger attached
Please note that, when enabled, this logging is in addition to the logging
configured via tune.lua.log.loggers.
Defaults to 'on'.
tune.max-checks-per-thread <number>
Sets the number of active checks per thread above which a thread will
actively try to search a less loaded thread to run the health check, or

View File

@ -267,8 +267,10 @@ Core class
**context**: body, init, task, action, sample-fetch, converter
This function sends a log. The log is sent, according with the HAProxy
configuration file, on the default syslog server if it is configured and on
the stderr if it is allowed.
configuration file, to the loggers relevant to the current context and
to stderr if it is allowed.
The exact behaviour depends on tune.lua.log.loggers and tune.lua.log.stderr.
:param integer loglevel: Is the log level associated with the message. It is a
number between 0 and 7.
@ -2648,8 +2650,10 @@ TXN class
.. js:function:: TXN.log(TXN, loglevel, msg)
This function sends a log. The log is sent, according with the HAProxy
configuration file, on the default syslog server if it is configured and on
the stderr if it is allowed.
configuration file, to the loggers relevant to the current context and
to stderr if it is allowed.
The exact behaviour depends on tune.lua.log.loggers and tune.lua.log.stderr.
:param class_txn txn: The class txn object containing the data.
:param integer loglevel: Is the log level associated with the message. It is

View File

@ -630,6 +630,10 @@ It displays a log during the HAProxy startup:
[alert] 285/083533 (14465) : Hello World !
Note: By default, logs originating from a LUA script are sent to the loggers
applicable to the current context, if any, and additionally to stderr. See
tune.lua.log.loggers and tune.lua.log.stderr for more information.
Default path and libraries
--------------------------

View File

@ -69,6 +69,20 @@
#include <haproxy/check.h>
#include <haproxy/mailers.h>
/* Global LUA flags */
enum hlua_log_opt {
/* tune.lua.log.loggers */
HLUA_LOG_LOGGERS_ON = 0x00000001, /* forward logs to current loggers */
/* tune.lua.log.stderr */
HLUA_LOG_STDERR_ON = 0x00000010, /* forward logs to stderr */
HLUA_LOG_STDERR_AUTO = 0x00000020, /* forward logs to stderr if no loggers */
HLUA_LOG_STDERR_MASK = 0x00000030,
};
/* default log options, made of flags in hlua_log_opt */
static uint hlua_log_opts = HLUA_LOG_LOGGERS_ON | HLUA_LOG_STDERR_ON;
/* Lua uses longjmp to perform yield or throwing errors. This
* macro is used only for identifying the function that can
* not return because a longjmp is executed.
@ -1366,8 +1380,9 @@ const char *hlua_show_current_location(const char *pfx)
return NULL;
}
/* This function is used to send logs. It try to send on screen (stderr)
* and on the default syslog server.
/* This function is used to send logs. It tries to send them to:
* - the log target applicable in the current context, AND
* - stderr if not in quiet mode or explicitly disabled
*/
static inline void hlua_sendlog(struct proxy *px, int level, const char *msg)
{
@ -1392,8 +1407,28 @@ static inline void hlua_sendlog(struct proxy *px, int level, const char *msg)
}
*p = '\0';
send_log(px, level, "%s\n", trash.area);
if (hlua_log_opts & HLUA_LOG_LOGGERS_ON)
send_log(px, level, "%s\n", trash.area);
if (!(global.mode & MODE_QUIET) || (global.mode & (MODE_VERBOSE | MODE_STARTING))) {
if (!(hlua_log_opts & HLUA_LOG_STDERR_MASK))
return;
/* when logging via stderr is set to 'auto', it behaves like 'off' unless one of:
* - logging via loggers is disabled
* - this is a non-proxy context and there is no global logger configured
* - this is a proxy context and the proxy has no logger configured
*/
if ((hlua_log_opts & (HLUA_LOG_STDERR_MASK | HLUA_LOG_LOGGERS_ON)) == (HLUA_LOG_STDERR_AUTO | HLUA_LOG_LOGGERS_ON)) {
/* AUTO=OFF in non-proxy context only if at least one global logger is defined */
if ((px == NULL) && (!LIST_ISEMPTY(&global.loggers)))
return;
/* AUTO=OFF in proxy context only if at least one logger is configured for the proxy */
if ((px != NULL) && (!LIST_ISEMPTY(&px->loggers)))
return;
}
if (level == LOG_DEBUG && !(global.mode & MODE_DEBUG))
return;
@ -12431,6 +12466,43 @@ static int hlua_parse_maxmem(char **args, int section_type, struct proxy *curpx,
return 0;
}
static int hlua_cfg_parse_log_loggers(char **args, int section_type, struct proxy *curpx,
const struct proxy *defpx, const char *file, int line,
char **err)
{
if (too_many_args(1, args, err, NULL))
return -1;
if (strcmp(args[1], "on") == 0)
hlua_log_opts |= HLUA_LOG_LOGGERS_ON;
else if (strcmp(args[1], "off") == 0)
hlua_log_opts &= ~HLUA_LOG_LOGGERS_ON;
else {
memprintf(err, "'%s' expects either 'on' or 'off' but got '%s'.", args[0], args[1]);
return -1;
}
return 0;
}
static int hlua_cfg_parse_log_stderr(char **args, int section_type, struct proxy *curpx,
const struct proxy *defpx, const char *file, int line,
char **err)
{
if (too_many_args(1, args, err, NULL))
return -1;
if (strcmp(args[1], "on") == 0)
hlua_log_opts = (hlua_log_opts & ~HLUA_LOG_STDERR_MASK) | HLUA_LOG_STDERR_ON;
else if (strcmp(args[1], "auto") == 0)
hlua_log_opts = (hlua_log_opts & ~HLUA_LOG_STDERR_MASK) | HLUA_LOG_STDERR_AUTO;
else if (strcmp(args[1], "off") == 0)
hlua_log_opts &= ~HLUA_LOG_STDERR_MASK;
else {
memprintf(err, "'%s' expects either 'on', 'auto', or 'off' but got '%s'.", args[0], args[1]);
return -1;
}
return 0;
}
/* This function is called by the main configuration key "lua-load". It loads and
* execute an lua file during the parsing of the HAProxy configuration file. It is
@ -12680,6 +12752,8 @@ static struct cfg_kw_list cfg_kws = {{ },{
{ CFG_GLOBAL, "tune.lua.burst-timeout", hlua_burst_timeout },
{ CFG_GLOBAL, "tune.lua.forced-yield", hlua_forced_yield },
{ CFG_GLOBAL, "tune.lua.maxmem", hlua_parse_maxmem },
{ CFG_GLOBAL, "tune.lua.log.loggers", hlua_cfg_parse_log_loggers },
{ CFG_GLOBAL, "tune.lua.log.stderr", hlua_cfg_parse_log_stderr },
{ 0, NULL, NULL },
}};