2017-06-19 6 views
0

ログバック付きのgroovy構成を使用しています。時には、ディレクトリやファイルの場所をログに記録し、HTMLログにリンクとして表示したいと思います。ここで私の設定は現在のように見えます。ログバックのフォーマットリンク

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を生成するには、2つの障害があります。私はログバックに反対しています。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のような文字列を交換する前に、任意の不審な文字をエスケープしようとしています。

第2に、HTMLLayout escapes everythingですが、不正な表が生成されず、セキュリティが強化されます(スクリプトの挿入などはできません)。したがって、新しいコンバータを配線して正しく参照しても、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)は レイアウト( "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)'でログバック設定の最上部近くに登録します。この質問のために作成しました。 – roby

関連する問題