searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

一文看懂OpenTelemetry

2025-05-26 10:21:37
1
0

OpenTelemetry 介绍

OpenTelemetry(简称 OTel)是由 CNCF(云原生计算基金会)孵化的开源项目,旨在提供统一的可观测框架和工具集(APIs、SDK),用于生成、收集、处理、传输遥测数据(Telemetry Data),包括指标(Metrics)、追踪(Traces)和日志(Logs),帮助用户分析应用程序的性能和行为。OpenTelemetry 是由 OpenTracing(Uber)和 OpenCensus(Google)两大可观测框架合并后的产物,具备厂商无关性,已成为云原生系统中可观测性(Observability)领域的工业级标准。其架构如下图所示:
image-43.png

主要包含如下3个部分:

  • Instrumentation:支持API(一组抽象接口并无实现,无法单独运行的类库)、SDK(对API的具体实现,能单独运行的服务)、零代码(类似代理机制,具体语言实现方式不同,针对特定库如HTTP、RPC、数据库访问、消息队列访问)方式使用 OpenTelemetry
  • OTLP: OpenTelemetry 定义的数据传输协议
  • OpenTelemetry Collector:是一个厂商无关的服务,用于收集(Receiver)、处理(Processor)和传输(Exporter)遥测数据。它可以作为应用的Sidecar或者单独的代理进程运行,接收不同来源的遥测数据,并将其导出到多种后端系统(如 Prometheus、Jaeger、Zipkin 等)进行存储、分析。

核心功能

数据模型

  • Traces​:记录请求在分布式系统中的访问路径,包含 Trace ID 和 Span(操作单元)信息。
    • Span​:一次具体访问路径,包含开始/结束时间、标签(Tags)、事件(Events)、状态(Status)。
    • Trace​:记录一次请求,每个Trace会关联一个或多个Span。
  • Metrics​:数值指标(如 CPU 使用率、请求速率)。
    • 支持 Counter、Gauge、Histogram 等指标类型。
  • Logs​:结构化日志,支持与 Traces 关联(通过 Trace ID 进行关联),方便问题定位。

传输协议

  • ​**OTLP(OpenTelemetry Protocol)**​:统一的遥测数据传输协议,支持 gRPC 和 HTTP。
  • 兼容性​:可无缝对接 Prometheus、Zipkin、Jaeger 等后端存储分析系统。

数据采集(Instrumentation)

  • 手动埋点​:OpenTelemetry 提供了一组 API接口,允许开发者在应用程序中插入遥测数据收集代码,同时支持多种编程语言。
    from opentelemetry import trace
    tracer = trace.get_tracer("my_tracer")
    with tracer.start_as_current_span("custom_operation"):
        # 业务逻辑
    
  • 自动埋点​:SDK 实现了 API接口具体功能,通过集成 SDK,应用程序自动采集框架(如 HTTP 调用、RPC 调用、数据库调用)的遥测数据。
    • 目前支持的编程语言:Java、Python、Go、.NET、Node.js 等。

数据管理

  • Processor​:对遥测数据进行过滤、聚合或转换,支持自定义数据处理逻辑。
    • Batch Processor​:批量压缩数据,减少网络开销。
    • Simple Processor​:直接转发原始数据。
  • Exporter​:将数据发送到后端存储分析系统(如 Jaeger、Prometheus、Zipkin等)。
    # 配置导出到 Jaeger
    exporters:
      jaeger:
        endpoint: "jaeger:14250"
        insecure: true
    

