【GO】LGTM_Grafana_gozero_配置trace(4)_代码实操及追踪

最近在尝试用 LGTM 来实现 Go 微服务的可观测性,就顺便整理一下文档。

Tempo 会分为 4 篇文章:

  1. Tempo 的架构
  2. 官网测试实操跑通
  3. gin 框架发送 trace 数据到 tempo
  4. go-zero 微服务框架发送数据到 tempo

本文就是写一下如何在 go-zero 微服务框架里面配置 trace 及 trace 的 handler 在哪里

代码地址:lgtm/example/go-zero-lgtm at main · zxmfke/lgtm (github.com)

这个代码里面包含一个 order 的 api 服务和一个 user 的 rpc 服务


go-zero 的服务接入 trace,是比较简单的,只需要在配置项中,配置 Telemetry 里面的参数就可以了。

Telemetry 配置

在 /etc 下有配置文件,其中配置:

...Telemetry:Name: "order"Endpoint: "127.0.0.1:4318"Batcher: "otlphttp"...

源码(core/trace/config.go)中可以配置的参数:

type Config struct {Name     string  `json:",optional"`Endpoint string  `json:",optional"`Sampler  float64 `json:",default=1.0"`Batcher  string  `json:",default=jaeger,options=jaeger|zipkin|otlpgrpc|otlphttp|file"`// OtlpHeaders represents the headers for OTLP gRPC or HTTP transport.// For example://  uptrace-dsn: 'http://project2_secret_token@localhost:14317/2'OtlpHeaders map[string]string `json:",optional"`// OtlpHttpPath represents the path for OTLP HTTP transport.// For example// /v1/tracesOtlpHttpPath string `json:",optional"`// Disabled indicates whether StartAgent starts the agent.Disabled bool `json:",optional"`
}

主要就是配置:

  • Name:服务名称
  • Endpoint:Trace provider 的 IP 地址
  • Batcher:用哪一种 provider 类型

注意,Disabled 如果没有设置为 true,就默认表示发送 trace 数据

Grafana Tempo Trace Data

请求接口后,trace 数据会发送到 Grafana 的 Tempo 里面,如下图:

在这里插入图片描述

可以看到分为三段:

  • order-api 收到请求的时候
  • order-api 请求 user-rpc 的时候
  • user-rpc 收到请求的时候

接下来我们可以追踪一下源码看看是在哪里发送的 trace 数据

追踪代码
初始化

order

order 是 api 服务,Telemetry 初始化的逻辑:

  • order.go

    // L24
    server := rest.MustNewServer(c.RestConf)
    
  • go-zero/rest/server.go

    // L35
    func MustNewServer(c RestConf, opts ...RunOption) *Server {server, err := NewServer(c, opts...)...
    }// L46
    func NewServer(c RestConf, opts ...RunOption) (*Server, error) {if err := c.SetUp(); err != nil {return nil, err}...return server, nil
    }
    
  • go-zero/core/sevice/serviceconf.go

    // L44
    func (sc ServiceConf) SetUp() error {...trace.StartAgent(sc.Telemetry)...return nil
    }
    
  • go-zero/core/trace/agent.go

    // L39
    func StartAgent(c Config) {...// if error happens, let later calls run.if err := startAgent(c); err != nil {return}...
    }
    

user

  • user.go

    // L29
    s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {userclient.RegisterUserServer(grpcServer, srv)if c.Mode == service.DevMode || c.Mode == service.TestMode {reflection.Register(grpcServer)}
    })
    defer s.Stop()
    
  • go-zero/zrpc/server.go

    // L23 
    func MustNewServer(c RpcServerConf, register internal.RegisterFn) *RpcServer {server, err := NewServer(c, register)logx.Must(err)return server
    }// L30
    func NewServer(c RpcServerConf, register internal.RegisterFn) (*RpcServer, error) {...if err = c.SetUp(); err != nil {return nil, err}return rpcServer, nil
    }
    
  • Setup() 跟 order 的一样了

