Blame view

main.go 4.03 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
28
  	outputFileName string
  	maxFileSize    int64
df74f4a7e   Marko Tikvić   new filename format
29
30
  
  	splitCount int
a99c98307   Marko Tikvić   first commit
31
  }
98cf2ceeb   Marko Tikvić   new interaface; a...
32
  func New(name string, maxFileSize int64) (logger *Logger, err error) {
5eaa49d2a   Marko Tikvić   new design; allow...
33
  	logger = &Logger{}
23ce66f0f   Marko Tikvić   optional init par...
34

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

98cf2ceeb   Marko Tikvić   new interaface; a...
39
40
41
42
43
  	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...
44
  			return nil, err
a99c98307   Marko Tikvić   first commit
45
46
  		}
  	}
df74f4a7e   Marko Tikvić   new filename format
47
48
49
  	date := strings.Replace(time.Now().Format(time.RFC3339), ":", ".", -1)
  	logger.outputFileName += "_" + date + ".txt"
  	path := filepath.Join(logDirName, logger.outputFileName)
98cf2ceeb   Marko Tikvić   new interaface; a...
50
51
52
53
54
  	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...
55
  	}
5eaa49d2a   Marko Tikvić   new design; allow...
56
  	return logger, nil
98708cdaf   Marko Tikvić   new version, does...
57
  }
