From: Aurelien DARRAGON Date: Thu, 24 Aug 2023 18:46:12 +0000 (+0200) Subject: MEDIUM: log/sink: simplify log header handling X-Git-Tag: v2.9-dev8~65 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6dad0549a5261757efd34b002120afdcc55d2fa5;p=thirdparty%2Fhaproxy.git MEDIUM: log/sink: simplify log header handling Introduce log_header struct to easily pass log header data between functions and use that to simplify the logic around log header handling. While at it, some outdated comments were updated as well. No change in behavior should be expected. --- diff --git a/include/haproxy/log-t.h b/include/haproxy/log-t.h index b8a46fd951..36d9c19ec0 100644 --- a/include/haproxy/log-t.h +++ b/include/haproxy/log-t.h @@ -97,6 +97,20 @@ enum log_meta { LOG_META_FIELDS /* must always be the last */ }; +/* log header data */ +struct log_header { + enum log_fmt format; /* how to format the header */ + int level, facility; /* used by several formats */ + struct ist *metadata; /* optional metadata - per-format */ +}; + +#define LOG_HEADER_NONE (struct log_header){ \ + .format = LOG_FORMAT_UNSPEC, \ + .level = 0, \ + .facility = 0, \ + .metadata = NULL \ + } + /* log target types */ enum log_tgt { LOG_TARGET_DGRAM = 0, // datagram address (udp, unix socket) diff --git a/include/haproxy/log.h b/include/haproxy/log.h index d34f482b67..497b486eeb 100644 --- a/include/haproxy/log.h +++ b/include/haproxy/log.h @@ -163,7 +163,7 @@ static inline int build_logline(struct stream *s, char *dst, size_t maxsize, str return sess_build_logline(strm_sess(s), s, dst, maxsize, list_format); } -struct ist *build_log_header(enum log_fmt format, int level, int facility, struct ist *metadata, size_t *nbelem); +struct ist *build_log_header(struct log_header hdr, size_t *nbelem); /* * lookup log forward proxy by name diff --git a/include/haproxy/sink.h b/include/haproxy/sink.h index 19f2df912d..bed687fe3c 100644 --- a/include/haproxy/sink.h +++ b/include/haproxy/sink.h @@ -32,22 +32,24 @@ extern struct proxy *sink_proxies_list; struct sink *sink_find(const char *name); struct sink *sink_new_fd(const char *name, const char *desc, enum log_fmt, int fd); -ssize_t __sink_write(struct sink *sink, size_t maxlen, - const struct ist msg[], size_t nmsg, - int level, int facility, struct ist * metadata); -int sink_announce_dropped(struct sink *sink, int facility); +ssize_t __sink_write(struct sink *sink, struct log_header hdr, size_t maxlen, + const struct ist msg[], size_t nmsg); +int sink_announce_dropped(struct sink *sink, struct log_header hdr); -/* tries to send message parts (up to 8, ignored above) from message - * array to sink . Formatting according to the sink's preference is - * done here. Lost messages are accounted for in the sink's counter. If there +/* tries to send message parts from message array to sink . + * Formatting according to the sink's preferences is done here. + * + * It will stop writing at instead of sink->maxlen if is + * positive and inferior to sink->maxlen. + * + * Lost messages are accounted for in the sink's counter. If there * were lost messages, an attempt is first made to indicate it. * The function returns the number of Bytes effectively sent or announced. * or <= 0 in other cases. */ -static inline ssize_t sink_write(struct sink *sink, size_t maxlen, - const struct ist msg[], size_t nmsg, - int level, int facility, struct ist *metadata) +static inline ssize_t sink_write(struct sink *sink, struct log_header hdr, + size_t maxlen, const struct ist msg[], size_t nmsg) { ssize_t sent; @@ -59,7 +61,7 @@ static inline ssize_t sink_write(struct sink *sink, size_t maxlen, * position. */ HA_RWLOCK_WRLOCK(RING_LOCK, &sink->ctx.lock); - sent = sink_announce_dropped(sink, facility); + sent = sink_announce_dropped(sink, hdr); HA_RWLOCK_WRUNLOCK(RING_LOCK, &sink->ctx.lock); if (!sent) { @@ -71,7 +73,7 @@ static inline ssize_t sink_write(struct sink *sink, size_t maxlen, } HA_RWLOCK_RDLOCK(RING_LOCK, &sink->ctx.lock); - sent = __sink_write(sink, maxlen, msg, nmsg, level, facility, metadata); + sent = __sink_write(sink, hdr, maxlen, msg, nmsg); HA_RWLOCK_RDUNLOCK(RING_LOCK, &sink->ctx.lock); fail: diff --git a/src/log.c b/src/log.c index 3a1341020e..efe1d5b754 100644 --- a/src/log.c +++ b/src/log.c @@ -1435,18 +1435,18 @@ void send_log(struct proxy *p, int level, const char *format, ...) logline, data_len, default_rfc5424_sd_log_format, 2); } /* - * This function builds a log header of given format using given - * metadata, if format is set to LOF_FORMAT_UNSPEC, it tries - * to determine format based on given metadas. It is useful - * for log-forwarding to be able to forward any format without - * settings. + * This function builds a log header according to settings. + * + * If hdr.format is set to LOG_FORMAT_UNSPEC, it tries to determine + * format based on hdr.metadata. It is useful for log-forwarding to be + * able to forward any format without settings. + * * This function returns a struct ist array of elements of the header * nbelem is set to the number of available elements. * This function returns currently a maximum of NB_LOG_HDR_IST_ELEMENTS * elements. */ -struct ist *build_log_header(enum log_fmt format, int level, int facility, - struct ist *metadata, size_t *nbelem) +struct ist *build_log_header(struct log_header hdr, size_t *nbelem) { static THREAD_LOCAL struct { struct ist ist_vector[NB_LOG_HDR_MAX_ELEMENTS]; @@ -1459,6 +1459,10 @@ struct ist *build_log_header(enum log_fmt format, int level, int facility, int len; int fac_level = 0; time_t time = date.tv_sec; + struct ist *metadata = hdr.metadata; + enum log_fmt format = hdr.format; + int facility = hdr.facility; + int level = hdr.level; *nbelem = 0; @@ -1740,18 +1744,16 @@ struct ist *build_log_header(enum log_fmt format, int level, int facility, /* * This function sends a syslog message. * is the actual log target where log will be sent, - * The argument MUST be an array of size - * LOG_META_FIELDS*sizeof(struct ist) containing data to build the header. - * It overrides the last byte of the message vector with an LF character. * + * Message will be prefixed by header according to setting. * Final message will be truncated parameter and will be * terminated with an LF character. * * Does not return any error */ -static inline void __do_send_log(struct log_target *target, enum log_fmt format, +static inline void __do_send_log(struct log_target *target, struct log_header hdr, int nblogger, size_t maxlen, - int level, int facility, struct ist *metadata, char *message, size_t size) + char *message, size_t size) { static THREAD_LOCAL struct iovec iovec[NB_LOG_HDR_MAX_ELEMENTS+1+1] = { }; /* header elements + message + LF */ static THREAD_LOCAL struct msghdr msghdr = { @@ -1807,7 +1809,7 @@ static inline void __do_send_log(struct log_target *target, enum log_fmt format, } } - msg_header = build_log_header(format, level, facility, metadata, &nbelem); + msg_header = build_log_header(hdr, &nbelem); send: if (target->type == LOG_TARGET_BUFFER) { struct ist msg; @@ -1820,7 +1822,7 @@ static inline void __do_send_log(struct log_target *target, enum log_fmt format, */ e_maxlen -= 1; - sent = sink_write(target->sink, e_maxlen, &msg, 1, level, facility, metadata); + sent = sink_write(target->sink, hdr, e_maxlen, &msg, 1); } else if (target->addr->ss_family == AF_CUST_EXISTING_FD) { struct ist msg; @@ -1922,11 +1924,15 @@ void process_send_log(struct list *loggers, int level, int facility, } while (!_HA_ATOMIC_CAS(&logger->lb.curr_rg_idx, &curr_rg_idx, next_rg_idx) && __ha_cpu_relax()); } - if (in_range) - __do_send_log(&logger->target, logger->format, ++nblogger, logger->maxlen, - MAX(level, logger->minlvl), - (facility == -1) ? logger->facility : facility, - metadata, message, size); + if (in_range) { + struct log_header hdr; + + hdr.level = MAX(level, logger->minlvl); + hdr.facility = (facility == -1) ? logger->facility : facility; + hdr.format = logger->format; + hdr.metadata = metadata; + __do_send_log(&logger->target, hdr, ++nblogger, logger->maxlen, message, size); + } } } diff --git a/src/sample.c b/src/sample.c index 57cb7c6f82..65985e32b8 100644 --- a/src/sample.c +++ b/src/sample.c @@ -1761,7 +1761,7 @@ static int sample_conv_debug(const struct arg *arg_p, struct sample *smp, void * done: line = ist2(buf->area, buf->data); - sink_write(sink, 0, &line, 1, 0, 0, NULL); + sink_write(sink, LOG_HEADER_NONE, 0, &line, 1); end: free_trash_chunk(buf); return 1; diff --git a/src/sink.c b/src/sink.c index 177505a6fb..569b4c8d27 100644 --- a/src/sink.c +++ b/src/sink.c @@ -164,18 +164,18 @@ struct sink *sink_new_buf(const char *name, const char *desc, enum log_fmt fmt, return NULL; } -/* tries to send message parts (up to 8, ignored above) from message - * array to sink . Formatting according to the sink's preference is - * done here. Lost messages are NOT accounted for. It is preferable to call - * sink_write() instead which will also try to emit the number of dropped - * messages when there are any. It will stop writing at instead of - * sink->maxlen if is positive and inferior to sink->maxlen. +/* tries to send message parts from message array to sink . + * Formatting according to the sink's preference is done here. Lost messages + * are NOT accounted for. It is preferable to call sink_write() instead which + * will also try to emit the number of dropped messages when there are any. + * + * It will stop writing at instead of sink->maxlen if is + * positive and inferior to sink->maxlen. * * It returns >0 if it could write anything, <=0 otherwise. */ - ssize_t __sink_write(struct sink *sink, size_t maxlen, - const struct ist msg[], size_t nmsg, - int level, int facility, struct ist *metadata) + ssize_t __sink_write(struct sink *sink, struct log_header hdr, + size_t maxlen, const struct ist msg[], size_t nmsg) { struct ist *pfx = NULL; size_t npfx = 0; @@ -183,7 +183,8 @@ struct sink *sink_new_buf(const char *name, const char *desc, enum log_fmt fmt, if (sink->fmt == LOG_FORMAT_RAW) goto send; - pfx = build_log_header(sink->fmt, level, facility, metadata, &npfx); + hdr.format = sink->fmt; /* sink format prevails over log one */ + pfx = build_log_header(hdr, &npfx); send: if (!maxlen) @@ -197,16 +198,17 @@ send: return 0; } -/* Tries to emit a message indicating the number of dropped events. In case of - * success, the amount of drops is reduced by as much. It's supposed to be - * called under an exclusive lock on the sink to avoid multiple produces doing - * the same. On success, >0 is returned, otherwise <=0 on failure. +/* Tries to emit a message indicating the number of dropped events. + * The log header of the original message that we tried to emit is reused + * here with the only difference that we override the log level. This is + * possible since the announce message will be sent from the same context. + * + * In case of success, the amount of drops is reduced by as much. It's supposed + * to be called under an exclusive lock on the sink to avoid multiple producers + * doing the same. On success, >0 is returned, otherwise <=0 on failure. */ -int sink_announce_dropped(struct sink *sink, int facility) +int sink_announce_dropped(struct sink *sink, struct log_header hdr) { - static THREAD_LOCAL struct ist metadata[LOG_META_FIELDS]; - static THREAD_LOCAL pid_t curr_pid; - static THREAD_LOCAL char pidstr[16]; unsigned int dropped; struct buffer msg; struct ist msgvec[1]; @@ -217,24 +219,9 @@ int sink_announce_dropped(struct sink *sink, int facility) chunk_printf(&msg, "%u event%s dropped", dropped, dropped > 1 ? "s" : ""); msgvec[0] = ist2(msg.area, msg.data); - if (!metadata[LOG_META_HOST].len) { - if (global.log_send_hostname) - metadata[LOG_META_HOST] = ist(global.log_send_hostname); - } - - if (!metadata[LOG_META_TAG].len) - metadata[LOG_META_TAG] = ist2(global.log_tag.area, global.log_tag.data); - - if (unlikely(curr_pid != getpid())) - metadata[LOG_META_PID].len = 0; - - if (!metadata[LOG_META_PID].len) { - curr_pid = getpid(); - ltoa_o(curr_pid, pidstr, sizeof(pidstr)); - metadata[LOG_META_PID] = ist2(pidstr, strlen(pidstr)); - } + hdr.level = LOG_NOTICE; /* override level but keep original log header data */ - if (__sink_write(sink, 0, msgvec, 1, LOG_NOTICE, facility, metadata) <= 0) + if (__sink_write(sink, hdr, 0, msgvec, 1) <= 0) return 0; /* success! */ HA_ATOMIC_SUB(&sink->ctx.dropped, dropped); diff --git a/src/trace.c b/src/trace.c index 30fca7ae13..7cbbd132b9 100644 --- a/src/trace.c +++ b/src/trace.c @@ -291,7 +291,7 @@ void __trace(enum trace_level level, uint64_t mask, struct trace_source *src, } if (src->sink) - sink_write(src->sink, 0, line, words, 0, 0, NULL); + sink_write(src->sink, LOG_HEADER_NONE, 0, line, words); end: /* check if we need to stop the trace now */