forked from rclone/rclone
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlog.go
223 lines (200 loc) · 6.19 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
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
package fs
import (
"context"
"fmt"
"log"
"os"
"github.com/sirupsen/logrus"
)
// LogLevel describes rclone's logs. These are a subset of the syslog log levels.
type LogLevel byte
// Log levels. These are the syslog levels of which we only use a
// subset.
//
// LOG_EMERG system is unusable
// LOG_ALERT action must be taken immediately
// LOG_CRIT critical conditions
// LOG_ERR error conditions
// LOG_WARNING warning conditions
// LOG_NOTICE normal, but significant, condition
// LOG_INFO informational message
// LOG_DEBUG debug-level message
const (
LogLevelEmergency LogLevel = iota
LogLevelAlert
LogLevelCritical
LogLevelError // Error - can't be suppressed
LogLevelWarning
LogLevelNotice // Normal logging, -q suppresses
LogLevelInfo // Transfers, needs -v
LogLevelDebug // Debug level, needs -vv
)
var logLevelToString = []string{
LogLevelEmergency: "EMERGENCY",
LogLevelAlert: "ALERT",
LogLevelCritical: "CRITICAL",
LogLevelError: "ERROR",
LogLevelWarning: "WARNING",
LogLevelNotice: "NOTICE",
LogLevelInfo: "INFO",
LogLevelDebug: "DEBUG",
}
// String turns a LogLevel into a string
func (l LogLevel) String() string {
if l >= LogLevel(len(logLevelToString)) {
return fmt.Sprintf("LogLevel(%d)", l)
}
return logLevelToString[l]
}
// Set a LogLevel
func (l *LogLevel) Set(s string) error {
for n, name := range logLevelToString {
if s != "" && name == s {
*l = LogLevel(n)
return nil
}
}
return fmt.Errorf("unknown log level %q", s)
}
// Type of the value
func (l *LogLevel) Type() string {
return "string"
}
// UnmarshalJSON makes sure the value can be parsed as a string or integer in JSON
func (l *LogLevel) UnmarshalJSON(in []byte) error {
return UnmarshalJSONFlag(in, l, func(i int64) error {
if i < 0 || i >= int64(LogLevel(len(logLevelToString))) {
return fmt.Errorf("unknown log level %d", i)
}
*l = (LogLevel)(i)
return nil
})
}
// LogPrintPid enables process pid in log
var LogPrintPid = false
// LogPrint sends the text to the logger of level
var LogPrint = func(level LogLevel, text string) {
text = fmt.Sprintf("%-6s: %s", level, text)
if LogPrintPid {
text = fmt.Sprintf("[%d] %s", os.Getpid(), text)
}
_ = log.Output(4, text)
}
// LogValueItem describes keyed item for a JSON log entry
type LogValueItem struct {
key string
value interface{}
render bool
}
// LogValue should be used as an argument to any logging calls to
// augment the JSON output with more structured information.
//
// key is the dictionary parameter used to store value.
func LogValue(key string, value interface{}) LogValueItem {
return LogValueItem{key: key, value: value, render: true}
}
// LogValueHide should be used as an argument to any logging calls to
// augment the JSON output with more structured information.
//
// key is the dictionary parameter used to store value.
//
// String() will return a blank string - this is useful to put items
// in which don't print into the log.
func LogValueHide(key string, value interface{}) LogValueItem {
return LogValueItem{key: key, value: value, render: false}
}
// String returns the representation of value. If render is fals this
// is an empty string so LogValueItem entries won't show in the
// textual representation of logs.
func (j LogValueItem) String() string {
if !j.render {
return ""
}
if do, ok := j.value.(fmt.Stringer); ok {
return do.String()
}
return fmt.Sprint(j.value)
}
// LogPrintf produces a log string from the arguments passed in
func LogPrintf(level LogLevel, o interface{}, text string, args ...interface{}) {
out := fmt.Sprintf(text, args...)
if GetConfig(context.TODO()).UseJSONLog {
fields := logrus.Fields{}
if o != nil {
fields = logrus.Fields{
"object": fmt.Sprintf("%+v", o),
"objectType": fmt.Sprintf("%T", o),
}
}
for _, arg := range args {
if item, ok := arg.(LogValueItem); ok {
fields[item.key] = item.value
}
}
switch level {
case LogLevelDebug:
logrus.WithFields(fields).Debug(out)
case LogLevelInfo:
logrus.WithFields(fields).Info(out)
case LogLevelNotice, LogLevelWarning:
logrus.WithFields(fields).Warn(out)
case LogLevelError:
logrus.WithFields(fields).Error(out)
case LogLevelCritical:
logrus.WithFields(fields).Fatal(out)
case LogLevelEmergency, LogLevelAlert:
logrus.WithFields(fields).Panic(out)
}
} else {
if o != nil {
out = fmt.Sprintf("%v: %s", o, out)
}
LogPrint(level, out)
}
}
// LogLevelPrintf writes logs at the given level
func LogLevelPrintf(level LogLevel, o interface{}, text string, args ...interface{}) {
if GetConfig(context.TODO()).LogLevel >= level {
LogPrintf(level, o, text, args...)
}
}
// Errorf writes error log output for this Object or Fs. It
// should always be seen by the user.
func Errorf(o interface{}, text string, args ...interface{}) {
if GetConfig(context.TODO()).LogLevel >= LogLevelError {
LogPrintf(LogLevelError, o, text, args...)
}
}
// Logf writes log output for this Object or Fs. This should be
// considered to be Notice level logging. It is the default level.
// By default rclone should not log very much so only use this for
// important things the user should see. The user can filter these
// out with the -q flag.
func Logf(o interface{}, text string, args ...interface{}) {
if GetConfig(context.TODO()).LogLevel >= LogLevelNotice {
LogPrintf(LogLevelNotice, o, text, args...)
}
}
// Infof writes info on transfers for this Object or Fs. Use this
// level for logging transfers, deletions and things which should
// appear with the -v flag.
func Infof(o interface{}, text string, args ...interface{}) {
if GetConfig(context.TODO()).LogLevel >= LogLevelInfo {
LogPrintf(LogLevelInfo, o, text, args...)
}
}
// Debugf writes debugging output for this Object or Fs. Use this for
// debug only. The user must have to specify -vv to see this.
func Debugf(o interface{}, text string, args ...interface{}) {
if GetConfig(context.TODO()).LogLevel >= LogLevelDebug {
LogPrintf(LogLevelDebug, o, text, args...)
}
}
// LogDirName returns an object for the logger, logging a root
// directory which would normally be "" as the Fs
func LogDirName(f Fs, dir string) interface{} {
if dir != "" {
return dir
}
return f
}