表内にアンカータグまたはその他の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だ
はここで完全な実装です。
これは激しい、素晴らしい仕事です!あなたはすでにこれを持っていましたか、この質問のためだけにすべてを構築しましたか? – Steve
パターン内の%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
@Steveはい、'%m'を置き換えます。私はそれを 'conversionRule(" linkEscaper "、LinkConverter.class)'でログバック設定の最上部近くに登録します。この質問のために作成しました。 – roby