转载

自定义ApiBoot Logging链路以及单元ID生成策略

ApiBoot Logging 会为每一个请求都对应创建链路编号( TraceID )以及单元编号( SpanID ),用于归类每一次请求日志,通过一个链路下日志单元的 Parent SpanID 可以进行上下级关系的梳理。

前文回顾

  • 使用ApiBoot Logging进行统一管理请求日志

  • 将ApiBoot Logging采集的日志上报到Admin

了解链路编号的传递方式

自定义ApiBoot Logging链路以及单元ID生成策略

在每一次请求中链路编号( traceId )、单元编号 (spanId) 都是通过 HttpHeader 的方式进行传递,日志的起始位置会主动生成 traceIdspanId ,而起始位置的 Parent SpanId 则是不存在的,值为 null

这样每次通过 restTemplateOpenfeign 的形式访问其他服务的接口时,就会 携带起始位置生成的 traceIdspanId 到下一个服务单元

默认编号

ApiBoot Logging 内部提供了默认的编号格式,默认为通用格式,没有区分性,无法从编号上进行区分日志的具体归类。

默认的链路编号

ApiBoot Logging 内部通过集成 minbox-logging 日志组件来完成日志的采集等基本功能,每一次生成采集的日志时都会通过 LoggingTraceGenerator 接口进行生成链路编号( TraceID ),该接口源码如下所示:

/**
 * ApiBoot Logging Tracer
 * Create new traceId
 *
 * @author:恒宇少年 - 于起宇
 * <p>
 * DateTime:2019-07-10 17:01
 * Blog:http://blog.yuqiyu.com
 * WebSite:http://www.jianshu.com/u/092df3f77bca
 * Gitee:https://gitee.com/hengboy
 * GitHub:https://github.com/hengboy
 */
public interface LoggingTraceGenerator {
    /**
     * create new traceId
     *
     * @return traceId
     * @throws MinBoxLoggingException exception
     */
    String createTraceId() throws MinBoxLoggingException;

}
复制代码

ApiBoot Logging 默认的链路编号( TraceID )采用的是 UUID随机字符串 的方式生成的,内部实现是通过 LoggingTraceGenerator 接口的默认实现类 LoggingDefaultTraceGenerator 进行生成,生成类源码如下所示:

/**
 * ApiBoot Logging Tracer Default Support Instance
 *
 * @author:恒宇少年 - 于起宇
 * <p>
 * DateTime:2019-07-10 17:28
 * Blog:http://blog.yuqiyu.com
 * WebSite:http://www.jianshu.com/u/092df3f77bca
 * Gitee:https://gitee.com/hengboy
 * GitHub:https://github.com/hengboy
 */
public class LoggingDefaultTraceGenerator implements LoggingTraceGenerator {
    /**
     * Use UUID as the default traceId
     *
     * @return traceId
     * @throws MinBoxLoggingException Exception
     */
    @Override
    public String createTraceId() throws MinBoxLoggingException {
        return UUID.randomUUID().toString();
    }
}

复制代码

默认的单元编号

单元编号 是一条链路下经过的每一个业务单元的唯一标识,在 SpringCloud 微服务的场景下每发起一个请求内部通过 Openfeign 可能会经过多个 服务 ,这样每经过的一个服务称之为单元,而当前这条链路下的单元唯一标识字符串就称为 单元编号

minbox-logging 提供了生成 单元编号 的接口 LoggingSpanGenerator ,源码如下所示:

/**
 * ApiBoot Logging Span
 * Create new spanId
 *
 * @author:恒宇少年 - 于起宇
 * <p>
 * DateTime:2019-07-10 17:02
 * Blog:http://blog.yuqiyu.com
 * WebSite:http://www.jianshu.com/u/092df3f77bca
 * Gitee:https://gitee.com/hengboy
 * GitHub:https://github.com/hengboy
 */
public interface LoggingSpanGenerator {
    /**
     * create new spanId
     *
     * @return span id
     * @throws MinBoxLoggingException exception
     */
    String createSpanId() throws MinBoxLoggingException;
}
复制代码

spanId 默认采用的跟 traceId 生成方式一致,都是 UUID 随机字符串, minbox-logging 提供了 LoggingSpanGenerator 接口默认的实现 LoggingDefaultSpanGenerator ,源码如下所示:

/**
 * ApiBoot Logging Default Span
 * Use By Create New SpanId
 *
 * @author:恒宇少年 - 于起宇
 * <p>
 * DateTime:2019-07-15 17:24
 * Blog:http://blog.yuqiyu.com
 * WebSite:http://www.jianshu.com/u/092df3f77bca
 * Gitee:https://gitee.com/hengboy
 * GitHub:https://github.com/hengboy
 */
public class LoggingDefaultSpanGenerator implements LoggingSpanGenerator {
    /**
     * Create New SpanId
     *
     * @return SpanId
     * @throws MinBoxLoggingException Exception
     */
    @Override
    public String createSpanId() throws MinBoxLoggingException {
        return UUID.randomUUID().toString();
    }
}
复制代码

自定义编号

我们可以根据自己的业务进行自定义 traceIdspanId ,可以加入一些自己业务的元素,只需要提供 minbox-logging 提供的生成 traceId 的接口 LoggingTraceGenerator 、生成 spanId 的接口 LoggingSpanGenerator 对应的实现类,并将实现类交给 LoggingFaceBean 管理即可。

自定义链路编号

/**
 * 自定义traceId生成策略
 *
 * @author 恒宇少年
 */
public class CustomTraceIdGenerator implements LoggingTraceGenerator {
    /**
     * 链路编号前缀
     */
    private static final String TRACE_ID_PREFIX = "local";
    
    @Override
    public String createTraceId() throws MinBoxLoggingException {
        return TRACE_ID_PREFIX + UUID.randomUUID().toString().hashCode();
    }
}
复制代码

我们创建名为 CustomTraceIdGenerator 的类并实现 LoggingTraceGenerator 接口,实现 createTraceId() 方法的返回值根据 local- 作为前缀,拼接 UUID 随机字符串的 hashCode 值作为后缀。

自定义单元编号

/**
 * 自定义单元编号生成策略
 *
 * @author 恒宇少年
 */
public class CustomSpanIdGenerator implements LoggingSpanGenerator {
    /**
     * 单元编号前缀
     */
    private static final String SPAN_ID_PREFIX = "group";

    @Override
    public String createSpanId() throws MinBoxLoggingException {
        return SPAN_ID_PREFIX + UUID.randomUUID().toString().hashCode();
    }
}
复制代码

我们创建名为 CustomSpanIdGenerator 的类并实现 LoggingSpanGenerator 接口,在 createSpanId() 方法的返回值根据 group- 作为前缀,使用 UUID 随机字符串的 hashCode 值作为后缀。

在上面我们已经创建了自定义 traceId 以及 spanId 的实现类,我们需要将实现类的实例交给 LoggingFactoryBean 管理,这样我们才可以实现自定义编号。

LoggingFactoryBeanCustomizer

ApiBoot Logging 提供了一个自定义设置 LoggingFactoryBean 的接口 LoggingFactoryBeanCustomizer ,通过该接口可以修改 LoggingFactoryBean 内允许修改的任意值。

我们创建名为 CustomCreateTraceAndSpanId 类并实现 LoggingFactoryBeanCustomizer 接口,源码如下所示:

/**
 * 自定义创建链路以及单元编号
 *
 * @author 恒宇少年
 * @see LoggingFactoryBeanCustomizer
 * @see LoggingFactoryBean
 * @see org.minbox.framework.logging.client.tracer.LoggingTraceGenerator
 * @see org.minbox.framework.logging.client.span.LoggingSpanGenerator
 */
@Component
public class CustomCreateTraceAndSpanId implements LoggingFactoryBeanCustomizer {
    /**
     * {@link CustomTraceIdGenerator} 自定义链路编号生成策略
     * {@link CustomSpanIdGenerator} 自定义单元编号生成策略
     *
     * @param factoryBean {@link LoggingFactoryBean}
     */
    @Override
    public void customize(LoggingFactoryBean factoryBean) {
        CustomTraceIdGenerator traceIdGenerator = new CustomTraceIdGenerator();
        factoryBean.setTraceGenerator(traceIdGenerator);

        CustomSpanIdGenerator spanIdGenerator = new CustomSpanIdGenerator();
        factoryBean.setSpanGenerator(spanIdGenerator);
    }
}

复制代码

customize 这种设计方式是在 SpringBoot 中比较常见的, ApiBoot 也沿用了这种设计方式, customize() 方法提供了 LoggingFactoryBean 对象实例作为参数,我们可以直接通过 setXxx 方法进行修改内定义的默认配置。

通过 facetory.setTraceGenerator 方法可以修改默认的 traceId 生成策略。

通过 facetory.setSpanGenerator 方法可以修改默认的 spanId 生成策略。

测试

启动项目后我们来查看控制台打印的日志内容,确认是否修改成功。

{
	"endTime":1571711067664,
	"httpStatus":200,
	"requestBody":"",
	"requestHeaders":{
		"accept":"*/*",
		"host":"localhost:8080",
		"user-agent":"curl/7.64.1"
	},
	"requestIp":"0:0:0:0:0:0:0:1",
	"requestMethod":"GET",
	"requestParam":"{}",
	"requestUri":"/index",
	"responseBody":"this is index.",
	"responseHeaders":{},
	"serviceId":"apiboot-custom-logging-traceid",
	"serviceIp":"127.0.0.1",
	"servicePort":"8080",
	"spanId":"group-1780993769",
	"startTime":1571711067643,
	"timeConsuming":21,
	"traceId":"local1111437283"
}
复制代码

traceIdspanId 已经修改成我们自定义的编号生成策略方式。

敲黑板划重点

本章节主要是讲到了如何自定义 traceId 以及 spanId ,我们可以通过 LoggingFactoryBeanCustomizerLoggingFactoryBean 对象进行深度的自定义配置,有关 ApiBoot Logging 使用的正确姿势还有很多,敬请期待。

请结合文中前文回顾部分进行编写测试。 作者个人 博客 使用开源框架 ApiBoot 助你成为Api接口服务架构师

原文  https://juejin.im/post/5dae6e08f265da5b5a722eab
正文到此结束
Loading...