-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
zap_disk_logging.go
139 lines (110 loc) · 3.05 KB
/
zap_disk_logging.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package logger
import (
"sync"
"time"
"github.com/smartcontractkit/chainlink/v2/core/utils"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
const (
// `Fatal` is the max log level allowed, so log levels like `Panic` or `Critical` won't be logged to disk if this is set.
disabledLevel = zapcore.FatalLevel + 1
diskPollInterval = 1 * time.Minute
)
type zapDiskPollConfig struct {
stop func()
pollChan <-chan time.Time
}
func (c zapDiskPollConfig) isSet() bool {
return c.stop != nil || c.pollChan != nil
}
func newDiskPollConfig(interval time.Duration) zapDiskPollConfig {
ticker := time.NewTicker(utils.WithJitter(interval))
return zapDiskPollConfig{
pollChan: ticker.C,
stop: ticker.Stop,
}
}
var _ Logger = &zapDiskLogger{}
type zapDiskLogger struct {
zapLogger
config Config
diskLogLevel zap.AtomicLevel
pollDiskSpaceStop chan struct{}
pollDiskSpaceDone chan struct{}
}
func (l *zapDiskLogger) pollDiskSpace() {
defer l.config.diskPollConfig.stop()
defer close(l.pollDiskSpaceDone)
for {
select {
case <-l.pollDiskSpaceStop:
return
case <-l.config.diskPollConfig.pollChan:
lvl := zapcore.DebugLevel
diskUsage, err := l.config.DiskSpaceAvailable(l.config.Dir)
if err != nil {
// Will no longer log to disk
lvl = disabledLevel
l.Warnw("Error getting disk space available for logging", "err", err)
} else if diskUsage < l.config.RequiredDiskSpace() {
// Will no longer log to disk
lvl = disabledLevel
l.Warnf(
"Disk space is not enough to log into disk any longer, required disk space: %s, Available disk space: %s",
l.config.RequiredDiskSpace(),
diskUsage,
)
}
lvlBefore := l.diskLogLevel.Level()
l.diskLogLevel.SetLevel(lvl)
if lvlBefore == disabledLevel && lvl == zapcore.DebugLevel {
l.Info("Resuming disk logs, disk has enough space")
}
if l.config.testDiskLogLvlChan != nil {
l.config.testDiskLogLvlChan <- lvl
}
}
}
}
func newRotatingFileLogger(zcfg zap.Config, c Config, cores ...zapcore.Core) (*zapDiskLogger, func() error, error) {
defaultCore, defaultCloseFn, err := newDefaultLoggingCore(zcfg, c.UnixTS)
if err != nil {
return nil, nil, err
}
cores = append(cores, defaultCore)
diskLogLevel := zap.NewAtomicLevelAt(zapcore.DebugLevel)
diskCore, diskErr := newDiskCore(diskLogLevel, c)
if diskErr != nil {
defaultCloseFn()
return nil, nil, diskErr
}
cores = append(cores, diskCore)
core := zapcore.NewTee(cores...)
l, diskCloseFn, err := newLoggerForCore(zcfg, core)
if err != nil {
defaultCloseFn()
return nil, nil, err
}
lggr := &zapDiskLogger{
config: c,
pollDiskSpaceStop: make(chan struct{}),
pollDiskSpaceDone: make(chan struct{}),
zapLogger: *l,
diskLogLevel: diskLogLevel,
}
go lggr.pollDiskSpace()
var once sync.Once
closeLogger := func() error {
var innerErr error
once.Do(func() {
defer defaultCloseFn()
defer diskCloseFn()
close(lggr.pollDiskSpaceStop)
<-lggr.pollDiskSpaceDone
innerErr = lggr.Sync()
})
return innerErr
}
return lggr, closeLogger, err
}