Files
EchoChat/backend/go-service/cmd/server/main.go
bujinyuan 63c6079667 feat(logs): 日志系统升级 — 文件轮转 + 分级存储
- 引入 lumberjack 实现日志文件自动轮转(按大小切割、保留数量、过期清理)
- app.log: 全量日志(JSON 格式),便于后期接入 ELK/Loki
- error.log: 仅 WARN 及以上级别,便于快速定位问题
- 控制台输出保持不变(彩色可读文本)
- 配置新增 log.file 节,支持 enable/dir/max_size/max_backups/max_age/compress

Made-with: Cursor
2026-02-28 15:15:00 +08:00

102 lines
2.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package main 是 EchoChat 后端服务的入口
package main
import (
"context"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/echochat/backend/config"
"github.com/echochat/backend/pkg/logs"
"github.com/echochat/backend/pkg/middleware"
"github.com/echochat/backend/pkg/utils"
"github.com/echochat/backend/app/provider"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
func main() {
// 1. 加载配置
cfg, err := config.Load("config", "config.dev")
if err != nil {
fmt.Printf("加载配置失败: %v\n", err)
os.Exit(1)
}
// 2. 初始化日志系统
if err := logs.Init(&cfg.Log); err != nil {
fmt.Printf("初始化日志失败: %v\n", err)
os.Exit(1)
}
defer logs.Sync()
ctx := context.Background()
logs.Info(ctx, "main", "EchoChat 服务启动中",
zap.String("mode", cfg.Server.Mode),
zap.Int("port", cfg.Server.Port),
)
// 3. 通过 Wire 初始化所有组件
app, err := provider.InitializeApp(cfg)
if err != nil {
logs.Fatal(ctx, "main", "初始化应用失败", zap.Error(err))
}
_ = app
// 4. 创建 Gin Engine
if cfg.Server.Mode == "release" {
gin.SetMode(gin.ReleaseMode)
}
engine := gin.New()
// 5. 注册中间件顺序Trace → Logger → CORS → Recovery
engine.Use(
middleware.Trace(),
middleware.Logger(),
middleware.CORS(),
middleware.Recovery(),
)
// 6. 注册路由
engine.GET("/health", func(c *gin.Context) {
utils.ResponseOK(c, gin.H{
"status": "ok",
"service": "echochat",
"time": time.Now().Format("2006-01-02 15:04:05"),
})
})
// 7. 启动 HTTP 服务(优雅关闭)
addr := fmt.Sprintf(":%d", cfg.Server.Port)
srv := &http.Server{
Addr: addr,
Handler: engine,
}
go func() {
logs.Info(ctx, "main", "HTTP 服务启动", zap.String("addr", addr))
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
logs.Fatal(ctx, "main", "HTTP 服务启动失败", zap.Error(err))
}
}()
// 等待中断信号,优雅关闭
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
logs.Info(ctx, "main", "正在关闭服务...")
shutdownCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
if err := srv.Shutdown(shutdownCtx); err != nil {
logs.Error(ctx, "main", "服务关闭失败", zap.Error(err))
}
logs.Info(ctx, "main", "服务已停止")
}