first commit

This commit is contained in:
2026-07-09 22:16:19 +02:00
commit 869749bb01
34 changed files with 3204 additions and 0 deletions

60
logging.go Normal file
View File

@@ -0,0 +1,60 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (C) 2026 Bryan Joshua Pedini
package main
import (
"log/slog"
"net/http"
"os"
"time"
)
// NewLogger builds the process-wide structured logger, text output to
// stdout, level driven by LOG_LEVEL.
func NewLogger(level string) *slog.Logger {
var lvl slog.Level
switch level {
case "debug":
lvl = slog.LevelDebug
case "warn":
lvl = slog.LevelWarn
case "error":
lvl = slog.LevelError
default:
lvl = slog.LevelInfo
}
handler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: lvl})
return slog.New(handler)
}
// statusRecorder captures the status code written by downstream handlers so
// the logging middleware can report it.
type statusRecorder struct {
http.ResponseWriter
status int
}
func (r *statusRecorder) WriteHeader(status int) {
r.status = status
r.ResponseWriter.WriteHeader(status)
}
// loggingMiddleware logs method, path, status, and duration at info level
// for every request.
func (s *WebServer) loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
rec := &statusRecorder{ResponseWriter: w, status: http.StatusOK}
next.ServeHTTP(rec, r)
s.Logger.Info("request",
"method", r.Method,
"path", r.URL.Path,
"status", rec.status,
"duration", time.Since(start),
)
})
}