feat(watchdog): add exception handling and webhook integration
- Implement exception handling in TCP client to process error messages - Add webhook functionality to send notifications for exceptions - Introduce utility functions for string parsing - Update config with webhook template
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"super-frpc/database"
|
"super-frpc/database"
|
||||||
"super-frpc/global"
|
"super-frpc/global"
|
||||||
@@ -128,3 +129,35 @@ func LogRequest(r *http.Request, userID int) {
|
|||||||
func IntToString(i int) string {
|
func IntToString(i int) string {
|
||||||
return strconv.Itoa(i)
|
return strconv.Itoa(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetTextMiddle(text, left, right string) string {
|
||||||
|
start := 0
|
||||||
|
if left != "" {
|
||||||
|
idx := strings.Index(text, left)
|
||||||
|
if idx == -1 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
start = idx + len(left)
|
||||||
|
}
|
||||||
|
|
||||||
|
if right == "" {
|
||||||
|
if start > len(text) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return text[start:]
|
||||||
|
}
|
||||||
|
|
||||||
|
endIdx := strings.Index(text[start:], right)
|
||||||
|
if endIdx == -1 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return text[start : start+endIdx]
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCmdType(source string) string {
|
||||||
|
return GetTextMiddle(source, "[", "]")
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCmdParams(source string, param string) string {
|
||||||
|
return GetTextMiddle(source, "<"+param+">", "</"+param+">")
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package watchdog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"super-frpc/global"
|
||||||
|
"super-frpc/webhook"
|
||||||
|
)
|
||||||
|
|
||||||
|
func exceptionHandle(exceptionType string, serviceName string, errorMsg string) {
|
||||||
|
body := make(map[string]string)
|
||||||
|
for k, v := range global.CurrentConfig.Webhook.Body {
|
||||||
|
replaced := v
|
||||||
|
for strings.Contains(replaced, "{{ exceptionType }}") ||
|
||||||
|
strings.Contains(replaced, "{{ serviceName }}") ||
|
||||||
|
strings.Contains(replaced, "{{ exceptionMsg }}") {
|
||||||
|
replaced = strings.ReplaceAll(replaced, "{{ exceptionType }}", exceptionType)
|
||||||
|
replaced = strings.ReplaceAll(replaced, "{{ serviceName }}", serviceName)
|
||||||
|
replaced = strings.ReplaceAll(replaced, "{{ exceptionMsg }}", errorMsg)
|
||||||
|
}
|
||||||
|
body[k] = replaced
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyJSON := ""
|
||||||
|
for k, v := range body {
|
||||||
|
bodyJSON = fmt.Sprintf(`{"%s": "%s"}`, k, v)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
webhook.SendHook(global.CurrentConfig.Webhook.URL, global.CurrentConfig.Webhook.Method, global.CurrentConfig.Webhook.Headers, bodyJSON)
|
||||||
|
}
|
||||||
+11
-2
@@ -6,6 +6,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"super-frpc/postLog"
|
"super-frpc/postLog"
|
||||||
|
"super-frpc/utils"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -108,15 +109,23 @@ func recvMsg() {
|
|||||||
|
|
||||||
if len(data) > 0 {
|
if len(data) > 0 {
|
||||||
line := strings.TrimSpace(string(data))
|
line := strings.TrimSpace(string(data))
|
||||||
|
|
||||||
if len(line) > 0 {
|
if len(line) > 0 {
|
||||||
select {
|
select {
|
||||||
case recvChan <- line:
|
case recvChan <- line:
|
||||||
default:
|
default:
|
||||||
|
// drop the message
|
||||||
}
|
}
|
||||||
|
// Here add logic to handle the message
|
||||||
if !isResponseMessage(line) {
|
if !isResponseMessage(line) {
|
||||||
postLog.Debug(fmt.Sprintf("[Watchdog] TCP Socket received message: %s", line))
|
postLog.Debug(fmt.Sprintf("[Watchdog] TCP Socket received message: %s", line))
|
||||||
|
cmdType := utils.GetCmdType(line)
|
||||||
|
if cmdType == "Exception" {
|
||||||
|
exceptionType := utils.GetCmdParams(line, "exceptionType")
|
||||||
|
serviceName := utils.GetCmdParams(line, "serviceName")
|
||||||
|
errorMsg := utils.GetCmdParams(line, "errorMsg")
|
||||||
|
postLog.Error(fmt.Sprintf("[Watchdog] Exception[%s]: %s, %s", serviceName, exceptionType, errorMsg))
|
||||||
|
exceptionHandle(exceptionType, serviceName, errorMsg)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package webhook
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"super-frpc/postLog"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SendHook sends a webhook to the specified URL.
|
||||||
|
// Returns the error message, status code, and response message.
|
||||||
|
// If the status code is not 200, it logs the error and returns the status code and response message.
|
||||||
|
// If the status code is 200, it returns an empty error message, status code, and response message.
|
||||||
|
func SendHook(url string, method string, headers map[string]string, body string) (err string, code int, msg string) {
|
||||||
|
req, reqErr := http.NewRequest(method, url, strings.NewReader(body))
|
||||||
|
if reqErr != nil {
|
||||||
|
return reqErr.Error(), 500, ""
|
||||||
|
}
|
||||||
|
for k, v := range headers {
|
||||||
|
req.Header.Set(k, v)
|
||||||
|
}
|
||||||
|
resp, doErr := http.DefaultClient.Do(req)
|
||||||
|
if doErr != nil {
|
||||||
|
return doErr.Error(), 500, ""
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
respMsg := ""
|
||||||
|
if resp.Body != nil {
|
||||||
|
respBody, _ := io.ReadAll(resp.Body)
|
||||||
|
respMsg = string(respBody)
|
||||||
|
}
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
postLog.Debug(fmt.Sprintf("[SendHook] SendHook { %s, %s, %s, %s } failed, status code: %d, response: [%s]: %s", url, method, headers, body, resp.StatusCode, resp.Status, respMsg))
|
||||||
|
return fmt.Sprintf("unexpected status code: %d, response: [%s]: %s", resp.StatusCode, resp.Status, respMsg), resp.StatusCode, respMsg
|
||||||
|
}
|
||||||
|
return "", 200, ""
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user