Order api 的 trace handler

之前看过源码,go-zero 的 api 和 rpc 是分开两个目录,所以 api 的代码一定在 go-zero/rest 下面。 要在请求的收到的时候发送一个 trace 数据,只有可能以中间件的形式加入,因此可以找到 rest 下的 handler 文件夹,里面就有一个 tracinghandler.go。

源码位置:go-zero/rest/handler/tracinghandler.go

这个就类似上一篇的 gin server 加 trace middleware 一样。

func TracingHandler(serviceName, path string) func(http.Handler) http.Handler {return func(next http.Handler) http.Handler {propagator := otel.GetTextMapPropagator()tracer := otel.GetTracerProvider().Tracer(trace.TraceName)return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {ctx := propagator.Extract(r.Context(), propagation.HeaderCarrier(r.Header))spanName := pathif len(spanName) == 0 {spanName = r.URL.Path}spanCtx, span := tracer.Start(ctx,spanName,oteltrace.WithSpanKind(oteltrace.SpanKindServer),oteltrace.WithAttributes(semconv.HTTPServerAttributesFromHTTPRequest(serviceName, spanName, r)...),)defer span.End()// convenient for tracking error messagespropagator.Inject(spanCtx, propagation.HeaderCarrier(w.Header()))next.ServeHTTP(w, r.WithContext(spanCtx))})}
}
User rpc 的 trace handler

同理,user 是 rpc 服务,所以就到 zrpc 下面找,按照惯性,找到 go-zero/zrpc/internal/serverinterceptors ,这个时候就可以看到 tracinginterceptor.go

源码位置:go-zero/zrpc/internal/serverinterceptors/tracinginterceptor.go

func UnaryTracingInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo,handler grpc.UnaryHandler) (interface{}, error) {ctx, span := startSpan(ctx, info.FullMethod)defer span.End()ztrace.MessageReceived.Event(ctx, 1, req)resp, err := handler(ctx, req)if err != nil {s, ok := status.FromError(err)if ok {span.SetStatus(codes.Error, s.Message())span.SetAttributes(ztrace.StatusCodeAttr(s.Code()))ztrace.MessageSent.Event(ctx, 1, s.Proto())} else {span.SetStatus(codes.Error, err.Error())}return nil, err}span.SetAttributes(ztrace.StatusCodeAttr(gcodes.OK))ztrace.MessageSent.Event(ctx, 1, resp)return resp, nil
}

找到这个,但是没有发现 order-api 调用 user 的 handler。就很奇怪,又返回 rest 里面找,不过还是没找到,后面才发现 zrpc/internal 下面有一个 clientinterceptors ,原来在这边。

func UnaryTracingInterceptor(ctx context.Context, method string, req, reply interface{},cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {ctx, span := startSpan(ctx, method, cc.Target())defer span.End()ztrace.MessageSent.Event(ctx, 1, req)ztrace.MessageReceived.Event(ctx, 1, reply)if err := invoker(ctx, method, req, reply, cc, opts...); err != nil {s, ok := status.FromError(err)if ok {span.SetStatus(codes.Error, s.Message())span.SetAttributes(ztrace.StatusCodeAttr(s.Code()))} else {span.SetStatus(codes.Error, err.Error())}return err}span.SetAttributes(ztrace.StatusCodeAttr(gcodes.OK))return nil
}

ror(err)
if ok {
span.SetStatus(codes.Error, s.Message())
span.SetAttributes(ztrace.StatusCodeAttr(s.Code()))
} else {
span.SetStatus(codes.Error, err.Error())
}
return err
}

span.SetAttributes(ztrace.StatusCodeAttr(gcodes.OK))
return nil

}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/140696.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++ list容器的实现及讲解

