Skip to content

Commit

Permalink
feat: [#473] ORM has its own logger instead of using facades.Log() (#781
Browse files Browse the repository at this point in the history
)

* feat: [#473] ORM has its own logger instead of using facades.Log()

* fix test

* fix test

* remove with

* fix test
  • Loading branch information
hwbrzzl authored Dec 21, 2024
1 parent 3e77574 commit 9b776be
Show file tree
Hide file tree
Showing 8 changed files with 380 additions and 168 deletions.
24 changes: 6 additions & 18 deletions database/gorm/gorm.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
package gorm

import (
"log"
"os"
"time"

gormio "gorm.io/gorm"
gormlogger "gorm.io/gorm/logger"
"gorm.io/gorm/schema"
"gorm.io/plugin/dbresolver"

"github.com/goravel/framework/contracts/config"
"github.com/goravel/framework/contracts/database"
"github.com/goravel/framework/contracts/log"
"github.com/goravel/framework/errors"
"github.com/goravel/framework/support/carbon"
)
Expand All @@ -20,12 +18,14 @@ type Builder struct {
config config.Config
configBuilder database.ConfigBuilder
instance *gormio.DB
log log.Log
}

func NewGorm(config config.Config, configBuilder database.ConfigBuilder) (*gormio.DB, error) {
func NewGorm(config config.Config, configBuilder database.ConfigBuilder, log log.Log) (*gormio.DB, error) {
builder := &Builder{
config: config,
configBuilder: configBuilder,
log: log,
}

return builder.Build()
Expand Down Expand Up @@ -99,23 +99,11 @@ func (r *Builder) init(fullConfig database.FullConfig) error {
return errors.OrmNoDialectorsFound
}

var logLevel gormlogger.LogLevel
if r.config.GetBool("app.debug") {
logLevel = gormlogger.Info
} else {
logLevel = gormlogger.Error
}

logger := NewLogger(log.New(os.Stdout, "\r\n", log.LstdFlags), gormlogger.Config{
SlowThreshold: 200 * time.Millisecond,
LogLevel: gormlogger.Info,
IgnoreRecordNotFoundError: true,
Colorful: true,
})
logger := NewLogger(r.config, r.log)
instance, err := gormio.Open(dialectors[0], &gormio.Config{
DisableForeignKeyConstraintWhenMigrating: true,
SkipDefaultTransaction: true,
Logger: logger.LogMode(logLevel),
Logger: logger,
NowFunc: func() time.Time {
return carbon.Now().StdTime()
},
Expand Down
100 changes: 46 additions & 54 deletions database/gorm/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package gorm

import (
"context"
"fmt"
"net"
"regexp"
"runtime"
Expand All @@ -12,70 +11,58 @@ import (

"gorm.io/gorm/logger"

"github.com/goravel/framework/contracts/config"
"github.com/goravel/framework/contracts/log"
"github.com/goravel/framework/errors"
)

func NewLogger(writer logger.Writer, config logger.Config) logger.Interface {
var (
infoStr = "%s\n[Orm] "
warnStr = "%s\n[Orm] "
errStr = "%s\n[Orm] "
traceStr = "%s\n[%.3fms] [rows:%v] %s"
traceWarnStr = "%s %s\n[%.3fms] [rows:%v] %s"
traceErrStr = "%s %s\n[%.3fms] [rows:%v] %s"
)
func NewLogger(config config.Config, log log.Log) logger.Interface {
level := logger.Warn
if config.GetBool("app.debug") {
level = logger.Info
}

if config.Colorful {
infoStr = logger.Green + "%s\n" + logger.Reset + logger.Green + "[Orm] " + logger.Reset
warnStr = logger.BlueBold + "%s\n" + logger.Reset + logger.Magenta + "[Orm] " + logger.Reset
errStr = logger.Magenta + "%s\n" + logger.Reset + logger.Red + "[Orm] " + logger.Reset
traceStr = logger.Green + "%s\n" + logger.Reset + logger.Yellow + "[%.3fms] " + logger.BlueBold + "[rows:%v]" + logger.Reset + " %s"
traceWarnStr = logger.Green + "%s " + logger.Yellow + "%s\n" + logger.Reset + logger.RedBold + "[%.3fms] " + logger.Yellow + "[rows:%v]" + logger.Magenta + " %s" + logger.Reset
traceErrStr = logger.RedBold + "%s " + logger.MagentaBold + "%s\n" + logger.Reset + logger.Yellow + "[%.3fms] " + logger.BlueBold + "[rows:%v]" + logger.Reset + " %s"
slowThreshold := config.GetInt("database.slow_threshold", 200)
if slowThreshold <= 0 {
slowThreshold = 200
}

return &Logger{
Writer: writer,
Config: config,
infoStr: infoStr,
warnStr: warnStr,
errStr: errStr,
traceStr: traceStr,
traceWarnStr: traceWarnStr,
traceErrStr: traceErrStr,
log: log,
level: level,
slowThreshold: time.Duration(slowThreshold) * time.Millisecond,
}
}

type Logger struct {
logger.Writer
logger.Config
infoStr, warnStr, errStr string
traceStr, traceErrStr, traceWarnStr string
log log.Log
level logger.LogLevel
slowThreshold time.Duration
}

// LogMode log mode
func (l *Logger) LogMode(level logger.LogLevel) logger.Interface {
newlogger := *l
newlogger.LogLevel = level
return &newlogger
func (r *Logger) LogMode(level logger.LogLevel) logger.Interface {
r.level = level

return r
}

// Info print info
func (l Logger) Info(ctx context.Context, msg string, data ...any) {
if l.LogLevel >= logger.Info {
l.Printf(l.infoStr+msg, append([]any{FileWithLineNum()}, data...)...)
func (r *Logger) Info(ctx context.Context, msg string, data ...any) {
if r.level >= logger.Info {
r.log.Infof(msg, data...)
}
}

// Warn print warn messages
func (l Logger) Warn(ctx context.Context, msg string, data ...any) {
if l.LogLevel >= logger.Warn {
l.Printf(l.warnStr+msg, append([]any{FileWithLineNum()}, data...)...)
func (r *Logger) Warn(ctx context.Context, msg string, data ...any) {
if r.level >= logger.Warn {
r.log.Warningf(msg, data...)
}
}

// Error print error messages
func (l Logger) Error(ctx context.Context, msg string, data ...any) {
func (r *Logger) Error(ctx context.Context, msg string, data ...any) {
// Let upper layer function deals with connection refused error
var cancel bool
for _, item := range data {
Expand All @@ -97,40 +84,45 @@ func (l Logger) Error(ctx context.Context, msg string, data ...any) {
return
}

if l.LogLevel >= logger.Error {
l.Printf(l.errStr+msg, append([]any{FileWithLineNum()}, data...)...)
if r.level >= logger.Error {
r.log.Errorf(msg, data...)
}
}

// Trace print sql message
func (l Logger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
if l.LogLevel <= logger.Silent {
func (r *Logger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
if r.level <= logger.Silent {
return
}

var (
traceStr = "[%.3fms] [rows:%v] %s"
traceWarnStr = "[%.3fms] [rows:%v] [SLOW] %s"
traceErrStr = "[%.3fms] [rows:%v] %s\t%s"
)

elapsed := time.Since(begin)
switch {
case err != nil && l.LogLevel >= logger.Error && (!errors.Is(err, logger.ErrRecordNotFound) || !l.IgnoreRecordNotFoundError):
case err != nil && r.level >= logger.Error && !errors.Is(err, logger.ErrRecordNotFound):
sql, rows := fc()
if rows == -1 {
l.Printf(l.traceErrStr, FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, "-", sql)
r.log.Errorf(traceErrStr, float64(elapsed.Nanoseconds())/1e6, "-", sql, err)
} else {
l.Printf(l.traceErrStr, FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, rows, sql)
r.log.Errorf(traceErrStr, float64(elapsed.Nanoseconds())/1e6, rows, sql, err)
}
case elapsed > l.SlowThreshold && l.SlowThreshold != 0 && l.LogLevel >= logger.Warn:
case elapsed > r.slowThreshold && r.slowThreshold != 0 && r.level >= logger.Warn:
sql, rows := fc()
slowLog := fmt.Sprintf("SLOW SQL >= %v", l.SlowThreshold)
if rows == -1 {
l.Printf(l.traceWarnStr, FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, "-", sql)
r.log.Warningf(traceWarnStr, float64(elapsed.Nanoseconds())/1e6, "-", sql)
} else {
l.Printf(l.traceWarnStr, FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, rows, sql)
r.log.Warningf(traceWarnStr, float64(elapsed.Nanoseconds())/1e6, rows, sql)
}
case l.LogLevel == logger.Info:
case r.level == logger.Info:
sql, rows := fc()
if rows == -1 {
l.Printf(l.traceStr, FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, "-", sql)
r.log.Infof(traceStr, float64(elapsed.Nanoseconds())/1e6, "-", sql)
} else {
l.Printf(l.traceStr, FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, rows, sql)
r.log.Infof(traceStr, float64(elapsed.Nanoseconds())/1e6, rows, sql)
}
}
}
Expand Down
Loading

0 comments on commit 9b776be

Please sign in to comment.