repository
0.0.0-20211101094231-5793ecd6aeec
Repository: https://github.com/yeqown/tracing-practice.git
Documentation: pkg.go.dev
# Packages
No description provided by the author
# README
tracing-practice
tracing practice in golang micro server (gRPC + HTTP). I'm not using any standalone tools to trace,
but part of them(zipkin/jaeger) implementation of opentracing appoint, and another integration solution sentry
.
Practice trace chain
+-- process internal trace2
|
+---> process internal trace1
|
| +---> b trace(gRPC)
entry(HTTP) ---> a trace--gRPC--|
+---> c trace(gRPC)
|
+----> process internal trace3
Get started
Conclusion [WIP] 🚀
how to using opentracing?
first of all, you must boot an opentracing tracer, then register it into global (this is not necessary, but practical).
package x
import (
"github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
xzipkin "github.com/yeqown/tracing-practice/x/x-zipkin"
)
func BootTracerWrapper(localServiceName string, hostPort string) error {
tracer, err := xzipkin.BootZipkinTracer(localServiceName, hostPort)
if err != nil {
return errors.Wrap(err, "BootTracerWrapper.BootZipkinTracer")
}
opentracing.SetGlobalTracer(tracer)
return nil
}
-
cross process(cross servers)
-
HTTP
client side.if you are doing a REST request and want to trace it, you may need to start span here.
package main func main() { // ... // generate span _, sp := x.StartSpanFromContext(context.Background()) defer sp.Finish() // set up request related info(URI, Method) ext.SpanKindRPCClient.Set(sp) ext.HTTPUrl.Set(sp, req.URI) ext.HTTPMethod.Set(sp, req.Method) // inject into request headere carrier := opentracing.HTTPHeadersCarrier(req.Header) err := opentracing.GlobalTracer().Inject(sp.Context(), opentracing.HTTPHeaders, carrier) // ... }
-
HTTP
middleware for server side.middleware need to do:
- parse parent span if HTTP client carried to you.
- create a root span to pass by.
type getTraceID func(spCtx opentracing.SpanContext) string // get trace info from header, if not then create an new one func Opentracing(getTraceIdFromSpanContext getTraceID) gin.HandlerFunc { return func(c *gin.Context) { // prepare work ... carrier := opentracing.HTTPHeadersCarrier(c.Request.Header) clientSpCtx, err := tracer.Extract(opentracing.HTTPHeaders, carrier) if err == nil && clientSpCtx != nil { sp = tracer.StartSpan( c.Request.RequestURI, opentracing.ChildOf(clientSpCtx), ) } else { sp = tracer.StartSpan(c.Request.RequestURI) } defer sp.Finish() // do some work // ... ctx = opentracing.ContextWithSpan(c.Request.Context(), sp) c.Set(_traceContextKey, ctx) traceId := getTraceIdFromSpanContext(sp.Context()) c.Header("X-Trace-Id", traceId) // continue process request c.Next() // do some work // ... } }
-
gRPC
interceptor (client and server).
-
-
internal process(in one server)
- derive the span
func StartSpanFromContext(ctx context.Context) (context.Context, opentracing.Span) { opName := WhoCalling() // StartSpanFromContext will create a span if ctx do not contains trace data. sp, ctx := opentracing.StartSpanFromContext(ctx, opName) return ctx, sp }