debug log level is dynamic and set after Logger creation

So we should use dynamic handler to set the log level after. With this
patch we can clearly see the output. Before we were always stuck in log
level "info" and not seeing debug log level

```
bin/helm upgrade --install --debug --wait frontend \
--namespace test \
--set replicaCount=2 \
--set backend=http://backend-podinfo:9898/echo \
podinfo/podinfo
level=DEBUG msg="getting history for release" release=frontend
level=DEBUG msg="preparing upgrade" name=frontend
level=DEBUG msg="performing update" name=frontend
level=DEBUG msg="creating upgraded release" name=frontend
level=DEBUG msg="checking resources for changes" resources=2
level=DEBUG msg="no changes detected" kind=Service name=frontend-podinfo
level=DEBUG msg="patching resource" kind=Deployment name=frontend-podinfo namespace=test
level=DEBUG msg="waiting for resources" count=2 timeout=5m0s
level=DEBUG msg="waiting for resource" name=frontend-podinfo kind=Deployment expectedStatus=Current actualStatus=Unknown
level=DEBUG msg="updating status for upgraded release" name=frontend
Release "frontend" has been upgraded. Happy Helming!
NAME: frontend
LAST DEPLOYED: Thu Apr 10 09:56:25 2025
NAMESPACE: test
STATUS: deployed
REVISION: 6
DESCRIPTION: Upgrade complete
```

Signed-off-by: Benoit Tigeot <benoit.tigeot@lifen.fr>
pull/30708/head
Benoit Tigeot 5 months ago
parent 0c85456788
commit 6b5fa33633
No known key found for this signature in database
GPG Key ID: 8E6D4FC8AEBDA62C

@ -17,19 +17,53 @@ limitations under the License.
package cli
import (
"context"
"log/slog"
"os"
)
func NewLogger(debug bool) *slog.Logger {
level := slog.LevelInfo
if debug {
level = slog.LevelDebug
// DebugCheckHandler checks settings.Debug at log time
type DebugCheckHandler struct {
handler slog.Handler
settings *EnvSettings
}
// Enabled implements slog.Handler.Enabled
func (h *DebugCheckHandler) Enabled(_ context.Context, level slog.Level) bool {
if level == slog.LevelDebug {
return h.settings.Debug // Check settings.Debug at log time
}
return true // Always log other levels
}
// Create a handler that removes timestamps
handler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
Level: level,
// Handle implements slog.Handler.Handle
func (h *DebugCheckHandler) Handle(ctx context.Context, r slog.Record) error {
return h.handler.Handle(ctx, r)
}
// WithAttrs implements slog.Handler.WithAttrs
func (h *DebugCheckHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
return &DebugCheckHandler{
handler: h.handler.WithAttrs(attrs),
settings: h.settings,
}
}
// WithGroup implements slog.Handler.WithGroup
func (h *DebugCheckHandler) WithGroup(name string) slog.Handler {
return &DebugCheckHandler{
handler: h.handler.WithGroup(name),
settings: h.settings,
}
}
// NewLogger creates a new logger with dynamic debug checking
func NewLogger(settings *EnvSettings) *slog.Logger {
// Create base handler that removes timestamps
baseHandler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
// Always use LevelDebug here to allow all messages through
// Our custom handler will do the filtering
Level: slog.LevelDebug,
ReplaceAttr: func(_ []string, a slog.Attr) slog.Attr {
// Remove the time attribute
if a.Key == slog.TimeKey {
@ -39,5 +73,11 @@ func NewLogger(debug bool) *slog.Logger {
},
})
return slog.New(handler)
// Wrap with our dynamic debug-checking handler
dynamicHandler := &DebugCheckHandler{
handler: baseHandler,
settings: settings,
}
return slog.New(dynamicHandler)
}

@ -95,7 +95,7 @@ By default, the default directories depend on the Operating System. The defaults
`
var settings = cli.New()
var Logger = cli.NewLogger(settings.Debug)
var Logger = cli.NewLogger(settings)
func NewRootCmd(out io.Writer, args []string) (*cobra.Command, error) {
actionConfig := new(action.Configuration)

Loading…
Cancel
Save