Isolate MAL CounterWindow cache by metric name. (#11526)

This commit is contained in:
weixiang1862 2023-11-11 00:09:37 +08:00 committed by GitHub
parent 247016fbb5
commit 019c6feb2e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 46 additions and 30 deletions

View File

@ -37,6 +37,7 @@
* Support output key parameters in the booting logs.
* Fix cannot query zipkin traces with `annotationQuery` parameter in the JDBC related storage.
* Fix `limit` doesn't work for `findEndpoint` API in ES storage.
* Isolate MAL CounterWindow cache by metric name.
#### UI

View File

@ -84,7 +84,7 @@ public class Analyzer {
final String filterExpression,
final String expression,
final MeterSystem meterSystem) {
Expression e = DSL.parse(expression);
Expression e = DSL.parse(metricName, expression);
FilterExpression filter = null;
if (!Strings.isNullOrEmpty(filterExpression)) {
filter = new FilterExpression(filterExpression);

View File

@ -120,7 +120,7 @@ public class MetricConvert {
}
private void handleInitExp(String exp) {
Expression e = DSL.parse(exp);
Expression e = DSL.parse(null, exp);
final Result result = e.run(ImmutableMap.of());
if (!result.isSuccess() && result.isThrowable()) {
throw new ExpressionParsingException(

View File

@ -46,10 +46,11 @@ public final class DSL {
/**
* Parse string literal to Expression object, which can be reused.
*
* @param metricName the name of metric defined in mal rule
* @param expression string literal represents the DSL expression.
* @return Expression object could be executed.
*/
public static Expression parse(final String expression) {
public static Expression parse(final String metricName, final String expression) {
CompilerConfiguration cc = new CompilerConfiguration();
cc.setScriptBaseClass(DelegatingScript.class.getName());
ImportCustomizer icz = new ImportCustomizer();
@ -82,6 +83,6 @@ public final class DSL {
GroovyShell sh = new GroovyShell(new Binding(), cc);
DelegatingScript script = (DelegatingScript) sh.parse(expression);
return new Expression(expression, script);
return new Expression(metricName, expression, script);
}
}

View File

@ -36,11 +36,14 @@ import lombok.extern.slf4j.Slf4j;
public class Expression {
private static final ThreadLocal<Map<String, SampleFamily>> PROPERTY_REPOSITORY = new ThreadLocal<>();
private final String metricName;
private final String literal;
private final DelegatingScript expression;
public Expression(final String literal, final DelegatingScript expression) {
public Expression(final String metricName, final String literal, final DelegatingScript expression) {
this.metricName = metricName;
this.literal = literal;
this.expression = expression;
this.empower();
@ -94,7 +97,7 @@ public class Expression {
}
private void empower() {
expression.setDelegate(new ExpressionDelegate(literal));
expression.setDelegate(new ExpressionDelegate(metricName, literal));
extendNumber(Number.class);
}
@ -115,23 +118,26 @@ public class Expression {
public static final DownsamplingType LATEST = DownsamplingType.LATEST;
public static final DownsamplingType SUM_PER_MIN = DownsamplingType.SUM_PER_MIN;
private final String metricName;
private final String literal;
public SampleFamily propertyMissing(String metricName) {
public SampleFamily propertyMissing(String sampleName) {
ExpressionParsingContext.get().ifPresent(ctx -> {
if (!ctx.samples.contains(metricName)) {
ctx.samples.add(metricName);
if (!ctx.samples.contains(sampleName)) {
ctx.samples.add(sampleName);
}
});
Map<String, SampleFamily> sampleFamilies = PROPERTY_REPOSITORY.get();
if (sampleFamilies == null) {
return SampleFamily.EMPTY;
}
if (sampleFamilies.containsKey(metricName)) {
return sampleFamilies.get(metricName);
if (sampleFamilies.containsKey(sampleName)) {
SampleFamily sampleFamily = sampleFamilies.get(sampleName);
sampleFamily.context.setMetricName(this.metricName);
return sampleFamily;
}
if (!ExpressionParsingContext.get().isPresent()) {
log.warn("{} referred by \"{}\" doesn't exist in {}", metricName, literal, sampleFamilies.keySet());
if (ExpressionParsingContext.get().isEmpty()) {
log.warn("{} referred by \"{}\" doesn't exist in {}", sampleName, literal, sampleFamilies.keySet());
}
return SampleFamily.EMPTY;
}

View File

@ -46,14 +46,14 @@ public class Sample {
return toBuilder().value(transform.apply(value)).build();
}
Sample increase(String range, Function2<Double, Long, Double> transform) {
Tuple2<Long, Double> i = CounterWindow.INSTANCE.increase(name, labels, value, Duration.parse(range).toMillis(), timestamp);
Sample increase(String range, String metricName, Function2<Double, Long, Double> transform) {
Tuple2<Long, Double> i = CounterWindow.INSTANCE.increase(metricName, labels, value, Duration.parse(range).toMillis(), timestamp);
double nv = transform.apply(i._2, i._1);
return newValue(ignored -> nv);
}
Sample increase(Function2<Double, Long, Double> transform) {
Tuple2<Long, Double> i = CounterWindow.INSTANCE.pop(name, labels, value, timestamp);
Sample increase(String metricName, Function2<Double, Long, Double> transform) {
Tuple2<Long, Double> i = CounterWindow.INSTANCE.pop(metricName, labels, value, timestamp);
double nv = transform.apply(i._2, i._1);
return newValue(ignored -> nv);
}

View File

@ -276,7 +276,11 @@ public class SampleFamily {
return SampleFamily.build(
this.context,
Arrays.stream(samples)
.map(sample -> sample.increase(range, (lowerBoundValue, unused) -> sample.value - lowerBoundValue))
.map(sample -> sample.increase(
range,
context.metricName,
(lowerBoundValue, unused) -> sample.value - lowerBoundValue
))
.toArray(Sample[]::new)
);
}
@ -291,6 +295,7 @@ public class SampleFamily {
Arrays.stream(samples)
.map(sample -> sample.increase(
range,
context.metricName,
(lowerBoundValue, lowerBoundTime) -> {
final long timeDiff = (sample.timestamp - lowerBoundTime) / 1000;
return timeDiff < 1L ? 0.0 : (sample.value - lowerBoundValue) / timeDiff;
@ -308,6 +313,7 @@ public class SampleFamily {
this.context,
Arrays.stream(samples)
.map(sample -> sample.increase(
context.metricName,
(lowerBoundValue, lowerBoundTime) -> {
final long timeDiff = (sample.timestamp - lowerBoundTime) / 1000;
return timeDiff < 1L ? 0.0 : (sample.value - lowerBoundValue) / timeDiff;
@ -637,7 +643,7 @@ public class SampleFamily {
* The parsing context holds key results more than sample collection.
*/
@ToString
@EqualsAndHashCode
@EqualsAndHashCode(exclude = "metricName")
@Getter
@Setter
@Builder
@ -651,6 +657,8 @@ public class SampleFamily {
.build();
}
private String metricName;
@Builder.Default
private Map<MeterEntity, Sample[]> meterSamples = new HashMap<>();

View File

@ -157,7 +157,7 @@ public class AggregationTest {
String expression,
Result want,
boolean isThrow) {
Expression e = DSL.parse(expression);
Expression e = DSL.parse(name, expression);
Result r = null;
try {
r = e.run(input);

View File

@ -453,7 +453,7 @@ public class ArithmeticTest {
String expression,
Result want,
boolean isThrow) {
Expression e = DSL.parse(expression);
Expression e = DSL.parse(name, expression);
Result r = null;
try {
r = e.run(input);

View File

@ -58,7 +58,7 @@ public class BasicTest {
String expression,
Result want,
boolean isThrow) {
Expression e = DSL.parse(expression);
Expression e = DSL.parse(name, expression);
Result r = null;
try {
r = e.run(input);

View File

@ -95,7 +95,7 @@ public class ExpressionParsingTest {
String expression,
ExpressionParsingContext want,
boolean isThrow) {
Expression e = DSL.parse(expression);
Expression e = DSL.parse(name, expression);
ExpressionParsingContext r = null;
try {
r = e.parse();

View File

@ -85,7 +85,7 @@ public class FilterTest {
ImmutableMap<String, SampleFamily> input,
String expression,
Result want) {
Expression e = DSL.parse(expression);
Expression e = DSL.parse(name, expression);
Result r = e.run(input);
assertThat(r).isEqualTo(want);
}

View File

@ -122,7 +122,7 @@ public class FunctionTest {
String expression,
Result want,
boolean isThrow) {
Expression e = DSL.parse(expression);
Expression e = DSL.parse(name, expression);
Result r = null;
try {
r = e.run(input);

View File

@ -218,7 +218,7 @@ public class IncreaseTest {
String expression,
List<Result> want,
boolean isThrow) {
Expression e = DSL.parse(expression);
Expression e = DSL.parse(name, expression);
CounterWindow.INSTANCE.reset();
for (int i = 0; i < input.size(); i++) {
Result r = null;

View File

@ -270,7 +270,7 @@ public class K8sTagTest {
String expression,
Result want,
boolean isThrow) {
Expression e = DSL.parse(expression);
Expression e = DSL.parse(name, expression);
Result r = null;
try {
r = e.run(input);

View File

@ -614,7 +614,7 @@ public class ScopeTest {
final String expression,
final boolean isThrow,
final Map<MeterEntity, Sample[]> want) {
Expression e = DSL.parse(expression);
Expression e = DSL.parse(name, expression);
Result r = null;
try {
r = e.run(input);

View File

@ -120,7 +120,7 @@ public class TagFilterTest {
String expression,
Result want,
boolean isThrow) {
Expression e = DSL.parse(expression);
Expression e = DSL.parse(name, expression);
Result r = null;
try {
r = e.run(input);

View File

@ -128,7 +128,7 @@ public class ValueFilterTest {
final String expression,
final Result want,
final boolean isThrow) {
Expression e = DSL.parse(expression);
Expression e = DSL.parse(name, expression);
Result r = null;
try {
r = e.run(input);