2017-06-19 30 views
0

我正在使用groovy配置和logback。偶尔,我会记录一个目录或文件位置,并且我希望它作为链接出现在我的HTML日志中。这是我的配置目前的样子。logback中的格式链接

appender("htmlLog", FileAppender) { 
    file = "${logPath}/${logName}.html" 
    append = false 
    encoder(LayoutWrappingEncoder) { 
    layout("ch.qos.logback.classic.html.HTMLLayout"){ 
     pattern = "%d{yyyy/MM/dd HH:mm:ss}%-5p%logger{0}%m" 
    } 
    } 
} 

任何人都有一个想法,我怎么能得到这个?

回答

1

在表格中生成锚标记或任何其他HTML有两个障碍。我正在对抗logback 1.2.3

首先,您需要一种方法来转换您的消息,寻找路径并将其替换为锚点。创建可以在模式中使用的自定义转换器非常简单,并且可以使用documented here。我的原油实现看起来是这样,你可能要修改的路径检测,以满足您:

package ch.qos.logback.classic.html; 

import ch.qos.logback.classic.pattern.ClassicConverter; 
import ch.qos.logback.classic.spi.ILoggingEvent; 
import ch.qos.logback.core.helpers.Transform; 

public class LinkConverter extends ClassicConverter { 
    public String convert(ILoggingEvent iLoggingEvent) { 
     String message = iLoggingEvent.getMessage(); 
     message = Transform.escapeTags(message); 
     message = message.replaceAll(" (/\\S+)", " <a href=\"$1\">file://$1</a>"); 
     return message; 
    } 
} 

这是试图用一个锚标记替换像/path/to/thing字符串之前转义任何可疑人物。

其次,HTMLLayout escapes everything,这是因为它不会生成格式不正确的表并提高安全性(脚本不能被注入等)。所以,即使您的新转换器连线并正确引用,HTMLLayout也会逃离主播。

为了解决这个问题,我扩展了HTMLLayout,但不幸的是,您必须重写该类的内涵并将其放在同一个包中以访问包专用字段。

所有你想改变的是逃跑线,我改变它为String s = c.getClass().equals(LinkConverter.class) ? c.convert(event): Transform.escapeTags(c.convert(event));试图尽量减少影响。

这里是全面实施:

package ch.qos.logback.classic.html; 

import ch.qos.logback.classic.spi.ILoggingEvent; 
import ch.qos.logback.core.CoreConstants; 
import ch.qos.logback.core.helpers.Transform; 
import ch.qos.logback.core.pattern.Converter; 

public class UnsafeHTMLLayout extends HTMLLayout{ 

    public String doLayout(ILoggingEvent event) { 
     StringBuilder buf = new StringBuilder(); 
     this.startNewTableIfLimitReached(buf); 
     boolean odd = true; 
     if((this.counter++ & 1L) == 0L) { 
      odd = false; 
     } 

     String level = event.getLevel().toString().toLowerCase(); 
     buf.append(CoreConstants.LINE_SEPARATOR); 
     buf.append("<tr class=\""); 
     buf.append(level); 
     if(odd) { 
      buf.append(" odd\">"); 
     } else { 
      buf.append(" even\">"); 
     } 

     buf.append(CoreConstants.LINE_SEPARATOR); 

     for(Converter c = this.head; c != null; c = c.getNext()) { 
      this.appendEventToBuffer(buf, c, event); 
     } 

     buf.append("</tr>"); 
     buf.append(CoreConstants.LINE_SEPARATOR); 
     if(event.getThrowableProxy() != null) { 
      this.throwableRenderer.render(buf, event); 
     } 

     return buf.toString(); 
    } 

    private void appendEventToBuffer(StringBuilder buf, Converter<ILoggingEvent> c, ILoggingEvent event) { 
     buf.append("<td class=\""); 
     buf.append(this.computeConverterName(c)); 
     buf.append("\">"); 
     String s = c.getClass().equals(LinkConverter.class) ? c.convert(event): Transform.escapeTags(c.convert(event)); 
     buf.append(s); 
     buf.append("</td>"); 
     buf.append(CoreConstants.LINE_SEPARATOR); 
    } 
} 

我最后的logback的配置是这样的:

import ch.qos.logback.classic.html.LinkConverter 

conversionRule("linkEscaper", LinkConverter.class) 

appender("htmlLog", FileAppender) { 
    file = "/tmp/out.html" 
    append = false 
    encoder(LayoutWrappingEncoder) { 
     layout("ch.qos.logback.classic.html.UnsafeHTMLLayout"){ 
      pattern = "%d{yyyy/MM/dd HH:mm:ss}%-5p%logger{0}%linkEscaper" 
     } 
    } 
} 

root(INFO, ["htmlLog"]) 

这里是my repo with this code

+0

这是一个激烈的,不错的工作!你有没有这个,或者你是否只是为了这个问题而构建它? – Steve

+0

我正确的说%linkEscaper取代了模式中的%m吗?我的问题是,log.info(“blahblah {}”,var)不会替代 layout(“ch.qos.logback.classic.html.CustomHTMLLayout”){pattern =“%d {yyyy/MM/dd HH:mm:ss}% - 5p%logger {0}%linkEscaper“} – Steve

+0

@Steve是它代替'%m'。我使用'conversionRule(“linkEscaper”,LinkConverter.class)''在logback配置的顶部附近注册它。为此问题构建它。 – roby