Jaeger UI使用、采集应用API排除特定路径
Jaeger使用
注:
Jaeger服务端版本为:jaegertracing/all-in-one-1.6.0
OpenTracing版本为:0.33.0,最后一个版本,停留在May 06, 2019。最好升级到OpenTelemetry。
Jaeger客户端版本为:jaeger-client-1.3.2
。
Tags
Tag是一个非常常见的概念,时序数据库如InfluxDB,Prometheus里的基础概念。Jaeger也有这个概念,如下Jaeger UI里有一个Tags,主要用于筛选过滤部分可能会造成干扰的数据。
点击某个Trace进去,会发现如下信息:
因此,可输入如下内容实现过滤搜索:
- 精确匹配:
hostname=DESKTOP-L20EH42
- 排除匹配:
hostname=~DESKTOP-L20EH42
其他可用的Tag(常用的在前面):
- hostname
- ip
http.status_code
http.method
http.url
jaeger.version
- component
span.kind
sampler.type
sampler.param
排除特定路径
如上图,Operation里列出该应用下的所有接口。
在k8s集群里,pod健康检查需要应用暴露一个/health
接口。这个/health
接口是写在框架Jar里的,而不是每个应用都写一个HealthController(虽然可以这样做,我在上家公司也这样干过)。
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
@Slf4j
@Component
@RequiredArgsConstructor
public class HealthyConfiguration implements ApplicationRunner {
private final RequestMappingHandlerMapping requestMappingHandlerMapping;
@Override
public void run(ApplicationArguments args) {
RequestMappingInfo healthRequestMappingInfo = RequestMappingInfo.paths("/health")
.methods(RequestMethod.GET)
.produces(MediaType.APPLICATION_JSON_VALUE)
.options(requestMappingHandlerMapping.getBuilderConfiguration())
.build();
Method healthMethod = ReflectionUtils.findMethod(getClass(), "health", HttpServletRequest.class, HttpServletResponse.class);
requestMappingHandlerMapping.registerMapping(healthRequestMappingInfo, this, healthMethod);
}
@ResponseBody
public R<String> health(HttpServletRequest request, HttpServletResponse response) {
return R.success("ok", "ok");
}
}
需求:类似于这个GitHub Issue,Jaeger能不能不收集应用下的特定接口,即,排除特定路径。
方案
经过各种尝试,以及Google,DeepSeek,ChatGPT,最后还是GitHub Copilot给出的答复能解决问题。
新增一个Filter类,当然这个Filter类也是需要放在框架Jar里,然后所有应用都需要去引用它:
import com.johnny.security.util.CommonUtil;
import io.opentracing.Tracer;
import io.opentracing.util.GlobalTracer;
import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* @author johnny
*/
@Configuration
public class TracingInterceptor implements Filter {
private final Tracer tracer;
public TracingInterceptor() {
this.tracer = GlobalTracer.get();
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
String path = CommonUtil.getRequestPath(request);
// 排除/health路径
if ("/health".equals(path)) {
// 停止当前请求的Tracing
tracer.activeSpan().finish();
chain.doFilter(servletRequest, response);
return;
}
chain.doFilter(servletRequest, response);
}
}
CommonUtil工具类如下:
public class CommonUtil {
/**
* 获取请求路径
*/
public static @NotNull String getRequestPath(HttpServletRequest request) {
String path = "";
String servletPath = request.getServletPath();
if (StrUtil.isNotBlank(servletPath)) {
path += servletPath;
}
String contextPath = request.getContextPath();
if (StrUtil.isNotBlank(contextPath)) {
path += contextPath;
}
String pathInfo = request.getPathInfo();
if (StrUtil.isNotBlank(pathInfo)) {
path += pathInfo;
}
return path;
}
}
参考
- GitHub Copilot