Skip to content

Commit fa9121a

Browse files
committed
chore: remove unused vars (componentKey and serviceKey
1 parent e9f4032 commit fa9121a

File tree

2 files changed

+410
-0
lines changed

2 files changed

+410
-0
lines changed
Lines changed: 372 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,372 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package test
5+
6+
import (
7+
"context"
8+
"math/rand"
9+
"net"
10+
"reflect"
11+
"sync"
12+
"testing"
13+
"time"
14+
15+
otgrpc "github.com/opentracing-contrib/go-grpc"
16+
testpb "github.com/opentracing-contrib/go-grpc/test/otgrpc_testing"
17+
ot "github.com/opentracing/opentracing-go"
18+
"github.com/stretchr/testify/assert"
19+
"github.com/stretchr/testify/require"
20+
"google.golang.org/grpc"
21+
"google.golang.org/grpc/credentials/insecure"
22+
23+
"go.opentelemetry.io/otel/attribute"
24+
ototel "go.opentelemetry.io/otel/bridge/opentracing"
25+
"go.opentelemetry.io/otel/bridge/opentracing/migration"
26+
"go.opentelemetry.io/otel/codes"
27+
"go.opentelemetry.io/otel/propagation"
28+
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
29+
"go.opentelemetry.io/otel/trace"
30+
"go.opentelemetry.io/otel/trace/embedded"
31+
"go.opentelemetry.io/otel/trace/noop"
32+
)
33+
34+
type testGRPCServer struct{}
35+
36+
var (
37+
statusCodeKey = attribute.Key("status.code")
38+
statusMessageKey = attribute.Key("status.message")
39+
errorKey = attribute.Key("error")
40+
nameKey = attribute.Key("name")
41+
)
42+
43+
type mockContextKeyValue struct {
44+
Key any
45+
Value any
46+
}
47+
48+
type mockTracer struct {
49+
embedded.Tracer
50+
51+
FinishedSpans []*mockSpan
52+
SpareTraceIDs []trace.TraceID
53+
SpareSpanIDs []trace.SpanID
54+
SpareContextKeyValues []mockContextKeyValue
55+
TraceFlags trace.TraceFlags
56+
57+
randLock sync.Mutex
58+
rand *rand.Rand
59+
}
60+
61+
func newMockTracer() *mockTracer {
62+
return &mockTracer{
63+
FinishedSpans: nil,
64+
SpareTraceIDs: nil,
65+
SpareSpanIDs: nil,
66+
SpareContextKeyValues: nil,
67+
68+
rand: rand.New(rand.NewSource(time.Now().Unix())),
69+
}
70+
}
71+
72+
func (t *mockTracer) Start(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) {
73+
config := trace.NewSpanStartConfig(opts...)
74+
startTime := config.Timestamp()
75+
if startTime.IsZero() {
76+
startTime = time.Now()
77+
}
78+
spanContext := trace.NewSpanContext(trace.SpanContextConfig{
79+
TraceID: t.getTraceID(ctx, &config),
80+
SpanID: t.getSpanID(),
81+
TraceFlags: t.TraceFlags,
82+
})
83+
span := &mockSpan{
84+
mockTracer: t,
85+
officialTracer: t,
86+
spanContext: spanContext,
87+
Attributes: config.Attributes(),
88+
StartTime: startTime,
89+
EndTime: time.Time{},
90+
ParentSpanID: t.getParentSpanID(ctx, &config),
91+
Events: nil,
92+
SpanKind: trace.ValidateSpanKind(config.SpanKind()),
93+
}
94+
if !migration.SkipContextSetup(ctx) {
95+
ctx = trace.ContextWithSpan(ctx, span)
96+
ctx = t.addSpareContextValue(ctx)
97+
}
98+
return ctx, span
99+
}
100+
101+
func (t *mockTracer) addSpareContextValue(ctx context.Context) context.Context {
102+
if len(t.SpareContextKeyValues) > 0 {
103+
pair := t.SpareContextKeyValues[0]
104+
t.SpareContextKeyValues[0] = mockContextKeyValue{}
105+
t.SpareContextKeyValues = t.SpareContextKeyValues[1:]
106+
if len(t.SpareContextKeyValues) == 0 {
107+
t.SpareContextKeyValues = nil
108+
}
109+
ctx = context.WithValue(ctx, pair.Key, pair.Value)
110+
}
111+
return ctx
112+
}
113+
114+
func (t *mockTracer) getTraceID(ctx context.Context, config *trace.SpanConfig) trace.TraceID {
115+
if parent := t.getParentSpanContext(ctx, config); parent.IsValid() {
116+
return parent.TraceID()
117+
}
118+
if len(t.SpareTraceIDs) > 0 {
119+
traceID := t.SpareTraceIDs[0]
120+
t.SpareTraceIDs = t.SpareTraceIDs[1:]
121+
if len(t.SpareTraceIDs) == 0 {
122+
t.SpareTraceIDs = nil
123+
}
124+
return traceID
125+
}
126+
return t.getRandTraceID()
127+
}
128+
129+
func (t *mockTracer) getParentSpanID(ctx context.Context, config *trace.SpanConfig) trace.SpanID {
130+
if parent := t.getParentSpanContext(ctx, config); parent.IsValid() {
131+
return parent.SpanID()
132+
}
133+
return trace.SpanID{}
134+
}
135+
136+
func (t *mockTracer) getParentSpanContext(ctx context.Context, config *trace.SpanConfig) trace.SpanContext {
137+
if !config.NewRoot() {
138+
return trace.SpanContextFromContext(ctx)
139+
}
140+
return trace.SpanContext{}
141+
}
142+
143+
func (t *mockTracer) getSpanID() trace.SpanID {
144+
if len(t.SpareSpanIDs) > 0 {
145+
spanID := t.SpareSpanIDs[0]
146+
t.SpareSpanIDs = t.SpareSpanIDs[1:]
147+
if len(t.SpareSpanIDs) == 0 {
148+
t.SpareSpanIDs = nil
149+
}
150+
return spanID
151+
}
152+
return t.getRandSpanID()
153+
}
154+
155+
func (t *mockTracer) getRandSpanID() trace.SpanID {
156+
t.randLock.Lock()
157+
defer t.randLock.Unlock()
158+
159+
sid := trace.SpanID{}
160+
_, _ = t.rand.Read(sid[:])
161+
162+
return sid
163+
}
164+
165+
func (t *mockTracer) getRandTraceID() trace.TraceID {
166+
t.randLock.Lock()
167+
defer t.randLock.Unlock()
168+
169+
tid := trace.TraceID{}
170+
_, _ = t.rand.Read(tid[:])
171+
172+
return tid
173+
}
174+
175+
func (t *mockTracer) DeferredContextSetupHook(ctx context.Context, span trace.Span) context.Context {
176+
return t.addSpareContextValue(ctx)
177+
}
178+
179+
type mockEvent struct {
180+
Timestamp time.Time
181+
Name string
182+
Attributes []attribute.KeyValue
183+
}
184+
185+
type mockLink struct {
186+
SpanContext trace.SpanContext
187+
Attributes []attribute.KeyValue
188+
}
189+
190+
type mockSpan struct {
191+
embedded.Span
192+
193+
mockTracer *mockTracer
194+
officialTracer trace.Tracer
195+
spanContext trace.SpanContext
196+
SpanKind trace.SpanKind
197+
recording bool
198+
199+
Attributes []attribute.KeyValue
200+
StartTime time.Time
201+
EndTime time.Time
202+
ParentSpanID trace.SpanID
203+
Events []mockEvent
204+
Links []mockLink
205+
}
206+
207+
func (s *mockSpan) SpanContext() trace.SpanContext {
208+
return s.spanContext
209+
}
210+
211+
func (s *mockSpan) IsRecording() bool {
212+
return s.recording
213+
}
214+
215+
func (s *mockSpan) SetStatus(code codes.Code, msg string) {
216+
s.SetAttributes(statusCodeKey.Int(int(code)), statusMessageKey.String(msg))
217+
}
218+
219+
func (s *mockSpan) SetName(name string) {
220+
s.SetAttributes(nameKey.String(name))
221+
}
222+
223+
func (s *mockSpan) SetError(v bool) {
224+
s.SetAttributes(errorKey.Bool(v))
225+
}
226+
227+
func (s *mockSpan) SetAttributes(attributes ...attribute.KeyValue) {
228+
s.applyUpdate(attributes)
229+
}
230+
231+
func (s *mockSpan) applyUpdate(update []attribute.KeyValue) {
232+
updateM := make(map[attribute.Key]attribute.Value, len(update))
233+
for _, kv := range update {
234+
updateM[kv.Key] = kv.Value
235+
}
236+
237+
seen := make(map[attribute.Key]struct{})
238+
for i, kv := range s.Attributes {
239+
if v, ok := updateM[kv.Key]; ok {
240+
s.Attributes[i].Value = v
241+
seen[kv.Key] = struct{}{}
242+
}
243+
}
244+
245+
for k, v := range updateM {
246+
if _, ok := seen[k]; ok {
247+
continue
248+
}
249+
s.Attributes = append(s.Attributes, attribute.KeyValue{Key: k, Value: v})
250+
}
251+
}
252+
253+
func (s *mockSpan) End(options ...trace.SpanEndOption) {
254+
if !s.EndTime.IsZero() {
255+
return // already finished
256+
}
257+
config := trace.NewSpanEndConfig(options...)
258+
endTime := config.Timestamp()
259+
if endTime.IsZero() {
260+
endTime = time.Now()
261+
}
262+
s.EndTime = endTime
263+
s.mockTracer.FinishedSpans = append(s.mockTracer.FinishedSpans, s)
264+
}
265+
266+
func (s *mockSpan) RecordError(err error, opts ...trace.EventOption) {
267+
if err == nil {
268+
return // no-op on nil error
269+
}
270+
271+
if !s.EndTime.IsZero() {
272+
return // already finished
273+
}
274+
275+
s.SetStatus(codes.Error, "")
276+
opts = append(opts, trace.WithAttributes(
277+
semconv.ExceptionType(reflect.TypeOf(err).String()),
278+
semconv.ExceptionMessage(err.Error()),
279+
))
280+
s.AddEvent(semconv.ExceptionEventName, opts...)
281+
}
282+
283+
func (s *mockSpan) Tracer() trace.Tracer {
284+
return s.officialTracer
285+
}
286+
287+
func (s *mockSpan) AddEvent(name string, o ...trace.EventOption) {
288+
c := trace.NewEventConfig(o...)
289+
s.Events = append(s.Events, mockEvent{
290+
Timestamp: c.Timestamp(),
291+
Name: name,
292+
Attributes: c.Attributes(),
293+
})
294+
}
295+
296+
func (s *mockSpan) AddLink(link trace.Link) {
297+
s.Links = append(s.Links, mockLink{
298+
SpanContext: link.SpanContext,
299+
Attributes: link.Attributes,
300+
})
301+
}
302+
303+
func (s *mockSpan) OverrideTracer(tracer trace.Tracer) {
304+
s.officialTracer = tracer
305+
}
306+
307+
func (s *mockSpan) TracerProvider() trace.TracerProvider { return noop.NewTracerProvider() }
308+
309+
func (*testGRPCServer) UnaryCall(ctx context.Context, r *testpb.SimpleRequest) (*testpb.SimpleResponse, error) {
310+
return &testpb.SimpleResponse{Payload: r.Payload * 2}, nil
311+
}
312+
313+
func (*testGRPCServer) StreamingOutputCall(*testpb.SimpleRequest, testpb.TestService_StreamingOutputCallServer) error {
314+
return nil
315+
}
316+
317+
func (*testGRPCServer) StreamingInputCall(testpb.TestService_StreamingInputCallServer) error {
318+
return nil
319+
}
320+
321+
func (*testGRPCServer) StreamingBidirectionalCall(testpb.TestService_StreamingBidirectionalCallServer) error {
322+
return nil
323+
}
324+
325+
func startTestGRPCServer(t *testing.T, tracer ot.Tracer) (*grpc.Server, net.Addr) {
326+
lis, _ := net.Listen("tcp", ":0")
327+
server := grpc.NewServer(
328+
grpc.UnaryInterceptor(otgrpc.OpenTracingServerInterceptor(tracer)),
329+
)
330+
testpb.RegisterTestServiceServer(server, &testGRPCServer{})
331+
332+
go func() {
333+
err := server.Serve(lis)
334+
require.NoError(t, err)
335+
}()
336+
337+
return server, lis.Addr()
338+
}
339+
340+
func TestBridgeTracer_ExtractAndInject_gRPC(t *testing.T) {
341+
tracer := newMockTracer()
342+
bridge := ototel.NewBridgeTracer()
343+
bridge.SetOpenTelemetryTracer(tracer)
344+
bridge.SetTextMapPropagator(propagation.TraceContext{})
345+
346+
srv, addr := startTestGRPCServer(t, bridge)
347+
defer srv.Stop()
348+
349+
conn, err := grpc.NewClient(
350+
addr.String(),
351+
grpc.WithTransportCredentials(insecure.NewCredentials()),
352+
grpc.WithUnaryInterceptor(otgrpc.OpenTracingClientInterceptor(bridge)),
353+
)
354+
require.NoError(t, err)
355+
cli := testpb.NewTestServiceClient(conn)
356+
357+
ctx, cx := context.WithTimeout(context.Background(), 10*time.Second)
358+
defer cx()
359+
res, err := cli.UnaryCall(ctx, &testpb.SimpleRequest{Payload: 42})
360+
require.NoError(t, err)
361+
assert.EqualValues(t, 84, res.Payload)
362+
363+
checkSpans := func() bool {
364+
return len(tracer.FinishedSpans) == 2
365+
}
366+
require.Eventuallyf(t, checkSpans, 5*time.Second, 5*time.Millisecond, "expecting two spans")
367+
assert.Equal(t,
368+
tracer.FinishedSpans[0].SpanContext().TraceID(),
369+
tracer.FinishedSpans[1].SpanContext().TraceID(),
370+
"expecting same trace ID",
371+
)
372+
}

0 commit comments

Comments
 (0)