1. 整体架构
- OpenTelemetry:负责采集 Trace(追踪)、Metric(指标)。
- Loki:收集应用日志(需注入 TraceId)。
- Prometheus:存储指标数据。
- Tempo/Jaeger:存储分布式追踪数据。
- Grafana:统一展示日志、指标、追踪,并通过 TraceId 关联三者。
2. 配置 OpenTelemetry
2.1 添加 OpenTelemetry 依赖
在 pom.xml 中引入:
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
<version>1.30.1</version>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk</artifactId>
<version>1.30.1</version>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
<version>1.30.1</version>
</dependency>
2.2 初始化 OpenTelemetry
在 Spring Boot 启动类中配置:
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
@SpringBootApplication
public class MyApp {
public static void main(String[] args) {
// 配置 OpenTelemetry
OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
.setTracerProvider(
SdkTracerProvider.builder()
.addSpanProcessor(
BatchSpanProcessor.builder(
OtlpGrpcSpanExporter.builder()
.setEndpoint("http://otel-collector:4317")
.build()
).build()
)
.setResource(Resource.getDefault()
.merge(Resource.create(Attributes.of(
ResourceAttributes.SERVICE_NAME, "my-service"
)))
.build()
)
.buildAndRegisterGlobal();
SpringApplication.run(MyApp.class, args);
}
}
3. 注入 TraceId 到日志
在日志中自动添加 TraceId,便于 Loki 收集后与 Trace 关联。
3.1 配置 Logback
在 logback-spring.xml 中添加 MDC 转换:
xml
复制
下载
运行
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - [traceId=%X{traceId}] - %msg%n</pattern>
</encoder>
</appender>
<!-- 自动注入 TraceId -->
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator"/>
<contextListener class="org.springframework.boot.logging.logback.LogbackLoggingSystem"/>
</configuration>
3.2 自动捕获 TraceId
通过 OpenTelemetry 的自动注入,确保日志中的 traceId 字段与当前请求的 TraceId 一致。
4. 配置 OpenTelemetry Collector
部署 Collector 并配置数据转发(示例 otel-collector-config.yaml):
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
exporters:
prometheus:
endpoint: "prometheus:9090"
loki:
endpoint: "http://loki:3100/loki/api/v1/push"
labels:
job: "my-service"
tempo:
endpoint: "tempo:4317"
insecure: true
service:
pipelines:
traces:
receivers: [otlp]
exporters: [tempo]
metrics:
receivers: [otlp]
exporters: [prometheus]
logs:
receivers: [otlp]
exporters: [loki]
5. Grafana 数据源配置
- Loki:用于日志查询。
- Prometheus:用于指标查询。
- Tempo:用于分布式追踪。
在 Grafana 的 Configuration > Data Sources 中添加三者,并确保地址正确。
6. 实现 Trace-日志-指标联动
6.1 查看 Trace 详情
在 Tempo 数据源中,通过 TraceId 查询完整的调用链路。
6.2 关联日志
在 Grafana Explore 中选择 Loki 数据源,输入查询:
{job="my-service"} | json | traceId="替换为TraceId"
6.3 关联指标
在 Prometheus 中查询与 Trace 相关的指标(如接口耗时):
http_server_duration_seconds_bucket{trace_id="替换为TraceId"}
7. 创建统一监控面板
在 Grafana 中创建 Dashboard,整合以下内容:
- 指标图表:显示接口 QPS、平均耗时、错误率。
- 日志面板:显示最近错误日志(带 TraceId)。
- Trace 列表:显示最近慢请求的 Trace 详情。
8. 验证全链路
- 发起一个请求,观察日志中是否包含 TraceId。
- 在 Tempo 中通过 TraceId 查看调用链路。
- 在 Loki 中通过 TraceId 过滤相关日志。
- 在 Prometheus 中查看该请求的指标统计。
常见问题
Q1:日志中未出现 TraceId
- 检查 Logback 配置的
%X{traceId}是否正确。 - 确保 OpenTelemetry 的自动注入已启用。
Q2:Grafana 无法关联数据源
- 确认所有数据源(Loki、Prometheus、Tempo)在 Grafana 中已正确配置并测试通过。
- 确保 TraceId 的格式一致(如 16 进制或 Base64 编码)。
总结
通过 OpenTelemetry 统一采集 Trace 和 Metric,配合 Loki 的日志收集,最终在 Grafana 中实现三者的无缝关联。核心步骤包括:
- 注入 TraceId 到日志。
- 通过 OpenTelemetry Collector 转发数据到对应存储。
- 在 Grafana 中通过 TraceId 实现跨数据源查询。