从 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语言中,短变量声明是一种简洁的变量声明方式,使用:=运算符,可以自动推断变量类型,下面就来具体介绍一下如何使用,感兴趣的可以了解一下... 目录基本语法功能特点与var的区别适用场景注意事项基本语法variableName := value功能特点1、自动类型推

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

Go之errors.New和fmt.Errorf 的区别小结

《Go之errors.New和fmt.Errorf的区别小结》本文主要介绍了Go之errors.New和fmt.Errorf的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考... 目录error的基本用法1. 获取错误信息2. 在条件判断中使用基本区别1.函数签名2.使用场景详细对

Go语言连接MySQL数据库执行基本的增删改查

《Go语言连接MySQL数据库执行基本的增删改查》在后端开发中,MySQL是最常用的关系型数据库之一,本文主要为大家详细介绍了如何使用Go连接MySQL数据库并执行基本的增删改查吧... 目录Go语言连接mysql数据库准备工作安装 MySQL 驱动代码实现运行结果注意事项Go语言执行基本的增删改查准备工作

Go中select多路复用的实现示例

《Go中select多路复用的实现示例》Go的select用于多通道通信,实现多路复用,支持随机选择、超时控制及非阻塞操作,建议合理使用以避免协程泄漏和死循环,感兴趣的可以了解一下... 目录一、什么是select基本语法:二、select 使用示例示例1:监听多个通道输入三、select的特性四、使用se

Go语言使用Gin处理路由参数和查询参数

《Go语言使用Gin处理路由参数和查询参数》在WebAPI开发中,处理路由参数(PathParameter)和查询参数(QueryParameter)是非常常见的需求,下面我们就来看看Go语言... 目录一、路由参数 vs 查询参数二、Gin 获取路由参数和查询参数三、示例代码四、运行与测试1. 测试编程路

Go语言使用net/http构建一个RESTful API的示例代码

《Go语言使用net/http构建一个RESTfulAPI的示例代码》Go的标准库net/http提供了构建Web服务所需的强大功能,虽然众多第三方框架(如Gin、Echo)已经封装了很多功能,但... 目录引言一、什么是 RESTful API?二、实战目标:用户信息管理 API三、代码实现1. 用户数据

Go语言网络故障诊断与调试技巧

《Go语言网络故障诊断与调试技巧》在分布式系统和微服务架构的浪潮中,网络编程成为系统性能和可靠性的核心支柱,从高并发的API服务到实时通信应用,网络的稳定性直接影响用户体验,本文面向熟悉Go基本语法和... 目录1. 引言2. Go 语言网络编程的优势与特色2.1 简洁高效的标准库2.2 强大的并发模型2.

深入理解go中interface机制

《深入理解go中interface机制》本文主要介绍了深入理解go中interface机制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录前言interface使用类型判断总结前言go的interface是一组method的集合,不

Go语言使用sync.Mutex实现资源加锁

《Go语言使用sync.Mutex实现资源加锁》数据共享是一把双刃剑,Go语言为我们提供了sync.Mutex,一种最基础也是最常用的加锁方式,用于保证在任意时刻只有一个goroutine能访问共享... 目录一、什么是 Mutex二、为什么需要加锁三、实战案例:并发安全的计数器1. 未加锁示例(存在竞态)