Commit 8d63648a352543f3bc1a23d8a73dfcbe25ebe123

Authored by Marko Tikvić
1 parent d9c0226889
Exists in master

CallerFilenameAndLineNumber()

Showing 1 changed file with 1 additions and 1 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 ... 92 // CallerFilenameAndLineNumber ...
93 func CallerFilenameAndLineNumber() (string, int) { 93 func CallerFilenameAndLineNumber() (string, int) {
94 _, path, line, _ := runtime.Caller(1) 94 _, path, line, _ := runtime.Caller(2)
95 file := filepath.Base(path) 95 file := filepath.Base(path)
96 return file, line 96 return file, line
97 } 97 }
98 98
99 // PrintTrace ... 99 // PrintTrace ...
100 func (l *Logger) PrintTrace(format string, v ...interface{}) { 100 func (l *Logger) PrintTrace(format string, v ...interface{}) {
101 file, line := CallerFilenameAndLineNumber() 101 file, line := CallerFilenameAndLineNumber()
102 102
103 msg := fmt.Sprintf(format, v...) 103 msg := fmt.Sprintf(format, v...)
104 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)
105 } 105 }
106 106
107 // Trace ... 107 // Trace ...
108 func (l *Logger) Trace(format string, v ...interface{}) { 108 func (l *Logger) Trace(format string, v ...interface{}) {
109 if l.outputFile == nil { 109 if l.outputFile == nil {
110 return 110 return
111 } 111 }
112 112
113 l.mu.Lock() 113 l.mu.Lock()
114 defer l.mu.Unlock() 114 defer l.mu.Unlock()
115 115
116 file, line := CallerFilenameAndLineNumber() 116 file, line := CallerFilenameAndLineNumber()
117 117
118 msg := fmt.Sprintf(format, v...) 118 msg := fmt.Sprintf(format, v...)
119 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)
120 120
121 if l.shouldSplit(len(s)) { 121 if l.shouldSplit(len(s)) {
122 l.split() 122 l.split()
123 } 123 }
124 l.outputFile.WriteString(s) 124 l.outputFile.WriteString(s)
125 } 125 }
126 126
127 // PrintAndTrace ... 127 // PrintAndTrace ...
128 func (l *Logger) PrintAndTrace(format string, v ...interface{}) { 128 func (l *Logger) PrintAndTrace(format string, v ...interface{}) {
129 l.Print(format, v...) 129 l.Print(format, v...)
130 l.Trace(format, v...) 130 l.Trace(format, v...)
131 } 131 }
132 132
133 // LogHTTPRequest ... 133 // LogHTTPRequest ...
134 func (l *Logger) LogHTTPRequest(req *http.Request, userID string) string { 134 func (l *Logger) LogHTTPRequest(req *http.Request, userID string) string {
135 if userID == "" { 135 if userID == "" {
136 userID = "-" 136 userID = "-"
137 } 137 }
138 138
139 var b strings.Builder 139 var b strings.Builder
140 140
141 b.WriteString("Request:\n") 141 b.WriteString("Request:\n")
142 // CLF-like header 142 // CLF-like header
143 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))
144 144
145 body, err := httputil.DumpRequest(req, true) 145 body, err := httputil.DumpRequest(req, true)
146 if err != nil { 146 if err != nil {
147 fmt.Fprintf(os.Stderr, "%v\n", err) 147 fmt.Fprintf(os.Stderr, "%v\n", err)
148 } 148 }
149 149
150 const sepStr = "\r\n\r\n" 150 const sepStr = "\r\n\r\n"
151 sepIndex := bytes.Index(body, []byte(sepStr)) 151 sepIndex := bytes.Index(body, []byte(sepStr))
152 if sepIndex == -1 { 152 if sepIndex == -1 {
153 b.WriteString(string(body) + "\n\n") 153 b.WriteString(string(body) + "\n\n")
154 } else { 154 } else {
155 sepIndex += len(sepStr) 155 sepIndex += len(sepStr)
156 payload, _ := printJSON(body[sepIndex:]) 156 payload, _ := printJSON(body[sepIndex:])
157 b.WriteString(string(body[:sepIndex]) + string(payload) + "\n\n") 157 b.WriteString(string(body[:sepIndex]) + string(payload) + "\n\n")
158 } 158 }
159 159
160 return b.String() 160 return b.String()
161 } 161 }
162 162
163 const splitLine = "==============================================================" 163 const splitLine = "=============================================================="
164 164
165 // LogHTTPResponse ... 165 // LogHTTPResponse ...
166 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 {
167 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)
168 } 168 }
169 169
170 // CombineHTTPLogs ... 170 // CombineHTTPLogs ...
171 func (l *Logger) CombineHTTPLogs(in string, out string) { 171 func (l *Logger) CombineHTTPLogs(in string, out string) {
172 if l.outputFile == nil { 172 if l.outputFile == nil {
173 return 173 return
174 } 174 }
175 175
176 l.mu.Lock() 176 l.mu.Lock()
177 defer l.mu.Unlock() 177 defer l.mu.Unlock()
178 178
179 msg := in + out 179 msg := in + out
180 if l.shouldSplit(len(msg)) { 180 if l.shouldSplit(len(msg)) {
181 l.split() 181 l.split()
182 } 182 }
183 l.outputFile.WriteString(msg) 183 l.outputFile.WriteString(msg)
184 } 184 }
185 185
186 // Close ... 186 // Close ...
187 func (l *Logger) Close() error { 187 func (l *Logger) Close() error {
188 if l.outputFile == nil { 188 if l.outputFile == nil {
189 return nil 189 return nil
190 } 190 }
191 191
192 return l.outputFile.Close() 192 return l.outputFile.Close()
193 } 193 }
194 194
195 func (l *Logger) split() error { 195 func (l *Logger) split() error {
196 if l.outputFile == nil { 196 if l.outputFile == nil {
197 return nil 197 return nil
198 } 198 }
199 199
200 // close old file 200 // close old file
201 err := l.outputFile.Close() 201 err := l.outputFile.Close()
202 if err != nil { 202 if err != nil {
203 return err 203 return err
204 } 204 }
205 205
206 // open new file 206 // open new file
207 l.splitCount++ 207 l.splitCount++
208 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")
209 l.outputFile, err = os.Create(path) 209 l.outputFile, err = os.Create(path)
210 210
211 return err 211 return err
212 } 212 }
213 213
214 func (l *Logger) shouldSplit(nextEntrySize int) bool { 214 func (l *Logger) shouldSplit(nextEntrySize int) bool {
215 stats, _ := l.outputFile.Stat() 215 stats, _ := l.outputFile.Stat()
216 return int64(nextEntrySize) >= (l.maxFileSize - stats.Size()) 216 return int64(nextEntrySize) >= (l.maxFileSize - stats.Size())
217 } 217 }
218 218
219 func printJSON(in []byte) (out []byte, err error) { 219 func printJSON(in []byte) (out []byte, err error) {
220 var buf bytes.Buffer 220 var buf bytes.Buffer
221 err = json.Indent(&buf, in, "", " ") 221 err = json.Indent(&buf, in, "", " ")
222 return buf.Bytes(), err 222 return buf.Bytes(), err
223 } 223 }
224 224