feat(logging): add detailed logging throughout application components

- Implement logging in router setup, auth handlers, and frpc operations
- Add SoftwareInfo struct for version tracking and logging
- Enhance error messages with more context and logging
- Replace direct error returns with formatted error logging
- Add debug logs for token operations and request validations
This commit is contained in:
2026-02-27 23:44:41 +08:00
parent 72eb90957c
commit e3b3a3aa98
5 changed files with 167 additions and 85 deletions
+73 -36
View File
@@ -12,6 +12,7 @@ import (
"path/filepath"
"strconv"
"strings"
"super-frpc/postLog"
"time"
)
@@ -58,13 +59,15 @@ func CloseFrpcDatabase() error {
func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
SendErrorResponse(w, http.StatusMethodNotAllowed, "invalid request method")
SendErrorResponse(w, http.StatusMethodNotAllowed, "Invalid request method")
postLog.Debug(fmt.Sprintf("[CreateInstanceHandler] Invalid request method: %s", r.Method))
return
}
body, err := io.ReadAll(r.Body)
if err != nil {
SendErrorResponse(w, http.StatusBadRequest, "failed to read request body")
postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to read request body: %v", err))
SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body")
return
}
defer r.Body.Close()
@@ -72,7 +75,8 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) {
// 先解析为map,处理类型不匹配的情况
var reqMap map[string]interface{}
if err := json.Unmarshal(body, &reqMap); err != nil {
SendErrorResponse(w, http.StatusBadRequest, "invalid request format")
postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to unmarshal request body: %v", err))
SendErrorResponse(w, http.StatusBadRequest, "Invalid request format")
return
}
@@ -107,7 +111,7 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) {
// 处理instanceInfo字段
instanceInfoMap, ok := reqMap["instanceInfo"].(map[string]interface{})
if !ok {
SendErrorResponse(w, http.StatusBadRequest, "invalid instanceInfo format")
SendErrorResponse(w, http.StatusBadRequest, "Invalid instanceInfo format")
return
}
@@ -137,24 +141,27 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) {
// 重新序列化为JSON,用于ValidateRequestWithBody
reqBody, err := json.Marshal(req)
if err != nil {
SendErrorResponse(w, http.StatusBadRequest, "invalid request format")
postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to marshal request body: %v", err))
SendErrorResponse(w, http.StatusBadRequest, "Invalid request format")
return
}
userID, _, err := ValidateRequestWithBody(w, r, reqBody)
if err != nil {
postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to validate request body: %v", err))
SendErrorResponse(w, http.StatusUnauthorized, err.Error())
return
}
if err := CheckPermission(userID, "superuser", "admin"); err != nil {
postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to check permission: %v", err))
SendErrorResponse(w, http.StatusForbidden, err.Error())
return
}
if req.InstanceInfo.Name == "" || req.InstanceInfo.ServerAddr == "" ||
req.InstanceInfo.ServerPort == "" || req.InstanceInfo.AuthMethod == "" {
SendErrorResponse(w, http.StatusBadRequest, "missing required fields in instanceInfo")
SendErrorResponse(w, http.StatusBadRequest, "Missing required fields in instanceInfo")
return
}
@@ -165,13 +172,15 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) {
user, err := GetUserByID(userID)
if err != nil {
SendErrorResponse(w, http.StatusInternalServerError, "failed to get user info")
postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to get user info: %v", err))
SendErrorResponse(w, http.StatusInternalServerError, "Failed to get user info")
return
}
configDir, err := GetConfigDir()
if err != nil {
SendErrorResponse(w, http.StatusInternalServerError, "failed to get config directory")
postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to get config directory: %v", err))
SendErrorResponse(w, http.StatusInternalServerError, "Failed to get config directory")
return
}
@@ -180,7 +189,8 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) {
configContent := generateFrpcConfig(req.InstanceInfo)
if err := os.WriteFile(configPath, []byte(configContent), 0644); err != nil {
SendErrorResponse(w, http.StatusInternalServerError, "failed to create config file")
postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to create config file %s: %v", configPath, err))
SendErrorResponse(w, http.StatusInternalServerError, "Failed to create config file")
return
}
@@ -192,7 +202,8 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) {
if err != nil {
os.Remove(configPath)
SendErrorResponse(w, http.StatusInternalServerError, "failed to save instance to database")
postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to save instance %s to database: %v", req.InstanceInfo.Name, err))
SendErrorResponse(w, http.StatusInternalServerError, "Failed to save instance to database")
return
}
@@ -200,12 +211,13 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) {
if err := createBootService(user.Username, req.InstanceInfo.Name, configPath, runUser); err != nil {
frpcDB.Exec("DELETE FROM frpcInstances WHERE userID = ? AND name = ?", userID, req.InstanceInfo.Name)
os.Remove(configPath)
SendErrorResponse(w, http.StatusInternalServerError, "failed to create boot service")
postLog.Error(fmt.Sprintf("[CreateInstanceHandler] Failed to create boot service for instance %s: %v", req.InstanceInfo.Name, err))
SendErrorResponse(w, http.StatusInternalServerError, "Failed to create boot service")
return
}
}
SendSuccessResponse(w, "instance created successfully", map[string]interface{}{
SendSuccessResponse(w, "Instance created successfully", map[string]interface{}{
"name": req.InstanceInfo.Name,
"configPath": configPath,
"bootAtStart": req.BootAtStart,
@@ -214,31 +226,35 @@ func CreateInstanceHandler(w http.ResponseWriter, r *http.Request) {
func DeleteInstanceHandler(w http.ResponseWriter, r *http.Request, instanceName string) {
if r.Method != http.MethodPost {
SendErrorResponse(w, http.StatusMethodNotAllowed, "invalid request method")
SendErrorResponse(w, http.StatusMethodNotAllowed, "Invalid request method")
return
}
body, err := io.ReadAll(r.Body)
if err != nil {
SendErrorResponse(w, http.StatusBadRequest, "failed to read request body")
postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] Failed to read request body: %v", err))
SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body")
return
}
defer r.Body.Close()
userID, _, err := ValidateRequestWithBody(w, r, body)
if err != nil {
postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] Failed to validate request body: %v", err))
SendErrorResponse(w, http.StatusUnauthorized, err.Error())
return
}
if err := CheckPermission(userID, "superuser", "admin"); err != nil {
postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] Failed to check permission: %v", err))
SendErrorResponse(w, http.StatusForbidden, err.Error())
return
}
user, err := GetUserByID(userID)
if err != nil {
SendErrorResponse(w, http.StatusInternalServerError, "failed to get user info")
postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] Failed to get user info: %v", err))
SendErrorResponse(w, http.StatusInternalServerError, "Failed to get user info")
return
}
@@ -255,68 +271,78 @@ func DeleteInstanceHandler(w http.ResponseWriter, r *http.Request, instanceName
return
}
if err != nil {
SendErrorResponse(w, http.StatusInternalServerError, "failed to query instance")
postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] Failed to query instance: %v", err))
SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance")
return
}
if instance.BootAtStart {
if err := removeBootService(user.Username, instanceName); err != nil {
SendErrorResponse(w, http.StatusInternalServerError, "failed to remove boot service")
postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] Failed to remove boot service for instance %s: %v", instanceName, err))
SendErrorResponse(w, http.StatusInternalServerError, "Failed to remove boot service")
return
}
}
if _, err := os.Stat(instance.ConfigPath); err == nil {
if err := os.Remove(instance.ConfigPath); err != nil {
SendErrorResponse(w, http.StatusInternalServerError, "failed to remove config file")
postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] Failed to remove config file %s: %v", instance.ConfigPath, err))
SendErrorResponse(w, http.StatusInternalServerError, "Failed to remove config file")
return
}
}
_, err = frpcDB.Exec("DELETE FROM frpcInstances WHERE id = ?", instance.ID)
if err != nil {
SendErrorResponse(w, http.StatusInternalServerError, "failed to delete instance from database")
postLog.Error(fmt.Sprintf("[DeleteInstanceHandler] Failed to delete instance %s from database: %v", instanceName, err))
SendErrorResponse(w, http.StatusInternalServerError, "Failed to delete instance from database")
return
}
SendSuccessResponse(w, "instance deleted successfully", map[string]interface{}{
SendSuccessResponse(w, "Instance deleted successfully", map[string]interface{}{
"name": instanceName,
})
}
func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request, instanceName string) {
if r.Method != http.MethodPost {
SendErrorResponse(w, http.StatusMethodNotAllowed, "invalid request method")
postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Invalid request method: %s", r.Method))
SendErrorResponse(w, http.StatusMethodNotAllowed, "Invalid request method")
return
}
body, err := io.ReadAll(r.Body)
if err != nil {
SendErrorResponse(w, http.StatusBadRequest, "failed to read request body")
postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to read request body: %v", err))
SendErrorResponse(w, http.StatusBadRequest, "Failed to read request body")
return
}
defer r.Body.Close()
var reqMap map[string]interface{}
if err := json.Unmarshal(body, &reqMap); err != nil {
SendErrorResponse(w, http.StatusBadRequest, "invalid request format")
postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to unmarshal request body: %v", err))
SendErrorResponse(w, http.StatusBadRequest, "Invalid request format")
return
}
userID, _, err := ValidateRequestWithBody(w, r, body)
if err != nil {
postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to validate request body: %v", err))
SendErrorResponse(w, http.StatusUnauthorized, err.Error())
return
}
if err := CheckPermission(userID, "superuser", "admin"); err != nil {
postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to check permission: %v", err))
SendErrorResponse(w, http.StatusForbidden, err.Error())
return
}
user, err := GetUserByID(userID)
if err != nil {
SendErrorResponse(w, http.StatusInternalServerError, "failed to get user info")
postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to get user info: %v", err))
SendErrorResponse(w, http.StatusInternalServerError, "Failed to get user info")
return
}
@@ -333,7 +359,8 @@ func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request, instanceName
return
}
if err != nil {
SendErrorResponse(w, http.StatusInternalServerError, "failed to query instance")
postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to query instance: %v", err))
SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instance")
return
}
@@ -368,7 +395,8 @@ func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request, instanceName
if newName != instance.Name || newRunUser != instance.RunUser {
configDir, err := GetConfigDir()
if err != nil {
SendErrorResponse(w, http.StatusInternalServerError, "failed to get config directory")
postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to get config directory: %v", err))
SendErrorResponse(w, http.StatusInternalServerError, "Failed to get config directory")
return
}
@@ -378,7 +406,8 @@ func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request, instanceName
if oldConfigPath != newConfigPath {
if _, err := os.Stat(oldConfigPath); err == nil {
if err := os.Rename(oldConfigPath, newConfigPath); err != nil {
SendErrorResponse(w, http.StatusInternalServerError, "failed to rename config file")
postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to rename config file %s to %s: %v", oldConfigPath, newConfigPath, err))
SendErrorResponse(w, http.StatusInternalServerError, "Failed to rename config file")
return
}
}
@@ -397,7 +426,8 @@ func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request, instanceName
configContent := generateFrpcConfig(info)
if err := os.WriteFile(newConfigPath, []byte(configContent), 0644); err != nil {
SendErrorResponse(w, http.StatusInternalServerError, "failed to update config file")
postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to update config file: %v", err))
SendErrorResponse(w, http.StatusInternalServerError, "Failed to update config file")
return
}
@@ -408,7 +438,8 @@ func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request, instanceName
`, newName, newServerAddr, newServerPort, newAuthMethod, newBootAtStart, newRunUser, newConfigPath, instance.ID)
if err != nil {
SendErrorResponse(w, http.StatusInternalServerError, "failed to update instance in database")
postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to update instance in database: %v", err))
SendErrorResponse(w, http.StatusInternalServerError, "Failed to update instance in database")
return
}
@@ -421,7 +452,7 @@ func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request, instanceName
createBootService(user.Username, newName, newConfigPath, newRunUser)
}
SendSuccessResponse(w, "instance modified successfully", map[string]interface{}{
SendSuccessResponse(w, "Instance modified successfully", map[string]interface{}{
"name": newName,
"configPath": newConfigPath,
})
@@ -429,19 +460,21 @@ func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request, instanceName
func ListInstancesHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
SendErrorResponse(w, http.StatusMethodNotAllowed, "invalid request method")
SendErrorResponse(w, http.StatusMethodNotAllowed, "Invalid request method")
return
}
userID, _, err := ValidateRequestWithHeader(w, r)
if err != nil {
SendErrorResponse(w, http.StatusUnauthorized, err.Error())
postLog.Error(fmt.Sprintf("[ListInstancesHandler] Failed to validate request: %v", err))
SendErrorResponse(w, http.StatusUnauthorized, "Failed to validate request")
return
}
userType, err := GetUserType(userID)
if err != nil {
SendErrorResponse(w, http.StatusInternalServerError, "failed to get user type")
postLog.Error(fmt.Sprintf("[ListInstancesHandler] Failed to get user type: %v", err))
SendErrorResponse(w, http.StatusInternalServerError, "Failed to get user type")
return
}
@@ -450,7 +483,8 @@ func ListInstancesHandler(w http.ResponseWriter, r *http.Request) {
FROM frpcInstances WHERE userID = ?
`, userID)
if err != nil {
SendErrorResponse(w, http.StatusInternalServerError, "failed to query instances")
postLog.Error(fmt.Sprintf("[ListInstancesHandler] Failed to query instances: %v", err))
SendErrorResponse(w, http.StatusInternalServerError, "Failed to query instances")
return
}
defer rows.Close()
@@ -463,7 +497,8 @@ func ListInstancesHandler(w http.ResponseWriter, r *http.Request) {
&instance.ID, &instance.UserID, &instance.Name, &instance.ServerAddr, &instance.ServerPort,
&instance.AuthMethod, &instance.BootAtStart, &instance.RunUser, &instance.ConfigPath, &createdAtStr,
); err != nil {
SendErrorResponse(w, http.StatusInternalServerError, "failed to scan instance")
postLog.Error(fmt.Sprintf("[ListInstancesHandler] Failed to scan instance: %v", err))
SendErrorResponse(w, http.StatusInternalServerError, "Failed to scan instance")
return
}
@@ -491,7 +526,7 @@ func ListInstancesHandler(w http.ResponseWriter, r *http.Request) {
instances = []map[string]interface{}{}
}
SendSuccessResponse(w, "instances retrieved successfully", instances)
SendSuccessResponse(w, "Instances retrieved successfully", instances)
}
func generateFrpcConfig(info InstanceInfo) string {
@@ -511,6 +546,7 @@ func generateFrpcConfig(info InstanceInfo) string {
func GetConfigDir() (string, error) {
config, err := GetConfig()
if err != nil {
postLog.Error(fmt.Sprintf("[GetConfigDir] Failed to get config: %v", err))
return "", err
}
return config.InstancePath, nil
@@ -519,6 +555,7 @@ func GetConfigDir() (string, error) {
func GetFrpcPath() (string, error) {
config, err := GetConfig()
if err != nil {
postLog.Error(fmt.Sprintf("[GetFrpcPath] Failed to get config: %v", err))
return "", err
}
return config.FrpcPath, nil