Skip to content

Commit 6223c61

Browse files
committed
Added to write logs to files
1 parent 195ed41 commit 6223c61

File tree

9 files changed

+261
-33
lines changed

9 files changed

+261
-33
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,8 @@ request.Session().Set("user", "alice")
397397

398398
The logger provides the eight logging levels defined in [RFC 5424]( https://tools.ietf.org/html/rfc5424 ): **emergency**, **alert**, **critical**, **error**, **warning**, **notice**, **info** and **debug**.
399399

400+
#### Basic Usage
401+
400402
```go
401403
import "github.com/thinkoner/thinkgo/log"
402404

@@ -410,6 +412,24 @@ log.Alert("log with Alert")
410412
log.Emerg("log with Emerg")
411413
```
412414

415+
#### Log Storage
416+
417+
Out of the box, ThinkGo supports writing log information to `daily` files, the `console`.
418+
419+
For example, if you wish to use `daily` log files, you can do this:
420+
421+
```go
422+
import (
423+
"github.com/thinkoner/thinkgo/log"
424+
"github.com/thinkoner/thinkgo/log/handler"
425+
"github.com/thinkoner/thinkgo/log/record"
426+
)
427+
428+
fh := handler.NewFileHandler("path/to/thinkgo.log", record.INFO)
429+
430+
log.GetLogger().PushHandler(fh)
431+
```
432+
413433
## Cache
414434

415435
ThinkGo Cache Currently supports redis, memory, and can customize the store adapter.

log/handler/console.go

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"os"
55
"sync"
66

7-
"github.com/thinkoner/thinkgo/log/formatter"
87
"github.com/thinkoner/thinkgo/log/record"
98
)
109

@@ -18,7 +17,7 @@ func newBrush(color string) brush {
1817
}
1918
}
2019

