1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-02-05 13:15:41 +02:00

Decouple instrumentation from SDK (#983)

* Remove otel/sdk dependency from grpctrace

Use otel/trace/testtrace instead and cleanup testing code.

* Update httptrace to not depend on the SDK

Update testing to use api/trace/testtrace instead.

* Add changes to Changelog

* Restore check for `http.local` attr on `http.getconn`
This commit is contained in:
Tyler Yahn 2020-07-28 19:59:04 -07:00 committed by GitHub
parent 42c2a86ea4
commit d6bf2fbfc3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 142 additions and 306 deletions

View File

@ -45,6 +45,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Use `global.Handle` for span export errors in the OTLP exporter. (#946)
- Correct Go language formatting in the README documentation. (#961)
- Remove default SDK dependencies from the `go.opentelemetry.io/otel/api` package. (#977)
- Remove default SDK dependencies from the `go.opentelemetry.io/otel/instrumentation` package. (#983)
- Move documented examples for `go.opentelemetry.io/otel/instrumentation/grpctrace` interceptors into Go example tests. (#984)
## [0.9.0] - 2020-07-20

View File

@ -20,6 +20,7 @@ import (
"time"
"go.opentelemetry.io/otel/api/standard"
"go.opentelemetry.io/otel/api/trace/testtrace"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -32,19 +33,30 @@ import (
"google.golang.org/grpc/status"
"go.opentelemetry.io/otel/api/kv"
export "go.opentelemetry.io/otel/sdk/export/trace"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)
type testExporter struct {
mu sync.Mutex
spanMap map[string]*export.SpanData
type SpanRecorder struct {
mu sync.RWMutex
spans map[string]*testtrace.Span
}
func (t *testExporter) ExportSpan(ctx context.Context, s *export.SpanData) {
t.mu.Lock()
defer t.mu.Unlock()
t.spanMap[s.Name] = s
func NewSpanRecorder() *SpanRecorder {
return &SpanRecorder{spans: make(map[string]*testtrace.Span)}
}
func (sr *SpanRecorder) OnStart(span *testtrace.Span) {}
func (sr *SpanRecorder) OnEnd(span *testtrace.Span) {
sr.mu.Lock()
defer sr.mu.Unlock()
sr.spans[span.Name()] = span
}
func (sr *SpanRecorder) Get(name string) (*testtrace.Span, bool) {
sr.mu.RLock()
defer sr.mu.RUnlock()
s, ok := sr.spans[name]
return s, ok
}
type mockUICInvoker struct {
@ -69,18 +81,13 @@ func (mm *mockProtoMessage) ProtoMessage() {
}
func TestUnaryClientInterceptor(t *testing.T) {
exp := &testExporter{spanMap: make(map[string]*export.SpanData)}
tp, _ := sdktrace.NewProvider(sdktrace.WithSyncer(exp),
sdktrace.WithConfig(sdktrace.Config{
DefaultSampler: sdktrace.AlwaysSample(),
},
))
clientConn, err := grpc.Dial("fake:connection", grpc.WithInsecure())
if err != nil {
t.Fatalf("failed to create client connection: %v", err)
}
sr := NewSpanRecorder()
tp := testtrace.NewProvider(testtrace.WithSpanRecorder(sr))
tracer := tp.Tracer("grpctrace/client")
unaryInterceptor := UnaryClientInterceptor(tracer)
@ -210,70 +217,26 @@ func TestUnaryClientInterceptor(t *testing.T) {
}
for _, check := range checks {
err = unaryInterceptor(context.Background(), check.method, req, reply, clientConn, uniInterceptorInvoker.invoker)
if err != nil {
t.Errorf("failed to run unary interceptor: %v", err)
if !assert.NoError(t, unaryInterceptor(context.Background(), check.method, req, reply, clientConn, uniInterceptorInvoker.invoker)) {
continue
}
spanData, ok := exp.spanMap[check.name]
if !ok {
t.Errorf("no span data found for name < %s >", check.name)
span, ok := sr.Get(check.name)
if !assert.True(t, ok, "missing span %q", check.name) {
continue
}
attrs := spanData.Attributes
if len(check.expectedAttr) > len(attrs) {
t.Errorf("attributes received are less than expected attributes, received %d, expected %d",
len(attrs), len(check.expectedAttr))
}
for _, attr := range attrs {
expectedAttr, ok := check.expectedAttr[attr.Key]
if ok {
if expectedAttr != attr.Value {
t.Errorf("name: %s invalid %s found. expected %s, actual %s", check.name, string(attr.Key),
expectedAttr.AsString(), attr.Value.AsString())
}
delete(check.expectedAttr, attr.Key)
} else {
t.Errorf("attribute %s not found in expected attributes map", string(attr.Key))
}
}
// Check if any expected attr not seen
if len(check.expectedAttr) > 0 {
for attr := range check.expectedAttr {
t.Errorf("missing attribute %s in span", string(attr))
}
}
events := spanData.MessageEvents
if len(check.eventsAttr) > len(events) {
t.Errorf("events received are less than expected events, received %d, expected %d",
len(events), len(check.eventsAttr))
}
for event := 0; event < len(check.eventsAttr); event++ {
for _, attr := range events[event].Attributes {
expectedAttr, ok := check.eventsAttr[event][attr.Key]
if ok {
if attr.Value != expectedAttr {
t.Errorf("invalid value for attribute %s in events, expected %s actual %s",
string(attr.Key), attr.Value.AsString(), expectedAttr.AsString())
}
delete(check.eventsAttr[event], attr.Key)
} else {
t.Errorf("attribute in event %s not found in expected attributes map", string(attr.Key))
}
}
if len(check.eventsAttr[event]) > 0 {
for attr := range check.eventsAttr[event] {
t.Errorf("missing attribute %s in span event", string(attr))
}
}
}
assert.Equal(t, check.expectedAttr, span.Attributes())
assert.Equal(t, check.eventsAttr, eventAttrMap(span.Events()))
}
}
func eventAttrMap(events []testtrace.Event) []map[kv.Key]kv.Value {
maps := make([]map[kv.Key]kv.Value, len(events))
for i, event := range events {
maps[i] = event.Attributes
}
return maps
}
type mockClientStream struct {
Desc *grpc.StreamDesc
Ctx context.Context
@ -287,18 +250,14 @@ func (mockClientStream) Header() (metadata.MD, error) { return nil, nil }
func (mockClientStream) Trailer() metadata.MD { return nil }
func TestStreamClientInterceptor(t *testing.T) {
exp := &testExporter{spanMap: make(map[string]*export.SpanData)}
tp, _ := sdktrace.NewProvider(sdktrace.WithSyncer(exp),
sdktrace.WithConfig(sdktrace.Config{
DefaultSampler: sdktrace.AlwaysSample(),
},
))
clientConn, err := grpc.Dial("fake:connection", grpc.WithInsecure())
if err != nil {
t.Fatalf("failed to create client connection: %v", err)
}
// tracer
sr := NewSpanRecorder()
tp := testtrace.NewProvider(testtrace.WithSpanRecorder(sr))
tracer := tp.Tracer("grpctrace/Server")
streamCI := StreamClientInterceptor(tracer)
@ -306,7 +265,8 @@ func TestStreamClientInterceptor(t *testing.T) {
method := "/github.com.serviceName/bar"
name := "github.com.serviceName/bar"
streamClient, err := streamCI(context.Background(),
streamClient, err := streamCI(
context.Background(),
&grpc.StreamDesc{ServerStreams: true},
clientConn,
method,
@ -317,16 +277,11 @@ func TestStreamClientInterceptor(t *testing.T) {
opts ...grpc.CallOption) (grpc.ClientStream, error) {
mockClStr = mockClientStream{Desc: desc, Ctx: ctx}
return mockClStr, nil
})
if err != nil {
t.Fatalf("failed to initialize grpc stream client: %v", err)
}
// no span exported while stream is open
if _, ok := exp.spanMap[name]; ok {
t.Fatalf("span shouldn't end while stream is open")
}
},
)
require.NoError(t, err, "initialize grpc stream client")
_, ok := sr.Get(name)
require.False(t, ok, "span should ended while stream is open")
req := &mockProtoMessage{}
reply := &mockProtoMessage{}
@ -343,53 +298,36 @@ func TestStreamClientInterceptor(t *testing.T) {
_ = streamClient.RecvMsg(reply)
// added retry because span end is called in separate go routine
var spanData *export.SpanData
var span *testtrace.Span
for retry := 0; retry < 5; retry++ {
ok := false
exp.mu.Lock()
spanData, ok = exp.spanMap[name]
exp.mu.Unlock()
span, ok = sr.Get(name)
if ok {
break
}
time.Sleep(time.Second * 1)
}
if spanData == nil {
t.Fatalf("no span data found for name < %s >", name)
}
require.True(t, ok, "missing span %s", name)
attrs := spanData.Attributes
expectedAttr := map[kv.Key]string{
standard.RPCSystemKey: "grpc",
standard.RPCServiceKey: "github.com.serviceName",
standard.RPCMethodKey: "bar",
standard.NetPeerIPKey: "fake",
standard.NetPeerPortKey: "connection",
expectedAttr := map[kv.Key]kv.Value{
standard.RPCSystemKey: kv.StringValue("grpc"),
standard.RPCServiceKey: kv.StringValue("github.com.serviceName"),
standard.RPCMethodKey: kv.StringValue("bar"),
standard.NetPeerIPKey: kv.StringValue("fake"),
standard.NetPeerPortKey: kv.StringValue("connection"),
}
assert.Equal(t, expectedAttr, span.Attributes())
for _, attr := range attrs {
expected, ok := expectedAttr[attr.Key]
if ok {
if expected != attr.Value.AsString() {
t.Errorf("name: %s invalid %s found. expected %s, actual %s", name, string(attr.Key),
expected, attr.Value.AsString())
}
}
}
events := spanData.MessageEvents
if len(events) != 20 {
t.Fatalf("incorrect number of events expected 20 got %d", len(events))
}
events := span.Events()
require.Len(t, events, 20)
for i := 0; i < 20; i += 2 {
msgID := i/2 + 1
validate := func(eventName string, attrs []kv.KeyValue) {
for _, attr := range attrs {
if attr.Key == standard.RPCMessageTypeKey && attr.Value.AsString() != eventName {
t.Errorf("invalid event on index: %d expecting %s event, receive %s event", i, eventName, attr.Value.AsString())
validate := func(eventName string, attrs map[kv.Key]kv.Value) {
for k, v := range attrs {
if k == standard.RPCMessageTypeKey && v.AsString() != eventName {
t.Errorf("invalid event on index: %d expecting %s event, receive %s event", i, eventName, v.AsString())
}
if attr.Key == standard.RPCMessageIDKey && attr.Value != kv.IntValue(msgID) {
t.Errorf("invalid id for message event expected %d received %d", msgID, attr.Value.AsInt32())
if k == standard.RPCMessageIDKey && v != kv.IntValue(msgID) {
t.Errorf("invalid id for message event expected %d received %d", msgID, v.AsInt32())
}
}
}
@ -402,37 +340,30 @@ func TestStreamClientInterceptor(t *testing.T) {
}
func TestServerInterceptorError(t *testing.T) {
exp := &testExporter{spanMap: make(map[string]*export.SpanData)}
tp, err := sdktrace.NewProvider(
sdktrace.WithSyncer(exp),
sdktrace.WithConfig(sdktrace.Config{
DefaultSampler: sdktrace.AlwaysSample(),
}),
)
require.NoError(t, err)
sr := NewSpanRecorder()
tp := testtrace.NewProvider(testtrace.WithSpanRecorder(sr))
tracer := tp.Tracer("grpctrace/Server")
usi := UnaryServerInterceptor(tracer)
deniedErr := status.Error(codes.PermissionDenied, "PERMISSION_DENIED_TEXT")
handler := func(_ context.Context, _ interface{}) (interface{}, error) {
return nil, deniedErr
}
_, err = usi(context.Background(), &mockProtoMessage{}, &grpc.UnaryServerInfo{}, handler)
_, err := usi(context.Background(), &mockProtoMessage{}, &grpc.UnaryServerInfo{}, handler)
require.Error(t, err)
assert.Equal(t, err, deniedErr)
span, ok := exp.spanMap[""]
span, ok := sr.Get("")
if !ok {
t.Fatalf("failed to export error span")
}
assert.Equal(t, span.StatusCode, codes.PermissionDenied)
assert.Contains(t, deniedErr.Error(), span.StatusMessage)
assert.Len(t, span.MessageEvents, 2)
assert.Equal(t, []kv.KeyValue{
kv.String("message.type", "SENT"),
kv.Int("message.id", 1),
kv.Int("message.uncompressed_size", 26),
}, span.MessageEvents[1].Attributes)
assert.Equal(t, span.StatusCode(), codes.PermissionDenied)
assert.Contains(t, deniedErr.Error(), span.StatusMessage())
assert.Len(t, span.Events(), 2)
assert.Equal(t, map[kv.Key]kv.Value{
kv.Key("message.type"): kv.StringValue("SENT"),
kv.Key("message.id"): kv.IntValue(1),
kv.Key("message.uncompressed_size"): kv.IntValue(26),
}, span.Events()[1].Attributes)
}
func TestParseFullMethod(t *testing.T) {

View File

@ -18,46 +18,26 @@ import (
"net/http"
"net/http/httptest"
nhtrace "net/http/httptrace"
"sync"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/trace/testtrace"
"go.opentelemetry.io/otel/instrumentation/httptrace"
export "go.opentelemetry.io/otel/sdk/export/trace"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)
type testExporter struct {
mu sync.Mutex
spanMap map[string][]*export.SpanData
}
type SpanRecorder map[string]*testtrace.Span
func (t *testExporter) ExportSpan(ctx context.Context, s *export.SpanData) {
t.mu.Lock()
defer t.mu.Unlock()
var spans []*export.SpanData
var ok bool
if spans, ok = t.spanMap[s.Name]; !ok {
spans = []*export.SpanData{}
t.spanMap[s.Name] = spans
}
spans = append(spans, s)
t.spanMap[s.Name] = spans
}
var _ export.SpanSyncer = (*testExporter)(nil)
func (sr *SpanRecorder) OnStart(span *testtrace.Span) {}
func (sr *SpanRecorder) OnEnd(span *testtrace.Span) { (*sr)[span.Name()] = span }
func TestHTTPRequestWithClientTrace(t *testing.T) {
exp := &testExporter{
spanMap: make(map[string][]*export.SpanData),
}
tp, _ := sdktrace.NewProvider(sdktrace.WithSyncer(exp), sdktrace.WithConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()}))
sr := SpanRecorder{}
tp := testtrace.NewProvider(testtrace.WithSpanRecorder(&sr))
global.SetTraceProvider(tp)
tr := tp.Tracer("httptrace/client")
// Mock http server
@ -86,34 +66,23 @@ func TestHTTPRequestWithClientTrace(t *testing.T) {
panic("unexpected error in http request: " + err.Error())
}
getSpan := func(name string) *export.SpanData {
spans, ok := exp.spanMap[name]
if !ok {
t.Fatalf("no spans found with the name %s, %v", name, exp.spanMap)
}
if len(spans) != 1 {
t.Fatalf("Expected exactly one span for %s but found %d", name, len(spans))
}
return spans[0]
}
testLen := []struct {
name string
attributes []kv.KeyValue
attributes map[kv.Key]kv.Value
parent string
}{
{
name: "http.connect",
attributes: []kv.KeyValue{kv.String("http.remote", address.String())},
parent: "http.getconn",
name: "http.connect",
attributes: map[kv.Key]kv.Value{
kv.Key("http.remote"): kv.StringValue(address.String()),
},
parent: "http.getconn",
},
{
name: "http.getconn",
attributes: []kv.KeyValue{
kv.String("http.remote", address.String()),
kv.String("http.host", address.String()),
attributes: map[kv.Key]kv.Value{
kv.Key("http.remote"): kv.StringValue(address.String()),
kv.Key("http.host"): kv.StringValue(address.String()),
},
parent: "test",
},
@ -134,51 +103,42 @@ func TestHTTPRequestWithClientTrace(t *testing.T) {
},
}
for _, tl := range testLen {
span := getSpan(tl.name)
if !assert.Contains(t, sr, tl.name) {
continue
}
span := sr[tl.name]
if tl.parent != "" {
parentSpan := getSpan(tl.parent)
if span.ParentSpanID != parentSpan.SpanContext.SpanID {
t.Fatalf("[span %s] does not have expected parent span %s", tl.name, tl.parent)
if assert.Contains(t, sr, tl.parent) {
assert.Equal(t, span.ParentSpanID(), sr[tl.parent].SpanContext().SpanID)
}
}
actualAttrs := make(map[kv.Key]string)
for _, attr := range span.Attributes {
actualAttrs[attr.Key] = attr.Value.Emit()
}
expectedAttrs := make(map[kv.Key]string)
for _, attr := range tl.attributes {
expectedAttrs[attr.Key] = attr.Value.Emit()
}
if tl.name == "http.getconn" {
local := kv.Key("http.local")
// http.local attribute is not deterministic, just make sure it exists for `getconn`.
if _, ok := actualAttrs[local]; ok {
delete(actualAttrs, local)
} else {
t.Fatalf("[span %s] is missing attribute %v", tl.name, local)
if len(tl.attributes) > 0 {
attrs := span.Attributes()
if tl.name == "http.getconn" {
// http.local attribute uses a non-deterministic port.
local := kv.Key("http.local")
assert.Contains(t, attrs, local)
delete(attrs, local)
}
}
if diff := cmp.Diff(actualAttrs, expectedAttrs); diff != "" {
t.Fatalf("[span %s] Attributes are different: %v", tl.name, diff)
assert.Equal(t, tl.attributes, attrs)
}
}
}
type MultiSpanRecorder map[string][]*testtrace.Span
func (sr *MultiSpanRecorder) Reset() { (*sr) = MultiSpanRecorder{} }
func (sr *MultiSpanRecorder) OnStart(span *testtrace.Span) {}
func (sr *MultiSpanRecorder) OnEnd(span *testtrace.Span) {
(*sr)[span.Name()] = append((*sr)[span.Name()], span)
}
func TestConcurrentConnectionStart(t *testing.T) {
exp := &testExporter{
spanMap: make(map[string][]*export.SpanData),
}
tp, _ := sdktrace.NewProvider(sdktrace.WithSyncer(exp), sdktrace.WithConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()}))
global.SetTraceProvider(tp)
sr := MultiSpanRecorder{}
global.SetTraceProvider(
testtrace.NewProvider(testtrace.WithSpanRecorder(&sr)),
)
ct := httptrace.NewClientTrace(context.Background())
tts := []struct {
name string
run func()
@ -186,8 +146,6 @@ func TestConcurrentConnectionStart(t *testing.T) {
{
name: "Open1Close1Open2Close2",
run: func() {
exp.spanMap = make(map[string][]*export.SpanData)
ct.ConnectStart("tcp", "127.0.0.1:3000")
ct.ConnectDone("tcp", "127.0.0.1:3000", nil)
ct.ConnectStart("tcp", "[::1]:3000")
@ -197,8 +155,6 @@ func TestConcurrentConnectionStart(t *testing.T) {
{
name: "Open2Close2Open1Close1",
run: func() {
exp.spanMap = make(map[string][]*export.SpanData)
ct.ConnectStart("tcp", "[::1]:3000")
ct.ConnectDone("tcp", "[::1]:3000", nil)
ct.ConnectStart("tcp", "127.0.0.1:3000")
@ -208,8 +164,6 @@ func TestConcurrentConnectionStart(t *testing.T) {
{
name: "Open1Open2Close1Close2",
run: func() {
exp.spanMap = make(map[string][]*export.SpanData)
ct.ConnectStart("tcp", "127.0.0.1:3000")
ct.ConnectStart("tcp", "[::1]:3000")
ct.ConnectDone("tcp", "127.0.0.1:3000", nil)
@ -219,8 +173,6 @@ func TestConcurrentConnectionStart(t *testing.T) {
{
name: "Open1Open2Close2Close1",
run: func() {
exp.spanMap = make(map[string][]*export.SpanData)
ct.ConnectStart("tcp", "127.0.0.1:3000")
ct.ConnectStart("tcp", "[::1]:3000")
ct.ConnectDone("tcp", "[::1]:3000", nil)
@ -230,8 +182,6 @@ func TestConcurrentConnectionStart(t *testing.T) {
{
name: "Open2Open1Close1Close2",
run: func() {
exp.spanMap = make(map[string][]*export.SpanData)
ct.ConnectStart("tcp", "[::1]:3000")
ct.ConnectStart("tcp", "127.0.0.1:3000")
ct.ConnectDone("tcp", "127.0.0.1:3000", nil)
@ -241,8 +191,6 @@ func TestConcurrentConnectionStart(t *testing.T) {
{
name: "Open2Open1Close2Close1",
run: func() {
exp.spanMap = make(map[string][]*export.SpanData)
ct.ConnectStart("tcp", "[::1]:3000")
ct.ConnectStart("tcp", "127.0.0.1:3000")
ct.ConnectDone("tcp", "[::1]:3000", nil)
@ -251,70 +199,40 @@ func TestConcurrentConnectionStart(t *testing.T) {
},
}
expectedRemotes := []kv.KeyValue{
kv.String("http.remote", "127.0.0.1:3000"),
kv.String("http.remote", "[::1]:3000"),
}
for _, tt := range tts {
t.Run(tt.name, func(t *testing.T) {
sr.Reset()
tt.run()
spans := exp.spanMap["http.connect"]
spans := sr["http.connect"]
require.Len(t, spans, 2)
if l := len(spans); l != 2 {
t.Fatalf("Expected 2 'http.connect' traces but found %d", l)
}
remotes := make(map[string]struct{})
var gotRemotes []kv.KeyValue
for _, span := range spans {
if l := len(span.Attributes); l != 1 {
t.Fatalf("Expected 1 attribute on each span but found %d", l)
}
attr := span.Attributes[0]
if attr.Key != "http.remote" {
t.Fatalf("Expected attribute to be 'http.remote' but found %s", attr.Key)
}
remotes[attr.Value.Emit()] = struct{}{}
}
if l := len(remotes); l != 2 {
t.Fatalf("Expected 2 different 'http.remote' but found %d", l)
}
for _, remote := range []string{"127.0.0.1:3000", "[::1]:3000"} {
if _, ok := remotes[remote]; !ok {
t.Fatalf("Missing remote %s", remote)
for k, v := range span.Attributes() {
gotRemotes = append(gotRemotes, kv.Any(string(k), v.AsInterface()))
}
}
assert.ElementsMatch(t, expectedRemotes, gotRemotes)
})
}
}
func TestEndBeforeStartCreatesSpan(t *testing.T) {
exp := &testExporter{
spanMap: make(map[string][]*export.SpanData),
}
tp, _ := sdktrace.NewProvider(sdktrace.WithSyncer(exp), sdktrace.WithConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()}))
global.SetTraceProvider(tp)
tr := tp.Tracer("httptrace/client")
ctx, span := tr.Start(context.Background(), "test")
defer span.End()
ct := httptrace.NewClientTrace(ctx)
sr := MultiSpanRecorder{}
global.SetTraceProvider(
testtrace.NewProvider(testtrace.WithSpanRecorder(&sr)),
)
ct := httptrace.NewClientTrace(context.Background())
ct.DNSDone(nhtrace.DNSDoneInfo{})
ct.DNSStart(nhtrace.DNSStartInfo{Host: "example.com"})
getSpan := func(name string) *export.SpanData {
spans, ok := exp.spanMap[name]
if !ok {
t.Fatalf("no spans found with the name %s, %v", name, exp.spanMap)
}
if len(spans) != 1 {
t.Fatalf("Expected exactly one span for %s but found %d", name, len(spans))
}
return spans[0]
}
getSpan("http.dns")
name := "http.dns"
require.Contains(t, sr, name)
spans := sr[name]
require.Len(t, spans, 1)
}

View File

@ -24,23 +24,15 @@ import (
"github.com/google/go-cmp/cmp"
"go.opentelemetry.io/otel/api/correlation"
"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/propagation"
"go.opentelemetry.io/otel/api/standard"
"go.opentelemetry.io/otel/api/trace/testtrace"
"go.opentelemetry.io/otel/instrumentation/httptrace"
export "go.opentelemetry.io/otel/sdk/export/trace"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)
func TestRoundtrip(t *testing.T) {
exp := &testExporter{
spanMap: make(map[string][]*export.SpanData),
}
tp, _ := sdktrace.NewProvider(sdktrace.WithSyncer(exp), sdktrace.WithConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()}))
global.SetTraceProvider(tp)
tr := tp.Tracer("httptrace/client")
tr := testtrace.NewProvider().Tracer("httptrace/client")
var expectedAttrs map[kv.Key]string
expectedCorrs := map[kv.Key]string{kv.Key("foo"): "bar"}
@ -121,13 +113,7 @@ func TestRoundtrip(t *testing.T) {
}
func TestSpecifyPropagators(t *testing.T) {
exp := &testExporter{
spanMap: make(map[string][]*export.SpanData),
}
tp, _ := sdktrace.NewProvider(sdktrace.WithSyncer(exp), sdktrace.WithConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()}))
global.SetTraceProvider(tp)
tr := tp.Tracer("httptrace/client")
tr := testtrace.NewProvider().Tracer("httptrace/client")
expectedCorrs := map[kv.Key]string{kv.Key("foo"): "bar"}