Commit dda53db017c8a649ef6f2631c915ce626b66d440
1 parent
cccb4b47c0
Exists in
master
log response changes
Showing
1 changed file
with
6 additions
and
4 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 | maxFileSize int64 | 29 | maxFileSize int64 |
30 | 30 | ||
31 | splitCount int | 31 | splitCount int |
32 | } | 32 | } |
33 | 33 | ||
34 | func New(name string, maxFileSize int64) (logger *Logger, err error) { | 34 | func New(name string, maxFileSize int64) (logger *Logger, err error) { |
35 | logger = &Logger{} | 35 | logger = &Logger{} |
36 | 36 | ||
37 | logger.outputFileName = name + "-log" | 37 | logger.outputFileName = name + "-log" |
38 | logger.mu = &sync.Mutex{} | 38 | logger.mu = &sync.Mutex{} |
39 | logger.maxFileSize = maxFileSize | 39 | logger.maxFileSize = maxFileSize |
40 | 40 | ||
41 | err = os.Mkdir(logDirName, os.ModePerm) | 41 | err = os.Mkdir(logDirName, os.ModePerm) |
42 | if err != nil { | 42 | if err != nil { |
43 | if !os.IsExist(err) { | 43 | if !os.IsExist(err) { |
44 | fmt.Printf("logger: mkdir: couldn't create event log directory\n") | 44 | fmt.Printf("logger: mkdir: couldn't create event log directory\n") |
45 | return nil, err | 45 | return nil, err |
46 | } | 46 | } |
47 | } | 47 | } |
48 | 48 | ||
49 | date := strings.Replace(time.Now().Format(time.RFC3339), ":", ".", -1) | 49 | date := strings.Replace(time.Now().Format(time.RFC3339), ":", ".", -1) |
50 | logger.outputFileName += "_" + date + ".txt" | 50 | logger.outputFileName += "_" + date + ".txt" |
51 | path := filepath.Join(logDirName, logger.outputFileName) | 51 | path := filepath.Join(logDirName, logger.outputFileName) |
52 | logger.outputFile, err = os.Create(path) | 52 | logger.outputFile, err = os.Create(path) |
53 | if err != nil { | 53 | if err != nil { |
54 | fmt.Printf("logger: new: couldn't create event log file\n") | 54 | fmt.Printf("logger: new: couldn't create event log file\n") |
55 | return nil, err | 55 | return nil, err |
56 | } | 56 | } |
57 | 57 | ||
58 | return logger, nil | 58 | return logger, nil |
59 | } | 59 | } |
60 | 60 | ||
61 | func (l *Logger) Print(format string, v ...interface{}) { | 61 | func (l *Logger) Print(format string, v ...interface{}) { |
62 | msg := fmt.Sprintf(format, v...) | 62 | msg := fmt.Sprintf(format, v...) |
63 | fmt.Printf(time.Now().Format(time.RFC3339) + ": " + msg + "\n") | 63 | fmt.Printf(time.Now().Format(time.RFC3339) + ": " + msg + "\n") |
64 | } | 64 | } |
65 | 65 | ||
66 | func (l *Logger) Log(format string, v ...interface{}) { | 66 | func (l *Logger) Log(format string, v ...interface{}) { |
67 | if l.outputFile != nil { | 67 | if l.outputFile != nil { |
68 | l.mu.Lock() | 68 | l.mu.Lock() |
69 | defer l.mu.Unlock() | 69 | defer l.mu.Unlock() |
70 | 70 | ||
71 | msg := fmt.Sprintf(format, v...) | 71 | msg := fmt.Sprintf(format, v...) |
72 | s := time.Now().Format(time.RFC3339) + ": " + msg + "\n" | 72 | s := time.Now().Format(time.RFC3339) + ": " + msg + "\n" |
73 | if l.shouldSplit(len(s)) { | 73 | if l.shouldSplit(len(s)) { |
74 | l.split() | 74 | l.split() |
75 | } | 75 | } |
76 | l.outputFile.WriteString(s) | 76 | l.outputFile.WriteString(s) |
77 | } | 77 | } |
78 | } | 78 | } |
79 | 79 | ||
80 | func (l *Logger) LogRequest(req *http.Request, userid string) { | 80 | func (l *Logger) LogRequest(req *http.Request, userid string) { |
81 | if l.outputFile != nil { | 81 | if l.outputFile != nil { |
82 | if userid == "" { | 82 | if userid == "" { |
83 | userid = "-" | 83 | userid = "-" |
84 | } | 84 | } |
85 | 85 | ||
86 | var b strings.Builder | 86 | var b strings.Builder |
87 | b.WriteString("Request:\n") | 87 | b.WriteString("Request:\n") |
88 | // CLF-like header | 88 | // CLF-like header |
89 | ts := time.Now().Format(time.RFC3339) | 89 | ts := time.Now().Format(time.RFC3339) |
90 | fmt.Fprintf(&b, "%s %s\n", req.RemoteAddr, ts) | 90 | fmt.Fprintf(&b, "%s %s\n", req.RemoteAddr, ts) |
91 | 91 | ||
92 | body, err := httputil.DumpRequest(req, true) | 92 | body, err := httputil.DumpRequest(req, true) |
93 | if err != nil { | 93 | if err != nil { |
94 | fmt.Fprintf(os.Stderr, "%v\n", err) | 94 | fmt.Fprintf(os.Stderr, "%v\n", err) |
95 | } else { | 95 | } else { |
96 | b.WriteString(string(body)) | 96 | b.WriteString(string(body)) |
97 | } | 97 | } |
98 | b.WriteString("\n\n") | 98 | b.WriteString("\n") |
99 | 99 | ||
100 | msg := b.String() | 100 | msg := b.String() |
101 | 101 | ||
102 | l.mu.Lock() | 102 | l.mu.Lock() |
103 | defer l.mu.Unlock() | 103 | defer l.mu.Unlock() |
104 | 104 | ||
105 | if l.shouldSplit(len(msg)) { | 105 | if l.shouldSplit(len(msg)) { |
106 | l.split() | 106 | l.split() |
107 | } | 107 | } |
108 | l.outputFile.WriteString(msg) | 108 | l.outputFile.WriteString(msg) |
109 | } | 109 | } |
110 | } | 110 | } |
111 | 111 | ||
112 | func (l *Logger) LogResponse(w http.ResponseWriter, duration time.Duration) { | 112 | func (l *Logger) LogResponse(w http.ResponseWriter, req *http.Request, duration time.Duration) { |
113 | if l.outputFile != nil { | 113 | if l.outputFile != nil { |
114 | var b strings.Builder | 114 | var b strings.Builder |
115 | b.WriteString("Response:\n") | 115 | b.WriteString("Response:\n") |
116 | fmt.Fprintf(&b, "%s %s\n", req.Method, req.RequestURI) | ||
116 | for k, v := range w.Header() { | 117 | for k, v := range w.Header() { |
117 | b.WriteString(fmt.Sprintf("%s: %s\n", k, v)) | 118 | fmt.Fprintf(&b, "%s: %s\n", k, v) |
118 | } | 119 | } |
119 | b.WriteString(fmt.Sprintf("\nCompleted in: %v\n", duration)) | 120 | fmt.Fprintf(&b, "\nCompleted in: %v\n", duration) |
121 | b.WriteString("==============================================================\n\n") | ||
120 | msg := b.String() | 122 | msg := b.String() |
121 | 123 | ||
122 | l.mu.Lock() | 124 | l.mu.Lock() |
123 | defer l.mu.Unlock() | 125 | defer l.mu.Unlock() |
124 | 126 | ||
125 | if l.shouldSplit(len(msg)) { | 127 | if l.shouldSplit(len(msg)) { |
126 | l.split() | 128 | l.split() |
127 | } | 129 | } |
128 | l.outputFile.WriteString(msg) | 130 | l.outputFile.WriteString(msg) |
129 | } | 131 | } |
130 | } | 132 | } |
131 | 133 | ||
132 | func (l *Logger) Trace(format string, v ...interface{}) { | 134 | func (l *Logger) Trace(format string, v ...interface{}) { |
133 | if l.outputFile != nil { | 135 | if l.outputFile != nil { |
134 | l.mu.Lock() | 136 | l.mu.Lock() |
135 | defer l.mu.Unlock() | 137 | defer l.mu.Unlock() |
136 | _, file, line, ok := runtime.Caller(1) | 138 | _, file, line, ok := runtime.Caller(1) |
137 | 139 | ||
138 | s := "" | 140 | s := "" |
139 | msg := fmt.Sprintf(format, v...) | 141 | msg := fmt.Sprintf(format, v...) |
140 | if ok { | 142 | if ok { |
141 | s = fmt.Sprintf("%s: %s %d: %s\n", time.Now().Format(time.RFC3339), file, line, msg) | 143 | s = fmt.Sprintf("%s: %s %d: %s\n", time.Now().Format(time.RFC3339), file, line, msg) |
142 | } else { | 144 | } else { |
143 | s = fmt.Sprintf(time.Now().Format(time.RFC3339) + ": [can't retreive stack details]:" + msg + "\n") | 145 | s = fmt.Sprintf(time.Now().Format(time.RFC3339) + ": [can't retreive stack details]:" + msg + "\n") |
144 | } | 146 | } |
145 | if l.shouldSplit(len(s)) { | 147 | if l.shouldSplit(len(s)) { |
146 | l.split() | 148 | l.split() |
147 | } | 149 | } |
148 | l.outputFile.WriteString(s) | 150 | l.outputFile.WriteString(s) |
149 | } | 151 | } |
150 | } | 152 | } |
151 | 153 | ||
152 | func (l *Logger) Close() { | 154 | func (l *Logger) Close() { |
153 | if l.outputFile != nil { | 155 | if l.outputFile != nil { |
154 | err := l.outputFile.Close() | 156 | err := l.outputFile.Close() |
155 | if err != nil { | 157 | if err != nil { |
156 | fmt.Printf("logger: on exit: couldn't close event log file\n") | 158 | fmt.Printf("logger: on exit: couldn't close event log file\n") |
157 | } | 159 | } |
158 | } | 160 | } |
159 | } | 161 | } |
160 | 162 | ||
161 | func (l *Logger) split() { | 163 | func (l *Logger) split() { |
162 | // close old file | 164 | // close old file |
163 | err := l.outputFile.Close() | 165 | err := l.outputFile.Close() |
164 | if err != nil { | 166 | if err != nil { |
165 | fmt.Printf("logger: split: couldn't close event file\n") | 167 | fmt.Printf("logger: split: couldn't close event file\n") |
166 | return | 168 | return |
167 | } | 169 | } |
168 | 170 | ||
169 | l.splitCount++ | 171 | l.splitCount++ |
170 | // open new file | 172 | // open new file |
171 | var errnew error | 173 | var errnew error |
172 | path := filepath.Join(logDirName, l.outputFileName+fmt.Sprintf("(%d)", l.splitCount)) | 174 | path := filepath.Join(logDirName, l.outputFileName+fmt.Sprintf("(%d)", l.splitCount)) |
173 | l.outputFile, errnew = os.Create(path) | 175 | l.outputFile, errnew = os.Create(path) |
174 | 176 | ||
175 | if errnew != nil { | 177 | if errnew != nil { |
176 | fmt.Printf("logger: split: couldn't create event log file\n") | 178 | fmt.Printf("logger: split: couldn't create event log file\n") |
177 | } | 179 | } |
178 | } | 180 | } |
179 | 181 | ||
180 | func (l *Logger) shouldSplit(nextEntrySize int) bool { | 182 | func (l *Logger) shouldSplit(nextEntrySize int) bool { |
181 | stats, _ := l.outputFile.Stat() | 183 | stats, _ := l.outputFile.Stat() |
182 | return int64(nextEntrySize) >= (l.maxFileSize - stats.Size()) | 184 | return int64(nextEntrySize) >= (l.maxFileSize - stats.Size()) |
183 | } | 185 | } |
184 | 186 |