Skip to content

Commit 067d35e

Browse files
author
Russ Egan
committed
Use HandlerFn type instead of func signature
Improves readability
1 parent dce65a3 commit 067d35e

File tree

4 files changed

+81
-51
lines changed

4 files changed

+81
-51
lines changed

v2/config_from_env.go

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ func MustConfigFromEnv(envvars ...string) {
6666
func UnmarshalEnv(o *HandlerOptions, envvars ...string) error {
6767
for _, v := range envvars {
6868
if configString := os.Getenv(v); configString != "" {
69+
// todo: need to add a branch here to handle when the environment variable is
70+
// set to a raw levels string, and isn't JSON
6971
err := json.Unmarshal([]byte(configString), o)
7072
if err != nil {
7173
return fmt.Errorf("parsing configuration from environment variable %v: %w", v, err)
@@ -85,15 +87,21 @@ func resetBuiltInHandlerFns() {
8587
textHandlerFn := func(_ string, w io.Writer, opts *slog.HandlerOptions) slog.Handler {
8688
return slog.NewTextHandler(w, opts)
8789
}
88-
handlerFns.Store(TextHandler, textHandlerFn)
90+
registerHandlerFn(TextHandler, textHandlerFn)
8991
// for v1 compatibility, "console" is an alias for "text"
90-
handlerFns.Store(ConsoleHandler, textHandlerFn)
91-
handlerFns.Store(JSONHandler, func(_ string, w io.Writer, opts *slog.HandlerOptions) slog.Handler {
92+
registerHandlerFn(ConsoleHandler, textHandlerFn)
93+
registerHandlerFn(JSONHandler, func(_ string, w io.Writer, opts *slog.HandlerOptions) slog.Handler {
9294
return slog.NewJSONHandler(w, opts)
9395
})
94-
handlerFns.Store(TermHandler, termHandlerFn(false))
95-
handlerFns.Store(TermColorHandler, termHandlerFn(true))
96-
handlerFns.Store(NoopHandler, func(_ string, _ io.Writer, _ *slog.HandlerOptions) slog.Handler {
96+
registerHandlerFn(TermHandler, func(_ string, w io.Writer, opts *slog.HandlerOptions) slog.Handler {
97+
termOpts := termHandlerOptions(opts)
98+
termOpts.NoColor = true
99+
return console.NewHandler(w, termOpts)
100+
})
101+
registerHandlerFn(TermColorHandler, func(_ string, w io.Writer, opts *slog.HandlerOptions) slog.Handler {
102+
return console.NewHandler(w, termHandlerOptions(opts))
103+
})
104+
registerHandlerFn(NoopHandler, func(_ string, _ io.Writer, _ *slog.HandlerOptions) slog.Handler {
97105
return noop
98106
})
99107
}
@@ -104,17 +112,23 @@ func initHandlerFns() {
104112
})
105113
}
106114

107-
func LookupHandlerFn(name string) func(string, io.Writer, *slog.HandlerOptions) slog.Handler {
115+
func LookupHandlerFn(name string) HandlerFn {
108116
initHandlerFns()
109117
v, ok := handlerFns.Load(name)
110118
if !ok {
111119
return nil
112120
}
113-
return v.(func(string, io.Writer, *slog.HandlerOptions) slog.Handler) //nolint:forcetypeassert // if it's not a HandlerFn, we should panic
121+
// fn := v.(func(string, io.Writer, *slog.HandlerOptions) slog.Handler) //nolint:forcetypeassert // if it's not a HandlerFn, we should panic
122+
fn := v.(HandlerFn) //nolint:forcetypeassert // if it's not a HandlerFn, we should panic
123+
return fn
114124
}
115125

116-
func RegisterHandlerFn(name string, fn func(string, io.Writer, *slog.HandlerOptions) slog.Handler) {
126+
func RegisterHandlerFn(name string, fn HandlerFn) {
117127
initHandlerFns()
128+
registerHandlerFn(name, fn)
129+
}
130+
131+
func registerHandlerFn(name string, fn HandlerFn) {
118132
if fn == nil {
119133
panic(fmt.Sprintf("constructor for sink %q is nil", name))
120134
}
@@ -124,19 +138,26 @@ func RegisterHandlerFn(name string, fn func(string, io.Writer, *slog.HandlerOpti
124138
handlerFns.Store(name, fn)
125139
}
126140

127-
func termHandlerFn(color bool) func(string, io.Writer, *slog.HandlerOptions) slog.Handler {
128-
return func(_ string, w io.Writer, opts *slog.HandlerOptions) slog.Handler {
129-
if opts == nil {
130-
opts = &slog.HandlerOptions{}
131-
}
132-
return console.NewHandler(w, &console.HandlerOptions{
133-
NoColor: !color,
134-
AddSource: opts.AddSource,
135-
Theme: console.NewDefaultTheme(),
136-
ReplaceAttr: opts.ReplaceAttr,
137-
TimeFormat: "15:04:05.000",
138-
HeaderFormat: "%t %[" + LoggerKey + "]8h %l | %m",
139-
TruncateSourcePath: 2,
140-
})
141+
func termHandlerOptions(opts *slog.HandlerOptions) *console.HandlerOptions {
142+
// todo: it would be nice if consumers could tweak this, either programatically
143+
// or via configuration, but that would mean exposing the dependency on console-slog,
144+
// which is currently opaque. For now, I want to keep this opaque. That means, if
145+
// a consumer was a slightly different configuration of console-slog, they will
146+
// have to construct it from scratch themselves.
147+
if opts == nil {
148+
opts = &slog.HandlerOptions{}
149+
}
150+
theme := console.NewDefaultTheme()
151+
theme.Name = "flume"
152+
theme.Source = console.ToANSICode(console.BrightBlack, console.Italic)
153+
theme.AttrKey = console.ToANSICode(console.Green, console.Faint)
154+
return &console.HandlerOptions{
155+
AddSource: opts.AddSource,
156+
ReplaceAttr: opts.ReplaceAttr,
157+
Level: opts.Level,
158+
Theme: theme,
159+
TimeFormat: "15:04:05.000",
160+
HeaderFormat: "%t %[" + LoggerKey + "]8h |%l| %m %a %(source){→ %s%}",
161+
TruncateSourcePath: 2,
141162
}
142163
}

v2/flumetest/flumetest.go

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,12 @@ import (
2525
"encoding/json"
2626
"flag"
2727
"fmt"
28-
"io"
29-
"log/slog"
3028
"os"
3129
"strconv"
3230
"sync"
3331
"sync/atomic"
3432

3533
"github.com/ThalesGroup/flume/v2"
36-
"github.com/ansel1/console-slog"
3734
)
3835

3936
var Disabled bool
@@ -90,20 +87,9 @@ func MustSetDefaults() {
9087
}
9188

9289
func TestDefaults() *flume.HandlerOptions {
93-
return &flume.HandlerOptions{
94-
Level: slog.LevelDebug,
95-
HandlerFn: func(_ string, w io.Writer, opts *slog.HandlerOptions) slog.Handler {
96-
return console.NewHandler(w, &console.HandlerOptions{
97-
TimeFormat: "15:04:05.000",
98-
Level: opts.Level,
99-
AddSource: opts.AddSource,
100-
NoColor: true,
101-
TruncateSourcePath: 2,
102-
HeaderFormat: "%t %[" + flume.LoggerKey + "]12h %l | %m",
103-
})
104-
},
105-
AddSource: true,
106-
}
90+
dd := flume.DevDefaults()
91+
dd.Level = flume.LevelAll
92+
return dd
10793
}
10894

10995
// Start captures all logs written during the test. If the test succeeds, the

v2/flumetest/flumetest_test.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@ import (
1212
)
1313

1414
func init() {
15-
MustSetDefaults()
15+
opts := &flume.HandlerOptions{
16+
HandlerFn: flume.LookupHandlerFn(flume.TermHandler),
17+
AddSource: true,
18+
Level: flume.LevelAll,
19+
}
20+
flume.Default().SetHandlerOptions(opts)
1621
}
1722

1823
type mockT struct {

v2/handler_options.go

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ var (
1818
ErrInvalidLevelType = errors.New("levels must be a string or int value")
1919
)
2020

21+
type HandlerFn func(name string, w io.Writer, opts *slog.HandlerOptions) slog.Handler
22+
2123
type HandlerOptions struct {
2224
// default level for all loggers, defaults to slog.LevelInfo
2325
Level slog.Leveler
@@ -27,14 +29,20 @@ type HandlerOptions struct {
2729
AddSource bool
2830
// replace attributes
2931
ReplaceAttrs []func(groups []string, a slog.Attr) slog.Attr
30-
// constructor for sinks, defaults to slog.NewTextHandler
31-
HandlerFn func(name string, w io.Writer, opts *slog.HandlerOptions) slog.Handler
32+
// If set, will be called to construct handler instances.
33+
// `name` is the name of the logger being created. For the default
34+
// logger, this will be empty.
35+
// `w` and `opts` will naver be nil.
36+
//
37+
// `name` may be used to return different handlers or unique middleware
38+
// for particular loggers.
39+
HandlerFn HandlerFn
3240
// middleware applied to all sinks
3341
Middleware []Middleware
3442
}
3543

36-
func DevDefaults() HandlerOptions {
37-
return HandlerOptions{
44+
func DevDefaults() *HandlerOptions {
45+
return &HandlerOptions{
3846
HandlerFn: LookupHandlerFn(TermColorHandler),
3947
AddSource: true,
4048
}
@@ -70,13 +78,15 @@ func (o *HandlerOptions) UnmarshalJSON(bytes []byte) error {
7078
return fmt.Errorf("invalid json config: %w", err)
7179
}
7280

73-
var opts HandlerOptions
74-
if o != nil {
75-
opts = *o
76-
}
81+
var opts *HandlerOptions
7782

78-
if s.Development {
83+
switch {
84+
case s.Development:
7985
opts = DevDefaults()
86+
case o == nil:
87+
opts = &HandlerOptions{}
88+
default:
89+
opts = o.Clone()
8090
}
8191

8292
if s.Level != nil {
@@ -111,6 +121,14 @@ func (o *HandlerOptions) UnmarshalJSON(bytes []byte) error {
111121
return fmt.Errorf("%w: %v", ErrInvalidLevelsValue, s.Levels)
112122
}
113123

124+
// for backward compatibility with flumev1, if there is a level named "*"
125+
// in the levels map, treat it like setting the default level. Again,
126+
// to match v1 behavior, this overrides the default level option.
127+
if lvl, ok := opts.Levels["*"]; ok {
128+
opts.Level = lvl
129+
delete(opts.Levels, "*")
130+
}
131+
114132
// for backward compat with v1, allow "addCaller" as
115133
// an alias for "addSource"
116134
if s.AddSource == nil {
@@ -131,7 +149,7 @@ func (o *HandlerOptions) UnmarshalJSON(bytes []byte) error {
131149
opts.HandlerFn = LookupHandlerFn(s.Handler)
132150
}
133151

134-
*o = opts
152+
*o = *opts
135153

136154
return nil
137155
}

0 commit comments

Comments
 (0)