MINOR: trace: support -dt optional format

Add an optional argument for "-dt". This argument is interpreted as a
list of several trace statement separated by comma. For each statement,
a specific trace name can be specifed, or none to act on all sources.
Using double-colon separator, it is possible to add specifications on
the wanted level and verbosity.
This commit is contained in:
Amaury Denoyelle 2023-11-22 17:27:57 +01:00
parent 670520cff8
commit e97489a526
4 changed files with 117 additions and 12 deletions

View File

@ -402,9 +402,13 @@ list of options is :
the libc fails to resolve an address, the startup sequence is not
interrupted.
-dt : activate traces on stderr. This enables all trace sources on error
level. This can notably be useful to detect protocol violations from
clients or servers.
-dt [<trace_desc>,...] : activates traces on stderr. Without argument, this
enables all trace sources on error level. This can notably be useful to
detect protocol violations from clients or servers. An optional argument
can be used to specify a list of various trace configurations using ',' as
separator. Each element activates one or all trace sources. Additionnaly,
level and verbosity can be optionaly specified on each element using ':' as
inner separator with trace name.
-m <limit> : limit the total allocatable memory to <limit> megabytes across
all processes. This may cause some connection refusals or some slowdowns

View File

@ -190,7 +190,7 @@ void trace_no_cb(enum trace_level level, uint64_t mask, const struct trace_sourc
void trace_register_source(struct trace_source *source);
int trace_parse_cmd();
int trace_parse_cmd(char *arg, char **errmsg);
/* return a single char to describe a trace state */
static inline char trace_state_char(enum trace_state st)

View File

@ -1708,7 +1708,17 @@ static void init_args(int argc, char **argv)
kwd_dump = flag + 2;
}
else if (*flag == 'd' && flag[1] == 't') {
trace_parse_cmd();
if (argc > 1 && argv[1][0] != '-') {
if (trace_parse_cmd(argv[1], &err_msg)) {
ha_alert("-dt: %s.\n", err_msg);
ha_free(&err_msg);
exit(EXIT_FAILURE);
}
argc--; argv++;
}
else {
trace_parse_cmd(NULL, NULL);
}
}
else if (*flag == 'd')
arg_mode |= MODE_DEBUG;

View File

@ -770,19 +770,110 @@ static int trace_parse_statement(char **args, char **msg)
}
void _trace_parse_cmd(struct trace_source *src, int level, int verbosity)
{
src->sink = sink_find("stderr");
src->level = level >= 0 ? level : TRACE_LEVEL_ERROR;
src->verbosity = verbosity >= 0 ? verbosity : 1;
src->state = TRACE_STATE_RUNNING;
}
/* Parse a process argument specified via "-dt".
*
* Returns 0 on success else non-zero.
*/
int trace_parse_cmd()
int trace_parse_cmd(char *arg, char **errmsg)
{
struct trace_source *src;
char *str;
list_for_each_entry(src, &trace_sources, source_link) {
src->sink = sink_find("stderr");
src->level = TRACE_LEVEL_ERROR;
src->verbosity = 1;
src->state = TRACE_STATE_RUNNING;
if (!arg) {
/* No trace specification, activate all sources on error level. */
struct trace_source *src = NULL;
list_for_each_entry(src, &trace_sources, source_link)
_trace_parse_cmd(src, -1, -1);
return 0;
}
while ((str = strtok(arg, ","))) {
struct trace_source *src = NULL;
char *field, *name;
char *sep;
int level = -1, verbosity = -1;
/* 1. name */
name = str;
sep = strchr(str, ':');
if (sep) {
str = sep + 1;
*sep = '\0';
}
else {
str = NULL;
}
if (strlen(name)) {
src = trace_find_source(name);
if (!src) {
memprintf(errmsg, "unknown trace source '%s'", name);
return 1;
}
}
if (!str || !strlen(str))
goto parse;
/* 2. level */
field = str;
sep = strchr(str, ':');
if (sep) {
str = sep + 1;
*sep = '\0';
}
else {
str = NULL;
}
if (strlen(field)) {
level = trace_parse_level(field);
if (level < 0) {
memprintf(errmsg, "no such level '%s'", field);
return 1;
}
}
if (!str || !strlen(str))
goto parse;
/* 3. verbosity */
field = str;
if (strchr(field, ':')) {
memprintf(errmsg, "too many double-colon separator");
return 1;
}
if (!src && strcmp(field, "quiet") != 0) {
memprintf(errmsg, "trace source must be specified for verbosity other than 'quiet'");
return 1;
}
verbosity = trace_source_parse_verbosity(src, field);
if (verbosity < 0) {
memprintf(errmsg, "no such verbosity '%s' for source '%s'", field, name);
return 1;
}
parse:
if (src) {
_trace_parse_cmd(src, level, verbosity);
}
else {
list_for_each_entry(src, &trace_sources, source_link)
_trace_parse_cmd(src, level, verbosity);
}
/* Reset arg to NULL for strtok. */
arg = NULL;
}
return 0;