当前位置: 首页 > news >正文

golang学习笔记(二):链路追踪

自定义http连接的服务端

package serverimport ("github.com/gin-gonic/gin""go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin""net/http"
)type MyServer struct {Server *http.Server
}func GetServer() *MyServer {gin.SetMode(gin.ReleaseMode)engine := gin.New()s := &http.Server{Handler: engine,}return &MyServer{Server: s,}
}func (s *MyServer) GetEngine() *gin.Engine {return s.Server.Handler.(*gin.Engine)
}func (s *MyServer) Start(addr string) error {e := s.GetEngine()err2 := e.Run(addr)if err2 != nil {return err2}err := s.Server.ListenAndServe()if err != nil {return err}return nil
}func (s *MyServer) EnableTracing() {s.GetEngine().Use(otelgin.Middleware("go20230923"))
}

初始化链路追踪

package tracingimport ("context""fmt""go.opentelemetry.io/contrib/propagators/b3""go.opentelemetry.io/otel""go.opentelemetry.io/otel/exporters/jaeger""go.opentelemetry.io/otel/exporters/stdout/stdouttrace""go.opentelemetry.io/otel/propagation""go.opentelemetry.io/otel/sdk/resource""go.opentelemetry.io/otel/sdk/trace"semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
)var tracer = otel.Tracer("go20230923")func InitStdoutProvider(serviceName string) (func(ctx context.Context) error, error) {tracer = otel.Tracer(serviceName)// stdout as exporterexporter, err := stdouttrace.New(stdouttrace.WithPrettyPrint())if err != nil {return nil, err}tp := trace.NewTracerProvider(trace.WithSampler(trace.AlwaysSample()),trace.WithBatcher(exporter),)otel.SetTracerProvider(tp)otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))return tp.Shutdown, nil
}

注册路由

package routerimport ("fmt""github.com/gin-gonic/gin""go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp""go.opentelemetry.io/otel/trace""go20230923/pkg/server""log""net/http"
)func InitRouter(s *server.MyServer) {engine := s.GetEngine()group := engine.Group("/v1")group.GET("/hello", Hello)group.GET("/world", World)
}func Hello(c *gin.Context) {if trace.SpanFromContext(c.Request.Context()).SpanContext().IsValid() {spanCtx := trace.SpanFromContext(c.Request.Context()).SpanContext()traceId := spanCtx.TraceID()spanId := spanCtx.SpanID()fmt.Printf("traceId : %s\n", traceId)fmt.Printf("spanId : %s\n", spanId)}fmt.Println("hello world")request, err := http.NewRequestWithContext(c.Request.Context(), "GET", "http://localhost:8080/v1/world", nil)if err != nil {log.Fatal(err)}client := http.Client{Transport: otelhttp.NewTransport(http.DefaultTransport)}client.Do(request)
}func World(c *gin.Context) {if trace.SpanFromContext(c.Request.Context()).SpanContext().IsValid() {spanCtx := trace.SpanFromContext(c.Request.Context()).SpanContext()traceId := spanCtx.TraceID()spanId := spanCtx.SpanID()fmt.Printf("traceId : %s\n", traceId)fmt.Printf("spanId : %s\n", spanId)}fmt.Println("hello world")
}

启动入口

package mainimport ("fmt""go20230923/pkg/server""go20230923/pkg/tracing""go20230923/router"
)func main() {s := server.GetServer()s.EnableTracing()tracing.InitStdoutProvider("go20230923")router.InitRouter(s)err := s.Start(":8080")if err != nil {fmt.Println(err)}
}

GET http://localhost:8080/v1/hello 输出:

