github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/logconfig/rollingwriter/rollingwriter.go (about) 1 /* 2 * Copyright (C) 2019 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package rollingwriter 19 20 import ( 21 "fmt" 22 "io" 23 "os" 24 "path" 25 "sort" 26 "strings" 27 28 "github.com/arthurkiller/rollingwriter" 29 "github.com/rs/zerolog/log" 30 ) 31 32 // RollingWriter represents logs writer with logs rolling and cleanup support. 33 type RollingWriter struct { 34 config rollingwriter.Config 35 Writer io.Writer 36 } 37 38 // NewRollingWriter creates new rolling writer. 39 func NewRollingWriter(filepath string) (writer *RollingWriter, err error) { 40 writer = &RollingWriter{} 41 writer.config = rollingwriter.Config{ 42 TimeTagFormat: "20060102T150405", 43 LogPath: path.Dir(filepath), 44 FileName: path.Base(filepath), 45 RollingPolicy: rollingwriter.VolumeRolling, 46 RollingVolumeSize: "50MB", 47 Compress: true, 48 WriterMode: "lock", 49 MaxRemain: 5, 50 } 51 writer.Writer, err = rollingwriter.NewWriterFromConfig(&writer.config) 52 return writer, err 53 } 54 55 // Write writes to underlying rolling writer. 56 func (w *RollingWriter) Write(b []byte) (int, error) { 57 return w.Writer.Write(b) 58 } 59 60 // CleanObsoleteLogs cleans obsolete logs so that the count of remaining log files is equal to w.config.MaxRemain. 61 // rollingWriter only handles file rolling at runtime, but if the node is restarted, the count is lost thus we have 62 // to do this manually. 63 func (w *RollingWriter) CleanObsoleteLogs() error { 64 files, err := os.ReadDir(w.config.LogPath) 65 if err != nil { 66 return err 67 } 68 var oldLogFiles []os.FileInfo 69 baseFilename := w.config.FileName + ".log" 70 for _, file := range files { 71 if strings.Contains(file.Name(), baseFilename) && file.Name() != baseFilename { 72 fInfo, err := file.Info() 73 if err != nil { 74 return fmt.Errorf("failed to get file info: %w", err) 75 } 76 oldLogFiles = append(oldLogFiles, fInfo) 77 } 78 } 79 if len(oldLogFiles) <= w.config.MaxRemain { 80 log.Debug().Msgf("Found %d old log files in log directory, skipping cleanup", len(oldLogFiles)) 81 return nil 82 } 83 log.Debug().Msgf("Found %d old log files in log directory, proceeding to cleanup", len(oldLogFiles)) 84 sort.Slice(oldLogFiles, func(i, j int) bool { 85 return oldLogFiles[i].ModTime().After(oldLogFiles[j].ModTime()) 86 }) 87 for i := w.config.MaxRemain; i < len(oldLogFiles); i++ { 88 fp := path.Join(w.config.LogPath, oldLogFiles[i].Name()) 89 if err := os.Remove(fp); err != nil { 90 log.Warn().Err(err).Msg("Failed to remove log file: " + fp) 91 } 92 } 93 return nil 94 }