Skip to content

Commit

Permalink
Added to write logs to files
Browse files Browse the repository at this point in the history
  • Loading branch information
leeqvip committed Mar 21, 2019
1 parent 195ed41 commit 6223c61
Show file tree
Hide file tree
Showing 9 changed files with 261 additions and 33 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,8 @@ request.Session().Set("user", "alice")

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**.

#### Basic Usage

```go
import "github.com/thinkoner/thinkgo/log"

Expand All @@ -410,6 +412,24 @@ log.Alert("log with Alert")
log.Emerg("log with Emerg")
```

#### Log Storage

Out of the box, ThinkGo supports writing log information to `daily` files, the `console`.

For example, if you wish to use `daily` log files, you can do this:

```go
import (
"github.com/thinkoner/thinkgo/log"
"github.com/thinkoner/thinkgo/log/handler"
"github.com/thinkoner/thinkgo/log/record"
)

fh := handler.NewFileHandler("path/to/thinkgo.log", record.INFO)

log.GetLogger().PushHandler(fh)
```

## Cache

ThinkGo Cache Currently supports redis, memory, and can customize the store adapter.
Expand Down
32 changes: 7 additions & 25 deletions log/handler/console.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"os"
"sync"

"github.com/thinkoner/thinkgo/log/formatter"
"github.com/thinkoner/thinkgo/log/record"
)

Expand All @@ -18,7 +17,7 @@ func newBrush(color string) brush {
}
}

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

type ConsoleHandler struct {
Handler
sync.Mutex
level int
formatter formatter.Formatter
bubble bool
level record.Level

bubble bool
}