traceId : 302c3e67a16bd20ce35b9220a4297d08
spanId : f80dd7189261ed84
hello world
traceId : 302c3e67a16bd20ce35b9220a4297d08
spanId : 7826014d750cf1c5
hello world
{"Name": "/v1/world","SpanContext": {"TraceID": "302c3e67a16bd20ce35b9220a4297d08","SpanID": "7826014d750cf1c5","TraceFlags": "01","TraceState": "","Remote": false},"Parent": {"TraceID": "302c3e67a16bd20ce35b9220a4297d08","SpanID": "aaa69798fdc0e90c","TraceFlags": "01","TraceState": "","Remote": true},"SpanKind": 2,"StartTime": "2023-09-29T11:32:41.5265746+08:00","EndTime": "2023-09-29T11:32:41.5271363+08:00","Attributes": [{"Key": "http.method","Value": {"Type": "STRING","Value": "GET"}},{"Key": "http.scheme","Value": {"Type": "STRING","Value": "http"}},{"Key": "http.flavor","Value": {"Type": "STRING","Value": "1.1"}},{"Key": "net.host.name","Value": {"Type": "STRING","Value": "go20230923"}},{"Key": "net.host.port","Value": {"Type": "INT64","Value": 8080}},{"Key": "net.sock.peer.addr","Value": {"Type": "STRING","Value": "::1"}},{"Key": "net.sock.peer.port","Value": {"Type": "INT64","Value": 62471}},{"Key": "http.user_agent","Value": {"Type": "STRING","Value": "Go-http-client/1.1"}},{"Key": "http.route","Value": {"Type": "STRING","Value": "/v1/world"}},{"Key": "http.status_code","Value": {"Type": "INT64","Value": 200}}],"Events": null,"Links": null,"Status": {"Code": "Unset","Description": ""},"DroppedAttributes": 0,"DroppedEvents": 0,"DroppedLinks": 0,"ChildSpanCount": 0,"Resource": [{"Key": "service.name","Value": {"Type": "STRING","Value": "unknown_service:___go_build_go20230923.exe"}},{"Key": "telemetry.sdk.language","Value": {"Type": "STRING","Value": "go"}},{"Key": "telemetry.sdk.name","Value": {"Type": "STRING","Value": "opentelemetry"}},{"Key": "telemetry.sdk.version","Value": {"Type": "STRING","Value": "1.18.0"}}],"InstrumentationLibrary": {"Name": "go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin","Version": "0.44.0","SchemaURL": ""}
}
{"Name": "/v1/hello","SpanContext": {"TraceID": "302c3e67a16bd20ce35b9220a4297d08","SpanID": "f80dd7189261ed84","TraceFlags": "01","TraceState": "","Remote": false},"Parent": {"TraceID": "00000000000000000000000000000000","SpanID": "0000000000000000","TraceFlags": "00","TraceState": "","Remote": false},"SpanKind": 2,"StartTime": "2023-09-29T11:32:41.5252493+08:00","EndTime": "2023-09-29T11:32:41.5271363+08:00","Attributes": [{"Key": "http.method","Value": {"Type": "STRING","Value": "GET"}},{"Key": "http.scheme","Value": {"Type": "STRING","Value": "http"}},{"Key": "http.flavor","Value": {"Type": "STRING","Value": "1.1"}},{"Key": "net.host.name","Value": {"Type": "STRING","Value": "go20230923"}},{"Key": "net.host.port","Value": {"Type": "INT64","Value": 8080}},{"Key": "net.sock.peer.addr","Value": {"Type": "STRING","Value": "::1"}},{"Key": "net.sock.peer.port","Value": {"Type": "INT64","Value": 64585}},{"Key": "http.user_agent","Value": {"Type": "STRING","Value": "PostmanRuntime/7.28.0"}},{"Key": "http.route","Value": {"Type": "STRING","Value": "/v1/hello"}},{"Key": "http.status_code","Value": {"Type": "INT64","Value": 200}}],"Events": null,"Links": null,"Status": {"Code": "Unset","Description": ""},"DroppedAttributes": 0,"DroppedEvents": 0,"DroppedLinks": 0,"ChildSpanCount": 1,"Resource": [{"Key": "service.name","Value": {"Type": "STRING","Value": "unknown_service:___go_build_go20230923.exe"}},{"Key": "telemetry.sdk.language","Value": {"Type": "STRING","Value": "go"}},{"Key": "telemetry.sdk.name","Value": {"Type": "STRING","Value": "opentelemetry"}},{"Key": "telemetry.sdk.version","Value": {"Type": "STRING","Value": "1.18.0"}}],"InstrumentationLibrary": {"Name": "go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin","Version": "0.44.0","SchemaURL": ""}
}
参考

