Skip to content

Commit

Permalink
v0.0.10 版本发布
Browse files Browse the repository at this point in the history
  • Loading branch information
FishGoddess committed Mar 10, 2020
2 parents 14d9c0f + 4ad01da commit efeee87
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 19 deletions.
9 changes: 7 additions & 2 deletions FUTURE.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
## ✒ 未来版本的新特性 (Features in future version)

### v0.0.11
### v0.0.12
* 时间格式化操作中 time.Time.AppendFormat 消耗性能很多,思考优化方案

### v0.0.10
### v0.0.11
* 支持日志输出为 Json 形式,通过增加 JSON 日志处理器实现

### v0.0.10
* 扩展了 Logger 的方法,可以获取到内部的属性,为日志处理器做准备
* 支持创建 Logger 对象之后修改它的输出源 writer(这是个之前被遗漏的功能特性哈哈)
* 调整了内部 log 方法的锁机制,使用类似于写时复制的方式释放日志输出的并发性

### v0.0.9
* 支持日志输出函数,日志信息可以是一个返回 string 的函数
* 公开 PrefixOf 方法,方便用户自定义处理器的时候获取日志级别字符串
Expand Down
6 changes: 6 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
## ✒ 历史版本的特性介绍 (Features in old version)

### v0.0.10
> 此版本发布于 2020-03-10
* 扩展了 Logger 的方法,可以获取到内部的属性,为日志处理器做准备
* 支持创建 Logger 对象之后修改它的输出源 writer(这是个之前被遗漏的功能特性哈哈)
* 调整了内部 log 方法的锁机制,使用类似于写时复制的方式释放日志输出的并发性

### v0.0.9
> 此版本发布于 2020-03-09
* 支持日志输出函数,日志信息可以是一个返回 string 的函数
Expand Down
2 changes: 1 addition & 1 deletion README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ module your_project_name
go 1.14

require (
github.com/FishGoddess/logit v0.0.9
github.com/FishGoddess/logit v0.0.10
)
```

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ module your_project_name
go 1.14

require (
github.com/FishGoddess/logit v0.0.9
github.com/FishGoddess/logit v0.0.10
)
```

Expand Down Expand Up @@ -126,7 +126,7 @@ $ go test -v ./_examples/benchmarks_test.go -bench=. -benchtime=1s
**行为,主要体现在对参数 v interface{} 进行类型检测的逻辑上,而日志输出都是字符串,这一个**
**判断是可以省略的,可以减少很多运行时操作时间!v0.0.8 版本开始使用了更有效率的输出方式!**

**3. 经过对 v0.0.8 版本的性能检测,发现时间格式化操作消耗了接近一般的处理时间**
**3. 经过对 v0.0.8 版本的性能检测,发现时间格式化操作消耗了接近一半的处理时间**
**主要体现在 time.Time.AppendFormat 的调用上。目前正在思考优化方案,或许会在之后的版本中解决!**

### 👥 贡献者
Expand Down
7 changes: 5 additions & 2 deletions _examples/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ func main() {

// Then you will be easy to log!
logger.Debug("this is a debug message!")
logger.Info("this is a info message!")
logger.Info("this is an info message!")
logger.Warn("this is a warn message!")
logger.Error("this is a error message!")
logger.Error("this is an error message!")

// NewLogger creates a new Logger holder.
// The first parameter "os.Stdout" is a writer for logging.
Expand All @@ -60,4 +60,7 @@ func main() {
r := rand.New(rand.NewSource(time.Now().Unix()))
return "debug rand int: " + strconv.Itoa(r.Intn(100))
})

// If you want to change logger's writer, try this:
logger.ChangeWriterTo(os.Stdout)
}
9 changes: 6 additions & 3 deletions doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ Package logit provides an easy way to use foundation for your logging operations
// Then you will be easy to log!
logger.Debug("this is a debug message!")
logger.Info("this is a info message!")
logger.Info("this is an info message!")
logger.Warn("this is a warn message!")
logger.Error("this is a error message!")
logger.Error("this is an error message!")
// NewLogger creates a new Logger holder.
// The first parameter "os.Stdout" is a writer for logging.
Expand All @@ -69,6 +69,9 @@ Package logit provides an easy way to use foundation for your logging operations
return "debug rand int: " + strconv.Itoa(r.Intn(100))
})
// If you want to change logger's writer, try this:
logger.ChangeWriterTo(os.Stdout)
3. enable or disable:
// Every new Logger is running.
Expand Down Expand Up @@ -167,4 +170,4 @@ Package logit provides an easy way to use foundation for your logging operations
package logit // import "github.com/FishGoddess/logit"

