提交 6475ab3d 编写于 作者: G Gao Hongtao 提交者: wu-sheng

Add apdex function to OAL (#3855)

* Add apdex function to OAL

* Add empty line

* Setup config watcher

* Add identifier type to function parameter

* Add config test

* Update score algorithm

* Replace responseCode with status

* Add comments about apdex score algorithm

* Add docs

* Add e2e test case

* Update test case

* Fix disptch class generating error

* Update value name of apdex metric

* Tuning threshold

* Fix single tolerated point bug
上级 125e96e7
# Apdex threshold
Apdex is a measure of response time based against a set threshold. It measures the ratio of satisfactory response times
to unsatisfactory response times. The response time is measured from an asset request to completed delivery back to
the requestor.
A user defines a response time threshold T. All responses handled in T or less time satisfy the user.
For example, if T is 1.2 seconds and a response completes in 0.5 seconds, then the user is satisfied. All responses
greater than 1.2 seconds dissatisfy the user. Responses greater than 4.8 seconds frustrate the user.
The apdex threshold T can be configured in `service-apdex-threshold.yml` file or via [Dynamic Configuration](dynamic-config.md).
The `default` item will be apply to a service isn't defined in this configuration as the default threshold.
## Configuration Format
The configuration content includes the service' names and their threshold:
```yml
# default threshold is 500ms
default: 500
# example:
# the threshold of service "tomcat" is 1s
# tomcat: 1000
# the threshold of service "springboot1" is 50ms
# springboot1: 50
```
......@@ -9,6 +9,7 @@ Right now, SkyWalking supports following dynamic configurations.
|receiver-trace.default.slowDBAccessThreshold| Thresholds of slow Database statement, override `receiver-trace/default/slowDBAccessThreshold` of `applciation.yml`. | default:200,mongodb:50|
|receiver-trace.default.uninstrumentedGateways| The uninstrumented gateways, override `gateways.yml`. | same as [`gateways.yml`](uninstrumented-gateways.md#configuration-format) |
|alarm.default.alarm-settings| The alarm settings, will override `alarm-settings.yml`. | same as [`alarm-settings.yml`](backend-alarm.md) |
|core.default.apdexThreshold| The apdex threshold settings, will override `service-apdex-threshold.yml`. | same as [`service-apdex-threshold.yml`](apdex-threshold.md) |
This feature depends on upstream service, so it is **OFF** as default.
......
......@@ -83,7 +83,7 @@ funcParamExpression
;
literalExpression
: BOOL_LITERAL | NUMBER_LITERAL
: BOOL_LITERAL | NUMBER_LITERAL | IDENTIFIER
;
expression
......
......@@ -50,7 +50,7 @@ public class AnalysisResult {
private List<ConditionExpression> funcConditionExpressions;
private List<String> funcArgs;
private List<Argument> funcArgs;
private int argGetIdx = 0;
private List<DataColumn> persistentFields;
......@@ -88,14 +88,14 @@ public class AnalysisResult {
filterExpressionsParserResult.add(conditionExpression);
}
public void addFuncArg(String value) {
public void addFuncArg(Argument argument) {
if (funcArgs == null) {
funcArgs = new LinkedList<>();
}
funcArgs.add(value);
funcArgs.add(argument);
}
public String getNextFuncArg() {
public Argument getNextFuncArg() {
return funcArgs.get(argGetIdx++);
}
......
/*
* 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 lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* Function argument.
*
* @author hongtaogao
*/
@Getter
@RequiredArgsConstructor
public class Argument {
private final int type;
private final String text;
}
......@@ -20,18 +20,39 @@ package org.apache.skywalking.oal.rt.parser;
import java.util.*;
import lombok.*;
import org.apache.skywalking.oal.rt.util.ClassMethodUtil;
@Getter(AccessLevel.PUBLIC)
@Setter(AccessLevel.PUBLIC)
public class EntryMethod {
private static final int LITERAL_TYPE = 1;
private static final int EXPRESSION_TYPE = 2;
static final int LITERAL_TYPE = 1;
static final int IDENTIFIER_TYPE = 2;
static final int EXPRESSION_TYPE = 3;
private String methodName;
private List<Integer> argTypes = new ArrayList<>();
private List<Object> argsExpressions = new ArrayList<>();
public void addArg(Class<?> parameterType, String expression) {
void addArg(Class<?> parameterType, Argument arg) {
if (arg.getType() == LITERAL_TYPE) {
addArg(parameterType, arg.getType(), arg.getText());
return;
}
addArg(parameterType, arg.getType(), parameterType.equals(boolean.class)
? "source." + ClassMethodUtil.toIsMethod(arg.getText()) + "()"
: "source." + ClassMethodUtil.toGetMethod(arg.getText()) + "()");
}
void addArg(Class<?> parameterType, String expression) {
addArg(parameterType, LITERAL_TYPE, expression);
}
void addArg(Expression expression) {
argTypes.add(EXPRESSION_TYPE);
argsExpressions.add(expression);
}
private void addArg(Class<?> parameterType, int type, String expression) {
if (parameterType.equals(int.class)) {
expression = "(int)(" + expression + ")";
} else if (parameterType.equals(long.class)) {
......@@ -41,12 +62,7 @@ public class EntryMethod {
} else if (parameterType.equals(float.class)) {
expression = "(float)(" + expression + ")";
}
argTypes.add(LITERAL_TYPE);
argsExpressions.add(expression);
}
public void addArg(Expression expression) {
argTypes.add(EXPRESSION_TYPE);
argTypes.add(type);
argsExpressions.add(expression);
}
}
......@@ -20,7 +20,8 @@ package org.apache.skywalking.oal.rt.parser;
import java.util.List;
import org.antlr.v4.runtime.misc.NotNull;
import org.apache.skywalking.oal.rt.grammar.*;
import org.apache.skywalking.oal.rt.grammar.OALParser;
import org.apache.skywalking.oal.rt.grammar.OALParserBaseListener;
import org.apache.skywalking.oap.server.core.source.DefaultScopeDefine;
public class OALListener extends OALParserBaseListener {
......@@ -148,7 +149,11 @@ public class OALListener extends OALParserBaseListener {
////////////
@Override public void enterLiteralExpression(OALParser.LiteralExpressionContext ctx) {
current.addFuncArg(ctx.getText());
if (ctx.IDENTIFIER() == null) {
current.addFuncArg(new Argument(EntryMethod.LITERAL_TYPE, ctx.getText()));
return;
}
current.addFuncArg(new Argument(EntryMethod.IDENTIFIER_TYPE, ctx.getText()));
}
private String metricsNameFormat(String source) {
......
......@@ -15,7 +15,7 @@ private void do${metricsName}(org.apache.skywalking.oap.server.core.source.${sou
</#list>
metrics.${entryMethod.methodName}(
<#list entryMethod.argsExpressions as arg>
<#if entryMethod.argTypes[arg_index] == 1>
<#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})
......
......@@ -33,6 +33,7 @@ service_p95 = from(Service.latency).p95(10);
service_p90 = from(Service.latency).p90(10);
service_p75 = from(Service.latency).p75(10);
service_p50 = from(Service.latency).p50(10);
service_apdex = from(Service.latency).apdex(name, status);
// Service relation scope metrics for topology
service_relation_client_cpm = from(ServiceRelation.*).filter(detectPoint == DetectPoint.CLIENT).cpm();
......
# 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.
# default threshold is 500ms
default: 500
# example:
# the threshold of service "tomcat" is 1s
# tomcat: 1000
# the threshold of service "springboot1" is 50ms
# springboot1: 50
\ No newline at end of file
......@@ -85,6 +85,11 @@
<artifactId>grpc-testing</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-testing</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
......
......@@ -20,7 +20,9 @@ package org.apache.skywalking.oap.server.core;
import java.io.IOException;
import org.apache.skywalking.oap.server.configuration.api.ConfigurationModule;
import org.apache.skywalking.oap.server.configuration.api.DynamicConfigurationService;
import org.apache.skywalking.oap.server.core.analysis.*;
import org.apache.skywalking.oap.server.core.analysis.metrics.ApdexMetrics;
import org.apache.skywalking.oap.server.core.analysis.worker.MetricsStreamProcessor;
import org.apache.skywalking.oap.server.core.analysis.worker.TopNStreamProcessor;
import org.apache.skywalking.oap.server.core.annotation.AnnotationScan;
......@@ -59,6 +61,7 @@ public class CoreModuleProvider extends ModuleProvider {
private final StorageModels storageModels;
private final SourceReceiverImpl receiver;
private OALEngine oalEngine;
private ApdexThresholdConfig apdexThresholdConfig;
public CoreModuleProvider() {
super();
......@@ -172,9 +175,12 @@ public class CoreModuleProvider extends ModuleProvider {
MetricsStreamProcessor.getInstance().setEnableDatabaseSession(moduleConfig.isEnableDatabaseSession());
TopNStreamProcessor.getInstance().setTopNWorkerReportCycle(moduleConfig.getTopNReportPeriod());
apdexThresholdConfig = new ApdexThresholdConfig(this);
ApdexMetrics.setDICT(apdexThresholdConfig);
}
@Override public void start() throws ModuleStartException {
grpcServer.addHandler(new RemoteServiceHandler(getManager()));
grpcServer.addHandler(new HealthCheckServiceHandler());
remoteClientManager.start();
......@@ -193,6 +199,8 @@ public class CoreModuleProvider extends ModuleProvider {
this.getManager().find(ClusterModule.NAME).provider().getService(ClusterRegister.class).registerRemote(gRPCServerInstance);
}
DynamicConfigurationService dynamicConfigurationService = getManager().find(ConfigurationModule.NAME).provider().getService(DynamicConfigurationService.class);
dynamicConfigurationService.registerConfigChangeWatcher(apdexThresholdConfig);
}
@Override public void notifyAfterCompleted() throws ModuleStartException {
......
/*
* 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;
import java.io.FileNotFoundException;
import java.io.Reader;
import java.io.StringReader;
import java.util.Collections;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.configuration.api.ConfigChangeWatcher;
import org.apache.skywalking.oap.server.core.Const;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.CoreModuleProvider;
import org.apache.skywalking.oap.server.library.util.ResourceUtils;
import org.yaml.snakeyaml.Yaml;
/**
* Apdex threshold configuration dictionary adapter.
* Looking up a service apdex threshold from dynamic config service.
*
* @author hongtaogao
*/
@Slf4j
public class ApdexThresholdConfig extends ConfigChangeWatcher implements ConfigurationDictionary {
private static final String CONFIG_FILE_NAME = "service-apdex-threshold.yml";
private static final int SYSTEM_RESERVED_THRESHOLD = 500;
private Map<String, Integer> dictionary = Collections.emptyMap();
private String rawConfig = Const.EMPTY_STRING;
public ApdexThresholdConfig(final CoreModuleProvider provider) {
super(CoreModule.NAME, provider, "apdexThreshold");
try {
updateConfig(ResourceUtils.read(CONFIG_FILE_NAME));
} catch (final FileNotFoundException e) {
log.error("Cannot config from: {}", CONFIG_FILE_NAME, e);
}
}
@Override public Number lookup(String name) {
int t = dictionary.getOrDefault(name, -1);
if (t < 0) {
t = dictionary.getOrDefault("default", -1);
}
if (t < 0) {
log.warn("Pick up system reserved threshold {}ms because of config missing", SYSTEM_RESERVED_THRESHOLD);
return SYSTEM_RESERVED_THRESHOLD;
}
if (log.isDebugEnabled()) {
log.debug("Apdex threshold of {} is {}ms", name, t);
}
return t;
}
@Override public void notify(ConfigChangeEvent value) {
if (EventType.DELETE.equals(value.getEventType())) {
activeSetting("");
} else {
activeSetting(value.getNewValue());
}
}
@Override public String value() {
return rawConfig;
}
private synchronized void activeSetting(String config) {
if (log.isDebugEnabled()) {
log.debug("Updating using new static config: {}", config);
}
rawConfig = config;
updateConfig(new StringReader(config));
}
@SuppressWarnings("unchecked")
private void updateConfig(final Reader contentRender) {
dictionary = (Map<String, Integer>)new Yaml().load(contentRender);
if (dictionary == null) {
dictionary = Collections.emptyMap();
}
}
}
/*
* 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;
/**
* Dictionary for lookup config item.
*
* @author gaohongtao
*/
public interface ConfigurationDictionary {
/**
* Lookup a number config item.
*
* @param name config key.
* @return a number config value.
*/
Number lookup(String name);
}
/*
* 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;
import lombok.Getter;
import lombok.Setter;
import org.apache.skywalking.oap.server.core.analysis.ConfigurationDictionary;
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.Arg;
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.Entrance;
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.MetricsFunction;
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.SourceFrom;
import org.apache.skywalking.oap.server.core.query.sql.Function;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
/**
* Apdex dissatisfaction levels of Tolerating (apdex_t) and Frustrated (apdex_f) indicate how slow site performance
* contributes to poor customer experiences in your app. For example:
*
* 10000: All responses are satisfactory.
* Tolerating responses half satisfy a user. For example, if all responses are Tolerating, then the Apdex value will
* be 5000.
* 0: None of the responses are satisfactory.
*
* @author gaohongtao
*/
@MetricsFunction(functionName = "apdex")
public abstract class ApdexMetrics extends Metrics implements IntValueHolder {
@Setter
private static ConfigurationDictionary DICT;
protected static final String TOTAL_NUM = "total_num";
// Level: satisfied
protected static final String S_NUM = "s_num";
// Level: tolerated
protected static final String T_NUM = "t_num";
protected static final String VALUE = "value";
@Getter @Setter @Column(columnName = TOTAL_NUM) private int totalNum;
@Getter @Setter @Column(columnName = S_NUM) private int sNum;
@Getter @Setter @Column(columnName = T_NUM) private int tNum;
@Getter @Setter @Column(columnName = VALUE, isValue = true, function = Function.Avg) private int value;
@Entrance
public final void combine(@SourceFrom int value, @Arg String name, @Arg boolean status) {
int t = DICT.lookup(name).intValue();
int t4 = t * 4;
totalNum++;
if (!status || value >= t4) {
return;
}
if (value >= t) {
tNum++;
} else {
sNum++;
}
}
@Override public final void combine(Metrics metrics) {
tNum += ((ApdexMetrics)metrics).tNum;
sNum += ((ApdexMetrics)metrics).sNum;
totalNum += ((ApdexMetrics)metrics).totalNum;
}
@Override public void calculate() {
value = (sNum * 10000 + tNum * 10000 / 2) / totalNum;
}
@Override public int getValue() {
return value;
}
}
/*
* 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;
import java.util.Set;
import org.apache.skywalking.oap.server.configuration.api.ConfigTable;
import org.apache.skywalking.oap.server.configuration.api.ConfigWatcherRegister;
import org.apache.skywalking.oap.server.core.CoreModuleProvider;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class ApdexThresholdConfigTest {
@Mock
private CoreModuleProvider provider;
@Test
public void testLookupOfBeforeInit() {
ApdexThresholdConfig config = new ApdexThresholdConfig(provider);
assertThat(config.lookup("foo"), is(500));
assertThat(config.lookup("default"), is(500));
assertThat(config.lookup("bar"), is(500));
}
@Test(timeout = 20000)
public void testLookupOfDynamicUpdate() throws InterruptedException {
ConfigWatcherRegister register = new MockConfigWatcherRegister(3);
when(provider.name()).thenReturn("default");
ApdexThresholdConfig config = new ApdexThresholdConfig(provider);
register.registerConfigChangeWatcher(config);
register.start();
while (config.lookup("foo").intValue() == 500) {
Thread.sleep(2000);
}
assertThat(config.lookup("foo"), is(200));
assertThat(config.lookup("default"), is(1000));
assertThat(config.lookup("bar"), is(1000));
}
public static class MockConfigWatcherRegister extends ConfigWatcherRegister {
public MockConfigWatcherRegister(long syncPeriod) {
super(syncPeriod);
}
@Override public ConfigTable readConfig(Set<String> keys) {
ConfigTable table = new ConfigTable();
table.add(new ConfigTable.ConfigItem("core.default.apdexThreshold", "default: 1000 \nfoo: 200"));
return table;
}
}
}
\ No newline at end of file
/*
* 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;
import org.apache.skywalking.oap.server.core.remote.grpc.proto.RemoteData;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.*;
public class ApdexMetricsTest {
@Before
public void setUp() {
ApdexMetrics.setDICT(name -> name.equals("foo") ? 500 : 1000);
}
@Test
public void testEntrance() {
ApdexMetrics apdex = new ApdexMetricsImpl();
apdex.combine(200, "foo", true);
apdex.calculate();
assertThat(apdex.getValue(), is(10000));
apdex = new ApdexMetricsImpl();
apdex.combine(1000, "foo", true);
apdex.calculate();
assertThat(apdex.getValue(), is(5000));
apdex = new ApdexMetricsImpl();
apdex.combine(2000, "foo", true);
apdex.calculate();
assertThat(apdex.getValue(), is(0));
apdex = new ApdexMetricsImpl();
apdex.combine(200, "foo", true);
apdex.combine(300, "bar", true);
apdex.calculate();
assertThat(apdex.getValue(), is(10000));
apdex = new ApdexMetricsImpl();
apdex.combine(200, "foo", true);
apdex.combine(1500, "bar", true);
apdex.calculate();
assertThat(apdex.getValue(), is(7500));
apdex = new ApdexMetricsImpl();
apdex.combine(200, "foo", true);
apdex.combine(300, "bar", false);
apdex.calculate();
assertThat(apdex.getValue(), is(5000));
apdex = new ApdexMetricsImpl();
apdex.combine(200, "foo", true);
apdex.combine(1500, "bar", false);
apdex.calculate();
assertThat(apdex.getValue(), is(5000));
apdex = new ApdexMetricsImpl();
apdex.combine(200, "foo", true);
apdex.combine(5000, "bar", true);
apdex.calculate();
assertThat(apdex.getValue(), is(5000));
}
@Test
public void testCombine() {
ApdexMetrics apdex1 = new ApdexMetricsImpl();
apdex1.combine(200, "foo", true);
apdex1.combine(300, "bar", true);
apdex1.combine(200, "foo", true);
apdex1.combine(1500, "bar", true);
ApdexMetrics apdex2 = new ApdexMetricsImpl();
apdex2.combine(200, "foo", true);
apdex2.combine(300, "bar", false);
apdex2.combine(200, "foo", true);
apdex2.combine(1500, "bar", false);
apdex2.combine(200, "foo", true);
apdex2.combine(5000, "bar", true);
apdex1.combine(apdex2);
apdex1.calculate();
assertThat(apdex1.getValue(), is(6500));
}
public class ApdexMetricsImpl extends ApdexMetrics {
@Override public String id() {
return null;
}
@Override public Metrics toHour() {
return null;
}
@Override public Metrics toDay() {
return null;
}
@Override public Metrics toMonth() {
return null;
}
@Override public int remoteHashCode() {
return 0;
}
@Override public void deserialize(RemoteData remoteData) {
}
@Override public RemoteData.Builder serialize() {
return null;
}
}
}
# 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.
# default threshold is 500ms
default: 500
# example:
# the threshold of service "tomcat" is 1s
# tomcat: 1000
# the threshold of service "springboot1" is 50ms
# springboot1: 50
\ No newline at end of file
......@@ -29,12 +29,14 @@ public class MetricsQuery extends AbstractQuery<MetricsQuery> {
public static String SERVICE_P90 = "service_p90";
public static String SERVICE_P75 = "service_p75";
public static String SERVICE_P50 = "service_p50";
public static String SERVICE_APDEX = "service_apdex";
public static String[] ALL_SERVICE_METRICS = {
SERVICE_P99,
SERVICE_P95,
SERVICE_P90,
SERVICE_P75,
SERVICE_P50
SERVICE_P50,
SERVICE_APDEX
};
public static String ENDPOINT_P99 = "endpoint_p99";
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册