cloudflared-mirror/tracing/client_test.go

162 lines
5.0 KiB
Go

package tracing
import (
"context"
"testing"
"time"
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
semconv "go.opentelemetry.io/otel/semconv/v1.7.0"
"go.opentelemetry.io/otel/trace"
commonpb "go.opentelemetry.io/proto/otlp/common/v1"
resourcepb "go.opentelemetry.io/proto/otlp/resource/v1"
tracepb "go.opentelemetry.io/proto/otlp/trace/v1"
)
const (
resourceSchemaUrl = "http://example.com/custom-resource-schema"
instrumentSchemaUrl = semconv.SchemaURL
)
var (
traceId = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}
spanId = []byte{0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8}
parentSpanId = []byte{0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08}
startTime = time.Date(2022, 4, 4, 0, 0, 0, 0, time.UTC)
endTime = startTime.Add(5 * time.Second)
traceState, _ = trace.ParseTraceState("key1=val1,key2=val2")
instrScope = &commonpb.InstrumentationScope{Name: "go.opentelemetry.io/test/otel", Version: "v1.6.0"}
otlpKeyValues = []*commonpb.KeyValue{
{
Key: "string_key",
Value: &commonpb.AnyValue{
Value: &commonpb.AnyValue_StringValue{
StringValue: "string value",
},
},
},
{
Key: "bool_key",
Value: &commonpb.AnyValue{
Value: &commonpb.AnyValue_BoolValue{
BoolValue: true,
},
},
},
}
otlpResource = &resourcepb.Resource{
Attributes: []*commonpb.KeyValue{
{
Key: "service.name",
Value: &commonpb.AnyValue{
Value: &commonpb.AnyValue_StringValue{
StringValue: "service-name",
},
},
},
},
}
)
var _ otlptrace.Client = (*InMemoryOtlpClient)(nil)
var _ InMemoryClient = (*InMemoryOtlpClient)(nil)
var _ otlptrace.Client = (*NoopOtlpClient)(nil)
var _ InMemoryClient = (*NoopOtlpClient)(nil)
func TestUploadTraces(t *testing.T) {
client := &InMemoryOtlpClient{}
spans := createResourceSpans([]*tracepb.Span{createOtlpSpan(traceId)})
spans2 := createResourceSpans([]*tracepb.Span{createOtlpSpan(traceId)})
err := client.UploadTraces(context.Background(), spans)
assert.NoError(t, err)
err = client.UploadTraces(context.Background(), spans2)
assert.NoError(t, err)
assert.Len(t, client.spans, 2)
}
func TestSpans(t *testing.T) {
client := &InMemoryOtlpClient{}
spans := createResourceSpans([]*tracepb.Span{createOtlpSpan(traceId)})
err := client.UploadTraces(context.Background(), spans)
assert.NoError(t, err)
assert.Len(t, client.spans, 1)
enc, err := client.Spans()
assert.NoError(t, err)
expected := "CsECCiAKHgoMc2VydmljZS5uYW1lEg4KDHNlcnZpY2UtbmFtZRLxAQonCh1nby5vcGVudGVsZW1ldHJ5LmlvL3Rlc3Qvb3RlbBIGdjEuNi4wEp0BChAAAQIDBAUGBwgJCgsMDQ4PEgj//v38+/r5+BoTa2V5MT12YWwxLGtleTI9dmFsMiIIDw4NDAsKCQgqCnRyYWNlX25hbWUwATkAANJvaYjiFkEA8teZaojiFkocCgpzdHJpbmdfa2V5Eg4KDHN0cmluZyB2YWx1ZUoOCghib29sX2tleRICEAF6EhIOc3RhdHVzIG1lc3NhZ2UYARomaHR0cHM6Ly9vcGVudGVsZW1ldHJ5LmlvL3NjaGVtYXMvMS43LjAaKWh0dHA6Ly9leGFtcGxlLmNvbS9jdXN0b20tcmVzb3VyY2Utc2NoZW1h"
assert.Equal(t, expected, enc)
}
func TestSpansEmpty(t *testing.T) {
client := &InMemoryOtlpClient{}
err := client.UploadTraces(context.Background(), []*tracepb.ResourceSpans{})
assert.NoError(t, err)
assert.Len(t, client.spans, 0)
_, err = client.Spans()
assert.ErrorIs(t, err, errNoTraces)
}
func TestSpansNil(t *testing.T) {
client := &InMemoryOtlpClient{}
err := client.UploadTraces(context.Background(), nil)
assert.NoError(t, err)
assert.Len(t, client.spans, 0)
_, err = client.Spans()
assert.ErrorIs(t, err, errNoTraces)
}
func TestSpansTooManySpans(t *testing.T) {
client := &InMemoryOtlpClient{}
for i := 0; i < MaxTraceAmount+1; i++ {
spans := createResourceSpans([]*tracepb.Span{createOtlpSpan(traceId)})
err := client.UploadTraces(context.Background(), spans)
assert.NoError(t, err)
}
assert.Len(t, client.spans, MaxTraceAmount)
_, err := client.Spans()
assert.NoError(t, err)
}
func createResourceSpans(spans []*tracepb.Span) []*tracepb.ResourceSpans {
return []*tracepb.ResourceSpans{createResourceSpan(spans)}
}
func createResourceSpan(spans []*tracepb.Span) *tracepb.ResourceSpans {
return &tracepb.ResourceSpans{
Resource: otlpResource,
ScopeSpans: []*tracepb.ScopeSpans{
{
Scope: instrScope,
Spans: spans,
SchemaUrl: instrumentSchemaUrl,
},
},
InstrumentationLibrarySpans: nil,
SchemaUrl: resourceSchemaUrl,
}
}
func createOtlpSpan(tid []byte) *tracepb.Span {
return &tracepb.Span{
TraceId: tid,
SpanId: spanId,
TraceState: traceState.String(),
ParentSpanId: parentSpanId,
Name: "trace_name",
Kind: tracepb.Span_SPAN_KIND_INTERNAL,
StartTimeUnixNano: uint64(startTime.UnixNano()),
EndTimeUnixNano: uint64(endTime.UnixNano()),
Attributes: otlpKeyValues,
DroppedAttributesCount: 0,
Events: nil,
DroppedEventsCount: 0,
Links: nil,
DroppedLinksCount: 0,
Status: &tracepb.Status{
Message: "status message",
Code: tracepb.Status_STATUS_CODE_OK,
},
}
}