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中都有很广泛的应用,但是一直有一个模糊的概念困扰着我,今天刚好有时间来搞清楚并记录下来。 关于fucntion的返回值的问题: function integer clog2( input logic[255:0] value);for(cl…...

微服务的初步使用
环境说明 jdk1.8 maven3.6.3 mysql8 idea2022 spring cloud2022.0.8 微服务案例的搭建 新建父工程 打开IDEA,File->New ->Project,填写Name(工程名称)和Location(工程存储位置),选…...

【2023年11月第四版教材】第18章《项目绩效域》(合集篇)
第18章《项目绩效域》(合集篇) 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 速率 了解速率之前,先详细了解一下比特: 比特 计算机中数据量的单位,也是信息论中信…...
每日一题 518零钱兑换2(完全背包)
题目 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带符号整…...

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

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

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...

23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...