ZBLOG

golang基于grpc的微服务开发脚手架分布式日志链路追踪设计

在Golang基于gRPC的微服务开发中,常常需要对分布式系统进行日志和链路追踪,以便更好地进行监控和调试。下面是一个简单的设计示例:

  1. 安装依赖:
$ go get google.golang.org/grpc
$ go get github.com/golang/protobuf/proto
$ go get github.com/golang/protobuf/protoc-gen-go

# 安装logrus和logrus的json格式输出插件。
$ go get github.com/sirupsen/logrus
$ go get github.com/mattn/go-isatty

# 安装opentracing相关库。
$ go get github.com/opentracing/opentracing-go
$ go get github.com/uber/jaeger-client-go/config
  1. 在main函数中初始化Logrus、Jaeger等组件并设置日志级别、输出格式等参数:
import (
	"log"
	"os"

	"github.com/sirupsen/logrus"
	"github.com/mattn/go-isatty"

    "github.com/opentracing/opentracing-go"
    "github.com/uber/jaeger-client-go/config"
)

func main() {
    // 初始化Logrus,并设置日志级别、输出格式等参数。
	logrus.SetFormatter(&logrus.JSONFormatter{})
	if isatty.IsTerminal(os.Stdout.Fd()) {
		logrus.SetLevel(logrus.DebugLevel)
	} else {
		logrus.SetLevel(logrus.InfoLevel)
	}
	logrus.SetOutput(os.Stdout)

    // 初始化Jaeger Tracer。
	cfg, err := config.FromEnv()
	if err != nil {
        log.Fatalf("Failed to read Jaeger config from env: %v", err)
    }
	tracer, closer, err := cfg.NewTracer()
	if err != nil {
		log.Fatalf("Failed to create Jaeger tracer: %v", err)
	}
	defer closer.Close()
	opentracing.SetGlobalTracer(tracer)

    // ...
}

  1. 封装Logrus和Jaeger,以便在Golang基于gRPC的微服务开发中进行使用:
import (
    "github.com/sirupsen/logrus"

    "github.com/opentracing/opentracing-go"
    "github.com/opentracing/opentracing-go/ext"
    "github.com/uber/jaeger-client-go"
    jaegercfg "github.com/uber/jaeger-client-go/config"
)

var log *logrus.Entry

func init() {
    log = logrus.WithFields(logrus.Fields{
        "app": "myapp",
        "env": "production",
    })
}

func doSomething(ctx context.Context) {
	// 创建Span。
	span, ctx := opentracing.StartSpanFromContext(ctx, "doSomething")
	defer span.Finish()

	// 记录日志。
	log.WithFields(logrus.Fields{
		"operation": span.OperationName(),
        "trace_id":  span.Context().(jaeger.SpanContext).TraceID().String(),
        "span_id":   span.Context().(jaeger.SpanContext).SpanID().String(),
        }).Infof("doing something")

	// 发起下游调用,将当前Span传递给下游服务。
	req := &pb.Request{...}
	resp, err := client.Call(ctx, req)
	if err != nil {...}

	// 记录返回结果,并设置相关标签。
	ext.HTTPStatusCode.Set(span, uint16(resp.StatusCode))
	log.WithFields(logrus.Fields{
		"operation":     span.OperationName(),
        "trace_id":      span.Context().(jaeger.SpanContext).TraceID().String(),
        "span_id":       span.Context().(jaeger.SpanContext).SpanID().String(),
        "response_code": resp.StatusCode,
        }).Infof("got response")

	// ...
}

在这个设计中,我们使用了Logrus作为日志组件,并使用Jaeger作为分布式链路追踪组件。在main函数中初始化Logrus和Jaeger,并设置日志级别、输出格式等参数。封装Logrus和Jaeger时,可以在init函数中创建全局log实例和tracer实例,并设置一些默认的字段值,然后在需要打印日志或者记录Span的地方调用对应的方法即可。注意,在记录日志和记录Span时都要将当前上下文ctx传递给相关方法,以便进行跨服务间的信息传递。同时,在发起下游调用时也需要将当前Span传递给下游服务,以便进行链路追踪。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=7029

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?