Add files via upload
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"home-vue-go/internal/config"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var logBuffer []string
|
||||
var maxLogLines = 1000
|
||||
|
||||
// 初始化日志缓冲区
|
||||
func InitLogBuffer() {
|
||||
logBuffer = make([]string, 0, maxLogLines)
|
||||
}
|
||||
|
||||
// 添加日志到缓冲区
|
||||
func AddLogToBuffer(logLine string) {
|
||||
logBuffer = append(logBuffer, logLine)
|
||||
if len(logBuffer) > maxLogLines {
|
||||
logBuffer = logBuffer[len(logBuffer)-maxLogLines:]
|
||||
}
|
||||
}
|
||||
|
||||
// 获取后端日志
|
||||
func GetBackendLogs(cfg *config.Config) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
lines := c.DefaultQuery("lines", "100")
|
||||
linesInt := 100
|
||||
if lines == "all" {
|
||||
linesInt = maxLogLines
|
||||
} else {
|
||||
// 尝试解析lines参数
|
||||
if n, err := parseIntLogs(lines); err == nil && n > 0 {
|
||||
linesInt = n
|
||||
if linesInt > maxLogLines {
|
||||
linesInt = maxLogLines
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 从缓冲区获取日志
|
||||
logs := make([]string, 0)
|
||||
if len(logBuffer) > linesInt {
|
||||
logs = logBuffer[len(logBuffer)-linesInt:]
|
||||
} else {
|
||||
logs = logBuffer
|
||||
}
|
||||
|
||||
// 尝试从日志文件读取(如果存在)
|
||||
logFile := filepath.Join(cfg.DataDir, "app.log")
|
||||
if fileLogs, err := readLogFile(logFile, linesInt); err == nil && len(fileLogs) > 0 {
|
||||
// 合并文件日志和缓冲区日志
|
||||
allLogs := append(fileLogs, logs...)
|
||||
// 去重并排序
|
||||
logs = deduplicateLogs(allLogs)
|
||||
if len(logs) > linesInt {
|
||||
logs = logs[len(logs)-linesInt:]
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"logs": logs,
|
||||
"count": len(logs),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 读取日志文件
|
||||
func readLogFile(filePath string, maxLines int) ([]string, error) {
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
var lines []string
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
lines = append(lines, scanner.Text())
|
||||
if len(lines) >= maxLines*2 {
|
||||
// 只保留最后maxLines行
|
||||
lines = lines[len(lines)-maxLines:]
|
||||
}
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 返回最后maxLines行
|
||||
if len(lines) > maxLines {
|
||||
return lines[len(lines)-maxLines:], nil
|
||||
}
|
||||
return lines, nil
|
||||
}
|
||||
|
||||
// 去重日志
|
||||
func deduplicateLogs(logs []string) []string {
|
||||
seen := make(map[string]bool)
|
||||
result := make([]string, 0)
|
||||
for i := len(logs) - 1; i >= 0; i-- {
|
||||
if !seen[logs[i]] {
|
||||
seen[logs[i]] = true
|
||||
result = append([]string{logs[i]}, result...)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// 简单的整数解析(logs.go专用)
|
||||
func parseIntLogs(s string) (int, error) {
|
||||
var n int
|
||||
for _, char := range s {
|
||||
if char >= '0' && char <= '9' {
|
||||
n = n*10 + int(char-'0')
|
||||
} else {
|
||||
return 0, io.EOF
|
||||
}
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// 日志中间件 - 记录请求日志
|
||||
func LoggingMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
start := time.Now()
|
||||
path := c.Request.URL.Path
|
||||
query := c.Request.URL.RawQuery
|
||||
ip := c.ClientIP()
|
||||
|
||||
c.Next()
|
||||
|
||||
latency := time.Since(start)
|
||||
method := c.Request.Method
|
||||
statusCode := c.Writer.Status()
|
||||
|
||||
logLine := formatLogLine(start, method, statusCode, latency, path, query, ip)
|
||||
AddLogToBuffer(logLine)
|
||||
}
|
||||
}
|
||||
|
||||
func formatLogLine(timestamp time.Time, method string, statusCode int, latency time.Duration, path, query, ip string) string {
|
||||
if query != "" {
|
||||
path = path + "?" + query
|
||||
}
|
||||
// 使用Asia/Shanghai时区格式化时间
|
||||
loc, _ := time.LoadLocation("Asia/Shanghai")
|
||||
shanghaiTime := timestamp.In(loc)
|
||||
// 格式化日志:只包含一个时间戳
|
||||
return fmt.Sprintf("[%s] %s %s :: %s %d %s",
|
||||
shanghaiTime.Format("2006-01-02 15:04:05"),
|
||||
method,
|
||||
path,
|
||||
ip,
|
||||
statusCode,
|
||||
latency.String(),
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user