-
Notifications
You must be signed in to change notification settings - Fork 16
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
Context based error reporting #37
Context based error reporting #37
Conversation
To keep the Honeybadger context scoped to a single request, store the `*contextSync` value in a `context.Context`. This way there's no possibility of the request context data being overwritten due to the function being called in a concurrent setting.
In order to get the context stored in the `Client.SetContext` call, need to require a context as the first argument.
Same as other functions, `client.Notify` requires a `context.Context` as the first argument so Monitor has to be updated as well. Does mean that a panic won't have the context information unless it's called within the function that might panic instead of at the top level. Ie: ``` func main(){ ctx := context.Background() defer honeybadger.Monitor(ctx) // set up http handlers and whatnot } ``` Won't be able to get the values set unless it's called like so: ``` func handler(w http.ResponseWriter, r *http.Request){ defer honeybadger.Monitor(r.Context()) // rest of handler } ```
This should address #35 |
Not sure why this is failing or what can be done to fix:
|
@seanhagen super sorry for the delay in reviewing this--thanks for submitting it! I'm looking over it now. Prepare for some dumb questions; context passing in go is pretty new to me. :) It sounds like this solves the problem of scoping context to the request when using the My first question is how to get
Where does If that's the case, is there anything we can do to smooth the user interface for users who don't want to think about shared context (i.e., say they just want to call |
Because contexts are not modifiable in-place (eg, calling `context.WithValue` returns a new context, it doesn't return the same context you've passed in with the value set), need to set some data in the Honeybadger HTTP middleware. Unfortunately, any additional info set with `SetContext` within the handler is lost if the handler panics.
Yeah, this will prevent the honeybadger context ( ie, setting the information that should be reported if I also just updated the Basically, think of the Unfortunately, in the case of the http handler, because the request context can't be replaced if I don't think that's too clear, so here's a code example: mux := http.NewServeMux()
mux.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request){
ctx := honeybadger.SetContext(r.Context(), map[string]interface{}{"value": "something important"})
// important code
if err != nil {
// this error in honeybadger will have "value" = "something important" in the context
honeybadger.Notify(ctx, err)
}
})
mux.HandleFunc("/panics", func(w http.ResponseWriter, r *http.Request){
// this data won't be seen if the function panics
// because it's a new context, not the same one that the panic handler in client.go
// has access to
ctx := honeybadger.SetContext(r.Context(), map[string]interface{}{"value": "very important"})
// important code
if err != nil {
panic(err)
}
})
http.ListenAndServe(":8080", honeybadger.Handler(mux)) In the route However, in It's a downside, for sure, but there's no way around it without global values -- and then we're right back to data getting clobbered when it's run in goroutines ( which is just unavoidable in web servers, Re: still being able to call I could change the new |
I've been using my fork in production for a bit now, and it works fine and no data gets clobbered or shows up where it shouldn't in the Honeybadger app. |
@seanhagen Take a look at how Bugsnag handles context--they do something similar to what you're doing here: https://docs.bugsnag.com/platforms/go/net-http/#manage-http-session-data-with-context-context In their I'd like to take the same approach (adding What do you think? |
@@ -89,13 +117,27 @@ func (client *Client) Handler(h http.Handler) http.Handler { | |||
h = http.DefaultServeMux | |||
} | |||
fn := func(w http.ResponseWriter, r *http.Request) { | |||
ctx := r.Context() | |||
ctx = client.SetContext(ctx, map[string]interface{}{ | |||
"path": r.URL.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.
Adding this data is great, but we'll want to send it as cgi_data
(with special keys) instead of context--that's what we use to display request data in error reports. For an example, search for "cgi_data" on this page: https://docs.honeybadger.io/api/exceptions.html#sample-payload
Here's how we construct it in Elixir, for instance: https://github.com/honeybadger-io/honeybadger-elixir/blob/94c6c1f29cef70ae754bf12aa99779849ddd0b70/lib/honeybadger/plug_data.ex#L49
I'd probably hold off on including this in the current PR (since it's kind of a separate feature) and then submit a subsequent PR after we get the new ctx
API worked out.
What is the status of this PR? It would be really nice to get it merged soon. |
I can't merge this PR as-is, unfortunately. See my comment here (and my review). I don't have time to do it myself atm; PRs are welcome of course, but otherwise I could schedule this to happen in the next couple months. If anyone does want to work on this, comment here/on #35 to make sure that we don't duplicate effort. |
This allows building up a honeybadger.Context riding along with a context.Context so it can be sent with errors. The goal is to make it so that the context sent to Honeybadger is tied to the request (or stack) rather than multiple requests clobbering the global state (see honeybadger-io#35). Fixes honeybadger-io#35 Closes honeybadger-io#37
Closing this in favor of #39 (which is also hanging atm, but a better direction). |
This allows building up a honeybadger.Context riding along with a context.Context so it can be sent with errors. The goal is to make it so that the context sent to Honeybadger is tied to the request (or stack) rather than multiple requests clobbering the global state (see honeybadger-io#35). Fixes honeybadger-io#35 Closes honeybadger-io#37
This allows building up a honeybadger.Context riding along with a context.Context so it can be sent with errors. The goal is to make it so that the context sent to Honeybadger is tied to the request (or stack) rather than multiple requests clobbering the global state (see honeybadger-io#35). Fixes honeybadger-io#35 Closes honeybadger-io#37
Update
Client.SetContext
to requirecontext.Context
To keep the Honeybadger context scoped to a single request, store
the
*contextSync
value in acontext.Context
. This way there's no possibilityof the request context data being overwritten due to the function being called
in a concurrent setting.
Update
Client.Notify
to requirecontext.Context
In order to get the context stored in the
Client.SetContext
call, need torequire a context as the first argument.
Update Monitor to require
context.Context
Same as other functions,
client.Notify
requires acontext.Context
as thefirst argument so Monitor has to be updated as well. Does mean that a panic
won't have the context information unless it's called within the function that
might panic instead of at the top level.
Ie:
Won't be able to get the values set unless it's called like so:
No more need for
Client.context
, so removing itUpdate
Client.Handler
to user.Context()
Update functions to require
context.Context
Use
context.Background
inMonitor()
Version bump -- v0.5.0