我希望为每个请求生成唯一的traceId,并将其传递给所有服务。在SpringMVC中,使用MDC上下文并将traceId放在头文件中相当容易,但在反应式堆栈中,由于ThreadLocal,它根本不起作用。
一般来说,我希望使用单个traceId记录我拥有的每个服务上的每个请求和响应,该traceId可以识别整个系统中的特定操作。
我试图根据文章创建自定义过滤器:https://azizulhaq-ananto.medium.com/how-to-handle-logs-and-tracing-in-spring-webflux-and-microservices-a0b45adc4610但它似乎不起作用。我目前的解决方案只有日志响应和TraceId在发出请求后丢失,所以没有on响应。让我们试着想象有两个服务:service1
和service2
。下面我试着勾勒出它应该如何工作。
它应该如何工作
客户端
-它实际上是如何工作的
客户端
-这是我的做法
@Component
public class TraceIdFilter implements WebFilter {
private static final Logger log = LoggerFactory.getLogger(TraceIdFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
Map<String, String> headers = exchange.getRequest().getHeaders().toSingleValueMap();
return Mono.fromCallable(() -> {
final long startTime = System.currentTimeMillis();
return new ServerWebExchangeDecorator(exchange) {
@Override
public ServerHttpRequest getRequest() {
return new RequestLoggingInterceptor(super.getRequest(), false);
}
@Override
public ServerHttpResponse getResponse() {
return new ResponseLoggingInterceptor(super.getResponse(), startTime, false);
}
};
}).contextWrite(context -> {
var traceId = "";
if (headers.containsKey("X-B3-TRACEID")) {
traceId = headers.get("X-B3-TRACEID");
MDC.put("X-B3-TraceId", traceId);
} else if (!exchange.getRequest().getURI().getPath().contains("/actuator")) {
traceId = UUID.randomUUID().toString();
MDC.put("X-B3-TraceId", traceId);
}
Context contextTmp = context.put("X-B3-TraceId", traceId);
exchange.getAttributes().put("X-B3-TraceId", traceId);
return contextTmp;
}).flatMap(chain::filter);
}
}
Github:https://github.com/Faelivrinx/kotlin-spring-boot
有什么现有的解决方案吗?
在SpringWebFlow中,您不再拥有ThreadLocal,但是您对每个链请求都有一个独特的上下文。您可以附加一个跟踪到这个上下文如下:
@Component
public class TraceIdFilter implements WebFilter {
private static final Logger log = LoggerFactory.getLogger(TraceIdFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return chain.filter(exchange)
.subscriberContext(
ctx -> {
.....
var traceId = UUID.randomUUID().toString();
return ctx.put("X-B3-TraceId", traceId);
.....
}
);
}
}
现在,服务中的链将在上下文中具有此属性。您可以使用静态方法Mono.subscriberContext()从服务中检索它。例如,您可以通过这种方式获取traceId
Mono.subscriberContext()
.flaMap(ctx -> {
.....
var traceId = ctx.getOrDefault("traceId", null);
.....
)
(我想一个选择是重新修改我们的Feign接口,使其具有@feignclient,并重新修改所有自定义拦截器、编码器等的应用方式,但最终这可能是一项很大的工作,风险也很大。) 我是否需要做一个特殊的请求拦截器来手动地注入这些(例如,从一个自动连线的跟踪器)?有没有一种干净的方法(或现有的类)来做到这一点?
跟踪行为控制着 Entity Framework Core 是否会在其变更跟踪器里维持实体实例的信息。如果实体是被跟踪的,任何检测到的该实体的变更都将在 SaveChanges() 时持久化到数据库中。Entity Framework Core 还会对已跟踪的、之前已加载到 DbContext 实例中的查询和实体进行相互的导航属性装配。 提示 你可以在 GitHub 上查阅当前文章涉及的代码样例。
我最近将我的项目从spring boot 1.4.1、spring cloud Sleuth 1.1.0、spring cloud Zipkin 1.1.0升级到spring boot 1.5.3、spring cloud Sleuth 1.2.0、spring cloud Zipkin 1.2.0。 在最新版本的spring cloud Sleuth中,他们添加了“错误”标签,一旦出现任何异常,
我试图使用grpc客户端的StackDrive/谷歌云跟踪定义在https://github.com/googleapis/googleapis/blob/master/google/devtools/cloudtrace/v1/trace.proto 我正在发送协议 但我得到的唯一回报是这个例外: 同样,我尝试了以下ListTrace请求 并获得: 我对API非常陌生,所以我不知道我在这里做错了
问题内容: 在程序快要结束时,我希望将类的所有实例中的特定变量加载到字典中。 例如: 假设实例数量会有所不同,我希望将Foo()的每个实例的x dict加载到新的dict中。我该怎么办? 我在SO中看到的示例假定一个已经具有实例列表。 问题答案: 跟踪实例的一种方法是使用类变量: 在程序结束时,您可以像下面这样创建字典: 只有一个列表:
Trace 事件提供了一种机制,可以集中由 V8,Node 核心, 以及用户代码生成的跟踪信息。 启动 Node.js 应用时添加 --trace-events-enabled 标记,可以启用 Tracing. 可以通过在 --trace-event-categories 标记后跟一个用逗号分隔的类别名称列表, 来指定特定的跟踪记录集合。 node 和 v8 默认启用。 node --trace-