type Logger interface {
// 核心日志方法
Debug(msg string, fields ...zap.Field)
Info(msg string, fields ...zap.Field)
Warn(msg string, fields ...zap.Field)
Error(msg string, fields ...zap.Field)
Fatal(msg string, fields ...zap.Field)
// 便捷方法
With(fields ...zap.Field) Logger
Named(name string) Logger
// 同步方法
Sync() error
}
type AuditLogger interface {
// 记录审计事件
Record(entry *AuditEntry) error
// 查询审计日志
Query(filter *AuditFilter) ([]*AuditEntry, error)
// 清理过期数据
Cleanup(retention time.Duration) error
// 同步方法
Sync() error
}
type LoggerOption func(*loggerConfig)
func WithLevel(level zapcore.Level) LoggerOption {
return func(c *loggerConfig) {
c.level = level
}
}
func WithOutputPaths(paths ...string) LoggerOption {
return func(c *loggerConfig) {
c.outputPaths = paths
}
}
func WithDevelopment(dev bool) LoggerOption {
return func(c *loggerConfig) {
c.development = dev
}
}
type AuditOption func(*auditConfig)
func WithDatabasePath(path string) AuditOption {
return func(c *auditConfig) {
c.dbPath = path
}
}
func WithRetention(days int) AuditOption {
return func(c *auditConfig) {
c.retentionDays = days
}
}
func NewLogger(opts ...LoggerOption) (Logger, error) {
config := &loggerConfig{
level: zapcore.InfoLevel,
development: false,
encoding: "json",
outputPaths: []string{"stdout"},
}
for _, opt := range opts {
opt(config)
}
return newZapLogger(config)
}
func NewAuditLogger(opts ...AuditOption) (AuditLogger, error) {
config := &auditConfig{
enabled: true,
dbPath: "audit.db",
retentionDays: 90,
bufferSize: 1000,
}
for _, opt := range opts {
opt(config)
}
return newSQLiteAuditLogger(config)
}
type AuditEntry struct {
ID string `json:"id"`
Timestamp time.Time `json:"timestamp"`
UserID string `json:"user_id,omitempty"`
Username string `json:"username,omitempty"`
Action string `json:"action"`
Resource string `json:"resource,omitempty"`
Details string `json:"details,omitempty"`
IP string `json:"ip,omitempty"`
UserAgent string `json:"user_agent,omitempty"`
Success bool `json:"success"`
Error string `json:"error,omitempty"`
}
type AuditFilter struct {
UserID string
Action string
Resource string
StartTime *time.Time
EndTime *time.Time
Success *bool
Limit int
Offset int
}
// 创建日志器
logger, err := NewLogger(
WithLevel(zapcore.DebugLevel),
WithDevelopment(true),
WithOutputPaths("stdout", "app.log"),
)
if err != nil {
panic(err)
}
defer logger.Sync()
// 使用日志
logger.Info("用户登录",
zap.String("user_id", "123"),
zap.String("ip", "192.168.1.1"))
// 创建审计日志器
audit, err := NewAuditLogger(
WithDatabasePath("audit.db"),
WithRetention(90),
)
if err != nil {
panic(err)
}
defer audit.Sync()
// 记录审计事件
err = audit.Record(&AuditEntry{
UserID: "123",
Username: "john_doe",
Action: "login",
IP: "192.168.1.1",
Success: true,
})
// 创建带上下文的日志器
userLogger := logger.Named("user_service").With(
zap.String("user_id", "123"),
zap.String("request_id", "req_001"),
)
// 在函数中使用
func processUser(ctx context.Context, userID string) error {
logger := userLogger.With(zap.String("operation", "process_user"))
logger.Info("开始处理用户")
defer logger.Info("处理用户完成")
// 处理逻辑
if err := doSomething(); err != nil {
logger.Error("处理失败", zap.Error(err))
return err
}
return nil
}
func AuditMiddleware(audit AuditLogger) gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()
// 处理请求
c.Next()
// 记录审计
entry := &AuditEntry{
UserID: getUserID(c),
Action: c.Request.Method + " " + c.Request.URL.Path,
IP: c.ClientIP(),
UserAgent: c.Request.UserAgent(),
Success: c.Writer.Status() < 400,
}
if err := audit.Record(entry); err != nil {
// 审计失败不应该影响正常业务
c.Error(err)
}
// 记录访问日志
duration := time.Since(start)
logger.Info("HTTP请求",
zap.String("method", c.Request.Method),
zap.String("path", c.Request.URL.Path),
zap.Int("status", c.Writer.Status()),
zap.Duration("duration", duration),
)
}
}
type LoggerError struct {
Op string // 操作
Err error // 底层错误
}
func (e *LoggerError) Error() string {
return fmt.Sprintf("logger %s: %v", e.Op, e.Err)
}
func (e *LoggerError) Unwrap() error {
return e.Err
}
// 检查是否为日志错误
var loggerErr *LoggerError
if errors.As(err, &loggerErr) {
// 处理日志相关错误
}
// 检查特定操作的错误
if errors.Is(err, ErrAuditDisabled) {
// 审计功能被禁用
}
func TestLogger(t *testing.T) {
logger, err := NewLogger(WithDevelopment(true))
require.NoError(t, err)
defer logger.Sync()
// 测试日志输出
logger.Info("测试消息", zap.String("key", "value"))
// 验证日志内容(通过钩子或缓冲区)
}
func TestAuditLogger(t *testing.T) {
audit, err := NewAuditLogger(WithDatabasePath(":memory:"))
require.NoError(t, err)
defer audit.Sync()
// 插入测试数据
entry := &AuditEntry{
UserID: "test_user",
Action: "test_action",
Success: true,
}
err = audit.Record(entry)
require.NoError(t, err)
// 查询验证
entries, err := audit.Query(&AuditFilter{
UserID: "test_user",
Limit: 10,
})
require.NoError(t, err)
require.Len(t, entries, 1)
}
var auditEntryPool = sync.Pool{
New: func() interface{} {
return &AuditEntry{}
},
}
func getAuditEntry() *AuditEntry {
return auditEntryPool.Get().(*AuditEntry)
}
func putAuditEntry(entry *AuditEntry) {
// 重置对象
*entry = AuditEntry{}
auditEntryPool.Put(entry)
}
type asyncAuditLogger struct {
AuditLogger
entries chan *AuditEntry
done chan struct{}
}
func (a *asyncAuditLogger) Record(entry *AuditEntry) error {
select {
case a.entries <- entry:
return nil
case <-a.done:
return ErrLoggerClosed
default:
return ErrBufferFull
}
}
// Package logger 提供基于Zap的高性能日志和审计功能
//
// 设计理念:
// - 简单性: 最小化API,专注于核心功能
// - 性能: 利用Zap的高性能特性
// - 可组合性: 支持中间件和选项模式
// - 并发安全: 所有操作都是goroutine安全的
//
// 基本使用:
//
// logger, _ := logger.NewLogger(logger.WithDevelopment(true))
// logger.Info("应用启动")
// defer logger.Sync()
//
// 审计使用:
//
// audit, _ := logger.NewAuditLogger(logger.WithRetention(90))
// audit.Record(&logger.AuditEntry{Action: "login", Success: true})
package logger
这个重新设计的日志系统完全遵循Go语言的核心理念,提供了简单、高效、可组合的日志和审计解决方案。