You've already forked opentelemetry-go
mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2025-08-15 20:03:15 +02:00
Add OpenCensus bridge internal package (#2146)
* Add internal pkg to bridge/opencensus * Use the bridge/opencensus/internal pkg * Correct testing comments * Remove added unit tests
This commit is contained in:
@@ -15,15 +15,9 @@
|
|||||||
package opencensus
|
package opencensus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
octrace "go.opencensus.io/trace"
|
octrace "go.opencensus.io/trace"
|
||||||
|
|
||||||
"go.opentelemetry.io/otel"
|
"go.opentelemetry.io/otel/bridge/opencensus/internal"
|
||||||
"go.opentelemetry.io/otel/attribute"
|
|
||||||
"go.opentelemetry.io/otel/bridge/opencensus/utils"
|
|
||||||
"go.opentelemetry.io/otel/codes"
|
|
||||||
"go.opentelemetry.io/otel/trace"
|
"go.opentelemetry.io/otel/trace"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -31,160 +25,5 @@ import (
|
|||||||
// uses OpenTelemetry APIs. Using this implementation of Tracer "upgrades"
|
// uses OpenTelemetry APIs. Using this implementation of Tracer "upgrades"
|
||||||
// libraries that use OpenCensus to OpenTelemetry to facilitate a migration.
|
// libraries that use OpenCensus to OpenTelemetry to facilitate a migration.
|
||||||
func NewTracer(tracer trace.Tracer) octrace.Tracer {
|
func NewTracer(tracer trace.Tracer) octrace.Tracer {
|
||||||
return &otelTracer{tracer: tracer}
|
return internal.NewTracer(tracer)
|
||||||
}
|
|
||||||
|
|
||||||
type otelTracer struct {
|
|
||||||
tracer trace.Tracer
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ octrace.Tracer = (*otelTracer)(nil)
|
|
||||||
|
|
||||||
func (o *otelTracer) StartSpan(ctx context.Context, name string, s ...octrace.StartOption) (context.Context, *octrace.Span) {
|
|
||||||
ctx, sp := o.tracer.Start(ctx, name, convertStartOptions(s, name)...)
|
|
||||||
return ctx, octrace.NewSpan(&span{otSpan: sp})
|
|
||||||
}
|
|
||||||
|
|
||||||
func convertStartOptions(optFns []octrace.StartOption, name string) []trace.SpanStartOption {
|
|
||||||
var ocOpts octrace.StartOptions
|
|
||||||
for _, fn := range optFns {
|
|
||||||
fn(&ocOpts)
|
|
||||||
}
|
|
||||||
otOpts := []trace.SpanStartOption{}
|
|
||||||
switch ocOpts.SpanKind {
|
|
||||||
case octrace.SpanKindClient:
|
|
||||||
otOpts = append(otOpts, trace.WithSpanKind(trace.SpanKindClient))
|
|
||||||
case octrace.SpanKindServer:
|
|
||||||
otOpts = append(otOpts, trace.WithSpanKind(trace.SpanKindServer))
|
|
||||||
case octrace.SpanKindUnspecified:
|
|
||||||
otOpts = append(otOpts, trace.WithSpanKind(trace.SpanKindUnspecified))
|
|
||||||
}
|
|
||||||
|
|
||||||
if ocOpts.Sampler != nil {
|
|
||||||
otel.Handle(fmt.Errorf("ignoring custom sampler for span %q created by OpenCensus because OpenTelemetry does not support creating a span with a custom sampler", name))
|
|
||||||
}
|
|
||||||
return otOpts
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *otelTracer) StartSpanWithRemoteParent(ctx context.Context, name string, parent octrace.SpanContext, s ...octrace.StartOption) (context.Context, *octrace.Span) {
|
|
||||||
// make sure span context is zero'd out so we use the remote parent
|
|
||||||
ctx = trace.ContextWithSpan(ctx, nil)
|
|
||||||
ctx = trace.ContextWithRemoteSpanContext(ctx, utils.OCSpanContextToOTel(parent))
|
|
||||||
return o.StartSpan(ctx, name, s...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *otelTracer) FromContext(ctx context.Context) *octrace.Span {
|
|
||||||
otSpan := trace.SpanFromContext(ctx)
|
|
||||||
return octrace.NewSpan(&span{otSpan: otSpan})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *otelTracer) NewContext(parent context.Context, s *octrace.Span) context.Context {
|
|
||||||
if otSpan, ok := s.Internal().(*span); ok {
|
|
||||||
return trace.ContextWithSpan(parent, otSpan.otSpan)
|
|
||||||
}
|
|
||||||
otel.Handle(fmt.Errorf("unable to create context with span %q, since it was created using a different tracer", s.String()))
|
|
||||||
return parent
|
|
||||||
}
|
|
||||||
|
|
||||||
type span struct {
|
|
||||||
otSpan trace.Span
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *span) IsRecordingEvents() bool {
|
|
||||||
return s.otSpan.IsRecording()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *span) End() {
|
|
||||||
s.otSpan.End()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *span) SpanContext() octrace.SpanContext {
|
|
||||||
return utils.OTelSpanContextToOC(s.otSpan.SpanContext())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *span) SetName(name string) {
|
|
||||||
s.otSpan.SetName(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *span) SetStatus(status octrace.Status) {
|
|
||||||
s.otSpan.SetStatus(codes.Code(status.Code), status.Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *span) AddAttributes(attributes ...octrace.Attribute) {
|
|
||||||
s.otSpan.SetAttributes(convertAttributes(attributes)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func convertAttributes(attributes []octrace.Attribute) []attribute.KeyValue {
|
|
||||||
otAttributes := make([]attribute.KeyValue, len(attributes))
|
|
||||||
for i, a := range attributes {
|
|
||||||
otAttributes[i] = attribute.KeyValue{
|
|
||||||
Key: attribute.Key(a.Key()),
|
|
||||||
Value: convertValue(a.Value()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return otAttributes
|
|
||||||
}
|
|
||||||
|
|
||||||
func convertValue(ocval interface{}) attribute.Value {
|
|
||||||
switch v := ocval.(type) {
|
|
||||||
case bool:
|
|
||||||
return attribute.BoolValue(v)
|
|
||||||
case int64:
|
|
||||||
return attribute.Int64Value(v)
|
|
||||||
case float64:
|
|
||||||
return attribute.Float64Value(v)
|
|
||||||
case string:
|
|
||||||
return attribute.StringValue(v)
|
|
||||||
default:
|
|
||||||
return attribute.StringValue("unknown")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *span) Annotate(attributes []octrace.Attribute, str string) {
|
|
||||||
s.otSpan.AddEvent(str, trace.WithAttributes(convertAttributes(attributes)...))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *span) Annotatef(attributes []octrace.Attribute, format string, a ...interface{}) {
|
|
||||||
s.Annotate(attributes, fmt.Sprintf(format, a...))
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
uncompressedKey = attribute.Key("uncompressed byte size")
|
|
||||||
compressedKey = attribute.Key("compressed byte size")
|
|
||||||
)
|
|
||||||
|
|
||||||
func (s *span) AddMessageSendEvent(messageID, uncompressedByteSize, compressedByteSize int64) {
|
|
||||||
s.otSpan.AddEvent("message send",
|
|
||||||
trace.WithAttributes(
|
|
||||||
attribute.KeyValue{
|
|
||||||
Key: uncompressedKey,
|
|
||||||
Value: attribute.Int64Value(uncompressedByteSize),
|
|
||||||
},
|
|
||||||
attribute.KeyValue{
|
|
||||||
Key: compressedKey,
|
|
||||||
Value: attribute.Int64Value(compressedByteSize),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *span) AddMessageReceiveEvent(messageID, uncompressedByteSize, compressedByteSize int64) {
|
|
||||||
s.otSpan.AddEvent("message receive",
|
|
||||||
trace.WithAttributes(
|
|
||||||
attribute.KeyValue{
|
|
||||||
Key: uncompressedKey,
|
|
||||||
Value: attribute.Int64Value(uncompressedByteSize),
|
|
||||||
},
|
|
||||||
attribute.KeyValue{
|
|
||||||
Key: compressedKey,
|
|
||||||
Value: attribute.Int64Value(compressedByteSize),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *span) AddLink(l octrace.Link) {
|
|
||||||
otel.Handle(fmt.Errorf("ignoring OpenCensus link %+v for span %q because OpenTelemetry doesn't support setting links after creation", l, s.String()))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *span) String() string {
|
|
||||||
return fmt.Sprintf("span %s", s.otSpan.SpanContext().SpanID().String())
|
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,7 @@ import (
|
|||||||
octrace "go.opencensus.io/trace"
|
octrace "go.opencensus.io/trace"
|
||||||
|
|
||||||
"go.opentelemetry.io/otel/attribute"
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/bridge/opencensus/internal"
|
||||||
"go.opentelemetry.io/otel/bridge/opencensus/utils"
|
"go.opentelemetry.io/otel/bridge/opencensus/utils"
|
||||||
"go.opentelemetry.io/otel/codes"
|
"go.opentelemetry.io/otel/codes"
|
||||||
"go.opentelemetry.io/otel/oteltest"
|
"go.opentelemetry.io/otel/oteltest"
|
||||||
@@ -129,7 +130,7 @@ func TestToFromContext(t *testing.T) {
|
|||||||
defer otSpan1.End()
|
defer otSpan1.End()
|
||||||
|
|
||||||
// Use NewContext instead of the context from Start
|
// Use NewContext instead of the context from Start
|
||||||
ctx = octrace.NewContext(ctx, octrace.NewSpan(&span{otSpan: otSpan1}))
|
ctx = octrace.NewContext(ctx, internal.NewSpan(otSpan1))
|
||||||
|
|
||||||
ctx, _ = tracer.Start(ctx, "OpenTelemetrySpan2")
|
ctx, _ = tracer.Start(ctx, "OpenTelemetrySpan2")
|
||||||
|
|
||||||
@@ -256,22 +257,22 @@ func TestSetThings(t *testing.T) {
|
|||||||
if v := annotateEvent.Attributes[attribute.Key("string")]; v.AsString() != "annotateval" {
|
if v := annotateEvent.Attributes[attribute.Key("string")]; v.AsString() != "annotateval" {
|
||||||
t.Errorf("Got annotateEvent.Attributes[string] = %v, expected annotateval", v.AsString())
|
t.Errorf("Got annotateEvent.Attributes[string] = %v, expected annotateval", v.AsString())
|
||||||
}
|
}
|
||||||
if sendEvent.Name != "message send" {
|
if sendEvent.Name != internal.MessageSendEvent {
|
||||||
t.Errorf("Got sendEvent.Name = %v, expected message send", sendEvent.Name)
|
t.Errorf("Got sendEvent.Name = %v, expected message send", sendEvent.Name)
|
||||||
}
|
}
|
||||||
if v := sendEvent.Attributes[uncompressedKey]; v.AsInt64() != 456 {
|
if v := sendEvent.Attributes[internal.UncompressedKey]; v.AsInt64() != 456 {
|
||||||
t.Errorf("Got sendEvent.Attributes[uncompressedKey] = %v, expected 456", v.AsInt64())
|
t.Errorf("Got sendEvent.Attributes[uncompressedKey] = %v, expected 456", v.AsInt64())
|
||||||
}
|
}
|
||||||
if v := sendEvent.Attributes[compressedKey]; v.AsInt64() != 789 {
|
if v := sendEvent.Attributes[internal.CompressedKey]; v.AsInt64() != 789 {
|
||||||
t.Errorf("Got sendEvent.Attributes[compressedKey] = %v, expected 789", v.AsInt64())
|
t.Errorf("Got sendEvent.Attributes[compressedKey] = %v, expected 789", v.AsInt64())
|
||||||
}
|
}
|
||||||
if receiveEvent.Name != "message receive" {
|
if receiveEvent.Name != internal.MessageReceiveEvent {
|
||||||
t.Errorf("Got receiveEvent.Name = %v, expected message receive", receiveEvent.Name)
|
t.Errorf("Got receiveEvent.Name = %v, expected message receive", receiveEvent.Name)
|
||||||
}
|
}
|
||||||
if v := receiveEvent.Attributes[uncompressedKey]; v.AsInt64() != 135 {
|
if v := receiveEvent.Attributes[internal.UncompressedKey]; v.AsInt64() != 135 {
|
||||||
t.Errorf("Got receiveEvent.Attributes[uncompressedKey] = %v, expected 135", v.AsInt64())
|
t.Errorf("Got receiveEvent.Attributes[uncompressedKey] = %v, expected 135", v.AsInt64())
|
||||||
}
|
}
|
||||||
if v := receiveEvent.Attributes[compressedKey]; v.AsInt64() != 369 {
|
if v := receiveEvent.Attributes[internal.CompressedKey]; v.AsInt64() != 369 {
|
||||||
t.Errorf("Got receiveEvent.Attributes[compressedKey] = %v, expected 369", v.AsInt64())
|
t.Errorf("Got receiveEvent.Attributes[compressedKey] = %v, expected 369", v.AsInt64())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
21
bridge/opencensus/internal/handler.go
Normal file
21
bridge/opencensus/internal/handler.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// 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 internal
|
||||||
|
|
||||||
|
import "go.opentelemetry.io/otel"
|
||||||
|
|
||||||
|
// Handle is the package level function to handle errors. It can be
|
||||||
|
// overwritten for testing.
|
||||||
|
var Handle = otel.Handle
|
47
bridge/opencensus/internal/oc2otel/attributes.go
Normal file
47
bridge/opencensus/internal/oc2otel/attributes.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
// 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 oc2otel
|
||||||
|
|
||||||
|
import (
|
||||||
|
octrace "go.opencensus.io/trace"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Attributes(attr []octrace.Attribute) []attribute.KeyValue {
|
||||||
|
otelAttr := make([]attribute.KeyValue, len(attr))
|
||||||
|
for i, a := range attr {
|
||||||
|
otelAttr[i] = attribute.KeyValue{
|
||||||
|
Key: attribute.Key(a.Key()),
|
||||||
|
Value: AttributeValue(a.Value()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return otelAttr
|
||||||
|
}
|
||||||
|
|
||||||
|
func AttributeValue(ocval interface{}) attribute.Value {
|
||||||
|
switch v := ocval.(type) {
|
||||||
|
case bool:
|
||||||
|
return attribute.BoolValue(v)
|
||||||
|
case int64:
|
||||||
|
return attribute.Int64Value(v)
|
||||||
|
case float64:
|
||||||
|
return attribute.Float64Value(v)
|
||||||
|
case string:
|
||||||
|
return attribute.StringValue(v)
|
||||||
|
default:
|
||||||
|
return attribute.StringValue("unknown")
|
||||||
|
}
|
||||||
|
}
|
33
bridge/opencensus/internal/oc2otel/span_context.go
Normal file
33
bridge/opencensus/internal/oc2otel/span_context.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
// 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 oc2otel
|
||||||
|
|
||||||
|
import (
|
||||||
|
octrace "go.opencensus.io/trace"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SpanContext(sc octrace.SpanContext) trace.SpanContext {
|
||||||
|
var traceFlags trace.TraceFlags
|
||||||
|
if sc.IsSampled() {
|
||||||
|
traceFlags = trace.FlagsSampled
|
||||||
|
}
|
||||||
|
return trace.NewSpanContext(trace.SpanContextConfig{
|
||||||
|
TraceID: trace.TraceID(sc.TraceID),
|
||||||
|
SpanID: trace.SpanID(sc.SpanID),
|
||||||
|
TraceFlags: traceFlags,
|
||||||
|
})
|
||||||
|
}
|
@@ -12,63 +12,18 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package utils
|
package oc2otel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"go.opencensus.io/trace/tracestate"
|
|
||||||
|
|
||||||
octrace "go.opencensus.io/trace"
|
octrace "go.opencensus.io/trace"
|
||||||
|
"go.opencensus.io/trace/tracestate"
|
||||||
|
|
||||||
"go.opentelemetry.io/otel/trace"
|
"go.opentelemetry.io/otel/trace"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestOTelSpanContextToOC(t *testing.T) {
|
func TestSpanContextConversion(t *testing.T) {
|
||||||
for _, tc := range []struct {
|
|
||||||
description string
|
|
||||||
input trace.SpanContext
|
|
||||||
expected octrace.SpanContext
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
description: "empty",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: "sampled",
|
|
||||||
input: trace.NewSpanContext(trace.SpanContextConfig{
|
|
||||||
TraceID: trace.TraceID([16]byte{1}),
|
|
||||||
SpanID: trace.SpanID([8]byte{2}),
|
|
||||||
TraceFlags: trace.FlagsSampled,
|
|
||||||
}),
|
|
||||||
expected: octrace.SpanContext{
|
|
||||||
TraceID: octrace.TraceID([16]byte{1}),
|
|
||||||
SpanID: octrace.SpanID([8]byte{2}),
|
|
||||||
TraceOptions: octrace.TraceOptions(0x1),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: "not sampled",
|
|
||||||
input: trace.NewSpanContext(trace.SpanContextConfig{
|
|
||||||
TraceID: trace.TraceID([16]byte{1}),
|
|
||||||
SpanID: trace.SpanID([8]byte{2}),
|
|
||||||
}),
|
|
||||||
expected: octrace.SpanContext{
|
|
||||||
TraceID: octrace.TraceID([16]byte{1}),
|
|
||||||
SpanID: octrace.SpanID([8]byte{2}),
|
|
||||||
TraceOptions: octrace.TraceOptions(0),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
t.Run(tc.description, func(t *testing.T) {
|
|
||||||
output := OTelSpanContextToOC(tc.input)
|
|
||||||
if output != tc.expected {
|
|
||||||
t.Fatalf("Got %+v spancontext, exepected %+v.", output, tc.expected)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOCSpanContextToOTel(t *testing.T) {
|
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
description string
|
description string
|
||||||
input octrace.SpanContext
|
input octrace.SpanContext
|
||||||
@@ -116,7 +71,7 @@ func TestOCSpanContextToOTel(t *testing.T) {
|
|||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(tc.description, func(t *testing.T) {
|
t.Run(tc.description, func(t *testing.T) {
|
||||||
output := OCSpanContextToOTel(tc.input)
|
output := SpanContext(tc.input)
|
||||||
if !output.Equal(tc.expected) {
|
if !output.Equal(tc.expected) {
|
||||||
t.Fatalf("Got %+v spancontext, exepected %+v.", output, tc.expected)
|
t.Fatalf("Got %+v spancontext, exepected %+v.", output, tc.expected)
|
||||||
}
|
}
|
46
bridge/opencensus/internal/oc2otel/tracer_start_options.go
Normal file
46
bridge/opencensus/internal/oc2otel/tracer_start_options.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// 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 oc2otel
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
octrace "go.opencensus.io/trace"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
)
|
||||||
|
|
||||||
|
func StartOptions(optFuncs []octrace.StartOption) ([]trace.SpanStartOption, error) {
|
||||||
|
var ocOpts octrace.StartOptions
|
||||||
|
for _, fn := range optFuncs {
|
||||||
|
fn(&ocOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
var otelOpts []trace.SpanStartOption
|
||||||
|
switch ocOpts.SpanKind {
|
||||||
|
case octrace.SpanKindClient:
|
||||||
|
otelOpts = append(otelOpts, trace.WithSpanKind(trace.SpanKindClient))
|
||||||
|
case octrace.SpanKindServer:
|
||||||
|
otelOpts = append(otelOpts, trace.WithSpanKind(trace.SpanKindServer))
|
||||||
|
case octrace.SpanKindUnspecified:
|
||||||
|
otelOpts = append(otelOpts, trace.WithSpanKind(trace.SpanKindUnspecified))
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
if ocOpts.Sampler != nil {
|
||||||
|
err = fmt.Errorf("unsupported sampler: %v", ocOpts.Sampler)
|
||||||
|
}
|
||||||
|
return otelOpts, err
|
||||||
|
}
|
34
bridge/opencensus/internal/otel2oc/span_context.go
Normal file
34
bridge/opencensus/internal/otel2oc/span_context.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// 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 otel2oc
|
||||||
|
|
||||||
|
import (
|
||||||
|
octrace "go.opencensus.io/trace"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SpanContext(sc trace.SpanContext) octrace.SpanContext {
|
||||||
|
var to octrace.TraceOptions
|
||||||
|
if sc.IsSampled() {
|
||||||
|
// OpenCensus doesn't expose functions to directly set sampled
|
||||||
|
to = 0x1
|
||||||
|
}
|
||||||
|
return octrace.SpanContext{
|
||||||
|
TraceID: octrace.TraceID(sc.TraceID()),
|
||||||
|
SpanID: octrace.SpanID(sc.SpanID()),
|
||||||
|
TraceOptions: to,
|
||||||
|
}
|
||||||
|
}
|
67
bridge/opencensus/internal/otel2oc/span_context_test.go
Normal file
67
bridge/opencensus/internal/otel2oc/span_context_test.go
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
// 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 otel2oc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
octrace "go.opencensus.io/trace"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSpanContextConversion(t *testing.T) {
|
||||||
|
for _, tc := range []struct {
|
||||||
|
description string
|
||||||
|
input trace.SpanContext
|
||||||
|
expected octrace.SpanContext
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "empty",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "sampled",
|
||||||
|
input: trace.NewSpanContext(trace.SpanContextConfig{
|
||||||
|
TraceID: trace.TraceID([16]byte{1}),
|
||||||
|
SpanID: trace.SpanID([8]byte{2}),
|
||||||
|
TraceFlags: trace.FlagsSampled,
|
||||||
|
}),
|
||||||
|
expected: octrace.SpanContext{
|
||||||
|
TraceID: octrace.TraceID([16]byte{1}),
|
||||||
|
SpanID: octrace.SpanID([8]byte{2}),
|
||||||
|
TraceOptions: octrace.TraceOptions(0x1),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "not sampled",
|
||||||
|
input: trace.NewSpanContext(trace.SpanContextConfig{
|
||||||
|
TraceID: trace.TraceID([16]byte{1}),
|
||||||
|
SpanID: trace.SpanID([8]byte{2}),
|
||||||
|
}),
|
||||||
|
expected: octrace.SpanContext{
|
||||||
|
TraceID: octrace.TraceID([16]byte{1}),
|
||||||
|
SpanID: octrace.SpanID([8]byte{2}),
|
||||||
|
TraceOptions: octrace.TraceOptions(0),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tc.description, func(t *testing.T) {
|
||||||
|
output := SpanContext(tc.input)
|
||||||
|
if output != tc.expected {
|
||||||
|
t.Fatalf("Got %+v spancontext, exepected %+v.", output, tc.expected)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
131
bridge/opencensus/internal/span.go
Normal file
131
bridge/opencensus/internal/span.go
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
// 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 internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
octrace "go.opencensus.io/trace"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel"
|
||||||
|
"go.opentelemetry.io/otel/bridge/opencensus/internal/otel2oc"
|
||||||
|
"go.opentelemetry.io/otel/codes"
|
||||||
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// MessageSendEvent is the name of the message send event.
|
||||||
|
MessageSendEvent = "message send"
|
||||||
|
// MessageReceiveEvent is the name of the message receive event.
|
||||||
|
MessageReceiveEvent = "message receive"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// UncompressedKey is used for the uncompressed byte size attribute.
|
||||||
|
UncompressedKey = attribute.Key("uncompressed byte size")
|
||||||
|
// CompressedKey is used for the compressed byte size attribute.
|
||||||
|
CompressedKey = attribute.Key("compressed byte size")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Span is an OpenCensus SpanInterface wrapper for an OpenTelemetry Span.
|
||||||
|
type Span struct {
|
||||||
|
otelSpan trace.Span
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSpan returns an OpenCensus Span wrapping an OpenTelemetry Span.
|
||||||
|
func NewSpan(s trace.Span) *octrace.Span {
|
||||||
|
return octrace.NewSpan(&Span{otelSpan: s})
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRecordingEvents returns true if events are being recorded for this span.
|
||||||
|
func (s *Span) IsRecordingEvents() bool {
|
||||||
|
return s.otelSpan.IsRecording()
|
||||||
|
}
|
||||||
|
|
||||||
|
// End ends thi span.
|
||||||
|
func (s *Span) End() {
|
||||||
|
s.otelSpan.End()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SpanContext returns the SpanContext of this span.
|
||||||
|
func (s *Span) SpanContext() octrace.SpanContext {
|
||||||
|
return otel2oc.SpanContext(s.otelSpan.SpanContext())
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetName sets the name of this span, if it is recording events.
|
||||||
|
func (s *Span) SetName(name string) {
|
||||||
|
s.otelSpan.SetName(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStatus sets the status of this span, if it is recording events.
|
||||||
|
func (s *Span) SetStatus(status octrace.Status) {
|
||||||
|
s.otelSpan.SetStatus(codes.Code(status.Code), status.Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddAttributes sets attributes in this span.
|
||||||
|
func (s *Span) AddAttributes(attributes ...octrace.Attribute) {
|
||||||
|
s.otelSpan.SetAttributes(oc2otel.Attributes(attributes)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Annotate adds an annotation with attributes to this span.
|
||||||
|
func (s *Span) Annotate(attributes []octrace.Attribute, str string) {
|
||||||
|
s.otelSpan.AddEvent(str, trace.WithAttributes(oc2otel.Attributes(attributes)...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Annotatef adds a formatted annotation with attributes to this span.
|
||||||
|
func (s *Span) Annotatef(attributes []octrace.Attribute, format string, a ...interface{}) {
|
||||||
|
s.Annotate(attributes, fmt.Sprintf(format, a...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddMessageSendEvent adds a message send event to this span.
|
||||||
|
func (s *Span) AddMessageSendEvent(messageID, uncompressedByteSize, compressedByteSize int64) {
|
||||||
|
s.otelSpan.AddEvent(MessageSendEvent,
|
||||||
|
trace.WithAttributes(
|
||||||
|
attribute.KeyValue{
|
||||||
|
Key: UncompressedKey,
|
||||||
|
Value: attribute.Int64Value(uncompressedByteSize),
|
||||||
|
},
|
||||||
|
attribute.KeyValue{
|
||||||
|
Key: CompressedKey,
|
||||||
|
Value: attribute.Int64Value(compressedByteSize),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddMessageReceiveEvent adds a message receive event to this span.
|
||||||
|
func (s *Span) AddMessageReceiveEvent(messageID, uncompressedByteSize, compressedByteSize int64) {
|
||||||
|
s.otelSpan.AddEvent(MessageReceiveEvent,
|
||||||
|
trace.WithAttributes(
|
||||||
|
attribute.KeyValue{
|
||||||
|
Key: UncompressedKey,
|
||||||
|
Value: attribute.Int64Value(uncompressedByteSize),
|
||||||
|
},
|
||||||
|
attribute.KeyValue{
|
||||||
|
Key: CompressedKey,
|
||||||
|
Value: attribute.Int64Value(compressedByteSize),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddLink adds a link to this span.
|
||||||
|
func (s *Span) AddLink(l octrace.Link) {
|
||||||
|
Handle(fmt.Errorf("ignoring OpenCensus link %+v for span %q because OpenTelemetry doesn't support setting links after creation", l, s.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// String prints a string representation of this span.
|
||||||
|
func (s *Span) String() string {
|
||||||
|
return fmt.Sprintf("span %s", s.otelSpan.SpanContext().SpanID().String())
|
||||||
|
}
|
69
bridge/opencensus/internal/tracer.go
Normal file
69
bridge/opencensus/internal/tracer.go
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
// 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 internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
octrace "go.opencensus.io/trace"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel"
|
||||||
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Tracer is an OpenCensus Tracer that wraps an OpenTelemetry Tracer.
|
||||||
|
type Tracer struct {
|
||||||
|
otelTracer trace.Tracer
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTracer returns an OpenCensus Tracer that wraps the OpenTelemetry tracer.
|
||||||
|
func NewTracer(tracer trace.Tracer) octrace.Tracer {
|
||||||
|
return &Tracer{otelTracer: tracer}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartSpan starts a new child span of the current span in the context. If
|
||||||
|
// there is no span in the context, it creates a new trace and span.
|
||||||
|
func (o *Tracer) StartSpan(ctx context.Context, name string, s ...octrace.StartOption) (context.Context, *octrace.Span) {
|
||||||
|
otelOpts, err := oc2otel.StartOptions(s)
|
||||||
|
if err != nil {
|
||||||
|
Handle(fmt.Errorf("starting span %q: %w", name, err))
|
||||||
|
}
|
||||||
|
ctx, sp := o.otelTracer.Start(ctx, name, otelOpts...)
|
||||||
|
return ctx, NewSpan(sp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartSpanWithRemoteParent starts a new child span of the span from the
|
||||||
|
// given parent.
|
||||||
|
func (o *Tracer) StartSpanWithRemoteParent(ctx context.Context, name string, parent octrace.SpanContext, s ...octrace.StartOption) (context.Context, *octrace.Span) {
|
||||||
|
// make sure span context is zero'd out so we use the remote parent
|
||||||
|
ctx = trace.ContextWithSpan(ctx, nil)
|
||||||
|
ctx = trace.ContextWithRemoteSpanContext(ctx, oc2otel.SpanContext(parent))
|
||||||
|
return o.StartSpan(ctx, name, s...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromContext returns the Span stored in a context.
|
||||||
|
func (o *Tracer) FromContext(ctx context.Context) *octrace.Span {
|
||||||
|
return NewSpan(trace.SpanFromContext(ctx))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewContext returns a new context with the given Span attached.
|
||||||
|
func (o *Tracer) NewContext(parent context.Context, s *octrace.Span) context.Context {
|
||||||
|
if otSpan, ok := s.Internal().(*Span); ok {
|
||||||
|
return trace.ContextWithSpan(parent, otSpan.otelSpan)
|
||||||
|
}
|
||||||
|
Handle(fmt.Errorf("unable to create context with span %q, since it was created using a different tracer", s.String()))
|
||||||
|
return parent
|
||||||
|
}
|
@@ -17,6 +17,8 @@ package utils // import "go.opentelemetry.io/otel/bridge/opencensus/utils"
|
|||||||
import (
|
import (
|
||||||
octrace "go.opencensus.io/trace"
|
octrace "go.opencensus.io/trace"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel"
|
||||||
|
"go.opentelemetry.io/otel/bridge/opencensus/internal/otel2oc"
|
||||||
"go.opentelemetry.io/otel/trace"
|
"go.opentelemetry.io/otel/trace"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -24,28 +26,11 @@ import (
|
|||||||
// OpenCensus SpanContext, and handles any incompatibilities with the global
|
// OpenCensus SpanContext, and handles any incompatibilities with the global
|
||||||
// error handler.
|
// error handler.
|
||||||
func OTelSpanContextToOC(sc trace.SpanContext) octrace.SpanContext {
|
func OTelSpanContextToOC(sc trace.SpanContext) octrace.SpanContext {
|
||||||
var to octrace.TraceOptions
|
return otel2oc.SpanContext(sc)
|
||||||
if sc.IsSampled() {
|
|
||||||
// OpenCensus doesn't expose functions to directly set sampled
|
|
||||||
to = 0x1
|
|
||||||
}
|
|
||||||
return octrace.SpanContext{
|
|
||||||
TraceID: octrace.TraceID(sc.TraceID()),
|
|
||||||
SpanID: octrace.SpanID(sc.SpanID()),
|
|
||||||
TraceOptions: to,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OCSpanContextToOTel converts from an OpenCensus SpanContext to an
|
// OCSpanContextToOTel converts from an OpenCensus SpanContext to an
|
||||||
// OpenTelemetry SpanContext.
|
// OpenTelemetry SpanContext.
|
||||||
func OCSpanContextToOTel(sc octrace.SpanContext) trace.SpanContext {
|
func OCSpanContextToOTel(sc octrace.SpanContext) trace.SpanContext {
|
||||||
var traceFlags trace.TraceFlags
|
return oc2otel.SpanContext(sc)
|
||||||
if sc.IsSampled() {
|
|
||||||
traceFlags = trace.FlagsSampled
|
|
||||||
}
|
|
||||||
return trace.NewSpanContext(trace.SpanContextConfig{
|
|
||||||
TraceID: trace.TraceID(sc.TraceID),
|
|
||||||
SpanID: trace.SpanID(sc.SpanID),
|
|
||||||
TraceFlags: traceFlags,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user