// Copyright 2017 Michal Witkowski. All Rights Reserved. // See LICENSE for licensing terms. package grpc_opentracing import ( "encoding/base64" "strings" "google.golang.org/grpc/metadata" ) const ( binHdrSuffix = "-bin" ) // metadataTextMap extends a metadata.MD to be an opentracing textmap type metadataTextMap metadata.MD // Set is a opentracing.TextMapReader interface that extracts values. func (m metadataTextMap) Set(key, val string) { // gRPC allows for complex binary values to be written. encodedKey, encodedVal := encodeKeyValue(key, val) // The metadata object is a multimap, and previous values may exist, but for opentracing headers, we do not append // we just override. m[encodedKey] = []string{encodedVal} } // ForeachKey is a opentracing.TextMapReader interface that extracts values. func (m metadataTextMap) ForeachKey(callback func(key, val string) error) error { for k, vv := range m { for _, v := range vv { if err := callback(k, v); err != nil { return err } } } return nil } // encodeKeyValue encodes key and value qualified for transmission via gRPC. // note: copy pasted from private values of grpc.metadata func encodeKeyValue(k, v string) (string, string) { k = strings.ToLower(k) if strings.HasSuffix(k, binHdrSuffix) { val := base64.StdEncoding.EncodeToString([]byte(v)) v = string(val) } return k, v }