Skip to content

Commit

Permalink
[propagator] Add Jaeger propagator (#375)
Browse files Browse the repository at this point in the history
* [propagator] Initial commit of jaeger propagator.

* [propagator] Add more test & copyright header.

* [propagator] Add injection integration test.

* [propagator] Address comments.

* [propagator] Address the comment.
Change traceID so that we can verify the propagator will not just take the  low 64 bits.

* [propagator] Add necessary doc for functions and types

Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>
  • Loading branch information
TommyCpp and MrAlias authored Oct 9, 2020
1 parent 082e67f commit bbc03fa
Show file tree
Hide file tree
Showing 6 changed files with 759 additions and 0 deletions.
17 changes: 17 additions & 0 deletions propagators/jaeger/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright The OpenTelemetry Authors
//
// 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.

// This package implements the Jaeger propagator specification as defined
// at https://www.jaegertracing.io/docs/1.18/client-libraries/#propagation-format
package jaeger // import "go.opentelemetry.io/contrib/propagators/jaeger"
270 changes: 270 additions & 0 deletions propagators/jaeger/jaeger_data_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
// Copyright The OpenTelemetry Authors
//
// 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 jaeger_test

import (
"fmt"

"go.opentelemetry.io/otel/api/trace"
)

const (
traceID16Str = "a3ce929d0e0e4736"
traceID32Str = "a1ce929d0e0e4736a3ce929d0e0e4736"
spanIDStr = "00f067aa0ba902b7"
jaegerHeader = "uber-trace-id"
)

var (
traceID16 = trace.ID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa3, 0xce, 0x92, 0x9d, 0x0e, 0x0e, 0x47, 0x36}
traceID32 = trace.ID{0xa1, 0xce, 0x92, 0x9d, 0x0e, 0x0e, 0x47, 0x36, 0xa3, 0xce, 0x92, 0x9d, 0x0e, 0x0e, 0x47, 0x36}
spanID = trace.SpanID{0x00, 0xf0, 0x67, 0xaa, 0x0b, 0xa9, 0x02, 0xb7}
)

type extractTest struct {
name string
headers map[string]string
expected trace.SpanContext
}

var extractHeaders = []extractTest{
{
"empty",
map[string]string{},
trace.SpanContext{},
},
{
"sampling state not sample",
map[string]string{
jaegerHeader: fmt.Sprintf("%s:%s:0:0", traceID32Str, spanIDStr),
},
trace.SpanContext{
TraceID: traceID32,
SpanID: spanID,
},
},
{
"sampling state sampled",
map[string]string{
jaegerHeader: fmt.Sprintf("%s:%s:0:1", traceID32Str, spanIDStr),
},
trace.SpanContext{
TraceID: traceID32,
SpanID: spanID,
TraceFlags: trace.FlagsSampled,
},
},
{
"sampling state debug",
map[string]string{
jaegerHeader: fmt.Sprintf("%s:%s:0:3", traceID32Str, spanIDStr),
},
trace.SpanContext{
TraceID: traceID32,
SpanID: spanID,
TraceFlags: trace.FlagsSampled | trace.FlagsDebug,
},
},
{
"sampling state debug but sampled bit didn't set, result in not sampled decision",
map[string]string{
jaegerHeader: fmt.Sprintf("%s:%s:0:2", traceID32Str, spanIDStr),
},
trace.SpanContext{
TraceID: traceID32,
SpanID: spanID,
},
},
{
"flag can be various length",
map[string]string{
jaegerHeader: fmt.Sprintf("%s:%s:0:00001", traceID32Str, spanIDStr),
},
trace.SpanContext{
TraceID: traceID32,
SpanID: spanID,
TraceFlags: trace.FlagsSampled,
},
},
{
"flag can be hex numbers",
map[string]string{
jaegerHeader: fmt.Sprintf("%s:%s:0:ff", traceID32Str, spanIDStr),
},
trace.SpanContext{
TraceID: traceID32,
SpanID: spanID,
TraceFlags: trace.FlagsDebug | trace.FlagsSampled,
},
},
{
"left padding 64 bit trace ID",
map[string]string{
jaegerHeader: fmt.Sprintf("%s:%s:0:1", traceID16Str, spanIDStr),
},
trace.SpanContext{
TraceID: traceID16,
SpanID: spanID,
TraceFlags: trace.FlagsSampled,
},
},
{
"128 bit trace ID",
map[string]string{
jaegerHeader: fmt.Sprintf("%s:%s:0:1", traceID32Str, spanIDStr),
},
trace.SpanContext{
TraceID: traceID32,
SpanID: spanID,
TraceFlags: trace.FlagsSampled,
},
},
{
"ignore parent span id",
map[string]string{
jaegerHeader: fmt.Sprintf("%s:%s:whatever:1", traceID32Str, spanIDStr),
},
trace.SpanContext{
TraceID: traceID32,
SpanID: spanID,
TraceFlags: trace.FlagsSampled,
},
},
}

