From 086a163f3cf451d37d90c02a8a20706379932ad9 Mon Sep 17 00:00:00 2001 From: genofire Date: Sun, 14 Jun 2020 13:25:30 +0200 Subject: [PATCH] prometheus: yanic_node_up=0 --- webserver/prometheus/exporter.go | 47 +++++++++++++----------- webserver/prometheus/transform.go | 61 ++++++++++++++++++------------- 2 files changed, 62 insertions(+), 46 deletions(-) diff --git a/webserver/prometheus/exporter.go b/webserver/prometheus/exporter.go index 391529fc..9268ae40 100644 --- a/webserver/prometheus/exporter.go +++ b/webserver/prometheus/exporter.go @@ -33,7 +33,7 @@ func (ex *Exporter) ServeHTTP(res http.ResponseWriter, req *http.Request) { return } ip = node.Address.IP - if ex.writeNode(res, node) { + if ex.writeNode(res, node, true) { log.WithFields(map[string]interface{}{ "ip": ip, "node_id": nodeID, @@ -51,22 +51,17 @@ func (ex *Exporter) ServeHTTP(res http.ResponseWriter, req *http.Request) { nodeID = n.Nodeinfo.NodeID return n_addr != nil && ip.Equal(n_addr.IP) }) - getOne := false if len(node_select) == 1 { - if ex.writeNode(res, node_select[0]) { - getOne = true + if ex.writeNode(res, node_select[0], true) { + log.WithFields(map[string]interface{}{ + "ip": ip, + "node_id": nodeID, + }).Debug("take node from cache") + return } } else if len(node_select) > 1 { log.Error("strange count of nodes") } - - if getOne { - log.WithFields(map[string]interface{}{ - "ip": ip, - "node_id": nodeID, - }).Debug("take node from cache") - return - } } else { http.Error(res, "please request with ?ip= or ?node_id=", http.StatusNotFound) return @@ -88,26 +83,36 @@ func (ex *Exporter) ServeHTTP(res http.ResponseWriter, req *http.Request) { http.Error(res, "not able to fetch this node", http.StatusGatewayTimeout) return } - if ex.writeNode(res, node) { - return - } - http.Error(res, "not able to fetch new values from this node", http.StatusGatewayTimeout) + ex.writeNode(res, node, false) } -func (ex *Exporter) writeNode(res http.ResponseWriter, node *runtime.Node) bool { +func (ex *Exporter) writeNode(res http.ResponseWriter, node *runtime.Node, dry bool) bool { + logger := log.WithField("database", "prometheus") + if nodeinfo := node.Nodeinfo; nodeinfo != nil { + logger = logger.WithField("node_id", nodeinfo.NodeID) + } + if !time.Now().Before(node.Lastseen.GetTime().Add(ex.config.Outdated.Duration)) { + if dry { + return false + } + m := Metric{Labels: MetricLabelsFromNode(node), Name: "yanic_node_up", Value: 0} + str, err := m.String() + if err == nil { + io.WriteString(res, str+"\n") + } else { + logger.Warnf("not able to get metrics from node: %s", err) + http.Error(res, "not able to generate metric from node", http.StatusInternalServerError) + } return false } + metrics := MetricsFromNode(ex.nodes, node) for _, m := range metrics { str, err := m.String() if err == nil { io.WriteString(res, str+"\n") } else { - logger := log.WithField("database", "prometheus") - if nodeinfo := node.Nodeinfo; nodeinfo != nil { - logger = logger.WithField("node_id", nodeinfo.NodeID) - } logger.Warnf("not able to get metrics from node: %s", err) http.Error(res, "not able to generate metric from node", http.StatusInternalServerError) } diff --git a/webserver/prometheus/transform.go b/webserver/prometheus/transform.go index 1fe70c4d..570feb96 100644 --- a/webserver/prometheus/transform.go +++ b/webserver/prometheus/transform.go @@ -4,35 +4,16 @@ import ( "github.com/FreifunkBremen/yanic/runtime" ) -func MetricsFromNode(nodes *runtime.Nodes, node *runtime.Node) []Metric { - m := []Metric{} - - // before node metrics to get link statics undependent of node validation - for _, link := range nodes.NodeLinks(node) { - m = append(m, Metric{ - Labels: map[string]interface{}{ - "source_id": link.SourceID, - "source_addr": link.SourceAddress, - "target_id": link.TargetID, - "target_addr": link.TargetAddress, - }, - Name: "yanic_link", - Value: link.TQ * 100, - }) - } +func MetricLabelsFromNode(node *runtime.Node) (labels map[string]interface{}) { + labels = make(map[string]interface{}) nodeinfo := node.Nodeinfo - stats := node.Statistics - - // validation - if nodeinfo == nil || stats == nil { - return m + if nodeinfo == nil { + return } - labels := map[string]interface{}{ - "node_id": nodeinfo.NodeID, - "hostname": nodeinfo.Hostname, - } + labels["node_id"] = nodeinfo.NodeID + labels["hostname"] = nodeinfo.Hostname if nodeinfo.System.SiteCode != "" { labels["site_code"] = nodeinfo.System.SiteCode @@ -59,6 +40,36 @@ func MetricsFromNode(nodes *runtime.Nodes, node *runtime.Node) []Metric { labels["location_long"] = location.Longitude } + return +} + +func MetricsFromNode(nodes *runtime.Nodes, node *runtime.Node) []Metric { + m := []Metric{} + + // before node metrics to get link statics undependent of node validation + for _, link := range nodes.NodeLinks(node) { + m = append(m, Metric{ + Labels: map[string]interface{}{ + "source_id": link.SourceID, + "source_addr": link.SourceAddress, + "target_id": link.TargetID, + "target_addr": link.TargetAddress, + }, + Name: "yanic_link", + Value: link.TQ * 100, + }) + } + + nodeinfo := node.Nodeinfo + stats := node.Statistics + + // validation + if nodeinfo == nil || stats == nil { + return m + } + + labels := MetricLabelsFromNode(node) + addMetric := func(name string, value interface{}) { m = append(m, Metric{Labels: labels, Name: "yanic_" + name, Value: value}) }