核心优势

  • 标准化
    • 统一 指标(Metrics)、追踪(Traces)、日志(Logs) 的采集、处理与传输,终结了多套 SDK 并存的混乱局面;
    • 支持指标数据(Metrics)收集、处理,如请求计数、延迟等指标帮助宏观上快速发现系统问题;
    • 支持分布式追踪数据(Traces)收集和处理,允许开发者追踪请求在微服务架构中的调用链,帮助识别性能瓶颈、定位故障;
    • 支持日志数据(Logs)收集、处理,提供全面的观察系统运行情况、定位故障能力。
  • 多语言支持
    • 支持多种编程语言,例如 Java、JavaScript、Python、Go、C# 等,在不同技术栈中使用相同的遥测数据采集框架,不会因技术栈不同导致可观测技术体系碎片化。
  • 功能灵活扩展
    • 通过 收集器(Collector) 组件实现遥测数据接收、路由、过滤和转发,支持自定义 Processor 和 Exporter来处理、传输遥测数据。
  • 云原生友好
    • 原生支持 Kubernetes、Service Mesh(如 Istio)等云原生技术框架。

使用场景

分布式追踪(Distributed Tracing)

  • 问题定位​:追踪微服务调用链,快速定位延迟或故障。
  • 故障排查​:分布式追踪功能可以帮助开发者快速定位故障,了解请求的详细处理流程。
  • 依赖分析​:可视化微服务调用关系(如通过 Jaeger UI)。

性能监控(Performance Monitoring)

  • 指标聚合​:统计吞吐量、错误率、延迟分布(P90/P99)。
  • 告警联动​:通过对接 Prometheus、Grafana 实现数据实时告警。
  • 通过收集和分析指标,开发者可以监控应用程序的性能,及时发现和解决问题。

日志关联(Log Correlation)

  • Trace-Driven Logging​:通过 Trace ID 关联日志信息,还原请求的完整上下文信息。
    // 日志示例
    {"trace_id": "4bf92f35...", "message": "DB query failed", "level": "error"}
    

基础设施监控

  • Kubernetes 监控​:采集 Pod/Node 资源指标,结合 OpenTelemetry Collector (配置Prometheus接收器(Receiver)定时抓取)实现基础设施监控及应用监控数据的统一收集处理。

生态与工具

  1. OpenTelemetry Collector
    • 负责接收、处理、导出数据,支持插件化方式扩展数据处理逻辑
    • 该组件是可选组件(如果没有Collector,应用集成SDK、API之后可直接对接存储分析系统如ElasticSearch、Jaeger、Prometheus等),用于集中式收集、处理、导出遥测数据。
  2. 可视化工具
    • Prometheus/Grafana​:指标数据(Metrics)监控与仪表盘。
    • Jaeger​:分布式追踪数据(Traces)可视化(如微服务调用链)。
    • Elasticsearch/Fluentd​:日志数据(Logs)存储与分析。
  3. 服务网格集成
    • 与微服务网格框架 Istio、Linkerd 集成,自动采集微服务之间调用请求性能指标和追踪数据。

部署与使用

OpenTelemetry Collector 部署模式

  • Sidecar 模式​:通过 Kubernetes 平台在每个应用程序 Pod 中部署 OpenTelemetry Collector,减少应用侵入性。
  • Gateway 模式​:集中式 OpenTelemetry Collector 集群,统一收集所有遥测数据并转发到不同后端存储分析系统。

指标数据(Metrics)示例

在代码中使用OpenTelemetry API生成度量指标数据(Metrics),将指标数据(Metrics)以 Prometheus 兼容格式输出到 localhost:8080/metrics 页面,Prometheus 实例定时抓取该页面指标数据进行存储、分析。

package main

import (
    "context"
    "log"
    "net/http"
    "time"

    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/sdk/metric"
    "go.opentelemetry.io/otel/sdk/metric/controller/push"
    "go.opentelemetry.io/otel/sdk/resource"
    "go.opentelemetry.io/otel/exporters/prometheus"
)

