blob: 6cebf2aa5106dbab514ee5f1839a062d0715b51d [file] [log] [blame]
Willy Tarreau67b5a162019-08-11 16:38:56 +02001/*
2 * Event sink management
3 *
4 * Copyright (C) 2000-2019 Willy Tarreau - w@1wt.eu
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation, version 2.1
9 * exclusively.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <sys/uio.h>
22#include <common/compat.h>
23#include <common/config.h>
24#include <common/ist.h>
25#include <common/mini-clist.h>
26#include <proto/log.h>
27#include <proto/sink.h>
28
29struct list sink_list = LIST_HEAD_INIT(sink_list);
30
31struct sink *sink_find(const char *name)
32{
33 struct sink *sink;
34
35 list_for_each_entry(sink, &sink_list, sink_list)
36 if (strcmp(sink->name, name) == 0)
37 return sink;
38 return NULL;
39}
40
41/* creates a new sink and adds it to the list, it's still generic and not fully
42 * initialized. Returns NULL on allocation failure. If another one already
43 * exists with the same name, it will be returned. The caller can detect it as
44 * a newly created one has type SINK_TYPE_NEW.
45 */
46static __maybe_unused struct sink *__sink_new(const char *name, const char *desc, enum sink_fmt fmt)
47{
48 struct sink *sink;
49
50 sink = sink_find(name);
51 if (sink)
52 goto end;
53
54 sink = malloc(sizeof(*sink));
55 if (!sink)
56 goto end;
57
58 sink->name = name;
59 sink->desc = desc;
60 sink->fmt = fmt;
61 sink->type = SINK_TYPE_NEW;
62 /* set defaults for syslog ones */
63 sink->syslog_facility = 0;
64 sink->syslog_minlvl = 0;
65 sink->maxlen = MAX_SYSLOG_LEN;
66 /* address will be filled by the caller if needed */
67 sink->ctx.dropped = 0;
68 HA_RWLOCK_INIT(&sink->ctx.lock);
69 LIST_ADDQ(&sink_list, &sink->sink_list);
70 end:
71 return sink;
72}
73
74/* tries to send <nmsg> message parts (up to 8, ignored above) from message
75 * array <msg> to sink <sink>. Formating according to the sink's preference is
76 * done here. Lost messages are accounted for in the sink's counter.
77 */
78void sink_write(struct sink *sink, const struct ist msg[], size_t nmsg)
79{
80 struct iovec iovec[10];
81 char short_hdr[4];
82 size_t maxlen = sink->maxlen ? sink->maxlen : ~0;
83 size_t sent = 0;
84 int vec = 0;
85
86 /* keep one char for a possible trailing '\n' in any case */
87 maxlen--;
88
89 if (sink->fmt == SINK_FMT_SHORT) {
90 short_hdr[0] = '<';
91 short_hdr[1] = '0' + sink->syslog_minlvl;
92 short_hdr[2] = '>';
93
94 iovec[vec].iov_base = short_hdr;
95 iovec[vec].iov_len = MIN(maxlen, 3);
96 maxlen -= iovec[vec].iov_len;
97 vec++;
98 }
99
100 /* copy the remaining entries from the original message. Skip empty fields and
101 * truncate the whole message to maxlen.
102 */
103 while (nmsg && vec < (sizeof(iovec) / sizeof(iovec[0]) - 1)) {
104 iovec[vec].iov_base = msg->ptr;
105 iovec[vec].iov_len = MIN(maxlen, msg->len);
106 maxlen -= iovec[vec].iov_len;
107 if (iovec[vec].iov_len)
108 vec++;
109 msg++; nmsg--;
110 }
111
112 /* now deal with the various sink types here */
113
114 /* account for errors now */
115 if (sent <= 0)
116 HA_ATOMIC_ADD(&sink->ctx.dropped, 1);
117}
118
119/*
120 * Local variables:
121 * c-indent-level: 8
122 * c-basic-offset: 8
123 * End:
124 */