// Version is the version string representation of the "logit" package.
const Version = "0.0.9"
const Version = "0.0.10"
52 changes: 46 additions & 6 deletions logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,13 @@ func (l *Logger) ChangeLevelTo(newLevel LoggerLevel) {
l.level = newLevel
}

// Level returns the logger level of l.
func (l *Logger) Level() LoggerLevel {
l.mu.RLock()
defer l.mu.RUnlock()
return l.level
}

// EnableFileInfo means every log will contain file info like line number.
// However, you should know that this is expensive in time.
// So be sure you really need it or keep it disabled.
Expand Down Expand Up @@ -155,12 +162,24 @@ func (l *Logger) SetHandlers(handlers ...LoggerHandler) bool {
return false
}

// 先清空原本的日志处理器,再添加新的日志处理器
l.mu.Lock()
defer l.mu.Unlock()
l.handlers = handlers
l.handlers = nil
l.handlers = append(l.handlers, handlers...)
return true
}

// Handlers returns all handlers of l in a copy slice.
func (l *Logger) Handlers() []LoggerHandler {
l.mu.RLock()
defer l.mu.RUnlock()

// 返回的是日志处理器的副本,防止被非法篡改
handlers := make([]LoggerHandler, 0, len(l.handlers))
return append(handlers, l.handlers...)
}

