To gitea and beyond, let's go(-yco)
This commit is contained in:
190
internal/database/monitoring_plugin.go
Normal file
190
internal/database/monitoring_plugin.go
Normal file
@@ -0,0 +1,190 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"goyco/internal/middleware"
|
||||
)
|
||||
|
||||
type contextKey string
|
||||
|
||||
const gormOperationStartKey contextKey = "gorm_operation_start"
|
||||
|
||||
type GormDBMonitor struct {
|
||||
monitor middleware.DBMonitor
|
||||
}
|
||||
|
||||
func NewGormDBMonitor(monitor middleware.DBMonitor) *GormDBMonitor {
|
||||
return &GormDBMonitor{
|
||||
monitor: monitor,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GormDBMonitor) Name() string {
|
||||
return "db_monitor"
|
||||
}
|
||||
|
||||
func (g *GormDBMonitor) Initialize(db *gorm.DB) error {
|
||||
|
||||
db.Callback().Create().Before("gorm:create").Register("db_monitor:before_create", g.beforeCreate)
|
||||
db.Callback().Create().After("gorm:create").Register("db_monitor:after_create", g.afterCreate)
|
||||
|
||||
db.Callback().Query().Before("gorm:query").Register("db_monitor:before_query", g.beforeQuery)
|
||||
db.Callback().Query().After("gorm:query").Register("db_monitor:after_query", g.afterQuery)
|
||||
|
||||
db.Callback().Update().Before("gorm:update").Register("db_monitor:before_update", g.beforeUpdate)
|
||||
db.Callback().Update().After("gorm:update").Register("db_monitor:after_update", g.afterUpdate)
|
||||
|
||||
db.Callback().Delete().Before("gorm:delete").Register("db_monitor:before_delete", g.beforeDelete)
|
||||
db.Callback().Delete().After("gorm:delete").Register("db_monitor:after_delete", g.afterDelete)
|
||||
|
||||
db.Callback().Row().Before("gorm:row").Register("db_monitor:before_row", g.beforeRow)
|
||||
db.Callback().Row().After("gorm:row").Register("db_monitor:after_row", g.afterRow)
|
||||
|
||||
db.Callback().Raw().Before("gorm:raw").Register("db_monitor:before_raw", g.beforeRaw)
|
||||
db.Callback().Raw().After("gorm:raw").Register("db_monitor:after_raw", g.afterRaw)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *GormDBMonitor) beforeCreate(db *gorm.DB) {
|
||||
if g.monitor == nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.WithValue(db.Statement.Context, gormOperationStartKey, time.Now())
|
||||
db.Statement.Context = ctx
|
||||
}
|
||||
|
||||
func (g *GormDBMonitor) afterCreate(db *gorm.DB) {
|
||||
if g.monitor == nil {
|
||||
return
|
||||
}
|
||||
|
||||
g.logOperation(db, "CREATE")
|
||||
}
|
||||
|
||||
func (g *GormDBMonitor) beforeQuery(db *gorm.DB) {
|
||||
if g.monitor == nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.WithValue(db.Statement.Context, gormOperationStartKey, time.Now())
|
||||
db.Statement.Context = ctx
|
||||
}
|
||||
|
||||
func (g *GormDBMonitor) afterQuery(db *gorm.DB) {
|
||||
if g.monitor == nil {
|
||||
return
|
||||
}
|
||||
|
||||
g.logOperation(db, "SELECT")
|
||||
}
|
||||
|
||||
func (g *GormDBMonitor) beforeUpdate(db *gorm.DB) {
|
||||
if g.monitor == nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.WithValue(db.Statement.Context, gormOperationStartKey, time.Now())
|
||||
db.Statement.Context = ctx
|
||||
}
|
||||
|
||||
func (g *GormDBMonitor) afterUpdate(db *gorm.DB) {
|
||||
if g.monitor == nil {
|
||||
return
|
||||
}
|
||||
|
||||
g.logOperation(db, "UPDATE")
|
||||
}
|
||||
|
||||
func (g *GormDBMonitor) beforeDelete(db *gorm.DB) {
|
||||
if g.monitor == nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.WithValue(db.Statement.Context, gormOperationStartKey, time.Now())
|
||||
db.Statement.Context = ctx
|
||||
}
|
||||
|
||||
func (g *GormDBMonitor) afterDelete(db *gorm.DB) {
|
||||
if g.monitor == nil {
|
||||
return
|
||||
}
|
||||
|
||||
g.logOperation(db, "DELETE")
|
||||
}
|
||||
|
||||
func (g *GormDBMonitor) beforeRow(db *gorm.DB) {
|
||||
if g.monitor == nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.WithValue(db.Statement.Context, gormOperationStartKey, time.Now())
|
||||
db.Statement.Context = ctx
|
||||
}
|
||||
|
||||
func (g *GormDBMonitor) afterRow(db *gorm.DB) {
|
||||
if g.monitor == nil {
|
||||
return
|
||||
}
|
||||
|
||||
g.logOperation(db, "ROW")
|
||||
}
|
||||
|
||||
func (g *GormDBMonitor) beforeRaw(db *gorm.DB) {
|
||||
if g.monitor == nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.WithValue(db.Statement.Context, gormOperationStartKey, time.Now())
|
||||
db.Statement.Context = ctx
|
||||
}
|
||||
|
||||
func (g *GormDBMonitor) afterRaw(db *gorm.DB) {
|
||||
if g.monitor == nil {
|
||||
return
|
||||
}
|
||||
|
||||
g.logOperation(db, "RAW")
|
||||
}
|
||||
|
||||
func (g *GormDBMonitor) logOperation(db *gorm.DB, operation string) {
|
||||
if g.monitor == nil {
|
||||
return
|
||||
}
|
||||
|
||||
startTime, ok := db.Statement.Context.Value(gormOperationStartKey).(time.Time)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
duration := time.Since(startTime)
|
||||
|
||||
query := g.buildQueryString(db, operation)
|
||||
|
||||
g.monitor.LogQuery(query, duration, db.Error)
|
||||
}
|
||||
|
||||
func (g *GormDBMonitor) buildQueryString(db *gorm.DB, operation string) string {
|
||||
if db.Statement.SQL.String() != "" {
|
||||
return db.Statement.SQL.String()
|
||||
}
|
||||
|
||||
query := operation
|
||||
|
||||
if db.Statement.Table != "" {
|
||||
query += " FROM " + db.Statement.Table
|
||||
}
|
||||
|
||||
if db.Statement.Model != nil {
|
||||
|
||||
if stmt := db.Statement; stmt.Schema != nil {
|
||||
query = operation + " " + stmt.Schema.Table
|
||||
}
|
||||
}
|
||||
|
||||
return query
|
||||
}
|
||||
Reference in New Issue
Block a user