-
Notifications
You must be signed in to change notification settings - Fork 44
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
handler sql error #15
Conversation
Related to #10 You are breaking the public API here. If we merged this PR everyones build would break. I think some point we need a nice new API to cover this use case + better performance. but in the meantime, can I suggest changing the PR to adding a
then if hooks implements |
@keegancsmith love the |
Don't need |
@keegancsmith now I miss understood your point, I assumed that having an |
Ok, I will do some changes. 😄 |
1 similar comment
Should I hook the error happens in |
I think
|
Oh I see that is what you did, didn't notice you pushed a commit. Let me review what you have. |
sqlhooks.go
Outdated
@@ -110,6 +119,9 @@ func (conn *ExecerContext) ExecContext(ctx context.Context, query string, args [ | |||
|
|||
results, err := conn.execContext(ctx, query, args) | |||
if err != nil { | |||
if h, ok := conn.hooks.(OnError); ok { | |||
ctx, err = h.OnError(ctx, err, query, list...) | |||
} |
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 think you should override err
. Otherwise OnError
could supress errors that happen by returning nil for an error, which is likely won't most people will do.
I'd expect that if OnError
did return a non-nil err
, you return that error, otherwise you would return the original 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.
This is a good point, while error overriding/suppressing can generate confusions it might also be helpful if you want to bypass driver specific errors. I'm not sure 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.
If err
is suppressed, hook must generate another results
.
If both of them are nil
, it is easy to panic. maybe I really need to change it to just like @keegancsmith said.
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 of Hooks
as something which doesn't influence behaviour, rather observes it. We currently can mutate what ctx
is, but that is more to do with it being useful to store some "request" data in it that we can then access in After
. I think being able to cancel out err will lead to API which is easy to make a mistake in. Especially since we could then return nil, 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.
@keegancsmith I agree, but do you think it might be useful to suppress or modify errors?
I'm not talking about implementing it in this Hook
or not, but if it's useful we might need to come up with some way to do it.
.gitignore
Outdated
@@ -22,3 +22,6 @@ _testmain.go | |||
*.exe | |||
*.test | |||
*.prof | |||
|
|||
.idea |
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.
Do you mind to not add these?
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, sorry for that. I will remove it.
sqlhooks.go
Outdated
@@ -110,6 +119,9 @@ func (conn *ExecerContext) ExecContext(ctx context.Context, query string, args [ | |||
|
|||
results, err := conn.execContext(ctx, query, args) | |||
if err != nil { | |||
if h, ok := conn.hooks.(OnError); ok { | |||
ctx, err = h.OnError(ctx, err, query, list...) | |||
} |
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 good point, while error overriding/suppressing can generate confusions it might also be helpful if you want to bypass driver specific errors. I'm not sure here.
I think the question here is if Error hooks should just observe the errors or actually be able to modify it. |
Yeah this is the approach I think is the correct one. It technically allows you to modify the error, but if you return nil as error it returns the original error. So all thats missing is some docstrings, but LGTM |
Should we bother with returning a context from |
@keegancsmith right, it's useless |
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 I finally gave this a proper review. Sorry for the delayed review asking for changes, but we want to merge this in and tag a new release of sqlhooks :)
If you don't have time to make these changes, I'm happy to do them.
hooks/othooks/othooks.go
Outdated
defer span.Finish() | ||
span.SetTag("error", true) | ||
span.LogFields( | ||
log.String("error_msg", err.Error()), |
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 is log.Error(err)
for logging an error field.
hooks/loghooks/loghooks.go
Outdated
@@ -28,3 +28,8 @@ func (h *Hook) After(ctx context.Context, query string, args ...interface{}) (co | |||
h.log.Printf("Query: `%s`, Args: `%q`. took: %s", query, args, time.Since(ctx.Value("started").(time.Time))) | |||
return ctx, nil | |||
} | |||
|
|||
func (h *Hook) OnError(ctx context.Context, err error, query string, args ...interface{}) error { | |||
h.log.Printf("Error: %v, Took: %s", err, time.Since(ctx.Value("started").(time.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.
Including the query and args may be useful, like we do above for After
sqlhooks.go
Outdated
@@ -9,12 +9,27 @@ import ( | |||
// Hook is the hook callback signature | |||
type Hook func(ctx context.Context, query string, args ...interface{}) (context.Context, error) | |||
|
|||
// ErrorHandler is the error handling callback signature | |||
type ErrorHandler func(ctx context.Context, err error, query string, args ...interface{}) error |
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 I suggest calling this ErrorHook
to be more consistent with Hook
above?
sqlhooks.go
Outdated
// Hooks instances may be passed to Wrap() to define an instrumented driver | ||
type Hooks interface { | ||
Before(ctx context.Context, query string, args ...interface{}) (context.Context, error) | ||
After(ctx context.Context, query string, args ...interface{}) (context.Context, error) | ||
} | ||
|
||
// ErrHook instances will be called if any error happens | ||
type ErrHook interface { |
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 idiomatic name for an interface with a single function is the function name with er
suffix. EG fmt.Stringer
has a String
function. So in this case the interface name would be OnErrorer
.
sqlhooks.go
Outdated
return e | ||
} | ||
return 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.
you could simplify the below code if you took a Hook
instead of an ErrHook
. Then if the Hook
implements the error hook interface you use it, otherwise you just return the err.
OK, I will makes those changes tomorrow. My time zone is UTC+8, I really have to sleep now. |
Sorry for my delayed change because of work busy recently. Please let me know if anything Improperly. |
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. I'll let @gchaincl take a look and merge.
Now if any SQL error happens, After hook will not be called.
It's cause OpenTracing span can't be finished normally. And the span will disappear on OpenTracing dashboard(I'm using Jaeger).
It makes lot's of inconvenient because the only thing I really care about is the error message.