forked from SoveraNia/SyzVegas
-
Notifications
You must be signed in to change notification settings - Fork 5
/
log.go
109 lines (98 loc) · 2.49 KB
/
log.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// 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 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("vv", 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 Fatal(err error) {
golog.Fatal(err)
}
func Fatalf(msg string, args ...interface{}) {
golog.Fatalf(msg, args...)
}
type VerboseWriter int
func (w VerboseWriter) Write(data []byte) (int, error) {
Logf(int(w), "%s", data)
return len(data), nil
}