From 9c0ed68785208dbc3404ef301a39dbf7a01b2c8d Mon Sep 17 00:00:00 2001 From: Arnob kumar saha Date: Tue, 9 Jan 2024 15:39:43 +0600 Subject: [PATCH] rename Signed-off-by: Arnob kumar saha --- pkg/dashboard/db.go | 51 +----------------- pkg/dashboard/parser.go | 114 +++++++++++++++++++++++++++------------- 2 files changed, 79 insertions(+), 86 deletions(-) diff --git a/pkg/dashboard/db.go b/pkg/dashboard/db.go index 6e2b88612..b499edec7 100644 --- a/pkg/dashboard/db.go +++ b/pkg/dashboard/db.go @@ -56,7 +56,7 @@ func Run(f cmdutil.Factory, args []string, branch string, prom PromSvc) { dashboardData := getDashboard(url) - queries := getQueryInformation(dashboardData) + queries := parseAllExpressions(dashboardData) config, err := f.ToRESTConfig() if err != nil { @@ -123,52 +123,3 @@ func Run(f cmdutil.Factory, args []string, branch string, prom PromSvc) { fmt.Println("All metrics found") } } - -func getQueryInformation(dashboardData map[string]interface{}) []queryInformation { - var queries []queryInformation - if panels, ok := dashboardData["panels"].([]interface{}); ok { - for _, panel := range panels { - if targets, ok := panel.(map[string]interface{})["targets"].([]interface{}); ok { - for _, target := range targets { - if expr, ok := target.(map[string]interface{})["expr"]; ok { - if expr != "" { - query := expr.(string) - queries = append(queries, getMetricAndLabels(query)...) - } - } - } - } - } - } - return queries -} - -// Steps: -// - if current character is '{' -// - extract metric name by matching metric regex -// - get label selector substring inside { } -// - get label name from this substring by matching label regex -// - move i to its closing bracket position. -func getMetricAndLabels(query string) []queryInformation { - var queries []queryInformation - for i := 0; i < len(query); i++ { - if query[i] == '{' { - j := i - for { - if j-1 < 0 || (!matchMetricRegex(rune(query[j-1]))) { - break - } - j-- - } - metric := query[j:i] - labelSelector, closingPosition := substringInsideLabelSelector(query, i) - labelNames := getLabelNames(labelSelector) - queries = append(queries, queryInformation{ - metric: metric, - labelNames: labelNames, - }) - i = closingPosition - } - } - return queries -} diff --git a/pkg/dashboard/parser.go b/pkg/dashboard/parser.go index c37d567db..156ce4430 100644 --- a/pkg/dashboard/parser.go +++ b/pkg/dashboard/parser.go @@ -22,45 +22,61 @@ import ( "unicode" ) -func excludeQuotedSubstrings(input string) string { - // Define the regular expression pattern to match string inside double quotation - re := regexp.MustCompile(`"[^"]*"`) - - // Replace all quoted substring with an empty string - result := re.ReplaceAllString(input, "") - - return result -} - -func excludeNonAlphanumericUnderscore(input string) string { - // Define the regular expression pattern to match non-alphanumeric characters except underscore - pattern := `[^a-zA-Z0-9_]` - re := regexp.MustCompile(pattern) - - // Replace non-alphanumeric or underscore characters with an empty string - result := re.ReplaceAllString(input, "") - - return result +func parseAllExpressions(dashboardData map[string]interface{}) []queryInformation { + var queries []queryInformation + if panels, ok := dashboardData["panels"].([]interface{}); ok { + for _, panel := range panels { + if targets, ok := panel.(map[string]interface{})["targets"].([]interface{}); ok { + for _, target := range targets { + if expr, ok := target.(map[string]interface{})["expr"]; ok { + if expr != "" { + query := expr.(string) + queries = append(queries, parseSingleExpression(query)...) + } + } + } + } + } + } + return queries } -// Labels may contain ASCII letters, numbers, as well as underscores. They must match the regex [a-zA-Z_][a-zA-Z0-9_]* -// So we need to split the selector string by comma. then extract label name with the help of the regex format -// Ref: https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels -func getLabelNames(labelSelector string) []string { - var labelNames []string - unQuoted := excludeQuotedSubstrings(labelSelector) - commaSeparated := strings.Split(unQuoted, ",") - for _, s := range commaSeparated { - labelName := excludeNonAlphanumericUnderscore(s) - if labelName != "" { - labelNames = append(labelNames, labelName) +// Steps: +// - if current character is '{' +// - extract metric name by matching metric regex +// - 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 + for i := 0; i < len(query); i++ { + if query[i] == '{' { + j := i + for { + if j-1 < 0 || (!matchMetricRegex(rune(query[j-1]))) { + break + } + j-- + } + metric := query[j:i] + fullLabelString, closingPosition := getFullLabelString(query, i) + labelNames := parseLabelNames(fullLabelString) + queries = append(queries, queryInformation{ + metric: metric, + labelNames: labelNames, + }) + i = closingPosition } } - return labelNames + return queries +} + +func matchMetricRegex(char rune) bool { // Must match the regex [a-zA-Z_:][a-zA-Z0-9_:]* + return unicode.IsLetter(char) || unicode.IsDigit(char) || char == '_' || char == ':' } // Finding valid bracket sequence from startPosition -func substringInsideLabelSelector(query string, startPosition int) (string, int) { +func getFullLabelString(query string, startPosition int) (string, int) { balance := 0 closingPosition := startPosition for i := startPosition; i < len(query); i++ { @@ -78,9 +94,35 @@ func substringInsideLabelSelector(query string, startPosition int) (string, int) return query[startPosition+1 : closingPosition], closingPosition } -// Metric names may contain ASCII letters, digits, underscores, and colons. It must match the regex [a-zA-Z_:][a-zA-Z0-9_:]* -// So we can use this if the character is in a metric name +// Labels may contain ASCII letters, numbers, as well as underscores. They must match the regex [a-zA-Z_][a-zA-Z0-9_]* +// So we need to split the selector string by comma. then extract label name with the help of the regex format // Ref: https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels -func matchMetricRegex(char rune) bool { - return unicode.IsLetter(char) || unicode.IsDigit(char) || char == '_' || char == ':' +func parseLabelNames(fullLabelString string) []string { + // Define the regular expression pattern to match string inside double quotation + // Replace all quoted substring with an empty string + excludeQuotedSubstrings := func(input string) string { + re := regexp.MustCompile(`"[^"]*"`) + result := re.ReplaceAllString(input, "") + return result + } + + // Define the regular expression pattern to match non-alphanumeric characters except underscore + // Replace non-alphanumeric or underscore characters with an empty string + excludeNonAlphanumericUnderscore := func(input string) string { + pattern := `[^a-zA-Z0-9_]` + re := regexp.MustCompile(pattern) + result := re.ReplaceAllString(input, "") + return result + } + + var labelNames []string + unQuoted := excludeQuotedSubstrings(fullLabelString) + commaSeparated := strings.Split(unQuoted, ",") + for _, s := range commaSeparated { + labelName := excludeNonAlphanumericUnderscore(s) + if labelName != "" { + labelNames = append(labelNames, labelName) + } + } + return labelNames }