feat: adjust comment
This commit is contained in:
@@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// globalTinyLogManager keeps track of all active TinyLog instances
|
||||
// globalTinyLogManager 跟踪所有活跃的 TinyLog 实例
|
||||
globalTinyLogManager = &TinyLogManager{
|
||||
logs: make(map[uint]*TinyLog),
|
||||
}
|
||||
@@ -43,12 +43,12 @@ func (m *TinyLogManager) Get(logID uint) *TinyLog {
|
||||
return m.logs[logID]
|
||||
}
|
||||
|
||||
// GetActiveLog returns an active TinyLog by its ID
|
||||
// GetActiveLog 通过 ID 获取活跃的 TinyLog 实例
|
||||
func GetActiveLog(logID uint) *TinyLog {
|
||||
return globalTinyLogManager.Get(logID)
|
||||
}
|
||||
|
||||
// TinyLog is a high-performance, low-memory log collector
|
||||
// TinyLog 是一个高性能、低内存占用的日志收集器
|
||||
type TinyLog struct {
|
||||
LogID uint
|
||||
mu sync.RWMutex
|
||||
@@ -60,7 +60,7 @@ type TinyLog struct {
|
||||
closed bool
|
||||
}
|
||||
|
||||
// NewTinyLog creates a new TinyLog instance backed by a temporary file and registers it
|
||||
// NewTinyLog 创建一个新的 TinyLog 实例(基于临时文件存储)并注册它
|
||||
func NewTinyLog(logID uint) (*TinyLog, error) {
|
||||
f, err := os.CreateTemp("", "task_log_*.log")
|
||||
if err != nil {
|
||||
@@ -78,7 +78,7 @@ func NewTinyLog(logID uint) (*TinyLog, error) {
|
||||
return tl, nil
|
||||
}
|
||||
|
||||
// Write implements io.Writer
|
||||
// Write 实现 io.Writer 接口
|
||||
func (l *TinyLog) Write(p []byte) (n int, err error) {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
@@ -87,7 +87,7 @@ func (l *TinyLog) Write(p []byte) (n int, err error) {
|
||||
return 0, os.ErrClosed
|
||||
}
|
||||
|
||||
// 1. Combine with remainder from previous call
|
||||
// 1. 合并上次调用剩余的字节(可能是半个 UTF-8 字符)
|
||||
originalInputLen := len(p)
|
||||
payload := p
|
||||
if len(l.remainder) > 0 {
|
||||
@@ -95,13 +95,13 @@ func (l *TinyLog) Write(p []byte) (n int, err error) {
|
||||
l.remainder = nil
|
||||
}
|
||||
|
||||
// 2. Identify trailing partial UTF-8 sequence
|
||||
// 2. 识别结尾不完整的 UTF-8 序列
|
||||
lastSafe := len(payload)
|
||||
// UTF-8 characters are max 4 bytes. Check the last few bytes.
|
||||
// UTF-8 字符最多 4 字节,检查最后几个字节
|
||||
for i := len(payload) - 1; i >= 0 && i >= len(payload)-4; i-- {
|
||||
if utf8.RuneStart(payload[i]) {
|
||||
if !utf8.FullRune(payload[i:]) {
|
||||
// Indeed a partial rune at the end
|
||||
// 发现末尾存在不完整字符
|
||||
lastSafe = i
|
||||
l.remainder = make([]byte, len(payload)-i)
|
||||
copy(l.remainder, payload[i:])
|
||||
@@ -110,29 +110,29 @@ func (l *TinyLog) Write(p []byte) (n int, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// If the entire payload is partial and not longer than a max UTF-8 char,
|
||||
// keep it all for the next call.
|
||||
// 如果整个负载都不完整且不超过一个 UTF-8 字符的最大长度,
|
||||
// 则全部保留到下次调用
|
||||
if lastSafe == 0 && len(l.remainder) > 0 {
|
||||
return originalInputLen, nil
|
||||
}
|
||||
|
||||
// 3. Convert only the complete part to UTF-8
|
||||
// 3. 仅将完整的部分转换为 UTF-8
|
||||
text := utils.ToUTF8(payload[:lastSafe])
|
||||
data := []byte(text)
|
||||
|
||||
// 4. Write to file buffer
|
||||
// 4. 写入文件缓冲区
|
||||
_, err = l.writer.Write(data)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// 5. Broadcast to subscribers
|
||||
// 5. 广播给所有订阅者
|
||||
if len(l.subscribers) > 0 {
|
||||
for _, ch := range l.subscribers {
|
||||
select {
|
||||
case ch <- data:
|
||||
default:
|
||||
// Drop message if subscriber is too slow to avoid blocking writer
|
||||
// 如果订阅者处理太慢,丢弃消息以避免阻塞写入
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,7 +140,7 @@ func (l *TinyLog) Write(p []byte) (n int, err error) {
|
||||
return originalInputLen, nil
|
||||
}
|
||||
|
||||
// Subscribe returns a channel that receives log chunks in real-time
|
||||
// Subscribe 返回一个实时接收日志块的通道
|
||||
func (l *TinyLog) Subscribe() chan []byte {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
@@ -150,7 +150,7 @@ func (l *TinyLog) Subscribe() chan []byte {
|
||||
return ch
|
||||
}
|
||||
|
||||
// Unsubscribe removes a subscriber
|
||||
// Unsubscribe 移除订阅者
|
||||
func (l *TinyLog) Unsubscribe(ch chan []byte) {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
@@ -164,7 +164,7 @@ func (l *TinyLog) Unsubscribe(ch chan []byte) {
|
||||
}
|
||||
}
|
||||
|
||||
// Close finishes writing and closes the file, and unregisters itself
|
||||
// Close 完成写入,关闭文件并注销实例
|
||||
func (l *TinyLog) Close() error {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
@@ -173,13 +173,13 @@ func (l *TinyLog) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Process any remaining bytes
|
||||
// 处理剩余的字节
|
||||
if len(l.remainder) > 0 {
|
||||
text := utils.ToUTF8(l.remainder)
|
||||
data := []byte(text)
|
||||
_, _ = l.writer.Write(data)
|
||||
|
||||
// Also notify subscribers of the last bit
|
||||
// 通知订阅者最后一部分内容
|
||||
for _, ch := range l.subscribers {
|
||||
select {
|
||||
case ch <- data:
|
||||
@@ -189,12 +189,12 @@ func (l *TinyLog) Close() error {
|
||||
l.remainder = nil
|
||||
}
|
||||
|
||||
// Flush buffer to file
|
||||
// 将缓冲区刷新到文件
|
||||
if err := l.writer.Flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Close all subscribers
|
||||
// 关闭所有订阅者通道
|
||||
for _, ch := range l.subscribers {
|
||||
close(ch)
|
||||
}
|
||||
@@ -205,14 +205,14 @@ func (l *TinyLog) Close() error {
|
||||
return l.file.Close()
|
||||
}
|
||||
|
||||
// CompressAndCleanup reads the temporary file, compresses it, returns the result, and removes the file
|
||||
// CompressAndCleanup 读取临时文件,进行压缩处理,返回结果并删除临时文件
|
||||
func (l *TinyLog) CompressAndCleanup() (string, error) {
|
||||
// Ensure closed
|
||||
if !l.closed {
|
||||
l.Close()
|
||||
}
|
||||
|
||||
// Open temp file for reading
|
||||
// 打开临时文件进行读取
|
||||
f, err := os.Open(l.path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -222,17 +222,17 @@ func (l *TinyLog) CompressAndCleanup() (string, error) {
|
||||
os.Remove(l.path) // Cleanup
|
||||
}()
|
||||
|
||||
// Create buffer for compressed output
|
||||
// 创建压缩输出缓冲区
|
||||
var buf bytes.Buffer
|
||||
b64Writer := base64.NewEncoder(base64.StdEncoding, &buf)
|
||||
zlibWriter := zlib.NewWriter(b64Writer)
|
||||
|
||||
// Stream: File -> Zlib -> Base64 -> Buffer
|
||||
// 流处理: 文件 -> Zlib -> Base64 -> 缓冲区
|
||||
if _, err := io.Copy(zlibWriter, f); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Close generic writers to flush data
|
||||
// 关闭写入器以刷新数据
|
||||
if err := zlibWriter.Close(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -243,12 +243,12 @@ func (l *TinyLog) CompressAndCleanup() (string, error) {
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// ReadLastLines returns the last n lines of the log
|
||||
// ReadLastLines 返回日志的最后 n 行
|
||||
func (l *TinyLog) ReadLastLines(n int) ([]byte, error) {
|
||||
l.mu.RLock()
|
||||
defer l.mu.RUnlock()
|
||||
|
||||
// Flush writer to ensure file on disk is up to date
|
||||
// 刷新写入器以确保磁盘上的文件是最新的
|
||||
_ = l.writer.Flush()
|
||||
|
||||
stat, err := os.Stat(l.path)
|
||||
@@ -257,7 +257,7 @@ func (l *TinyLog) ReadLastLines(n int) ([]byte, error) {
|
||||
}
|
||||
|
||||
size := stat.Size()
|
||||
var limit int64 = 65536 // Max 64KB for "last 100 lines" preview
|
||||
var limit int64 = 65536 // 预览限制:最大 64KB
|
||||
if size < limit {
|
||||
limit = size
|
||||
}
|
||||
@@ -282,7 +282,7 @@ func (l *TinyLog) ReadLastLines(n int) ([]byte, error) {
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// GetPath returns the temporary file path
|
||||
// GetPath 返回临时文件路径
|
||||
func (l *TinyLog) GetPath() string {
|
||||
return l.path
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user