garm/util/logging.go
Gabriel Adrian Samfira 61e674e1fd Add workflow job URL and some logging improvements
Record the workflow job run URL for both scaleset and workflow jobs and
add some logging fixes.

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
2026-02-15 09:52:17 +02:00

109 lines
2.6 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 {
attrMap := map[string]struct{}{}
for _, val := range attrs {
attrMap[val.Key] = struct{}{}
}
newAttrs := attrs
existingAttrs, ok := ctx.Value(slogCtxFields).([]slog.Attr)
if ok {
for _, val := range existingAttrs {
if _, ok := attrMap[val.Key]; !ok {
newAttrs = append(newAttrs, val)
}
}
}
return context.WithValue(ctx, slogCtxFields, newAttrs)
}
func GetSlogValuesFromContext(ctx context.Context) []slog.Attr {
vals, ok := ctx.Value(slogCtxFields).([]slog.Attr)
if ok {
return vals
}
return []slog.Attr{}
}
func CopySlogValuesToNewCtx(sourceCtx, destCtx context.Context) context.Context {
vals := GetSlogValuesFromContext(sourceCtx)
return WithSlogContext(destCtx, vals...)
}
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}
}