Commit 9dd4c982b887a6cdc9ef5d59d993a96193771790

Authored by Marko Tikvić
1 parent c138614d93
Exists in master

add CallerFilenameAndLineNumber()

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