Codebase list golang-github-go-kit-kit / debian/0.6.0-3 tracing / opentracing / grpc.go
debian/0.6.0-3

Tree @debian/0.6.0-3 (Download .tar.gz)

grpc.go @debian/0.6.0-3

d98deb7
 
 
4a29204
7edf859
 
 
d98deb7
0bc00f3
d98deb7
28a1b0d
 
d98deb7
 
0ecbed2
d98deb7
 
0ecbed2
d98deb7
 
 
0bc00f3
8df4980
79f8b0c
d98deb7
 
 
 
 
0ecbed2
d98deb7
 
 
 
0ecbed2
8864ce8
0bc00f3
8864ce8
9e45827
0bc00f3
 
941a019
d98deb7
 
 
 
 
 
 
 
 
 
 
7edf859
 
 
 
d98deb7
 
 
 
 
 
 
 
 
 
 
 
 
package opentracing

import (
	"context"
	"encoding/base64"
	"strings"

	"github.com/opentracing/opentracing-go"
	"github.com/opentracing/opentracing-go/ext"
	"google.golang.org/grpc/metadata"

	"github.com/go-kit/kit/log"
)

// ContextToGRPC returns a grpc RequestFunc that injects an OpenTracing Span
// found in `ctx` into the grpc Metadata. If no such Span can be found, the
// RequestFunc is a noop.
func ContextToGRPC(tracer opentracing.Tracer, logger log.Logger) func(ctx context.Context, md *metadata.MD) context.Context {
	return func(ctx context.Context, md *metadata.MD) context.Context {
		if span := opentracing.SpanFromContext(ctx); span != nil {
			// There's nothing we can do with an error here.
			if err := tracer.Inject(span.Context(), opentracing.TextMap, metadataReaderWriter{md}); err != nil {
				logger.Log("err", err)
			}
		}
		return ctx
	}
}

// GRPCToContext returns a grpc RequestFunc that tries to join with an
// OpenTracing trace found in `req` and starts a new Span called
// `operationName` accordingly. If no trace could be found in `req`, the Span
// will be a trace root. The Span is incorporated in the returned Context and
// can be retrieved with opentracing.SpanFromContext(ctx).
func GRPCToContext(tracer opentracing.Tracer, operationName string, logger log.Logger) func(ctx context.Context, md metadata.MD) context.Context {
	return func(ctx context.Context, md metadata.MD) context.Context {
		var span opentracing.Span
		wireContext, err := tracer.Extract(opentracing.TextMap, metadataReaderWriter{&md})
		if err != nil && err != opentracing.ErrSpanContextNotFound {
			logger.Log("err", err)
		}
		span = tracer.StartSpan(operationName, ext.RPCServerOption(wireContext))
		return opentracing.ContextWithSpan(ctx, span)
	}
}

// A type that conforms to opentracing.TextMapReader and
// opentracing.TextMapWriter.
type metadataReaderWriter struct {
	*metadata.MD
}

func (w metadataReaderWriter) Set(key, val string) {
	key = strings.ToLower(key)
	if strings.HasSuffix(key, "-bin") {
		val = string(base64.StdEncoding.EncodeToString([]byte(val)))
	}
	(*w.MD)[key] = append((*w.MD)[key], val)
}

func (w metadataReaderWriter) ForeachKey(handler func(key, val string) error) error {
	for k, vals := range *w.MD {
		for _, v := range vals {
			if err := handler(k, v); err != nil {
				return err
			}
		}
	}
	return nil
}