Skip to main content

Java应用接入KubeGems OpenTelemetry


1. 引入 Java Agent

步骤一、 进入 KubeGems 可观测性功能下的接入中心,选择 Java 应用,查看接入说明

步骤二、 封装 java 类型基础镜像

1.Dockerfile

将 java agent 拷贝到路径 /opt/otel/lib/opentelemetry-javaagent.jar 下

RUN mkdir -p /opt/otel/lib && \
curl -o /opt/otel/lib/ https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
  1. entrypoint.sh (业务启动脚本)
提供伪代码来说明脚本启动逻辑
if exist and true << (ENV OTEL_ENABLED)
java -javaagent:/opt/otel/lib/opentelemetry-javaagent.jar -jar myapp.jar
else
java -jar myapp.jar
fi

步骤三、 在 KubeGems 中需要接入的应用,在编排中添加环境变量,并同步成功

spec:
template:
spec:
containers:
- env:
- name: OTEL_ENABLED
value: "true"
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: http://opentelemetry-collector.observability:4317
- name: OTEL_SERVICE_NAME
value: <你的应用名称>
- name: OTEL_K8S_NODE_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
- name: OTEL_K8S_POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: OTEL_K8S_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
- name: OTEL_RESOURCE_ATTRIBUTES
value: >-
service.name=$(OTEL_SERVICE_NAME),namespace=$(OTEL_K8S_NAMESPACE),node=$(OTEL_K8S_NODE_NAME),pod=$(OTEL_K8S_POD_NAME)

步骤四、在 KubeGems 应用性能中查看接口和内部方法的监控视图

在 KuebGems 链路查询器中查看链路视图

2. 打印 Trace Context 日志

映射的诊断上下文(MDC)是

是一种工具,用于区分来自不同来源的交错日志输出。 log4j MDC documentation

它包含线程本地的上下文信息,这些信息后来被复制到由日志库捕获的每个日志事件中。

OpenTelementry Java Agent将关于当前跨度的几个信息注入到每个日志事件的MDC副本中。

  • trace_id - 当前的跟踪 ID(与 Span.current().getSpanContext().getTraceId()相同)。
  • span_id - 当前的span id(与Span.current().getSpanContext().getSpanId()相同)。
  • trace_flags - 当前的跟踪标志,格式为W3C traceflags格式(与Span.current().getSpanContext().getTraceFlags().asHex()相同)。

这三条信息可以通过在模式/格式中指定它们来包含在由日志库产生的日志语句中。

对于使用logback的Spring Boot配置,只需覆盖logging.pattern.level,就可以在日志行中添加MDC。
logging.pattern.level = trace_id=%mdc{trace_id} span_id=%mdc{span_id} trace_flags=%mdc{trace_flags} %5p

这样,任何解析应用程序日志的服务或工具都可以将跟踪/跨度与日志语句相关联。

支持的日志库

LibraryVersion
Log4j 11.2+
Log4j 22.7+
Logback1.0+

2.1 Log4j instrumentation 注入 TraceID

tip

本文参考腾讯云文档 OpenTelementry 增强探针(Java)

  1. 添加 Log4j2 与 OpenTelemetry-api 库到依赖库 dependencies 中:
  • Maven project:
<dependencies>
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-log4j-2.13.2</artifactId>
<version>1.9.2-alpha</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
<version>1.11.0</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
</dependencies>
  • Gradle projects:
dependencies {
runtimeOnly("io.opentelemetry.instrumentation:opentelemetry-log4j-2.13.2:1.9.2-alpha")
implementation("io.opentelemetry:opentelemetry-api:1.11.0"

implementation("org.slf4j:slf4j-api")
}
  1. 更新 log4j2.properties 配置文件,示例配置如下:
status=info
name=properties_configuration
property.basePath=/Users/tcenent/java/opentelemetry-logger-tracer/logs/

appender.rolling.type=RollingFile
[appender.rolling.name](http://appender.rolling.name/)=fileLogger
appender.rolling.fileName=${basePath}/opentelemetry-tracer.log
appender.rolling.filePattern=${basePath}app_%d{yyyyMMdd}.log.gz
appender.rolling.layout.type=PatternLayout
appender.rolling.layout.pattern=%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} traceId: %X{trace_id} spanId: %X{span_id} - %msg%n
appender.rolling.policies.type=Policies

appender.rolling.policies.time.type=TimeBasedTriggeringPolicy
appender.rolling.policies.time.interval=1
appender.rolling.policies.time.modulate=true
appender.rolling.strategy.type=DefaultRolloverStrategy
appender.rolling.strategy.delete.type=Delete
appender.rolling.strategy.delete.basePath=${basePath}
appender.rolling.strategy.delete.maxDepth=1
appender.rolling.strategy.delete.ifLastModified.type=IfLastModified
appender.rolling.strategy.delete.ifLastModified.age=30d

rootLogger.level=info
rootLogger.additivity=false
rootLogger.appenderRef.rolling.ref=fileLogger
建议将 log4j 的日志输出到 STDOUT,便于在日志查询器中进行过滤查询
  1. 配置完后,可在 logger 日志文件中查看到 TraceID 与 SpanID,如下图所示

2.2 Logback instrumentation 注入 TraceID

  1. 添加 logback 工程依赖库到 dependencies 中:
  • maven project
<dependencies>
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-logback-1.0</artifactId>
<version>1.9.2-alpha</version>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
  • Gradle projects:
dependencies {
runtimeOnly("io.opentelemetry.instrumentation:opentelemetry-logback-1.0:1.9.2-alpha")

implementation("ch.qos.logback:logback-core:1.11.0"

implementation("ch.qos.logback:logback-classic"

implementation("ch.qos.logback:logback-access"
}
  • 更新 logback.xml 配置文件,下面是一个示例配置:
<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="3 seconds">
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<encoder>
<pattern><![CDATA[%date{HH:mm:ss.SSS} [%thread] %-5level %logger{15}#%line %X{req.requestURI} traceId: %X{trace_id} spanId: %X{span_id} %msg\n]]></pattern>
</encoder>
<File>/Users/tencent/java/opentelemetry-logger-tracer/logs/logFile.log</File>
<append>true</append>
</appender>
<appender name="OTEL" class="io.opentelemetry.instrumentation.logback.v1_0.OpenTelemetryAppender">
<appender-ref ref="FILE" />
</appender>
<root>
<level value="INFO" />
<appender-ref ref="FILE" />
</root>
</configuration>
建议将 logback 的日志输出到 STDOUT,便于在日志查询器中进行过滤查询
  1. 配置完后,可在 logger 日志文件中查看到 TraceID 与 SpanID,如下图所示:

2.3 注意事项

因为 spring-boot 会自带 logger 的配置,所以要我们配置的文件生效,需要在引入 spring-boot 依赖示去掉默认的 loger 库:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>org.springframework.boot</artifactId>
<groupId>spring-boot-starter-logging</groupId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>