MXS-1405: Log subprocess output according to log level

If the executed subprocess prefixes its output with either `error:`,
`warning:` or `info:`, the message will be logged on the appropriate
level. If no prefix is provided, the message is logged on the notice
level.
This commit is contained in:
Markus Mäkelä 2017-09-18 06:30:27 +03:00
parent 130b686d9b
commit bd3e2904e7
3 changed files with 74 additions and 2 deletions

View File

@ -87,6 +87,17 @@ For example, the previous example will be executed as:
/home/user/myscript.sh initiator=[192.168.0.10]:3306 event=master_down live_nodes=[192.168.0.201]:3306,[192.168.0.121]:3306
```
Any output by the executed script will be logged into the MaxScale log. Each
outputted line will be logged as a separate log message.
The log level on which the messages are logged depends on the format of the
messages. If the first word in the output line is one of `alert:`, `error:`,
`warning:`, `notice:`, `info:` or `debug:`, the message will be logged on the
corresponding level. If the message is not prefixed with one of the keywords,
the message will be logged on the notice level. Whitespace before, after or
inbetween the keyword and the colon is ignored and the matching is
case-insensitive.
### `script_timeout`
The timeout for the executed script in seconds. The default value is 90

View File

@ -24,6 +24,11 @@ that a monitor will wait until the executed script is done or until a
timeout is exceeded. The timeout is configurable with the `script_timeout`
parameter.
In addition to this, the output of the script is logged into the MaxScale log
file. The message is logged on the matching log level if it is prefixed with one
of `alert:`, `error:`, `warning:`, `notice:`, `info:` or `debug:`. If no prefix
is provided, the message is logged on the notice level.
For more information, refer to the [monitor documentation](../Monitors/Monitor-Common.md).
### Read-only Administrative Users

View File

@ -21,6 +21,7 @@
#include <string>
#include <maxscale/alloc.h>
#include <maxscale/debug.h>
#include <maxscale/log_manager.h>
#include <maxscale/pcre2.h>
#include <maxscale/thread.h>
@ -159,6 +160,61 @@ void externcmd_free(EXTERNCMD* cmd)
}
}
static const char* skip_whitespace(const char* ptr)
{
while (*ptr && isspace(*ptr))
{
ptr++;
}
return ptr;
}
static const char* skip_prefix(const char* str)
{
const char* ptr = strchr(str, ':');
ss_dassert(ptr);
ptr++;
return skip_whitespace(ptr);
}
static void log_output(const char* cmd, const std::string& str)
{
int err;
if (mxs_pcre2_simple_match("(?i)^[[:space:]]*alert[[:space:]]*[:]",
str.c_str(), 0, &err) == MXS_PCRE2_MATCH)
{
MXS_ALERT("%s: %s", cmd, skip_prefix(str.c_str()));
}
else if (mxs_pcre2_simple_match("(?i)^[[:space:]]*error[[:space:]]*[:]",
str.c_str(), 0, &err) == MXS_PCRE2_MATCH)
{
MXS_ERROR("%s: %s", cmd, skip_prefix(str.c_str()));
}
else if (mxs_pcre2_simple_match("(?i)^[[:space:]]*warning[[:space:]]*[:]",
str.c_str(), 0, &err) == MXS_PCRE2_MATCH)
{
MXS_WARNING("%s: %s", cmd, skip_prefix(str.c_str()));
}
else if (mxs_pcre2_simple_match("(?i)^[[:space:]]*notice[[:space:]]*[:]",
str.c_str(), 0, &err) == MXS_PCRE2_MATCH)
{
MXS_NOTICE("%s: %s", cmd, skip_prefix(str.c_str()));
}
else if (mxs_pcre2_simple_match("(?i)^[[:space:]]*(info|debug)[[:space:]]*[:]",
str.c_str(), 0, &err) == MXS_PCRE2_MATCH)
{
MXS_INFO("%s: %s", cmd, skip_prefix(str.c_str()));
}
else
{
// No special format, log as notice level message
MXS_NOTICE("%s: %s", cmd, skip_whitespace(str.c_str()));
}
}
int externcmd_execute(EXTERNCMD* cmd)
{
// Create a pipe where the command can print output
@ -290,7 +346,7 @@ int externcmd_execute(EXTERNCMD* cmd)
{
std::string line = output.substr(0, pos);
output.erase(0, pos + 1);
MXS_NOTICE("%s", line.c_str());
log_output(cmd->argv[0], line);
}
}
}
@ -298,7 +354,7 @@ int externcmd_execute(EXTERNCMD* cmd)
if (!output.empty())
{
MXS_NOTICE("%s", output.c_str());
log_output(cmd->argv[0], output);
}
// Close the read end of the pipe and copy the data to the output parameter