Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #1272 #1273

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 4 additions & 8 deletions entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,18 +269,14 @@ func (entry *Entry) getBufferPool() (pool BufferPool) {
}

func (entry *Entry) fireHooks() {
var tmpHooks LevelHooks
//Replication can indeed improve performance, but it will lead to this instant.
//If a new hook is added, the hook may not be triggered
entry.Logger.mu.Lock()
tmpHooks = make(LevelHooks, len(entry.Logger.Hooks))
for k, v := range entry.Logger.Hooks {
tmpHooks[k] = v
}
entry.Logger.mu.Unlock()

err := tmpHooks.Fire(entry.Level, entry)
err := entry.Logger.Hooks.Fire(entry.Level, entry)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
}
entry.Logger.mu.Unlock()
}

func (entry *Entry) write() {
Expand Down
18 changes: 18 additions & 0 deletions logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,24 @@ func (logger *Logger) ReplaceHooks(hooks LevelHooks) LevelHooks {
return oldHooks
}

// ReplaceHook replaces the logger hook and returns hook exists or not
func (logger *Logger) ReplaceHook(hook Hook) bool {
logger.mu.Lock()
oldHooks := logger.Hooks
hasReplaced := false
for _, level := range hook.Levels() {
for index, h := range oldHooks[level] {
if h == hook {
oldHooks[level] = append(oldHooks[level][:index], oldHooks[level][index+1:]...)
hasReplaced = true
break
}
}
}
logger.mu.Unlock()
return hasReplaced
}

// SetBufferPool sets the logger buffer pool.
func (logger *Logger) SetBufferPool(pool BufferPool) {
logger.mu.Lock()
Expand Down
103 changes: 102 additions & 1 deletion logger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@ package logrus

import (
"bytes"
"context"
"encoding/json"
"fmt"
"path/filepath"
"runtime"
"strconv"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -70,7 +75,7 @@ func TestWarninglnNotEqualToWarning(t *testing.T) {

type testBufferPool struct {
buffers []*bytes.Buffer
get int
get int
}

func (p *testBufferPool) Get() *bytes.Buffer {
Expand All @@ -95,3 +100,99 @@ func TestLogger_SetBufferPool(t *testing.T) {
assert.Equal(t, pool.get, 1, "Logger.SetBufferPool(): The BufferPool.Get() must be called")
assert.Len(t, pool.buffers, 1, "Logger.SetBufferPool(): The BufferPool.Put() must be called")
}

func TestLogger_concurrentLock(t *testing.T) {
SetFormatter(&LogFormatter{})
go func() {
for {
func() {
defer func() {
if p := recover(); p != nil {
}
}()
hook := AddTraceIdHook("123")
defer RemoveTraceHook(hook)
Infof("test why ")
}()
}
}()
go func() {
for {
func() {
defer func() {
if p := recover(); p != nil {
}
}()
hook := AddTraceIdHook("1233")
defer RemoveTraceHook(hook)
Infof("test why 2")
}()
}
}()
time.Sleep(5 * time.Second)
}

func AddTraceIdHook(traceId string) Hook {
traceHook := newTraceIdHook(traceId)
if StandardLogger().Hooks == nil {
hooks := new(LevelHooks)
StandardLogger().ReplaceHooks(*hooks)
}
AddHook(traceHook)
return traceHook
}

func RemoveTraceHook(hook Hook) {
StandardLogger().ReplaceHook(hook)
}

type TraceIdHook struct {
TraceId string
GID uint64
}

func newTraceIdHook(traceId string) Hook {
return &TraceIdHook{
TraceId: traceId,
GID: getGID(),
}
}

func (t TraceIdHook) Levels() []Level {
return AllLevels
}

func (t TraceIdHook) Fire(entry *Entry) error {
if getGID() == t.GID {
entry.Context = context.WithValue(context.Background(), "trace_id", t.TraceId)
}
return nil
}

type LogFormatter struct{}

func (s *LogFormatter) Format(entry *Entry) ([]byte, error) {
timestamp := time.Now().Format("2006-01-02 15:04:05")
var file string
var line int
if entry.Caller != nil {
file = filepath.Base(entry.Caller.File)
line = entry.Caller.Line
}
level := entry.Level.String()
if entry.Context == nil || entry.Context.Value("trace_id") == "" {
uuid := "NO UUID"
entry.Context = context.WithValue(context.Background(), "trace_id", uuid)
}
msg := fmt.Sprintf("%-15s [%-3d] [%-5s] [%s] %s:%d %s\n", timestamp, getGID(), level, entry.Context.Value("trace_id"), file, line, entry.Message)
return []byte(msg), nil
}

func getGID() uint64 {
b := make([]byte, 64)
b = b[:runtime.Stack(b, false)]
b = bytes.TrimPrefix(b, []byte("goroutine "))
b = b[:bytes.IndexByte(b, ' ')]
n, _ := strconv.ParseUint(string(b), 10, 64)
return n
}