func main() {
    // 创建 Prometheus 导出器
    exporter, err := prometheus.New()
    if err != nil {
        log.Fatalf("failed to create Prometheus exporter: %v", err)
    }

    // 创建资源
    res, err := resource.New(context.Background(), resource.WithAttributes())
    if err != nil {
        log.Fatalf("failed to create resource: %v", err)
    }

    // 创建指标控制器
    controller := push.New(
        controller.WithExporter(exporter),
        controller.WithResource(res),
        controller.WithCollectPeriod(2*time.Second),
    )

    // 启动控制器
    if err := controller.Start(context.Background()); err != nil {
        log.Fatalf("failed to start controller: %v", err)
    }
    defer func() {
        if err := controller.Stop(context.Background()); err != nil {
            log.Fatalf("failed to stop controller: %v", err)
        }
    }()

    // 注册 Prometheus HTTP 处理程序
    http.Handle("/metrics", exporter)
    go func() {
        log.Fatal(http.ListenAndServe(":8080", nil))
    }()

    // 创建一个计数器
    meter := otel.Meter("example-meter")
    counter := metric.Must(meter).NewInt64Counter("example_counter")

    // 模拟指标收集
    for {
        counter.Add(context.Background(), 1)
        time.Sleep(1 * time.Second)
    }
}

追踪数据(Traces)示例

在代码中使用OpenTelemetry API生成请求调用追踪数据(Traces),并将追踪数据(Traces)写入Jaeger进行可视化分析。

package main

import (
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/exporters/jaeger"
	"go.opentelemetry.io/otel/sdk/resource"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
)

func main() {
	// 1. 创建 Jaeger Exporter
	exporter, _ := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint("jaeger:14268/api/traces")))
	
	// 2. 配置 Trace Provider
	tp := sdktrace.NewTracerProvider(
		sdktrace.WithBatcher(exporter),
		sdktrace.WithResource(resource.NewWithAttributes("service.name", "my-app")),
	)
	otel.SetTracerProvider(tp)
	
	// 3. 业务代码埋点
	tracer := otel.Tracer("main")
	ctx, span := tracer.Start(context.Background(), "hello-span")
	defer span.End()
}

日志数据(Logs)示例

在代码中使用OpenTelemetry API生成日志数据(Logs),将日志数据(Logs)导出到支持 OTLP 的后端,例如 localhost:4317(可使用 OpenTelemetry Collector,统一收集后导出到 ElasticSearch)。

package main

import (
    "context"
    "log"
    "time"

    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/sdk/resource"
    "go.opentelemetry.io/otel/sdk/log"
    "go.opentelemetry.io/otel/exporters/otlp"
    "google.golang.org/grpc"
)

func main() {
    // 创建 OTLP 导出器
    ctx := context.Background()
    conn, err := grpc.Dial("localhost:4317", grpc.WithInsecure())
    if err != nil {
        log.Fatalf("failed to create gRPC connection: %v", err)
    }
    exporter, err := otlp.NewExporter(otlp.WithGRPCConn(conn))
    if err != nil {
        log.Fatalf("failed to create OTLP exporter: %v", err)
    }

    // 创建资源
    res, err := resource.New(ctx, resource.WithAttributes())
    if err != nil {
        log.Fatalf("failed to create resource: %v", err)
    }

    // 创建日志记录器
    logger := log.New(
        log.WithResource(res),
        log.WithExporter(exporter),
        log.WithFlushInterval(5*time.Second),
    )

    // 启动日志记录器
    if err := logger.Start(ctx); err != nil {
        log.Fatalf("failed to start logger: %v", err)
    }
    defer func() {
        if err := logger.Stop(ctx); err != nil {
            log.Fatalf("failed to stop logger: %v", err)
        }
    }()

    // 生成日志
    for {
        logger.Info("This is an info log message")
        logger.Error("This is an error log message")
        time.Sleep(2 * time.Second)
    }
}

总结

OpenTelemetry 通过标准化可观测数据的采集、处理与传输,成为构建 可观测性体系 的基石。无论是微服务、Serverless 还是传统单体应用,均可通过 OTel 构建可观测能力,帮助应用开发者处理故障诊断、性能分析、性能优化、根因定位,其强大的社区支持和灵活的扩展能力,使其成为云原生时代 ​不可或缺的工具​。

0条评论
0 / 1000
张军
4文章数
0粉丝数
张军
4 文章 | 0 粉丝
原创

