diff --git a/formatters/json.go b/formatters/json.go index e79acab..0edfda3 100644 --- a/formatters/json.go +++ b/formatters/json.go @@ -10,6 +10,8 @@ import ( "github.com/spf13/viper" ) +const FormatJSON string = "json" + func newJson(ff *viper.Viper) (Formatter, error) { js := new(Json) err := ff.Unmarshal(js) @@ -24,7 +26,7 @@ type Json struct { } func (js *Json) Name() string { - return "json" + return FormatJSON } func (js *Json) marshal(v any) (o []byte, err error) { diff --git a/formatters/new.go b/formatters/new.go index ff9610d..bd063fa 100644 --- a/formatters/new.go +++ b/formatters/new.go @@ -2,18 +2,22 @@ package formatters import ( "context" + "errors" "fmt" + "sync" "codeberg.org/danjones000/my-log/config" "github.com/spf13/viper" ) -type formatMaker func(config *viper.Viper) (Formatter, error) +var mut sync.RWMutex -var formatterMap = map[string]formatMaker{ - "plain": newPlain, - "json": newJson, - "zero": newNull, +type FormatInit func(config *viper.Viper) (Formatter, error) + +var formatterMap = map[string]FormatInit{ + FormatPlain: newPlain, + FormatJSON: newJson, + FormatNull: newNull, } func Preferred(ctx context.Context) (f Formatter, err error) { @@ -25,6 +29,8 @@ func New(ctx context.Context, kind string) (f Formatter, err error) { v, _ := config.RetrieveFromContext(ctx) formatterConf := v.Sub("formatters." + kind) + mut.RLock() + defer mut.RUnlock() if maker, ok := formatterMap[kind]; ok { return maker(formatterConf) } @@ -34,8 +40,24 @@ func New(ctx context.Context, kind string) (f Formatter, err error) { func Kinds() []string { r := []string{} + + mut.RLock() + defer mut.RUnlock() for kind, _ := range formatterMap { r = append(r, kind) } return r } + +var ErrAlreadyAdded = errors.New("formatter already present") + +func AddFormatter(key string, f FormatInit) error { + mut.Lock() + defer mut.Unlock() + if _, present := formatterMap[key]; present { + return fmt.Errorf("%w: %s", ErrAlreadyAdded, key) + } + + formatterMap[key] = f + return nil +} diff --git a/formatters/new_test.go b/formatters/new_test.go index d680709..df51a0a 100644 --- a/formatters/new_test.go +++ b/formatters/new_test.go @@ -39,3 +39,17 @@ func TestPreferred(t *testing.T) { be.Err(t, err, nil) be.True(t, form != nil) } + +type dummyFormatter struct{ Null } + +func (dummyFormatter) Name() string { return "dummy" } + +func TestAddFormatter(t *testing.T) { + var df dummyFormatter + dummyInit := func(*viper.Viper) (Formatter, error) { return df, nil } + err := AddFormatter(df.Name(), dummyInit) + be.Err(t, err, nil) + + err = AddFormatter(df.Name(), dummyInit) + be.Err(t, err, ErrAlreadyAdded) +} diff --git a/formatters/null.go b/formatters/null.go index f83cbde..8851e04 100644 --- a/formatters/null.go +++ b/formatters/null.go @@ -5,28 +5,19 @@ import ( "github.com/spf13/viper" ) -func newNull(ff *viper.Viper) (Formatter, error) { - return &Null{}, nil +const FormatNull = "zero" + +func newNull(*viper.Viper) (Formatter, error) { + return Null{}, nil } type Null struct{} -func (n *Null) Name() string { - return "zero" +func (Null) Name() string { + return FormatNull } -func (n *Null) Meta(m models.Meta) (o []byte, err error) { - return -} - -func (n *Null) Entry(e models.Entry) (o []byte, err error) { - return -} - -func (n *Null) Log(l models.Log) (o []byte, err error) { - return -} - -func (n *Null) Logs(logs []models.Log) (out []byte, err error) { - return -} +func (Null) Meta(m models.Meta) (o []byte, err error) { return } +func (Null) Entry(e models.Entry) (o []byte, err error) { return } +func (Null) Log(l models.Log) (o []byte, err error) { return } +func (Null) Logs(logs []models.Log) (out []byte, err error) { return } diff --git a/formatters/plain.go b/formatters/plain.go index 0a94f81..6bf5c4f 100644 --- a/formatters/plain.go +++ b/formatters/plain.go @@ -8,16 +8,16 @@ import ( "github.com/spf13/viper" ) -func newPlain(ff *viper.Viper) (Formatter, error) { +const FormatPlain string = "plain" + +func newPlain(*viper.Viper) (Formatter, error) { return &PlainText{}, nil } -type PlainText struct { - // config might go here some day -} +type PlainText struct{} -func (pt *PlainText) Name() string { - return "plain" +func (*PlainText) Name() string { + return FormatPlain } func (pt *PlainText) Logs(logs []models.Log) (out []byte, err error) {