Blame view

main.go 3.95 KB
a99c98307   Marko Tikvić   first commit
1
2
3
4
  package gologger
  
  import (
  	"fmt"
df74f4a7e   Marko Tikvić   new filename format
5
  	"net/http"
cccb4b47c   Marko Tikvić   log http response
6
  	"net/http/httputil"
a99c98307   Marko Tikvić   first commit
7
  	"os"
e025a8738   Marko Tikvić   platform agnostic...
8
  	"path/filepath"
98708cdaf   Marko Tikvić   new version, does...
9
  	"runtime"
aa60a45ee   Marko Tikvić   changed log file ...
10
  	"strings"
3ba7b5695   Marko Tikvić   added mutex locks...
11
  	"sync"
baa4468b7   Marko Tikvić   Comments go befor...
12
  	"time"
a99c98307   Marko Tikvić   first commit
13
  )
434e7da25   Marko Tikvić   changed initializ...
14
15
16
17
18
19
  const (
  	MaxLogSize5MB   int64 = 5 * 1024 * 1024
  	MaxLogSize1MB   int64 = 1 * 1024 * 1024
  	MaxLogSize500KB int64 = 500 * 1024
  	MaxLogSize100KB int64 = 100 * 1024
  	MaxLogSize512B  int64 = 512
98cf2ceeb   Marko Tikvić   new interaface; a...
20
  	logDirName            = "log"
434e7da25   Marko Tikvić   changed initializ...
21
  )
a99c98307   Marko Tikvić   first commit
22

5eaa49d2a   Marko Tikvić   new design; allow...
23
  type Logger struct {
98cf2ceeb   Marko Tikvić   new interaface; a...
24
25
  	mu         *sync.Mutex
  	outputFile *os.File
23ce66f0f   Marko Tikvić   optional init par...
26

98cf2ceeb   Marko Tikvić   new interaface; a...
27
  	outputFileName string
3e936a3c2   Marko Tikvić   output file name ...
28
  	fullName       string
98cf2ceeb   Marko Tikvić   new interaface; a...
29
  	maxFileSize    int64
df74f4a7e   Marko Tikvić   new filename format
30
31
  
  	splitCount int
a99c98307   Marko Tikvić   first commit
32
  }
