From f6cb9e62471baa3a74dd048ed320898ce7cd85d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C3=B3n=20Berrutti?= Date: Wed, 8 Nov 2023 04:56:58 -0300 Subject: [PATCH] [ADDED] Time metrics to the exporter (#265) --- collector/collector.go | 43 +++++++++++++++++++++++++++---------- collector/collector_test.go | 25 +++++++++++++++++++++ 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/collector/collector.go b/collector/collector.go index 3aaa4b1..5ab29bc 100644 --- a/collector/collector.go +++ b/collector/collector.go @@ -45,6 +45,7 @@ type CollectedServer struct { type metric struct { path []string metric interface{} + time bool } // NATSCollector collects NATS metrics @@ -240,8 +241,12 @@ func (nc *NATSCollector) collectStatsFromRequests( case float64: // json only has floats m.WithLabelValues(id).Set(v) case string: - m.Reset() - m.With(prometheus.Labels{"server_id": id, "value": v}).Set(1) + if stat.time { + m.WithLabelValues(id).Set(parseDateString(v)) + } else { + m.Reset() + m.With(prometheus.Labels{"server_id": id, "value": v}).Set(1) + } default: Debugf("value %s no longer a float", key, id, v) } @@ -332,14 +337,18 @@ func (nc *NATSCollector) objectToMetrics(response map[string]interface{}, namesp "gateway_tls_timeout": {}, "gateway_connect_retries": {}, } + labelKeys := map[string]struct{}{ - "server_id": {}, - "server_name": {}, - "version": {}, - "domain": {}, - "leader": {}, - "name": {}, + "server_id": {}, + "server_name": {}, + "version": {}, + "domain": {}, + "leader": {}, + "name": {}, + "start": {}, + "config_load_time": {}, } + for k := range response { fqn, path := fqName(k, prefix...) if _, ok := skipFQN[fqn]; ok { @@ -360,9 +369,21 @@ func (nc *NATSCollector) objectToMetrics(response map[string]interface{}, namesp if _, ok := labelKeys[k]; !ok { break } - nc.Stats[fqn] = metric{ - path: path, - metric: newLabelGauge(nc.system, nc.endpoint, fqn, "", namespace, "value"), + + // Check if the value is a valid time string. + // Go JSONMarshal time.Time in RFC3339Nano format. + _, err := time.Parse(time.RFC3339Nano, v) + if err == nil { + nc.Stats[fqn] = metric{ + path: path, + metric: newPrometheusGaugeVec(nc.system, nc.endpoint, fqn, "", namespace), + time: true, + } + } else { + nc.Stats[fqn] = metric{ + path: path, + metric: newLabelGauge(nc.system, nc.endpoint, fqn, "", namespace, "value"), + } } case map[string]interface{}: // recurse and flatten diff --git a/collector/collector_test.go b/collector/collector_test.go index a65977e..fa6094c 100644 --- a/collector/collector_test.go +++ b/collector/collector_test.go @@ -213,6 +213,31 @@ func TestVarz(t *testing.T) { verifyCollector(CoreSystem, url, "varz", cases, t) } +func TestStartAndConfigLoadTimeVarz(t *testing.T) { + s := pet.RunServer() + defer s.Shutdown() + + varz, err := s.Varz(nil) + if err != nil { + t.Fatal(err) + } + + url := fmt.Sprintf("http://localhost:%d/", pet.MonitorPort) + + nc := pet.CreateClientConnSubscribeAndPublish(t) + defer nc.Close() + + // see if we get the same stats as the original monitor testing code. + // just for our monitoring_port + + cases := map[string]float64{ + "gnatsd_varz_start": float64(varz.Start.UnixMilli()), + "gnatsd_varz_config_load_time": float64(varz.ConfigLoadTime.UnixMilli()), + } + + verifyCollector(CoreSystem, url, "varz", cases, t) +} + func TestConnz(t *testing.T) { s := pet.RunServer() defer s.Shutdown()