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
|
// Package log implements a basic level based logger
package log
import (
"fmt"
"io"
"log"
"os"
"path"
"github.com/eduvpn/eduvpn-common/internal/oauth"
"github.com/eduvpn/eduvpn-common/internal/util"
"github.com/go-errors/errors"
)
type ErrLevel int8
const (
ErrOther ErrLevel = iota
ErrInfo
ErrWarning
ErrFatal
)
func GetErrorLevel(err error) ErrLevel {
// Get the inner error
e := err
if err1, ok := err.(*errors.Error); ok {
e = err1.Err
}
switch e.(type) {
case *oauth.CancelledCallbackError:
return ErrInfo
default:
return ErrOther
}
}
// FileLogger defines the type of logger that this package implements
// As the name suggests, it saves the log to a file.
type FileLogger struct {
// Level indicates which maximum level this logger actually forwards to the file
Level Level
// file represents a pointer to the open log file
file *os.File
}
type Level int8
const (
// LevelNotSet indicates level not set, not allowed.
LevelNotSet Level = iota
// LevelDebug indicates that the message is not an error but is there for debugging.
LevelDebug
// LevelInfo indicates that the message is not an error but is there for additional information.
LevelInfo
// LevelWarning indicates only a warning, the app still functions.
LevelWarning
// LevelError indicates a generic error, the app still functions but some functionality might not work.
LevelError
// LevelFatal indicates a fatal error, the app cannot function correctly when such an error occurs.
LevelFatal
)
// String returns the string of each level.
func (e Level) String() string {
switch e {
case LevelNotSet:
return "NOTSET"
case LevelDebug:
return "DEBUG"
case LevelInfo:
return "INFO"
case LevelWarning:
return "WARNING"
case LevelError:
return "ERROR"
case LevelFatal:
return "FATAL"
default:
return "UNKNOWN"
}
}
// Init initializes the logger by forwarding a max level 'level' and a directory 'directory' where the log should be stored
// If the logger cannot be initialized, for example an error in opening the log file, an error is returned.
func (logger *FileLogger) Init(lvl Level, dir string) error {
err := util.EnsureDirectory(dir)
if err != nil {
return err
}
f, err := os.OpenFile(
logger.filename(dir),
os.O_RDWR|os.O_CREATE|os.O_APPEND,
0o666,
)
if err != nil {
return errors.WrapPrefix(err, "failed creating log", 0)
}
multi := io.MultiWriter(os.Stdout, f)
log.SetOutput(multi)
logger.file = f
logger.Level = lvl
return nil
}
// Inheritf logs an error with a message and params using the error level verbosity of the error.
// The message is always prefixed with the error.
func (logger *FileLogger) Inheritf(err error, msg string, params...interface{}) {
if err == nil {
return
}
s := err.Error() + msg
switch GetErrorLevel(err) {
case ErrInfo:
logger.Infof(s, params...)
case ErrWarning:
logger.Warningf(s, params...)
case ErrOther:
logger.Errorf(s, params...)
case ErrFatal:
logger.Fatalf(s, params...)
}
}
// Debugf logs a message with parameters as level LevelDebug.
func (logger *FileLogger) Debugf(msg string, params ...interface{}) {
logger.log(LevelDebug, msg, params...)
}
// Infof logs a message with parameters as level LevelInfo.
func (logger *FileLogger) Infof(msg string, params ...interface{}) {
logger.log(LevelInfo, msg, params...)
}
// Warningf logs a message with parameters as level LevelWarning.
func (logger *FileLogger) Warningf(msg string, params ...interface{}) {
logger.log(LevelWarning, msg, params...)
}
// Errorf logs a message with parameters as level LevelError.
func (logger *FileLogger) Errorf(msg string, params ...interface{}) {
logger.log(LevelError, msg, params...)
}
// Fatalf logs a message with parameters as level LevelFatal.
func (logger *FileLogger) Fatalf(msg string, params ...interface{}) {
logger.log(LevelFatal, msg, params...)
}
// Close closes the logger by closing the internal file.
func (logger *FileLogger) Close() error {
return logger.file.Close()
}
// filename returns the filename of the logger by returning the full path as a string.
func (logger *FileLogger) filename(directory string) string {
return path.Join(directory, "log")
}
// log logs as level 'level' a message 'msg' with parameters 'params'.
func (logger *FileLogger) log(lvl Level, msg string, params ...interface{}) {
if lvl >= logger.Level && logger.Level != LevelNotSet {
fMsg := fmt.Sprintf(msg, params...)
f := fmt.Sprintf("- Go - %s - %s", lvl.String(), fMsg)
// To log file
log.Println(f)
}
}
|