Files
teleport/api/observability/tracing/client_test.go
T
rosstimothy ad1d9b1aae Prevent forwarding traces to servers which don't support tracing (#14281)
* Prevent forwarding traces to servers which don't support tracing

Tracing clients can detect if a server doesn't support tracing by
checking for a trace.NotImplented error in response to an
UploadTraces request. Since the grpc.Conn used by the client is
likely to be bound to that server for the duration of its life
it doesn't make sense to keep trying to forward traces. Instead
the client now remembers that a server doesn't support tracing
and will drop any spans.

Part of #12241
2022-07-11 21:09:32 +00:00

110 lines
3.0 KiB
Go

// Copyright 2022 Gravitational, Inc
//
// 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 tracing
import (
"context"
"testing"
"github.com/gravitational/trace"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
otlp "go.opentelemetry.io/proto/otlp/trace/v1"
)
var _ otlptrace.Client = (*mockClient)(nil)
type mockClient struct {
uploadError error
spans []*otlp.ResourceSpans
}
func (m mockClient) Start(ctx context.Context) error {
return nil
}
func (m mockClient) Stop(ctx context.Context) error {
return nil
}
func (m *mockClient) UploadTraces(ctx context.Context, protoSpans []*otlp.ResourceSpans) error {
m.spans = append(m.spans, protoSpans...)
return m.uploadError
}
func TestUploadTraces(t *testing.T) {
const (
spanCount = 10
uploadCount = 5
)
cases := []struct {
name string
client mockClient
spans []*otlp.ResourceSpans
errorAssertion require.ErrorAssertionFunc
spanAssertion require.ValueAssertionFunc
}{
{
name: "no spans to upload",
spans: make([]*otlp.ResourceSpans, 0, spanCount),
errorAssertion: require.NoError,
spanAssertion: require.Empty,
},
{
name: "successfully uploads spans",
spans: make([]*otlp.ResourceSpans, spanCount),
errorAssertion: require.NoError,
spanAssertion: func(t require.TestingT, i interface{}, i2 ...interface{}) {
require.NotEmpty(t, i, i2...)
require.Len(t, i, spanCount*uploadCount, i2...)
},
},
{
name: "error uploading spans",
spans: make([]*otlp.ResourceSpans, spanCount),
client: mockClient{uploadError: trace.ConnectionProblem(nil, "test")},
errorAssertion: require.Error,
spanAssertion: func(t require.TestingT, i interface{}, i2 ...interface{}) {
require.NotEmpty(t, i, i2...)
require.Len(t, i, spanCount*uploadCount, i2...)
},
},
{
name: "not implemented",
spans: make([]*otlp.ResourceSpans, spanCount),
client: mockClient{uploadError: trace.NotImplemented("test")},
errorAssertion: require.NoError,
spanAssertion: func(t require.TestingT, i interface{}, i2 ...interface{}) {
require.NotEmpty(t, i, i2...)
require.Len(t, i, spanCount, i2...)
},
},
}
for _, tt := range cases {
t.Run(tt.name, func(t *testing.T) {
client := &Client{
Client: &tt.client,
}
for i := 0; i < uploadCount; i++ {
tt.errorAssertion(t, client.UploadTraces(context.Background(), tt.spans))
}
tt.spanAssertion(t, tt.client.spans)
})
}
}