Go语言 如何获取有关 *gin.Context.Request.Context()的详细信息
golang 使用 OpenTelemetry 实现跨服务全链路追踪
github go-moda项目

相关文章:

golang学习笔记(二):链路追踪

自定义http连接的服务端 package serverimport ("github.com/gin-gonic/gin""go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin""net/http" )type MyServer struct {Server *http.Server }func GetServer() *MyS…...

git提交代码实际操作

1.仓库的代码 2.克隆代码下存在的分支 git clobe https://gitee.com/sadsadasad/big-event-11.git 3.查看当下存在的分支 git branch -a 在很多情况下,我们是要围绕着dev分支进行开发,所以我们可以在开发之前问明白围绕那个分支进行开发。 4.直接拉去dev分支代码 5.如果没在…...

TF坐标变换

ROS小乌龟跟随 5.1 TF坐标变换 Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 tf模块:在 ROS 中用于实现不同坐标系之间的点或向量的转换。 在ROS中坐标变换最初对应的是tf,不过在 hydro 版本开始, tf 被弃用,迁移到 tf2,后者更…...

如何进行网络编程和套接字操作?

网络编程是计算机编程中重要的领域之一,它使程序能够在网络上进行数据传输和通信。C语言是一种强大的编程语言,也可以用于网络编程。网络编程通常涉及套接字(Socket)操作,套接字是一种用于网络通信的抽象接口。本文将详…...

在Spark中集成和使用Hudi

本文介绍了在Spark中集成和使用Hudi的功能。使用Spark数据源API(scala和python)和Spark SQL,插入、更新、删除和查询Hudi表的代码片段。 1.安装 Hudi适用于Spark-2.4.3+和Spark 3.x版本。 1.1 Spark 3支持矩阵 Hudi...

力扣第226翻转二叉数 c++三种方法 +注释

题目 226. 翻转二叉树 简单 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。 示例 1: 输入:root [4,2,7,1,3,6,9] 输出:[4,7,2,9,6,3,1]示例 2: 输入:root [2,1,3] 输出&am…...

React项目部署 - Nginx配置

写在前面:博主是一只经过实战开发历练后投身培训事业的“小山猪”,昵称取自动画片《狮子王》中的“彭彭”,总是以乐观、积极的心态对待周边的事物。本人的技术路线从Java全栈工程师一路奔向大数据开发、数据挖掘领域,如今终有小成…...

【Vue3】定义全局变量和全局函数

// main.ts import { createApp } from vue import App from ./App.vue const app createApp(App)// 解决 ts 报错 type Filter {format<T>(str: T): string } declare module vue {export interface ComponentCustomProperties {$filters: Filter,$myArgs: string} }a…...

【Pandas】Apply自定义行数

文章目录 1. Series的apply方法2. DataFrame的apply方法2.1 针对列使用apply2.2 针对行使用apply Pandas提供了很多数据处理的API,但当提供的API不能满足需求的时候,需要自己编写数据处理函数, 这个时候可以使用apply函数apply函数可以接收一个自定义函数, 可以将DataFrame的行…...

C#,数值计算——完全VEGAS编码的蒙特·卡洛计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { /// <summary> /// Complete VEGAS Code /// adaptive/recursive Monte Carlo /// </summary> public abstract class VEGAS { const int NDMX 50; const int …...

纯css实现3D鼠标跟随倾斜

老规矩先上图 为什么今天会想起来整这个呢?这是因为和我朋友吵架, 就是关于这个效果的,就是这个 卡片懸停毛玻璃效果, 我朋友认为纯css也能写, 我则坦言他就是在放狗屁,这种跟随鼠标的3D效果要怎么可能能用纯css写, 然后吵着吵着发现,欸,好像真能用css写哦,我以前还写过这种…...

