logback 自定义

1 篇文章 0 订阅

Overview

自定义Converter,通过conversionRule或者layout实现注入
常规使用Logback的方式不在本篇wiki的范围内
本文旨在解决我写的common_util.log组件在包装slf4j后丢失行号的问题,这是给出的logback解决方案

LineConverter

包装logback + slf4j之后,使用会丢失行号

    // 注入Converter,全局覆盖对“L”,“line”的处理
    <conversionRule conversionWord="L"
                    converterClass="com.qunar.flight.pangolin.pay.web.SimpleConverter" />
    <conversionRule conversionWord="line"
                    converterClass="com.qunar.flight.pangolin.pay.web.SimpleConverter" />



    // 针对appender设定Layout,局部覆盖defaultConverterMap
 <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender" >
    <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
         <layout class="com.qunar.flight.pangolin.pay.web.SimplePatternLayout"/>
    </encoder>
    <encoder>
        <pattern>${normal-pattern}</pattern>
        <charset>${encoding}</charset>
    </encoder>
 </appender>

Code

package com.qunar.flight.pangolin.pay.web;

import ch.qos.logback.classic.ClassicConstants;
import ch.qos.logback.classic.pattern.LineOfCallerConverter;
import ch.qos.logback.classic.spi.CallerData;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.LoggingEvent;

/**
 * @author guohang.ding on 16-11-10
 */
public class SimpleConverter extends LineOfCallerConverter {

    private static final String FQCN = com.qunar.flight.log.LogService.class.getName();
    private static final String FQCN_BY_UTIL = com.qunar.flight.log.LogUtil.class.getName();

    @Override
    public String convert(ILoggingEvent le) {
        if (!(le instanceof LoggingEvent)) {
            return super.convert(le);

        }
        if (!checkIsService(FQCN, FQCN_BY_UTIL)) {
            return super.convert(le);
        }
        StackTraceElement[] cda = getCallerData((LoggingEvent) le);
        if (cda != null && cda.length > 0) {
            return Integer.toString(cda[0].getLineNumber());
        } else {
            return CallerData.NA;
        }
    }

    private boolean checkIsService(String class1, String class2) {
        StackTraceElement[] steArray = new Throwable().getStackTrace();
        // check if LogService or LogUtil
        for (StackTraceElement aSteArray : steArray) {
            if (class1.equals(aSteArray.getClassName())
                    || class2.equals(aSteArray.getClassName())) {
                return true;
            }
        }
        return false;
    }

    private StackTraceElement[] getCallerData(LoggingEvent event) {
        if (event.hasCallerData()) {
            StackTraceElement[] array = extract(new Throwable(), FQCN, FQCN_BY_UTIL, ClassicConstants.DEFAULT_MAX_CALLEDER_DATA_DEPTH);
            event.setCallerData(array);
        }
        return event.getCallerData();
    }

    private StackTraceElement[] extract(Throwable t, String fqnOfInvokingClass, String fqnOfInvokingClass2, final int maxDepth) {
        if (t == null) {
            return null;
        }

        StackTraceElement[] steArray = t.getStackTrace();
        StackTraceElement[] callerDataArray;

        int found = CallerData.LINE_NA;
        for (int i = 0; i < steArray.length; i++) {
            if (CallerData.isDirectlyInvokingClass(steArray[i].getClassName(), fqnOfInvokingClass) || fqnOfInvokingClass.equals(fqnOfInvokingClass2)) {
                // the caller is assumed to be the next stack frame, hence the +1.
                found = i + 1;
            } else {
                if (found != CallerData.LINE_NA) {
                    break;
                }
            }
        }

        // we failed to extract caller data
        if (found == CallerData.LINE_NA) {
            return CallerData.EMPTY_CALLER_DATA_ARRAY;
        }

        int availableDepth = steArray.length - found;
        int desiredDepth = maxDepth < (availableDepth) ? maxDepth : availableDepth;

        callerDataArray = new StackTraceElement[desiredDepth];
        for (int i = 0; i < desiredDepth; i++) {
            callerDataArray[i] = steArray[found + i];
        }
        return callerDataArray;
    }
}


package com.qunar.flight.pangolin.pay.web;

import ch.qos.logback.classic.PatternLayout;

/**
 * @author guohang.ding on 16-11-10
 */
public class SimplePatternLayout extends PatternLayout {

    static {
        defaultConverterMap.put("L", SimpleConverter.class.getName());
        defaultConverterMap.put("line", SimpleConverter.class.getName());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值