MEDIUM: log/sink: re-work and merge of build message API.

This patch merges build message code between sink and log
and introduce a new API based on struct ist array to
prepare message header with zero copy, targeting the
log forwarding feature.

Log format 'iso' and 'timed' are now avalaible on logs line.
A new log format 'priority' is also added.
This commit is contained in:
Emeric Brun 2020-07-06 15:54:06 +02:00 committed by Willy Tarreau
parent 3835c0dcb5
commit 546488559a
9 changed files with 520 additions and 492 deletions

View File

@ -1051,12 +1051,26 @@ log <address> [len <length>] [format <format>] [sample <ranges>:<smp_size>]
rfc5424 The RFC5424 syslog message format.
(https://tools.ietf.org/html/rfc5424)
priority A message containing only a level plus syslog facility between
angle brackets such as '<63>', followed by the text. The PID,
date, time, process name and system name are omitted. This is
designed to be used with a local log server.
short A message containing only a level between angle brackets such as
'<3>', followed by the text. The PID, date, time, process name
and system name are omitted. This is designed to be used with a
local log server. This format is compatible with what the systemd
logger consumes.
timed A message containing only a level between angle brackets such as
'<3>', followed by ISO date and by the text. The PID, process
name and system name are omitted. This is designed to be
used with a local log server.
iso A message containing only the ISO date, followed by the text.
The PID, process name and system name are omitted. This is
designed to be used with a local log server.
raw A message containing only the text. The level, PID, date, time,
process name and system name are omitted. This is designed to be
used in containers or during development, where the severity only
@ -2663,6 +2677,11 @@ format <format>
local log server. This format is compatible with what the systemd
logger consumes.
priority A message containing only a level plus syslog facility between angle
brackets such as '<63>', followed by the text. The PID, date, time,
process name and system name are omitted. This is designed to be used
with a local log server.
timed A message containing only a level between angle brackets such as
'<3>', followed by ISO date and by the text. The PID, process
name and system name are omitted. This is designed to be
@ -6778,12 +6797,26 @@ no log
rfc5424 The RFC5424 syslog message format.
(https://tools.ietf.org/html/rfc5424)
priority A message containing only a level plus syslog facility between
angle brackets such as '<63>', followed by the text. The PID,
date, time, process name and system name are omitted. This is
designed to be used with a local log server.
short A message containing only a level between angle brackets such as
'<3>', followed by the text. The PID, date, time, process name
and system name are omitted. This is designed to be used with a
local log server. This format is compatible with what the
systemd logger consumes.
timed A message containing only a level between angle brackets such as
'<3>', followed by ISO date and by the text. The PID, process
name and system name are omitted. This is designed to be
used with a local log server.
iso A message containing only the ISO date, followed by the text.
The PID, process name and system name are omitted. This is
designed to be used with a local log server.
raw A message containing only the text. The level, PID, date, time,
process name and system name are omitted. This is designed to
be used in containers or during development, where the severity

View File

@ -33,7 +33,7 @@
#define NB_LOG_FACILITIES 24
#define NB_LOG_LEVELS 8
#define NB_MSG_IOVEC_ELEMENTS 8
#define NB_LOG_HDR_MAX_ELEMENTS 15
#define SYSLOG_PORT 514
#define UNIQUEID_LEN 128
@ -67,14 +67,33 @@
#define LW_FRTIP 8192 /* frontend IP */
#define LW_XPRT 16384 /* transport layer information (eg: SSL) */
#define LOG_LEGACYTIME_LEN 15
#define LOG_ISOTIME_MINLEN 20
#define LOG_ISOTIME_MAXLEN 32
/* enum for log format */
enum {
LOG_FORMAT_RFC3164 = 0,
enum log_fmt {
LOG_FORMAT_UNSPEC = 0,
LOG_FORMAT_RFC3164,
LOG_FORMAT_RFC5424,
LOG_FORMAT_PRIO,
LOG_FORMAT_SHORT,
LOG_FORMAT_TIMED,
LOG_FORMAT_ISO,
LOG_FORMAT_RAW,
LOG_FORMATS, /* number of supported log formats, must always be last */
LOG_FORMATS /* number of supported log formats, must always be last */
};
/* enum log header meta data */
enum log_meta {
LOG_META_PRIO,
LOG_META_TIME,
LOG_META_HOST,
LOG_META_TAG,
LOG_META_PID,
LOG_META_MSGID,
LOG_META_STDATA,
LOG_META_FIELDS /* must always be the last */
};
/* log target types */
@ -210,7 +229,7 @@ struct logsrv {
struct sink *sink;
char *ring_name;
enum log_tgt type;
int format;
enum log_fmt format;
int facility;
int level;
int minlvl;

View File

@ -43,8 +43,6 @@ extern char default_rfc5424_sd_log_format[];
extern unsigned int dropped_logs;
extern THREAD_LOCAL char *logheader;
extern THREAD_LOCAL char *logheader_rfc5424;
extern THREAD_LOCAL char *logline;
extern THREAD_LOCAL char *logline_rfc5424;
@ -99,9 +97,9 @@ void send_log(struct proxy *p, int level, const char *format, ...)
void __send_log(struct list *logsrvs, struct buffer *tag, int level, char *message, size_t size, char *sd, size_t sd_size);
/*
* returns log format for <fmt> or -1 if not found.
* returns log format for <fmt> or LOG_FORMAT_UNSPEC if not found.
*/
int get_log_format(const char *fmt);
enum log_fmt get_log_format(const char *fmt);
/*
* returns log level for <lev> or -1 if not found.
@ -161,6 +159,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);
#endif /* _HAPROXY_LOG_H */
/*

View File

@ -24,6 +24,7 @@
#include <import/ist.h>
#include <haproxy/api-t.h>
#include <haproxy/log-t.h>
/* A sink may be of 4 distinct types :
* - file descriptor (such as stdout)
@ -35,18 +36,6 @@ enum sink_type {
SINK_TYPE_BUFFER, // events sent to a ring buffer
};
/* This indicates the default event format, which is the destination's
* preferred format, but may be overridden by the source.
*/
enum sink_fmt {
SINK_FMT_RAW, // raw text sent as-is
SINK_FMT_SHORT, // raw text prefixed with a syslog level
SINK_FMT_ISO, // raw text prefixed with ISO time
SINK_FMT_TIMED, // syslog level then ISO
SINK_FMT_RFC3164, // regular syslog
SINK_FMT_RFC5424, // extended syslog
};
struct sink_forward_target {
struct server *srv; // used server
struct appctx *appctx; // appctx of current session
@ -60,7 +49,7 @@ struct sink {
struct list sink_list; // position in the sink list
char *name; // sink name
char *desc; // sink description
enum sink_fmt fmt; // format expected by the sink
enum log_fmt fmt; // format expected by the sink
enum sink_type type; // type of storage
uint32_t maxlen; // max message length (truncated above)
struct proxy* forward_px; // proxy used to forward

View File

@ -29,11 +29,10 @@
extern struct list sink_list;
struct sink *sink_find(const char *name);
struct sink *sink_new_fd(const char *name, const char *desc, enum sink_fmt fmt, int fd);
struct sink *sink_new_fd(const char *name, const char *desc, enum log_fmt, int fd);
ssize_t __sink_write(struct sink *sink, const struct ist msg[], size_t nmsg,
int level, int facility, struct ist * tag,
struct ist *pid, struct ist *sd);
int sink_announce_dropped(struct sink *sink, int facility, struct ist *pid);
int level, int facility, struct ist * metadata);
int sink_announce_dropped(struct sink *sink, int facility);
/* tries to send <nmsg> message parts (up to 8, ignored above) from message
@ -44,8 +43,7 @@ int sink_announce_dropped(struct sink *sink, int facility, struct ist *pid);
* or <= 0 in other cases.
*/
static inline ssize_t sink_write(struct sink *sink, const struct ist msg[], size_t nmsg,
int level, int facility, struct ist * tag,
struct ist *pid, struct ist *sd)
int level, int facility, struct ist *metadata)
{
ssize_t sent;
@ -57,7 +55,7 @@ static inline ssize_t sink_write(struct sink *sink, const struct ist msg[], size
* position.
*/
HA_RWLOCK_WRLOCK(LOGSRV_LOCK, &sink->ctx.lock);
sent = sink_announce_dropped(sink, facility, pid);
sent = sink_announce_dropped(sink, facility);
HA_RWLOCK_WRUNLOCK(LOGSRV_LOCK, &sink->ctx.lock);
if (!sent) {
@ -69,7 +67,7 @@ static inline ssize_t sink_write(struct sink *sink, const struct ist msg[], size
}
HA_RWLOCK_RDLOCK(LOGSRV_LOCK, &sink->ctx.lock);
sent = __sink_write(sink, msg, nmsg, level, facility, tag, pid, sd);
sent = __sink_write(sink, msg, nmsg, level, facility, metadata);
HA_RWLOCK_RDUNLOCK(LOGSRV_LOCK, &sink->ctx.lock);
fail:

760
src/log.c
View File

@ -43,57 +43,34 @@
#include <haproxy/version.h>
struct log_fmt {
struct log_fmt_st {
char *name;
struct {
struct buffer sep1; /* first pid separator */
struct buffer sep2; /* second pid separator */
} pid;
};
static const struct log_fmt log_formats[LOG_FORMATS] = {
static const struct log_fmt_st log_formats[LOG_FORMATS] = {
[LOG_FORMAT_RFC3164] = {
.name = "rfc3164",
.pid = {
.sep1 = { .area = "[", .data = 1 },
.sep2 = { .area = "]: ", .data = 3 }
}
},
[LOG_FORMAT_RFC5424] = {
.name = "rfc5424",
.pid = {
.sep1 = { .area = " ", .data = 1 },
.sep2 = { .area = " - ", .data = 3 }
}
},
[LOG_FORMAT_PRIO] = {
.name = "priority",
},
[LOG_FORMAT_SHORT] = {
.name = "short",
.pid = {
.sep1 = { .area = "", .data = 0 },
.sep2 = { .area = " ", .data = 1 },
}
},
[LOG_FORMAT_TIMED] = {
.name = "timed",
},
[LOG_FORMAT_ISO] = {
.name = "iso",
},
[LOG_FORMAT_RAW] = {
.name = "raw",
.pid = {
.sep1 = { .area = "", .data = 0 },
.sep2 = { .area = "", .data = 0 },
}
},
};
char *get_format_pid_sep1(int format, size_t *len)
{
*len = log_formats[format].pid.sep1.data;
return log_formats[format].pid.sep1.area;
}
char *get_format_pid_sep2(int format, size_t *len)
{
*len = log_formats[format].pid.sep2.data;
return log_formats[format].pid.sep2.area;
}
/*
* This map is used with all the FD_* macros to check whether a particular bit
* is set or not. Each bit represents an ACSII code. ha_bit_set() sets those
@ -233,19 +210,6 @@ char default_rfc5424_sd_log_format[] = "- ";
/* total number of dropped logs */
unsigned int dropped_logs = 0;
/* This is a global syslog header, common to all outgoing messages in
* RFC3164 format. It begins with time-based part and is updated by
* update_log_hdr().
*/
THREAD_LOCAL char *logheader = NULL;
THREAD_LOCAL char *logheader_end = NULL;
/* This is a global syslog header for messages in RFC5424 format. It is
* updated by update_log_hdr_rfc5424().
*/
THREAD_LOCAL char *logheader_rfc5424 = NULL;
THREAD_LOCAL char *logheader_rfc5424_end = NULL;
/* This is a global syslog message buffer, common to all outgoing
* messages. It contains only the data part.
*/
@ -922,7 +886,7 @@ int parse_logsrv(char **args, struct list *logsrvs, int do_del, char **err)
/* after the length, a format may be specified */
if (strcmp(args[cur_arg], "format") == 0) {
logsrv->format = get_log_format(args[cur_arg+1]);
if (logsrv->format < 0) {
if (logsrv->format == LOG_FORMAT_UNSPEC) {
memprintf(err, "unknown log format '%s'", args[cur_arg+1]);
goto error;
}
@ -1179,16 +1143,18 @@ void qfprintf(FILE *out, const char *fmt, ...)
}
/*
* returns log format for <fmt> or -1 if not found.
* returns log format, LOG_FORMAT_UNSPEC is return if not found.
*/
int get_log_format(const char *fmt)
enum log_fmt get_log_format(const char *fmt)
{
int format;
enum log_fmt format;
format = LOG_FORMATS - 1;
while (format >= 0 && strcmp(log_formats[format].name, fmt))
while (format > 0 && log_formats[format].name
&& strcmp(log_formats[format].name, fmt))
format--;
/* Note: 0 is LOG_FORMAT_UNSPEC */
return format;
}
@ -1431,94 +1397,6 @@ char *lf_port(char *dst, const struct sockaddr *sockaddr, size_t size, const str
return ret;
}
/* Re-generate time-based part of the syslog header in RFC3164 format at
* the beginning of logheader once a second and return the pointer to the
* first character after it.
*/
char *update_log_hdr(const time_t time)
{
static THREAD_LOCAL long tvsec;
static THREAD_LOCAL struct buffer host = { };
static THREAD_LOCAL int sep = 0;
if (unlikely(time != tvsec || logheader_end == NULL)) {
/* this string is rebuild only once a second */
struct tm tm;
int hdr_len;
tvsec = time;
get_localtime(tvsec, &tm);
if (unlikely(global.log_send_hostname != host.area)) {
host.area = global.log_send_hostname;
host.data = host.area ? strlen(host.area) : 0;
sep = host.data ? 1 : 0;
}
hdr_len = snprintf(logheader, global.max_syslog_len,
"<<<<>%s %2d %02d:%02d:%02d %.*s%*s",
monthname[tm.tm_mon],
tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
(int)host.data, host.area, sep, "");
/* WARNING: depending upon implementations, snprintf may return
* either -1 or the number of bytes that would be needed to store
* the total message. In both cases, we must adjust it.
*/
if (hdr_len < 0 || hdr_len > global.max_syslog_len)
hdr_len = global.max_syslog_len;
logheader_end = logheader + hdr_len;
}
logheader_end[0] = 0; // ensure we get rid of any previous attempt
return logheader_end;
}
/* Re-generate time-based part of the syslog header in RFC5424 format at
* the beginning of logheader_rfc5424 once a second and return the pointer
* to the first character after it.
*/
char *update_log_hdr_rfc5424(const time_t time, const suseconds_t frac)
{
static THREAD_LOCAL long tvsec;
const char *gmt_offset;
char c;
if (unlikely(time != tvsec || logheader_rfc5424_end == NULL)) {
/* this string is rebuild only once a second */
struct tm tm;
int hdr_len;
tvsec = time;
get_localtime(tvsec, &tm);
gmt_offset = get_gmt_offset(time, &tm);
hdr_len = snprintf(logheader_rfc5424, global.max_syslog_len,
"<<<<>1 %4d-%02d-%02dT%02d:%02d:%02d.000000%.3s:%.2s %s ",
tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec,
gmt_offset, gmt_offset+3,
global.log_send_hostname ? global.log_send_hostname : hostname);
/* WARNING: depending upon implementations, snprintf may return
* either -1 or the number of bytes that would be needed to store
* the total message. In both cases, we must adjust it.
*/
if (hdr_len < 0 || hdr_len > global.max_syslog_len)
hdr_len = global.max_syslog_len;
logheader_rfc5424_end = logheader_rfc5424 + hdr_len;
}
/* utoa_pad add a trailing '\0' so we save the char to restore */
c = logheader_rfc5424[33];
utoa_pad(frac, logheader_rfc5424 + 27, 7);
logheader_rfc5424[33] = c;
logheader_rfc5424_end[0] = 0; // ensure we get rid of any previous attempt
return logheader_rfc5424_end;
}
/*
* This function sends the syslog message using a printf format string. It
@ -1541,52 +1419,325 @@ void send_log(struct proxy *p, int level, const char *format, ...)
__send_log((p ? &p->logsrvs : NULL), (p ? &p->log_tag : NULL), level,
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 returns a struct ist array of elements of the header
* nbelem is set to the number of available elements.
* Thos 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)
{
static THREAD_LOCAL struct {
struct ist ist_vector[NB_LOG_HDR_MAX_ELEMENTS];
char timestamp_buffer[LOG_LEGACYTIME_LEN+1+1];
time_t cur_legacy_time;
char priority_buffer[6];
} hdr_ctx = { .priority_buffer = "<<<<>" };
struct tm logtime;
int len;
int fac_level = 0;
time_t time = date.tv_sec;
*nbelem = 0;
if (format == LOG_FORMAT_UNSPEC) {
format = LOG_FORMAT_RAW;
if (metadata) {
/* If a hostname is set, it appears we want to perform syslog
* because only rfc5427 or rfc3164 support an hostname.
*/
if (metadata[LOG_META_HOST].len) {
/* If a rfc5424 compliant timestamp is used we consider
* that output format is rfc5424, else legacy format
* is used as specified default for local logs
* in documentation.
*/
if ((metadata[LOG_META_TIME].len == 1 && metadata[LOG_META_TIME].ptr[0] == '-')
|| (metadata[LOG_META_TIME].len >= LOG_ISOTIME_MINLEN))
format = LOG_FORMAT_RFC5424;
else
format = LOG_FORMAT_RFC3164;
}
else if (metadata[LOG_META_PRIO].len) {
/* the source seems a parsed message
* offering a valid level/prio prefix
* so we consider this format.
*/
format = LOG_FORMAT_PRIO;
}
}
}
/* prepare priority, stored into 1 single elem */
switch (format) {
case LOG_FORMAT_RFC3164:
case LOG_FORMAT_RFC5424:
case LOG_FORMAT_PRIO:
fac_level = facility << 3;
/* further format ignore the facility */
/* fall through */
case LOG_FORMAT_TIMED:
case LOG_FORMAT_SHORT:
fac_level += level;
hdr_ctx.ist_vector[*nbelem].ptr = &hdr_ctx.priority_buffer[3]; /* last digit of the log level */
do {
*hdr_ctx.ist_vector[*nbelem].ptr = '0' + fac_level % 10;
fac_level /= 10;
hdr_ctx.ist_vector[*nbelem].ptr--;
} while (fac_level && hdr_ctx.ist_vector[*nbelem].ptr > &hdr_ctx.priority_buffer[0]);
*hdr_ctx.ist_vector[*nbelem].ptr = '<';
hdr_ctx.ist_vector[(*nbelem)++].len = &hdr_ctx.priority_buffer[5] - hdr_ctx.ist_vector[0].ptr;
break;
case LOG_FORMAT_ISO:
case LOG_FORMAT_RAW:
break;
case LOG_FORMAT_UNSPEC:
case LOG_FORMATS:
ABORT_NOW();
}
/* prepare timestamp, stored into a max of 4 elems */
switch (format) {
case LOG_FORMAT_RFC3164:
/* rfc3164 ex: 'Jan 1 00:00:00 ' */
if (metadata && metadata[LOG_META_TIME].len == LOG_LEGACYTIME_LEN) {
hdr_ctx.ist_vector[(*nbelem)++] = metadata[LOG_META_TIME];
hdr_ctx.ist_vector[(*nbelem)++] = ist2(" ", 1);
/* time is set, break immediatly */
break;
}
else if (metadata && metadata[LOG_META_TIME].len >= LOG_ISOTIME_MINLEN) {
int month;
char *timestamp = metadata[LOG_META_TIME].ptr;
/* iso time always begins like this: '1970-01-01T00:00:00' */
/* compute month */
month = 10*(timestamp[5] - '0') + (timestamp[6] - '0');
if (month)
month--;
if (month <= 11) {
/* builds log prefix ex: 'Jan 1 ' */
len = snprintf(hdr_ctx.timestamp_buffer, sizeof(hdr_ctx.timestamp_buffer),
"%s %c%c ", monthname[month],
timestamp[8] != '0' ? timestamp[8] : ' ',
timestamp[9]);
/* we reused the timestamp_buffer, signal that it does not
* contain local time anymore
*/
hdr_ctx.cur_legacy_time = 0;
if (len == 7) {
hdr_ctx.ist_vector[(*nbelem)++] = ist2(&hdr_ctx.timestamp_buffer[0], len);
/* adds 'HH:MM:SS' from iso time */
hdr_ctx.ist_vector[(*nbelem)++] = ist2(&timestamp[11], 8);
hdr_ctx.ist_vector[(*nbelem)++] = ist2(" ", 1);
/* we successfully reuse iso time, we can break */
break;
}
}
/* Failed to reuse isotime time, fallback to local legacy time */
}
if (unlikely(time != hdr_ctx.cur_legacy_time)) {
/* re-builds timestamp from the current local time */
get_localtime(time, &logtime);
len = snprintf(hdr_ctx.timestamp_buffer, sizeof(hdr_ctx.timestamp_buffer),
"%s %2d %02d:%02d:%02d ",
monthname[logtime.tm_mon],
logtime.tm_mday, logtime.tm_hour, logtime.tm_min, logtime.tm_sec);
if (len != LOG_LEGACYTIME_LEN+1)
hdr_ctx.cur_legacy_time = 0;
else
hdr_ctx.cur_legacy_time = time;
}
if (likely(hdr_ctx.cur_legacy_time))
hdr_ctx.ist_vector[(*nbelem)++] = ist2(&hdr_ctx.timestamp_buffer[0], LOG_LEGACYTIME_LEN+1);
else
hdr_ctx.ist_vector[(*nbelem)++] = ist2("Jan 1 00:00:00 ", LOG_LEGACYTIME_LEN+1);
break;
case LOG_FORMAT_RFC5424:
/* adds rfc5425 version prefix */
hdr_ctx.ist_vector[(*nbelem)++] = ist2("1 ", 2);
if (metadata && metadata[LOG_META_TIME].len == 1 && metadata[LOG_META_TIME].ptr[0] == '-') {
/* submited len is NILVALUE, it is a valid timestamp for rfc5425 */
hdr_ctx.ist_vector[(*nbelem)++] = metadata[LOG_META_TIME];
hdr_ctx.ist_vector[(*nbelem)++] = ist2(" ", 1);
break;
}
/* let continue as 'timed' and 'iso' format for usual timestamp */
/* fall through */
case LOG_FORMAT_TIMED:
case LOG_FORMAT_ISO:
/* ISO format ex: '1900:01:01T12:00:00.123456Z'
* '1900:01:01T14:00:00+02:00'
* '1900:01:01T10:00:00.123456-02:00'
*/
if (metadata && metadata[LOG_META_TIME].len >= LOG_ISOTIME_MINLEN) {
hdr_ctx.ist_vector[(*nbelem)++] = metadata[LOG_META_TIME];
hdr_ctx.ist_vector[(*nbelem)++] = ist2(" ", 1);
/* time is set, break immediatly */
break;
}
else if (metadata && metadata[LOG_META_TIME].len == LOG_LEGACYTIME_LEN) {
int month;
char *timestamp = metadata[LOG_META_TIME].ptr;
for (month = 0; month < 12; month++)
if (!memcmp(monthname[month], timestamp, 3))
break;
if (month < 12) {
/* get local time to retrieve year */
get_localtime(time, &logtime);
/* year seems changed since log */
if (logtime.tm_mon < month)
logtime.tm_year--;
/* builds rfc5424 prefix ex: '1900-01-01T' */
len = snprintf(hdr_ctx.timestamp_buffer, sizeof(hdr_ctx.timestamp_buffer),
"%4d-%02d-%c%cT",
logtime.tm_year+1900, month+1,
timestamp[4] != ' ' ? timestamp[4] : '0',
timestamp[5]);
/* we reused the timestamp_buffer, signal that it does not
* contain local time anymore
*/
hdr_ctx.cur_legacy_time = 0;
if (len == 11) {
hdr_ctx.ist_vector[(*nbelem)++] = ist2(&hdr_ctx.timestamp_buffer[0], len);
/* adds HH:MM:SS from legacy timestamp */
hdr_ctx.ist_vector[(*nbelem)++] = ist2(&timestamp[7], 8);
/* skip secfraq because optionnal */
/* according to rfc: -00:00 means we don't know the timezone */
hdr_ctx.ist_vector[(*nbelem)++] = ist2("-00:00 ", 7);
/* we successfully reuse legacy time, we can break */
break;
}
}
/* Failed to reuse legacy time, fallback to local iso time */
}
hdr_ctx.ist_vector[(*nbelem)++] = ist2(timeofday_as_iso_us(1), LOG_ISOTIME_MAXLEN + 1);
break;
case LOG_FORMAT_PRIO:
case LOG_FORMAT_SHORT:
case LOG_FORMAT_RAW:
break;
case LOG_FORMAT_UNSPEC:
case LOG_FORMATS:
ABORT_NOW();
}
/* prepare other meta data, stored into a max of 10 elems */
switch (format) {
case LOG_FORMAT_RFC3164:
if (metadata && metadata[LOG_META_HOST].len) {
hdr_ctx.ist_vector[(*nbelem)++] = metadata[LOG_META_HOST];
hdr_ctx.ist_vector[(*nbelem)++] = ist2(" ", 1);
}
else /* the caller MUST fill the hostname */
hdr_ctx.ist_vector[(*nbelem)++] = ist2("localhost ", 10);
if (!metadata || !metadata[LOG_META_TAG].len)
break;
hdr_ctx.ist_vector[(*nbelem)++] = metadata[LOG_META_TAG];
if (metadata[LOG_META_PID].len) {
hdr_ctx.ist_vector[(*nbelem)++] = ist2("[", 1);
hdr_ctx.ist_vector[(*nbelem)++] = metadata[LOG_META_PID];
hdr_ctx.ist_vector[(*nbelem)++] = ist2("]", 1);
}
hdr_ctx.ist_vector[(*nbelem)++] = ist2(": ", 2);
break;
case LOG_FORMAT_RFC5424:
if (metadata && metadata[LOG_META_HOST].len) {
hdr_ctx.ist_vector[(*nbelem)++] = metadata[LOG_META_HOST];
hdr_ctx.ist_vector[(*nbelem)++] = ist2(" ", 1);
}
else
hdr_ctx.ist_vector[(*nbelem)++] = ist2("- ", 2);
if (metadata && metadata[LOG_META_TAG].len) {
hdr_ctx.ist_vector[(*nbelem)++] = metadata[LOG_META_TAG];
hdr_ctx.ist_vector[(*nbelem)++] = ist2(" ", 1);
}
else
hdr_ctx.ist_vector[(*nbelem)++] = ist2("- ", 2);
if (metadata && metadata[LOG_META_PID].len) {
hdr_ctx.ist_vector[(*nbelem)++] = metadata[LOG_META_PID];
hdr_ctx.ist_vector[(*nbelem)++] = ist2(" ", 1);
}
else
hdr_ctx.ist_vector[(*nbelem)++] = ist2("- ", 2);
if (metadata && metadata[LOG_META_MSGID].len) {
hdr_ctx.ist_vector[(*nbelem)++] = metadata[LOG_META_MSGID];
hdr_ctx.ist_vector[(*nbelem)++] = ist2(" ", 1);
}
else
hdr_ctx.ist_vector[(*nbelem)++] = ist2("- ", 2);
if (metadata && metadata[LOG_META_STDATA].len) {
hdr_ctx.ist_vector[(*nbelem)++] = metadata[LOG_META_STDATA];
hdr_ctx.ist_vector[(*nbelem)++] = ist2(" ", 1);
}
else
hdr_ctx.ist_vector[(*nbelem)++] = ist2("- ", 2);
break;
case LOG_FORMAT_PRIO:
case LOG_FORMAT_SHORT:
case LOG_FORMAT_TIMED:
case LOG_FORMAT_ISO:
case LOG_FORMAT_RAW:
break;
case LOG_FORMAT_UNSPEC:
case LOG_FORMATS:
ABORT_NOW();
}
return hdr_ctx.ist_vector;
}
/*
* This function sends a syslog message to <logsrv>.
* <pid_str> is the string to be used for the PID of the caller, <pid_size> is length.
* Same thing for <sd> and <sd_size> which are used for the structured-data part
* in RFC5424 formatted syslog messages, and <tag_str> and <tag_size> the syslog tag.
* The argument <metadata> 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.
* Does not return any error,
*/
static inline void __do_send_log(struct logsrv *logsrv, int nblogger, char *pid_str, size_t pid_size,
int level, char *message, size_t size, char *sd, size_t sd_size,
char *tag_str, size_t tag_size)
static inline void __do_send_log(struct logsrv *logsrv, int nblogger, int level, int facility, struct ist *metadata, char *message, size_t size)
{
static THREAD_LOCAL struct iovec iovec[NB_MSG_IOVEC_ELEMENTS] = { };
static THREAD_LOCAL struct iovec iovec[NB_LOG_HDR_MAX_ELEMENTS+1+1] = { }; /* header elements + message + LF */
static THREAD_LOCAL struct msghdr msghdr = {
//.msg_iov = iovec,
.msg_iovlen = NB_MSG_IOVEC_ELEMENTS
.msg_iovlen = NB_LOG_HDR_MAX_ELEMENTS+2
};
static THREAD_LOCAL int logfdunix = -1; /* syslog to AF_UNIX socket */
static THREAD_LOCAL int logfdinet = -1; /* syslog to AF_INET socket */
static THREAD_LOCAL char *dataptr = NULL;
time_t time = date.tv_sec;
char *hdr, *hdr_ptr = NULL;
size_t hdr_size;
int fac_level;
int *plogfd;
char *pid_sep1 = "", *pid_sep2 = "";
char logheader_short[3];
int sent;
int maxlen;
int hdr_max = 0;
int tag_max = 0;
int pid_sep1_max = 0;
int pid_max = 0;
int pid_sep2_max = 0;
int sd_max = 0;
int max = 0;
size_t nbelem;
struct ist *msg_header = NULL;
msghdr.msg_iov = iovec;
dataptr = message;
/* historically some messages used to already contain the trailing LF
* or Zero. Let's remove all trailing LF or Zero
*/
while (size && ((dataptr[size-1] == '\n' || (dataptr[size-1] == 0))))
while (size && (message[size-1] == '\n' || (message[size-1] == 0)))
size--;
if (logsrv->type == LOG_TARGET_FD) {
@ -1623,161 +1774,47 @@ static inline void __do_send_log(struct logsrv *logsrv, int nblogger, char *pid_
}
}
switch (logsrv->format) {
case LOG_FORMAT_RFC3164:
hdr = logheader;
hdr_ptr = update_log_hdr(time);
break;
case LOG_FORMAT_RFC5424:
hdr = logheader_rfc5424;
hdr_ptr = update_log_hdr_rfc5424(time, date.tv_usec);
sd_max = sd_size; /* the SD part allowed only in RFC5424 */
break;
case LOG_FORMAT_SHORT:
/* all fields are known, skip the header generation */
hdr = logheader_short;
hdr[0] = '<';
hdr[1] = '0' + MAX(level, logsrv->minlvl);
hdr[2] = '>';
hdr_ptr = hdr;
hdr_max = 3;
maxlen = logsrv->maxlen - hdr_max;
max = MIN(size, maxlen - 1);
goto send;
case LOG_FORMAT_RAW:
/* all fields are known, skip the header generation */
hdr_ptr = hdr = "";
hdr_max = 0;
maxlen = logsrv->maxlen;
max = MIN(size, maxlen - 1);
goto send;
default:
return; /* must never happen */
}
hdr_size = hdr_ptr - hdr;
/* For each target, we may have a different facility.
* We can also have a different log level for each message.
* This induces variations in the message header length.
* Since we don't want to recompute it each time, nor copy it every
* time, we only change the facility in the pre-computed header,
* and we change the pointer to the header accordingly.
*/
fac_level = (logsrv->facility << 3) + MAX(level, logsrv->minlvl);
hdr_ptr = hdr + 3; /* last digit of the log level */
do {
*hdr_ptr = '0' + fac_level % 10;
fac_level /= 10;
hdr_ptr--;
} while (fac_level && hdr_ptr > hdr);
*hdr_ptr = '<';
hdr_max = hdr_size - (hdr_ptr - hdr);
/* time-based header */
if (unlikely(hdr_size >= logsrv->maxlen)) {
hdr_max = MIN(hdr_max, logsrv->maxlen) - 1;
sd_max = 0;
goto send;
}
maxlen = logsrv->maxlen - hdr_max;
/* tag */
tag_max = tag_size;
if (unlikely(tag_max >= maxlen)) {
tag_max = maxlen - 1;
sd_max = 0;
goto send;
}
maxlen -= tag_max;
/* first pid separator */
pid_sep1_max = log_formats[logsrv->format].pid.sep1.data;
if (unlikely(pid_sep1_max >= maxlen)) {
pid_sep1_max = maxlen - 1;
sd_max = 0;
goto send;
}
pid_sep1 = log_formats[logsrv->format].pid.sep1.area;
maxlen -= pid_sep1_max;
/* pid */
pid_max = pid_size;
if (unlikely(pid_size >= maxlen)) {
pid_size = maxlen - 1;
sd_max = 0;
goto send;
}
maxlen -= pid_size;
/* second pid separator */
pid_sep2_max = log_formats[logsrv->format].pid.sep2.data;
if (unlikely(pid_sep2_max >= maxlen)) {
pid_sep2_max = maxlen - 1;
sd_max = 0;
goto send;
}
pid_sep2 = log_formats[logsrv->format].pid.sep2.area;
maxlen -= pid_sep2_max;
/* structured-data */
if (sd_max >= maxlen) {
sd_max = maxlen - 1;
goto send;
}
max = MIN(size, maxlen - sd_max - 1);
send:
msg_header = build_log_header(logsrv->format, level, facility, metadata, &nbelem);
send:
if (logsrv->addr.ss_family == AF_UNSPEC) {
/* the target is a file descriptor or a ring buffer */
struct ist msg[7];
struct ist msg;
msg = ist2(message, size);
if (msg.len > logsrv->maxlen)
msg.len = logsrv->maxlen;
if (logsrv->type == LOG_TARGET_BUFFER) {
msg[0] = ist2(message, MIN(size, logsrv->maxlen));
msg[1] = ist2(tag_str, tag_size);
msg[2] = ist2(pid_str, pid_size);
msg[3] = ist2(sd, sd_size);
sent = sink_write(logsrv->sink, msg, 1, level, logsrv->facility, &msg[1], &msg[2], &msg[3]);
}
else /* LOG_TARGET_FD */ {
msg[0] = ist2(hdr_ptr, hdr_max);
msg[1] = ist2(tag_str, tag_max);
msg[2] = ist2(pid_sep1, pid_sep1_max);
msg[3] = ist2(pid_str, pid_max);
msg[4] = ist2(pid_sep2, pid_sep2_max);
msg[5] = ist2(sd, sd_max);
msg[6] = ist2(dataptr, max);
sent = fd_write_frag_line(*plogfd, ~0, NULL, 0, msg, 7, 1);
sent = sink_write(logsrv->sink, &msg, 1, level, logsrv->facility, metadata);
}
else /* LOG_TARGET_FD */
sent = fd_write_frag_line(*plogfd, logsrv->maxlen, msg_header, nbelem, &msg, 1, 1);
}
else {
iovec[0].iov_base = hdr_ptr;
iovec[0].iov_len = hdr_max;
iovec[1].iov_base = tag_str;
iovec[1].iov_len = tag_max;
iovec[2].iov_base = pid_sep1;
iovec[2].iov_len = pid_sep1_max;
iovec[3].iov_base = pid_str;
iovec[3].iov_len = pid_max;
iovec[4].iov_base = pid_sep2;
iovec[4].iov_len = pid_sep2_max;
iovec[5].iov_base = sd;
iovec[5].iov_len = sd_max;
iovec[6].iov_base = dataptr;
iovec[6].iov_len = max;
iovec[7].iov_base = "\n"; /* insert a \n at the end of the message */
iovec[7].iov_len = 1;
int i = 0;
int totlen = logsrv->maxlen;
for (i = 0 ; i < nbelem ; i++ ) {
iovec[i].iov_base = msg_header[i].ptr;
iovec[i].iov_len = msg_header[i].len;
if (totlen <= iovec[i].iov_len) {
iovec[i].iov_len = totlen;
totlen = 0;
break;
}
totlen -= iovec[i].iov_len;
}
if (totlen) {
iovec[i].iov_base = message;
iovec[i].iov_len = size;
if (totlen <= iovec[i].iov_len)
iovec[i].iov_len = totlen;
i++;
}
iovec[i].iov_base = "\n"; /* insert a \n at the end of the message */
iovec[i].iov_len = 1;
i++;
msghdr.msg_iovlen = i;
msghdr.msg_name = (struct sockaddr *)&logsrv->addr;
msghdr.msg_namelen = get_addr_len(&logsrv->addr);
@ -1800,34 +1837,15 @@ send:
/*
* This function sends a syslog message.
* It doesn't care about errors nor does it report them.
* The arguments <sd> and <sd_size> are used for the structured-data part
* in RFC5424 formatted syslog messages.
* The argument <metadata> MUST be an array of size
* LOG_META_FIELDS*sizeof(struct ist) containing
* data to build the header.
*/
void __send_log(struct list *logsrvs, struct buffer *tag, int level,
char *message, size_t size, char *sd, size_t sd_size)
void process_send_log(struct list *logsrvs, int level, int facility,
struct ist *metadata, char *message, size_t size)
{
struct logsrv *logsrv;
int nblogger;
static THREAD_LOCAL int curr_pid;
static THREAD_LOCAL char pidstr[100];
static THREAD_LOCAL struct buffer pid;
if (logsrvs == NULL) {
if (!LIST_ISEMPTY(&global.logsrvs)) {
logsrvs = &global.logsrvs;
}
}
if (!tag || !tag->area)
tag = &global.log_tag;
if (!logsrvs || LIST_ISEMPTY(logsrvs))
return;
if (unlikely(curr_pid != getpid())) {
curr_pid = getpid();
ltoa_o(curr_pid, pidstr, sizeof(pidstr));
chunk_initstr(&pid, pidstr);
}
/* Send log messages to syslog server. */
nblogger = 0;
@ -1856,11 +1874,63 @@ void __send_log(struct list *logsrvs, struct buffer *tag, int level,
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);
__do_send_log(logsrv, ++nblogger, MAX(level, logsrv->minlvl),
(facility == -1) ? logsrv->facility : facility,
metadata, message, size);
}
}
/*
* This function sends a syslog message.
* It doesn't care about errors nor does it report them.
* The arguments <sd> and <sd_size> are used for the structured-data part
* in RFC5424 formatted syslog messages.
*/
void __send_log(struct list *logsrvs, struct buffer *tagb, int level,
char *message, size_t size, char *sd, size_t sd_size)
{
static THREAD_LOCAL pid_t curr_pid;
static THREAD_LOCAL char pidstr[16];
static THREAD_LOCAL struct ist metadata[LOG_META_FIELDS];
if (logsrvs == NULL) {
if (!LIST_ISEMPTY(&global.logsrvs)) {
logsrvs = &global.logsrvs;
}
}
if (!logsrvs || LIST_ISEMPTY(logsrvs))
return;
if (!metadata[LOG_META_HOST].len) {
if (global.log_send_hostname)
metadata[LOG_META_HOST] = ist2(global.log_send_hostname, strlen(global.log_send_hostname));
else
metadata[LOG_META_HOST] = ist2(hostname, strlen(hostname));
}
if (!tagb || !tagb->area)
tagb = &global.log_tag;
if (tagb)
metadata[LOG_META_TAG] = ist2(tagb->area, tagb->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));
}
metadata[LOG_META_STDATA] = ist2(sd, sd_size);
/* Remove trailing space of structured data */
while (metadata[LOG_META_STDATA].len && metadata[LOG_META_STDATA].ptr[metadata[LOG_META_STDATA].len-1] == ' ')
metadata[LOG_META_STDATA].len--;
return process_send_log(logsrvs, level, -1, metadata, message, size);
}
const char sess_cookie[8] = "NIDVEOU7"; /* No cookie, Invalid cookie, cookie for a Down server, Valid cookie, Expired cookie, Old cookie, Unused, unknown */
const char sess_set_cookie[8] = "NPDIRU67"; /* No set-cookie, Set-cookie found and left unchanged (passive),
@ -1958,13 +2028,9 @@ INITCALL0(STG_PREPARE, init_log);
/* Initialize log buffers used for syslog messages */
int init_log_buffers()
{
logheader = my_realloc2(logheader, global.max_syslog_len + 1);
logheader_end = NULL;
logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
logheader_rfc5424_end = NULL;
logline = my_realloc2(logline, global.max_syslog_len + 1);
logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
if (!logheader || !logline_rfc5424 || !logline || !logline_rfc5424)
if (!logline || !logline_rfc5424)
return 0;
return 1;
}
@ -1972,13 +2038,9 @@ int init_log_buffers()
/* Deinitialize log buffers used for syslog messages */
void deinit_log_buffers()
{
free(logheader);
free(logheader_rfc5424);
free(logline);
free(logline_rfc5424);
ring_free(_HA_ATOMIC_XCHG(&startup_logs, NULL));
logheader = NULL;
logheader_rfc5424 = NULL;
logline = NULL;
logline_rfc5424 = NULL;
}

View File

@ -1483,7 +1483,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, &line, 1, 0, 0, NULL, NULL, NULL);
sink_write(sink, &line, 1, 0, 0, NULL);
end:
free_trash_chunk(buf);
return 1;

View File

@ -50,7 +50,7 @@ struct sink *sink_find(const char *name)
* exists with the same name, it will be returned. The caller can detect it as
* a newly created one has type SINK_TYPE_NEW.
*/
static struct sink *__sink_new(const char *name, const char *desc, enum sink_fmt fmt)
static struct sink *__sink_new(const char *name, const char *desc, int fmt)
{
struct sink *sink;
@ -80,7 +80,7 @@ static struct sink *__sink_new(const char *name, const char *desc, enum sink_fmt
* and description <desc>. Returns NULL on allocation failure or conflict.
* Perfect duplicates are merged (same type, fd, and name).
*/
struct sink *sink_new_fd(const char *name, const char *desc, enum sink_fmt fmt, int fd)
struct sink *sink_new_fd(const char *name, const char *desc, enum log_fmt fmt, int fd)
{
struct sink *sink;
@ -104,7 +104,7 @@ struct sink *sink_new_fd(const char *name, const char *desc, enum sink_fmt fmt,
* Perfect duplicates are merged (same type and name). If sizes differ, the
* largest one is kept.
*/
struct sink *sink_new_buf(const char *name, const char *desc, enum sink_fmt fmt, size_t size)
struct sink *sink_new_buf(const char *name, const char *desc, enum log_fmt fmt, size_t size)
{
struct sink *sink;
@ -147,87 +147,16 @@ struct sink *sink_new_buf(const char *name, const char *desc, enum sink_fmt fmt,
* messages when there are any. It returns >0 if it could write anything,
* <=0 otherwise.
*/
ssize_t __sink_write(struct sink *sink, const struct ist msg[], size_t nmsg,
int level, int facility, struct ist *tag,
struct ist *pid, struct ist *sd)
{
int log_format;
char short_hdr[4];
struct ist pfx[6];
ssize_t __sink_write(struct sink *sink, const struct ist msg[], size_t nmsg,
int level, int facility, struct ist *metadata)
{
struct ist *pfx = NULL;
size_t npfx = 0;
char *hdr_ptr;
int fac_level;
if (sink->fmt == SINK_FMT_RAW)
if (sink->fmt == LOG_FORMAT_RAW)
goto send;
if (sink->fmt == SINK_FMT_SHORT || sink->fmt == SINK_FMT_TIMED) {
short_hdr[0] = '<';
short_hdr[1] = '0' + level;
short_hdr[2] = '>';
pfx[npfx].ptr = short_hdr;
pfx[npfx].len = 3;
npfx++;
if (sink->fmt == SINK_FMT_SHORT)
goto send;
}
if (sink->fmt == SINK_FMT_ISO || sink->fmt == SINK_FMT_TIMED) {
pfx[npfx].ptr = timeofday_as_iso_us(1);
pfx[npfx].len = 33;
npfx++;
goto send;
}
else if (sink->fmt == SINK_FMT_RFC5424) {
pfx[npfx].ptr = logheader_rfc5424;
pfx[npfx].len = update_log_hdr_rfc5424(date.tv_sec, date.tv_usec) - pfx[npfx].ptr;
log_format = LOG_FORMAT_RFC5424;
}
else {
pfx[npfx].ptr = logheader;
pfx[npfx].len = update_log_hdr(date.tv_sec) - pfx[npfx].ptr;
log_format = LOG_FORMAT_RFC3164;
sd = NULL;
}
fac_level = (facility << 3) + level;
hdr_ptr = pfx[npfx].ptr + 3; /* last digit of the log level */
do {
*hdr_ptr = '0' + fac_level % 10;
fac_level /= 10;
hdr_ptr--;
} while (fac_level && hdr_ptr > pfx[npfx].ptr);
*hdr_ptr = '<';
pfx[npfx].len -= hdr_ptr - pfx[npfx].ptr;
pfx[npfx].ptr = hdr_ptr;
npfx++;
if (tag && tag->len) {
pfx[npfx].ptr = tag->ptr;
pfx[npfx].len = tag->len;
npfx++;
}
pfx[npfx].ptr = get_format_pid_sep1(log_format, &pfx[npfx].len);
if (pfx[npfx].len)
npfx++;
if (pid && pid->len) {
pfx[npfx].ptr = pid->ptr;
pfx[npfx].len = pid->len;
npfx++;
}
pfx[npfx].ptr = get_format_pid_sep2(log_format, &pfx[npfx].len);
if (pfx[npfx].len)
npfx++;
if (sd && sd->len) {
pfx[npfx].ptr = sd->ptr;
pfx[npfx].len = sd->len;
npfx++;
}
pfx = build_log_header(sink->fmt, level, facility, metadata, &npfx);
send:
if (sink->type == SINK_TYPE_FD) {
@ -244,25 +173,41 @@ send:
* called under an exclusive lock on the sink to avoid multiple produces doing
* the same. On success, >0 is returned, otherwise <=0 on failure.
*/
int sink_announce_dropped(struct sink *sink, int facility, struct ist *pid)
int sink_announce_dropped(struct sink *sink, int facility)
{
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];
char logbuf[64];
struct ist sd;
struct ist tag;
while (unlikely((dropped = sink->ctx.dropped) > 0)) {
chunk_init(&msg, logbuf, sizeof(logbuf));
chunk_printf(&msg, "%u event%s dropped", dropped, dropped > 1 ? "s" : "");
msgvec[0] = ist2(msg.area, msg.data);
sd.ptr = default_rfc5424_sd_log_format;
sd.len = 2;
tag.ptr = global.log_tag.area;
tag.len = global.log_tag.data;
if (__sink_write(sink, msgvec, 1, LOG_NOTICE, facility, &tag, pid, &sd) <= 0)
if (!metadata[LOG_META_HOST].len) {
if (global.log_send_hostname)
metadata[LOG_META_HOST] = ist2(global.log_send_hostname, strlen(global.log_send_hostname));
else
metadata[LOG_META_HOST] = ist2(hostname, strlen(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));
}
if (__sink_write(sink, msgvec, 1, LOG_NOTICE, facility, metadata) <= 0)
return 0;
/* success! */
HA_ATOMIC_SUB(&sink->ctx.dropped, dropped);
@ -818,7 +763,7 @@ int cfg_parse_ring(const char *file, int linenum, char **args, int kwm)
goto err;
}
cfg_sink = sink_new_buf(args[1], args[1] , SINK_FMT_RAW, size);
cfg_sink = sink_new_buf(args[1], args[1], LOG_FORMAT_RAW, size);
if (!cfg_sink || cfg_sink->type != SINK_TYPE_BUFFER) {
ha_alert("parsing [%s:%d] : unable to create a new sink buffer for ring '%s'.\n", file, linenum, args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
@ -909,25 +854,8 @@ int cfg_parse_ring(const char *file, int linenum, char **args, int kwm)
goto err;
}
if (strcmp(args[1], "raw") == 0) {
cfg_sink->fmt = SINK_FMT_RAW;
}
else if (strcmp(args[1], "short") == 0) {
cfg_sink->fmt = SINK_FMT_SHORT;
}
else if (strcmp(args[1], "iso") == 0) {
cfg_sink->fmt = SINK_FMT_ISO;
}
else if (strcmp(args[1], "timed") == 0) {
cfg_sink->fmt = SINK_FMT_TIMED;
}
else if (strcmp(args[1], "rfc3164") == 0) {
cfg_sink->fmt = SINK_FMT_RFC3164;
}
else if (strcmp(args[1], "rfc5424") == 0) {
cfg_sink->fmt = SINK_FMT_RFC5424;
}
else {
cfg_sink->fmt = get_log_format(args[1]);
if (cfg_sink->fmt == LOG_FORMAT_UNSPEC) {
ha_alert("parsing [%s:%d] : unknown format '%s'.\n", file, linenum, args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
goto err;
@ -1079,9 +1007,9 @@ int post_sink_resolve()
static void sink_init()
{
sink_new_fd("stdout", "standard output (fd#1)", SINK_FMT_RAW, 1);
sink_new_fd("stderr", "standard output (fd#2)", SINK_FMT_RAW, 2);
sink_new_buf("buf0", "in-memory ring buffer", SINK_FMT_TIMED, 1048576);
sink_new_fd("stdout", "standard output (fd#1)", LOG_FORMAT_RAW, 1);
sink_new_fd("stderr", "standard output (fd#2)", LOG_FORMAT_RAW, 2);
sink_new_buf("buf0", "in-memory ring buffer", LOG_FORMAT_TIMED, 1048576);
}
static void sink_deinit()

View File

@ -230,7 +230,7 @@ void __trace(enum trace_level level, uint64_t mask, struct trace_source *src,
}
if (src->sink)
sink_write(src->sink, line, words, 0, 0, NULL, NULL, NULL);
sink_write(src->sink, line, words, 0, 0, NULL);
end:
/* check if we need to stop the trace now */