Support !=, like filter expressions in OAL (#5269)
This commit is contained in:
parent
7f7e96b088
commit
ecc18b9be3
|
|
@ -14,11 +14,12 @@ packages/
|
||||||
/docker/snapshot/*.gz
|
/docker/snapshot/*.gz
|
||||||
.mvn/wrapper/*.jar
|
.mvn/wrapper/*.jar
|
||||||
OALLexer.tokens
|
OALLexer.tokens
|
||||||
.factorypath
|
.factorypath
|
||||||
.vscode
|
.vscode
|
||||||
.checkstyle
|
.checkstyle
|
||||||
.externalToolBuilders
|
.externalToolBuilders
|
||||||
/test/plugin/dist
|
/test/plugin/dist
|
||||||
/test/plugin/workspace
|
/test/plugin/workspace
|
||||||
/test/jacoco/classes
|
/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.
|
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 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.
|
or code generation error if incompatible.
|
||||||
|
|
||||||
## Aggregation Function
|
## 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)
|
Endpoint_p99 = from(Endpoint.latency).filter(name in ("Endpoint1", "Endpoint2")).summary(0.99)
|
||||||
|
|
||||||
// Caculate p99 of Endpoint name started with `serv`
|
// 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
|
// Caculate the avg response time of each Endpoint
|
||||||
Endpoint_avg = from(Endpoint.latency).avg()
|
Endpoint_avg = from(Endpoint.latency).avg()
|
||||||
|
|
@ -112,7 +112,7 @@ Endpoint_avg = from(Endpoint.latency).avg()
|
||||||
Endpoint_percentile = from(Endpoint.latency).percentile(10)
|
Endpoint_percentile = from(Endpoint.latency).percentile(10)
|
||||||
|
|
||||||
// Caculate the percent of response status is true, for each service.
|
// 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.
|
// Caculate the percent of response code in [200, 299], for each service.
|
||||||
Endpoint_200 = from(Endpoint.*).filter(responseCode like "2%").percent()
|
Endpoint_200 = from(Endpoint.*).filter(responseCode like "2%").percent()
|
||||||
|
|
|
||||||
|
|
@ -133,4 +133,6 @@ ALL: '*';
|
||||||
GREATER: '>';
|
GREATER: '>';
|
||||||
LESS: '<';
|
LESS: '<';
|
||||||
GREATER_EQUAL: '>=';
|
GREATER_EQUAL: '>=';
|
||||||
LESS_EQUAL: '<=';
|
LESS_EQUAL: '<=';
|
||||||
|
NOT_EQUAL: '!=';
|
||||||
|
LIKE: 'like';
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ literalExpression
|
||||||
;
|
;
|
||||||
|
|
||||||
expression
|
expression
|
||||||
: booleanMatch | stringMatch | greaterMatch | lessMatch | greaterEqualMatch | lessEqualMatch
|
: booleanMatch | stringMatch | greaterMatch | lessMatch | greaterEqualMatch | lessEqualMatch | notEqualMatch | booleanNotEqualMatch | likeMatch
|
||||||
;
|
;
|
||||||
|
|
||||||
booleanMatch
|
booleanMatch
|
||||||
|
|
@ -115,6 +115,18 @@ lessEqualMatch
|
||||||
: conditionAttribute LESS_EQUAL numberConditionValue
|
: conditionAttribute LESS_EQUAL numberConditionValue
|
||||||
;
|
;
|
||||||
|
|
||||||
|
booleanNotEqualMatch
|
||||||
|
: conditionAttribute NOT_EQUAL booleanConditionValue
|
||||||
|
;
|
||||||
|
|
||||||
|
notEqualMatch
|
||||||
|
: conditionAttribute NOT_EQUAL (numberConditionValue | stringConditionValue | enumConditionValue)
|
||||||
|
;
|
||||||
|
|
||||||
|
likeMatch
|
||||||
|
: conditionAttribute LIKE stringConditionValue
|
||||||
|
;
|
||||||
|
|
||||||
conditionAttribute
|
conditionAttribute
|
||||||
: IDENTIFIER
|
: IDENTIFIER
|
||||||
;
|
;
|
||||||
|
|
@ -133,4 +145,4 @@ enumConditionValue
|
||||||
|
|
||||||
numberConditionValue
|
numberConditionValue
|
||||||
: NUMBER_LITERAL
|
: 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.AllDispatcherContext;
|
||||||
import org.apache.skywalking.oal.rt.output.DispatcherContext;
|
import org.apache.skywalking.oal.rt.output.DispatcherContext;
|
||||||
import org.apache.skywalking.oal.rt.parser.AnalysisResult;
|
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.OALScripts;
|
||||||
import org.apache.skywalking.oal.rt.parser.ScriptParser;
|
import org.apache.skywalking.oal.rt.parser.ScriptParser;
|
||||||
import org.apache.skywalking.oal.rt.parser.SourceColumn;
|
import org.apache.skywalking.oal.rt.parser.SourceColumn;
|
||||||
|
|
@ -144,12 +143,6 @@ public class OALRuntime implements OALEngine {
|
||||||
this.currentClassLoader = currentClassLoader;
|
this.currentClassLoader = currentClassLoader;
|
||||||
Reader read;
|
Reader read;
|
||||||
|
|
||||||
try {
|
|
||||||
MetricsHolder.init();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new ModuleStartException("load metrics functions error.", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
read = ResourceUtils.read(oalDefine.getConfigFile());
|
read = ResourceUtils.read(oalDefine.getConfigFile());
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,15 @@
|
||||||
|
|
||||||
package org.apache.skywalking.oal.rt.parser;
|
package org.apache.skywalking.oal.rt.parser;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
public class ConditionExpression {
|
public class ConditionExpression {
|
||||||
// original from script
|
// original from script
|
||||||
private String expressionType;
|
private String expressionType;
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Parameter;
|
import java.lang.reflect.Parameter;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.apache.skywalking.oal.rt.util.ClassMethodUtil;
|
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.Arg;
|
||||||
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.ConstOne;
|
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.ConstOne;
|
||||||
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.Entrance;
|
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
|
// 1. Set sub package name by source.metrics
|
||||||
result.setPackageName(result.getSourceName().toLowerCase());
|
result.setPackageName(result.getSourceName().toLowerCase());
|
||||||
|
|
||||||
Class<? extends org.apache.skywalking.oap.server.core.analysis.metrics.Metrics> metricsClass = MetricsHolder.find(result
|
Class<? extends Metrics> metricsClass = MetricsHolder.find(result.getAggregationFunctionName());
|
||||||
.getAggregationFunctionName());
|
|
||||||
String metricsClassSimpleName = metricsClass.getSimpleName();
|
String metricsClassSimpleName = metricsClass.getSimpleName();
|
||||||
|
|
||||||
result.setMetricsClassName(metricsClassSimpleName);
|
result.setMetricsClassName(metricsClassSimpleName);
|
||||||
|
|
@ -45,45 +45,22 @@ public class DeepAnalysis {
|
||||||
List<ConditionExpression> expressions = result.getFilterExpressionsParserResult();
|
List<ConditionExpression> expressions = result.getFilterExpressionsParserResult();
|
||||||
if (expressions != null && expressions.size() > 0) {
|
if (expressions != null && expressions.size() > 0) {
|
||||||
for (ConditionExpression expression : expressions) {
|
for (ConditionExpression expression : expressions) {
|
||||||
Expression filterExpression = new Expression();
|
final FilterMatchers.MatcherInfo matcherInfo = FilterMatchers.INSTANCE.find(expression.getExpressionType());
|
||||||
if ("booleanMatch".equals(expression.getExpressionType())) {
|
|
||||||
filterExpression.setExpressionObject("EqualMatch");
|
final String getter = matcherInfo.isBooleanType()
|
||||||
filterExpression.setLeft("source." + ClassMethodUtil.toIsMethod(expression.getAttribute()) + "()");
|
? ClassMethodUtil.toIsMethod(expression.getAttribute())
|
||||||
filterExpression.setRight(expression.getValue());
|
: ClassMethodUtil.toGetMethod(expression.getAttribute());
|
||||||
result.addFilterExpressions(filterExpression);
|
|
||||||
} else if ("stringMatch".equals(expression.getExpressionType())) {
|
final Expression filterExpression = new Expression();
|
||||||
filterExpression.setExpressionObject("EqualMatch");
|
filterExpression.setExpressionObject(matcherInfo.getMatcher().getName());
|
||||||
filterExpression.setLeft("source." + ClassMethodUtil.toGetMethod(expression.getAttribute()) + "()");
|
filterExpression.setLeft("source." + getter + "()");
|
||||||
filterExpression.setRight(expression.getValue());
|
filterExpression.setRight(expression.getValue());
|
||||||
result.addFilterExpressions(filterExpression);
|
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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Find Entrance method of this metrics
|
// 3. Find Entrance method of this metrics
|
||||||
Class c = metricsClass;
|
Class<?> c = metricsClass;
|
||||||
Method entranceMethod = null;
|
Method entranceMethod = null;
|
||||||
SearchEntrance:
|
SearchEntrance:
|
||||||
while (!c.equals(Object.class)) {
|
while (!c.equals(Object.class)) {
|
||||||
|
|
@ -117,36 +94,17 @@ public class DeepAnalysis {
|
||||||
entryMethod.addArg(parameterType, "1");
|
entryMethod.addArg(parameterType, "1");
|
||||||
} else if (annotation instanceof org.apache.skywalking.oap.server.core.analysis.metrics.annotation.Expression) {
|
} else if (annotation instanceof org.apache.skywalking.oap.server.core.analysis.metrics.annotation.Expression) {
|
||||||
if (result.getFuncConditionExpressions().size() == 1) {
|
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();
|
final String getter = matcherInfo.isBooleanType()
|
||||||
if ("booleanMatch".equals(expression.getExpressionType())) {
|
? ClassMethodUtil.toIsMethod(expression.getAttribute())
|
||||||
argExpression.setExpressionObject("EqualMatch");
|
: ClassMethodUtil.toGetMethod(expression.getAttribute());
|
||||||
argExpression.setLeft("source." + ClassMethodUtil.toIsMethod(expression.getAttribute()) + "()");
|
|
||||||
argExpression.setRight(expression.getValue());
|
final Expression argExpression = new Expression();
|
||||||
} else if ("stringMatch".equals(expression.getExpressionType())) {
|
argExpression.setRight(expression.getValue());
|
||||||
argExpression.setExpressionObject("EqualMatch");
|
argExpression.setExpressionObject(matcherInfo.getMatcher().getName());
|
||||||
argExpression.setLeft("source." + ClassMethodUtil.toGetMethod(expression.getAttribute()) + "()");
|
argExpression.setLeft("source." + getter + "()");
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
entryMethod.addArg(argExpression);
|
entryMethod.addArg(argExpression);
|
||||||
} else {
|
} 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.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
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.Metrics;
|
||||||
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.MetricsFunction;
|
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.MetricsFunction;
|
||||||
|
|
||||||
|
@SuppressWarnings("UnstableApiUsage")
|
||||||
public class MetricsHolder {
|
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());
|
ClassPath classpath = ClassPath.from(MetricsHolder.class.getClassLoader());
|
||||||
ImmutableSet<ClassPath.ClassInfo> classes = classpath.getTopLevelClassesRecursive("org.apache.skywalking");
|
ImmutableSet<ClassPath.ClassInfo> classes = classpath.getTopLevelClassesRecursive("org.apache.skywalking");
|
||||||
for (ClassPath.ClassInfo classInfo : classes) {
|
for (ClassPath.ClassInfo classInfo : classes) {
|
||||||
|
|
@ -45,13 +48,16 @@ public class MetricsHolder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Class<? extends Metrics> find(
|
@SneakyThrows
|
||||||
String functionName) {
|
public static Class<? extends Metrics> find(String functionName) {
|
||||||
String func = functionName;
|
if (!INITIALIZED) {
|
||||||
Class<? extends Metrics> metricsClass = REGISTER.get(
|
init();
|
||||||
func);
|
INITIALIZED = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Class<? extends Metrics> metricsClass = REGISTER.get(functionName);
|
||||||
if (metricsClass == null) {
|
if (metricsClass == null) {
|
||||||
throw new IllegalArgumentException("Can't find metrics, " + func);
|
throw new IllegalArgumentException("Can't find metrics, " + functionName);
|
||||||
}
|
}
|
||||||
return metricsClass;
|
return metricsClass;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ ${metricsClassPackage}${metricsName}Metrics metrics = new ${metricsClassPackage}
|
||||||
|
|
||||||
<#if filterExpressions??>
|
<#if filterExpressions??>
|
||||||
<#list filterExpressions as filterExpression>
|
<#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;
|
return;
|
||||||
}
|
}
|
||||||
</#list>
|
</#list>
|
||||||
|
|
@ -18,7 +18,7 @@ metrics.${entryMethod.methodName}(
|
||||||
<#if entryMethod.argTypes[arg_index] < 3>
|
<#if entryMethod.argTypes[arg_index] < 3>
|
||||||
${arg}
|
${arg}
|
||||||
<#else>
|
<#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>
|
</#if><#if arg_has_next>, </#if>
|
||||||
</#list>);
|
</#list>);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,10 @@ package org.apache.skywalking.oal.rt.parser;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
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.annotation.AnnotationScan;
|
||||||
import org.apache.skywalking.oap.server.core.source.DefaultScopeDefine;
|
import org.apache.skywalking.oap.server.core.source.DefaultScopeDefine;
|
||||||
import org.apache.skywalking.oap.server.core.storage.StorageException;
|
import org.apache.skywalking.oap.server.core.storage.StorageException;
|
||||||
|
|
@ -28,14 +32,15 @@ import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class DeepAnalysisTest {
|
public class DeepAnalysisTest {
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void init() throws IOException, StorageException {
|
public static void init() throws IOException, StorageException {
|
||||||
AnnotationScan scopeScan = new AnnotationScan();
|
AnnotationScan scopeScan = new AnnotationScan();
|
||||||
scopeScan.registerListener(new DefaultScopeDefine.Listener());
|
scopeScan.registerListener(new DefaultScopeDefine.Listener());
|
||||||
scopeScan.scan();
|
scopeScan.scan();
|
||||||
|
|
||||||
MetricsHolder.init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
|
|
@ -122,8 +127,53 @@ public class DeepAnalysisTest {
|
||||||
List<Expression> filterExpressions = result.getFilterExpressions();
|
List<Expression> filterExpressions = result.getFilterExpressions();
|
||||||
Assert.assertEquals(1, filterExpressions.size());
|
Assert.assertEquals(1, filterExpressions.size());
|
||||||
Expression filterExpression = filterExpressions.get(0);
|
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("source.getName()", filterExpression.getLeft());
|
||||||
Assert.assertEquals("\"/service/prod/save\"", filterExpression.getRight());
|
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
|
@BeforeClass
|
||||||
public static void init() throws IOException, StorageException {
|
public static void init() throws IOException, StorageException {
|
||||||
MetricsHolder.init();
|
|
||||||
|
|
||||||
AnnotationScan scopeScan = new AnnotationScan();
|
AnnotationScan scopeScan = new AnnotationScan();
|
||||||
scopeScan.registerListener(new DefaultScopeDefine.Listener());
|
scopeScan.registerListener(new DefaultScopeDefine.Listener());
|
||||||
scopeScan.scan();
|
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;
|
package org.apache.skywalking.oap.server.core.analysis.metrics.expression;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.FilterMatcher;
|
||||||
|
|
||||||
|
@FilterMatcher("stringMatch")
|
||||||
public class EqualMatch {
|
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) {
|
public boolean match(Object left, Object right) {
|
||||||
return Objects.equals(left, right);
|
return Objects.equals(left, right);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@
|
||||||
|
|
||||||
package org.apache.skywalking.oap.server.core.analysis.metrics.expression;
|
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 class GreaterEqualMatch {
|
||||||
public boolean match(int left, int right) {
|
public boolean match(int left, int right) {
|
||||||
return left >= right;
|
return left >= right;
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@
|
||||||
|
|
||||||
package org.apache.skywalking.oap.server.core.analysis.metrics.expression;
|
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 class GreaterMatch {
|
||||||
public boolean match(int left, int right) {
|
public boolean match(int left, int right) {
|
||||||
return left > right;
|
return left > right;
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@
|
||||||
|
|
||||||
package org.apache.skywalking.oap.server.core.analysis.metrics.expression;
|
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 class LessEqualMatch {
|
||||||
public boolean match(int left, int right) {
|
public boolean match(int left, int right) {
|
||||||
return left <= right;
|
return left <= right;
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@
|
||||||
|
|
||||||
package org.apache.skywalking.oap.server.core.analysis.metrics.expression;
|
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 class LessMatch {
|
||||||
public boolean match(int left, int right) {
|
public boolean match(int left, int right) {
|
||||||
return left < 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