feat: add logging
This commit is contained in:
71
internal/pkg/logging/gormlogrus/gormlogrus.go
Normal file
71
internal/pkg/logging/gormlogrus/gormlogrus.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package gormlogrus
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"gorm.io/gorm"
|
||||
gormlogger "gorm.io/gorm/logger"
|
||||
"gorm.io/gorm/utils"
|
||||
)
|
||||
|
||||
type GormLogrusAdapter struct {
|
||||
SlowThreshold time.Duration
|
||||
SourceField string
|
||||
SkipErrRecordNotFound bool
|
||||
Logger logrus.FieldLogger
|
||||
}
|
||||
|
||||
func New(logger logrus.FieldLogger) *GormLogrusAdapter {
|
||||
return &GormLogrusAdapter{
|
||||
Logger: logger,
|
||||
SkipErrRecordNotFound: false,
|
||||
SourceField: "gorm",
|
||||
SlowThreshold: 1 * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GormLogrusAdapter) LogMode(gormlogger.LogLevel) gormlogger.Interface {
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *GormLogrusAdapter) Info(ctx context.Context, s string, args ...interface{}) {
|
||||
l.Logger.Infof(s, args)
|
||||
}
|
||||
|
||||
func (l *GormLogrusAdapter) Warn(ctx context.Context, s string, args ...interface{}) {
|
||||
logrus.Warnf(s, args)
|
||||
}
|
||||
|
||||
func (l *GormLogrusAdapter) Error(ctx context.Context, s string, args ...interface{}) {
|
||||
logrus.Errorf(s, args)
|
||||
}
|
||||
|
||||
func (l *GormLogrusAdapter) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
|
||||
elapsed := time.Since(begin)
|
||||
sql, rowsAffectedNum := fc()
|
||||
fields := logrus.Fields{}
|
||||
if l.SourceField != "" {
|
||||
fields[l.SourceField] = utils.FileWithLineNum()
|
||||
}
|
||||
|
||||
// format := "%s [cost: %s] [rows: %d]"
|
||||
// args := []interface{}{sql, elapsed, rowsAffectedNum}
|
||||
msg := fmt.Sprintf("%s [cost: %s] [rows: %d]", sql, elapsed, rowsAffectedNum)
|
||||
if err != nil && !(errors.Is(err, gorm.ErrRecordNotFound) && l.SkipErrRecordNotFound) {
|
||||
fields[logrus.ErrorKey] = err
|
||||
l.Logger.WithFields(fields).Error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
if l.SlowThreshold != 0 && elapsed > l.SlowThreshold {
|
||||
l.Logger.WithFields(fields).Warn(msg)
|
||||
return
|
||||
}
|
||||
|
||||
l.Logger.WithFields(fields).Debug(msg)
|
||||
}
|
75
internal/pkg/logging/logrus.go
Normal file
75
internal/pkg/logging/logrus.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultTimestampFormat = "2006-01-02 15:04:05.000000"
|
||||
defaultLoggerLevel = logrus.DebugLevel
|
||||
)
|
||||
|
||||
var DefaultConfig = defaultConfig()
|
||||
|
||||
func defaultConfig() *Config {
|
||||
return &Config{
|
||||
Level: defaultLoggerLevel.String(),
|
||||
TimestampFormat: defaultTimestampFormat,
|
||||
ReportCaller: true,
|
||||
}
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Level string
|
||||
TimestampFormat string `mapstructure:"timestamp_format"`
|
||||
ReportCaller bool `mapstructure:"report_caller"`
|
||||
}
|
||||
|
||||
func (cfg Config) GetLevel() logrus.Level {
|
||||
l, err := logrus.ParseLevel(cfg.Level)
|
||||
if err != nil {
|
||||
logrus.
|
||||
WithError(err).
|
||||
Errorf("parse logger level failed with: %s", cfg.Level)
|
||||
return defaultLoggerLevel
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
func (cfg Config) GetTimestampFormat() string {
|
||||
if cfg.TimestampFormat != "" {
|
||||
return cfg.TimestampFormat
|
||||
}
|
||||
return defaultTimestampFormat
|
||||
}
|
||||
|
||||
func Init() {
|
||||
InitLogger(DefaultConfig)
|
||||
}
|
||||
|
||||
func InitLogger(cfg *Config, hooks ...logrus.Hook) {
|
||||
logrus.SetLevel(cfg.GetLevel())
|
||||
logrus.SetReportCaller(cfg.ReportCaller)
|
||||
formatter := logrus.JSONFormatter{
|
||||
PrettyPrint: true,
|
||||
TimestampFormat: cfg.GetTimestampFormat(),
|
||||
}
|
||||
logrus.SetFormatter(&formatter)
|
||||
|
||||
for _, hook := range hooks {
|
||||
logrus.AddHook(hook)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func New() logrus.FieldLogger {
|
||||
return logrus.StandardLogger()
|
||||
}
|
||||
|
||||
func WithScope(scope string) logrus.FieldLogger {
|
||||
return logrus.WithField("scope", scope)
|
||||
}
|
||||
|
||||
func AddHook(hook logrus.Hook) {
|
||||
logrus.AddHook(hook)
|
||||
}
|
50
internal/pkg/logging/pgxlogrus/pgxlogrus.go
Normal file
50
internal/pkg/logging/pgxlogrus/pgxlogrus.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package pgxlogrus
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v4"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type pgxLogger struct {
|
||||
logger logrus.FieldLogger
|
||||
}
|
||||
|
||||
func New(logger logrus.FieldLogger) *pgxLogger {
|
||||
return &pgxLogger{
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (lg pgxLogger) Log(ctx context.Context, level pgx.LogLevel, msg string, data map[string]interface{}) {
|
||||
lg.logger.WithFields(lg.fieldsData(data)).Info(msg)
|
||||
}
|
||||
|
||||
func (lg pgxLogger) fieldsData(data map[string]interface{}) logrus.Fields {
|
||||
fields := make(logrus.Fields)
|
||||
if v, ok := data["time"]; ok && v != nil {
|
||||
fields["cost"] = v
|
||||
fields["costString"] = fmt.Sprintf("%v", time.Duration(v.(time.Duration)))
|
||||
}
|
||||
|
||||
if v, ok := data["sql"]; ok {
|
||||
fields["SQL"] = v
|
||||
}
|
||||
|
||||
if v, ok := data["pid"]; ok {
|
||||
fields["PID"] = v
|
||||
}
|
||||
|
||||
if v, ok := data["args"]; ok {
|
||||
fields["args"] = v
|
||||
}
|
||||
|
||||
if v, ok := data["rowCount"]; ok {
|
||||
fields["rowCount"] = v
|
||||
}
|
||||
|
||||
return fields
|
||||
}
|
Reference in New Issue
Block a user