所需要的基础知识 对C类的基本了解 默认构造函数 操作符重载 this指针 引用 模板等知识具有一定的了解&#xff0c;阅读该文章会很轻松。 链表节点 template<class T>struct list_node{T _data;list_node<T>* _next;list_node<T>* _prev;list_node(const T&…

顺序表的实现和练习

杂谈&#xff1a; 有些数据结构&#xff08;C语言实现&#xff09;的教材/教程中会使用C中引用的语法&#xff0c;引用确实在形式上比指针简洁&#xff0c;这样做无非是为了避免后续对二级指针的使用。 我认为既然使用C语言实现数据结构&#xff0c;那么指针就不应该是门槛。…

关于地址存放的例题

unsigned int a 0x1234; unsigned char b *(unsigned char*)&a; 上面代码大端存储和小端存储的值分别是多少&#xff1f; 大端存储的是把高位地址存放在低位地址处&#xff0c;低位存放到高位。小端是高位存放在高位&#xff0c;低位在低位。因为a是整型&#xff0c;所…

Kafka的消息存储机制

前面咱们简单讲了K啊开发入门相关的概念、架构、特点以及安装启动。 今天咱们来说一下它的消息存储机制。 前言&#xff1a; Kafka通过将消息持久化到磁盘上的日志文件来实现高吞吐量的消息传递。 这种存储机制使得Kafka能够处理大量的消息&#xff0c;并保证消息的可靠性。 1…

vue重修003

文章目录 版权声明day03一、今日目标1.生命周期2.综合案例-小黑记账清单3.工程化开发入门4.综合案例-小兔仙首页 二、Vue生命周期三、Vue生命周期钩子四、生命周期钩子小案例1.在created中发送数据2.在mounted中获取焦点 五、案例-小黑记账清单1.需求图示&#xff1a;2.需求分析…

ChatGPT批量写作文章软件

什么是ChatGPT批量写作文章。简单来说&#xff0c;它是一种使用ChatGPT技术的方法&#xff0c;可以帮助您批量生成各种类型的文章和内容。无论您是需要新闻报道、博客文章、产品描述、社交媒体帖子还是其他类型的内容&#xff0c;ChatGPT都能满足您的需求。它可以在极短的时间内…

探索 GO 项目依赖包管理与Go Module常规操作

探索 GO 项目依赖包管理与Go Module常规操作 文章目录 探索 GO 项目依赖包管理与Go Module常规操作一.Go 构建模式的演变1.1 GOPATH &#xff08;初版&#xff09;1.1.1 go get 1.2 vendor 机制&#xff08;中版&#xff09;1.3 Go Module&#xff08;最新版&#xff09; 二.创…

C语言 cortex-A7核UART总线实验

一、C 1&#xff09;uart4.h #ifndef __UART4_H__ #define __UART4_H__ #include "stm32mp1xx_rcc.h" #include "stm32mp1xx_gpio.h" #include "stm32mp1xx_uart.h&quo…

4k、VR与万兆光网

“全光万兆”对VR意义重大。 pico4的分辨率 PICO 4 的单眼分辨率是 2160 2160&#xff0c;整体分辨率高达 4320 2160。这是一款高性能的 VR 一体机&#xff0c;采用了 2.56 英寸的 Fast-LCD 屏幕&#xff0c;最高可实现 90Hz 刷新率&#xff0c;还有 1200 PPI 和 20.6 PPD 的…

基于海康Ehome/ISUP接入到LiveNVR实现海康摄像头、录像机视频统一汇聚,做到物联网无插件直播回放和控制

LiveNVR支持海康NVR摄像头通EHOME接入ISUP接入LiveNVR分发视频流或是转GB28181 1、海康 ISUP 接入配置2、海康设备接入2.1、海康EHOME接入配置示例2.2、海康ISUP接入配置示例 3、通道配置3.1、直播流接入类型 海康ISUP3.2、海康 ISUP 设备ID3.3、启用保存3.4、接入成功 4、相关…

