WIP: instrument net/http.ServeHTTP implementations #175
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
What does this PR do?
TODO - tests
Makes sure we instrument
net/http
handlers and servers.Background
There are two general ways to start an HTTP server with
net/http
:http.ListenAndServe
http.ListenAndServeTLS
http.Serve
http.ServeTLS
net/http.Server
methods:http.(*Server).ListenAndServe
http.(*Server).ListenAndServeTLS
http.(*Server).Serve
http.(*Server).ServeTLS
The package-level functions create a
Server
and dispatch to the matching methods.All of these work with the
http.Handler
interface, which defines the "application" logic for handling an HTTP request. TheServer
type has aHandler
field, and all of the package-level functions take anhttp.Handler
argument. Many packages, likegithub.com/gorilla/mux
, providehttp.Handler
implementations.The
net/http
package has twohttp.Handler
implementations:net/http.ServeMux
, andnet/http.HandlerFunc
.What this PR actually does
Before, we instrumented the
Handler
field ofServer
literals, and function literals cast tohttp.HandlerFunc
. But this could lead to redundant instrumentation, and also didn't cover common patterns. For example, this doesn't get instrumented today:For another example, we get redundant instrumentation for this
github.com/gorilla/mux
example:The
Handler
field of theServer
literal gets instrumented, and thehttp.HandlerFunc
literal is instrumented, and the router returned viamux.NewRouter
is instrumented. We have at least one too many layers of instrumentation.So this PR takes this approach:
MaybeWrapHandler
function. It takes anhttp.Handler
and returns anhttp.Handler
. If the input handler is one of thenet/http
handler types, we wrap it with tracing instrumentation. Otherwise we pass it on unchanged under the assumption it is already instrumented.http.Handler
passed to the package-level functions.Handler
field of aServer
literal, similar to what we did before.This doesn't provide complete coverage. For example, the user could do something like
s := new(http.Server); s.Handler = foo
and we wouldn't catch it. But this hopefully improves our coverage significantly and avoids some redundant instrumentation.Motivation
Fixes #173
Reviewer's Checklist