refactor: 重构日志模块并清理未使用的依赖
This commit is contained in:
parent
9f27da2dce
commit
d3ad49d11e
9
go.mod
9
go.mod
|
@ -8,9 +8,9 @@ require (
|
|||
github.com/gin-contrib/pprof v1.4.0
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
github.com/go-resty/resty/v2 v2.7.0
|
||||
github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
|
||||
github.com/panjf2000/ants/v2 v2.8.1
|
||||
github.com/panjf2000/gnet v1.6.7
|
||||
github.com/smartystreets/goconvey v1.8.1
|
||||
|
@ -23,6 +23,7 @@ require (
|
|||
go.uber.org/zap v1.25.0
|
||||
golang.org/x/crypto v0.14.0
|
||||
google.golang.org/grpc v1.59.0
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||
)
|
||||
|
||||
require (
|
||||
|
@ -36,16 +37,13 @@ require (
|
|||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/gopherjs/gopherjs v1.17.2 // indirect
|
||||
github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jonboulle/clockwork v0.3.0 // indirect
|
||||
github.com/jtolds/gls v4.20.0+incompatible // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||
github.com/klauspost/reedsolomon v1.11.8 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/lestrrat-go/strftime v1.0.6 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||
|
@ -69,6 +67,5 @@ require (
|
|||
golang.org/x/text v0.13.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
|
16
go.sum
16
go.sum
|
@ -2,8 +2,6 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
|
|||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/RussellLuo/timingwheel v0.0.0-20220218152713-54845bda3108 h1:iPugyBI7oFtbDZXC4dnY093M1kZx6k/95sen92gafbY=
|
||||
github.com/RussellLuo/timingwheel v0.0.0-20220218152713-54845bda3108/go.mod h1:WAMLHwunr1hi3u7OjGV6/VWG9QbdMhGpEKjROiSFd10=
|
||||
github.com/alphadose/haxmap v1.2.0 h1:noGrAmCE+gNheZ4KpW+sYj9W5uMcO1UAjbAq9XBOAfM=
|
||||
github.com/alphadose/haxmap v1.2.0/go.mod h1:rjHw1IAqbxm0S3U5tD16GoKsiAd8FWx5BJ2IYqXwgmM=
|
||||
github.com/alphadose/haxmap v1.3.0 h1:C/2LboOnPCZP27GmmSXOcwx360st0P8N0fTJ3voefKc=
|
||||
github.com/alphadose/haxmap v1.3.0/go.mod h1:rjHw1IAqbxm0S3U5tD16GoKsiAd8FWx5BJ2IYqXwgmM=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
|
@ -82,8 +80,6 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm
|
|||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jonboulle/clockwork v0.3.0 h1:9BSCMi8C+0qdApAp4auwX0RkLGUjs956h0EkuQymUhg=
|
||||
github.com/jonboulle/clockwork v0.3.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
|
||||
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/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
|
@ -105,15 +101,9 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
|||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
||||
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
||||
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.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205AhTIGQQ=
|
||||
github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
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=
|
||||
|
@ -134,8 +124,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
|||
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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
|
|
|
@ -1,20 +1,9 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"github.com/kercylan98/minotaur/utils/log"
|
||||
"time"
|
||||
)
|
||||
|
||||
type (
|
||||
RunMode = log.RunMode
|
||||
)
|
||||
|
||||
const (
|
||||
RunModeDev RunMode = log.RunModeDev
|
||||
RunModeProd RunMode = log.RunModeProd
|
||||
RunModeTest RunMode = log.RunModeTest
|
||||
)
|
||||
|
||||
const (
|
||||
serverMultipleMark = "Minotaur Multiple Server"
|
||||
serverMark = "Minotaur Server"
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package logger
|
||||
|
||||
import "github.com/kercylan98/minotaur/utils/log"
|
||||
|
||||
type Ants struct {
|
||||
}
|
||||
|
||||
func (slf *Ants) Printf(format string, args ...interface{}) {
|
||||
log.Warn(format, log.Any("args", args))
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/kercylan98/minotaur/utils/log"
|
||||
)
|
||||
|
||||
type GNet struct {
|
||||
}
|
||||
|
||||
func (slf *GNet) Debugf(format string, args ...interface{}) {
|
||||
log.Debug(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (slf *GNet) Infof(format string, args ...interface{}) {
|
||||
log.Info(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (slf *GNet) Warnf(format string, args ...interface{}) {
|
||||
log.Warn(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (slf *GNet) Errorf(format string, args ...interface{}) {
|
||||
log.Error(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (slf *GNet) Fatalf(format string, args ...interface{}) {
|
||||
log.Fatal(fmt.Sprintf(format, args...))
|
||||
}
|
|
@ -195,14 +195,6 @@ func WithGRPCServerOptions(options ...grpc.ServerOption) Option {
|
|||
}
|
||||
}
|
||||
|
||||
// WithRunMode 通过特定模式运行服务器
|
||||
// - 默认为 RunModeDev
|
||||
func WithRunMode(mode RunMode) Option {
|
||||
return func(srv *Server) {
|
||||
srv.runMode = mode
|
||||
}
|
||||
}
|
||||
|
||||
// WithWebsocketMessageType 设置仅支持特定类型的Websocket消息
|
||||
func WithWebsocketMessageType(messageTypes ...int) Option {
|
||||
return func(srv *Server) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/kercylan98/minotaur/server/internal/logger"
|
||||
"github.com/kercylan98/minotaur/utils/concurrent"
|
||||
"github.com/kercylan98/minotaur/utils/log"
|
||||
"github.com/kercylan98/minotaur/utils/network"
|
||||
|
@ -14,7 +15,6 @@ import (
|
|||
"github.com/kercylan98/minotaur/utils/timer"
|
||||
"github.com/panjf2000/ants/v2"
|
||||
"github.com/panjf2000/gnet"
|
||||
"github.com/panjf2000/gnet/pkg/logging"
|
||||
"github.com/xtaci/kcp-go/v5"
|
||||
"google.golang.org/grpc"
|
||||
"net"
|
||||
|
@ -67,7 +67,7 @@ func New(network Network, options ...Option) *Server {
|
|||
server.antsPoolSize = DefaultAsyncPoolSize
|
||||
}
|
||||
var err error
|
||||
server.ants, err = ants.NewPool(server.antsPoolSize, ants.WithLogger(log.GetLogger()))
|
||||
server.ants, err = ants.NewPool(server.antsPoolSize, ants.WithLogger(new(logger.Ants)))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -93,7 +93,6 @@ type Server struct {
|
|||
online *concurrent.BalanceMap[string, *Conn] // 在线连接
|
||||
network Network // 网络类型
|
||||
addr string // 侦听地址
|
||||
runMode RunMode // 运行模式
|
||||
systemSignal chan os.Signal // 系统信号
|
||||
closeChannel chan struct{} // 关闭信号
|
||||
multipleRuntimeErrorChan chan error // 多服务器模式下的运行时错误
|
||||
|
@ -177,8 +176,7 @@ func (slf *Server) Run(addr string) error {
|
|||
slf.isRunning = true
|
||||
slf.OnStartBeforeEvent()
|
||||
if err := gnet.Serve(slf.gServer, protoAddr,
|
||||
gnet.WithLogger(log.GetLogger()),
|
||||
gnet.WithLogLevel(super.If(slf.runMode == RunModeProd, logging.ErrorLevel, logging.DebugLevel)),
|
||||
gnet.WithLogger(new(logger.GNet)),
|
||||
gnet.WithTicker(true),
|
||||
gnet.WithMulticore(true),
|
||||
); err != nil {
|
||||
|
@ -230,18 +228,19 @@ func (slf *Server) Run(addr string) error {
|
|||
}
|
||||
})
|
||||
case NetworkHttp:
|
||||
switch slf.runMode {
|
||||
case RunModeDev:
|
||||
gin.SetMode(gin.DebugMode)
|
||||
case RunModeTest:
|
||||
gin.SetMode(gin.TestMode)
|
||||
case RunModeProd:
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
}
|
||||
go func() {
|
||||
slf.isRunning = true
|
||||
slf.OnStartBeforeEvent()
|
||||
slf.httpServer.Addr = slf.addr
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
slf.ginServer.Use(func(c *gin.Context) {
|
||||
t := time.Now()
|
||||
c.Next()
|
||||
log.Info("Server", log.String("type", "http"),
|
||||
log.String("method", c.Request.Method), log.Int("status", c.Writer.Status()),
|
||||
log.String("ip", c.ClientIP()), log.String("path", c.Request.URL.Path),
|
||||
log.Duration("cost", time.Since(t)))
|
||||
})
|
||||
go connectionInitHandle(nil)
|
||||
if len(slf.certFile)+len(slf.keyFile) > 0 {
|
||||
if err := slf.httpServer.ListenAndServeTLS(slf.certFile, slf.keyFile); err != nil {
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"github.com/kercylan98/minotaur/server"
|
||||
"github.com/kercylan98/minotaur/server/client"
|
||||
"github.com/kercylan98/minotaur/utils/log"
|
||||
"github.com/kercylan98/minotaur/utils/times"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -29,6 +30,13 @@ func TestNew(t *testing.T) {
|
|||
//}
|
||||
})
|
||||
|
||||
srv.RegStartFinishEvent(func(srv *server.Server) {
|
||||
log.Warn("启动完成")
|
||||
log.Error("启动完成")
|
||||
log.Info("启动完成")
|
||||
log.Debug("启动完成")
|
||||
})
|
||||
|
||||
srv.RegConnectionReceivePacketEvent(func(srv *server.Server, conn *server.Conn, packet []byte) {
|
||||
conn.Write(packet)
|
||||
})
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
package log
|
||||
|
||||
import "go.uber.org/zap/zapcore"
|
||||
|
||||
type Core = zapcore.Core
|
|
@ -1,26 +1,53 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"time"
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Encoder = zapcore.Encoder
|
||||
|
||||
// NewEncoder 创建一个 Minotaur 默认使用的编码器
|
||||
func NewEncoder() Encoder {
|
||||
return zapcore.NewConsoleEncoder(zapcore.EncoderConfig{
|
||||
MessageKey: "msg",
|
||||
LevelKey: "level",
|
||||
EncodeLevel: zapcore.CapitalLevelEncoder,
|
||||
TimeKey: "ts",
|
||||
EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
|
||||
enc.AppendString(t.Format(time.DateTime))
|
||||
},
|
||||
CallerKey: "file",
|
||||
EncodeCaller: zapcore.ShortCallerEncoder,
|
||||
EncodeDuration: func(d time.Duration, enc zapcore.PrimitiveArrayEncoder) {
|
||||
enc.AppendInt64(int64(d) / 1000000)
|
||||
},
|
||||
})
|
||||
type Encoder struct {
|
||||
e zapcore.Encoder
|
||||
cores []Core
|
||||
conf *Config
|
||||
}
|
||||
|
||||
func (slf *Encoder) Split(config *lumberjack.Logger) *Encoder {
|
||||
slf.cores = append(slf.cores, zapcore.NewCore(slf.e, zapcore.AddSync(config), zapcore.DebugLevel))
|
||||
return slf
|
||||
}
|
||||
|
||||
func (slf *Encoder) AddCore(ws WriteSyncer, enab LevelEnabler) *Encoder {
|
||||
slf.cores = append(slf.cores, zapcore.NewCore(slf.e, ws, enab))
|
||||
return slf
|
||||
}
|
||||
|
||||
func (slf *Encoder) Build(options ...LoggerOption) *Minotaur {
|
||||
l, err := slf.conf.Build()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
options = append([]LoggerOption{zap.AddCaller(), zap.AddCallerSkip(1)}, options...)
|
||||
l = l.WithOptions(options...)
|
||||
if len(slf.cores) == 0 {
|
||||
// stdout、stderr,不使用 lumberjack.Logger
|
||||
slf.cores = append(slf.cores, zapcore.NewCore(
|
||||
slf.e,
|
||||
zapcore.Lock(os.Stdout),
|
||||
zapcore.InfoLevel,
|
||||
))
|
||||
slf.cores = append(slf.cores, zapcore.NewCore(
|
||||
slf.e,
|
||||
zapcore.Lock(os.Stderr),
|
||||
zapcore.ErrorLevel,
|
||||
))
|
||||
}
|
||||
l = l.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core {
|
||||
return zapcore.NewTee(slf.cores...)
|
||||
}))
|
||||
return &Minotaur{
|
||||
Logger: l,
|
||||
Sugared: l.Sugar(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,6 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"github.com/kercylan98/minotaur/utils/hash"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
type Level = zapcore.Level
|
||||
type LevelEnablerFunc = zap.LevelEnablerFunc
|
||||
import "go.uber.org/zap/zapcore"
|
||||
|
||||
const (
|
||||
// DebugLevel 调试级别日志通常非常庞大,并且通常在生产中被禁用
|
||||
|
@ -25,86 +18,3 @@ const (
|
|||
// FatalLevel 记录一条消息,然后调用 os.Exit(1)
|
||||
FatalLevel Level = zapcore.FatalLevel
|
||||
)
|
||||
|
||||
var (
|
||||
levels = []Level{DebugLevel, InfoLevel, WarnLevel, ErrorLevel, DPanicLevel, PanicLevel, FatalLevel}
|
||||
defaultLevelPartition = map[Level]func() LevelEnablerFunc{
|
||||
DebugLevel: DebugLevelPartition,
|
||||
InfoLevel: InfoLevelPartition,
|
||||
WarnLevel: WarnLevelPartition,
|
||||
ErrorLevel: ErrorLevelPartition,
|
||||
DPanicLevel: DPanicLevelPartition,
|
||||
PanicLevel: PanicLevelPartition,
|
||||
FatalLevel: FatalLevelPartition,
|
||||
}
|
||||
)
|
||||
|
||||
// Levels 返回所有日志级别
|
||||
func Levels() []Level {
|
||||
return levels
|
||||
}
|
||||
|
||||
// MultiLevelPartition 返回一个 LevelEnablerFunc,该函数在指定的多个级别时返回 true
|
||||
// - 该函数被用于划分不同级别的日志输出
|
||||
func MultiLevelPartition(levels ...Level) LevelEnablerFunc {
|
||||
var levelMap = hash.ToIterator(levels)
|
||||
return func(level zapcore.Level) bool {
|
||||
return hash.Exist(levelMap, level)
|
||||
}
|
||||
}
|
||||
|
||||
// DebugLevelPartition 返回一个 LevelEnablerFunc,该函数在 DebugLevel 时返回 true
|
||||
// - 该函数被用于划分不同级别的日志输出
|
||||
func DebugLevelPartition() LevelEnablerFunc {
|
||||
return func(level zapcore.Level) bool {
|
||||
return level == DebugLevel
|
||||
}
|
||||
}
|
||||
|
||||
// InfoLevelPartition 返回一个 LevelEnablerFunc,该函数在 InfoLevel 时返回 true
|
||||
// - 该函数被用于划分不同级别的日志输出
|
||||
func InfoLevelPartition() LevelEnablerFunc {
|
||||
return func(level zapcore.Level) bool {
|
||||
return level == InfoLevel
|
||||
}
|
||||
}
|
||||
|
||||
// WarnLevelPartition 返回一个 LevelEnablerFunc,该函数在 WarnLevel 时返回 true
|
||||
// - 该函数被用于划分不同级别的日志输出
|
||||
func WarnLevelPartition() LevelEnablerFunc {
|
||||
return func(level zapcore.Level) bool {
|
||||
return level == WarnLevel
|
||||
}
|
||||
}
|
||||
|
||||
// ErrorLevelPartition 返回一个 LevelEnablerFunc,该函数在 ErrorLevel 时返回 true
|
||||
// - 该函数被用于划分不同级别的日志输出
|
||||
func ErrorLevelPartition() LevelEnablerFunc {
|
||||
return func(level zapcore.Level) bool {
|
||||
return level == ErrorLevel
|
||||
}
|
||||
}
|
||||
|
||||
// DPanicLevelPartition 返回一个 LevelEnablerFunc,该函数在 DPanicLevel 时返回 true
|
||||
// - 该函数被用于划分不同级别的日志输出
|
||||
func DPanicLevelPartition() LevelEnablerFunc {
|
||||
return func(level zapcore.Level) bool {
|
||||
return level == DPanicLevel
|
||||
}
|
||||
}
|
||||
|
||||
// PanicLevelPartition 返回一个 LevelEnablerFunc,该函数在 PanicLevel 时返回 true
|
||||
// - 该函数被用于划分不同级别的日志输出
|
||||
func PanicLevelPartition() LevelEnablerFunc {
|
||||
return func(level zapcore.Level) bool {
|
||||
return level == PanicLevel
|
||||
}
|
||||
}
|
||||
|
||||
// FatalLevelPartition 返回一个 LevelEnablerFunc,该函数在 FatalLevel 时返回 true
|
||||
// - 该函数被用于划分不同级别的日志输出
|
||||
func FatalLevelPartition() LevelEnablerFunc {
|
||||
return func(level zapcore.Level) bool {
|
||||
return level == FatalLevel
|
||||
}
|
||||
}
|
||||
|
|
170
utils/log/log.go
170
utils/log/log.go
|
@ -1,170 +0,0 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/kercylan98/minotaur/utils/str"
|
||||
"github.com/kercylan98/minotaur/utils/times"
|
||||
rotateLogs "github.com/lestrrat-go/file-rotatelogs"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// NewLog 创建一个日志记录器
|
||||
func NewLog(options ...Option) *Log {
|
||||
log := &Log{
|
||||
filename: func(level Level) string {
|
||||
return fmt.Sprintf("%s.log", level.String())
|
||||
},
|
||||
rotateFilename: func(level Level) string {
|
||||
return strings.Join([]string{level.String(), "%Y%m%d.log"}, ".")
|
||||
},
|
||||
levelPartition: defaultLevelPartition,
|
||||
}
|
||||
|
||||
for _, option := range options {
|
||||
option(log)
|
||||
}
|
||||
|
||||
if len(log.rotateOptions) == 0 {
|
||||
log.rotateOptions = []rotateLogs.Option{
|
||||
rotateLogs.WithMaxAge(times.Week),
|
||||
rotateLogs.WithRotationTime(times.Day),
|
||||
}
|
||||
}
|
||||
|
||||
if len(log.cores) == 0 {
|
||||
var encoder = NewEncoder()
|
||||
|
||||
switch log.mode {
|
||||
case RunModeDev:
|
||||
var partition LevelEnablerFunc = func(lvl Level) bool {
|
||||
return true
|
||||
}
|
||||
log.cores = append(log.cores, zapcore.NewCore(encoder, os.Stdout, partition))
|
||||
case RunModeTest, RunModeProd:
|
||||
if log.mode == RunModeTest {
|
||||
infoRotate, err := rotateLogs.New(
|
||||
filepath.Join(log.rotateLogDir, log.rotateFilename(InfoLevel)),
|
||||
append([]rotateLogs.Option{rotateLogs.WithLinkName(filepath.Join(log.logDir, log.filename(InfoLevel)))}, log.rotateOptions...)...,
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
errRotate, err := rotateLogs.New(
|
||||
filepath.Join(log.rotateLogDir, log.rotateFilename(ErrorLevel)),
|
||||
append([]rotateLogs.Option{rotateLogs.WithLinkName(filepath.Join(log.logDir, log.filename(ErrorLevel)))}, log.rotateOptions...)...,
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if log.logDir != str.None {
|
||||
log.cores = append(log.cores, zapcore.NewCore(encoder, zapcore.AddSync(infoRotate), LevelEnablerFunc(func(lvl Level) bool { return lvl < ErrorLevel })))
|
||||
log.cores = append(log.cores, zapcore.NewCore(encoder, zapcore.AddSync(errRotate), LevelEnablerFunc(func(lvl Level) bool { return lvl >= ErrorLevel })))
|
||||
log.cores = append(log.cores, zapcore.NewCore(encoder, os.Stdout, LevelEnablerFunc(func(lvl Level) bool { return lvl < ErrorLevel })))
|
||||
log.cores = append(log.cores, zapcore.NewCore(encoder, os.Stdout, LevelEnablerFunc(func(lvl Level) bool { return lvl >= ErrorLevel })))
|
||||
}
|
||||
} else {
|
||||
infoRotate, err := rotateLogs.New(
|
||||
filepath.Join(log.rotateLogDir, log.rotateFilename(InfoLevel)),
|
||||
append([]rotateLogs.Option{rotateLogs.WithLinkName(filepath.Join(log.logDir, log.filename(InfoLevel)))}, log.rotateOptions...)...,
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
errRotate, err := rotateLogs.New(
|
||||
filepath.Join(log.rotateLogDir, log.rotateFilename(ErrorLevel)),
|
||||
append([]rotateLogs.Option{rotateLogs.WithLinkName(filepath.Join(log.logDir, log.filename(ErrorLevel)))}, log.rotateOptions...)...,
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if log.logDir != str.None {
|
||||
log.cores = append(log.cores, zapcore.NewCore(encoder, zapcore.AddSync(infoRotate), LevelEnablerFunc(func(lvl Level) bool { return lvl == InfoLevel })))
|
||||
log.cores = append(log.cores, zapcore.NewCore(encoder, zapcore.AddSync(errRotate), LevelEnablerFunc(func(lvl Level) bool { return lvl >= ErrorLevel })))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.zap = zap.New(zapcore.NewTee(log.cores...), zap.AddCaller(), zap.AddCallerSkip(2))
|
||||
log.sugar = log.zap.Sugar()
|
||||
return log
|
||||
}
|
||||
|
||||
type Log struct {
|
||||
zap *zap.Logger
|
||||
sugar *zap.SugaredLogger
|
||||
filename func(level Level) string
|
||||
rotateFilename func(level Level) string
|
||||
rotateOptions []rotateLogs.Option
|
||||
levelPartition map[Level]func() LevelEnablerFunc
|
||||
cores []Core
|
||||
mode RunMode
|
||||
logDir string
|
||||
rotateLogDir string
|
||||
}
|
||||
|
||||
func (slf *Log) Debugf(format string, args ...interface{}) {
|
||||
slf.sugar.Debugf(format, args...)
|
||||
}
|
||||
|
||||
func (slf *Log) Infof(format string, args ...interface{}) {
|
||||
slf.sugar.Infof(format, args...)
|
||||
}
|
||||
|
||||
func (slf *Log) Warnf(format string, args ...interface{}) {
|
||||
slf.sugar.Warnf(format, args...)
|
||||
}
|
||||
|
||||
func (slf *Log) Errorf(format string, args ...interface{}) {
|
||||
slf.sugar.Errorf(format, args...)
|
||||
}
|
||||
|
||||
func (slf *Log) Fatalf(format string, args ...interface{}) {
|
||||
slf.sugar.Fatalf(format, args...)
|
||||
}
|
||||
|
||||
func (slf *Log) Printf(format string, args ...interface{}) {
|
||||
slf.sugar.Infof(format, args...)
|
||||
}
|
||||
|
||||
// Debug 在 DebugLevel 记录一条消息。该消息包括在日志站点传递的任何字段以及记录器上累积的任何字段
|
||||
func (slf *Log) Debug(msg string, fields ...Field) {
|
||||
slf.zap.Debug(msg, fields...)
|
||||
}
|
||||
|
||||
// Info 在 InfoLevel 记录一条消息。该消息包括在日志站点传递的任何字段以及记录器上累积的任何字段
|
||||
func (slf *Log) Info(msg string, fields ...Field) {
|
||||
slf.zap.Info(msg, fields...)
|
||||
}
|
||||
|
||||
// Warn 在 WarnLevel 记录一条消息。该消息包括在日志站点传递的任何字段以及记录器上累积的任何字段
|
||||
func (slf *Log) Warn(msg string, fields ...Field) {
|
||||
slf.zap.Warn(msg, fields...)
|
||||
}
|
||||
|
||||
// Error 在 ErrorLevel 记录一条消息。该消息包括在日志站点传递的任何字段以及记录器上累积的任何字段
|
||||
func (slf *Log) Error(msg string, fields ...Field) {
|
||||
slf.zap.Error(msg, fields...)
|
||||
}
|
||||
|
||||
// DPanic 在 DPanicLevel 记录一条消息。该消息包括在日志站点传递的任何字段以及记录器上累积的任何字段
|
||||
// - 如果记录器处于开发模式,它就会出现 panic(DPanic 的意思是“development panic”)。这对于捕获可恢复但不应该发生的错误很有用
|
||||
func (slf *Log) DPanic(msg string, fields ...Field) {
|
||||
slf.zap.DPanic(msg, fields...)
|
||||
}
|
||||
|
||||
// Panic 在 PanicLevel 记录一条消息。该消息包括在日志站点传递的任何字段以及记录器上累积的任何字段
|
||||
// - 即使禁用了 PanicLevel 的日志记录,记录器也会出现 panic
|
||||
func (slf *Log) Panic(msg string, fields ...Field) {
|
||||
slf.zap.Panic(msg, fields...)
|
||||
}
|
||||
|
||||
// Fatal 在 FatalLevel 记录一条消息。该消息包括在日志站点传递的任何字段以及记录器上累积的任何字段
|
||||
// - 然后记录器调用 os.Exit(1),即使 FatalLevel 的日志记录被禁用
|
||||
func (slf *Log) Fatal(msg string, fields ...Field) {
|
||||
slf.zap.Fatal(msg, fields...)
|
||||
}
|
|
@ -1,16 +1,22 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"github.com/panjf2000/ants/v2"
|
||||
"github.com/panjf2000/gnet/pkg/logging"
|
||||
)
|
||||
var logger Logger
|
||||
|
||||
var logger Logger = NewLog()
|
||||
func init() {
|
||||
logger = Default().Build()
|
||||
}
|
||||
|
||||
// SetLogger 设置日志记录器
|
||||
func SetLogger(l Logger) {
|
||||
if m, ok := l.(*Minotaur); ok && m != nil {
|
||||
_ = m.Sync()
|
||||
_ = m.Sugared.Sync()
|
||||
}
|
||||
logger = l
|
||||
}
|
||||
|
||||
// Logger 适用于 Minotaur 的日志接口
|
||||
type Logger interface {
|
||||
ants.Logger
|
||||
logging.Logger
|
||||
// Debug 在 DebugLevel 记录一条消息。该消息包括在日志站点传递的任何字段以及记录器上累积的任何字段
|
||||
Debug(msg string, fields ...Field)
|
||||
// Info 在 InfoLevel 记录一条消息。该消息包括在日志站点传递的任何字段以及记录器上累积的任何字段
|
||||
|
@ -67,13 +73,3 @@ func Panic(msg string, fields ...Field) {
|
|||
func Fatal(msg string, fields ...Field) {
|
||||
logger.Fatal(msg, fields...)
|
||||
}
|
||||
|
||||
// SetLogger 设置日志记录器
|
||||
func SetLogger(log Logger) {
|
||||
logger = log
|
||||
}
|
||||
|
||||
// GetLogger 获取日志记录器
|
||||
func GetLogger() Logger {
|
||||
return logger
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package log
|
||||
|
||||
import "go.uber.org/zap"
|
||||
|
||||
type Minotaur struct {
|
||||
*zap.Logger
|
||||
Sugared *zap.SugaredLogger
|
||||
}
|
|
@ -1,52 +1,237 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
rotateLogs "github.com/lestrrat-go/file-rotatelogs"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Option func(log *Log)
|
||||
type (
|
||||
Config = zap.Config
|
||||
Level = zapcore.Level
|
||||
LevelEncoder = zapcore.LevelEncoder
|
||||
TimeEncoder = zapcore.TimeEncoder
|
||||
DurationEncoder = zapcore.DurationEncoder
|
||||
CallerEncoder = zapcore.CallerEncoder
|
||||
NameEncoder = zapcore.NameEncoder
|
||||
ReflectedEncoder = zapcore.ReflectedEncoder
|
||||
WriteSyncer = zapcore.WriteSyncer
|
||||
LoggerOption = zap.Option
|
||||
Core = zapcore.Core
|
||||
LevelEnabler = zapcore.LevelEnabler
|
||||
Option func(config *Config)
|
||||
)
|
||||
|
||||
// WithRunMode 设置运行模式
|
||||
// - 默认的运行模式为: RunModeDev
|
||||
// - 当 handle 不为空时,将会调用 handle(),并将返回值添加到日志记录器中,同时将会抑制默认的日志记录器
|
||||
func WithRunMode(mode RunMode, handle func() Core) Option {
|
||||
return func(log *Log) {
|
||||
log.mode = mode
|
||||
if handle != nil {
|
||||
log.cores = append(log.cores, handle())
|
||||
func Default(opts ...Option) *Encoder {
|
||||
config := &zap.Config{
|
||||
Level: zap.NewAtomicLevelAt(zap.DebugLevel),
|
||||
Development: true,
|
||||
DisableStacktrace: true,
|
||||
Sampling: &zap.SamplingConfig{
|
||||
Initial: 100,
|
||||
Thereafter: 100,
|
||||
},
|
||||
EncoderConfig: zapcore.EncoderConfig{
|
||||
TimeKey: "Time",
|
||||
LevelKey: "Level",
|
||||
NameKey: "Name",
|
||||
CallerKey: "Caller",
|
||||
MessageKey: "Msg",
|
||||
StacktraceKey: "Stack",
|
||||
EncodeLevel: zapcore.CapitalLevelEncoder,
|
||||
EncodeTime: func(t time.Time, encoder zapcore.PrimitiveArrayEncoder) {
|
||||
encoder.AppendString(t.Format(time.DateTime))
|
||||
},
|
||||
EncodeDuration: zapcore.StringDurationEncoder,
|
||||
EncodeCaller: zapcore.ShortCallerEncoder,
|
||||
},
|
||||
}
|
||||
|
||||
// 应用选项
|
||||
for _, opt := range opts {
|
||||
opt(config)
|
||||
}
|
||||
|
||||
if len(config.Encoding) == 0 {
|
||||
if config.Development {
|
||||
config.Encoding = "console"
|
||||
} else {
|
||||
config.Encoding = "json"
|
||||
}
|
||||
}
|
||||
|
||||
var encoder = new(Encoder)
|
||||
encoder.conf = config
|
||||
switch config.Encoding {
|
||||
case "console":
|
||||
encoder.e = zapcore.NewConsoleEncoder(config.EncoderConfig)
|
||||
case "json":
|
||||
encoder.e = zapcore.NewJSONEncoder(config.EncoderConfig)
|
||||
default:
|
||||
panic("unknown encoding")
|
||||
}
|
||||
|
||||
return encoder
|
||||
}
|
||||
|
||||
// WithFilename 设置日志文件名
|
||||
// - 默认的日志文件名为: {level}.log
|
||||
func WithFilename(filename func(level Level) string) Option {
|
||||
return func(log *Log) {
|
||||
log.filename = filename
|
||||
// WithLevel 设置日志级别
|
||||
func WithLevel(level Level) Option {
|
||||
return func(config *Config) {
|
||||
config.Level.SetLevel(level)
|
||||
}
|
||||
}
|
||||
|
||||
// WithRotateFilename 设置日志分割文件名
|
||||
// - 默认的日志分割文件名为: {level}.%Y%m%d.log
|
||||
func WithRotateFilename(filename func(level Level) string) Option {
|
||||
return func(log *Log) {
|
||||
log.rotateFilename = filename
|
||||
// WithDevelopment 设置是否为开发模式
|
||||
func WithDevelopment(development bool) Option {
|
||||
return func(config *Config) {
|
||||
config.Development = development
|
||||
}
|
||||
}
|
||||
|
||||
// WithRotateOption 设置日志分割选项
|
||||
// - 默认的日志分割选项为: WithMaxAge(7天), WithRotationTime(1天)
|
||||
func WithRotateOption(options ...rotateLogs.Option) Option {
|
||||
return func(log *Log) {
|
||||
log.rotateOptions = options
|
||||
// WithDisableCaller 设置是否禁用调用者
|
||||
func WithDisableCaller(disableCaller bool) Option {
|
||||
return func(config *Config) {
|
||||
config.DisableCaller = disableCaller
|
||||
}
|
||||
}
|
||||
|
||||
// WithLogDir 设置日志文件夹
|
||||
// - 默认情况下不会设置日志文件夹,日志将不会被文件存储
|
||||
func WithLogDir(logDir, rotateLogDir string) Option {
|
||||
return func(log *Log) {
|
||||
log.logDir = logDir
|
||||
log.rotateLogDir = rotateLogDir
|
||||
// WithDisableStacktrace 设置是否禁用堆栈跟踪
|
||||
func WithDisableStacktrace(disableStacktrace bool) Option {
|
||||
return func(config *Config) {
|
||||
config.DisableStacktrace = disableStacktrace
|
||||
}
|
||||
}
|
||||
|
||||
// WithSampling 设置采样策略
|
||||
func WithSampling(sampling *zap.SamplingConfig) Option {
|
||||
return func(config *Config) {
|
||||
config.Sampling = sampling
|
||||
}
|
||||
}
|
||||
|
||||
// WithEncoding 设置编码器
|
||||
func WithEncoding(encoding string) Option {
|
||||
return func(config *Config) {
|
||||
config.Encoding = encoding
|
||||
}
|
||||
}
|
||||
|
||||
// WithEncoderMessageKey 设置消息键
|
||||
func WithEncoderMessageKey(encoderMessageKey string) Option {
|
||||
return func(config *Config) {
|
||||
config.EncoderConfig.MessageKey = encoderMessageKey
|
||||
}
|
||||
}
|
||||
|
||||
// WithEncoderLevelKey 设置级别键
|
||||
func WithEncoderLevelKey(encoderLevelKey string) Option {
|
||||
return func(config *Config) {
|
||||
config.EncoderConfig.LevelKey = encoderLevelKey
|
||||
}
|
||||
}
|
||||
|
||||
// WithEncoderTimeKey 设置时间键
|
||||
func WithEncoderTimeKey(encoderTimeKey string) Option {
|
||||
return func(config *Config) {
|
||||
config.EncoderConfig.TimeKey = encoderTimeKey
|
||||
}
|
||||
}
|
||||
|
||||
// WithEncoderNameKey 设置名称键
|
||||
func WithEncoderNameKey(encoderNameKey string) Option {
|
||||
return func(config *Config) {
|
||||
config.EncoderConfig.NameKey = encoderNameKey
|
||||
}
|
||||
}
|
||||
|
||||
// WithEncoderCallerKey 设置调用者键
|
||||
func WithEncoderCallerKey(encoderCallerKey string) Option {
|
||||
return func(config *Config) {
|
||||
config.EncoderConfig.CallerKey = encoderCallerKey
|
||||
}
|
||||
}
|
||||
|
||||
// WithEncoderFunctionKey 设置函数键
|
||||
func WithEncoderFunctionKey(encoderFunctionKey string) Option {
|
||||
return func(config *Config) {
|
||||
config.EncoderConfig.FunctionKey = encoderFunctionKey
|
||||
}
|
||||
}
|
||||
|
||||
// WithEncoderStacktraceKey 设置堆栈跟踪键
|
||||
func WithEncoderStacktraceKey(encoderStacktraceKey string) Option {
|
||||
return func(config *Config) {
|
||||
config.EncoderConfig.StacktraceKey = encoderStacktraceKey
|
||||
}
|
||||
}
|
||||
|
||||
// WithEncoderLineEnding 设置行尾
|
||||
func WithEncoderLineEnding(encoderLineEnding string) Option {
|
||||
return func(config *Config) {
|
||||
config.EncoderConfig.LineEnding = encoderLineEnding
|
||||
}
|
||||
}
|
||||
|
||||
// WithEncoderLevel 设置级别编码器
|
||||
func WithEncoderLevel(encoderLevel LevelEncoder) Option {
|
||||
return func(config *Config) {
|
||||
config.EncoderConfig.EncodeLevel = encoderLevel
|
||||
}
|
||||
}
|
||||
|
||||
// WithEncoderTime 设置时间编码器
|
||||
func WithEncoderTime(encoderTime TimeEncoder) Option {
|
||||
return func(config *Config) {
|
||||
config.EncoderConfig.EncodeTime = encoderTime
|
||||
}
|
||||
}
|
||||
|
||||
// WithEncoderDuration 设置持续时间编码器
|
||||
func WithEncoderDuration(encoderDuration DurationEncoder) Option {
|
||||
return func(config *Config) {
|
||||
config.EncoderConfig.EncodeDuration = encoderDuration
|
||||
}
|
||||
}
|
||||
|
||||
// WithEncoderCaller 设置调用者编码器
|
||||
func WithEncoderCaller(encoderCaller CallerEncoder) Option {
|
||||
return func(config *Config) {
|
||||
config.EncoderConfig.EncodeCaller = encoderCaller
|
||||
}
|
||||
}
|
||||
|
||||
// WithEncoderName 设置名称编码器
|
||||
func WithEncoderName(encoderName NameEncoder) Option {
|
||||
return func(config *Config) {
|
||||
config.EncoderConfig.EncodeName = encoderName
|
||||
}
|
||||
}
|
||||
|
||||
// WithEncoderNewReflectedEncoder 设置反射编码器
|
||||
func WithEncoderNewReflectedEncoder(encoderNewReflectedEncoder func(io.Writer) ReflectedEncoder) Option {
|
||||
return func(config *Config) {
|
||||
config.EncoderConfig.NewReflectedEncoder = encoderNewReflectedEncoder
|
||||
}
|
||||
}
|
||||
|
||||
// WithOutputPaths 设置输出路径
|
||||
func WithOutputPaths(outputPaths ...string) Option {
|
||||
return func(config *Config) {
|
||||
config.OutputPaths = outputPaths
|
||||
}
|
||||
}
|
||||
|
||||
// WithErrorOutputPaths 设置错误输出路径
|
||||
func WithErrorOutputPaths(errorOutputPaths ...string) Option {
|
||||
return func(config *Config) {
|
||||
config.ErrorOutputPaths = errorOutputPaths
|
||||
}
|
||||
}
|
||||
|
||||
// WithInitialFields 设置初始字段
|
||||
func WithInitialFields(initialFields map[string]interface{}) Option {
|
||||
return func(config *Config) {
|
||||
config.InitialFields = initialFields
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
package log
|
||||
|
||||
const (
|
||||
// RunModeDev 开发模式是默认的运行模式,同时也是最基础的运行模式
|
||||
// - 开发模式下,将会输出所有级别的日志到控制台
|
||||
// - 默认不再输出日志到文件
|
||||
RunModeDev RunMode = iota
|
||||
// RunModeTest 测试模式是一种特殊的运行模式,用于测试
|
||||
// - 测试模式下,将会输出所有级别的日志到控制台和文件
|
||||
RunModeTest
|
||||
// RunModeProd 生产模式是一种特殊的运行模式,用于生产
|
||||
// - 生产模式下,将会输出 InfoLevel 及以上级别的日志到控制台和文件
|
||||
RunModeProd
|
||||
)
|
||||
|
||||
type RunMode uint8
|
Loading…
Reference in New Issue