2017-05-05 11 views
3

(別のデバイス上の)ログサーバーへのソケットハンドラを作成して使用するアプリがあります。これは正常に動作します。java logging sockethandlerがまだ実行されているかどうかを確認するには?

ログサーバーが終了して再起動した場合、アプリケーションはこれを認識しません。アプリケーションは古いソケットハンドラを削除し、新しいソケットハンドラを追加する必要があります。

java logging sockethandlerがまだ実行されているかどうかを確認するにはどうすればよいですか?

編集:SocketHandler をラップし、例外をリッスンする(内部クラスなど)のカスタムjava.util.logging.ErrorManagerをインストールするには、プロキシハンドラを作成します

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; 
} 

答えて

0

と:私は動作するようです、それ以下のコードを思い付いエラー時に内部ハンドラを再接続してください。

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; 
     } 
    } 
} 

このコードは、通常のパスにソケットハンドラに公開されます:あなたが改善し、あなたがそれを使用する前にユニットがそれをテストすることを確認するためにここで

は、いくつかのサンプルコードです。例外として、ソケットハンドラを閉じて再作成します。それが失敗すると、このコードは最新の1000レコードまでの現行レコードを遅延発行用のキューに格納します。

ソケットハンドラを削除してロガーツリーに追加すると操作が面倒になり、ログレコードが失われたり、再接続が発生する可能性があります。プロキシハンドラを使用すると、再接続の回数を適切に制御することができ、そうしなければ失われる可能性のあるエラーを再発行することができます。

Javaロギングsockethandlerがまだ実行されているかどうかを確認するにはどうすればよいですか?

閉じたソケットを検出するためには、定期的にflushに電話をかけてみてください。しかし、それは過剰です。オブザーバーデバイスがダウンし、ソースアプリケーションにエラーが発生していない場合、ソケットが起動しているかどうかは問題になりません。おそらく、失敗時に反応することは、あなたがする必要があるだけです。

+0

可能な限り多くのメッセージを保存しようとしているように、 –

+0

の編集内容をご覧ください。私の場合、これらは、各デバイスのファイルアダプタにログオンするフィールドの専用タブレットです。タブレットを箱に取り付けることができるので、ケーブルを差し込むことは必ずしも実現可能ではない。ラップトップがwifiネットワークに表示され、ログをキャプチャすることがあります。だから、パワーサイクルや他のことがうまくいかなくなったときに、ソケットハンドラを終了して正常に再開したかったのです。 –

+0

@RayTayek例のコードは、接続が切断されたときにのみレコードを格納しています。すべてのパブリッシュは、ソケットハンドラの再接続とレコードのバックログの発行を試みます。 – jmehrens

関連する問題