Commit 3e936a3c2f80ff83b96672d6474b2358499ade44
1 parent
ed6549a336
Exists in
master
output file name sequence fix
Showing
1 changed file
with
22 additions
and
7 deletions
Show diff stats
main.go
1 | package gologger | 1 | package gologger |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "fmt" | 4 | "fmt" |
5 | "net/http" | 5 | "net/http" |
6 | "net/http/httputil" | 6 | "net/http/httputil" |
7 | "os" | 7 | "os" |
8 | "path/filepath" | 8 | "path/filepath" |
9 | "runtime" | 9 | "runtime" |
10 | "strings" | 10 | "strings" |
11 | "sync" | 11 | "sync" |
12 | "time" | 12 | "time" |
13 | ) | 13 | ) |
14 | 14 | ||
15 | const ( | 15 | const ( |
16 | MaxLogSize5MB int64 = 5 * 1024 * 1024 | 16 | MaxLogSize5MB int64 = 5 * 1024 * 1024 |
17 | MaxLogSize1MB int64 = 1 * 1024 * 1024 | 17 | MaxLogSize1MB int64 = 1 * 1024 * 1024 |
18 | MaxLogSize500KB int64 = 500 * 1024 | 18 | MaxLogSize500KB int64 = 500 * 1024 |
19 | MaxLogSize100KB int64 = 100 * 1024 | 19 | MaxLogSize100KB int64 = 100 * 1024 |
20 | MaxLogSize512B int64 = 512 | 20 | MaxLogSize512B int64 = 512 |
21 | logDirName = "log" | 21 | logDirName = "log" |
22 | ) | 22 | ) |
23 | 23 | ||
24 | type Logger struct { | 24 | type Logger struct { |
25 | mu *sync.Mutex | 25 | mu *sync.Mutex |
26 | outputFile *os.File | 26 | outputFile *os.File |
27 | 27 | ||
28 | outputFileName string | 28 | outputFileName string |
29 | fullName string | ||
29 | maxFileSize int64 | 30 | maxFileSize int64 |
30 | 31 | ||
31 | splitCount int | 32 | splitCount int |
32 | } | 33 | } |
33 | 34 | ||
34 | func New(name string, maxFileSize int64) (logger *Logger, err error) { | 35 | func New(name string, maxFileSize int64) (logger *Logger, err error) { |
35 | logger = &Logger{} | 36 | logger = &Logger{} |
36 | 37 | ||
37 | logger.outputFileName = name + "-log" | 38 | logger.outputFileName = name + "-log" |
38 | logger.mu = &sync.Mutex{} | 39 | logger.mu = &sync.Mutex{} |
39 | logger.maxFileSize = maxFileSize | 40 | logger.maxFileSize = maxFileSize |
40 | 41 | ||
41 | err = os.Mkdir(logDirName, os.ModePerm) | 42 | err = os.Mkdir(logDirName, os.ModePerm) |
42 | if err != nil { | 43 | if err != nil { |
43 | if !os.IsExist(err) { | 44 | if !os.IsExist(err) { |
44 | fmt.Printf("logger: mkdir: couldn't create event log directory\n") | 45 | fmt.Printf("logger: mkdir: couldn't create event log directory\n") |
45 | return nil, err | 46 | return nil, err |
46 | } | 47 | } |
47 | } | 48 | } |
48 | 49 | ||
49 | date := strings.Replace(time.Now().Format(time.RFC3339), ":", ".", -1) | 50 | date := strings.Replace(time.Now().Format(time.RFC3339), ":", ".", -1) |
50 | logger.outputFileName += "_" + date + ".txt" | 51 | logger.outputFileName += "_" + date |
51 | path := filepath.Join(logDirName, logger.outputFileName) | 52 | logger.fullName = logger.outputFileName + ".txt" |
53 | path := filepath.Join(logDirName, logger.fullName) | ||
52 | logger.outputFile, err = os.Create(path) | 54 | logger.outputFile, err = os.Create(path) |
53 | if err != nil { | 55 | if err != nil { |
54 | fmt.Printf("logger: new: couldn't create event log file\n") | 56 | fmt.Printf("logger: new: couldn't create event log file\n") |
55 | return nil, err | 57 | return nil, err |
56 | } | 58 | } |
57 | 59 | ||
58 | return logger, nil | 60 | return logger, nil |
59 | } | 61 | } |
60 | 62 | ||
61 | func (l *Logger) Print(format string, v ...interface{}) { | 63 | func (l *Logger) Print(format string, v ...interface{}) { |
62 | msg := fmt.Sprintf(format, v...) | 64 | msg := fmt.Sprintf(format, v...) |
63 | fmt.Printf(time.Now().Format(time.RFC3339) + ": " + msg + "\n") | 65 | fmt.Printf(time.Now().Format(time.RFC3339) + ": " + msg + "\n") |
64 | } | 66 | } |
65 | 67 | ||
66 | func (l *Logger) Log(format string, v ...interface{}) { | 68 | func (l *Logger) Log(format string, v ...interface{}) { |
67 | if l.outputFile == nil { | 69 | if l.outputFile == nil { |
68 | return | 70 | return |
69 | } | 71 | } |
70 | 72 | ||
71 | l.mu.Lock() | 73 | l.mu.Lock() |
72 | defer l.mu.Unlock() | 74 | defer l.mu.Unlock() |
73 | 75 | ||
74 | msg := fmt.Sprintf(format, v...) | 76 | msg := fmt.Sprintf(format, v...) |
75 | s := time.Now().Format(time.RFC3339) + ": " + msg + "\n" | 77 | s := time.Now().Format(time.RFC3339) + ": " + msg + "\n" |
76 | if l.shouldSplit(len(s)) { | 78 | if l.shouldSplit(len(s)) { |
77 | l.split() | 79 | l.split() |
78 | } | 80 | } |
79 | l.outputFile.WriteString(s) | 81 | l.outputFile.WriteString(s) |
80 | } | 82 | } |
81 | 83 | ||
82 | func (l *Logger) RequestLog(req *http.Request, userid string) string { | 84 | func (l *Logger) RequestLog(req *http.Request, userid string) string { |
83 | if l.outputFile == nil { | 85 | if l.outputFile == nil { |
84 | return "" | 86 | return "" |
85 | } | 87 | } |
86 | 88 | ||
87 | if userid == "" { | 89 | if userid == "" { |
88 | userid = "-" | 90 | userid = "-" |
89 | } | 91 | } |
90 | 92 | ||
91 | var b strings.Builder | 93 | var b strings.Builder |
92 | b.WriteString("Request:\n") | 94 | b.WriteString("Request:\n") |
93 | // CLF-like header | 95 | // CLF-like header |
94 | ts := time.Now().Format(time.RFC3339) | 96 | ts := time.Now().Format(time.RFC3339) |
95 | fmt.Fprintf(&b, "%s %s\n", req.RemoteAddr, ts) | 97 | fmt.Fprintf(&b, "%s %s\n", req.RemoteAddr, ts) |
96 | 98 | ||
97 | body, err := httputil.DumpRequest(req, true) | 99 | headers := req.Header |
98 | if err != nil { | 100 | content := headers.Get("Content-Type") |
99 | fmt.Fprintf(os.Stderr, "%v\n", err) | 101 | if content != "application/json" { |
102 | b.WriteString(fmt.Sprintf("%s %s\n", req.Method, req.URL)) | ||
103 | for k, h := range headers { | ||
104 | b.WriteString(k + ": ") | ||
105 | for _, h2 := range h { | ||
106 | b.WriteString(h2 + " ") | ||
107 | } | ||
108 | b.WriteString("\n") | ||
109 | } | ||
100 | } else { | 110 | } else { |
101 | b.WriteString(string(body)) | 111 | body, err := httputil.DumpRequest(req, true) |
112 | if err != nil { | ||
113 | fmt.Fprintf(os.Stderr, "%v\n", err) | ||
114 | } else { | ||
115 | b.WriteString(string(body)) | ||
116 | } | ||
102 | } | 117 | } |
103 | b.WriteString("\n\n") | 118 | b.WriteString("\n\n") |
104 | 119 | ||
105 | msg := b.String() | 120 | msg := b.String() |
106 | 121 | ||
107 | return msg | 122 | return msg |
108 | } | 123 | } |
109 | 124 | ||
110 | func (l *Logger) ResponseLog(status int, duration time.Duration, size int64) string { | 125 | func (l *Logger) ResponseLog(status int, duration time.Duration, size int64) string { |
111 | if l.outputFile == nil { | 126 | if l.outputFile == nil { |
112 | return "" | 127 | return "" |
113 | } | 128 | } |
114 | 129 | ||
115 | var b strings.Builder | 130 | var b strings.Builder |
116 | fmt.Fprintf(&b, "Response:\n%d %v %dB\n", status, duration, size) | 131 | fmt.Fprintf(&b, "Response:\n%d %v %dB\n", status, duration, size) |
117 | b.WriteString("==============================================================\n") | 132 | b.WriteString("==============================================================\n") |
118 | msg := b.String() | 133 | msg := b.String() |
119 | 134 | ||
120 | return msg | 135 | return msg |
121 | } | 136 | } |
122 | 137 | ||
123 | func (l *Logger) LogHTTPTraffic(in string, out string) { | 138 | func (l *Logger) LogHTTPTraffic(in string, out string) { |
124 | if l.outputFile == nil { | 139 | if l.outputFile == nil { |
125 | return | 140 | return |
126 | } | 141 | } |
127 | 142 | ||
128 | msg := in + out | 143 | msg := in + out |
129 | 144 | ||
130 | l.mu.Lock() | 145 | l.mu.Lock() |
131 | defer l.mu.Unlock() | 146 | defer l.mu.Unlock() |
132 | 147 | ||
133 | if l.shouldSplit(len(msg)) { | 148 | if l.shouldSplit(len(msg)) { |
134 | l.split() | 149 | l.split() |
135 | } | 150 | } |
136 | l.outputFile.WriteString(msg) | 151 | l.outputFile.WriteString(msg) |
137 | } | 152 | } |
138 | 153 | ||
139 | func (l *Logger) Trace(format string, v ...interface{}) { | 154 | func (l *Logger) Trace(format string, v ...interface{}) { |
140 | if l.outputFile == nil { | 155 | if l.outputFile == nil { |
141 | return | 156 | return |
142 | } | 157 | } |
143 | 158 | ||
144 | l.mu.Lock() | 159 | l.mu.Lock() |
145 | defer l.mu.Unlock() | 160 | defer l.mu.Unlock() |
146 | _, file, line, ok := runtime.Caller(1) | 161 | _, file, line, ok := runtime.Caller(1) |
147 | 162 | ||
148 | s := "" | 163 | s := "" |
149 | msg := fmt.Sprintf(format, v...) | 164 | msg := fmt.Sprintf(format, v...) |
150 | if ok { | 165 | if ok { |
151 | s = fmt.Sprintf("%s: %s %d: %s\n", time.Now().Format(time.RFC3339), file, line, msg) | 166 | s = fmt.Sprintf("%s: %s %d: %s\n", time.Now().Format(time.RFC3339), file, line, msg) |
152 | } else { | 167 | } else { |
153 | s = fmt.Sprintf(time.Now().Format(time.RFC3339) + ": [can't retreive stack details]:" + msg + "\n") | 168 | s = fmt.Sprintf(time.Now().Format(time.RFC3339) + ": [can't retreive stack details]:" + msg + "\n") |
154 | } | 169 | } |
155 | if l.shouldSplit(len(s)) { | 170 | if l.shouldSplit(len(s)) { |
156 | l.split() | 171 | l.split() |
157 | } | 172 | } |
158 | l.outputFile.WriteString(s) | 173 | l.outputFile.WriteString(s) |
159 | } | 174 | } |
160 | 175 | ||
161 | func (l *Logger) Close() { | 176 | func (l *Logger) Close() { |
162 | if l.outputFile == nil { | 177 | if l.outputFile == nil { |
163 | return | 178 | return |
164 | } | 179 | } |
165 | 180 | ||
166 | err := l.outputFile.Close() | 181 | err := l.outputFile.Close() |
167 | if err != nil { | 182 | if err != nil { |
168 | fmt.Printf("logger: on exit: couldn't close event log file\n") | 183 | fmt.Printf("logger: on exit: couldn't close event log file\n") |
169 | } | 184 | } |
170 | } | 185 | } |
171 | 186 | ||
172 | func (l *Logger) split() { | 187 | func (l *Logger) split() { |
173 | if l.outputFile == nil { | 188 | if l.outputFile == nil { |
174 | return | 189 | return |
175 | } | 190 | } |
176 | 191 | ||
177 | // close old file | 192 | // close old file |
178 | err := l.outputFile.Close() | 193 | err := l.outputFile.Close() |
179 | if err != nil { | 194 | if err != nil { |
180 | fmt.Printf("logger: split: couldn't close event file\n") | 195 | fmt.Printf("logger: split: couldn't close event file\n") |
181 | return | 196 | return |
182 | } | 197 | } |
183 | 198 | ||
184 | l.splitCount++ | 199 | l.splitCount++ |
185 | // open new file | 200 | // open new file |
186 | var errnew error | 201 | var errnew error |
187 | path := filepath.Join(logDirName, l.outputFileName+fmt.Sprintf("(%d)", l.splitCount)) | 202 | path := filepath.Join(logDirName, l.outputFileName+fmt.Sprintf("(%d)", l.splitCount)+".txt") |
188 | l.outputFile, errnew = os.Create(path) | 203 | l.outputFile, errnew = os.Create(path) |
189 | 204 | ||
190 | if errnew != nil { | 205 | if errnew != nil { |
191 | fmt.Printf("logger: split: couldn't create event log file\n") | 206 | fmt.Printf("logger: split: couldn't create event log file\n") |
192 | } | 207 | } |
193 | } | 208 | } |
194 | 209 | ||
195 | func (l *Logger) shouldSplit(nextEntrySize int) bool { | 210 | func (l *Logger) shouldSplit(nextEntrySize int) bool { |
196 | stats, _ := l.outputFile.Stat() | 211 | stats, _ := l.outputFile.Stat() |
197 | return int64(nextEntrySize) >= (l.maxFileSize - stats.Size()) | 212 | return int64(nextEntrySize) >= (l.maxFileSize - stats.Size()) |
198 | } | 213 | } |
199 | 214 |