使用 OpenTelemetry 构建可观测性 03 - 导出
上一个博文中,我提到如何使用 OpenTelemery 的特定语言 API 来收集遥测数据,包含手动和自动的埋点技术,这很重要!但是,收集遥测数据只是解决方案的第一步。
你需要把遥测数据路由转发到其他地方,同时添加额外的元数据信息。这时就轮到 SDK 发挥作用了。
链路追踪生产者( Tracer Provider )
链路追踪生产者是 SDK 中一个关键概念。用于将通过 API 收集的遥测数据与其他组件联系起来。在 Go 语言中,TracerProvider 对象只有一个 Tracer 方法的接口,方法签名如下:
Tracer(instrumentationName string, opts ...TracerOption) Tracer
Tracer 方法返回一个实现 Tracer 接口的对象,这个接口也只有一个方法 Start,其方法签名如下:
Start(ctx context.Context, spanName string, opts ...spanStartOption) (context.Context, Span)
样例项目中通过链路追踪生产者创建了跨度( span ):
import "go.opentelemetry.io/otel"// ...ctx, span := otel.Tracer(telemetry.TelemetryLibrary).Start(ctx, "get_product_price")
可以发现通过otel.Tracer 查找并创建全局的链路追踪生产者最终返回 Tracer 对象,需要注意要使用链路追踪生产者,其初始化设置是不可缺少的。
Note: 在文中提及是获取‘全局’链路追踪生产者的方法。使用全局链路追踪最简单的一种方式就是调用 otel.Tracer 的 API 。不过实际使用中如果上面方案不满足,还可以通过链路追踪生产者传递给消费者以替代全局查找的方法。
Note: trace 代表整个请求的路径信息、span 代表链路中的具体节点信息
资源( Resource )
链路追踪生产者还需要配置‘资源’对象,它是元数据信息的一部分。资源是遥测数据产生描述过程或者服务的信息,描述了服务本身的元数据,有助于解析遥测数据。
这是样例项目中购物车服务的‘资源’对象定义:
import ("go.opentelemetry.io/otel/sdk/resource"semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
)// ...res, err := resource.New(ctx,resource.WithAttributes(semconv.ServiceNameKey.String("cart"),semconv.ServiceVersionKey.String("v1.0.0"),),
)
资源对象定义的关键是设置属性参数,OpenTelemetry 已经定义了一些资源属性的键值对,可以参考这篇文档 OTel’s 资源语义约定。 例如,你可以通过上面例子看到,如何定义服务名称和版本号信息。但是可能还有更多信息你需要配置,比如服务自身依赖的资源有哪些;服务运行在云上吗?需要约定不同的属性给不同的云服务供应商;服务运行在 Kubernetes 吗?是的话,这里有份指导手册 Kubernetes 的资源语义约定。
最终样例项目中, 链路追踪数据中 span 都包含这样的‘资源’数据:
Resource labels:-> service.name: STRING(cart)-> service.version: STRING(v1.0.0)
导出器( Exporter )
既然我们已经创建了资源对象,我们接下来定义一下遥测数据的目的地。
导出器的选择范围很广,可以根据自己的需求选择不同的导出器,不过在当前项目例子中我使用 OpenTelemetry 控制器(会在下一篇细聊),它支持 HTTP 和 gRPC 协议。我选择使用 gRPC 协议和 OTLP 导出器:
import ("go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc""google.golang.org/grpc"
)// ...hostIP := os.Getenv("HOST_IP")
if hostIP == "" {return nil, fmt.Errorf("unexpected no host IP address for receiver")
}
receiverAddress := fmt.Sprintf("%s:%d", hostIP, 4317)conn, err := grpc.DialContext(ctx,receiverAddress,grpc.WithTransportCredentials(insecure.NewCredentials()),grpc.WithBlock(),
)
if err != nil {return nil, fmt.Errorf("error creating client connection to collector: %w", err)
}otlpTraceExporter, err := otlptracegrpc.New(ctx,otlptracegrpc.WithGRPCConn(conn),
)
Note: 文中例子是演示的程序,使用的非安全的连接方式来获取数据,不过生产环境中你最起码应该要使用带鉴权的连接方式。
就导出器而言,有多种方式输出结果渠道供你选择,例如:控制台输出(输出到 stdout ), Jaeger (直接发送数据给它), Prometheus 等。使用 OTLP 导出器并将数据发送到 OTel Collector 的好处是,您可以创建数据副本、并行处理数据,并拥有更多控制权(将在下一篇文章中介绍)。
由于使用 OTLP 导出器非常灵活,我们可以根据需要在 Collector 中使用遥测数据(输出到 stdout、发送到 Jaeger 等)。下一篇文章将详细介绍这一点!
整合( Tying it all together )
现在我们有了资源(生成遥测数据)和导出器(遥测数据的目的地),我们将它们放在一起形成链路追踪生产者:
tp := trace.NewTracerProvider(trace.WithSampler(trace.AlwaysSample()),trace.WithResource(res),trace.WithSpanProcessor(trace.NewBatchSpanProcessor(otlpTraceExporter)),
)
当链路追踪生产者创建后,我们需要将其设置为全局链路追踪生产者:
import ("go.opentelemetry.io/otel"
)// ...otel.SetTracerProvider(tp)
接下来我们需要设置‘传播’。在后续博文中,将深入讨论传播和附加数据( baggage ,整个链路中传递业务自定义 KV 属性),但现在只需要知道‘传播’可以将 OTel 链路追踪的上下文信息跨多个服务进行传递。让‘分布式’概念在‘分布式链路追踪’中实现。
import ("go.opentelemetry.io/otel/propagation"
)// ...otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{},propagation.Baggage{}),
)
最后,我们需要调用 TracerProvider.Shutdown 来清理并关闭跨度处理器(在例子中,我们使用批量 span 处理器,按批次将 span 数据进行聚合和批量处理,然后将完整的批处理结果发送给导出器):
defer func() {if err := tp.Shutdown(context.Background()); err != nil {fmt.Printf("Error shutting down tracer provider: %v", err)os.Exit(1)}
}()
Note: 为了可靠性和可读性,仅通过调用 defer tp.Shutdown(context.Background()) 是不够的,需要处理函数返回的一些错误。
链路追踪生产者 Python 版( Python tracer provider )
样例项目中大部分服务都用 Go 语言来编写,用 Python 写了一个服务(定价服务)。为了完整起见,以下是如何在 Python 中创建和设置类似的链路追踪生产者的例子:
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource, SERVICE_NAME, SERVICE_VERSION
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessorresource = Resource(attributes={SERVICE_NAME: "price",SERVICE_VERSION: "v1.0.0"
})
tracer_provider = TracerProvider(resource=resource)host_ip = os.environ.get("HOST_IP")
if host_ip is None:print("Must pass in environment var HOST_IP")sys.exit(1)tracer_provider.add_span_processor(span_processor=BatchSpanProcessor(OTLPSpanExporter(endpoint=f"{host_ip}:4317", insecure=True)
))
trace.set_tracer_provider(tracer_provider)
其中资源、span 处理器和设置全局链路追踪生产者的实现与 Go 描述相同。
总结
很棒前进了一步!按照上面步骤实现了,通过 API 获取了遥测数据,并将其从当前组件中被发送到一个导出器,并向其中添加了一些元数据(资源)!接下来我们将了解如何使用 OpenTelemetry 收集器来处理这来数据。
本文翻译自:Observability with OpenTelemetry Part 3 - SDK and Exporting | Thomas Stringer
扩展阅读:
- 方法论:面向故障处理的可观测性体系建设
- 白皮书:事件 OnCall 中心建设方法
- 好工具:FlashDuty - 一站式告警处理平台:告警降噪、排班OnCall
相关文章:
使用 OpenTelemetry 构建可观测性 03 - 导出
上一个博文中,我提到如何使用 OpenTelemery 的特定语言 API 来收集遥测数据,包含手动和自动的埋点技术,这很重要!但是,收集遥测数据只是解决方案的第一步。 你需要把遥测数据路由转发到其他地方,同时添加额…...
Pyqt5打开电脑摄像头进行拍照
目录 1、设计UI界面 2、设计逻辑代码,建立连接显示窗口 3、结果 1、设计UI界面 将ui界面转为py文件后获得的逻辑代码为:(文件名为 Camera.py) # -*- coding: utf-8 -*-# Form implementation generated from reading ui file …...
Flowable 7.0.0.M2 版本功能
CMMN 支持批量迁移重复支持案例重新激活支持停止内务处理批处理Http 任务支持 HTTP HEAD and OPTIONS for the Http Tasks移除了 Spring Boot 启动器 flowable-spring-boot-starter-basic - 切换为 flowable-spring-boot-starter-process flowable-spring-boot-starter-rest-ap…...
【golang】关于指针的有限操作
传统意义上来说,指针是一个指向某个确切的内存地址的值。这个内存地址可以是任何数据或代码的起始地址。在Go语言中有几种东西可以代表"指针"。其中最贴切传统意义的当属uintptr类型的了。该类型实际上是一个数值类型,也是Go语言内建的数据类型…...
ProGuard + SpringBoot3 + JDK17
1、pom依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.…...
Kafka面试
文章内容转自: 华仔聊技术(Kafka 面试连环炮) 目录 一.初级 1.Kafka核心组件图 2.在 Kafka 中 Zookeeper 作用是什么? 3.生产者有哪些发消息的模式? 4.Kafka 如何合理设置分区数,越多越好吗? Kafka 如何合理设置分区数 分区设置越多越好吗? 5.如何保证 Kafka 中的…...
Amazon CloudFront 部署小指南(六)- Lambda@Edge 基础与诊断
内容简介 本文适用于希望使用 Amazon CloudFront LambdaEdge 提升 Amazon CloudFront 边缘计算能力的用户,旨在帮助您更好的进行 CloudFront LambdaEdge 的开发、调试、测试、部署等工作。 首先我们会对 CloudFront LambdaEdge 做个简单的介绍,然后分七个…...
centos7安装hadoop 单机版
1.解压 (1)将hadoop压缩包复制到/opt/software路径下 (2)解压hadoop到/opt/module目录下 [rootkb135 software]# tar -zxvf hadoop-3.1.3.tar.gz -C /opt/module/ (3)修改hadoop属主和属组 [rootkb135 m…...
村口的人家排放污水,污水浸染了整个村子,怎么办
从前有一个很不错的村子里,村子里有很多户人家,随着生活水平越来越好,房子也修起来了,柏油马路也宽敞了,大家进出村子,都要走那条马路,要不就出不去。 目录 1. 修厕所 2. 村口的日家 3. 告诉…...
算法leetcode|72. 编辑距离(rust重拳出击)
文章目录 72. 编辑距离:样例 1:样例 2:提示: 分析:题解:rust:二维数组(易懂)滚动数组(更加优化的内存空间) go:c:python&a…...
实训笔记8.21
8.21笔记 8.21笔记一、Hive数据仓库技术的基本概念和组成1.1 Hive的组成架构1.1.1 Hive的客户端(1)Hive的命令行客户端 hive命令(2)Hive的JDBC的客户端(Java API)hive的JDBC客户端又有多种使用方式 &#x…...
robust distortion-free watermarks for language models
本文是LLM系列文章,针对《robust distortion-free watermarks for language models》的翻译。 语言模的鲁棒无失真水印 摘要1 引言2 方法和理论分析3 实验结果4 讨论 摘要 我们提出了一种从自回归语言模型中在文本中植入水印的方法,该方法对扰动具有鲁…...
PTS性能测试工具-使用记录
因为PTS使用是要收费的,所以文中会有大量图片记录,为我自己以后工作中,可能会再次使用PTS做个参照,以免时间长,容易忘记~ 目录 一、创建场景 二、填写一个压测节点 1、填写节点基本信息 2、Body / Header填写 …...
【boost网络库从青铜到王者】第六篇:asio网络编程中的socket异步读(接收)写(发送)
文章目录 1、简介2、异步写 void AsyncWriteSomeToSocketErr(const std::string& buffer)3、异步写void AsyncWriteSomeToSocket(const std::string& buffer)4、异步写void AsyncSendToSocket(const std::string& buffer)5、异步读void AsyncReadSomeToSocket(cons…...
django sqlite3操作和manage.py功能介绍
参考链接:https://www.cnblogs.com/csd97/p/8432715.html manage.py 常用命令_python manage.py_追逐&梦想的博客-CSDN博客 python django操作sqlite3_django sqlite_浪子仙迹的博客-CSDN博客...
【SQL语句】SQL编写规范
简介 本文编写原因主要来于XC迁移过程中修改SQL语句时,发现大部分修改均源自于项目SQL编写不规范,以此文档做以总结。 注:此文档覆盖不甚全面,大体只围绕迁移遇到的修改而展开。 正文 1、【字段引号】 列名、表名如无特殊情况…...
后端项目开发:工具类封装(序列化、反射)
1.整合Jackson 根据《阿里巴巴开发规范》,包名使用单数,类名可以使用复数。 所以generic-common创建util包和utils工具类 很多时候我们需要将接收到的json数据转换为对象,或者将对象转为json存储。这时候我们需要编写用于json转换的工具类。…...
软件测试技术分享丨遇到bug怎么分析?
为什么定位问题如此重要? 可以明确一个问题是不是真的“bug” 很多时候,我们找到了问题的原因,结果发现这根本不是bug。原因明确,误报就会降低 多个系统交互,可以明确指出是哪个系统的缺陷,防止“踢皮球…...
LeetCode无重复字符的最长子串
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: s “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。 示例 2: 输入: s “bbbbb” 输出: 1 解释: 因为无重复字符的最长子串是 “…...
17.2.2 【Linux】通过systemctl观察系统上所有的服务
使用 systemctl list-unit-files 会将系统上所有的服务通通列出来~而不像 list-units 仅以 unit 分类作大致的说明。 至于 STATE 状态就是前两个小节谈到的开机是否会载入的那个状态项目。主要有 enabled / disabled / mask / static 等等。 假设我不想要知道这么多…...
告别规则几何!用Python+Matlab为gprMax创建任意复杂地质模型(附HDF5文件生成代码)
突破几何限制:用PythonMatlab构建gprMax复杂地质模型的完整指南 地质雷达模拟领域的研究者常面临一个尴尬困境:脑海中的地质结构复杂多变,但建模工具却只能生成规则几何体。本文将彻底解决这一矛盾,带您掌握跨平台协作建模技术&am…...
BMI160六轴IMU嵌入式驱动开发与FIFO中断实践
1. BMI160惯性测量单元技术深度解析与嵌入式驱动开发实践BMI160是由博世传感器技术公司(Bosch Sensortec)推出的超低功耗、高精度六轴惯性测量单元(IMU),集成三轴加速度计与三轴陀螺仪于单一封装内。该器件专为可穿戴设…...
基于FPGA的智能车牌识别系统Verilog代码详解:含OV5640图像采集与HDMI显示功能...
基于FPGA的车牌识别系统verilog代码,包含verilog仿真代码,matlab仿真 OV5640采集图像,HDMI显示图像,车牌字符显示在车牌左上角,并且把车牌用红框框起。 正点原子达芬奇或者达芬奇pro都可以直接使用,fpga芯片…...
Redis集群模式下如何高效模糊匹配Key?RedisTemplate+Scan全节点遍历实战
Redis集群环境下高效模糊匹配Key的工程实践 Redis作为高性能缓存数据库,在分布式系统中扮演着重要角色。当系统规模扩大,单节点Redis无法满足需求时,集群模式成为必然选择。但在集群环境下,如何高效地进行模糊Key匹配却成为开发者…...
提示内容用户体验优化框架:提示工程架构师的实战指南
提示内容用户体验优化框架:提示工程架构师的实战指南 一、引言:为什么“提示内容”是AI产品的“用户体验咽喉”? 1. 一个真实的痛点:用户与AI的“对话困境” 上周,我在某知名AI写作平台上看到一条用户评论:…...
R语言孟德尔随机化环境搭建:手把手教你搞定gwasvcf、gwasglue等包的安装报错(附本地安装包)
R语言孟德尔随机化环境搭建:从报错到成功的全流程指南 第一次在R中安装孟德尔随机化相关工具包时,那种挫败感我至今记忆犹新。明明按照教程一步步操作,却不断遭遇各种报错——网络超时、依赖缺失、API限制...这些看似简单的问题足以让一个生物…...
MATLAB实时绘图卡顿?优化串口通信与图形刷新的几个实用技巧
MATLAB实时绘图性能优化:突破串口通信与图形刷新的瓶颈 当你在实验室里盯着屏幕上跳动的数据曲线,却发现它像老式幻灯片一样一卡一顿时,那种挫败感简直让人抓狂。特别是在处理高速ADC采样或长时间运行的实验时,MATLAB默认的绘图方…...
AnythingLLM文档处理革命:如何用统一接口解析20+文件格式构建智能知识库
AnythingLLM文档处理革命:如何用统一接口解析20文件格式构建智能知识库 【免费下载链接】anything-llm 这是一个全栈应用程序,可以将任何文档、资源(如网址链接、音频、视频)或内容片段转换为上下文,以便任何大语言模型…...
敏捷开发实战指南:提升团队效率的5个秘诀
在快速迭代的敏捷开发中,测试团队既是质量守门人,也是流程加速器。本文从软件测试从业者的专业视角,提炼五个经过实战验证的高效实践,助力团队突破协作瓶颈、缩短反馈周期,实现质量与速度的双重提升。秘诀一࿱…...
OpenClaw从入门到应用——安装:更新OpenClaw
通过OpenClaw实现副业收入:《OpenClaw赚钱实录:从“养龙虾“到可持续变现的实践指南》 推荐方式:重新运行网站安装程序(原地升级) 首选的更新方式是重新运行官网提供的安装脚本。该脚本会自动检测现有安装࿰…...
