upaas/internal/logger/logger.go
sneak 3f9d83c436 Initial commit with server startup infrastructure
Core infrastructure:
- Uber fx dependency injection
- Chi router with middleware stack
- SQLite database with embedded migrations
- Embedded templates and static assets
- Structured logging with slog

Features implemented:
- Authentication (login, logout, session management, argon2id hashing)
- App management (create, edit, delete, list)
- Deployment pipeline (clone, build, deploy, health check)
- Webhook processing for Gitea
- Notifications (ntfy, Slack)
- Environment variables, labels, volumes per app
- SSH key generation for deploy keys

Server startup:
- Server.Run() starts HTTP server on configured port
- Server.Shutdown() for graceful shutdown
- SetupRoutes() wires all handlers with chi router
2025-12-29 15:46:03 +07:00

87 lines
1.8 KiB
Go

// Package logger provides structured logging with slog.
package logger
import (
"log/slog"
"os"
"go.uber.org/fx"
"git.eeqj.de/sneak/upaas/internal/globals"
)
// Params contains dependencies for Logger.
type Params struct {
fx.In
Globals *globals.Globals
}
// Logger wraps slog.Logger with level control.
type Logger struct {
log *slog.Logger
level *slog.LevelVar
params Params
}
// New creates a new Logger with TTY detection for output format.
func New(_ fx.Lifecycle, params Params) (*Logger, error) {
loggerInstance := &Logger{
level: new(slog.LevelVar),
params: params,
}
loggerInstance.level.Set(slog.LevelInfo)
// TTY detection for dev vs prod output
isTTY := detectTTY()
var handler slog.Handler
if isTTY {
// Text output for development
handler = slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
Level: loggerInstance.level,
AddSource: true,
})
} else {
// JSON output for production
handler = slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: loggerInstance.level,
AddSource: true,
})
}
loggerInstance.log = slog.New(handler)
return loggerInstance, nil
}
func detectTTY() bool {
fileInfo, err := os.Stdout.Stat()
if err != nil {
return false
}
return (fileInfo.Mode() & os.ModeCharDevice) != 0
}
// Get returns the underlying slog.Logger.
func (l *Logger) Get() *slog.Logger {
return l.log
}
// EnableDebugLogging sets the log level to debug.
func (l *Logger) EnableDebugLogging() {
l.level.Set(slog.LevelDebug)
l.log.Debug("debug logging enabled", "debug", true)
}
// Identify logs application startup information.
func (l *Logger) Identify() {
l.log.Info("starting",
"appname", l.params.Globals.Appname,
"version", l.params.Globals.Version,
"buildarch", l.params.Globals.Buildarch,
)
}