From 9a9761008c6bd1131ae13aa6ae5a590c86cf6dae Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Tue, 10 Sep 2024 18:44:48 +0200 Subject: [PATCH] build: add handler set implementations This commit then also adds an implementation of the btclog.Handler interface called `handlerSets` which basically lets us have a Handler backed by many Handlers (we need one for the stdout and one for our log file). --- build/handler_sets.go | 177 ++++++++++++++++++++++++++++++++++++++++++ go.mod | 3 +- go.sum | 5 +- 3 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 build/handler_sets.go diff --git a/build/handler_sets.go b/build/handler_sets.go new file mode 100644 index 000000000..f37fdc22b --- /dev/null +++ b/build/handler_sets.go @@ -0,0 +1,177 @@ +package build + +import ( + "context" + "log/slog" + + btclogv1 "github.com/btcsuite/btclog" + "github.com/btcsuite/btclog/v2" +) + +// handlerSet is an implementation of Handler that abstracts away multiple +// Handlers. +type handlerSet struct { + level btclogv1.Level + set []btclog.Handler +} + +// newHandlerSet constructs a new HandlerSet. +func newHandlerSet(level btclogv1.Level, set ...btclog.Handler) *handlerSet { + h := &handlerSet{ + set: set, + level: level, + } + h.SetLevel(level) + + return h +} + +// Enabled reports whether the handler handles records at the given level. +// +// NOTE: this is part of the slog.Handler interface. +func (h *handlerSet) Enabled(ctx context.Context, level slog.Level) bool { + for _, handler := range h.set { + if !handler.Enabled(ctx, level) { + return false + } + } + + return true +} + +// Handle handles the Record. +// +// NOTE: this is part of the slog.Handler interface. +func (h *handlerSet) Handle(ctx context.Context, record slog.Record) error { + for _, handler := range h.set { + if err := handler.Handle(ctx, record); err != nil { + return err + } + } + + return nil +} + +// WithAttrs returns a new Handler whose attributes consist of both the +// receiver's attributes and the arguments. +// +// NOTE: this is part of the slog.Handler interface. +func (h *handlerSet) WithAttrs(attrs []slog.Attr) slog.Handler { + newSet := &reducedSet{set: make([]slog.Handler, len(h.set))} + for i, handler := range h.set { + newSet.set[i] = handler.WithAttrs(attrs) + } + + return newSet +} + +// WithGroup returns a new Handler with the given group appended to the +// receiver's existing groups. +// +// NOTE: this is part of the slog.Handler interface. +func (h *handlerSet) WithGroup(name string) slog.Handler { + newSet := &reducedSet{set: make([]slog.Handler, len(h.set))} + for i, handler := range h.set { + newSet.set[i] = handler.WithGroup(name) + } + + return newSet +} + +// SubSystem creates a new Handler with the given sub-system tag. +// +// NOTE: this is part of the Handler interface. +func (h *handlerSet) SubSystem(tag string) btclog.Handler { + newSet := &handlerSet{set: make([]btclog.Handler, len(h.set))} + for i, handler := range h.set { + newSet.set[i] = handler.SubSystem(tag) + } + + return newSet +} + +// SetLevel changes the logging level of the Handler to the passed +// level. +// +// NOTE: this is part of the btclog.Handler interface. +func (h *handlerSet) SetLevel(level btclogv1.Level) { + for _, handler := range h.set { + handler.SetLevel(level) + } + h.level = level +} + +// Level returns the current logging level of the Handler. +// +// NOTE: this is part of the btclog.Handler interface. +func (h *handlerSet) Level() btclogv1.Level { + return h.level +} + +// A compile-time check to ensure that handlerSet implements btclog.Handler. +var _ btclog.Handler = (*handlerSet)(nil) + +// reducedSet is an implementation of the slog.Handler interface which is +// itself backed by multiple slog.Handlers. This is used by the handlerSet +// WithGroup and WithAttrs methods so that we can apply the WithGroup and +// WithAttrs to the underlying handlers in the set. These calls, however, +// produce slog.Handlers and not btclog.Handlers. So the reducedSet represents +// the resulting set produced. +type reducedSet struct { + set []slog.Handler +} + +// Enabled reports whether the handler handles records at the given level. +// +// NOTE: this is part of the slog.Handler interface. +func (r *reducedSet) Enabled(ctx context.Context, level slog.Level) bool { + for _, handler := range r.set { + if !handler.Enabled(ctx, level) { + return false + } + } + + return true +} + +// Handle handles the Record. +// +// NOTE: this is part of the slog.Handler interface. +func (r *reducedSet) Handle(ctx context.Context, record slog.Record) error { + for _, handler := range r.set { + if err := handler.Handle(ctx, record); err != nil { + return err + } + } + + return nil +} + +// WithAttrs returns a new Handler whose attributes consist of both the +// receiver's attributes and the arguments. +// +// NOTE: this is part of the slog.Handler interface. +func (r *reducedSet) WithAttrs(attrs []slog.Attr) slog.Handler { + newSet := &reducedSet{set: make([]slog.Handler, len(r.set))} + for i, handler := range r.set { + newSet.set[i] = handler.WithAttrs(attrs) + } + + return newSet +} + +// WithGroup returns a new Handler with the given group appended to the +// receiver's existing groups. +// +// NOTE: this is part of the slog.Handler interface. +func (r *reducedSet) WithGroup(name string) slog.Handler { + newSet := &reducedSet{set: make([]slog.Handler, len(r.set))} + for i, handler := range r.set { + newSet.set[i] = handler.WithGroup(name) + } + + return newSet +} + +// A compile-time check to ensure that handlerSet implements slog.Handler. +var _ slog.Handler = (*reducedSet)(nil) diff --git a/go.mod b/go.mod index b1e63f8cf..692e5ad75 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,8 @@ require ( github.com/btcsuite/btcd/btcutil v1.1.5 github.com/btcsuite/btcd/btcutil/psbt v1.1.8 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 - github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f + github.com/btcsuite/btclog v0.0.0-20241003133417-09c4e92e319c + github.com/btcsuite/btclog/v2 v2.0.0-20241017175713-3428138b75c7 github.com/btcsuite/btcwallet v0.16.10-0.20240912233857-ffb143c77cc5 github.com/btcsuite/btcwallet/wallet/txauthor v1.3.5 github.com/btcsuite/btcwallet/wallet/txrules v1.2.2 diff --git a/go.sum b/go.sum index 5c3b97e88..d0f1882f3 100644 --- a/go.sum +++ b/go.sum @@ -89,8 +89,11 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtyd github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btclog v0.0.0-20241003133417-09c4e92e319c h1:4HxD1lBUGUddhzgaNgrCPsFWd7cGYNpeFUgd9ZIgyM0= +github.com/btcsuite/btclog v0.0.0-20241003133417-09c4e92e319c/go.mod h1:w7xnGOhwT3lmrS4H3b/D1XAXxvh+tbhUm8xeHN2y3TQ= +github.com/btcsuite/btclog/v2 v2.0.0-20241017175713-3428138b75c7 h1:3Ct3zN3VCEKVm5nceWBBEKczc+jvTfVyOEG71ob2Yuc= +github.com/btcsuite/btclog/v2 v2.0.0-20241017175713-3428138b75c7/go.mod h1:XItGUfVOxotJL8kkuk2Hj3EVow5KCugXl3wWfQ6K0AE= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcwallet v0.16.10-0.20240912233857-ffb143c77cc5 h1:zYy233eUBvkF3lq2MUkybEhxhDsrRDSgiToIKN57mtk= github.com/btcsuite/btcwallet v0.16.10-0.20240912233857-ffb143c77cc5/go.mod h1:1HJXYbjJzgumlnxOC2+ViR1U+gnHWoOn7WeK5OfY1eU=