打造 Zap 开箱即用日志组件(打造娱乐帝国 万乘北宸)
1374
2022-08-19
项目使用了 ORM,具体执行的是什么 SQL 语句总是很迷?xorm1.0 解决了(使用其他项目)
昨天有人问,能不能讲讲 xorm,于是今天先来一篇简单的。
自定义上下文 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-,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 日志。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~