var invalidExtractHeaders = []extractTest{
{
name: "trace ID length > 32",
headers: map[string]string{
jaegerHeader: fmt.Sprintf("%s:%s:0:1", traceID32Str+"0000", spanIDStr),
},
},
{
name: "trace ID length is not 32 or 16",
headers: map[string]string{
jaegerHeader: fmt.Sprintf("%s:%s:0:1", "1234567890abcd01234", spanIDStr),
},
},
{
name: "span ID length is not 16 or 32",
headers: map[string]string{
jaegerHeader: fmt.Sprintf("%s:%s:0:1", traceID32Str, spanIDStr+"0000"),
},
},
{
name: "invalid trace ID",
headers: map[string]string{
jaegerHeader: fmt.Sprintf("%s:%s:0:1", "zcd00v0000000000a3ce929d0e0e4736", spanIDStr),
},
},
{
name: "invalid span ID",
headers: map[string]string{
jaegerHeader: fmt.Sprintf("%s:%s:0:1", traceID32Str, "00f0wiredba902b7"),
},
},
{
name: "invalid flags",
headers: map[string]string{
jaegerHeader: fmt.Sprintf("%s:%s:0:wired", traceID32Str, spanIDStr),
},
},
{
name: "invalid separator",
headers: map[string]string{
jaegerHeader: fmt.Sprintf("%s-%s-0-1", traceID32Str, spanIDStr),
},
},
{
name: "missing jaeger header",
headers: map[string]string{
jaegerHeader + "not": fmt.Sprintf("%s:%s:0:1", traceID32Str, spanIDStr),
},
},
{
name: "empty header value",
headers: map[string]string{
jaegerHeader: "",
},
},
}

type injectTest struct {
name string
sc trace.SpanContext
wantHeaders map[string]string
}

var injectHeaders = []injectTest{
{
name: "sampled",
sc: trace.SpanContext{
TraceID: traceID32,
SpanID: spanID,
TraceFlags: trace.FlagsSampled,
},
wantHeaders: map[string]string{
jaegerHeader: fmt.Sprintf("%s:%s:0:1", traceID32Str, spanIDStr),
},
},
{
name: "debug",
sc: trace.SpanContext{
TraceID: traceID32,
SpanID: spanID,
TraceFlags: trace.FlagsSampled | trace.FlagsDebug,
},
wantHeaders: map[string]string{
jaegerHeader: fmt.Sprintf("%s:%s:0:3", traceID32Str, spanIDStr),
},
},
{
name: "not sampled",
sc: trace.SpanContext{
TraceID: traceID32,
SpanID: spanID,
},
wantHeaders: map[string]string{
jaegerHeader: fmt.Sprintf("%s:%s:0:0", traceID32Str, spanIDStr),
},
},
}

var invalidInjectHeaders = []injectTest{
{
name: "empty",
sc: trace.SpanContext{},
},
{
name: "missing traceID",
sc: trace.SpanContext{
SpanID: spanID,
TraceFlags: trace.FlagsSampled,
},
},
{
name: "missing spanID",
sc: trace.SpanContext{
TraceID: traceID32,
TraceFlags: trace.FlagsSampled,
},
},
{
name: "missing both traceID and spanID",
sc: trace.SpanContext{
TraceFlags: trace.FlagsSampled,
},
},
}
30 changes: 30 additions & 0 deletions propagators/jaeger/jaeger_example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright The OpenTelemetry Authors
//
// 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 jaeger_test

import (
"go.opentelemetry.io/contrib/propagators/jaeger"
"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/api/propagation"
)

func ExampleJaeger() {
jaeger := jaeger.Jaeger{}
// register jaeger propagator
global.SetPropagators(propagation.New(
propagation.WithExtractors(jaeger),
propagation.WithInjectors(jaeger),
))
}
Loading

0 comments on commit bbc03fa

Please sign in to comment.