From d1b315aa6eec1a7703a06d6d24ba8c49879a8702 Mon Sep 17 00:00:00 2001 From: Julian Kornberger Date: Sat, 12 Mar 2016 13:32:55 +0100 Subject: [PATCH] Copy data structs from node-informant/gluon-collector/data Some fields are missing there --- data/neighbours.go | 26 +++++++++++++ data/nodeinfo.go | 69 +++++++++++++++++++++++++++++++++++ data/statistics.go | 60 ++++++++++++++++++++++++++++++ data/statistics_test.go | 34 +++++++++++++++++ data/testdata/nodeinfo.json | 63 ++++++++++++++++++++++++++++++++ data/testdata/statistics.json | 63 ++++++++++++++++++++++++++++++++ main.go | 6 +-- models/nodes.go | 16 ++++---- respond/collector.go | 2 +- respond/multi_collector.go | 6 +-- stats_db.go | 51 ++++++++++++++++++-------- 11 files changed, 366 insertions(+), 30 deletions(-) create mode 100644 data/neighbours.go create mode 100644 data/nodeinfo.go create mode 100644 data/statistics.go create mode 100644 data/statistics_test.go create mode 100644 data/testdata/nodeinfo.json create mode 100644 data/testdata/statistics.json diff --git a/data/neighbours.go b/data/neighbours.go new file mode 100644 index 0000000..9d43353 --- /dev/null +++ b/data/neighbours.go @@ -0,0 +1,26 @@ +package data + +type Neighbours struct { + Batadv map[string]BatadvNeighbours `json:"batadv"` + //WifiNeighbours map[string]WifiNeighbours `json:"wifi"` + NodeId string `json:"node_id"` +} + +type WifiLink struct { + Inactive int `json:"inactive"` + Noise int `json:"nois"` + Signal int `json:"signal"` +} + +type BatmanLink struct { + Lastseen float64 `json:"lastseen"` + Tq int `json:"tq"` +} + +type BatadvNeighbours struct { + Neighbours map[string]BatmanLink `json:"neighbours"` +} + +type WifiNeighbours struct { + Neighbours map[string]WifiLink `json:"neighbours"` +} diff --git a/data/nodeinfo.go b/data/nodeinfo.go new file mode 100644 index 0000000..7fdecf1 --- /dev/null +++ b/data/nodeinfo.go @@ -0,0 +1,69 @@ +package data + +type NodeInfo struct { + NodeId string `json:"node_id"` + Network Network `json:"network"` + Owner *Owner `json:"owner,omitempty"` + System System `json:"system"` + Hostname string `json:"hostname"` + Location *Location `json:"location,omitempty"` + Software Software `json:"software"` + Hardware Hardware `json:"hardware"` + VPN bool `json:"vpn"` +} + +type Network struct { + Mac string `json:"mac"` + Addresses []string `json:"addresses"` + Mesh struct { + Bat0 struct { + Interfaces struct { + Wireless []string `json:"wireless,omitempty"` + Other []string `json:"other,omitempty"` + Tunnel []string `json:"tunnel,omitempty"` + } `json:"interfaces"` + } `json:"bat0"` + } `json:"mesh"` + MeshInterfaces []string `json:"mesh_interfaces"` +} + +type Owner struct { + Contact string `json:"contact"` +} + +type System struct { + SiteCode string `json:"site_code"` +} + +type Location struct { + Longtitude float64 `json:"longitude"` + Latitude float64 `json:"latitude"` + Altitude float64 `json:"altitude,omitempty"` +} + +type Software struct { + Autoupdater *struct { + Enabled bool `json:"enabled"` + Branch string `json:"branch"` + } `json:"autoupdater,omitempty"` + BatmanAdv *struct { + Version string `json:"version"` + Compat int `json:"compat"` + } `json:"batman-adv,omitempty"` + Fastd *struct { + Enabled bool `json:"enabled"` + Version string `json:"version"` + } `json:"fastd,omitempty"` + Firmware *struct { + Base string `json:"base"` + Release string `json:"release"` + } `json:"firmware,omitempty"` + StatusPage *struct { + Api int `json:"api"` + } `json:"status-page,omitempty"` +} + +type Hardware struct { + Nproc int `json:"nproc"` + Model string `json:"model"` +} diff --git a/data/statistics.go b/data/statistics.go new file mode 100644 index 0000000..fc73e72 --- /dev/null +++ b/data/statistics.go @@ -0,0 +1,60 @@ +package data + +type Statistics struct { + NodeId string `json:"node_id"` + Clients Clients `json:"clients"` + RootFsUsage float64 `json:"rootfs_usage"` + Traffic *Traffic `json:"traffic"` + Memory Memory `json:"memory"` + Uptime float64 `json:"uptime"` + Idletime float64 `json:"idletime"` + Gateway string `json:"gateway"` + Processes struct { + Total uint32 `json:"total"` + Running uint32 `json:"running"` + } `json:"processes"` + LoadAverage float64 `json:"loadavg"` + MeshVpn *MeshVPN `json:"mesh_vpn,omitempty"` +} + +type MeshVPNPeerLink struct { + Established float64 `json:"established"` +} + +type MeshVPNPeerGroup struct { + Peers map[string]*MeshVPNPeerLink `json:"peers"` + Groups map[string]*MeshVPNPeerGroup `json:"groups"` +} + +type MeshVPN struct { + Groups map[string]*MeshVPNPeerGroup `json:"groups,omitempty"` +} + +type TrafficEntry struct { + // Some nodes return bytes as float value + Bytes float64 `json:"bytes,omitempty"` + Packets float64 `json:"packets,omitempty"` + Dropped float64 `json:"dropped,omitempty"` +} + +type Traffic struct { + Tx *TrafficEntry `json:"tx"` + Rx *TrafficEntry `json:"rx"` + Forward *TrafficEntry `json:"forward"` + MgmtTx *TrafficEntry `json:"mgmt_tx"` + MgmtRx *TrafficEntry `json:"mgmt_rx"` +} + +type Clients struct { + Wifi uint32 `json:"wifi"` + Wifi24 uint32 `json:"wifi24"` + Wifi5 uint32 `json:"wifi5"` + Total uint32 `json:"total"` +} + +type Memory struct { + Cached uint64 `json:"cached"` + Total uint64 `json:"total"` + Buffers uint64 `json:"buffers"` + Free uint64 `json:"free"` +} diff --git a/data/statistics_test.go b/data/statistics_test.go new file mode 100644 index 0000000..fc95f28 --- /dev/null +++ b/data/statistics_test.go @@ -0,0 +1,34 @@ +package data + +import ( + "encoding/json" + "io/ioutil" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestStatistics(t *testing.T) { + assert := assert.New(t) + obj := &Statistics{} + testfile("statistics.json", obj) + + assert.Equal("f81a67a601ea", obj.NodeId) + assert.Equal("52:54:00:a9:f7:6e", obj.Gateway) + assert.Equal(float64(57861871176), obj.Traffic.Rx.Bytes) + assert.Equal(uint32(35), obj.Clients.Total) + assert.Equal(uint32(35), obj.Clients.Wifi) + assert.Equal(uint32(30), obj.Clients.Wifi24) + assert.Equal(uint32(8), obj.Clients.Wifi5) +} + +func testfile(name string, obj interface{}) { + file, err := ioutil.ReadFile("testdata/" + name) + if err != nil { + panic(err) + } + + if err := json.Unmarshal(file, obj); err != nil { + panic(err) + } +} diff --git a/data/testdata/nodeinfo.json b/data/testdata/nodeinfo.json new file mode 100644 index 0000000..bdd1e11 --- /dev/null +++ b/data/testdata/nodeinfo.json @@ -0,0 +1,63 @@ +{ + "software": { + "autoupdater": { + "branch": "stable", + "enabled": true + }, + "batman-adv": { + "version": "2013.4.0", + "compat": 14 + }, + "fastd": { + "version": "v17", + "enabled": true + }, + "firmware": { + "base": "gluon-v2016.1.2", + "release": "2016.1.2+bremen1" + }, + "status-page": { + "api": 1 + } + }, + "network": { + "addresses": [ + "fd2f:5119:f2c:0:fa1a:67ff:fea6:1ea", + "2a06:8782:ffbb:1337:fa1a:67ff:fea6:1ea", + "fe80::fa1a:67ff:fea6:1ea" + ], + "mesh": { + "bat0": { + "interfaces": { + "wireless": [ + "fa:1d:69:a6:01:ea", + "fa:1d:68:a6:01:ea" + ], + "tunnel": [ + "fa:1e:67:a6:01:ea" + ], + "other": [ + "fa:1b:68:a6:01:ea" + ] + } + } + }, + "mac": "f8:1a:67:a6:01:ea" + }, + "location": { + "latitude": 53.079362250000006, + "longitude": 8.88002693 + }, + "owner": { + "contact": "freifunk@example.com" + }, + "system": { + "site_code": "ffhb" + }, + "node_id": "f81a67a601ea", + "hostname": "foo-bar", + "hardware": { + "model": "TP-Link TL-WDR4900 v1", + "nproc": 1 + } +} diff --git a/data/testdata/statistics.json b/data/testdata/statistics.json new file mode 100644 index 0000000..51e3fac --- /dev/null +++ b/data/testdata/statistics.json @@ -0,0 +1,63 @@ +{ + "clients": { + "total": 35, + "wifi": 35, + "wifi24": 30, + "wifi5": 8 + }, + "traffic": { + "rx": { + "packets": 66182267, + "bytes": 57861871176 + }, + "tx": { + "packets": 26751682, + "bytes": 3669258402.9999998, + "dropped": 23764 + }, + "forward": { + "packets": 2223, + "bytes": 252299 + }, + "mgmt_rx": { + "packets": 3461523, + "bytes": 427521481 + }, + "mgmt_tx": { + "packets": 7694493, + "bytes": 1500526811 + } + }, + "gateway": "52:54:00:a9:f7:6e", + "mesh_vpn": { + "groups": { + "backbone": { + "peers": { + "vpn02": null, + "vpn01": null, + "vpn06": { + "established": 138270.378 + }, + "vpn05": null, + "vpn04": null, + "vpn03": null + } + } + } + }, + "node_id": "f81a67a601ea", + "rootfs_usage": 0.04178994082840237, + "memory": { + "total": 126200, + "free": 86452, + "buffers": 2308, + "cached": 8596 + }, + "uptime": 138355.13, + "idletime": 106305.02, + "loadavg": 0.48, + "processes": { + "running": 3, + "total": 47 + } +} diff --git a/main.go b/main.go index 3ce1ea3..569fd20 100644 --- a/main.go +++ b/main.go @@ -10,7 +10,7 @@ import ( "syscall" "time" - "github.com/ffdo/node-informant/gluon-collector/data" + "github.com/monitormap/micro-daemon/data" "github.com/monitormap/micro-daemon/models" "github.com/monitormap/micro-daemon/respond" "github.com/monitormap/micro-daemon/websocketserver" @@ -82,10 +82,10 @@ func onReceive(addr net.UDPAddr, msg interface{}) { case *data.NodeInfo: nodes.Get(msg.NodeId).Nodeinfo = msg - case *data.NeighbourStruct: + case *data.Neighbours: nodes.Get(msg.NodeId).Neighbours = msg - case *data.StatisticsStruct: + case *data.Statistics: nodes.Get(msg.NodeId).Statistics = msg // store data? diff --git a/models/nodes.go b/models/nodes.go index 56672cd..f067bff 100644 --- a/models/nodes.go +++ b/models/nodes.go @@ -8,16 +8,16 @@ import ( "sync" "time" - "github.com/ffdo/node-informant/gluon-collector/data" + "github.com/monitormap/micro-daemon/data" ) // Node struct type Node struct { - Firstseen time.Time `json:"firstseen"` - Lastseen time.Time `json:"lastseen"` - Statistics *data.StatisticsStruct `json:"statistics"` - Nodeinfo *data.NodeInfo `json:"nodeinfo"` - Neighbours *data.NeighbourStruct `json:"-"` + Firstseen time.Time `json:"firstseen"` + Lastseen time.Time `json:"lastseen"` + Statistics *data.Statistics `json:"statistics"` + Nodeinfo *data.NodeInfo `json:"nodeinfo"` + Neighbours *data.Neighbours `json:"-"` } type NodeElement struct { @@ -53,8 +53,8 @@ func (nodes *Nodes) Get(nodeID string) *Node { node = &Node{ Firstseen: now, Nodeinfo: &data.NodeInfo{}, - Statistics: &data.StatisticsStruct{}, - Neighbours: &data.NeighbourStruct{}, + Statistics: &data.Statistics{}, + Neighbours: &data.Neighbours{}, } nodes.List[nodeID] = node } diff --git a/respond/collector.go b/respond/collector.go index 624d4be..ae52cf0 100644 --- a/respond/collector.go +++ b/respond/collector.go @@ -104,7 +104,7 @@ func (coll *Collector) parser() { if err := json.Unmarshal(obj.Raw, data); err == nil { coll.onReceive(obj.Address, data) } else { - log.Println("unable to decode response from", obj.Address.String(), err) + log.Println("unable to decode response from", obj.Address.String(), err, "\n", string(obj.Raw)) } } } diff --git a/respond/multi_collector.go b/respond/multi_collector.go index 2e164ed..a46d6a4 100644 --- a/respond/multi_collector.go +++ b/respond/multi_collector.go @@ -1,7 +1,7 @@ package respond import ( - "github.com/ffdo/node-informant/gluon-collector/data" + "github.com/monitormap/micro-daemon/data" "time" ) @@ -14,9 +14,9 @@ type MultiCollector struct { func NewMultiCollector(interval time.Duration, onReceive OnReceive) *MultiCollector { return &MultiCollector{ collectors: []*Collector{ - NewCollector("statistics", interval, data.StatisticsStruct{}, onReceive), + NewCollector("statistics", interval, data.Statistics{}, onReceive), NewCollector("nodeinfo", interval, data.NodeInfo{}, onReceive), - NewCollector("neighbours", interval, data.NeighbourStruct{}, onReceive), + NewCollector("neighbours", interval, data.Neighbours{}, onReceive), }, } } diff --git a/stats_db.go b/stats_db.go index 6046568..d4e0793 100644 --- a/stats_db.go +++ b/stats_db.go @@ -5,8 +5,8 @@ import ( "sync" "time" - "github.com/ffdo/node-informant/gluon-collector/data" "github.com/influxdata/influxdb/client/v2" + "github.com/monitormap/micro-daemon/data" ) const ( @@ -43,24 +43,45 @@ func NewStatsDb() *StatsDb { return db } -func (c *StatsDb) Add(stats *data.StatisticsStruct) { +func (c *StatsDb) Add(stats *data.Statistics) { tags := map[string]string{ "nodeid": stats.NodeId, } fields := map[string]interface{}{ - "load": stats.LoadAverage, - "processes.open": stats.Processes.Running, - "clients.wifi": stats.Clients.Wifi, - "clients.total": stats.Clients.Total, - "traffic.forward": stats.Traffic.Forward, - "traffic.rx": stats.Traffic.Rx, - "traffic.tx": stats.Traffic.Tx, - "traffic.mgmt.rx": stats.Traffic.MgmtRx, - "traffic.mgmt.tx": stats.Traffic.MgmtTx, - "traffic.memory.buffers": stats.Memory.Buffers, - "traffic.memory.cached": stats.Memory.Cached, - "traffic.memory.free": stats.Memory.Free, - "traffic.memory.total": stats.Memory.Total, + "load": stats.LoadAverage, + "idletime": uint64(stats.Idletime), + "uptime": uint64(stats.Uptime), + "processes.running": stats.Processes.Running, + "clients.wifi": stats.Clients.Wifi, + "clients.wifi24": stats.Clients.Wifi24, + "clients.wifi5": stats.Clients.Wifi5, + "clients.total": stats.Clients.Total, + "memory.buffers": stats.Memory.Buffers, + "memory.cached": stats.Memory.Cached, + "memory.free": stats.Memory.Free, + "memory.total": stats.Memory.Total, + } + + if t := stats.Traffic.Rx; t != nil { + fields["traffic.rx.bytes"] = uint64(t.Bytes) + fields["traffic.rx.packets"] = t.Packets + } + if t := stats.Traffic.Tx; t != nil { + fields["traffic.tx.bytes"] = uint64(t.Bytes) + fields["traffic.tx.packets"] = t.Packets + fields["traffic.tx.dropped"] = t.Dropped + } + if t := stats.Traffic.Forward; t != nil { + fields["traffic.forward.bytes"] = uint64(t.Bytes) + fields["traffic.forward.packets"] = t.Packets + } + if t := stats.Traffic.MgmtRx; t != nil { + fields["traffic.mgmt_rx.bytes"] = uint64(t.Bytes) + fields["traffic.mgmt_rx.packets"] = t.Packets + } + if t := stats.Traffic.MgmtTx; t != nil { + fields["traffic.mgmt_tx.bytes"] = uint64(t.Bytes) + fields["traffic.mgmt_tx.packets"] = t.Packets } point, err := client.NewPoint("node", tags, fields, time.Now())