Logback 集成 Skywalking Trace ID 并结合skywalking agent源码进行分析(二)

日志中的Trace ID 如何在skywalking agent中进行添加

本文针对Logback 集成 Skywalking Trace ID 后,日志中的Trace ID在agent中如何添加做讲解


文章目录

  • 日志中的Trace ID 如何在skywalking agent中进行添加
  • 前言
  • 一、日志拦截源码分析
  • 二、拦截步骤
    • 1.日志入口类
    • 2.agent端源码
  • 总结


前言

skywalking agent 通过javaagent的方式集成到自身系统中,在对类加载之前进行拦截,然后通过字节码增强(bytebuddy)技术进行环绕增强,从而做到对类的字节码修改。


一、日志拦截源码分析

日志类字节码增加

二、拦截步骤

1.日志入口类

如下:TraceIdPatternLogbackLayout该类便是日志Tid添加的入口

  <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">

具体源码如下:

public class TraceIdPatternLogbackLayout extends PatternLayout {
    public TraceIdPatternLogbackLayout() {
    }

    static {
        defaultConverterMap.put("tid", LogbackPatternConverter.class.getName());
        defaultConverterMap.put("sw_ctx", LogbackSkyWalkingContextPatternConverter.class.getName());
    }
}

分析
可以看出该类会像defaultConverterMap中添加tid作为key ,LogbackPatternConverter类名作为value,那我们继续往下深入看。先点击defaultConverterMap,我截取PatternLayout 部分代码可以看出,这是所有pattern表达式的入口

public class PatternLayout extends PatternLayoutBase<ILoggingEvent> {
    public static final Map<String, String> defaultConverterMap = new HashMap();
    public static final String HEADER_PREFIX = "#logback.classic pattern: ";

    public PatternLayout() {
        this.postCompileProcessor = new EnsureExceptionHandling();
    }

    public Map<String, String> getDefaultConverterMap() {
        return defaultConverterMap;
    }

    public String doLayout(ILoggingEvent event) {
        return !this.isStarted() ? "" : this.writeLoopOnConverters(event);
    }

    protected String getPresentationHeaderPrefix() {
        return "#logback.classic pattern: ";
    }

    static {
        defaultConverterMap.putAll(Parser.DEFAULT_COMPOSITE_CONVERTER_MAP);
        defaultConverterMap.put("d", DateConverter.class.getName());
        defaultConverterMap.put("date", DateConverter.class.getName());
        defaultConverterMap.put("r", RelativeTimeConverter.class.getName());
        defaultConverterMap.put("relative", RelativeTimeConverter.class.getName());
        defaultConverterMap.put("level", LevelConverter.class.getName());
        defaultConverterMap.put("le", LevelConverter.class.getName());
        defaultConverterMap.put("p", LevelConverter.class.getName());
        defaultConverterMap.put("t", ThreadConverter.class.getName());
        defaultConverterMap.put("thread", ThreadConverter.class.getName());
        defaultConverterMap.put("lo", LoggerConverter.class.getName());

之后我们在点击LogbackPatternConverter该类,代码如下:

public class LogbackPatternConverter extends ClassicConverter {
    public LogbackPatternConverter() {
    }

    public String convert(ILoggingEvent iLoggingEvent) {
        return "TID: N/A";
    }
}

分析
该类中的convert方法便是我们之后将要在agent中要增强的类。他会返回实际的TID值。

2.agent端源码

首先在agent端找到apm-toolkit-activation包然后找到apm-toolkit-logback-1.x-activation包。
Logback 集成 Skywalking Trace ID 并结合skywalking agent源码进行分析(二)_第1张图片
之后进入包下找到LogbackPatternConverterActivation类,类源码如下:

public class LogbackPatternConverterActivation extends ClassInstanceMethodsEnhancePluginDefine {
    //实际拦截的类
    public static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.toolkit.activation.log.logback.v1.x.PrintTraceIdInterceptor";
    //需要增强的类名
    public static final String ENHANCE_CLASS = "org.apache.skywalking.apm.toolkit.log.logback.v1.x.LogbackPatternConverter";
    //需要增强的类名
    public static final String ENHANCE_METHOD = "convert";

    /**
     * @return the target class, which needs active.
     */
    @Override
    protected ClassMatch enhanceClass() {
        return byName(ENHANCE_CLASS);
    }

    /**
     * @return null, no need to intercept constructor of enhance class.
     */
    @Override
    public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
        return null;
    }

    /**
     * @return the collection of {@link StaticMethodsInterceptPoint}, represent the intercepted methods and their
     * interceptors.
     */
    @Override
    public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
        return new InstanceMethodsInterceptPoint[] {
            new InstanceMethodsInterceptPoint() {
                @Override
                public ElementMatcher<MethodDescription> getMethodsMatcher() {
                    return named(ENHANCE_METHOD).and(takesArgumentWithType(0, "ch.qos.logback.classic.spi.ILoggingEvent"));
                }

                @Override
                public String getMethodsInterceptor() {
                    return INTERCEPT_CLASS;
                }

                @Override
                public boolean isOverrideArgs() {
                    return false;
                }
            }
        };
    }
}

从代码中可以看出要增强的类的方法和skywalking实际拦截的类PrintTraceIdInterceptor


进入实际拦截的类PrintTraceIdInterceptor,代码如下:
public class PrintTraceIdInterceptor implements InstanceMethodsAroundInterceptor {
     //方法之前
    @Override
    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
        MethodInterceptResult result) throws Throwable {

    }
     //方法之后将在skywalking中实际产生的TraceId进行返回
    @Override
    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
        Object ret) throws Throwable {
        if (!ContextManager.isActive()) {
            if (allArguments[0] instanceof EnhancedInstance) {
                SkyWalkingContext skyWalkingContext = (SkyWalkingContext) ((EnhancedInstance) allArguments[0]).getSkyWalkingDynamicField();
                if (skyWalkingContext != null) {
                    return "TID:" + skyWalkingContext.getTraceId();
                }
            }
        }
        return "TID:" + ContextManager.getGlobalTraceId();
    }
    //异常处理
    @Override
    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
        Class<?>[] argumentsTypes, Throwable t) {

    }
}

总结

skywalking agent 源码部分相对比较简单,主要就是通过字节码增强技术在写入TID换成skywalking的链路跟踪里的TraceID。

字节码增强技术byteBuddy

你可能感兴趣的:(skywalking,skywalking)