mysql.go 3.7 KB

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