如何在 golang 中为 new relic(Golang New relic 集成)创建通用或全局上下文?
How to create generic or global context in golang for new relic (Golang New relic integration)?
我正在 main.go 中创建新的遗物交易,必须将其传递给处理程序,然后传递给控制器,依此类推。有没有一种方法可以全局定义它,然后可以在任何处理程序、控制器或数据库事务中访问?
import(
"github.com/gin-gonic/gin"
newrelic "github.com/newrelic/go-agent"
)
// main.go
func newrelicHandler() (gin.HandlerFunc, newrelic.Application) {
newrelicConfig := newrelic.NewConfig("NEW_RELIC_APP_NAME", "NEW_RELIC_APP_KEY")
app, err := newrelic.NewApplication(newrelicConfig)
if err != nil {
return func(c *gin.Context) {
c.Next()
}, app
}
return func(c *gin.Context) {
txn := app.StartTransaction(c.Request.URL.Path, c.Writer, c.Request)
c.Set("newRelicTransaction", txn)
apm, ok := c.Get("newRelicTransaction")
defer txn.End()
c.Next()
}, app
}
func main() {
r := gin.New()
x, app := newrelicHandler()
r.Use(x)
}
// test/handler.go
func (t *TestHandler) Display(c *gin.Context) {
apmTxn, ok := c.Get("newRelicTransaction")
test, err := t.testCtrl.Display(apmTxn)
if err != nil {
return err
}
c.JSON(http.StatusOK, gin.H{"message": "success"})
}
// test/controller.go
func (t *TestCtrl) Display(txn interface{}) {
apmTxn, ok := txn.(newrelic.Transaction)
if !ok {
fmt.Println("ERR")
}
segment := newrelic.StartSegment(apmTxn, "SomeSegmentName")
// get data
segment.End()
return
}
避免使用全局上下文,而是在入口点创建一个,然后将其作为参数传递给任何需要它的函数。
您可以使用 Gin 框架提供的 nrgin
包。
并且在main()
函数中
- 创建 newrelic 实例 -
newrelic.NewApplication(cfg)
- 调用传入newrelic实例的-
nrgin.Middleware(app)
函数。这会将 Gin 事务上下文键 - newRelicTransaction
添加到上下文中。
- 将步骤 2 中的函数注册为所有路由的中间件 -
router.Use(nrgin.Middleware(app))
然后您可以将相同的上下文对象传递给可以接受类型 context.Context
参数的其他函数,因为 gin.Context
只是实现了 Go 的 context
接口。
示例代码
import "github.com/newrelic/go-agent/_integrations/nrgin/v1"
func main() {
cfg := newrelic.NewConfig("Gin App", mustGetEnv("NEW_RELIC_LICENSE_KEY"))
app, err := newrelic.NewApplication(cfg)
if nil != err {
fmt.Println(err)
}
router := gin.Default()
router.Use(nrgin.Middleware(app))
router.GET("/example-get", GetController)
router.Run(":80")
}
func GetController(c *gin.Context) {
if txn := nrgin.Transaction(c); nil != txn {
txn.SetName("custom-name")
}
databaseGet(c)
c.Writer.WriteString("example response...")
}
func databaseGet(c context.Context) {
if txn := nrgin.Transaction(c); nil != txn {
txn.SetName("custom-name")
}
c.Writer.WriteString("example response...")
}
我正在 main.go 中创建新的遗物交易,必须将其传递给处理程序,然后传递给控制器,依此类推。有没有一种方法可以全局定义它,然后可以在任何处理程序、控制器或数据库事务中访问?
import(
"github.com/gin-gonic/gin"
newrelic "github.com/newrelic/go-agent"
)
// main.go
func newrelicHandler() (gin.HandlerFunc, newrelic.Application) {
newrelicConfig := newrelic.NewConfig("NEW_RELIC_APP_NAME", "NEW_RELIC_APP_KEY")
app, err := newrelic.NewApplication(newrelicConfig)
if err != nil {
return func(c *gin.Context) {
c.Next()
}, app
}
return func(c *gin.Context) {
txn := app.StartTransaction(c.Request.URL.Path, c.Writer, c.Request)
c.Set("newRelicTransaction", txn)
apm, ok := c.Get("newRelicTransaction")
defer txn.End()
c.Next()
}, app
}
func main() {
r := gin.New()
x, app := newrelicHandler()
r.Use(x)
}
// test/handler.go
func (t *TestHandler) Display(c *gin.Context) {
apmTxn, ok := c.Get("newRelicTransaction")
test, err := t.testCtrl.Display(apmTxn)
if err != nil {
return err
}
c.JSON(http.StatusOK, gin.H{"message": "success"})
}
// test/controller.go
func (t *TestCtrl) Display(txn interface{}) {
apmTxn, ok := txn.(newrelic.Transaction)
if !ok {
fmt.Println("ERR")
}
segment := newrelic.StartSegment(apmTxn, "SomeSegmentName")
// get data
segment.End()
return
}
避免使用全局上下文,而是在入口点创建一个,然后将其作为参数传递给任何需要它的函数。
您可以使用 Gin 框架提供的 nrgin
包。
并且在main()
函数中
- 创建 newrelic 实例 -
newrelic.NewApplication(cfg)
- 调用传入newrelic实例的-
nrgin.Middleware(app)
函数。这会将 Gin 事务上下文键 -newRelicTransaction
添加到上下文中。 - 将步骤 2 中的函数注册为所有路由的中间件 -
router.Use(nrgin.Middleware(app))
然后您可以将相同的上下文对象传递给可以接受类型 context.Context
参数的其他函数,因为 gin.Context
只是实现了 Go 的 context
接口。
示例代码
import "github.com/newrelic/go-agent/_integrations/nrgin/v1"
func main() {
cfg := newrelic.NewConfig("Gin App", mustGetEnv("NEW_RELIC_LICENSE_KEY"))
app, err := newrelic.NewApplication(cfg)
if nil != err {
fmt.Println(err)
}
router := gin.Default()
router.Use(nrgin.Middleware(app))
router.GET("/example-get", GetController)
router.Run(":80")
}
func GetController(c *gin.Context) {
if txn := nrgin.Transaction(c); nil != txn {
txn.SetName("custom-name")
}
databaseGet(c)
c.Writer.WriteString("example response...")
}
func databaseGet(c context.Context) {
if txn := nrgin.Transaction(c); nil != txn {
txn.SetName("custom-name")
}
c.Writer.WriteString("example response...")
}