diff --git a/include/common/hathreads.h b/include/common/hathreads.h index 7cbb3495b8..308bcb1f12 100644 --- a/include/common/hathreads.h +++ b/include/common/hathreads.h @@ -443,6 +443,7 @@ enum lock_label { START_LOCK, TLSKEYS_REF_LOCK, AUTH_LOCK, + LOGSRV_LOCK, OTHER_LOCK, LOCK_LABELS }; @@ -559,6 +560,7 @@ static inline const char *lock_label(enum lock_label label) case START_LOCK: return "START"; case TLSKEYS_REF_LOCK: return "TLSKEYS_REF"; case AUTH_LOCK: return "AUTH"; + case LOGSRV_LOCK: return "LOGSRV"; case OTHER_LOCK: return "OTHER"; case LOCK_LABELS: break; /* keep compiler happy */ }; diff --git a/include/proto/log.h b/include/proto/log.h index b05ab3efc4..7b056c5fef 100644 --- a/include/proto/log.h +++ b/include/proto/log.h @@ -54,6 +54,17 @@ extern THREAD_LOCAL char *logline; extern THREAD_LOCAL char *logline_rfc5424; +/* + * Test if index numbered from 0 is in range with low and high + * limits of indexes numbered from 1. + */ +static inline int in_smp_log_range(struct smp_log_range *rg, unsigned int idx) +{ + if (idx + 1 <= rg->high && idx + 1 >= rg->low) + return 1; + return 0; +} + /* Initialize/Deinitialize log buffers used for syslog messages */ int init_log_buffers(); void deinit_log_buffers(); diff --git a/include/types/log.h b/include/types/log.h index 9f9912aa20..affcd92d29 100644 --- a/include/types/log.h +++ b/include/types/log.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #define NB_LOG_FACILITIES 24 @@ -202,6 +203,7 @@ struct logsrv { int minlvl; int maxlen; struct logsrv *ref; + __decl_hathreads(HA_SPINLOCK_T lock); }; #endif /* _TYPES_LOG_H */ diff --git a/src/log.c b/src/log.c index cffd8f1483..49de5709f4 100644 --- a/src/log.c +++ b/src/log.c @@ -946,6 +946,7 @@ int parse_logsrv(char **args, struct list *logsrvs, int do_del, char **err) cur_arg += 2; } + HA_SPIN_INIT(&logsrv->lock); /* parse the facility */ logsrv->facility = get_log_facility(args[cur_arg]); if (logsrv->facility < 0) { @@ -1722,12 +1723,32 @@ void __send_log(struct proxy *p, int level, char *message, size_t size, char *sd /* Send log messages to syslog server. */ nblogger = 0; list_for_each_entry(logsrv, logsrvs, list) { + static THREAD_LOCAL int in_range = 1; + /* we can filter the level of the messages that are sent to each logger */ if (level > logsrv->level) continue; - __do_send_log(logsrv, ++nblogger, pid.area, pid.data, level, - message, size, sd, sd_size, tag->area, tag->data); + if (logsrv->lb.smp_rgs) { + struct smp_log_range *curr_rg; + + HA_SPIN_LOCK(LOGSRV_LOCK, &logsrv->lock); + curr_rg = &logsrv->lb.smp_rgs[logsrv->lb.curr_rg]; + in_range = in_smp_log_range(curr_rg, logsrv->lb.curr_idx); + if (in_range) { + /* Let's consume this range. */ + curr_rg->curr_idx = (curr_rg->curr_idx + 1) % curr_rg->sz; + if (!curr_rg->curr_idx) { + /* If consumed, let's select the next range. */ + logsrv->lb.curr_rg = (logsrv->lb.curr_rg + 1) % logsrv->lb.smp_rgs_sz; + } + } + logsrv->lb.curr_idx = (logsrv->lb.curr_idx + 1) % logsrv->lb.smp_sz; + HA_SPIN_UNLOCK(LOGSRV_LOCK, &logsrv->lock); + } + if (in_range) + __do_send_log(logsrv, ++nblogger, pid.area, pid.data, level, + message, size, sd, sd_size, tag->area, tag->data); } }