skywalking agent中链路追踪的手动忽略采样
if (pathMatcher.match(pattern, operationName)) { //拿到请求路径和配置文件中的配置,进行匹配,匹配成功了,就证明是要ignore的,这儿就返回false。//通过createTraceContext去创建AbstractTracerContext,但是强制采样标识传递的是false。//这儿,在span数据没有跨线程、跨进程的时候,是不会走这儿的!
个人录制的skywalking 源码阅读课程,如果需要点开看看吧
skywalking agent+oap端源码阅读 + 二开实践 原创视频
在一个JVM进程中,一个线程请求产生的链路数据要不要采样在创建AbstractTracerContext的时候就已经决定了(其实,就是取决于创建TracingContext还是IgnoredTracerContext,说到底就是要不要去创建TraceSegment)。而AbstractTracerContext一般都是在创建EntrySpan的时候创建。
在agent的配置文件中,已经有一部分,主动忽略的文件了
agent.ignore_suffix=${SW_AGENT_IGNORE_SUFFIX:.jpg,.jpeg,.js,.css,.png,.bmp,.gif,.ico,.mp3,.mp4,.html,.svg}
但是,如果我要忽略前缀、路径之类的,应该怎么操作?
需要配合apm-trace-ignore-plugin完成,此插件在optional-plugins目录下,若要使用,需要拷贝到plugins目录下。
然后阅读trace-ignore-plugin.md文件,得知
## How to configure There are two ways to configure ignore patterns. Settings through system env has higher priority. 1. Set through the system environment variable,you need to add `skywalking.trace.ignore_path` to the system variables, the value is the path that you need to ignore, multiple paths should be separated by `,` 2. Create file named as `apm-trace-ignore-plugin.config` in `/agent/config/` dir, and add rules to filter traces
然后到配置文件,新增如下的配置
agent.trace.ignore_path=/user/**
其实,这儿的文档上是有坑的,我们需要改成如下的格式
trace.ignore_path=GET:/user/**
那么如果改成,上面的填写方式,会得到如下的链路图

User微服务的span都没有创建,那么我们来看源码。
我们知道,请求先进入Tomcat的拦截器的beforeMathod方法
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
Request request = (Request) allArguments[0];
ContextCarrier contextCarrier = new ContextCarrier();
CarrierItem next = contextCarrier.items();
while (next.hasNext()) {
next = next.next();
next.setHeadValue(request.getHeader(next.getHeadKey()));
}
String operationName = String.join(":", request.getMethod(), request.getRequestURI());
//通过createEntrySpan方法去创建EntrySpan
AbstractSpan span = ContextManager.createEntrySpan(operationName, contextCarrier);
Tags.URL.set(span, request.getRequestURL().toString());
Tags.HTTP.METHOD.set(span, request.getMethod());
span.setComponent(ComponentsDefine.TOMCAT);
SpanLayer.asHttp(span);
if (TomcatPluginConfig.Plugin.Tomcat.COLLECT_HTTP_PARAMS) {
collectHttpParam(request, span);
}
}
创建EntrySpan的逻辑
public static AbstractSpan createEntrySpan(String operationName, ContextCarrier carrier) {
AbstractSpan span;
AbstractTracerContext context;
operationName = StringUtil.cut(operationName, OPERATION_NAME_THRESHOLD);
//这儿,在span数据没有跨线程、跨进程的时候,是不会走这儿的!
if (carrier != null && carrier.isValid()) {
SamplingService samplingService = ServiceManager.INSTANCE.findService(SamplingService.class);
samplingService.forceSampled();
//如果上游有采样数据,那么这儿就需要使用强制采样。
context = getOrCreate(operationName, true);
span = context.createEntrySpan(operationName);
context.extract(carrier);
} else {
//这儿去创建AbstractTracerContext,但是强制采样标识传递的是false
context = getOrCreate(operationName, false);
span = context.createEntrySpan(operationName);
}
return span;
}
通过getOrCreate去创建AbstractTracerContext
private static AbstractTracerContext getOrCreate(String operationName, boolean forceSampling) {
AbstractTracerContext context = CONTEXT.get();
if (context == null) {
if (StringUtil.isEmpty(operationName)) {
if (LOGGER.isDebugEnable()) {
LOGGER.debug("No operation name, ignore this trace.");
}
context = new IgnoredTracerContext();
} else {
if (EXTEND_SERVICE == null) {
EXTEND_SERVICE = ServiceManager.INSTANCE.findService(ContextManagerExtendService.class);
}
//通过createTraceContext去创建AbstractTracerContext,但是强制采样标识传递的是false
context = EXTEND_SERVICE.createTraceContext(operationName, forceSampling);
}
CONTEXT.set(context);
}
return context;
}
通过createTraceContext去创建AbstractTracerContext
public AbstractTracerContext createTraceContext(String operationName, boolean forceSampling) {
AbstractTracerContext context;
if (!Config.Agent.KEEP_TRACING && GRPCChannelStatus.DISCONNECT.equals(status)) {
return new IgnoredTracerContext();
}
int suffixIdx = operationName.lastIndexOf(".");
if (suffixIdx > -1 && Arrays.stream(ignoreSuffixArray)
.anyMatch(a -> a.equals(operationName.substring(suffixIdx)))) {
context = new IgnoredTracerContext();
} else {
SamplingService samplingService = ServiceManager.INSTANCE.findService(SamplingService.class);
//此时强制采样forceSampling为false,那么就取决于samplingService.trySampling(operationName)
if (forceSampling || samplingService.trySampling(operationName)) {
context = new TracingContext(operationName, spanLimitWatcher);
} else {
context = new IgnoredTracerContext();
}
}
return context;
}
通过samplingService.trySampling(operationName)进入SamplingService,那,我们这儿进入的是SamplingService类么?其实不是,是进入的TraceIgnoreExtendService类!
@Override
public boolean trySampling(final String operationName) {
if (patterns.length > 0) {
for (String pattern : patterns) {
if (pathMatcher.match(pattern, operationName)) { //拿到请求路径和配置文件中的配置,进行匹配,匹配成功了,就证明是要ignore的,这儿就返回false
LOGGER.debug("operationName : " + operationName + " Ignore tracking");
return false;
}
}
}
return super.trySampling(operationName);
}
为什么会走TraceIgnoreExtendService?
更多推荐

所有评论(0)