2020-03-24 07:41:10 +02:00
// Copyright The OpenTelemetry Authors
2019-09-25 08:12:22 +02:00
//
// 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 opentracing
import (
"context"
"fmt"
"testing"
ot "github.com/opentracing/opentracing-go"
2020-11-16 19:30:54 +02:00
"go.opentelemetry.io/otel"
2021-02-18 19:59:37 +02:00
"go.opentelemetry.io/otel/attribute"
2021-06-08 17:06:37 +02:00
"go.opentelemetry.io/otel/baggage"
2019-11-01 20:40:29 +02:00
"go.opentelemetry.io/otel/bridge/opentracing/internal"
2021-11-13 18:35:04 +02:00
"go.opentelemetry.io/otel/trace"
2019-09-25 08:12:22 +02:00
)
type mixedAPIsTestCase struct {
desc string
setup func ( * testing . T , * internal . MockTracer )
run func ( * testing . T , context . Context )
check func ( * testing . T , * internal . MockTracer )
}
func getMixedAPIsTestCases ( ) [ ] mixedAPIsTestCase {
st := newSimpleTest ( )
cast := newCurrentActiveSpanTest ( )
coin := newContextIntactTest ( )
bip := newBaggageItemsPreservationTest ( )
2020-03-10 19:32:01 +02:00
bio := newBaggageInteroperationTest ( )
2019-09-25 08:12:22 +02:00
return [ ] mixedAPIsTestCase {
{
desc : "simple otel -> ot -> otel" ,
setup : st . setup ,
run : st . runOtelOTOtel ,
check : st . check ,
} ,
{
desc : "simple ot -> otel -> ot" ,
setup : st . setup ,
run : st . runOTOtelOT ,
check : st . check ,
} ,
{
desc : "current/active span otel -> ot -> otel" ,
setup : cast . setup ,
run : cast . runOtelOTOtel ,
check : cast . check ,
} ,
{
desc : "current/active span ot -> otel -> ot" ,
setup : cast . setup ,
run : cast . runOTOtelOT ,
check : cast . check ,
} ,
{
desc : "context intact otel -> ot -> otel" ,
setup : coin . setup ,
run : coin . runOtelOTOtel ,
check : coin . check ,
} ,
{
desc : "context intact ot -> otel -> ot" ,
setup : coin . setup ,
run : coin . runOTOtelOT ,
check : coin . check ,
} ,
{
desc : "baggage items preservation across layers otel -> ot -> otel" ,
setup : bip . setup ,
run : bip . runOtelOTOtel ,
check : bip . check ,
} ,
{
desc : "baggage items preservation across layers ot -> otel -> ot" ,
setup : bip . setup ,
run : bip . runOTOtelOT ,
check : bip . check ,
} ,
2020-03-10 19:32:01 +02:00
{
desc : "baggage items interoperation across layers ot -> otel -> ot" ,
setup : bio . setup ,
run : bio . runOTOtelOT ,
check : bio . check ,
} ,
{
desc : "baggage items interoperation across layers otel -> ot -> otel" ,
setup : bio . setup ,
run : bio . runOtelOTOtel ,
check : bio . check ,
} ,
2019-09-25 08:12:22 +02:00
}
}
func TestMixedAPIs ( t * testing . T ) {
for idx , tc := range getMixedAPIsTestCases ( ) {
t . Logf ( "Running test case %d: %s" , idx , tc . desc )
mockOtelTracer := internal . NewMockTracer ( )
2020-03-10 19:32:01 +02:00
ctx , otTracer , otelProvider := NewTracerPairWithContext ( context . Background ( ) , mockOtelTracer )
2019-09-25 08:12:22 +02:00
otTracer . SetWarningHandler ( func ( msg string ) {
t . Log ( msg )
} )
2020-11-16 19:30:54 +02:00
otel . SetTracerProvider ( otelProvider )
2019-09-25 08:12:22 +02:00
ot . SetGlobalTracer ( otTracer )
tc . setup ( t , mockOtelTracer )
tc . run ( t , ctx )
tc . check ( t , mockOtelTracer )
}
}
// simple test
type simpleTest struct {
2020-11-07 00:13:31 +02:00
traceID trace . TraceID
spanIDs [ ] trace . SpanID
2019-09-25 08:12:22 +02:00
}
func newSimpleTest ( ) * simpleTest {
return & simpleTest {
traceID : simpleTraceID ( ) ,
spanIDs : simpleSpanIDs ( 3 ) ,
}
}
func ( st * simpleTest ) setup ( t * testing . T , tracer * internal . MockTracer ) {
tracer . SpareTraceIDs = append ( tracer . SpareTraceIDs , st . traceID )
tracer . SpareSpanIDs = append ( tracer . SpareSpanIDs , st . spanIDs ... )
}
func ( st * simpleTest ) check ( t * testing . T , tracer * internal . MockTracer ) {
checkTraceAndSpans ( t , tracer , st . traceID , st . spanIDs )
}
func ( st * simpleTest ) runOtelOTOtel ( t * testing . T , ctx context . Context ) {
runOtelOTOtel ( t , ctx , "simple" , st . noop )
}
func ( st * simpleTest ) runOTOtelOT ( t * testing . T , ctx context . Context ) {
runOTOtelOT ( t , ctx , "simple" , st . noop )
}
2020-03-10 19:32:01 +02:00
func ( st * simpleTest ) noop ( t * testing . T , ctx context . Context ) context . Context {
return ctx
2019-09-25 08:12:22 +02:00
}
// current/active span test
type currentActiveSpanTest struct {
2020-11-07 00:13:31 +02:00
traceID trace . TraceID
spanIDs [ ] trace . SpanID
2019-09-25 08:12:22 +02:00
2020-11-07 00:13:31 +02:00
recordedCurrentOtelSpanIDs [ ] trace . SpanID
recordedActiveOTSpanIDs [ ] trace . SpanID
2019-09-25 08:12:22 +02:00
}
func newCurrentActiveSpanTest ( ) * currentActiveSpanTest {
return & currentActiveSpanTest {
traceID : simpleTraceID ( ) ,
spanIDs : simpleSpanIDs ( 3 ) ,
}
}
func ( cast * currentActiveSpanTest ) setup ( t * testing . T , tracer * internal . MockTracer ) {
tracer . SpareTraceIDs = append ( tracer . SpareTraceIDs , cast . traceID )
tracer . SpareSpanIDs = append ( tracer . SpareSpanIDs , cast . spanIDs ... )
cast . recordedCurrentOtelSpanIDs = nil
cast . recordedActiveOTSpanIDs = nil
}
func ( cast * currentActiveSpanTest ) check ( t * testing . T , tracer * internal . MockTracer ) {
checkTraceAndSpans ( t , tracer , cast . traceID , cast . spanIDs )
if len ( cast . recordedCurrentOtelSpanIDs ) != len ( cast . spanIDs ) {
t . Errorf ( "Expected to have %d recorded Otel current spans, got %d" , len ( cast . spanIDs ) , len ( cast . recordedCurrentOtelSpanIDs ) )
}
if len ( cast . recordedActiveOTSpanIDs ) != len ( cast . spanIDs ) {
t . Errorf ( "Expected to have %d recorded OT active spans, got %d" , len ( cast . spanIDs ) , len ( cast . recordedActiveOTSpanIDs ) )
}
minLen := min ( len ( cast . recordedCurrentOtelSpanIDs ) , len ( cast . spanIDs ) )
minLen = min ( minLen , len ( cast . recordedActiveOTSpanIDs ) )
for i := 0 ; i < minLen ; i ++ {
if cast . recordedCurrentOtelSpanIDs [ i ] != cast . spanIDs [ i ] {
t . Errorf ( "Expected span idx %d (%d) to be recorded as current span in Otel, got %d" , i , cast . spanIDs [ i ] , cast . recordedCurrentOtelSpanIDs [ i ] )
}
if cast . recordedActiveOTSpanIDs [ i ] != cast . spanIDs [ i ] {
t . Errorf ( "Expected span idx %d (%d) to be recorded as active span in OT, got %d" , i , cast . spanIDs [ i ] , cast . recordedActiveOTSpanIDs [ i ] )
}
}
}
func ( cast * currentActiveSpanTest ) runOtelOTOtel ( t * testing . T , ctx context . Context ) {
runOtelOTOtel ( t , ctx , "cast" , cast . recordSpans )
}
func ( cast * currentActiveSpanTest ) runOTOtelOT ( t * testing . T , ctx context . Context ) {
runOTOtelOT ( t , ctx , "cast" , cast . recordSpans )
}
2020-03-10 19:32:01 +02:00
func ( cast * currentActiveSpanTest ) recordSpans ( t * testing . T , ctx context . Context ) context . Context {
2021-03-09 18:17:29 +02:00
spanID := trace . SpanContextFromContext ( ctx ) . SpanID ( )
2019-09-25 08:12:22 +02:00
cast . recordedCurrentOtelSpanIDs = append ( cast . recordedCurrentOtelSpanIDs , spanID )
2020-11-07 00:13:31 +02:00
spanID = trace . SpanID { }
2019-09-25 08:12:22 +02:00
if bridgeSpan , ok := ot . SpanFromContext ( ctx ) . ( * bridgeSpan ) ; ok {
2021-03-09 18:17:29 +02:00
spanID = bridgeSpan . otelSpan . SpanContext ( ) . SpanID ( )
2019-09-25 08:12:22 +02:00
}
cast . recordedActiveOTSpanIDs = append ( cast . recordedActiveOTSpanIDs , spanID )
2020-03-10 19:32:01 +02:00
return ctx
2019-09-25 08:12:22 +02:00
}
// context intact test
type contextIntactTest struct {
contextKeyValues [ ] internal . MockContextKeyValue
recordedContextValues [ ] interface { }
recordIdx int
}
type coin1Key struct { }
type coin1Value struct { }
type coin2Key struct { }
type coin2Value struct { }
type coin3Key struct { }
type coin3Value struct { }
func newContextIntactTest ( ) * contextIntactTest {
return & contextIntactTest {
contextKeyValues : [ ] internal . MockContextKeyValue {
2019-10-16 19:24:38 +02:00
{
2019-09-25 08:12:22 +02:00
Key : coin1Key { } ,
Value : coin1Value { } ,
} ,
2019-10-16 19:24:38 +02:00
{
2019-09-25 08:12:22 +02:00
Key : coin2Key { } ,
Value : coin2Value { } ,
} ,
2019-10-16 19:24:38 +02:00
{
2019-09-25 08:12:22 +02:00
Key : coin3Key { } ,
Value : coin3Value { } ,
} ,
} ,
}
}
func ( coin * contextIntactTest ) setup ( t * testing . T , tracer * internal . MockTracer ) {
tracer . SpareContextKeyValues = append ( tracer . SpareContextKeyValues , coin . contextKeyValues ... )
coin . recordedContextValues = nil
coin . recordIdx = 0
}
func ( coin * contextIntactTest ) check ( t * testing . T , tracer * internal . MockTracer ) {
if len ( coin . recordedContextValues ) != len ( coin . contextKeyValues ) {
t . Errorf ( "Expected to have %d recorded context values, got %d" , len ( coin . contextKeyValues ) , len ( coin . recordedContextValues ) )
}
minLen := min ( len ( coin . recordedContextValues ) , len ( coin . contextKeyValues ) )
for i := 0 ; i < minLen ; i ++ {
key := coin . contextKeyValues [ i ] . Key
value := coin . contextKeyValues [ i ] . Value
gotValue := coin . recordedContextValues [ i ]
if value != gotValue {
t . Errorf ( "Expected value %#v for key %#v, got %#v" , value , key , gotValue )
}
}
}
func ( coin * contextIntactTest ) runOtelOTOtel ( t * testing . T , ctx context . Context ) {
runOtelOTOtel ( t , ctx , "coin" , coin . recordValue )
}
func ( coin * contextIntactTest ) runOTOtelOT ( t * testing . T , ctx context . Context ) {
runOTOtelOT ( t , ctx , "coin" , coin . recordValue )
}
2020-03-10 19:32:01 +02:00
func ( coin * contextIntactTest ) recordValue ( t * testing . T , ctx context . Context ) context . Context {
2019-09-25 08:12:22 +02:00
if coin . recordIdx >= len ( coin . contextKeyValues ) {
t . Errorf ( "Too many steps?" )
2020-03-10 19:32:01 +02:00
return ctx
2019-09-25 08:12:22 +02:00
}
key := coin . contextKeyValues [ coin . recordIdx ] . Key
coin . recordIdx ++
coin . recordedContextValues = append ( coin . recordedContextValues , ctx . Value ( key ) )
2020-03-10 19:32:01 +02:00
return ctx
2019-09-25 08:12:22 +02:00
}
// baggage items preservation test
type bipBaggage struct {
key string
value string
}
type baggageItemsPreservationTest struct {
baggageItems [ ] bipBaggage
step int
recordedBaggage [ ] map [ string ] string
}
func newBaggageItemsPreservationTest ( ) * baggageItemsPreservationTest {
return & baggageItemsPreservationTest {
baggageItems : [ ] bipBaggage {
{
key : "First" ,
value : "one" ,
} ,
{
key : "Second" ,
value : "two" ,
} ,
{
key : "Third" ,
value : "three" ,
} ,
} ,
}
}
func ( bip * baggageItemsPreservationTest ) setup ( t * testing . T , tracer * internal . MockTracer ) {
bip . step = 0
bip . recordedBaggage = nil
}
func ( bip * baggageItemsPreservationTest ) check ( t * testing . T , tracer * internal . MockTracer ) {
if len ( bip . recordedBaggage ) != len ( bip . baggageItems ) {
t . Errorf ( "Expected %d recordings, got %d" , len ( bip . baggageItems ) , len ( bip . recordedBaggage ) )
}
minLen := min ( len ( bip . recordedBaggage ) , len ( bip . baggageItems ) )
for i := 0 ; i < minLen ; i ++ {
recordedItems := bip . recordedBaggage [ i ]
if len ( recordedItems ) != i + 1 {
t . Errorf ( "Expected %d recorded baggage items in recording %d, got %d" , i + 1 , i + 1 , len ( bip . recordedBaggage [ i ] ) )
}
minItemLen := min ( len ( bip . baggageItems ) , i + 1 )
for j := 0 ; j < minItemLen ; j ++ {
expectedItem := bip . baggageItems [ j ]
if gotValue , ok := recordedItems [ expectedItem . key ] ; ! ok {
t . Errorf ( "Missing baggage item %q in recording %d" , expectedItem . key , i + 1 )
} else if gotValue != expectedItem . value {
t . Errorf ( "Expected recorded baggage item %q in recording %d + 1to be %q, got %q" , expectedItem . key , i , expectedItem . value , gotValue )
} else {
delete ( recordedItems , expectedItem . key )
}
}
for key , value := range recordedItems {
t . Errorf ( "Unexpected baggage item in recording %d: %q -> %q" , i + 1 , key , value )
}
}
}
func ( bip * baggageItemsPreservationTest ) runOtelOTOtel ( t * testing . T , ctx context . Context ) {
runOtelOTOtel ( t , ctx , "bip" , bip . addAndRecordBaggage )
}
func ( bip * baggageItemsPreservationTest ) runOTOtelOT ( t * testing . T , ctx context . Context ) {
runOTOtelOT ( t , ctx , "bip" , bip . addAndRecordBaggage )
}
2020-03-10 19:32:01 +02:00
func ( bip * baggageItemsPreservationTest ) addAndRecordBaggage ( t * testing . T , ctx context . Context ) context . Context {
2019-09-25 08:12:22 +02:00
if bip . step >= len ( bip . baggageItems ) {
t . Errorf ( "Too many steps?" )
2020-03-10 19:32:01 +02:00
return ctx
2019-09-25 08:12:22 +02:00
}
span := ot . SpanFromContext ( ctx )
if span == nil {
t . Errorf ( "No active OpenTracing span" )
2020-03-10 19:32:01 +02:00
return ctx
2019-09-25 08:12:22 +02:00
}
idx := bip . step
bip . step ++
span . SetBaggageItem ( bip . baggageItems [ idx ] . key , bip . baggageItems [ idx ] . value )
sctx := span . Context ( )
recording := make ( map [ string ] string )
sctx . ForeachBaggageItem ( func ( key , value string ) bool {
recording [ key ] = value
return true
} )
bip . recordedBaggage = append ( bip . recordedBaggage , recording )
2020-03-10 19:32:01 +02:00
return ctx
2019-09-25 08:12:22 +02:00
}
2020-03-10 19:32:01 +02:00
// baggage interoperation test
type baggageInteroperationTest struct {
baggageItems [ ] bipBaggage
step int
recordedOTBaggage [ ] map [ string ] string
recordedOtelBaggage [ ] map [ string ] string
}
func newBaggageInteroperationTest ( ) * baggageInteroperationTest {
return & baggageInteroperationTest {
baggageItems : [ ] bipBaggage {
{
key : "First" ,
value : "one" ,
} ,
{
key : "Second" ,
value : "two" ,
} ,
{
key : "Third" ,
value : "three" ,
} ,
} ,
}
}
func ( bio * baggageInteroperationTest ) setup ( t * testing . T , tracer * internal . MockTracer ) {
bio . step = 0
bio . recordedOTBaggage = nil
bio . recordedOtelBaggage = nil
}
func ( bio * baggageInteroperationTest ) check ( t * testing . T , tracer * internal . MockTracer ) {
checkBIORecording ( t , "OT" , bio . baggageItems , bio . recordedOTBaggage )
checkBIORecording ( t , "Otel" , bio . baggageItems , bio . recordedOtelBaggage )
}
func checkBIORecording ( t * testing . T , apiDesc string , initialItems [ ] bipBaggage , recordings [ ] map [ string ] string ) {
// expect recordings count to equal the number of initial
// items
// each recording should have a duplicated item from initial
// items, one with OT suffix, another one with Otel suffix
// expect each subsequent recording to have two more items, up
// to double of the count of the initial items
if len ( initialItems ) != len ( recordings ) {
t . Errorf ( "Expected %d recordings from %s, got %d" , len ( initialItems ) , apiDesc , len ( recordings ) )
}
minRecLen := min ( len ( initialItems ) , len ( recordings ) )
for i := 0 ; i < minRecLen ; i ++ {
recordedItems := recordings [ i ]
expectedItemsInStep := ( i + 1 ) * 2
if expectedItemsInStep != len ( recordedItems ) {
t . Errorf ( "Expected %d recorded items in recording %d from %s, got %d" , expectedItemsInStep , i , apiDesc , len ( recordedItems ) )
}
recordedItemsCopy := make ( map [ string ] string , len ( recordedItems ) )
for k , v := range recordedItems {
recordedItemsCopy [ k ] = v
}
for j := 0 ; j < i + 1 ; j ++ {
otKey , otelKey := generateBaggageKeys ( initialItems [ j ] . key )
value := initialItems [ j ] . value
for _ , k := range [ ] string { otKey , otelKey } {
if v , ok := recordedItemsCopy [ k ] ; ok {
if value != v {
t . Errorf ( "Expected value %s under key %s in recording %d from %s, got %s" , value , k , i , apiDesc , v )
}
delete ( recordedItemsCopy , k )
} else {
t . Errorf ( "Missing key %s in recording %d from %s" , k , i , apiDesc )
}
}
}
for k , v := range recordedItemsCopy {
t . Errorf ( "Unexpected key-value pair %s = %s in recording %d from %s" , k , v , i , apiDesc )
}
}
}
func ( bio * baggageInteroperationTest ) runOtelOTOtel ( t * testing . T , ctx context . Context ) {
runOtelOTOtel ( t , ctx , "bio" , bio . addAndRecordBaggage )
}
func ( bio * baggageInteroperationTest ) runOTOtelOT ( t * testing . T , ctx context . Context ) {
runOTOtelOT ( t , ctx , "bio" , bio . addAndRecordBaggage )
}
func ( bio * baggageInteroperationTest ) addAndRecordBaggage ( t * testing . T , ctx context . Context ) context . Context {
if bio . step >= len ( bio . baggageItems ) {
t . Errorf ( "Too many steps?" )
return ctx
}
otSpan := ot . SpanFromContext ( ctx )
if otSpan == nil {
t . Errorf ( "No active OpenTracing span" )
return ctx
}
idx := bio . step
bio . step ++
key := bio . baggageItems [ idx ] . key
otKey , otelKey := generateBaggageKeys ( key )
value := bio . baggageItems [ idx ] . value
otSpan . SetBaggageItem ( otKey , value )
2021-06-08 17:06:37 +02:00
m , err := baggage . NewMember ( otelKey , value )
if err != nil {
t . Error ( err )
return ctx
}
b , err := baggage . FromContext ( ctx ) . SetMember ( m )
if err != nil {
t . Error ( err )
return ctx
}
ctx = baggage . ContextWithBaggage ( ctx , b )
2020-03-10 19:32:01 +02:00
otRecording := make ( map [ string ] string )
otSpan . Context ( ) . ForeachBaggageItem ( func ( key , value string ) bool {
otRecording [ key ] = value
return true
} )
otelRecording := make ( map [ string ] string )
2021-06-08 17:06:37 +02:00
for _ , m := range baggage . FromContext ( ctx ) . Members ( ) {
otelRecording [ m . Key ( ) ] = m . Value ( )
}
2020-03-10 19:32:01 +02:00
bio . recordedOTBaggage = append ( bio . recordedOTBaggage , otRecording )
bio . recordedOtelBaggage = append ( bio . recordedOtelBaggage , otelRecording )
return ctx
}
func generateBaggageKeys ( key string ) ( otKey , otelKey string ) {
otKey , otelKey = key + "-Ot" , key + "-Otel"
return
2019-09-25 08:12:22 +02:00
}
// helpers
2020-11-07 00:13:31 +02:00
func checkTraceAndSpans ( t * testing . T , tracer * internal . MockTracer , expectedTraceID trace . TraceID , expectedSpanIDs [ ] trace . SpanID ) {
2019-09-25 08:12:22 +02:00
expectedSpanCount := len ( expectedSpanIDs )
// reverse spanIDs, since first span ID belongs to root, that
// finishes last
2020-11-07 00:13:31 +02:00
spanIDs := make ( [ ] trace . SpanID , len ( expectedSpanIDs ) )
2019-09-25 08:12:22 +02:00
copy ( spanIDs , expectedSpanIDs )
reverse ( len ( spanIDs ) , func ( i , j int ) {
spanIDs [ i ] , spanIDs [ j ] = spanIDs [ j ] , spanIDs [ i ]
} )
// the last finished span has no parent
2020-11-07 00:13:31 +02:00
parentSpanIDs := append ( spanIDs [ 1 : ] , trace . SpanID { } )
2019-09-25 08:12:22 +02:00
2020-11-07 00:13:31 +02:00
sks := map [ trace . SpanID ] trace . SpanKind {
{ 125 } : trace . SpanKindProducer ,
{ 124 } : trace . SpanKindInternal ,
{ 123 } : trace . SpanKindClient ,
2019-10-24 01:25:14 +02:00
}
2019-09-25 08:12:22 +02:00
if len ( tracer . FinishedSpans ) != expectedSpanCount {
t . Errorf ( "Expected %d finished spans, got %d" , expectedSpanCount , len ( tracer . FinishedSpans ) )
}
for idx , span := range tracer . FinishedSpans {
sctx := span . SpanContext ( )
2021-03-09 18:17:29 +02:00
if sctx . TraceID ( ) != expectedTraceID {
t . Errorf ( "Expected trace ID %v in span %d (%d), got %v" , expectedTraceID , idx , sctx . SpanID ( ) , sctx . TraceID ( ) )
2019-09-25 08:12:22 +02:00
}
expectedSpanID := spanIDs [ idx ]
expectedParentSpanID := parentSpanIDs [ idx ]
2021-03-09 18:17:29 +02:00
if sctx . SpanID ( ) != expectedSpanID {
t . Errorf ( "Expected finished span %d to have span ID %d, but got %d" , idx , expectedSpanID , sctx . SpanID ( ) )
2019-09-25 08:12:22 +02:00
}
if span . ParentSpanID != expectedParentSpanID {
2021-03-09 18:17:29 +02:00
t . Errorf ( "Expected finished span %d (span ID: %d) to have parent span ID %d, but got %d" , idx , sctx . SpanID ( ) , expectedParentSpanID , span . ParentSpanID )
2019-09-25 08:12:22 +02:00
}
2021-03-09 18:17:29 +02:00
if span . SpanKind != sks [ span . SpanContext ( ) . SpanID ( ) ] {
t . Errorf ( "Expected finished span %d (span ID: %d) to have span.kind to be '%v' but was '%v'" , idx , sctx . SpanID ( ) , sks [ span . SpanContext ( ) . SpanID ( ) ] , span . SpanKind )
2019-10-24 01:25:14 +02:00
}
2019-09-25 08:12:22 +02:00
}
}
func reverse ( length int , swap func ( i , j int ) ) {
for left , right := 0 , length - 1 ; left < right ; left , right = left + 1 , right - 1 {
swap ( left , right )
}
}
2020-11-07 00:13:31 +02:00
func simpleTraceID ( ) trace . TraceID {
2019-10-23 08:01:33 +02:00
return [ 16 ] byte { 123 , 42 }
2019-09-25 08:12:22 +02:00
}
2020-11-07 00:13:31 +02:00
func simpleSpanIDs ( count int ) [ ] trace . SpanID {
base := [ ] trace . SpanID {
2019-10-28 19:05:06 +02:00
{ 123 } ,
{ 124 } ,
{ 125 } ,
{ 126 } ,
{ 127 } ,
{ 128 } ,
2019-09-25 08:12:22 +02:00
}
2019-10-28 19:05:06 +02:00
return base [ : count ]
2019-09-25 08:12:22 +02:00
}
func min ( a , b int ) int {
if a > b {
return b
}
return a
}
2020-03-10 19:32:01 +02:00
func runOtelOTOtel ( t * testing . T , ctx context . Context , name string , callback func ( * testing . T , context . Context ) context . Context ) {
2020-11-16 19:30:54 +02:00
tr := otel . Tracer ( "" )
2020-11-07 00:13:31 +02:00
ctx , span := tr . Start ( ctx , fmt . Sprintf ( "%s_Otel_OTOtel" , name ) , trace . WithSpanKind ( trace . SpanKindClient ) )
2019-09-27 19:48:10 +02:00
defer span . End ( )
2020-03-10 19:32:01 +02:00
ctx = callback ( t , ctx )
2019-09-25 08:12:22 +02:00
func ( ctx2 context . Context ) {
span , ctx2 := ot . StartSpanFromContext ( ctx2 , fmt . Sprintf ( "%sOtel_OT_Otel" , name ) )
defer span . Finish ( )
2020-03-10 19:32:01 +02:00
ctx2 = callback ( t , ctx2 )
2019-09-25 08:12:22 +02:00
func ( ctx3 context . Context ) {
2020-11-07 00:13:31 +02:00
ctx3 , span := tr . Start ( ctx3 , fmt . Sprintf ( "%sOtelOT_Otel_" , name ) , trace . WithSpanKind ( trace . SpanKindProducer ) )
2019-09-27 19:48:10 +02:00
defer span . End ( )
2020-03-10 19:32:01 +02:00
_ = callback ( t , ctx3 )
2019-09-25 08:12:22 +02:00
} ( ctx2 )
} ( ctx )
}
2020-03-10 19:32:01 +02:00
func runOTOtelOT ( t * testing . T , ctx context . Context , name string , callback func ( * testing . T , context . Context ) context . Context ) {
2020-11-16 19:30:54 +02:00
tr := otel . Tracer ( "" )
2019-10-24 01:25:14 +02:00
span , ctx := ot . StartSpanFromContext ( ctx , fmt . Sprintf ( "%s_OT_OtelOT" , name ) , ot . Tag { Key : "span.kind" , Value : "client" } )
2019-09-25 08:12:22 +02:00
defer span . Finish ( )
2020-03-10 19:32:01 +02:00
ctx = callback ( t , ctx )
2019-09-25 08:12:22 +02:00
func ( ctx2 context . Context ) {
2019-10-22 22:19:11 +02:00
ctx2 , span := tr . Start ( ctx2 , fmt . Sprintf ( "%sOT_Otel_OT" , name ) )
2019-09-27 19:48:10 +02:00
defer span . End ( )
2020-03-10 19:32:01 +02:00
ctx2 = callback ( t , ctx2 )
2019-09-25 08:12:22 +02:00
func ( ctx3 context . Context ) {
2019-10-24 01:25:14 +02:00
span , ctx3 := ot . StartSpanFromContext ( ctx3 , fmt . Sprintf ( "%sOTOtel_OT_" , name ) , ot . Tag { Key : "span.kind" , Value : "producer" } )
2019-09-25 08:12:22 +02:00
defer span . Finish ( )
2020-03-10 19:32:01 +02:00
_ = callback ( t , ctx3 )
2019-09-25 08:12:22 +02:00
} ( ctx2 )
} ( ctx )
}
2021-02-17 02:23:58 +02:00
2022-04-18 16:31:31 +02:00
func TestOtTagToOTelAttrCheckTypeConversions ( t * testing . T ) {
2021-02-17 02:23:58 +02:00
tableTest := [ ] struct {
key string
value interface { }
2021-02-18 19:59:37 +02:00
expectedValueType attribute . Type
2021-02-17 02:23:58 +02:00
} {
{
key : "bool to bool" ,
value : true ,
2021-02-18 19:59:37 +02:00
expectedValueType : attribute . BOOL ,
2021-02-17 02:23:58 +02:00
} ,
{
key : "int to int64" ,
value : 123 ,
2021-02-18 19:59:37 +02:00
expectedValueType : attribute . INT64 ,
2021-02-17 02:23:58 +02:00
} ,
{
key : "uint to string" ,
value : uint ( 1234 ) ,
2021-02-18 19:59:37 +02:00
expectedValueType : attribute . STRING ,
2021-02-17 02:23:58 +02:00
} ,
{
key : "int32 to int64" ,
value : int32 ( 12345 ) ,
2021-02-18 19:59:37 +02:00
expectedValueType : attribute . INT64 ,
2021-02-17 02:23:58 +02:00
} ,
{
key : "uint32 to int64" ,
value : uint32 ( 123456 ) ,
2021-02-18 19:59:37 +02:00
expectedValueType : attribute . INT64 ,
2021-02-17 02:23:58 +02:00
} ,
{
key : "int64 to int64" ,
value : int64 ( 1234567 ) ,
2021-02-18 19:59:37 +02:00
expectedValueType : attribute . INT64 ,
2021-02-17 02:23:58 +02:00
} ,
{
key : "uint64 to string" ,
value : uint64 ( 12345678 ) ,
2021-02-18 19:59:37 +02:00
expectedValueType : attribute . STRING ,
2021-02-17 02:23:58 +02:00
} ,
{
key : "float32 to float64" ,
value : float32 ( 3.14 ) ,
2021-02-18 19:59:37 +02:00
expectedValueType : attribute . FLOAT64 ,
2021-02-17 02:23:58 +02:00
} ,
{
key : "float64 to float64" ,
value : float64 ( 3.14 ) ,
2021-02-18 19:59:37 +02:00
expectedValueType : attribute . FLOAT64 ,
2021-02-17 02:23:58 +02:00
} ,
{
key : "string to string" ,
value : "string_value" ,
2021-02-18 19:59:37 +02:00
expectedValueType : attribute . STRING ,
2021-02-17 02:23:58 +02:00
} ,
{
key : "unexpected type to string" ,
value : struct { } { } ,
2021-02-18 19:59:37 +02:00
expectedValueType : attribute . STRING ,
2021-02-17 02:23:58 +02:00
} ,
}
for _ , test := range tableTest {
2022-04-18 16:31:31 +02:00
got := otTagToOTelAttr ( test . key , test . value )
2021-02-17 02:23:58 +02:00
if test . expectedValueType != got . Value . Type ( ) {
t . Errorf ( "Expected type %s, but got %s after conversion '%v' value" ,
test . expectedValueType ,
got . Value . Type ( ) ,
test . value )
}
}
}