ctdb-logging: Add logging via UDP to 127.0.0.1:514 to syslog backend
authorMartin Schwenke <martin@meltin.net>
Fri, 8 Aug 2014 10:59:21 +0000 (20:59 +1000)
committerAmitay Isaacs <amitay@samba.org>
Tue, 28 Oct 2014 04:42:04 +0000 (05:42 +0100)
This has most of the advantages of the old logd with none of the
complexity of the extra process.  There are several good syslog
implementations that can listen on the UDP port.

Signed-off-by: Martin Schwenke <martin@meltin.net>
Reviewed-by: Amitay Isaacs <amitay@gmail.com>
ctdb/config/ctdbd_wrapper
ctdb/config/functions
ctdb/doc/ctdbd.1.xml
ctdb/doc/ctdbd.conf.5.xml
ctdb/server/ctdb_logging_syslog.c

index dd9d66f4956ccca88b029abf653d43d53a6baa23..b22d1169a049275eca6501e3a7f0a26f0dc218c0 100755 (executable)
@@ -187,6 +187,9 @@ start()
     fi
 
     case "$CTDB_LOGGING" in
+       syslog:udp)
+           logger -t ctdbd "CTDB is being run with ${CTDB_LOGGING}.  If nothing is logged then check your syslogd configuration"
+           ;;
        syslog|syslog:*) : ;;
        file:*)
            logger -t ctdbd "CTDB is being run without syslog enabled.  Logs will be in ${CTDB_LOGGING#file:}"
index 5c9497dc520a97ed69ba0660e611ddc778f57100..53a36dc3355a80549521edfce63499a190c6f007 100755 (executable)
@@ -102,6 +102,8 @@ script_log ()
            } >>"$_file"
            ;;
        *)
+           # Handle all syslog:* variants here too.  There's no tool to do
+           # the lossy things, so just use logger.
            logger -t "ctdbd: ${_tag}" $*
            ;;
     esac
index fdf03d1e3a0d80a4f60d88616d8cd1a8d723d676..fabc2446fab0a394eb8e6986f8d8fcfb61edd2a5 100644 (file)
                      </para>
                    </listitem>
                  </varlistentry>
+                 <varlistentry>
+                   <term>udp</term>
+                   <listitem>
+                     <para>
+                       CTDB will log to syslog via UDP to
+                       localhost:514.  The syslog daemon must be
+                       configured to listen on (at least)
+                       localhost:514.  Most syslog daemons will log
+                       the messages with hostname "localhost" - this
+                       is a limitation of the implementation, for
+                       compatibility with more syslog daemons.
+                     </para>
+                   </listitem>
+                 </varlistentry>
                </variablelist>
              </listitem>
            </varlistentry>
index 95f37021d3a75ec6eda7b0a7780016be6c7c0e51..7eb191e60598a9612970b185e66f3f2ae61c21c0 100644 (file)
                      </para>
                    </listitem>
                  </varlistentry>
+                 <varlistentry>
+                   <term>udp</term>
+                   <listitem>
+                     <para>
+                       CTDB will log to syslog via UDP to
+                       localhost:514.  The syslog daemon must be
+                       configured to listen on (at least)
+                       localhost:514.  Most implementations will log
+                       the messages against hostname "localhost" -
+                       this is a limit of the implementation for
+                       compatibility with more syslog daemon
+                       implementations.
+                     </para>
+                   </listitem>
+                 </varlistentry>
                </variablelist>
              </listitem>
            </varlistentry>
