从 Elastic 的 Go APM 代理迁移到 OpenTelemetry Go SDK

2024-04-20 01:20

本文主要是介绍从 Elastic 的 Go APM 代理迁移到 OpenTelemetry Go SDK,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

作者:来自 Elastic Damien Mathieu

正如我们之前所分享的,Elastic 致力于帮助 OpenTelemetry(OTel)取得成功,这意味着在某些情况下构建语言 SDK 的分发版本。

Elastic 在观察性和安全数据收集方面战略性地选择了 OTel 标准。此外,Elastic 承诺与 OTel 社区合作,成为观察性生态系统中最佳的数据收集基础设施。Elastic 正在加深与 OTel 的合作关系,超越了最近将 Elastic Common Schema(ECS)贡献给 OpenTelemetry、在 OTel Java 代理中调用动态语言技术(invokedynamic)以及即将捐赠的分析代理。

自 Elastic 版本 7.14 起,Elastic 已通过能够直接接收基于 OpenTelemetry 协议(OTLP)的跟踪、度量和日志,原生支持 OTel。

与其他语言 SDK 不同,Go SDK 稍有不同,因为 Go 语言本身缺乏允许构建非分支(not a fork)分发的动态性。

然而,缺乏分发并不意味着你不应该使用 OTel 从 Go 应用程序收集数据到 Elastic Stack。

Elastic 目前有一个 APM Go 代理,但我们建议切换到 OTel Go SDK。在本文中,我们将介绍两种迁移方式:

  1. 通过替换应用程序代码中的所有遥测数据(“一次性大规模迁移”)并发布更改
  2. 通过将迁移拆分成原子更改,以减少回归风险

一次性大规模迁移

从我们的 APM Go agent 迁移到 OTel SDK 的最简单方法可能是移除代理提供的所有遥测数据,并用新的 SDK 替换它们。

自动化检测

你的大部分检测可能是自动进行的,因为它是你所使用的框架或库的一部分。

例如,如果你使用 Elastic Go agent,你可能像这样使用我们的 net/http 自动化检测模块:

import ("net/http""go.elastic.co/apm/module/apmhttp/v2"
)func handler(w http.ResponseWriter, req *http.Request) {fmt.Fprintf(w, "Hello World!")
}func main() {http.ListenAndServe(":8080",apmhttp.Wrap(http.HandlerFunc(handler)),)
}

使用 OpenTelemetry,你将改用 otelhttp 模块:

import ("net/http""go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
)func handler(w http.ResponseWriter, req *http.Request) {fmt.Fprintf(w, "Hello World!")
}func main() {http.ListenAndServe(":8080",otelhttp.NewHandler(http.HandlerFunc(handler), "http"),)
}

你应该对你从我们的代理使用的每个其他模块执行相同的更改。

手动检测

你的应用程序可能还有手动检测部分,这些部分是通过调用 Elastic APM agent API 直接在应用程序代码中创建跟踪和跨度(spans)的。

你可能会使用 Elastic 的 APM SDK 创建 transactions 和 spans,就像这样:

import ("go.elastic.co/apm/v2"
)func main() {// Create a transaction, and assign it to the context.tx :=  apm.DefaultTracer().StartTransaction("GET /", "request")defer tx.End()ctx = apm.ContextWithTransaction(ctx, tx)// Create a spanspan, ctx := apm.StartSpan(ctx, "span")defer span.End()
}

在 OpenTelemetry 中,无论是 transactions 还是 spans,都使用同一套 API —— 在 OTel 中,Elastic 视为 “transactions” 的内容,仅仅是没有父级的 spans(“根 spans”)。

因此,你的检测代码将变更为以下内容:

import ("go.opentelemetry.io/otel/trace"
)func main() {tracer := otel.Tracer("my library")// Create a root span.// It is assigned to the returned context automatically.ctx, span := tracer.Start(ctx, "GET /")defer span.End()// Create a child span (as the context has a parent).ctx, span := tracer.Start(ctx, "span")defer span.End()
}

在进行一次性大迁移时,你需要在发布到生产环境之前迁移所有内容。你不能将迁移过程拆分成小块进行。

对于小型应用程序或只使用自动化检测的应用程序来说,这种限制可能是可以接受的。它允许你快速验证迁移并继续前进。

然而,如果你在处理一组复杂的服务、一个大型应用程序或一个有大量手动检测的应用程序,你可能希望能够在迁移过程中多次发布代码,而不是一次性全部完成。

分步迁移

分步迁移是一种你可以逐步发布原子性改变并保持应用程序正常工作的方式。然后,你可以在最后,当你准备好时,才进行最终的切换。

为了帮助进行分步迁移,我们提供了我们的 APM Go agent 和 OpenTelemetry 之间的桥梁。

这座桥梁允许你同时运行我们的 agent 和 OTel,并且可以在同一个进程中使用这两个库的检测,数据将被传输到相同的位置并以相同的格式。

