mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-21 22:01:31 +02:00
MINOR: log: introduce extra log profile steps
add a way to register additional log origins using log_origin_register() that may be used as log profile steps from log profile sections. For now this does nothing as no extra origins are registered and extra log origins are not yet considered for runtime logging paths. When specifying an extra logging step for on <step> under log-profile section, the logging step is stored within a binary tree for efficient lookup during runtime. No performance impact should be expected if extra log origins are not being used, and slight performance impact if extra log origins are used. Don't forget to update the documentation when new log origins are added (both %OG log alias and on <step> log-profile keyword are concerned.
This commit is contained in:
parent
facf259d88
commit
818475c5cc
@ -270,6 +270,21 @@ enum log_orig {
|
||||
LOG_ORIG_TXN_CONNECT, /* during stream connect handling */
|
||||
LOG_ORIG_TXN_RESPONSE, /* during stream response handling */
|
||||
LOG_ORIG_TXN_CLOSE, /* during stream termination */
|
||||
LOG_ORIG_EXTRA, /* end of hard-coded/legacy log origins,
|
||||
* beginning of extra ones. 1 extra orig
|
||||
* = 1 logging step
|
||||
*/
|
||||
LOG_ORIG_MAX = 0xFFFF, /* max log origin number (65k) */
|
||||
};
|
||||
|
||||
/* max number of extra log origins */
|
||||
#define LOG_ORIG_EXTRA_SLOTS LOG_ORIG_MAX - LOG_ORIG_EXTRA
|
||||
|
||||
/* used to register extra log origins */
|
||||
struct log_origin_node {
|
||||
struct list list; /* per-name lookup during config */
|
||||
const char *name;
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
/* log profile step flags */
|
||||
@ -284,6 +299,12 @@ struct log_profile_step {
|
||||
enum log_ps_flags flags; /* LOG_PS_FL_* */
|
||||
};
|
||||
|
||||
struct log_profile_step_extra {
|
||||
struct log_profile_step step;
|
||||
struct eb32_node node;
|
||||
struct log_origin_node *orig; // reference to log_origin config node
|
||||
};
|
||||
|
||||
struct log_profile {
|
||||
struct list list;
|
||||
struct {
|
||||
@ -299,6 +320,7 @@ struct log_profile {
|
||||
struct log_profile_step *close;
|
||||
struct log_profile_step *error; // override error-log-format
|
||||
struct log_profile_step *any; // override log-format
|
||||
struct eb_root extra; // extra log profile steps (if any)
|
||||
};
|
||||
|
||||
#endif /* _HAPROXY_LOG_T_H */
|
||||
|
@ -136,6 +136,7 @@ struct logger *dup_logger(struct logger *def);
|
||||
void free_logger(struct logger *logger);
|
||||
void deinit_log_target(struct log_target *target);
|
||||
struct log_profile *log_profile_find_by_name(const char *name);
|
||||
enum log_orig log_orig_register(const char *name);
|
||||
|
||||
/* Parse "log" keyword and update the linked list. */
|
||||
int parse_logger(char **args, struct list *loggers, int do_del, const char *file, int linenum, char **err);
|
||||
|
151
src/log.c
151
src/log.c
@ -89,6 +89,9 @@ static const struct log_fmt_st log_formats[LOG_FORMATS] = {
|
||||
},
|
||||
};
|
||||
|
||||
/* list of extra log origins */
|
||||
static struct list log_origins = LIST_HEAD_INIT(log_origins);
|
||||
|
||||
/* get human readable representation for log_orig enum members */
|
||||
const char *log_orig_to_str(enum log_orig orig)
|
||||
{
|
||||
@ -6090,13 +6093,18 @@ static inline void log_profile_step_init(struct log_profile_step *lprof_step)
|
||||
lprof_step->flags = LOG_PS_FL_NONE;
|
||||
}
|
||||
|
||||
static inline void log_profile_step_free(struct log_profile_step *lprof_step)
|
||||
static inline void log_profile_step_deinit(struct log_profile_step *lprof_step)
|
||||
{
|
||||
if (!lprof_step)
|
||||
return;
|
||||
|
||||
lf_expr_deinit(&lprof_step->logformat);
|
||||
lf_expr_deinit(&lprof_step->logformat_sd);
|
||||
}
|
||||
|
||||
static inline void log_profile_step_free(struct log_profile_step *lprof_step)
|
||||
{
|
||||
log_profile_step_deinit(lprof_step);
|
||||
free(lprof_step);
|
||||
}
|
||||
|
||||
@ -6141,6 +6149,9 @@ static inline int log_profile_step_postcheck(struct proxy *px, const char *step_
|
||||
*/
|
||||
static int log_profile_postcheck(struct proxy *px, struct log_profile *prof, char **err)
|
||||
{
|
||||
struct eb32_node *node;
|
||||
struct log_profile_step_extra *extra;
|
||||
|
||||
/* log profile steps are only relevant under proxy
|
||||
* context
|
||||
*/
|
||||
@ -6157,11 +6168,23 @@ static int log_profile_postcheck(struct proxy *px, struct log_profile *prof, cha
|
||||
!log_profile_step_postcheck(px, "any", prof->any, err))
|
||||
return 0;
|
||||
|
||||
/* postcheck extra steps (if any) */
|
||||
node = eb32_first(&prof->extra);
|
||||
while (node) {
|
||||
extra = eb32_entry(node, struct log_profile_step_extra, node);
|
||||
node = eb32_next(node);
|
||||
if (!log_profile_step_postcheck(px, extra->orig->name, &extra->step, err))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void log_profile_free(struct log_profile *prof)
|
||||
{
|
||||
struct eb32_node *node;
|
||||
struct log_profile_step_extra *extra;
|
||||
|
||||
ha_free(&prof->id);
|
||||
ha_free(&prof->conf.file);
|
||||
chunk_destroy(&prof->log_tag);
|
||||
@ -6174,6 +6197,16 @@ static void log_profile_free(struct log_profile *prof)
|
||||
log_profile_step_free(prof->error);
|
||||
log_profile_step_free(prof->any);
|
||||
|
||||
/* free extra steps (if any) */
|
||||
node = eb32_first(&prof->extra);
|
||||
while (node) {
|
||||
extra = eb32_entry(node, struct log_profile_step_extra, node);
|
||||
node = eb32_next(node);
|
||||
eb32_delete(&extra->node);
|
||||
log_profile_step_deinit(&extra->step);
|
||||
free(extra);
|
||||
}
|
||||
|
||||
ha_free(&prof);
|
||||
}
|
||||
|
||||
@ -6247,6 +6280,7 @@ int cfg_parse_log_profile(const char *file, int linenum, char **args, int kwm)
|
||||
}
|
||||
prof->conf.file = strdup(file);
|
||||
prof->conf.line = linenum;
|
||||
prof->extra = EB_ROOT_UNIQUE;
|
||||
|
||||
/* add to list */
|
||||
LIST_APPEND(&log_profile_list, &prof->list);
|
||||
@ -6267,11 +6301,14 @@ int cfg_parse_log_profile(const char *file, int linenum, char **args, int kwm)
|
||||
}
|
||||
}
|
||||
else if (strcmp(args[0], "on") == 0) { /* log profile step */
|
||||
struct log_profile_step **target_step;
|
||||
struct log_profile_step **target_step = NULL;
|
||||
struct log_profile_step *extra_step;
|
||||
struct lf_expr *target_lf;
|
||||
int cur_arg;
|
||||
|
||||
/* get targeted log-profile step */
|
||||
/* get targeted log-profile step:
|
||||
* first try with native ones
|
||||
*/
|
||||
if (strcmp(args[1], "accept") == 0)
|
||||
target_step = &prof->accept;
|
||||
else if (strcmp(args[1], "request") == 0)
|
||||
@ -6287,9 +6324,50 @@ int cfg_parse_log_profile(const char *file, int linenum, char **args, int kwm)
|
||||
else if (strcmp(args[1], "any") == 0)
|
||||
target_step = &prof->any;
|
||||
else {
|
||||
ha_alert("parsing [%s:%d] : '%s' expects a log step.\n"
|
||||
"expected values are: 'accept', 'request', 'connect', 'response', 'close', 'error' or 'any'\n",
|
||||
file, linenum, args[0]);
|
||||
struct log_origin_node *cur;
|
||||
struct log_profile_step_extra *extra = NULL;
|
||||
|
||||
/* then try extra ones (if any) */
|
||||
list_for_each_entry(cur, &log_origins, list) {
|
||||
if (strcmp(args[1], cur->name) == 0) {
|
||||
/* found matching one */
|
||||
extra = malloc(sizeof(*extra));
|
||||
if (extra == NULL) {
|
||||
ha_alert("parsing [%s:%d]: cannot allocate memory for '%s %s'.\n", file, linenum, args[0], args[1]);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
log_profile_step_init(&extra->step);
|
||||
extra->orig = cur;
|
||||
extra->node.key = cur->id;
|
||||
eb32_insert(&prof->extra, &extra->node);
|
||||
extra_step = &extra->step;
|
||||
target_step = &extra_step;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (target_step == NULL) {
|
||||
char *extra_origins = NULL;
|
||||
struct log_origin_node *cur;
|
||||
|
||||
list_for_each_entry(cur, &log_origins, list) {
|
||||
if (extra_origins)
|
||||
memprintf(&extra_origins, "%s, '%s'", extra_origins, cur->name);
|
||||
else
|
||||
memprintf(&extra_origins, "'%s'", cur->name);
|
||||
}
|
||||
|
||||
memprintf(&errmsg, "'%s' expects a log step.\n"
|
||||
"expected values are: 'accept', 'request', 'connect', "
|
||||
"'response', 'close', 'error' or 'any'.",
|
||||
args[0]);
|
||||
if (extra_origins)
|
||||
memprintf(&errmsg, "%s\nOr one of the additional log steps: %s.", errmsg, extra_origins);
|
||||
free(extra_origins);
|
||||
|
||||
ha_alert("parsing [%s:%d]: %s\n", file, linenum, errmsg);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
@ -6368,6 +6446,66 @@ out:
|
||||
return err_code;
|
||||
}
|
||||
|
||||
/* suitable for use with INITCALL0(STG_PREPARE), may not be used anymore
|
||||
* once config parsing has started since it will depend on this.
|
||||
*
|
||||
* Returns the ID of the log origin on success and LOG_ORIG_UNSPEC on failure.
|
||||
* ID must be saved for later use (ie: inside static variable), in order
|
||||
* to use it as log origin during runtime.
|
||||
*
|
||||
* If the origin is already defined, the existing ID is returned.
|
||||
*
|
||||
* Don't forget to update the documentation when new log origins are added
|
||||
* (both %OG log alias and on <step> log-profile keyword are concerned)
|
||||
*/
|
||||
enum log_orig log_orig_register(const char *name)
|
||||
{
|
||||
struct log_origin_node *cur;
|
||||
size_t last = 0;
|
||||
|
||||
list_for_each_entry(cur, &log_origins, list) {
|
||||
if (strcmp(name, cur->name) == 0)
|
||||
return cur->id;
|
||||
last = cur->id;
|
||||
}
|
||||
/* not found, need to register new log origin */
|
||||
|
||||
if (last == LOG_ORIG_EXTRA_SLOTS) {
|
||||
ha_alert("Reached maximum number of log origins. Please report to developers if you see this message.\n");
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
cur = malloc(sizeof(*cur));
|
||||
if (cur == NULL)
|
||||
goto out_oom;
|
||||
|
||||
cur->id = LOG_ORIG_EXTRA + last;
|
||||
cur->name = strdup(name);
|
||||
if (!cur->name) {
|
||||
free(cur);
|
||||
goto out_oom;
|
||||
}
|
||||
LIST_APPEND(&log_origins, &cur->list);
|
||||
return cur->id;
|
||||
|
||||
out_oom:
|
||||
ha_alert("Failed to register additional log origin. Out of memory\n");
|
||||
out_error:
|
||||
return LOG_ORIG_UNSPEC;
|
||||
}
|
||||
|
||||
/* Deinitialize all extra log origins */
|
||||
static void deinit_log_origins()
|
||||
{
|
||||
struct log_origin_node *orig, *back;
|
||||
|
||||
list_for_each_entry_safe(orig, back, &log_origins, list) {
|
||||
LIST_DEL_INIT(&orig->list);
|
||||
free((char *)orig->name);
|
||||
free(orig);
|
||||
}
|
||||
}
|
||||
|
||||
/* function: post-resolve a single list of loggers
|
||||
*
|
||||
* Returns err_code which defaults to ERR_NONE and can be set to a combination
|
||||
@ -6439,6 +6577,7 @@ REGISTER_PER_THREAD_FREE(deinit_log_buffers);
|
||||
|
||||
REGISTER_POST_DEINIT(deinit_log_forward);
|
||||
REGISTER_POST_DEINIT(deinit_log_profiles);
|
||||
REGISTER_POST_DEINIT(deinit_log_origins);
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
|
Loading…
x
Reference in New Issue
Block a user