Merge branch 'apache-3.2' into apache-3.3

This commit is contained in:
Albumen Kevin 2023-05-23 20:00:42 +08:00
commit 59758f4b58
69 changed files with 844 additions and 513 deletions

View File

@ -18,6 +18,8 @@
package org.apache.dubbo.rpc.cluster.support.wrapper;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.url.component.ServiceConfigURL;
import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.rpc.Exporter;
@ -38,12 +40,14 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY;
import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
import static org.apache.dubbo.rpc.Constants.LOCAL_PROTOCOL;
import static org.apache.dubbo.rpc.Constants.SCOPE_KEY;
import static org.apache.dubbo.rpc.Constants.SCOPE_REMOTE;
import static org.apache.dubbo.rpc.Constants.SCOPE_LOCAL;
import static org.apache.dubbo.rpc.cluster.Constants.PEER_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.BROADCAST_CLUSTER;
/**
* ScopeClusterInvoker is a cluster invoker which handles the invocation logic of a single service in a specific scope.
@ -53,6 +57,10 @@ import static org.apache.dubbo.rpc.cluster.Constants.PEER_KEY;
* @param <T> the type of service interface
*/
public class ScopeClusterInvoker<T> implements ClusterInvoker<T>, ExporterChangeListener {
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(ScopeClusterInvoker.class);
private final Object createLock = new Object();
private Protocol protocolSPI;
private final Directory<T> directory;
@ -119,14 +127,30 @@ public class ScopeClusterInvoker<T> implements ClusterInvoker<T>, ExporterChange
*/
@Override
public Result invoke(Invocation invocation) throws RpcException {
// When broadcasting, it should be called remotely.
if (BROADCAST_CLUSTER.equalsIgnoreCase(getUrl().getParameter(CLUSTER_KEY))) {
if (logger.isDebugEnabled()) {
logger.debug("Performing broadcast call for method: " + invocation.getMethodName() + " of service: " + getUrl().getServiceKey());
}
return invoker.invoke(invocation);
}
if (peerFlag) {
if (logger.isDebugEnabled()) {
logger.debug("Performing point-to-point call for method: " + invocation.getMethodName() + " of service: " + getUrl().getServiceKey());
}
// If it's a point-to-point direct connection, invoke the original Invoker
return invoker.invoke(invocation);
}
if (isInjvmExported()) {
if (logger.isDebugEnabled()) {
logger.debug("Performing local JVM call for method: " + invocation.getMethodName() + " of service: " + getUrl().getServiceKey());
}
// If it's exported to the local JVM, invoke the corresponding Invoker
return injvmInvoker.invoke(invocation);
}
if (logger.isDebugEnabled()) {
logger.debug("Performing remote call for method: " + invocation.getMethodName() + " of service: " + getUrl().getServiceKey());
}
// Otherwise, delegate the invocation to the original Invoker
return invoker.invoke(invocation);
}

View File

@ -80,7 +80,7 @@ class MetricsClusterFilterTest {
collector = applicationModel.getBeanFactory().getOrRegisterBean(DefaultMetricsCollector.class);
if(!initApplication.get()) {
collector.collectApplication(applicationModel);
collector.collectApplication();
initApplication.set(true);
}
filter.setApplicationModel(applicationModel);

View File

@ -320,6 +320,24 @@ class ScopeClusterInvokerTest {
Assertions.assertEquals("doSomething8", ret3.getValue());
}
@Test
void testBroadcast() {
URL url = URL.valueOf("remote://1.2.3.4/" + DemoService.class.getName());
url = url.addParameter(REFER_KEY,
URL.encode(PATH_KEY + "=" + DemoService.class.getName()));
url = url.addParameter("cluster","broadcast");
url = url.setScopeModel(ApplicationModel.defaultModel().getDefaultModule());
Invoker<DemoService> cluster = getClusterInvoker(url);
invokers.add(cluster);
RpcInvocation invocation = new RpcInvocation();
invocation.setMethodName("doSomething8");
invocation.setParameterTypes(new Class[]{});
Result ret = cluster.invoke(invocation);
Assertions.assertEquals("doSomething8", ret.getValue());
}
private Invoker<DemoService> getClusterInvoker(URL url) {
final URL durl = url.addParameter("proxy", "jdk");
invokers.clear();

View File

@ -239,6 +239,10 @@ public interface CommonConstants {
String REMOTE_METADATA_STORAGE_TYPE = "remote";
String INTERFACE_REGISTER_MODE = "interface";
String DEFAULT_REGISTER_MODE = "all";
String GENERIC_KEY = "generic";
/**

View File

@ -28,6 +28,8 @@ public interface MetricsConstants {
String TAG_APPLICATION_NAME = "application.name";
String TAG_APPLICATION_MODULE = "application.module.id";
String TAG_INTERFACE_KEY = "interface";
String TAG_METHOD_KEY = "method";

View File

@ -22,6 +22,7 @@ import org.apache.dubbo.common.url.component.param.DynamicParamTable;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.StringUtils;
import java.util.AbstractMap;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
@ -247,7 +248,7 @@ public class URLParam {
* copy-on-write mode, urlParam reference will be changed after modify actions.
* If wishes to get the result after modify, please use {@link URLParamMap#getUrlParam()}
*/
public static class URLParamMap implements Map<String, String> {
public static class URLParamMap extends AbstractMap<String, String> {
private URLParam urlParam;
public URLParamMap(URLParam urlParam) {

View File

@ -418,7 +418,7 @@ public interface AnnotationUtils {
static boolean isAnnotationPresent(AnnotatedElement annotatedElement, String annotationClassName) {
ClassLoader classLoader = annotatedElement.getClass().getClassLoader();
Class<?> resolvedType = resolveClass(annotationClassName, classLoader);
if (!Annotation.class.isAssignableFrom(resolvedType)) {
if (resolvedType == null || !Annotation.class.isAssignableFrom(resolvedType)) {
return false;
}
return isAnnotationPresent(annotatedElement, (Class<? extends Annotation>) resolvedType);

View File

@ -147,4 +147,9 @@ public class ReflectionUtils {
}
}
public static boolean match(Class<?> clazz, Class<?> interfaceClass, Object event) {
List<Class<?>> eventTypes = ReflectionUtils.getClassGenerics(clazz, interfaceClass);
return eventTypes.stream().allMatch(eventType -> eventType.isInstance(event));
}
}

View File

@ -23,7 +23,9 @@ import org.apache.dubbo.rpc.model.ModuleModel;
import org.apache.dubbo.rpc.model.ScopeModel;
import java.beans.Transient;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
/**
* AbstractMethodConfig
@ -240,7 +242,8 @@ public abstract class AbstractMethodConfig extends AbstractConfig {
}
public Map<String, String> getParameters() {
return parameters;
this.parameters = Optional.ofNullable(this.parameters).orElseGet(HashMap::new);
return this.parameters;
}
public void setParameters(Map<String, String> parameters) {

View File

@ -19,8 +19,8 @@ package org.apache.dubbo.config;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.UrlUtils;
import org.apache.dubbo.config.nested.AggregationConfig;
import org.apache.dubbo.config.nested.PrometheusConfig;
import org.apache.dubbo.config.nested.HistogramConfig;
import org.apache.dubbo.config.nested.PrometheusConfig;
import org.apache.dubbo.config.support.Nested;
import org.apache.dubbo.rpc.model.ApplicationModel;
@ -56,6 +56,11 @@ public class MetricsConfig extends AbstractConfig {
*/
private Boolean enableMetadata;
/**
* Export metrics service.
*/
private Boolean exportMetricsService;
/**
* @deprecated After metrics config is refactored.
* This parameter should no longer use and will be deleted in the future.
@ -186,6 +191,14 @@ public class MetricsConfig extends AbstractConfig {
this.enableMetadata = enableMetadata;
}
public Boolean getExportMetricsService() {
return exportMetricsService;
}
public void setExportMetricsService(Boolean exportMetricsService) {
this.exportMetricsService = exportMetricsService;
}
public Boolean getEnableThreadpool() {
return enableThreadpool;
}

View File

@ -220,6 +220,7 @@ class URLParamTest {
Assertions.assertFalse(urlParam1.getParameters().containsKey("aaa"));
Assertions.assertFalse(urlParam1.getParameters().containsKey("version"));
Assertions.assertFalse(urlParam1.getParameters().containsKey(new Object()));
Assertions.assertEquals(new HashMap<>(urlParam1.getParameters()).toString(), urlParam1.getParameters().toString());
URLParam urlParam2 = URLParam.parse("aaa=aaa&version=1.0");
URLParam.URLParamMap urlParam2Map = (URLParam.URLParamMap) urlParam2.getParameters();
@ -284,6 +285,10 @@ class URLParamTest {
set.add(urlParam4.getParameters());
Assertions.assertEquals(2,set.size());
URLParam urlParam5 = URLParam.parse("version=1.0");
Assertions.assertEquals(new HashMap<>(urlParam5.getParameters()).toString(), urlParam5.getParameters().toString());
}
@Test

View File

@ -17,6 +17,8 @@
package com.alibaba.dubbo.rpc;
import org.apache.dubbo.rpc.AsyncRpcResult;
@Deprecated
public interface Filter extends org.apache.dubbo.rpc.Filter {
@ -26,8 +28,18 @@ public interface Filter extends org.apache.dubbo.rpc.Filter {
default org.apache.dubbo.rpc.Result invoke(org.apache.dubbo.rpc.Invoker<?> invoker,
org.apache.dubbo.rpc.Invocation invocation)
throws org.apache.dubbo.rpc.RpcException {
Result.CompatibleResult result = (Result.CompatibleResult) invoke(new Invoker.CompatibleInvoker<>(invoker),
new Invocation.CompatibleInvocation(invocation));
return result.getDelegate();
Result invokeResult = invoke(new Invoker.CompatibleInvoker<>(invoker),
new Invocation.CompatibleInvocation(invocation));
if (invokeResult instanceof Result.CompatibleResult) {
return invokeResult;
}
AsyncRpcResult asyncRpcResult = AsyncRpcResult.newDefaultAsyncResult(invocation);
asyncRpcResult.setValue(invokeResult.getValue());
asyncRpcResult.setException(invokeResult.getException());
asyncRpcResult.setObjectAttachments(invokeResult.getObjectAttachments());
return asyncRpcResult;
}
}

View File

@ -17,6 +17,8 @@
package com.alibaba.dubbo.rpc;
import org.apache.dubbo.rpc.AsyncRpcResult;
import com.alibaba.dubbo.common.URL;
@Deprecated
@ -54,9 +56,22 @@ public interface Invoker<T> extends org.apache.dubbo.rpc.Invoker<T> {
public org.apache.dubbo.rpc.Result invoke(org.apache.dubbo.rpc.Invocation invocation) throws org.apache.dubbo.rpc.RpcException {
return new Result.CompatibleResult(invoker.invoke(invocation));
}
@Override
public Result invoke(Invocation invocation) throws RpcException {
if (invoker instanceof Invoker) {
Result result = ((Invoker) invoker).invoke(invocation);
if (result instanceof Result.CompatibleResult) {
return result;
} else {
AsyncRpcResult asyncRpcResult = AsyncRpcResult.newDefaultAsyncResult(invocation.getOriginal());
asyncRpcResult.setValue(result.getValue());
asyncRpcResult.setException(result.getException());
asyncRpcResult.setObjectAttachments(result.getObjectAttachments());
return new Result.CompatibleResult(asyncRpcResult);
}
}
return new Result.CompatibleResult(invoker.invoke(invocation.getOriginal()));
}

View File

@ -64,35 +64,7 @@ public interface Result extends org.apache.dubbo.rpc.Result {
return null;
}
abstract class AbstractResult implements Result {
@Override
public void setValue(Object value) {
}
@Override
public org.apache.dubbo.rpc.Result whenCompleteWithContext(BiConsumer<org.apache.dubbo.rpc.Result, Throwable> fn) {
return null;
}
@Override
public <U> CompletableFuture<U> thenApply(Function<org.apache.dubbo.rpc.Result, ? extends U> fn) {
return null;
}
@Override
public org.apache.dubbo.rpc.Result get() throws InterruptedException, ExecutionException {
return null;
}
@Override
public org.apache.dubbo.rpc.Result get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return null;
}
}
class CompatibleResult extends AbstractResult {
class CompatibleResult implements Result {
private org.apache.dubbo.rpc.Result delegate;
public CompatibleResult(org.apache.dubbo.rpc.Result result) {
@ -177,5 +149,20 @@ public interface Result extends org.apache.dubbo.rpc.Result {
public void setObjectAttachment(String key, Object value) {
delegate.setObjectAttachment(key, value);
}
@Override
public <U> CompletableFuture<U> thenApply(Function<org.apache.dubbo.rpc.Result, ? extends U> fn) {
return delegate.thenApply(fn);
}
@Override
public org.apache.dubbo.rpc.Result get() throws InterruptedException, ExecutionException {
return delegate.get();
}
@Override
public org.apache.dubbo.rpc.Result get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return delegate.get(timeout, unit);
}
}
}

View File

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.dubbo.rpc;
import org.apache.dubbo.rpc.AppResponse;
@Deprecated
public class RpcResult extends AppResponse implements com.alibaba.dubbo.rpc.Result {
public RpcResult() {
}
public RpcResult(Object result) {
super(result);
}
public RpcResult(Throwable exception) {
super(exception);
}
}

View File

@ -18,11 +18,11 @@
package org.apache.dubbo.filter;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -46,15 +46,23 @@ class FilterTest {
}
@Test
void testDefault() {
void testDefault() throws Throwable {
Invoker<FilterTest> invoker = new LegacyInvoker<FilterTest>(null);
Invocation invocation = new LegacyInvocation("bbb");
Result res = myFilter.invoke(invoker, invocation);
System.out.println(res);
org.apache.dubbo.rpc.Invocation invocation = new RpcInvocation(null, "echo", "DemoService", "DemoService", new Class[]{String.class}, new Object[]{"bbb"});
org.apache.dubbo.rpc.Result res = myFilter.invoke(invoker, invocation);
Assertions.assertEquals("alibaba", res.recreate());
}
@Test
void testRecreate() throws Throwable {
Invoker<FilterTest> invoker = new LegacyInvoker<FilterTest>(null);
org.apache.dubbo.rpc.Invocation invocation = new RpcInvocation(null, "echo", "DemoService", "DemoService", new Class[]{String.class}, new Object[]{"cc"});
org.apache.dubbo.rpc.Result res = myFilter.invoke(invoker, invocation);
Assertions.assertEquals("123test", res.recreate());
}
@AfterAll
public static void tear() {
Assertions.assertEquals(2, MyFilter.count);
Assertions.assertEquals(3, MyFilter.count);
}
}

View File

@ -17,7 +17,6 @@
package org.apache.dubbo.filter;
import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.service.DemoService;
import com.alibaba.dubbo.common.URL;
@ -25,6 +24,7 @@ import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.dubbo.rpc.RpcResult;
public class LegacyInvoker<T> implements Invoker<T> {
@ -58,13 +58,13 @@ public class LegacyInvoker<T> implements Invoker<T> {
}
public Result invoke(Invocation invocation) throws RpcException {
AppResponse result = new AppResponse();
RpcResult result = new RpcResult();
if (!hasException) {
result.setValue("alibaba");
} else {
result.setException(new RuntimeException("mocked exception"));
}
return new Result.CompatibleResult(result);
return result;
}
@Override

View File

@ -22,6 +22,7 @@ import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.dubbo.rpc.RpcResult;
public class MyFilter implements Filter {
@ -36,6 +37,10 @@ public class MyFilter implements Filter {
throw new RpcException(new IllegalArgumentException("arg0 illegal"));
}
if (invocation.getArguments()[0].equals("cc")) {
return new RpcResult("123test");
}
Result tmp = invoker.invoke(invocation);
return tmp;
}

View File

@ -90,7 +90,7 @@ public class DubboShutdownHook extends Thread {
boolean hasModuleBindSpring = false;
// check if any modules are bound to Spring
for (ModuleModel module: applicationModel.getModuleModels()) {
for (ModuleModel module : applicationModel.getModuleModels()) {
if (module.isLifeCycleManagedExternally()) {
hasModuleBindSpring = true;
break;
@ -104,14 +104,14 @@ public class DubboShutdownHook extends Thread {
To avoid shutdown conflicts between Dubbo and Spring,
wait for the modules bound to Spring to be handled by Spring until timeout.
*/
logger.info("Waiting for modules managed by Spring to be shutdown.");
logger.info("Waiting for modules(" + applicationModel.getDesc() + ") managed by Spring to be shutdown.");
while (!applicationModel.isDestroyed() && hasModuleBindSpring
&& (System.currentTimeMillis() - start) < timeout) {
try {
TimeUnit.MILLISECONDS.sleep(10);
hasModuleBindSpring = false;
if (!applicationModel.isDestroyed()) {
for (ModuleModel module: applicationModel.getModuleModels()) {
for (ModuleModel module : applicationModel.getModuleModels()) {
if (module.isLifeCycleManagedExternally()) {
hasModuleBindSpring = true;
break;
@ -123,11 +123,15 @@ public class DubboShutdownHook extends Thread {
Thread.currentThread().interrupt();
}
}
if (!applicationModel.isDestroyed()) {
long usage = System.currentTimeMillis() - start;
logger.info("Dubbo wait for application(" + applicationModel.getDesc() + ") managed by Spring to be shutdown failed, " +
"time usage: " + usage + "ms");
}
}
}
if (!applicationModel.isDestroyed()) {
logger.info("Dubbo shuts down application " +
"after Spring fails to do in time or doesn't do it completely.");
logger.info("Dubbo shutdown hooks execute now. " + applicationModel.getDesc());
applicationModel.destroy();
}
}

View File

@ -38,6 +38,7 @@ import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.threadpool.manager.ExecutorRepository;
import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
import org.apache.dubbo.common.utils.ArrayUtils;
import org.apache.dubbo.common.utils.ClassUtils;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.ApplicationConfig;
@ -373,25 +374,15 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
Optional<MetricsConfig> configOptional = configManager.getMetrics();
// TODO compatible with old usage of metrics, remove protocol check after new metrics is ready for use.
boolean importMetricsPrometheus; // Use package references instead of config checks
try {
Class.forName("io.micrometer.prometheus.PrometheusConfig");
importMetricsPrometheus = true;
} catch (ClassNotFoundException e) {
importMetricsPrometheus = false;
}
if (!importMetricsPrometheus) {
//use old metrics
if (!isSupportPrometheus()) {
return;
}
MetricsConfig metricsConfig = configOptional.orElse(new MetricsConfig(applicationModel));
if (StringUtils.isBlank(metricsConfig.getProtocol())) {
metricsConfig.setProtocol(PROTOCOL_PROMETHEUS);
}
collector.setCollectEnabled(true);
collector.collectApplication(applicationModel);
collector.collectApplication();
collector.setThreadpoolCollectEnabled(Optional.ofNullable(metricsConfig.getEnableThreadpool()).orElse(true));
MetricsReporterFactory metricsReporterFactory = getExtensionLoader(MetricsReporterFactory.class).getAdaptiveExtension();
MetricsReporter metricsReporter = metricsReporterFactory.createMetricsReporter(metricsConfig.toUrl());
@ -399,6 +390,18 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
applicationModel.getBeanFactory().registerBean(metricsReporter);
}
public static boolean isSupportPrometheus() {
return isClassPresent("io.micrometer.prometheus.PrometheusConfig")
&& isClassPresent("io.prometheus.client.exporter.BasicAuthHttpConnectionFactory")
&& isClassPresent("io.prometheus.client.exporter.HttpConnectionFactory")
&& isClassPresent("io.prometheus.client.exporter.PushGateway");
}
private static boolean isClassPresent(String className) {
return ClassUtils.isPresent(className, DefaultApplicationDeployer.class.getClassLoader());
}
private boolean isUsedRegistryAsConfigCenter(RegistryConfig registryConfig) {
return isUsedRegistryAsCenter(registryConfig, registryConfig::getUseAsConfigCenter, "config",
@ -748,11 +751,15 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
}
private void exportMetricsService() {
try {
metricsServiceExporter.export();
} catch (Exception e) {
logger.error(LoggerCodeConstants.COMMON_METRICS_COLLECTOR_EXCEPTION, "", "",
"exportMetricsService an exception occurred when handle starting event", e);
boolean exportMetrics = applicationModel.getApplicationConfigManager().getMetrics()
.map(MetricsConfig::getExportMetricsService).orElse(true);
if (exportMetrics) {
try {
metricsServiceExporter.export();
} catch (Exception e) {
logger.error(LoggerCodeConstants.COMMON_METRICS_COLLECTOR_EXCEPTION, "", "",
"exportMetricsService an exception occurred when handle starting event", e);
}
}
}

View File

@ -316,7 +316,7 @@ public class DefaultModuleDeployer extends AbstractDeployer<ModuleModel> impleme
try {
setFailed(ex);
logger.error(CONFIG_FAILED_START_MODEL, "", "", "Model start failed: " + msg, ex);
applicationDeployer.notifyModuleChanged(moduleModel, DeployState.STARTED);
applicationDeployer.notifyModuleChanged(moduleModel, DeployState.FAILED);
} finally {
completeStartFuture(false);
}

View File

@ -23,6 +23,8 @@ import org.apache.dubbo.registry.client.metadata.MetadataServiceDelegation;
import org.apache.dubbo.rpc.model.ApplicationModel;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_REGISTER_MODE;
import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_REGISTER_MODE;
import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
public class ExporterDeployListener implements ApplicationDeployListener, Prioritized {
@ -56,6 +58,13 @@ public class ExporterDeployListener implements ApplicationDeployListener, Priori
return type;
}
private String getRegisterMode(ApplicationModel applicationModel) {
String type = applicationModel.getApplicationConfigManager().getApplicationOrElseThrow().getRegisterMode();
if (StringUtils.isEmpty(type)) {
type = DEFAULT_REGISTER_MODE;
}
return type;
}
public ConfigurableMetadataServiceExporter getMetadataServiceExporter() {
return metadataServiceExporter;
@ -72,7 +81,7 @@ public class ExporterDeployListener implements ApplicationDeployListener, Priori
if (metadataServiceExporter == null) {
metadataServiceExporter = new ConfigurableMetadataServiceExporter(applicationModel, metadataService);
// fixme, let's disable local metadata service export at this moment
if (!REMOTE_METADATA_STORAGE_TYPE.equals(getMetadataType(applicationModel))) {
if (!REMOTE_METADATA_STORAGE_TYPE.equals(getMetadataType(applicationModel)) && !INTERFACE_REGISTER_MODE.equals(getRegisterMode(applicationModel))) {
metadataServiceExporter.export();
}
}

View File

@ -0,0 +1,33 @@
/*
* 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.dubbo.config.deploy;
import org.apache.dubbo.common.utils.Assert;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class DefaultApplicationDeployerTest {
@Test
void isSupportPrometheus() {
boolean supportPrometheus = new DefaultApplicationDeployer(ApplicationModel.defaultModel()).isSupportPrometheus();
Assert.assertTrue(supportPrometheus,"DefaultApplicationDeployer.isSupportPrometheus() should return true");
}
}

View File

@ -27,7 +27,7 @@ import org.springframework.util.Assert;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@ -154,7 +154,7 @@ public class DubboAnnotationUtils {
*/
public static Map<String, String> convertParameters(String[] parameters) {
if (ArrayUtils.isEmpty(parameters)) {
return Collections.emptyMap();
return new HashMap<>();
}
List<String> compatibleParameterArray = Arrays.stream(parameters)

View File

@ -1087,6 +1087,12 @@
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="export-metrics-service" type="xsd:boolean" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[ Enable export metrics service. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="port" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[ Deprecated. No longer use. ]]></xsd:documentation>

View File

@ -89,7 +89,7 @@ public class KubernetesConfigUtils {
.withLoggingInterval(url.getParameter(LOGGING_INTERVAL, base.getLoggingInterval())) //
.withTrustCerts(url.getParameter(TRUST_CERTS, base.isTrustCerts())) //
.withHttp2Disable(url.getParameter(HTTP2_DISABLE, base.isTrustCerts())) //
.withHttp2Disable(url.getParameter(HTTP2_DISABLE, base.isHttp2Disable())) //
.withHttpProxy(url.getParameter(HTTP_PROXY, base.getHttpProxy())) //
.withHttpsProxy(url.getParameter(HTTPS_PROXY, base.getHttpsProxy())) //

View File

@ -28,9 +28,9 @@ import org.apache.dubbo.metrics.model.key.MetricsKey;
*/
public interface ApplicationMetricsCollector<E extends TimeCounterEvent> extends MetricsCollector<E> {
void increment(String applicationName, MetricsKey metricsKey);
void increment(MetricsKey metricsKey);
void addRt(String applicationName, String registryOpType, Long responseTime);
void addRt(String registryOpType, Long responseTime);
}

View File

@ -46,36 +46,36 @@ public abstract class CombMetricsCollector<E extends TimeCounterEvent> extends A
}
@Override
public void setNum(MetricsKeyWrapper metricsKey, String applicationName, String serviceKey, int num) {
this.stats.setServiceKey(metricsKey, applicationName, serviceKey, num);
public void setNum(MetricsKeyWrapper metricsKey, String serviceKey, int num) {
this.stats.setServiceKey(metricsKey, serviceKey, num);
}
@Override
public void increment(String applicationName, MetricsKey metricsKey) {
this.stats.incrementApp(metricsKey, applicationName, SELF_INCREMENT_SIZE);
public void increment(MetricsKey metricsKey) {
this.stats.incrementApp(metricsKey, SELF_INCREMENT_SIZE);
}
public void increment(String applicationName, String serviceKey, MetricsKeyWrapper metricsKeyWrapper, int size) {
this.stats.incrementServiceKey(metricsKeyWrapper, applicationName, serviceKey, size);
public void increment(String serviceKey, MetricsKeyWrapper metricsKeyWrapper, int size) {
this.stats.incrementServiceKey(metricsKeyWrapper, serviceKey, size);
}
@Override
public void addRt(String applicationName, String registryOpType, Long responseTime) {
stats.calcApplicationRt(applicationName, registryOpType, responseTime);
public void addRt(String registryOpType, Long responseTime) {
stats.calcApplicationRt(registryOpType, responseTime);
}
public void addRt(String applicationName, String serviceKey, String registryOpType, Long responseTime) {
stats.calcServiceKeyRt(applicationName, serviceKey, registryOpType, responseTime);
public void addRt(String serviceKey, String registryOpType, Long responseTime) {
stats.calcServiceKeyRt(serviceKey, registryOpType, responseTime);
}
@Override
public void increment(String applicationName, Invocation invocation, MetricsKeyWrapper wrapper, int size) {
this.stats.incrementMethodKey(wrapper, applicationName, invocation, size);
public void increment(Invocation invocation, MetricsKeyWrapper wrapper, int size) {
this.stats.incrementMethodKey(wrapper, invocation, size);
}
@Override
public void addRt(String applicationName, Invocation invocation, String registryOpType, Long responseTime) {
stats.calcMethodKeyRt(applicationName, invocation, registryOpType, responseTime);
public void addRt(Invocation invocation, String registryOpType, Long responseTime) {
stats.calcMethodKeyRt(invocation, registryOpType, responseTime);
}
protected List<MetricSample> export(MetricsCategory category) {

View File

@ -26,8 +26,8 @@ import org.apache.dubbo.rpc.Invocation;
*/
public interface MethodMetricsCollector<E extends TimeCounterEvent> extends MetricsCollector<E> {
void increment(String applicationName, Invocation invocation, MetricsKeyWrapper wrapper, int size);
void increment(Invocation invocation, MetricsKeyWrapper wrapper, int size);
void addRt(String applicationName, Invocation invocation, String registryOpType, Long responseTime);
void addRt(Invocation invocation, String registryOpType, Long responseTime);
}

View File

@ -26,10 +26,10 @@ import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
*/
public interface ServiceMetricsCollector<E extends TimeCounterEvent> extends MetricsCollector<E> {
void increment(String applicationName, String serviceKey, MetricsKeyWrapper wrapper, int size);
void increment(String serviceKey, MetricsKeyWrapper wrapper, int size);
void setNum(MetricsKeyWrapper metricsKey, String applicationName, String serviceKey, int num);
void setNum(MetricsKeyWrapper metricsKey, String serviceKey, int num);
void addRt(String applicationName, String serviceKey, String registryOpType, Long responseTime);
void addRt(String serviceKey, String registryOpType, Long responseTime);
}

View File

@ -23,7 +23,8 @@ import org.apache.dubbo.metrics.model.MetricsSupport;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import org.apache.dubbo.metrics.report.MetricsExport;
import org.apache.dubbo.metrics.report.AbstractMetricsExport;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.ArrayList;
import java.util.List;
@ -31,42 +32,49 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
public class ApplicationStatComposite implements MetricsExport {
/**
* Application-level data container, for the initialized MetricsKey,
* different from the null value of the Map type (the key is not displayed when there is no data),
* the key is displayed and the initial data is 0 value of the AtomicLong type
*/
public class ApplicationStatComposite extends AbstractMetricsExport {
private final Map<MetricsKey, Map<String, AtomicLong>> applicationNumStats = new ConcurrentHashMap<>();
public ApplicationStatComposite(ApplicationModel applicationModel) {
super(applicationModel);
}
private final Map<MetricsKey, AtomicLong> applicationNumStats = new ConcurrentHashMap<>();
public void init(List<MetricsKey> appKeys) {
if (CollectionUtils.isEmpty(appKeys)) {
return;
}
appKeys.forEach(appKey -> applicationNumStats.put(appKey, new ConcurrentHashMap<>()));
appKeys.forEach(appKey -> applicationNumStats.put(appKey, new AtomicLong(0L)));
}
public void incrementSize(MetricsKey metricsKey, String applicationName, int size) {
public void incrementSize(MetricsKey metricsKey, int size) {
if (!applicationNumStats.containsKey(metricsKey)) {
return;
}
applicationNumStats.get(metricsKey).computeIfAbsent(applicationName, k -> new AtomicLong(0L)).getAndAdd(size);
applicationNumStats.get(metricsKey).getAndAdd(size);
}
public List<MetricSample> export(MetricsCategory category) {
List<MetricSample> list = new ArrayList<>();
for (MetricsKey type : applicationNumStats.keySet()) {
Map<String, AtomicLong> stringAtomicLongMap = applicationNumStats.get(type);
for (String applicationName : stringAtomicLongMap.keySet()) {
list.add(convertToSample(applicationName, type, category, stringAtomicLongMap.get(applicationName)));
}
list.add(convertToSample(type, category, applicationNumStats.get(type)));
}
return list;
}
@SuppressWarnings({"rawtypes"})
private GaugeMetricSample convertToSample(String applicationName, MetricsKey type, MetricsCategory category, AtomicLong targetNumber) {
return new GaugeMetricSample<>(type, MetricsSupport.applicationTags(applicationName), category, targetNumber, AtomicLong::get);
private GaugeMetricSample convertToSample(MetricsKey type, MetricsCategory category, AtomicLong targetNumber) {
return new GaugeMetricSample<>(type, MetricsSupport.applicationTags(getApplicationModel()), category, targetNumber, AtomicLong::get);
}
public Map<MetricsKey, Map<String, AtomicLong>> getApplicationNumStats() {
public Map<MetricsKey, AtomicLong> getApplicationNumStats() {
return applicationNumStats;
}

View File

@ -24,6 +24,7 @@ import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import org.apache.dubbo.metrics.report.MetricsExport;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.ArrayList;
import java.util.List;
@ -36,60 +37,63 @@ import java.util.List;
*/
public abstract class BaseStatComposite implements MetricsExport {
private final ApplicationStatComposite applicationStatComposite = new ApplicationStatComposite();
private final ServiceStatComposite serviceStatComposite = new ServiceStatComposite();
private ApplicationStatComposite applicationStatComposite;
private ServiceStatComposite serviceStatComposite;
private final MethodStatComposite methodStatComposite = new MethodStatComposite();
private final RtStatComposite rtStatComposite = new RtStatComposite();
private MethodStatComposite methodStatComposite;
private RtStatComposite rtStatComposite;
public BaseStatComposite() {
init(applicationStatComposite);
init(serviceStatComposite);
init(methodStatComposite);
init(rtStatComposite);
public BaseStatComposite(ApplicationModel applicationModel) {
init(new ApplicationStatComposite(applicationModel));
init(new ServiceStatComposite(applicationModel));
init(new MethodStatComposite(applicationModel));
init(new RtStatComposite(applicationModel));
}
protected void init(ApplicationStatComposite applicationStatComposite) {
this.applicationStatComposite = applicationStatComposite;
}
protected void init(ServiceStatComposite serviceStatComposite) {
this.serviceStatComposite = serviceStatComposite;
}
protected void init(MethodStatComposite methodStatComposite) {
this.methodStatComposite = methodStatComposite;
}
protected void init(RtStatComposite rtStatComposite) {
this.rtStatComposite = rtStatComposite;
}
public void calcApplicationRt(String applicationName, String registryOpType, Long responseTime) {
rtStatComposite.calcApplicationRt(applicationName, registryOpType, responseTime);
public void calcApplicationRt(String registryOpType, Long responseTime) {
rtStatComposite.calcApplicationRt(registryOpType, responseTime);
}
public void calcServiceKeyRt(String applicationName, String serviceKey, String registryOpType, Long responseTime) {
rtStatComposite.calcServiceKeyRt(applicationName, serviceKey, registryOpType, responseTime);
public void calcServiceKeyRt(String serviceKey, String registryOpType, Long responseTime) {
rtStatComposite.calcServiceKeyRt(serviceKey, registryOpType, responseTime);
}
public void calcMethodKeyRt(String applicationName, Invocation invocation, String registryOpType, Long responseTime) {
rtStatComposite.calcMethodKeyRt(applicationName, invocation, registryOpType, responseTime);
public void calcMethodKeyRt(Invocation invocation, String registryOpType, Long responseTime) {
rtStatComposite.calcMethodKeyRt(invocation, registryOpType, responseTime);
}
public void setServiceKey(MetricsKeyWrapper metricsKey, String applicationName, String serviceKey, int num) {
serviceStatComposite.setServiceKey(metricsKey, applicationName, serviceKey, num);
public void setServiceKey(MetricsKeyWrapper metricsKey, String serviceKey, int num) {
serviceStatComposite.setServiceKey(metricsKey, serviceKey, num);
}
public void incrementApp(MetricsKey metricsKey, String applicationName, int size) {
applicationStatComposite.incrementSize(metricsKey, applicationName, size);
public void incrementApp(MetricsKey metricsKey, int size) {
applicationStatComposite.incrementSize(metricsKey, size);
}
public void incrementServiceKey(MetricsKeyWrapper metricsKeyWrapper, String applicationName, String attServiceKey, int size) {
serviceStatComposite.incrementServiceKey(metricsKeyWrapper, applicationName, attServiceKey, size);
public void incrementServiceKey(MetricsKeyWrapper metricsKeyWrapper, String attServiceKey, int size) {
serviceStatComposite.incrementServiceKey(metricsKeyWrapper, attServiceKey, size);
}
public void incrementMethodKey(MetricsKeyWrapper metricsKeyWrapper, String applicationName, Invocation invocation, int size) {
methodStatComposite.incrementMethodKey(metricsKeyWrapper, applicationName, invocation, size);
public void incrementMethodKey(MetricsKeyWrapper metricsKeyWrapper, Invocation invocation, int size) {
methodStatComposite.incrementMethodKey(metricsKeyWrapper, invocation, size);
}
@Override

View File

@ -24,8 +24,9 @@ import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
import org.apache.dubbo.metrics.model.sample.CounterMetricSample;
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import org.apache.dubbo.metrics.report.MetricsExport;
import org.apache.dubbo.metrics.report.AbstractMetricsExport;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.ArrayList;
import java.util.List;
@ -33,8 +34,16 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
public class MethodStatComposite implements MetricsExport {
/**
* Method-level data container,
* if there is no actual call to the existing call method,
* the key will not be displayed when exporting (to be optimized)
*/
public class MethodStatComposite extends AbstractMetricsExport {
public MethodStatComposite(ApplicationModel applicationModel) {
super(applicationModel);
}
private final Map<MetricsKeyWrapper, Map<MethodMetric, AtomicLong>> methodNumStats = new ConcurrentHashMap<>();
public void initWrapper(List<MetricsKeyWrapper> metricsKeyWrappers) {
@ -44,11 +53,11 @@ public class MethodStatComposite implements MetricsExport {
metricsKeyWrappers.forEach(appKey -> methodNumStats.put(appKey, new ConcurrentHashMap<>()));
}
public void incrementMethodKey(MetricsKeyWrapper wrapper, String applicationName, Invocation invocation, int size) {
public void incrementMethodKey(MetricsKeyWrapper wrapper, Invocation invocation, int size) {
if (!methodNumStats.containsKey(wrapper)) {
return;
}
methodNumStats.get(wrapper).computeIfAbsent(new MethodMetric(applicationName, invocation), k -> new AtomicLong(0L)).getAndAdd(size);
methodNumStats.get(wrapper).computeIfAbsent(new MethodMetric(getApplicationModel(), invocation), k -> new AtomicLong(0L)).getAndAdd(size);
}
public List<MetricSample> export(MetricsCategory category) {

View File

@ -19,16 +19,17 @@ package org.apache.dubbo.metrics.data;
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
import org.apache.dubbo.metrics.model.MetricsCategory;
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
import org.apache.dubbo.metrics.model.container.AtomicLongContainer;
import org.apache.dubbo.metrics.model.container.LongAccumulatorContainer;
import org.apache.dubbo.metrics.model.container.LongContainer;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import org.apache.dubbo.metrics.report.MetricsExport;
import org.apache.dubbo.metrics.report.AbstractMetricsExport;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.ArrayList;
import java.util.Arrays;
@ -38,8 +39,17 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAccumulator;
import java.util.stream.Collectors;
/**
* The data container of the rt dimension, including application, service, and method levels,
* if there is no actual call to the existing call method,
* the key will not be displayed when exporting (to be optimized)
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public class RtStatComposite implements MetricsExport {
public class RtStatComposite extends AbstractMetricsExport {
public RtStatComposite(ApplicationModel applicationModel) {
super(applicationModel);
}
private final List<LongContainer<? extends Number>> rtStats = new ArrayList<>();
@ -68,23 +78,23 @@ public class RtStatComposite implements MetricsExport {
return singleRtStats;
}
public void calcApplicationRt(String applicationName, String registryOpType, Long responseTime) {
public void calcApplicationRt(String registryOpType, Long responseTime) {
for (LongContainer container : rtStats.stream().filter(longContainer -> longContainer.specifyType(registryOpType)).collect(Collectors.toList())) {
Number current = (Number) ConcurrentHashMapUtils.computeIfAbsent(container, applicationName, container.getInitFunc());
Number current = (Number) ConcurrentHashMapUtils.computeIfAbsent(container, getAppName(), container.getInitFunc());
container.getConsumerFunc().accept(responseTime, current);
}
}
public void calcServiceKeyRt(String applicationName, String serviceKey, String registryOpType, Long responseTime) {
public void calcServiceKeyRt(String serviceKey, String registryOpType, Long responseTime) {
for (LongContainer container : rtStats.stream().filter(longContainer -> longContainer.specifyType(registryOpType)).collect(Collectors.toList())) {
Number current = (Number) ConcurrentHashMapUtils.computeIfAbsent(container, applicationName + "_" + serviceKey, container.getInitFunc());
Number current = (Number) ConcurrentHashMapUtils.computeIfAbsent(container, serviceKey, container.getInitFunc());
container.getConsumerFunc().accept(responseTime, current);
}
}
public void calcMethodKeyRt(String applicationName, Invocation invocation, String registryOpType, Long responseTime) {
public void calcMethodKeyRt(Invocation invocation, String registryOpType, Long responseTime) {
for (LongContainer container : rtStats.stream().filter(longContainer -> longContainer.specifyType(registryOpType)).collect(Collectors.toList())) {
Number current = (Number) ConcurrentHashMapUtils.computeIfAbsent(container, applicationName + "_" + invocation.getServiceName() + "_" + invocation.getMethodName(), container.getInitFunc());
Number current = (Number) ConcurrentHashMapUtils.computeIfAbsent(container, invocation.getServiceName() + "_" + invocation.getMethodName(), container.getInitFunc());
container.getConsumerFunc().accept(responseTime, current);
}
}
@ -94,7 +104,7 @@ public class RtStatComposite implements MetricsExport {
for (LongContainer<? extends Number> rtContainer : rtStats) {
MetricsKeyWrapper metricsKeyWrapper = rtContainer.getMetricsKeyWrapper();
for (Map.Entry<String, ? extends Number> entry : rtContainer.entrySet()) {
list.add(new GaugeMetricSample<>(metricsKeyWrapper.targetKey(), metricsKeyWrapper.targetDesc(), metricsKeyWrapper.tagName(entry.getKey()), category, entry.getKey().intern(), value -> rtContainer.getValueSupplier().apply(value.intern())));
list.add(new GaugeMetricSample<>(metricsKeyWrapper.targetKey(), metricsKeyWrapper.targetDesc(), metricsKeyWrapper.tagName(getApplicationModel(), entry.getKey()), category, entry.getKey().intern(), value -> rtContainer.getValueSupplier().apply(value.intern())));
}
}
return list;

View File

@ -23,7 +23,8 @@ import org.apache.dubbo.metrics.model.ServiceKeyMetric;
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import org.apache.dubbo.metrics.report.MetricsExport;
import org.apache.dubbo.metrics.report.AbstractMetricsExport;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.ArrayList;
import java.util.List;
@ -31,7 +32,16 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
public class ServiceStatComposite implements MetricsExport {
/**
* Service-level data container, for the initialized MetricsKey,
* different from the null value of the Map type (the key is not displayed when there is no data),
* the key is displayed and the initial data is 0 value of the AtomicLong type
*/
public class ServiceStatComposite extends AbstractMetricsExport {
public ServiceStatComposite(ApplicationModel applicationModel) {
super(applicationModel);
}
private final Map<MetricsKeyWrapper, Map<ServiceKeyMetric, AtomicLong>> serviceWrapperNumStats = new ConcurrentHashMap<>();
@ -42,18 +52,18 @@ public class ServiceStatComposite implements MetricsExport {
metricsKeyWrappers.forEach(appKey -> serviceWrapperNumStats.put(appKey, new ConcurrentHashMap<>()));
}
public void incrementServiceKey(MetricsKeyWrapper wrapper, String applicationName, String serviceKey, int size) {
public void incrementServiceKey(MetricsKeyWrapper wrapper, String serviceKey, int size) {
if (!serviceWrapperNumStats.containsKey(wrapper)) {
return;
}
serviceWrapperNumStats.get(wrapper).computeIfAbsent(new ServiceKeyMetric(applicationName, serviceKey), k -> new AtomicLong(0L)).getAndAdd(size);
serviceWrapperNumStats.get(wrapper).computeIfAbsent(new ServiceKeyMetric(getApplicationModel(), serviceKey), k -> new AtomicLong(0L)).getAndAdd(size);
}
public void setServiceKey(MetricsKeyWrapper wrapper, String applicationName, String serviceKey, int num) {
public void setServiceKey(MetricsKeyWrapper wrapper, String serviceKey, int num) {
if (!serviceWrapperNumStats.containsKey(wrapper)) {
return;
}
serviceWrapperNumStats.get(wrapper).computeIfAbsent(new ServiceKeyMetric(applicationName, serviceKey), k -> new AtomicLong(0L)).set(num);
serviceWrapperNumStats.get(wrapper).computeIfAbsent(new ServiceKeyMetric(getApplicationModel(), serviceKey), k -> new AtomicLong(0L)).set(num);
}
public List<MetricSample> export(MetricsCategory category) {

View File

@ -20,16 +20,19 @@ package org.apache.dubbo.metrics.listener;
import org.apache.dubbo.common.utils.ReflectionUtils;
import org.apache.dubbo.metrics.event.MetricsEvent;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public abstract class AbstractMetricsListener<E extends MetricsEvent> implements MetricsListener<E> {
private final Map<Class<?>, Boolean> eventMatchCache = new ConcurrentHashMap<>();
/**
* Whether to support the general determination of event points depends on the event type
*/
public boolean isSupport(MetricsEvent event) {
List<Class<?>> eventTypes = ReflectionUtils.getClassGenerics(getClass(), AbstractMetricsListener.class);
return event.isAvailable() && eventTypes.stream().allMatch(clazz -> clazz.isInstance(event));
Boolean eventMatch = eventMatchCache.computeIfAbsent(event.getClass(), clazz -> ReflectionUtils.match(getClass(), AbstractMetricsListener.class, event));
return event.isAvailable() && eventMatch;
}
@Override

View File

@ -21,7 +21,7 @@ import org.apache.dubbo.metrics.collector.CombMetricsCollector;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
public class MetricsApplicationListener extends AbstractMetricsKeyListener {
public class MetricsApplicationListener extends AbstractMetricsKeyListener {
public MetricsApplicationListener(MetricsKey metricsKey) {
super(metricsKey);
@ -29,25 +29,25 @@ public class MetricsApplicationListener extends AbstractMetricsKeyListener {
public static AbstractMetricsKeyListener onPostEventBuild(MetricsKey metricsKey, CombMetricsCollector collector) {
return AbstractMetricsKeyListener.onEvent(metricsKey,
event -> collector.increment(event.appName(), metricsKey)
event -> collector.increment(metricsKey)
);
}
public static AbstractMetricsKeyListener onFinishEventBuild(MetricsKey metricsKey, MetricsPlaceValue placeType, CombMetricsCollector collector) {
return AbstractMetricsKeyListener.onFinish(metricsKey,
event -> {
collector.increment(event.appName(), metricsKey);
collector.addRt(event.appName(), placeType.getType(), event.getTimePair().calc());
}
event -> {
collector.increment(metricsKey);
collector.addRt(placeType.getType(), event.getTimePair().calc());
}
);
}
public static AbstractMetricsKeyListener onErrorEventBuild(MetricsKey metricsKey, MetricsPlaceValue placeType, CombMetricsCollector collector) {
return AbstractMetricsKeyListener.onError(metricsKey,
event -> {
collector.increment(event.appName(), metricsKey);
collector.addRt(event.appName(), placeType.getType(), event.getTimePair().calc());
}
event -> {
collector.increment(metricsKey);
collector.addRt(placeType.getType(), event.getTimePair().calc());
}
);
}
}

View File

@ -19,29 +19,33 @@ package org.apache.dubbo.metrics.model;
import org.apache.dubbo.common.Version;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.HashMap;
import java.util.Map;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_HOSTNAME;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_INTERFACE_KEY;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_IP;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_NAME;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_VERSION_KEY;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_HOSTNAME;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_IP;
import static org.apache.dubbo.common.utils.NetUtils.getLocalHost;
import static org.apache.dubbo.common.utils.NetUtils.getLocalHostName;
public class ApplicationMetric implements Metric {
private final String applicationName;
private final ApplicationModel applicationModel;
private static final String version = Version.getVersion();
private static final String commitId = Version.getLastCommitId();
public ApplicationMetric(String applicationName) {
this.applicationName = applicationName;
public ApplicationMetric(ApplicationModel applicationModel) {
this.applicationModel = applicationModel;
}
public ApplicationModel getApplicationModel() {
return applicationModel;
}
public String getApplicationName() {
return applicationName;
return getApplicationModel().getApplicationName();
}
public String getData() {
@ -50,23 +54,12 @@ public class ApplicationMetric implements Metric {
@Override
public Map<String, String> getTags() {
return getTagsByName(this.getApplicationName());
}
public static Map<String, String> getTagsByName(String applicationName) {
Map<String, String> tags = new HashMap<>();
tags.put(TAG_IP, getLocalHost());
tags.put(TAG_HOSTNAME, getLocalHostName());
tags.put(TAG_APPLICATION_NAME, applicationName);
tags.put(TAG_APPLICATION_NAME, getApplicationName());
tags.put(TAG_APPLICATION_VERSION_KEY, version);
tags.put(MetricsKey.METADATA_GIT_COMMITID_METRIC.getName(), commitId);
return tags;
}
public static Map<String, String> getServiceTags(String appAndServiceName) {
String[] keys = appAndServiceName.split("_");
Map<String, String> tags = getTagsByName(keys[0]);
tags.put(TAG_INTERFACE_KEY, keys[1]);
return tags;
}
}

View File

@ -19,71 +19,38 @@ package org.apache.dubbo.metrics.model;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_CHAR_SEPARATOR;
import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_NAME;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_GROUP_KEY;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_HOSTNAME;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_INTERFACE_KEY;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_IP;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_METHOD_KEY;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_VERSION_KEY;
import static org.apache.dubbo.common.utils.NetUtils.getLocalHost;
import static org.apache.dubbo.common.utils.NetUtils.getLocalHostName;
import static org.apache.dubbo.metrics.MetricsConstants.INVOCATION_METRICS_COUNTER;
import static org.apache.dubbo.rpc.support.RpcUtils.isGenericCall;
/**
* Metric class for method.
*/
public class MethodMetric implements Metric {
private String applicationName;
public class MethodMetric extends ServiceKeyMetric {
private String side;
private String interfaceName;
private String methodName;
private final String methodName;
private String group;
private String version;
private final MetricSample.Type sampleType;
private MetricSample.Type sampleType;
public MethodMetric() {
}
public MethodMetric(String applicationName, Invocation invocation) {
this.applicationName = applicationName;
public MethodMetric(ApplicationModel applicationModel, Invocation invocation) {
super(applicationModel, MetricsSupport.getInterfaceName(invocation));
this.methodName = MetricsSupport.getMethodName(invocation);
this.side = MetricsSupport.getSide(invocation);
this.group = MetricsSupport.getGroup(invocation);
this.version = MetricsSupport.getVersion(invocation);
this.sampleType = (MetricSample.Type) invocation.get(INVOCATION_METRICS_COUNTER);
init(invocation);
}
public MetricSample.Type getSampleType() {
return sampleType;
}
public String getInterfaceName() {
return interfaceName;
}
public void setInterfaceName(String interfaceName) {
this.interfaceName = interfaceName;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public String getGroup() {
return group;
}
@ -101,52 +68,14 @@ public class MethodMetric implements Metric {
}
public Map<String, String> getTags() {
Map<String, String> tags = new HashMap<>();
tags.put(TAG_IP, getLocalHost());
tags.put(TAG_HOSTNAME, getLocalHostName());
tags.put(TAG_APPLICATION_NAME, applicationName);
tags.put(TAG_INTERFACE_KEY, interfaceName);
tags.put(TAG_METHOD_KEY, methodName);
Map<String, String> tags = MetricsSupport.methodTags(getApplicationModel(), getInterfaceName(), methodName);
tags.put(TAG_GROUP_KEY, group);
tags.put(TAG_VERSION_KEY, version);
return tags;
}
private void init(Invocation invocation) {
String serviceUniqueName = invocation.getTargetServiceUniqueName();
String methodName = invocation.getMethodName();
if (invocation instanceof RpcInvocation
&& isGenericCall(((RpcInvocation) invocation).getParameterTypesDesc(), methodName)
&& invocation.getArguments() != null
&& invocation.getArguments().length == 3) {
methodName = ((String) invocation.getArguments()[0]).trim();
}
String group = null;
String interfaceAndVersion;
String[] arr = serviceUniqueName.split(PATH_SEPARATOR);
if (arr.length == 2) {
group = arr[0];
interfaceAndVersion = arr[1];
} else {
interfaceAndVersion = arr[0];
}
String[] ivArr = interfaceAndVersion.split(GROUP_CHAR_SEPARATOR);
String interfaceName = ivArr[0];
String version = ivArr.length == 2 ? ivArr[1] : null;
Optional<? extends Invoker<?>> invoker = Optional.ofNullable(invocation.getInvoker());
this.side = invoker.isPresent() ? invoker.get().getUrl().getSide() : PROVIDER_SIDE;
this.interfaceName = interfaceName;
this.methodName = methodName;
this.group = group;
this.version = version;
}
public String getApplicationName() {
return applicationName;
}
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
public String getMethodName() {
return methodName;
}
public String getSide() {
@ -160,9 +89,9 @@ public class MethodMetric implements Metric {
@Override
public String toString() {
return "MethodMetric{" +
"applicationName='" + applicationName + '\'' +
"applicationName='" + getApplicationName() + '\'' +
", side='" + side + '\'' +
", interfaceName='" + interfaceName + '\'' +
", interfaceName='" + getInterfaceName() + '\'' +
", methodName='" + methodName + '\'' +
", group='" + group + '\'' +
", version='" + version + '\'' +
@ -174,11 +103,11 @@ public class MethodMetric implements Metric {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MethodMetric that = (MethodMetric) o;
return Objects.equals(applicationName, that.applicationName) && Objects.equals(side, that.side) && Objects.equals(interfaceName, that.interfaceName) && Objects.equals(methodName, that.methodName) && Objects.equals(group, that.group) && Objects.equals(version, that.version);
return Objects.equals(getApplicationName(), that.getApplicationName()) && Objects.equals(side, that.side) && Objects.equals(getInterfaceName(), that.getInterfaceName()) && Objects.equals(methodName, that.methodName) && Objects.equals(group, that.group) && Objects.equals(version, that.version);
}
@Override
public int hashCode() {
return Objects.hash(applicationName, side, interfaceName, methodName, group, version);
return Objects.hash(getApplicationName(), side, getInterfaceName(), methodName, group, version);
}
}

View File

@ -29,6 +29,8 @@ import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.HashMap;
import java.util.Map;
@ -37,6 +39,7 @@ import java.util.Optional;
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_CHAR_SEPARATOR;
import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_MODULE;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_NAME;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_VERSION_KEY;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_HOSTNAME;
@ -48,40 +51,42 @@ import static org.apache.dubbo.common.utils.NetUtils.getLocalHostName;
import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SERVICE;
import static org.apache.dubbo.metrics.MetricsConstants.INVOCATION;
import static org.apache.dubbo.metrics.MetricsConstants.SELF_INCREMENT_SIZE;
import static org.apache.dubbo.rpc.support.RpcUtils.isGenericCall;
public class MetricsSupport {
private static final String version = Version.getVersion();
private static final String commitId = Version.getLastCommitId();
public static Map<String, String> applicationTags(String applicationName) {
public static Map<String, String> applicationTags(ApplicationModel applicationModel) {
Map<String, String> tags = new HashMap<>();
tags.put(TAG_IP, getLocalHost());
tags.put(TAG_HOSTNAME, getLocalHostName());
tags.put(TAG_APPLICATION_NAME, applicationName);
tags.put(TAG_APPLICATION_NAME, applicationModel.getApplicationName());
tags.put(TAG_APPLICATION_MODULE, applicationModel.getInternalId());
tags.put(TAG_APPLICATION_VERSION_KEY, version);
tags.put(MetricsKey.METADATA_GIT_COMMITID_METRIC.getName(), commitId);
return tags;
}
public static Map<String, String> serviceTags(String appAndServiceName) {
String[] keys = appAndServiceName.split("_");
if (keys.length != 2) {
throw new MetricsNeverHappenException("Error service name: " + appAndServiceName);
}
Map<String, String> tags = applicationTags(keys[0]);
tags.put(TAG_INTERFACE_KEY, keys[1]);
public static Map<String, String> serviceTags(ApplicationModel applicationModel, String serviceKey) {
Map<String, String> tags = applicationTags(applicationModel);
tags.put(TAG_INTERFACE_KEY, serviceKey);
return tags;
}
public static Map<String, String> methodTags(String names) {
public static Map<String, String> methodTags(ApplicationModel applicationModel, String names) {
String[] keys = names.split("_");
if (keys.length != 3) {
if (keys.length != 2) {
throw new MetricsNeverHappenException("Error names: " + names);
}
Map<String, String> tags = applicationTags(keys[0]);
tags.put(TAG_INTERFACE_KEY, keys[1]);
tags.put(TAG_METHOD_KEY, keys[2]);
return methodTags(applicationModel, keys[0], keys[1]);
}
public static Map<String, String> methodTags(ApplicationModel applicationModel, String serviceKey, String methodName) {
Map<String, String> tags = applicationTags(applicationModel);
tags.put(TAG_INTERFACE_KEY, serviceKey);
tags.put(TAG_METHOD_KEY, methodName);
return tags;
}
@ -150,47 +155,73 @@ public class MetricsSupport {
return ivArr[0];
}
public static String getMethodName(Invocation invocation) {
String methodName = invocation.getMethodName();
if (invocation instanceof RpcInvocation
&& isGenericCall(((RpcInvocation) invocation).getParameterTypesDesc(), methodName)
&& invocation.getArguments() != null
&& invocation.getArguments().length == 3) {
methodName = ((String) invocation.getArguments()[0]).trim();
}
return methodName;
}
public static String getGroup(Invocation invocation) {
String serviceUniqueName = invocation.getTargetServiceUniqueName();
String group = null;
String[] arr = serviceUniqueName.split(PATH_SEPARATOR);
if (arr.length == 2) {
group = arr[0];
}
return group;
}
public static String getVersion(Invocation invocation) {
String interfaceAndVersion;
String[] arr = invocation.getTargetServiceUniqueName().split(PATH_SEPARATOR);
if (arr.length == 2) {
interfaceAndVersion = arr[1];
} else {
interfaceAndVersion = arr[0];
}
String[] ivArr = interfaceAndVersion.split(GROUP_CHAR_SEPARATOR);
return ivArr.length == 2 ? ivArr[1] : null;
}
/**
* Incr service num
*/
public static void increment(MetricsKey metricsKey, MetricsPlaceValue placeType, ServiceMetricsCollector<TimeCounterEvent> collector, MetricsEvent event) {
collector.increment(event.appName(), event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
}
/**
* Dec service num
*/
public static void dec(MetricsKey metricsKey, MetricsPlaceValue placeType, ServiceMetricsCollector<TimeCounterEvent> collector, MetricsEvent event) {
collector.increment(event.appName(), event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), new MetricsKeyWrapper(metricsKey, placeType), -SELF_INCREMENT_SIZE);
collector.increment(event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
}
/**
* Incr service num&&rt
*/
public static void incrAndAddRt(MetricsKey metricsKey, MetricsPlaceValue placeType, ServiceMetricsCollector<TimeCounterEvent> collector, TimeCounterEvent event) {
collector.increment(event.appName(), event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
collector.addRt(event.appName(), event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), placeType.getType(), event.getTimePair().calc());
collector.increment(event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
collector.addRt(event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), placeType.getType(), event.getTimePair().calc());
}
/**
* Incr method num
*/
public static void increment(MetricsKey metricsKey, MetricsPlaceValue placeType, MethodMetricsCollector<TimeCounterEvent> collector, MetricsEvent event) {
collector.increment(event.appName(), event.getAttachmentValue(INVOCATION), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
collector.increment(event.getAttachmentValue(INVOCATION), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
}
/**
* Dec method num
*/
public static void dec(MetricsKey metricsKey, MetricsPlaceValue placeType, MethodMetricsCollector<TimeCounterEvent> collector, MetricsEvent event) {
collector.increment(event.appName(), event.getAttachmentValue(INVOCATION), new MetricsKeyWrapper(metricsKey, placeType), -SELF_INCREMENT_SIZE);
collector.increment(event.getAttachmentValue(INVOCATION), new MetricsKeyWrapper(metricsKey, placeType), -SELF_INCREMENT_SIZE);
}
/**
* Incr method num&&rt
*/
public static void incrAndAddRt(MetricsKey metricsKey, MetricsPlaceValue placeType, MethodMetricsCollector<TimeCounterEvent> collector, TimeCounterEvent event) {
collector.increment(event.appName(), event.getAttachmentValue(INVOCATION), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
collector.addRt(event.appName(), event.getAttachmentValue(INVOCATION), placeType.getType(), event.getTimePair().calc());
collector.increment(event.getAttachmentValue(INVOCATION), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
collector.addRt(event.getAttachmentValue(INVOCATION), placeType.getType(), event.getTimePair().calc());
}
}

View File

@ -17,36 +17,28 @@
package org.apache.dubbo.metrics.model;
import java.util.HashMap;
import java.util.Map;
import org.apache.dubbo.rpc.model.ApplicationModel;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_NAME;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_HOSTNAME;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_INTERFACE_KEY;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_IP;
import static org.apache.dubbo.common.utils.NetUtils.getLocalHost;
import static org.apache.dubbo.common.utils.NetUtils.getLocalHostName;
import java.util.Map;
/**
* Metric class for service.
*/
public class ServiceKeyMetric implements Metric {
private final String applicationName;
private final String serviceKey;
public class ServiceKeyMetric extends ApplicationMetric {
private final String interfaceName;
public ServiceKeyMetric(String applicationName, String serviceKey) {
this.applicationName = applicationName;
this.serviceKey = serviceKey;
public ServiceKeyMetric(ApplicationModel applicationModel, String serviceKey) {
super(applicationModel);
this.interfaceName = serviceKey;
}
@Override
public Map<String, String> getTags() {
Map<String, String> tags = new HashMap<>();
tags.put(TAG_IP, getLocalHost());
tags.put(TAG_HOSTNAME, getLocalHostName());
tags.put(TAG_APPLICATION_NAME, applicationName);
tags.put(TAG_INTERFACE_KEY, serviceKey);
return tags;
return MetricsSupport.serviceTags(getApplicationModel(), interfaceName);
}
public String getInterfaceName() {
return interfaceName;
}
@Override
@ -60,24 +52,24 @@ public class ServiceKeyMetric implements Metric {
ServiceKeyMetric that = (ServiceKeyMetric) o;
if (!applicationName.equals(that.applicationName)) {
if (!getApplicationName().equals(that.getApplicationName())) {
return false;
}
return serviceKey.equals(that.serviceKey);
return interfaceName.equals(that.interfaceName);
}
@Override
public int hashCode() {
int result = applicationName.hashCode();
result = 31 * result + serviceKey.hashCode();
int result = getApplicationName().hashCode();
result = 31 * result + interfaceName.hashCode();
return result;
}
@Override
public String toString() {
return "ServiceKeyMetric{" +
"applicationName='" + applicationName + '\'' +
", serviceKey='" + serviceKey + '\'' +
'}';
"applicationName='" + getApplicationName() + '\'' +
", serviceKey='" + interfaceName + '\'' +
'}';
}
}

View File

@ -55,6 +55,8 @@ public enum MetricsKey {
METRIC_RT_AVG("dubbo.%s.rt.milliseconds.avg", "Average Response Time"),
METRIC_RT_P99("dubbo.%s.rt.milliseconds.p99", "Response Time P99"),
METRIC_RT_P95("dubbo.%s.rt.milliseconds.p95", "Response Time P95"),
METRIC_RT_P90("dubbo.%s.rt.milliseconds.p90", "Response Time P90"),
METRIC_RT_P50("dubbo.%s.rt.milliseconds.p50", "Response Time P50"),
// register metrics key

View File

@ -19,6 +19,7 @@ package org.apache.dubbo.metrics.model.key;
import io.micrometer.common.lang.Nullable;
import org.apache.dubbo.metrics.model.MetricsSupport;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.Map;
import java.util.Objects;
@ -89,17 +90,17 @@ public class MetricsKeyWrapper {
}
}
public Map<String, String> tagName(String key) {
public Map<String, String> tagName(ApplicationModel applicationModel, String key) {
MetricsLevel level = getLevel();
switch (level) {
case APP:
return MetricsSupport.applicationTags(key);
return MetricsSupport.applicationTags(applicationModel);
case SERVICE:
return MetricsSupport.serviceTags(key);
return MetricsSupport.serviceTags(applicationModel, key);
case METHOD:
return MetricsSupport.methodTags(key);
return MetricsSupport.methodTags(applicationModel, key);
}
return MetricsSupport.applicationTags(key);
return MetricsSupport.applicationTags(applicationModel);
}
public static MetricsKeyWrapper wrapper(MetricsKey metricsKey) {

View File

@ -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.dubbo.metrics.report;
import org.apache.dubbo.rpc.model.ApplicationModel;
/**
* Store public information such as application
*/
public abstract class AbstractMetricsExport implements MetricsExport {
private final ApplicationModel applicationModel;
public AbstractMetricsExport(ApplicationModel applicationModel) {
this.applicationModel = applicationModel;
}
public ApplicationModel getApplicationModel() {
return applicationModel;
}
public String getAppName() {
return getApplicationModel().getApplicationName();
}
}

View File

@ -132,7 +132,7 @@ public class AggregateMetricsCollector implements MetricsCollector<RequestEvent>
}
private void onRTEvent(RequestEvent event) {
MethodMetric metric = new MethodMetric(applicationModel.getApplicationName(), event.getAttachmentValue(MetricsConstants.INVOCATION));
MethodMetric metric = new MethodMetric(applicationModel, event.getAttachmentValue(MetricsConstants.INVOCATION));
long responseTime = event.getTimePair().calc();
TimeWindowQuantile quantile = ConcurrentHashMapUtils.computeIfAbsent(rt, metric, k -> new TimeWindowQuantile(DEFAULT_COMPRESSION, bucketNum, timeWindowSeconds));
quantile.add(responseTime);
@ -142,7 +142,7 @@ public class AggregateMetricsCollector implements MetricsCollector<RequestEvent>
private MethodMetric calcWindowCounter(RequestEvent event, MetricsKey targetKey) {
MetricsPlaceValue placeType = MetricsPlaceValue.of(event.getAttachmentValue(MetricsConstants.INVOCATION_SIDE), MetricsLevel.SERVICE);
MetricsKeyWrapper metricsKeyWrapper = new MetricsKeyWrapper(targetKey, placeType);
MethodMetric metric = new MethodMetric(applicationModel.getApplicationName(), event.getAttachmentValue(MetricsConstants.INVOCATION));
MethodMetric metric = new MethodMetric(applicationModel, event.getAttachmentValue(MetricsConstants.INVOCATION));
ConcurrentMap<MethodMetric, TimeWindowCounter> counter = methodTypeCounter.computeIfAbsent(metricsKeyWrapper, k -> new ConcurrentHashMap<>());
@ -198,7 +198,11 @@ public class AggregateMetricsCollector implements MetricsCollector<RequestEvent>
list.add(new GaugeMetricSample<>(MetricsKey.METRIC_RT_P99.getNameByType(k.getSide()),
MetricsKey.METRIC_RT_P99.getDescription(), k.getTags(), RT, v, value -> value.quantile(0.99)));
list.add(new GaugeMetricSample<>(MetricsKey.METRIC_RT_P95.getNameByType(k.getSide()),
MetricsKey.METRIC_RT_P99.getDescription(), k.getTags(), RT, v, value -> value.quantile(0.95)));
MetricsKey.METRIC_RT_P95.getDescription(), k.getTags(), RT, v, value -> value.quantile(0.95)));
list.add(new GaugeMetricSample<>(MetricsKey.METRIC_RT_P90.getNameByType(k.getSide()),
MetricsKey.METRIC_RT_P90.getDescription(), k.getTags(), RT, v, value -> value.quantile(0.90)));
list.add(new GaugeMetricSample<>(MetricsKey.METRIC_RT_P50.getNameByType(k.getSide()),
MetricsKey.METRIC_RT_P50.getDescription(), k.getTags(), RT, v, value -> value.quantile(0.50)));
});
}

View File

@ -56,25 +56,28 @@ public class DefaultMetricsCollector extends CombMetricsCollector<RequestEvent>
private volatile boolean threadpoolCollectEnabled = false;
private final ThreadPoolMetricsSampler threadPoolSampler = new ThreadPoolMetricsSampler(this);
private String applicationName;
private ApplicationModel applicationModel;
private final ApplicationModel applicationModel;
private final List<MetricsSampler> samplers = new ArrayList<>();
public DefaultMetricsCollector() {
super(new BaseStatComposite() {
public DefaultMetricsCollector(ApplicationModel applicationModel) {
super(new BaseStatComposite(applicationModel) {
@Override
protected void init(MethodStatComposite methodStatComposite) {
super.init(methodStatComposite);
methodStatComposite.initWrapper(DefaultConstants.METHOD_LEVEL_KEYS);
}
@Override
protected void init(RtStatComposite rtStatComposite) {
super.init(rtStatComposite);
rtStatComposite.init(MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD),
MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD));
MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD));
}
});
super.setEventMulticaster(new DefaultSubDispatcher(this));
samplers.add(applicationSampler);
samplers.add(threadPoolSampler);
this.applicationModel = applicationModel;
}
public void addSampler(MetricsSampler sampler) {
@ -109,9 +112,8 @@ public class DefaultMetricsCollector extends CombMetricsCollector<RequestEvent>
this.threadpoolCollectEnabled = threadpoolCollectEnabled;
}
public void collectApplication(ApplicationModel applicationModel) {
public void collectApplication() {
this.setApplicationName(applicationModel.getApplicationName());
this.applicationModel = applicationModel;
applicationSampler.inc(applicationName, MetricsEvent.Type.APPLICATION_INFO);
}
@ -144,18 +146,18 @@ public class DefaultMetricsCollector extends CombMetricsCollector<RequestEvent>
public List<MetricSample> sample() {
List<MetricSample> samples = new ArrayList<>();
this.getCount(MetricsEvent.Type.APPLICATION_INFO).filter(e -> !e.isEmpty())
.ifPresent(map -> map.forEach((k, v) ->
samples.add(new CounterMetricSample<>(APPLICATION_METRIC_INFO.getName(),
APPLICATION_METRIC_INFO.getDescription(),
k.getTags(), APPLICATION, v)))
);
.ifPresent(map -> map.forEach((k, v) ->
samples.add(new CounterMetricSample<>(APPLICATION_METRIC_INFO.getName(),
APPLICATION_METRIC_INFO.getDescription(),
k.getTags(), APPLICATION, v)))
);
return samples;
}
@Override
protected void countConfigure(
MetricsCountSampleConfigurer<String, MetricsEvent.Type, ApplicationMetric> sampleConfigure) {
sampleConfigure.configureMetrics(configure -> new ApplicationMetric(sampleConfigure.getSource()));
MetricsCountSampleConfigurer<String, MetricsEvent.Type, ApplicationMetric> sampleConfigure) {
sampleConfigure.configureMetrics(configure -> new ApplicationMetric(applicationModel));
}
};
}

View File

@ -86,7 +86,7 @@ public class HistogramMetricsCollector extends AbstractMetricsListener<RequestEv
private void onRTEvent(RequestEvent event) {
if (metricRegister != null) {
MethodMetric metric = new MethodMetric(applicationModel.getApplicationName(), event.getAttachmentValue(MetricsConstants.INVOCATION));
MethodMetric metric = new MethodMetric(applicationModel, event.getAttachmentValue(MetricsConstants.INVOCATION));
long responseTime = event.getTimePair().calc();
HistogramMetricSample sample = new HistogramMetricSample(MetricsKey.METRIC_RT_HISTOGRAM.getNameByType(metric.getSide()),

View File

@ -20,6 +20,7 @@ package org.apache.dubbo.metrics.collector;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.ReflectionUtils;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.MetricsConfig;
@ -33,6 +34,7 @@ import org.apache.dubbo.metrics.event.MetricsEventBus;
import org.apache.dubbo.metrics.event.RequestBeforeEvent;
import org.apache.dubbo.metrics.event.RequestEvent;
import org.apache.dubbo.metrics.filter.MetricsFilter;
import org.apache.dubbo.metrics.listener.MetricsListener;
import org.apache.dubbo.metrics.model.MethodMetric;
import org.apache.dubbo.metrics.model.MetricsSupport;
import org.apache.dubbo.metrics.model.TimePair;
@ -86,12 +88,9 @@ class AggregateMetricsCollectorTest {
private AggregateMetricsCollector collector;
private MetricsFilter metricsFilter;
public static MethodMetric getTestMethodMetric() {
public MethodMetric getTestMethodMetric() {
MethodMetric methodMetric = new MethodMetric();
methodMetric.setApplicationName("TestApp");
methodMetric.setInterfaceName("TestInterface");
methodMetric.setMethodName("TestMethod");
MethodMetric methodMetric = new MethodMetric(applicationModel, invocation);
methodMetric.setGroup("TestGroup");
methodMetric.setVersion("1.0.0");
methodMetric.setSide("PROVIDER");
@ -118,7 +117,7 @@ class AggregateMetricsCollectorTest {
collector = applicationModel.getBeanFactory().getOrRegisterBean(AggregateMetricsCollector.class);
collector.setCollectEnabled(true);
defaultCollector = new DefaultMetricsCollector();
defaultCollector = new DefaultMetricsCollector(applicationModel);
defaultCollector.setCollectEnabled(true);
metricsFilter = new MetricsFilter();
@ -171,7 +170,6 @@ class AggregateMetricsCollectorTest {
metricsFilter.onResponse(result, new TestMetricsInvoker(side), invocation);
List<MetricSample> samples = collector.collect();
for (MetricSample sample : samples) {
Map<String, String> tags = sample.getTags();
@ -201,7 +199,7 @@ class AggregateMetricsCollectorTest {
when(applicationModel.getApplicationConfigManager()).thenReturn(configManager);
when(applicationModel.getBeanFactory()).thenReturn(beanFactory);
when(beanFactory.getBean(DefaultMetricsCollector.class)).thenReturn(new DefaultMetricsCollector());
when(beanFactory.getBean(DefaultMetricsCollector.class)).thenReturn(new DefaultMetricsCollector(applicationModel));
when(configManager.getMetrics()).thenReturn(Optional.of(metricsConfig));
when(metricsConfig.getAggregation()).thenReturn(aggregationConfig);
when(aggregationConfig.getEnabled()).thenReturn(Boolean.TRUE);
@ -271,16 +269,16 @@ class AggregateMetricsCollectorTest {
List<MetricSample> samples = collector.collect();
GaugeMetricSample<?> p95Sample = samples.stream()
.filter(sample -> sample.getName().endsWith("p95"))
.map(sample -> (GaugeMetricSample<?>) sample)
.findFirst()
.orElse(null);
.filter(sample -> sample.getName().endsWith("p95"))
.map(sample -> (GaugeMetricSample<?>) sample)
.findFirst()
.orElse(null);
GaugeMetricSample<?> p99Sample = samples.stream()
.filter(sample -> sample.getName().endsWith("p99"))
.map(sample -> (GaugeMetricSample<?>) sample)
.findFirst()
.orElse(null);
.filter(sample -> sample.getName().endsWith("p99"))
.map(sample -> (GaugeMetricSample<?>) sample)
.findFirst()
.orElse(null);
Assertions.assertNotNull(p95Sample);
Assertions.assertNotNull(p99Sample);
@ -294,6 +292,13 @@ class AggregateMetricsCollectorTest {
Assertions.assertTrue(Math.abs(1 - p99 / manualP99) < 0.05);
}
@Test
void testGenericCache() {
List<Class<?>> classGenerics = ReflectionUtils.getClassGenerics(AggregateMetricsCollector.class, MetricsListener.class);
Assertions.assertTrue(CollectionUtils.isNotEmpty(classGenerics));
Assertions.assertEquals(RequestEvent.class, classGenerics.get(0));
}
public static class TestRequestEvent extends RequestEvent {
private long rt;

View File

@ -110,7 +110,7 @@ class DefaultCollectorTest {
@Test
void testListener() {
DefaultMetricsCollector metricsCollector = new DefaultMetricsCollector();
DefaultMetricsCollector metricsCollector = new DefaultMetricsCollector(applicationModel);
RequestEvent event = RequestEvent.toRequestEvent(applicationModel, invocation);
RequestBeforeEvent beforeEvent = new RequestBeforeEvent(applicationModel, new TypeWrapper(MetricsLevel.METHOD, MetricsKey.METRIC_REQUESTS));
Assertions.assertTrue(metricsCollector.isSupport(event));

View File

@ -50,7 +50,7 @@ public class ThreadPoolMetricsSamplerTest {
@BeforeEach
void setUp() {
DefaultMetricsCollector collector = new DefaultMetricsCollector();
DefaultMetricsCollector collector = new DefaultMetricsCollector(applicationModel);
sampler = new ThreadPoolMetricsSampler(collector);
}
@ -135,12 +135,12 @@ public class ThreadPoolMetricsSamplerTest {
public void setUp2() {
MockitoAnnotations.openMocks(this);
collector = new DefaultMetricsCollector();
collector = new DefaultMetricsCollector(applicationModel);
sampler2 = new ThreadPoolMetricsSampler(collector);
when(scopeBeanFactory.getBean(FrameworkExecutorRepository.class)).thenReturn(new FrameworkExecutorRepository());
collector.collectApplication(applicationModel);
collector.collectApplication();
when(applicationModel.getBeanFactory()).thenReturn(scopeBeanFactory);
when(applicationModel.getExtensionLoader(DataStore.class)).thenReturn(extensionLoader);
when(extensionLoader.getDefaultExtension()).thenReturn(dataStore);

View File

@ -77,8 +77,6 @@ class MetricsFilterTest {
public void setup() {
ApplicationConfig config = new ApplicationConfig();
config.setName("MockMetrics");
//RpcContext.getContext().setAttachment("MockMetrics","MockMetrics");
applicationModel = ApplicationModel.defaultModel();
applicationModel.getApplicationConfigManager().setApplication(config);
@ -87,7 +85,7 @@ class MetricsFilterTest {
collector = applicationModel.getBeanFactory().getOrRegisterBean(DefaultMetricsCollector.class);
if (!initApplication.get()) {
collector.collectApplication(applicationModel);
collector.collectApplication();
initApplication.set(true);
}
filter.setApplicationModel(applicationModel);

View File

@ -18,9 +18,11 @@
package org.apache.dubbo.metrics.metrics.model;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.metrics.model.MethodMetric;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@ -41,7 +43,7 @@ import static org.apache.dubbo.common.utils.NetUtils.getLocalHostName;
class MethodMetricTest {
private static final String applicationName = null;
private static ApplicationModel applicationModel;
private static String interfaceName;
private static String methodName;
private static String group;
@ -50,6 +52,12 @@ class MethodMetricTest {
@BeforeAll
public static void setup() {
ApplicationConfig config = new ApplicationConfig();
config.setName("MockMetrics");
applicationModel = ApplicationModel.defaultModel();
applicationModel.getApplicationConfigManager().setApplication(config);
interfaceName = "org.apache.dubbo.MockInterface";
methodName = "mockMethod";
group = "mockGroup";
@ -64,7 +72,7 @@ class MethodMetricTest {
@Test
void test() {
MethodMetric metric = new MethodMetric(applicationName, invocation);
MethodMetric metric = new MethodMetric(applicationModel, invocation);
Assertions.assertEquals(metric.getInterfaceName(), interfaceName);
Assertions.assertEquals(metric.getMethodName(), methodName);
Assertions.assertEquals(metric.getGroup(), group);
@ -73,7 +81,7 @@ class MethodMetricTest {
Map<String, String> tags = metric.getTags();
Assertions.assertEquals(tags.get(TAG_IP), getLocalHost());
Assertions.assertEquals(tags.get(TAG_HOSTNAME), getLocalHostName());
Assertions.assertEquals(tags.get(TAG_APPLICATION_NAME), applicationName);
Assertions.assertEquals(tags.get(TAG_APPLICATION_NAME), applicationModel.getApplicationName());
Assertions.assertEquals(tags.get(TAG_INTERFACE_KEY), interfaceName);
Assertions.assertEquals(tags.get(TAG_METHOD_KEY), methodName);

View File

@ -51,19 +51,22 @@ public class MetadataMetricsCollector extends CombMetricsCollector<MetadataEvent
private final ApplicationModel applicationModel;
public MetadataMetricsCollector(ApplicationModel applicationModel) {
super(new BaseStatComposite() {
super(new BaseStatComposite(applicationModel) {
@Override
protected void init(ApplicationStatComposite applicationStatComposite) {
super.init(applicationStatComposite);
applicationStatComposite.init(MetadataMetricsConstants.APP_LEVEL_KEYS);
}
@Override
protected void init(ServiceStatComposite serviceStatComposite) {
super.init(serviceStatComposite);
serviceStatComposite.initWrapper(MetadataMetricsConstants.SERVICE_LEVEL_KEYS);
}
@Override
protected void init(RtStatComposite rtStatComposite) {
super.init(rtStatComposite);
rtStatComposite.init(OP_TYPE_PUSH, OP_TYPE_SUBSCRIBE, OP_TYPE_STORE_PROVIDER_INTERFACE);
}
});

View File

@ -92,17 +92,17 @@ class MetadataMetricsCollectorTest {
List<MetricSample> metricSamples = collector.collect();
// push success +1
Assertions.assertEquals(1, metricSamples.size());
Assertions.assertTrue(metricSamples.get(0) instanceof GaugeMetricSample);
Assertions.assertEquals(metricSamples.get(0).getName(), MetricsKey.METADATA_PUSH_METRIC_NUM.getName());
Assertions.assertEquals(MetadataMetricsConstants.APP_LEVEL_KEYS.size(), metricSamples.size());
Assertions.assertTrue(metricSamples.stream().allMatch(metricSample -> metricSample instanceof GaugeMetricSample));
Assertions.assertTrue(metricSamples.stream().anyMatch(metricSample -> ((GaugeMetricSample) metricSample).applyAsDouble() == 1));
return null;
}
);
// push finish rt +1
List<MetricSample> metricSamples = collector.collect();
//num(total+success) + rt(5) = 7
Assertions.assertEquals(7, metricSamples.size());
// App(6) + rt(5) = 7
Assertions.assertEquals(MetadataMetricsConstants.APP_LEVEL_KEYS.size() + 5, metricSamples.size());
long c1 = pushEvent.getTimePair().calc();
pushEvent = MetadataEvent.toPushEvent(applicationModel);
@ -121,8 +121,8 @@ class MetadataMetricsCollectorTest {
long c2 = lastTimePair.calc();
metricSamples = collector.collect();
// num(total+success+error) + rt(5)
Assertions.assertEquals(8, metricSamples.size());
// App(6) + rt(5)
Assertions.assertEquals(MetadataMetricsConstants.APP_LEVEL_KEYS.size() + 5, metricSamples.size());
// calc rt
for (MetricSample sample : metricSamples) {
@ -150,9 +150,9 @@ class MetadataMetricsCollectorTest {
List<MetricSample> metricSamples = collector.collect();
// push success +1
Assertions.assertEquals(1, metricSamples.size());
Assertions.assertTrue(metricSamples.get(0) instanceof GaugeMetricSample);
Assertions.assertEquals(metricSamples.get(0).getName(), MetricsKey.METADATA_SUBSCRIBE_METRIC_NUM.getName());
Assertions.assertEquals(MetadataMetricsConstants.APP_LEVEL_KEYS.size(), metricSamples.size());
Assertions.assertTrue(metricSamples.stream().allMatch(metricSample -> metricSample instanceof GaugeMetricSample));
Assertions.assertTrue(metricSamples.stream().anyMatch(metricSample -> ((GaugeMetricSample) metricSample).applyAsDouble() == 1));
return null;
}
);
@ -160,8 +160,9 @@ class MetadataMetricsCollectorTest {
// push finish rt +1
List<MetricSample> metricSamples = collector.collect();
//num(total+success) + rt(5) = 7
Assertions.assertEquals(7, metricSamples.size());
// App(6) + rt(5) = 7
Assertions.assertEquals(MetadataMetricsConstants.APP_LEVEL_KEYS.size() + 5, metricSamples.size());
subscribeEvent = MetadataEvent.toSubscribeEvent(applicationModel);
TimePair lastTimePair = subscribeEvent.getTimePair();
MetricsEventBus.post(subscribeEvent,
@ -179,8 +180,8 @@ class MetadataMetricsCollectorTest {
long c2 = lastTimePair.calc();
metricSamples = collector.collect();
// num(total+success+error) + rt(5)
Assertions.assertEquals(8, metricSamples.size());
// App(6) + rt(5)
Assertions.assertEquals(MetadataMetricsConstants.APP_LEVEL_KEYS.size() + 5, metricSamples.size());
// calc rt
for (MetricSample sample : metricSamples) {
@ -209,19 +210,19 @@ class MetadataMetricsCollectorTest {
() -> {
List<MetricSample> metricSamples = collector.collect();
// push success +1
Assertions.assertEquals(1, metricSamples.size());
Assertions.assertTrue(metricSamples.get(0) instanceof GaugeMetricSample);
Assertions.assertEquals(metricSamples.get(0).getName(), MetricsKey.STORE_PROVIDER_METADATA.getName());
Assertions.assertEquals(metricSamples.get(0).getTags().get("interface"), serviceKey);
// App(6) + service success(1)
Assertions.assertEquals(MetadataMetricsConstants.APP_LEVEL_KEYS.size() + 1, metricSamples.size());
Assertions.assertTrue(metricSamples.stream().allMatch(metricSample -> metricSample instanceof GaugeMetricSample));
Assertions.assertTrue(metricSamples.stream().anyMatch(metricSample -> ((GaugeMetricSample) metricSample).applyAsDouble() == 1));
return null;
}
);
// push finish rt +1
List<MetricSample> metricSamples = collector.collect();
//num(total+success) + rt(5) = 7
Assertions.assertEquals(7, metricSamples.size());
// App(6) + service total/success(2) + rt(5) = 7
Assertions.assertEquals(MetadataMetricsConstants.APP_LEVEL_KEYS.size() + 2 + 5, metricSamples.size());
long c1 = metadataEvent.getTimePair().calc();
metadataEvent = MetadataEvent.toServiceSubscribeEvent(applicationModel, serviceKey);
TimePair lastTimePair = metadataEvent.getTimePair();
@ -240,8 +241,8 @@ class MetadataMetricsCollectorTest {
metricSamples = collector.collect();
// num(total+success+error) + rt(5)
Assertions.assertEquals(8, metricSamples.size());
// App(6) + service total/success/failed(3) + rt(5)
Assertions.assertEquals(MetadataMetricsConstants.APP_LEVEL_KEYS.size() +3 + 5, metricSamples.size());
// calc rt
for (MetricSample sample : metricSamples) {

View File

@ -17,43 +17,58 @@
package org.apache.dubbo.metrics.metadata;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.metrics.data.ApplicationStatComposite;
import org.apache.dubbo.metrics.data.BaseStatComposite;
import org.apache.dubbo.metrics.data.RtStatComposite;
import org.apache.dubbo.metrics.data.ServiceStatComposite;
import org.apache.dubbo.metrics.model.container.LongContainer;
import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import static org.apache.dubbo.metrics.metadata.MetadataMetricsConstants.OP_TYPE_PUSH;
import static org.apache.dubbo.metrics.metadata.MetadataMetricsConstants.OP_TYPE_STORE_PROVIDER_INTERFACE;
import static org.apache.dubbo.metrics.metadata.MetadataMetricsConstants.OP_TYPE_SUBSCRIBE;
public class MetadataStatCompositeTest {
private ApplicationModel applicationModel;
private BaseStatComposite statComposite;
private final String applicationName = "app1";
@BeforeEach
public void setup() {
FrameworkModel frameworkModel = FrameworkModel.defaultModel();
applicationModel = frameworkModel.newApplication();
ApplicationConfig application = new ApplicationConfig();
application.setName("App1");
applicationModel.getApplicationConfigManager().setApplication(application);
statComposite = new BaseStatComposite(applicationModel) {
@Override
protected void init(ApplicationStatComposite applicationStatComposite) {
super.init(applicationStatComposite);
applicationStatComposite.init(MetadataMetricsConstants.APP_LEVEL_KEYS);
}
private final BaseStatComposite statComposite = new BaseStatComposite() {
@Override
protected void init(ApplicationStatComposite applicationStatComposite) {
applicationStatComposite.init(MetadataMetricsConstants.APP_LEVEL_KEYS);
}
@Override
protected void init(ServiceStatComposite serviceStatComposite) {
super.init(serviceStatComposite);
serviceStatComposite.initWrapper(MetadataMetricsConstants.SERVICE_LEVEL_KEYS);
}
@Override
protected void init(ServiceStatComposite serviceStatComposite) {
serviceStatComposite.initWrapper(MetadataMetricsConstants.SERVICE_LEVEL_KEYS);
}
@Override
protected void init(RtStatComposite rtStatComposite) {
rtStatComposite.init(OP_TYPE_PUSH, OP_TYPE_SUBSCRIBE, OP_TYPE_STORE_PROVIDER_INTERFACE);
}
};
@Override
protected void init(RtStatComposite rtStatComposite) {
super.init(rtStatComposite);
rtStatComposite.init(OP_TYPE_PUSH, OP_TYPE_SUBSCRIBE, OP_TYPE_STORE_PROVIDER_INTERFACE);
}
};
}
@Test
void testInit() {
@ -62,7 +77,7 @@ public class MetadataStatCompositeTest {
//(rt)5 * (push,subscribe,service)3
Assertions.assertEquals(5 * 3, statComposite.getRtStatComposite().getRtStats().size());
statComposite.getApplicationStatComposite().getApplicationNumStats().values().forEach((v ->
Assertions.assertEquals(v, new ConcurrentHashMap<>())));
Assertions.assertEquals(v.get(), new AtomicLong(0L).get())));
statComposite.getRtStatComposite().getRtStats().forEach(rtContainer ->
{
for (Map.Entry<String, ? extends Number> entry : rtContainer.entrySet()) {
@ -73,16 +88,16 @@ public class MetadataStatCompositeTest {
@Test
void testIncrement() {
statComposite.incrementApp(MetricsKey.METADATA_PUSH_METRIC_NUM, applicationName, 1);
statComposite.incrementApp(MetricsKey.METADATA_PUSH_METRIC_NUM, 1);
Assertions.assertEquals(1L, statComposite.getApplicationStatComposite().getApplicationNumStats().get(MetricsKey.METADATA_PUSH_METRIC_NUM).get(applicationName).get());
Assertions.assertEquals(1L, statComposite.getApplicationStatComposite().getApplicationNumStats().get(MetricsKey.METADATA_PUSH_METRIC_NUM).get());
}
@Test
void testCalcRt() {
statComposite.calcApplicationRt(applicationName, OP_TYPE_SUBSCRIBE.getType(), 10L);
statComposite.calcApplicationRt( OP_TYPE_SUBSCRIBE.getType(), 10L);
Assertions.assertTrue(statComposite.getRtStatComposite().getRtStats().stream().anyMatch(longContainer -> longContainer.specifyType(OP_TYPE_SUBSCRIBE.getType())));
Optional<LongContainer<? extends Number>> subContainer = statComposite.getRtStatComposite().getRtStats().stream().filter(longContainer -> longContainer.specifyType(OP_TYPE_SUBSCRIBE.getType())).findFirst();
subContainer.ifPresent(v -> Assertions.assertEquals(10L, v.get(applicationName).longValue()));
subContainer.ifPresent(v -> Assertions.assertEquals(10L, v.get(applicationModel.getApplicationName()).longValue()));
}
}

View File

@ -15,6 +15,7 @@
* limitations under the License.
*/
package org.apache.dubbo.metrics.prometheus;
import com.sun.net.httpserver.HttpServer;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.MetricsConfig;
@ -24,7 +25,6 @@ import org.apache.dubbo.metrics.collector.sample.ThreadRejectMetricsCountSampler
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
@ -33,6 +33,7 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
@ -43,19 +44,18 @@ import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static org.apache.dubbo.common.constants.MetricsConstants.PROTOCOL_PROMETHEUS;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_NAME;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_THREAD_NAME;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_HOSTNAME;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_IP;
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_THREAD_NAME;
import static org.apache.dubbo.common.utils.NetUtils.getLocalHost;
import static org.apache.dubbo.common.utils.NetUtils.getLocalHostName;
public class PrometheusMetricsThreadPoolTest {
private FrameworkModel frameworkModel;
private ApplicationModel applicationModel;
private MetricsConfig metricsConfig;
@ -71,8 +71,7 @@ public class PrometheusMetricsThreadPoolTest {
applicationModel.getApplicationConfigManager().setApplication(config);
metricsConfig = new MetricsConfig();
metricsConfig.setProtocol(PROTOCOL_PROMETHEUS);
frameworkModel = FrameworkModel.defaultModel();
metricsCollector = frameworkModel.getBeanFactory().getOrRegisterBean(DefaultMetricsCollector.class);
metricsCollector = applicationModel.getBeanFactory().getOrRegisterBean(DefaultMetricsCollector.class);
}
@AfterEach
@ -92,7 +91,7 @@ public class PrometheusMetricsThreadPoolTest {
metricsConfig.setEnableJvm(false);
metricsCollector.setCollectEnabled(true);
metricsConfig.setEnableThreadpool(true);
metricsCollector.collectApplication(applicationModel);
metricsCollector.collectApplication();
PrometheusMetricsReporter reporter = new PrometheusMetricsReporter(metricsConfig.toUrl(), applicationModel);
reporter.init();
exportHttpServer(reporter,port);
@ -142,7 +141,7 @@ public class PrometheusMetricsThreadPoolTest {
@Test
@SuppressWarnings("rawtypes")
void testThreadPoolRejectMetrics() {
DefaultMetricsCollector collector = new DefaultMetricsCollector();
DefaultMetricsCollector collector = new DefaultMetricsCollector(applicationModel);
collector.setCollectEnabled(true);
collector.setApplicationName(applicationModel.getApplicationName());
String threadPoolExecutorName="DubboServerHandler-20816";

View File

@ -53,19 +53,22 @@ public class RegistryMetricsCollector extends CombMetricsCollector<RegistryEvent
private final ApplicationModel applicationModel;
public RegistryMetricsCollector(ApplicationModel applicationModel) {
super(new BaseStatComposite() {
super(new BaseStatComposite(applicationModel) {
@Override
protected void init(ApplicationStatComposite applicationStatComposite) {
super.init(applicationStatComposite);
applicationStatComposite.init(RegistryMetricsConstants.APP_LEVEL_KEYS);
}
@Override
protected void init(ServiceStatComposite serviceStatComposite) {
super.init(serviceStatComposite);
serviceStatComposite.initWrapper(RegistryMetricsConstants.SERVICE_LEVEL_KEYS);
}
@Override
protected void init(RtStatComposite rtStatComposite) {
super.init(rtStatComposite);
rtStatComposite.init(OP_TYPE_REGISTER, OP_TYPE_SUBSCRIBE, OP_TYPE_NOTIFY, OP_TYPE_REGISTER_SERVICE, OP_TYPE_SUBSCRIBE_SERVICE);
}
});

View File

@ -89,7 +89,7 @@ public final class RegistrySubDispatcher extends SimpleMetricsEventMulticaster {
collector.addRt(event.appName(), placeType.getType(), event.getTimePair().calc());
Map<String, Integer> lastNumMap = Collections.unmodifiableMap(event.getAttachmentValue(ATTACHMENT_KEY_LAST_NUM_MAP));
lastNumMap.forEach(
(k, v) -> collector.setNum(new MetricsKeyWrapper(key, OP_TYPE_NOTIFY), event.appName(), k, v));
(k, v) -> collector.setNum(new MetricsKeyWrapper(key, OP_TYPE_NOTIFY), k, v));
}
));
@ -101,7 +101,7 @@ public final class RegistrySubDispatcher extends SimpleMetricsEventMulticaster {
Map<MetricsKey, Map<String, Integer>> summaryMap = event.getAttachmentValue(ATTACHMENT_DIRECTORY_MAP);
summaryMap.forEach((metricsKey, map) ->
map.forEach(
(k, v) -> collector.setNum(new MetricsKeyWrapper(key, OP_TYPE_DIRECTORY), event.appName(), k, v)));
(k, v) -> collector.setNum(new MetricsKeyWrapper(metricsKey, OP_TYPE_DIRECTORY), k, v)));
}
));

View File

@ -25,6 +25,7 @@ import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import org.apache.dubbo.metrics.registry.RegistryMetricsConstants;
import org.apache.dubbo.metrics.registry.collector.RegistryMetricsCollector;
import org.apache.dubbo.metrics.registry.event.RegistryEvent;
import org.apache.dubbo.rpc.model.ApplicationModel;
@ -76,17 +77,18 @@ class RegistryMetricsCollectorTest {
MetricsEventBus.post(registryEvent,
() -> {
List<MetricSample> metricSamples = collector.collect();
// push success +1
Assertions.assertEquals(1, metricSamples.size());
Assertions.assertTrue(metricSamples.get(0) instanceof GaugeMetricSample);
// push success +1 -> other default 0 = RegistryMetricsConstants.APP_LEVEL_KEYS.size()
Assertions.assertEquals(RegistryMetricsConstants.APP_LEVEL_KEYS.size(), metricSamples.size());
Assertions.assertTrue(metricSamples.stream().allMatch(metricSample -> metricSample instanceof GaugeMetricSample));
Assertions.assertTrue(metricSamples.stream().anyMatch(metricSample -> ((GaugeMetricSample) metricSample).applyAsDouble() == 1));
return null;
}
);
// push finish rt +1
List<MetricSample> metricSamples = collector.collect();
//num(total+success) + rt(5) = 7
Assertions.assertEquals(7, metricSamples.size());
// RegistryMetricsConstants.APP_LEVEL_KEYS.size() + rt(5) = 12
Assertions.assertEquals(RegistryMetricsConstants.APP_LEVEL_KEYS.size() + 5, metricSamples.size());
long c1 = registryEvent.getTimePair().calc();
@ -108,7 +110,7 @@ class RegistryMetricsCollectorTest {
metricSamples = collector.collect();
// num(total+success+error) + rt(5)
Assertions.assertEquals(8, metricSamples.size());
Assertions.assertEquals(RegistryMetricsConstants.APP_LEVEL_KEYS.size() + 5, metricSamples.size());
// calc rt
for (MetricSample sample : metricSamples) {
@ -138,18 +140,17 @@ class RegistryMetricsCollectorTest {
List<MetricSample> metricSamples = collector.collect();
// push success +1
Assertions.assertEquals(1, metricSamples.size());
Assertions.assertTrue(metricSamples.get(0) instanceof GaugeMetricSample);
Assertions.assertEquals(metricSamples.get(0).getName(), MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS.getName());
Assertions.assertEquals(metricSamples.get(0).getTags().get("interface"), serviceName);
Assertions.assertEquals(RegistryMetricsConstants.APP_LEVEL_KEYS.size() + 1, metricSamples.size());
// Service num only 1 and contains tag of interface
Assertions.assertEquals(1, metricSamples.stream().filter(metricSample -> serviceName.equals(metricSample.getTags().get("interface"))).count());
return null;
}
);
// push finish rt +1
List<MetricSample> metricSamples = collector.collect();
//num(total+success) + rt(5) = 7
Assertions.assertEquals(7, metricSamples.size());
// App(7) + rt(5) + service(total/success) = 14
Assertions.assertEquals(RegistryMetricsConstants.APP_LEVEL_KEYS.size() + 5 + 2, metricSamples.size());
long c1 = registryEvent.getTimePair().calc();
registryEvent = RegistryEvent.toRsEvent(applicationModel, serviceName, 2);
@ -169,8 +170,8 @@ class RegistryMetricsCollectorTest {
metricSamples = collector.collect();
// num(total+success+error) + rt(5)
Assertions.assertEquals(8, metricSamples.size());
// App(7) + rt(5) + service(total/success/failed) = 15
Assertions.assertEquals(RegistryMetricsConstants.APP_LEVEL_KEYS.size() + 5 + 3, metricSamples.size());
// calc rt
for (MetricSample sample : metricSamples) {
@ -198,20 +199,20 @@ class RegistryMetricsCollectorTest {
MetricsEventBus.post(subscribeEvent,
() -> {
List<MetricSample> metricSamples = collector.collect();
// push success +1
Assertions.assertEquals(1, metricSamples.size());
Assertions.assertTrue(metricSamples.get(0) instanceof GaugeMetricSample);
Assertions.assertEquals(metricSamples.get(0).getName(), MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM.getName());
Assertions.assertEquals(metricSamples.get(0).getTags().get("interface"), serviceName);
Assertions.assertTrue(metricSamples.stream().allMatch(metricSample -> metricSample instanceof GaugeMetricSample));
Assertions.assertTrue(metricSamples.stream().anyMatch(metricSample -> ((GaugeMetricSample) metricSample).applyAsDouble() == 1));
// App(7) + (service success +1)
Assertions.assertEquals(RegistryMetricsConstants.APP_LEVEL_KEYS.size() + 1, metricSamples.size());
// Service num only 1 and contains tag of interface
Assertions.assertEquals(1, metricSamples.stream().filter(metricSample -> serviceName.equals(metricSample.getTags().get("interface"))).count());
return null;
}
);
// push finish rt +1
List<MetricSample> metricSamples = collector.collect();
//num(total+success) + rt(5) = 7
Assertions.assertEquals(7, metricSamples.size());
// App(7) + rt(5) + service(total/success) = 14
Assertions.assertEquals(RegistryMetricsConstants.APP_LEVEL_KEYS.size() + 5 + 2, metricSamples.size());
long c1 = subscribeEvent.getTimePair().calc();
subscribeEvent = RegistryEvent.toSsEvent(applicationModel, serviceName);
@ -231,8 +232,8 @@ class RegistryMetricsCollectorTest {
metricSamples = collector.collect();
// num(total+success+error) + rt(5)
Assertions.assertEquals(8, metricSamples.size());
// App(7) + rt(5) + service(total/success/failed) = 15
Assertions.assertEquals(RegistryMetricsConstants.APP_LEVEL_KEYS.size() + 5 + 3, metricSamples.size());
// calc rt
for (MetricSample sample : metricSamples) {
@ -269,8 +270,8 @@ class RegistryMetricsCollectorTest {
}
);
List<MetricSample> metricSamples = collector.collect();
// num(total+service*3) + rt(5) = 9
Assertions.assertEquals(9, metricSamples.size());
// App(7) + num(service*3) + rt(5) = 9
Assertions.assertEquals(RegistryMetricsConstants.APP_LEVEL_KEYS.size() + 3 + 5, metricSamples.size());
}
}

View File

@ -87,8 +87,7 @@ class RegistryMetricsSampleTest {
void testListener() {
RegistryMetricsCollector collector = new RegistryMetricsCollector(applicationModel);
collector.setCollectEnabled(true);
String applicationName = applicationModel.getApplicationName();
collector.increment(applicationName, MetricsKey.REGISTER_METRIC_REQUESTS);
collector.increment(MetricsKey.REGISTER_METRIC_REQUESTS);
}
}

View File

@ -17,6 +17,7 @@
package org.apache.dubbo.metrics.registry.metrics.collector;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.metrics.data.ApplicationStatComposite;
import org.apache.dubbo.metrics.data.BaseStatComposite;
import org.apache.dubbo.metrics.data.RtStatComposite;
@ -26,13 +27,16 @@ import org.apache.dubbo.metrics.model.container.LongContainer;
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
import org.apache.dubbo.metrics.model.sample.MetricSample;
import org.apache.dubbo.metrics.registry.RegistryMetricsConstants;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_RT_AVG;
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_RT_MAX;
@ -46,24 +50,38 @@ import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE
public class RegistryStatCompositeTest {
private ApplicationModel applicationModel;
private String applicationName;
private BaseStatComposite statComposite;
private final String applicationName = "app1";
private final BaseStatComposite statComposite = new BaseStatComposite() {
@Override
protected void init(ApplicationStatComposite applicationStatComposite) {
applicationStatComposite.init(RegistryMetricsConstants.APP_LEVEL_KEYS);
}
@BeforeEach
public void setup() {
FrameworkModel frameworkModel = FrameworkModel.defaultModel();
applicationModel = frameworkModel.newApplication();
ApplicationConfig application = new ApplicationConfig();
application.setName("App1");
applicationModel.getApplicationConfigManager().setApplication(application);
applicationName = applicationModel.getApplicationName();
statComposite = new BaseStatComposite(applicationModel) {
@Override
protected void init(ApplicationStatComposite applicationStatComposite) {
super.init(applicationStatComposite);
applicationStatComposite.init(RegistryMetricsConstants.APP_LEVEL_KEYS);
}
@Override
protected void init(ServiceStatComposite serviceStatComposite) {
serviceStatComposite.initWrapper(RegistryMetricsConstants.SERVICE_LEVEL_KEYS);
}
@Override
protected void init(ServiceStatComposite serviceStatComposite) {
super.init(serviceStatComposite);
serviceStatComposite.initWrapper(RegistryMetricsConstants.SERVICE_LEVEL_KEYS);
}
@Override
protected void init(RtStatComposite rtStatComposite) {
rtStatComposite.init(OP_TYPE_REGISTER, OP_TYPE_SUBSCRIBE, OP_TYPE_NOTIFY, OP_TYPE_REGISTER_SERVICE, OP_TYPE_SUBSCRIBE_SERVICE);
}
};
@Override
protected void init(RtStatComposite rtStatComposite) {
super.init(rtStatComposite);
rtStatComposite.init(OP_TYPE_REGISTER, OP_TYPE_SUBSCRIBE, OP_TYPE_NOTIFY, OP_TYPE_REGISTER_SERVICE, OP_TYPE_SUBSCRIBE_SERVICE);
}
};
}
@Test
void testInit() {
@ -71,7 +89,7 @@ public class RegistryStatCompositeTest {
//(rt)5 * (applicationRegister,subscribe,notify,applicationRegister.service,subscribe.service)
Assertions.assertEquals(5 * 5, statComposite.getRtStatComposite().getRtStats().size());
statComposite.getApplicationStatComposite().getApplicationNumStats().values().forEach((v ->
Assertions.assertEquals(v, new ConcurrentHashMap<>())));
Assertions.assertEquals(v.get(), new AtomicLong(0L).get())));
statComposite.getRtStatComposite().getRtStats().forEach(rtContainer ->
{
for (Map.Entry<String, ? extends Number> entry : rtContainer.entrySet()) {
@ -82,13 +100,13 @@ public class RegistryStatCompositeTest {
@Test
void testIncrement() {
statComposite.incrementApp(REGISTER_METRIC_REQUESTS, applicationName, 1);
Assertions.assertEquals(1L, statComposite.getApplicationStatComposite().getApplicationNumStats().get(REGISTER_METRIC_REQUESTS).get(applicationName).get());
statComposite.incrementApp(REGISTER_METRIC_REQUESTS, 1);
Assertions.assertEquals(1L, statComposite.getApplicationStatComposite().getApplicationNumStats().get(REGISTER_METRIC_REQUESTS).get());
}
@Test
void testCalcRt() {
statComposite.calcApplicationRt(applicationName, OP_TYPE_NOTIFY.getType(), 10L);
statComposite.calcApplicationRt(OP_TYPE_NOTIFY.getType(), 10L);
Assertions.assertTrue(statComposite.getRtStatComposite().getRtStats().stream().anyMatch(longContainer -> longContainer.specifyType(OP_TYPE_NOTIFY.getType())));
Optional<LongContainer<? extends Number>> subContainer = statComposite.getRtStatComposite().getRtStats().stream().filter(longContainer -> longContainer.specifyType(OP_TYPE_NOTIFY.getType())).findFirst();
subContainer.ifPresent(v -> Assertions.assertEquals(10L, v.get(applicationName).longValue()));
@ -97,29 +115,28 @@ public class RegistryStatCompositeTest {
@Test
@SuppressWarnings("rawtypes")
void testCalcServiceKeyRt() {
String applicationName = "TestApp";
String serviceKey = "TestService";
String registryOpType = OP_TYPE_REGISTER_SERVICE.getType();
Long responseTime1 = 100L;
Long responseTime2 = 200L;
statComposite.calcServiceKeyRt(applicationName, serviceKey, registryOpType, responseTime1);
statComposite.calcServiceKeyRt(applicationName, serviceKey, registryOpType, responseTime2);
statComposite.calcServiceKeyRt(serviceKey, registryOpType, responseTime1);
statComposite.calcServiceKeyRt(serviceKey, registryOpType, responseTime2);
List<MetricSample> exportedRtMetrics = statComposite.export(MetricsCategory.RT);
GaugeMetricSample minSample = (GaugeMetricSample) exportedRtMetrics.stream()
.filter(sample -> sample.getTags().containsValue(applicationName))
.filter(sample -> sample.getName().equals(METRIC_RT_MIN.getNameByType("register.service")))
.findFirst().orElse(null);
.filter(sample -> sample.getTags().containsValue(applicationName))
.filter(sample -> sample.getName().equals(METRIC_RT_MIN.getNameByType("register.service")))
.findFirst().orElse(null);
GaugeMetricSample maxSample = (GaugeMetricSample) exportedRtMetrics.stream()
.filter(sample -> sample.getTags().containsValue(applicationName))
.filter(sample -> sample.getName().equals(METRIC_RT_MAX.getNameByType("register.service")))
.findFirst().orElse(null);
.filter(sample -> sample.getTags().containsValue(applicationName))
.filter(sample -> sample.getName().equals(METRIC_RT_MAX.getNameByType("register.service")))
.findFirst().orElse(null);
GaugeMetricSample avgSample = (GaugeMetricSample) exportedRtMetrics.stream()
.filter(sample -> sample.getTags().containsValue(applicationName))
.filter(sample -> sample.getName().equals(METRIC_RT_AVG.getNameByType("register.service")))
.findFirst().orElse(null);
.filter(sample -> sample.getTags().containsValue(applicationName))
.filter(sample -> sample.getName().equals(METRIC_RT_AVG.getNameByType("register.service")))
.findFirst().orElse(null);
Assertions.assertNotNull(minSample);
Assertions.assertNotNull(maxSample);

View File

@ -144,8 +144,10 @@ public interface Constants {
String TELNET_KEY = "telnet";
String HEARTBEAT_KEY = "heartbeat";
String HEARTBEAT_CONFIG_KEY = "dubbo.protocol.default-heartbeat";
String CLOSE_TIMEOUT_CONFIG_KEY = "dubbo.protocol.default-close-timeout";
int DEFAULT_HEARTBEAT = 60 * 1000;
String HEARTBEAT_TIMEOUT_KEY = "heartbeat.timeout";
String CLOSE_TIMEOUT_KEY = "close.timeout";
String CONNECTIONS_KEY = "connections";
int DEFAULT_BACKLOG = 1024;

View File

@ -32,11 +32,11 @@ public class CloseTimerTask extends AbstractTimerTask {
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(CloseTimerTask.class);
private final int idleTimeout;
private final int closeTimeout;
public CloseTimerTask(ChannelProvider channelProvider, HashedWheelTimer hashedWheelTimer, Long heartbeatTimeoutTick, int idleTimeout) {
super(channelProvider, hashedWheelTimer, heartbeatTimeoutTick);
this.idleTimeout = idleTimeout;
public CloseTimerTask(ChannelProvider channelProvider, HashedWheelTimer hashedWheelTimer, Long tick, int closeTimeout) {
super(channelProvider, hashedWheelTimer, tick);
this.closeTimeout = closeTimeout;
}
@Override
@ -46,9 +46,9 @@ public class CloseTimerTask extends AbstractTimerTask {
Long lastWrite = lastWrite(channel);
Long now = now();
// check ping & pong at server
if ((lastRead != null && now - lastRead > idleTimeout)
|| (lastWrite != null && now - lastWrite > idleTimeout)) {
logger.warn(PROTOCOL_FAILED_RESPONSE, "", "", "Close channel " + channel + ", because idleCheck timeout: " + idleTimeout + "ms");
if ((lastRead != null && now - lastRead > closeTimeout)
|| (lastWrite != null && now - lastWrite > closeTimeout)) {
logger.warn(PROTOCOL_FAILED_RESPONSE, "", "", "Close channel " + channel + ", because idleCheck timeout: " + closeTimeout + "ms");
channel.close();
}
} catch (Throwable t) {

View File

@ -49,8 +49,7 @@ import static org.apache.dubbo.common.constants.LoggerCodeConstants.TRANSPORT_FA
import static org.apache.dubbo.remoting.Constants.HEARTBEAT_CHECK_TICK;
import static org.apache.dubbo.remoting.Constants.LEAST_HEARTBEAT_DURATION;
import static org.apache.dubbo.remoting.Constants.TICKS_PER_WHEEL;
import static org.apache.dubbo.remoting.utils.UrlUtils.getHeartbeat;
import static org.apache.dubbo.remoting.utils.UrlUtils.getIdleTimeout;
import static org.apache.dubbo.remoting.utils.UrlUtils.getCloseTimeout;
/**
* ExchangeServerImpl
@ -211,11 +210,9 @@ public class HeaderExchangeServer implements ExchangeServer {
public void reset(URL url) {
server.reset(url);
try {
int currHeartbeat = getHeartbeat(getUrl());
int currIdleTimeout = getIdleTimeout(getUrl());
int heartbeat = getHeartbeat(url);
int idleTimeout = getIdleTimeout(url);
if (currHeartbeat != heartbeat || currIdleTimeout != idleTimeout) {
int currCloseTimeout = getCloseTimeout(getUrl());
int closeTimeout = getCloseTimeout(url);
if (closeTimeout != currCloseTimeout) {
cancelCloseTask();
startIdleCheckTask(url);
}
@ -262,9 +259,9 @@ public class HeaderExchangeServer implements ExchangeServer {
private void startIdleCheckTask(URL url) {
if (!server.canHandleIdle()) {
AbstractTimerTask.ChannelProvider cp = () -> unmodifiableCollection(HeaderExchangeServer.this.getChannels());
int idleTimeout = getIdleTimeout(url);
long idleTimeoutTick = calculateLeastDuration(idleTimeout);
this.closeTimer = new CloseTimerTask(cp, IDLE_CHECK_TIMER.get(), idleTimeoutTick, idleTimeout);
int closeTimeout = getCloseTimeout(url);
long closeTimeoutTick = calculateLeastDuration(closeTimeout);
this.closeTimer = new CloseTimerTask(cp, IDLE_CHECK_TIMER.get(), closeTimeoutTick, closeTimeout);
}
}
}

View File

@ -36,6 +36,27 @@ import static org.apache.dubbo.remoting.Constants.SERIALIZATION_KEY;
public class UrlUtils {
private static final String ALLOWED_SERIALIZATION_KEY = "allowedSerialization";
public static int getCloseTimeout(URL url) {
String configuredCloseTimeout = System.getProperty(Constants.CLOSE_TIMEOUT_CONFIG_KEY);
int defaultCloseTimeout = -1;
if (StringUtils.isNotEmpty(configuredCloseTimeout)) {
try {
defaultCloseTimeout = Integer.parseInt(configuredCloseTimeout);
} catch (NumberFormatException e) {
// use default heartbeat
}
}
if (defaultCloseTimeout < 0) {
defaultCloseTimeout = getIdleTimeout(url);
}
int closeTimeout = url.getParameter(Constants.CLOSE_TIMEOUT_KEY, defaultCloseTimeout);
int heartbeat = getHeartbeat(url);
if (closeTimeout < heartbeat * 2) {
throw new IllegalStateException("closeTimeout < heartbeatInterval * 2");
}
return closeTimeout;
}
public static int getIdleTimeout(URL url) {
int heartBeat = getHeartbeat(url);
// idleTimeout should be at least more than twice heartBeat because possible retries of client.

View File

@ -46,4 +46,28 @@ class UrlUtilsTest {
Assertions.assertEquals(200, UrlUtils.getHeartbeat(url));
System.clearProperty(Constants.HEARTBEAT_CONFIG_KEY);
}
@Test
void testGetCloseTimeout() {
URL url1 = URL.valueOf("dubbo://127.0.0.1:12345?heartbeat=10000");
URL url2 = URL.valueOf("dubbo://127.0.0.1:12345?heartbeat=10000&heartbeat.timeout=50000");
URL url3 = URL.valueOf("dubbo://127.0.0.1:12345?heartbeat=10000&heartbeat.timeout=10000");
URL url4 = URL.valueOf("dubbo://127.0.0.1:12345?close.timeout=30000&heartbeat=10000&heartbeat.timeout=10000");
URL url5 = URL.valueOf("dubbo://127.0.0.1:12345?close.timeout=40000&heartbeat=10000&heartbeat.timeout=50000");
URL url6 = URL.valueOf("dubbo://127.0.0.1:12345?close.timeout=10000&heartbeat=10000&heartbeat.timeout=10000");
Assertions.assertEquals(30000, UrlUtils.getCloseTimeout(url1));
Assertions.assertEquals(50000, UrlUtils.getCloseTimeout(url2));
Assertions.assertThrows(RuntimeException.class, () -> UrlUtils.getCloseTimeout(url3));
Assertions.assertThrows(RuntimeException.class, () -> UrlUtils.getCloseTimeout(url4));
Assertions.assertEquals(40000, UrlUtils.getCloseTimeout(url5));
Assertions.assertThrows(RuntimeException.class, () -> UrlUtils.getCloseTimeout(url6));
}
@Test
void testConfiguredClose() {
System.setProperty(Constants.CLOSE_TIMEOUT_CONFIG_KEY, "180000");
URL url = URL.valueOf("dubbo://127.0.0.1:12345");
Assertions.assertEquals(180000, UrlUtils.getCloseTimeout(url));
System.clearProperty(Constants.HEARTBEAT_CONFIG_KEY);
}
}

View File

@ -72,7 +72,7 @@ final class NettyChannel extends AbstractChannel {
private final Netty4BatchWriteQueue writeQueue;
private final Codec2 codec;
private Codec2 codec;
private final boolean encodeInIOThread;
@ -365,4 +365,8 @@ final class NettyChannel extends AbstractChannel {
return frameworkModel.getExtensionLoader(Codec2.class).getExtension("default");
}
}
public void setCodec(Codec2 codec) {
this.codec = codec;
}
}

View File

@ -60,6 +60,7 @@ public class NettyConfigOperator implements ChannelOperator {
}
if (!(codec2 instanceof DefaultCodec)){
((NettyChannel) channel).setCodec(codec2);
NettyCodecAdapter codec = new NettyCodecAdapter(codec2, channel.getUrl(), handler);
((NettyChannel) channel).getNioChannel().pipeline().addLast(
codec.getDecoder()

View File

@ -136,14 +136,13 @@ public class NettyServer extends AbstractServer {
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
// FIXME: should we use getTimeout()?
int idleTimeout = UrlUtils.getIdleTimeout(getUrl());
int closeTimeout = UrlUtils.getCloseTimeout(getUrl());
NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyServer.this);
ch.pipeline().addLast("negotiation", new SslServerTlsHandler(getUrl()));
ch.pipeline()
.addLast("decoder", adapter.getDecoder())
.addLast("encoder", adapter.getEncoder())
.addLast("server-idle-handler", new IdleStateHandler(0, 0, idleTimeout, MILLISECONDS))
.addLast("server-idle-handler", new IdleStateHandler(0, 0, closeTimeout, MILLISECONDS))
.addLast("handler", nettyServerHandler);
}
});