Pandas数据结构

文章目录 1. Series数据结构1.1 Series数据类型创建1.2 Series的常用属性valuesindex/keys()shapeTloc/iloc 1.3 Series的常用方法mean()max()/min()var()/std()value_counts()describe() 1.4 Series运算加/减法乘法 2. DataFrame数据结构2.1 DataFrame数据类型创建2.2 布尔索引…...

systemverilog function的一点小case

关于function的应用无论是在systemverilog还是verilog中都有很广泛的应用&#xff0c;但是一直有一个模糊的概念困扰着我&#xff0c;今天刚好有时间来搞清楚并记录下来。 关于fucntion的返回值的问题&#xff1a; function integer clog2( input logic[255:0] value);for(cl…...

微服务的初步使用

环境说明 jdk1.8 maven3.6.3 mysql8 idea2022 spring cloud2022.0.8 微服务案例的搭建 新建父工程 打开IDEA&#xff0c;File->New ->Project&#xff0c;填写Name&#xff08;工程名称&#xff09;和Location&#xff08;工程存储位置&#xff09;&#xff0c;选…...

【2023年11月第四版教材】第18章《项目绩效域》(合集篇)

第18章《项目绩效域》&#xff08;合集篇&#xff09; 1 章节内容2 干系人绩效域2.1 绩效要点2.2 执行效果检查2.3 与其他绩效域的相互作用 3 团队绩效域3.1 绩效要点3.2 与其他绩效域的相互作用3.3 执行效果检查3.4 开发方法和生命周期绩效域 4 绩效要点4.1 与其他绩效域的相互…...

Android 11.0 mt6771新增分区功能实现三

1.前言 在11.0的系统开发中,在对某些特殊模块中关于数据的存储方面等需要新增分区来保存, 所以就需要在系统分区新增分区,接下来就来实现这个功能,看系列三的实现过程 2.mt6771新增分区功能实现三的核心类 build/make/tools/releasetools/common.py device/mediatek/mt6…...

计算机网络——计算机网络的性能指标(上)-速率、带宽、吞吐量、时延

目录 速率 比特 速率 例1 带宽 带宽在模拟信号系统中的意义 带宽在计算机网络中的意义 吞吐量 时延 发送时延 传播时延 处理时延 例2 例3 速率 了解速率之前&#xff0c;先详细了解一下比特&#xff1a; 比特 计算机中数据量的单位&#xff0c;也是信息论中信…...

每日一题 518零钱兑换2(完全背包)

题目 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带符号整…...

Linux shell编程学习笔记8:使用字符串

一、前言 字符串是大多数编程语言中最常用最有用的数据类型&#xff0c;这在Linux shell编程中也不例外。 本文讨论了Linux Shell编程中的字符串的三种定义方式的差别&#xff0c;以及字符串拼接、取字符串长度、提取字符串、查找子字符串等常用字符串操作,&#xff0c;以及反…...

【Spring笔记03】Spring依赖注入各种数据类型

这篇文章&#xff0c;详细介绍一下Spring框架中如何注入各种数据类型&#xff0c;包含&#xff1a;注入基本数据类型、数组、集合、Map映射、Property属性、注入空字符串、注入null值、注入特殊字符等内容&#xff0c;以及如何使用命名空间进行依赖注入。 目录 一、注入各种数据…...

OpenClaw多模态探索:Qwen3-32B+RTX4090D镜像截图转报告实践

OpenClaw多模态探索&#xff1a;Qwen3-32BRTX4090D镜像截图转报告实践 1. 为什么选择这个技术组合 上周团队头脑风暴时&#xff0c;我遇到了一个典型痛点&#xff1a;会议室白板上写满了讨论要点&#xff0c;但拍照后整理成电子版纪要需要手动誊写半小时。作为技术负责人&…...

SRAM vs ReRAM vs Flash:一张表看懂不同存内计算芯片的优缺点与选型指南

