2016-03-12 02:36:02 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"log"
|
2016-07-04 12:39:48 +00:00
|
|
|
"strconv"
|
2016-03-12 02:36:02 +00:00
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
2016-03-15 22:26:30 +00:00
|
|
|
"github.com/FreifunkBremen/respond-collector/data"
|
2016-03-12 02:36:02 +00:00
|
|
|
"github.com/influxdata/influxdb/client/v2"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2016-03-28 13:46:22 +00:00
|
|
|
batchDuration = time.Second * 5
|
2016-03-12 02:36:02 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type StatsDb struct {
|
|
|
|
points chan *client.Point
|
|
|
|
wg sync.WaitGroup
|
|
|
|
client client.Client
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewStatsDb() *StatsDb {
|
|
|
|
// Make client
|
|
|
|
c, err := client.NewHTTPClient(client.HTTPConfig{
|
2016-04-29 10:39:53 +00:00
|
|
|
Addr: config.Influxdb.Addr,
|
2016-03-12 02:36:02 +00:00
|
|
|
Username: config.Influxdb.Username,
|
|
|
|
Password: config.Influxdb.Password,
|
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
db := &StatsDb{
|
|
|
|
client: c,
|
|
|
|
points: make(chan *client.Point, 500),
|
|
|
|
}
|
|
|
|
|
|
|
|
// start worker
|
|
|
|
db.wg.Add(1)
|
|
|
|
go db.worker()
|
|
|
|
|
|
|
|
return db
|
|
|
|
}
|
|
|
|
|
2016-03-12 12:32:55 +00:00
|
|
|
func (c *StatsDb) Add(stats *data.Statistics) {
|
2016-03-12 02:36:02 +00:00
|
|
|
tags := map[string]string{
|
|
|
|
"nodeid": stats.NodeId,
|
|
|
|
}
|
|
|
|
fields := map[string]interface{}{
|
2016-03-12 12:32:55 +00:00
|
|
|
"load": stats.LoadAverage,
|
2016-03-23 21:19:53 +00:00
|
|
|
"idletime": int64(stats.Idletime),
|
|
|
|
"uptime": int64(stats.Uptime),
|
2016-03-12 12:32:55 +00:00
|
|
|
"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 {
|
2016-03-23 21:19:53 +00:00
|
|
|
fields["traffic.rx.bytes"] = int64(t.Bytes)
|
2016-03-12 12:32:55 +00:00
|
|
|
fields["traffic.rx.packets"] = t.Packets
|
|
|
|
}
|
|
|
|
if t := stats.Traffic.Tx; t != nil {
|
2016-03-23 21:19:53 +00:00
|
|
|
fields["traffic.tx.bytes"] = int64(t.Bytes)
|
2016-03-12 12:32:55 +00:00
|
|
|
fields["traffic.tx.packets"] = t.Packets
|
|
|
|
fields["traffic.tx.dropped"] = t.Dropped
|
|
|
|
}
|
|
|
|
if t := stats.Traffic.Forward; t != nil {
|
2016-03-23 21:19:53 +00:00
|
|
|
fields["traffic.forward.bytes"] = int64(t.Bytes)
|
2016-03-12 12:32:55 +00:00
|
|
|
fields["traffic.forward.packets"] = t.Packets
|
|
|
|
}
|
|
|
|
if t := stats.Traffic.MgmtRx; t != nil {
|
2016-03-23 21:19:53 +00:00
|
|
|
fields["traffic.mgmt_rx.bytes"] = int64(t.Bytes)
|
2016-03-12 12:32:55 +00:00
|
|
|
fields["traffic.mgmt_rx.packets"] = t.Packets
|
|
|
|
}
|
|
|
|
if t := stats.Traffic.MgmtTx; t != nil {
|
2016-03-23 21:19:53 +00:00
|
|
|
fields["traffic.mgmt_tx.bytes"] = int64(t.Bytes)
|
2016-03-12 12:32:55 +00:00
|
|
|
fields["traffic.mgmt_tx.packets"] = t.Packets
|
2016-03-12 02:36:02 +00:00
|
|
|
}
|
2016-07-04 12:39:48 +00:00
|
|
|
if w := stats.Wireless; w != nil {
|
|
|
|
if time := w.Airtime24; time != nil {
|
|
|
|
fields["airtime24.active"] = time.Active
|
|
|
|
fields["airtime24.busy"] = time.Busy
|
|
|
|
fields["airtime24.tx"] = time.Tx
|
|
|
|
fields["airtime24.rx"] = time.Rx
|
|
|
|
fields["airtime24.noise"] = time.Noise
|
|
|
|
fields["airtime24.frequency"] = time.Frequency
|
|
|
|
tags["frequency24"] = strconv.Itoa(int(time.Frequency))
|
|
|
|
}
|
|
|
|
if time := w.Airtime5; time != nil {
|
|
|
|
fields["airtime5.active"] = time.Active
|
|
|
|
fields["airtime5.busy"] = time.Busy
|
|
|
|
fields["airtime5.tx"] = time.Tx
|
|
|
|
fields["airtime5.rx"] = time.Rx
|
|
|
|
fields["airtime5.noise"] = time.Noise
|
|
|
|
fields["airtime5.frequency"] = time.Frequency
|
|
|
|
tags["frequency5"] = strconv.Itoa(int(time.Frequency))
|
|
|
|
}
|
|
|
|
}
|
2016-03-12 02:36:02 +00:00
|
|
|
|
|
|
|
point, err := client.NewPoint("node", tags, fields, time.Now())
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
c.points <- point
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *StatsDb) Close() {
|
|
|
|
close(c.points)
|
|
|
|
c.wg.Wait()
|
|
|
|
c.client.Close()
|
|
|
|
}
|
|
|
|
|
2016-03-12 02:58:36 +00:00
|
|
|
// stores data points in batches into the influxdb
|
2016-03-12 02:36:02 +00:00
|
|
|
func (c *StatsDb) worker() {
|
|
|
|
bpConfig := client.BatchPointsConfig{
|
|
|
|
Database: config.Influxdb.Database,
|
|
|
|
Precision: "m",
|
|
|
|
}
|
|
|
|
|
|
|
|
var bp client.BatchPoints
|
|
|
|
var err error
|
2016-03-28 13:46:22 +00:00
|
|
|
var writeNow, closed bool
|
|
|
|
timer := time.NewTimer(batchDuration)
|
2016-03-12 02:36:02 +00:00
|
|
|
|
2016-03-12 15:27:52 +00:00
|
|
|
for !closed {
|
2016-03-12 02:36:02 +00:00
|
|
|
|
|
|
|
// wait for new points
|
|
|
|
select {
|
|
|
|
case point, ok := <-c.points:
|
|
|
|
if ok {
|
2016-03-28 13:46:22 +00:00
|
|
|
if bp == nil {
|
|
|
|
// create new batch
|
|
|
|
timer.Reset(batchDuration)
|
|
|
|
if bp, err = client.NewBatchPoints(bpConfig); err != nil {
|
2016-07-04 12:39:48 +00:00
|
|
|
log.Fatal(err)
|
2016-03-28 13:46:22 +00:00
|
|
|
}
|
2016-03-12 15:27:52 +00:00
|
|
|
}
|
2016-03-28 13:46:22 +00:00
|
|
|
bp.AddPoint(point)
|
2016-03-12 02:36:02 +00:00
|
|
|
} else {
|
2016-03-12 15:27:52 +00:00
|
|
|
closed = true
|
2016-03-12 02:36:02 +00:00
|
|
|
}
|
2016-03-28 13:46:22 +00:00
|
|
|
case <-timer.C:
|
|
|
|
if bp == nil {
|
|
|
|
timer.Reset(batchDuration)
|
|
|
|
} else {
|
|
|
|
writeNow = true
|
|
|
|
}
|
2016-03-12 02:36:02 +00:00
|
|
|
}
|
|
|
|
|
2016-03-12 02:58:36 +00:00
|
|
|
// write batch now?
|
2016-03-28 13:46:22 +00:00
|
|
|
if bp != nil && (writeNow || closed) {
|
2016-03-12 02:36:02 +00:00
|
|
|
log.Println("saving", len(bp.Points()), "points")
|
|
|
|
|
2016-03-12 02:58:36 +00:00
|
|
|
if err = c.client.Write(bp); err != nil {
|
2016-07-04 12:39:48 +00:00
|
|
|
log.Fatal(err)
|
2016-03-12 02:36:02 +00:00
|
|
|
}
|
2016-03-28 13:46:22 +00:00
|
|
|
writeNow = false
|
2016-03-12 02:36:02 +00:00
|
|
|
bp = nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-28 13:46:22 +00:00
|
|
|
timer.Stop()
|
2016-03-12 02:36:02 +00:00
|
|
|
c.wg.Done()
|
|
|
|
}
|