go - 如何在golang中为new relic(Golang New relic integration)创建通用或全局上下文?

标签 go newrelic

我正在 main.go 中创建新的 relic 事务,并且必须将它传递给处理程序,然后传递给 Controller ​​等等。有没有办法可以全局定义它,然后可以在任何处理程序、 Controller 或数据库事务中访问它?

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 
}


最佳答案

避免使用全局上下文,而是在入口点创建一个,然后将其作为参数传递给任何需要它的函数。
您可以使用 nrgin Gin 框架提供的包。
而在 main()功能

  • 创建 newrelic 的实例 - newrelic.NewApplication(cfg)
  • 调用 - nrgin.Middleware(app)传入 newrelic 实例的函数。这将添加 Gin 事务上下文键 - newRelicTransaction到上下文。
  • 将步骤 2 中的函数注册为所有路由的中间件 - router.Use(nrgin.Middleware(app))

  • 然后,您可以将这个相同的上下文对象传递给可以接受 context.Context 类型参数的其他函数。自 gin.Context只是实现 context Go的界面。
    示例代码
    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...")
    }
    

    关于go - 如何在golang中为new relic(Golang New relic integration)创建通用或全局上下文?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69523822/

    相关文章:

    go - 使用 Go/Negroni/Gorilla Mux 从静态 url 提供文件

    newrelic - 我可以将字符串发送到 New Relic 吗?

    android - 没有安装 newrelic 的应用程序上的 NoClassDefFoundError

    ruby-on-rails - 如何使用NewRelic监控Rails异常

    node.js - 新的遗迹网络交易出现在根目录下

    go - 使用 goavro 处理多种类型的解码数据

    go - 来自不同文件的全局变量 Golang

    go - 为什么 struct Client(在 coreos/etcd/clientv3/client.go 中)有 PUT 方法

    git - 如何以编程方式找到两个分支的共同祖先

    nginx - 如何使用 stub_status 创建/status