-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add log configuration #63
Open
yzj0911
wants to merge
7
commits into
mosn:master
Choose a base branch
from
yzj0911:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 6 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
ac2c3f8
add log configuration And ingore linter G302
yzj0911 cf9ba21
doc: delete coveraeg.txt updated
yzj0911 7c1ffb9
doc:delete coveraeg.txt
yzj0911 31a5e97
refactor:logginfo use *roller
yzj0911 770bffd
fix:roller_test error
yzj0911 948c3ee
chore:use default number
yzj0911 c201ec7
fix:sync.waitgroup
yzj0911 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,12 +18,16 @@ | |
package log | ||
|
||
import ( | ||
"compress/gzip" | ||
"errors" | ||
"fmt" | ||
"io" | ||
"io/ioutil" | ||
"os" | ||
"path/filepath" | ||
"runtime/debug" | ||
"sort" | ||
"strconv" | ||
"strings" | ||
"sync" | ||
"time" | ||
|
@@ -76,7 +80,7 @@ type Logger struct { | |
} | ||
|
||
type LoggerInfo struct { | ||
LogRoller Roller | ||
LogRoller *Roller | ||
FileName string | ||
CreateTime time.Time | ||
} | ||
|
@@ -205,6 +209,7 @@ func (l *Logger) start() error { | |
l.create = time.Now() | ||
} | ||
l.writer = file | ||
l.mill() | ||
l.once.Do(l.startRotate) // start rotate, only once | ||
} | ||
} | ||
|
@@ -247,6 +252,7 @@ func (l *Logger) handler() { | |
} | ||
} | ||
case buf := <-l.writeBufferChan: | ||
|
||
yzj0911 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
l.Write(buf.Bytes()) | ||
PutLogBuffer(buf) | ||
} | ||
|
@@ -411,7 +417,7 @@ func doRotateFunc(l *Logger, interval time.Duration) { | |
case <-timer.C: | ||
now := time.Now() | ||
info := LoggerInfo{FileName: l.output, CreateTime: l.create} | ||
info.LogRoller = *l.roller | ||
info.LogRoller = l.roller | ||
l.roller.Handler(&info) | ||
l.create = now | ||
go l.Reopen() | ||
|
@@ -471,3 +477,204 @@ func parseSyslogAddress(location string) *syslogAddress { | |
|
||
return nil | ||
} | ||
|
||
const ( | ||
compressSuffix = ".gz" | ||
) | ||
|
||
// millRunOnce performs compression and removal of stale log files. | ||
// Log files are compressed if enabled via configuration and old log | ||
// files are removed, keeping at most l.MaxBackups files, as long as | ||
// none of them are older than MaxAge. | ||
func (l *Logger) millRunOnce() error { | ||
files, err := l.oldLogFiles() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
compress, remove := l.screeningCompressFile(files) | ||
|
||
for _, f := range remove { | ||
_ = os.Remove(filepath.Join(l.dir(), f.FileName)) | ||
} | ||
var wg sync.WaitGroup | ||
for _, f := range compress { | ||
var fnCompress, fileName string | ||
fileName = f.FileName | ||
wg.Add(1) | ||
fnCompress, err = l.findCompressFile(fileName) | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "logger %s findCompressFile , error: %v", l.output, err) | ||
return err | ||
} | ||
go func(fnCompress, fileName string, wg *sync.WaitGroup) { | ||
wg.Done() | ||
yzj0911 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
err = l.compressLogFile(fileName, fnCompress) | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "logger %s compressLogFile , error: %v", l.output, err) | ||
} | ||
}(fnCompress, fileName, &wg) | ||
} | ||
wg.Wait() | ||
return err | ||
} | ||
|
||
func (l *Logger) screeningCompressFile(files []LoggerInfo) (compress, remove []LoggerInfo) { | ||
resFiles, removeByMaxAge := l.screeningCompressFileByMaxAge(files) | ||
resFiles, remove = l.screeningCompressFileByMaxBackups(resFiles, removeByMaxAge) | ||
|
||
if l.roller.Compress { | ||
for i := range resFiles { | ||
if !strings.HasSuffix(resFiles[i].FileName, compressSuffix) { | ||
compress = append(compress, resFiles[i]) | ||
} | ||
} | ||
} | ||
return | ||
} | ||
|
||
func (l *Logger) screeningCompressFileByMaxAge(files []LoggerInfo) (resFiles, remove []LoggerInfo) { | ||
if l.roller.MaxAge > 0 { | ||
diff := time.Duration(int64(maxRotateHour*time.Hour) * int64(l.roller.MaxAge)) | ||
cutoff := time.Now().Add(-1 * diff) | ||
|
||
for i := range files { | ||
if files[i].CreateTime.Before(cutoff) { | ||
remove = append(remove, files[i]) | ||
} else { | ||
resFiles = append(resFiles, files[i]) | ||
} | ||
} | ||
} else { | ||
resFiles = files | ||
} | ||
return | ||
} | ||
|
||
func (l *Logger) screeningCompressFileByMaxBackups(files, remove []LoggerInfo) (resFiles, resRemove []LoggerInfo) { | ||
if l.roller.MaxBackups > 0 && l.roller.MaxBackups < len(files) { | ||
preserved := make(map[string]bool) | ||
|
||
for i := range files { | ||
// Only count the uncompressed log file or the | ||
// compressed log file, not both. | ||
fn := files[i].FileName | ||
|
||
preserved[strings.TrimSuffix(fn, compressSuffix)] = true | ||
|
||
if len(preserved) > l.roller.MaxBackups { | ||
remove = append(remove, files[i]) | ||
} else { | ||
resFiles = append(resFiles, files[i]) | ||
} | ||
} | ||
} else { | ||
resFiles = files | ||
} | ||
resRemove = remove | ||
return | ||
} | ||
|
||
//findCompressFile Find the compressed file name based on the file name ,compressed file is not exist。 | ||
func (l *Logger) findCompressFile(fileName string) (string, error) { | ||
var ( | ||
num = 1 | ||
statName = fileName | ||
err error | ||
) | ||
|
||
for i := 0; i <= l.roller.MaxBackups; i++ { | ||
if _, err = os.Stat(l.dir() + statName + compressSuffix); os.IsNotExist(err) { | ||
return statName + compressSuffix, nil | ||
} | ||
statName = fileName + "." + strconv.Itoa(num) | ||
num++ | ||
} | ||
return fileName, err | ||
} | ||
|
||
func (l *Logger) mill() { | ||
if l.roller.MaxBackups != defaultRotateKeep || l.roller.MaxAge != defaultRotateAge || l.roller.Compress { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这个判断套件不太对啊。 |
||
_ = l.millRunOnce() | ||
} | ||
} | ||
|
||
// oldLogFiles returns the list of backup log files stored in the same | ||
// directory as the current log file, sorted by ModTime | ||
func (l *Logger) oldLogFiles() ([]LoggerInfo, error) { | ||
files, err := ioutil.ReadDir(l.dir()) | ||
if err != nil { | ||
return nil, err | ||
} | ||
logFiles := []LoggerInfo{} | ||
|
||
for _, f := range files { | ||
if f.IsDir() { | ||
continue | ||
} | ||
if !strings.HasPrefix(f.Name(), filepath.Base(l.output)+".") { | ||
continue | ||
} | ||
logFiles = append(logFiles, LoggerInfo{l.roller, f.Name(), f.ModTime()}) | ||
} | ||
sort.Sort(byFormatTime(logFiles)) | ||
|
||
return logFiles, nil | ||
} | ||
|
||
// dir returns the directory for the current filename. | ||
func (l *Logger) dir() string { | ||
return filepath.Dir(l.output) | ||
} | ||
|
||
// compressLogFile compresses the given log file, removing the | ||
// uncompressed log file if successful. | ||
func (l *Logger) compressLogFile(srcFile, dstFile string) error { | ||
f, err := os.Open(filepath.Join(l.dir(), filepath.Clean(srcFile))) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
defer func() { | ||
_ = f.Close() | ||
}() | ||
|
||
gzf, err := os.OpenFile(filepath.Join(l.dir(), filepath.Clean(dstFile)), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
defer func() { | ||
_ = gzf.Close() | ||
if err != nil { | ||
_ = os.Remove(filepath.Join(l.dir(), filepath.Clean(dstFile))) | ||
} | ||
}() | ||
|
||
gz := gzip.NewWriter(gzf) | ||
|
||
if _, err = io.Copy(gz, f); err != nil { | ||
nejisama marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return err | ||
} | ||
|
||
if err = gz.Close(); err != nil { | ||
return err | ||
} | ||
|
||
return os.Remove(filepath.Join(l.dir(), filepath.Clean(srcFile))) | ||
} | ||
|
||
// byFormatTime sorts by newest time formatted in the name. | ||
type byFormatTime []LoggerInfo | ||
|
||
func (b byFormatTime) Less(i, j int) bool { | ||
return b[i].CreateTime.After(b[j].CreateTime) | ||
} | ||
|
||
func (b byFormatTime) Swap(i, j int) { | ||
b[i], b[j] = b[j], b[i] | ||
} | ||
|
||
func (b byFormatTime) Len() int { | ||
return len(b) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -400,3 +400,60 @@ WAIT: | |
t.Logf("received %d reopens", reopens) | ||
close(l.stopRotate) | ||
} | ||
|
||
func TestLogRollerTimeAndCompress(t *testing.T) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 测试应该覆盖如下场景:
|
||
logName := "/tmp/mosn_bench/defaultCompress.log" | ||
rollerName := logName + "." + time.Now().Format("2006-01-02_15") | ||
os.Remove(logName) | ||
os.Remove(rollerName) | ||
// replace rotate interval for test | ||
doRotate = testRotateByKeep | ||
defer func() { | ||
doRotate = testRotateByKeep | ||
}() | ||
//default MaxBackups=10 | ||
logger, err := GetOrCreateLogger(logName, &Roller{MaxTime: 1, Handler: rollerHandler, Compress: true, MaxBackups: 1}) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
// 1111 will be rotated to rollerName | ||
logger.Print(newLogBufferString("1111111"), false) | ||
time.Sleep(2 * time.Second) | ||
// 2222 will be writed in logName | ||
logger.Print(newLogBufferString("2222222"), false) | ||
time.Sleep(1 * time.Second) | ||
logger.Close() // stop the rotate | ||
|
||
if !exists(rollerName + compressSuffix) { | ||
t.Fatalf("compress is failed") | ||
} | ||
} | ||
|
||
func testRotateByKeep(l *Logger, interval time.Duration) { | ||
doRotateFunc(l, 1*time.Second) | ||
} | ||
func TestLogRollerTimeAndKeep(t *testing.T) { | ||
yzj0911 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
logName := "/tmp/mosn_bench/defaultKeep.log" | ||
rollerName := logName + "." + time.Now().Format("2006-01-02_15") | ||
os.Remove(logName) | ||
os.Remove(rollerName) | ||
// replace rotate interval for test | ||
doRotate = testRotateByKeep | ||
defer func() { | ||
doRotate = testRotateByKeep | ||
}() | ||
logger, err := GetOrCreateLogger(logName, &Roller{MaxTime: 2, Handler: rollerHandler, MaxBackups: 1}) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
logger.Print(newLogBufferString("1111111"), false) | ||
time.Sleep(2 * time.Second) | ||
logger.Print(newLogBufferString("2222222"), false) | ||
time.Sleep(2 * time.Second) | ||
logger.Print(newLogBufferString("3333333"), false) | ||
time.Sleep(1 * time.Second) | ||
logger.Close() // stop the rotate | ||
if exists(rollerName) { | ||
t.Fatalf(" %s is exists", rollerName) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里执行mill ,看上去可能会有一些耗时。在这期间这个logger实际上是没有办法正常工作的(后面的l.handler没有执行)。如果这里mill 卡太久,可能会导致日志丢失等情况出现,这是需要考虑的风险。
是否可以考虑将这个mill 做成异步的,可以按照日志路径有锁避免并发冲突?但是不影响start的时候及时可以执行写新日志,可以讨论一下