mirror of https://github.com/grafana/grafana
parent
1c3ad78672
commit
02975256d1
@ -0,0 +1,91 @@ |
||||
# Zipkin compatibility features |
||||
|
||||
## `NewZipkinB3HTTPHeaderPropagator()` |
||||
|
||||
Adds support for injecting and extracting Zipkin B3 Propagation HTTP headers, |
||||
for use with other Zipkin collectors. |
||||
|
||||
```go |
||||
|
||||
// ... |
||||
import ( |
||||
opentracing "github.com/opentracing/opentracing-go" |
||||
jaeger "github.com/uber/jaeger-client-go" |
||||
"github.com/uber/jaeger-client-go/zipkin" |
||||
) |
||||
|
||||
func main() { |
||||
// ... |
||||
|
||||
zipkinPropagator := zipkin.NewZipkinB3HTTPHeaderPropagator() |
||||
injector := jaeger.TracerOptions.Injector(opentracing.HTTPHeaders, zipkinPropagator) |
||||
extractor := jaeger.TracerOptions.Extractor(opentracing.HTTPHeaders, zipkinPropagator) |
||||
|
||||
// Zipkin shares span ID between client and server spans; it must be enabled via the following option. |
||||
zipkinSharedRPCSpan := jaeger.TracerOptions.ZipkinSharedRPCSpan(true) |
||||
|
||||
// create Jaeger tracer |
||||
tracer, closer := jaeger.NewTracer( |
||||
"myService", |
||||
mySampler, // as usual |
||||
myReporter // as usual |
||||
injector, |
||||
extractor, |
||||
zipkinSharedRPCSpan, |
||||
) |
||||
|
||||
opentracing.SetGlobalTracer(tracer) |
||||
|
||||
// continue main() |
||||
} |
||||
``` |
||||
|
||||
If you'd like to follow the official guides from https://godoc.org/github.com/uber/jaeger-client-go/config#example-Configuration-InitGlobalTracer-Production, here is an example. |
||||
|
||||
```go |
||||
import ( |
||||
"time" |
||||
|
||||
opentracing "github.com/opentracing/opentracing-go" |
||||
"github.com/uber/jaeger-client-go" |
||||
jaegerClientConfig "github.com/uber/jaeger-client-go/config" |
||||
"github.com/uber/jaeger-client-go/zipkin" |
||||
"github.com/uber/jaeger-client-go/log" |
||||
"github.com/uber/jaeger-lib/metrics" |
||||
) |
||||
|
||||
func main(){ |
||||
//... |
||||
|
||||
// Recommended configuration for production. |
||||
cfg := jaegercfg.Configuration{} |
||||
|
||||
// Example logger and metrics factory. Use github.com/uber/jaeger-client-go/log |
||||
// and github.com/uber/jaeger-lib/metrics respectively to bind to real logging and metrics |
||||
// frameworks. |
||||
jLogger := jaegerlog.StdLogger |
||||
jMetricsFactory := metrics.NullFactory |
||||
|
||||
// Zipkin shares span ID between client and server spans; it must be enabled via the following option. |
||||
zipkinPropagator := zipkin.NewZipkinB3HTTPHeaderPropagator() |
||||
|
||||
// Create tracer and then initialize global tracer |
||||
closer, err := cfg.InitGlobalTracer( |
||||
serviceName, |
||||
jaegercfg.Logger(jLogger), |
||||
jaegercfg.Metrics(jMetricsFactory), |
||||
jaegercfg.Injector(opentracing.HTTPHeaders, zipkinPropagator), |
||||
jaegercfg.Extractor(opentracing.HTTPHeaders, zipkinPropagator), |
||||
jaegercfg.ZipkinSharedRPCSpan(true), |
||||
) |
||||
|
||||
if err != nil { |
||||
log.Printf("Could not initialize jaeger tracer: %s", err.Error()) |
||||
return |
||||
} |
||||
defer closer.Close() |
||||
|
||||
// continue main() |
||||
} |
||||
|
||||
``` |
@ -0,0 +1,16 @@ |
||||
// Copyright (c) 2017 Uber Technologies, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package zipkin comprises Zipkin functionality for Zipkin compatibility.
|
||||
package zipkin |
@ -0,0 +1,121 @@ |
||||
// Copyright (c) 2017 Uber Technologies, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package zipkin |
||||
|
||||
import ( |
||||
"strconv" |
||||
"strings" |
||||
|
||||
opentracing "github.com/opentracing/opentracing-go" |
||||
|
||||
"github.com/uber/jaeger-client-go" |
||||
) |
||||
|
||||
// Option is a function that sets an option on Propagator
|
||||
type Option func(propagator *Propagator) |
||||
|
||||
// BaggagePrefix is a function that sets baggage prefix on Propagator
|
||||
func BaggagePrefix(prefix string) Option { |
||||
return func(propagator *Propagator) { |
||||
propagator.baggagePrefix = prefix |
||||
} |
||||
} |
||||
|
||||
// Propagator is an Injector and Extractor
|
||||
type Propagator struct { |
||||
baggagePrefix string |
||||
} |
||||
|
||||
// NewZipkinB3HTTPHeaderPropagator creates a Propagator for extracting and injecting
|
||||
// Zipkin HTTP B3 headers into SpanContexts. Baggage is by default enabled and uses prefix
|
||||
// 'baggage-'.
|
||||
func NewZipkinB3HTTPHeaderPropagator(opts ...Option) Propagator { |
||||
p := Propagator{baggagePrefix: "baggage-"} |
||||
for _, opt := range opts { |
||||
opt(&p) |
||||
} |
||||
return p |
||||
} |
||||
|
||||
// Inject conforms to the Injector interface for decoding Zipkin HTTP B3 headers
|
||||
func (p Propagator) Inject( |
||||
sc jaeger.SpanContext, |
||||
abstractCarrier interface{}, |
||||
) error { |
||||
textMapWriter, ok := abstractCarrier.(opentracing.TextMapWriter) |
||||
if !ok { |
||||
return opentracing.ErrInvalidCarrier |
||||
} |
||||
|
||||
textMapWriter.Set("x-b3-traceid", sc.TraceID().String()) |
||||
if sc.ParentID() != 0 { |
||||
textMapWriter.Set("x-b3-parentspanid", strconv.FormatUint(uint64(sc.ParentID()), 16)) |
||||
} |
||||
textMapWriter.Set("x-b3-spanid", strconv.FormatUint(uint64(sc.SpanID()), 16)) |
||||
if sc.IsSampled() { |
||||
textMapWriter.Set("x-b3-sampled", "1") |
||||
} else { |
||||
textMapWriter.Set("x-b3-sampled", "0") |
||||
} |
||||
sc.ForeachBaggageItem(func(k, v string) bool { |
||||
textMapWriter.Set(p.baggagePrefix+k, v) |
||||
return true |
||||
}) |
||||
return nil |
||||
} |
||||
|
||||
// Extract conforms to the Extractor interface for encoding Zipkin HTTP B3 headers
|
||||
func (p Propagator) Extract(abstractCarrier interface{}) (jaeger.SpanContext, error) { |
||||
textMapReader, ok := abstractCarrier.(opentracing.TextMapReader) |
||||
if !ok { |
||||
return jaeger.SpanContext{}, opentracing.ErrInvalidCarrier |
||||
} |
||||
var traceID jaeger.TraceID |
||||
var spanID uint64 |
||||
var parentID uint64 |
||||
sampled := false |
||||
var baggage map[string]string |
||||
err := textMapReader.ForeachKey(func(rawKey, value string) error { |
||||
key := strings.ToLower(rawKey) // TODO not necessary for plain TextMap
|
||||
var err error |
||||
if key == "x-b3-traceid" { |
||||
traceID, err = jaeger.TraceIDFromString(value) |
||||
} else if key == "x-b3-parentspanid" { |
||||
parentID, err = strconv.ParseUint(value, 16, 64) |
||||
} else if key == "x-b3-spanid" { |
||||
spanID, err = strconv.ParseUint(value, 16, 64) |
||||
} else if key == "x-b3-sampled" && (value == "1" || value == "true") { |
||||
sampled = true |
||||
} else if strings.HasPrefix(key, p.baggagePrefix) { |
||||
if baggage == nil { |
||||
baggage = make(map[string]string) |
||||
} |
||||
baggage[key[len(p.baggagePrefix):]] = value |
||||
} |
||||
return err |
||||
}) |
||||
|
||||
if err != nil { |
||||
return jaeger.SpanContext{}, err |
||||
} |
||||
if !traceID.IsValid() { |
||||
return jaeger.SpanContext{}, opentracing.ErrSpanContextNotFound |
||||
} |
||||
return jaeger.NewSpanContext( |
||||
traceID, |
||||
jaeger.SpanID(spanID), |
||||
jaeger.SpanID(parentID), |
||||
sampled, baggage), nil |
||||
} |
Loading…
Reference in new issue