javaloggingsyslogrsyslogsyslog4j

syslog4j stops logging when rsyslog restarted


After a restart of the rsyslog daemon, syslog4j 0.9.46 can no longer successfully write to the syslog without restarting the java process. No exception is thrown and I see no way to check, via the API, whether logging is still working. Is there some way to get syslog4j to recover from a rsyslog restart, or at least throw an exception so that the connection can be manually restarted?

Sample code:

import java.util.Scanner;

import org.productivity.java.syslog4j.SyslogConstants;
import org.productivity.java.syslog4j.SyslogIF;
import org.productivity.java.syslog4j.impl.unix.socket.UnixSocketSyslog;
import org.productivity.java.syslog4j.impl.unix.socket.UnixSocketSyslogConfig;


public class SysLogging {

    public static void main(String[] args) {
        UnixSocketSyslogConfig cfg = new UnixSocketSyslogConfig();
        cfg.setFacility(SyslogConstants.FACILITY_LOCAL1);
        cfg.removeAllMessageModifiers();
        cfg.setIdent(null);
        cfg.setThrowExceptionOnWrite(true);
        cfg.setWriteRetries(5);
        SyslogIF log = new UnixSocketSyslog();
        log.initialize(SyslogConstants.UNIX_SOCKET, cfg);

        Scanner scanner = new Scanner(System.in);
        System.out.println("type quit to quit, anything else to log");
        String line = scanner.nextLine();
        while(!line.equals("quit")) {
            log.info(line);
            System.out.println("type quit to quit, anything else to log");
            line = scanner.nextLine();
        }
        scanner.close();
    }
}

The code above works as you'd think until rsyslog is restarted. At that point no more messages appear in the syslog although everything seems to work otherwise.


Solution

  • Hack similar to this should help:

        SyslogIF log = new UnixSocketSyslog() {
            @Override
            protected void write(int level, byte[] message) throws SyslogRuntimeException {
                if (this.fd == -1)
                    connect();
                if (this.fd == -1)
                    return;
                ByteBuffer byteBuffer = ByteBuffer.wrap(message);
                int ret = this.libraryInstance.write(this.fd,byteBuffer,message.length);
                if (ret < 0) {
                    shutdown();
                    connect();
                    if (this.fd == -1)
                        return;
                    ret = this.libraryInstance.write(this.fd,byteBuffer,message.length);
                }
            }
        };