98cf2ceeb   Marko Tikvić   new interaface; a...
33
  func New(name string, maxFileSize int64) (logger *Logger, err error) {
5eaa49d2a   Marko Tikvić   new design; allow...
34
  	logger = &Logger{}
23ce66f0f   Marko Tikvić   optional init par...
35

98cf2ceeb   Marko Tikvić   new interaface; a...
36
37
38
  	logger.outputFileName = name + "-log"
  	logger.mu = &sync.Mutex{}
  	logger.maxFileSize = maxFileSize
a99c98307   Marko Tikvić   first commit
39

98cf2ceeb   Marko Tikvić   new interaface; a...
40
41
42
43
44
  	err = os.Mkdir(logDirName, os.ModePerm)
  	if err != nil {
  		if !os.IsExist(err) {
  			fmt.Printf("logger: mkdir: couldn't create event log directory
  ")
5eaa49d2a   Marko Tikvić   new design; allow...
45
  			return nil, err
a99c98307   Marko Tikvić   first commit
46
47
  		}
  	}
df74f4a7e   Marko Tikvić   new filename format
48
  	date := strings.Replace(time.Now().Format(time.RFC3339), ":", ".", -1)
3e936a3c2   Marko Tikvić   output file name ...
49
50
51
  	logger.outputFileName += "_" + date
  	logger.fullName = logger.outputFileName + ".txt"
  	path := filepath.Join(logDirName, logger.fullName)
98cf2ceeb   Marko Tikvić   new interaface; a...
52
53
54
55
56
  	logger.outputFile, err = os.Create(path)
  	if err != nil {
  		fmt.Printf("logger: new: couldn't create event log file
  ")
  		return nil, err
e025a8738   Marko Tikvić   platform agnostic...
57
  	}
5eaa49d2a   Marko Tikvić   new design; allow...
58
  	return logger, nil
98708cdaf   Marko Tikvić   new version, does...
59
  }
df74f4a7e   Marko Tikvić   new filename format
60
  func (l *Logger) Log(format string, v ...interface{}) {
372beaf62   Marko Tikvić   refactored if sta...
61
62
63
64
65
66
67
68
69
70
71
72
  	if l.outputFile == nil {
  		return
  	}
  
  	l.mu.Lock()
  	defer l.mu.Unlock()
  
  	msg := fmt.Sprintf(format, v...)
  	s := time.Now().Format(time.RFC3339) + ": " + msg + "
  "
  	if l.shouldSplit(len(s)) {
  		l.split()
23ce66f0f   Marko Tikvić   optional init par...
73
  	}
372beaf62   Marko Tikvić   refactored if sta...
74
  	l.outputFile.WriteString(s)
98708cdaf   Marko Tikvić   new version, does...
75
  }
093191eb2   Marko Tikvić   much cleaner, muc...
76
  func (l *Logger) LogHTTPRequest(req *http.Request, userID string) string {
1f7fbc601   Marko Tikvić   logging user ID
77
78
  	if userID == "" {
  		userID = "-"
372beaf62   Marko Tikvić   refactored if sta...
79
  	}
df74f4a7e   Marko Tikvić   new filename format
80

372beaf62   Marko Tikvić   refactored if sta...
81
  	var b strings.Builder
093191eb2   Marko Tikvić   much cleaner, muc...
82

372beaf62   Marko Tikvić   refactored if sta...
83
84
85
  	b.WriteString("Request:
  ")
  	// CLF-like header
093191eb2   Marko Tikvić   much cleaner, muc...
86
87
  	fmt.Fprintf(&b, "%s %s %s
  ", req.RemoteAddr, userID, time.Now().Format(time.RFC3339))
cccb4b47c   Marko Tikvić   log http response
88

093191eb2   Marko Tikvić   much cleaner, muc...
89
90
91
92
  	body, err := httputil.DumpRequest(req, true)
  	if err != nil {
  		fmt.Fprintf(os.Stderr, "%v
  ", err)
cccb4b47c   Marko Tikvić   log http response
93
  	}
093191eb2   Marko Tikvić   much cleaner, muc...
94
95
96
  	b.WriteString(string(body) + "
  
  ")
372beaf62   Marko Tikvić   refactored if sta...
97

093191eb2   Marko Tikvić   much cleaner, muc...
98
99
  	return b.String()
  }
372beaf62   Marko Tikvić   refactored if sta...
100

feba66094   Marko Tikvić   split line constant
101
  const splitLine = "=============================================================="
093191eb2   Marko Tikvić   much cleaner, muc...
102
  func (l *Logger) LogHTTPResponse(status int, duration time.Duration, size int) string {
feba66094   Marko Tikvić   split line constant
103
104
105
106
  	return fmt.Sprintf("Response:
  %d %v %dB
  %s
  ", status, duration, size, splitLine)
cccb4b47c   Marko Tikvić   log http response
107
  }
093191eb2   Marko Tikvić   much cleaner, muc...
108
  func (l *Logger) CombineHTTPLogs(in string, out string) {
372beaf62   Marko Tikvić   refactored if sta...
109
110
111
  	if l.outputFile == nil {
  		return
  	}
df74f4a7e   Marko Tikvić   new filename format
112

372beaf62   Marko Tikvić   refactored if sta...
113
114
  	l.mu.Lock()
  	defer l.mu.Unlock()
093191eb2   Marko Tikvić   much cleaner, muc...
115
  	msg := in + out
372beaf62   Marko Tikvić   refactored if sta...
116
117
  	if l.shouldSplit(len(msg)) {
  		l.split()
98708cdaf   Marko Tikvić   new version, does...
118
  	}
372beaf62   Marko Tikvić   refactored if sta...
119
  	l.outputFile.WriteString(msg)
98708cdaf   Marko Tikvić   new version, does...
120
  }
0adcd8502   Marko Tikvić   printing and tracing
121
  func (l *Logger) PrintTrace(format string, v ...interface{}) {
a62c16cbd   Marko Tikvić   more detailed pri...
122
123
124
125
126
127
  	_, file, line, _ := runtime.Caller(1)
  
  	msg := fmt.Sprintf(format, v...)
  	fmt.Printf("%s: %s %d: %s
  ", time.Now().Format(time.RFC3339), file, line, msg)
  }
0adcd8502   Marko Tikvić   printing and tracing
128
129
130
131
132
  func (l *Logger) Print(format string, v ...interface{}) {
  	msg := fmt.Sprintf(format, v...)
  	fmt.Printf("%s: %s
  ", time.Now().Format(time.RFC3339), msg)
  }
df74f4a7e   Marko Tikvić   new filename format
133
  func (l *Logger) Trace(format string, v ...interface{}) {
372beaf62   Marko Tikvić   refactored if sta...
134
135
136
137
138
139
  	if l.outputFile == nil {
  		return
  	}
  
  	l.mu.Lock()
  	defer l.mu.Unlock()
372beaf62   Marko Tikvić   refactored if sta...
140

a62c16cbd   Marko Tikvić   more detailed pri...
141
  	_, file, line, _ := runtime.Caller(1)
372beaf62   Marko Tikvić   refactored if sta...
142
  	msg := fmt.Sprintf(format, v...)
a62c16cbd   Marko Tikvić   more detailed pri...
143
144
  	s := fmt.Sprintf("%s: %s %d: %s
  ", time.Now().Format(time.RFC3339), file, line, msg)
372beaf62   Marko Tikvić   refactored if sta...
145
146
147
148
  	if l.shouldSplit(len(s)) {
  		l.split()
  	}
  	l.outputFile.WriteString(s)
a99c98307   Marko Tikvić   first commit
149
  }
df74f4a7e   Marko Tikvić   new filename format
150
  func (l *Logger) Close() {
372beaf62   Marko Tikvić   refactored if sta...
151
152
153
154
155
156
157
158
  	if l.outputFile == nil {
  		return
  	}
  
  	err := l.outputFile.Close()
  	if err != nil {
  		fmt.Printf("logger: on exit: couldn't close event log file
  ")
a99c98307   Marko Tikvić   first commit
159
  	}
a99c98307   Marko Tikvić   first commit
160
  }
98cf2ceeb   Marko Tikvić   new interaface; a...
161
  func (l *Logger) split() {
372beaf62   Marko Tikvić   refactored if sta...
162
163
164
  	if l.outputFile == nil {
  		return
  	}
98cf2ceeb   Marko Tikvić   new interaface; a...
165
166
167
168
169
170
171
  	// close old file
  	err := l.outputFile.Close()
  	if err != nil {
  		fmt.Printf("logger: split: couldn't close event file
  ")
  		return
  	}
df74f4a7e   Marko Tikvić   new filename format
172
173
  
  	l.splitCount++
98cf2ceeb   Marko Tikvić   new interaface; a...
174
175
  	// open new file
  	var errnew error
3e936a3c2   Marko Tikvić   output file name ...
176
  	path := filepath.Join(logDirName, l.outputFileName+fmt.Sprintf("(%d)", l.splitCount)+".txt")
98cf2ceeb   Marko Tikvić   new interaface; a...
177
  	l.outputFile, errnew = os.Create(path)
a99c98307   Marko Tikvić   first commit
178

98cf2ceeb   Marko Tikvić   new interaface; a...
179
180
181
  	if errnew != nil {
  		fmt.Printf("logger: split: couldn't create event log file
  ")
a99c98307   Marko Tikvić   first commit
182
183
  	}
  }
98cf2ceeb   Marko Tikvić   new interaface; a...
184
185
186
  func (l *Logger) shouldSplit(nextEntrySize int) bool {
  	stats, _ := l.outputFile.Stat()
  	return int64(nextEntrySize) >= (l.maxFileSize - stats.Size())
a99c98307   Marko Tikvić   first commit
187
  }