How can I tell if sockethandler is running in java log?

I have an application that creates a socket handler for my log server (on another device) and uses it. This works great.

If interrupting and restarting the log is interrupted, the application does not know this. The application should remove the old socket handler and add a new one.

How can I tell if sockethandler is running in java log?

Edit: I came up with some code that seems to work:

    public static class MySocketHandler extends SocketHandler {
        public MySocketHandler(String host,int port, Logger logger) throws IOException {
            super(host,port);
            this.logger=logger;
            setErrorManager(new ErrorManager() {
                @Override public synchronized void error(String msg,Exception ex,int code) {
                    super.error(msg,ex,code);
                    System.out.println("error: "+msg+", "+ex+", "+code);
                    removeHandler();
                    failed=true;
                }
            });
        }
        void removeHandler() {
            logger.removeHandler(MySocketHandler.this);
            System.out.println("removed my socket handler");
        }
        final Logger logger;
        Boolean failed=false;
}

      

+3


source to share


1 answer


Create a proxy handler to wrap the SocketHandler and set a custom java.util.logging.ErrorManager

(as inner class) to listen for exceptions and reconnect the inner handler on error.

Here's some sample code to improve, and make sure you unit test it before using it:

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayDeque;
import java.util.logging.ErrorManager;
import java.util.logging.Filter;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.SocketHandler;

public class ReconnectingSocketHandler extends Handler {

    private SocketHandler target;
    private boolean active;
    private final Watcher listener = new Watcher();
    private final ArrayDeque<LogRecord> pending = new ArrayDeque<>(1);

    public ReconnectingSocketHandler() {
        //@todo Read properties from LogManager.
    }

    @Override
    public synchronized void publish(LogRecord record) {
        if (!active) {  //Prevent reentrance.
            active = true;
            try {
                if (record != null && isLoggable(record)) {
                    pending.add(record);
                }

                //Store only the last few records only on error.
                if (pending.size() > 1000) {
                    pending.pollFirst();
                }

                //While we have retries and records.
                for (int r = 0; r < 2 && !pending.isEmpty(); ++r) {
                    if (target == null) {
                        //@todo implement time based backoff.
                        target = new SocketHandler();
                        target.setLevel(super.getLevel());
                        target.setEncoding(super.getEncoding());
                        target.setFilter(super.getFilter());
                        target.setFormatter(super.getFormatter());
                        target.setErrorManager(listener);
                    }

                    //Write the queue to the socket handler.
                    for (LogRecord lr; (lr = pending.poll()) != null;) {
                        target.publish(lr);
                        //On error, close and retry.
                        if (listener.last != null) {
                            pending.addFirst(lr);
                            reportError(null, listener.last,
                                    ErrorManager.WRITE_FAILURE);
                            listener.last = null;
                            target.close();
                            target = null;
                            break;
                        }
                    }
                }
            } catch (IOException ioe) {
                target = null; //Try again later.
                reportError(null, ioe, ErrorManager.WRITE_FAILURE);
            } finally {
                active = false;
            }
        }
    }

    @Override
    public synchronized void flush() {
        publish((LogRecord) null);
        if (target != null) {
            target.flush();
        }
    }

    @Override
    public synchronized void close() {
        super.setLevel(Level.OFF);
        flush();
        if (target != null) {
            target.close();
            target = null;
        }
    }

    @Override
    public synchronized void setLevel(Level newLevel) {
        super.setLevel(newLevel);
        if (target != null) {
            target.setLevel(newLevel);
        }
    }

    @Override
    public synchronized void setFilter(Filter newFilter) {
        super.setFilter(newFilter);
        if (target != null) {
            target.setFilter(newFilter);
        }
    }

    @Override
    public synchronized void setEncoding(String encoding) throws UnsupportedEncodingException {
        super.setEncoding(encoding);
        if (target != null) {
            target.setEncoding(encoding);
        }
    }

    @Override
    public synchronized void setFormatter(Formatter newFormatter) {
        super.setFormatter(newFormatter);
        if (target != null) {
            target.setFormatter(newFormatter);
        }
    }

    private class Watcher extends ErrorManager {

        Exception last;

        Watcher() {
        }

        @Override
        public void error(String msg, Exception ex, int code) {
            last = ex;
        }
    }
}

      

This code will publish to the socket handler in the normal path. In case of an exception, it closes and re-creates the socket handler. If that fails, this code will keep the current entry up to the last 1000 entries in the postponed queue.



Removing and adding a socket handler to the log tree is a flashy operation and can lead to lost log entries or failed reconnections. A proxy handler will allow you to properly control the number of retries and allows you to re-publish errors that would otherwise be lost.

How can I tell if sockethandler is running in java log?

You can call periodically flush

to detect a closed socket, but this is too much. If the watcher is off and there are no errors in the original application, it doesn't really matter if the socket is inserted or not. Reacting during a crash is probably all you need to do.

0


source







All Articles