-
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
Support -H, -B, --jaeger for headers and baggage #121
Conversation
@kriskowal, thanks for your PR! By analyzing the history of the files in this pull request, we identified @prashantv, @abhinav and @blampe to be potential reviewers. |
@@ -302,6 +330,7 @@ func runWithOptions(opts Options, out output) { | |||
runBenchmark(out, opts, benchmarkMethod{ | |||
serializer: serializer, | |||
req: req, | |||
tracer: tracer, |
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.
could be removed and assume NoopTracer downstream from here
@@ -30,6 +30,8 @@ import ( | |||
"strconv" | |||
"time" | |||
|
|||
"github.com/opentracing/opentracing-go" | |||
|
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 remove blank since this is a third party import like the below import
ServiceName: "foo", | ||
HostPorts: []string{s.hostPort()}, | ||
} | ||
tp, err := getTransport(tOpts, encoding.Thrift) | ||
tp, err := getTransport(tOpts, encoding.Thrift, 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.
What is the difference in behaviour between nil
here and NoopTracer
in bench_method.go
?
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.
If you thread nil, TChannel and YARPC will fall back to the global tracer. I’m going to explicitly thread NoopTracer and mandate a non-nil tracer in getTransport, so there’s no question for yab.
@@ -38,7 +39,7 @@ type benchmarkMethod struct { | |||
// up by making some number of requests through it. | |||
func (m benchmarkMethod) WarmTransport(opts TransportOptions, warmupRequests int) (transport.Transport, error) { | |||
opts.benchmarking = true | |||
transport, err := getTransport(opts, m.serializer.Encoding()) | |||
transport, err := getTransport(opts, m.serializer.Encoding(), opentracing.NoopTracer{}) |
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 realized, baggage only gets with the Jaeger tracer right? Perhaps we can't do this unless we explicitly disallow baggage with benchmarking? Otherwise, the initial request will use baggage but the benchmarking requests will not.
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 observation. I’ll simplify this so the only rule regarding tracing is that it must be enabled to pass baggage. I’ll work out a way to ensure that only the first request is sampled, and sampling is off for benchmarking. Whether to use Jaeger and whether to sample should be orthogonal.
opts.TOpts.CallerName = "yab-" + os.Getenv("USER") | ||
} | ||
|
||
var tracer opentracing.Tracer |
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 the logic of get a tracer into a separate method?
Baggage map[string]string | ||
RoutingKey string | ||
RoutingDelegate string | ||
ShardKey string |
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 know if routing key/delegate/shard key belong as top level fields on the request, unless we've made those transport-agnostic concerns in YARPC?
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.
These are made transport-agnostic in YARPC. There are equivalent HTTP headers for all of these properties and they’re threaded by reqmeta in YARPC. However, I didn’t finish that angle in this PR, so I’ll take them out for now. We can add them either when we refactor yab to use YARPC or explicitly plumb them in future work.
RoutingDelegate string | ||
ShardKey string | ||
Body []byte | ||
Tracer opentracing.Tracer |
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 Request
and Response
objects only contain values that represent the on-wire presentation currently. I'm not sure if Tracer should be here, should we move it into the Call
interface instead?
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.
In YARPC, the tracer is a dependency for instantiating a transport. I’ll try to do something similar here instead.
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 still a WIP? Can you prepend the title with "WIP - " in that case?
@@ -2,6 +2,9 @@ Changelog | |||
========= | |||
|
|||
* Upgrade to TChannel 1.2.0 and add Open Tracing support. | |||
* Add support for -H key:value header arguments. |
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.
Suggest:
- Add support for headers with argument
-H key:value
. - Add support for baggage with argument
-B key:value
when--jaeger
is passed.
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
@@ -384,8 +384,7 @@ func TestAlises(t *testing.T) { | |||
{ | |||
args: []cmdArgs{ | |||
{"-P", "file"}, | |||
{"-H", "file"}, |
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.
So we're stealing the -H
flag for headers?
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.
yes.
Added passing tests for baggage. Added a passing test for TChannel headers. Left a broken test for HTTP headers with #125 Now seeking only a stamp from @prashantv |
return t.Call(ctx, request) | ||
} | ||
|
||
func makeInitialRequest(out output, transport transport.Transport, serializer encoding.Serializer, req *transport.Request) { |
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 am not sure where this new code is coming from. There might be rebase magic 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.
yeah looks like the diff needs to be rebased off the latest dev
branch
@@ -25,6 +25,7 @@ import ( | |||
"sync" | |||
"time" | |||
|
|||
"github.com/opentracing/opentracing-go" |
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.
Import group ordering. Third party imports should be in a separate group.
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.
+1, same throughout this change
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.
import group ordering nits
"strings" | ||
|
||
"github.com/opentracing/opentracing-go" | ||
"github.com/uber/tchannel-go" | ||
"gopkg.in/yaml.v2" |
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.
third party group should be below first party group
@@ -23,15 +23,19 @@ package transport | |||
import ( | |||
"time" | |||
|
|||
"github.com/opentracing/opentracing-go" |
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.
should be in same group as bellow
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.
✔
"os" | ||
"testing" | ||
"time" | ||
|
||
"github.com/opentracing/opentracing-go" | ||
opentracing_ext "github.com/opentracing/opentracing-go/ext" |
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.
should separate third party group below
@@ -25,6 +25,7 @@ import ( | |||
"sync" | |||
"time" | |||
|
|||
"github.com/opentracing/opentracing-go" |
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.
+1, same throughout this change
@@ -78,11 +83,21 @@ func (methodsT) echo() handler { | |||
|
|||
func (methodsT) traceEnabled() handler { |
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 add a comment that explains the returned result from the method
}{ | ||
{ | ||
hostPort: s.hostPort(), | ||
}, | ||
{ |
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.
this looks unrelated to headers -- should this have been handled in a previous diff?
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.
This is a far flung effect of refactoring tracing. Tracing is no longer a transport level concern, since we no longer use trace sampling on the channel level. Consequently it becomes a request scoped concern and the logic to detect whether the caller was overridden had to be factored upward so I could validate benchmark options.
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.
…which invalidated this test case.
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.
Ahh I see
@@ -37,8 +39,10 @@ type server struct { | |||
|
|||
type handler func(ctx context.Context, args *raw.Args) (*raw.Res, error) | |||
|
|||
func newServer(t *testing.T) *server { | |||
ch := testutils.NewServer(t, testutils.NewOpts().SetServiceName("foo").DisableLogVerification()) | |||
func newServer(t *testing.T, tracer opentracing.Tracer) *server { |
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.
Rather than take a tracer (and get into the pattern of everyone passing nil
for default options), we should probably just implement a lightweight options pattern here,
func withTracer(opentracing.Tracer) func(*testutils.ChannelOpts) {
return func(opts *testutils.ChannelOpts) {
opts.Tracer = tracer
}
}
func newServer(t *testing.T, opts... func(*testutils.ChannelOpts)) {
chOpts := testutils.NewOpts().[...]
for _, opt := range opts {
opt(chOpts)
}
[...]
}
ret = 0xfe | ||
} | ||
} else { | ||
ret = 0xff |
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 span in context case returning 0 seems like a good default
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.
these cases were helpful in isolating test errors during development. I’ll scale it back down.
return t.Call(ctx, request) | ||
} | ||
|
||
func makeInitialRequest(out output, transport transport.Transport, serializer encoding.Serializer, req *transport.Request) { |
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.
yeah looks like the diff needs to be rebased off the latest dev
branch
@@ -141,7 +141,7 @@ func TestGetHeaders(t *testing.T) { | |||
} | |||
|
|||
for _, tt := range tests { | |||
got, err := getHeaders(tt.inline, tt.file) | |||
got, err := getHeaders(tt.inline, tt.file, 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.
can we add unit tests for the override
here
@@ -174,7 +174,6 @@ func TestTChannelCallSuccessRaw(t *testing.T) { | |||
for _, tt := range tests { | |||
var lastSpan uint64 | |||
testutils.RegisterFunc(svr, "echo", func(ctx context.Context, args *raw.Args) (*raw.Res, error) { | |||
// assert.False(t, tchannel.CurrentSpan(ctx).TracingEnabled(), "Tracing should be disabled") |
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.
intentional change? shouldn't this just be uncommenting?
func (t *tchan) Protocol() Protocol { | ||
return TChannel | ||
} | ||
|
||
func (t *tchan) Call(ctx context.Context, r *Request) (*Response, error) { | ||
call, err := t.sc.BeginCall(ctx, r.Method, t.callOptions) | ||
req := *r |
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 add a comment for why we do this
@@ -54,24 +55,18 @@ func benchmarkMethodForTest(t *testing.T, methodString string, p transport.Proto | |||
} | |||
|
|||
func TestBenchmarkMethodWarmTransport(t *testing.T) { | |||
s := newServer(t) | |||
s := newServer(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.
optional nit: naked nils are uninformative. Consider using a parameter object
where you set Tracer only when you need it. Alternatively, add a /* tracer */
comment next to the nil.
func getTracer(opts Options, out output) (opentracing.Tracer, io.Closer) { | ||
var tracer opentracing.Tracer | ||
var closer io.Closer | ||
tracer = opentracing.NoopTracer{} |
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: use var group and initialize tracer at declaration:
var (
tracer opentracing.Tracer = opentracing.NoopTracer{}
closer 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.
lgtm, just left a few minor comments
}{ | ||
{ | ||
hostPort: s.hostPort(), | ||
}, | ||
{ |
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.
Ahh I see
val := span.BaggageItem("baggagekey") | ||
if val == "" { | ||
return errors.New("missing baggage") | ||
} else if val != "baggagevalue" { |
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 else
since the above case returns,
val := span.BaggageItem(..)
if val == "" {
return errors.New("missing baggage")
}
if val != "baggagevalue" {
return errors.New("unexpected baggage")
}
return nil
|
||
func verifyThriftHeaders(ctx thrift.Context) error { | ||
headers := ctx.Headers() | ||
if val, ok := headers["headerkey"]; 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: i'd write this the same as the verifyBaggage
to reduce nesting
val, ok := ctx.Headers()["headerkey"]
if !ok {
return errors.New("missing header")
}
if val != "headervalue" {
return errors.New("unexpected header")
}
return nil
} | ||
|
||
func verifyYARPCHeaders(reqMeta yarpc.ReqMeta) error { | ||
headers := reqMeta.Headers() |
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 we instead have a single veriyHeaders(headers map[string]string) error
method, and pass in the ctx.Headers()
or reqMeta.Headers()
? That way we can avoid the duplication 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.
YARPC does not expose Headers().Items().
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.
Ahh, I forgot that yarpc headers are not an actual map, this is fine then.
@@ -75,7 +81,7 @@ func NewTChannel(opts TChannelOptions) (Transport, error) { | |||
} | |||
|
|||
callerName := opts.SourceService | |||
if cn, ok := opts.TransportOpts["cn"]; ok { | |||
if cn, ok := opts.TransportOpts["cn"]; ok && cn != "" { |
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: should we keep this as is -- it might be we want to test what happens if the cn
header is empty in a request.
No description provided.