Publish more event details

This commit is contained in:
Jakob Borg 2014-07-17 13:38:36 +02:00
parent ec212f73eb
commit f88a7a8e6a
5 changed files with 101 additions and 46 deletions

View File

@ -209,7 +209,7 @@ func restGetModel(m *model.Model, w http.ResponseWriter, r *http.Request) {
res["inSyncFiles"], res["inSyncBytes"] = globalFiles-needFiles, globalBytes-needBytes res["inSyncFiles"], res["inSyncBytes"] = globalFiles-needFiles, globalBytes-needBytes
res["state"] = m.State(repo) res["state"], res["stateChanged"] = m.State(repo)
res["version"] = m.LocalVersion(repo) res["version"] = m.LocalVersion(repo)
w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set("Content-Type", "application/json; charset=utf-8")

View File

@ -163,6 +163,8 @@ func main() {
confDir = expandTilde(confDir) confDir = expandTilde(confDir)
events.Default.Log(events.Starting, map[string]string{"home": confDir})
if _, err := os.Stat(confDir); err != nil && confDir == getDefaultConfDir() { if _, err := os.Stat(confDir); err != nil && confDir == getDefaultConfDir() {
// We are supposed to use the default configuration directory. It // We are supposed to use the default configuration directory. It
// doesn't exist. In the past our default has been ~/.syncthing, so if // doesn't exist. In the past our default has been ~/.syncthing, so if

View File

@ -15,6 +15,7 @@ import (
"time" "time"
"github.com/calmh/syncthing/beacon" "github.com/calmh/syncthing/beacon"
"github.com/calmh/syncthing/events"
"github.com/calmh/syncthing/protocol" "github.com/calmh/syncthing/protocol"
) )
@ -256,12 +257,12 @@ func (d *Discoverer) recvAnnouncements() {
var newNode bool var newNode bool
if bytes.Compare(pkt.This.ID, d.myID[:]) != 0 { if bytes.Compare(pkt.This.ID, d.myID[:]) != 0 {
n := d.registerNode(addr, pkt.This) newNode = d.registerNode(addr, pkt.This)
newNode = newNode || n
for _, node := range pkt.Extra { for _, node := range pkt.Extra {
if bytes.Compare(node.ID, d.myID[:]) != 0 { if bytes.Compare(node.ID, d.myID[:]) != 0 {
n := d.registerNode(nil, node) if d.registerNode(nil, node) {
newNode = newNode || n newNode = true
}
} }
} }
} }
@ -302,6 +303,13 @@ func (d *Discoverer) registerNode(addr net.Addr, node Node) bool {
_, seen := d.registry[id] _, seen := d.registry[id]
d.registry[id] = addrs d.registry[id] = addrs
d.registryLock.Unlock() d.registryLock.Unlock()
if !seen {
events.Default.Log(events.NodeDiscovered, map[string]interface{}{
"node": id.String(),
"addrs": addrs,
})
}
return !seen return !seen
} }

View File

@ -11,13 +11,16 @@ type EventType uint64
const ( const (
Ping = 1 << iota Ping = 1 << iota
Starting
StartupComplete StartupComplete
NodeDiscovered
NodeConnected NodeConnected
NodeDisconnected NodeDisconnected
LocalIndexUpdated LocalIndexUpdated
RemoteIndexUpdated RemoteIndexUpdated
ItemStarted ItemStarted
ItemCompleted ItemCompleted
StateChanged
AllEvents = ^EventType(0) AllEvents = ^EventType(0)
) )
@ -26,8 +29,12 @@ func (t EventType) String() string {
switch t { switch t {
case Ping: case Ping:
return "Ping" return "Ping"
case Starting:
return "Starting"
case StartupComplete: case StartupComplete:
return "StartupComplete" return "StartupComplete"
case NodeDiscovered:
return "NodeDiscovered"
case NodeConnected: case NodeConnected:
return "NodeConnected" return "NodeConnected"
case NodeDisconnected: case NodeDisconnected:
@ -38,6 +45,8 @@ func (t EventType) String() string {
return "RemoteIndexUpdated" return "RemoteIndexUpdated"
case ItemStarted: case ItemStarted:
return "ItemStarted" return "ItemStarted"
case StateChanged:
return "StateChanged"
default: default:
return "Unknown" return "Unknown"
} }

View File

@ -33,6 +33,21 @@ const (
RepoCleaning RepoCleaning
) )
func (s repoState) String() string {
switch s {
case RepoIdle:
return "idle"
case RepoScanning:
return "scanning"
case RepoCleaning:
return "cleaning"
case RepoSyncing:
return "syncing"
default:
return "unknown"
}
}
// Somewhat arbitrary amount of bytes that we choose to let represent the size // Somewhat arbitrary amount of bytes that we choose to let represent the size
// of an unsynchronized directory entry or a deleted file. We need it to be // of an unsynchronized directory entry or a deleted file. We need it to be
// larger than zero so that it's visible that there is some amount of bytes to // larger than zero so that it's visible that there is some amount of bytes to
@ -58,6 +73,7 @@ type Model struct {
rmut sync.RWMutex // protects the above rmut sync.RWMutex // protects the above
repoState map[string]repoState // repo -> state repoState map[string]repoState // repo -> state
repoStateChanged map[string]time.Time // repo -> time when state changed
smut sync.RWMutex smut sync.RWMutex
protoConn map[protocol.NodeID]protocol.Connection protoConn map[protocol.NodeID]protocol.Connection
@ -94,6 +110,7 @@ func NewModel(indexDir string, cfg *config.Configuration, clientName, clientVers
repoNodes: make(map[string][]protocol.NodeID), repoNodes: make(map[string][]protocol.NodeID),
nodeRepos: make(map[protocol.NodeID][]string), nodeRepos: make(map[protocol.NodeID][]string),
repoState: make(map[string]repoState), repoState: make(map[string]repoState),
repoStateChanged: make(map[string]time.Time),
suppressor: make(map[string]*suppressor), suppressor: make(map[string]*suppressor),
protoConn: make(map[protocol.NodeID]protocol.Connection), protoConn: make(map[protocol.NodeID]protocol.Connection),
rawConn: make(map[protocol.NodeID]io.Closer), rawConn: make(map[protocol.NodeID]io.Closer),
@ -322,16 +339,20 @@ func (m *Model) Index(nodeID protocol.NodeID, repo string, fs []protocol.FileInf
} }
m.rmut.RLock() m.rmut.RLock()
if r, ok := m.repoFiles[repo]; ok { r, ok := m.repoFiles[repo]
m.rmut.RUnlock()
if ok {
r.Replace(nodeID, fs) r.Replace(nodeID, fs)
} else { } else {
l.Fatalf("Index for nonexistant repo %q", repo) l.Fatalf("Index for nonexistant repo %q", repo)
} }
m.rmut.RUnlock() m.rmut.RUnlock()
events.Default.Log(events.RemoteIndexUpdated, map[string]string{ events.Default.Log(events.RemoteIndexUpdated, map[string]interface{}{
"node": nodeID.String(), "node": nodeID.String(),
"repo": repo, "repo": repo,
"items": len(fs),
"version": r.LocalVersion(nodeID),
}) })
} }
@ -348,16 +369,21 @@ func (m *Model) IndexUpdate(nodeID protocol.NodeID, repo string, fs []protocol.F
} }
m.rmut.RLock() m.rmut.RLock()
if r, ok := m.repoFiles[repo]; ok { r, ok := m.repoFiles[repo]
m.rmut.RUnlock()
m.rmut.RLock()
if ok {
r.Update(nodeID, fs) r.Update(nodeID, fs)
} else { } else {
l.Fatalf("IndexUpdate for nonexistant repo %q", repo) l.Fatalf("IndexUpdate for nonexistant repo %q", repo)
} }
m.rmut.RUnlock() m.rmut.RUnlock()
events.Default.Log(events.RemoteIndexUpdated, map[string]string{ events.Default.Log(events.RemoteIndexUpdated, map[string]interface{}{
"node": nodeID.String(), "node": nodeID.String(),
"repo": repo, "repo": repo,
"items": len(fs),
"version": r.LocalVersion(nodeID),
}) })
} }
@ -620,7 +646,13 @@ func (m *Model) updateLocal(repo string, f protocol.FileInfo) {
m.rmut.RLock() m.rmut.RLock()
m.repoFiles[repo].Update(protocol.LocalNodeID, []protocol.FileInfo{f}) m.repoFiles[repo].Update(protocol.LocalNodeID, []protocol.FileInfo{f})
m.rmut.RUnlock() m.rmut.RUnlock()
events.Default.Log(events.LocalIndexUpdated, map[string]string{"repo": repo}) events.Default.Log(events.LocalIndexUpdated, map[string]interface{}{
"repo": repo,
"name": f.Name,
"modified": time.Unix(f.Modified, 0),
"flags": fmt.Sprintf("0%o", f.Flags),
"size": f.Size(),
})
} }
func (m *Model) requestGlobal(nodeID protocol.NodeID, repo, name string, offset int64, size int, hash []byte) ([]byte, error) { func (m *Model) requestGlobal(nodeID protocol.NodeID, repo, name string, offset int64, size int, hash []byte) ([]byte, error) {
@ -797,26 +829,30 @@ func (m *Model) clusterConfig(node protocol.NodeID) protocol.ClusterConfigMessag
func (m *Model) setState(repo string, state repoState) { func (m *Model) setState(repo string, state repoState) {
m.smut.Lock() m.smut.Lock()
oldState := m.repoState[repo]
changed, ok := m.repoStateChanged[repo]
if state != oldState {
m.repoState[repo] = state m.repoState[repo] = state
m.repoStateChanged[repo] = time.Now()
eventData := map[string]interface{}{
"repo": repo,
"to": state.String(),
}
if ok {
eventData["duration"] = time.Since(changed).Seconds()
eventData["from"] = oldState.String()
}
events.Default.Log(events.StateChanged, eventData)
}
m.smut.Unlock() m.smut.Unlock()
} }
func (m *Model) State(repo string) string { func (m *Model) State(repo string) (string, time.Time) {
m.smut.RLock() m.smut.RLock()
state := m.repoState[repo] state := m.repoState[repo]
changed := m.repoStateChanged[repo]
m.smut.RUnlock() m.smut.RUnlock()
switch state { return state.String(), changed
case RepoIdle:
return "idle"
case RepoScanning:
return "scanning"
case RepoCleaning:
return "cleaning"
case RepoSyncing:
return "syncing"
default:
return "unknown"
}
} }
func (m *Model) Override(repo string) { func (m *Model) Override(repo string) {