All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alipay.sofa.lookout.server.interfaces.common.QueryExpressionUtil Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alipay.sofa.lookout.server.interfaces.common;

import com.alipay.sofa.lookout.server.interfaces.exception.PromClientException;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

/**
 * Created by [email protected] on 2018/5/6.
 */
public final class QueryExpressionUtil {
    private QueryExpressionUtil() {
    }

    /**
     * 从查询表达式中剔除掉不需要的的查询条件限制
     *
     * @param expr       目标查询表达式
     * @param labelNames 忽略的查询条件(存在于目标 expr 中的)
     * @return expr 加工处理后的表达式
     */
    public static String ignoreLabelMatches(String expr, List labelNames) {
        if (CollectionUtils.isEmpty(labelNames) || StringUtils.isEmpty(expr)) {
            return expr;
        }
        String newExprStr = expr;
        int leftBracePos = newExprStr.indexOf('{');
        int rightBracePos = -1;
        while (leftBracePos < newExprStr.length() && leftBracePos > 0) {
            rightBracePos = newExprStr.indexOf('}', leftBracePos);
            Preconditions.checkTrue(rightBracePos > leftBracePos, "illegal query expression:" + expr + ",no pair brace {...}");
            String labelSelector = newExprStr.substring(leftBracePos + 1, rightBracePos);
            if (labelSelector.length() > 0) {
                boolean matched = false;
                Stream labelMatcheStream = Splitter.on(",").splitToList(labelSelector).stream();
                int tmp = rightBracePos - labelSelector.length();//minus old length
                //需要排除的labels
                for (String ln : labelNames) {
                    //不包含,实际上也没有携带;
                    if (!labelSelector.contains(ln)) {
                        continue;
                    }
                    //包含需要剔除的
                    matched = true;
                    labelMatcheStream = labelMatcheStream.filter(lm -> !lm.trim().startsWith(ln));
                }
                if (matched) {
                    labelSelector = Joiner.on(',').join(labelMatcheStream.iterator());
                    newExprStr = newExprStr.substring(0, leftBracePos + 1) + labelSelector + newExprStr.substring(rightBracePos);
                    rightBracePos = tmp + labelSelector.length();//add new length. refresh right brace pos
                }
            }
            leftBracePos = newExprStr.indexOf('{', rightBracePos);
        }
        return newExprStr;
    }

    public static void checkNoTagFilter(String queryStr) {
        //check no tag filter query;
        int leftBracePos = queryStr.indexOf('{');
        if (leftBracePos < 0 || (leftBracePos > 0 && queryStr.charAt(leftBracePos + 1) == '}')) {
            throw new PromClientException(
                "In order to improve query performance, you need to add tag filtering!")
                .setRealQuery(queryStr);
        }
    }

    /**
     * 如果PromQL查询语句含有正则匹配查询,必须含有一个精确匹配的tag
     *
     * @param queryStr
     */
    public static void checkRegexMatcher(String queryStr) {
        String newExprStr = queryStr;
        int leftBracePos = newExprStr.indexOf('{');
        int rightBracePos = -1;
        while (leftBracePos < newExprStr.length() && leftBracePos > 0) {
            rightBracePos = newExprStr.indexOf('}', leftBracePos);
            Preconditions.checkTrue(rightBracePos > leftBracePos, "illegal query expression:"
                                                                  + queryStr
                                                                  + ",no pair brace {...}");
            String labelSelector = newExprStr.substring(leftBracePos + 1, rightBracePos);
            int regexPos = labelSelector.indexOf("=~");
            int orPos = labelSelector.indexOf("=~|");
            // =~| 操作不需要精确匹配的tag进行查询
            if (regexPos > -1 && orPos != regexPos) {
                //check left quote
                int regexValuePos = checkRegexValueLeftQuotePos(labelSelector);
                //check right quote
                labelSelector = labelSelector.substring(regexValuePos + 1);
                regexValuePos = checkRegexValueRightQuotePos(labelSelector);
                labelSelector = labelSelector.substring(regexValuePos + 1);
                if (labelSelector.indexOf("=") == -1 && labelSelector.indexOf("!=") == -1) {
                    throw new PromClientException(
                        "In order to improve query performance, when use regex you need to add two tags. one of the tag must use "
                                + "equal operator").setRealQuery(queryStr);
                }

            }
            leftBracePos = newExprStr.indexOf('{', rightBracePos);
        }
    }

    private static int checkRegexValueLeftQuotePos(String labelSelector) {
        Pattern pattern = Pattern.compile("\\s*\"");
        Matcher matcher = pattern.matcher(labelSelector);
        if (matcher.find()) {
            return matcher.start();
        } else {
            throw new PromClientException("illegal query expression:" + labelSelector
                                          + ",no pair quote \"...\" for regex value ");
        }
    }

    private static int checkRegexValueRightQuotePos(String labelSelector) {
        Pattern pattern = Pattern.compile("\"\\s*,?");
        Matcher matcher = pattern.matcher(labelSelector);
        if (matcher.find()) {
            return matcher.start();
        } else {
            throw new PromClientException("illegal query expression:" + labelSelector
                                          + ",no pair quote \"...\" for regex value ");
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy