Using OpenTelemetry Tracing
本指南解释了 Quarkus 应用程序如何利用 OpenTelemetry (OTel) 为交互式 Web 应用程序提供分布式跟踪。
|
Prerequisites
Unresolved directive in opentelemetry-tracing.adoc - include::{includes}/prerequisites.adoc[]
Solution
我们建议你按照后续章节中的说明,逐步创建应用程序。但是,你可以直接跳到已完成的示例。
克隆 Git 存储库: git clone {quickstarts-clone-url},或下载 {quickstarts-archive-url}[存档]。
解决方案位于 opentelemetry-quickstart directory。
Creating the Maven project
首先,我们需要一个新项目。使用以下命令创建一个新项目:
Unresolved directive in opentelemetry-tracing.adoc - include::{includes}/devtools/create-app.adoc[]
此命令会生成 Maven 项目并导入 quarkus-opentelemetry 扩展,其中包括默认的 OpenTelemetry 支持以及用于 OTLP 的 gRPC span 导出器。
如果 Quarkus 项目已配置,则可以通过在项目基本目录中运行以下命令来将 quarkus-opentelemetry 扩展添加到项目中:
Unresolved directive in opentelemetry-tracing.adoc - include::{includes}/devtools/extension-add.adoc[]
这会将以下内容添加到构建文件中:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-opentelemetry</artifactId>
</dependency>
implementation("io.quarkus:quarkus-opentelemetry")
Examine the Jakarta REST resource
使用以下内容创建 src/main/java/org/acme/opentelemetry/TracedResource.java 文件:
package org.acme.opentelemetry;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import org.jboss.logging.Logger;
@Path("/hello")
public class TracedResource {
private static final Logger LOG = Logger.getLogger(TracedResource.class);
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
LOG.info("hello");
return "hello";
}
}
请注意,应用程序中不包含任何跟踪特定代码。默认情况下,发送到此端点的请求将在无需任何所需代码更改的情况下被跟踪。
Run the application
首先我们需要启动一个系统来可视化 OpenTelemetry 数据。我们有 2 个选项:
-
为跟踪和指标启动一体化 Grafana OTel LGTM 系统。
-
Jaeger 系统仅用于跟踪。
Grafana OTel LGTM option
此功能包含 Quarkus Dev 服务,其中包括用于可视化数据的 Grafana、用于存储日志的 Loki、用于存储跟踪的 Tempo 以及用于存储指标的 Prometheus。还提供和 OTel 收集器来接收数据。
Jaeger to see traces option
配置并启动 OpenTelemetry Collector 以接收、处理和将遥测数据导出到 Jaeger,该数据将显示捕获的跟踪。
|
一体化 Jaeger 包括 Jaeger 代理、OTel 收集器和查询服务/UI。您无需安装单独收集器。您可以直接将跟踪数据发送到 Jaeger(在此处启用 OTLP 接收器后,参见此 blog entry 了解更多详细信息)。 |
通过以下 docker-compose.yml 文件启动 OpenTelemetry 收集器和 Jaeger 系统,您可以通过 docker-compose up -d 启动此文件:
version: "2"
services:
# Jaeger
jaeger-all-in-one:
image: jaegertracing/all-in-one:latest
ports:
- "16686:16686" # Jaeger UI
- "14268:14268" # Receive legacy OpenTracing traces, optional
- "4317:4317" # OTLP gRPC receiver
- "4318:4318" # OTLP HTTP receiver, not yet used by Quarkus, optional
- "14250:14250" # Receive from external otel-collector, optional
environment:
- COLLECTOR_OTLP_ENABLED=true
您应删除不需要的可选端口。
Start the application
现在我们已准备好运行我们的应用程序。如果使用 application.properties 配置跟踪器:
Unresolved directive in opentelemetry-tracing.adoc - include::{includes}/devtools/dev.adoc[]
或者通过 JVM 参数配置 OTLP gRPC 端点:
include::{includes}/devtools/dev.adoc[]:!dev-additional-parameters:
当 OpenTelemetry 收集器、Jaeger 系统和应用程序正在运行时,可以向提供的端点发出请求:
$ curl http://localhost:8080/hello
hello
当提交第一个请求时,您将能够在日志中看到跟踪信息:
10:49:02 INFO traceId=, parentId=, spanId=, sampled= [io.quarkus] (main) Installed features: [cdi, opentelemetry, resteasy-client, resteasy, smallrye-context-propagation, vertx]
10:49:03 INFO traceId=17ceb8429b9f25b0b879fa1503259456, parentId=3125c8bee75b7ad6, spanId=58ce77c86dd23457, sampled=true [or.ac.op.TracedResource] (executor-thread-1) hello
10:49:03 INFO traceId=ad23acd6d9a4ed3d1de07866a52fa2df, parentId=, spanId=df13f5b45cf4d1e2, sampled=true [or.ac.op.TracedResource] (executor-thread-0) hello
然后访问 Jaeger UI 以查看跟踪信息。
按 CTRL+C 或键入 q 停止应用程序。
JDBC
JDBC instrumentation 会为您的应用程序执行的每个 JDBC 查询添加一个 span,要启用它,请将以下依赖项添加到您的构建文件:
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-jdbc</artifactId>
</dependency>
implementation("io.opentelemetry.instrumentation:opentelemetry-jdbc")
由于它使用专用 JDBC 数据源包装器,因此您必须为数据源启用遥测:
# enable tracing
quarkus.datasource.jdbc.telemetry=true
# configure datasource
quarkus.datasource.db-kind=postgresql
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/mydatabase
Additional configuration
某些用例将需要 OpenTelemetry 的自定义配置。这些章节将概述正确配置它所需的步骤。
ID Generator
OpenTelemetry 扩展将默认情况下在创建跟踪和跨度标识符时使用随机 ID Generator。
某些特定于供应商的协议需要自定义 ID 生成器,可通过创建生成器来覆盖默认值。OpenTelemetry 扩展将检测 `IdGenerator`CDI bean,并在配置跟踪生成器时使用该 bean。
@Singleton
public class CustomConfiguration {
/** Creates a custom IdGenerator for OpenTelemetry */
@Produces
@Singleton
public IdGenerator idGenerator() {
return AwsXrayIdGenerator.getInstance();
}
}
Propagators
OpenTelemetry 通过 propagators跨越式地传播关注点,该关注点将共享一个底层的 `Context`以在分布式事务的生命周期中存储状态和访问数据。
默认情况下,OpenTelemetry 扩展启用 W3C Trace Context和 W3C Baggage传播器,但是,您可以通过设置 OpenTelemetry Configuration Reference中描述的 `propagators`配置来选择任何受支持的 OpenTelemetry 传播器。
Additional Propagators
-
b3、b3multi、`jaeger`和 `ottrace`传播器需要将 trace-propagators扩展作为依赖项添加到您的项目中。
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-extension-trace-propagators</artifactId>
</dependency>
implementation("io.opentelemetry:opentelemetry-extension-trace-propagators")
-
`xray`传播器需要将 aws扩展作为依赖项添加到您的项目中。
<dependency>
<groupId>io.opentelemetry.contrib</groupId>
<artifactId>opentelemetry-aws-xray-propagator</artifactId>
</dependency>
implementation("io.opentelemetry.contrib:opentelemetry-aws-xray-propagator")
Customise Propagator
若要自定义传播报头,您可以实现 `TextMapPropagatorCustomizer`接口。例如,可将其用于限制 OpenTelemetry 跟踪报头传播并防止机密数据被发送到第三方系统。
/**
* /**
* Meant to be implemented by a CDI bean that provides arbitrary customization for the TextMapPropagator
* that are to be registered with OpenTelemetry
*/
public interface TextMapPropagatorCustomizer {
TextMapPropagator customize(Context context);
interface Context {
TextMapPropagator propagator();
ConfigProperties otelConfigProperties();
}
}
Resource
请参阅主 OpenTelemetry Guide resources 部分。
End User attributes
启用时,Quarkus 将 OpenTelemetry 最终用户属性作为跨度属性添加。在启用此功能之前,请验证 Quarkus Security 扩展是否存在且已配置。有关 Quarkus Security 的更多信息,请参阅 Quarkus Security overview。
只有在已尽力进行身份验证的情况下才会添加属性。是否将最终用户属性作为跨度属性添加取决于 Quarkus 应用程序的身份验证和授权配置。如果您在身份验证之前创建自定义跨度,Quarkus 无法向其添加最终用户属性。身份验证完成后,Quarkus 只能将属性添加到当前跨度。关于自定义跨度的另一个重要事项是用于传播 Quarkus `SecurityIdentity`的活动 CDI 请求上下文。原则上,当在创建自定义跨度之前已为您激活 CDI 请求上下文时,Quarkus 能够添加最终用户属性。
quarkus.otel.traces.eusp.enabled=true 1
quarkus.http.auth.proactive=true 2
<1> 启用最终用户属性功能,以便将 `SecurityIdentity`主体和角色作为跨度属性添加。最终用户属性是个人身份信息,因此在启用此功能之前,请确保您要导出这些信息。 <1> 选择性地启用主动身份验证。在启用主动身份验证时,可实现最佳效果,因为身份验证会更早发生。确定是否应在 Quarkus 应用程序中启用主动身份验证的一个好方法是阅读 Quarkus xref:security-proactive-authentication.adoc[Proactive authentication]指南。
当使用自定义 Jakarta REST SecurityContexts时,不支持此功能。
Sampler
sampler决定是否应放弃或转发跟踪,它有效地管理噪声,并通过限制发送给收集器的收集的跟踪数来减少开销。
Quarkus 配备了 built-in sampler,您还可以选择创建自定义抽样器。
若要使用内置抽样器,您可以通过设置 OpenTelemetry Configuration Reference中详述的所需抽样器参数来对其进行配置。例如,您可以将抽样器配置为保留 50% 的跟踪:
# build time property only:
quarkus.otel.traces.sampler=traceidratio
# Runtime property:
quarkus.otel.traces.sampler.arg=0.5
|
抽样器的一个有趣用例是根据此示例在运行时激活和停用跟踪导出:
|
|
Quarkus 3.0 在配置方面引入了重大变更。
抽样器相关的属性名称和值更改以符合最新的 Java OpenTelemetry SDK。在过渡期间,可以将新配置值设置为旧属性,因为我们正在映射
|
如果您需要使用自定义采样器,现在有 2 种不同的方法:
Sampler CDI Producer
您可以创建一个采样器 CDI 制造者。Quarkus OpenTelemetry 扩展将检测 Sampler CDI bean,并在配置 Tracer 时使用它。
@Singleton
public class CustomConfiguration {
/** Creates a custom sampler for OpenTelemetry */
@Produces
@Singleton
public Sampler sampler() {
return JaegerRemoteSampler.builder()
.setServiceName("my-service")
.build();
}
}
OTel Sampler SPI
这将使用 OTel 自动配置提供的 SPI 钩子。您可以创建简单的采样器类:
public class CustomSPISampler implements Sampler {
@Override
public SamplingResult shouldSample(Context context,
String s,
String s1,
SpanKind spanKind,
Attributes attributes,
List<LinkData> list) {
// Do some sampling here
return Sampler.alwaysOn().shouldSample(context, s, s1, spanKind, attributes, list);
}
@Override
public String getDescription() {
return "custom-spi-sampler-description";
}
}
然后是采样器提供程序:
public class CustomSPISamplerProvider implements ConfigurableSamplerProvider {
@Override
public Sampler createSampler(ConfigProperties configProperties) {
return new CustomSPISampler();
}
@Override
public String getName() {
return "custom-spi-sampler";
}
}
在 resources/META-INF/services 上使用名称 io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider 编写 SPI 加载器文本文件,其中包含 CustomSPISamplerProvider 类的完全限定名称。
然后在配置中激活:
quarkus.otel.traces.sampler=custom-spi-sampler
如您所见,CDI 更易于使用。
Additional instrumentation
某些 Quarkus 扩展将需要额外的代码来确保跟踪传播到后续执行。这些部分将概述跨进程边界传播跟踪所需的条件。
本节中记录的检测已通过 Quarkus 测试,并且可在标准模式和原生模式下工作。
CDI
使用 io.opentelemetry.instrumentation.annotations.WithSpan 注释对任何 CDI 感知 bean 中的方法进行注释将创建一个新 Span,并与当前 Trace 上下文建立任何所需的关系。
使用 io.opentelemetry.instrumentation.annotations.AddingSpanAttributes 对任何 CDI 感知 bean 中的方法进行注释不会创建新 Span,而是将带注释的方法参数添加到当前 Span 中的属性。
如果某个方法错误地使用 @AddingSpanAttributes 和 @WithSpan 注释进行了注释,那么 @WithSpan 注释将具有优先权。
方法参数可以使用 io.opentelemetry.instrumentation.annotations.SpanAttribute 注释进行注释,以指示哪些方法参数应成为 Span 的一部分。参数名称也可以自定义。
示例:
@ApplicationScoped
class SpanBean {
@WithSpan
void span() {
}
@WithSpan("name")
void spanName() {
}
@WithSpan(kind = SERVER)
void spanKind() {
}
@WithSpan
void spanArgs(@SpanAttribute(value = "arg") String arg) {
}
@AddingSpanAttributes
void addArgumentToExistingSpan(@SpanAttribute(value = "arg") String arg) {
}
}
Available OpenTelemetry CDI injections
根据 MicroProfile Telemetry Tracing 规范,Quarkus 支持下列类的 CDI 注入:
-
io.opentelemetry.api.OpenTelemetry -
io.opentelemetry.api.trace.Tracer -
io.opentelemetry.api.trace.Span -
io.opentelemetry.api.baggage.Baggage
您可以在任何启用了 CDI 的 bean 中注入这些类。例如,Tracer 对于启动自定义 Span 特别有用:
@Inject
Tracer tracer;
...
public void tracedWork() {
Span span = tracer.spanBuilder("My custom span")
.setAttribute("attr", "attr.value")
.setParent(Context.current().with(Span.current()))
.setSpanKind(SpanKind.INTERNAL)
.startSpan();
// traced work
span.end();
}
Quarkus Messaging - Kafka
在使用针对 Kafka 的 Quarkus 消息传递扩展时,我们可以将跨度传播到 Kafka 记录中,方法是:
TracingMetadata tm = TracingMetadata.withPrevious(Context.current());
Message out = Message.of(...).withMetadata(tm);
以上内容创建了一个 TracingMetadata 对象,我们可以将其添加到正在生成的 Message,该对象会检索 OpenTelemetry Context 以提取用于传播的当前跨度。
Quarkus Security Events
Quarkus 支持将 Security events 导出为 OpenTelemetry Span 事件。
quarkus.otel.security-events.enabled=true 1
<1> 将 Quarkus Security 事件导出为 OpenTelemetry Span 事件。
Exporters
请参阅 OpenTelemetry Guide exporters 主部分。
Quarkus core extensions instrumented with OpenTelemetry tracing
-
-
AMQP 1.0
-
RabbitMQ
-
Kafka
-
Pulsar
-
-
quarkus-vertx(http requests)
OpenTelemetry Configuration Reference
请参阅 OpenTelemetry Guide configuration 主参考。