diff --git a/deepfence_server/reporters/search/search.go b/deepfence_server/reporters/search/search.go index 0697b92492..ca15e6ae01 100644 --- a/deepfence_server/reporters/search/search.go +++ b/deepfence_server/reporters/search/search.go @@ -70,6 +70,45 @@ type ResultGroupResp struct { Groups []ResultGroup `json:"groups"` } +func CountAllNodeLabels(ctx context.Context) (map[string]int64, error) { + res := map[string]int64{} + driver, err := directory.Neo4jClient(ctx) + if err != nil { + return res, err + } + + session := driver.NewSession(neo4j.SessionConfig{AccessMode: neo4j.AccessModeRead}) + defer session.Close() + + tx, err := session.BeginTransaction(neo4j.WithTxTimeout(30 * time.Second)) + if err != nil { + return res, err + } + defer tx.Close() + + query := `CALL apoc.meta.stats() YIELD labels RETURN labels;` + r, err := tx.Run(query, map[string]interface{}{}) + if err != nil { + return res, err + } + rec, err := r.Single() + if err != nil { + return res, err + } + + val, found := rec.Get("labels") + if !found { + return res, nil + } + + labels := val.(map[string]interface{}) + for k, v := range labels { + res[k] = v.(int64) + } + + return res, nil +} + func CountNodes(ctx context.Context) (NodeCountResp, error) { res := NodeCountResp{} driver, err := directory.Neo4jClient(ctx) diff --git a/deepfence_server/router/metrics.go b/deepfence_server/router/metrics.go index 88255fedd3..2e9a8339c7 100644 --- a/deepfence_server/router/metrics.go +++ b/deepfence_server/router/metrics.go @@ -9,9 +9,10 @@ import ( ) type Collector struct { - activeAgents *prometheus.Desc - activeUsers *prometheus.Desc - userInfo *prometheus.Desc + activeAgents *prometheus.Desc + activeUsers *prometheus.Desc + userInfo *prometheus.Desc + neo4jNodesCount *prometheus.Desc } func newCollector() *Collector { @@ -31,6 +32,11 @@ func newCollector() *Collector { "users info", []string{"namespace", "company"}, nil, ), + neo4jNodesCount: prometheus.NewDesc( + "neo4j_node_label_count", + "all neo4j nodes count", + []string{"label", "namespace"}, nil, + ), } } @@ -38,6 +44,7 @@ func (collector *Collector) Describe(ch chan<- *prometheus.Desc) { ch <- collector.activeAgents ch <- collector.activeUsers ch <- collector.userInfo + ch <- collector.neo4jNodesCount } func (collector *Collector) Collect(ch chan<- prometheus.Metric) { @@ -65,6 +72,16 @@ func (collector *Collector) Collect(ch chan<- prometheus.Metric) { float64(counts.Namespace), "kubernetes_namespace", ns) } + allNodes, err := reporters_search.CountAllNodeLabels(ctx) + if err != nil { + log.Error().Err(err).Msg("failed to fetch all nodes count for metrics") + } else { + for k, v := range allNodes { + ch <- prometheus.MustNewConstMetric(collector.neo4jNodesCount, prometheus.GaugeValue, + float64(v), k, ns) + } + } + // get number of users pgClient, err := directory.PostgresClient(ctx) if err != nil {