mirror of
https://github.com/skyle1995/NetworkAuth.git
synced 2026-05-25 02:24:05 +08:00
255 lines
7.8 KiB
Go
255 lines
7.8 KiB
Go
package utils
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"log"
|
||
"runtime"
|
||
"time"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
// ErrorResponse 统一的错误响应结构
|
||
// 用于标准化API错误响应格式
|
||
type ErrorResponse struct {
|
||
Success bool `json:"success"` // 请求是否成功,错误响应时固定为false
|
||
Message string `json:"message"` // 错误消息描述
|
||
ErrorCode string `json:"error_code,omitempty"` // 错误代码,用于客户端识别错误类型
|
||
Data interface{} `json:"data"` // 附加数据,可为空
|
||
Timestamp int64 `json:"timestamp"` // 响应时间戳
|
||
}
|
||
|
||
// SuccessResponse 统一的成功响应结构
|
||
// 用于标准化API成功响应格式
|
||
type SuccessResponse struct {
|
||
Success bool `json:"success"` // 请求是否成功,成功响应时固定为true
|
||
Message string `json:"message"` // 成功消息描述
|
||
Data interface{} `json:"data"` // 响应数据
|
||
Timestamp int64 `json:"timestamp"` // 响应时间戳
|
||
}
|
||
|
||
// ErrorCode 错误代码常量
|
||
// 定义标准化的错误代码,用于客户端识别和处理不同类型的错误
|
||
const (
|
||
ErrCodeInvalidRequest = "INVALID_REQUEST" // 无效请求,通常是请求参数格式错误
|
||
ErrCodeUnauthorized = "UNAUTHORIZED" // 未授权,需要登录或token无效
|
||
ErrCodeForbidden = "FORBIDDEN" // 禁止访问,权限不足
|
||
ErrCodeNotFound = "NOT_FOUND" // 资源不存在
|
||
ErrCodeConflict = "CONFLICT" // 资源冲突,如重复创建
|
||
ErrCodeInternalError = "INTERNAL_ERROR" // 服务器内部错误
|
||
ErrCodeDatabaseError = "DATABASE_ERROR" // 数据库操作错误
|
||
ErrCodeValidationError = "VALIDATION_ERROR" // 数据验证错误
|
||
ErrCodeTokenExpired = "TOKEN_EXPIRED" // 令牌已过期
|
||
ErrCodeInsufficientData = "INSUFFICIENT_DATA" // 数据不足,缺少必要信息
|
||
)
|
||
|
||
// LogLevel 日志级别
|
||
// 定义不同的日志记录级别
|
||
type LogLevel int
|
||
|
||
const (
|
||
LogLevelInfo LogLevel = iota // 信息级别,记录一般信息
|
||
LogLevelWarn // 警告级别,记录潜在问题
|
||
LogLevelError // 错误级别,记录错误信息
|
||
LogLevelDebug // 调试级别,记录调试信息
|
||
)
|
||
|
||
// LogEntry 日志条目结构
|
||
// 包含完整的日志信息,用于结构化日志记录
|
||
type LogEntry struct {
|
||
Level LogLevel `json:"level"` // 日志级别
|
||
Message string `json:"message"` // 日志消息
|
||
Error string `json:"error,omitempty"` // 错误信息,仅在错误日志中存在
|
||
Context interface{} `json:"context,omitempty"` // 上下文信息,额外的结构化数据
|
||
Timestamp time.Time `json:"timestamp"` // 日志时间戳
|
||
File string `json:"file"` // 源文件路径
|
||
Line int `json:"line"` // 源文件行号
|
||
}
|
||
|
||
// WriteErrorResponse 写入错误响应
|
||
// c: Gin上下文
|
||
// statusCode: HTTP状态码
|
||
// message: 错误消息
|
||
// errorCode: 错误代码
|
||
// data: 附加数据
|
||
func WriteErrorResponse(c *gin.Context, statusCode int, message, errorCode string, data interface{}) {
|
||
response := ErrorResponse{
|
||
Success: false,
|
||
Message: message,
|
||
ErrorCode: errorCode,
|
||
Data: data,
|
||
Timestamp: time.Now().Unix(),
|
||
}
|
||
|
||
c.JSON(statusCode, response)
|
||
}
|
||
|
||
// WriteSuccessResponse 写入成功响应
|
||
// c: Gin上下文
|
||
// statusCode: HTTP状态码
|
||
// message: 成功消息
|
||
// data: 响应数据
|
||
func WriteSuccessResponse(c *gin.Context, statusCode int, message string, data interface{}) {
|
||
response := SuccessResponse{
|
||
Success: true,
|
||
Message: message,
|
||
Data: data,
|
||
Timestamp: time.Now().Unix(),
|
||
}
|
||
|
||
c.JSON(statusCode, response)
|
||
}
|
||
|
||
// HandleDatabaseError 处理数据库错误
|
||
// c: Gin上下文
|
||
// err: 数据库错误
|
||
// operation: 操作描述
|
||
func HandleDatabaseError(c *gin.Context, err error, operation string) {
|
||
if err == gorm.ErrRecordNotFound {
|
||
LogWarn(fmt.Sprintf("Record not found during %s", operation), map[string]interface{}{
|
||
"operation": operation,
|
||
"error": err.Error(),
|
||
})
|
||
WriteErrorResponse(c, 404, "记录不存在", ErrCodeNotFound, nil)
|
||
return
|
||
}
|
||
|
||
LogError(fmt.Sprintf("Database error during %s", operation), err, map[string]interface{}{
|
||
"operation": operation,
|
||
})
|
||
WriteErrorResponse(c, 500, "数据库操作失败", ErrCodeDatabaseError, nil)
|
||
}
|
||
|
||
// HandleValidationError 处理验证错误
|
||
// c: Gin上下文
|
||
// message: 验证错误消息
|
||
// details: 验证错误详情
|
||
func HandleValidationError(c *gin.Context, message string, details interface{}) {
|
||
LogWarn("Validation error: "+message, map[string]interface{}{
|
||
"details": details,
|
||
})
|
||
WriteErrorResponse(c, 400, message, ErrCodeValidationError, details)
|
||
}
|
||
|
||
// HandleUnauthorizedError 处理未授权错误
|
||
// c: Gin上下文
|
||
// message: 错误消息
|
||
func HandleUnauthorizedError(c *gin.Context, message string) {
|
||
LogWarn("Unauthorized access: "+message, nil)
|
||
WriteErrorResponse(c, 401, message, ErrCodeUnauthorized, nil)
|
||
}
|
||
|
||
// HandleInternalError 处理内部错误
|
||
// c: Gin上下文
|
||
// err: 错误
|
||
// operation: 操作描述
|
||
func HandleInternalError(c *gin.Context, err error, operation string) {
|
||
LogError(fmt.Sprintf("Internal error during %s", operation), err, map[string]interface{}{
|
||
"operation": operation,
|
||
})
|
||
WriteErrorResponse(c, 500, "服务器内部错误", ErrCodeInternalError, nil)
|
||
}
|
||
|
||
// LogInfo 记录信息日志
|
||
// message: 日志消息
|
||
// context: 上下文信息
|
||
func LogInfo(message string, context interface{}) {
|
||
logEntry := createLogEntry(LogLevelInfo, message, nil, context)
|
||
printLog(logEntry)
|
||
}
|
||
|
||
// LogWarn 记录警告日志
|
||
// message: 日志消息
|
||
// context: 上下文信息
|
||
func LogWarn(message string, context interface{}) {
|
||
logEntry := createLogEntry(LogLevelWarn, message, nil, context)
|
||
printLog(logEntry)
|
||
}
|
||
|
||
// LogError 记录错误日志
|
||
// message: 日志消息
|
||
// err: 错误对象
|
||
// context: 上下文信息
|
||
func LogError(message string, err error, context interface{}) {
|
||
errorStr := ""
|
||
if err != nil {
|
||
errorStr = err.Error()
|
||
}
|
||
logEntry := createLogEntry(LogLevelError, message, &errorStr, context)
|
||
printLog(logEntry)
|
||
}
|
||
|
||
// LogDebug 记录调试日志
|
||
// message: 日志消息
|
||
// context: 上下文信息
|
||
func LogDebug(message string, context interface{}) {
|
||
logEntry := createLogEntry(LogLevelDebug, message, nil, context)
|
||
printLog(logEntry)
|
||
}
|
||
|
||
// createLogEntry 创建日志条目
|
||
// level: 日志级别
|
||
// message: 日志消息
|
||
// errorStr: 错误字符串
|
||
// context: 上下文信息
|
||
// 返回: 日志条目
|
||
func createLogEntry(level LogLevel, message string, errorStr *string, context interface{}) LogEntry {
|
||
_, file, line, _ := runtime.Caller(2)
|
||
|
||
entry := LogEntry{
|
||
Level: level,
|
||
Message: message,
|
||
Context: context,
|
||
Timestamp: time.Now(),
|
||
File: file,
|
||
Line: line,
|
||
}
|
||
|
||
if errorStr != nil {
|
||
entry.Error = *errorStr
|
||
}
|
||
|
||
return entry
|
||
}
|
||
|
||
// printLog 打印日志
|
||
// entry: 日志条目
|
||
func printLog(entry LogEntry) {
|
||
levelStr := getLevelString(entry.Level)
|
||
timestamp := entry.Timestamp.Format("2006-01-02 15:04:05")
|
||
|
||
logMessage := fmt.Sprintf("[%s] %s %s", levelStr, timestamp, entry.Message)
|
||
|
||
if entry.Error != "" {
|
||
logMessage += fmt.Sprintf(" | Error: %s", entry.Error)
|
||
}
|
||
|
||
if entry.Context != nil {
|
||
contextJSON, _ := json.Marshal(entry.Context)
|
||
logMessage += fmt.Sprintf(" | Context: %s", string(contextJSON))
|
||
}
|
||
|
||
logMessage += fmt.Sprintf(" | %s:%d", entry.File, entry.Line)
|
||
|
||
log.Println(logMessage)
|
||
}
|
||
|
||
// getLevelString 获取日志级别字符串
|
||
// level: 日志级别
|
||
// 返回: 级别字符串
|
||
func getLevelString(level LogLevel) string {
|
||
switch level {
|
||
case LogLevelInfo:
|
||
return "INFO"
|
||
case LogLevelWarn:
|
||
return "WARN"
|
||
case LogLevelError:
|
||
return "ERROR"
|
||
case LogLevelDebug:
|
||
return "DEBUG"
|
||
default:
|
||
return "UNKNOWN"
|
||
}
|
||
} |