Commit 98cf2ceebd0d095ad926538279e57a3612a0898e
1 parent
5eaa49d2a4
Exists in
master
new interaface; allow multiple logger instances
Showing
1 changed file
with
75 additions
and
143 deletions
Show diff stats
main.go
1 | package gologger | 1 | package gologger |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "fmt" | 4 | "fmt" |
5 | "os" | 5 | "os" |
6 | "path/filepath" | 6 | "path/filepath" |
7 | "runtime" | 7 | "runtime" |
8 | "sync" | 8 | "sync" |
9 | "time" | 9 | "time" |
10 | ) | 10 | ) |
11 | 11 | ||
12 | type Option uint8 | ||
13 | |||
14 | const ( | ||
15 | Events Option = 0x01 | ||
16 | Errors Option = 0x02 | ||
17 | ) | ||
18 | |||
19 | const ( | 12 | const ( |
20 | MaxLogSize5MB int64 = 5 * 1024 * 1024 | 13 | MaxLogSize5MB int64 = 5 * 1024 * 1024 |
21 | MaxLogSize1MB int64 = 1 * 1024 * 1024 | 14 | MaxLogSize1MB int64 = 1 * 1024 * 1024 |
22 | MaxLogSize500KB int64 = 500 * 1024 | 15 | MaxLogSize500KB int64 = 500 * 1024 |
23 | MaxLogSize100KB int64 = 100 * 1024 | 16 | MaxLogSize100KB int64 = 100 * 1024 |
24 | MaxLogSize512B int64 = 512 | 17 | MaxLogSize512B int64 = 512 |
18 | logDirName = "log" | ||
25 | ) | 19 | ) |
26 | 20 | ||
27 | const errDirName = "error-logs" | ||
28 | const evtDirName = "event-logs" | ||
29 | |||
30 | type Logger struct { | 21 | type Logger struct { |
31 | muEv *sync.Mutex | 22 | mu *sync.Mutex |
32 | eventf *os.File | 23 | outputFile *os.File |
33 | |||
34 | eventFileName string | ||
35 | 24 | ||
36 | muEr *sync.Mutex | 25 | outputFileName string |
37 | errorf *os.File | 26 | maxFileSize int64 |
38 | |||
39 | errorFileName string | ||
40 | |||
41 | splitSize int64 | ||
42 | } | 27 | } |
43 | 28 | ||
44 | func New(name string, flags Option, splitSize int64) (logger *Logger, err error) { | 29 | func New(name string, maxFileSize int64) (logger *Logger, err error) { |
45 | logger = &Logger{} | 30 | logger = &Logger{} |
46 | 31 | ||
47 | logger.splitSize = splitSize | 32 | logger.outputFileName = name + "-log" |
48 | 33 | logger.mu = &sync.Mutex{} | |
49 | timestamp := "_" + time.Now().Format(time.RFC3339) | 34 | logger.maxFileSize = maxFileSize |
50 | |||
51 | // event file/dir | ||
52 | if flags&Events > 0 { | ||
53 | err = os.Mkdir(evtDirName, os.ModePerm) | ||
54 | if err != nil { | ||
55 | if !os.IsExist(err) { | ||
56 | fmt.Printf("logger: mkdir: couldn't create event log directory\n") | ||
57 | return nil, err | ||
58 | } | ||
59 | } | ||
60 | 35 | ||
61 | logger.eventFileName = name + "-events" | 36 | err = os.Mkdir(logDirName, os.ModePerm) |
62 | path := filepath.Join(evtDirName, logger.eventFileName+timestamp+".txt") | 37 | if err != nil { |
63 | logger.eventf, err = os.Create(path) | 38 | if !os.IsExist(err) { |
64 | if err != nil { | 39 | fmt.Printf("logger: mkdir: couldn't create event log directory\n") |
65 | fmt.Printf("logger: new: couldn't create event log file\n") | ||
66 | return nil, err | 40 | return nil, err |
67 | } | 41 | } |
68 | |||
69 | logger.muEv = &sync.Mutex{} | ||
70 | } | 42 | } |
71 | 43 | ||
72 | // error file/dir | 44 | timestamp := "_" + time.Now().Format(time.RFC3339) |
73 | if flags&Errors > 0 { | 45 | path := filepath.Join(logDirName, logger.outputFileName+timestamp+".txt") |
74 | err = os.Mkdir(errDirName, os.ModePerm) | 46 | logger.outputFile, err = os.Create(path) |
75 | if err != nil { | 47 | if err != nil { |
76 | if !os.IsExist(err) { | 48 | fmt.Printf("logger: new: couldn't create event log file\n") |
77 | fmt.Printf("logger: new: couldn't create error log directory\n") | 49 | return nil, err |
78 | return nil, err | ||
79 | } | ||
80 | } | ||
81 | |||
82 | logger.errorFileName = name + "-errors" | ||
83 | path := filepath.Join(errDirName, logger.errorFileName+timestamp+".txt") | ||
84 | logger.errorf, err = os.Create(path) | ||
85 | if err != nil { | ||
86 | fmt.Printf("logger: new: couldn't create error log file\n") | ||
87 | return nil, err | ||
88 | } | ||
89 | |||
90 | logger.muEr = &sync.Mutex{} | ||
91 | } | 50 | } |
92 | 51 | ||
93 | return logger, nil | 52 | return logger, nil |
94 | } | 53 | } |
95 | 54 | ||
96 | func (logger *Logger) Print(s string) { | 55 | func (logger *Logger) Print(format string, v ...interface{}) { |
97 | fmt.Printf(time.Now().Format(time.RFC3339) + ": " + s + "\n") | 56 | msg := fmt.Sprintf(format, v...) |
57 | fmt.Printf(time.Now().Format(time.RFC3339) + ": " + msg + "\n") | ||
98 | } | 58 | } |
99 | 59 | ||
100 | func (logger *Logger) LogEvent(event string) { | 60 | func (logger *Logger) Log(format string, v ...interface{}) { |
101 | if logger.eventf != nil { | 61 | if logger.outputFile != nil { |
102 | logger.muEv.Lock() | 62 | logger.mu.Lock() |
103 | defer logger.muEv.Unlock() | 63 | defer logger.mu.Unlock() |
104 | logger.eventf.WriteString(time.Now().Format(time.RFC3339) + ": " + event + "\n") | ||
105 | logger.splitEventLog() | ||
106 | } | ||
107 | } | ||
108 | 64 | ||
109 | func (logger *Logger) LogError(comment string, err error) { | 65 | msg := fmt.Sprintf(format, v...) |
110 | if logger.errorf != nil { | 66 | s := time.Now().Format(time.RFC3339) + ": " + msg + "\n" |
111 | logger.muEr.Lock() | 67 | if logger.shouldSplit(len(s)) { |
112 | defer logger.muEr.Unlock() | 68 | logger.split() |
113 | logger.errorf.WriteString(time.Now().Format(time.RFC3339) + ": " + comment + ": " + err.Error() + "\n") | 69 | } |
114 | logger.splitErrorLog() | 70 | logger.outputFile.WriteString(s) |
115 | } | 71 | } |
116 | } | 72 | } |
117 | 73 | ||
118 | func (logger *Logger) TraceEvent(event string) { | 74 | // TODO(marko) |
119 | if logger.eventf != nil { | 75 | /* |
120 | logger.muEv.Lock() | 76 | func (logger *Logger) LogHTTPRequest(req *http.Request) { |
121 | defer logger.muEv.Unlock() | 77 | if logger.outputFile != nil { |
122 | _, file, line, ok := runtime.Caller(1) | 78 | logger.mu.Lock() |
123 | var s string | 79 | defer logger.mu.Unlock() |
124 | if ok { | 80 | |
125 | s = fmt.Sprintf("%s: %s %d: %s\n", time.Now().Format(time.RFC3339), file, line, event) | 81 | msg := fmt.Sprintf(format, v...) |
126 | } else { | 82 | if logger.shouldSplit(len(s)) { |
127 | s = fmt.Sprintf(time.Now().Format(time.RFC3339) + ": [can't retreive stack details]:" + event + "\n") | 83 | logger.split() |
128 | } | 84 | } |
129 | logger.eventf.WriteString(s) | 85 | logger.outputFile.WriteString(time.Now().Format(time.RFC3339) + ": " + msg + "\n") |
130 | logger.splitEventLog() | ||
131 | } | 86 | } |
132 | } | 87 | } |
88 | */ | ||
133 | 89 | ||
134 | func (logger *Logger) TraceError(err error) { | 90 | func (logger *Logger) Trace(format string, v ...interface{}) { |
135 | if logger.errorf != nil { | 91 | if logger.outputFile != nil { |
136 | logger.muEr.Lock() | 92 | logger.mu.Lock() |
137 | defer logger.muEr.Unlock() | 93 | defer logger.mu.Unlock() |
138 | _, file, line, ok := runtime.Caller(1) | 94 | _, file, line, ok := runtime.Caller(1) |
139 | var s string | 95 | |
96 | s := "" | ||
97 | msg := fmt.Sprintf(format, v...) | ||
140 | if ok { | 98 | if ok { |
141 | s = fmt.Sprintf("%s %s %d: %s\n", time.Now().Format(time.RFC3339), file, line, err.Error()) | 99 | s = fmt.Sprintf("%s: %s %d: %s\n", time.Now().Format(time.RFC3339), file, line, msg) |
142 | } else { | 100 | } else { |
143 | s = fmt.Sprintf(time.Now().Format(time.RFC3339) + ": [can't retreive stack details]:" + err.Error() + "\n") | 101 | s = fmt.Sprintf(time.Now().Format(time.RFC3339) + ": [can't retreive stack details]:" + msg + "\n") |
102 | } | ||
103 | if logger.shouldSplit(len(s)) { | ||
104 | logger.split() | ||
144 | } | 105 | } |
145 | logger.errorf.WriteString(s) | 106 | logger.outputFile.WriteString(s) |
146 | logger.splitErrorLog() | ||
147 | } | 107 | } |
148 | } | 108 | } |
149 | 109 | ||
150 | func (logger *Logger) Close() { | 110 | func (logger *Logger) Close() { |
151 | if logger.eventf != nil { | 111 | if logger.outputFile != nil { |
152 | err := logger.eventf.Close() | 112 | err := logger.outputFile.Close() |
153 | if err != nil { | 113 | if err != nil { |
154 | fmt.Printf("logger: on exit: couldn't close event log file\n") | 114 | fmt.Printf("logger: on exit: couldn't close event log file\n") |
155 | } | 115 | } |
156 | } | 116 | } |
157 | |||
158 | if logger.errorf != nil { | ||
159 | err := logger.errorf.Close() | ||
160 | if err != nil { | ||
161 | fmt.Printf("logger: on exit: couldn't close error log file\n") | ||
162 | } | ||
163 | } | ||
164 | } | 117 | } |
165 | 118 | ||
166 | func (l *Logger) splitEventLog() { | 119 | func (l *Logger) split() { |
167 | timestamp := "_" + time.Now().Format(time.RFC3339) | 120 | timestamp := "_" + time.Now().Format(time.RFC3339) |
121 | // close old file | ||
122 | err := l.outputFile.Close() | ||
123 | if err != nil { | ||
124 | fmt.Printf("logger: split: couldn't close event file\n") | ||
125 | return | ||
126 | } | ||
127 | // open new file | ||
128 | var errnew error | ||
129 | path := filepath.Join(logDirName, l.outputFileName+timestamp) | ||
130 | l.outputFile, errnew = os.Create(path) | ||
168 | 131 | ||
169 | evfstats, _ := l.eventf.Stat() | 132 | if errnew != nil { |
170 | if evfstats.Size() >= l.splitSize { | 133 | fmt.Printf("logger: split: couldn't create event log file\n") |
171 | // close old file | ||
172 | err := l.eventf.Close() | ||
173 | if err != nil { | ||
174 | fmt.Printf("logger: split: couldn't close event file\n") | ||
175 | return | ||
176 | } | ||
177 | // open new file | ||
178 | var errnew error | ||
179 | path := filepath.Join(evtDirName, l.eventFileName+timestamp) | ||
180 | l.eventf, errnew = os.Create(path) | ||
181 | |||
182 | if errnew != nil { | ||
183 | fmt.Printf("logger: split: couldn't create event log file\n") | ||
184 | } | ||
185 | } | 134 | } |
186 | } | 135 | } |
187 | 136 | ||
188 | func (l *Logger) splitErrorLog() { | 137 | func (l *Logger) shouldSplit(nextEntrySize int) bool { |
189 | timestamp := "_" + time.Now().Format(time.RFC3339) | 138 | stats, _ := l.outputFile.Stat() |
190 | 139 | return int64(nextEntrySize) >= (l.maxFileSize - stats.Size()) | |
191 | erfstats, _ := l.errorf.Stat() |