mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2024-12-12 10:04:29 +02:00
5568a30723
* Add semconv/v1.12.0 * Update all semconv use to v1.12.0 Co-authored-by: Aaron Clawson <3766680+MadVikingGod@users.noreply.github.com>
724 lines
19 KiB
Go
724 lines
19 KiB
Go
// Copyright The OpenTelemetry Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package jaeger
|
|
|
|
import (
|
|
"context"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"os"
|
|
"sort"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"go.opentelemetry.io/otel/attribute"
|
|
"go.opentelemetry.io/otel/codes"
|
|
gen "go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/jaeger"
|
|
ottest "go.opentelemetry.io/otel/internal/internaltest"
|
|
"go.opentelemetry.io/otel/sdk/instrumentation"
|
|
"go.opentelemetry.io/otel/sdk/resource"
|
|
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
|
"go.opentelemetry.io/otel/sdk/trace/tracetest"
|
|
semconv "go.opentelemetry.io/otel/semconv/v1.12.0"
|
|
"go.opentelemetry.io/otel/trace"
|
|
)
|
|
|
|
func TestNewRawExporter(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
endpoint EndpointOption
|
|
}{
|
|
{
|
|
name: "default exporter with collector endpoint",
|
|
endpoint: WithCollectorEndpoint(),
|
|
},
|
|
{
|
|
name: "default exporter with agent endpoint",
|
|
endpoint: WithAgentEndpoint(),
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
_, err := New(tc.endpoint)
|
|
assert.NoError(t, err)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNewRawExporterUseEnvVarIfOptionUnset(t *testing.T) {
|
|
// Record and restore env
|
|
envStore := ottest.NewEnvStore()
|
|
envStore.Record(envEndpoint)
|
|
defer func() {
|
|
require.NoError(t, envStore.Restore())
|
|
}()
|
|
|
|
// If the user sets the environment variable OTEL_EXPORTER_JAEGER_ENDPOINT, endpoint will always get a value.
|
|
require.NoError(t, os.Unsetenv(envEndpoint))
|
|
_, err := New(
|
|
WithCollectorEndpoint(),
|
|
)
|
|
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
type testCollectorEndpoint struct {
|
|
batchesUploaded []*gen.Batch
|
|
}
|
|
|
|
func (c *testCollectorEndpoint) shutdown(context.Context) error {
|
|
return nil
|
|
}
|
|
|
|
func (c *testCollectorEndpoint) upload(_ context.Context, batch *gen.Batch) error {
|
|
c.batchesUploaded = append(c.batchesUploaded, batch)
|
|
return nil
|
|
}
|
|
|
|
var _ batchUploader = (*testCollectorEndpoint)(nil)
|
|
|
|
func withTestCollectorEndpoint() EndpointOption {
|
|
return endpointOptionFunc(func() (batchUploader, error) {
|
|
return &testCollectorEndpoint{}, nil
|
|
})
|
|
}
|
|
|
|
func withTestCollectorEndpointInjected(ce *testCollectorEndpoint) EndpointOption {
|
|
return endpointOptionFunc(func() (batchUploader, error) {
|
|
return ce, nil
|
|
})
|
|
}
|
|
|
|
func TestExporterExportSpan(t *testing.T) {
|
|
const (
|
|
serviceName = "test-service"
|
|
tagKey = "key"
|
|
tagVal = "val"
|
|
)
|
|
|
|
testCollector := &testCollectorEndpoint{}
|
|
exp, err := New(withTestCollectorEndpointInjected(testCollector))
|
|
require.NoError(t, err)
|
|
tp := sdktrace.NewTracerProvider(
|
|
sdktrace.WithBatcher(exp),
|
|
sdktrace.WithResource(resource.NewSchemaless(
|
|
semconv.ServiceNameKey.String(serviceName),
|
|
attribute.String(tagKey, tagVal),
|
|
)),
|
|
)
|
|
|
|
tracer := tp.Tracer("test-tracer")
|
|
|
|
ctx := context.Background()
|
|
for i := 0; i < 3; i++ {
|
|
_, span := tracer.Start(ctx, fmt.Sprintf("test-span-%d", i))
|
|
span.End()
|
|
assert.True(t, span.SpanContext().IsValid())
|
|
}
|
|
|
|
require.NoError(t, tp.Shutdown(ctx))
|
|
|
|
batchesUploaded := testCollector.batchesUploaded
|
|
require.Len(t, batchesUploaded, 1)
|
|
uploadedBatch := batchesUploaded[0]
|
|
assert.Equal(t, serviceName, uploadedBatch.GetProcess().GetServiceName())
|
|
assert.Len(t, uploadedBatch.GetSpans(), 3)
|
|
|
|
require.Len(t, uploadedBatch.GetProcess().GetTags(), 1)
|
|
assert.Equal(t, tagKey, uploadedBatch.GetProcess().GetTags()[0].GetKey())
|
|
assert.Equal(t, tagVal, uploadedBatch.GetProcess().GetTags()[0].GetVStr())
|
|
}
|
|
|
|
func TestSpanSnapshotToThrift(t *testing.T) {
|
|
now := time.Now()
|
|
traceID, _ := trace.TraceIDFromHex("0102030405060708090a0b0c0d0e0f10")
|
|
spanID, _ := trace.SpanIDFromHex("0102030405060708")
|
|
parentSpanID, _ := trace.SpanIDFromHex("0807060504030201")
|
|
|
|
linkTraceID, _ := trace.TraceIDFromHex("0102030405060709090a0b0c0d0e0f11")
|
|
linkSpanID, _ := trace.SpanIDFromHex("0102030405060709")
|
|
|
|
eventNameValue := "event-test"
|
|
eventDropped := int64(10)
|
|
keyValue := "value"
|
|
statusCodeValue := "ERROR"
|
|
doubleValue := 123.456
|
|
intValue := int64(123)
|
|
boolTrue := true
|
|
arrValue := "[0,1,2,3]"
|
|
statusMessage := "this is a problem"
|
|
spanKind := "client"
|
|
rv1 := "rv11"
|
|
rv2 := int64(5)
|
|
instrLibName := "instrumentation-library"
|
|
instrLibVersion := "semver:1.0.0"
|
|
|
|
tests := []struct {
|
|
name string
|
|
data tracetest.SpanStub
|
|
want *gen.Span
|
|
}{
|
|
{
|
|
name: "no status description",
|
|
data: tracetest.SpanStub{
|
|
SpanContext: trace.NewSpanContext(trace.SpanContextConfig{
|
|
TraceID: traceID,
|
|
SpanID: spanID,
|
|
}),
|
|
Name: "/foo",
|
|
StartTime: now,
|
|
EndTime: now,
|
|
Status: sdktrace.Status{Code: codes.Error},
|
|
SpanKind: trace.SpanKindClient,
|
|
InstrumentationLibrary: instrumentation.Library{
|
|
Name: instrLibName,
|
|
Version: instrLibVersion,
|
|
},
|
|
},
|
|
want: &gen.Span{
|
|
TraceIdLow: 651345242494996240,
|
|
TraceIdHigh: 72623859790382856,
|
|
SpanId: 72623859790382856,
|
|
OperationName: "/foo",
|
|
StartTime: now.UnixNano() / 1000,
|
|
Duration: 0,
|
|
Tags: []*gen.Tag{
|
|
{Key: keyError, VType: gen.TagType_BOOL, VBool: &boolTrue},
|
|
{Key: keyInstrumentationLibraryName, VType: gen.TagType_STRING, VStr: &instrLibName},
|
|
{Key: keyInstrumentationLibraryVersion, VType: gen.TagType_STRING, VStr: &instrLibVersion},
|
|
{Key: keyStatusCode, VType: gen.TagType_STRING, VStr: &statusCodeValue},
|
|
// Should not have a status message because it was unset
|
|
{Key: keySpanKind, VType: gen.TagType_STRING, VStr: &spanKind},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "no parent",
|
|
data: tracetest.SpanStub{
|
|
SpanContext: trace.NewSpanContext(trace.SpanContextConfig{
|
|
TraceID: traceID,
|
|
SpanID: spanID,
|
|
}),
|
|
Name: "/foo",
|
|
StartTime: now,
|
|
EndTime: now,
|
|
Links: []sdktrace.Link{
|
|
{
|
|
SpanContext: trace.NewSpanContext(trace.SpanContextConfig{
|
|
TraceID: linkTraceID,
|
|
SpanID: linkSpanID,
|
|
}),
|
|
},
|
|
},
|
|
Attributes: []attribute.KeyValue{
|
|
attribute.String("key", keyValue),
|
|
attribute.Float64("double", doubleValue),
|
|
attribute.Int64("int", intValue),
|
|
},
|
|
Events: []sdktrace.Event{
|
|
{
|
|
Name: eventNameValue,
|
|
Attributes: []attribute.KeyValue{attribute.String("k1", keyValue)},
|
|
DroppedAttributeCount: int(eventDropped),
|
|
Time: now,
|
|
},
|
|
},
|
|
Status: sdktrace.Status{
|
|
Code: codes.Error,
|
|
Description: statusMessage,
|
|
},
|
|
SpanKind: trace.SpanKindClient,
|
|
InstrumentationLibrary: instrumentation.Library{
|
|
Name: instrLibName,
|
|
Version: instrLibVersion,
|
|
},
|
|
},
|
|
want: &gen.Span{
|
|
TraceIdLow: 651345242494996240,
|
|
TraceIdHigh: 72623859790382856,
|
|
SpanId: 72623859790382856,
|
|
OperationName: "/foo",
|
|
StartTime: now.UnixNano() / 1000,
|
|
Duration: 0,
|
|
Tags: []*gen.Tag{
|
|
{Key: "double", VType: gen.TagType_DOUBLE, VDouble: &doubleValue},
|
|
{Key: "key", VType: gen.TagType_STRING, VStr: &keyValue},
|
|
{Key: "int", VType: gen.TagType_LONG, VLong: &intValue},
|
|
{Key: keyError, VType: gen.TagType_BOOL, VBool: &boolTrue},
|
|
{Key: keyInstrumentationLibraryName, VType: gen.TagType_STRING, VStr: &instrLibName},
|
|
{Key: keyInstrumentationLibraryVersion, VType: gen.TagType_STRING, VStr: &instrLibVersion},
|
|
{Key: keyStatusCode, VType: gen.TagType_STRING, VStr: &statusCodeValue},
|
|
{Key: keyStatusMessage, VType: gen.TagType_STRING, VStr: &statusMessage},
|
|
{Key: keySpanKind, VType: gen.TagType_STRING, VStr: &spanKind},
|
|
},
|
|
References: []*gen.SpanRef{
|
|
{
|
|
RefType: gen.SpanRefType_FOLLOWS_FROM,
|
|
TraceIdHigh: int64(binary.BigEndian.Uint64(linkTraceID[0:8])),
|
|
TraceIdLow: int64(binary.BigEndian.Uint64(linkTraceID[8:16])),
|
|
SpanId: int64(binary.BigEndian.Uint64(linkSpanID[:])),
|
|
},
|
|
},
|
|
Logs: []*gen.Log{
|
|
{
|
|
Timestamp: now.UnixNano() / 1000,
|
|
Fields: []*gen.Tag{
|
|
{
|
|
Key: keyEventName,
|
|
VStr: &eventNameValue,
|
|
VType: gen.TagType_STRING,
|
|
},
|
|
{
|
|
Key: "k1",
|
|
VStr: &keyValue,
|
|
VType: gen.TagType_STRING,
|
|
},
|
|
{
|
|
Key: keyDroppedAttributeCount,
|
|
VLong: &eventDropped,
|
|
VType: gen.TagType_LONG,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "with parent",
|
|
data: tracetest.SpanStub{
|
|
SpanContext: trace.NewSpanContext(trace.SpanContextConfig{
|
|
TraceID: traceID,
|
|
SpanID: spanID,
|
|
}),
|
|
Parent: trace.NewSpanContext(trace.SpanContextConfig{
|
|
TraceID: traceID,
|
|
SpanID: parentSpanID,
|
|
}),
|
|
Links: []sdktrace.Link{
|
|
{
|
|
SpanContext: trace.NewSpanContext(trace.SpanContextConfig{
|
|
TraceID: linkTraceID,
|
|
SpanID: linkSpanID,
|
|
}),
|
|
},
|
|
},
|
|
Name: "/foo",
|
|
StartTime: now,
|
|
EndTime: now,
|
|
Attributes: []attribute.KeyValue{
|
|
attribute.IntSlice("arr", []int{0, 1, 2, 3}),
|
|
},
|
|
Status: sdktrace.Status{
|
|
Code: codes.Unset,
|
|
Description: statusMessage,
|
|
},
|
|
SpanKind: trace.SpanKindInternal,
|
|
InstrumentationLibrary: instrumentation.Library{
|
|
Name: instrLibName,
|
|
Version: instrLibVersion,
|
|
},
|
|
},
|
|
want: &gen.Span{
|
|
TraceIdLow: 651345242494996240,
|
|
TraceIdHigh: 72623859790382856,
|
|
SpanId: 72623859790382856,
|
|
ParentSpanId: 578437695752307201,
|
|
OperationName: "/foo",
|
|
StartTime: now.UnixNano() / 1000,
|
|
Duration: 0,
|
|
Tags: []*gen.Tag{
|
|
// status code, message and span kind should NOT be populated
|
|
{Key: "arr", VType: gen.TagType_STRING, VStr: &arrValue},
|
|
{Key: keyInstrumentationLibraryName, VType: gen.TagType_STRING, VStr: &instrLibName},
|
|
{Key: keyInstrumentationLibraryVersion, VType: gen.TagType_STRING, VStr: &instrLibVersion},
|
|
},
|
|
References: []*gen.SpanRef{
|
|
{
|
|
RefType: gen.SpanRefType_FOLLOWS_FROM,
|
|
TraceIdHigh: int64(binary.BigEndian.Uint64(linkTraceID[0:8])),
|
|
TraceIdLow: int64(binary.BigEndian.Uint64(linkTraceID[8:16])),
|
|
SpanId: int64(binary.BigEndian.Uint64(linkSpanID[:])),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "resources do not affect the tags",
|
|
data: tracetest.SpanStub{
|
|
SpanContext: trace.NewSpanContext(trace.SpanContextConfig{
|
|
TraceID: traceID,
|
|
SpanID: spanID,
|
|
}),
|
|
Parent: trace.NewSpanContext(trace.SpanContextConfig{
|
|
TraceID: traceID,
|
|
SpanID: parentSpanID,
|
|
}),
|
|
Name: "/foo",
|
|
StartTime: now,
|
|
EndTime: now,
|
|
Resource: resource.NewSchemaless(
|
|
attribute.String("rk1", rv1),
|
|
attribute.Int64("rk2", rv2),
|
|
semconv.ServiceNameKey.String("service name"),
|
|
),
|
|
Status: sdktrace.Status{
|
|
Code: codes.Unset,
|
|
Description: statusMessage,
|
|
},
|
|
SpanKind: trace.SpanKindInternal,
|
|
InstrumentationLibrary: instrumentation.Library{
|
|
Name: instrLibName,
|
|
Version: instrLibVersion,
|
|
},
|
|
},
|
|
want: &gen.Span{
|
|
TraceIdLow: 651345242494996240,
|
|
TraceIdHigh: 72623859790382856,
|
|
SpanId: 72623859790382856,
|
|
ParentSpanId: 578437695752307201,
|
|
OperationName: "/foo",
|
|
StartTime: now.UnixNano() / 1000,
|
|
Duration: 0,
|
|
Tags: []*gen.Tag{
|
|
{Key: keyInstrumentationLibraryName, VType: gen.TagType_STRING, VStr: &instrLibName},
|
|
{Key: keyInstrumentationLibraryVersion, VType: gen.TagType_STRING, VStr: &instrLibVersion},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := spanToThrift(tt.data.Snapshot())
|
|
sort.Slice(got.Tags, func(i, j int) bool {
|
|
return got.Tags[i].Key < got.Tags[j].Key
|
|
})
|
|
sort.Slice(tt.want.Tags, func(i, j int) bool {
|
|
return tt.want.Tags[i].Key < tt.want.Tags[j].Key
|
|
})
|
|
if diff := cmp.Diff(got, tt.want); diff != "" {
|
|
t.Errorf("Diff%v", diff)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestExporterShutdownHonorsCancel(t *testing.T) {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel()
|
|
|
|
e, err := New(withTestCollectorEndpoint())
|
|
require.NoError(t, err)
|
|
assert.EqualError(t, e.Shutdown(ctx), context.Canceled.Error())
|
|
}
|
|
|
|
func TestExporterShutdownHonorsTimeout(t *testing.T) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Nanosecond)
|
|
<-ctx.Done()
|
|
|
|
e, err := New(withTestCollectorEndpoint())
|
|
require.NoError(t, err)
|
|
assert.EqualError(t, e.Shutdown(ctx), context.DeadlineExceeded.Error())
|
|
cancel()
|
|
}
|
|
|
|
func TestErrorOnExportShutdownExporter(t *testing.T) {
|
|
e, err := New(withTestCollectorEndpoint())
|
|
require.NoError(t, err)
|
|
assert.NoError(t, e.Shutdown(context.Background()))
|
|
assert.NoError(t, e.ExportSpans(context.Background(), nil))
|
|
}
|
|
|
|
func TestExporterExportSpansHonorsCancel(t *testing.T) {
|
|
e, err := New(withTestCollectorEndpoint())
|
|
require.NoError(t, err)
|
|
now := time.Now()
|
|
ss := tracetest.SpanStubs{
|
|
{
|
|
Name: "s1",
|
|
Resource: resource.NewSchemaless(
|
|
semconv.ServiceNameKey.String("name"),
|
|
attribute.Key("r1").String("v1"),
|
|
),
|
|
StartTime: now,
|
|
EndTime: now,
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Resource: resource.NewSchemaless(
|
|
semconv.ServiceNameKey.String("name"),
|
|
attribute.Key("r2").String("v2"),
|
|
),
|
|
StartTime: now,
|
|
EndTime: now,
|
|
},
|
|
}
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel()
|
|
|
|
assert.EqualError(t, e.ExportSpans(ctx, ss.Snapshots()), context.Canceled.Error())
|
|
}
|
|
|
|
func TestExporterExportSpansHonorsTimeout(t *testing.T) {
|
|
e, err := New(withTestCollectorEndpoint())
|
|
require.NoError(t, err)
|
|
now := time.Now()
|
|
ss := tracetest.SpanStubs{
|
|
{
|
|
Name: "s1",
|
|
Resource: resource.NewSchemaless(
|
|
semconv.ServiceNameKey.String("name"),
|
|
attribute.Key("r1").String("v1"),
|
|
),
|
|
StartTime: now,
|
|
EndTime: now,
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Resource: resource.NewSchemaless(
|
|
semconv.ServiceNameKey.String("name"),
|
|
attribute.Key("r2").String("v2"),
|
|
),
|
|
StartTime: now,
|
|
EndTime: now,
|
|
},
|
|
}
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Nanosecond)
|
|
defer cancel()
|
|
<-ctx.Done()
|
|
|
|
assert.EqualError(t, e.ExportSpans(ctx, ss.Snapshots()), context.DeadlineExceeded.Error())
|
|
}
|
|
|
|
func TestJaegerBatchList(t *testing.T) {
|
|
newString := func(value string) *string {
|
|
return &value
|
|
}
|
|
spanKind := "unspecified"
|
|
now := time.Now()
|
|
|
|
testCases := []struct {
|
|
name string
|
|
roSpans []sdktrace.ReadOnlySpan
|
|
defaultServiceName string
|
|
expectedBatchList []*gen.Batch
|
|
}{
|
|
{
|
|
name: "no span shots",
|
|
roSpans: nil,
|
|
expectedBatchList: nil,
|
|
},
|
|
{
|
|
name: "span's snapshot contains nil span",
|
|
roSpans: []sdktrace.ReadOnlySpan{
|
|
tracetest.SpanStub{
|
|
Name: "s1",
|
|
Resource: resource.NewSchemaless(
|
|
semconv.ServiceNameKey.String("name"),
|
|
attribute.Key("r1").String("v1"),
|
|
),
|
|
StartTime: now,
|
|
EndTime: now,
|
|
}.Snapshot(),
|
|
nil,
|
|
},
|
|
expectedBatchList: []*gen.Batch{
|
|
{
|
|
Process: &gen.Process{
|
|
ServiceName: "name",
|
|
Tags: []*gen.Tag{
|
|
{Key: "r1", VType: gen.TagType_STRING, VStr: newString("v1")},
|
|
},
|
|
},
|
|
Spans: []*gen.Span{
|
|
{
|
|
OperationName: "s1",
|
|
Tags: []*gen.Tag{
|
|
{Key: keySpanKind, VType: gen.TagType_STRING, VStr: &spanKind},
|
|
},
|
|
StartTime: now.UnixNano() / 1000,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "merge spans that have the same resources",
|
|
roSpans: tracetest.SpanStubs{
|
|
{
|
|
Name: "s1",
|
|
Resource: resource.NewSchemaless(
|
|
semconv.ServiceNameKey.String("name"),
|
|
attribute.Key("r1").String("v1"),
|
|
),
|
|
StartTime: now,
|
|
EndTime: now,
|
|
},
|
|
{
|
|
Name: "s2",
|
|
Resource: resource.NewSchemaless(
|
|
semconv.ServiceNameKey.String("name"),
|
|
attribute.Key("r1").String("v1"),
|
|
),
|
|
StartTime: now,
|
|
EndTime: now,
|
|
},
|
|
{
|
|
Name: "s3",
|
|
Resource: resource.NewSchemaless(
|
|
semconv.ServiceNameKey.String("name"),
|
|
attribute.Key("r2").String("v2"),
|
|
),
|
|
StartTime: now,
|
|
EndTime: now,
|
|
},
|
|
}.Snapshots(),
|
|
expectedBatchList: []*gen.Batch{
|
|
{
|
|
Process: &gen.Process{
|
|
ServiceName: "name",
|
|
Tags: []*gen.Tag{
|
|
{Key: "r1", VType: gen.TagType_STRING, VStr: newString("v1")},
|
|
},
|
|
},
|
|
Spans: []*gen.Span{
|
|
{
|
|
OperationName: "s1",
|
|
Tags: []*gen.Tag{
|
|
{Key: "span.kind", VType: gen.TagType_STRING, VStr: &spanKind},
|
|
},
|
|
StartTime: now.UnixNano() / 1000,
|
|
},
|
|
{
|
|
OperationName: "s2",
|
|
Tags: []*gen.Tag{
|
|
{Key: "span.kind", VType: gen.TagType_STRING, VStr: &spanKind},
|
|
},
|
|
StartTime: now.UnixNano() / 1000,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Process: &gen.Process{
|
|
ServiceName: "name",
|
|
Tags: []*gen.Tag{
|
|
{Key: "r2", VType: gen.TagType_STRING, VStr: newString("v2")},
|
|
},
|
|
},
|
|
Spans: []*gen.Span{
|
|
{
|
|
OperationName: "s3",
|
|
Tags: []*gen.Tag{
|
|
{Key: "span.kind", VType: gen.TagType_STRING, VStr: &spanKind},
|
|
},
|
|
StartTime: now.UnixNano() / 1000,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "no service name in spans",
|
|
roSpans: tracetest.SpanStubs{
|
|
{
|
|
Name: "s1",
|
|
Resource: resource.NewSchemaless(
|
|
attribute.Key("r1").String("v1"),
|
|
),
|
|
StartTime: now,
|
|
EndTime: now,
|
|
},
|
|
}.Snapshots(),
|
|
defaultServiceName: "default service name",
|
|
expectedBatchList: []*gen.Batch{
|
|
{
|
|
Process: &gen.Process{
|
|
ServiceName: "default service name",
|
|
Tags: []*gen.Tag{
|
|
{Key: "r1", VType: gen.TagType_STRING, VStr: newString("v1")},
|
|
},
|
|
},
|
|
Spans: []*gen.Span{
|
|
{
|
|
OperationName: "s1",
|
|
Tags: []*gen.Tag{
|
|
{Key: "span.kind", VType: gen.TagType_STRING, VStr: &spanKind},
|
|
},
|
|
StartTime: now.UnixNano() / 1000,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
batchList := jaegerBatchList(tc.roSpans, tc.defaultServiceName)
|
|
|
|
assert.ElementsMatch(t, tc.expectedBatchList, batchList)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestProcess(t *testing.T) {
|
|
v1 := "v1"
|
|
|
|
testCases := []struct {
|
|
name string
|
|
res *resource.Resource
|
|
defaultServiceName string
|
|
expectedProcess *gen.Process
|
|
}{
|
|
{
|
|
name: "resources contain service name",
|
|
res: resource.NewSchemaless(
|
|
semconv.ServiceNameKey.String("service name"),
|
|
attribute.Key("r1").String("v1"),
|
|
),
|
|
defaultServiceName: "default service name",
|
|
expectedProcess: &gen.Process{
|
|
ServiceName: "service name",
|
|
Tags: []*gen.Tag{
|
|
{Key: "r1", VType: gen.TagType_STRING, VStr: &v1},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "resources don't have service name",
|
|
res: resource.NewSchemaless(attribute.Key("r1").String("v1")),
|
|
defaultServiceName: "default service name",
|
|
expectedProcess: &gen.Process{
|
|
ServiceName: "default service name",
|
|
Tags: []*gen.Tag{
|
|
{Key: "r1", VType: gen.TagType_STRING, VStr: &v1},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
pro := process(tc.res, tc.defaultServiceName)
|
|
|
|
assert.Equal(t, tc.expectedProcess, pro)
|
|
})
|
|
}
|
|
}
|