英文:
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())
这样可以解决问题。
在这个截图中,你可以看到第一个微服务上的两个跨度。
英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论