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:
@ -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
|
/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`
|
### `script_timeout`
|
||||||
|
|
||||||
The timeout for the executed script in seconds. The default value is 90
|
The timeout for the executed script in seconds. The default value is 90
|
||||||
|
@ -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`
|
timeout is exceeded. The timeout is configurable with the `script_timeout`
|
||||||
parameter.
|
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).
|
For more information, refer to the [monitor documentation](../Monitors/Monitor-Common.md).
|
||||||
|
|
||||||
### Read-only Administrative Users
|
### Read-only Administrative Users
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <maxscale/alloc.h>
|
#include <maxscale/alloc.h>
|
||||||
|
#include <maxscale/debug.h>
|
||||||
#include <maxscale/log_manager.h>
|
#include <maxscale/log_manager.h>
|
||||||
#include <maxscale/pcre2.h>
|
#include <maxscale/pcre2.h>
|
||||||
#include <maxscale/thread.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)
|
int externcmd_execute(EXTERNCMD* cmd)
|
||||||
{
|
{
|
||||||
// Create a pipe where the command can print output
|
// 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);
|
std::string line = output.substr(0, pos);
|
||||||
output.erase(0, pos + 1);
|
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())
|
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
|
// Close the read end of the pipe and copy the data to the output parameter
|
||||||
|
Reference in New Issue
Block a user