MarketingSystemDataExportTool/server/internal/logging/logging.go

143 lines
3.2 KiB
Go

// Package logging 提供统一的日志功能
package logging
import (
"encoding/json"
"fmt"
"io"
"log"
"os"
"path/filepath"
"runtime"
"time"
)
// ==================== 日志级别 ====================
// Level 日志级别
type Level string
const (
LevelDebug Level = "DEBUG"
LevelInfo Level = "INFO"
LevelWarn Level = "WARN"
LevelError Level = "ERROR"
)
// ==================== 初始化 ====================
// Init 初始化日志系统
func Init(dir string) error {
if dir == "" {
dir = "log"
}
if err := os.MkdirAll(dir, 0755); err != nil {
return err
}
name := fmt.Sprintf("server-%s.log", time.Now().Format("20060102"))
p := filepath.Join(dir, name)
f, err := os.OpenFile(p, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
return err
}
mw := io.MultiWriter(os.Stdout, f)
log.SetOutput(mw)
log.SetFlags(0)
return nil
}
// ==================== 结构化日志 ====================
// JSON 输出JSON格式日志
func JSON(level string, fields map[string]interface{}) {
m := map[string]interface{}{"level": level, "ts": time.Now().Format(time.RFC3339)}
for k, v := range fields {
m[k] = v
}
b, _ := json.Marshal(m)
log.Println(string(b))
}
// ==================== 便捷方法 ====================
// Debug 输出Debug级别日志
func Debug(event string, fields map[string]interface{}) {
if fields == nil {
fields = make(map[string]interface{})
}
fields["event"] = event
JSON(string(LevelDebug), fields)
}
// Info 输出Info级别日志
func Info(event string, fields map[string]interface{}) {
if fields == nil {
fields = make(map[string]interface{})
}
fields["event"] = event
JSON(string(LevelInfo), fields)
}
// Warn 输出Warn级别日志
func Warn(event string, fields map[string]interface{}) {
if fields == nil {
fields = make(map[string]interface{})
}
fields["event"] = event
JSON(string(LevelWarn), fields)
}
// Error 输出Error级别日志
func Error(event string, err error, fields map[string]interface{}) {
if fields == nil {
fields = make(map[string]interface{})
}
fields["event"] = event
if err != nil {
fields["error"] = err.Error()
}
// 添加调用位置信息
_, file, line, ok := runtime.Caller(1)
if ok {
fields["caller"] = fmt.Sprintf("%s:%d", filepath.Base(file), line)
}
JSON(string(LevelError), fields)
}
// ==================== 专用日志 ====================
// DBError 数据库错误日志
func DBError(action string, jobID uint64, err error) {
Error("db_error", err, map[string]interface{}{
"action": action,
"job_id": jobID,
})
}
// ExportProgress 导出进度日志
func ExportProgress(jobID uint64, totalRows int64) {
Info("progress_update", map[string]interface{}{
"job_id": jobID,
"total_rows": totalRows,
})
}
// ExportSQL 导出SQL日志
func ExportSQL(jobID uint64, datasource, mainTable, sql string, args []interface{}) {
Info("export_sql", map[string]interface{}{
"job_id": jobID,
"datasource": datasource,
"main_table": mainTable,
"sql": sql,
"args": args,
})
}
// FieldsRemoved 字段移除日志
func FieldsRemoved(event string, removed []string, reason string) {
Info(event, map[string]interface{}{
"removed": removed,
"reason": reason,
})
}