.
This commit is contained in:
94
lib/apperrors/errors.go
Normal file
94
lib/apperrors/errors.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package apperrors
|
||||
|
||||
import "errors"
|
||||
|
||||
type ErrorType int
|
||||
|
||||
const (
|
||||
ErrorOther ErrorType = iota
|
||||
ErrorNetwork
|
||||
ErrorGemini
|
||||
)
|
||||
|
||||
type AppError struct {
|
||||
Type ErrorType
|
||||
StatusCode int
|
||||
Fatal bool
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *AppError) Error() string {
|
||||
if e == nil || e.Err == nil {
|
||||
return ""
|
||||
}
|
||||
return e.Err.Error()
|
||||
}
|
||||
|
||||
func (e *AppError) Unwrap() error {
|
||||
if e == nil {
|
||||
return nil
|
||||
}
|
||||
return e.Err
|
||||
}
|
||||
|
||||
func NewError(err error) error {
|
||||
return &AppError{
|
||||
Type: ErrorOther,
|
||||
StatusCode: 0,
|
||||
Fatal: false,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
func NewFatalError(err error) error {
|
||||
return &AppError{
|
||||
Type: ErrorOther,
|
||||
StatusCode: 0,
|
||||
Fatal: true,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
func NewNetworkError(err error) error {
|
||||
return &AppError{
|
||||
Type: ErrorNetwork,
|
||||
StatusCode: 0,
|
||||
Fatal: false,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
func NewGeminiError(err error, statusCode int) error {
|
||||
return &AppError{
|
||||
Type: ErrorGemini,
|
||||
StatusCode: statusCode,
|
||||
Fatal: false,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
func GetStatusCode(err error) int {
|
||||
var appError *AppError
|
||||
if errors.As(err, &appError) && appError != nil {
|
||||
return appError.StatusCode
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func IsGeminiError(err error) bool {
|
||||
var appError *AppError
|
||||
if errors.As(err, &appError) && appError != nil {
|
||||
if appError.Type == ErrorGemini {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func IsFatal(err error) bool {
|
||||
var appError *AppError
|
||||
if errors.As(err, &appError) && appError != nil {
|
||||
return appError.Fatal
|
||||
}
|
||||
return false
|
||||
}
|
||||
74
lib/logging/logging.go
Normal file
74
lib/logging/logging.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"gemserve/config"
|
||||
|
||||
"github.com/lmittmann/tint"
|
||||
)
|
||||
|
||||
type contextKey int
|
||||
|
||||
const loggerKey contextKey = 0
|
||||
|
||||
var (
|
||||
programLevel *slog.LevelVar = new(slog.LevelVar) // Info by default
|
||||
Logger *slog.Logger
|
||||
)
|
||||
|
||||
func WithLogger(ctx context.Context, logger *slog.Logger) context.Context {
|
||||
return context.WithValue(ctx, loggerKey, logger)
|
||||
}
|
||||
|
||||
func FromContext(ctx context.Context) *slog.Logger {
|
||||
if logger, ok := ctx.Value(loggerKey).(*slog.Logger); ok {
|
||||
return logger
|
||||
}
|
||||
// Return default logger instead of panicking
|
||||
return slog.Default()
|
||||
}
|
||||
|
||||
func SetupLogging() {
|
||||
programLevel.Set(config.CONFIG.LogLevel)
|
||||
// With coloring (uses external package)
|
||||
opts := &tint.Options{
|
||||
AddSource: true,
|
||||
Level: programLevel,
|
||||
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
|
||||
if a.Key == slog.SourceKey {
|
||||
if source, ok := a.Value.Any().(*slog.Source); ok {
|
||||
source.File = filepath.Base(source.File)
|
||||
}
|
||||
}
|
||||
// Customize level colors:
|
||||
// gray for debug, blue for info,
|
||||
// yellow for warnings, black on red bg for errors
|
||||
if a.Key == slog.LevelKey && len(groups) == 0 {
|
||||
level, ok := a.Value.Any().(slog.Level)
|
||||
if ok {
|
||||
switch level {
|
||||
case slog.LevelDebug:
|
||||
// Use grayscale color (232-255 range) for gray/faint debug messages
|
||||
return tint.Attr(240, a)
|
||||
case slog.LevelInfo:
|
||||
// Use color code 12 (bright blue) for info
|
||||
return tint.Attr(12, a)
|
||||
case slog.LevelWarn:
|
||||
// Use color code 11 (bright yellow) for warnings
|
||||
return tint.Attr(11, a)
|
||||
case slog.LevelError:
|
||||
// For black on red background, we need to modify the string value directly
|
||||
// since tint.Attr() only supports foreground colors
|
||||
return slog.String(a.Key, "\033[30;41m"+a.Value.String()+"\033[0m")
|
||||
}
|
||||
}
|
||||
}
|
||||
return a
|
||||
},
|
||||
}
|
||||
Logger = slog.New(tint.NewHandler(os.Stdout, opts))
|
||||
}
|
||||
Reference in New Issue
Block a user