diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2017-06-01 18:52:11 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2017-06-03 10:41:09 +0200 |
| commit | 23b94422d32946ab68a4f1423274bf4daa33cef9 (patch) | |
| tree | 887059e6bf16bbfcb786047dc8ec0246be7c82d6 /pkg | |
| parent | d1032c21a09c38fed45c34ffe9b7681139b8f812 (diff) | |
pkg/log: move from log
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/log/log.go | 98 | ||||
| -rw-r--r-- | pkg/log/log_test.go | 32 |
2 files changed, 130 insertions, 0 deletions
diff --git a/pkg/log/log.go b/pkg/log/log.go new file mode 100644 index 000000000..d57e8c1ad --- /dev/null +++ b/pkg/log/log.go @@ -0,0 +1,98 @@ +// Copyright 2016 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +// log package provides functionality similar to standard log package with some extensions: +// - verbosity levels +// - global verbosity setting that can be used by multiple packages +// - ability to disable all output +// - ability to cache recent output in memory +package log + +import ( + "bytes" + "flag" + "fmt" + golog "log" + "sync" + "time" +) + +var ( + flagV = flag.Int("v", 0, "verbosity") + mu sync.Mutex + cacheMem int + cacheMaxMem int + cachePos int + cacheEntries []string + prependTime = true // for testing +) + +// EnableCaching enables in memory caching of log output. +// Caches up to maxLines, but no more than maxMem bytes. +// Cached output can later be queried with CachedOutput. +func EnableLogCaching(maxLines, maxMem int) { + mu.Lock() + defer mu.Unlock() + if cacheEntries != nil { + Fatalf("log caching is already enabled") + } + if maxLines < 1 || maxMem < 1 { + panic("invalid maxLines/maxMem") + } + cacheMaxMem = maxMem + cacheEntries = make([]string, maxLines) +} + +// Retrieves cached log output. +func CachedLogOutput() string { + mu.Lock() + defer mu.Unlock() + buf := new(bytes.Buffer) + for i := range cacheEntries { + pos := (cachePos + i) % len(cacheEntries) + if cacheEntries[pos] == "" { + continue + } + buf.WriteString(cacheEntries[pos]) + buf.Write([]byte{'\n'}) + } + return buf.String() +} + +func Logf(v int, msg string, args ...interface{}) { + mu.Lock() + doLog := v <= *flagV + if cacheEntries != nil && v <= 1 { + cacheMem -= len(cacheEntries[cachePos]) + if cacheMem < 0 { + panic("log cache size underflow") + } + timeStr := "" + if prependTime { + timeStr = time.Now().Format("2006/01/02 15:04:05 ") + } + cacheEntries[cachePos] = fmt.Sprintf(timeStr+msg, args...) + cacheMem += len(cacheEntries[cachePos]) + cachePos++ + if cachePos == len(cacheEntries) { + cachePos = 0 + } + for i := 0; i < len(cacheEntries)-1 && cacheMem > cacheMaxMem; i++ { + pos := (cachePos + i) % len(cacheEntries) + cacheMem -= len(cacheEntries[pos]) + cacheEntries[pos] = "" + } + if cacheMem < 0 { + panic("log cache size underflow") + } + } + mu.Unlock() + + if doLog { + golog.Printf(msg, args...) + } +} + +func Fatalf(msg string, args ...interface{}) { + golog.Fatalf(msg, args...) +} diff --git a/pkg/log/log_test.go b/pkg/log/log_test.go new file mode 100644 index 000000000..cb40aceab --- /dev/null +++ b/pkg/log/log_test.go @@ -0,0 +1,32 @@ +// Copyright 2016 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package log + +import ( + "testing" +) + +func TestCaching(t *testing.T) { + tests := []struct{ str, want string }{ + {"", ""}, + {"a", "a\n"}, + {"bb", "a\nbb\n"}, + {"ccc", "a\nbb\nccc\n"}, + {"dddd", "a\nbb\nccc\ndddd\n"}, + {"eeeee", "bb\nccc\ndddd\neeeee\n"}, + {"ffffff", "ccc\ndddd\neeeee\nffffff\n"}, + {"ggggggg", "eeeee\nffffff\nggggggg\n"}, + {"hhhhhhhh", "ggggggg\nhhhhhhhh\n"}, + {"jjjjjjjjjjjjjjjjjjjjjjjjj", "jjjjjjjjjjjjjjjjjjjjjjjjj\n"}, + } + EnableLogCaching(4, 20) + prependTime = false + for _, test := range tests { + Logf(1, test.str) + out := CachedLogOutput() + if out != test.want { + t.Fatalf("wrote: %v\nwant: %v\ngot: %v", test.str, test.want, out) + } + } +} |
