-
Notifications
You must be signed in to change notification settings - Fork 84
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Integrate OpenTracing #426
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,8 @@ import ( | |
"os" | ||
"testing" | ||
|
||
"github.com/opentracing/opentracing-go" | ||
"github.com/opentracing/opentracing-go/mocktracer" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
@@ -67,7 +69,6 @@ func TestStats(t *testing.T) { | |
peerInfo := ch.PeerInfo() | ||
tags := ch.StatsTags() | ||
assert.NotNil(t, ch.StatsReporter(), "StatsReporter missing") | ||
assert.NotNil(t, ch.TraceReporter(), "TraceReporter missing") | ||
assert.Equal(t, peerInfo.ProcessName, tags["app"], "app tag") | ||
assert.Equal(t, peerInfo.ServiceName, tags["service"], "service tag") | ||
assert.Equal(t, hostname, tags["host"], "hostname tag") | ||
|
@@ -112,3 +113,25 @@ func TestIsolatedSubChannelsDontSharePeers(t *testing.T) { | |
assert.NotNil(t, sub.peers.peersByHostPort["127.0.0.1:3000"]) | ||
assert.Nil(t, isolatedSub.peers.peersByHostPort["127.0.0.1:3000"]) | ||
} | ||
|
||
func TestChannelTracerMethod(t *testing.T) { | ||
mockTracer := mocktracer.New() | ||
ch, err := NewChannel("svc", &ChannelOptions{ | ||
Tracer: mockTracer, | ||
}) | ||
require.NoError(t, err) | ||
defer ch.Close() | ||
assert.Equal(t, mockTracer, ch.Tracer(), "expecting tracer passed at initialization") | ||
|
||
ch, err = NewChannel("svc", &ChannelOptions{}) | ||
require.NoError(t, err) | ||
defer ch.Close() | ||
assert.EqualValues(t, opentracing.GlobalTracer(), ch.Tracer(), "expecting default tracer") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you change the opentracing global tracer, and make sure that it's returned when you call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see what you mean, but my concern with that is that there is actually a global variable behind GlobalTracer(), and changing a global variable in a unit test feels iffy. Probably no harm, but if any tests happen to run concurrently, it could be a problem. Wdyt? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Definitely agree it's a little iffy, but we don't run our test in parallel (none of them use the |
||
|
||
// because ch.Tracer() function is doing dynamic lookup, we can change global tracer | ||
origTracer := opentracing.GlobalTracer() | ||
defer opentracing.InitGlobalTracer(origTracer) | ||
|
||
opentracing.InitGlobalTracer(mockTracer) | ||
assert.Equal(t, mockTracer, ch.Tracer(), "expecting tracer set as global tracer") | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,7 +36,7 @@ const ( | |
) | ||
|
||
type tchannelCtxParams struct { | ||
span *Span | ||
tracingDisabled bool | ||
call IncomingCall | ||
options *CallOptions | ||
retryOptions *RetryOptions | ||
|
@@ -76,9 +76,7 @@ func getTChannelParams(ctx context.Context) *tchannelCtxParams { | |
|
||
// NewContext returns a new root context used to make TChannel requests. | ||
func NewContext(timeout time.Duration) (context.Context, context.CancelFunc) { | ||
return NewContextBuilder(timeout). | ||
setSpan(NewRootSpan()). | ||
Build() | ||
return NewContextBuilder(timeout).Build() | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When you make a new context, is there any way to know what the trace ID will be for the call you're about to make? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. First, trace ID is not a concept that's exposed in OpenTracing API, so strictly speaking - no. In practice, if there is already an OpenTracing span in the current context, then a child span will be created when the outbound call is made (but not when the context is created). If the tracer is Zipkin-compatible, then technically it's possible to extract trace ID from the current span, and internally the outbound call will do that and store that trace ID in the frame's There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One use case we have is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The main issue I had with Context doing anything related to spans is that spans can only be created by the Tracer. Passing the tracer to Context methods seemed very wrong. I think we should revisit the use case of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While it is a debugging feature, the TChannel library should allow these use cases. E.g. There also seems internal users using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NB: if returning nil from CurrentSpan is a concern, we could return a pointer to a default/empty There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry I should have been clearer. Returning I'll sync up over email about what existing callers are and we can figure out whether they need it to work or not. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In YARPC, we should guarantee that there is a span associated with a response context. We do need tracing to expose an arbitrary string for applications like what @prashantv mentions for tools and logging. Something you can use to associate and search for the trace. It does not have to conform to the Zipkin scheme. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @kriskowal OpenTracing cannot impose any specific restrictions on how a "trace identity" is represented in a string, because it's an implementation detail of the tracer and they vary greatly. However, it is reasonable to require that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be satisfying for spans to be Stringers without any requirements for the form of the string. This would reinforce the need for YARPC to return a context. We need a mechanism for YARPC to communicate back the span it created on your behalf. cc @bombela |
||
|
||
// WrapContextForTest returns a copy of the given Context that is associated with the call. | ||
|
@@ -90,10 +88,9 @@ func WrapContextForTest(ctx context.Context, call IncomingCall) context.Context | |
} | ||
|
||
// newIncomingContext creates a new context for an incoming call with the given span. | ||
func newIncomingContext(call IncomingCall, timeout time.Duration, span *Span) (context.Context, context.CancelFunc) { | ||
func newIncomingContext(call IncomingCall, timeout time.Duration) (context.Context, context.CancelFunc) { | ||
return NewContextBuilder(timeout). | ||
setIncomingCall(call). | ||
setSpan(span). | ||
Build() | ||
} | ||
|
||
|
@@ -105,17 +102,16 @@ func CurrentCall(ctx context.Context) IncomingCall { | |
return nil | ||
} | ||
|
||
// CurrentSpan returns the Span value for the provided Context | ||
func CurrentSpan(ctx context.Context) *Span { | ||
func currentCallOptions(ctx context.Context) *CallOptions { | ||
if params := getTChannelParams(ctx); params != nil { | ||
return params.span | ||
return params.options | ||
} | ||
return nil | ||
} | ||
|
||
func currentCallOptions(ctx context.Context) *CallOptions { | ||
func isTracingDisabled(ctx context.Context) bool { | ||
if params := getTChannelParams(ctx); params != nil { | ||
return params.options | ||
return params.tracingDisabled | ||
} | ||
return nil | ||
return false | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't we only need to do this check once when creating the channel rather than everytime
Tracer
is called?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did it as late binding, in case the global tracer is set after the channel is created
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i don't understand -- you can't change
ccc.tracer
after the channel is created right?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
correct, but
opentracing.GlobalTracer()
can change (by default it returns Noop tracer, not a real one).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, makes sense. Can you update the comment to call that out, so we don't accidentally "optimize" this and break it. (ideally a unit test too).