Git Repository

Mini Video Library

Mini Video Library scannt lokale Medienordner, verwaltet Metadaten und Vorschaubilder und streamt kompatible Videos direkt per HTTP an den Browser.

Projektseite ↗
HTTPShttps://zanvex.de/git/mini-video-library.git

internal/logging/logging.go

Zum Verzeichnis
package logging

import (
	"context"
	"log/slog"
	"sync"
	"time"
)

type Entry struct {
	Time       time.Time         `json:"time"`
	Level      string            `json:"level"`
	Message    string            `json:"message"`
	Attributes map[string]string `json:"attributes,omitempty"`
}
type Store struct {
	mu       sync.RWMutex
	entries  []Entry
	capacity int
}

func NewStore(capacity int) *Store {
	if capacity < 1 {
		capacity = 500
	}
	return &Store{capacity: capacity}
}
func (s *Store) Add(e Entry) {
	s.mu.Lock()
	defer s.mu.Unlock()
	if len(s.entries) >= s.capacity {
		copy(s.entries, s.entries[1:])
		s.entries = s.entries[:s.capacity-1]
	}
	s.entries = append(s.entries, e)
}
func (s *Store) List(limit int) []Entry {
	s.mu.RLock()
	defer s.mu.RUnlock()
	if limit <= 0 || limit > s.capacity {
		limit = s.capacity
	}
	start := len(s.entries) - limit
	if start < 0 {
		start = 0
	}
	out := make([]Entry, len(s.entries)-start)
	copy(out, s.entries[start:])
	return out
}

type Handler struct {
	base  slog.Handler
	store *Store
	attrs []slog.Attr
	group string
}

func NewHandler(base slog.Handler, store *Store) slog.Handler {
	return &Handler{base: base, store: store}
}
func (h *Handler) Enabled(ctx context.Context, l slog.Level) bool { return h.base.Enabled(ctx, l) }
func (h *Handler) Handle(ctx context.Context, r slog.Record) error {
	e := Entry{Time: r.Time, Level: r.Level.String(), Message: r.Message, Attributes: map[string]string{}}
	for _, a := range h.attrs {
		e.Attributes[h.key(a.Key)] = a.Value.String()
	}
	r.Attrs(func(a slog.Attr) bool { e.Attributes[h.key(a.Key)] = a.Value.String(); return true })
	if len(e.Attributes) == 0 {
		e.Attributes = nil
	}
	h.store.Add(e)
	return h.base.Handle(ctx, r)
}
func (h *Handler) WithAttrs(a []slog.Attr) slog.Handler {
	return &Handler{base: h.base.WithAttrs(a), store: h.store, attrs: append(append([]slog.Attr{}, h.attrs...), a...), group: h.group}
}
func (h *Handler) WithGroup(g string) slog.Handler {
	group := g
	if h.group != "" {
		group = h.group + "." + g
	}
	return &Handler{base: h.base.WithGroup(g), store: h.store, attrs: h.attrs, group: group}
}
func (h *Handler) key(k string) string {
	if h.group != "" {
		return h.group + "." + k
	}
	return k
}