garm/util/logging.go
Gabriel Adrian Samfira 0faeee703d Make the debug-log command more useful
The debug-log command now supports log level filtering and attribute
filtering. The log level filtering will only be able to set the minimum
log level as low as the server is configured to stream. If the server has
its log level set as INFO, then setting the log level in the CLI to DEBUG
will have no effect.

But anything above what the server sends, is within the control of the client
to filter. This is all done client side.

Attribute filters are useful if you need to watch the logs for a particular
worker, entity, etc.

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
2025-08-27 13:21:56 +00:00

82 lines
2 KiB
Go

// Copyright 2025 Cloudbase Solutions SRL
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package util
import (
"context"
"log/slog"
)
type slogContextKey string
const (
slogCtxFields slogContextKey = "slog_ctx_fields"
)
var _ slog.Handler = &SlogMultiHandler{}
func WithSlogContext(ctx context.Context, attrs ...slog.Attr) context.Context {
return context.WithValue(ctx, slogCtxFields, attrs)
}
type SlogMultiHandler struct {
Handlers []slog.Handler
}
func (m *SlogMultiHandler) Enabled(ctx context.Context, level slog.Level) bool {
// Enabled if any handler is enabled
for _, h := range m.Handlers {
if h.Enabled(ctx, level) {
return true
}
}
return false
}
func (m *SlogMultiHandler) Handle(ctx context.Context, r slog.Record) error {
record := r.Clone()
attrs, ok := ctx.Value(slogCtxFields).([]slog.Attr)
if ok {
for _, v := range attrs {
record.AddAttrs(v)
}
}
var firstErr error
for _, h := range m.Handlers {
if err := h.Handle(ctx, record); err != nil && firstErr == nil {
firstErr = err
}
}
return firstErr
}
func (m *SlogMultiHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
hs := make([]slog.Handler, len(m.Handlers))
for i, h := range m.Handlers {
hs[i] = h.WithAttrs(attrs)
}
return &SlogMultiHandler{
Handlers: hs,
}
}
func (m *SlogMultiHandler) WithGroup(name string) slog.Handler {
hs := make([]slog.Handler, len(m.Handlers))
for i, h := range m.Handlers {
hs[i] = h.WithGroup(name)
}
return &SlogMultiHandler{hs}
}