refactor(handlers, monitoring): improve API request handling and metrics logging

- Refactored HandleAPIRequest to use a result channel for better error handling and response management.
- Updated metrics logging to directly use the full referer instead of just the main domain, enhancing data accuracy.
- Fixed recent requests display in HTML to correctly format timestamps for better readability.
This commit is contained in:
wood chen 2024-12-01 00:37:50 +08:00
parent 2720f6ebf0
commit 1248508302
3 changed files with 22 additions and 23 deletions

View File

@ -28,7 +28,13 @@ func (h *Handlers) HandleAPIRequest(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second) ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
defer cancel() defer cancel()
done := make(chan struct{}) // 创建一个响应通道,用于传递结果
type result struct {
url string
err error
}
resultChan := make(chan result, 1)
go func() { go func() {
start := time.Now() start := time.Now()
realIP := utils.GetRealIP(r) realIP := utils.GetRealIP(r)
@ -57,7 +63,7 @@ func (h *Handlers) HandleAPIRequest(w http.ResponseWriter, r *http.Request) {
IP: realIP, IP: realIP,
Referer: sourceInfo, Referer: sourceInfo,
}) })
http.NotFound(w, r) resultChan <- result{err: fmt.Errorf("not found")}
return return
} }
@ -78,7 +84,7 @@ func (h *Handlers) HandleAPIRequest(w http.ResponseWriter, r *http.Request) {
IP: realIP, IP: realIP,
Referer: sourceInfo, Referer: sourceInfo,
}) })
http.NotFound(w, r) resultChan <- result{err: fmt.Errorf("not found")}
return return
} }
@ -94,7 +100,7 @@ func (h *Handlers) HandleAPIRequest(w http.ResponseWriter, r *http.Request) {
IP: realIP, IP: realIP,
Referer: sourceInfo, Referer: sourceInfo,
}) })
http.Error(w, "Failed to fetch content", http.StatusInternalServerError) resultChan <- result{err: err}
return return
} }
@ -108,7 +114,7 @@ func (h *Handlers) HandleAPIRequest(w http.ResponseWriter, r *http.Request) {
IP: realIP, IP: realIP,
Referer: sourceInfo, Referer: sourceInfo,
}) })
http.Error(w, "No content available", http.StatusNotFound) resultChan <- result{err: fmt.Errorf("no content available")}
return return
} }
@ -136,14 +142,17 @@ func (h *Handlers) HandleAPIRequest(w http.ResponseWriter, r *http.Request) {
randomURL, randomURL,
) )
http.Redirect(w, r, randomURL, http.StatusFound) resultChan <- result{url: randomURL}
done <- struct{}{}
}() }()
// 等待结果或超时
select { select {
case <-done: case res := <-resultChan:
// 请求成功完成 if res.err != nil {
http.Error(w, res.err.Error(), http.StatusInternalServerError)
return
}
http.Redirect(w, r, res.url, http.StatusFound)
case <-ctx.Done(): case <-ctx.Done():
http.Error(w, "Request timeout", http.StatusGatewayTimeout) http.Error(w, "Request timeout", http.StatusGatewayTimeout)
} }

View File

@ -3,7 +3,6 @@ package monitoring
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/url"
"runtime" "runtime"
"strings" "strings"
"sync" "sync"
@ -122,18 +121,9 @@ func LogRequest(log RequestLog) {
metrics.StatusCodes[log.StatusCode]++ metrics.StatusCodes[log.StatusCode]++
// 处理 referer只保留域名 // 直接使用完整的 referer
if log.Referer != "direct" { if log.Referer != "direct" {
if parsedURL, err := url.Parse(log.Referer); err == nil { metrics.TopReferers[log.Referer]++
// 只保留主域名
parts := strings.Split(parsedURL.Host, ".")
if len(parts) >= 2 {
domain := parts[len(parts)-2] + "." + parts[len(parts)-1]
metrics.TopReferers[domain]++
} else {
metrics.TopReferers[parsedURL.Host]++
}
}
} else { } else {
metrics.TopReferers["直接访问"]++ metrics.TopReferers["直接访问"]++
} }

View File

@ -232,7 +232,7 @@
// 最近请求 // 最近请求
const recentRequestsHtml = metrics.recent_requests.map(req => ` const recentRequestsHtml = metrics.recent_requests.map(req => `
<tr> <tr>
<td>${new Date(req.time).toLocaleString()}</td> <td>${new Date(req.time * 1000).toLocaleString()}</td>
<td>${req.path}</td> <td>${req.path}</td>
<td>${req.method}</td> <td>${req.method}</td>
<td>${req.status_code}</td> <td>${req.status_code}</td>