如何判断 java logging sockethandler 是否仍然是 运行?
How to tell if the java logging sockethandler is still running?
我有一个应用程序可以为我的日志服务器(在不同的设备上)创建套接字处理程序并使用它。这很好用。
如果日志服务器终止并重新启动,应用程序不知道这一点。该应用程序应删除旧的套接字处理程序并添加一个新的。
如何判断 java 日志套接字处理程序是否仍然是 运行?
编辑:我想出了下面似乎有效的代码:
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;
}
创建一个代理处理程序来包装 SocketHandler
并安装自定义 java.util.logging.ErrorManager
(作为内部 class)以侦听异常并在出错时重新连接内部处理程序。
下面是一些示例代码,供您改进并确保在使用前对其进行单元测试:
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 条记录以用于延迟发布。
删除套接字处理程序并将其添加到记录器树是一种不正当的操作,可能会导致丢失日志记录或大量重新连接。代理处理程序将允许您正确控制重新连接的次数,并允许您重新发布否则会丢失的错误。
How can I tell if the java logging sockethandler is still running?
您可以尝试定期调用 flush
来检测已关闭的套接字,但这有点矫枉过正。如果观察者设备关闭并且源应用程序中没有发生错误,那么套接字是否打开并不重要。在失败时做出反应可能就是您需要做的。
我有一个应用程序可以为我的日志服务器(在不同的设备上)创建套接字处理程序并使用它。这很好用。
如果日志服务器终止并重新启动,应用程序不知道这一点。该应用程序应删除旧的套接字处理程序并添加一个新的。
如何判断 java 日志套接字处理程序是否仍然是 运行?
编辑:我想出了下面似乎有效的代码:
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;
}
创建一个代理处理程序来包装 SocketHandler
并安装自定义 java.util.logging.ErrorManager
(作为内部 class)以侦听异常并在出错时重新连接内部处理程序。
下面是一些示例代码,供您改进并确保在使用前对其进行单元测试:
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 条记录以用于延迟发布。
删除套接字处理程序并将其添加到记录器树是一种不正当的操作,可能会导致丢失日志记录或大量重新连接。代理处理程序将允许您正确控制重新连接的次数,并允许您重新发布否则会丢失的错误。
How can I tell if the java logging sockethandler is still running?
您可以尝试定期调用 flush
来检测已关闭的套接字,但这有点矫枉过正。如果观察者设备关闭并且源应用程序中没有发生错误,那么套接字是否打开并不重要。在失败时做出反应可能就是您需要做的。