Skip to content

Commit

Permalink
re-organize files & switch to go-logr/logr
Browse files Browse the repository at this point in the history
  • Loading branch information
zhcpku committed Jul 6, 2019
1 parent d13006f commit 3312f28
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 26 deletions.
21 changes: 5 additions & 16 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,25 +1,14 @@

GOFILES=$(wildcard *.go)
BACKENDS=$(wildcard ./backend/*.go)
EXAMPLE=./example/main.go
GOBIN=./bin

all: build test

.PHONY: build
build:
@echo " > formating file ..."
go fmt $(GOFILES)
go fmt $(BACKENDS)
golangci-lint run $(GOFILES)
golangci-lint run $(BACKENDS)
@rm -rf $(GOBIN)
@-mkdir $(GOBIN)
go build -o $(patsubst %.go, $(GOBIN)/%, $(notdir $(EXAMPLE))) $(EXAMPLE)
@scripts/go-build

.PHONY: test
test:
@echo " > testing file ..."

.PHONY:clean
.PHONY: clean
clean:
@echo " > cleaning file ..."
rm -rf $(GOBIN)
rm -rf ./bin/
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## 功能介绍

[`go-coder/logr`](https://github.com/go-coder/logr) 的一个基础实现方案。`go-coder/logr`[`go-logr/logr`](https://github.com/go-logr/logr) 的一个分支,对于当前实现简单改动就能应用到 `go-logr/logr`
[`go-logr/logr`](https://github.com/go-logr/logr) 的一个基础实现方案

## 设计思路

Expand All @@ -17,8 +17,9 @@

+ 远程日志:pubsub、 gRPC、HTTP网页 等形式
+ AB测试:同时运行新旧版本的程序,自动对比日志不同,从中发现可能存在的问题
+ 日志归集:将多个不同程序的日志汇总到一个地址进行分析

## 竞争问题
## 前端的竞争问题

考虑两种使用场景:

Expand All @@ -40,7 +41,7 @@ go func() {
}()
```

1. logr.V / logr.WithName / logr.WithFields
1. logr.V / logr.WithName / logr.WithValues

实现的时候,都是在副本中进行的操作,只需要考虑 copy 函数是否有竞争问题即可。

Expand All @@ -57,3 +58,7 @@ go func() {
### 结论

logr 通过 log 对象只读的方式避免了竞争问题。所有对 log 进行改变的操作都是在新生成的副本之上进行的,从而保证了不会发生竞争。

## 后端竞争问题

由后端自行控制,stderr 的竞争问题分析参见 [README.md](./backend/README.md)
20 changes: 18 additions & 2 deletions backend/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
# stderr 解决竞争的方案
# logr 后端设计

logr 在设计的时候充分考虑了扩展性,可以添加多种不同的后端方案,方便日志打印和日志归集。只要实现了 [`types.go`](../types/types.go) 中定义的 [`EntryWriter`](../types/types.go#L15) 接口,就可以直接切换后端,而不必担心日志前端的兼容问题。

这里,我们默认提供了 `stderr`[后端实现](./stderr.go)

## stderr 解决竞争的方案

log 前端部分采用只读类型解决了竞争问题,后端的竞争问题由后端自行解决。这里的解决思路同样是两个:只读、加锁(包括 chan 也是用到了锁)。

我们注意到,可能存在的竞争发生在调用 os.Stderr.WriteString 的时候,由于这不是一个原子操作,也就存在着一条日志没打完,另一条日志混入的情况。只读的解决办法看样子不行,我们这里考虑加互斥锁、或者使用 channel,下面比较一下两种方案的优势和不足:

使用 channel 的好处在于直观,所有的 log 请求被组织成了一个队列的形式,所有的日志汇集到了一个 goroutine 中进行处理;可能存在的问题是,当日志请求过多的时候,这个负责处理日志的 goroutine 可能会成为性能瓶颈。

加锁的话,日志请求在原来的 goroutine 中完成,避免了单个 goroutine 的性能我呢提,但是会影响当前 goroutine 的性能。
加锁的话,日志请求在原来的 goroutine 中完成,避免了单个 goroutine 的性能问题,但是会影响当前 goroutine 的性能。

我们假定日志组织良好,不会达到 goroutine 性能瓶颈。这样,采用 channel 的方式排队处理请求,把日志处理从普通 goroutine 中提取出来,由专门的 goroutine 来处理,以期提高性能。

### 思考1

如果使用的是无缓冲chan的话,日志库性能并不高,因为阻塞队列必须每产生一条日志就打印下来,这其实是一个同步操作。带缓冲的chan能够提高性能。(这里其实是假设所有的 goroutine 是在一个线程内部了,被分配到一个核上执行)

ps: goroutine 是否能够充分利用多核CPU,把打印日志的 goroutine 单独放到另一个核中?这样的话就不存在阻塞问题了,性能会很好。

### 思考2

单独启动一个 goroutine 负责日志后端打印的话,存在一个问题:当主程序执行完一条打印日志命令后很快结束程序的时候,所有 goroutine 都会被杀死,但是这时候可能日志还没打印完毕,会有丢失日志的情况出现。我们需要一个同步的操作来等待日志打印完毕再结束进程。
Binary file added bin/main
Binary file not shown.
2 changes: 1 addition & 1 deletion example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
func main() {
log.Info("yes I can call it directly")

logr := log.NewLogger(backend.Stderr()).WithName("test").WithFields("key", "value")
logr := log.NewLogger(backend.Stderr()).WithName("test").WithValues("key", "value")

logr.V(1).Info("msg", "uint", 112, "int", 211, "nil", nil)
var typedNil *int
Expand Down
4 changes: 2 additions & 2 deletions frontend/logr.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import (
"runtime/debug"
"time"

"github.com/go-coder/logr"
"github.com/go-coder/log/types"
"github.com/go-logr/logr"
"github.com/spf13/pflag"
)

Expand Down Expand Up @@ -75,7 +75,7 @@ func (l *rlog) WithName(name string) logr.Logger {
return out
}

func (l *rlog) WithFields(kvList ...interface{}) logr.Logger {
func (l *rlog) WithValues(kvList ...interface{}) logr.Logger {
out := l.clone()
out.fields = append(out.fields, kvList...)
return out
Expand Down
9 changes: 9 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module github.com/go-coder/log

go 1.12

require (
github.com/go-coder/logr v0.1.0
github.com/go-logr/logr v0.1.0
github.com/spf13/pflag v1.0.3
)
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
github.com/go-coder/logr v0.1.0 h1:cKKbRhVJXz38rq0AG/QVIM6Atx14po8nL8It6wgi7+w=
github.com/go-coder/logr v0.1.0/go.mod h1:Wb42XhUxL//12vqkxbdiqPP04fqnODPsXhd87jSiKqw=
github.com/go-logr/logr v0.1.0 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
4 changes: 2 additions & 2 deletions logr.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package log
import (
"github.com/go-coder/log/backend"
"github.com/go-coder/log/frontend"
"github.com/go-coder/logr"
"github.com/go-logr/logr"
)

var (
Expand All @@ -13,7 +13,7 @@ var (

V = syslog.V
WithName = syslog.WithName
WithFields = syslog.WithFields
WithValues = syslog.WithValues
Info = syslog.Info
Error = syslog.Error
)
18 changes: 18 additions & 0 deletions scripts/go-build
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash

# Use the Unofficial Bash Strict Mode (Unless You Looove Debugging) | Aaron Maxwell
# http://redsymbol.net/articles/unofficial-bash-strict-mode/
set -euo pipefail
IFS=$'\n\t'

main() {
echo " > formating file ..."
for dir in . ./types ./frontend ./backend ./example; do
go fmt $dir/...
golangci-lint run $dir/...
done
echo " > building file ..."
go build -o ./bin/main ./example/main.go
}

main ${@:-}

0 comments on commit 3312f28

Please sign in to comment.