index 6a3fd02c1622a1fd7bc8dedab71ee220586b9790..cc699556e338ed0edfae4535880226e5e4c0e12d 100644 (file)
@@ -72,11 +72,14 @@ static int ctdb_debug_to_syslog_level(int dbglevel)
 
 /* It appears that some syslog daemon implementations do not allow a
  * hostname when messages are sent via a Unix domain socket, so omit
- * it.  A timestamp could be sent but rsyslogd on Linux limits the
- * timestamp logged to the precision that was received on /dev/log.
- * It seems sane to send degenerate RFC3164 messages without a header
- * at all, so that the daemon will generate high resolution timestamps
- * if configured. */
+ * it.  Similarly, syslogd on FreeBSD does not understand the hostname
+ * part of the header, even when logging via UDP.  Note that most
+ * implementations will log messages against "localhost" when logging
+ * via UDP.  A timestamp could be sent but rsyslogd on Linux limits
+ * the timestamp logged to the precision that was received on
+ * /dev/log.  It seems sane to send degenerate RFC3164 messages
+ * without a header at all, so that the daemon will generate high
+ * resolution timestamps if configured. */
 static int format_rfc3164(int dbglevel, struct ctdb_syslog_sock_state *state,
                          const char *str, char *buf, int bsize)
 {
@@ -127,6 +130,23 @@ ctdb_syslog_sock_state_destructor(struct ctdb_syslog_sock_state *state)
        return 0;
 }
 
+static struct ctdb_syslog_sock_state *
+ctdb_log_setup_syslog_common(TALLOC_CTX *mem_ctx,
+                            const char *app_name)
+{
+       struct ctdb_syslog_sock_state *state;
+
+       state = talloc_zero(mem_ctx, struct ctdb_syslog_sock_state);
+       if (state == NULL) {
+               return NULL;
+       }
+       state->fd = -1;
+       state->app_name = app_name;
+       talloc_set_destructor(state, ctdb_syslog_sock_state_destructor);
+
+       return state;
+}
+
 static int ctdb_log_setup_syslog_un(TALLOC_CTX *mem_ctx,
                                    const char *app_name)
 {
@@ -134,7 +154,7 @@ static int ctdb_log_setup_syslog_un(TALLOC_CTX *mem_ctx,
        struct sockaddr_un dest;
        int ret;
 
-       state = talloc_zero(mem_ctx, struct ctdb_syslog_sock_state);
+       state = ctdb_log_setup_syslog_common(mem_ctx, app_name);
        if (state == NULL) {
                return ENOMEM;
        }
@@ -157,9 +177,41 @@ static int ctdb_log_setup_syslog_un(TALLOC_CTX *mem_ctx,
        }
        set_blocking(state->fd, false);
 
-       state->app_name = app_name;
+       debug_set_callback(state, ctdb_log_to_syslog_sock);
+
+       return 0;
+}
+
+static int ctdb_log_setup_syslog_udp(TALLOC_CTX *mem_ctx,
+                                    const char *app_name)
+{
+       struct ctdb_syslog_sock_state *state;
+       struct sockaddr_in dest;
+       int ret;
+
+       state = ctdb_log_setup_syslog_common(mem_ctx, app_name);
+       if (state == NULL) {
+               return ENOMEM;
+       }
+
+       state->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+       if (state->fd == -1) {
+               int save_errno = errno;
+               talloc_free(state);
+               return save_errno;
+       }
+
+       dest.sin_family = AF_INET;
+       dest.sin_port   = htons(514);
+       dest.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+       ret = connect(state->fd,
+                     (struct sockaddr *)&dest, sizeof(dest));
+       if (ret == -1) {
+               int save_errno = errno;
+               talloc_free(state);
+               return save_errno;
+       }
 
-       talloc_set_destructor(state, ctdb_syslog_sock_state_destructor);
        debug_set_callback(state, ctdb_log_to_syslog_sock);
 
        return 0;
@@ -191,6 +243,10 @@ static int ctdb_log_setup_syslog(TALLOC_CTX *mem_ctx,
                        ctdb_log_setup_syslog_un(mem_ctx, app_name);
                        return 0;
                }
+               if (strcmp(method, "udp") == 0) {
+                       ctdb_log_setup_syslog_udp(mem_ctx, app_name);
+                       return 0;
+               }
 
                return EINVAL;
        }