SRAM vs ReRAM vs Flash&#xff1a;存内计算芯片技术选型全景指南 在AI算力需求爆炸式增长的今天&#xff0c;传统冯诺依曼架构的"内存墙"瓶颈日益凸显。存内计算技术通过将计算单元嵌入存储阵列&#xff0c;彻底打破了数据搬运的能耗桎梏。根据最新行业报告&#x…...

从零开始手搓一个xv6内核页表:跟着MIT 6.S081源码一步步理解虚拟内存初始化

从零构建xv6内核页表&#xff1a;深入解析RISC-V虚拟内存初始化实战 在MIT 6.S081操作系统的学习过程中&#xff0c;xv6作为教学用精简内核&#xff0c;其虚拟内存实现是理解现代计算机内存管理的关键。本文将带您从第一行代码开始&#xff0c;完整复现xv6内核页表的构建过程&…...

终极免费EVE舰船配置神器:Pyfa完整实战指南

终极免费EVE舰船配置神器&#xff1a;Pyfa完整实战指南 【免费下载链接】Pyfa Python fitting assistant, cross-platform fitting tool for EVE Online 项目地址: https://gitcode.com/gh_mirrors/py/Pyfa 在EVE Online这个充满挑战的宇宙中&#xff0c;打造一艘完美的…...

Dify工作流终极指南:3天从新手到专家的完整免费教程

Dify工作流终极指南&#xff1a;3天从新手到专家的完整免费教程 【免费下载链接】Awesome-Dify-Workflow 分享一些好用的 Dify DSL 工作流程&#xff0c;自用、学习两相宜。 Sharing some Dify workflows. 项目地址: https://gitcode.com/GitHub_Trending/aw/Awesome-Dify-Wo…...

零基础养龙虾:OpenClaw部署从入门到上手,一篇讲透!

2026年&#xff0c;OpenClaw&#xff08;昵称 “龙虾”&#xff09;凭借 “能真正动手干活” 的核心能力&#xff0c;成为开源AI Agent领域的顶流。它不仅能像ChatGPT一样聊天&#xff0c;更能自主操作电脑——整理文件、控制浏览器、发送邮件、甚至调用硬件设备。因其图标酷似…...

ReaR实战:构建企业级Linux裸机灾难恢复体系

1. 为什么企业需要裸机灾难恢复方案 想象一下这样的场景&#xff1a;凌晨三点&#xff0c;机房突然响起刺耳的警报声。值班工程师冲进机房&#xff0c;发现核心数据库服务器已经宕机&#xff0c;硬盘指示灯全灭——这是一次严重的硬件故障。更糟糕的是&#xff0c;这台服务器上…...

RT-Thread Nano 3.0.3移植STM32F103后,第一个实战:用FinSH组件实现串口命令行调试

RT-Thread Nano 3.0.3移植STM32F103实战&#xff1a;FinSH组件实现串口命令行调试 当你成功将RT-Thread Nano移植到STM32F103开发板后&#xff0c;第一个令人兴奋的里程碑就是让系统真正"活"起来——而FinSH组件正是实现这一目标的完美起点。这个内置的命令行交互工具…...

Qt与MongoDB的C++实战:从基础连接到图像数据存储

1. 为什么选择Qt与MongoDB组合 在开发需要处理大量非结构化数据的应用时&#xff0c;传统关系型数据库往往会遇到性能瓶颈。我曾经在一个智能安防项目中&#xff0c;需要存储和分析数万张人脸识别图片&#xff0c;正是这个需求让我深入研究了Qt与MongoDB的组合方案。 MongoDB作…...

LFM2.5-1.2B-Thinking-GGUF部署指南:ss端口监听+curl health检测标准化运维流程

LFM2.5-1.2B-Thinking-GGUF部署指南&#xff1a;ss端口监听curl health检测标准化运维流程 1. 平台简介 LFM2.5-1.2B-Thinking-GGUF是Liquid AI推出的轻量级文本生成模型&#xff0c;特别适合在资源有限的环境中快速部署和使用。这个镜像内置了GGUF模型文件和llama.cpp运行时…...