mysql.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. package base
  2. import (
  3. "fmt"
  4. "github.com/gin-gonic/gin"
  5. _ "github.com/go-sql-driver/mysql"
  6. "github.com/opentracing/opentracing-go"
  7. "github.com/opentracing/opentracing-go/ext"
  8. "time"
  9. )
  10. const SqlTraceContextKey = "traceContext"
  11. type MysqlConf struct {
  12. User string
  13. Password string
  14. Addr string
  15. DataBase string
  16. MaxIdleConns int
  17. MaxOpenConns int
  18. ConnMaxLifeTime time.Duration
  19. LogMode bool
  20. }
  21. // InitMysqlClient 一定要在bootstrap之后
  22. func InitMysqlClient(conf MysqlConf) (client *gorm.DB, err error) {
  23. client, err = gorm.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Asia%%2FShanghai",
  24. conf.User,
  25. conf.Password,
  26. conf.Addr,
  27. conf.DataBase))
  28. if err != nil {
  29. return client, err
  30. }
  31. client.DB().SetMaxIdleConns(conf.MaxIdleConns)
  32. client.DB().SetMaxOpenConns(conf.MaxOpenConns)
  33. client.DB().SetConnMaxLifetime(conf.ConnMaxLifeTime)
  34. client.LogMode(conf.LogMode)
  35. // register tracer callback
  36. setCallback(client, "create")
  37. setCallback(client, "delete")
  38. setCallback(client, "update")
  39. setCallback(client, "query")
  40. setCallback(client, "row_query")
  41. return client, nil
  42. }
  43. func setCallback(client *gorm.DB, callbackName string) {
  44. beforeName := fmt.Sprintf("tracer:%v_before", callbackName)
  45. afterName := fmt.Sprintf("tracer:%v_after", callbackName)
  46. gormCallbackName := fmt.Sprintf("gorm:%v", callbackName)
  47. switch callbackName {
  48. case "create":
  49. client.Callback().Create().Before(gormCallbackName).Register(beforeName, func(scope *gorm.Scope) {
  50. tracerBefore(scope, callbackName)
  51. })
  52. client.Callback().Create().After(gormCallbackName).Register(afterName, func(scope *gorm.Scope) {
  53. tracerAfter(scope, callbackName)
  54. })
  55. case "query":
  56. client.Callback().Query().Before(gormCallbackName).Register(beforeName, func(scope *gorm.Scope) {
  57. tracerBefore(scope, callbackName)
  58. })
  59. client.Callback().Query().After(gormCallbackName).Register(afterName, func(scope *gorm.Scope) {
  60. tracerAfter(scope, callbackName)
  61. })
  62. case "update":
  63. client.Callback().Update().Before(gormCallbackName).Register(beforeName, func(scope *gorm.Scope) {
  64. tracerBefore(scope, callbackName)
  65. })
  66. client.Callback().Update().After(gormCallbackName).Register(afterName, func(scope *gorm.Scope) {
  67. tracerAfter(scope, callbackName)
  68. })
  69. case "delete":
  70. client.Callback().Delete().Before(gormCallbackName).Register(beforeName, func(scope *gorm.Scope) {
  71. tracerBefore(scope, callbackName)
  72. })
  73. client.Callback().Delete().After(gormCallbackName).Register(afterName, func(scope *gorm.Scope) {
  74. tracerAfter(scope, callbackName)
  75. })
  76. case "row_query":
  77. client.Callback().RowQuery().Before(gormCallbackName).Register(beforeName, func(scope *gorm.Scope) {
  78. tracerBefore(scope, callbackName)
  79. })
  80. client.Callback().RowQuery().After(gormCallbackName).Register(afterName, func(scope *gorm.Scope) {
  81. tracerAfter(scope, callbackName)
  82. })
  83. }
  84. }
  85. func tracerBefore(scope *gorm.Scope, callbackName string) {
  86. ctx, ok := scope.Search.GetCtx().(*gin.Context)
  87. if !ok {
  88. return
  89. }
  90. var parentSpanContext opentracing.SpanContext
  91. if ctx != nil {
  92. tempSpan, exist := ctx.Get(TraceContextKey)
  93. if exist {
  94. parentSpanContext = tempSpan.(opentracing.Span).Context()
  95. }
  96. }
  97. span := TracerStartSpan(parentSpanContext, "DB_"+callbackName, map[string]interface{}{
  98. ext.SpanKindRPCClient.Key: ext.SpanKindRPCClient,
  99. string(ext.Component): "gorm",
  100. string(ext.DBInstance): scope.InstanceID(),
  101. string(ext.DBType): "mysql",
  102. })
  103. scope.Set(SqlTraceContextKey, span)
  104. }
  105. func tracerAfter(scope *gorm.Scope, callbackName string) {
  106. tempSpan, exist := scope.Get(SqlTraceContextKey)
  107. if !exist {
  108. return
  109. }
  110. span := tempSpan.(opentracing.Span)
  111. span.SetTag(string(ext.DBStatement), scope.SQL)
  112. span.Finish()
  113. }