-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor DefaultSinks() into RegisterSink
Akin to RegisterEncoder
- Loading branch information
Showing
5 changed files
with
134 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package zap | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"io" | ||
"os" | ||
"sync" | ||
|
||
"go.uber.org/zap/zapcore" | ||
) | ||
|
||
var ( | ||
_sinkMutex sync.RWMutex | ||
errSinkNotFound = errors.New("sink for the given key not found") | ||
_sinkFactories = map[string]func() (Sink, error){ | ||
"stdout": func() (Sink, error) { return NopCloserSink{os.Stdout}, nil }, | ||
"stderr": func() (Sink, error) { return NopCloserSink{os.Stderr}, nil }, | ||
} | ||
) | ||
|
||
// Sink defines the interface to write to and close logger destinations. | ||
type Sink interface { | ||
zapcore.WriteSyncer | ||
io.Closer | ||
} | ||
|
||
// RegisterSink adds a Sink at the given key so it can be referenced | ||
// in config OutputPaths. | ||
func RegisterSink(key string, sinkFactory func() (Sink, error)) error { | ||
_sinkMutex.Lock() | ||
defer _sinkMutex.Unlock() | ||
if key == "" { | ||
return errors.New("sink key cannot be blank") | ||
} | ||
if _, ok := _sinkFactories[key]; ok { | ||
return fmt.Errorf("sink already registered for key %q", key) | ||
} | ||
_sinkFactories[key] = sinkFactory | ||
return nil | ||
} | ||
|
||
// newSink invokes the registered sink factory to create and return the | ||
// sink for the given key. Returns errSinkNotFound if the key cannot be found. | ||
func newSink(key string) (Sink, error) { | ||
_sinkMutex.RLock() | ||
defer _sinkMutex.RUnlock() | ||
sinkFactory, ok := _sinkFactories[key] | ||
if !ok { | ||
return nil, errSinkNotFound | ||
} | ||
return sinkFactory() | ||
} | ||
|
||
// NopCloserSink wraps a WriteSyncer with a no-op Close() method. | ||
type NopCloserSink struct{ zapcore.WriteSyncer } | ||
|
||
// Close does nothing (no-op). | ||
func (NopCloserSink) Close() error { return nil } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package zap | ||
|
||
import ( | ||
"errors" | ||
"os" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestRegisterSink(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
key string | ||
factory func() (Sink, error) | ||
wantError bool | ||
}{ | ||
{"valid", "valid", func() (Sink, error) { return NopCloserSink{os.Stdout}, nil }, false}, | ||
{"empty", "", func() (Sink, error) { return NopCloserSink{os.Stdout}, nil }, true}, | ||
{"stdout", "stdout", func() (Sink, error) { return NopCloserSink{os.Stdout}, nil }, true}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
err := RegisterSink(tt.key, tt.factory) | ||
if tt.wantError { | ||
assert.NotNil(t, err) | ||
} else { | ||
assert.Nil(t, err) | ||
assert.NotNil(t, _sinkFactories[tt.key], "expected the factory to be present") | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestNewSink(t *testing.T) { | ||
errTestSink := errors.New("test erroring") | ||
err := RegisterSink("errors", func() (Sink, error) { return nil, errTestSink }) | ||
assert.Nil(t, err) | ||
tests := []struct { | ||
key string | ||
err error | ||
}{ | ||
{"stdout", nil}, | ||
{"errors", errTestSink}, | ||
{"nonexistent", errSinkNotFound}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.key, func(t *testing.T) { | ||
_, err := newSink(tt.key) | ||
assert.Equal(t, tt.err, err) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters