这篇文章中我们会讨论可观测性概念,并了解了有关 OpenTelemetry 的一些细节,然后会在 Golang 服务中对接 OpenTelemetry 实现分布式系统可观测性。
Test Project
我们将使用 Go 1.22 开发我们的测试服务。我们将构建一个 API,返回服务的名称及其版本。
我们将把我们的项目分成两个简单的文件(main.go 和 info.go)。
1 | // file: main.go |
1 | // file: info.go |
使用 go run .
运行后,应该在 console 中输出:
1 | Starting http server. |
访问 localhost:8080
会显示:
1 | // http://localhost:8080/info |
现在我们的服务已经可以运行了,现在要以对其进行监控(或者配置我们的流水线)。在这里,我们将执行手动监控以理解一些观测细节。
First Steps
第一步是安装 Open Telemetry 的依赖。
1 | go get "go.opentelemetry.io/otel" \ |
目前,我们只会安装项目的初始依赖。这里我们将 OpenTelemetry 配置 otel.go文件。
在我们开始之前,先看下配置的流水线:
定义 Exporter
为了演示简单,我们将在这里使用 console Exporter 。
1 | // file: otel.go |
main.go 的代码如下:
1 | // file: main.go |
Trace
我们的首个信号将是 Trace。为了与这个信号互动,我们必须创建一个 provider,如下所示。作为一个参数,我们将拥有一个 Exporter,它将接收收集到的信息。
1 | // file: otel.go |
在 main.go 文件中,我们将使用创建跟踪提供程序的函数。
1 | // file: main.go |
请注意,在实例化一个 provider 时,我们必须保证它会“关闭”。这样可以避免内存泄露。
现在我们的服务已经配置了一个 trace provider,我们准备好收集数据了。让我们调用 “/info” 接口来产生数据。
1 | // file: info.go |
tracer = otel.Tracer(“info-service”)
将在我们已经在main.go
中注册的全局 trace provider 中创建一个命名的跟踪器。如果未提供名称,则将使用默认名称。
tracer.Start(r.Context(), “info”)
创建一个 Span
和一个包含新创建的 span
的 context.Context
。如果 “ctx” 中提供的 context.Context
包含一个 Span
,那么新创建的 Span
将是该 Span
的子Span
,否则它将是根 Span
。
Span 对我们来说是一个新的概念。Span 代表一个工作单元或操作。Span 是跟踪(Traces)的构建块。
同样地,正如提供程序一样,我们必须始终关闭 Spans 以避免“内存泄漏”。
现在,我们的端点已经被监控,我们可以在控制台中查看我们的观测数据。
1 | { |
添加 Metrics
我们已经有了我们的 tracing 配置。现在来添加我们的第一个指标。
首先,安装并配置一个专门用于指标的导出器。
1 | go get "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" |
通过修改我们的 otel.go 文件,我们将有两个导出器:一个专门用于 tracing,另一个用于 metrics。
1 | // file: otel.go |
现在添加我们的 metrics Provider 实例化:
1 | // file: otel.go |
我将提供商的行为更改为每10秒进行一次定期读取(默认为1分钟)。
在实例化一个 MeterProvide r时,我们将创建一个Meter。Meters 允许您创建您可以使用的仪器,以创建不同类型的指标(计数器、异步计数器、直方图、异步仪表、增减计数器、异步增减计数器……)。
现在我们可以在 main.go 中配置我们的新 exporter 和 provider。
1 | // file: main.go |
最后,让我们测量我们想要的数据。我们将在 info.go 中做这件事,这与我们之前在 trace 中所做的非常相似。
我们将使用 otel.Meter("info-service")
在已经注册的全局提供者上创建一个命名的计量器。我们还将通过 metric.Int64Counter
定义我们的测量工具。Int64Counter 是一种记录递增的 int64 值的工具。
然而,与 trace不同,我们需要初始化我们的测量工具。我们将为我们的度量配置名称、描述和单位。
1 | // file: info.go |
一旦完成这个步骤,我们就可以开始测量了。最终代码看起来会像这样:
1 | // file: info.go |
运行我们的服务时,每10秒系统将在控制台显示我们的数据:
1 | { |
Context
为了将追踪信息发送出去,我们需要传播上下文。为了做到这一点,我们必须注册一个传播器。我们将在 otel.go和main.go 中实现,跟追 Tracing 和 metric 的实现差不多。
1 | // file: otel.go |
1 | // file: main.go |
HTTP Server
我们将通过观测数据来丰富我们的 HTTP 服务器以完成我们的监控。为此我们将使用带有 OTel 的 http handler 。
1 | // main.go |
因此,我们将在我们的收集到的数据中获得来自 HTTP 服务器的额外信息(用户代理、HTTP方法、协议、路由等)。
Conclusion
这篇文章我们详细展示了如何使用 Go 来对接 OpenTelemetry 以实现完整的可观测系统,这里使用 console Exporter 仅作演示使用 ,在实际的开发中我们可能需要使用更加强大的 Exporter 将数据可视化,比如可以使用 Google Cloud Trace 来将数据直接导出到 Goole Cloud Monitoring 。
References
OpenTelemetry
The Future of Observability with OpenTelemetry
Cloud-Native Observability with OpenTelemetry
Learning OpenTelemetry