21-
var colors = map[int]brush{
20+
var colors = map[record.Level]brush{
2221
record.EMERGENCY: newBrush("1;41"), // Emergency Red background
2322
record.ALERT: newBrush("1;35"), // Alert purple
2423
record.CRITICAL: newBrush("1;34"), // Critical blue
@@ -30,15 +29,16 @@ var colors = map[int]brush{
3029
}
3130

3231
type ConsoleHandler struct {
32+
Handler
3333
sync.Mutex
34-
level int
35-
formatter formatter.Formatter
36-
bubble bool
34+
level record.Level
35+
36+
bubble bool
3737
}
3838

39-
func NewConsoleHandler() *ConsoleHandler {
39+
func NewConsoleHandler(level record.Level) *ConsoleHandler {
4040
return &ConsoleHandler{
41-
level: record.DEBUG,
41+
level: level,
4242
bubble: true,
4343
}
4444
}
@@ -67,21 +67,3 @@ func (h *ConsoleHandler) write(r record.Record) {
6767
message := colors[r.Level](r.Formatted)
6868
os.Stdout.Write(append([]byte(message)))
6969
}
70-
71-
// GetFormatter Gets the formatter.
72-
func (h *ConsoleHandler) GetFormatter() formatter.Formatter {
73-
if h.formatter == nil {
74-
h.formatter = h.getDefaultFormatter()
75-
}
76-
return h.formatter
77-
}
78-
79-
// SetFormatter Sets the formatter.
80-
func (h *ConsoleHandler) SetFormatter(f formatter.Formatter) *ConsoleHandler {
81-
h.formatter = f
82-
return h
83-
}
84-
85-
func (h *ConsoleHandler) getDefaultFormatter() formatter.Formatter {
86-
return formatter.NewLineFormatter()
87-
}

log/handler/file.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package handler
2+
3+
import (
4+
"os"
5+
"path"
6+
"strings"
7+
"sync"
8+
"time"
9+
10+
"github.com/thinkoner/thinkgo/log/record"
11+
)
12+
13+
type FileHandler struct {
14+
Handler
15+
sync.Mutex
16+
level record.Level
17+
bubble bool
18+
filename string
19+
20+
filenameFormat string
21+
dateFormat string
22+
timedFilename string
23+
}
24+
25+
func NewFileHandler(filename string, level record.Level) *FileHandler {
26+
h := &FileHandler{
27+
level: level,
28+
bubble: true,
29+
filename: filename,
30+
filenameFormat: "{filename}-{date}",
31+
dateFormat: "2006-01-02",
32+
}
33+
h.timedFilename = h.GetTimedFilename()
34+
return h
35+
}
36+
37+
// IsHandling Checks whether the given record will be handled by this handler.
38+
func (h *FileHandler) IsHandling(r record.Record) bool {
39+
return r.Level >= h.level
40+
}
41+
42+
// Handle Handles a record.
43+
func (h *FileHandler) Handle(r record.Record) bool {
44+
if !h.IsHandling(r) {
45+
return false
46+
}
47+
48+
r.Formatted = h.GetFormatter().Format(r)
49+
50+
h.write(r)
51+
52+
return false == h.bubble
53+
}
54+
55+
// SetLevel Sets minimum logging level at which this handler will be triggered.
56+
func (h *FileHandler) SetLevel(level record.Level) {
57+
h.level = level
58+
}
59+
60+
func (h *FileHandler) write(r record.Record) {
61+
h.Lock()
62+
defer h.Unlock()
63+
file, _ := os.OpenFile(h.timedFilename, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
64+
defer file.Close()
65+
file.Write([]byte(r.Formatted))
66+
}
67+
68+
// GetTimedFilename Gets the Timed filename.
69+
func (h *FileHandler) GetTimedFilename() string {
70+
dirname := path.Dir(h.filename)
71+
filename := path.Base(h.filename)
72+
fileExt := path.Ext(h.filename)
73+
filename = strings.TrimSuffix(filename, fileExt)
74+
75+
timedFilename := strings.Replace(path.Join(dirname, h.filenameFormat), "{filename}", filename, -1)
76+
timedFilename = strings.Replace(timedFilename, "{date}", time.Now().Local().Format(h.dateFormat), -1)
77+
78+
if len(fileExt) > 0 {
79+
timedFilename = timedFilename + fileExt
80+
}
81+
82+
return timedFilename
83+
}

log/handler/file_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package handler
2+
3+
import (
4+
"io/ioutil"
5+
"os"
6+
"path"
7+
"strings"
8+
"testing"
9+
"time"
10+
11+
"github.com/thinkoner/thinkgo/log/record"
12+
)
13+
14+
func TestNewFileHandler(t *testing.T) {
15+
filename := path.Join(os.TempDir(), "thinkgo.log")
16+
17+
h := NewFileHandler(filename, record.DEBUG)
18+
filename = h.GetTimedFilename()
19+
20+
os.Remove(filename)
21+
22+
message := "Log write to file"
23+
r := getRecord(message)
24+
h.Handle(r)
25+
26+
b, err := ioutil.ReadFile(filename)
27+
if err != nil {
28+
t.Error(err)
29+
}
30+
content := string(b)
31+
32+
if !strings.Contains(content, message) {
33+
t.Error("test FileHandler error")
34+
}
35+
36+
}
37+
38+
func getRecord(message string) record.Record {
39+
return record.Record{
40+
Level: 200,
41+
Message: message,
42+
LevelName: "INFO",
43+
Channel: "testing",
44+
Datetime: time.Now(),
45+
}
46+
}

log/handler/handler.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package handler
2+
3+
import (
4+
"github.com/thinkoner/thinkgo/log/formatter"
5+
"github.com/thinkoner/thinkgo/log/record"
6+
)
7+
8+
type Handler struct {
9+
formatter formatter.Formatter
10+
level record.Level
11+
}
12+
13+
// GetFormatter Gets the formatter.
14+
func (h *Handler) GetFormatter() formatter.Formatter {
15+
if h.formatter == nil {
16+
h.formatter = h.getDefaultFormatter()
17+
}
18+
return h.formatter
19+
}
20+
21+
// SetFormatter Sets the formatter.
22+
func (h *Handler) SetFormatter(f formatter.Formatter) *Handler {
23+
h.formatter = f
24+
return h
25+
}
26+
27+
func (h *Handler) getDefaultFormatter() formatter.Formatter {
28+
return formatter.NewLineFormatter()
29+
}

log/log.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package log
22

3+
import (
4+
"github.com/thinkoner/thinkgo/log/record"
5+
)
6+
37
var logger *Logger
48

59
func init() {
6-
logger = NewLogger("develop")
10+
logger = NewLogger("develop", record.DEBUG)
711
}
812

913
// Debug Adds a log record at the DEBUG level.
@@ -45,3 +49,13 @@ func Alert(format string, v ...interface{}) (bool, error) {
4549
func Emerg(format string, v ...interface{}) (bool, error) {
4650
return logger.Emerg(format, v...)
4751
}
52+
53+
// GetLogger Get the default Logger
54+
func GetLogger() *Logger {
55+
return logger
56+
}
57+
58+
// SetLogger Set the default Logger
59+
func SetLogger(l *Logger) {
60+
logger = l
61+
}

log/log_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
package log
22

33
import (
4+
"errors"
5+
"io/ioutil"
6+
"os"
7+
"path"
8+
"strings"
49
"testing"
10+
11+
"github.com/thinkoner/thinkgo/log/handler"
12+
"github.com/thinkoner/thinkgo/log/record"
513
)
614

715
func TestLog(t *testing.T) {
@@ -14,3 +22,43 @@ func TestLog(t *testing.T) {
1422
Alert("log with Alert")
1523
Emerg("log with Emerg")
1624
}
25+
26+
func TestLogWithFileHandler(t *testing.T) {
27+
28+
filename := path.Join(os.TempDir(), "thinkgo.log")
29+
30+
h := handler.NewFileHandler(filename, record.INFO)
31+
32+
l := NewLogger("testing", record.INFO)
33+
l.PushHandler(h)
34+
35+
filename = h.GetTimedFilename()
36+
37+
os.Remove(filename)
38+
39+
message := "Log write to file"
40+
41+
l.Debug(message)
42+
43+
_, err := ioutil.ReadFile(filename)
44+
if err == nil {
45+
t.Error(errors.New("test FileHandler error"))
46+
}
47+
48+
49+
h.SetLevel(record.DEBUG)
50+
l = NewLogger("testing", record.DEBUG)
51+
l.PushHandler(h)
52+
l.Debug(message)
53+
54+
b, err := ioutil.ReadFile(filename)
55+
if err != nil {
56+
t.Error(errors.New("test FileHandler error"))
57+
}
58+
content := string(b)
59+
60+
if !strings.Contains(content, message) {
61+
t.Error("test FileHandler error")
62+
}
63+
64+
}

log/logger.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@ type Handler interface {
1717

1818
type Logger struct {
1919
name string
20+
level record.Level
2021
handlers *list.List
2122
}
2223

23-
func NewLogger(name string) *Logger {
24+
// NewLogger New a Logger instance
25+
func NewLogger(name string, level record.Level) *Logger {
2426
logger := &Logger{
2527
name: name,
2628
handlers: list.New(),
29+
level: level,
2730
}
2831
return logger
2932
}
@@ -71,9 +74,10 @@ func (logger *Logger) GetHandlers() []Handler {
7174
return handler
7275
}
7376

74-
func (logger *Logger) AddRecord(level int, format string, v ...interface{}) (bool, error) {
77+
// AddRecord Adds a log record.
78+
func (logger *Logger) AddRecord(level record.Level, format string, v ...interface{}) (bool, error) {
7579
if logger.handlers.Len() == 0 {
76-
logger.PushHandler(handler.NewConsoleHandler())
80+
logger.PushHandler(handler.NewConsoleHandler(logger.level))
7781
}
7882

7983
levelName, err := GetLevelName(level)
@@ -156,7 +160,7 @@ func (logger *Logger) Emerg(format string, v ...interface{}) (bool, error) {
156160
}
157161

158162
// Gets the name of the logging level.
159-
func GetLevelName(level int) (string, error) {
163+
func GetLevelName(level record.Level) (string, error) {
160164
levels := record.GetLevels()
161165
l, ok := levels[level]
162166
if !ok {

0 commit comments

Comments
 (0)