func NewConsoleHandler() *ConsoleHandler {
func NewConsoleHandler(level record.Level) *ConsoleHandler {
return &ConsoleHandler{
level: record.DEBUG,
level: level,
bubble: true,
}
}
Expand Down Expand Up @@ -67,21 +67,3 @@ func (h *ConsoleHandler) write(r record.Record) {
message := colors[r.Level](r.Formatted)
os.Stdout.Write(append([]byte(message)))
}

// GetFormatter Gets the formatter.
func (h *ConsoleHandler) GetFormatter() formatter.Formatter {
if h.formatter == nil {
h.formatter = h.getDefaultFormatter()
}
return h.formatter
}

// SetFormatter Sets the formatter.
func (h *ConsoleHandler) SetFormatter(f formatter.Formatter) *ConsoleHandler {
h.formatter = f
return h
}

func (h *ConsoleHandler) getDefaultFormatter() formatter.Formatter {
return formatter.NewLineFormatter()
}
83 changes: 83 additions & 0 deletions log/handler/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package handler

import (
"os"
"path"
"strings"
"sync"
"time"

"github.com/thinkoner/thinkgo/log/record"
)

type FileHandler struct {
Handler
sync.Mutex
level record.Level
bubble bool
filename string

filenameFormat string
dateFormat string
timedFilename string
}

func NewFileHandler(filename string, level record.Level) *FileHandler {
h := &FileHandler{
level: level,
bubble: true,
filename: filename,
filenameFormat: "{filename}-{date}",
dateFormat: "2006-01-02",
}
h.timedFilename = h.GetTimedFilename()
return h
}

// IsHandling Checks whether the given record will be handled by this handler.
func (h *FileHandler) IsHandling(r record.Record) bool {
return r.Level >= h.level
}

// Handle Handles a record.
func (h *FileHandler) Handle(r record.Record) bool {
if !h.IsHandling(r) {
return false
}

r.Formatted = h.GetFormatter().Format(r)

h.write(r)

return false == h.bubble
}

// SetLevel Sets minimum logging level at which this handler will be triggered.
func (h *FileHandler) SetLevel(level record.Level) {
h.level = level
}

func (h *FileHandler) write(r record.Record) {
h.Lock()
defer h.Unlock()
file, _ := os.OpenFile(h.timedFilename, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
defer file.Close()
file.Write([]byte(r.Formatted))
}

// GetTimedFilename Gets the Timed filename.
func (h *FileHandler) GetTimedFilename() string {
dirname := path.Dir(h.filename)
filename := path.Base(h.filename)
fileExt := path.Ext(h.filename)
filename = strings.TrimSuffix(filename, fileExt)

timedFilename := strings.Replace(path.Join(dirname, h.filenameFormat), "{filename}", filename, -1)
timedFilename = strings.Replace(timedFilename, "{date}", time.Now().Local().Format(h.dateFormat), -1)

if len(fileExt) > 0 {
timedFilename = timedFilename + fileExt
}

return timedFilename
}
46 changes: 46 additions & 0 deletions log/handler/file_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package handler

import (
"io/ioutil"
"os"
"path"
"strings"
"testing"
"time"

"github.com/thinkoner/thinkgo/log/record"
)

func TestNewFileHandler(t *testing.T) {
filename := path.Join(os.TempDir(), "thinkgo.log")

h := NewFileHandler(filename, record.DEBUG)
filename = h.GetTimedFilename()

os.Remove(filename)

message := "Log write to file"
r := getRecord(message)
h.Handle(r)

b, err := ioutil.ReadFile(filename)
if err != nil {
t.Error(err)
}
content := string(b)

if !strings.Contains(content, message) {
t.Error("test FileHandler error")
}

}

func getRecord(message string) record.Record {
return record.Record{
Level: 200,
Message: message,
LevelName: "INFO",
Channel: "testing",
Datetime: time.Now(),
}
}
29 changes: 29 additions & 0 deletions log/handler/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package handler

import (
"github.com/thinkoner/thinkgo/log/formatter"
"github.com/thinkoner/thinkgo/log/record"
)

type Handler struct {
formatter formatter.Formatter
level record.Level
}

// GetFormatter Gets the formatter.
func (h *Handler) GetFormatter() formatter.Formatter {
if h.formatter == nil {
h.formatter = h.getDefaultFormatter()
}
return h.formatter
}

// SetFormatter Sets the formatter.
func (h *Handler) SetFormatter(f formatter.Formatter) *Handler {
h.formatter = f
return h
}

func (h *Handler) getDefaultFormatter() formatter.Formatter {
return formatter.NewLineFormatter()
}
16 changes: 15 additions & 1 deletion log/log.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package log

import (
"github.com/thinkoner/thinkgo/log/record"
)

var logger *Logger

func init() {
logger = NewLogger("develop")
logger = NewLogger("develop", record.DEBUG)
}

// Debug Adds a log record at the DEBUG level.
Expand Down Expand Up @@ -45,3 +49,13 @@ func Alert(format string, v ...interface{}) (bool, error) {
func Emerg(format string, v ...interface{}) (bool, error) {
return logger.Emerg(format, v...)
}

// GetLogger Get the default Logger
func GetLogger() *Logger {
return logger
}

// SetLogger Set the default Logger
func SetLogger(l *Logger) {
logger = l
}
48 changes: 48 additions & 0 deletions log/log_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
package log

import (
"errors"
"io/ioutil"
"os"
"path"
"strings"
"testing"

"github.com/thinkoner/thinkgo/log/handler"
"github.com/thinkoner/thinkgo/log/record"
)

func TestLog(t *testing.T) {
Expand All @@ -14,3 +22,43 @@ func TestLog(t *testing.T) {
Alert("log with Alert")
Emerg("log with Emerg")
}

func TestLogWithFileHandler(t *testing.T) {

filename := path.Join(os.TempDir(), "thinkgo.log")

h := handler.NewFileHandler(filename, record.INFO)

l := NewLogger("testing", record.INFO)
l.PushHandler(h)

filename = h.GetTimedFilename()

os.Remove(filename)

message := "Log write to file"

l.Debug(message)

_, err := ioutil.ReadFile(filename)
if err == nil {
t.Error(errors.New("test FileHandler error"))
}


h.SetLevel(record.DEBUG)
l = NewLogger("testing", record.DEBUG)
l.PushHandler(h)
l.Debug(message)

b, err := ioutil.ReadFile(filename)
if err != nil {
t.Error(errors.New("test FileHandler error"))
}
content := string(b)

if !strings.Contains(content, message) {
t.Error("test FileHandler error")
}

}
12 changes: 8 additions & 4 deletions log/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ type Handler interface {

type Logger struct {
name string
level record.Level
handlers *list.List
}

func NewLogger(name string) *Logger {
// NewLogger New a Logger instance
func NewLogger(name string, level record.Level) *Logger {
logger := &Logger{
name: name,
handlers: list.New(),
level: level,
}
return logger
}
Expand Down Expand Up @@ -71,9 +74,10 @@ func (logger *Logger) GetHandlers() []Handler {
return handler
}

func (logger *Logger) AddRecord(level int, format string, v ...interface{}) (bool, error) {
// AddRecord Adds a log record.
func (logger *Logger) AddRecord(level record.Level, format string, v ...interface{}) (bool, error) {
if logger.handlers.Len() == 0 {
logger.PushHandler(handler.NewConsoleHandler())
logger.PushHandler(handler.NewConsoleHandler(logger.level))
}

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

// Gets the name of the logging level.
func GetLevelName(level int) (string, error) {
func GetLevelName(level record.Level) (string, error) {
levels := record.GetLevels()
l, ok := levels[level]
if !ok {
Expand Down
Loading

0 comments on commit 6223c61

Please sign in to comment.