mirror of
https://github.com/octoleo/syncthing.git
synced 2025-02-02 11:58:28 +00:00
Report transfer stats
This commit is contained in:
parent
cd2040a7d2
commit
746d52930d
@ -229,7 +229,6 @@ func (d *Discoverer) externalLookup(node string) (string, bool) {
|
|||||||
log.Printf("discover/external: %v; no external lookup", err)
|
log.Printf("discover/external: %v; no external lookup", err)
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
log.Println("query", extIP)
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
var buf = make([]byte, 1024)
|
var buf = make([]byte, 1024)
|
||||||
|
4
main.go
4
main.go
@ -162,7 +162,7 @@ func main() {
|
|||||||
// XXX: Should use some fsnotify mechanism.
|
// XXX: Should use some fsnotify mechanism.
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
time.Sleep(time.Duration(opts.ScanInterval) * time.Second)
|
time.Sleep(opts.ScanInterval)
|
||||||
updateLocalModel(m)
|
updateLocalModel(m)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -291,7 +291,7 @@ func connect(myID string, addr string, nodeAddrs map[string][]string, m *Model,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(time.Duration(opts.ConnInterval) * time.Second)
|
time.Sleep(opts.ConnInterval)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
31
model.go
31
model.go
@ -14,6 +14,7 @@ TODO(jb): Keep global and per node transfer and performance statistics.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"sync"
|
"sync"
|
||||||
@ -49,6 +50,7 @@ func NewModel(dir string) *Model {
|
|||||||
nodes: make(map[string]*protocol.Connection),
|
nodes: make(map[string]*protocol.Connection),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
go m.printStats()
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +58,35 @@ func (m *Model) Start() {
|
|||||||
go m.puller()
|
go m.puller()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Model) printStats() {
|
||||||
|
for {
|
||||||
|
time.Sleep(15 * time.Second)
|
||||||
|
m.RLock()
|
||||||
|
for node, conn := range m.nodes {
|
||||||
|
stats := conn.Statistics()
|
||||||
|
if (stats.InBytesPerSec > 0 || stats.OutBytesPerSec > 0) && stats.Latency > 0 {
|
||||||
|
infof("%s: %sB/s in, %sB/s out, %0.02f ms", node, toSI(stats.InBytesPerSec), toSI(stats.OutBytesPerSec), stats.Latency.Seconds()*1000)
|
||||||
|
} else if stats.InBytesPerSec > 0 || stats.OutBytesPerSec > 0 {
|
||||||
|
infof("%s: %sB/s in, %sB/s out", node, toSI(stats.InBytesPerSec), toSI(stats.OutBytesPerSec))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.RUnlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toSI(n int) string {
|
||||||
|
if n > 1<<30 {
|
||||||
|
return fmt.Sprintf("%.02f G", float64(n)/(1<<30))
|
||||||
|
}
|
||||||
|
if n > 1<<20 {
|
||||||
|
return fmt.Sprintf("%.02f M", float64(n)/(1<<20))
|
||||||
|
}
|
||||||
|
if n > 1<<10 {
|
||||||
|
return fmt.Sprintf("%.01f K", float64(n)/(1<<10))
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%d ", n)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Model) Index(nodeID string, fs []protocol.FileInfo) {
|
func (m *Model) Index(nodeID string, fs []protocol.FileInfo) {
|
||||||
m.Lock()
|
m.Lock()
|
||||||
defer m.Unlock()
|
defer m.Unlock()
|
||||||
|
@ -42,18 +42,19 @@ type Model interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Connection struct {
|
type Connection struct {
|
||||||
ID string
|
ID string
|
||||||
receiver Model
|
receiver Model
|
||||||
reader io.Reader
|
reader io.Reader
|
||||||
mreader *marshalReader
|
mreader *marshalReader
|
||||||
writer io.Writer
|
writer io.Writer
|
||||||
mwriter *marshalWriter
|
mwriter *marshalWriter
|
||||||
wLock sync.RWMutex
|
wLock sync.RWMutex
|
||||||
closed bool
|
closed bool
|
||||||
awaiting map[int]chan asyncResult
|
awaiting map[int]chan asyncResult
|
||||||
nextId int
|
nextId int
|
||||||
lastReceive time.Time
|
lastReceive time.Time
|
||||||
peerLatency time.Duration
|
peerLatency time.Duration
|
||||||
|
lastStatistics Statistics
|
||||||
}
|
}
|
||||||
|
|
||||||
var ErrClosed = errors.New("Connection closed")
|
var ErrClosed = errors.New("Connection closed")
|
||||||
@ -74,14 +75,15 @@ func NewConnection(nodeID string, reader io.Reader, writer io.Writer, receiver M
|
|||||||
}
|
}
|
||||||
|
|
||||||
c := Connection{
|
c := Connection{
|
||||||
receiver: receiver,
|
receiver: receiver,
|
||||||
reader: flrd,
|
reader: flrd,
|
||||||
mreader: &marshalReader{flrd, 0, nil},
|
mreader: &marshalReader{flrd, 0, nil},
|
||||||
writer: flwr,
|
writer: flwr,
|
||||||
mwriter: &marshalWriter{flwr, 0, nil},
|
mwriter: &marshalWriter{flwr, 0, nil},
|
||||||
awaiting: make(map[int]chan asyncResult),
|
awaiting: make(map[int]chan asyncResult),
|
||||||
lastReceive: time.Now(),
|
lastReceive: time.Now(),
|
||||||
ID: nodeID,
|
ID: nodeID,
|
||||||
|
lastStatistics: Statistics{At: time.Now()},
|
||||||
}
|
}
|
||||||
|
|
||||||
go c.readerLoop()
|
go c.readerLoop()
|
||||||
@ -313,3 +315,29 @@ func (c *Connection) pingerLoop() {
|
|||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Statistics struct {
|
||||||
|
At time.Time
|
||||||
|
InBytesTotal int
|
||||||
|
InBytesPerSec int
|
||||||
|
OutBytesTotal int
|
||||||
|
OutBytesPerSec int
|
||||||
|
Latency time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) Statistics() Statistics {
|
||||||
|
c.wLock.Lock()
|
||||||
|
defer c.wLock.Unlock()
|
||||||
|
|
||||||
|
secs := time.Since(c.lastStatistics.At).Seconds()
|
||||||
|
stats := Statistics{
|
||||||
|
At: time.Now(),
|
||||||
|
InBytesTotal: c.mreader.tot,
|
||||||
|
InBytesPerSec: int(float64(c.mreader.tot-c.lastStatistics.InBytesTotal) / secs),
|
||||||
|
OutBytesTotal: c.mwriter.tot,
|
||||||
|
OutBytesPerSec: int(float64(c.mwriter.tot-c.lastStatistics.OutBytesTotal) / secs),
|
||||||
|
Latency: c.peerLatency,
|
||||||
|
}
|
||||||
|
c.lastStatistics = stats
|
||||||
|
return stats
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user