你可以像这样配置我们的代理与 OTel 的桥接 (bridge):

import ("go.elastic.co/apm/v2""go.elastic.co/apm/module/apmotel/v2""go.opentelemetry.io/otel"
)func main() {provider, err := apmotel.NewTracerProvider()if err != nil {log.Fatal(err)}otel.SetTracerProvider(provider)
}

一旦设置了这个配置,OTel 创建的每个 span 都将被传输到 Elastic APM agent。

有了这个桥梁,你可以通过以下过程使迁移更加安全:

  • 将桥接器添加到你的应用程序中。
  • 逐个切换一个检测(自动化或手动)从代理到 OpenTelemetry,就像上面的一次性大迁移一样,但一次只进行一个。
    • 重复以上步骤,直到所有内容都已迁移。
  • 删除桥梁和我们的代理,并配置 OpenTelemetry 通过其 SDK 传输数据。

这些步骤中的每一个都可以作为应用程序中的一个单一更改,并立即投入生产。

如果在迁移过程中出现任何问题,你应该能够立即看到并修复它,然后再继续进行。

使用 OTel 构建可观察性的好处

由于 OTel 迅速成为行业标准,并且 Elastic 致力于使其变得更好,因此对工程团队来说迁移到 OTel 可能会带来很多好处。

在 Go 中,无论是通过一次性大规模迁移还是使用 Elastic 的 OTel 桥梁,这样做都将使您能够受益于全球社区维护的仪器化工具,从而使您的可观察性更加有效,并更好地了解应用程序中发生的情况。

本文中描述的任何特性或功能的发布和时间安排均由 Elastic 自行决定。 当前不可用的任何特性或功能可能无法按时交付或根本无法交付。

原文:Migrating from Elastic’s Go APM agent to OpenTelemetry Go SDK | Elastic Blog

这篇关于从 Elastic 的 Go APM 代理迁移到 OpenTelemetry Go SDK的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/918943

相关文章

go动态限制并发数量的实现示例

《go动态限制并发数量的实现示例》本文主要介绍了Go并发控制方法,通过带缓冲通道和第三方库实现并发数量限制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录带有缓冲大小的通道使用第三方库其他控制并发的方法因为go从语言层面支持并发,所以面试百分百会问到

Go语言并发之通知退出机制的实现

《Go语言并发之通知退出机制的实现》本文主要介绍了Go语言并发之通知退出机制的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1、通知退出机制1.1 进程/main函数退出1.2 通过channel退出1.3 通过cont

Go语言编译环境设置教程

《Go语言编译环境设置教程》Go语言支持高并发(goroutine)、自动垃圾回收,编译为跨平台二进制文件,云原生兼容且社区活跃,开发便捷,内置测试与vet工具辅助检测错误,依赖模块化管理,提升开发效... 目录Go语言优势下载 Go  配置编译环境配置 GOPROXYIDE 设置(VS Code)一些基本

使用Go实现文件复制的完整流程

《使用Go实现文件复制的完整流程》本案例将实现一个实用的文件操作工具:将一个文件的内容完整复制到另一个文件中,这是文件处理中的常见任务,比如配置文件备份、日志迁移、用户上传文件转存等,文中通过代码示例... 目录案例说明涉及China编程知识点示例代码代码解析示例运行练习扩展小结案例说明我们将通过标准库 os

MySQL 迁移至 Doris 最佳实践方案(最新整理)

《MySQL迁移至Doris最佳实践方案(最新整理)》本文将深入剖析三种经过实践验证的MySQL迁移至Doris的最佳方案,涵盖全量迁移、增量同步、混合迁移以及基于CDC(ChangeData... 目录一、China编程JDBC Catalog 联邦查询方案(适合跨库实时查询)1. 方案概述2. 环境要求3.

深入理解Go语言中二维切片的使用

《深入理解Go语言中二维切片的使用》本文深入讲解了Go语言中二维切片的概念与应用,用于表示矩阵、表格等二维数据结构,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录引言二维切片的基本概念定义创建二维切片二维切片的操作访问元素修改元素遍历二维切片二维切片的动态调整追加行动态

go中的时间处理过程

《go中的时间处理过程》:本文主要介绍go中的时间处理过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1 获取当前时间2 获取当前时间戳3 获取当前时间的字符串格式4 相互转化4.1 时间戳转时间字符串 (int64 > string)4.2 时间字符串转时间

Go语言中make和new的区别及说明

《Go语言中make和new的区别及说明》:本文主要介绍Go语言中make和new的区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1 概述2 new 函数2.1 功能2.2 语法2.3 初始化案例3 make 函数3.1 功能3.2 语法3.3 初始化

Go语言中nil判断的注意事项(最新推荐)

《Go语言中nil判断的注意事项(最新推荐)》本文给大家介绍Go语言中nil判断的注意事项,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1.接口变量的特殊行为2.nil的合法类型3.nil值的实用行为4.自定义类型与nil5.反射判断nil6.函数返回的

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