Grails 日志记录 - 是否有任何现有的解决方案能够记录实际发生调用的文件 + 行?

标签 grails logging log4j

我是 Grails 的新手,我正在尝试配置 Log4j,以便它记录发生日志调用的确切文件和行。否 pattern用作 conversionPattern ! Grails 似乎以一种 Log4j 看不到调用的真正来源的方式包装记录器。

我知道这个 thread ,但我不确定如何创建自定义 appender。我简直不敢相信没有人已经开发出一些东西来解决这个问题!

我愿意接受任何建议:

  • 在 Grails 中使用 Log4j 以外的其他东西是否可以获取实际的文件+行(Logback?)?
  • 有人愿意分享现有的“自定义附加程序”吗?

  • 提前致谢!

    最佳答案

    其实是我自己做的。我想我应该为它做一个合适的 Grails 插件,但我对 Grails 仍然不够满意,无法确保代码始终有效。我使用 Grails 2.2.4 通过从 Controller 和服务登录来测试它,它似乎运行良好。

    它的工作原理是检查堆栈跟踪以查找发生调用的实际文件和行,然后将此信息添加到 MDC 中。线程上下文。添加到 MDC 的值可以由(其他)附加程序使用 %X{fileAndLine} 使用 token 。

    这是代码和 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");
            }
        }
    }
    

    如果有什么不清楚的地方或者您找到改进方法,请告诉我!

    关于Grails 日志记录 - 是否有任何现有的解决方案能够记录实际发生调用的文件 + 行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18070863/

    相关文章:

    debugging - 如何在 Tomcat 中将日志级别设置为 DEBUG?

    java mybatis isTraceEnabled()Z错误

    grails - Grails和Tomcat重复 “java.lang.IllegalStateException: Cannot forward after response has been committed”错误

    linux - 在 Linux 中 : Print last line of log file that starts with

    javascript - Grails用 Angular 上传文件

    java - "GC--"在 java 垃圾收集日志中意味着什么?

    java - struts2 的 log4j 配置

    java - 设置 log4j 配置文件时出错

    grails - 禁用 Grails Spring Security 插件

    grails - grails注册页面