-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathglogger.go
192 lines (158 loc) · 5.03 KB
/
glogger.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
package glog
import (
"io"
"os"
"sync"
)
const (
ERROR LogLevel = "ERROR"
INFO LogLevel = "INFO"
DEBUG LogLevel = "DEBUG"
WARN LogLevel = "WARN"
)
type LogLevel string
// Glogger is the interface for controlling logging
type Glogger interface {
Error(...interface{}) // error logger without format
Warn(...interface{}) // warning logger without format
Info(...interface{}) // info logger without format
Debug(...interface{}) // debug logger without format
log(LogLevel, ...interface{}) // logger without format
Errorf(string, ...interface{}) // error logger with format
Warnf(string, ...interface{}) // warning logger with format
Infof(string, ...interface{}) // info logger with format
Debugf(string, ...interface{}) // debug logger with format
logf(string, LogLevel, ...interface{}) // logger with format
Cleanup() // safely close the glogger
}
// Options is a struct for setting the format of the log messages
type Options struct {
Format string
Position string
}
// glog type is the logger data for logging concurrently to file
type glog struct {
out io.Writer // writer for logging to file / cmd line
queue chan interface{} // queue for logging
wg *sync.WaitGroup // wait group for logging
options []Options // options for formatting the log messages
depth int // depth of the function caller
}
// defaultGlogger is the default glogger
var defaultGlogger *UnstructureGlog
// initialize a default logger when user doesnot want a custom logger
func init() {
NewDefaultGlogger()
}
// NewDefaultGlogger creates a new Glog object for stdout and options for formatting
func NewDefaultGlogger() Glogger {
var wg sync.WaitGroup
// set std out as the default glogger
defaultGlogger = &UnstructureGlog{
glog: glog{
out: os.Stderr,
queue: make(chan interface{}, 1000),
wg: &wg,
options: []Options{},
depth: 2,
},
}
// start a goroutine to write to the file
sink(&defaultGlogger.glog)
return defaultGlogger
}
// safely close the default logger
func Cleanup() {
close(defaultGlogger.queue)
defaultGlogger.wg.Wait()
}
// NewUnstructureGlogger creates a new Glog object with the given file name and options for formatting
// the log messages. The file is created if it does not exist.
// The file is opened in append mode.
// The log messages are queued and written to the file in a separate goroutine.
// The queue is unbuffered.
func NewUnstructureGlogger(filePath string, options ...Options) Glogger {
// create new unstructured glogger
glogger, err := newUnstructuredGlogger(filePath, options...)
if err != nil {
return nil
}
// start a goroutine to write to the file
sink(&glogger.glog)
return glogger
}
// NewJSONGlogger creates a new Glog object with the given file name and options for formatting
// the log messages. The file is created if it does not exist.
// The file is opened in append mode.
// The log messages are queued and written to the file in a separate goroutine.
// The queue is unbuffered.
func NewJSONGlogger(filePath string, options ...Options) Glogger {
// create new unstructured glogger
glogger, err := newJSONGlogger(filePath, options...)
if err != nil {
return nil
}
// start a goroutine to write to the file
sink(&glogger.glog)
return glogger
}
// sink for logging asynchronously
func sink(glogger *glog) {
glogger.wg.Add(1)
// start a goroutine to write to the file
// and close the file when the glogger is closed
// this will block until the queue is empty
// and all the messages have been written
// to the file
// the is the only log writter for glogger
go func() {
defer glogger.wg.Done()
// defer glogger.out.Close()
for {
// dequeue new messages to be logged,
// if chan is closed, break from the loop and close logger
msg, ok := <-glogger.queue
if ok {
glogger.out.Write(msg.([]byte))
} else {
break
}
}
}()
}
// Error logs the error message to the file
func Error(msg ...interface{}) {
defaultGlogger.log(ERROR, msg...)
}
// Warn logs the warning message to the file
func Warn(msg ...interface{}) {
defaultGlogger.log(WARN, msg...)
}
// Info logs the warning message to the file
func Info(msg ...interface{}) {
defaultGlogger.log(INFO, msg...)
}
// Debug logs the warning message to the file
func Debug(msg ...interface{}) {
defaultGlogger.log(DEBUG, msg...)
}
// Error logs the error message to the file
func Errorf(format string, msg ...interface{}) {
defaultGlogger.logf(format, ERROR, msg...)
}
// Warn logs the warning message to the file
func Warnf(format string, msg ...interface{}) {
defaultGlogger.logf(format, WARN, msg...)
}
// Info logs the warning message to the file
func Infof(format string, msg ...interface{}) {
defaultGlogger.logf(format, INFO, msg...)
}
// Debug logs the warning message to the file
func Debugf(format string, msg ...interface{}) {
defaultGlogger.logf(format, DEBUG, msg...)
}
// returns the string representation of the log level
func (level LogLevel) string() string {
return string(level)
}