Observability:使用 OpenTelemetry 自动检测 Java 应用程序

作者:David Hope

在快节奏的软件开发领域,特别是在云原生领域,DevOps 和 SRE 团队日益成为应用程序稳定性和增长的重要合作伙伴。

DevOps 工程师不断优化软件交付,而 SRE 团队则充当应用程序可靠性、可扩展性和顶级性能的管理者。 挑战? 这些团队需要一种尖端的可观察性解决方案,该解决方案包含全栈洞察,使他们能够在潜在的干扰最终导致运营挑战之前快速管理、监控和纠正它们。

现代分布式软件生态系统中的可观察性不仅仅是监控 ------ 它需要无限的数据收集、处理精度以及将这些数据与可操作的见解相关联。 然而,实现这一整体视图的道路充满了障碍,从解决版本不兼容性到与限制性专有代码作斗争。

OpenTelemetry (OTel) 将为采用它的用户带来以下好处:

  • 通过 OTel 摆脱供应商限制,将自己从供应商锁定中解放出来,并确保一流的可观察性。
  • 查看统一日志、指标和跟踪的和谐统一,以提供完整的系统视图。
  • 通过更丰富和增强的工具来改善您的应用程序监督。
  • 利用向后兼容性的优势来保护你之前的检测投资。
  • 通过简单的学习曲线踏上 OpenTelemetry 之旅,简化入门和可扩展性。
  • 依靠经过验证的、面向未来的标准来增强你对每项投资的信心。

在本博客中,我们将探讨如何使用 Docker 在 Java 应用程序中使用自动检测,而无需重构应用程序代码的任何部分。 我们将使用一个名为 Elastiflix 的应用程序,它有助于以简单的方式突出显示自动检测。

应用程序、先决条件和配置

我们在这个博客中使用的应用程序称为 Elastiflix,一个电影流应用程序。 它由多个用 .NET、NodeJS、Go 和 Python 编写的微服务组成。

在我们检测示例应用程序之前,我们首先需要了解 Elastic 如何接收遥测数据。
OpenTelemetry 的 Elastic 配置选项

Elastic Observability 的所有 APM 功能均可通过 OTel 数据使用。 其中一些包括:

  • 服务地图
  • 服务详细信息(延迟、吞吐量、失败的 transactions)
  • 服务之间的依赖关系、分布式追踪
  • Transactions(跟踪)
  • 机器学习 (ML) 相关性
  • 日志相关性

除了 Elastic 的 APM 和遥测数据的统一视图之外,你还可以使用 Elastic 强大的机器学习功能来减少分析,并发出警报以帮助降低 MTTR。

先决条件

查看示例源代码

完整的源代码,包括本博客中使用的 Dockerfile,可以在 GitHub 上找到。 该存储库还包含相同的应用程序,但没有检测。 这使你可以比较每个文件并查看差异。

以下步骤将向您展示如何实现此应用程序并在命令行或 Docker 中运行它。 如果您对更完整的 OTel 示例感兴趣,请查看此处的 docker-compose 文件,它将显示完整的项目。

分步指南

步骤 0:登录您的 Elastic Cloud 帐户

本博客假设你有 Elastic Cloud 帐户 - 如果没有,请按照说明开始使用 Elastic Cloud

步骤 1:为 Java 服务配置自动检测

我们将通过 Elastiflix 演示应用程序中的 Java 服务使用自动检测。

我们将使用 Elastiflix 的以下服务:

Elastiflix/java-favorite-otel-auto

根据 OpenTelemetry Automatic Instrumentation for Java 文档和文档,你只需安装适当的 Java 包即可。

创建本地 OTel 目录以下载 OpenTelemetry Java 代理。 下载 opentelemetry-javaagent.jar。

>mkdir /otel

>curl -L https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar --output /otel/opentelemetry-javaagent.jar

如果要在命令行上运行该服务,则可以使用以下命令:

java -javaagent:/otel/opentelemetry-javaagent.jar \
-jar /usr/src/app/target/favorite-0.0.1-SNAPSHOT.jar --server.port=5000

对于我们的应用程序,我们将把它作为 Dockerfile 的一部分来执行。

Dockerfile

