mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 23:16:45 +00:00
* log: fix bugs expand coverage and optimise * log: fix linter issues * log: fix linter issue and pack methods in same file * log: drop defer * logger: move global check inside getfields and remove unused test function * logger: Increase note thanks @gloriouscode * logger: wrap error with writer type * logger: change variable name * logger: change variable names and remove validsublogger func as it doesn't add functionality over a standard map call * logs: error when unsupported output is applied on setup calls * logs: add glorious suggestion * logger: add protection to reduce olympic gold medal races * logger: fix linter issues * log: glorious niterinos
92 lines
2.0 KiB
Go
92 lines
2.0 KiB
Go
package log
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
var (
|
|
errWriterAlreadyLoaded = errors.New("io.Writer already loaded")
|
|
errWriterNotFound = errors.New("io.Writer not found")
|
|
)
|
|
|
|
// Add appends a new writer to the multiwriter slice
|
|
func (mw *multiWriter) Add(writer io.Writer) error {
|
|
mw.mu.Lock()
|
|
defer mw.mu.Unlock()
|
|
for i := range mw.writers {
|
|
if mw.writers[i] == writer {
|
|
return errWriterAlreadyLoaded
|
|
}
|
|
}
|
|
mw.writers = append(mw.writers, writer)
|
|
return nil
|
|
}
|
|
|
|
// Remove removes existing writer from multiwriter slice
|
|
func (mw *multiWriter) Remove(writer io.Writer) error {
|
|
mw.mu.Lock()
|
|
defer mw.mu.Unlock()
|
|
for i := range mw.writers {
|
|
if mw.writers[i] != writer {
|
|
continue
|
|
}
|
|
mw.writers[i] = mw.writers[len(mw.writers)-1]
|
|
mw.writers[len(mw.writers)-1] = nil
|
|
mw.writers = mw.writers[:len(mw.writers)-1]
|
|
return nil
|
|
}
|
|
return errWriterNotFound
|
|
}
|
|
|
|
// Write concurrent safe Write for each writer
|
|
func (mw *multiWriter) Write(p []byte) (int, error) {
|
|
type data struct {
|
|
n int
|
|
err error
|
|
}
|
|
|
|
results := make(chan data, len(mw.writers))
|
|
mw.mu.RLock()
|
|
defer mw.mu.RUnlock()
|
|
for x := range mw.writers {
|
|
go func(w io.Writer, p []byte, ch chan<- data) {
|
|
n, err := w.Write(p)
|
|
if err != nil {
|
|
ch <- data{n, fmt.Errorf("%T %w", w, err)}
|
|
return
|
|
}
|
|
if n != len(p) {
|
|
ch <- data{n, fmt.Errorf("%T %w", w, io.ErrShortWrite)}
|
|
return
|
|
}
|
|
ch <- data{n, nil}
|
|
}(mw.writers[x], p, results)
|
|
}
|
|
|
|
for range mw.writers {
|
|
// NOTE: These results do not necessarily reflect the current io.writer
|
|
// due to the go scheduler and writer finishing at different times, the
|
|
// response coming from the channel might not match up with the for loop
|
|
// writer.
|
|
d := <-results
|
|
if d.err != nil {
|
|
return d.n, d.err
|
|
}
|
|
}
|
|
return len(p), nil
|
|
}
|
|
|
|
// MultiWriter make and return a new copy of multiWriter
|
|
func MultiWriter(writers ...io.Writer) (*multiWriter, error) {
|
|
mw := &multiWriter{}
|
|
for x := range writers {
|
|
err := mw.Add(writers[x])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return mw, nil
|
|
}
|