Commit bc20b9e5d508eff5fd4dc3a84887d372a11b6fc7
1 parent
31ebd1bdef
Exists in
master
new stuff
Showing
2 changed files
with
3 additions
and
4 deletions
Show diff stats
http_logs.go
1 | package gologger | 1 | package gologger |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "bytes" | 4 | "bytes" |
5 | "fmt" | 5 | "fmt" |
6 | "net/http" | 6 | "net/http" |
7 | "net/http/httputil" | 7 | "net/http/httputil" |
8 | "os" | 8 | "os" |
9 | "strings" | 9 | "strings" |
10 | "time" | 10 | "time" |
11 | ) | 11 | ) |
12 | 12 | ||
13 | const splitLine = "==============================================================" | ||
14 | |||
13 | // LogHTTPRequest ... | 15 | // LogHTTPRequest ... |
14 | func (l *Logger) LogHTTPRequest(req *http.Request, userID string) string { | 16 | func (l *Logger) LogHTTPRequest(req *http.Request, userID string) string { |
15 | if userID == "" { | 17 | if userID == "" { |
16 | userID = "-" | 18 | userID = "-" |
17 | } | 19 | } |
18 | 20 | ||
19 | var b strings.Builder | 21 | var b strings.Builder |
20 | 22 | ||
21 | b.WriteString("Request:\n") | 23 | b.WriteString("Request:\n") |
22 | // CLF-like header | 24 | // CLF-like header |
23 | fmt.Fprintf(&b, "%s %s %s\n", req.RemoteAddr, userID, time.Now().Format(dateTimeFormat)) | 25 | fmt.Fprintf(&b, "%s %s %s\n", req.RemoteAddr, userID, time.Now().Format(dateTimeFormat)) |
24 | 26 | ||
25 | body, err := httputil.DumpRequest(req, true) | 27 | body, err := httputil.DumpRequest(req, true) |
26 | if err != nil { | 28 | if err != nil { |
27 | fmt.Fprintf(os.Stderr, "%v\n", err) | 29 | fmt.Fprintf(os.Stderr, "%v\n", err) |
28 | } | 30 | } |
29 | 31 | ||
30 | const sepStr = "\r\n\r\n" | 32 | const sepStr = "\r\n\r\n" |
31 | sepIndex := bytes.Index(body, []byte(sepStr)) | 33 | sepIndex := bytes.Index(body, []byte(sepStr)) |
32 | if sepIndex == -1 { | 34 | if sepIndex == -1 { |
33 | b.WriteString(string(body) + "\n\n") | 35 | b.WriteString(string(body) + "\n\n") |
34 | } else { | 36 | } else { |
35 | sepIndex += len(sepStr) | 37 | sepIndex += len(sepStr) |
36 | payload, _ := printJSON(body[sepIndex:]) | 38 | payload, _ := printJSON(body[sepIndex:]) |
37 | b.WriteString(string(body[:sepIndex]) + string(payload) + "\n\n") | 39 | b.WriteString(string(body[:sepIndex]) + string(payload) + "\n\n") |
38 | } | 40 | } |
39 | 41 | ||
40 | return b.String() | 42 | return b.String() |
41 | } | 43 | } |
42 | 44 | ||
43 | const splitLine = "##############################################################" | ||
44 | |||
45 | // LogHTTPResponse ... | 45 | // LogHTTPResponse ... |
46 | func (l *Logger) LogHTTPResponse(status int, duration time.Duration, size int) string { | 46 | func (l *Logger) LogHTTPResponse(status int, duration time.Duration, size int) string { |
47 | return fmt.Sprintf("Response:\n%d %v %dB\n%s\n", status, duration, size, splitLine) | 47 | return fmt.Sprintf("Response:\n%d %v %dB\n%s\n\n", status, duration, size, splitLine) |
48 | } | 48 | } |
49 | 49 | ||
50 | // CombineHTTPLogs ... | 50 | // CombineHTTPLogs ... |
51 | func (l *Logger) CombineHTTPLogs(in string, out string) { | 51 | func (l *Logger) CombineHTTPLogs(in string, out string) { |
52 | if l.outputFile == nil { | 52 | if l.outputFile == nil { |
53 | return | 53 | return |
54 | } | 54 | } |
55 | 55 | ||
56 | l.mu.Lock() | 56 | l.mu.Lock() |
57 | defer l.mu.Unlock() | 57 | defer l.mu.Unlock() |
58 | 58 | ||
59 | msg := in + out | 59 | msg := in + out |
60 | if l.shouldSplit(len(msg)) { | 60 | if l.shouldSplit(len(msg)) { |
61 | l.split() | 61 | l.split() |
62 | } | 62 | } |
63 | l.outputFile.WriteString(msg) | 63 | l.outputFile.WriteString(msg) |
main.go
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 | "os" | 7 | "os" |
8 | "path/filepath" | 8 | "path/filepath" |
9 | "strings" | 9 | "strings" |
10 | "sync" | 10 | "sync" |
11 | "time" | 11 | "time" |
12 | ) | 12 | ) |
13 | 13 | ||
14 | const dateTimeFormat = "2006-01-02 15:04:05" | 14 | const dateTimeFormat = "2006-01-02 15:04:05" |
15 | const thisFile = "" | ||
16 | 15 | ||
17 | // Block ... | 16 | // Block ... |
18 | const ( | 17 | const ( |
19 | MaxLogSize5MB int64 = 5 * 1024 * 1024 | 18 | MaxLogSize5MB int64 = 5 * 1024 * 1024 |
20 | MaxLogSize1MB int64 = 1 * 1024 * 1024 | 19 | MaxLogSize1MB int64 = 1 * 1024 * 1024 |
21 | MaxLogSize500KB int64 = 500 * 1024 | 20 | MaxLogSize500KB int64 = 500 * 1024 |
22 | MaxLogSize100KB int64 = 100 * 1024 | 21 | MaxLogSize100KB int64 = 100 * 1024 |
23 | MaxLogSize512B int64 = 512 | 22 | MaxLogSize512B int64 = 512 |
24 | ) | 23 | ) |
25 | 24 | ||
26 | // Logger ... | 25 | // Logger ... |
27 | type Logger struct { | 26 | type Logger struct { |
28 | mu *sync.Mutex | 27 | mu *sync.Mutex |
29 | outputFile *os.File | 28 | outputFile *os.File |
30 | 29 | ||
31 | outputFileName string | 30 | outputFileName string |
32 | fullName string | 31 | fullName string |
33 | maxFileSize int64 | 32 | maxFileSize int64 |
34 | 33 | ||
35 | splitCount int | 34 | splitCount int |
36 | 35 | ||
37 | directory string | 36 | directory string |
38 | } | 37 | } |
39 | 38 | ||
40 | // New ... | 39 | // New ... |
41 | func New(name, dir string, maxFileSize int64) (logger *Logger, err error) { | 40 | func New(name, dir string, maxFileSize int64) (logger *Logger, err error) { |
42 | logger = &Logger{} | 41 | logger = &Logger{} |
43 | 42 | ||
44 | logger.outputFileName = name | 43 | logger.outputFileName = name |
45 | logger.mu = &sync.Mutex{} | 44 | logger.mu = &sync.Mutex{} |
46 | logger.maxFileSize = maxFileSize | 45 | logger.maxFileSize = maxFileSize |
47 | logger.directory = dir | 46 | logger.directory = dir |
48 | 47 | ||
49 | err = os.Mkdir(dir, os.ModePerm) | 48 | err = os.Mkdir(dir, os.ModePerm) |
50 | if err != nil { | 49 | if err != nil { |
51 | if !os.IsExist(err) { | 50 | if !os.IsExist(err) { |
52 | return nil, err | 51 | return nil, err |
53 | } | 52 | } |
54 | } | 53 | } |
55 | 54 | ||
56 | date := strings.Replace(time.Now().Format(dateTimeFormat), ":", ".", -1) | 55 | date := strings.Replace(time.Now().Format(dateTimeFormat), ":", ".", -1) |
57 | logger.outputFileName += " " + date | 56 | logger.outputFileName += " " + date |
58 | logger.fullName = logger.outputFileName + ".txt" | 57 | logger.fullName = logger.outputFileName + ".txt" |
59 | path := filepath.Join(dir, logger.fullName) | 58 | path := filepath.Join(dir, logger.fullName) |
60 | if logger.outputFile, err = os.Create(path); err != nil { | 59 | if logger.outputFile, err = os.Create(path); err != nil { |
61 | return nil, err | 60 | return nil, err |
62 | } | 61 | } |
63 | 62 | ||
64 | return logger, nil | 63 | return logger, nil |
65 | } | 64 | } |
66 | 65 | ||
67 | // Log ... | 66 | // Log ... |
68 | func (l *Logger) Log(format string, v ...interface{}) { | 67 | func (l *Logger) Log(format string, v ...interface{}) { |
69 | if l.outputFile == nil { | 68 | if l.outputFile == nil { |
70 | return | 69 | return |
71 | } | 70 | } |
72 | 71 | ||
73 | l.mu.Lock() | 72 | l.mu.Lock() |
74 | defer l.mu.Unlock() | 73 | defer l.mu.Unlock() |
75 | 74 | ||
76 | msg := fmt.Sprintf(format, v...) | 75 | msg := fmt.Sprintf(format, v...) |
77 | s := time.Now().Format(dateTimeFormat) + ": " + msg + "\n" | 76 | s := time.Now().Format(dateTimeFormat) + ": " + msg + "\n" |
78 | if l.shouldSplit(len(s)) { | 77 | if l.shouldSplit(len(s)) { |
79 | l.split() | 78 | l.split() |
80 | } | 79 | } |
81 | l.outputFile.WriteString(s) | 80 | l.outputFile.WriteString(s) |
82 | } | 81 | } |
83 | 82 | ||
84 | // Print ... | 83 | // Print ... |
85 | func (l *Logger) Print(format string, v ...interface{}) { | 84 | func (l *Logger) Print(format string, v ...interface{}) { |
86 | msg := fmt.Sprintf(format, v...) | 85 | msg := fmt.Sprintf(format, v...) |
87 | fmt.Printf("%s: %s\n", time.Now().Format(dateTimeFormat), msg) | 86 | fmt.Printf("%s: %s\n", time.Now().Format(dateTimeFormat), msg) |
88 | } | 87 | } |
89 | 88 | ||
90 | // Trace ... | 89 | // Trace ... |
91 | func (l *Logger) Trace(format string, v ...interface{}) string { | 90 | func (l *Logger) Trace(format string, v ...interface{}) string { |
92 | if l.outputFile == nil { | 91 | if l.outputFile == nil { |
93 | return "" | 92 | return "" |
94 | } | 93 | } |
95 | 94 | ||
96 | l.mu.Lock() | 95 | l.mu.Lock() |
97 | defer l.mu.Unlock() | 96 | defer l.mu.Unlock() |
98 | 97 | ||
99 | s := getTrace(format, v...) + "\n" | 98 | s := getTrace(format, v...) + "\n" |
100 | 99 | ||
101 | if l.shouldSplit(len(s)) { | 100 | if l.shouldSplit(len(s)) { |
102 | l.split() | 101 | l.split() |
103 | } | 102 | } |
104 | l.outputFile.WriteString(s) | 103 | l.outputFile.WriteString(s) |
105 | 104 | ||
106 | return s | 105 | return s |
107 | } | 106 | } |
108 | 107 | ||
109 | // PrintTrace ... | 108 | // PrintTrace ... |
110 | func (l *Logger) PrintTrace(format string, v ...interface{}) { | 109 | func (l *Logger) PrintTrace(format string, v ...interface{}) { |
111 | s := getTrace(format, v...) | 110 | s := getTrace(format, v...) |
112 | fmt.Printf("%s\n", s) | 111 | fmt.Printf("%s\n", s) |
113 | } | 112 | } |
114 | 113 | ||
115 | // PrintAndTrace ... | 114 | // PrintAndTrace ... |
116 | func (l *Logger) PrintAndTrace(format string, v ...interface{}) { | 115 | func (l *Logger) PrintAndTrace(format string, v ...interface{}) { |
117 | t := l.Trace(format, v...) | 116 | t := l.Trace(format, v...) |
118 | fmt.Println(t) | 117 | fmt.Println(t) |
119 | } | 118 | } |
120 | 119 | ||
121 | // Close ... | 120 | // Close ... |
122 | func (l *Logger) Close() error { | 121 | func (l *Logger) Close() error { |
123 | if l.outputFile == nil { | 122 | if l.outputFile == nil { |
124 | return nil | 123 | return nil |
125 | } | 124 | } |
126 | 125 | ||
127 | return l.outputFile.Close() | 126 | return l.outputFile.Close() |
128 | } | 127 | } |
129 | 128 | ||
130 | func (l *Logger) split() error { | 129 | func (l *Logger) split() error { |
131 | if l.outputFile == nil { | 130 | if l.outputFile == nil { |
132 | return nil | 131 | return nil |
133 | } | 132 | } |
134 | 133 | ||
135 | // close old file | 134 | // close old file |
136 | err := l.outputFile.Close() | 135 | err := l.outputFile.Close() |
137 | if err != nil { | 136 | if err != nil { |
138 | return err | 137 | return err |
139 | } | 138 | } |
140 | 139 | ||
141 | // open new file | 140 | // open new file |
142 | l.splitCount++ | 141 | l.splitCount++ |
143 | path := filepath.Join(l.directory, l.outputFileName+fmt.Sprintf("(%d)", l.splitCount)+".txt") | 142 | path := filepath.Join(l.directory, l.outputFileName+fmt.Sprintf("(%d)", l.splitCount)+".txt") |
144 | l.outputFile, err = os.Create(path) | 143 | l.outputFile, err = os.Create(path) |
145 | 144 | ||
146 | return err | 145 | return err |
147 | } | 146 | } |
148 | 147 | ||
149 | func (l *Logger) shouldSplit(nextEntrySize int) bool { | 148 | func (l *Logger) shouldSplit(nextEntrySize int) bool { |
150 | stats, _ := l.outputFile.Stat() | 149 | stats, _ := l.outputFile.Stat() |
151 | return int64(nextEntrySize) >= (l.maxFileSize - stats.Size()) | 150 | return int64(nextEntrySize) >= (l.maxFileSize - stats.Size()) |
152 | } | 151 | } |
153 | 152 | ||
154 | func printJSON(in []byte) (out []byte, err error) { | 153 | func printJSON(in []byte) (out []byte, err error) { |
155 | var buf bytes.Buffer | 154 | var buf bytes.Buffer |
156 | err = json.Indent(&buf, in, "", " ") | 155 | err = json.Indent(&buf, in, "", " ") |
157 | return buf.Bytes(), err | 156 | return buf.Bytes(), err |
158 | } | 157 | } |
159 | 158 | ||
160 | // GetOutDir ... | 159 | // GetOutDir ... |
161 | func (l *Logger) GetOutDir() string { | 160 | func (l *Logger) GetOutDir() string { |
162 | return l.directory | 161 | return l.directory |
163 | } | 162 | } |
164 | 163 |