github.com/newrelic/go-agent@v3.26.0+incompatible/_integrations/nrhttprouter/nrhttprouter.go (about) 1 // Copyright 2020 New Relic Corporation. All rights reserved. 2 // SPDX-License-Identifier: Apache-2.0 3 4 // Package nrhttprouter instruments https://github.com/julienschmidt/httprouter 5 // applications. 6 // 7 // Use this package to instrument inbound requests handled by a 8 // httprouter.Router. Use an *nrhttprouter.Router in place of your 9 // *httprouter.Router. Example: 10 // 11 // package main 12 // 13 // import ( 14 // "fmt" 15 // "net/http" 16 // "os" 17 // 18 // "github.com/julienschmidt/httprouter" 19 // newrelic "github.com/newrelic/go-agent" 20 // "github.com/newrelic/go-agent/_integrations/nrhttprouter" 21 // ) 22 // 23 // func main() { 24 // cfg := newrelic.NewConfig("httprouter App", os.Getenv("NEW_RELIC_LICENSE_KEY")) 25 // app, _ := newrelic.NewApplication(cfg) 26 // 27 // // Create the Router replacement: 28 // router := nrhttprouter.New(app) 29 // 30 // router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { 31 // w.Write([]byte("welcome\n")) 32 // }) 33 // router.GET("/hello/:name", (w http.ResponseWriter, r *http.Request, ps httprouter.Params) { 34 // w.Write([]byte(fmt.Sprintf("hello %s\n", ps.ByName("name")))) 35 // }) 36 // http.ListenAndServe(":8000", router) 37 // } 38 // 39 // Runnable example: https://github.com/newrelic/go-agent/tree/master/_integrations/nrhttprouter/example/main.go 40 package nrhttprouter 41 42 import ( 43 "net/http" 44 45 "github.com/julienschmidt/httprouter" 46 newrelic "github.com/newrelic/go-agent" 47 "github.com/newrelic/go-agent/internal" 48 ) 49 50 func init() { internal.TrackUsage("integration", "framework", "httprouter") } 51 52 // Router should be used in place of httprouter.Router. Create it using 53 // New(). 54 type Router struct { 55 *httprouter.Router 56 57 application newrelic.Application 58 } 59 60 // New creates a new Router to be used in place of httprouter.Router. 61 func New(app newrelic.Application) *Router { 62 return &Router{ 63 Router: httprouter.New(), 64 application: app, 65 } 66 } 67 68 func txnName(method, path string) string { 69 return method + " " + path 70 } 71 72 func (r *Router) handle(method string, path string, original httprouter.Handle) { 73 handle := original 74 if nil != r.application { 75 handle = func(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { 76 txn := r.application.StartTransaction(txnName(method, path), w, req) 77 defer txn.End() 78 79 req = newrelic.RequestWithTransactionContext(req, txn) 80 81 original(txn, req, ps) 82 } 83 } 84 r.Router.Handle(method, path, handle) 85 } 86 87 // DELETE replaces httprouter.Router.DELETE. 88 func (r *Router) DELETE(path string, h httprouter.Handle) { 89 r.handle(http.MethodDelete, path, h) 90 } 91 92 // GET replaces httprouter.Router.GET. 93 func (r *Router) GET(path string, h httprouter.Handle) { 94 r.handle(http.MethodGet, path, h) 95 } 96 97 // HEAD replaces httprouter.Router.HEAD. 98 func (r *Router) HEAD(path string, h httprouter.Handle) { 99 r.handle(http.MethodHead, path, h) 100 } 101 102 // OPTIONS replaces httprouter.Router.OPTIONS. 103 func (r *Router) OPTIONS(path string, h httprouter.Handle) { 104 r.handle(http.MethodOptions, path, h) 105 } 106 107 // PATCH replaces httprouter.Router.PATCH. 108 func (r *Router) PATCH(path string, h httprouter.Handle) { 109 r.handle(http.MethodPatch, path, h) 110 } 111 112 // POST replaces httprouter.Router.POST. 113 func (r *Router) POST(path string, h httprouter.Handle) { 114 r.handle(http.MethodPost, path, h) 115 } 116 117 // PUT replaces httprouter.Router.PUT. 118 func (r *Router) PUT(path string, h httprouter.Handle) { 119 r.handle(http.MethodPut, path, h) 120 } 121 122 // Handle replaces httprouter.Router.Handle. 123 func (r *Router) Handle(method, path string, h httprouter.Handle) { 124 r.handle(method, path, h) 125 } 126 127 // Handler replaces httprouter.Router.Handler. 128 func (r *Router) Handler(method, path string, handler http.Handler) { 129 _, h := newrelic.WrapHandle(r.application, txnName(method, path), handler) 130 r.Router.Handler(method, path, h) 131 } 132 133 // HandlerFunc replaces httprouter.Router.HandlerFunc. 134 func (r *Router) HandlerFunc(method, path string, handler http.HandlerFunc) { 135 r.Handler(method, path, handler) 136 } 137 138 // ServeHTTP replaces httprouter.Router.ServeHTTP. 139 func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { 140 if nil != r.application { 141 h, _, _ := r.Router.Lookup(req.Method, req.URL.Path) 142 if nil == h { 143 txn := r.application.StartTransaction("NotFound", w, req) 144 defer txn.End() 145 w = txn 146 req = newrelic.RequestWithTransactionContext(req, txn) 147 } 148 } 149 150 r.Router.ServeHTTP(w, req) 151 }