自定义上下文 SQL Log 需求有哪些
- 可以使用自己的封装日志库,拓展日志输出问题,可以输出到 es(elasticsearch)等,方便日志分析。
- 方便定位 sql 问题。
- 集成 sql 指标监控,可以找出慢 sql,优化 sql 语句。
- 集成链路追踪(opentracing),更清楚知道业务都执行了哪些 sql 语句。
前提是 xorm 对应版本要求 >=1.0 以上的
先看下 xorm ContextLogger interface 是什么样的?https://pkg.go.dev/xorm.io/xorm/log?tab=doc#ContextLogger
type SQLLogger interface { BeforeSQL(context LogContext) // only invoked when IsShowSQL is true AfterSQL(context LogContext) // only invoked when IsShowSQL is true } type ContextLogger interface { SQLLogger // 内嵌接口,主要实现这个接口,需要开启sql 输出。 Debugf(format string, v ...interface{}) Errorf(format string, v ...interface{}) Infof(format string, v ...interface{}) Warnf(format string, v ...interface{}) Level() LogLevel // 日志等级 SetLevel(l LogLevel) // 设置日志等级 ShowSQL(show ...bool) IsShowSQL() bool }
接下来就实现以上这些接口即可。以 logrus log 库为例, 简单实现一下。
-
golang 版本使用 go 1.13+ 以上版本, 并开启 go mod。
export GONOPROXY="xorm.io" export GOPROXY="https://goproxy.cn,direct" go get xorm.i/xorm@v1.0.0
-
golang 日志库选择其一
目前比较使用多的日志库 logrus, zap 等开源日志库。性能都比较好,结合自己的需求,选择合适的日志库。logrus[1] doc[2]
zap[3] doc[4]
-
安装 logrus 库依赖
go get github.com/sirupsen/logrus
关键代码实现, 需要注意的是 ContextLogger 这个接口必须都要重新实现一遍。
type LogCtx struct { logger *logrus.Logger showSQL bool } func NewLogCtx(l *logrus.Logger) *LogCtx { return &LogCtx{logger: l} } // 可自行实现, sql 执行之前操作 func (l *LogCtx) BeforeSQL(ctx xormlog.LogContext) {} func (l *LogCtx) AfterSQL(ctx xormlog.LogContext) { // 转成完整sql, 方面查看。如果不需要输出完整sql的拼接。 可以直接输出,看下面注释这行即可。 // l.logger.Errorf("[SQL] %v %v - %v", ctx.SQL, ctx.Args, ctx.ExecuteTime) fullSqlStr, err := builder.ConvertToBoundSQL(ctx.SQL, ctx.Args) if err != nil { l.logger.Errorf("[SQL] %v %v - %v", ctx.SQL, ctx.Args, ctx.ExecuteTime) } else { l.logger.Infof("[SQL] %s - %v", fullSqlStr, ctx.ExecuteTime) } } func (l *LogCtx) Debugf(format string, v ...interface{}) { l.logger.Debugf(format, v...) } func (l *LogCtx) Errorf(format string, v ...interface{}) { l.logger.Errorf(format, v...) } func (l *LogCtx) Infof(format string, v ...interface{}) { l.logger.Infof(format, v...) } func (l *LogCtx) Warnf(format string, v ...interface{}) { l.logger.Warnf(format, v...) } func (l *LogCtx) Level() xormlog.LogLevel { return logrus2xormlogLevel[l.logger.GetLevel()] } func (l *LogCtx) SetLevel(lv xormlog.LogLevel) { l.logger.SetLevel(xormlog2logrusLevel[lv]) } func (l *LogCtx) ShowSQL(show ...bool) { if len(show) == 0 { l.showSQL = true return } l.showSQL = show[0] } func (l *LogCtx) IsShowSQL() bool { return l.showSQL }
调用示例 main.go
// mysql 实例 func NewMySQL() *xorm.Engine { engine, err := xorm.NewEngine("mysql", "dsn") if err != nil { panic(err) } logs := logrus.New() // 使用自定义日志实现 logctx := xormlog.NewLogCtx(logs) engine.SetLogger(logctx) // 需要开启sql输出 engine.ShowSQL(true) return engine }
完整代码实现链接:xormlog[5]
总结
当然这个 sql 日志实现输出是同步的。如果有影响到返回业务数据的性能,可以改成异步输出 sql 日志。
扫码二维码 获取免费视频学习资料
- 本文固定链接: http://www.phpxs.com/post/7240/
- 转载请注明:转载必须在正文中标注并保留原文链接
- 扫码: 扫上方二维码获取免费视频资料
查 看2022高级编程视频教程免费获取