MINOR: log: rename 'log-format tag' to 'log-format alias'

In 2.9 we started to introduce an ambiguity in the documentation by
referring to historical log-format variables ('%var') as log-format
tags in 739c4e5b1e ("MINOR: sample: accept_date / request_date return
%Ts / %tr timestamp values") and 454c372b60 ("DOC: configuration: add
sample fetches for timing events").

In fact, we've had this confusion between log-format tag and log-format
var for more than 10 years now, but in 2.9 it was the first time the
confusion was exposed in the documentation.

Indeed, both 'log-format variable' and 'log-format tag' actually refer
to the same feature (that is: '%B' and friends that can be used for
direct access to some log-oriented predefined fetches instead of using
%[expr] with generic sample expressions).

This feature was first implemented in 723b73ad75 ("MINOR: config: Parse
the string of the log-format config keyword") and later documented in
4894040fa ("DOC: log-format documentation"). At that time, it was clear
that we used to name it 'log-format variable'.

But later the same year, 'log-format tag' naming started to appear in
some commit messages (while still referring to the same feature), for
instance with ffc3fcd6d ("MEDIUM: log: report SSL ciphers and version
in logs using logformat %sslc/%sslv").

Unfortunately in 2.9 when we added (and documented) new log-format
variables we officially started drifting to the misleading 'log-format
tag' naming (perhaps because it was the most recent naming found for
this feature in git log history, or because the confusion has always
been there)

Even worse, in 3.0 this confusion led us to rename all 'var' occurrences
to 'tag' in log-format related code to unify the code with the doc.

Hopefully William quickly noticed that we made a mistake there, but
instead of reverting to historical naming (log-format variable), it was
decided that we must use a different name that is less confusing than
'tags' or 'variables' (tags and variables are keywords that are already
used to designate other features in the code and that are not very
explicit under log-format context today).

Now we refer to '%B' and friends as a logformat alias, which is
essentially a handy way to print some log oriented information in the
log string instead of leveraging '%[expr]' with generic sample expressions
made of fetches and converters. Of course, there are some subtelties, such
as a few log-format aliases that still don't have sample fetch equivalent
for historical reasons, and some aliases that may be a little faster than
their generic sample expression equivalents because most aliases are
pretty much hardcoded in the log building function. But in general
logformat aliases should be simply considered as an alternative to using
expressions (with '%[expr']')

Also, under log-format context, when we want to refer to either an alias
('%alias') or an expression ('%[expr]'), we should use the generic term
'logformat item', which in fact designates a single item within the
logformat string provided by the user. Indeed, a logformat item (whether
is is an alias or an expression) always starts with '%' and may accept
optional flags / arguments

Both the code and the documentation were updated in that sense, hopefully
this will clarify things and prevent future confusions.
This commit is contained in:
Aurelien DARRAGON 2024-05-27 10:18:10 +02:00
parent 7e943cdf27
commit 435a9da267
4 changed files with 125 additions and 118 deletions

View File

@ -9883,7 +9883,7 @@ no option logasap
Arguments : none
By default, logs are emitted when all the log format variables and sample
By default, logs are emitted when all the log format aliases and sample
fetches used in the definition of the log-format string return a value, or
when the stream is terminated. This allows the built in log-format strings
to account for the transfer time, or the number of bytes in log messages.
@ -13977,7 +13977,7 @@ unique-id-format <fmt>
This keyword creates a ID for each request using the custom log format. A
unique ID is useful to trace a request passing through many components of
a complex infrastructure. The newly created ID may also be logged using the
%ID tag the Custom log format string.
%ID alias in the Custom log format string.
The format should be composed from elements that are guaranteed to be
unique when combined together. For instance, if multiple HAProxy instances
@ -24379,7 +24379,7 @@ hdr([<name>[,<occ>]]) : string
request_date([<unit>]) : integer
This is the exact date when the first byte of the HTTP request was received
by HAProxy (log-format tag %tr). This is computed from accept_date +
by HAProxy (log-format alias %tr). This is computed from accept_date +
handshake time (%Th) + idle time (%Ti).
Returns a value in number of seconds since epoch.
@ -24646,8 +24646,8 @@ req.hdr_names([<delim>]) : string
req.ver : string
req_ver : string (deprecated)
Returns the version string from the HTTP request, for example "1.1". This can
be useful for ACL. For logs use the "%HV" log variable. Some predefined ACL
already check for versions 1.0 and 1.1.
be useful for ACL. For logs use the "%HV" logformat alias. Some predefined
ACL already check for versions 1.0 and 1.1.
Common values are "1.0", "1.1", "2.0" or "3.0".
@ -25901,24 +25901,30 @@ are still commonly encountered due to the massive adoption of log formats after
version 1.5-dev9, 3 years before quotes were usable, but it is recommended to
convert them to quoted strings and to drop the backslashes now.
HAProxy understands some log format variables, preceeded by character '%'.
In order to emit a verbatim '%', it must be preceded by another '%' resulting
in '%%'.
A log format definition is made of any number of log format items separated
by text and spaces. A log format item starts with character '%'. In order to
emit a verbatim '%', it must be preceded by another '%' resulting in '%%'.
Variables can take arguments using braces ('{}'), and multiple arguments are
separated by commas within the braces. Flags may be added or removed by
prefixing them with a '+' or '-' sign.
Logformat items may either be aliases or sample expressions:
Special variable "%o" may be used to propagate its flags to all other
variables on the same format string. This is particularly handy with quoted
("Q") and escaped ("E") string formats.
If a variable is named between square brackets ('[' .. ']') then it is used
If an item is named between square brackets ('[' .. ']') then it is used
as a sample expression rule (see section 7.3). This it useful to add some
less common information such as the client's SSL certificate's DN, or to log
the key that would be used to store an entry into a stick table. It is also
commonly used with non-log actions (header manipulation, variables etc).
Else if the item is named using an alpha-numerical name, it is an alias.
(Refer to the table below for the list of available aliases)
Items can take arguments using braces ('{}'), and multiple arguments are
separated by commas within the braces. Flags may be added or removed by
prefixing them with a '+' or '-' sign (see below for the list of available
flags).
Special alias "%o" may be used to propagate its flags to all other
logformat items on the same format string. This is particularly handy with
quoted ("Q") and escaped ("E") string formats.
Due to the original goal of custom log formats to be used for logging only,
there is a special case made of non-printable and unsafe characters (those
outside ASCII codes 32 to 126 plus a few other ones) depending where they are
@ -25939,7 +25945,7 @@ Note: when using the RFC5424 syslog message format, the characters '"',
https://tools.ietf.org/html/rfc5424#section-6.3.3 for more details). In
such cases, the use of the flag "E" should be considered.
Flags are :
Supported item flags are (may be enabled/disabled from item's arguments):
* Q: quote a string
* X: hexadecimal representation (IPs, Ports, %Ts, %rt, %pid)
* E: escape characters '"', '\' and ']' in a string with '\' as prefix
@ -25951,14 +25957,14 @@ Flags are :
don't expect. Thus it is mainly intended for use with set-var-fmt,
rings and binary-capable log endpoints.
This option can only be set globally (with %o), it will be ignored
if set on an individual node's options.
if set on an individual item's options.
* json: automatically encode value in JSON format
(when set globally, only named format variables are considered)
(when set globally, only named logformat items are considered)
Incomplete numerical values (e.g.: '%B' when logasap is used),
which are normally prefixed with '+' without encoding, will be
encoded as-is. Also, '+E' option will be ignored.
* cbor: automatically encode value in CBOR format
(when set globally, only named format variables are considered)
(when set globally, only named logformat items are considered)
By default, cbor encoded data is represented in HEX form so
that it remains printable on stdout an can be used with usual
syslog endpoints.
@ -25979,13 +25985,13 @@ Flags are :
log-format "%{+json}o %(request)r %(custom_expr)[str(custom)]"
log-format "%{+cbor}o %(request)r %(custom_expr)[str(custom)]"
Please refer to the table below for currently defined variables :
Please refer to the table below for currently defined aliases :
+---+------+------------------------------------------------------+---------+
| R | var | field name (8.2.2 and 8.2.3 for description) | type |
| R | alias| field name (8.2.2 and 8.2.3 for description) | type |
| | | sample fetch alternative | |
+===+======+======================================================+=========+
| | %o | special variable, apply flags on all next var | |
| | %o | special, apply flags on all following items | |
+---+------+------------------------------------------------------+---------+
| date formats |
+---+------+------------------------------------------------------+---------+
@ -26290,7 +26296,7 @@ Timings events in TCP mode:
all request to calculate the amortized value. The second and subsequent
request will always report zero here.
This timer is named %Th as a log-format tag, and fc.timer.handshake as a
This timer is named %Th as a log-format alias, and fc.timer.handshake as a
sample fetch.
- Ti: is the idle time before the HTTP request (HTTP mode only). This timer
@ -26303,7 +26309,7 @@ Timings events in TCP mode:
pending until they need it. This delay will be reported as the idle time. A
value of -1 indicates that nothing was received on the connection.
This timer is named %Ti as a log-format tag, and req.timer.idle as a
This timer is named %Ti as a log-format alias, and req.timer.idle as a
sample fetch.
- TR: total time to get the client request (HTTP mode only). It's the time
@ -26314,7 +26320,7 @@ Timings events in TCP mode:
since most requests fit in a single packet. A large time may indicate a
request typed by hand during a test.
This timer is named %TR as a log-format tag, and req.timer.hdr as a
This timer is named %TR as a log-format alias, and req.timer.hdr as a
sample fetch.
- Tq: total time to get the client request from the accept date or since the
@ -26325,7 +26331,7 @@ Timings events in TCP mode:
it in favor of TR nowadays, as the idle time adds a lot of noise to the
reports.
This timer is named %Tq as a log-format tag, and req.timer.tq as a
This timer is named %Tq as a log-format alias, and req.timer.tq as a
sample fetch.
- Tw: total time spent in the queues waiting for a connection slot. It
@ -26334,7 +26340,7 @@ Timings events in TCP mode:
requests. The value "-1" means that the request was killed before reaching
the queue, which is generally what happens with invalid or denied requests.
This timer is named %Tw as a log-format tag, and req.timer.queue as a
This timer is named %Tw as a log-format alias, and req.timer.queue as a
sample fetch.
- Tc: total time to establish the TCP connection to the server. It's the time
@ -26343,7 +26349,7 @@ Timings events in TCP mode:
the matching SYN/ACK packet in return. The value "-1" means that the
connection never established.
This timer is named %Tc as a log-format tag, and bc.timer.connect as a
This timer is named %Tc as a log-format alias, and bc.timer.connect as a
sample fetch.
- Tr: server response time (HTTP mode only). It's the time elapsed between
@ -26358,7 +26364,7 @@ Timings events in TCP mode:
header (empty line) was never seen, most likely because the server timeout
stroke before the server managed to process the request.
This timer is named %Tr as a log-format tag, and res.timer.hdr as a
This timer is named %Tr as a log-format alias, and res.timer.hdr as a
sample fetch.
- Td: this is the total transfer time of the response payload till the last
@ -26368,7 +26374,7 @@ Timings events in TCP mode:
The data sent are not guaranteed to be received by the client, they can be
stuck in either the kernel or the network.
This timer is named %Td as a log-format tag, and res.timer.data as a
This timer is named %Td as a log-format alias, and res.timer.data as a
sample fetch.
- Ta: total active time for the HTTP request, between the moment the proxy
@ -26383,7 +26389,7 @@ Timings events in TCP mode:
Timers with "-1" values have to be excluded from this equation. Note that
"Ta" can never be negative.
This timer is named %Ta as a log-format tag, and txn.timer.total as a
This timer is named %Ta as a log-format alias, and txn.timer.total as a
sample fetch.
- Tt: total stream duration time, between the moment the proxy accepted it
@ -26398,7 +26404,7 @@ Timings events in TCP mode:
mode, "Ti", "Tq" and "Tr" have to be excluded too. Note that "Tt" can never
be negative and that for HTTP, Tt is simply equal to (Th+Ti+Ta).
This timer is named %Tt as a log-format tag, and fc.timer.total as a
This timer is named %Tt as a log-format alias, and fc.timer.total as a
sample fetch.
- Tu: total estimated time as seen from client, between the moment the proxy
@ -26410,7 +26416,7 @@ Timings events in TCP mode:
option is specified. In this case, it only equals (Th+TR+Tw+Tc+Tr), and is
prefixed with a '+' sign.
This timer is named %Tu as a log-format tag, and txn.timer.user as a
This timer is named %Tu as a log-format alias, and txn.timer.user as a
sample fetch.
These timers provide precious indications on trouble causes. Since the TCP

View File

@ -131,7 +131,7 @@ enum {
LOG_FMT_TEXT = 0, /* raw text */
LOG_FMT_EXPR, /* sample expression */
LOG_FMT_SEPARATOR, /* separator replaced by one space */
LOG_FMT_TAG, /* reference to logformat_tag */
LOG_FMT_ALIAS, /* reference to logformat_alias */
};
/* enum for parse_logformat_string */
@ -139,8 +139,8 @@ enum {
LF_INIT = 0, // before first character
LF_TEXT, // normal text
LF_SEPARATOR, // a single separator
LF_TAG, // tag name, after '%' or '%{..}'
LF_STARTTAG, // % in text
LF_ALIAS, // alias name, after '%' or '%{..}'
LF_STARTALIAS, // % in text
LF_STONAME, // after '%(' and before ')'
LF_STOTYPE, // after ':' while in STONAME
LF_EDONAME, // ')' after '%('
@ -151,11 +151,11 @@ enum {
LF_END, // \0 found
};
/* log_format tags (ie: %tag), see logformat_tags table in log.c for
* available tags definitions
/* log_format aliases (ie: %alias), see logformat_aliases table in log.c for
* available aliases definitions
*/
struct logformat_node; // forward-declaration
struct logformat_tag {
struct logformat_alias {
char *name;
int type;
int mode;
@ -171,7 +171,7 @@ struct logformat_node {
char *name; // printable name for output types that require named fields (ie: json)
char *arg; // text for LOG_FMT_TEXT, arg for others
void *expr; // for use with LOG_FMT_EXPR
const struct logformat_tag *tag; // set if ->type == LOG_FMT_TAG
const struct logformat_alias *alias; // set if ->type == LOG_FMT_ALIAS
};
enum lf_expr_flags {

View File

@ -102,8 +102,7 @@ ssize_t syslog_applet_append_event(void *ctx, struct ist v1, struct ist v2, size
/*
* Parse the log_format string and fill a linked list.
* Tag name are preceded by % and composed by characters [a-zA-Z0-9]* : %tagname
* You can set arguments using { } : %{many arguments}tagname
* Refer to source file for details
*/
int parse_logformat_string(const char *str, struct proxy *curproxy, struct lf_expr *lf_expr, int options, int cap, char **err);

152
src/log.c
View File

@ -124,8 +124,8 @@ const struct buffer empty = { };
int prepare_addrsource(struct logformat_node *node, struct proxy *curproxy);
/* logformat tag types (internal use) */
enum logformat_tag_type {
/* logformat alias types (internal use) */
enum logformat_alias_type {
LOG_FMT_GLOBAL,
LOG_FMT_CLIENTIP,
LOG_FMT_CLIENTPORT,
@ -192,8 +192,8 @@ enum logformat_tag_type {
LOG_FMT_SSL_VERSION,
};
/* log_format tag names */
static const struct logformat_tag logformat_tags[] = {
/* log_format alias names */
static const struct logformat_alias logformat_aliases[] = {
{ "o", LOG_FMT_GLOBAL, PR_MODE_TCP, 0, NULL }, /* global option */
/* please keep these lines sorted ! */
@ -318,12 +318,12 @@ THREAD_LOCAL char *logline = NULL;
*/
THREAD_LOCAL char *logline_rfc5424 = NULL;
struct logformat_tag_args {
struct logformat_node_args {
char *name;
int mask;
};
struct logformat_tag_args tag_args_list[] = {
struct logformat_node_args node_args_list[] = {
// global
{ "M", LOG_OPT_MANDATORY },
{ "Q", LOG_OPT_QUOTE },
@ -349,10 +349,10 @@ int prepare_addrsource(struct logformat_node *node, struct proxy *curproxy)
/*
* Parse args in a logformat_tag. Returns 0 in error
* Parse args in a logformat_node. Returns 0 in error
* case, otherwise, it returns 1.
*/
int parse_logformat_tag_args(char *args, struct logformat_node *node, char **err)
int parse_logformat_node_args(char *args, struct logformat_node *node, char **err)
{
int i = 0;
int end = 0;
@ -360,7 +360,7 @@ int parse_logformat_tag_args(char *args, struct logformat_node *node, char **err
char *sp = NULL; // start pointer
if (args == NULL) {
memprintf(err, "internal error: parse_logformat_tag_args() expects non null 'args'");
memprintf(err, "internal error: parse_logformat_node_args() expects non null 'args'");
return 0;
}
@ -381,19 +381,19 @@ int parse_logformat_tag_args(char *args, struct logformat_node *node, char **err
if (*args == '\0' || *args == ',') {
*args = '\0';
for (i = 0; sp && tag_args_list[i].name; i++) {
if (strcmp(sp, tag_args_list[i].name) == 0) {
for (i = 0; sp && node_args_list[i].name; i++) {
if (strcmp(sp, node_args_list[i].name) == 0) {
if (flags == 1) {
/* Ensure we don't mix encoding types, existing
* encoding type prevails over new ones
*/
if (node->options & LOG_OPT_ENCODE)
node->options |= (tag_args_list[i].mask & ~LOG_OPT_ENCODE);
node->options |= (node_args_list[i].mask & ~LOG_OPT_ENCODE);
else
node->options |= tag_args_list[i].mask;
node->options |= node_args_list[i].mask;
break;
} else if (flags == 2) {
node->options &= ~tag_args_list[i].mask;
node->options &= ~node_args_list[i].mask;
break;
}
}
@ -408,40 +408,40 @@ int parse_logformat_tag_args(char *args, struct logformat_node *node, char **err
}
/*
* Parse a tag '%tagname' or '%{args}tagname' in log-format. The caller
* Parse an alias '%aliasname' or '%{args}aliasname' in log-format. The caller
* must pass the args part in the <arg> pointer with its length in <arg_len>,
* and tagname with its length in <tag> and <tag_len> respectively. <arg> is
* ignored when arg_len is 0. Neither <tag> nor <tag_len> may be null.
* and aliasname with its length in <alias> and <alias_len> respectively. <arg>
* is ignored when arg_len is 0. Neither <alias> nor <alias_len> may be null.
* Returns false in error case and err is filled, otherwise returns true.
*/
static int parse_logformat_tag(char *arg, int arg_len, char *name, int name_len, int typecast,
char *tag, int tag_len, struct lf_expr *lf_expr,
int *defoptions, char **err)
static int parse_logformat_alias(char *arg, int arg_len, char *name, int name_len, int typecast,
char *alias, int alias_len, struct lf_expr *lf_expr,
int *defoptions, char **err)
{
int j;
struct list *list_format= &lf_expr->nodes.list;
struct logformat_node *node = NULL;
for (j = 0; logformat_tags[j].name; j++) { // search a log type
if (strlen(logformat_tags[j].name) == tag_len &&
strncmp(tag, logformat_tags[j].name, tag_len) == 0) {
for (j = 0; logformat_aliases[j].name; j++) { // search a log type
if (strlen(logformat_aliases[j].name) == alias_len &&
strncmp(alias, logformat_aliases[j].name, alias_len) == 0) {
node = calloc(1, sizeof(*node));
if (!node) {
memprintf(err, "out of memory error");
goto error_free;
}
node->type = LOG_FMT_TAG;
node->tag = &logformat_tags[j];
node->type = LOG_FMT_ALIAS;
node->alias = &logformat_aliases[j];
node->typecast = typecast;
if (name && name_len)
node->name = my_strndup(name, name_len);
node->options = *defoptions;
if (arg_len) {
node->arg = my_strndup(arg, arg_len);
if (!parse_logformat_tag_args(node->arg, node, err))
if (!parse_logformat_node_args(node->arg, node, err))
goto error_free;
}
if (node->tag->type == LOG_FMT_GLOBAL) {
if (node->alias->type == LOG_FMT_GLOBAL) {
*defoptions = node->options;
if (lf_expr->nodes.options == LOG_OPT_NONE)
lf_expr->nodes.options = node->options;
@ -466,10 +466,10 @@ static int parse_logformat_tag(char *arg, int arg_len, char *name, int name_len,
}
}
j = tag[tag_len];
tag[tag_len] = 0;
memprintf(err, "no such format tag '%s'. If you wanted to emit the '%%' character verbatim, you need to use '%%%%'", tag);
tag[tag_len] = j;
j = alias[alias_len];
alias[alias_len] = 0;
memprintf(err, "no such format alias '%s'. If you wanted to emit the '%%' character verbatim, you need to use '%%%%'", alias);
alias[alias_len] = j;
error_free:
free_logformat_node(node);
@ -560,7 +560,7 @@ static int add_sample_to_logformat_list(char *text, char *name, int name_len, in
if (arg_len) {
node->arg = my_strndup(arg, arg_len);
if (!parse_logformat_tag_args(node->arg, node, err))
if (!parse_logformat_node_args(node->arg, node, err))
goto error_free;
}
if (expr->fetch->val & cap & SMP_VAL_REQUEST)
@ -591,8 +591,10 @@ static int add_sample_to_logformat_list(char *text, char *name, int name_len, in
/*
* Compile logformat expression (from string to list of logformat nodes)
*
* Tag name are preceded by % and composed by characters [a-zA-Z0-9]* : %tagname
* You can set arguments using { } : %{many arguments}tagname.
* Aliases are preceded by % and composed by characters [a-zA-Z0-9]* : %aliasname
* Expressions are preceded by % and enclosed in square brackets: %[expr]
* You can set arguments using { } : %{many arguments}aliasname
* %{many arguments}[expr]
*
* lf_expr: the destination logformat expression (logformat_node list)
* which is supposed to be configured (str and conf set) but
@ -610,11 +612,11 @@ int lf_expr_compile(struct lf_expr *lf_expr,
char *fmt = lf_expr->str; /* will be freed unless default */
char *sp, *str, *backfmt; /* start pointer for text parts */
char *arg = NULL; /* start pointer for args */
char *tag = NULL; /* start pointer for tags */
char *alias = NULL; /* start pointer for aliases */
char *name = NULL; /* token name (optional) */
char *typecast_str = NULL; /* token output type (if custom name is set) */
int arg_len = 0;
int tag_len = 0;
int alias_len = 0;
int name_len = 0;
int typecast = SMP_T_SAME; /* relaxed by default */
int cformat; /* current token format */
@ -653,18 +655,18 @@ int lf_expr_compile(struct lf_expr *lf_expr,
* We use the common LF_INIT state to dispatch to the different final states.
*/
switch (pformat) {
case LF_STARTTAG: // text immediately following a '%'
arg = NULL; tag = NULL;
case LF_STARTALIAS: // text immediately following a '%'
arg = NULL; alias = NULL;
name = NULL;
name_len = 0;
typecast = SMP_T_SAME;
arg_len = tag_len = 0;
arg_len = alias_len = 0;
if (*str == '(') { // custom output name
cformat = LF_STONAME;
name = str + 1;
}
else
goto starttag;
goto startalias;
break;
case LF_STONAME: // text immediately following '%('
@ -697,18 +699,18 @@ int lf_expr_compile(struct lf_expr *lf_expr,
break;
case LF_EDONAME: // text immediately following %(name)
starttag:
startalias:
if (*str == '{') { // optional argument
cformat = LF_STARG;
arg = str + 1;
}
else if (*str == '[') {
cformat = LF_STEXPR;
tag = str + 1; // store expr in tag name
alias = str + 1; // store expr in alias name
}
else if (isalpha((unsigned char)*str)) { // tag name
cformat = LF_TAG;
tag = str;
else if (isalpha((unsigned char)*str)) { // alias name
cformat = LF_ALIAS;
alias = str;
}
else if (*str == '%')
cformat = LF_TEXT; // convert this character to a literal (useful for '%')
@ -717,7 +719,7 @@ int lf_expr_compile(struct lf_expr *lf_expr,
cformat = LF_TEXT;
pformat = LF_TEXT; /* finally we include the previous char as well */
sp = str - 1; /* send both the '%' and the current char */
memprintf(err, "unexpected tag name near '%c' at position %d line : '%s'. Maybe you want to write a single '%%', use the syntax '%%%%'",
memprintf(err, "unexpected alias name near '%c' at position %d line : '%s'. Maybe you want to write a single '%%', use the syntax '%%%%'",
*str, (int)(str - backfmt), fmt);
goto fail;
@ -737,15 +739,15 @@ int lf_expr_compile(struct lf_expr *lf_expr,
case LF_EDARG: // text immediately following '%{arg}'
if (*str == '[') {
cformat = LF_STEXPR;
tag = str + 1; // store expr in tag name
alias = str + 1; // store expr in alias name
break;
}
else if (isalnum((unsigned char)*str)) { // tag name
cformat = LF_TAG;
tag = str;
else if (isalnum((unsigned char)*str)) { // alias name
cformat = LF_ALIAS;
alias = str;
break;
}
memprintf(err, "parse argument modifier without tag name near '%%{%s}'", arg);
memprintf(err, "parse argument modifier without alias name near '%%{%s}'", arg);
goto fail;
case LF_STEXPR: // text immediately following '%['
@ -754,7 +756,7 @@ int lf_expr_compile(struct lf_expr *lf_expr,
* part of the expression, which MUST be the trailing
* angle bracket.
*/
if (!add_sample_to_logformat_list(tag, name, name_len, typecast, arg, arg_len, lf_expr, al, options, cap, err, &str))
if (!add_sample_to_logformat_list(alias, name, name_len, typecast, arg, arg_len, lf_expr, al, options, cap, err, &str))
goto fail;
if (*str == ']') {
@ -766,26 +768,26 @@ int lf_expr_compile(struct lf_expr *lf_expr,
char c = *str;
*str = 0;
if (isprint((unsigned char)c))
memprintf(err, "expected ']' after '%s', but found '%c'", tag, c);
memprintf(err, "expected ']' after '%s', but found '%c'", alias, c);
else
memprintf(err, "missing ']' after '%s'", tag);
memprintf(err, "missing ']' after '%s'", alias);
goto fail;
}
break;
case LF_TAG: // text part of a tag name
tag_len = str - tag;
case LF_ALIAS: // text part of a alias name
alias_len = str - alias;
if (!isalnum((unsigned char)*str))
cformat = LF_INIT; // not tag name anymore
cformat = LF_INIT; // not alias name anymore
break;
default: // LF_INIT, LF_TEXT, LF_SEPARATOR, LF_END, LF_EDEXPR
cformat = LF_INIT;
}
if (cformat == LF_INIT) { /* resynchronize state to text/sep/starttag */
if (cformat == LF_INIT) { /* resynchronize state to text/sep/startalias */
switch (*str) {
case '%': cformat = LF_STARTTAG; break;
case '%': cformat = LF_STARTALIAS; break;
case 0 : cformat = LF_END; break;
case ' ':
if (options & LOG_OPT_MERGE_SPACES) {
@ -799,8 +801,8 @@ int lf_expr_compile(struct lf_expr *lf_expr,
if (cformat != pformat || pformat == LF_SEPARATOR) {
switch (pformat) {
case LF_TAG:
if (!parse_logformat_tag(arg, arg_len, name, name_len, typecast, tag, tag_len, lf_expr, &options, err))
case LF_ALIAS:
if (!parse_logformat_alias(arg, arg_len, name, name_len, typecast, alias, alias_len, lf_expr, &options, err))
goto fail;
break;
case LF_TEXT:
@ -813,8 +815,8 @@ int lf_expr_compile(struct lf_expr *lf_expr,
}
}
if (pformat == LF_STARTTAG || pformat == LF_STARG || pformat == LF_STEXPR || pformat == LF_STONAME || pformat == LF_STOTYPE || pformat == LF_EDONAME) {
memprintf(err, "truncated line after '%s'", tag ? tag : arg ? arg : "%");
if (pformat == LF_STARTALIAS || pformat == LF_STARG || pformat == LF_STEXPR || pformat == LF_STONAME || pformat == LF_STOTYPE || pformat == LF_EDONAME) {
memprintf(err, "truncated line after '%s'", alias ? alias : arg ? arg : "%");
goto fail;
}
logformat_str_free(&fmt);
@ -984,20 +986,20 @@ int lf_expr_postcheck(struct lf_expr *lf_expr, struct proxy *px, char **err)
if (px->http_needed)
px->to_log |= LW_REQ;
}
else if (lf->type == LOG_FMT_TAG) {
if (lf->tag->mode == PR_MODE_HTTP && px->mode != PR_MODE_HTTP) {
memprintf(err, "format tag '%s' is reserved for HTTP mode",
lf->tag->name);
else if (lf->type == LOG_FMT_ALIAS) {
if (lf->alias->mode == PR_MODE_HTTP && px->mode != PR_MODE_HTTP) {
memprintf(err, "format alias '%s' is reserved for HTTP mode",
lf->alias->name);
goto fail;
}
if (lf->tag->config_callback &&
!lf->tag->config_callback(lf, px)) {
memprintf(err, "cannot configure format tag '%s' in this context",
lf->tag->name);
if (lf->alias->config_callback &&
!lf->alias->config_callback(lf, px)) {
memprintf(err, "cannot configure format alias '%s' in this context",
lf->alias->name);
goto fail;
}
if (!(px->flags & PR_FL_CHECKED))
px->to_log |= lf->tag->lw;
px->to_log |= lf->alias->lw;
}
next_node:
/* postcheck individual node's options */
@ -3854,10 +3856,10 @@ int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t
goto next_fmt;
}
BUG_ON(tmp->type != LOG_FMT_TAG);
BUG_ON(tmp->type != LOG_FMT_ALIAS);
/* logformat tag */
switch (tmp->tag->type) {
/* logformat alias */
switch (tmp->alias->type) {
case LOG_FMT_CLIENTIP: // %ci
addr = (s ? sc_src(s->scf) : sess_src(sess));
if (addr)