mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-25 06:02:08 +00:00
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 in739c4e5b1e
("MINOR: sample: accept_date / request_date return %Ts / %tr timestamp values") and454c372b60
("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 in723b73ad75
("MINOR: config: Parse the string of the log-format config keyword") and later documented in4894040fa
("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 withffc3fcd6d
("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:
parent
7e943cdf27
commit
435a9da267
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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
152
src/log.c
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user