-
Notifications
You must be signed in to change notification settings - Fork 35
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
Add Jaeger throttling config #233
Conversation
Signed-off-by: Isaac Hier <ihier@uber.com>
68ad722
to
887371b
Compare
Codecov Report
@@ Coverage Diff @@
## dev #233 +/- ##
==========================================
+ Coverage 93.42% 93.84% +0.42%
==========================================
Files 40 40
Lines 2721 2194 -527
==========================================
- Hits 2542 2059 -483
+ Misses 130 85 -45
- Partials 49 50 +1
Continue to review full report at Codecov.
|
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.
duck typing an interface in the internal
directory of another repo might be dangerous but I don't see a better way to do this. The alternative is to mock the agent but that's mocking the dependency of a dependency which seems even weirder. TLDR; this is ok(?)
Ya I agree. @yurishkuro @vprithvi any thoughts about how to test debug trace throttling in this code without mocking Jaeger components here? |
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.
Thanks for the PR, I have a couple of questions:
- Will this impact tracer creation of run on a machine that doesn't have the Jaeger agent? E.g., local developer laptops?
- Why are credits floats? It seems like they're used as ints throughout.
integration_test.go
Outdated
@@ -89,13 +89,10 @@ func verifyBaggage(ctx context.Context) error { | |||
return errors.New("missing span") | |||
} | |||
|
|||
spanCtx, ok := span.Context().(jaeger.SpanContext) | |||
_, ok := span.Context().(jaeger.SpanContext) | |||
if !ok { |
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.
nit: can you inline the ok :=
into the if,
if _, ok := span.Context().(jaeger.SpanContext); !ok {
[...]
}
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.
Ya sure.
main.go
Outdated
tracer, closer, err = jaeger_config.Configuration{ | ||
ServiceName: opts.TOpts.CallerName, | ||
Throttler: &jaeger_config.ThrottlerConfig{ | ||
SynchronousInitialization: true, |
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.
can you explain this a little -- i'm assuming it means we try to get the throttling information synchronously? if that fails (e.g., on machines without jaeger), what is the impact?
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.
Synchronous initialization is required for scripting tools such as yab that will likely exist in a short-lived process. For a service, we can periodically fetch the credit information (i.e. every 10 seconds). That is not feasible in a short script, so we set this flag to indicate we need to request credits from the Jaeger agent synchronously if there are no credits available for a given operation (credits represent number of debug spans we can emit without violating the throttling API). On machines without Jaeger, this would fail the request and refuse to emit debug spans, which is fine for those machines without agents. I would have thought the initial query could take a while to determine that the agent is not running and return an error, but local tests indicate no significant lag.
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.
@isaachier add this justification as a code comment.
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.
Good idea.
utils_for_test.go
Outdated
return getTestTracerWithCredits(serviceName, credits, nil) | ||
} | ||
|
||
func getTestTracerWithCredits(serviceName string, credits float64, t *testing.T) (opentracing.Tracer, io.Closer) { |
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.
why is credits a float?
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.
Just because the rate limiting API uses a token bucket to increment the total... floats are easier to use when you have a constant rate over time. The spending amount is always 1.
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.
Changing this to int
s for internal mocks.
utils_for_test.go
Outdated
return getTestTracerWithCredits(serviceName, credits, nil) | ||
} | ||
|
||
func getTestTracerWithCredits(serviceName string, credits float64, t *testing.T) (opentracing.Tracer, io.Closer) { |
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.
make t *testing.T
the first argument
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.
Makes sense. Good idea.
utils_for_test.go
Outdated
func getTestTracer(serviceName string) (opentracing.Tracer, io.Closer) { | ||
return jaeger.NewTracer(serviceName, jaeger.NewConstSampler(true), jaeger.NewNullReporter()) | ||
const ( |
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.
nit: no need for var group, just const credits = 10
is fine
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.
Good to know. Didn't think about that.
utils_for_test.go
Outdated
t *testing.T | ||
} | ||
|
||
func newDebugTraceCounter(numDebugTraces int, t *testing.T) jaeger.Reporter { |
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.
t *testing.T
should be the first argument
utils_for_test.go
Outdated
} | ||
|
||
func (d *debugTraceCounter) Report(span *jaeger.Span) { | ||
if span == nil { |
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.
is this actually possible?
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.
Doesn't seem to be. Will remove. I miss assert(span != nil)
😢.
utils_for_test.go
Outdated
func (d *debugTraceCounter) Close() { | ||
d.Lock() | ||
defer d.Unlock() | ||
if d.t == nil { |
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.
will this ever happen?
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.
Same assertion pattern from above. Will remove.
Actually, this is the case if any test case calls getTestTracer
instead of getTestTracerWithCredits
. The former method does not take a *testing.T
argument, and we hit this if statement upon tracer.Close()
.
utils_for_test.go
Outdated
creditsPerDebugTrace = 1 | ||
) | ||
d.Lock() | ||
defer d.Unlock() |
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.
nit: can you add a blank line after the defer
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.
Sure
Added some comments. |
3a98ebd
to
4e3e297
Compare
main.go
Outdated
@@ -360,7 +361,27 @@ func getTracer(opts Options, out output) (opentracing.Tracer, io.Closer) { | |||
closer io.Closer | |||
) | |||
if opts.TOpts.Jaeger && !opts.TOpts.NoJaeger { | |||
tracer, closer = jaeger.NewTracer(opts.TOpts.CallerName, jaeger.NewConstSampler(true), jaeger.NewNullReporter()) | |||
// yab must set the `SynchronousInitialization` flag to indicate that |
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.
Comment explaining SynchronousInitialization
.
@prashantv anything else? |
@@ -2,8 +2,8 @@ sudo: false | |||
language: go | |||
|
|||
go: | |||
- 1.8 | |||
- 1.9 | |||
- "1.9" |
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.
is this required?
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.
The 1.10 addition is needed for the new Zap that we use. Something about type aliasing there. If you are referring to the quotes, Travis explains that without quotes, 1.10
is a float, so it becomes 1.1
.
main.go
Outdated
// yab must set the `SynchronousInitialization` flag to indicate that | ||
// the Jaeger client must fetch debug credits synchronously. In a | ||
// short-lived process like yab, the Jaeger client cannot afford to | ||
// postpone the credit request for later in time. |
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.
please add a note about what happens if this fails (e.g., that it will just not send spans).
the comment should make it clear that err != nil
does not happen if we fail to get the credits synchronously
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.
Sure
main.go
Outdated
// short-lived process like yab, the Jaeger client cannot afford to | ||
// postpone the credit request for later in time. | ||
var err error | ||
tracer, closer, err = jaeger_config.Configuration{ |
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.
can we move all of the logic (which is now no longer a simple line) into a separate function, so the comment + all the logic for synchronous initialization is in a single createJaegerTracer
function
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.
definitely
|
||
func (d *debugTraceCounter) Close() { | ||
d.Lock() | ||
defer d.Unlock() |
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.
nit: blank after defer
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.
Will do
utils_for_test.go
Outdated
func getTestTracer(serviceName string) (opentracing.Tracer, io.Closer) { | ||
return jaeger.NewTracer(serviceName, jaeger.NewConstSampler(true), jaeger.NewNullReporter()) | ||
const credits = 10 | ||
return getTestTracerWithCredits(nil, serviceName, credits) |
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.
there's only 2 callers of getTestTracer
, i'd suggest changing it to take a *testing.T
as the first argument, and propagating it, instead of the nil
check you have above.
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.
OK if that is the entire usage, I am totally fine. I was under the impression there were more callers.
main.go
Outdated
} else if len(opts.ROpts.Baggage) > 0 { | ||
return createJaegerTracer(opts, out) | ||
} | ||
if len(opts.ROpts.Baggage) > 0 { | ||
out.Fatalf("To propagate baggage, you must opt-into a tracing client, i.e., --jaeger") | ||
} | ||
return tracer, closer |
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.
no need for vars
at the beginning, you can just do:
return opentracing.NoopTracer{}, closer
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.
Thanks for addressing all my comments, @yurishkuro, does this look good to you as well?
main.go
Outdated
if opts.TOpts.Jaeger && !opts.TOpts.NoJaeger { | ||
tracer, closer = jaeger.NewTracer(opts.TOpts.CallerName, jaeger.NewConstSampler(true), jaeger.NewNullReporter()) |
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.
@prashantv why was yab using a null reporter? Do you have a specific need to omit the root span?
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 have just changed this based on @yurishkuro's advice. Unless you mind, we might as well do this all at once.
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 was going to suggest not making this discussion a part of this PR, but move to #234.
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'm going to undo this and potentially open a new PR about this.
56023bb
to
a290a0f
Compare
// only enable the span when we have not hit the throttling | ||
// threshold. | ||
jaeger_config.Sampler(jaeger.NewConstSampler(false)), | ||
jaeger_config.Reporter(jaeger.NewNullReporter()), |
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 think these two customizations are not necessary, but can be discussed separately - #234.
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.
lgtm
@prashantv can you please merge this PR? |
Thanks! |
No description provided.