Support !=, like filter expressions in OAL (#5269)
This commit is contained in:
parent
7f7e96b088
commit
ecc18b9be3
|
|
@ -14,11 +14,12 @@ packages/
|
|||
/docker/snapshot/*.gz
|
||||
.mvn/wrapper/*.jar
|
||||
OALLexer.tokens
|
||||
.factorypath
|
||||
.vscode
|
||||
.factorypath
|
||||
.vscode
|
||||
.checkstyle
|
||||
.externalToolBuilders
|
||||
/test/plugin/dist
|
||||
/test/plugin/workspace
|
||||
/test/jacoco/classes
|
||||
/test/jacoco/*.exec
|
||||
/test/jacoco/*.exec
|
||||
oap-server/oal-grammar/**/gen/
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ Read [Scope Definitions](scope-definitions.md), you can find all existing Scopes
|
|||
Use filter to build the conditions for the value of fields, by using field name and expression.
|
||||
|
||||
The expressions support to link by `and`, `or` and `(...)`.
|
||||
The OPs support `=`, `!=`, `>`, `<`, `in (v1, v2, ...`, `like "%..."`, with type detection based of field type. Trigger compile
|
||||
The OPs support `==`, `!=`, `>`, `<`, `>=`, `<=`, `like %...`, `like ...%` and `like %...%`, with type detection based of field type. Trigger compile
|
||||
or code generation error if incompatible.
|
||||
|
||||
## Aggregation Function
|
||||
|
|
@ -103,7 +103,7 @@ In default, no one is being disable.
|
|||
Endpoint_p99 = from(Endpoint.latency).filter(name in ("Endpoint1", "Endpoint2")).summary(0.99)
|
||||
|
||||
// Caculate p99 of Endpoint name started with `serv`
|
||||
serv_Endpoint_p99 = from(Endpoint.latency).filter(name like ("serv%")).summary(0.99)
|
||||
serv_Endpoint_p99 = from(Endpoint.latency).filter(name like "serv%").summary(0.99)
|
||||
|
||||
// Caculate the avg response time of each Endpoint
|
||||
Endpoint_avg = from(Endpoint.latency).avg()
|
||||
|
|
@ -112,7 +112,7 @@ Endpoint_avg = from(Endpoint.latency).avg()
|
|||
Endpoint_percentile = from(Endpoint.latency).percentile(10)
|
||||
|
||||
// Caculate the percent of response status is true, for each service.
|
||||
Endpoint_success = from(Endpoint.*).filter(status = "true").percent()
|
||||
Endpoint_success = from(Endpoint.*).filter(status == true).percent()
|
||||
|
||||
// Caculate the percent of response code in [200, 299], for each service.
|
||||
Endpoint_200 = from(Endpoint.*).filter(responseCode like "2%").percent()
|
||||
|
|
|
|||
|
|
@ -133,4 +133,6 @@ ALL: '*';
|
|||
GREATER: '>';
|
||||
LESS: '<';
|
||||
GREATER_EQUAL: '>=';
|
||||
LESS_EQUAL: '<=';
|
||||
LESS_EQUAL: '<=';
|
||||
NOT_EQUAL: '!=';
|
||||
LIKE: 'like';
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ literalExpression
|
|||
;
|
||||
|
||||
expression
|
||||
: booleanMatch | stringMatch | greaterMatch | lessMatch | greaterEqualMatch | lessEqualMatch
|
||||
: booleanMatch | stringMatch | greaterMatch | lessMatch | greaterEqualMatch | lessEqualMatch | notEqualMatch | booleanNotEqualMatch | likeMatch
|
||||
;
|
||||
|
||||
booleanMatch
|
||||
|
|
@ -115,6 +115,18 @@ lessEqualMatch
|
|||
: conditionAttribute LESS_EQUAL numberConditionValue
|
||||
;
|
||||
|
||||
booleanNotEqualMatch
|
||||
: conditionAttribute NOT_EQUAL booleanConditionValue
|
||||
;
|
||||
|
||||
notEqualMatch
|
||||
: conditionAttribute NOT_EQUAL (numberConditionValue | stringConditionValue | enumConditionValue)
|
||||
;
|
||||
|
||||
likeMatch
|
||||
: conditionAttribute LIKE stringConditionValue
|
||||
;
|
||||
|
||||
conditionAttribute
|
||||
: IDENTIFIER
|
||||
;
|
||||
|
|
@ -133,4 +145,4 @@ enumConditionValue
|
|||
|
||||
numberConditionValue
|
||||
: NUMBER_LITERAL
|
||||
;
|
||||
;
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ import org.apache.skywalking.apm.util.StringUtil;
|
|||
import org.apache.skywalking.oal.rt.output.AllDispatcherContext;
|
||||
import org.apache.skywalking.oal.rt.output.DispatcherContext;
|
||||
import org.apache.skywalking.oal.rt.parser.AnalysisResult;
|
||||
import org.apache.skywalking.oal.rt.parser.MetricsHolder;
|
||||
import org.apache.skywalking.oal.rt.parser.OALScripts;
|
||||
import org.apache.skywalking.oal.rt.parser.ScriptParser;
|
||||
import org.apache.skywalking.oal.rt.parser.SourceColumn;
|
||||
|
|
@ -144,12 +143,6 @@ public class OALRuntime implements OALEngine {
|
|||
this.currentClassLoader = currentClassLoader;
|
||||
Reader read;
|
||||
|
||||
try {
|
||||
MetricsHolder.init();
|
||||
} catch (IOException e) {
|
||||
throw new ModuleStartException("load metrics functions error.", e);
|
||||
}
|
||||
|
||||
try {
|
||||
read = ResourceUtils.read(oalDefine.getConfigFile());
|
||||
} catch (FileNotFoundException e) {
|
||||
|
|
|
|||
|
|
@ -18,11 +18,15 @@
|
|||
|
||||
package org.apache.skywalking.oal.rt.parser;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ConditionExpression {
|
||||
// original from script
|
||||
private String expressionType;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import java.lang.reflect.Method;
|
|||
import java.lang.reflect.Parameter;
|
||||
import java.util.List;
|
||||
import org.apache.skywalking.oal.rt.util.ClassMethodUtil;
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.Arg;
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.ConstOne;
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.Entrance;
|
||||
|
|
@ -35,8 +36,7 @@ public class DeepAnalysis {
|
|||
// 1. Set sub package name by source.metrics
|
||||
result.setPackageName(result.getSourceName().toLowerCase());
|
||||
|
||||
Class<? extends org.apache.skywalking.oap.server.core.analysis.metrics.Metrics> metricsClass = MetricsHolder.find(result
|
||||
.getAggregationFunctionName());
|
||||
Class<? extends Metrics> metricsClass = MetricsHolder.find(result.getAggregationFunctionName());
|
||||
String metricsClassSimpleName = metricsClass.getSimpleName();
|
||||
|
||||
result.setMetricsClassName(metricsClassSimpleName);
|
||||
|
|
@ -45,45 +45,22 @@ public class DeepAnalysis {
|
|||
List<ConditionExpression> expressions = result.getFilterExpressionsParserResult();
|
||||
if (expressions != null && expressions.size() > 0) {
|
||||
for (ConditionExpression expression : expressions) {
|
||||
Expression filterExpression = new Expression();
|
||||
if ("booleanMatch".equals(expression.getExpressionType())) {
|
||||
filterExpression.setExpressionObject("EqualMatch");
|
||||
filterExpression.setLeft("source." + ClassMethodUtil.toIsMethod(expression.getAttribute()) + "()");
|
||||
filterExpression.setRight(expression.getValue());
|
||||
result.addFilterExpressions(filterExpression);
|
||||
} else if ("stringMatch".equals(expression.getExpressionType())) {
|
||||
filterExpression.setExpressionObject("EqualMatch");
|
||||
filterExpression.setLeft("source." + ClassMethodUtil.toGetMethod(expression.getAttribute()) + "()");
|
||||
filterExpression.setRight(expression.getValue());
|
||||
result.addFilterExpressions(filterExpression);
|
||||
} else if ("greaterMatch".equals(expression.getExpressionType())) {
|
||||
filterExpression.setExpressionObject("GreaterMatch");
|
||||
filterExpression.setLeft("source." + ClassMethodUtil.toGetMethod(expression.getAttribute()) + "()");
|
||||
filterExpression.setRight(expression.getValue());
|
||||
result.addFilterExpressions(filterExpression);
|
||||
} else if ("lessMatch".equals(expression.getExpressionType())) {
|
||||
filterExpression.setExpressionObject("LessMatch");
|
||||
filterExpression.setLeft("source." + ClassMethodUtil.toGetMethod(expression.getAttribute()) + "()");
|
||||
filterExpression.setRight(expression.getValue());
|
||||
result.addFilterExpressions(filterExpression);
|
||||
} else if ("greaterEqualMatch".equals(expression.getExpressionType())) {
|
||||
filterExpression.setExpressionObject("GreaterEqualMatch");
|
||||
filterExpression.setLeft("source." + ClassMethodUtil.toGetMethod(expression.getAttribute()) + "()");
|
||||
filterExpression.setRight(expression.getValue());
|
||||
result.addFilterExpressions(filterExpression);
|
||||
} else if ("lessEqualMatch".equals(expression.getExpressionType())) {
|
||||
filterExpression.setExpressionObject("LessEqualMatch");
|
||||
filterExpression.setLeft("source." + ClassMethodUtil.toGetMethod(expression.getAttribute()) + "()");
|
||||
filterExpression.setRight(expression.getValue());
|
||||
result.addFilterExpressions(filterExpression);
|
||||
} else {
|
||||
throw new IllegalArgumentException("filter expression [" + expression.getExpressionType() + "] not found");
|
||||
}
|
||||
final FilterMatchers.MatcherInfo matcherInfo = FilterMatchers.INSTANCE.find(expression.getExpressionType());
|
||||
|
||||
final String getter = matcherInfo.isBooleanType()
|
||||
? ClassMethodUtil.toIsMethod(expression.getAttribute())
|
||||
: ClassMethodUtil.toGetMethod(expression.getAttribute());
|
||||
|
||||
final Expression filterExpression = new Expression();
|
||||
filterExpression.setExpressionObject(matcherInfo.getMatcher().getName());
|
||||
filterExpression.setLeft("source." + getter + "()");
|
||||
filterExpression.setRight(expression.getValue());
|
||||
result.addFilterExpressions(filterExpression);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Find Entrance method of this metrics
|
||||
Class c = metricsClass;
|
||||
Class<?> c = metricsClass;
|
||||
Method entranceMethod = null;
|
||||
SearchEntrance:
|
||||
while (!c.equals(Object.class)) {
|
||||
|
|
@ -117,36 +94,17 @@ public class DeepAnalysis {
|
|||
entryMethod.addArg(parameterType, "1");
|
||||
} else if (annotation instanceof org.apache.skywalking.oap.server.core.analysis.metrics.annotation.Expression) {
|
||||
if (result.getFuncConditionExpressions().size() == 1) {
|
||||
ConditionExpression expression = result.getFuncConditionExpressions().get(0);
|
||||
final ConditionExpression expression = result.getFuncConditionExpressions().get(0);
|
||||
final FilterMatchers.MatcherInfo matcherInfo = FilterMatchers.INSTANCE.find(expression.getExpressionType());
|
||||
|
||||
Expression argExpression = new Expression();
|
||||
if ("booleanMatch".equals(expression.getExpressionType())) {
|
||||
argExpression.setExpressionObject("EqualMatch");
|
||||
argExpression.setLeft("source." + ClassMethodUtil.toIsMethod(expression.getAttribute()) + "()");
|
||||
argExpression.setRight(expression.getValue());
|
||||
} else if ("stringMatch".equals(expression.getExpressionType())) {
|
||||
argExpression.setExpressionObject("EqualMatch");
|
||||
argExpression.setLeft("source." + ClassMethodUtil.toGetMethod(expression.getAttribute()) + "()");
|
||||
argExpression.setRight(expression.getValue());
|
||||
} else if ("greaterMatch".equals(expression.getExpressionType())) {
|
||||
argExpression.setExpressionObject("GreaterMatch");
|
||||
argExpression.setLeft("source." + ClassMethodUtil.toGetMethod(expression.getAttribute()) + "()");
|
||||
argExpression.setRight(expression.getValue());
|
||||
} else if ("lessMatch".equals(expression.getExpressionType())) {
|
||||
argExpression.setExpressionObject("LessMatch");
|
||||
argExpression.setLeft("source." + ClassMethodUtil.toGetMethod(expression.getAttribute()) + "()");
|
||||
argExpression.setRight(expression.getValue());
|
||||
} else if ("greaterEqualMatch".equals(expression.getExpressionType())) {
|
||||
argExpression.setExpressionObject("GreaterEqualMatch");
|
||||
argExpression.setLeft("source." + ClassMethodUtil.toGetMethod(expression.getAttribute()) + "()");
|
||||
argExpression.setRight(expression.getValue());
|
||||
} else if ("lessEqualMatch".equals(expression.getExpressionType())) {
|
||||
argExpression.setExpressionObject("LessEqualMatch");
|
||||
argExpression.setLeft("source." + ClassMethodUtil.toGetMethod(expression.getAttribute()) + "()");
|
||||
argExpression.setRight(expression.getValue());
|
||||
} else {
|
||||
throw new IllegalArgumentException("filter expression [" + expression.getExpressionType() + "] not found");
|
||||
}
|
||||
final String getter = matcherInfo.isBooleanType()
|
||||
? ClassMethodUtil.toIsMethod(expression.getAttribute())
|
||||
: ClassMethodUtil.toGetMethod(expression.getAttribute());
|
||||
|
||||
final Expression argExpression = new Expression();
|
||||
argExpression.setRight(expression.getValue());
|
||||
argExpression.setExpressionObject(matcherInfo.getMatcher().getName());
|
||||
argExpression.setLeft("source." + getter + "()");
|
||||
|
||||
entryMethod.addArg(argExpression);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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 org.apache.skywalking.oal.rt.parser;
|
||||
|
||||
import com.google.common.reflect.ClassPath;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.BooleanValueFilterMatcher;
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.FilterMatcher;
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
public enum FilterMatchers {
|
||||
INSTANCE;
|
||||
|
||||
FilterMatchers() {
|
||||
try {
|
||||
init();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final Map<String, MatcherInfo> matchersKeyedByType = new HashMap<>();
|
||||
|
||||
private void init() throws IOException {
|
||||
final ClassPath classpath = ClassPath.from(FilterMatchers.class.getClassLoader());
|
||||
final Set<ClassPath.ClassInfo> classes = classpath.getTopLevelClassesRecursive("org.apache.skywalking");
|
||||
for (ClassPath.ClassInfo classInfo : classes) {
|
||||
final Class<?> clazz = classInfo.load();
|
||||
|
||||
final FilterMatcher plainFilterMatcher = clazz.getAnnotation(FilterMatcher.class);
|
||||
final BooleanValueFilterMatcher booleanFilterMatcher = clazz.getAnnotation(BooleanValueFilterMatcher.class);
|
||||
if (plainFilterMatcher != null && booleanFilterMatcher != null) {
|
||||
throw new IllegalStateException(
|
||||
"A matcher class can not be annotated with both @FilterMatcher and @BooleanValueFilterMatcher"
|
||||
);
|
||||
}
|
||||
|
||||
if (plainFilterMatcher != null) {
|
||||
for (final String type : plainFilterMatcher.value()) {
|
||||
matchersKeyedByType.put(type, new MatcherInfo(clazz, false));
|
||||
}
|
||||
if (plainFilterMatcher.value().length == 0) {
|
||||
final String defaultTypeName = StringUtils.uncapitalize(clazz.getSimpleName());
|
||||
matchersKeyedByType.put(defaultTypeName, new MatcherInfo(clazz, false));
|
||||
}
|
||||
}
|
||||
|
||||
if (booleanFilterMatcher != null) {
|
||||
for (final String type : booleanFilterMatcher.value()) {
|
||||
matchersKeyedByType.put(type, new MatcherInfo(clazz, true));
|
||||
}
|
||||
if (booleanFilterMatcher.value().length == 0) {
|
||||
final String defaultTypeName = StringUtils.uncapitalize(clazz.getSimpleName());
|
||||
matchersKeyedByType.put(defaultTypeName, new MatcherInfo(clazz, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MatcherInfo find(final String type) {
|
||||
if (!matchersKeyedByType.containsKey(type)) {
|
||||
throw new IllegalArgumentException("filter expression [" + type + "] not found");
|
||||
}
|
||||
return matchersKeyedByType.get(type);
|
||||
}
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public static class MatcherInfo {
|
||||
private final Class<?> matcher;
|
||||
private final boolean isBooleanType;
|
||||
}
|
||||
}
|
||||
|
|
@ -23,13 +23,16 @@ import com.google.common.reflect.ClassPath;
|
|||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.MetricsFunction;
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
public class MetricsHolder {
|
||||
private static Map<String, Class<? extends Metrics>> REGISTER = new HashMap<>();
|
||||
private static final Map<String, Class<? extends Metrics>> REGISTER = new HashMap<>();
|
||||
private static volatile boolean INITIALIZED = false;
|
||||
|
||||
public static void init() throws IOException {
|
||||
private static void init() throws IOException {
|
||||
ClassPath classpath = ClassPath.from(MetricsHolder.class.getClassLoader());
|
||||
ImmutableSet<ClassPath.ClassInfo> classes = classpath.getTopLevelClassesRecursive("org.apache.skywalking");
|
||||
for (ClassPath.ClassInfo classInfo : classes) {
|
||||
|
|
@ -45,13 +48,16 @@ public class MetricsHolder {
|
|||
}
|
||||
}
|
||||
|
||||
public static Class<? extends Metrics> find(
|
||||
String functionName) {
|
||||
String func = functionName;
|
||||
Class<? extends Metrics> metricsClass = REGISTER.get(
|
||||
func);
|
||||
@SneakyThrows
|
||||
public static Class<? extends Metrics> find(String functionName) {
|
||||
if (!INITIALIZED) {
|
||||
init();
|
||||
INITIALIZED = true;
|
||||
}
|
||||
|
||||
Class<? extends Metrics> metricsClass = REGISTER.get(functionName);
|
||||
if (metricsClass == null) {
|
||||
throw new IllegalArgumentException("Can't find metrics, " + func);
|
||||
throw new IllegalArgumentException("Can't find metrics, " + functionName);
|
||||
}
|
||||
return metricsClass;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ ${metricsClassPackage}${metricsName}Metrics metrics = new ${metricsClassPackage}
|
|||
|
||||
<#if filterExpressions??>
|
||||
<#list filterExpressions as filterExpression>
|
||||
if (!new org.apache.skywalking.oap.server.core.analysis.metrics.expression.${filterExpression.expressionObject}().match(${filterExpression.left}, ${filterExpression.right})) {
|
||||
if (!new ${filterExpression.expressionObject}().match(${filterExpression.left}, ${filterExpression.right})) {
|
||||
return;
|
||||
}
|
||||
</#list>
|
||||
|
|
@ -18,7 +18,7 @@ metrics.${entryMethod.methodName}(
|
|||
<#if entryMethod.argTypes[arg_index] < 3>
|
||||
${arg}
|
||||
<#else>
|
||||
new org.apache.skywalking.oap.server.core.analysis.metrics.expression.${arg.expressionObject}().match(${arg.left}, ${arg.right})
|
||||
new ${arg.expressionObject}().match(${arg.left}, ${arg.right})
|
||||
</#if><#if arg_has_next>, </#if>
|
||||
</#list>);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@ package org.apache.skywalking.oal.rt.parser;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.expression.BooleanMatch;
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.expression.BooleanNotEqualMatch;
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.expression.EqualMatch;
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.expression.NotEqualMatch;
|
||||
import org.apache.skywalking.oap.server.core.annotation.AnnotationScan;
|
||||
import org.apache.skywalking.oap.server.core.source.DefaultScopeDefine;
|
||||
import org.apache.skywalking.oap.server.core.storage.StorageException;
|
||||
|
|
@ -28,14 +32,15 @@ import org.junit.Assert;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class DeepAnalysisTest {
|
||||
@BeforeClass
|
||||
public static void init() throws IOException, StorageException {
|
||||
AnnotationScan scopeScan = new AnnotationScan();
|
||||
scopeScan.registerListener(new DefaultScopeDefine.Listener());
|
||||
scopeScan.scan();
|
||||
|
||||
MetricsHolder.init();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
|
|
@ -122,8 +127,53 @@ public class DeepAnalysisTest {
|
|||
List<Expression> filterExpressions = result.getFilterExpressions();
|
||||
Assert.assertEquals(1, filterExpressions.size());
|
||||
Expression filterExpression = filterExpressions.get(0);
|
||||
Assert.assertEquals("EqualMatch", filterExpression.getExpressionObject());
|
||||
Assert.assertEquals(EqualMatch.class.getName(), filterExpression.getExpressionObject());
|
||||
Assert.assertEquals("source.getName()", filterExpression.getLeft());
|
||||
Assert.assertEquals("\"/service/prod/save\"", filterExpression.getRight());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldUseCorrectMatcher() {
|
||||
|
||||
AnalysisResult result = new AnalysisResult();
|
||||
result.setSourceName("Endpoint");
|
||||
result.setPackageName("endpoint.endpointavg");
|
||||
result.setSourceAttribute("latency");
|
||||
result.setMetricsName("EndpointAvg");
|
||||
result.setAggregationFunctionName("longAvg");
|
||||
|
||||
DeepAnalysis analysis = new DeepAnalysis();
|
||||
|
||||
result.setFilterExpressions(null);
|
||||
result.setFilterExpressionsParserResult(null);
|
||||
result.addFilterExpressionsParserResult(new ConditionExpression("booleanMatch", "valid", ""));
|
||||
result = analysis.analysis(result);
|
||||
assertTrue(result.getFilterExpressions().size() > 0);
|
||||
assertEquals(BooleanMatch.class.getName(), result.getFilterExpressions().get(0).getExpressionObject());
|
||||
assertEquals("source.isValid()", result.getFilterExpressions().get(0).getLeft());
|
||||
|
||||
result.setFilterExpressions(null);
|
||||
result.setFilterExpressionsParserResult(null);
|
||||
result.addFilterExpressionsParserResult(new ConditionExpression("stringMatch", "type", ""));
|
||||
result = analysis.analysis(result);
|
||||
assertTrue(result.getFilterExpressions().size() > 0);
|
||||
assertEquals(EqualMatch.class.getName(), result.getFilterExpressions().get(0).getExpressionObject());
|
||||
assertEquals("source.getType()", result.getFilterExpressions().get(0).getLeft());
|
||||
|
||||
result.setFilterExpressions(null);
|
||||
result.setFilterExpressionsParserResult(null);
|
||||
result.addFilterExpressionsParserResult(new ConditionExpression("notEqualMatch", "type", ""));
|
||||
result = analysis.analysis(result);
|
||||
assertTrue(result.getFilterExpressions().size() > 0);
|
||||
assertEquals(NotEqualMatch.class.getName(), result.getFilterExpressions().get(0).getExpressionObject());
|
||||
assertEquals("source.getType()", result.getFilterExpressions().get(0).getLeft());
|
||||
|
||||
result.setFilterExpressions(null);
|
||||
result.setFilterExpressionsParserResult(null);
|
||||
result.addFilterExpressionsParserResult(new ConditionExpression("booleanNotEqualMatch", "type", ""));
|
||||
result = analysis.analysis(result);
|
||||
assertTrue(result.getFilterExpressions().size() > 0);
|
||||
assertEquals(BooleanNotEqualMatch.class.getName(), result.getFilterExpressions().get(0).getExpressionObject());
|
||||
assertEquals("source.isType()", result.getFilterExpressions().get(0).getLeft());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,8 +34,6 @@ public class ScriptParserTest {
|
|||
|
||||
@BeforeClass
|
||||
public static void init() throws IOException, StorageException {
|
||||
MetricsHolder.init();
|
||||
|
||||
AnnotationScan scopeScan = new AnnotationScan();
|
||||
scopeScan.registerListener(new DefaultScopeDefine.Listener());
|
||||
scopeScan.scan();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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 org.apache.skywalking.oap.server.core.analysis.metrics.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Exactly the same functionalities as {@link FilterMatcher} except for the value type of this matcher is {@code
|
||||
* boolean}.
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface BooleanValueFilterMatcher {
|
||||
/**
|
||||
* @return see {@link FilterMatcher#value()}.
|
||||
*/
|
||||
String[] value() default {};
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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 org.apache.skywalking.oap.server.core.analysis.metrics.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.expression.BooleanMatch;
|
||||
|
||||
/**
|
||||
* Classes annotated with {@code FilterMatcher} are processors of the expressions in {@code filter} of the OAL script.
|
||||
* Take {@link BooleanMatch} as an example.
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface FilterMatcher {
|
||||
/**
|
||||
* @return the operator name(s) defined in the .g4 files, such as {@code lessEqualMatch} and {@code notEqualMatch},
|
||||
* the default value is the name of the class annotated with {@link FilterMatcher}, with the first letter being
|
||||
* lowercase.
|
||||
*/
|
||||
String[] value() default {};
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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 org.apache.skywalking.oap.server.core.analysis.metrics.expression;
|
||||
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.BooleanValueFilterMatcher;
|
||||
|
||||
@BooleanValueFilterMatcher
|
||||
public class BooleanMatch {
|
||||
public boolean match(Boolean left, Boolean right) {
|
||||
return left == right;
|
||||
}
|
||||
|
||||
public boolean match(boolean left, boolean right) {
|
||||
return left == right;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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 org.apache.skywalking.oap.server.core.analysis.metrics.expression;
|
||||
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.BooleanValueFilterMatcher;
|
||||
|
||||
@BooleanValueFilterMatcher
|
||||
public class BooleanNotEqualMatch {
|
||||
public boolean match(Boolean left, Boolean right) {
|
||||
return left != right;
|
||||
}
|
||||
|
||||
public boolean match(boolean left, boolean right) {
|
||||
return left != right;
|
||||
}
|
||||
}
|
||||
|
|
@ -19,48 +19,10 @@
|
|||
package org.apache.skywalking.oap.server.core.analysis.metrics.expression;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.FilterMatcher;
|
||||
|
||||
@FilterMatcher("stringMatch")
|
||||
public class EqualMatch {
|
||||
public boolean match(int left, int right) {
|
||||
return left == right;
|
||||
}
|
||||
|
||||
public boolean match(long left, long right) {
|
||||
return left == right;
|
||||
}
|
||||
|
||||
public boolean match(float left, float right) {
|
||||
return left == right;
|
||||
}
|
||||
|
||||
public boolean match(double left, double right) {
|
||||
return left == right;
|
||||
}
|
||||
|
||||
public boolean match(Integer left, Integer right) {
|
||||
return Objects.equals(left, right);
|
||||
}
|
||||
|
||||
public boolean match(Long left, Long right) {
|
||||
return Objects.equals(left, right);
|
||||
}
|
||||
|
||||
public boolean match(Float left, Float right) {
|
||||
return Objects.equals(left, right);
|
||||
}
|
||||
|
||||
public boolean match(Double left, Double right) {
|
||||
return Objects.equals(left, right);
|
||||
}
|
||||
|
||||
public boolean match(Boolean left, Boolean right) {
|
||||
return left == right;
|
||||
}
|
||||
|
||||
public boolean match(boolean left, boolean right) {
|
||||
return left == right;
|
||||
}
|
||||
|
||||
public boolean match(Object left, Object right) {
|
||||
return Objects.equals(left, right);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@
|
|||
|
||||
package org.apache.skywalking.oap.server.core.analysis.metrics.expression;
|
||||
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.FilterMatcher;
|
||||
|
||||
@FilterMatcher
|
||||
public class GreaterEqualMatch {
|
||||
public boolean match(int left, int right) {
|
||||
return left >= right;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@
|
|||
|
||||
package org.apache.skywalking.oap.server.core.analysis.metrics.expression;
|
||||
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.FilterMatcher;
|
||||
|
||||
@FilterMatcher
|
||||
public class GreaterMatch {
|
||||
public boolean match(int left, int right) {
|
||||
return left > right;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@
|
|||
|
||||
package org.apache.skywalking.oap.server.core.analysis.metrics.expression;
|
||||
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.FilterMatcher;
|
||||
|
||||
@FilterMatcher
|
||||
public class LessEqualMatch {
|
||||
public boolean match(int left, int right) {
|
||||
return left <= right;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@
|
|||
|
||||
package org.apache.skywalking.oap.server.core.analysis.metrics.expression;
|
||||
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.FilterMatcher;
|
||||
|
||||
@FilterMatcher
|
||||
public class LessMatch {
|
||||
public boolean match(int left, int right) {
|
||||
return left < right;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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 org.apache.skywalking.oap.server.core.analysis.metrics.expression;
|
||||
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.FilterMatcher;
|
||||
|
||||
@FilterMatcher
|
||||
public class LikeMatch {
|
||||
public boolean match(String left, String right) {
|
||||
if (left == null || right == null) {
|
||||
return false;
|
||||
}
|
||||
if (left.startsWith("%") && left.endsWith("%")) { // %keyword%
|
||||
return right.contains(left.substring(1, left.length() - 1));
|
||||
}
|
||||
return (left.startsWith("%") && right.endsWith(left.substring(1))) // %suffix
|
||||
|| (left.endsWith("%") && right.startsWith(left.substring(0, left.length() - 1))) // prefix%
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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 org.apache.skywalking.oap.server.core.analysis.metrics.expression;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.FilterMatcher;
|
||||
|
||||
@FilterMatcher
|
||||
public class NotEqualMatch {
|
||||
public boolean match(Object left, Object right) {
|
||||
return !Objects.equals(left, right);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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 org.apache.skywalking.oap.server.core.analysis.metrics.expression;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
public class LikeMatchTest {
|
||||
@Test
|
||||
public void testLike() {
|
||||
assertTrue(new LikeMatch().match("%Black", "MaxBlack"));
|
||||
assertTrue(new LikeMatch().match("Max%", "MaxBlack"));
|
||||
assertTrue(new LikeMatch().match("%axBl%", "MaxBlack"));
|
||||
|
||||
assertFalse(new LikeMatch().match("Max%", "CarolineChanning"));
|
||||
assertFalse(new LikeMatch().match("%Max", "CarolineChanning"));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue