本文主要对 SOFA Tracer 工具类进行介绍。
虚拟日志上下文工具类
Tracer 提供 DummyContextUtil
类,对虚拟日志(dummy log)上下文进行操作。
使用 DummyContextUtil 创建虚拟日志上下文时,必须及时调用对应的销毁方法进行销毁。建议将对销毁方法的调用写入 finally 方法中。
创建虚拟日志上下文
定义:public static void createDummyLogContext() throws Exception
说明:创建一个虚拟日志上下文,并且将其设置到线程上下文中。如果当前线程上下文中已经有了一个日志上下文,则抛出异常。
清理虚拟日志上下文
定义:public static void clearDummyLogContext() throws Exception
说明:清除当前的虚拟的日志上下文。如果当前线程上下文中的日志上下文不是 DummyLogContext
,则抛出异常。
设置全链路压测标记,通过 clearDummyLogContext
类进行调用,如下代码所示:
DummyContextUtil.createDummyLogContext();
DummyContextUtil.addPenetrateAttribute(PenAttrKeyEnum.LOAD_TEST_MARK,"T");
DummyContextUtil.clearDummyLogContext();
Tracer 上下文工具类
此工具类的主要作用是为业务方提供获取 traceId 的统一方法,另外还提供了获取和设置穿透数据的 API,类名为 TracerContextUtil
,使用方法如下:
获取当前的 Tracer 上下文中 TraceId
代码示例:
String traceId =TracerContextUtil.getTraceId();
如果当前的 Tracer 上下文为空,此方法返回一个空字符串。
如果当前的 Tracer 上下文不为空,但是 traceId 为空,则返回一个空字符串。
如果当前的 Tracer 上下文不为空,同时 traceId 不为空,则返回 traceId 本身。
说明
获取 TraceId,前提是存在 TracerContext,而 TracerContext 的创建分为两种情形: SOFA MVC 系统:每一次访问时作为入口创建一个 TracerContext,如果想激活 MVC 请求的 Tracer 功能,还需要在 sofa-config 配置文件里配置上 mvc_toolbox_plugin=ACTIVE 来激活 MVC 的插件。 SOFA CORE 系统:作为 RPC 等中间件首次发生调用的时候创建。
在链路中添加自定义 Tag
在个性化业务场景中,您可以通过在业务类中调用 Tracer 类的方式,来设置自定义 tag 及对应的值,示例代码如下:
public void handlerXxx(Map<String,String> request){
SofaTraceContext ctx =SofaTraceContextHolder.getSofaTraceContext();
SofaTracerSpan span = ctx.getCurrentSpan();
//显式依赖 Tracer,会带来一定侵入性,请做好封装。
if(span !=null){
//将参数添加到自定义tag:xxx_phone 中
span.setTag("xxx_phone", request.get("phone"));
}
// 处理业务逻辑
// ...
}
有关自定义 Tag 的更多信息,参见 添加自定义业务 Tag。
设置穿透数据
代码示例:
TracerContextUtil.putPenetrateAttribute("Hello","World");
说明:
如果当前传入的 key 或者 value 为 null,则抛出 TracerException。
如果当前的 Tracer 的上下文为空,则抛出 TracerException。
当加入该穿透数据,如果整体穿透数据量超过了最大的限制(目前最大的限制为 1024 个字符),则抛出 TracerException。
关于 key 的说明:
由于此接口的 key 是全站共享的,所以使用这个 key 的时候,必须保证不和其他 key 冲突,所以 Tracer 中保留的 key 存在 uid 和 mark 两个字段。
获取 Tracer 中的穿透数据
代码示例:
TracerContextUtil.getPenetrateAttribute("Hello");
如果当前的 Tracer 的上下文不为空,并且 Tracer 上下文中根据 key 取到的穿透数据为 null,则返回一个空字符串。
如果当前的 Tracer 的上下文不为空,并且 Tracer 上下文中根据 key 取到的穿透数据不为 null,则返回穿透数据。
如果 key 为 null,则抛出该异常。
如果当前的 Tracer 的上下文为空,则抛出该异常。
克隆当前线程的 Tracer 日志上下文
如果业务系统有自己的线程池来处理一些事情,那么业务开发人员就可能需要获取当前线程的 Tracer 日志上下文,来设置到子线程里面去。在 Tracer 1.0.15 之前的版本,都是直接通过 API 来获取父线程的 Tracer 上下文,然后设置到子线程里面的。这样,父子线程就共享一份 Tracer 日志上下文,有可能出现在一个线程里修改,却影响了另一个线程的情况。
所以在 Tracer 1.0.15 中,提供一个克隆当前线程的 Tracer 日志上下文的 API。如果有需要往子线程中设置的话,可以采用此 API 来从父线程中复制一份,防止出现相互影响的状况,代码示例如下:
AbstractLogContext abstractLogContext =TracerContextUtil.cloneLogContext();
如果当前线程的 Tracer 日志上下文为空,则返回 null。
如果当前线程的 Tracer 日志上下文不为空,则返回此上下文的一份克隆。
全链路工具类
提供静态方法对全链路压测进行判断,类名为:LoadTestUtil
。
定义:public static boolean isLoadTestMode()
说明:判断当前是否为全链路压测。如果当前线程上下文中取不到日志上下文,则返回 false。如果能够取到并且压测标记为 T,则返回 true;否则,返回 false。
当全链路压测模式开启时,日志文件会打印在 ${logging.path}/logs/tracelog/shadow/
目录下,同时在日志文件的透传数据的字段会有mark=T
标识。