// SetFormatOfTime sets format of time as you want.
// Default is "2006-01-02 15:04:05", see DefaultFormatOfTime.
func (l *Logger) SetFormatOfTime(formatOfTime string) {
Expand All @@ -169,8 +188,24 @@ func (l *Logger) SetFormatOfTime(formatOfTime string) {
l.formatOfTime = formatOfTime
}

// FormatOfTime returns the format of time in l.
func (l *Logger) FormatOfTime() string {
l.mu.RLock()
defer l.mu.RUnlock()
return l.formatOfTime
}

// ChangeWriterTo changes current writer to newWriter.
func (l *Logger) ChangeWriterTo(newWriter io.Writer) {
l.mu.Lock()
defer l.mu.Unlock()
l.writer = newWriter
}

// Writer returns the writer of l.
func (l *Logger) Writer() io.Writer {
l.mu.RLock()
defer l.mu.RUnlock()
return l.writer
}

Expand All @@ -183,21 +218,26 @@ func (l *Logger) log(callDepth int, level LoggerLevel, msg string) {

// 加上读锁
l.mu.RLock()
defer l.mu.RUnlock()

// 以下两种条件直接返回,不记录日志:
// 1. 日志处于禁用状态,也就是 l.running = false
// 2. 日志记录器的日志级别高于这条记录的日志级别
if !l.running || l.level > level {
l.mu.RUnlock()
return
}

// 提前释放读锁,后续操作非常消耗时间,可以不用加锁了,彻底释放并发的天性
// 但是 needFileInfo 的获取需要保证并发安全,就在释放锁之前拷贝一份副本,
// 即使释放锁之后有人修改了这个属性,也和这里无关了,因为在执行这个 log 方法的时间点上
// 这个属性的值就已经确定了,并且不允许被修改了,这类似于 copy on write 的解决思路。
// 这个解决并发竞争的方案是否没有问题,需要时间的验证才知道
needFileInfo := l.needFileInfo
l.mu.RUnlock()

// 如果需要文件信息,对当前的 msg 进行包装
if l.needFileInfo {
// 提前释放读锁,后续操作非常消耗时间,等获取完文件信息再上读锁
l.mu.RUnlock()
if needFileInfo {
msg = wrapMessageWithFileInfo(callDepth, msg)
l.mu.RLock()
}

// 处理日志
Expand Down
2 changes: 1 addition & 1 deletion logger_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ func (lh LoggerHandler) handle(logger *Logger, level LoggerLevel, now time.Time,
// The log handled by this handler will be like "[Info] [2020-03-06 16:10:44] msg".
// If you want to customize, just code your own handler, then replace it!
func DefaultLoggerHandler(logger *Logger, level LoggerLevel, now time.Time, msg string) bool {
logger.Writer().Write([]byte("[" + PrefixOf(level) + "] [" + now.Format(logger.formatOfTime) + "] " + msg + "\n"))
logger.Writer().Write([]byte("[" + PrefixOf(level) + "] [" + now.Format(logger.FormatOfTime()) + "] " + msg + "\n"))
return true
}
72 changes: 70 additions & 2 deletions logger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ package logit
import (
"fmt"
"os"
"strconv"
"strings"
"sync"
"testing"
"time"
)
Expand Down Expand Up @@ -62,6 +65,7 @@ func TestLoggerEnable(t *testing.T) {
// 测试日志记录器的级别控制是否可用
func TestLoggerLevel(t *testing.T) {
logger := NewLogger(os.Stdout, WarnLevel)
logger.Warn(logger.Level().String())
logger.Info("这条 info 级别的内容可以显示吗?")
logger.Error("这条 error 级别的内容可以显示吗?")
logger.Warn("这条 warn 级别的内容可以显示吗?")
Expand Down Expand Up @@ -131,7 +135,71 @@ func TestLoggerAddHandlersAndSetHandlers(t *testing.T) {
// 测试更改时间格式化标准的方法
func TestLoggerSetFormatOfTime(t *testing.T) {
logger := NewLogger(os.Stdout, InfoLevel)
logger.Info("当前时间格式化信息!")
logger.Info("当前时间格式化信息!" + logger.FormatOfTime())
logger.SetFormatOfTime("2006年01月02日 15点04分05秒")
logger.Info("更改之后的时间格式化信息!")
logger.Info("更改之后的时间格式化信息!" + logger.FormatOfTime())
}

// 测试获取日志处理器的方法
func TestLoggerHandlers(t *testing.T) {
logger := NewStdoutLogger(InfoLevel)
handlers := logger.Handlers()

// 需要判断地址是否一样,一样说明有问题
if &handlers[0] == &logger.handlers[0] {
t.Fatal("handlers 获取的数据和底层数据地址一样!这是有问题的!")
}

// 显示每个日志处理器的地址
logger.Info("handlers 个数:" + strconv.Itoa(len(handlers)))
logger.InfoFunction(func() string {
builder := strings.Builder{}
for _, handler := range handlers {
builder.WriteString(fmt.Sprintf("%p ", &handler))
}
return builder.String()
})

// 尝试非法篡改日志处理器
handlers[0] = func(logger *Logger, level LoggerLevel, now time.Time, msg string) bool {
fmt.Println("哈哈哈被非法篡改了!!!")
return false
}
logger.Warn("这条信息需要显示出来!")
}

// 测试更改写出器的方法
func TestLoggerChangeWriterTo(t *testing.T) {
logger := NewStdoutLogger(DebugLevel)
fmt.Println(logger.writer)
logger.Debug("哈哈哈")

file, _ := os.Create("Z:/TestLoggerChangeWriterTo.log")
logger.ChangeWriterTo(file)
fmt.Println(logger.writer)
logger.Debug("哈哈哈文件?")
}

// 测试并发情况下使用 Logger
func TestLoggerInConcurrency(t *testing.T) {

logger := NewFileLogger("Z:/TestLoggerInConcurrency.log", DebugLevel)
//logger := NewStdoutLogger(DebugLevel)

group := sync.WaitGroup{}
for i := 0; i < 100; i++ {
group.Add(1)
go func(num int) {
if num == 30 || num == 60 {
logger.ChangeLevelTo(InfoLevel)
}
logger.Info(strconv.Itoa(num))
if num == 60 || num == 90 {
logger.ChangeWriterTo(os.Stdout)
}
group.Done()
}(i)
}

group.Wait()
}
7 changes: 7 additions & 0 deletions logit.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

package logit

import "io"

// defaultLogger is a Logger holder for global usage.
// Default level is info level.
var defaultLogger = NewStdoutLogger(InfoLevel)
Expand Down Expand Up @@ -122,3 +124,8 @@ func WarnFunction(msgGenerator func() string) {
func ErrorFunction(messageGenerator func() string) {
defaultLogger.ErrorFunction(messageGenerator)
}

// ChangeWriterTo changes current writer to newWriter.
func ChangeWriterTo(newWriter io.Writer) {
defaultLogger.ChangeWriterTo(newWriter)
}

0 comments on commit efeee87

Please sign in to comment.