github.com/newrelic/go-agent@v3.26.0+incompatible/_integrations/nrecho/nrecho.go (about) 1 // Copyright 2020 New Relic Corporation. All rights reserved. 2 // SPDX-License-Identifier: Apache-2.0 3 4 // Package nrecho instruments https://github.com/labstack/echo applications. 5 // 6 // Use this package to instrument inbound requests handled by an echo.Echo 7 // instance. 8 // 9 // e := echo.New() 10 // // Add the nrecho middleware before other middlewares or routes: 11 // e.Use(nrecho.Middleware(app)) 12 // 13 // Example: https://github.com/newrelic/go-agent/tree/master/_integrations/nrecho/example/main.go 14 package nrecho 15 16 import ( 17 "net/http" 18 "reflect" 19 20 "github.com/labstack/echo" 21 newrelic "github.com/newrelic/go-agent" 22 "github.com/newrelic/go-agent/internal" 23 ) 24 25 func init() { internal.TrackUsage("integration", "framework", "echo") } 26 27 // FromContext returns the Transaction from the context if present, and nil 28 // otherwise. 29 func FromContext(c echo.Context) newrelic.Transaction { 30 return newrelic.FromContext(c.Request().Context()) 31 } 32 33 func handlerPointer(handler echo.HandlerFunc) uintptr { 34 return reflect.ValueOf(handler).Pointer() 35 } 36 37 func transactionName(c echo.Context) string { 38 ptr := handlerPointer(c.Handler()) 39 if ptr == handlerPointer(echo.NotFoundHandler) { 40 return "NotFoundHandler" 41 } 42 if ptr == handlerPointer(echo.MethodNotAllowedHandler) { 43 return "MethodNotAllowedHandler" 44 } 45 return c.Path() 46 } 47 48 // Middleware creates Echo middleware that instruments requests. 49 // 50 // e := echo.New() 51 // // Add the nrecho middleware before other middlewares or routes: 52 // e.Use(nrecho.Middleware(app)) 53 // 54 func Middleware(app newrelic.Application) func(echo.HandlerFunc) echo.HandlerFunc { 55 56 if nil == app { 57 return func(next echo.HandlerFunc) echo.HandlerFunc { 58 return next 59 } 60 } 61 62 return func(next echo.HandlerFunc) echo.HandlerFunc { 63 return func(c echo.Context) (err error) { 64 rw := c.Response().Writer 65 txn := app.StartTransaction(transactionName(c), rw, c.Request()) 66 defer txn.End() 67 68 c.Response().Writer = txn 69 70 // Add txn to c.Request().Context() 71 c.SetRequest(c.Request().WithContext(newrelic.NewContext(c.Request().Context(), txn))) 72 73 err = next(c) 74 75 // Record the response code. The response headers are not captured 76 // in this case because they are set after this middleware returns. 77 // Designed to mimic the logic in echo.DefaultHTTPErrorHandler. 78 if nil != err && !c.Response().Committed { 79 80 txn.SetWebResponse(nil) 81 c.Response().Writer = rw 82 83 if httperr, ok := err.(*echo.HTTPError); ok { 84 txn.WriteHeader(httperr.Code) 85 } else { 86 txn.WriteHeader(http.StatusInternalServerError) 87 } 88 } 89 90 return 91 } 92 } 93 }