OpenTelemetry Instrumentation 与 Java Agent 技术

OpenTelemetry Instrumentation 与 Java Agent 技术

Moreality's Blog

在之前的 blog: 分布式可观测性,链路追踪与OpenTelemetry 主要介绍了分布式链路追踪的概念和 OpenTelemetry (下文以 Otel 简称) 的起源。从本节开始,我会分享一些 OpenTelemetry 的基本概念,语言主要基于 Java(当然,Otel 本身的 SDK 支持多种语言,可以在 Otel Doc: Language APIs & SDKs 查看)。

本文介绍的内容主要涉及 OpenTelemetry[1] 的 Instrumentation 概念,如果你想了解如何将已有的代码接入 OpenTelemetry 以获得可观测性,那么可以试试看一下。

1 - OpenTelemetry Instrumentation Startup

如果你想把你的一个项目接入 OpenTelemetry,肯定要接触一个概念:”Instrumentation”,这是一个少有的我感觉没什么准确的一个中文词汇能表达出的意思,OpenTelemetry 将其翻译成「仪表化」,但我感觉仍然不太恰当。

这个词实际上表达的是:

向应用程序中注入跟踪和监控代码的过程,目的是收集有关应用程序运行时性能和行为的监控数据 [2]

OpenTelemetry 对 Instrumentation 主要提供了两种方案:

2 - Java Agent

下文都以 Java 为例,介绍 Otel 如何利用 Java Agent 机制实现 Auto Instrumentation。该部分主要参考官网文档:Doc: Java Agent

本章首先介绍 Java Agent 机制。

2.1 - 什么是 Java Agent

Java代理是一种特殊类型的类,通过使用Java Instrumentation API ,它可以拦截运行在JVM上的应用程序,修改它们的字节码。 (注意:区别于 Otel Instrumentation,虽然用的是一个词,表达的也都是「代码注入」这个概念)

Java代理并不是一项新技术,相反,它们从Java 5开始就存在了。但是即使过了这么长时间,还是有许多开发者对这个概念鲜有接触。

通过 Java Agent,可以轻松实现如下几类应用场景:

  • IDE 的调试功能,例如 Eclipse、IntelliJ IDEA;
  • 热部署功能,例如 JRebel、XRebel、spring-loaded;
  • 各种线上诊断工具,例如 Btrace、Greys,国内阿里的 Arthas;
  • 各种性能分析工具,例如 Visual VM、JConsole 等;
  • 全链路性能检测工具,例如 OpenTelemetry、Skywalking、Pinpoint 等。

2.2 - Java Agent 的运行机制

Java Agent 主要可以通过两种方式启动:Premain AgentAgentmain,分别在 JVM 启动前和启动后加载 Agent,达到的都是动态修改字节码的效果:

  • Premain Agent

Java Agent 在 Java 程序运行前:在Main方法执行之前,通过一个叫 premain方法来执行。

启动时需要在目标程序的启动参数中添加 -javaagent参数,Java Agent 内部通过注册 ClassFileTransformer ,这个转化器在 Java 程序 Main方法前加了一层拦截器。在类加载之前,完成对字节码修改。

其工作流程大致如下:[4]

  • Agentmain

该模式和 Premain 模式相似,主要区别在进行字节码增强前,拦截入口不同。一个叫Premain,一个叫Agentmain 。 运行时加载,当前 JVM 进程已经启动了。这时借助另一个 JVM 进程通信,调用 Attach API 再把 Agent 启动起来。后面的字节码修改和重加载的过程那就是一样的。

3 - Otel Java Auto Instrumentation

Otel Java Auto Instrumentation 主要通过 Java agent 机制实现。

Java Auto Instrumentation 实现都在 github: https://github.com/open-telemetry/opentelemetry-java-instrumentation/ 这个仓库中。

3.1 - 快速开始

可以参考 doc 快速在一个 java 项目中进行 instrumentation,只需要如下几步:

  1. Download opentelemetry-javaagent.jar from Releases of the opentelemetry-java-instrumentation
  2. 通过 java -javaagent:path/to/opentelemetry-javaagent.jar -Dotel.service.name=your-service-name -jar myapp.jar 启动你的 project app myapp.jar

通过这两步,就已经可以在这些 otel 支持的 library 上运行 opentelemetry 了,可以通过在环境变量或者 properties 中修改 这些配置 来进行更多自定义配置,包括但不限于:

  • 数据导出配置:导出数据的目标类型,如 Jaeger、Zipkin、Prometheus等。
  • 日志输出模式
  • 采样策略
  • 等等

下面通过一个我自己的示例来快速了解一下如何利用 Otel 提供的 @WithSpan@WithSpanAttribute Annotation 进行 Auto Instrumentation 的 Tracing。[6]

3.2 - Code 示例

首先创建一个 java 项目,并导入 opentelemetry-instrumentation-annotations 这个依赖,可以在 这里 查看 Maven 或者 Gradle 的导入方式。

这里以 gradle 为例,添加如下 dependencies 即可:

全部的 build.gradle.kts:

然后写一个简单的测试类:

使用 -Dotel.traces.exporter=logging-otlp 将输出指定为 otlp 的 json 格式(otlp 是 opentelemetry 定义的传输协议),通过 log 输出在控制台,然后把 logs 和 metrics 的 exporter 禁用后启动:

也可以通过环境变量来启动:

输出如下:

3.3 - Span 的结构分析

输出的 json 实际上的结构可以在 trace.proto 中查看: https://github.com/open-telemetry/opentelemetry-proto/blob/v1.3.0/opentelemetry/proto/trace/v1/trace.proto

  • 比如 main 方法对应的 span 对应包含如下信息

关于其中字段的详细解释可以参考:https://opentelemetry.io/docs/concepts/signals/traces/

这一章还处于比较浅的阶段,后面会再写写 otel 一些内部 code 结构的分析,以及如何通过 agent extensions 等机制来自定义 agent 行为等。

Reference

  1. https://opentelemetry.io/docs
  2. https://stackify.com/what-are-java-agents-and-how-to-profile-with-them/
  3. https://en.wikipedia.org/wiki/Instrumentation_(computer_programming)
  4. 深入 OpenTelemetry 源代码:Java 探针的实现和二次开发
  5. Java 自动化探针技术的核心原理和实践
  6. https://opentelemetry.io/docs/zero-code/java/agent/annotations/
  7. https://github.com/open-telemetry/opentelemetry-proto/blob/v1.3.0/opentelemetry/proto/trace/v1/trace.proto
  8. https://opentelemetry.io/docs/concepts/signals/traces/


Generated by RSStT. The copyright belongs to the original author.

Source

Report Page