如何使用Opentelemetry和Otelgin在两个Go微服务之间进行分布式跟踪?

huangapple go评论109阅读模式
英文:

How do I distribute tracing between 2 Go microservices using Opentelemetry & Otelgin?

问题

我正在尝试使用Opentelemetry和Gin-Gonic在两个Go微服务之间进行分布式跟踪。

请帮忙,我已经找到了Otelhttp的示例,但是找不到使用Otelgin的示例。

使用"go.opentelemetry.io/otel/sdk/trace"作为tracesdk。

微服务1:

func TracerProvider() (*tracesdk.TracerProvider, error) {
	otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
	exporter, _ := stdouttrace.New(stdouttrace.WithPrettyPrint())
	tp := tracesdk.NewTracerProvider(
		tracesdk.WithSampler(tracesdk.AlwaysSample()),
		tracesdk.WithBatcher(exporter),
		tracesdk.WithResource(resource.NewWithAttributes(
			semconv.ServiceNameKey.String("microservice-1"),
			attribute.String("environment", "test"),
		)),
	)

	otel.SetTracerProvider(tp)
	return tp, nil
}

func main() {
	TracerProvider()
	resty := resty.New()

	router := gin.Default()
	router.Use(otelgin.Middleware("microservice-1"))
	{
		router.GET("/ping", func(c *gin.Context) {
			result := Result{}
			req := resty.R().SetHeader("Content-Type", "application/json")
			ctx := req.Context()
			span := trace.SpanFromContext(ctx)
			defer span.End()
			otel.GetTextMapPropagator().Inject(ctx, propagation.HeaderCarrier(req.Header))
			resp, _ := req.Get("http://localhost:8088/pong")

			json.Unmarshal([]byte(resp.String()), &result)
			c.IndentedJSON(200, gin.H{
				"message": result.Message,
			})
		})
	}
	router.Run(":8085")
}

微服务2:

// TracerProvider函数与微服务1相同

// main函数
TracerProvider()
router := gin.Default()
router.Use(otelgin.Middleware("microservice-2"))
{
	router.GET("/pong", func(c *gin.Context) {
		ctx := c.Request.Context()
		span := trace.SpanFromContext(otel.GetTextMapPropagator().Extract(ctx, propagation.HeaderCarrier(c.Request.Header)))
		defer span.End()

		c.IndentedJSON(200, gin.H{
			"message": "pong",
		})
	})
}
router.Run(":8088")
英文:

I am trying to distribute tracing between 2 Go microservices using Opentelemetry and Gin-Gonic.

Please help, I have come across Otelhttp examples, but I couldn't find examples with Otelgin.

Using "go.opentelemetry.io/otel/sdk/trace" as tracesdk

Microservice 1

func TracerProvider() (*tracesdk.TracerProvider, error) {
	otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
	exporter, _:= stdouttrace.New(stdouttrace.WithPrettyPrint())
	tp := tracesdk.NewTracerProvider(
		tracesdk.WithSampler(tracesdk.AlwaysSample()),
		tracesdk.WithBatcher(exporter),
		tracesdk.WithResource(resource.NewWithAttributes(
			semconv.ServiceNameKey.String("microservice-1"),
			attribute.String("environment", "test"),
		)),
	)

	otel.SetTracerProvider(tp)
	return tp, nil
}
func main() {
	TracerProvider()
	resty := resty.New()

	router := gin.Default()
	router.Use(otelgin.Middleware("microservice-1"))
	{
		
		router.GET("/ping", func(c *gin.Context) {
            result := Result{}
		    req := resty.R().SetHeader("Content-Type", "application/json")
		    ctx := req.Context()
		    span := trace.SpanFromContext(ctx)
            defer span.End()
		    otel.GetTextMapPropagator().Inject(ctx, propagation.HeaderCarrier(req.Header))
		    resp, _ := req.Get("http://localhost:8088/pong")

		json.Unmarshal([]byte(resp.String()), &result)
			c.IndentedJSON(200, gin.H{
				"message": result.Message,
			})
		})
	}
	router.Run(":8085")

}

// Microservice 2

//TracerProvider func is the same as Microservice 1

//main

TracerProvider()
router := gin.Default()
router.Use(otelgin.Middleware("microservice-2"))
{
	router.GET("/pong", func(c *gin.Context) {
		ctx := c.Request.Context()
		span := trace.SpanFromContext(otel.GetTextMapPropagator().Extract(ctx, propagation.HeaderCarrier(c.Request.Header)))
		defer span.End()

		c.IndentedJSON(200, gin.H{
			"message": "pong",
		})
	})
}
router.Run(":8088")

答案1

得分: 2

在OpenTelemetry Go Contrib的官方存储库中有一个go-gin仪表化的示例:
https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/instrumentation/github.com/gin-gonic/gin/otelgin/example

基本上,你需要使用以下包:
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"

你还可以添加"otelgin.HTML"来渲染你的响应。

HTML将跟踪模板的渲染作为给定上下文中span的子级。
这是gin.Context.HTML函数的替代品-它在设置完span后调用原始函数。

详细的实现可以在这里找到:https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/github.com/gin-gonic/gin/otelgin/gintrace.go

英文:

There is an example of go-gin instrumentation in the official repository of OpenTelemetry Go Contrib:
https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/instrumentation/github.com/gin-gonic/gin/otelgin/example

Basically, you need use the package:
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"

And you can also add the otelgin.HTML to render your response.

> HTML will trace the rendering of the template as a child of the span in the given context.
This is a replacement for gin.Context.HTML function - it invokes the original function after setting up the span.

As detailed in its implementation: https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/github.com/gin-gonic/gin/otelgin/gintrace.go

答案2

得分: 0

可能有点晚,但仍然会有用。
在第一个微服务中,你需要添加以下代码:

req := resty.R().SetHeader("Content-Type", "application/json")
req.SetContext(c.Request.Context())

这样可以解决问题。
在这个截图中,你可以看到第一个微服务上的两个跨度。

如何使用Opentelemetry和Otelgin在两个Go微服务之间进行分布式跟踪?

英文:

It might be a bit late but it will still be useful.
In the 1st microservice, you need to put:

req := resty.R().SetHeader("Content-Type", "application/json")
req.SetContext(c.Request.Context())

That will fix the problem.
On this screenshot you are able to see the 2 spans on the 1st microservice

如何使用Opentelemetry和Otelgin在两个Go微服务之间进行分布式跟踪?

huangapple
  • 本文由 发表于 2022年2月21日 20:39:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/71206475.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定