golang使用elasticsearch APM简单实现数据库查询GORM时间线
前提
在用golang使用elasticsearch APM之前需要部署好elastic、kibana和apm-server,这些与其他方式使用apm一致,网上有许多教程,不再赘述
第一步初始化gin,并连接apm全局中间件
我们首先初始化gin,代码如下
package main
import (
"github.com/gin-gonic/gin"
"go.elastic.co/apm/module/apmgin"
"net/http"
)
func HttpInit() error {
Engine := gin.New()
//加上apm
Engine.Use(apmgin.Middleware(Engine))
Server := &http.Server{
Addr: ":8111",
Handler: Engine,
}
Engine.GET("/apmGormTest", apmGormTest)
// 线程执行
go func() {
err := Server.ListenAndServe()
if nil != err {
panic(err)
}
}()
return nil
}
//处理http请求
func apmGormTest(c *gin.Context) {
mes := GetMysqlData(c)
c.JSON(http.StatusOK, mes)
}
其中连接apm中间件的主要实现代码为:
apmgin需要我们导入包"go.elastic.co/apm/module/apmgin"
Engine.Use(apmgin.Middleware(Engine))
代码中func apmGormTest是我们处理http接口的方法,其中GetMysqlData()是从数据库取数据的方法,这个我们等下实现。
第二步初始化数据库配置
注意初始化数据库我们使用"go.elastic.co/apm/module/apmgorm"包
的apmgorm.Open方法,代码如下:
package main
import (
"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm"
"go.elastic.co/apm/module/apmgin"
"net/http"
"go.elastic.co/apm/module/apmgorm"
_ "go.elastic.co/apm/module/apmgorm/dialects/mysql"
)
var Db *gorm.DB
func DatabaseInit() (err error) {
//注意使用apmgorm,且dialects也要导入"go.elastic.co/apm/module/apmgorm/dialects/mysql"
Db, err = apmgorm.Open("mysql", "root:123456@tcp(192.168.177.1:3306)/world?charset=utf8&parseTime=True&loc=Local")
if err != nil {
return err
}
return nil
}
接着我们需要导入驱动包,注意这里的驱动包也需要导入apm封装好的包:
_ "go.elastic.co/apm/module/apmgorm/dialects/mysql"
第三步实现数据库读取数据,并将数据库读取数据操作加入http请求上下文
简单实现上面的GetMysqlData()读取数据库方法
其中需要传入http请求的上下文*gin.Context
// 数据库获取数据
func GetMysqlData(c *gin.Context) string {
var value []string
//为数据库请求绑定时间线
db := apmgorm.WithContext(c.Request.Context(), Db)
db.Table("country").Select("Name").Where("Code = ?", "CHN").Pluck("Name", &value)
if value != nil {
return value[0]
}
return ""
}
并将数据库请求操作绑定http请求的上下文
db := apmgorm.WithContext(c.Request.Context(), Db)
实现main方法
实现main方法后整体实现代码如下:
package main
import (
"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm"
"go.elastic.co/apm/module/apmgin"
"net/http"
"go.elastic.co/apm/module/apmgorm"
_ "go.elastic.co/apm/module/apmgorm/dialects/mysql"
)
var Db *gorm.DB
func HttpInit() error {
Engine := gin.New()
//加上apm
Engine.Use(apmgin.Middleware(Engine))
Server := &http.Server{
Addr: ":8111",
Handler: Engine,
}
Engine.GET("/apmGormTest", apmGormTest)
// 线程执行
go func() {
err := Server.ListenAndServe()
if nil != err {
panic(err)
}
}()
return nil
}
//处理http请求
func apmGormTest(c *gin.Context) {
mes := GetMysqlData(c)
c.JSON(http.StatusOK, mes)
}
func DatabaseInit() (err error) {
//注意使用apmgorm,且dialects也要导入"go.elastic.co/apm/module/apmgorm/dialects/mysql"
Db, err = apmgorm.Open("mysql", "root:123456@tcp(192.168.177.1:3306)/world?charset=utf8&parseTime=True&loc=Local")
if err != nil {
return err
}
return nil
}
// 数据库获取数据
func GetMysqlData(c *gin.Context) string {
var value []string
//为数据库请求绑定时间线
db := apmgorm.WithContext(c.Request.Context(), Db)
db.Table("country").Select("Name").Where("Code = ?", "CHN").Pluck("Name", &value)
if value != nil {
return value[0]
}
return ""
}
func main() {
//初始化http配置
err := HttpInit()
//初始化数据库配置
err = DatabaseInit()
if err != nil{
panic(err)
}
//让程序阻塞
c := make(chan int)
<-c
}
打包测试
打包我们的程序,在运行的时候,填上apm-server的地址就可以连接apm-server了,如下:
./apm-test -ELASTIC_APM_SERVICE_NAME=apmtest -ELASTIC_APM_SERVER_URL=127.0.0.1:8200
apm-test是我们打包好的程序包,ELASTIC_APM_SERVER_URL参数值为apm-server地址
结果
调用我们定义好的接口/apmGormTest,我们可以在kibana中看到生成的时间线,其中就有数据库服务操作:
注意点
1、数据库驱动也需要使用apm封装好的包"go.elastic.co/apm/module/apmgorm/dialects/mysql"
2、数据库查询操作需要绑定http请求的上下文db := apmgorm.WithContext(c.Request.Context(), Db)