代码之家  ›  专栏  ›  技术社区  ›  Hearen

使用regex从Grafana表达式检索Prometheus度量名称

  •  0
  • Hearen  · 技术社区  · 7 年前

    我试过很多不同的 regex 但不是很成功。

    这个问题的模式是:

    <method_name(> metric_name <{filter_condition}> <[time_duration]> <)> <by (some members)>
                ^------------------------------------------------------^
                              method_name(...) can be multiple
    

    如你所见 <...> 可以是可选的,而 metric_name 我一定要把它找回来 equation .

    Case # 1
    input: sum(log_search_by_service_total {service_name!~\"\"}) by (service_name, operator)
    output: log_search_by_service_total
    
    Case # 2
    input: log_request_total
    output: log_request_total
    
    Case # 3
    input:  sum(delta(log_request_total[5m])) by (args, user_id)
    output: log_request_total
    
    Case # 4
    input: log_request_total{methodName=~\"getAppDynamicsGraphMetrics|getAppDynamicsMetrics\"}
    output: log_request_total
    
    Case # 5
    input: sum(delta(log_request_total{className=~\".*ProductDashboardController\",methodName=~\"getDashboardConfig|updateMaintainers|addQuickLink|deleteQuickLink|addDependentMiddleware|addDependentService|updateErrorThreshold\"}[5m])) by (user_id)"
    output: log_request_total
    
    Case # 6
    input: count_scalar(sum(log_query_request_total) by (user_id))
    output: log_query_request_total
    

    这是一个演示我在Java中所做的尝试。但我似乎无法得到正确的答案 pattern 为了找到我上面提到的模式的确切答案。

    如果可能的话,请分享一些想法。

    public static void main(String... args) {
        String[] exprs = {"sum(log_query_task_cache_hit_rate_bucket)by(le)",
                "sum(log_search_by_service_total {service_name!~\"\"}) by (service_name, operator)",
                "log_request_total",
                " sum(delta(log_request_total[5m])) by (args, user_id)",
                "log_request_total{methodName=~\"getAppDynamicsGraphMetrics|getAppDynamicsMetrics\"}",
                "sum(delta(log_request_total{className=~\".*ProductDashboardController\",methodName=~\"getDashboardConfig|updateMaintainers|addQuickLink|deleteQuickLink|addDependentMiddleware|addDependentService|updateErrorThreshold\"}[5m])) by (user_id)",
                "sum(log_request_total{methodName=\"getInstanceNames\"}) by (user_id)",
                "sum(log_request_total{methodName=\"getVpcCardInfo\",user_id!~\"${user}\"}) by (envName)",
                "count_scalar(sum(log_query_request_total) by (user_id))",
                "avg(log_waiting_time_average) by (exported_tenant, exported_landscape)",
                "avg(task_processing_time_average{app=\"athena\"})",
                "avg(log_queue_time_average) by (log_type)",
                "sum(delta(product_dashboard_service_sum[2m]))",
                "ceil(delta(product_dashboard_service_count[5m]))]"
        };
        String[] expected = {
                "log_query_task_cache_hit_rate_bucket",
                "log_search_by_service_total",
                "log_request_total",
                "log_request_total",
                "log_request_total",
                "log_request_total",
                "log_request_total",
                "log_request_total",
                "log_query_request_total",
                "log_waiting_time_average",
                "task_processing_time_average",
                "log_queue_time_average",
                "product_dashboard_service_sum",
                "product_dashboard_service_count"
        };
        Pattern pattern = Pattern.compile(".*?\\(?([\\w|_]+)\\{?\\[?.*");
        testPattern(exprs, expected, pattern);
        pattern = Pattern.compile(".*\\(?([\\w|_]+)\\{?\\[?.*");
        testPattern(exprs, expected, pattern);
        pattern = Pattern.compile(".*?\\(?([\\w|_]+)\\{?\\[?.*");
        testPattern(exprs, expected, pattern);
    }
    
    private static void testPattern(String[] exprs, String[] expected, Pattern pattern) {
        System.out.println("\n********** Pattern Match Test *********\n");
        for (int i = 0; i < exprs.length; ++i) {
            String expr = exprs[i];
            Matcher matcher = pattern.matcher(expr);
            if (matcher.find()) {
                System.out.println("\nThe Original Expr: " + expr);
                System.out.println(String.format("Expected:\t %-40s Matched:\t %-40s", expected[i], matcher.group(1)));
            } else {
                System.out.println("expected: " + expected[i] + " not matched");
            }
        }
    }
    

    更新2018-08-06

    感谢波希米亚人的帮助,它真的启发了我(因为我一直相信 正则表达式 可以用干净的溶液施展魔法)。

    后来,我发现 expr s比我预想的要复杂,具体情况如下:

    Case # 7
    input: topk(10,autoindex_online_consume_time_total_sum{app=~"$app", DTO_Name=~"$c_class"})
    expected: autoindex_online_consume_time_total_sum
    // to get the metric name: autoindex_online_consume_time_total_sum
    // still I can make it work with small modifications as ^(?:\w+\()*(?:\d+,)*(\w+)
    

    但以下一个甚至更多不同的复杂组合使我转向了可靠的方法:

    Case # 8
    input: sum(hue_mail_sent_attachment_bytes_total) by (app)  / sum(hue_mail_sent_mails_with_attachment_total) by (app)
    Expected: [hue_mail_sent_attachment_bytes_total, hue_mail_sent_mails_with_attachment_total]
    

    现在更复杂了…甚至 不可预知的 因为没有办法控制 出口 来自用户的输入。

    因此,我用更可靠、更简单的解决方案实现了同样的目标:

    1. 存储 distinct 首先进入数据库的度量名称;
    2. 作为 出口 来,在内存中使用 contains(String s) ;
    3. 仍然可能存在一个问题:如果某些度量名称包含其他度量名称,则会过度匹配;
    1 回复  |  直到 7 年前
        1
  •  2
  •   Bohemian    7 年前

    此正则表达式捕获组1中的目标

    ^(?:\w+\()*(\w+)
    

    live demo .

    在java中,要获得目标:

    String metricName = input.replaceAll("^(?:\\w+\\()*(\\w+)", "$1");