diff --git a/pkg/dashboard/db.go b/pkg/dashboard/db.go index b499edec7..e75efa4c6 100644 --- a/pkg/dashboard/db.go +++ b/pkg/dashboard/db.go @@ -30,19 +30,20 @@ import ( cmdutil "k8s.io/kubectl/pkg/cmd/util" ) -type queryInformation struct { +type queryOpts struct { metric string + panelTitle string labelNames []string } +type missingOpts struct { + labelName []string + panelTitle []string +} type PromSvc struct { Name string Namespace string Port int } -type unknownLabel struct { - metric string - labelName string -} func Run(f cmdutil.Factory, args []string, branch string, prom PromSvc) { if len(args) < 2 { @@ -71,22 +72,22 @@ func Run(f cmdutil.Factory, args []string, branch string, prom PromSvc) { promClient := getPromClient(strconv.Itoa(tunnel.Local)) - var unknownMetrics []string - var unknownLabels []unknownLabel + // var unknown []missingOpts + unknown := make(map[string]*missingOpts) for _, query := range queries { metricName := query.metric - for _, labelKey := range query.labelNames { + endTime := time.Now() - endTime := time.Now() + result, _, err := promClient.Query(context.TODO(), metricName, endTime) + if err != nil { + log.Fatal("Error querying Prometheus:", err, " metric: ", metricName) + } - result, _, err := promClient.Query(context.TODO(), metricName, endTime) - if err != nil { - log.Fatal("Error querying Prometheus:", err, " metric: ", metricName) - } + matrix := result.(model.Vector) - matrix := result.(model.Vector) - if len(matrix) > 0 { + if len(matrix) > 0 { + for _, labelKey := range query.labelNames { // Check if the label exists for any result in the matrix labelExists := false @@ -100,26 +101,31 @@ func Run(f cmdutil.Factory, args []string, branch string, prom PromSvc) { } if !labelExists { - unknownLabels = uniqueAppend(unknownLabels, unknownLabel{ - metric: metricName, - labelName: labelKey, - }) + if unknown[metricName] == nil { + unknown[metricName] = &missingOpts{labelName: []string{}, panelTitle: []string{}} + } + unknown[metricName].labelName = uniqueAppend(unknown[metricName].labelName, labelKey) + unknown[metricName].panelTitle = uniqueAppend(unknown[metricName].panelTitle, query.panelTitle) } - } else { - unknownMetrics = uniqueAppend(unknownMetrics, metricName) } + } else { + if unknown[metricName] == nil { + unknown[metricName] = &missingOpts{labelName: []string{}, panelTitle: []string{}} + } + unknown[metricName].panelTitle = uniqueAppend(unknown[metricName].panelTitle, query.panelTitle) } } - if len(unknownMetrics) > 0 { - fmt.Printf("List of unknown metrics:\n%s\n", strings.Join(unknownMetrics, "\n")) - } - if len(unknownLabels) > 0 { - fmt.Println("List of unknown labels:") - for _, unknown := range unknownLabels { - fmt.Printf(`Metric: "%s" Label: "%s"\n`, unknown.metric, unknown.labelName) + if len(unknown) > 0 { + fmt.Println("Missing Information:") + for metric, opts := range unknown { + fmt.Println("---------------------------------------------------") + fmt.Printf("Metric: %s \n", metric) + if len(opts.labelName) > 0 { + fmt.Printf("Missing Lables: %s \n", strings.Join(opts.labelName, ", ")) + } + fmt.Printf("Effected Panel: %s \n", strings.Join(opts.panelTitle, ", ")) } - } - if len(unknownMetrics) == 0 && len(unknownLabels) == 0 { + } else { fmt.Println("All metrics found") } } diff --git a/pkg/dashboard/helper.go b/pkg/dashboard/helper.go index 1942ecf31..96b577af8 100644 --- a/pkg/dashboard/helper.go +++ b/pkg/dashboard/helper.go @@ -67,7 +67,7 @@ func getPromClient(localPort string) v1.API { return v1.NewAPI(client) } -func uniqueAppend[T comparable](slice []T, valueToAdd T) []T { +func uniqueAppend(slice []string, valueToAdd string) []string { for _, existingValue := range slice { if existingValue == valueToAdd { return slice diff --git a/pkg/dashboard/parser.go b/pkg/dashboard/parser.go index 156ce4430..7292099d0 100644 --- a/pkg/dashboard/parser.go +++ b/pkg/dashboard/parser.go @@ -17,21 +17,26 @@ limitations under the License. package dashboard import ( + "log" "regexp" "strings" "unicode" ) -func parseAllExpressions(dashboardData map[string]interface{}) []queryInformation { - var queries []queryInformation +func parseAllExpressions(dashboardData map[string]interface{}) []queryOpts { + var queries []queryOpts if panels, ok := dashboardData["panels"].([]interface{}); ok { for _, panel := range panels { if targets, ok := panel.(map[string]interface{})["targets"].([]interface{}); ok { + title, ok := panel.(map[string]interface{})["title"].(string) + if !ok { + log.Fatal("panel's title found empty") + } for _, target := range targets { if expr, ok := target.(map[string]interface{})["expr"]; ok { if expr != "" { query := expr.(string) - queries = append(queries, parseSingleExpression(query)...) + queries = append(queries, parseSingleExpression(query, title)...) } } } @@ -47,8 +52,8 @@ func parseAllExpressions(dashboardData map[string]interface{}) []queryInformatio // - get label selector substring inside { } // - get label name from this substring by matching label regex // - move i to its closing bracket position. -func parseSingleExpression(query string) []queryInformation { - var queries []queryInformation +func parseSingleExpression(query, title string) []queryOpts { + var queries []queryOpts for i := 0; i < len(query); i++ { if query[i] == '{' { j := i @@ -61,9 +66,10 @@ func parseSingleExpression(query string) []queryInformation { metric := query[j:i] fullLabelString, closingPosition := getFullLabelString(query, i) labelNames := parseLabelNames(fullLabelString) - queries = append(queries, queryInformation{ + queries = append(queries, queryOpts{ metric: metric, labelNames: labelNames, + panelTitle: title, }) i = closingPosition }