Skip to content

Commit 594819c

Browse files
author
zzy
committed
init
0 parents  commit 594819c

18 files changed

+1355
-0
lines changed

README.md

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# The Go Log
2+
3+
4+
![](https://travis-ci.org/boennemann/badges.svg?branch=master) ![](https://img.shields.io/badge/license-MIT-blue.svg) ![](https://img.shields.io/badge/godoc-reference-blue.svg)
5+
6+
Go Log is customizable modular log.
7+
8+
![](https://github.com/golang/go/blob/master/doc/gopher/fiveyears.jpg?raw=true)
9+
10+
11+
#### Download and Install
12+
13+
```shell
14+
go get github.com/zooyer/log
15+
```
16+
17+
#### Features
18+
19+
- zero config, out of the box feature
20+
- customizable modular
21+
- high performance
22+
23+
##### Example: [example/example.go](example/example.go)
24+
25+
1. zero config
26+
27+
```go
28+
package main
29+
30+
import (
31+
"github.com/zooyer/log"
32+
)
33+
34+
func main() {
35+
// 0 config
36+
log.D("debug message") // 2019-10-28 23:07:56.369 DEBUG "debug message"
37+
log.I("info message") // 2019-10-28 23:07:56.369 INFO "info message"
38+
log.W("warning message") // 2019-10-28 23:07:56.369 WARNING "warning message"
39+
log.E("error message") // 2019-10-28 23:07:56.369 ERROR "error message"
40+
}
41+
```
42+
43+
output:
44+
45+
```shell
46+
2019-10-28 23:07:56.369 DEBUG "debug message"
47+
2019-10-28 23:07:56.369 INFO "info message"
48+
2019-10-28 23:07:56.369 WARNING "warning message"
49+
2019-10-28 23:07:56.369 ERROR "error message"
50+
```
51+
52+
53+
54+
2. custom
55+
56+
```go
57+
package main
58+
59+
import (
60+
"time"
61+
62+
"github.com/zooyer/log"
63+
)
64+
65+
func main() {
66+
// 1. create file rotating(default: size/time)
67+
rotating := log.NewFileCountRotating(1024, 10)
68+
69+
// 2. create file recorder(default: terminal/file/network), custom formatter: json/text
70+
recorder, err := log.NewFileRecorder("example.log", log.FormatJson, rotating)
71+
if err != nil {
72+
panic(err)
73+
}
74+
defer recorder.Close()
75+
76+
// 3. create logger, each level can be mapped to different recorder
77+
logger := log.NewLogger()
78+
logger.SetRecorder(recorder, "DEBUG", "INFO")
79+
logger.SetDefault(recorder)
80+
81+
// 4. create log, logger's wrap
82+
l := log.NewLog(logger)
83+
l.Tag("id", "1001").Tag("type", "test").Debug("custom debug log")
84+
l.Error("custom error log")
85+
86+
// 5. custom
87+
var record = new(log.Record)
88+
record.Time = time.Now()
89+
record.Level = "record"
90+
record.Message = "custom log"
91+
record.Tag = make(log.Tag)
92+
record.Tag["id"] = "1001"
93+
record.Tag["type"] = "test"
94+
logger.Record(record)
95+
}
96+
```
97+
98+
output:
99+
100+
```shell
101+
cat example.log
102+
{"level":"DEBUG","message":"custom debug log","tag":{"id":"1001","type":"test"},"time":"2019-10-28 23:41:34.385"}
103+
{"level":"ERROR","message":"custom error log","time":"2019-10-28 23:41:34.386"}
104+
{"level":"record","message":"custom log","tag":{"id":"1001","type":"test"},"time":"2019-10-28 23:41:34.386"}
105+
```
106+
107+

default.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package log
2+
3+
var std = NewLog(defaultLogger())
4+
5+
func defaultLogger() Logger {
6+
var logger = NewLogger()
7+
stdout := NewStdoutRecorder(FormatColorText)
8+
stderr := NewStdoutRecorder(FormatColorText)
9+
logger.SetDefault(stdout)
10+
logger.SetRecorder(stdout, "DEBUG", "INFO")
11+
logger.SetRecorder(stderr, "WARNING", "ERROR")
12+
13+
return logger
14+
}
15+
16+
func Debug(v ...interface{}) {
17+
std.Debug(v...)
18+
}
19+
20+
func Info(v ...interface{}) {
21+
std.Info(v...)
22+
}
23+
24+
func Warning(v ...interface{}) {
25+
std.Warning(v...)
26+
}
27+
28+
func Error(v ...interface{}) {
29+
std.Error(v...)
30+
}
31+
32+
func D(v ...interface{}) {
33+
std.Debug(v...)
34+
}
35+
36+
func I(v ...interface{}) {
37+
std.Info(v...)
38+
}
39+
40+
func W(v ...interface{}) {
41+
std.Warning(v...)
42+
}
43+
44+
func E(v ...interface{}) {
45+
std.Error(v...)
46+
}

default_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package log
2+
3+
import (
4+
"errors"
5+
"testing"
6+
)
7+
8+
func TestDebug(t *testing.T) {
9+
Debug("level:", "debug")
10+
Info("hello", "world")
11+
Warning("warning", 404)
12+
Error("error", errors.New("test error"))
13+
}

example/example.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package main
2+
3+
import (
4+
"time"
5+
6+
"github.com/zooyer/log"
7+
)
8+
9+
func main() {
10+
// 0 config
11+
log.D("debug message") // 2019-10-28 23:07:56.369 DEBUG "debug message"
12+
log.I("info message") // 2019-10-28 23:07:56.369 INFO "info message"
13+
log.W("warning message") // 2019-10-28 23:07:56.369 WARNING "warning message"
14+
log.E("error message") // 2019-10-28 23:07:56.369 ERROR "error message"
15+
16+
// 1. create file rotating(default: size/time)
17+
rotating := log.NewFileCountRotating(1024, 10)
18+
19+
// 2. create file recorder(default: terminal/file/network), custom formatter: json/text
20+
recorder, err := log.NewFileRecorder("example.log", log.FormatJson, rotating)
21+
if err != nil {
22+
panic(err)
23+
}
24+
defer recorder.Close()
25+
26+
// 3. create logger, each level can be mapped to different recorder
27+
logger := log.NewLogger()
28+
logger.SetRecorder(recorder, "DEBUG", "INFO")
29+
logger.SetDefault(recorder)
30+
31+
// 4. create log, logger's wrap
32+
l := log.NewLog(logger)
33+
l.Tag("id", "1001").Tag("type", "test").Debug("custom debug log")
34+
l.Error("custom error log")
35+
36+
// 5. custom
37+
var record = new(log.Record)
38+
record.Time = time.Now()
39+
record.Level = "record"
40+
record.Message = "custom log"
41+
record.Tag = make(log.Tag)
42+
record.Tag["id"] = "1001"
43+
record.Tag["type"] = "test"
44+
logger.Record(record)
45+
}

example/example.log

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{"level":"DEBUG","message":"custom debug log","tag":{"id":"1001","type":"test"},"time":"2019-10-28 23:41:34.385"}
2+
{"level":"ERROR","message":"custom error log","time":"2019-10-28 23:41:34.386"}
3+
{"level":"record","message":"custom log","tag":{"id":"1001","type":"test"},"time":"2019-10-28 23:41:34.386"}

format.go

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package log
2+
3+
import (
4+
"encoding/json"
5+
"strconv"
6+
"strings"
7+
"sync"
8+
)
9+
10+
type Formatter func(record *Record) string
11+
12+
const format = "2006-01-02 15:04:05.000"
13+
14+
// {"level":"DEBUG","tag":{"rpc":"http","trace":"10001241235","type":"rpc"},"time":"2019-10-27 00:08:02.908","message":"debug"}
15+
func FormatJson(record *Record) string {
16+
var obj = make(map[string]interface{})
17+
obj["time"] = record.Time.Format(format)
18+
obj["level"] = record.Level
19+
obj["message"] = record.Message
20+
if record.Tag != nil {
21+
obj["tag"] = record.Tag
22+
}
23+
24+
data, _ := json.Marshal(obj)
25+
26+
return string(data)
27+
}
28+
29+
// date time level tag message
30+
// 2019-10-27 00:04:36.028 DEBUG "trace"="10001241235" "type"="rpc" "rpc"="http" "hello world"
31+
func FormatText(record *Record) string {
32+
var builder = pool.Get().(*strings.Builder)
33+
defer pool.Put(builder)
34+
35+
builder.Reset()
36+
builder.WriteString(record.Time.Format(format))
37+
builder.WriteString(" ")
38+
builder.WriteString(record.Level)
39+
40+
var key, val string
41+
for k, v := range record.Tag {
42+
key = strconv.Quote(k)
43+
val = strconv.Quote(v)
44+
45+
builder.WriteString(" ")
46+
builder.WriteString(key)
47+
builder.WriteString("=")
48+
builder.WriteString(val)
49+
}
50+
51+
message := strconv.Quote(record.Message)
52+
builder.WriteString(" ")
53+
builder.WriteString(message)
54+
55+
return builder.String()
56+
}
57+
58+
func FormatColorText(record *Record) string {
59+
var builder = pool.Get().(*strings.Builder)
60+
defer pool.Put(builder)
61+
62+
builder.Reset()
63+
64+
// 时间渲染为黄色
65+
builder.WriteString("\033[33m")
66+
builder.WriteString(record.Time.Format(format))
67+
builder.WriteString("\033[0m")
68+
builder.WriteString(" ")
69+
70+
// 等级按级别渲染
71+
switch record.Level {
72+
case "DEBUG":
73+
builder.WriteString("\033[32m")
74+
case "INFO":
75+
builder.WriteString("\033[34m")
76+
case "WARNING":
77+
builder.WriteString("\033[35m")
78+
case "ERROR":
79+
builder.WriteString("\033[31m")
80+
default:
81+
builder.WriteString("\033[31m")
82+
}
83+
builder.WriteString(record.Level)
84+
builder.WriteString("\033[0m")
85+
86+
// tag渲染为青色
87+
var key, val string
88+
for k, v := range record.Tag {
89+
key = strconv.Quote(k)
90+
val = strconv.Quote(v)
91+
92+
builder.WriteString(" ")
93+
builder.WriteString("\033[36m")
94+
builder.WriteString(key)
95+
builder.WriteString("=")
96+
builder.WriteString(val)
97+
builder.WriteString("\033[0m")
98+
}
99+
100+
message := strconv.Quote(record.Message)
101+
builder.WriteString(" ")
102+
builder.WriteString(message)
103+
104+
return builder.String()
105+
}
106+
107+
var pool = sync.Pool{
108+
New: func() interface{} {
109+
return new(strings.Builder)
110+
},
111+
}

format_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package log
2+
3+
import (
4+
"testing"
5+
"time"
6+
)
7+
8+
func TestFormat(t *testing.T) {
9+
var record = new(Record)
10+
record.Time = time.Now()
11+
record.Level = "DEBUG"
12+
record.Tag = map[string]string{
13+
"module": "apollo",
14+
"trace": "10001241235",
15+
"type": "rpc",
16+
"rpc": "http",
17+
"latency": "10",
18+
"other": `{"json":"value", " ": " "}`,
19+
}
20+
record.Message = "hello world"
21+
22+
t.Log(FormatJson(record))
23+
t.Log(FormatText(record))
24+
t.Log(FormatColorText(record))
25+
record.Level = "INFO"
26+
t.Log(FormatColorText(record))
27+
record.Level = "WARNING"
28+
t.Log(FormatColorText(record))
29+
record.Level = "ERROR"
30+
t.Log(FormatColorText(record))
31+
}

0 commit comments

Comments
 (0)