一文看懂OpenTelemetry

2025-05-26 10:21:37
1
0

OpenTelemetry 介绍

OpenTelemetry(简称 OTel)是由 CNCF(云原生计算基金会)孵化的开源项目,旨在提供统一的可观测框架和工具集(APIs、SDK),用于生成、收集、处理、传输遥测数据(Telemetry Data),包括指标(Metrics)、追踪(Traces)和日志(Logs),帮助用户分析应用程序的性能和行为。OpenTelemetry 是由 OpenTracing(Uber)和 OpenCensus(Google)两大可观测框架合并后的产物,具备厂商无关性,已成为云原生系统中可观测性(Observability)领域的工业级标准。其架构如下图所示:
image-43.png

主要包含如下3个部分:

  • Instrumentation:支持API(一组抽象接口并无实现,无法单独运行的类库)、SDK(对API的具体实现,能单独运行的服务)、零代码(类似代理机制,具体语言实现方式不同,针对特定库如HTTP、RPC、数据库访问、消息队列访问)方式使用 OpenTelemetry
  • OTLP: OpenTelemetry 定义的数据传输协议
  • OpenTelemetry Collector:是一个厂商无关的服务,用于收集(Receiver)、处理(Processor)和传输(Exporter)遥测数据。它可以作为应用的Sidecar或者单独的代理进程运行,接收不同来源的遥测数据,并将其导出到多种后端系统(如 Prometheus、Jaeger、Zipkin 等)进行存储、分析。

核心功能

数据模型

  • Traces​:记录请求在分布式系统中的访问路径,包含 Trace ID 和 Span(操作单元)信息。
    • Span​:一次具体访问路径,包含开始/结束时间、标签(Tags)、事件(Events)、状态(Status)。
    • Trace​:记录一次请求,每个Trace会关联一个或多个Span。
  • Metrics​:数值指标(如 CPU 使用率、请求速率)。
    • 支持 Counter、Gauge、Histogram 等指标类型。
  • Logs​:结构化日志,支持与 Traces 关联(通过 Trace ID 进行关联),方便问题定位。

传输协议

  • ​**OTLP(OpenTelemetry Protocol)**​:统一的遥测数据传输协议,支持 gRPC 和 HTTP。
  • 兼容性​:可无缝对接 Prometheus、Zipkin、Jaeger 等后端存储分析系统。

数据采集(Instrumentation)

  • 手动埋点​:OpenTelemetry 提供了一组 API接口,允许开发者在应用程序中插入遥测数据收集代码,同时支持多种编程语言。
    from opentelemetry import trace
    tracer = trace.get_tracer("my_tracer")
    with tracer.start_as_current_span("custom_operation"):
        # 业务逻辑
    
  • 自动埋点​:SDK 实现了 API接口具体功能,通过集成 SDK,应用程序自动采集框架(如 HTTP 调用、RPC 调用、数据库调用)的遥测数据。
    • 目前支持的编程语言:Java、Python、Go、.NET、Node.js 等。

数据管理

  • Processor​:对遥测数据进行过滤、聚合或转换,支持自定义数据处理逻辑。
    • Batch Processor​:批量压缩数据,减少网络开销。
    • Simple Processor​:直接转发原始数据。
  • Exporter​:将数据发送到后端存储分析系统(如 Jaeger、Prometheus、Zipkin等)。
    # 配置导出到 Jaeger
    exporters:
      jaeger:
        endpoint: "jaeger:14250"
        insecure: true
    

