gomog/pkg/logger/hook.go

167 lines
3.3 KiB
Go

package logger
import (
"fmt"
"io"
"os"
"sync"
)
// FileHook 文件钩子 - 将日志写入文件
type FileHook struct {
mu sync.Mutex
file *os.File
output io.Writer
levels []Level
formatter func(*Entry) string
}
// NewFileHook 创建文件钩子
func NewFileHook(filename string, levels []Level) (*FileHook, error) {
file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
return nil, err
}
return &FileHook{
file: file,
output: file,
levels: levels,
formatter: func(e *Entry) string {
return e.format()
},
}, nil
}
// Fire 触发钩子
func (h *FileHook) Fire(entry *Entry) error {
h.mu.Lock()
defer h.mu.Unlock()
_, err := h.output.Write([]byte(h.formatter(entry)))
return err
}
// Levels 返回支持的日志级别
func (h *FileHook) Levels() []Level {
return h.levels
}
// Close 关闭文件钩子
func (h *FileHook) Close() error {
h.mu.Lock()
defer h.mu.Unlock()
return h.file.Close()
}
// ErrorHook 错误钩子 - 专门记录错误日志
type ErrorHook struct {
mu sync.Mutex
output io.Writer
errors []string
maxSize int
}
// NewErrorHook 创建错误钩子
func NewErrorHook(output io.Writer, maxSize int) *ErrorHook {
return &ErrorHook{
output: output,
errors: make([]string, 0, maxSize),
maxSize: maxSize,
}
}
// Fire 触发钩子
func (h *ErrorHook) Fire(entry *Entry) error {
h.mu.Lock()
defer h.mu.Unlock()
msg := fmt.Sprintf("[%s] %s", entry.Time.Format("2006-01-02 15:04:05"), entry.Message)
// 添加到缓冲区
if len(h.errors) >= h.maxSize {
h.errors = h.errors[1:]
}
h.errors = append(h.errors, msg)
// 写入输出
_, err := h.output.Write([]byte(msg + "\n"))
return err
}
// Levels 返回支持的日志级别
func (h *ErrorHook) Levels() []Level {
return []Level{ERROR, FATAL}
}
// GetErrors 获取最近的错误
func (h *ErrorHook) GetErrors() []string {
h.mu.Lock()
defer h.mu.Unlock()
return h.errors
}
// PerformanceHook 性能钩子 - 记录慢操作
type PerformanceHook struct {
mu sync.Mutex
slowOps []map[string]interface{}
thresholdMs float64
}
// NewPerformanceHook 创建性能钩子
func NewPerformanceHook(thresholdMs float64) *PerformanceHook {
return &PerformanceHook{
slowOps: make([]map[string]interface{}, 0, 100),
thresholdMs: thresholdMs,
}
}
// Fire 触发钩子
func (h *PerformanceHook) Fire(entry *Entry) error {
// 只记录包含 duration 字段的日志
if duration, ok := entry.Fields["duration_ms"]; ok {
var d float64
switch v := duration.(type) {
case float64:
d = v
case int:
d = float64(v)
case int64:
d = float64(v)
default:
return nil
}
if d > h.thresholdMs {
h.mu.Lock()
slowOp := map[string]interface{}{
"time": entry.Time,
"operation": entry.Fields["operation"],
"duration": duration,
"message": entry.Message,
}
if len(h.slowOps) >= 100 {
h.slowOps = h.slowOps[1:]
}
h.slowOps = append(h.slowOps, slowOp)
h.mu.Unlock()
}
}
return nil
}
// Levels 返回支持的日志级别
func (h *PerformanceHook) Levels() []Level {
return []Level{INFO, WARN, ERROR}
}
// GetSlowOps 获取慢操作列表
func (h *PerformanceHook) GetSlowOps() []map[string]interface{} {
h.mu.Lock()
defer h.mu.Unlock()
return h.slowOps
}