-
Notifications
You must be signed in to change notification settings - Fork 438
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
Raphael/redigo #51
Raphael/redigo #51
Conversation
Conflicts: circle.yml
tracer/contrib/redigo/tracedredis.go
Outdated
host, port, err := net.SplitHostPort(u.Host) | ||
if err != nil { | ||
host = u.Host | ||
port = "6379" |
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 seems incorrect, shouldn't we only do this if port is ""?
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.
We set port to 6379 only when can't get the port via net.SplitHostPort (this is the err that gets in the if) https://github.com/garyburd/redigo/blob/master/redis/conn.go#L226
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 add a comment with that link
tracer/contrib/redigo/tracedredis.go
Outdated
|
||
func (tc TracedConn) Do(commandName string, args ...interface{}) (reply interface{}, err error) { | ||
ctx := context.Background() | ||
ok := 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.
don't need this line. just do a declaration on Line 62 ctx, ok := ...
tracer/contrib/redigo/tracedredis.go
Outdated
} | ||
span.SetMeta("redis.raw_command", raw_command) | ||
ret, err := tc.Conn.Do(commandName, args...) | ||
return ret, err |
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 return tc.Conn.Do(...)
tracer/contrib/redigo/tracedredis.go
Outdated
span.Resource = "redigo.Conn.Flush" | ||
} | ||
raw_command := commandName | ||
for _, arg := range args { |
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 can be slow and create a lot of garbage. use a bytes.Buffer
tracer/contrib/redigo/tracedredis.go
Outdated
span.Resource = commandName | ||
} else { | ||
// According to redigo doc: when the command argument to the Do method is "", | ||
// then the Do method will flush the output buffer |
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.
add a link to the doc please
tracer/contrib/redigo/tracedredis.go
Outdated
} | ||
|
||
span := tc.tracer.NewChildSpanFromContext("redis.command", ctx) | ||
defer func() { |
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.
actually we have a more idiomatic way to do this: defer span.FinishWithErr(err)
https://github.com/DataDog/dd-trace-go/blob/master/tracer/span.go#L171
tracer/contrib/redigo/tracedredis.go
Outdated
|
||
type TracedConn struct { | ||
redis.Conn | ||
tracer *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.
wrap host, port, network, service, tracer in a TraceParams struct and pass it to TracedConn . avoids conflicts in field names
tracer/contrib/redigo/tracedredis.go
Outdated
var ctx context.Context | ||
var ok bool | ||
if len(args) > 0 { | ||
ctx, ok = args[len(args)-1].(context.Context) |
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 it would be more idiomatic to use the sql style ExecContext https://golang.org/pkg/database/sql/#DB.ExecContext
so maybe another function DoContext
that takes a context as the first arg. Thoughts?
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 not familiar with that API but indeed having ctx as a last optional arg can lead to surprising behaviors. The reason for doing this is keeping the API unchanged when using or not using tracing, right ? Because this would work one way -> if you replace the Conn
by a TracedConn
, code is still going to work. But then all redis traces are lone traces, not related to their parents. So you have to put an extra arg. But if you do so, it does not work the other way, the day you go backwards and replace the TracedConn
by a Conn
, the code will fail because the Redis lib is going to receive an extra param it does not know what to do with. Dig into it, but probably DoContext
suggested by @talwai would be fine, it would cost some extra typing/refactor from people instrumenting the code, but would make it safer. Just my 2c.
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 approach, yet some little fixes to do for general stability I think.
ddagent: | ||
image: datadog/docker-dd-agent | ||
environment: | ||
- DD_APM_ENABLED=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.
could be useless now I think, since trace agent should be running by default: DataDog/datadog-trace-agent@a51dd0e#diff-b7db7d3e3d014cfcce344902b2d07a78
tracer/contrib/redigo/tracedredis.go
Outdated
c, err := redis.Dial(network, address) | ||
addr := strings.Split(address, ":") | ||
host := addr[0] | ||
port := addr[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.
Beware here, you might need to check if there's no :
in the string (no port given, and I think this is a real world case, just letting the lib pick up the default port) else we're going to have a panic() in our code and interrupt use code.
assert.Equal(span.GetMeta("redis.args_length"), "2") | ||
} | ||
|
||
func TestError(t *testing.T) { |
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.
You probably need another test that yields an error when connecting to the service, making sure if the underlying library can not connect to redis (bad credentials, bad host, whatever) it bubbles up to the caller.
tracer/contrib/redigo/tracedredis.go
Outdated
if len(addr) == 2 && addr[1] != "" { | ||
port = addr[1] | ||
} else { | ||
port = "6379" |
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.
👍
tracer/contrib/redigo/tracedredis.go
Outdated
var ctx context.Context | ||
var ok bool | ||
if len(args) > 0 { | ||
ctx, ok = args[len(args)-1].(context.Context) |
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 not familiar with that API but indeed having ctx as a last optional arg can lead to surprising behaviors. The reason for doing this is keeping the API unchanged when using or not using tracing, right ? Because this would work one way -> if you replace the Conn
by a TracedConn
, code is still going to work. But then all redis traces are lone traces, not related to their parents. So you have to put an extra arg. But if you do so, it does not work the other way, the day you go backwards and replace the TracedConn
by a Conn
, the code will fail because the Redis lib is going to receive an extra param it does not know what to do with. Dig into it, but probably DoContext
suggested by @talwai would be fine, it would cost some extra typing/refactor from people instrumenting the code, but would make it safer. Just my 2c.
|
||
_, err := TracedDial("redis-service", testTracer, "tcp", "000.0.0:1111") | ||
|
||
assert.Contains(err.Error(), "dial tcp: lookup 000.0.0:") |
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.
💯
About the DoContext suggestion: I guess we should add a warning message to people adding Context, they have to make sure that they've used TracedDial before using a Do with context in the args |
OK @furmmon I see your point with pools & co. What about writing a func that would maked a traced c := pool.Get()
c.Do(cmds, ...) Becomes: c := tracedredis.TracedConn(ctx, pool.Get())
c.Do(cmds, ...) @talwai does this make sense? |
Problem raisedWith current code, to pass the context for the creation of the redigo span we use the fact that redis.Conn The ideal solution would be to have a In our back-end we use alot of General overview of redigo patchingData we want:
Where to get those:
Transactions with redis are made in the Current stateBy using About the proposed solutions1. Add a DoWithContext function for TracedConnWhen we do
2. Insert context upstreamWe can easily set the context at the pool creation level without messing with the |
I'm open to any solution to the original problem, I didn't find any better then the current one |
Summary
Exemple span:
Patching guide:
using Dial()/DialURL() and Do
Instead of
You use
Using Pools
Instead of
Use