从 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学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

Go语言中泄漏缓冲区的问题解决

《Go语言中泄漏缓冲区的问题解决》缓冲区是一种常见的数据结构,常被用于在不同的并发单元之间传递数据,然而,若缓冲区使用不当,就可能引发泄漏缓冲区问题,本文就来介绍一下问题的解决,感兴趣的可以了解一下... 目录引言泄漏缓冲区的基本概念代码示例:泄漏缓冲区的产生项目场景:Web 服务器中的请求缓冲场景描述代码

Go语言如何判断两张图片的相似度

《Go语言如何判断两张图片的相似度》这篇文章主要为大家详细介绍了Go语言如何中实现判断两张图片的相似度的两种方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 在介绍技术细节前,我们先来看看图片对比在哪些场景下可以用得到:图片去重:自动删除重复图片,为存储空间"瘦身"。想象你是一个

Go语言中Recover机制的使用

《Go语言中Recover机制的使用》Go语言的recover机制通过defer函数捕获panic,实现异常恢复与程序稳定性,具有一定的参考价值,感兴趣的可以了解一下... 目录引言Recover 的基本概念基本代码示例简单的 Recover 示例嵌套函数中的 Recover项目场景中的应用Web 服务器中

VSCode设置python SDK路径的实现步骤

《VSCode设置pythonSDK路径的实现步骤》本文主要介绍了VSCode设置pythonSDK路径的实现步骤,包括命令面板切换、settings.json配置、环境变量及虚拟环境处理,具有一定... 目录一、通过命令面板快速切换(推荐方法)二、通过 settings.json 配置(项目级/全局)三、

Go语言中使用JWT进行身份验证的几种方式

《Go语言中使用JWT进行身份验证的几种方式》本文主要介绍了Go语言中使用JWT进行身份验证的几种方式,包括dgrijalva/jwt-go、golang-jwt/jwt、lestrrat-go/jw... 目录简介1. github.com/dgrijalva/jwt-go安装:使用示例:解释:2. gi

go rate 原生标准限速库的使用

《gorate原生标准限速库的使用》本文主要介绍了Go标准库golang.org/x/time/rate实现限流,采用令牌桶算法控制请求速率,提供Allow/Reserve/Wait方法,具有一定... 目录介绍安装API介绍rate.NewLimiter:创建限流器limiter.Allow():请求是否

Go 语言中的 Struct Tag 的用法详解

《Go语言中的StructTag的用法详解》在Go语言中,结构体字段标签(StructTag)是一种用于给字段添加元信息(metadata)的机制,常用于序列化(如JSON、XML)、ORM映... 目录一、结构体标签的基本语法二、json:"token"的具体含义三、常见的标签格式变体四、使用示例五、使用

Ubuntu上手动安装Go环境并解决“可执行文件格式错误”问题

《Ubuntu上手动安装Go环境并解决“可执行文件格式错误”问题》:本文主要介绍Ubuntu上手动安装Go环境并解决“可执行文件格式错误”问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未... 目录一、前言二、系统架构检测三、卸载旧版 Go四、下载并安装正确版本五、配置环境变量六、验证安装七、常见

Go语言使用slices包轻松实现排序功能

《Go语言使用slices包轻松实现排序功能》在Go语言开发中,对数据进行排序是常见的需求,Go1.18版本引入的slices包提供了简洁高效的排序解决方案,支持内置类型和用户自定义类型的排序操作,本... 目录一、内置类型排序:字符串与整数的应用1. 字符串切片排序2. 整数切片排序二、检查切片排序状态: