Commit 98cf2ceebd0d095ad926538279e57a3612a0898e

Authored by Marko Tikvić
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
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()