Skip to content

Commit

Permalink
Fix the data race in the formatter and content packages (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
mstmdev authored Jun 27, 2023
1 parent c702c1c commit 8a9fae7
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 2 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v0.2.1
v0.2.2
10 changes: 9 additions & 1 deletion content/time.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package content

import "time"
import (
"sync"
"time"
)

var (
defaultLogTimeFormat = "2006-01-02 15:04:05"
mu sync.RWMutex
)

// Time the custom Time for log
Expand All @@ -15,12 +19,16 @@ type Time struct {
// InitDefaultLogTimeFormat init the global default log time format
func InitDefaultLogTimeFormat(f string) {
if len(f) > 0 {
mu.Lock()
defaultLogTimeFormat = f
mu.Unlock()
}
}

// DefaultLogTimeFormat return the default log time format
func DefaultLogTimeFormat() string {
mu.RLock()
defer mu.RUnlock()
return defaultLogTimeFormat
}

Expand Down
18 changes: 18 additions & 0 deletions content/time_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package content

import (
"sync"
"testing"
"time"
)
Expand Down Expand Up @@ -34,5 +35,22 @@ func TestTime_MarshalText(t *testing.T) {
t.Errorf("test Time.MarshalText failed, expect to get %s, but actual get %s", expect, actual)
}
}
}

func TestInitDefaultLogTimeFormat_Concurrency(t *testing.T) {
c := 10
wg := sync.WaitGroup{}
wg.Add(c * 2)
for i := 0; i < c; i++ {
go func() {
InitDefaultLogTimeFormat(time.RFC3339)
wg.Done()
}()

go func() {
NewTime(time.Now())
wg.Done()
}()
}
wg.Wait()
}
6 changes: 6 additions & 0 deletions formatter/formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package formatter

import (
"strings"
"sync"

"github.com/no-src/log/content"
)
Expand All @@ -16,10 +17,13 @@ var (
formatters = make(map[string]Formatter)
defaultFormatterType = TextFormatter
defaultTerminator = "\n"
mu sync.RWMutex
)

// Default return the global default Formatter
func Default() Formatter {
mu.RLock()
defer mu.RUnlock()
return New(defaultFormatterType)
}

Expand All @@ -37,7 +41,9 @@ func NewTextFormatter() Formatter {
func InitDefaultFormatter(t string) {
_, ok := formatters[t]
if ok {
mu.Lock()
defaultFormatterType = t
mu.Unlock()
}
}

Expand Down
69 changes: 69 additions & 0 deletions formatter/formatter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package formatter_test

import (
"sync"
"testing"
"time"

"github.com/no-src/log/content"
"github.com/no-src/log/formatter"
_ "github.com/no-src/log/formatter/json"
_ "github.com/no-src/log/formatter/text"
"github.com/no-src/log/level"
)

func TestInitDefaultFormatter_Concurrency(t *testing.T) {
c := 10
wg := sync.WaitGroup{}
wg.Add(c * 2)
for i := 0; i < c; i++ {
go func() {
formatter.InitDefaultFormatter(formatter.JsonFormatter)
wg.Done()
}()

go func() {
formatter.Default()
wg.Done()
}()
}
wg.Wait()
}

func TestNewJsonFormatter(t *testing.T) {
f := formatter.NewJsonFormatter()
data, err := f.Serialize(content.NewContent(level.DebugLevel, nil, false, time.RFC3339, "json formatter"))
if err != nil {
t.Errorf("test json formatter error => %v", err)
return
}
expect := `{"level":"DEBUG","log":"json formatter"}` + "\n"
actual := string(data)
if expect != actual {
t.Errorf("test json formatter failed, expect to get %s, but actual get %s", expect, actual)
return
}
}

func TestNewTextFormatter(t *testing.T) {
testNewTextFormatter(t, formatter.NewTextFormatter())
}

func testNewTextFormatter(t *testing.T, f formatter.Formatter) {
data, err := f.Serialize(content.NewContent(level.DebugLevel, nil, false, time.RFC3339, "text formatter"))
if err != nil {
t.Errorf("test text formatter error => %v", err)
return
}
expect := `[DEBUG] text formatter` + "\n"
actual := string(data)
if expect != actual {
t.Errorf("test text formatter failed, expect to get %s, but actual get %s", expect, actual)
return
}
}

func TestNew_Unsupported(t *testing.T) {
formatter.InitDefaultFormatter(formatter.TextFormatter)
testNewTextFormatter(t, formatter.New("unsupported"))
}

0 comments on commit 8a9fae7

Please sign in to comment.