add logger, godotenv
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
// pkg/logger/helpers.go
|
||||
package logger
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// LogApplicationStart логирует запуск приложения
|
||||
func LogApplicationStart(version, environment, port string) {
|
||||
Get().Info("application starting",
|
||||
zap.String("version", version),
|
||||
zap.String("environment", environment),
|
||||
zap.String("port", port),
|
||||
zap.Time("start_time", time.Now()),
|
||||
)
|
||||
}
|
||||
|
||||
// LogApplicationShutdown логирует graceful shutdown
|
||||
func LogApplicationShutdown(reason string) {
|
||||
Get().Info("application shutting down",
|
||||
zap.String("reason", reason),
|
||||
zap.Time("shutdown_time", time.Now()),
|
||||
)
|
||||
}
|
||||
|
||||
// LogDatabaseStats логирует статистику базы данных
|
||||
func LogDatabaseStats(stats map[string]interface{}) {
|
||||
fields := make([]zap.Field, 0, len(stats))
|
||||
for key, value := range stats {
|
||||
fields = append(fields, zap.Any(key, value))
|
||||
}
|
||||
Get().Info("database statistics", fields...)
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// pkg/logger/interface.go
|
||||
package logger
|
||||
|
||||
import "go.uber.org/zap"
|
||||
|
||||
// Interface определяет контракт для логгера
|
||||
type Interface interface {
|
||||
Debug(msg string, fields ...zap.Field)
|
||||
Info(msg string, fields ...zap.Field)
|
||||
Warn(msg string, fields ...zap.Field)
|
||||
Error(msg string, fields ...zap.Field)
|
||||
Fatal(msg string, fields ...zap.Field)
|
||||
|
||||
Debugf(template string, args ...interface{})
|
||||
Infof(template string, args ...interface{})
|
||||
Warnf(template string, args ...interface{})
|
||||
Errorf(template string, args ...interface{})
|
||||
Fatalf(template string, args ...interface{})
|
||||
|
||||
With(fields ...zap.Field) Interface
|
||||
}
|
||||
|
||||
// wrapper обертка для zap.Logger
|
||||
type wrapper struct {
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
// NewWrapper создает новую обертку
|
||||
func NewWrapper(logger *zap.Logger) Interface {
|
||||
return &wrapper{logger: logger}
|
||||
}
|
||||
|
||||
func (w *wrapper) Debug(msg string, fields ...zap.Field) {
|
||||
w.logger.Debug(msg, fields...)
|
||||
}
|
||||
|
||||
func (w *wrapper) Info(msg string, fields ...zap.Field) {
|
||||
w.logger.Info(msg, fields...)
|
||||
}
|
||||
|
||||
func (w *wrapper) Warn(msg string, fields ...zap.Field) {
|
||||
w.logger.Warn(msg, fields...)
|
||||
}
|
||||
|
||||
func (w *wrapper) Error(msg string, fields ...zap.Field) {
|
||||
w.logger.Error(msg, fields...)
|
||||
}
|
||||
|
||||
func (w *wrapper) Fatal(msg string, fields ...zap.Field) {
|
||||
w.logger.Fatal(msg, fields...)
|
||||
}
|
||||
|
||||
func (w *wrapper) Debugf(template string, args ...interface{}) {
|
||||
w.logger.Sugar().Debugf(template, args...)
|
||||
}
|
||||
|
||||
func (w *wrapper) Infof(template string, args ...interface{}) {
|
||||
w.logger.Sugar().Infof(template, args...)
|
||||
}
|
||||
|
||||
func (w *wrapper) Warnf(template string, args ...interface{}) {
|
||||
w.logger.Sugar().Warnf(template, args...)
|
||||
}
|
||||
|
||||
func (w *wrapper) Errorf(template string, args ...interface{}) {
|
||||
w.logger.Sugar().Errorf(template, args...)
|
||||
}
|
||||
|
||||
func (w *wrapper) Fatalf(template string, args ...interface{}) {
|
||||
w.logger.Sugar().Fatalf(template, args...)
|
||||
}
|
||||
|
||||
func (w *wrapper) With(fields ...zap.Field) Interface {
|
||||
return &wrapper{logger: w.logger.With(fields...)}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// pkg/logger/logger.go
|
||||
package logger
|
||||
|
||||
import (
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
var globalLogger *zap.Logger
|
||||
|
||||
// Init инициализирует глобальный логгер
|
||||
func Init(level string, environment string) error {
|
||||
var config zap.Config
|
||||
|
||||
if environment == "production" {
|
||||
config = zap.NewProductionConfig()
|
||||
} else {
|
||||
config = zap.NewDevelopmentConfig()
|
||||
config.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
|
||||
}
|
||||
|
||||
// Устанавливаем уровень логирования
|
||||
switch level {
|
||||
case "debug":
|
||||
config.Level = zap.NewAtomicLevelAt(zap.DebugLevel)
|
||||
case "info":
|
||||
config.Level = zap.NewAtomicLevelAt(zap.InfoLevel)
|
||||
case "warn":
|
||||
config.Level = zap.NewAtomicLevelAt(zap.WarnLevel)
|
||||
case "error":
|
||||
config.Level = zap.NewAtomicLevelAt(zap.ErrorLevel)
|
||||
default:
|
||||
config.Level = zap.NewAtomicLevelAt(zap.InfoLevel)
|
||||
}
|
||||
|
||||
logger, err := config.Build()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
globalLogger = logger
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get возвращает глобальный логгер
|
||||
func Get() *zap.Logger {
|
||||
if globalLogger == nil {
|
||||
// Fallback на стандартный логгер если не инициализирован
|
||||
logger, _ := zap.NewProduction()
|
||||
return logger
|
||||
}
|
||||
return globalLogger
|
||||
}
|
||||
|
||||
// Sync синхронизирует буферы логгера
|
||||
func Sync() {
|
||||
if globalLogger != nil {
|
||||
globalLogger.Sync()
|
||||
}
|
||||
}
|
||||
|
||||
// Sugar возвращает SugaredLogger
|
||||
func Sugar() *zap.SugaredLogger {
|
||||
return Get().Sugar()
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// pkg/middleware/logger.go
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"api_bb/pkg/logger"
|
||||
|
||||
"github.com/go-chi/chi/v5/middleware"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Logger middleware для логирования HTTP запросов
|
||||
func Logger(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
start := time.Now()
|
||||
|
||||
// Получаем request ID
|
||||
reqID := middleware.GetReqID(r.Context())
|
||||
|
||||
// Создаем логгер с контекстом запроса
|
||||
requestLogger := logger.Get().With(
|
||||
zap.String("method", r.Method),
|
||||
zap.String("path", r.URL.Path),
|
||||
zap.String("remote_addr", r.RemoteAddr),
|
||||
zap.String("user_agent", r.UserAgent()),
|
||||
zap.String("request_id", reqID),
|
||||
)
|
||||
|
||||
// Обертываем ResponseWriter для получения статуса
|
||||
wrappedWriter := middleware.NewWrapResponseWriter(w, r.ProtoMajor)
|
||||
|
||||
// Обрабатываем запрос
|
||||
next.ServeHTTP(wrappedWriter, r)
|
||||
|
||||
// Логируем результат
|
||||
duration := time.Since(start)
|
||||
|
||||
requestLogger.Info("request completed",
|
||||
zap.Int("status", wrappedWriter.Status()),
|
||||
zap.Int("bytes", wrappedWriter.BytesWritten()),
|
||||
zap.Duration("duration", duration),
|
||||
)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user