This adds a statistic to track the last connection duration per device. It isn't used for much in this PR, but it's available for #7223 to use in deciding how to order device connection attempts (deprioritizing devices that just dropped our connection the last time).
This commit is contained in:
+36
-7
@@ -10,26 +10,34 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
"github.com/syncthing/syncthing/lib/db/backend"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
|
||||
const (
|
||||
lastSeenKey = "lastSeen"
|
||||
connDurationKey = "lastConnDuration"
|
||||
)
|
||||
|
||||
type DeviceStatistics struct {
|
||||
LastSeen time.Time `json:"lastSeen"`
|
||||
LastSeen time.Time `json:"lastSeen"`
|
||||
LastConnectionDurationS float64 `json:"lastConnectionDurationS"`
|
||||
}
|
||||
|
||||
type DeviceStatisticsReference struct {
|
||||
ns *db.NamespacedKV
|
||||
device string
|
||||
device protocol.DeviceID
|
||||
}
|
||||
|
||||
func NewDeviceStatisticsReference(ldb *db.Lowlevel, device string) *DeviceStatisticsReference {
|
||||
func NewDeviceStatisticsReference(dba backend.Backend, device protocol.DeviceID) *DeviceStatisticsReference {
|
||||
return &DeviceStatisticsReference{
|
||||
ns: db.NewDeviceStatisticsNamespace(ldb, device),
|
||||
ns: db.NewDeviceStatisticsNamespace(dba, device.String()),
|
||||
device: device,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DeviceStatisticsReference) GetLastSeen() (time.Time, error) {
|
||||
t, ok, err := s.ns.Time("lastSeen")
|
||||
t, ok, err := s.ns.Time(lastSeenKey)
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
} else if !ok {
|
||||
@@ -41,9 +49,25 @@ func (s *DeviceStatisticsReference) GetLastSeen() (time.Time, error) {
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (s *DeviceStatisticsReference) GetLastConnectionDuration() (time.Duration, error) {
|
||||
d, ok, err := s.ns.Int64(connDurationKey)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
} else if !ok {
|
||||
return 0, nil
|
||||
}
|
||||
l.Debugln("stats.DeviceStatisticsReference.GetLastConnectionDuration:", s.device, d)
|
||||
return time.Duration(d), nil
|
||||
}
|
||||
|
||||
func (s *DeviceStatisticsReference) WasSeen() error {
|
||||
l.Debugln("stats.DeviceStatisticsReference.WasSeen:", s.device)
|
||||
return s.ns.PutTime("lastSeen", time.Now())
|
||||
return s.ns.PutTime(lastSeenKey, time.Now())
|
||||
}
|
||||
|
||||
func (s *DeviceStatisticsReference) LastConnectionDuration(d time.Duration) error {
|
||||
l.Debugln("stats.DeviceStatisticsReference.LastConnectionDuration:", s.device, d)
|
||||
return s.ns.PutInt64(connDurationKey, d.Nanoseconds())
|
||||
}
|
||||
|
||||
func (s *DeviceStatisticsReference) GetStatistics() (DeviceStatistics, error) {
|
||||
@@ -51,7 +75,12 @@ func (s *DeviceStatisticsReference) GetStatistics() (DeviceStatistics, error) {
|
||||
if err != nil {
|
||||
return DeviceStatistics{}, err
|
||||
}
|
||||
lastConnDuration, err := s.GetLastConnectionDuration()
|
||||
if err != nil {
|
||||
return DeviceStatistics{}, err
|
||||
}
|
||||
return DeviceStatistics{
|
||||
LastSeen: lastSeen,
|
||||
LastSeen: lastSeen,
|
||||
LastConnectionDurationS: lastConnDuration.Seconds(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
// Copyright (C) 2016 The Syncthing Authors.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
// The existence of this file means we get 0% test coverage rather than no
|
||||
// test coverage at all. Remove when implementing an actual test.
|
||||
|
||||
package stats
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright (C) 2020 The Syncthing Authors.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
// The existence of this file means we get 0% test coverage rather than no
|
||||
// test coverage at all. Remove when implementing an actual test.
|
||||
|
||||
package stats
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/db/backend"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
|
||||
func TestDeviceStat(t *testing.T) {
|
||||
db := backend.OpenLevelDBMemory()
|
||||
defer db.Close()
|
||||
|
||||
sr := NewDeviceStatisticsReference(db, protocol.LocalDeviceID)
|
||||
if err := sr.WasSeen(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := sr.LastConnectionDuration(42 * time.Second); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
stat, err := sr.GetStatistics()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if d := time.Since(stat.LastSeen); d > 5*time.Second {
|
||||
t.Error("Last seen far in the past:", d)
|
||||
}
|
||||
if d := stat.LastConnectionDurationS; d != 42 {
|
||||
t.Error("Bad last duration:", d)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user