From 941e7a1871a017ee9a3dc0d07be297ed9ed86060 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Sat, 14 May 2022 13:04:01 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8B=86=E5=88=86logger=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 + config.go | 427 ++++++++++++++++++++++++++++++++++++++++++++ debug.go | 26 +++ error.go | 64 +++++++ go.mod | 35 +++- go.sum | 155 ++++++++++++++++ logger.go | 136 ++++++++++++++ wrapper/gorm_v2.go | 203 +++++++++++++++++++++ wrapper/http_gin.go | 142 +++++++++++++++ 9 files changed, 1189 insertions(+), 1 deletion(-) create mode 100644 README.md create mode 100644 config.go create mode 100644 debug.go create mode 100644 error.go create mode 100644 go.sum create mode 100644 logger.go create mode 100644 wrapper/gorm_v2.go create mode 100644 wrapper/http_gin.go diff --git a/README.md b/README.md new file mode 100644 index 0000000..3094be3 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# go-logger +基于zap log的包装,方便引入使用 diff --git a/config.go b/config.go new file mode 100644 index 0000000..2c34459 --- /dev/null +++ b/config.go @@ -0,0 +1,427 @@ +// Package logger... +// +// Description : config 日志配置 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2021-01-02 3:07 下午 +package logger + +import ( + "fmt" + "os" + "strings" + "time" + + "go.uber.org/zap/zapcore" +) + +// TimeIntervalType 日志时间间隔类型 +type TimeIntervalType uint + +const ( + // TimeIntervalTypeMinute 按分钟切割 + TimeIntervalTypeMinute = TimeIntervalType(0) + // TimeIntervalTypeHour 按小时切割 + TimeIntervalTypeHour = TimeIntervalType(1) + // TimeIntervalTypeDay 按天切割 + TimeIntervalTypeDay = TimeIntervalType(2) + // TimeIntervalTypeMonth 按月切割 + TimeIntervalTypeMonth = TimeIntervalType(3) + // TimeIntervalTypeYear 按年切割 + TimeIntervalTypeYear = TimeIntervalType(4) +) + +const ( + // DefaultDivisionChar 默认的时间格式分隔符 + DefaultDivisionChar = "-" +) + +// RotateLogConfig 日志切割的配置 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 3:08 下午 2021/1/2 +type RotateLogConfig struct { + TimeIntervalType TimeIntervalType `json:"time_interval_type" yaml:"time_interval_type"` // 日志切割的时间间隔类型 0 - 小时 1 - 天 2 - 月 3 - 年 + TimeInterval time.Duration `json:"time_interval" yaml:"time_interval"` // 日志切割的时间间隔 + LogPath string `json:"log_path" yaml:"log_path"` // 存储日志的路径 + LogFileName string `json:"log_file_name" yaml:"log_file_name"` // 日志文件名 + DivisionChar string `json:"division_char" yaml:"division_char"` // 日志文件拼时间分隔符 + FullLogFormat string `json:"full_log_format" yaml:"full_log_format"` // 完整的日志格式 + MaxAge time.Duration `json:"max_age" yaml:"max_age"` // 日志最长保存时间 +} + +// SetRotateLogConfigFunc 设置日志切割的选项 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 3:13 下午 2021/1/2 +type SetRotateLogConfigFunc func(rlc *RotateLogConfig) + +// WithTimeIntervalType 设置日志切割时间间隔 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 3:34 下午 2021/1/2 +func WithTimeIntervalType(timeIntervalType TimeIntervalType) SetRotateLogConfigFunc { + return func(rlc *RotateLogConfig) { + rlc.TimeIntervalType = timeIntervalType + } +} + +// WithDivisionChar 设置分隔符 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 3:49 下午 2021/1/2 +func WithDivisionChar(divisionChar string) SetRotateLogConfigFunc { + return func(rlc *RotateLogConfig) { + rlc.DivisionChar = divisionChar + } +} + +// WithMaxAge 设置日志保存时间 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 5:03 下午 2021/1/2 +func WithMaxAge(maxAge time.Duration) SetRotateLogConfigFunc { + return func(rlc *RotateLogConfig) { + rlc.MaxAge = maxAge + } +} + +// NewRotateLogConfig 生成日志切割的配置 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 3:53 下午 2021/1/2 +func NewRotateLogConfig(logPath string, logFile string, option ...SetRotateLogConfigFunc) (*RotateLogConfig, error) { + if len(logPath) == 0 || len(logFile) == 0 { + return nil, LogPathEmptyError() + } + c := &RotateLogConfig{ + TimeIntervalType: TimeIntervalTypeHour, + LogPath: logPath, + LogFileName: logFile, + DivisionChar: "", + } + + for _, o := range option { + o(c) + } + + if err := formatConfig(c); nil != err { + return nil, err + } + + return c, nil +} + +// formatConfig 格式化配置 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 4:23 下午 2021/1/2 +func formatConfig(c *RotateLogConfig) error { + + if len(c.DivisionChar) == 0 { + c.DivisionChar = DefaultDivisionChar + } + // 格式化路径 + logPathByte := []byte(c.LogPath) + if string(logPathByte[len(logPathByte)-1]) != "/" { + c.LogPath = c.LogPath + "/" + } + // 检测路径是否存在,不存在自动创建 + if _, err := os.Stat(c.LogPath); nil != err { + if !os.IsNotExist(err) { + // 异常不是路径不存在,抛异常 + return DealLogPathError(err, c.LogPath) + } + if err := os.Mkdir(c.LogPath, os.ModePerm); nil != err { + return DealLogPathError(err, "创建日志目录失败") + } + } + + // 生成格式化日志全路径 + switch c.TimeIntervalType { + case TimeIntervalTypeMinute: + c.TimeInterval = time.Minute + c.FullLogFormat = c.LogPath + "%Y" + c.DivisionChar + "%m" + c.DivisionChar + "%d" + c.DivisionChar + "%H" + c.DivisionChar + "%M" + c.DivisionChar + c.LogFileName + case TimeIntervalTypeHour: + c.TimeInterval = time.Hour + c.FullLogFormat = c.LogPath + "%Y" + c.DivisionChar + "%m" + c.DivisionChar + "%d" + c.DivisionChar + "%H" + c.DivisionChar + c.LogFileName + case TimeIntervalTypeDay: + c.TimeInterval = time.Hour * 24 + c.FullLogFormat = c.LogPath + "%Y" + c.DivisionChar + "%m" + c.DivisionChar + "%d" + c.DivisionChar + c.LogFileName + case TimeIntervalTypeMonth: + c.TimeInterval = time.Hour * 24 * 30 + c.FullLogFormat = c.LogPath + "%Y" + c.DivisionChar + "%m" + c.DivisionChar + c.LogFileName + case TimeIntervalTypeYear: + c.TimeInterval = time.Hour * 24 * 365 + c.FullLogFormat = c.LogPath + "%Y" + c.DivisionChar + c.LogFileName + default: + return LogSplitTypeError(c.TimeIntervalType) + } + + return nil +} + +// ============== 以下为zap相关配置 + +const ( + // defaultMessageKey 默认的message key + defaultMessageKey = "message" + // defaultLevelKey 默认的level + defaultLevelKey = "level" + // defaultTimeKey 默认时间key + defaultTimeKey = "time" + // defaultCallerKey 默认的文件key + defaultCallerKey = "file" + // defaultUserShortCaller 是否使用短的文件调用格式 + defaultUseShortCaller = true + // defaultUseJsonFormat 日志默认使用json格式 + defaultUseJsonFormat = true +) + +// defaultTimeEncoder 默认的时间处理 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 11:53 下午 2021/1/2 +func defaultTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) { + sec := t.UnixNano() / 1e9 + ms := t.UnixNano() / 1e6 % 1e3 + ns := t.UnixNano() % 1e6 + enc.AppendString(time.Unix(sec, ns).Format("2006-01-02 15:04:05") + "." + fmt.Sprintf("%v", ms) + "+" + fmt.Sprintf("%v", ns)) +} + +// SecondTimeEncoder 秒级时间戳格式化 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 8:34 下午 2021/1/3 +func SecondTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) { + enc.AppendString(t.Format("2006-01-02 15:04:05")) +} + +// MsTimeEncoder 毫秒时间格式化方法 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 8:35 下午 2021/1/3 +func MsTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) { + sec := t.UnixNano() / 1e9 + ms := t.UnixNano() / 1e6 % 1e3 + enc.AppendString(time.Unix(sec, 0).Format("2006-01-02 15:04:05") + "." + fmt.Sprintf("%v", ms)) +} + +// defaultEncodeDuration 默认的原始时间处理 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 11:56 下午 2021/1/2 +func defaultEncodeDuration(d time.Duration, enc zapcore.PrimitiveArrayEncoder) { + enc.AppendInt64(int64(d) / 1000000) +} + +// OptionLogger 日志配置的选项 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 11:41 下午 2021/1/2 +type OptionLogger struct { + UseJsonFormat bool // 日志使用json格式 + MessageKey string // message 字段 + LevelKey string // level 字段 + TimeKey string // 时间字段 + CallerKey string // 记录日志的文件的代码行数 + UseShortCaller bool // 使用短的调用文件格式 + TimeEncoder zapcore.TimeEncoder // 格式化时间的函数 + EncodeDuration zapcore.DurationEncoder // 原始时间信息 + WithCaller bool // 是否打印文件行号 + WithCallerSkip int // 跳过的调用数 + ConsoleOutput bool // 控制台输出 + Encoder zapcore.Encoder // 编码函数 +} + +// SetLoggerOptionFunc 设置日志配置 +type SetLoggerOptionFunc func(o *OptionLogger) + +// WithCaller 打开文件行号记录 +func WithCaller() SetLoggerOptionFunc { + return func(o *OptionLogger) { + o.WithCaller = true + } +} + +// WithCallerSkip ... +func WithCallerSkip(skip int) SetLoggerOptionFunc { + return func(o *OptionLogger) { + o.WithCallerSkip = skip + } +} + +// WithConsoleOutput 日志控制台输出 +func WithConsoleOutput() SetLoggerOptionFunc { + return func(o *OptionLogger) { + o.ConsoleOutput = true + } +} + +// WithEncoder ... +func WithEncoder(encoder zapcore.Encoder) SetLoggerOptionFunc { + return func(o *OptionLogger) { + o.Encoder = encoder + } +} + +// WithUseJsonFormat 日志是否使用json格式数据 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 12:30 上午 2021/1/3 +func WithUseJsonFormat(isJsonFormat bool) SetLoggerOptionFunc { + return func(o *OptionLogger) { + o.UseJsonFormat = isJsonFormat + } +} + +// WithMessageKey 使用message key +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 12:32 上午 2021/1/3 +func WithMessageKey(messageKey string) SetLoggerOptionFunc { + return func(o *OptionLogger) { + messageKey = strings.Trim(messageKey, " ") + if len(messageKey) == 0 { + return + } + o.MessageKey = messageKey + } +} + +// WithLevelKey 设置level key +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 12:33 上午 2021/1/3 +func WithLevelKey(levelKey string) SetLoggerOptionFunc { + return func(o *OptionLogger) { + levelKey = strings.Trim(levelKey, " ") + if len(levelKey) == 0 { + return + } + o.LevelKey = levelKey + } +} + +// WithTimeKey 设置time key ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 12:34 上午 2021/1/3 +func WithTimeKey(timeKey string) SetLoggerOptionFunc { + return func(o *OptionLogger) { + timeKey = strings.Trim(timeKey, " ") + if len(timeKey) == 0 { + return + } + o.TimeKey = timeKey + } +} + +// WithCallerKey 设置caller key +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 12:37 上午 2021/1/3 +func WithCallerKey(callerKey string) SetLoggerOptionFunc { + return func(o *OptionLogger) { + callerKey = strings.Trim(callerKey, " ") + if len(callerKey) == 0 { + return + } + o.CallerKey = callerKey + } +} + +// WithShortCaller 是否使用短caller格式 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 12:39 上午 2021/1/3 +func WithShortCaller(useShortCaller bool) SetLoggerOptionFunc { + return func(o *OptionLogger) { + o.UseShortCaller = useShortCaller + } +} + +// WithTimeEncoder 设置格式化时间方法 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 12:41 上午 2021/1/3 +func WithTimeEncoder(encoder zapcore.TimeEncoder) SetLoggerOptionFunc { + return func(o *OptionLogger) { + if nil == encoder { + return + } + o.TimeEncoder = encoder + } +} + +// WithEncodeDuration 原始时间 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 12:42 上午 2021/1/3 +func WithEncodeDuration(encoder zapcore.DurationEncoder) SetLoggerOptionFunc { + return func(o *OptionLogger) { + if nil == encoder { + return + } + o.EncodeDuration = encoder + } +} + +// GetEncoder 获取空中台输出的encoder +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 6:24 下午 2021/1/2 +func GetEncoder(option ...SetLoggerOptionFunc) zapcore.Encoder { + ol := &OptionLogger{ + UseJsonFormat: defaultUseJsonFormat, + MessageKey: defaultMessageKey, + LevelKey: defaultLevelKey, + TimeKey: defaultTimeKey, + TimeEncoder: defaultTimeEncoder, + CallerKey: defaultCallerKey, + EncodeDuration: defaultEncodeDuration, + UseShortCaller: defaultUseShortCaller, + } + for _, o := range option { + o(ol) + } + ec := zapcore.EncoderConfig{ + MessageKey: ol.MessageKey, + LevelKey: ol.LevelKey, + EncodeLevel: zapcore.CapitalLevelEncoder, + TimeKey: ol.TimeKey, + EncodeTime: ol.TimeEncoder, + CallerKey: ol.CallerKey, + EncodeCaller: zapcore.ShortCallerEncoder, + EncodeDuration: ol.EncodeDuration, + } + if !ol.UseShortCaller { + ec.EncodeCaller = zapcore.FullCallerEncoder + } + if !ol.UseJsonFormat { + return zapcore.NewConsoleEncoder(ec) + } + return zapcore.NewJSONEncoder(ec) +} diff --git a/debug.go b/debug.go new file mode 100644 index 0000000..6911177 --- /dev/null +++ b/debug.go @@ -0,0 +1,26 @@ +// Package logger... +// +// Description : logger... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2021-01-03 12:58 上午 +package logger + +import ( + "bytes" + "encoding/json" +) + +// FormatJson 格式化输出json +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 1:06 上午 2021/1/3 +func FormatJson(src interface{}) string { + byteData, _ := json.Marshal(src) + + var str bytes.Buffer + _ = json.Indent(&str, byteData, "", " ") + return str.String() +} diff --git a/error.go b/error.go new file mode 100644 index 0000000..1a5ddf4 --- /dev/null +++ b/error.go @@ -0,0 +1,64 @@ +// Package logger... +// +// Description : error 定义日志处理过程中的各种错误 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2021-01-02 2:44 下午 +package logger + +import "github.com/pkg/errors" + +// CreateLogFileError 创建日志文件失败 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2:55 下午 2021/1/2 +func CreateLogFileError(err error, logFilePath string) error { + return errors.Wrapf(err, "创建日志文件失败,日志文件路径 : %s", logFilePath) +} + +// LogPathEmptyError 日志路径为空 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 4:03 下午 2021/1/2 +func LogPathEmptyError() error { + return errors.Wrap(errors.New("日志存储路径或者日志文件名为空"), "日志存储路径或者日志文件名为空") +} + +// CustomTimeIntervalError 自定义日志切割时间间隔错误 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 4:11 下午 2021/1/2 +func CustomTimeIntervalError() error { + return errors.Wrap(errors.New("自定义时间间隔错误,必须是大于0的值"), "自定义时间间隔错误,必须是大于0的值") +} + +// DealLogPathError 日志路径处理异常 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 4:31 下午 2021/1/2 +func DealLogPathError(err error, logPath string) error { + return errors.Wrapf(err, "日志路径检测处理异常, 日志路径 : %s", logPath) +} + +// LogSplitTypeError 日志切割类型错误 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 4:50 下午 2021/1/2 +func LogSplitTypeError(splitType TimeIntervalType) error { + return errors.Wrapf(errors.New("日志切割时间类型错误"), "日志切割时间类型错误, 传入类型 : %v", splitType) +} + +// CreateIOWriteError 创建日志实例失败 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 5:20 下午 2021/1/2 +func CreateIOWriteError(err error) error { + return errors.Wrapf(err, "创建日志实例失败") +} diff --git a/go.mod b/go.mod index 0f03431..4baae0b 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,36 @@ module git.zhangdeman.cn/zhangdeman/logger -go 1.18 +go 1.17 + +require ( + git.zhangdeman.cn/zhangdeman/gopkg v0.0.0-20220404153548-f65ee3641a1e + github.com/gin-gonic/gin v1.7.7 + github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible + github.com/pkg/errors v0.9.1 + go.uber.org/zap v1.20.0 + gorm.io/gorm v1.22.4 +) + +require ( + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-playground/locales v0.14.0 // indirect + github.com/go-playground/universal-translator v0.18.0 // indirect + github.com/go-playground/validator/v10 v10.10.1 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.4 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/leodido/go-urn v1.2.1 // indirect + github.com/lestrrat-go/strftime v1.0.5 // indirect + github.com/mattn/go-isatty v0.0.12 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/ugorji/go/codec v1.2.7 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.7.0 // indirect + golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 // indirect + golang.org/x/sys v0.0.0-20220403205710-6acee93ad0eb // indirect + golang.org/x/text v0.3.7 // indirect + google.golang.org/protobuf v1.28.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..142215f --- /dev/null +++ b/go.sum @@ -0,0 +1,155 @@ +git.zhangdeman.cn/zhangdeman/gopkg v0.0.0-20220404153548-f65ee3641a1e h1:sSemK4Q1HmqM9ZM8KXre9polJeXVScNrPsXIDih5Xys= +git.zhangdeman.cn/zhangdeman/gopkg v0.0.0-20220404153548-f65ee3641a1e/go.mod h1:YuvLB+lJbmG1oFRUIMF7JVnrfLqeXUYoZqKt103xsOg= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs= +github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U= +github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= +github.com/go-playground/validator/v10 v10.10.1 h1:uA0+amWMiglNZKZ9FJRKUAe9U3RX91eVn1JYXMWt7ig= +github.com/go-playground/validator/v10 v10.10.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.3/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas= +github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= +github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= +github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4= +github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA= +github.com/lestrrat-go/strftime v1.0.5 h1:A7H3tT8DhTz8u65w+JRpiBxM4dINQhUXAZnhBa2xeOE= +github.com/lestrrat-go/strftime v1.0.5/go.mod h1:E1nN3pCbtMSu1yjSVeyuRFVm/U0xoR76fd03sz+Qz4g= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= +github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= +go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/zap v1.20.0 h1:N4oPlghZwYG55MlU6LXk/Zp00FVNE9X9wrYO8CEs4lc= +go.uber.org/zap v1.20.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 h1:tkVvjkPTB7pnW3jnid7kNyAMPVWllTNOf/qKDze4p9o= +golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220403205710-6acee93ad0eb h1:PVGECzEo9Y3uOidtkHGdd347NjLtITfJFO9BxFpmRoo= +golang.org/x/sys v0.0.0-20220403205710-6acee93ad0eb/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/gorm v1.22.4 h1:8aPcyEJhY0MAt8aY6Dc524Pn+pO29K+ydu+e/cXSpQM= +gorm.io/gorm v1.22.4/go.mod h1:1aeVC+pe9ZmvKZban/gW4QPra7PRoTEssyc922qCAkk= diff --git a/logger.go b/logger.go new file mode 100644 index 0000000..13b54b6 --- /dev/null +++ b/logger.go @@ -0,0 +1,136 @@ +// Package logger... +// +// Description : logger 日志文件 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2021-01-02 5:04 下午 +package logger + +import ( + "io" + "os" + + "github.com/pkg/errors" + + "go.uber.org/zap" + + "go.uber.org/zap/zapcore" + + rotatelogs "github.com/lestrrat-go/file-rotatelogs" +) + +// NewLogger 获取日志实例 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 5:05 下午 2021/1/2 +func NewLogger(loggerLevel zapcore.Level, splitConfig *RotateLogConfig, optionFunc ...SetLoggerOptionFunc) (*zap.Logger, error) { + if nil == splitConfig { + return nil, errors.New("未配置日志切割规则") + } + + o := &OptionLogger{} + + for _, f := range optionFunc { + f(o) + } + + if nil == o.Encoder { + o.Encoder = GetEncoder() + } + loggerLevelDeal := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { + return lvl >= loggerLevel + }) + l := &Logger{ + splitConfig: splitConfig, + encoder: o.Encoder, + } + var ( + err error + loggerWriter io.Writer + ) + // 获取 日志实现 + if loggerWriter, err = l.getWriter(); nil != err { + return nil, err + } + + fileHandlerList := []zapcore.Core{ + zapcore.NewCore(o.Encoder, zapcore.AddSync(loggerWriter), loggerLevelDeal), + } + + // 设置控制台输出 + if o.ConsoleOutput { + fileHandlerList = append(fileHandlerList, zapcore.NewCore(o.Encoder, zapcore.AddSync(os.Stdout), loggerLevelDeal)) + } + + // 最后创建具体的Logger + core := zapcore.NewTee(fileHandlerList...) + + // 需要传入 zap.AddCaller() 才会显示打日志点的文件名和行数, 跳过一行可以直接显示业务代码行号,否则显示日志包行号 + logConfList := make([]zap.Option, 0) + if o.WithCaller { + logConfList = append(logConfList, zap.AddCaller(), zap.AddCallerSkip(o.WithCallerSkip)) + } + log := zap.New(core, logConfList...) + return log, nil +} + +// NewConsoleLogger 获取控制台输出的日志实例 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 8:22 下午 2021/4/17 +func NewConsoleLogger(loggerLevel zapcore.Level, optionFunc ...SetLoggerOptionFunc) (*zap.Logger, error) { + o := &OptionLogger{} + + for _, f := range optionFunc { + f(o) + } + if nil == o.Encoder { + o.Encoder = GetEncoder() + } + loggerLevelDeal := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { + return lvl >= loggerLevel + }) + fileHandlerList := []zapcore.Core{ + zapcore.NewCore(o.Encoder, zapcore.AddSync(os.Stdout), loggerLevelDeal), + } + // 最后创建具体的Logger + core := zapcore.NewTee(fileHandlerList...) + + // 需要传入 zap.AddCaller() 才会显示打日志点的文件名和行数, 跳过一行可以直接显示业务代码行号,否则显示日志包行号 + logConfList := make([]zap.Option, 0) + if o.WithCaller { + logConfList = append(logConfList, zap.AddCaller(), zap.AddCallerSkip(o.WithCallerSkip)) + } + log := zap.New(core, logConfList...) + return log, nil +} + +type Logger struct { + splitConfig *RotateLogConfig + encoder zapcore.Encoder +} + +// getWriter 获取日志实例 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 5:08 下午 2021/1/2 +func (l *Logger) getWriter() (io.Writer, error) { + option := make([]rotatelogs.Option, 0) + option = append(option, rotatelogs.WithRotationTime(l.splitConfig.TimeInterval)) + if l.splitConfig.MaxAge > 0 { + option = append(option, rotatelogs.WithMaxAge(l.splitConfig.MaxAge)) + } + var ( + hook *rotatelogs.RotateLogs + err error + ) + if hook, err = rotatelogs.New(l.splitConfig.FullLogFormat, option...); nil != err { + return nil, CreateIOWriteError(err) + } + + return hook, nil +} diff --git a/wrapper/gorm_v2.go b/wrapper/gorm_v2.go new file mode 100644 index 0000000..75d781c --- /dev/null +++ b/wrapper/gorm_v2.go @@ -0,0 +1,203 @@ +// Package wrapper... +// +// Description : gorm v2 版本接口实现 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2021/03/01 9:52 下午 +package wrapper + +import ( + "context" + "fmt" + "strings" + "time" + + "github.com/gin-gonic/gin" + + "gorm.io/gorm" + + "go.uber.org/zap/zapcore" + + "go.uber.org/zap" + + logger2 "git.zhangdeman.cn/zhangdeman/logger" + "gorm.io/gorm/logger" +) + +// NewGormV2 获取日志实例 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 9:56 下午 2021/3/1 +func NewGormV2(loggerLevel zapcore.Level, consoleOutput bool, encoder zapcore.Encoder, splitConfig *logger2.RotateLogConfig, traceIDField string, skip int) (logger.Interface, error) { + logConfList := []logger2.SetLoggerOptionFunc{logger2.WithEncoder(encoder), logger2.WithCallerSkip(skip), logger2.WithCaller()} + if consoleOutput { + logConfList = append(logConfList, logger2.WithConsoleOutput()) + } + + logInstance, err := logger2.NewLogger(loggerLevel, splitConfig, logConfList...) + if nil != err { + return nil, err + } + if len(traceIDField) == 0 { + traceIDField = "trace_id" + } + + return &Gorm{ + instance: logInstance, + traceIDField: traceIDField, + }, nil +} + +// NewGormLoggerWithInstance 获取gorm日志实现 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 3:36 PM 2021/12/24 +func NewGormLoggerWithInstance(ctx *gin.Context, dbClient *gorm.DB, instance *zap.Logger, node string, extraCtxFieldList []string) logger.Interface { + return &Gorm{ + dbClient: dbClient, + instance: instance, + traceIDField: "", + extraCtxFieldList: extraCtxFieldList, + flag: "", + node: node, + ctx: ctx, + } +} + +// Gorm v2 版本库日志实现 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 9:55 下午 2021/3/1 +type Gorm struct { + dbClient *gorm.DB + instance *zap.Logger // 日志实例 + traceIDField string // 串联请求上下文的的ID + extraCtxFieldList []string // 从请求上线问提取的字段 + flag string // 数据库标识 + node string // 数据库节点 master / slave + ctx *gin.Context // gin上下文 +} + +// LogMode ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 10:08 下午 2021/3/1 +func (g *Gorm) LogMode(level logger.LogLevel) logger.Interface { + return g +} + +// Info 日志 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 10:18 下午 2021/3/1 +func (g *Gorm) Info(ctx context.Context, s string, i ...interface{}) { + g.write(nil, "info") +} + +// Warn ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 10:16 下午 2021/3/1 +func (g *Gorm) Warn(ctx context.Context, s string, i ...interface{}) { + g.write(nil, "warn") +} + +// Error 日志 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 10:18 下午 2021/3/1 +func (g *Gorm) Error(ctx context.Context, s string, i ...interface{}) { + g.write(nil, "error") +} + +// Trace Trace 记录 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 10:19 下午 2021/3/1 +func (g *Gorm) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) { + start := begin.UnixNano() + end := time.Now().UnixNano() + sql := "" + affectRows := int64(0) + if nil != fc { + sql, affectRows = fc() + } + + dataList := []zap.Field{ + zap.String(g.traceIDField, g.getTraceID(ctx)), + zap.String("db_flag", g.flag), + zap.Int64("begin_time", start), + zap.Int64("finish_time", end), + zap.String("used_time", fmt.Sprintf("%fms", float64(end-start)/1e6)), + zap.String("sql", sql), + zap.Int64("affect_rows", affectRows), + zap.Error(err), + } + g.write(dataList, "info") + +} + +// write ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 4:11 PM 2021/12/24 +func (g *Gorm) write(dataList []zap.Field, level string) { + if nil == g.instance { + // 未设置日志实例 + return + } + if nil == dataList { + dataList = make([]zap.Field, 0) + } + if nil != g.ctx { + for _, extraField := range g.extraCtxFieldList { + dataList = append(dataList, zap.Any(extraField, g.ctx.Value(extraField))) + } + } + + // 补齐 flag、node + sql := g.dbClient.Dialector.Explain(g.dbClient.Statement.SQL.String(), g.dbClient.Statement.Vars...) + affectRows := g.dbClient.RowsAffected + dataList = append(dataList, zap.String("db_node", g.node), zap.String("db_flag", g.flag), zap.String("execute_sql", sql), zap.Int64("affect_rows", affectRows)) + message := "SQL执行记录" + switch strings.ToLower(level) { + case "info": + g.instance.Info(message, dataList...) + case "warn": + g.instance.Warn(message, dataList...) + case "error": + g.instance.Error(message, dataList...) + default: + g.instance.Info(message, dataList...) + } +} + +// getTraceID 获取traceID +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 10:11 下午 2021/3/1 +func (g *Gorm) getTraceID(ctx context.Context) string { + return fmt.Sprintf("%v", ctx.Value(g.traceIDField)) +} + +// GetGormSQL 获取trace fn +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 10:38 下午 2021/3/1 +func GetGormSQL(dbClient *gorm.DB) func() (string, int64) { + return func() (string, int64) { + return dbClient.Dialector.Explain(dbClient.Statement.SQL.String(), dbClient.Statement.Vars...), dbClient.RowsAffected + } +} diff --git a/wrapper/http_gin.go b/wrapper/http_gin.go new file mode 100644 index 0000000..7f50041 --- /dev/null +++ b/wrapper/http_gin.go @@ -0,0 +1,142 @@ +// Package wrapper... +// +// Description : http_gin 使用gin框架时的,记录日志 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2021-01-03 3:43 下午 +package wrapper + +import ( + "encoding/json" + + "git.zhangdeman.cn/zhangdeman/gopkg/logger" + logger2 "git.zhangdeman.cn/zhangdeman/gopkg/logger" + "github.com/gin-gonic/gin" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +// NewGinLogger 使用gin框架记录日志 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 3:45 下午 2021/1/3 +func NewGinLogger(loggerLevel zapcore.Level, consoleOutput bool, encoder zapcore.Encoder, splitConfig *logger.RotateLogConfig, extractFieldList []string, skip int) (*Gin, error) { + var ( + err error + l *zap.Logger + ) + logConfList := []logger2.SetLoggerOptionFunc{logger2.WithEncoder(encoder), logger2.WithCaller(), logger2.WithCallerSkip(skip)} + if consoleOutput { + logConfList = append(logConfList, logger2.WithConsoleOutput()) + } + if l, err = logger.NewLogger(loggerLevel, splitConfig, logConfList...); nil != err { + return nil, err + } + + return &Gin{ + loggerInstance: l, + extractFieldList: extractFieldList, + }, nil +} + +// Gin 包装gin实例 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 3:59 下午 2021/1/3 +type Gin struct { + loggerInstance *zap.Logger // zap 的日志实例 + extractFieldList []string // 从gin中抽取的字段 +} + +// formatFieldList 格式化日志field列表 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 4:13 下午 2021/1/3 +func (gw *Gin) formatFieldList(ginCtx *gin.Context, inputFieldList []zap.Field) []zap.Field { + if nil == inputFieldList { + inputFieldList = make([]zap.Field, 0) + } + if nil != ginCtx { + // 自动扩充抽取字段,字段不存在的话,忽略掉 + for _, extractField := range gw.extractFieldList { + if v, exist := ginCtx.Get(extractField); exist { + byteData, _ := json.Marshal(v) + inputFieldList = append(inputFieldList, zap.String(extractField, string(byteData))) + } + } + } + return inputFieldList +} + +// Debug 日志 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 4:14 下午 2021/1/3 +func (gw *Gin) Debug(ginCtx *gin.Context, msg string, field ...zap.Field) { + fieldList := gw.formatFieldList(ginCtx, field) + gw.loggerInstance.Debug(msg, fieldList...) +} + +// Info 日志 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 4:28 下午 2021/1/3 +func (gw *Gin) Info(ginCtx *gin.Context, msg string, field ...zap.Field) { + fieldList := gw.formatFieldList(ginCtx, field) + gw.loggerInstance.Info(msg, fieldList...) +} + +// Warn 日志 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 4:29 下午 2021/1/3 +func (gw *Gin) Warn(ginCtx *gin.Context, msg string, field ...zap.Field) { + fieldList := gw.formatFieldList(ginCtx, field) + gw.loggerInstance.Warn(msg, fieldList...) +} + +// Error 日志 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 4:29 下午 2021/1/3 +func (gw *Gin) Error(ginCtx *gin.Context, msg string, field ...zap.Field) { + fieldList := gw.formatFieldList(ginCtx, field) + gw.loggerInstance.Error(msg, fieldList...) +} + +// Panic 日志 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 4:29 下午 2021/1/3 +func (gw *Gin) Panic(ginCtx *gin.Context, msg string, field ...zap.Field) { + fieldList := gw.formatFieldList(ginCtx, field) + gw.loggerInstance.Panic(msg, fieldList...) +} + +// DPanic 日志 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 4:30 下午 2021/1/3 +func (gw *Gin) DPanic(ginCtx *gin.Context, msg string, field ...zap.Field) { + fieldList := gw.formatFieldList(ginCtx, field) + gw.loggerInstance.DPanic(msg, fieldList...) +} + +// GetZapLoggerInstance 获取zap日志实例 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2021/01/03 22:56:47 +func (gw *Gin) GetZapLoggerInstance() *zap.Logger { + return gw.loggerInstance +}