ele*_*ype 5 grails logging log4j
我是Grails的新手,我正在尝试配置Log4j,因此它会记录日志调用发生的确切文件和行.没有模式可以作为conversionPattern!似乎Grails以Log4j看不到调用的真正来源的方式包装记录器.
我知道这个帖子,但我不确定如何创建自定义appender.我简直不敢相信没有人能够解决这个问题!
我愿意接受任何建议:
提前致谢!
我实际上是自己做的.我想我应该为它做一个正确的Grails插件,但是我仍然对Grails不够满意,以确保代码始终有效.我通过使用Grails 2.2.4从Controller和服务进行日志记录来测试它,它似乎运行良好.
它的工作原理是检查堆栈跟踪以找到发生调用的实际文件和行,然后在MDC线程上下文中添加此信息.添加到的值MDC可由(其他)appender使用%X{fileAndLine}令牌使用.
这是代码和javadoc(读它!):
package logFileLineInjectorGrailsPlugin
import org.apache.log4j.Appender;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.Logger;
import java.lang.StackTraceElement;
import org.apache.log4j.MDC;
/**
* Allows the log appenders to have access to the FILE and LINE where the log call actually occurred.
*
* (1) Add this pseudo appender to your other appenders, in Config.groovy. Then you can use
* "%X{fileAndLine}" in the other appenders to output the file and line where the log call actually occurred.
*
* ------------
* log4j = {
* appenders {
* appender name:'fileAndLineInjector', new logFileLineInjectorGrailsPlugin.FileAndLineInjector()
* // example of a console appender using the "%X{fileAndLine}" token :
* console name:'stdout', layout:pattern(conversionPattern: '[%d{yyyy-MM-dd HH:mm:ss}] %-5p ~ %m ~ %c ~ %X{fileAndLine}%n')
* }
* (...)
* ------------
*
* (2) Then add it has the *first* appender reference in the declarations of the loggers in which you want to use the "%X{fileAndLine}" token.
*
* For example :
*
* ------------
* root {
* error 'fileAndLineInjector', 'stdout'
* }
* ------------
*
* With this setup in place, a call to log.error("test!") will result in something like :
*
* [2013-08-12 19:16:15] ERROR ~ test! ~ grails.app.services.testProject.TestService ~ (TestService.groovy:8)
*
* In Eclipse/STS/GGTS (I didn't try in other IDEs), when "%X{fileAndLine}" is outputed in the internal console, the text is clickable
* and leads to the actual file/line.
*
*
*/
class FileAndLineInjector extends AppenderSkeleton {
@Override
public void close() {
}
@Override
public boolean requiresLayout() {
return false;
}
@Override
protected void append(LoggingEvent event) {
StackTraceElement[] strackTraceElements = Thread.currentThread().getStackTrace();
StackTraceElement targetStackTraceElement = null;
for(int i = 0; i < strackTraceElements.length; i++) {
StackTraceElement strackTraceElement = strackTraceElements[i];
if(strackTraceElement != null &&
strackTraceElement.declaringClass != null &&
strackTraceElement.declaringClass.startsWith("org.apache.commons.logging.Log\$") &&
i < (strackTraceElements.length - 1)) {
targetStackTraceElement = strackTraceElements[++i];
while(targetStackTraceElement.declaringClass != null &&
targetStackTraceElement.declaringClass.startsWith("org.codehaus.groovy.runtime.callsite.") &&
i < (strackTraceElements.length - 1)) {
targetStackTraceElement = strackTraceElements[++i];
}
break;
}
}
if(targetStackTraceElement != null) {
MDC.put("fileAndLine", "(" + targetStackTraceElement.getFileName() + ":" + targetStackTraceElement.getLineNumber() + ")");
} else {
MDC.remove("fileAndLine");
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果有什么不清楚,或者你找到了改进它的方法,请告诉我!