1. 概述
在这篇文章中,我们将探讨Spring Cloud Sleuth,以及如何在Spring Boot中使用它进行追踪。它为我们的日志添加了有用的信息,通过为操作添加唯一的标识符,使得调试变得更加容易。在Sleuth术语中,这些操作称为“痕迹”,可能由多个称为“断点”的步骤组成。
例如,一个痕迹可能是一个从我们的应用程序查询数据的GET请求。当我们的应用程序处理请求时,它可以被分解为更小的步骤:用户授权、执行数据库查询、处理响应。每个步骤都是属于同一痕迹的独立断点。
在某些情况下,我们可能希望获取当前痕迹或断点的ID。例如,当发生问题时,我们可以将这些ID发送给开发团队。这样他们就可以使用这些信息来调试并解决问题。
2. 应用程序设置
首先,让我们创建一个Spring Boot项目,并添加**spring-cloud-starter-sleuth**依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
<version>3.1.0</version>
</dependency>
这个启动依赖与Spring Boot集成良好,并提供了使用Spring Cloud Sleuth所需的配置。
然而,我们还可以采取额外的步骤。在application.properties文件中设置我们应用的名称,这样我们在日志中可以看到它,以及痕迹和断点的ID:
spring.application.name=Baeldung Sleuth Tutorial
现在我们需要一个应用程序的入口点。让我们创建一个带有单个GET端点的REST控制器:
@RestController
public class SleuthTraceIdController {
@GetMapping("/traceid")
public String getSleuthTraceId() {
return "Hello from Sleuth";
}
}
访问我们的API端点http://localhost:8080/traceid,我们应该能看到“Hello from Sleuth”的响应。
3. 日志
让我们在getSleuthTraceId
方法中添加一个日志语句。首先,我们需要为我们的类添加一个Logger
,然后我们可以记录消息:
private static final Logger logger = LoggerFactory.getLogger(SleuthTraceIdController.class);
@GetMapping("/traceid")
public String getSleuthTraceId() {
logger.info("Hello with Sleuth");
return "Hello from Sleuth";
}
再次访问我们的API端点并检查日志。我们可能会看到类似这样的内容:
INFO [Baeldung Sleuth Tutorial,e48f140a63bb9fbb,e48f140a63bb9fbb] 9208 --- [nio-8080-exec-1] c.b.s.traceid.SleuthTraceIdController : Hello with Sleuth
请注意,应用名称在括号内开头。这些括号是由Sleuth添加的,代表应用名称、痕迹ID和断点ID。
4. 当前痕迹和断点
我们可以使用上述示例来调试应用程序中的问题,但可能难以确定原因并跟踪哪个痕迹。这就是为什么我们将获取当前痕迹并使用它进行进一步调查的原因。
在我们的实现中,我们将简化这个用例,只是将痕迹ID日志输出到控制台。
首先,我们需要获取一个Tracer
对象的实例。让我们将其注入到控制器中,并获取当前的断点:
@Autowired
private Tracer tracer;
@GetMapping("/traceid")
public String getSleuthTraceId() {
logger.info("Hello with Sleuth");
Span span = tracer.currentSpan();
return "Hello from Sleuth";
}
注意,currentSpan
方法在没有活动断点时可能返回null。因此,我们需要进行额外的检查,以确保在不引发NullPointerException
的情况下使用这个Span
对象。让我们实现这个检查并记录当前的痕迹和断点ID:
Span span = tracer.currentSpan();
if (span != null) {
logger.info("Trace ID {}", span.context().traceIdString());
logger.info("Span ID {}", span.context().spanIdString());
}
运行应用程序并在访问API端点时查找这些消息。它们应该包含与Sleuth添加的括号相同的ID。
5. 痕迹和断点ID作为十进制数
还有另一种方式通过spanId
方法而不是spanIdString
获取断点ID。两者之间的区别在于,后者返回的是值的十六进制表示,而前者返回的是十进制数。让我们在实际操作中比较它们,并同时记录十进制值:
Span span = tracer.currentSpan();
if (span != null) {
logger.info("Span ID hex {}", span.context().spanIdString());
logger.info("Span ID decimal {}", span.context().spanId());
}
两个值代表相同的数字,输出应类似于以下内容:
INFO [Baeldung Sleuth Tutorial,0de46b6fcbc8da83,0de46b6fcbc8da83] 8648 --- [nio-8080-exec-3] c.b.s.traceid.SleuthTraceIdController : Span ID hex 0de46b6fcbc8da83
INFO [Baeldung Sleuth Tutorial,0de46b6fcbc8da83,0de46b6fcbc8da83] 8648 --- [nio-8080-exec-3] c.b.s.traceid.SleuthTraceIdController : Span ID decimal 1001043145087572611
同样,对于痕迹ID也适用。除了traceIdString
,我们也可以使用traceId
方法。traceIdString
返回的是十六进制值,而traceId
返回的是十进制值:
logger.info("Trace ID hex {}", span.context().traceIdString());
logger.info("Trace ID decimal {}", span.context().traceId());
输出与之前的非常相似。它首先显示痕迹ID的十六进制形式,然后是十进制形式:
INFO [Baeldung Sleuth Tutorial,34ec0b8ac9d65e91,34ec0b8ac9d65e91] 7384 --- [nio-8080-exec-1] c.b.s.traceid.SleuthTraceIdController : Trace ID hex 34ec0b8ac9d65e91
INFO [Baeldung Sleuth Tutorial,34ec0b8ac9d65e91,34ec0b8ac9d65e91] 7384 --- [nio-8080-exec-1] c.b.s.traceid.SleuthTraceIdController : Trace ID decimal 3813435675195629201
6. 总结
在这篇文章中,我们讨论了Spring Cloud Sleuth如何帮助在Spring Boot中调试和追踪事件。首先,我们使用Tracer
对象引用当前的断点和TraceContext
。接着,我们能够获取当前痕迹和断点的ID。此外,我们还了解了不同方法如何以不同的数值系统返回ID。
如往常一样,包含这些示例的源代码可以在GitHub上找到。