Skip to content

Commit ff6ef31

Browse files
author
Russ Egan
committed
Added a bunch more methods to Controller
Allows more granualar manipulation of levels, sinks, and middleware, as well as ways to get the current values, and to replace all of the values atomically. Also increased test coverage.
1 parent c891b6f commit ff6ef31

File tree

12 files changed

+1345
-213
lines changed

12 files changed

+1345
-213
lines changed

v2/TODO.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
*can* do this if they wish, by first setting a new default sink, then setting slog's default handler, but that there are caveats.
3737
- or should v2 act like v1 and not log anything until it has been configured? Should there be an option to buffer until a configuration
3838
has been set, so logs won't be lost?
39-
- [ ] When using Config to set all the levels, does that clear any prior level settings? Is there generally a way to clear/reset
39+
- [x] When using Config to set all the levels, does that clear any prior level settings? Is there generally a way to clear/reset
4040
all confs?
4141
- [ ] Should there be a bridge from v1 to v2? Add a way to direct all v1 calls to v2 calls?
4242
- Working on a slog handler -> zap core bridge, and a zap core -> slog handler bridge

v2/conf.go

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ type conf struct {
1717
globalMiddleware []Middleware
1818
}
1919

20-
func (c *conf) setSink(sink slog.Handler, isDefault bool) {
21-
if c.customSink && isDefault {
20+
func (c *conf) setSink(sink slog.Handler, isDefault, replace bool) {
21+
if !replace && c.customSink && isDefault {
2222
return
2323
}
2424

@@ -50,27 +50,23 @@ func (c *conf) rebuildDelegate() {
5050
c.delegatePtr.Store(&h)
5151
}
5252

53-
func (c *conf) setLevel(l slog.Level, isDefault bool) {
54-
// don't need a mutex here. this is already protected
55-
// by the Controller mutex, and the `lvl` pointer itself
56-
// is immutable.
57-
switch {
58-
case isDefault && !c.customLvl:
59-
c.lvl.Set(l)
60-
case !isDefault:
61-
c.customLvl = true
62-
c.lvl.Set(l)
53+
func (c *conf) setLevel(l slog.Level, isDefault, replace bool) {
54+
if !replace && c.customLvl && isDefault {
55+
return
6356
}
64-
}
6557

66-
func (c *conf) use(middleware ...Middleware) {
67-
c.middleware = append(c.middleware, middleware...)
58+
c.customLvl = !isDefault
6859

69-
c.rebuildDelegate()
60+
c.lvl.Set(l)
7061
}
7162

72-
func (c *conf) setGlobalMiddleware(middleware []Middleware) {
73-
c.globalMiddleware = middleware
63+
func (c *conf) use(global []Middleware, replace bool, local ...Middleware) {
64+
c.globalMiddleware = global
65+
if replace {
66+
c.middleware = local
67+
} else {
68+
c.middleware = append(c.middleware, local...)
69+
}
7470

7571
c.rebuildDelegate()
7672
}

v2/config.go

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,12 @@ const (
2727
TermColorSink = "term-color"
2828
)
2929

30-
func init() {
30+
func init() { //nolint:gochecknoinits
31+
resetBuiltInSinks()
32+
}
33+
34+
func resetBuiltInSinks() {
35+
sinkConstructors = sync.Map{}
3136
RegisterSinkConstructor(TextSink, textSinkConstructor)
3237
// for v1 compatibility, "console" is an alias for "text"
3338
RegisterSinkConstructor(ConsoleSink, textSinkConstructor)
@@ -37,6 +42,12 @@ func init() {
3742
}
3843

3944
func RegisterSinkConstructor(name string, constructor SinkConstructor) {
45+
if constructor == nil {
46+
panic(fmt.Sprintf("constructor for sink %q is nil", name))
47+
}
48+
if name == "" {
49+
panic("constructor registered with empty name")
50+
}
4051
sinkConstructors.Store(name, constructor)
4152
}
4253

@@ -144,16 +155,9 @@ type Config struct {
144155
ReplaceAttrs []func([]string, slog.Attr) slog.Attr
145156
}
146157

147-
const (
148-
EncodingJSON = "json"
149-
EncodingText = "text"
150-
EncodingTerm = "term"
151-
EncodingTermColor = "term-color"
152-
)
153-
154158
func DevDefaults() Config {
155159
return Config{
156-
DefaultSink: "term-color",
160+
DefaultSink: TermColorSink,
157161
AddSource: true,
158162
}
159163
}
@@ -181,9 +185,10 @@ func parseLevel(v any) (slog.Level, error) {
181185
case string:
182186
s = v
183187
case float64:
184-
// allow raw integer values for level
188+
// allow numbers to be used as level values
185189
return slog.Level(v), nil
186190
case int:
191+
// allow raw integer values for level
187192
return slog.Level(v), nil
188193
case bool:
189194
if v {
@@ -290,7 +295,7 @@ func (c *Config) UnmarshalJSON(bytes []byte) error {
290295
}
291296
}
292297
default:
293-
return merry.Errorf("invalid level value: %v", s.Levels)
298+
return merry.Errorf("invalid levels value: %v", s.Levels)
294299
}
295300

296301
// for backward compat with v1, allow "addCaller" as
@@ -339,16 +344,27 @@ func (c Config) Handler() (slog.Handler, error) {
339344
if !ok {
340345
return nil, errors.New("unknown sink constructor: " + c.DefaultSink)
341346
}
342-
constructor := v.(SinkConstructor)
347+
constructor, _ := v.(SinkConstructor)
343348
return constructor(c)
344349
}
345350

351+
// Controller returns a new controller configured with the given config.
352+
func (c Config) Controller() (*Controller, error) {
353+
ctl := NewController(nil)
354+
err := c.Configure(ctl)
355+
if err != nil {
356+
return nil, err
357+
}
358+
return ctl, nil
359+
}
360+
361+
// Configure configures a controller with the given config.
362+
//
363+
// It sets the default level, levels, and sink. Level settings
364+
// replace any current level settings.
346365
func (c Config) Configure(ctl *Controller) error {
347366
ctl.SetDefaultLevel(c.DefaultLevel)
348-
349-
for name, level := range c.Levels {
350-
ctl.SetLevel(name, level)
351-
}
367+
ctl.SetLevels(c.Levels, true)
352368

353369
h, err := c.Handler()
354370
if err != nil {

0 commit comments

Comments
 (0)