v0.342.0 (unreleased): the upload watch reads the host's weekly line test (GET /host/line-test, agent >= 0.164.0); qBittorrent's limit = 50 % of the TESTED line only (D41), the watch uses the higher of test and push floor, the system page names the source; red-proved
gates / gates (push) Successful in 1m15s
gates / gates (push) Successful in 1m15s
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/agentapi"
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/backup"
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/mediawire"
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/metrics"
|
||||
@@ -24,10 +25,11 @@ const baselineMinMinutes = 1200
|
||||
|
||||
// newUpwatch builds the upload and CPU watch (internal/upwatch; felhom.eu `08` §9). It does not start it.
|
||||
func newUpwatch(sett *settings.Settings, stackMgr *stacks.Manager, backupMgr *backup.Manager, metricsStore *metrics.MetricsStore,
|
||||
notifier *notify.Notifier, logger *log.Logger) *upwatch.Service {
|
||||
notifier *notify.Notifier, measured func(context.Context) (float64, time.Time, bool), logger *log.Logger) *upwatch.Service {
|
||||
box := mediawire.DockerBox{}
|
||||
qb := &upwatch.QBittorrent{Box: box}
|
||||
svc := &upwatch.Service{Store: sett, QB: qb, QBRunning: func() bool { return box.Running("qbittorrent") }, QBShare: qbLimitShare, Log: logger}
|
||||
svc := &upwatch.Service{Store: sett, QB: qb, QBRunning: func() bool { return box.Running("qbittorrent") }, QBShare: qbLimitShare,
|
||||
Measured: measured, Log: logger}
|
||||
w := &upwatch.Watcher{
|
||||
Source: &upwatch.DockerAPI{},
|
||||
Explainers: map[string]upwatch.Explainer{
|
||||
@@ -56,6 +58,29 @@ func newUpwatch(sett *settings.Settings, stackMgr *stacks.Manager, backupMgr *ba
|
||||
return svc
|
||||
}
|
||||
|
||||
// agentLineTest reads the host's weekly line test through the agent's local API (agent ≥ 0.164.0; an older agent
|
||||
// answers 404 → not measured). nil without a local API.
|
||||
func agentLineTest(endpoint, token, fingerprint string, logger *log.Logger) func(context.Context) (float64, time.Time, bool) {
|
||||
if endpoint == "" || token == "" {
|
||||
return nil
|
||||
}
|
||||
ac, err := agentapi.New(endpoint, token, fingerprint)
|
||||
if err != nil {
|
||||
logger.Printf("[WARN] [upwatch] agent client init failed (%v) — no line test; qBittorrent gets no limit", err)
|
||||
return nil
|
||||
}
|
||||
return func(ctx context.Context) (float64, time.Time, bool) {
|
||||
cctx, cancel := context.WithTimeout(ctx, 15*time.Second)
|
||||
defer cancel()
|
||||
st, err := ac.LineTest(cctx)
|
||||
if err != nil {
|
||||
logger.Printf("[DEBUG] [upwatch] line test read: %v", err)
|
||||
return 0, time.Time{}, false
|
||||
}
|
||||
return st.Mbps, st.MeasuredAtTime(), st.Present
|
||||
}
|
||||
}
|
||||
|
||||
// dailyBaseline caches each app's p95 for a day (a 7-day query is a few hundred thousand rows).
|
||||
func dailyBaseline(ms *metrics.MetricsStore) func(string, []string) (float64, bool) {
|
||||
type entry struct {
|
||||
@@ -80,6 +105,7 @@ func dailyBaseline(ms *metrics.MetricsStore) func(string, []string) (float64, bo
|
||||
|
||||
// startUpwatch runs the minute watcher and the 15-minute qBittorrent limit rule until ctx ends.
|
||||
func startUpwatch(ctx context.Context, svc *upwatch.Service, logger *log.Logger) {
|
||||
svc.RefreshMeasured(ctx)
|
||||
go svc.Watcher.Run(ctx, time.Minute)
|
||||
go func() {
|
||||
t := time.NewTicker(15 * time.Minute)
|
||||
@@ -101,5 +127,5 @@ func lineText(l float64, ok bool) string {
|
||||
if !ok {
|
||||
return "unknown — learning from the off-site push"
|
||||
}
|
||||
return "at least " + upwatch.MbpsText(int64(l*1e6/8)) + " Mbit/s"
|
||||
return upwatch.MbpsText(int64(l*1e6/8)) + " Mbit/s"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user