Mac磁盘空间满了怎么办?Mac如何清理磁盘空间

你是不是发现你的Mac电脑存储越来越满&#xff0c;甚至操作系统本身就占了100多G的空间&#xff1f;这不仅影响了电脑的性能&#xff0c;而且也让你无法存储更多的重要文件和软件。别担心&#xff0c;今天这篇文章将告诉你如何清除多余的文件&#xff0c;让你的Mac重获新生。 一…

Nginx的location作用

location Nginx 的 locaiton 作⽤是根据⽤户请求的 URI 不同&#xff0c;来执行不同的应用。针对用户请求的网站URL 进行匹配&#xff0c;匹配成功后进行对应的操作。 location [ | ~| ~* | ^~ ] url {#指定对应的动作 } 正则表达式解释 匹配符 匹配规则 优先级 精确匹配 1…

数据结构——二叉树层序遍历

链式二叉树的建立 前言一、层序遍历的概念和实现二、判断二叉树是否是完全二叉树总结 前言 来喽来喽~ 二叉树的层序遍历来喽~ 层序遍历那是相当有趣滴&#xff01; 我的朋友&#xff0c;请不要迷惘&#xff0c;你要记住&#xff0c;你终有鲲鹏一日&#xff01; 加油吧&#xf…

详解MySQL存储引擎

前言: 📕作者简介:热爱编程的小七,致力于C、Java、Python等多编程语言,热爱编程和长板的运动少年! 📘相关专栏Java基础语法,JavaEE初阶,数据库,数据结构和算法系列等,大家有兴趣的可以看一看。 😇😇😇有兴趣的话关注博主一起学习,一起进步吧! 一、MySQL存…

修改vscode底部栏背景和字体颜色

修改vscode底部栏背景和字体颜色 如图&#xff1a; 首先打开齿轮&#xff0c;打开设置搜索workbench.colorCustomizations,然后点击编辑setting.json修改setting.json内内容 "workbench.colorCustomizations": {"statusBar.foreground": "#FFFFFF…

5G通信与蜂窝模组之间的关系

5G通信是第五代移动通信技术的简称&#xff0c;它代表了一种新一代的无线通信技术标准。5G通信的主要目标是提供更高的数据传输速度、更低的延迟、更大的网络容量以及更可靠的连接&#xff0c;以支持各种新兴应用和服务&#xff0c;包括高清视频流、虚拟现实、物联网&#xff0…

安全生产一张图 安全生产三维地理信息平台

一、 建设目标 易图讯科技是一家专业从事大数据、移动互联网、物联网、三维GIS、AI系统研发&#xff0c;开发了三维电子沙盘、AI三维电子沙盘、WEB三维地球、移动端三维地球、数字武装三维电子沙盘、智慧动员三维电子沙盘、智慧公安三维电子沙盘、智慧安监三维电子沙盘、森林防…

【动手学深度学习-Pytorch版】序列到序列的学习(包含NLP常用的Mask技巧)

序言 这一节是对于“编码器-解码器”模型的实际应用&#xff0c;编码器和解码器架构可以使用长度可变的序列作为输入&#xff0c;并将其转换为固定形状的隐状态&#xff08;编码器实现&#xff09;。本小节将使用“fra-eng”数据集&#xff08;这也是《动手学习深度学习-Pytor…

linux 安装 wordpress

文章目录 linux 安装 wordpress1. wordpress 简介2. wordpress功能和特点3. 部署要求4. 环境搭建4.1 部署 nginx4.1.1 新增配置文件 4.2 部署 PHP74.2.1 查看当前版本4.2.2 YUM 安装 PHP74.2.3 查看 PHP 版本4.2.4 启动PHP-FPM4.2.5 修改配置文件4.2.6 重启服务 4.3 部署 mysql…

IDEA下使用Spring MVC

<?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.0.0 http://ma…