// 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, }) }