github.com/benz9527/xboot@v0.0.0-20240504061247-c23f15593274/xlog/file_core.go (about) 1 package xlog 2 3 import ( 4 "context" 5 "errors" 6 "io" 7 "os" 8 "path/filepath" 9 "time" 10 11 "go.uber.org/zap" 12 "go.uber.org/zap/zapcore" 13 ) 14 15 var _ xLogCore = (*consoleCore)(nil) 16 17 type fileCore struct { 18 core *commonCore 19 } 20 21 func (cc *fileCore) timeEncoder() zapcore.TimeEncoder { return cc.core.tsEnc } 22 func (cc *fileCore) levelEncoder() zapcore.LevelEncoder { return cc.core.lvlEnc } 23 func (cc *fileCore) writeSyncer() zapcore.WriteSyncer { return cc.core.ws } 24 func (cc *fileCore) outEncoder() func(cfg zapcore.EncoderConfig) zapcore.Encoder { 25 return cc.core.enc 26 } 27 func (cc *fileCore) context() context.Context { return cc.core.ctx } 28 func (cc *fileCore) Enabled(lvl zapcore.Level) bool { return cc.core.lvlEnabler.Enabled(lvl) } 29 func (cc *fileCore) With(fields []zap.Field) zapcore.Core { return cc.core.With(fields) } 30 func (cc *fileCore) Sync() error { return cc.core.Sync() } 31 func (cc *fileCore) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry { 32 return cc.core.Check(ent, ce) 33 } 34 35 func (cc *fileCore) Write(ent zapcore.Entry, fields []zap.Field) error { 36 return cc.core.Write(ent, fields) 37 } 38 39 type FileCoreConfig struct { 40 FilePath string `json:"filePath" yaml:"filePath"` 41 Filename string `json:"filename" yaml:"filename"` 42 FileMaxSize string `json:"fileMaxSize" yaml:"fileMaxSize"` 43 FileMaxAge string `json:"fileMaxAge" yaml:"fileMaxAge"` 44 FileZipName string `json:"fileZipName" yaml:"fileZipName"` 45 FileBufferSize string `json:"fileBufferSize" yaml:"fileBufferSize"` 46 FileBufferFlushInterval int64 `json:"fileBufferFlushInterval" yaml:"fileBufferFlushInterval"` // Milliseconds 47 FileMaxBackups int `json:"fileMaxBackups" yaml:"fileMaxBackups"` 48 FileCompressBatch int `json:"fileCompressBatch" yaml:"fileCompressBatch"` 49 FileCompressible bool `json:"fileCompressible" yaml:"fileCompressible"` 50 FileRotateEnable bool `json:"fileRotateEnable" yaml:"fileRotateEnable"` 51 } 52 53 // TODO Runtime modification and applying. 54 55 func newFileCore(cfg *FileCoreConfig) XLogCoreConstructor { 56 return func( 57 ctx context.Context, 58 lvlEnabler zapcore.LevelEnabler, 59 encoder logEncoderType, 60 lvlEnc zapcore.LevelEncoder, 61 tsEnc zapcore.TimeEncoder, 62 ) xLogCore { 63 // The root context is done and root writer will be close globally. 64 if ctx == nil { 65 return nil 66 } 67 68 if cfg == nil { 69 cfg = &FileCoreConfig{ 70 Filename: filepath.Base(os.Args[0]) + "_xlog.log", 71 FilePath: os.TempDir(), 72 FileRotateEnable: false, 73 } 74 } 75 76 var ( 77 err error 78 bufferEnabled = false 79 bufSize uint64 80 bufInterval int64 81 fileWriter io.WriteCloser 82 ws zapcore.WriteSyncer 83 ) 84 if cfg.FileBufferSize != "" && cfg.FileBufferFlushInterval > 0 { 85 bufSize, err = parseBufferSize(cfg.FileBufferSize) 86 if err != nil { 87 goto writerInit 88 } 89 if time.Duration(cfg.FileBufferFlushInterval).Milliseconds() < 200 { 90 bufInterval = 200 91 } else { 92 if bufInterval = cfg.FileBufferFlushInterval; bufInterval > _maxBufferFlushMs { 93 bufInterval = _maxBufferFlushMs 94 } 95 } 96 bufferEnabled = true 97 } 98 writerInit: 99 if cfg.FileRotateEnable { 100 fileWriter = RotateLog(ctx, cfg) 101 } else { 102 fileWriter = SingleLog(ctx, cfg) 103 } 104 if bufferEnabled { 105 ws = XLogBufferSyncer(ctx, fileWriter, bufSize, bufInterval) 106 } else { 107 ws = XLogLockSyncer(ctx, fileWriter) 108 } 109 110 cc := &fileCore{ 111 core: &commonCore{ 112 ctx: ctx, 113 lvlEnabler: lvlEnabler, 114 lvlEnc: lvlEnc, 115 tsEnc: tsEnc, 116 ws: ws, 117 enc: getEncoderByType(encoder), 118 }, 119 } 120 cfg := defaultCoreEncoderCfg() 121 cfg.EncodeLevel = cc.core.lvlEnc 122 cfg.EncodeTime = cc.core.tsEnc 123 cc.core.core = zapcore.NewCore(cc.core.enc(cfg), cc.core.ws, cc.core.lvlEnabler) 124 return cc 125 } 126 } 127 128 const ( 129 _maxBufferSize = 10 * MB 130 _maxBufferFlushMs = 3000 131 ) 132 133 func parseBufferSize(size string) (uint64, error) { 134 _size, err := parseFileSize(size) 135 if err != nil { 136 return 0, err 137 } 138 if _size > uint64(_maxBufferSize) { 139 return 0, errors.New("file buffer size too large") 140 } 141 return _size, nil 142 }