From 75228cf8bf78ca66705de1ead6f2a4c77150852b Mon Sep 17 00:00:00 2001 From: Julian Kornberger Date: Mon, 3 Oct 2016 19:56:02 +0200 Subject: [PATCH] Add importer for global RRD stats --- main.go | 24 ++++++++++++++++++++ rrd/rrd.go | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 rrd/rrd.go diff --git a/main.go b/main.go index 10e4838..fcffe3b 100644 --- a/main.go +++ b/main.go @@ -17,6 +17,7 @@ import ( "github.com/FreifunkBremen/respond-collector/database" "github.com/FreifunkBremen/respond-collector/models" "github.com/FreifunkBremen/respond-collector/respond" + "github.com/FreifunkBremen/respond-collector/rrd" ) var ( @@ -28,12 +29,19 @@ var ( ) func main() { + var importPath string + flag.StringVar(&importPath, "import", "", "import global statistics from the given RRD file, requires influxdb") flag.StringVar(&configFile, "config", "config.yml", "path of configuration file (default:config.yaml)") flag.Parse() config = models.ReadConfigFile(configFile) if config.Influxdb.Enable { db = database.New(config) + + if importPath != "" { + importRRD(importPath) + os.Exit(0) + } } nodes = models.NewNodes(config) @@ -74,3 +82,19 @@ func main() { db.Close() } } + +func importRRD(path string) { + log.Println("importing RRD from", path) + for ds := range rrd.Read(path) { + db.AddPoint( + database.MeasurementGlobal, + nil, + map[string]interface{}{ + "nodes": ds.Nodes, + "clients.total": ds.Clients, + }, + ds.Time, + ) + } + db.Close() +} diff --git a/rrd/rrd.go b/rrd/rrd.go new file mode 100644 index 0000000..160166f --- /dev/null +++ b/rrd/rrd.go @@ -0,0 +1,66 @@ +// Importer for global RRD stats +package rrd + +import ( + "bufio" + "io" + "os/exec" + "regexp" + "strconv" + "strings" + "time" +) + +var linePattern = regexp.MustCompile("^ ([^<]+)([^<]+)") + +type Dataset struct { + Time time.Time + Nodes float64 + Clients float64 +} + +func Read(rrdFile string) chan Dataset { + out := make(chan Dataset) + cmd := exec.Command("rrdtool", "dump", rrdFile) + stdout, err := cmd.StdoutPipe() + + if err != nil { + panic(err) + } + if err := cmd.Start(); err != nil { + panic(err) + } + + r := bufio.NewReader(stdout) + found := false + + go func() { + for { + // Read stdout by line + line, _, err := r.ReadLine() + if err == io.EOF { + break + } + str := strings.TrimSpace(string(line)) + + // Search for the start of the daily datasets + if !found { + found = strings.Contains(str, "") + continue + } + if matches := linePattern.FindStringSubmatch(str); matches != nil && matches[2] != "NaN" { + seconds, _ := strconv.Atoi(matches[1]) + nodes, _ := strconv.ParseFloat(matches[2], 64) + clients, _ := strconv.ParseFloat(matches[2], 64) + + out <- Dataset{ + Time: time.Unix(int64(seconds), 0), + Nodes: nodes, + Clients: clients, + } + } + } + close(out) + }() + return out +}