df74f4a7e   Marko Tikvić   new filename format
58
  func (l *Logger) Print(format string, v ...interface{}) {
98cf2ceeb   Marko Tikvić   new interaface; a...
59
60
61
  	msg := fmt.Sprintf(format, v...)
  	fmt.Printf(time.Now().Format(time.RFC3339) + ": " + msg + "
  ")
327c98634   Marko Tikvić   added Print() for...
62
  }
df74f4a7e   Marko Tikvić   new filename format
63
64
65
66
  func (l *Logger) Log(format string, v ...interface{}) {
  	if l.outputFile != nil {
  		l.mu.Lock()
  		defer l.mu.Unlock()
98708cdaf   Marko Tikvić   new version, does...
67

98cf2ceeb   Marko Tikvić   new interaface; a...
68
69
70
  		msg := fmt.Sprintf(format, v...)
  		s := time.Now().Format(time.RFC3339) + ": " + msg + "
  "
df74f4a7e   Marko Tikvić   new filename format
71
72
  		if l.shouldSplit(len(s)) {
  			l.split()
98cf2ceeb   Marko Tikvić   new interaface; a...
73
  		}
df74f4a7e   Marko Tikvić   new filename format
74
  		l.outputFile.WriteString(s)
23ce66f0f   Marko Tikvić   optional init par...
75
  	}
98708cdaf   Marko Tikvić   new version, does...
76
  }
df74f4a7e   Marko Tikvić   new filename format
77
78
79
80
81
  func (l *Logger) LogRequest(req *http.Request, userid string) {
  	if l.outputFile != nil {
  		if userid == "" {
  			userid = "-"
  		}
98cf2ceeb   Marko Tikvić   new interaface; a...
82

df74f4a7e   Marko Tikvić   new filename format
83
  		var b strings.Builder
cccb4b47c   Marko Tikvić   log http response
84
85
  		b.WriteString("Request:
  ")
df74f4a7e   Marko Tikvić   new filename format
86
87
  		// CLF-like header
  		ts := time.Now().Format(time.RFC3339)
cccb4b47c   Marko Tikvić   log http response
88
89
  		fmt.Fprintf(&b, "%s %s
  ", req.RemoteAddr, ts)
df74f4a7e   Marko Tikvić   new filename format
90

cccb4b47c   Marko Tikvić   log http response
91
92
  		body, err := httputil.DumpRequest(req, true)
  		if err != nil {
df74f4a7e   Marko Tikvić   new filename format
93
94
  			fmt.Fprintf(os.Stderr, "%v
  ", err)
cccb4b47c   Marko Tikvić   log http response
95
96
  		} else {
  			b.WriteString(string(body))
df74f4a7e   Marko Tikvić   new filename format
97
  		}
dda53db01   Marko Tikvić   log response changes
98
99
  		b.WriteString("
  ")
df74f4a7e   Marko Tikvić   new filename format
100
101
  
  		msg := b.String()
cccb4b47c   Marko Tikvić   log http response
102
103
104
105
106
107
108
109
110
111
  
  		l.mu.Lock()
  		defer l.mu.Unlock()
  
  		if l.shouldSplit(len(msg)) {
  			l.split()
  		}
  		l.outputFile.WriteString(msg)
  	}
  }
dda53db01   Marko Tikvić   log response changes
112
  func (l *Logger) LogResponse(w http.ResponseWriter, req *http.Request, duration time.Duration) {
cccb4b47c   Marko Tikvić   log http response
113
114
115
116
  	if l.outputFile != nil {
  		var b strings.Builder
  		b.WriteString("Response:
  ")
dda53db01   Marko Tikvić   log response changes
117
118
  		fmt.Fprintf(&b, "%s %s
  ", req.Method, req.RequestURI)
cccb4b47c   Marko Tikvić   log http response
119
  		for k, v := range w.Header() {
dda53db01   Marko Tikvić   log response changes
120
121
  			fmt.Fprintf(&b, "%s: %s
  ", k, v)
cccb4b47c   Marko Tikvić   log http response
122
  		}
dda53db01   Marko Tikvić   log response changes
123
124
125
126
127
128
  		fmt.Fprintf(&b, "
  Completed in: %v
  ", duration)
  		b.WriteString("==============================================================
  
  ")
cccb4b47c   Marko Tikvić   log http response
129
  		msg := b.String()
df74f4a7e   Marko Tikvić   new filename format
130
131
132
133
134
135
  
  		l.mu.Lock()
  		defer l.mu.Unlock()
  
  		if l.shouldSplit(len(msg)) {
  			l.split()
23ce66f0f   Marko Tikvić   optional init par...
136
  		}
df74f4a7e   Marko Tikvić   new filename format
137
  		l.outputFile.WriteString(msg)
98708cdaf   Marko Tikvić   new version, does...
138
  	}
98708cdaf   Marko Tikvić   new version, does...
139
  }
df74f4a7e   Marko Tikvić   new filename format
140
141
142
143
  func (l *Logger) Trace(format string, v ...interface{}) {
  	if l.outputFile != nil {
  		l.mu.Lock()
  		defer l.mu.Unlock()
23ce66f0f   Marko Tikvić   optional init par...
144
  		_, file, line, ok := runtime.Caller(1)
98cf2ceeb   Marko Tikvić   new interaface; a...
145
146
147
  
  		s := ""
  		msg := fmt.Sprintf(format, v...)
23ce66f0f   Marko Tikvić   optional init par...
148
  		if ok {
98cf2ceeb   Marko Tikvić   new interaface; a...
149
150
  			s = fmt.Sprintf("%s: %s %d: %s
  ", time.Now().Format(time.RFC3339), file, line, msg)
23ce66f0f   Marko Tikvić   optional init par...
151
  		} else {
98cf2ceeb   Marko Tikvić   new interaface; a...
152
153
154
  			s = fmt.Sprintf(time.Now().Format(time.RFC3339) + ": [can't retreive stack details]:" + msg + "
  ")
  		}
df74f4a7e   Marko Tikvić   new filename format
155
156
  		if l.shouldSplit(len(s)) {
  			l.split()
23ce66f0f   Marko Tikvić   optional init par...
157
  		}
df74f4a7e   Marko Tikvić   new filename format
158
  		l.outputFile.WriteString(s)
98708cdaf   Marko Tikvić   new version, does...
159
  	}
a99c98307   Marko Tikvić   first commit
160
  }
df74f4a7e   Marko Tikvić   new filename format
161
162
163
  func (l *Logger) Close() {
  	if l.outputFile != nil {
  		err := l.outputFile.Close()
23ce66f0f   Marko Tikvić   optional init par...
164
165
166
167
  		if err != nil {
  			fmt.Printf("logger: on exit: couldn't close event log file
  ")
  		}
a99c98307   Marko Tikvić   first commit
168
  	}
a99c98307   Marko Tikvić   first commit
169
  }
98cf2ceeb   Marko Tikvić   new interaface; a...
170
  func (l *Logger) split() {
98cf2ceeb   Marko Tikvić   new interaface; a...
171
172
173
174
175
176
177
  	// 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
178
179
  
  	l.splitCount++
98cf2ceeb   Marko Tikvić   new interaface; a...
180
181
  	// open new file
  	var errnew error
df74f4a7e   Marko Tikvić   new filename format
182
  	path := filepath.Join(logDirName, l.outputFileName+fmt.Sprintf("(%d)", l.splitCount))
98cf2ceeb   Marko Tikvić   new interaface; a...
183
  	l.outputFile, errnew = os.Create(path)
a99c98307   Marko Tikvić   first commit
184

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