Add traffic monitor
This commit is contained in:
@@ -150,6 +150,7 @@ func MainApp(configPath string) {
|
|||||||
config,
|
config,
|
||||||
api,
|
api,
|
||||||
workerPool,
|
workerPool,
|
||||||
|
hosts,
|
||||||
log.Named("router"),
|
log.Named("router"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/debridmediamanager/zurg/internal/config"
|
"github.com/debridmediamanager/zurg/internal/config"
|
||||||
@@ -25,7 +26,8 @@ type RootResponse struct {
|
|||||||
Dav string `json:"dav"`
|
Dav string `json:"dav"`
|
||||||
Infuse string `json:"infuse"`
|
Infuse string `json:"infuse"`
|
||||||
Logs string `json:"logs"`
|
Logs string `json:"logs"`
|
||||||
UserInfo *realdebrid.User `json:"user_info"` // Replace UserInfoType with the actual type
|
UserInfo *realdebrid.User `json:"user_info"`
|
||||||
|
RDTrafficUsed uint64 `json:"rd_traffic_used"`
|
||||||
LibrarySize int `json:"library_size"` // Number of torrents in the library
|
LibrarySize int `json:"library_size"` // Number of torrents in the library
|
||||||
RepairQueueStr string `json:"repair_queue"` // List of torrents in the repair queue
|
RepairQueueStr string `json:"repair_queue"` // List of torrents in the repair queue
|
||||||
MemAlloc uint64 `json:"mem_alloc"` // Memory allocation in MB
|
MemAlloc uint64 `json:"mem_alloc"` // Memory allocation in MB
|
||||||
@@ -35,7 +37,8 @@ type RootResponse struct {
|
|||||||
PID int `json:"pid"` // Process ID
|
PID int `json:"pid"` // Process ID
|
||||||
Sponsor SponsorResponse `json:"sponsor_zurg"` // Sponsorship links
|
Sponsor SponsorResponse `json:"sponsor_zurg"` // Sponsorship links
|
||||||
Config config.ZurgConfig `json:"config"`
|
Config config.ZurgConfig `json:"config"`
|
||||||
OnceDoneBin []string `json:"once_done_bin"`
|
IDsToDelete []string `json:"ids_to_delete"`
|
||||||
|
Hosts []string `json:"hosts"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (zr *Handlers) handleHome(resp http.ResponseWriter, req *http.Request) {
|
func (zr *Handlers) handleHome(resp http.ResponseWriter, req *http.Request) {
|
||||||
@@ -45,6 +48,12 @@ func (zr *Handlers) handleHome(resp http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trafficDetails, err := zr.api.GetTrafficDetails()
|
||||||
|
if err != nil {
|
||||||
|
http.Error(resp, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var mem runtime.MemStats
|
var mem runtime.MemStats
|
||||||
runtime.ReadMemStats(&mem)
|
runtime.ReadMemStats(&mem)
|
||||||
|
|
||||||
@@ -65,6 +74,16 @@ func (zr *Handlers) handleHome(resp http.ResponseWriter, req *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sortedIDs := zr.torMgr.OnceDoneBin.ToSlice()
|
||||||
|
sort.Strings(sortedIDs)
|
||||||
|
|
||||||
|
// check if real-debrid.com is in the traffic details
|
||||||
|
var rdTrafficUsed int64
|
||||||
|
rdTrafficUsed = 0
|
||||||
|
if _, ok := trafficDetails["real-debrid.com"]; ok {
|
||||||
|
rdTrafficUsed = trafficDetails["real-debrid.com"]
|
||||||
|
}
|
||||||
|
|
||||||
response := RootResponse{
|
response := RootResponse{
|
||||||
Version: version.GetVersion(),
|
Version: version.GetVersion(),
|
||||||
BuiltAt: version.GetBuiltAt(),
|
BuiltAt: version.GetBuiltAt(),
|
||||||
@@ -74,6 +93,7 @@ func (zr *Handlers) handleHome(resp http.ResponseWriter, req *http.Request) {
|
|||||||
Infuse: fmt.Sprintf("//%s/infuse/", req.Host),
|
Infuse: fmt.Sprintf("//%s/infuse/", req.Host),
|
||||||
Logs: fmt.Sprintf("//%s/logs/", req.Host),
|
Logs: fmt.Sprintf("//%s/logs/", req.Host),
|
||||||
UserInfo: userInfo,
|
UserInfo: userInfo,
|
||||||
|
RDTrafficUsed: bToGb(uint64(rdTrafficUsed)),
|
||||||
LibrarySize: allTorrents.Count(),
|
LibrarySize: allTorrents.Count(),
|
||||||
RepairQueueStr: repairQueueStr,
|
RepairQueueStr: repairQueueStr,
|
||||||
MemAlloc: bToMb(mem.Alloc),
|
MemAlloc: bToMb(mem.Alloc),
|
||||||
@@ -87,7 +107,8 @@ func (zr *Handlers) handleHome(resp http.ResponseWriter, req *http.Request) {
|
|||||||
Paypal: "https://paypal.me/yowmamasita",
|
Paypal: "https://paypal.me/yowmamasita",
|
||||||
},
|
},
|
||||||
Config: zr.cfg.GetConfig(),
|
Config: zr.cfg.GetConfig(),
|
||||||
OnceDoneBin: zr.torMgr.OnceDoneBin.ToSlice(),
|
IDsToDelete: sortedIDs,
|
||||||
|
Hosts: zr.hosts,
|
||||||
}
|
}
|
||||||
|
|
||||||
out := `<table border="1px">
|
out := `<table border="1px">
|
||||||
@@ -126,10 +147,6 @@ func (zr *Handlers) handleHome(resp http.ResponseWriter, req *http.Request) {
|
|||||||
<td>Library Size</td>
|
<td>Library Size</td>
|
||||||
<td colspan="2">%d items</td>
|
<td colspan="2">%d items</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td>Repair Queue</td>
|
|
||||||
<td colspan="2">%s</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Memory Allocation</td>
|
<td>Memory Allocation</td>
|
||||||
<td colspan="2">%d MB</td>
|
<td colspan="2">%d MB</td>
|
||||||
@@ -150,6 +167,10 @@ func (zr *Handlers) handleHome(resp http.ResponseWriter, req *http.Request) {
|
|||||||
<td>Process ID</td>
|
<td>Process ID</td>
|
||||||
<td colspan="2">%d</td>
|
<td colspan="2">%d</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>RD Traffic Used</td>
|
||||||
|
<td colspan="2">%d GB</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td rowspan="3">Sponsor Zurg</td>
|
<td rowspan="3">Sponsor Zurg</td>
|
||||||
<td>Patreon</td>
|
<td>Patreon</td>
|
||||||
@@ -189,7 +210,7 @@ func (zr *Handlers) handleHome(resp http.ResponseWriter, req *http.Request) {
|
|||||||
<td>%s</td>
|
<td>%s</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td rowspan="20">Config</td>
|
<td rowspan="23">Config</td>
|
||||||
<td>Version</td>
|
<td>Version</td>
|
||||||
<td>%s</td>
|
<td>%s</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -253,6 +274,18 @@ func (zr *Handlers) handleHome(resp http.ResponseWriter, req *http.Request) {
|
|||||||
<td>Retries Until Failed</td>
|
<td>Retries Until Failed</td>
|
||||||
<td>%d</td>
|
<td>%d</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Auto-Analyze New Torrents</td>
|
||||||
|
<td>%t</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Cache Network Test Results</td>
|
||||||
|
<td>%t</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Additional Playable Extensions</td>
|
||||||
|
<td>%s</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Network Buffer Size</td>
|
<td>Network Buffer Size</td>
|
||||||
<td>%d bytes</td>
|
<td>%d bytes</td>
|
||||||
@@ -273,6 +306,14 @@ func (zr *Handlers) handleHome(resp http.ResponseWriter, req *http.Request) {
|
|||||||
<td>IDs to be deleted</td>
|
<td>IDs to be deleted</td>
|
||||||
<td colspan="2">%v</td>
|
<td colspan="2">%v</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Repair Queue</td>
|
||||||
|
<td colspan="2">%s</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Hosts</td>
|
||||||
|
<td colspan="2">%v</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Utilities</td>
|
<td>Utilities</td>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
@@ -324,12 +365,12 @@ func (zr *Handlers) handleHome(resp http.ResponseWriter, req *http.Request) {
|
|||||||
response.Logs,
|
response.Logs,
|
||||||
response.Logs,
|
response.Logs,
|
||||||
response.LibrarySize,
|
response.LibrarySize,
|
||||||
response.RepairQueueStr,
|
|
||||||
response.MemAlloc,
|
response.MemAlloc,
|
||||||
response.TotalAlloc,
|
response.TotalAlloc,
|
||||||
response.Sys,
|
response.Sys,
|
||||||
response.NumGC,
|
response.NumGC,
|
||||||
response.PID,
|
response.PID,
|
||||||
|
response.RDTrafficUsed,
|
||||||
response.Sponsor.Patreon,
|
response.Sponsor.Patreon,
|
||||||
response.Sponsor.Patreon,
|
response.Sponsor.Patreon,
|
||||||
response.Sponsor.Github,
|
response.Sponsor.Github,
|
||||||
@@ -360,11 +401,16 @@ func (zr *Handlers) handleHome(resp http.ResponseWriter, req *http.Request) {
|
|||||||
response.Config.GetApiTimeoutSecs(),
|
response.Config.GetApiTimeoutSecs(),
|
||||||
response.Config.GetDownloadTimeoutSecs(),
|
response.Config.GetDownloadTimeoutSecs(),
|
||||||
response.Config.GetRetriesUntilFailed(),
|
response.Config.GetRetriesUntilFailed(),
|
||||||
|
response.Config.ShouldAutoAnalyzeNewTorrents(),
|
||||||
|
response.Config.ShouldCacheNetworkTestResults(),
|
||||||
|
response.Config.GetPlayableExtensions(),
|
||||||
response.Config.GetNetworkBufferSize(),
|
response.Config.GetNetworkBufferSize(),
|
||||||
response.Config.ShouldServeFromRclone(),
|
response.Config.ShouldServeFromRclone(),
|
||||||
response.Config.ShouldForceIPv6(),
|
response.Config.ShouldForceIPv6(),
|
||||||
response.Config.GetOnLibraryUpdate(),
|
response.Config.GetOnLibraryUpdate(),
|
||||||
response.OnceDoneBin,
|
response.IDsToDelete,
|
||||||
|
response.RepairQueueStr,
|
||||||
|
response.Hosts,
|
||||||
)
|
)
|
||||||
|
|
||||||
fmt.Fprint(resp, out)
|
fmt.Fprint(resp, out)
|
||||||
@@ -373,3 +419,7 @@ func (zr *Handlers) handleHome(resp http.ResponseWriter, req *http.Request) {
|
|||||||
func bToMb(b uint64) uint64 {
|
func bToMb(b uint64) uint64 {
|
||||||
return b / 1024 / 1024
|
return b / 1024 / 1024
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func bToGb(b uint64) uint64 {
|
||||||
|
return b / 1024 / 1024 / 1024
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ type Handlers struct {
|
|||||||
cfg config.ConfigInterface
|
cfg config.ConfigInterface
|
||||||
api *realdebrid.RealDebrid
|
api *realdebrid.RealDebrid
|
||||||
workerPool *ants.Pool
|
workerPool *ants.Pool
|
||||||
|
hosts []string
|
||||||
log *logutil.Logger
|
log *logutil.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,13 +35,14 @@ func init() {
|
|||||||
chi.RegisterMethod("MOVE")
|
chi.RegisterMethod("MOVE")
|
||||||
}
|
}
|
||||||
|
|
||||||
func AttachHandlers(router *chi.Mux, downloader *universal.Downloader, torMgr *torrent.TorrentManager, cfg config.ConfigInterface, api *realdebrid.RealDebrid, workerPool *ants.Pool, log *logutil.Logger) {
|
func AttachHandlers(router *chi.Mux, downloader *universal.Downloader, torMgr *torrent.TorrentManager, cfg config.ConfigInterface, api *realdebrid.RealDebrid, workerPool *ants.Pool, hosts []string, log *logutil.Logger) {
|
||||||
hs := &Handlers{
|
hs := &Handlers{
|
||||||
downloader: downloader,
|
downloader: downloader,
|
||||||
torMgr: torMgr,
|
torMgr: torMgr,
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
api: api,
|
api: api,
|
||||||
workerPool: workerPool,
|
workerPool: workerPool,
|
||||||
|
hosts: hosts,
|
||||||
log: log,
|
log: log,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -93,15 +93,15 @@ func (r *IPRepository) GetHosts(numberOfHosts int, ipv6 bool) []string {
|
|||||||
return kvList[i].Value < kvList[j].Value
|
return kvList[i].Value < kvList[j].Value
|
||||||
})
|
})
|
||||||
|
|
||||||
var optimalHosts []string
|
var hosts []string
|
||||||
if numberOfHosts == 0 {
|
if numberOfHosts == 0 {
|
||||||
numberOfHosts = len(kvList)
|
numberOfHosts = len(kvList)
|
||||||
}
|
}
|
||||||
for i := 0; i < numberOfHosts && i < len(kvList); i++ {
|
for i := 0; i < numberOfHosts && i < len(kvList); i++ {
|
||||||
optimalHosts = append(optimalHosts, kvList[i].Key)
|
hosts = append(hosts, kvList[i].Key)
|
||||||
}
|
}
|
||||||
|
|
||||||
return optimalHosts
|
return hosts
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *IPRepository) runLatencyTest() {
|
func (r *IPRepository) runLatencyTest() {
|
||||||
|
|||||||
@@ -297,6 +297,52 @@ func (rd *RealDebrid) GetUserInformation() (*User, error) {
|
|||||||
return &user, nil
|
return &user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TrafficDetails represents the structure of the traffic details response
|
||||||
|
type TrafficDetails map[string]struct {
|
||||||
|
Host map[string]int64 `json:"host"`
|
||||||
|
Bytes int64 `json:"bytes"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTrafficDetails gets the traffic details from the Real-Debrid API
|
||||||
|
func (rd *RealDebrid) GetTrafficDetails() (map[string]int64, error) {
|
||||||
|
// Construct request URL
|
||||||
|
reqURL := "https://api.real-debrid.com/rest/1.0/traffic/details"
|
||||||
|
req, err := http.NewRequest(http.MethodGet, reqURL, nil)
|
||||||
|
if err != nil {
|
||||||
|
rd.log.Errorf("Error when creating a traffic details request: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the request
|
||||||
|
resp, err := rd.apiClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
rd.log.Errorf("Error when executing the traffic details request: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// Decode the JSON response into the TrafficDetails struct
|
||||||
|
var trafficDetails TrafficDetails
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&trafficDetails)
|
||||||
|
if err != nil {
|
||||||
|
rd.log.Errorf("Error when decoding traffic details JSON: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the latest date in the traffic details
|
||||||
|
var latestDate string
|
||||||
|
for date := range trafficDetails {
|
||||||
|
if latestDate == "" || date > latestDate {
|
||||||
|
latestDate = date
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the traffic details for the latest date
|
||||||
|
latestTraffic := trafficDetails[latestDate].Host
|
||||||
|
|
||||||
|
return latestTraffic, nil
|
||||||
|
}
|
||||||
|
|
||||||
// AvailabilityCheck checks the instant availability of torrents
|
// AvailabilityCheck checks the instant availability of torrents
|
||||||
func (rd *RealDebrid) AvailabilityCheck(hashes []string) (AvailabilityResponse, error) {
|
func (rd *RealDebrid) AvailabilityCheck(hashes []string) (AvailabilityResponse, error) {
|
||||||
if len(hashes) == 0 {
|
if len(hashes) == 0 {
|
||||||
|
|||||||
Reference in New Issue
Block a user