Skip to content

Commit

Permalink
make logger configurable (#85)
Browse files Browse the repository at this point in the history
  • Loading branch information
ktong authored Feb 2, 2024
1 parent e5fbde2 commit 353e667
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 19 deletions.
19 changes: 12 additions & 7 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ import (
//
// To create a new Config, call [New].
type Config struct {
logger *slog.Logger
decodeHook mapstructure.DecodeHookFunc
delimiter string
tagName string
delimiter string

values map[string]any
providers []*provider
Expand All @@ -48,6 +49,10 @@ func New(opts ...Option) *Config {
for _, opt := range opts {
opt(option)
}
if option.logger == nil {
option.logger = slog.Default()
}
option.logger = option.logger.WithGroup("konf")
if option.delimiter == "" {
option.delimiter = "."
}
Expand Down Expand Up @@ -110,7 +115,7 @@ func (c *Config) Watch(ctx context.Context) error { //nolint:cyclop,funlen,gocog
watched = false
})
if watched {
slog.Warn("Config has been watched, call Watch again has no effects.")
c.logger.Warn("Config has been watched, call Watch again has no effects.")

return nil
}
Expand All @@ -133,7 +138,7 @@ func (c *Config) Watch(ctx context.Context) error { //nolint:cyclop,funlen,gocog
maps.Merge(values, w.values)
}
c.values = values
slog.DebugContext(ctx, "Configuration has been updated with change.")
c.logger.DebugContext(ctx, "Configuration has been updated with change.")

if len(onChanges) > 0 {
func() {
Expand All @@ -151,10 +156,10 @@ func (c *Config) Watch(ctx context.Context) error { //nolint:cyclop,funlen,gocog

select {
case <-done:
slog.DebugContext(ctx, "Configuration has been applied to onChanges.")
c.logger.DebugContext(ctx, "Configuration has been applied to onChanges.")
case <-ctx.Done():
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
slog.WarnContext(ctx, "Configuration has not been fully applied to onChanges due to timeout."+
c.logger.WarnContext(ctx, "Configuration has not been fully applied to onChanges due to timeout."+
" Please check if the onChanges is blocking or takes too long to complete.")
}
}
Expand Down Expand Up @@ -201,13 +206,13 @@ func (c *Config) Watch(ctx context.Context) error { //nolint:cyclop,funlen,gocog
}
onChangesChannel <- onChanges()

slog.Info(
c.logger.Info(
"Configuration has been changed.",
"loader", watcher,
)
}

slog.DebugContext(ctx, "Watching configuration change.", "loader", watcher)
c.logger.DebugContext(ctx, "Watching configuration change.", "loader", watcher)
if err := watcher.Watch(ctx, onChange); err != nil {
errChan <- fmt.Errorf("watch configuration change: %w", err)
cancel()
Expand Down
3 changes: 1 addition & 2 deletions default.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
package konf

import (
"log/slog"
"reflect"
"sync/atomic"

Expand All @@ -17,7 +16,7 @@ import (
func Get[T any](path string) T { //nolint:ireturn
var value T
if err := Unmarshal(path, &value); err != nil {
slog.Warn(
Default().logger.Warn(
"Could not read config, return empty value instead.",
"error", err,
"path", path,
Expand Down
4 changes: 2 additions & 2 deletions default_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func TestGet_error(t *testing.T) {

assert.True(t, !konf.Get[bool]("config"))
expected := "WARN Could not read config, return empty value instead." +
" error=\"decode: cannot parse '' as bool: strconv.ParseBool: parsing \\\"string\\\": invalid syntax\"" +
" path=config type=bool\n"
" konf.error=\"decode: cannot parse '' as bool: strconv.ParseBool: parsing \\\"string\\\": invalid syntax\"" +
" konf.path=config konf.type=bool\n"
assert.Equal(t, expected, buf.String())
}
15 changes: 14 additions & 1 deletion option.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@

package konf

import "github.com/go-viper/mapstructure/v2"
import (
"log/slog"

"github.com/go-viper/mapstructure/v2"
)

// WithDelimiter provides the delimiter used when specifying config paths.
// The delimiter is used to separate keys in the path.
Expand Down Expand Up @@ -36,6 +40,15 @@ func WithDecodeHook(decodeHook mapstructure.DecodeHookFunc) Option {
}
}

// WithLogger provides the slog.Logger for Config.
//
// By default, it uses slog.Default().
func WithLogger(logger *slog.Logger) Option {
return func(options *options) {
options.logger = logger
}
}

type (
// Option configures a Config with specific options.
Option func(*options)
Expand Down
7 changes: 6 additions & 1 deletion provider/file/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
//
// To create a new File, call [New].
type File struct {
logger *slog.Logger
path string
unmarshal func([]byte, any) error
ignoreNotExist bool
Expand All @@ -43,6 +44,10 @@ func New(path string, opts ...Option) File {
for _, opt := range opts {
opt(option)
}
if option.logger == nil {
option.logger = slog.Default()
}
option.logger = option.logger.WithGroup("konf.file")
if option.unmarshal == nil {
option.unmarshal = json.Unmarshal
}
Expand All @@ -54,7 +59,7 @@ func (f File) Load() (map[string]any, error) {
bytes, err := os.ReadFile(f.path)
if err != nil {
if f.ignoreNotExist && os.IsNotExist(err) {
slog.Warn("Config file does not exist.", "file", f.path)
f.logger.Warn("Config file does not exist.", "file", f.path)

return make(map[string]any), nil
}
Expand Down
11 changes: 11 additions & 0 deletions provider/file/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

package file

import "log/slog"

// WithUnmarshal provides the function used to parses the configuration file.
// The unmarshal function must be able to unmarshal the file content into a map[string]any.
//
Expand All @@ -20,6 +22,15 @@ func IgnoreFileNotExit() Option {
}
}

// WithLogger provides the slog.Logger for File loader.
//
// By default, it uses slog.Default().
func WithLogger(logger *slog.Logger) Option {
return func(options *options) {
options.logger = logger
}
}

type (
// Option configures the a File with specific options.
Option func(options *options)
Expand Down
9 changes: 4 additions & 5 deletions provider/file/watch.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package file
import (
"context"
"fmt"
"log/slog"
"path/filepath"
"time"

Expand All @@ -21,7 +20,7 @@ func (f File) Watch(ctx context.Context, onChange func(map[string]any)) error {
}
defer func() {
if err := watcher.Close(); err != nil {
slog.WarnContext(ctx, "Error when closing file watcher.", "file", f.path, "error", err)
f.logger.WarnContext(ctx, "Error when closing file watcher.", "file", f.path, "error", err)
}
}()

Expand Down Expand Up @@ -68,12 +67,12 @@ func (f File) Watch(ctx context.Context, onChange func(map[string]any)) error {

switch {
case event.Has(fsnotify.Remove):
slog.Warn("Config file has been removed.", "file", f.path)
f.logger.Warn("Config file has been removed.", "file", f.path)
onChange(nil)
case event.Has(fsnotify.Create) || event.Has(fsnotify.Write):
values, err := f.Load()
if err != nil {
slog.WarnContext(ctx, "Error when reloading config file", "file", f.path, "error", err)
f.logger.WarnContext(ctx, "Error when reloading config file", "file", f.path, "error", err)

continue
}
Expand All @@ -85,7 +84,7 @@ func (f File) Watch(ctx context.Context, onChange func(map[string]any)) error {
return nil
}

slog.WarnContext(ctx, "Error when watching file", "file", f.path, "error", err)
f.logger.WarnContext(ctx, "Error when watching file", "file", f.path, "error", err)

case <-ctx.Done():
return nil
Expand Down
7 changes: 6 additions & 1 deletion provider/fs/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
//
// To create a new FS, call [New].
type FS struct {
logger *slog.Logger
unmarshal func([]byte, any) error
fs fs.FS
path string
Expand All @@ -49,6 +50,10 @@ func New(fs fs.FS, path string, opts ...Option) FS { //nolint:varnamelen
for _, opt := range opts {
opt(option)
}
if option.logger == nil {
option.logger = slog.Default()
}
option.logger = option.logger.WithGroup("konf.fs")
if option.unmarshal == nil {
option.unmarshal = json.Unmarshal
}
Expand All @@ -60,7 +65,7 @@ func (f FS) Load() (map[string]any, error) {
bytes, err := fs.ReadFile(f.fs, f.path)
if err != nil {
if f.ignoreNotExist && os.IsNotExist(err) {
slog.Warn("Config file does not exist.", "file", f.path)
f.logger.Warn("Config file does not exist.", "file", f.path)

return make(map[string]any), nil
}
Expand Down
11 changes: 11 additions & 0 deletions provider/fs/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

package fs

import "log/slog"

// WithUnmarshal provides the function used to parses the configuration file.
// The unmarshal function must be able to unmarshal the file content into a map[string]any.
//
Expand All @@ -20,6 +22,15 @@ func IgnoreFileNotExit() Option {
}
}

// WithLogger provides the slog.Logger for FS loader.
//
// By default, it uses slog.Default().
func WithLogger(logger *slog.Logger) Option {
return func(options *options) {
options.logger = logger
}
}

type (
// Option configures the a FS with specific options.
Option func(file *options)
Expand Down

0 comments on commit 353e667

Please sign in to comment.