主要更改: 1. 核心重命名 - Seqlog -> LogHub (更准确地反映其作为日志中枢的角色) - NewSeqlog() -> NewLogHub() - LogCursor -> ProcessCursor (更准确地反映其用于处理场景) - seqlog_manager.go -> loghub.go (文件名与结构体名对应) 2. TopicProcessor.Reset 增强 - 如果正在运行且没有待处理的日志,会自动停止后重置 - 如果有待处理的日志,返回详细错误(显示已处理/总记录数) - 简化了 LogHub.ResetTopic,移除显式 Stop 调用 3. 新增查询方法 - TopicProcessor.QueryFromFirst(count) - 从第一条记录向索引递增方向查询 - TopicProcessor.QueryFromLast(count) - 从最后一条记录向索引递减方向查询 - LogHub.QueryFromFirst(topic, count) - LogHub.QueryFromLast(topic, count) 4. 测试覆盖 - 添加 query_test.go - QueryFromProcessing 测试 - 添加 TestQueryFromFirstAndLast - TopicProcessor 查询测试 - 添加 TestLogHubQueryFromFirstAndLast - LogHub 查询测试 - 添加 TestTopicResetWithPendingRecords - Reset 增强功能测试 5. 示例代码 - 添加 example/get_record/ - 演示 QueryFromProcessing 用法 - 更新所有示例以使用 LogHub 和新 API 所有测试通过 ✅ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
83 lines
2.9 KiB
Go
83 lines
2.9 KiB
Go
package seqlog
|
||
|
||
import "github.com/google/uuid"
|
||
|
||
// seqlog 是一个 Go 语言日志收集和处理库
|
||
//
|
||
// 核心特性:
|
||
// - 单文件日志处理:专注于单个日志文件的读取和处理
|
||
// - 游标尺机制:通过游标跟踪日志文件的读取位置,支持断点续读
|
||
// - 自动恢复:程序重启时自动发现已存在的日志文件并从上次位置继续处理
|
||
// - 日志收集:提供高效的日志收集和解析能力
|
||
// - tail -f 模式:支持持续监控日志文件的新增内容
|
||
// - UUID 去重:每条日志自动生成唯一 UUID,便于外部去重
|
||
// - slog 集成:内置 slog.Logger 支持,提供结构化日志记录
|
||
// - 统计功能:提供可恢复的统计信息,包括写入/处理次数、字节数、错误计数等
|
||
// - 双向查询:支持基于当前处理位置的向前/向后查询,自动标注记录状态
|
||
// - 事件通知:支持订阅各种事件(写入、处理、启动、停止等),实时状态变化通知
|
||
//
|
||
// 使用示例:
|
||
//
|
||
// // 写入日志
|
||
// writer, _ := seqlog.NewLogWriter("app.log")
|
||
// offset, _ := writer.Append([]byte("log message"))
|
||
//
|
||
// // 读取日志
|
||
// cursor, _ := seqlog.NewCursor("app.log")
|
||
// defer cursor.Close()
|
||
// for {
|
||
// rec, err := cursor.Next()
|
||
// if err != nil {
|
||
// break
|
||
// }
|
||
// // rec.UUID 是自动生成的唯一标识符,可用于去重
|
||
// fmt.Printf("UUID: %s, Data: %s\n", rec.UUID, string(rec.Data))
|
||
// }
|
||
//
|
||
// // tail -f 模式
|
||
// handler := func(rec *Record) error {
|
||
// fmt.Println(string(rec.Data))
|
||
// return nil
|
||
// }
|
||
// tailer, _ := seqlog.NewTailer("app.log", handler, nil)
|
||
// tailer.Start()
|
||
//
|
||
// // 使用 LogHub 管理器(带 slog 支持和自动恢复)
|
||
// logger := slog.Default()
|
||
// handler := func(topic string, rec *seqlog.Record) error {
|
||
// fmt.Printf("[%s] %s\n", topic, string(rec.Data))
|
||
// return nil
|
||
// }
|
||
// seq := seqlog.NewLogHub("/tmp/logs", logger, handler)
|
||
// seq.Start() // 自动发现并恢复已存在的日志文件
|
||
// seq.Write("app", []byte("application log"))
|
||
//
|
||
// // 获取统计信息
|
||
// stats, _ := seq.GetTopicStats("app")
|
||
// fmt.Printf("写入: %d 条, %d 字节\n", stats.WriteCount, stats.WriteBytes)
|
||
//
|
||
// // 查询记录
|
||
// query, _ := seq.NewTopicQuery("app")
|
||
// defer query.Close()
|
||
// current, _ := query.GetCurrent() // 获取当前处理位置
|
||
// backward, _ := query.QueryBackward(5) // 向后查询 5 条
|
||
// forward, _ := query.QueryForward(5) // 向前查询 5 条
|
||
//
|
||
// // 订阅事件
|
||
// seq.Subscribe("app", seqlog.EventWriteSuccess, func(event *seqlog.Event) {
|
||
// fmt.Printf("写入成功: offset=%d\n", event.Position)
|
||
// })
|
||
//
|
||
// seq.Stop()
|
||
|
||
// Record 日志记录
|
||
//
|
||
// 存储格式:[4B len][4B CRC][16B UUID][data]
|
||
// 注意:Offset 不存储在数据文件中,而是由索引文件管理
|
||
type Record struct {
|
||
Len uint32 // 数据长度
|
||
CRC uint32 // CRC 校验和
|
||
UUID uuid.UUID // UUID,用于去重
|
||
Data []byte // 实际数据
|
||
}
|