Start with a base image containing Java runtime
FROM maven:3.8.2-openjdk-17-slim as build

# Make port 8080 available to the world outside this container
EXPOSE 5000

# Change to the app directory
WORKDIR /usr/src/app

# Copy the local code to the container
COPY . .

# Build the application
RUN mvn clean install

USER root
RUN apt-get update && apt-get install -y zip curl
RUN mkdir /otel
RUN curl -L -o /otel/opentelemetry-javaagent.jar https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v1.28.0/opentelemetry-javaagent.jar

COPY start.sh /start.sh
RUN chmod +x /start.sh

ENTRYPOINT ["/start.sh"]

步骤 2:使用环境变量运行 Docker 镜像

按照 OTEL Java 文档中的规定,我们将使用环境变量并传入配置值以使其能够与 Elastic Observability 的 APM 服务器连接。

由于 Elastic 本身接受 OTLP,因此我们只需要提供 OTEL Exporter 需要发送数据的端点和身份验证,以及一些其他环境变量。

获取 Elastic Cloud 变量

你可以从 Kibana 的路径 "/app/home#/tutorial/apm" 下复制端点和令牌。

你将需要复制以下环境变量:

OTEL_EXPORTER_OTLP_ENDPOINT
OTEL_EXPORTER_OTLP_HEADERS

构建 Docker 镜像

docker build -t java-otel-auto-image .

运行 Docker 镜像

docker run \
       -e OTEL_EXPORTER_OTLP_ENDPOINT="REPLACE WITH OTEL_EXPORTER_OTLP_ENDPOINT" \
       -e OTEL_EXPORTER_OTLP_HEADERS="REPLACE WITH OTEL_EXPORTER_OTLP_HEADERS" \
       -e OTEL_RESOURCE_ATTRIBUTES="service.version=1.0,deployment.environment=production" \
       -e OTEL_SERVICE_NAME="java-favorite-otel-auto" \
       -p 5000:5000 \
       java-otel-auto-image

你现在可以发出一些请求来生成跟踪数据。 请注意,这些请求预计会返回错误,因为此服务依赖于你当前未运行的 Redis 连接。 如前所述,你可以在此处找到使用 docker-compose 的更完整示例。

curl localhost:5000/favorites

# or alternatively issue a request every second

while true; do curl "localhost:5000/favorites"; sleep 1; done;

步骤 3:探索 Elastic APM 中的跟踪和日志

启动并运行此程序后,你可以 ping 检测服务的端点(在我们的示例中为 /favorites),你应该会看到该应用程序出现在 Elastic APM 中,如下所示:

它将首先跟踪 SRE 需要关注的吞吐量和延迟关键指标。

深入研究,我们可以看到所有 transactions 的概述。

再看看具体的 transactions:

点击 Logs,我们看到日志也带了过来。 OTel Agent 将自动引入日志并将其与你的跟踪关联起来:

这使你可以完全了解日志、指标和跟踪!

基本概念:APM 如何与 Java 配合使用

在继续之前,我们首先了解一些基本概念和术语。

  • Java Agent:这是一个可用于检测(或修改)Java 虚拟机 (JVM) 中类文件字节码的工具。 Java 代理有多种用途,例如性能监控、日志记录、安全性等。
  • Bytecode:这是 Java 编译器根据 Java 源代码生成的中间代码。 该代码由 JVM 即时解释或编译,以生成可以执行的机器代码。
  • Byte Buddy:Byte Buddy 是一个 Java 代码生成和操作库。 它用于在运行时创建、修改或调整 Java 类。 在 Java Agent 的上下文中,Byte Buddy 提供了一种强大且灵活的方式来修改字节码。 Elastic APM 代理和 OpenTelemetry 代理都在幕后使用 Byte Buddy。

现在,我们来谈谈自动检测如何与 Byte Buddy 配合使用

自动检测是代理修改应用程序类的字节码的过程,通常是为了插入监视代码。 代理并不直接修改源代码,而是修改加载到 JVM 中的字节码。 这是在 JVM 加载类时完成的,因此修改在运行时有效。

