Skip to content

Commit

Permalink
sink writes now execute inside mutex lock
Browse files Browse the repository at this point in the history
To prevent thread safety issues the sink writers will execute the write function inside a mutex.  Sinks that access shared resources can now be treated as thread safe.
  • Loading branch information
ewilliams0305 committed Nov 6, 2023
1 parent 36ef943 commit f1d3dcf
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 32 deletions.
5 changes: 4 additions & 1 deletion logger/builder.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package golog

import "sync"

// The entry point for the [golog] logging framework.
// The [LoggingConfiguration] functions starts the golog configuration builder by returning a [loggerConfiguration]
// interface. The logging configuration proceeds the consumer to the next step configuring an log level and format template.
Expand Down Expand Up @@ -60,7 +62,8 @@ func (gl *goLog) Configure(minimuLevel LogLevel, template string) loggerWriter {
func (gl *goLog) WriteTo(sink SinkWriter) createWriters {

writer := &loggingSink{
sink: &sink,
sink: &sink,
mutex: sync.Mutex{},
config: configuration{
level: gl.config.level,
format: gl.config.format,
Expand Down
49 changes: 18 additions & 31 deletions logger/golog.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ type goLog struct {
type loggingSink struct {
sink *SinkWriter
config configuration
mutex sync.Mutex
}

// The logger is NOT responsible for writing messages to sinks.
Expand Down Expand Up @@ -117,44 +118,30 @@ func (gl *goLog) Fatal(message string, err error, args ...interface{}) {
gl.write(message, Fatal, err, args...)
}

func (gl *goLog) write(message string, level LogLevel, err error, args ...interface{}) {
var wg sync.WaitGroup

resultChan := make(chan string, len(gl.sinks))
var wg sync.WaitGroup
func (gl *goLog) write(message string, level LogLevel, err error, args ...interface{}) {

for _, s := range gl.sinks {
if s.config.level <= level {

wg.Add(1)

go func(sink *SinkWriter) {
writeSink(*sink, LogEvent{
Timestamp: time.Now(),
Level: level,
Message: message,
Error: err,
Args: args,
}, resultChan)
defer wg.Done()
}(s.sink)
go writeSink(s, LogEvent{
Timestamp: time.Now(),
Level: level,
Message: message,
Error: err,
Args: args,
})
}
}

go func() {
wg.Wait()
close(resultChan)
}()

for range resultChan {
}
wg.Wait()
}

func writeSink(s SinkWriter, e LogEvent, c chan string) {

err := s.WriteTo(e)
if err != nil {
c <- "Error: " + err.Error()
} else {
c <- "Success"
}
func writeSink(s *loggingSink, e LogEvent) error {
s.mutex.Lock()
sink := *s.sink
err := sink.WriteTo(e)
s.mutex.Unlock()
wg.Done()
return err
}

0 comments on commit f1d3dcf

Please sign in to comment.