核心优势

  • 标准化
    • 统一 指标(Metrics)、追踪(Traces)、日志(Logs) 的采集、处理与传输,终结了多套 SDK 并存的混乱局面;
    • 支持指标数据(Metrics)收集、处理,如请求计数、延迟等指标帮助宏观上快速发现系统问题;
    • 支持分布式追踪数据(Traces)收集和处理,允许开发者追踪请求在微服务架构中的调用链,帮助识别性能瓶颈、定位故障;
    • 支持日志数据(Logs)收集、处理,提供全面的观察系统运行情况、定位故障能力。
  • 多语言支持
    • 支持多种编程语言,例如 Java、JavaScript、Python、Go、C# 等,在不同技术栈中使用相同的遥测数据采集框架,不会因技术栈不同导致可观测技术体系碎片化。
  • 功能灵活扩展
    • 通过 收集器(Collector) 组件实现遥测数据接收、路由、过滤和转发,支持自定义 Processor 和 Exporter来处理、传输遥测数据。
  • 云原生友好
    • 原生支持 Kubernetes、Service Mesh(如 Istio)等云原生技术框架。

使用场景

分布式追踪(Distributed Tracing)

  • 问题定位​:追踪微服务调用链,快速定位延迟或故障。
  • 故障排查​:分布式追踪功能可以帮助开发者快速定位故障,了解请求的详细处理流程。
  • 依赖分析​:可视化微服务调用关系(如通过 Jaeger UI)。

性能监控(Performance Monitoring)

  • 指标聚合​:统计吞吐量、错误率、延迟分布(P90/P99)。
  • 告警联动​:通过对接 Prometheus、Grafana 实现数据实时告警。
  • 通过收集和分析指标,开发者可以监控应用程序的性能,及时发现和解决问题。

日志关联(Log Correlation)

  • Trace-Driven Logging​:通过 Trace ID 关联日志信息,还原请求的完整上下文信息。
    // 日志示例
    {"trace_id": "4bf92f35...", "message": "DB query failed", "level": "error"}
    

基础设施监控

  • Kubernetes 监控​:采集 Pod/Node 资源指标,结合 OpenTelemetry Collector (配置Prometheus接收器(Receiver)定时抓取)实现基础设施监控及应用监控数据的统一收集处理。

生态与工具

  1. OpenTelemetry Collector
    • 负责接收、处理、导出数据,支持插件化方式扩展数据处理逻辑
    • 该组件是可选组件(如果没有Collector,应用集成SDK、API之后可直接对接存储分析系统如ElasticSearch、Jaeger、Prometheus等),用于集中式收集、处理、导出遥测数据。
  2. 可视化工具
    • Prometheus/Grafana​:指标数据(Metrics)监控与仪表盘。
    • Jaeger​:分布式追踪数据(Traces)可视化(如微服务调用链)。
    • Elasticsearch/Fluentd​:日志数据(Logs)存储与分析。
  3. 服务网格集成
    • 与微服务网格框架 Istio、Linkerd 集成,自动采集微服务之间调用请求性能指标和追踪数据。

部署与使用

OpenTelemetry Collector 部署模式

  • Sidecar 模式​:通过 Kubernetes 平台在每个应用程序 Pod 中部署 OpenTelemetry Collector,减少应用侵入性。
  • Gateway 模式​:集中式 OpenTelemetry Collector 集群,统一收集所有遥测数据并转发到不同后端存储分析系统。

指标数据(Metrics)示例

在代码中使用OpenTelemetry API生成度量指标数据(Metrics),将指标数据(Metrics)以 Prometheus 兼容格式输出到 localhost:8080/metrics 页面,Prometheus 实例定时抓取该页面指标数据进行存储、分析。

package main

import (
    "context"
    "log"
    "net/http"
    "time"

    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/sdk/metric"
    "go.opentelemetry.io/otel/sdk/metric/controller/push"
    "go.opentelemetry.io/otel/sdk/resource"
    "go.opentelemetry.io/otel/exporters/prometheus"
)

