当前位置: 首页 > 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;以及如何使用命名空间进行依赖注入。 目录 一、注入各种数据…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...