chore: add log size limit
This commit is contained in:
@@ -169,6 +169,8 @@ const (
|
|||||||
PingPeriod = (PongWait * 9) / 10
|
PingPeriod = (PongWait * 9) / 10
|
||||||
// MaxMessageSize 允许的最大消息大小
|
// MaxMessageSize 允许的最大消息大小
|
||||||
MaxMessageSize = 1024 * 1024 // 1MB
|
MaxMessageSize = 1024 * 1024 // 1MB
|
||||||
|
// MaxLogSize 允许的最大日志大小 (保留末尾 10MB)
|
||||||
|
MaxLogSize = 10 * 1024 * 1024 // 10MB
|
||||||
)
|
)
|
||||||
|
|
||||||
// TablePrefix 表前缀,从配置文件读取
|
// TablePrefix 表前缀,从配置文件读取
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/engigu/baihu-panel/internal/logger"
|
"github.com/engigu/baihu-panel/internal/logger"
|
||||||
"github.com/engigu/baihu-panel/internal/models"
|
"github.com/engigu/baihu-panel/internal/models"
|
||||||
"github.com/engigu/baihu-panel/internal/systime"
|
"github.com/engigu/baihu-panel/internal/systime"
|
||||||
|
"github.com/engigu/baihu-panel/internal/constant"
|
||||||
"github.com/engigu/baihu-panel/internal/utils"
|
"github.com/engigu/baihu-panel/internal/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -161,8 +162,9 @@ func (s *TaskLogService) ProcessTaskCompletion(taskLog *models.TaskLog) error {
|
|||||||
|
|
||||||
// CreateTaskLogFromAgentResult 从 Agent 结果创建任务日志
|
// CreateTaskLogFromAgentResult 从 Agent 结果创建任务日志
|
||||||
func (s *TaskLogService) CreateTaskLogFromAgentResult(result *models.AgentTaskResult) (*models.TaskLog, error) {
|
func (s *TaskLogService) CreateTaskLogFromAgentResult(result *models.AgentTaskResult) (*models.TaskLog, error) {
|
||||||
// 压缩输出
|
// 裁剪并压缩输出
|
||||||
compressed, err := utils.CompressToBase64(result.Output)
|
trimmedOutput := utils.TrimLog(result.Output, constant.MaxLogSize)
|
||||||
|
compressed, err := utils.CompressToBase64(trimmedOutput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("[TaskLog] 压缩日志失败: %v", err)
|
logger.Errorf("[TaskLog] 压缩日志失败: %v", err)
|
||||||
compressed = ""
|
compressed = ""
|
||||||
@@ -202,8 +204,9 @@ func (s *TaskLogService) CreateTaskLogFromLocalExecution(taskID string, command,
|
|||||||
if isCompressed {
|
if isCompressed {
|
||||||
compressed = output
|
compressed = output
|
||||||
} else {
|
} else {
|
||||||
// 压缩输出
|
// 裁剪并压缩输出
|
||||||
compressed, err = utils.CompressToBase64(output)
|
trimmedOutput := utils.TrimLog(output, constant.MaxLogSize)
|
||||||
|
compressed, err = utils.CompressToBase64(trimmedOutput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("[TaskLog] 压缩日志失败: %v", err)
|
logger.Errorf("[TaskLog] 压缩日志失败: %v", err)
|
||||||
compressed = ""
|
compressed = ""
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/engigu/baihu-panel/internal/constant"
|
||||||
"github.com/engigu/baihu-panel/internal/utils"
|
"github.com/engigu/baihu-panel/internal/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -236,6 +238,33 @@ func (l *TinyLog) CompressAndCleanup() (string, error) {
|
|||||||
zw := utils.GetZlibWriter(b64Writer)
|
zw := utils.GetZlibWriter(b64Writer)
|
||||||
defer utils.PutZlibWriter(zw)
|
defer utils.PutZlibWriter(zw)
|
||||||
|
|
||||||
|
// 获取文件大小
|
||||||
|
stat, err := f.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
size := stat.Size()
|
||||||
|
maxSize := int64(constant.MaxLogSize)
|
||||||
|
if maxSize < 1024*1024 {
|
||||||
|
maxSize = 1024 * 1024
|
||||||
|
}
|
||||||
|
|
||||||
|
var readStart int64 = 0
|
||||||
|
if size > maxSize {
|
||||||
|
readStart = size - maxSize
|
||||||
|
// 写入一条截断提示
|
||||||
|
truncatedMsg := fmt.Sprintf("\n\n[System] 日志过长,已自动截断,仅保留末尾 %d MB...\n\n", maxSize/1024/1024)
|
||||||
|
if _, err := zw.Write([]byte(truncatedMsg)); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if readStart > 0 {
|
||||||
|
if _, err := f.Seek(readStart, io.SeekStart); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 流处理: 文件 -> Zlib -> Base64 -> 缓冲区
|
// 流处理: 文件 -> Zlib -> Base64 -> 缓冲区
|
||||||
if _, err := io.Copy(zw, f); err != nil {
|
if _, err := io.Copy(zw, f); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TailBuffer 是一个只保留最后 N 字节数据的缓冲区
|
||||||
|
type TailBuffer struct {
|
||||||
|
limit int
|
||||||
|
data []byte
|
||||||
|
size int // 当前实际存储的大小
|
||||||
|
pos int // 下一个写入位置 (针对环形缓冲区逻辑,但这里为了简单使用切片重排)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTailBuffer 创建一个限制大小为 limit 的尾部缓冲区
|
||||||
|
func NewTailBuffer(limit int) *TailBuffer {
|
||||||
|
return &TailBuffer{
|
||||||
|
limit: limit,
|
||||||
|
data: make([]byte, 0, limit),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write 实现 io.Writer 接口
|
||||||
|
func (b *TailBuffer) Write(p []byte) (n int, err error) {
|
||||||
|
n = len(p)
|
||||||
|
if n >= b.limit {
|
||||||
|
// 如果单次写入就超过了限制,直接取最后 limit 字节
|
||||||
|
b.data = append(b.data[:0], p[n-b.limit:]...)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
available := b.limit - len(b.data)
|
||||||
|
if n <= available {
|
||||||
|
// 空间足够,直接追加
|
||||||
|
b.data = append(b.data, p...)
|
||||||
|
} else {
|
||||||
|
// 空间不足,需要移除旧数据
|
||||||
|
toRemove := n - available
|
||||||
|
b.data = append(b.data[toRemove:], p...)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytes 返回缓冲区内的所有数据
|
||||||
|
func (b *TailBuffer) Bytes() []byte {
|
||||||
|
return b.data
|
||||||
|
}
|
||||||
|
|
||||||
|
// String 返回缓冲区内的字符串表示
|
||||||
|
func (b *TailBuffer) String() string {
|
||||||
|
return string(b.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len 返回当前存储的数据长度
|
||||||
|
func (b *TailBuffer) Len() int {
|
||||||
|
return len(b.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TrimLog 裁剪日志,保留末尾指定大小
|
||||||
|
func TrimLog(content string, limit int) string {
|
||||||
|
if len(content) <= limit {
|
||||||
|
return content
|
||||||
|
}
|
||||||
|
// 简单裁剪,不考虑字符完整性,因为这是针对大文本的保护
|
||||||
|
return fmt.Sprintf("\n\n[System] 日志过长,已自动截断,仅保留末尾 %d MB...\n\n", limit/1024/1024) + content[len(content)-limit:]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user