func main() {
    // 创建 Prometheus 导出器
    exporter, err := prometheus.New()
    if err != nil {
        log.Fatalf("failed to create Prometheus exporter: %v", err)
    }

    // 创建资源
    res, err := resource.New(context.Background(), resource.WithAttributes())
    if err != nil {
        log.Fatalf("failed to create resource: %v", err)
    }

    // 创建指标控制器
    controller := push.New(
        controller.WithExporter(exporter),
        controller.WithResource(res),
        controller.WithCollectPeriod(2*time.Second),
    )

    // 启动控制器
    if err := controller.Start(context.Background()); err != nil {
        log.Fatalf("failed to start controller: %v", err)
    }
    defer func() {
        if err := controller.Stop(context.Background()); err != nil {
            log.Fatalf("failed to stop controller: %v", err)
        }
    }()

    // 注册 Prometheus HTTP 处理程序
    http.Handle("/metrics", exporter)
    go func() {
        log.Fatal(http.ListenAndServe(":8080", nil))
    }()

    // 创建一个计数器
    meter := otel.Meter("example-meter")
    counter := metric.Must(meter).NewInt64Counter("example_counter")

    // 模拟指标收集
    for {
        counter.Add(context.Background(), 1)
        time.Sleep(1 * time.Second)
    }
}

追踪数据(Traces)示例

在代码中使用OpenTelemetry API生成请求调用追踪数据(Traces),并将追踪数据(Traces)写入Jaeger进行可视化分析。

package main

import (
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/exporters/jaeger"
	"go.opentelemetry.io/otel/sdk/resource"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
)

func main() {
	// 1. 创建 Jaeger Exporter
	exporter, _ := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint("jaeger:14268/api/traces")))
	
	// 2. 配置 Trace Provider
	tp := sdktrace.NewTracerProvider(
		sdktrace.WithBatcher(exporter),
		sdktrace.WithResource(resource.NewWithAttributes("service.name", "my-app")),
	)
	otel.SetTracerProvider(tp)
	
	// 3. 业务代码埋点
	tracer := otel.Tracer("main")
	ctx, span := tracer.Start(context.Background(), "hello-span")
	defer span.End()
}

日志数据(Logs)示例

在代码中使用OpenTelemetry API生成日志数据(Logs),将日志数据(Logs)导出到支持 OTLP 的后端,例如 localhost:4317(可使用 OpenTelemetry Collector,统一收集后导出到 ElasticSearch)。

package main

import (
    "context"
    "log"
    "time"

    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/sdk/resource"
    "go.opentelemetry.io/otel/sdk/log"
    "go.opentelemetry.io/otel/exporters/otlp"
    "google.golang.org/grpc"
)

func main() {
    // 创建 OTLP 导出器
    ctx := context.Background()
    conn, err := grpc.Dial("localhost:4317", grpc.WithInsecure())
    if err != nil {
        log.Fatalf("failed to create gRPC connection: %v", err)
    }
    exporter, err := otlp.NewExporter(otlp.WithGRPCConn(conn))
    if err != nil {
        log.Fatalf("failed to create OTLP exporter: %v", err)
    }

    // 创建资源
    res, err := resource.New(ctx, resource.WithAttributes())
    if err != nil {
        log.Fatalf("failed to create resource: %v", err)
    }

    // 创建日志记录器
    logger := log.New(
        log.WithResource(res),
        log.WithExporter(exporter),
        log.WithFlushInterval(5*time.Second),
    )

    // 启动日志记录器
    if err := logger.Start(ctx); err != nil {
        log.Fatalf("failed to start logger: %v", err)
    }
    defer func() {
        if err := logger.Stop(ctx); err != nil {
            log.Fatalf("failed to stop logger: %v", err)
        }
    }()

    // 生成日志
    for {
        logger.Info("This is an info log message")
        logger.Error("This is an error log message")
        time.Sleep(2 * time.Second)
    }
}

总结

OpenTelemetry 通过标准化可观测数据的采集、处理与传输,成为构建 可观测性体系 的基石。无论是微服务、Serverless 还是传统单体应用,均可通过 OTel 构建可观测能力,帮助应用开发者处理故障诊断、性能分析、性能优化、根因定位,其强大的社区支持和灵活的扩展能力,使其成为云原生时代 ​不可或缺的工具​。

文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
0
0