From 7e127f272a28a3ded0ca6912f4e2d2a85b41f41f Mon Sep 17 00:00:00 2001 From: David Ashpole Date: Tue, 24 Nov 2020 10:12:59 -0800 Subject: [PATCH] move opencensus binary propagation to contrib --- .github/dependabot.yml | 10 ++ propagators/opencensus/binary.go | 86 +++++++++++++++ propagators/opencensus/binary_test.go | 153 ++++++++++++++++++++++++++ propagators/opencensus/go.mod | 9 ++ propagators/opencensus/go.sum | 63 +++++++++++ 5 files changed, 321 insertions(+) create mode 100644 propagators/opencensus/binary.go create mode 100644 propagators/opencensus/binary_test.go create mode 100644 propagators/opencensus/go.mod create mode 100644 propagators/opencensus/go.sum diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 79bc51eb221..76aa11fb19b 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -397,6 +397,16 @@ updates: schedule: interval: "weekly" day: "sunday" + - + package-ecosystem: "gomod" + directory: "/propagators/opencensus" + labels: + - dependencies + - go + - "Skip Changelog" + schedule: + interval: "weekly" + day: "sunday" - package-ecosystem: "gomod" directory: "/tools" labels: diff --git a/propagators/opencensus/binary.go b/propagators/opencensus/binary.go new file mode 100644 index 00000000000..493ceeb0612 --- /dev/null +++ b/propagators/opencensus/binary.go @@ -0,0 +1,86 @@ +// 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 opencensus // import "go.opentelemetry.io/contrib/propagators/opencensus" + +import ( + "context" + + ocpropagation "go.opencensus.io/trace/propagation" + + "go.opentelemetry.io/otel/bridge/opencensus/utils" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/trace" +) + +type key uint + +const binaryKey key = 0 + +// binaryHeader is the same as traceContextKey is in opencensus: +// https://github.com/census-instrumentation/opencensus-go/blob/3fb168f674736c026e623310bfccb0691e6dec8a/plugin/ocgrpc/trace_common.go#L30 +const binaryHeader = "grpc-trace-bin" + +// Binary is an OpenTelemetry implementation of the OpenCensus grpc binary format. +// Binary propagation was temporarily removed from opentelemetry. See +// https://github.com/open-telemetry/opentelemetry-specification/issues/437 +type Binary struct{} + +var _ propagation.TextMapPropagator = Binary{} + +// Inject injects context into the TextMapCarrier +func (b Binary) Inject(ctx context.Context, carrier propagation.TextMapCarrier) { + binaryContext := ctx.Value(binaryKey) + if state, ok := binaryContext.(string); binaryContext != nil && ok { + carrier.Set(binaryHeader, state) + } + + sc := trace.SpanContextFromContext(ctx) + if !sc.IsValid() { + return + } + h := ocpropagation.Binary(utils.OTelSpanContextToOC(sc)) + carrier.Set(binaryHeader, string(h)) +} + +// Extract extracts the SpanContext from the TextMapCarrier +func (b Binary) Extract(ctx context.Context, carrier propagation.TextMapCarrier) context.Context { + state := carrier.Get(binaryHeader) + if state != "" { + ctx = context.WithValue(ctx, binaryKey, state) + } + + sc := b.extract(carrier) + if !sc.IsValid() { + return ctx + } + return trace.ContextWithRemoteSpanContext(ctx, sc) +} + +func (b Binary) extract(carrier propagation.TextMapCarrier) trace.SpanContext { + h := carrier.Get(binaryHeader) + if h == "" { + return trace.SpanContext{} + } + ocContext, ok := ocpropagation.FromBinary([]byte(h)) + if !ok { + return trace.SpanContext{} + } + return utils.OCSpanContextToOTel(ocContext) +} + +// Fields returns the fields that this propagator modifies. +func (b Binary) Fields() []string { + return []string{binaryHeader} +} diff --git a/propagators/opencensus/binary_test.go b/propagators/opencensus/binary_test.go new file mode 100644 index 00000000000..7edf5b084bb --- /dev/null +++ b/propagators/opencensus/binary_test.go @@ -0,0 +1,153 @@ +// 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 opencensus + +import ( + "context" + "fmt" + "net/http" + "testing" + + "go.opentelemetry.io/otel/oteltest" + "go.opentelemetry.io/otel/trace" +) + +var ( + traceID = trace.TraceID([16]byte{14, 54, 12}) + spanID = trace.SpanID([8]byte{2, 8, 14, 20}) + childSpanID = trace.SpanID([8]byte{0, 0, 0, 0, 0, 0, 0, 2}) + headerFmt = "\x00\x00\x0e6\f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00%s\x02%s" +) + +func TestFields(t *testing.T) { + b := Binary{} + fields := b.Fields() + if len(fields) != 1 { + t.Fatalf("Got %d fields, expected 1", len(fields)) + } + if fields[0] != "grpc-trace-bin" { + t.Errorf("Got fields[0] == %s, expected grpc-trace-bin", fields[0]) + } +} + +func TestInject(t *testing.T) { + mockTracer := oteltest.DefaultTracer() + prop := Binary{} + for _, tt := range []struct { + desc string + sc trace.SpanContext + wantHeader string + }{ + { + desc: "empty", + sc: trace.SpanContext{}, + wantHeader: "", + }, + { + desc: "valid spancontext, sampled", + sc: trace.SpanContext{ + TraceID: traceID, + SpanID: spanID, + TraceFlags: trace.FlagsSampled, + }, + wantHeader: fmt.Sprintf(headerFmt, "\x02", "\x01"), + }, + { + desc: "valid spancontext, not sampled", + sc: trace.SpanContext{ + TraceID: traceID, + SpanID: spanID, + }, + wantHeader: fmt.Sprintf(headerFmt, "\x03", "\x00"), + }, + { + desc: "valid spancontext, with unsupported bit set in traceflags", + sc: trace.SpanContext{ + TraceID: traceID, + SpanID: spanID, + TraceFlags: 0xff, + }, + wantHeader: fmt.Sprintf(headerFmt, "\x04", "\x01"), + }, + { + desc: "invalid spancontext", + sc: trace.SpanContext{}, + wantHeader: "", + }, + } { + t.Run(tt.desc, func(t *testing.T) { + req, _ := http.NewRequest("GET", "http://example.com", nil) + ctx := context.Background() + if tt.sc.IsValid() { + ctx = trace.ContextWithRemoteSpanContext(ctx, tt.sc) + ctx, _ = mockTracer.Start(ctx, "inject") + } + prop.Inject(ctx, req.Header) + + gotHeader := req.Header.Get("grpc-trace-bin") + if gotHeader != tt.wantHeader { + t.Errorf("Got header = %q, want %q", gotHeader, tt.wantHeader) + } + }) + } +} +func TestExtract(t *testing.T) { + prop := Binary{} + for _, tt := range []struct { + desc string + header string + wantSc trace.SpanContext + }{ + { + desc: "empty", + header: "", + wantSc: trace.SpanContext{}, + }, + { + desc: "header not binary", + header: "5435j345io34t5904w3jt894j3t854w89tp95jgt9", + wantSc: trace.SpanContext{}, + }, + { + desc: "valid binary header", + header: fmt.Sprintf(headerFmt, "\x02", "\x00"), + wantSc: trace.SpanContext{ + TraceID: traceID, + SpanID: childSpanID, + }, + }, + { + desc: "valid binary and sampled", + header: fmt.Sprintf(headerFmt, "\x02", "\x01"), + wantSc: trace.SpanContext{ + TraceID: traceID, + SpanID: childSpanID, + TraceFlags: trace.FlagsSampled, + }, + }, + } { + t.Run(tt.desc, func(t *testing.T) { + req, _ := http.NewRequest("GET", "http://example.com", nil) + req.Header.Set("grpc-trace-bin", tt.header) + + ctx := context.Background() + ctx = prop.Extract(ctx, req.Header) + gotSc := trace.RemoteSpanContextFromContext(ctx) + if gotSc != tt.wantSc { + t.Errorf("Got SpanContext: %+v, wanted %+v", gotSc, tt.wantSc) + } + }) + } +} diff --git a/propagators/opencensus/go.mod b/propagators/opencensus/go.mod new file mode 100644 index 00000000000..b5f47e3ec41 --- /dev/null +++ b/propagators/opencensus/go.mod @@ -0,0 +1,9 @@ +module go.opentelemetry.io/contrib/propagators/opencensus + +go 1.14 + +require ( + go.opencensus.io v0.22.6-0.20201102222123-380f4078db9f + go.opentelemetry.io/otel v0.14.0 + go.opentelemetry.io/otel/bridge/opencensus v0.14.0 +) diff --git a/propagators/opencensus/go.sum b/propagators/opencensus/go.sum new file mode 100644 index 00000000000..fdd1ce26633 --- /dev/null +++ b/propagators/opencensus/go.sum @@ -0,0 +1,63 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +go.opencensus.io v0.22.6-0.20201102222123-380f4078db9f h1:IUmbcoP9XyEXW+R9AbrZgDvaYVfTbISN92Y5RIV+Mx4= +go.opencensus.io v0.22.6-0.20201102222123-380f4078db9f/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opentelemetry.io/otel v0.14.0 h1:YFBEfjCk9MTjaytCNSUkp9Q8lF7QJezA06T71FbQxLQ= +go.opentelemetry.io/otel v0.14.0/go.mod h1:vH5xEuwy7Rts0GNtsCW3HYQoZDY+OmBJ6t1bFGGlxgw= +go.opentelemetry.io/otel/bridge/opencensus v0.14.0 h1:DbjcxWx77qllXXs2J3hOVU+wmhLLxm4KpUDHF8xyc+I= +go.opentelemetry.io/otel/bridge/opencensus v0.14.0/go.mod h1:5/mlsJabUEVEhdCcfEsBQtR9kvQ9ItyftweEb20EE94= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=