2 ctdb logging code - syslog backend
4 Copyright (C) Andrew Tridgell 2008
5 Copyright (C) Martin Schwenke 2014
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "system/network.h"
23 #include "system/syslog.h"
24 #include "lib/util/debug.h"
25 #include "lib/util/blocking.h"
26 #include "ctdb_logging.h"
28 /* Linux and FreeBSD define this appropriately - try good old /dev/log
29 * for anything that doesn't... */
31 #define _PATH_LOG "/dev/log"
34 #define CTDB_LOG_SYSLOG_PREFIX "syslog"
35 #define CTDB_SYSLOG_FACILITY LOG_USER
37 struct ctdb_syslog_sock_state {
42 /**********************************************************************/
44 static int ctdb_debug_to_syslog_level(int dbglevel)
69 /**********************************************************************/
71 /* Format messages as per RFC3164. */
73 /* It appears that some syslog daemon implementations do not allow a
74 * hostname when messages are sent via a Unix domain socket, so omit
75 * it. A timestamp could be sent but rsyslogd on Linux limits the
76 * timestamp logged to the precision that was received on /dev/log.
77 * It seems sane to send degenerate RFC3164 messages without a header
78 * at all, so that the daemon will generate high resolution timestamps
80 static int format_rfc3164(int dbglevel, struct ctdb_syslog_sock_state *state,
81 const char *str, char *buf, int bsize)
86 pri = CTDB_SYSLOG_FACILITY | ctdb_debug_to_syslog_level(dbglevel);
87 len = snprintf(buf, bsize, "<%d>%s[%u]: %s%s",
88 pri, state->app_name, getpid(), debug_extra, str);
89 len = MIN(len, bsize - 1);
94 /**********************************************************************/
96 /* Non-blocking logging */
98 static void ctdb_log_to_syslog_sock(void *private_ptr,
99 int dbglevel, const char *str)
101 struct ctdb_syslog_sock_state *state = talloc_get_type(
102 private_ptr, struct ctdb_syslog_sock_state);
104 /* RFC3164 says: The total length of the packet MUST be 1024
109 n = format_rfc3164(dbglevel, state, str, buf, sizeof(buf));
111 fprintf(stderr, "Failed to format syslog message %s\n", str);
115 /* Could extend this to count failures, which probably
116 * indicate dropped messages due to EAGAIN or EWOULDBLOCK */
117 (void)send(state->fd, buf, n, 0);
121 ctdb_syslog_sock_state_destructor(struct ctdb_syslog_sock_state *state)
123 if (state->fd != -1) {
130 static int ctdb_log_setup_syslog_un(TALLOC_CTX *mem_ctx,
131 const char *app_name)
133 struct ctdb_syslog_sock_state *state;
134 struct sockaddr_un dest;
137 state = talloc_zero(mem_ctx, struct ctdb_syslog_sock_state);
142 state->fd = socket(AF_UNIX, SOCK_DGRAM, 0);
143 if (state->fd == -1) {
144 int save_errno = errno;
149 dest.sun_family = AF_UNIX;
150 strncpy(dest.sun_path, _PATH_LOG, sizeof(dest.sun_path)-1);
151 ret = connect(state->fd,
152 (struct sockaddr *)&dest, sizeof(dest));
154 int save_errno = errno;
158 set_blocking(state->fd, false);
160 state->app_name = app_name;
162 talloc_set_destructor(state, ctdb_syslog_sock_state_destructor);
163 debug_set_callback(state, ctdb_log_to_syslog_sock);
168 /**********************************************************************/
170 static void ctdb_log_to_syslog(void *private_ptr, int dbglevel, const char *s)
172 syslog(ctdb_debug_to_syslog_level(dbglevel),
173 "%s%s", debug_extra, s);
176 static int ctdb_log_setup_syslog(TALLOC_CTX *mem_ctx,
178 const char *app_name)
180 size_t l = strlen(CTDB_LOG_SYSLOG_PREFIX);
182 if (logging[l] != '\0') {
183 /* Handle non-blocking extensions here */
186 if (logging[l] != ':') {
189 method = &logging[0] + l + 1;
190 if (strcmp(method, "nonblocking") == 0) {
191 ctdb_log_setup_syslog_un(mem_ctx, app_name);
198 debug_set_callback(NULL, ctdb_log_to_syslog);
202 void ctdb_log_init_syslog(void)
204 ctdb_log_register_backend(CTDB_LOG_SYSLOG_PREFIX,
205 ctdb_log_setup_syslog);