我花了一些时间来找出一种可持续的方法,从ERROR
服务器实时过滤掉我的应用程序中的JBoss
日志。使用Log4j
,我可以轻松使用SocketAppender
,并将其配置为实时通知ERROR
日志的方式。不幸的是我无法用JBoss AS 7
执行此操作。除了SocketAppender
之外,我找不到SMTPAppender
类型的实现。所以我想出了解决这个问题的方法。请看看到目前为止我做了什么。
我为Logger
编写了一种包装器。
我的应用程序的示例类
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyClass {
private Logger logger= LoggerFactory.getLogger(MyClass.class);
public void updateData(String data){
logger.info("updating data with {} ",data);
try {
// do somthing
}catch (Exception e){
//something went wrong
logger.error("update fail ",e);// I want to get this message real time
}
}
}
现在我想到了一种获取ERROR
日志的方法。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyLogger {
private Logger logger = null;
private MyLogger() {
}
public static MyLogger getLogger(Class clazz) {
MyLogger logger = new MyLogger();
logger.logger = LoggerFactory.getLogger(clazz);
return logger;
}
public void info(String format, Object... arguments) {
logger.info(format,arguments);
}
public void error(String format, Object... arguments) {
// now i can send this message real time,
// i am calling web service with error log by a new Thread
logger.error(format,arguments); // say line number 10
}
}
MyLogger
使用如下
public class MyClass {
private static MyLogger logger= MyLogger.getLogger(MyClass.class);
public void updateData(String data){
logger.info("updating data with {} ",data);
try {
// do somthing
}catch (Exception e){
//something went wrong
logger.error("update fail ",e); // say line number 14
}
}
}
此时我的要求匹配,但这会产生一个新问题。
以下是JBoss
<pattern-formatter pattern="%K{level}%d{HH:mm:ss,SSS} %-5p (%F:%L) (%t) %s%E%n"/>
现在%F
- 文件名将成为MyLogger
类。和%L
- 行号将成为导致不准确日志的MyLogger
行号。
示例日志的一部分
(MyLogger.java : 10) // but this should be (MyClass.java : 14)
现在我已将此模式更改为
<pattern-formatter pattern="%K{level}%d{HH:mm:ss,SSS} %-5p [%c:%L] (%t) %s%E%n"/>
这几乎可以正常工作,但是%c
- 类名按预期提供了正确的类。但是没有办法获得行号(正确的行号)。
改变记录器后,我得到了什么
(com.my.test.MyClass : 10) // but this should be (com.my.test.MyClass : 14)
以下是我的问题。
SocketAppender
或JMSAppender
)与JBoss AS7
一起使用?(找不到Jboss AS 7的解决方案)我已经在JBossDeveloper
中提出了一个问题。但至少还没有评论。
https://developer.jboss.org/thread/249729
任何帮助都非常感谢。
答案 0 :(得分:0)
如果您使用的版本与JBoss 7.2(EAP 6.1)相同或更高,则可以使用 Log4j appenders 作为自定义处理程序(check this issue)。
<强>例如强>
<custom-handler name="server" class="org.apache.log4j.net.SocketAppender" module="org.apache.log4j">
<level name="INFO"/>
<formatter>
<pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
</formatter>
<properties>
<property name="RemoteHost" value="10.10.10.10"/>
<property name="Port" value="1234"/>
<property name="LocationInfo" value="true"/>
<property name="ReconnectionDelay" value="10000"/>
</properties>
</custom-handler>
在其他情况下,使其在JBoss AS 7中运行的唯一方法是为java.util.logging.Handler
开发自定义SocketAppender
。
查看Creating a custom logging handler in JBOSS as 7.1.0 Final和Custom log handlers on 7.0.1以创建自定义日志处理程序,然后将其委派给Log4jAppenderHandler
。
例如(示例代码):
import java.util.Collections;
import java.util.logging.Filter;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.net.SocketAppender;
import org.apache.log4j.net.SyslogAppender;
import org.apache.log4j.spi.LocationInfo;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.ThrowableInformation;
import org.jboss.logmanager.ExtLogRecord;
import org.jboss.logmanager.log4j.handlers.Log4jAppenderHandler;
public class SocketHandler extends Handler {
private final Log4jAppenderHandler log4j = new Log4jAppenderHandler(new SocketAppender());
@Override
public void publish(LogRecord record) {
if (record == null) {
return;
}
ExtLogRecord extRecord;
if (record instanceof ExtLogRecord) {
extRecord = (ExtLogRecord) record;
} else {
extRecord = ExtLogRecord.wrap(record);
}
if (isLoggable(record)) {
LoggingEvent event = new LoggingEvent(extRecord.getLoggerClassName(),
Logger.getLogger(extRecord.getLoggerClassName()), extRecord.getMillis(),
Level.toLevel(extRecord.getLevel().toString()), extRecord.getFormattedMessage(),
extRecord.getThreadName(), extRecord.getThrown() == null ? null
: new ThrowableInformation(extRecord.getThrown()), extRecord.getNdc(),
new LocationInfo(new Throwable(), extRecord.getLoggerClassName()),
Collections.singletonMap("org.jboss.logmanager.record", extRecord));
((SyslogAppender) log4j.getAppender()).doAppend(event);
flush();
}
}
@Override
public void flush() {
log4j.flush();
}
@Override
public void close() throws SecurityException {
log4j.close();
}
@Override
public void setFilter(Filter filter) {
log4j.setFilter(filter);
}
@Override
public void setFormatter(Formatter formatter) {
log4j.setFormatter(formatter);
}
public void setThreshold(String threshold) {
((SocketAppender) log4j.getAppender()).setThreshold(Level.toLevel(threshold));
}
public void setRemoteHost(String remoteHost) {
((SocketAppender) log4j.getAppender()).setRemoteHost(remoteHost);
}
public void setPort(String port) {
try {
((SocketAppender) log4j.getAppender()).setPort(Integer.parseInt(port));
} catch (Exception e) {}
}
public void setReconnectionDelay(String reconnectionDelay) {
try {
((SocketAppender) log4j.getAppender()).setReconnectionDelay(Integer.parseInt(reconnectionDelay));
} catch (Exception e) {}
}
public void setLocationInfo(String locationInfo) {
try {
((SocketAppender) log4j.getAppender()).setLocationInfo(Boolean.parseBoolean(locationInfo));
} catch (Exception e) {}
}
}
我认为最好的方法就是这样,所以你不会在应用程序中使用日志记录实现。
我希望这有帮助。