3.1. Process management and security
3.2. Performance tuning
3.3. Debugging
+3.3.1. Traces
3.4. Userlists
3.5. Peers
3.6. Mailers
and a warning is emitted in so that the configuration anomaly can be
fixed. By default there is no limit. See also "nbthread".
-trace <args...>
- This command configures one "trace" subsystem statement. Each of them can be
- found in the management manual, and follow the exact same syntax. Only one
- statement per line is permitted (i.e. if some long trace configurations using
- semi-colons are to be imported, they must be placed one per line). Any output
- that the "trace" command would produce will be emitted during the parsing
- step of the section. Most of the time these will be errors and warnings, but
- certain incomplete commands might list permissible choices. This command is
- not meant for regular use, it will generally only be suggested by developers
- along complex debugging sessions. For this reason it is internally marked as
- experimental, meaning that "expose-experimental-directives" must appear on a
- line before any "trace" statement. Note that these directives are parsed on
- the fly, so referencing a ring buffer that is only declared further will not
- work. For such use cases it is suggested to place another "global" section
- with only the "trace" statements after the declaration of that ring. It is
- important to keep in mind that depending on the trace level and details,
- enabling traces can severely degrade the global performance. Please refer to
- the management manual for the statements syntax.
-
uid <number>
Changes the process's user ID to <number>. It is recommended that the user ID
is dedicated to HAProxy or to a small set of similar daemons. HAProxy must
report errors in such a case. This option is equivalent to command line
argument "-dW".
+3.3.1. Traces
+-------------
+
+For debugging purpose, it is possible to activate traces on an HAProxy's
+subsystem. This will dump debug messages about a specific subsystem. It is a
+very powerful tool to diagnose issues. Traces can be dynamically configured via
+the CLI. It is also possible to predefined some settings in the configuration
+file, in dedicated "traces" sections. More details about traces can be found in
+the management guide. It remains a developper tools used during complex
+debugging sessions. It is pretty verbose and have a cost, so use it with
+caution. And because it is a developper tool, there is no warranty about the
+backward compatibility of this section.
+
+traces
+ Starts a new traces section. One or multiple "traces" section may be
+ used. All direcitives are evaluated in the declararion order, the last ones
+ overriding previous ones.
+
+trace <args...>
+ Configures on "trace" subsystem. Each of them can be found in the management
+ manual, and follow the exact same syntax. Only one statement per line is
+ permitted (i.e. if some long trace configurations using semi-colons are to be
+ imported, they must be placed one per line). Any output that the "trace"
+ command would produce will be emitted during the parsing step of the
+ section. Most of the time these will be errors and warnings, but certain
+ incomplete commands might list permissible choices. This command is not meant
+ for regular use, it will generally only be suggested by developers along
+ complex debugging sessions. Note that these directives are parsed on the fly,
+ so referencing a ring buffer that is only declared further will not work. It
+ is important to keep in mind that depending on the trace level and details,
+ enabling traces can severely degrade the global performance. Please refer to
+ the management manual for the statements syntax.
+
+ Example:
+ ring buf1
+ size 10485760 # 10MB
+ format timed
+ backing-file /tmp/h1.traces
+
+ ring buf2
+ size 10485760 # 10MB
+ format timed
+ backing-file /tmp/h2.traces
+
+ traces
+ trace h1 sink buf1
+ trace h1 level developer
+ trace h1 verbosity complete
+ trace h1 start now
+
+ trace h2 sink buf1
+ trace h2 level developer
+ trace h2 verbosity complete
+ trace h2 start now
3.4. Userlists
--------------
#define CFG_PEERS 4
#define CFG_CRTLIST 5
#define CFG_CRTSTORE 6
+#define CFG_TRACES 7
/* various keyword modifiers */
enum kw_mod {
int cfg_parse_global(const char *file, int linenum, char **args, int inv);
int cfg_parse_listen(const char *file, int linenum, char **args, int inv);
+int cfg_parse_traces(const char *file, int linenum, char **args, int inv);
int cfg_parse_track_sc_num(unsigned int *track_sc_num,
const char *arg, const char *end, char **err);
int parse_cfg(const struct cfgfile *cfg);
}
}
}
-
+
best = cfg_find_best_match(args[0], &cfg_keywords.list, CFG_GLOBAL, common_kw_list);
if (best)
ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section; did you mean '%s' maybe ?\n", file, linenum, args[0], cursection, best);
REGISTER_CONFIG_SECTION("peers", cfg_parse_peers, NULL);
REGISTER_CONFIG_SECTION("mailers", cfg_parse_mailers, NULL);
REGISTER_CONFIG_SECTION("namespace_list", cfg_parse_netns, NULL);
+REGISTER_CONFIG_SECTION("traces", cfg_parse_traces, NULL);
static struct cfg_kw_list cfg_kws = {{ },{
{ CFG_GLOBAL, "default-path", cfg_parse_global_def_path },
}
ha_free(&msg);
}
+
return 0;
}
+/*
+ * parse a line in a <traces> section. Returns the error code, 0 if OK, or
+ * any combination of :
+ * - ERR_ABORT: must abort ASAP
+ * - ERR_FATAL: we can continue parsing but not start the service
+ * - ERR_WARN: a warning has been emitted
+ * - ERR_ALERT: an alert has been emitted
+ * Only the two first ones can stop processing, the two others are just
+ * indicators.
+ */
+int cfg_parse_traces(const char *file, int linenum, char **args, int inv)
+{
+ int err_code = 0;
+ char *errmsg = NULL;
+
+ if (strcmp(args[0], "traces") == 0) { /* new section */
+ /* no option, nothing special to do */
+ alertif_too_many_args(0, file, linenum, args, &err_code);
+ goto out;
+ }
+ else {
+ struct cfg_kw_list *kwl;
+ const char *best;
+ int index;
+ int rc;
+
+ list_for_each_entry(kwl, &cfg_keywords.list, list) {
+ for (index = 0; kwl->kw[index].kw != NULL; index++) {
+ if (kwl->kw[index].section != CFG_TRACES)
+ continue;
+ if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
+ if (check_kw_experimental(&kwl->kw[index], file, linenum, &errmsg)) {
+ ha_alert("%s\n", errmsg);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ rc = kwl->kw[index].parse(args, CFG_TRACES, NULL, NULL, file, linenum, &errmsg);
+ if (rc < 0) {
+ ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ }
+ else if (rc > 0) {
+ ha_warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
+ err_code |= ERR_WARN;
+ }
+ goto out;
+ }
+ }
+ }
+
+ best = cfg_find_best_match(args[0], &cfg_keywords.list, CFG_TRACES, NULL);
+ if (best)
+ ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section; did you mean '%s' maybe ?\n", file, linenum, args[0], cursection, best);
+ else
+ ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
+ err_code |= ERR_ALERT | ERR_FATAL;
+ }
+
+ out:
+ free(errmsg);
+ return err_code;
+}
+
/* parse the command, returns 1 if a message is returned, otherwise zero */
static int cli_parse_trace(char **args, char *payload, struct appctx *appctx, void *private)
{
INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
static struct cfg_kw_list cfg_kws = {ILH, {
- { CFG_GLOBAL, "trace", cfg_parse_trace, KWF_EXPERIMENTAL },
+ { CFG_TRACES, "trace", cfg_parse_trace },
{ /* END */ },
}};