以下是该过程的简化说明:

  1. 使用代理启动 JVM :启动 Java 应用程序时,可以使用 -javaagent 命令行选项指定 Java 代理。 这会指示 JVM 在调用应用程序的 main 方法之前加载代理。 此时,代理有机会设置类转换器(class transformers)。
  2. 向 Byte Buddy 注册类文件转换器:你的代理将向 Byte Buddy 注册类文件转换器。 转换器是每次将类加载到 JVM 时都会调用的一段代码。 该转换器接收类的 bytecode,并且可以在实际使用该类之前修改该字节码。
  3. 转换字节码 :当调用转换器时,它将使用 Byte Buddy 的 API 来修改字节码。 Byte Buddy 允许你以高级、富有表现力的方式指定转换,而不是手动编写复杂的字节码。 例如,你可以指定要检测的某个类和该类中的方法,并提供一个 "拦截器" 来向该方法添加新行为。
    1. 例如,假设你想要测量方法的执行时间。 你将指示 Byte Buddy 定位特定的类和方法,然后提供一个拦截器,用计时代码包装方法调用。 每次调用此方法时,都会首先调用拦截器并测量开始时间,然后调用原始方法,最后测量结束时间并打印持续时间。
  4. 使用转换后的类:一旦代理设置了其转换器,JVM 就会像往常一样继续加载类。 每次加载类时,都会调用转换器,允许它们修改字节码。 然后,你的应用程序将使用这些转换后的类,就像它们是原始类一样,但它们现在具有你通过拦截器注入的额外行为。

本质上,Byte Buddy 的自动检测就是在运行时修改 Java 类的行为,而不需要直接更改源代码。 这对于日志记录、监视或安全性等横切关注点特别有用,因为它允许你将此代码集中在 Java 代理中,而不是将其分散在整个应用程序中。

总结

借助此 Dockerfile,你已将简单的 Java 应用程序转换为使用 OpenTelemetry 自动检测的应用程序。 这将极大地帮助了解应用程序性能、跟踪错误以及深入了解用户如何与软件交互。

请记住,可观察性是现代应用程序开发的一个重要方面,尤其是在分布式系统中。 借助 OpenTelemetry 等工具,理解复杂系统变得更加容易。

在这篇博客中,我们讨论了以下内容:

  • 如何使用 OpenTelemetry 自动检测 Java。
  • 使用 Docker 文件中的标准命令,可以高效地完成自动检测,并且无需在多个位置添加代码,从而实现可管理性。
  • 使用 OpenTelemetry 及其对多种语言的支持,DevOps 和 SRE 团队可以自动检测其应用程序,轻松立即了解整个应用程序堆栈的运行状况,并缩短平均解决时间 (MTTR)。

由于 Elastic 可以支持多种摄取数据的方法,无论是使用开源 OpenTelemetry 的自动检测还是使用其本机 APM 代理进行手动检测,你都可以先关注一些应用程序,然后使用稍后以最适合你的业务需求的方式在你的应用程序中打开 OpenTelemetry。

原文:Auto-instrumentation of Java applications with OpenTelemetry | Elastic Blog

相关推荐
一只爱打拳的程序猿8 分钟前
【Spring】更加简单的将对象存入Spring中并使用
java·后端·spring
杨荧10 分钟前
【JAVA毕业设计】基于Vue和SpringBoot的服装商城系统学科竞赛管理系统
java·开发语言·vue.js·spring boot·spring cloud·java-ee·kafka
晨欣11 分钟前
Elasticsearch和Lucene之间是什么关系?(ChatGPT回答)
elasticsearch·chatgpt·lucene
minDuck12 分钟前
ruoyi-vue集成tianai-captcha验证码
java·前端·vue.js
白子寰16 分钟前
【C++打怪之路Lv14】- “多态“篇
开发语言·c++
王俊山IT28 分钟前
C++学习笔记----10、模块、头文件及各种主题(一)---- 模块(5)
开发语言·c++·笔记·学习
为将者,自当识天晓地。30 分钟前
c++多线程
java·开发语言
小政爱学习!32 分钟前
封装axios、环境变量、api解耦、解决跨域、全局组件注入
开发语言·前端·javascript
daqinzl38 分钟前
java获取机器ip、mac
java·mac·ip
k09331 小时前
sourceTree回滚版本到某次提交
开发语言·前端·javascript