Merge branch 'apache-3.3' into 3.3.0-beta.1-release
# Conflicts: # dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java # dubbo-plugin/dubbo-native/pom.xml # dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/PortUnificationServerTest.java # dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java
This commit is contained in:
commit
a0e7ebc735
|
|
@ -21,7 +21,6 @@ dubbo-auth
|
|||
dubbo-apache-release
|
||||
dubbo-all-shaded
|
||||
dubbo-bom
|
||||
dubbo-build-tools
|
||||
dubbo-cluster
|
||||
dubbo-common
|
||||
dubbo-compatible
|
||||
|
|
@ -66,6 +65,7 @@ dubbo-metrics-prometheus
|
|||
dubbo-metrics-registry
|
||||
dubbo-metrics-config-center
|
||||
dubbo-metrics-netty
|
||||
dubbo-metrics-event
|
||||
dubbo-monitor
|
||||
dubbo-monitor-api
|
||||
dubbo-monitor-common
|
||||
|
|
@ -141,3 +141,4 @@ dubbo-plugin-context
|
|||
dubbo-plugin-classloader-filter
|
||||
dubbo-plugin-proxy-bytebuddy
|
||||
dubbo-plugin-qos-trace
|
||||
dubbo-plugin-loom
|
||||
|
|
|
|||
|
|
@ -96,9 +96,9 @@ header:
|
|||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/MatchingGroupIdFilter.java'
|
||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/RunArguments.java'
|
||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/RunProcess.java'
|
||||
- 'dubbo-native/src/main/java/org/apache/dubbo/aot/generate/BasicJsonWriter.java'
|
||||
- 'dubbo-native/src/main/java/org/apache/dubbo/aot/api/ExecutableMode.java'
|
||||
- 'dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberCategory.java'
|
||||
- 'dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/BasicJsonWriter.java'
|
||||
- 'dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ExecutableMode.java'
|
||||
- 'dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberCategory.java'
|
||||
- 'dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/DubboMergingDigest.java'
|
||||
- 'dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/DubboAbstractTDigest.java'
|
||||
- 'dubbo-common/src/main/java/org/apache/dubbo/common/logger/helpers/FormattingTuple.java'
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ check 2.7.5 milestone for details.
|
|||
* In consumer side the app cannot catch the exception from provider that is configured serialization="kryo". #4238
|
||||
* fix StringUtils#isBlank #4725
|
||||
* when the interfaceName of the Reference annotation has duplicated,the exception is puzzled #4160
|
||||
* when anonymity bean is defined in spirng context,dubbo throw npe #
|
||||
* when anonymity bean is defined in spring context,dubbo throw npe #
|
||||
* add Thread ContextClassLoader #4712
|
||||
* Fix judgment ipv4 address #4729
|
||||
* The compilation of static methods should be excluded when generating the proxy. #4647
|
||||
|
|
|
|||
|
|
@ -224,10 +224,8 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
|
|||
|
||||
logger.warn(CLUSTER_NO_VALID_PROVIDER, "provider server or registry center crashed", "",
|
||||
"No provider available after connectivity filter for the service " + getConsumerUrl().getServiceKey()
|
||||
+ " All validInvokers' size: " + validInvokers.size()
|
||||
+ " All routed invokers' size: " + routedResult.size()
|
||||
+ " All invokers' size: " + invokers.size()
|
||||
+ " from registry " + getUrl().getAddress()
|
||||
+ " from registry " + this
|
||||
+ " on the consumer " + NetUtils.getLocalHost()
|
||||
+ " using the dubbo version " + Version.getVersion() + ".");
|
||||
}
|
||||
|
|
@ -350,6 +348,7 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
|
|||
if (!invokersToReconnect.isEmpty()) {
|
||||
checkConnectivity();
|
||||
}
|
||||
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
|
||||
}, reconnectTaskPeriod, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
|
||||
|
|
|
|||
|
|
@ -27,11 +27,12 @@ import org.apache.dubbo.rpc.cluster.RouterChain;
|
|||
import org.apache.dubbo.rpc.cluster.SingleRouterChain;
|
||||
import org.apache.dubbo.rpc.cluster.router.state.BitList;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_FAILED_SITE_SELECTION;
|
||||
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTER_MODE_KEY;
|
||||
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_KEY;
|
||||
|
||||
/**
|
||||
|
|
@ -130,6 +131,9 @@ public class StaticDirectory<T> extends AbstractDirectory<T> {
|
|||
|
||||
@Override
|
||||
protected Map<String, String> getDirectoryMeta() {
|
||||
return Collections.singletonMap(REGISTRY_KEY, "static");
|
||||
Map<String, String> metas = new HashMap<>();
|
||||
metas.put(REGISTRY_KEY, "static");
|
||||
metas.put(REGISTER_MODE_KEY, "static");
|
||||
return metas;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY;
|
|||
import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
|
||||
import static org.apache.dubbo.rpc.cluster.Constants.CLUSTER_AVAILABLE_CHECK_KEY;
|
||||
import static org.apache.dubbo.rpc.cluster.Constants.INVOCATION_NEED_MOCK;
|
||||
import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.same;
|
||||
|
|
|
|||
|
|
@ -21,10 +21,10 @@ import org.apache.dubbo.rpc.AppResponse;
|
|||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.Result;
|
||||
import org.apache.dubbo.rpc.RpcContext;
|
||||
import org.apache.dubbo.rpc.RpcException;
|
||||
import org.apache.dubbo.rpc.RpcInvocation;
|
||||
import org.apache.dubbo.rpc.cluster.Directory;
|
||||
import org.apache.dubbo.rpc.cluster.filter.DemoService;
|
||||
import org.apache.dubbo.rpc.RpcException;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
|
@ -56,6 +56,7 @@ class FailSafeClusterInvokerTest {
|
|||
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
RpcContext.removeServiceContext();
|
||||
|
||||
dic = mock(Directory.class);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,10 +24,10 @@ import org.apache.dubbo.common.utils.LogUtil;
|
|||
import org.apache.dubbo.rpc.AppResponse;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.Result;
|
||||
import org.apache.dubbo.rpc.RpcInvocation;
|
||||
import org.apache.dubbo.rpc.RpcContext;
|
||||
import org.apache.dubbo.rpc.cluster.Directory;
|
||||
import org.apache.dubbo.rpc.RpcException;
|
||||
import org.apache.dubbo.rpc.RpcInvocation;
|
||||
import org.apache.dubbo.rpc.cluster.Directory;
|
||||
|
||||
import org.apache.log4j.Level;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
|
|
@ -38,7 +38,6 @@ import org.junit.jupiter.api.MethodOrderer;
|
|||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestMethodOrder;
|
||||
import org.junit.jupiter.api.function.Executable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -47,7 +46,7 @@ import java.util.concurrent.CountDownLatch;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.RETRIES_KEY;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
|
|
@ -72,6 +71,7 @@ class FailbackClusterInvokerTest {
|
|||
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
RpcContext.removeServiceContext();
|
||||
|
||||
dic = mock(Directory.class);
|
||||
given(dic.getUrl()).willReturn(url);
|
||||
|
|
|
|||
|
|
@ -128,6 +128,8 @@ public interface CommonConstants {
|
|||
|
||||
String THREAD_POOL_EXHAUSTED_LISTENERS_KEY = "thread-pool-exhausted-listeners";
|
||||
|
||||
String JSON_CHECK_LEVEL_KEY = "jsonCheckLevel";
|
||||
|
||||
String THREADS_KEY = "threads";
|
||||
|
||||
String QUEUES_KEY = "queues";
|
||||
|
|
@ -643,7 +645,7 @@ public interface CommonConstants {
|
|||
|
||||
String SERVICE_DEPLOYER_ATTRIBUTE_KEY = "serviceDeployer";
|
||||
|
||||
String RESTEASY_NETTY_HTTP_REQUEST_ATTRIBUTE_KEY = "resteasyNettyHttpRequest";
|
||||
|
||||
|
||||
String DUBBO_MANUAL_REGISTER_KEY = "dubbo.application.manual-register";
|
||||
|
||||
|
|
|
|||
|
|
@ -40,17 +40,19 @@ public interface MetricsConstants {
|
|||
String TAG_VERSION_KEY = "version";
|
||||
|
||||
String TAG_APPLICATION_VERSION_KEY = "application.version";
|
||||
|
||||
|
||||
String TAG_KEY_KEY = "key";
|
||||
|
||||
|
||||
String TAG_CONFIG_CENTER = "config.center";
|
||||
|
||||
|
||||
String TAG_CHANGE_TYPE = "change.type";
|
||||
|
||||
String TAG_ERROR_CODE = "error";
|
||||
|
||||
String ENABLE_JVM_METRICS_KEY = "enable.jvm";
|
||||
|
||||
String ENABLE_COLLECTOR_SYNC_KEY = "enable.collector.sync";
|
||||
|
||||
String AGGREGATION_COLLECTOR_KEY = "aggregation";
|
||||
|
||||
String AGGREGATION_ENABLED_KEY = "aggregation.enabled";
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ public interface QosConstants {
|
|||
|
||||
String QOS_ENABLE = "qos.enable";
|
||||
|
||||
String QOS_CHECK = "qos.check";
|
||||
|
||||
String QOS_HOST = "qos.host";
|
||||
|
||||
String QOS_PORT = "qos.port";
|
||||
|
|
|
|||
|
|
@ -17,8 +17,23 @@
|
|||
|
||||
package org.apache.dubbo.common.logger;
|
||||
|
||||
import org.apache.dubbo.common.constants.LoggerCodeConstants;
|
||||
|
||||
/**
|
||||
* Logger interface with the ability of displaying solution of different types of error.
|
||||
*
|
||||
* <p>
|
||||
* This logger will log a message like this:
|
||||
*
|
||||
* <blockquote><pre>
|
||||
* ... (original logging message) This may be caused by (... cause),
|
||||
* go to https://dubbo.apache.org/faq/[Cat]/[X] to find instructions. (... extendedInformation)
|
||||
* </pre></blockquote>
|
||||
*
|
||||
* Where "[Cat]/[X]" is the error code ("code" in arguments). The link is clickable, leading user to
|
||||
* the "Error code and its corresponding solutions" page.
|
||||
*
|
||||
* @see LoggerCodeConstants Detailed Format of Error Code and Error Code Constants
|
||||
*/
|
||||
public interface ErrorTypeAwareLogger extends Logger {
|
||||
|
||||
|
|
|
|||
|
|
@ -145,6 +145,10 @@ public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy {
|
|||
if (!guard.tryAcquire()) {
|
||||
return;
|
||||
}
|
||||
// To avoid multiple dump, check again
|
||||
if (System.currentTimeMillis() - lastPrintTime < TEN_MINUTES_MILLS) {
|
||||
return;
|
||||
}
|
||||
|
||||
ExecutorService pool = Executors.newSingleThreadExecutor();
|
||||
pool.execute(() -> {
|
||||
|
|
@ -169,9 +173,9 @@ public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy {
|
|||
} catch (Exception t) {
|
||||
logger.error(COMMON_UNEXPECTED_CREATE_DUMP, "", "", "dump jStack error", t);
|
||||
} finally {
|
||||
lastPrintTime = System.currentTimeMillis();
|
||||
guard.release();
|
||||
}
|
||||
lastPrintTime = System.currentTimeMillis();
|
||||
});
|
||||
//must shutdown thread pool ,if not will lead to OOM
|
||||
pool.shutdown();
|
||||
|
|
|
|||
|
|
@ -103,6 +103,11 @@ public abstract class AbstractConfig implements Serializable {
|
|||
|
||||
protected final AtomicBoolean refreshed = new AtomicBoolean(false);
|
||||
|
||||
/**
|
||||
* Indicate that if current config needs to being refreshed, default is true
|
||||
*/
|
||||
protected transient volatile boolean needRefresh = true;
|
||||
|
||||
/**
|
||||
* Is default config or not
|
||||
*/
|
||||
|
|
@ -679,16 +684,18 @@ public abstract class AbstractConfig implements Serializable {
|
|||
* Dubbo config property override
|
||||
*/
|
||||
public void refresh() {
|
||||
try {
|
||||
// check and init before do refresh
|
||||
preProcessRefresh();
|
||||
refreshWithPrefixes(getPrefixes(), getConfigMode());
|
||||
} catch (Exception e) {
|
||||
logger.error(COMMON_FAILED_OVERRIDE_FIELD, "", "", "Failed to override field value of config bean: " + this, e);
|
||||
throw new IllegalStateException("Failed to override field value of config bean: " + this, e);
|
||||
}
|
||||
if (needRefresh) {
|
||||
try {
|
||||
// check and init before do refresh
|
||||
preProcessRefresh();
|
||||
refreshWithPrefixes(getPrefixes(), getConfigMode());
|
||||
} catch (Exception e) {
|
||||
logger.error(COMMON_FAILED_OVERRIDE_FIELD, "", "", "Failed to override field value of config bean: " + this, e);
|
||||
throw new IllegalStateException("Failed to override field value of config bean: " + this, e);
|
||||
}
|
||||
|
||||
postProcessRefresh();
|
||||
postProcessRefresh();
|
||||
}
|
||||
refreshed.set(true);
|
||||
}
|
||||
|
||||
|
|
@ -949,6 +956,17 @@ public abstract class AbstractConfig implements Serializable {
|
|||
this.isDefault = isDefault;
|
||||
}
|
||||
|
||||
@Transient
|
||||
@Parameter(excluded = true, attribute = false)
|
||||
public boolean isNeedRefresh() {
|
||||
return needRefresh;
|
||||
}
|
||||
|
||||
@Transient
|
||||
public void setNeedRefresh(boolean needRefresh) {
|
||||
this.needRefresh = needRefresh;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP_W
|
|||
import static org.apache.dubbo.common.constants.QosConstants.ANONYMOUS_ACCESS_ALLOW_COMMANDS;
|
||||
import static org.apache.dubbo.common.constants.QosConstants.ANONYMOUS_ACCESS_PERMISSION_LEVEL;
|
||||
import static org.apache.dubbo.common.constants.QosConstants.ANONYMOUS_ACCESS_PERMISSION_LEVEL_COMPATIBLE;
|
||||
import static org.apache.dubbo.common.constants.QosConstants.QOS_CHECK;
|
||||
import static org.apache.dubbo.common.constants.QosConstants.QOS_ENABLE;
|
||||
import static org.apache.dubbo.common.constants.QosConstants.QOS_ENABLE_COMPATIBLE;
|
||||
import static org.apache.dubbo.common.constants.QosConstants.QOS_HOST;
|
||||
|
|
@ -151,6 +152,11 @@ public class ApplicationConfig extends AbstractConfig {
|
|||
*/
|
||||
private Boolean qosEnable;
|
||||
|
||||
/**
|
||||
* Whether qos should start success or not, will check qosEnable first
|
||||
*/
|
||||
private Boolean qosCheck;
|
||||
|
||||
/**
|
||||
* The qos host to listen
|
||||
*/
|
||||
|
|
@ -448,6 +454,15 @@ public class ApplicationConfig extends AbstractConfig {
|
|||
this.qosEnable = qosEnable;
|
||||
}
|
||||
|
||||
@Parameter(key = QOS_CHECK)
|
||||
public Boolean getQosCheck() {
|
||||
return qosCheck;
|
||||
}
|
||||
|
||||
public void setQosCheck(Boolean qosCheck) {
|
||||
this.qosCheck = qosCheck;
|
||||
}
|
||||
|
||||
@Parameter(key = QOS_HOST)
|
||||
public String getQosHost() {
|
||||
return qosHost;
|
||||
|
|
|
|||
|
|
@ -66,6 +66,16 @@ public class MetricsConfig extends AbstractConfig {
|
|||
*/
|
||||
private Boolean enableNetty;
|
||||
|
||||
/**
|
||||
* Enable metrics init.
|
||||
*/
|
||||
private Boolean enableMetricsInit;
|
||||
|
||||
/**
|
||||
* Enable collector sync.
|
||||
*/
|
||||
private Boolean enableCollectorSync;
|
||||
|
||||
/**
|
||||
* @deprecated After metrics config is refactored.
|
||||
* This parameter should no longer use and will be deleted in the future.
|
||||
|
|
@ -99,6 +109,12 @@ public class MetricsConfig extends AbstractConfig {
|
|||
|
||||
private Boolean enableRpc;
|
||||
|
||||
/**
|
||||
* The level of the metrics, the value can be "SERVICE", "METHOD", default is method.
|
||||
*/
|
||||
private String rpcLevel;
|
||||
|
||||
|
||||
public MetricsConfig() {
|
||||
}
|
||||
|
||||
|
|
@ -129,6 +145,14 @@ public class MetricsConfig extends AbstractConfig {
|
|||
return enableJvm;
|
||||
}
|
||||
|
||||
public String getRpcLevel() {
|
||||
return rpcLevel;
|
||||
}
|
||||
|
||||
public void setRpcLevel(String rpcLevel) {
|
||||
this.rpcLevel = rpcLevel;
|
||||
}
|
||||
|
||||
public void setEnableJvm(Boolean enableJvm) {
|
||||
this.enableJvm = enableJvm;
|
||||
}
|
||||
|
|
@ -213,6 +237,22 @@ public class MetricsConfig extends AbstractConfig {
|
|||
this.enableThreadpool = enableThreadpool;
|
||||
}
|
||||
|
||||
public Boolean getEnableMetricsInit() {
|
||||
return enableMetricsInit;
|
||||
}
|
||||
|
||||
public void setEnableMetricsInit(Boolean enableMetricsInit) {
|
||||
this.enableMetricsInit = enableMetricsInit;
|
||||
}
|
||||
|
||||
public Boolean getEnableCollectorSync() {
|
||||
return enableCollectorSync;
|
||||
}
|
||||
|
||||
public void setEnableCollectorSync(Boolean enableCollectorSync) {
|
||||
this.enableCollectorSync = enableCollectorSync;
|
||||
}
|
||||
|
||||
public Boolean getUseGlobalRegistry() {
|
||||
return useGlobalRegistry;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import java.util.Map;
|
|||
import java.util.Optional;
|
||||
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.JSON_CHECK_LEVEL_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.SSL_ENABLED_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.THREAD_POOL_EXHAUSTED_LISTENERS_KEY;
|
||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_UNEXPECTED_EXCEPTION;
|
||||
|
|
@ -229,6 +230,8 @@ public class ProtocolConfig extends AbstractConfig {
|
|||
*/
|
||||
private String extProtocol;
|
||||
|
||||
private String jsonCheckLevel;
|
||||
|
||||
public ProtocolConfig() {
|
||||
}
|
||||
|
||||
|
|
@ -331,6 +334,15 @@ public class ProtocolConfig extends AbstractConfig {
|
|||
this.threadname = threadname;
|
||||
}
|
||||
|
||||
@Parameter(key = JSON_CHECK_LEVEL_KEY)
|
||||
public String getJsonCheckLevel() {
|
||||
return jsonCheckLevel;
|
||||
}
|
||||
|
||||
public void setJsonCheckLevel(String jsonCheckLevel) {
|
||||
this.jsonCheckLevel = jsonCheckLevel;
|
||||
}
|
||||
|
||||
@Parameter(key = THREAD_POOL_EXHAUSTED_LISTENERS_KEY)
|
||||
public String getThreadPoolExhaustedListeners() {
|
||||
return threadPoolExhaustedListeners;
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ java.util.Collections$EmptyList
|
|||
java.util.Collections$EmptyMap
|
||||
java.util.Collections$SingletonSet
|
||||
java.util.Collections$SingletonList
|
||||
java.util.Collections$SingletonMap
|
||||
java.util.Collections$UnmodifiableCollection
|
||||
java.util.Collections$UnmodifiableList
|
||||
java.util.Collections$UnmodifiableMap
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@
|
|||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>testcontainers</artifactId>
|
||||
<version>1.18.3</version>
|
||||
<version>1.19.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
|
|
|||
|
|
@ -228,8 +228,13 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
|
|||
}
|
||||
|
||||
if (ref == null) {
|
||||
// ensure start module, compatible with old api usage
|
||||
getScopeModel().getDeployer().start();
|
||||
if (getScopeModel().isLifeCycleManagedExternally()) {
|
||||
// prepare model for reference
|
||||
getScopeModel().getDeployer().prepare();
|
||||
} else {
|
||||
// ensure start module, compatible with old api usage
|
||||
getScopeModel().getDeployer().start();
|
||||
}
|
||||
|
||||
init(check);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,11 +38,15 @@ import org.apache.dubbo.config.invoker.DelegateProviderMetaDataInvoker;
|
|||
import org.apache.dubbo.config.support.Parameter;
|
||||
import org.apache.dubbo.config.utils.ConfigValidationUtils;
|
||||
import org.apache.dubbo.metadata.ServiceNameMapping;
|
||||
import org.apache.dubbo.metrics.event.MetricsEventBus;
|
||||
import org.apache.dubbo.metrics.event.MetricsInitEvent;
|
||||
import org.apache.dubbo.metrics.model.MethodMetric;
|
||||
import org.apache.dubbo.registry.client.metadata.MetadataUtils;
|
||||
import org.apache.dubbo.rpc.Exporter;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.Protocol;
|
||||
import org.apache.dubbo.rpc.ProxyFactory;
|
||||
import org.apache.dubbo.rpc.RpcInvocation;
|
||||
import org.apache.dubbo.rpc.ServerService;
|
||||
import org.apache.dubbo.rpc.cluster.ConfiguratorFactory;
|
||||
import org.apache.dubbo.rpc.model.ModuleModel;
|
||||
|
|
@ -61,6 +65,7 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.TreeSet;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
|
@ -294,8 +299,13 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
|
|||
return;
|
||||
}
|
||||
|
||||
// ensure start module, compatible with old api usage
|
||||
getScopeModel().getDeployer().start();
|
||||
if (getScopeModel().isLifeCycleManagedExternally()) {
|
||||
// prepare model for reference
|
||||
getScopeModel().getDeployer().prepare();
|
||||
} else {
|
||||
// ensure start module, compatible with old api usage
|
||||
getScopeModel().getDeployer().start();
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
if (this.exported) {
|
||||
|
|
@ -558,6 +568,17 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
|
|||
registerType = RegisterTypeEnum.NEVER_REGISTER;
|
||||
}
|
||||
exportUrl(url, registryURLs, registerType);
|
||||
|
||||
initServiceMethodMetrics(url);
|
||||
}
|
||||
|
||||
private void initServiceMethodMetrics(URL url) {
|
||||
String[] methods = Optional.ofNullable(url.getParameter(METHODS_KEY)).map(i -> i.split(",")).orElse(new String[]{});
|
||||
boolean serviceLevel = MethodMetric.isServiceLevel(application.getApplicationModel());
|
||||
Arrays.stream(methods).forEach(method -> {
|
||||
RpcInvocation invocation = new RpcInvocation(url.getServiceKey(), url.getServiceModel(), method, interfaceName, url.getProtocolServiceKey(), null, null, null, null, null, null);
|
||||
MetricsEventBus.publish(MetricsInitEvent.toMetricsInitEvent(application.getApplicationModel(), invocation, serviceLevel));
|
||||
});
|
||||
}
|
||||
|
||||
private void processServiceExecutor(URL url) {
|
||||
|
|
|
|||
|
|
@ -391,6 +391,7 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
|
|||
collector.setCollectEnabled(true);
|
||||
collector.collectApplication();
|
||||
collector.setThreadpoolCollectEnabled(Optional.ofNullable(metricsConfig.getEnableThreadpool()).orElse(true));
|
||||
collector.setMetricsInitEnabled(Optional.ofNullable(metricsConfig.getEnableMetricsInit()).orElse(true));
|
||||
MetricsReporterFactory metricsReporterFactory = getExtensionLoader(MetricsReporterFactory.class).getAdaptiveExtension();
|
||||
MetricsReporter metricsReporter = null;
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
<description>The spring config module of dubbo project</description>
|
||||
<properties>
|
||||
<skip_maven_deploy>false</skip_maven_deploy>
|
||||
<spring-boot.version>2.7.14</spring-boot.version>
|
||||
<spring-boot.version>2.7.15</spring-boot.version>
|
||||
<!-- Uncomment spring_version property to check Spring 4.x compatibility -->
|
||||
<!-- <spring_version>4.3.30.RELEASE</spring_version> -->
|
||||
</properties>
|
||||
|
|
@ -73,7 +73,7 @@
|
|||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
<version>1.9.20</version>
|
||||
<version>1.9.20.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import org.apache.dubbo.common.utils.ClassUtils;
|
|||
import org.apache.dubbo.common.utils.StringUtils;
|
||||
import org.apache.dubbo.config.ReferenceConfig;
|
||||
import org.apache.dubbo.config.spring.aot.AotWithSpringDetector;
|
||||
import org.apache.dubbo.config.spring.context.DubboConfigApplicationListener;
|
||||
import org.apache.dubbo.config.spring.context.DubboConfigBeanInitializer;
|
||||
import org.apache.dubbo.config.spring.reference.ReferenceAttributes;
|
||||
import org.apache.dubbo.config.spring.reference.ReferenceBeanManager;
|
||||
|
|
@ -54,6 +55,7 @@ import java.util.LinkedHashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_DUBBO_BEAN_INITIALIZER;
|
||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROXY_FAILED;
|
||||
|
||||
|
||||
|
|
@ -143,6 +145,9 @@ public class ReferenceBean<T> implements FactoryBean<T>,
|
|||
//actual reference config
|
||||
private ReferenceConfig referenceConfig;
|
||||
|
||||
// ReferenceBeanManager
|
||||
private ReferenceBeanManager referenceBeanManager;
|
||||
|
||||
// Registration sources of this reference, may be xml file or annotation location
|
||||
private List<Map<String, Object>> sources = new ArrayList<>();
|
||||
|
||||
|
|
@ -256,7 +261,7 @@ public class ReferenceBean<T> implements FactoryBean<T>,
|
|||
}
|
||||
Assert.notNull(this.interfaceName, "The interface name of ReferenceBean is not initialized");
|
||||
|
||||
ReferenceBeanManager referenceBeanManager = beanFactory.getBean(ReferenceBeanManager.BEAN_NAME, ReferenceBeanManager.class);
|
||||
this.referenceBeanManager = beanFactory.getBean(ReferenceBeanManager.BEAN_NAME, ReferenceBeanManager.class);
|
||||
referenceBeanManager.addReference(this);
|
||||
}
|
||||
|
||||
|
|
@ -393,7 +398,9 @@ public class ReferenceBean<T> implements FactoryBean<T>,
|
|||
|
||||
private Object getCallProxy() throws Exception {
|
||||
if (referenceConfig == null) {
|
||||
throw new IllegalStateException("ReferenceBean is not ready yet, please make sure to call reference interface method after dubbo is started.");
|
||||
referenceBeanManager.initReferenceBean(this);
|
||||
applicationContext.getBean(DubboConfigApplicationListener.class.getName(), DubboConfigApplicationListener.class).init();
|
||||
logger.warn(CONFIG_DUBBO_BEAN_INITIALIZER, "", "", "ReferenceBean is not ready yet, please make sure to call reference interface method after dubbo is started.");
|
||||
}
|
||||
//get reference proxy
|
||||
//Subclasses should synchronize on the given Object if they perform any sort of extended singleton creation phase.
|
||||
|
|
|
|||
|
|
@ -110,10 +110,10 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
|
|||
private final ConcurrentMap<InjectionMetadata.InjectedElement, String> injectedMethodReferenceBeanCache =
|
||||
new ConcurrentHashMap<>(CACHE_SIZE);
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
protected ApplicationContext applicationContext;
|
||||
|
||||
private ReferenceBeanManager referenceBeanManager;
|
||||
private BeanDefinitionRegistry beanDefinitionRegistry;
|
||||
protected ReferenceBeanManager referenceBeanManager;
|
||||
protected BeanDefinitionRegistry beanDefinitionRegistry;
|
||||
|
||||
/**
|
||||
* {@link com.alibaba.dubbo.config.annotation.Reference @com.alibaba.dubbo.config.annotation.Reference} has been supported since 2.7.3
|
||||
|
|
@ -211,7 +211,7 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
|
|||
* @param beanName
|
||||
* @param beanDefinition
|
||||
*/
|
||||
private void processReferenceAnnotatedBeanDefinition(String beanName, AnnotatedBeanDefinition beanDefinition) {
|
||||
protected void processReferenceAnnotatedBeanDefinition(String beanName, AnnotatedBeanDefinition beanDefinition) {
|
||||
|
||||
MethodMetadata factoryMethodMetadata = SpringCompatUtils.getFactoryMethodMetadata(beanDefinition);
|
||||
|
||||
|
|
@ -500,6 +500,9 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
|
|||
beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_CLASS, interfaceClass);
|
||||
beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_NAME, interfaceName);
|
||||
|
||||
beanDefinition.getPropertyValues().add(ReferenceAttributes.INTERFACE_CLASS, interfaceClass);
|
||||
beanDefinition.getPropertyValues().add(ReferenceAttributes.INTERFACE_NAME, interfaceName);
|
||||
|
||||
// create decorated definition for reference bean, Avoid being instantiated when getting the beanType of ReferenceBean
|
||||
// see org.springframework.beans.factory.support.AbstractBeanFactory#getTypeForFactoryBean()
|
||||
GenericBeanDefinition targetDefinition = new GenericBeanDefinition();
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ public class ServiceAnnotationPostProcessor implements BeanDefinitionRegistryPos
|
|||
}
|
||||
} else {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn(CONFIG_NO_ANNOTATIONS_FOUND, "No annotations were found on the class", "", "No class annotated by Dubbo @Service was found under package ["
|
||||
logger.warn(CONFIG_NO_ANNOTATIONS_FOUND, "No annotations were found on the class", "", "No class annotated by Dubbo @DubboService or @Service was found under package ["
|
||||
+ packageToScan + "], ignore re-scanned classes: " + scanExcludeFilter.getExcludedCount());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,21 +16,22 @@
|
|||
*/
|
||||
package org.apache.dubbo.config.spring.context;
|
||||
|
||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_DUBBO_BEAN_NOT_FOUND;
|
||||
import static org.springframework.util.ObjectUtils.nullSafeEquals;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.config.spring.context.event.DubboConfigInitEvent;
|
||||
import org.apache.dubbo.config.spring.util.DubboBeanUtils;
|
||||
import org.apache.dubbo.rpc.model.ModuleModel;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_DUBBO_BEAN_NOT_FOUND;
|
||||
import static org.springframework.util.ObjectUtils.nullSafeEquals;
|
||||
|
||||
/**
|
||||
* An ApplicationListener to load config beans
|
||||
*/
|
||||
|
|
@ -53,11 +54,15 @@ public class DubboConfigApplicationListener implements ApplicationListener<Dubbo
|
|||
@Override
|
||||
public void onApplicationEvent(DubboConfigInitEvent event) {
|
||||
if (nullSafeEquals(applicationContext, event.getSource())) {
|
||||
// It's expected to be notified at org.springframework.context.support.AbstractApplicationContext.registerListeners(),
|
||||
// before loading non-lazy singleton beans. At this moment, all BeanFactoryPostProcessor have been processed,
|
||||
if (initialized.compareAndSet(false, true)) {
|
||||
initDubboConfigBeans();
|
||||
}
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
||||
public void init() {
|
||||
// It's expected to be notified at org.springframework.context.support.AbstractApplicationContext.registerListeners(),
|
||||
// before loading non-lazy singleton beans. At this moment, all BeanFactoryPostProcessor have been processed,
|
||||
if (initialized.compareAndSet(false, true)) {
|
||||
initDubboConfigBeans();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ public class DubboSpringInitializer {
|
|||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DubboSpringInitializer.class);
|
||||
|
||||
private static final Map<BeanDefinitionRegistry, DubboSpringInitContext> contextMap = new ConcurrentHashMap<>();
|
||||
private static final Map<BeanDefinitionRegistry, DubboSpringInitContext> REGISTRY_CONTEXT_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
public DubboSpringInitializer() {
|
||||
}
|
||||
|
|
@ -54,7 +54,7 @@ public class DubboSpringInitializer {
|
|||
DubboSpringInitContext context = new DubboSpringInitContext();
|
||||
|
||||
// Spring ApplicationContext may not ready at this moment (e.g. load from xml), so use registry as key
|
||||
if (contextMap.putIfAbsent(registry, context) != null) {
|
||||
if (REGISTRY_CONTEXT_MAP.putIfAbsent(registry, context) != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -66,18 +66,18 @@ public class DubboSpringInitializer {
|
|||
}
|
||||
|
||||
public static boolean remove(BeanDefinitionRegistry registry) {
|
||||
return contextMap.remove(registry) != null;
|
||||
return REGISTRY_CONTEXT_MAP.remove(registry) != null;
|
||||
}
|
||||
|
||||
public static boolean remove(ApplicationContext springContext) {
|
||||
AutowireCapableBeanFactory autowireCapableBeanFactory = springContext.getAutowireCapableBeanFactory();
|
||||
for (Map.Entry<BeanDefinitionRegistry, DubboSpringInitContext> entry : contextMap.entrySet()) {
|
||||
for (Map.Entry<BeanDefinitionRegistry, DubboSpringInitContext> entry : REGISTRY_CONTEXT_MAP.entrySet()) {
|
||||
DubboSpringInitContext initContext = entry.getValue();
|
||||
if (initContext.getApplicationContext() == springContext ||
|
||||
initContext.getBeanFactory() == autowireCapableBeanFactory ||
|
||||
initContext.getRegistry() == autowireCapableBeanFactory
|
||||
) {
|
||||
DubboSpringInitContext context = contextMap.remove(entry.getKey());
|
||||
DubboSpringInitContext context = REGISTRY_CONTEXT_MAP.remove(entry.getKey());
|
||||
logger.info("Unbind " + safeGetModelDesc(context.getModuleModel()) + " from spring container: " +
|
||||
ObjectUtils.identityToString(entry.getKey()));
|
||||
return true;
|
||||
|
|
@ -87,11 +87,11 @@ public class DubboSpringInitializer {
|
|||
}
|
||||
|
||||
static Map<BeanDefinitionRegistry, DubboSpringInitContext> getContextMap() {
|
||||
return contextMap;
|
||||
return REGISTRY_CONTEXT_MAP;
|
||||
}
|
||||
|
||||
static DubboSpringInitContext findBySpringContext(ApplicationContext applicationContext) {
|
||||
for (DubboSpringInitContext initContext : contextMap.values()) {
|
||||
for (DubboSpringInitContext initContext : REGISTRY_CONTEXT_MAP.values()) {
|
||||
if (initContext.getApplicationContext() == applicationContext) {
|
||||
return initContext;
|
||||
}
|
||||
|
|
@ -184,7 +184,7 @@ public class DubboSpringInitializer {
|
|||
}
|
||||
|
||||
private static DubboSpringInitContext findContextForApplication(ApplicationModel applicationModel) {
|
||||
for (DubboSpringInitContext initializationContext : contextMap.values()) {
|
||||
for (DubboSpringInitContext initializationContext : REGISTRY_CONTEXT_MAP.values()) {
|
||||
if (initializationContext.getApplicationModel() == applicationModel) {
|
||||
return initializationContext;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ public class ReferenceBeanManager implements ApplicationContextAware {
|
|||
* @param referenceBean
|
||||
* @throws Exception
|
||||
*/
|
||||
private synchronized void initReferenceBean(ReferenceBean referenceBean) throws Exception {
|
||||
public synchronized void initReferenceBean(ReferenceBean referenceBean) throws Exception {
|
||||
|
||||
if (referenceBean.getReferenceConfig() != null) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -520,6 +520,11 @@
|
|||
<xsd:documentation><![CDATA[ Whether to enable qos or not. ]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="qos-check" type="xsd:boolean">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[ Whether qos should start success or not, will check qosEnable first. ]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="qos-host" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[ The qos host to listen. ]]></xsd:documentation>
|
||||
|
|
@ -1115,6 +1120,11 @@
|
|||
<xsd:documentation><![CDATA[ Enable record rpc metrics. ]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="rpc-level" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[ Is the metric for rpc requests at the METHOD level or SERVICE level ]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="tracingType">
|
||||
|
|
@ -1692,6 +1702,11 @@
|
|||
<xsd:documentation><![CDATA[ The protocol context path. ]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="json-check-level" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[ The level of json compatibility check. ]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="register" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[ The protocol can be register to registry. ]]></xsd:documentation>
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
<dubbo:config-center address="zookeeper://127.0.0.1:2181"/>
|
||||
<dubbo:metadata-report address="zookeeper://127.0.0.1:2181"/>
|
||||
<dubbo:registry id="registry1" address="zookeeper://127.0.0.1:2181?registry-type=service"/>
|
||||
<dubbo:registry id="registry1" address="zookeeper://127.0.0.1:2181"/>
|
||||
|
||||
<dubbo:protocol name="dubbo" port="-1"/>
|
||||
<dubbo:protocol name="tri" port="-1"/>
|
||||
|
|
|
|||
|
|
@ -19,26 +19,17 @@ package org.apache.dubbo.config.spring6.beans.factory.annotation;
|
|||
|
||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.common.utils.ArrayUtils;
|
||||
import org.apache.dubbo.common.utils.Assert;
|
||||
import org.apache.dubbo.common.utils.ClassUtils;
|
||||
import org.apache.dubbo.common.utils.StringUtils;
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.apache.dubbo.config.annotation.Reference;
|
||||
import org.apache.dubbo.config.spring.Constants;
|
||||
import org.apache.dubbo.config.spring.ReferenceBean;
|
||||
import org.apache.dubbo.config.spring.beans.factory.annotation.AbstractAnnotationBeanPostProcessor;
|
||||
import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor;
|
||||
import org.apache.dubbo.config.spring.context.event.DubboConfigInitEvent;
|
||||
import org.apache.dubbo.config.spring.reference.ReferenceAttributes;
|
||||
import org.apache.dubbo.config.spring.reference.ReferenceBeanManager;
|
||||
import org.apache.dubbo.config.spring.reference.ReferenceBeanSupport;
|
||||
import org.apache.dubbo.config.spring.util.SpringCompatUtils;
|
||||
import org.apache.dubbo.config.spring6.beans.factory.aot.ReferencedFieldValueResolver;
|
||||
import org.apache.dubbo.config.spring6.beans.factory.aot.ReferencedMethodArgumentsResolver;
|
||||
import org.apache.dubbo.config.spring6.utils.AotUtils;
|
||||
import org.apache.dubbo.rpc.service.Destroyable;
|
||||
import org.apache.dubbo.rpc.service.EchoService;
|
||||
import org.apache.dubbo.rpc.service.GenericService;
|
||||
import org.springframework.aop.SpringProxy;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aot.generate.AccessControl;
|
||||
|
|
@ -51,100 +42,44 @@ import org.springframework.aot.hint.RuntimeHints;
|
|||
import org.springframework.aot.hint.TypeReference;
|
||||
import org.springframework.aot.hint.support.ClassHintUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.PropertyValue;
|
||||
import org.springframework.beans.PropertyValues;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.annotation.InjectionMetadata;
|
||||
import org.springframework.beans.factory.aot.AutowiredArgumentsCodeGenerator;
|
||||
import org.springframework.beans.factory.aot.BeanRegistrationAotContribution;
|
||||
import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor;
|
||||
import org.springframework.beans.factory.aot.BeanRegistrationCode;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||
import org.springframework.beans.factory.support.AutowireCandidateResolver;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
import org.springframework.beans.factory.support.RegisteredBean;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.core.DecoratingProxy;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.MethodMetadata;
|
||||
import org.springframework.javapoet.ClassName;
|
||||
import org.springframework.javapoet.CodeBlock;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import static com.alibaba.spring.util.AnnotationUtils.getAttribute;
|
||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_DUBBO_BEAN_INITIALIZER;
|
||||
import static org.apache.dubbo.common.utils.AnnotationUtils.filterDefaultValues;
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Step 1:
|
||||
* The purpose of implementing {@link BeanFactoryPostProcessor} is to scan the registration reference bean definition earlier,
|
||||
* so that it can be shared with the xml bean configuration.
|
||||
* </p>
|
||||
* The purpose of implementing {@link BeanRegistrationAotProcessor} is to
|
||||
* supplement for {@link ReferenceAnnotationBeanPostProcessor} ability of AOT.
|
||||
*
|
||||
* <p>
|
||||
* Step 2:
|
||||
* By implementing {@link org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor},
|
||||
* inject the reference bean instance into the fields and setter methods which annotated with {@link DubboReference}.
|
||||
* </p>
|
||||
*
|
||||
* @see DubboReference
|
||||
* @see Reference
|
||||
* @see com.alibaba.dubbo.config.annotation.Reference
|
||||
* @since 2.5.7
|
||||
* @since 3.3
|
||||
*/
|
||||
public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotationBeanPostProcessor
|
||||
implements ApplicationContextAware, BeanRegistrationAotProcessor, BeanFactoryPostProcessor {
|
||||
|
||||
/**
|
||||
* The bean name of {@link ReferenceAnnotationWithAotBeanPostProcessor}
|
||||
*/
|
||||
public static final String BEAN_NAME = ReferenceAnnotationWithAotBeanPostProcessor.class.getName();
|
||||
|
||||
/**
|
||||
* Cache size
|
||||
*/
|
||||
private static final int CACHE_SIZE = Integer.getInteger(BEAN_NAME + ".cache.size", 32);
|
||||
public class ReferenceAnnotationWithAotBeanPostProcessor extends ReferenceAnnotationBeanPostProcessor
|
||||
implements BeanRegistrationAotProcessor {
|
||||
|
||||
private final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(getClass());
|
||||
|
||||
private final ConcurrentMap<InjectionMetadata.InjectedElement, String> injectedFieldReferenceBeanCache =
|
||||
new ConcurrentHashMap<>(CACHE_SIZE);
|
||||
|
||||
private final ConcurrentMap<InjectionMetadata.InjectedElement, String> injectedMethodReferenceBeanCache =
|
||||
new ConcurrentHashMap<>(CACHE_SIZE);
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private ReferenceBeanManager referenceBeanManager;
|
||||
private BeanDefinitionRegistry beanDefinitionRegistry;
|
||||
|
||||
@Nullable
|
||||
private ConfigurableListableBeanFactory beanFactory;
|
||||
|
|
@ -155,7 +90,7 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat
|
|||
* {@link DubboReference @DubboReference} has been supported since 2.7.7
|
||||
*/
|
||||
public ReferenceAnnotationWithAotBeanPostProcessor() {
|
||||
super(DubboReference.class, Reference.class, com.alibaba.dubbo.config.annotation.Reference.class);
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -192,18 +127,6 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat
|
|||
}
|
||||
}
|
||||
|
||||
// if (beanFactory instanceof AbstractBeanFactory) {
|
||||
// List<BeanPostProcessor> beanPostProcessors = ((AbstractBeanFactory) beanFactory).getBeanPostProcessors();
|
||||
// for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
|
||||
// if (beanPostProcessor == this) {
|
||||
// // This bean has been registered as BeanPostProcessor at org.apache.dubbo.config.spring.context.DubboInfraBeanRegisterPostProcessor.postProcessBeanFactory()
|
||||
// // so destroy this bean here, prevent register it as BeanPostProcessor again, avoid cause BeanPostProcessorChecker detection error
|
||||
// beanDefinitionRegistry.removeBeanDefinition(BEAN_NAME);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
try {
|
||||
// this is an early event, it will be notified at org.springframework.context.support.AbstractApplicationContext.registerListeners()
|
||||
applicationContext.publishEvent(new DubboConfigInitEvent(applicationContext));
|
||||
|
|
@ -227,157 +150,6 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* process @DubboReference at java-config @bean method
|
||||
* <pre class="code">
|
||||
* @Configuration
|
||||
* public class ConsumerConfig {
|
||||
*
|
||||
* @Bean
|
||||
* @DubboReference(group="demo", version="1.2.3")
|
||||
* public ReferenceBean<DemoService> demoService() {
|
||||
* return new ReferenceBean();
|
||||
* }
|
||||
*
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param beanName
|
||||
* @param beanDefinition
|
||||
*/
|
||||
private void processReferenceAnnotatedBeanDefinition(String beanName, AnnotatedBeanDefinition beanDefinition) {
|
||||
|
||||
MethodMetadata factoryMethodMetadata = SpringCompatUtils.getFactoryMethodMetadata(beanDefinition);
|
||||
|
||||
// Extract beanClass from generic return type of java-config bean method: ReferenceBean<DemoService>
|
||||
// see org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBeanFromMethod
|
||||
Class beanClass = getBeanFactory().getType(beanName);
|
||||
if (beanClass == Object.class) {
|
||||
beanClass = SpringCompatUtils.getGenericTypeOfReturnType(factoryMethodMetadata);
|
||||
}
|
||||
if (beanClass == Object.class) {
|
||||
// bean class is invalid, ignore it
|
||||
return;
|
||||
}
|
||||
|
||||
if (beanClass == null) {
|
||||
String beanMethodSignature = factoryMethodMetadata.getDeclaringClassName() + "#" + factoryMethodMetadata.getMethodName() + "()";
|
||||
throw new BeanCreationException("The ReferenceBean is missing necessary generic type, which returned by the @Bean method of Java-config class. " +
|
||||
"The generic type of the returned ReferenceBean must be specified as the referenced interface type, " +
|
||||
"such as ReferenceBean<DemoService>. Please check bean method: " + beanMethodSignature);
|
||||
}
|
||||
|
||||
// get dubbo reference annotation attributes
|
||||
Map<String, Object> annotationAttributes = null;
|
||||
// try all dubbo reference annotation types
|
||||
for (Class<? extends Annotation> annotationType : getAnnotationTypes()) {
|
||||
if (factoryMethodMetadata.isAnnotated(annotationType.getName())) {
|
||||
// Since Spring 5.2
|
||||
// return factoryMethodMetadata.getAnnotations().get(annotationType).filterDefaultValues().asMap();
|
||||
// Compatible with Spring 4.x
|
||||
annotationAttributes = factoryMethodMetadata.getAnnotationAttributes(annotationType.getName());
|
||||
annotationAttributes = filterDefaultValues(annotationType, annotationAttributes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (annotationAttributes != null) {
|
||||
// @DubboReference on @Bean method
|
||||
LinkedHashMap<String, Object> attributes = new LinkedHashMap<>(annotationAttributes);
|
||||
// reset id attribute
|
||||
attributes.put(ReferenceAttributes.ID, beanName);
|
||||
// convert annotation props
|
||||
ReferenceBeanSupport.convertReferenceProps(attributes, beanClass);
|
||||
|
||||
// get interface
|
||||
String interfaceName = (String) attributes.get(ReferenceAttributes.INTERFACE);
|
||||
|
||||
// check beanClass and reference interface class
|
||||
if (!StringUtils.isEquals(interfaceName, beanClass.getName()) && beanClass != GenericService.class) {
|
||||
String beanMethodSignature = factoryMethodMetadata.getDeclaringClassName() + "#" + factoryMethodMetadata.getMethodName() + "()";
|
||||
throw new BeanCreationException("The 'interfaceClass' or 'interfaceName' attribute value of @DubboReference annotation " +
|
||||
"is inconsistent with the generic type of the ReferenceBean returned by the bean method. " +
|
||||
"The interface class of @DubboReference is: " + interfaceName + ", but return ReferenceBean<" + beanClass.getName() + ">. " +
|
||||
"Please remove the 'interfaceClass' and 'interfaceName' attributes from @DubboReference annotation. " +
|
||||
"Please check bean method: " + beanMethodSignature);
|
||||
}
|
||||
|
||||
Class interfaceClass = beanClass;
|
||||
|
||||
// set attribute instead of property values
|
||||
beanDefinition.setAttribute(Constants.REFERENCE_PROPS, attributes);
|
||||
beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_CLASS, interfaceClass);
|
||||
beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_NAME, interfaceName);
|
||||
} else {
|
||||
// raw reference bean
|
||||
// the ReferenceBean is not yet initialized
|
||||
beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_CLASS, beanClass);
|
||||
if (beanClass != GenericService.class) {
|
||||
beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_NAME, beanClass.getName());
|
||||
}
|
||||
}
|
||||
|
||||
// set id
|
||||
beanDefinition.getPropertyValues().add(ReferenceAttributes.ID, beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
|
||||
if (beanType != null) {
|
||||
if (isReferenceBean(beanDefinition)) {
|
||||
//mark property value as optional
|
||||
List<PropertyValue> propertyValues = beanDefinition.getPropertyValues().getPropertyValueList();
|
||||
for (PropertyValue propertyValue : propertyValues) {
|
||||
propertyValue.setOptional(true);
|
||||
}
|
||||
} else if (isAnnotatedReferenceBean(beanDefinition)) {
|
||||
// extract beanClass from java-config bean method generic return type: ReferenceBean<DemoService>
|
||||
//Class beanClass = getBeanFactory().getType(beanName);
|
||||
} else {
|
||||
AnnotatedInjectionMetadata metadata = findInjectionMetadata(beanName, beanType, null);
|
||||
metadata.checkConfigMembers(beanDefinition);
|
||||
try {
|
||||
prepareInjection(metadata);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("Prepare dubbo reference injection element failed", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Alternatives to the {@link #postProcessProperties(PropertyValues, Object, String)}, that removed as of Spring
|
||||
* Framework 6.0.0, and in favor of {@link #postProcessProperties(PropertyValues, Object, String)}.
|
||||
* <p>In order to be compatible with the lower version of Spring, it is still retained.
|
||||
*
|
||||
* @see #postProcessProperties
|
||||
*/
|
||||
public PropertyValues postProcessPropertyValues(
|
||||
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
|
||||
return postProcessProperties(pvs, bean, beanName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alternatives to the {@link #postProcessPropertyValues(PropertyValues, PropertyDescriptor[], Object, String)}.
|
||||
*
|
||||
* @see #postProcessPropertyValues
|
||||
*/
|
||||
@Override
|
||||
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
|
||||
throws BeansException {
|
||||
try {
|
||||
AnnotatedInjectionMetadata metadata = findInjectionMetadata(beanName, bean.getClass(), pvs);
|
||||
prepareInjection(metadata);
|
||||
metadata.inject(bean, beanName, pvs);
|
||||
} catch (BeansException ex) {
|
||||
throw ex;
|
||||
} catch (Throwable ex) {
|
||||
throw new BeanCreationException(beanName, "Injection of @" + getAnnotationType().getSimpleName()
|
||||
+ " dependencies is failed", ex);
|
||||
}
|
||||
return pvs;
|
||||
}
|
||||
|
||||
private boolean isReferenceBean(BeanDefinition beanDefinition) {
|
||||
return ReferenceBean.class.getName().equals(beanDefinition.getBeanClassName());
|
||||
}
|
||||
|
|
@ -401,238 +173,6 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat
|
|||
return metadata;
|
||||
}
|
||||
|
||||
protected void prepareInjection(AnnotatedInjectionMetadata metadata) throws BeansException {
|
||||
try {
|
||||
//find and register bean definition for @DubboReference/@Reference
|
||||
for (AnnotatedFieldElement fieldElement : metadata.getFieldElements()) {
|
||||
if (fieldElement.injectedObject != null) {
|
||||
continue;
|
||||
}
|
||||
Class<?> injectedType = fieldElement.field.getType();
|
||||
AnnotationAttributes attributes = fieldElement.attributes;
|
||||
String referenceBeanName = registerReferenceBean(fieldElement.getPropertyName(), injectedType, attributes, fieldElement.field);
|
||||
|
||||
//associate fieldElement and reference bean
|
||||
fieldElement.injectedObject = referenceBeanName;
|
||||
injectedFieldReferenceBeanCache.put(fieldElement, referenceBeanName);
|
||||
|
||||
}
|
||||
|
||||
for (AnnotatedMethodElement methodElement : metadata.getMethodElements()) {
|
||||
if (methodElement.injectedObject != null) {
|
||||
continue;
|
||||
}
|
||||
Class<?> injectedType = methodElement.getInjectedType();
|
||||
AnnotationAttributes attributes = methodElement.attributes;
|
||||
String referenceBeanName = registerReferenceBean(methodElement.getPropertyName(), injectedType, attributes, methodElement.method);
|
||||
|
||||
//associate methodElement and reference bean
|
||||
methodElement.injectedObject = referenceBeanName;
|
||||
injectedMethodReferenceBeanCache.put(methodElement, referenceBeanName);
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new BeanCreationException("prepare reference annotation failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
public String registerReferenceBean(String propertyName, Class<?> injectedType, Map<String, Object> attributes, Member member) throws BeansException {
|
||||
|
||||
boolean renameable = true;
|
||||
// referenceBeanName
|
||||
String referenceBeanName = getAttribute(attributes, ReferenceAttributes.ID);
|
||||
if (hasText(referenceBeanName)) {
|
||||
renameable = false;
|
||||
} else {
|
||||
referenceBeanName = propertyName;
|
||||
}
|
||||
|
||||
String checkLocation = "Please check " + member.toString();
|
||||
|
||||
// convert annotation props
|
||||
ReferenceBeanSupport.convertReferenceProps(attributes, injectedType);
|
||||
|
||||
// get interface
|
||||
String interfaceName = (String) attributes.get(ReferenceAttributes.INTERFACE);
|
||||
if (StringUtils.isBlank(interfaceName)) {
|
||||
throw new BeanCreationException("Need to specify the 'interfaceName' or 'interfaceClass' attribute of '@DubboReference' if enable generic. " + checkLocation);
|
||||
}
|
||||
|
||||
// check reference key
|
||||
String referenceKey = ReferenceBeanSupport.generateReferenceKey(attributes, applicationContext);
|
||||
|
||||
// find reference bean name by reference key
|
||||
List<String> registeredReferenceBeanNames = referenceBeanManager.getBeanNamesByKey(referenceKey);
|
||||
if (registeredReferenceBeanNames.size() > 0) {
|
||||
// found same name and reference key
|
||||
if (registeredReferenceBeanNames.contains(referenceBeanName)) {
|
||||
return referenceBeanName;
|
||||
}
|
||||
}
|
||||
|
||||
//check bean definition
|
||||
boolean isContains;
|
||||
if ((isContains = beanDefinitionRegistry.containsBeanDefinition(referenceBeanName)) || beanDefinitionRegistry.isAlias(referenceBeanName)) {
|
||||
String preReferenceBeanName = referenceBeanName;
|
||||
if (!isContains) {
|
||||
// Look in the alias for the origin bean name
|
||||
String[] aliases = beanDefinitionRegistry.getAliases(referenceBeanName);
|
||||
if (ArrayUtils.isNotEmpty(aliases)) {
|
||||
for (String alias : aliases) {
|
||||
if (beanDefinitionRegistry.containsBeanDefinition(alias)) {
|
||||
preReferenceBeanName = alias;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BeanDefinition prevBeanDefinition = beanDefinitionRegistry.getBeanDefinition(preReferenceBeanName);
|
||||
String prevBeanType = prevBeanDefinition.getBeanClassName();
|
||||
String prevBeanDesc = referenceBeanName + "[" + prevBeanType + "]";
|
||||
String newBeanDesc = referenceBeanName + "[" + referenceKey + "]";
|
||||
|
||||
if (isReferenceBean(prevBeanDefinition)) {
|
||||
//check reference key
|
||||
String prevReferenceKey = ReferenceBeanSupport.generateReferenceKey(prevBeanDefinition, applicationContext);
|
||||
if (StringUtils.isEquals(prevReferenceKey, referenceKey)) {
|
||||
//found matched dubbo reference bean, ignore register
|
||||
return referenceBeanName;
|
||||
}
|
||||
//get interfaceName from attribute
|
||||
Assert.notNull(prevBeanDefinition, "The interface class of ReferenceBean is not initialized");
|
||||
prevBeanDesc = referenceBeanName + "[" + prevReferenceKey + "]";
|
||||
}
|
||||
|
||||
// bean name from attribute 'id' or java-config bean, cannot be renamed
|
||||
if (!renameable) {
|
||||
throw new BeanCreationException("Already exists another bean definition with the same bean name [" + referenceBeanName + "], " +
|
||||
"but cannot rename the reference bean name (specify the id attribute or java-config bean), " +
|
||||
"please modify the name of one of the beans: " +
|
||||
"prev: " + prevBeanDesc + ", new: " + newBeanDesc + ". " + checkLocation);
|
||||
}
|
||||
|
||||
// the prev bean type is different, rename the new reference bean
|
||||
int index = 2;
|
||||
String newReferenceBeanName = null;
|
||||
while (newReferenceBeanName == null || beanDefinitionRegistry.containsBeanDefinition(newReferenceBeanName)
|
||||
|| beanDefinitionRegistry.isAlias(newReferenceBeanName)) {
|
||||
newReferenceBeanName = referenceBeanName + "#" + index;
|
||||
index++;
|
||||
// double check found same name and reference key
|
||||
if (registeredReferenceBeanNames.contains(newReferenceBeanName)) {
|
||||
return newReferenceBeanName;
|
||||
}
|
||||
}
|
||||
newBeanDesc = newReferenceBeanName + "[" + referenceKey + "]";
|
||||
|
||||
logger.warn(CONFIG_DUBBO_BEAN_INITIALIZER, "", "", "Already exists another bean definition with the same bean name [" + referenceBeanName + "], " +
|
||||
"rename dubbo reference bean to [" + newReferenceBeanName + "]. " +
|
||||
"It is recommended to modify the name of one of the beans to avoid injection problems. " +
|
||||
"prev: " + prevBeanDesc + ", new: " + newBeanDesc + ". " + checkLocation);
|
||||
referenceBeanName = newReferenceBeanName;
|
||||
}
|
||||
attributes.put(ReferenceAttributes.ID, referenceBeanName);
|
||||
|
||||
// If registered matched reference before, just register alias
|
||||
if (registeredReferenceBeanNames.size() > 0) {
|
||||
beanDefinitionRegistry.registerAlias(registeredReferenceBeanNames.get(0), referenceBeanName);
|
||||
referenceBeanManager.registerReferenceKeyAndBeanName(referenceKey, referenceBeanName);
|
||||
return referenceBeanName;
|
||||
}
|
||||
|
||||
Class interfaceClass = injectedType;
|
||||
|
||||
// TODO Only register one reference bean for same (group, interface, version)
|
||||
|
||||
// Register the reference bean definition to the beanFactory
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition();
|
||||
beanDefinition.setBeanClassName(ReferenceBean.class.getName());
|
||||
beanDefinition.getPropertyValues().add(ReferenceAttributes.ID, referenceBeanName);
|
||||
|
||||
// set attribute instead of property values
|
||||
beanDefinition.setAttribute(Constants.REFERENCE_PROPS, attributes);
|
||||
beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_CLASS, interfaceClass);
|
||||
beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_NAME, interfaceName);
|
||||
// beanDefinition.getPropertyValues().add(Constants.REFERENCE_PROPS,attributes);
|
||||
beanDefinition.getPropertyValues().add(ReferenceAttributes.INTERFACE_CLASS, interfaceClass);
|
||||
beanDefinition.getPropertyValues().add(ReferenceAttributes.INTERFACE_NAME, interfaceName);
|
||||
// create decorated definition for reference bean, Avoid being instantiated when getting the beanType of ReferenceBean
|
||||
// see org.springframework.beans.factory.support.AbstractBeanFactory#getTypeForFactoryBean()
|
||||
GenericBeanDefinition targetDefinition = new GenericBeanDefinition();
|
||||
targetDefinition.setBeanClass(interfaceClass);
|
||||
beanDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, referenceBeanName + "_decorated"));
|
||||
|
||||
// signal object type since Spring 5.2
|
||||
beanDefinition.setAttribute(Constants.OBJECT_TYPE_ATTRIBUTE, interfaceClass);
|
||||
|
||||
beanDefinitionRegistry.registerBeanDefinition(referenceBeanName, beanDefinition);
|
||||
referenceBeanManager.registerReferenceKeyAndBeanName(referenceKey, referenceBeanName);
|
||||
logger.info("Register dubbo reference bean: " + referenceBeanName + " = " + referenceKey + " at " + member);
|
||||
return referenceBeanName;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
|
||||
AnnotatedInjectElement injectedElement) throws Exception {
|
||||
|
||||
if (injectedElement.injectedObject == null) {
|
||||
throw new IllegalStateException("The AnnotatedInjectElement of @DubboReference should be inited before injection");
|
||||
}
|
||||
|
||||
return getBeanFactory().getBean((String) injectedElement.injectedObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
this.referenceBeanManager = applicationContext.getBean(ReferenceBeanManager.BEAN_NAME, ReferenceBeanManager.class);
|
||||
this.beanDefinitionRegistry = (BeanDefinitionRegistry) applicationContext.getAutowireCapableBeanFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
super.destroy();
|
||||
this.injectedFieldReferenceBeanCache.clear();
|
||||
this.injectedMethodReferenceBeanCache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all beans of {@link ReferenceBean}
|
||||
*
|
||||
* @deprecated use {@link ReferenceBeanManager#getReferences()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public Collection<ReferenceBean<?>> getReferenceBeans() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link ReferenceBean} {@link Map} in injected field.
|
||||
*
|
||||
* @return non-null {@link Map}
|
||||
* @since 2.5.11
|
||||
*/
|
||||
public Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> getInjectedFieldReferenceBeanMap() {
|
||||
Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> map = new HashMap<>();
|
||||
for (Map.Entry<InjectionMetadata.InjectedElement, String> entry : injectedFieldReferenceBeanCache.entrySet()) {
|
||||
map.put(entry.getKey(), referenceBeanManager.getById(entry.getValue()));
|
||||
}
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link ReferenceBean} {@link Map} in injected method.
|
||||
*
|
||||
* @return non-null {@link Map}
|
||||
* @since 2.5.11
|
||||
*/
|
||||
public Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> getInjectedMethodReferenceBeanMap() {
|
||||
Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> map = new HashMap<>();
|
||||
for (Map.Entry<InjectionMetadata.InjectedElement, String> entry : injectedMethodReferenceBeanCache.entrySet()) {
|
||||
map.put(entry.getKey(), referenceBeanManager.getById(entry.getValue()));
|
||||
}
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private AutowireCandidateResolver getAutowireCandidateResolver() {
|
||||
if (this.beanFactory instanceof DefaultListableBeanFactory) {
|
||||
|
|
@ -665,19 +205,19 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat
|
|||
@Override
|
||||
public void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) {
|
||||
GeneratedClass generatedClass = generationContext.getGeneratedClasses()
|
||||
.addForFeatureComponent("DubboReference", this.target, type -> {
|
||||
type.addJavadoc("DubboReference for {@link $T}.", this.target);
|
||||
type.addModifiers(javax.lang.model.element.Modifier.PUBLIC);
|
||||
});
|
||||
.addForFeatureComponent("DubboReference", this.target, type -> {
|
||||
type.addJavadoc("DubboReference for {@link $T}.", this.target);
|
||||
type.addModifiers(javax.lang.model.element.Modifier.PUBLIC);
|
||||
});
|
||||
GeneratedMethod generateMethod = generatedClass.getMethods().add("apply", method -> {
|
||||
method.addJavadoc("Apply the dubbo reference.");
|
||||
method.addModifiers(javax.lang.model.element.Modifier.PUBLIC,
|
||||
javax.lang.model.element.Modifier.STATIC);
|
||||
javax.lang.model.element.Modifier.STATIC);
|
||||
method.addParameter(RegisteredBean.class, REGISTERED_BEAN_PARAMETER);
|
||||
method.addParameter(this.target, INSTANCE_PARAMETER);
|
||||
method.returns(this.target);
|
||||
method.addCode(generateMethodCode(generatedClass.getName(),
|
||||
generationContext.getRuntimeHints()));
|
||||
generationContext.getRuntimeHints()));
|
||||
});
|
||||
beanRegistrationCode.addInstancePostProcessor(generateMethod.toMethodReference());
|
||||
|
||||
|
|
@ -691,13 +231,13 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat
|
|||
if (!CollectionUtils.isEmpty(this.annotatedInjectionMetadata.getFieldElements())) {
|
||||
for (AnnotatedInjectElement referenceElement : this.annotatedInjectionMetadata.getFieldElements()) {
|
||||
code.addStatement(generateMethodStatementForElement(
|
||||
targetClassName, referenceElement, hints));
|
||||
targetClassName, referenceElement, hints));
|
||||
}
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(this.annotatedInjectionMetadata.getMethodElements())) {
|
||||
for (AnnotatedInjectElement referenceElement : this.annotatedInjectionMetadata.getMethodElements()) {
|
||||
code.addStatement(generateMethodStatementForElement(
|
||||
targetClassName, referenceElement, hints));
|
||||
targetClassName, referenceElement, hints));
|
||||
}
|
||||
}
|
||||
code.addStatement("return $L", INSTANCE_PARAMETER);
|
||||
|
|
@ -723,14 +263,14 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat
|
|||
|
||||
if (member instanceof Field) {
|
||||
return generateMethodStatementForField(
|
||||
targetClassName, (Field) member, attributes, injectedObject, hints);
|
||||
targetClassName, (Field) member, attributes, injectedObject, hints);
|
||||
}
|
||||
if (member instanceof Method) {
|
||||
return generateMethodStatementForMethod(
|
||||
targetClassName, (Method) member, attributes, injectedObject, hints);
|
||||
targetClassName, (Method) member, attributes, injectedObject, hints);
|
||||
}
|
||||
throw new IllegalStateException(
|
||||
"Unsupported member type " + member.getClass().getName());
|
||||
"Unsupported member type " + member.getClass().getName());
|
||||
}
|
||||
|
||||
private CodeBlock generateMethodStatementForField(ClassName targetClassName,
|
||||
|
|
@ -738,17 +278,17 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat
|
|||
|
||||
hints.reflection().registerField(field);
|
||||
CodeBlock resolver = CodeBlock.of("$T.$L($S)",
|
||||
ReferencedFieldValueResolver.class,
|
||||
"forRequiredField", field.getName());
|
||||
ReferencedFieldValueResolver.class,
|
||||
"forRequiredField", field.getName());
|
||||
CodeBlock shortcutResolver = CodeBlock.of("$L.withShortcut($S)", resolver, injectedObject);
|
||||
AccessControl accessControl = AccessControl.forMember(field);
|
||||
|
||||
if (!accessControl.isAccessibleFrom(targetClassName)) {
|
||||
return CodeBlock.of("$L.resolveAndSet($L, $L)", shortcutResolver,
|
||||
REGISTERED_BEAN_PARAMETER, INSTANCE_PARAMETER);
|
||||
REGISTERED_BEAN_PARAMETER, INSTANCE_PARAMETER);
|
||||
}
|
||||
return CodeBlock.of("$L.$L = $L.resolve($L)", INSTANCE_PARAMETER,
|
||||
field.getName(), shortcutResolver, REGISTERED_BEAN_PARAMETER);
|
||||
field.getName(), shortcutResolver, REGISTERED_BEAN_PARAMETER);
|
||||
}
|
||||
|
||||
private CodeBlock generateMethodStatementForMethod(ClassName targetClassName,
|
||||
|
|
@ -776,9 +316,9 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat
|
|||
} else {
|
||||
hints.reflection().registerMethod(method, ExecutableMode.INTROSPECT);
|
||||
CodeBlock arguments = new AutowiredArgumentsCodeGenerator(this.target,
|
||||
method).generateCode(method.getParameterTypes());
|
||||
method).generateCode(method.getParameterTypes());
|
||||
CodeBlock injectionCode = CodeBlock.of("args -> $L.$L($L)",
|
||||
INSTANCE_PARAMETER, method.getName(), arguments);
|
||||
INSTANCE_PARAMETER, method.getName(), arguments);
|
||||
code.add(".resolve($L, $L)", REGISTERED_BEAN_PARAMETER, injectionCode);
|
||||
}
|
||||
return code.build();
|
||||
|
|
@ -832,7 +372,7 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat
|
|||
private void registerProxyIfNecessary(RuntimeHints runtimeHints, DependencyDescriptor dependencyDescriptor) {
|
||||
if (this.candidateResolver != null) {
|
||||
Class<?> proxyClass =
|
||||
this.candidateResolver.getLazyResolutionProxyClass(dependencyDescriptor, null);
|
||||
this.candidateResolver.getLazyResolutionProxyClass(dependencyDescriptor, null);
|
||||
if (proxyClass != null) {
|
||||
ClassHintUtils.registerProxyIfNecessary(proxyClass, runtimeHints);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ package org.apache.dubbo.config.spring6.beans.factory.annotation;
|
|||
|
||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.config.annotation.Service;
|
||||
import org.apache.dubbo.config.spring.ServiceBean;
|
||||
import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor;
|
||||
import org.apache.dubbo.config.spring.schema.AnnotationBeanDefinitionParser;
|
||||
|
|
@ -29,21 +28,19 @@ import org.springframework.aot.hint.TypeReference;
|
|||
import org.springframework.beans.factory.aot.BeanRegistrationAotContribution;
|
||||
import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor;
|
||||
import org.springframework.beans.factory.aot.BeanRegistrationCode;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
|
||||
import org.springframework.beans.factory.support.RegisteredBean;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A {@link BeanFactoryPostProcessor} used for processing of {@link Service @Service} annotated classes and annotated bean in java config classes.
|
||||
* It's also the infrastructure class of XML {@link BeanDefinitionParser} on <dubbo:annotation />
|
||||
* The purpose of implementing {@link BeanRegistrationAotProcessor} is to
|
||||
* supplement for {@link ServiceAnnotationPostProcessor} ability of AOT.
|
||||
*
|
||||
* @see AnnotationBeanDefinitionParser
|
||||
* @see BeanDefinitionRegistryPostProcessor
|
||||
* @since 3.2
|
||||
* @since 3.3
|
||||
*/
|
||||
public class ServiceAnnotationWithAotPostProcessor extends ServiceAnnotationPostProcessor implements BeanRegistrationAotProcessor {
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
<properties>
|
||||
<skip_maven_deploy>true</skip_maven_deploy>
|
||||
<spring-boot-maven-plugin.version>2.7.14</spring-boot-maven-plugin.version>
|
||||
<spring-boot-maven-plugin.version>2.7.15</spring-boot-maven-plugin.version>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<properties>
|
||||
<skip_maven_deploy>true</skip_maven_deploy>
|
||||
<spring-boot-maven-plugin.version>2.7.14</spring-boot-maven-plugin.version>
|
||||
<spring-boot-maven-plugin.version>2.7.15</spring-boot-maven-plugin.version>
|
||||
</properties>
|
||||
|
||||
<artifactId>dubbo-demo-api</artifactId>
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@
|
|||
<plugin>
|
||||
<groupId>org.graalvm.buildtools</groupId>
|
||||
<artifactId>native-maven-plugin</artifactId>
|
||||
<version>0.9.24</version>
|
||||
<version>0.9.27</version>
|
||||
<configuration>
|
||||
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
|
||||
<metadataRepository>
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@
|
|||
<plugin>
|
||||
<groupId>org.graalvm.buildtools</groupId>
|
||||
<artifactId>native-maven-plugin</artifactId>
|
||||
<version>0.9.24</version>
|
||||
<version>0.9.27</version>
|
||||
<configuration>
|
||||
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
|
||||
<metadataRepository>
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<slf4j-log4j12.version>1.7.33</slf4j-log4j12.version>
|
||||
<spring-boot.version>2.7.14</spring-boot.version>
|
||||
<spring-boot.version>2.7.15</spring-boot.version>
|
||||
<skip_maven_deploy>true</skip_maven_deploy>
|
||||
</properties>
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<slf4j-log4j12.version>1.7.33</slf4j-log4j12.version>
|
||||
<spring-boot.version>2.7.14</spring-boot.version>
|
||||
<spring-boot.version>2.7.15</spring-boot.version>
|
||||
<skip_maven_deploy>true</skip_maven_deploy>
|
||||
</properties>
|
||||
|
||||
|
|
|
|||
|
|
@ -36,9 +36,9 @@
|
|||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<skip_maven_deploy>true</skip_maven_deploy>
|
||||
<spring-boot.version>2.7.14</spring-boot.version>
|
||||
<spring-boot-maven-plugin.version>2.7.14</spring-boot-maven-plugin.version>
|
||||
<micrometer-core.version>1.11.3</micrometer-core.version>
|
||||
<spring-boot.version>2.7.15</spring-boot.version>
|
||||
<spring-boot-maven-plugin.version>2.7.15</spring-boot-maven-plugin.version>
|
||||
<micrometer-core.version>1.11.4</micrometer-core.version>
|
||||
</properties>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
<properties>
|
||||
<skip_maven_deploy>true</skip_maven_deploy>
|
||||
<spring-boot-maven-plugin.version>2.7.14</spring-boot-maven-plugin.version>
|
||||
<spring-boot-maven-plugin.version>2.7.15</spring-boot-maven-plugin.version>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
|
|
|
|||
|
|
@ -92,17 +92,17 @@
|
|||
<!-- Common libs -->
|
||||
<!-- <spring_version>4.3.30.RELEASE</spring_version> -->
|
||||
<spring_version>5.3.25</spring_version>
|
||||
<spring_security_version>5.8.5</spring_security_version>
|
||||
<spring_security_version>5.8.6</spring_security_version>
|
||||
<javassist_version>3.29.2-GA</javassist_version>
|
||||
<bytebuddy.version>1.14.6</bytebuddy.version>
|
||||
<bytebuddy.version>1.14.8</bytebuddy.version>
|
||||
<netty_version>3.2.10.Final</netty_version>
|
||||
<netty4_version>4.1.95.Final</netty4_version>
|
||||
<netty4_version>4.1.97.Final</netty4_version>
|
||||
<mina_version>2.2.1</mina_version>
|
||||
<grizzly_version>2.4.4</grizzly_version>
|
||||
<httpclient_version>4.5.14</httpclient_version>
|
||||
<httpcore_version>4.4.16</httpcore_version>
|
||||
<fastjson_version>1.2.83</fastjson_version>
|
||||
<fastjson2_version>2.0.39</fastjson2_version>
|
||||
<fastjson2_version>2.0.40</fastjson2_version>
|
||||
<zookeeper_version>3.4.14</zookeeper_version>
|
||||
<curator_version>4.3.0</curator_version>
|
||||
<curator_test_version>2.12.0</curator_test_version>
|
||||
|
|
@ -112,12 +112,12 @@
|
|||
<consul_client_version>1.5.3</consul_client_version>
|
||||
<xmemcached_version>1.4.3</xmemcached_version>
|
||||
<cxf_version>3.5.5</cxf_version>
|
||||
<thrift_version>0.18.1</thrift_version>
|
||||
<thrift_version>0.19.0</thrift_version>
|
||||
<hessian_version>4.0.66</hessian_version>
|
||||
<protobuf-java_version>3.24.1</protobuf-java_version>
|
||||
<protobuf-java_version>3.24.3</protobuf-java_version>
|
||||
<javax_annotation-api_version>1.3.2</javax_annotation-api_version>
|
||||
<servlet_version>3.1.0</servlet_version>
|
||||
<jetty_version>9.4.51.v20230217</jetty_version>
|
||||
<jetty_version>9.4.52.v20230823</jetty_version>
|
||||
<validation_new_version>3.0.2</validation_new_version>
|
||||
<validation_version>1.1.0.Final</validation_version>
|
||||
<hibernate_validator_version>5.4.3.Final</hibernate_validator_version>
|
||||
|
|
@ -129,18 +129,18 @@
|
|||
<fst_version>2.57</fst_version>
|
||||
<avro_version>1.11.1</avro_version>
|
||||
<apollo_client_version>2.1.0</apollo_client_version>
|
||||
<snakeyaml_version>2.1</snakeyaml_version>
|
||||
<snakeyaml_version>2.2</snakeyaml_version>
|
||||
<commons_lang3_version>3.12.0</commons_lang3_version>
|
||||
<protostuff_version>1.8.0</protostuff_version>
|
||||
<envoy_api_version>0.1.35</envoy_api_version>
|
||||
<micrometer.version>1.11.3</micrometer.version>
|
||||
<micrometer.version>1.11.4</micrometer.version>
|
||||
<opentelemetry.version>1.26.0</opentelemetry.version>
|
||||
<zipkin-reporter.version>2.16.4</zipkin-reporter.version>
|
||||
<micrometer-tracing.version>1.1.4</micrometer-tracing.version>
|
||||
<micrometer-tracing.version>1.1.5</micrometer-tracing.version>
|
||||
<t_digest.version>3.3</t_digest.version>
|
||||
<prometheus_client.version>0.16.0</prometheus_client.version>
|
||||
<reactive.version>1.0.4</reactive.version>
|
||||
<reactor.version>3.5.9</reactor.version>
|
||||
<reactor.version>3.5.10</reactor.version>
|
||||
<rxjava.version>2.2.21</rxjava.version>
|
||||
<okhttp_version>3.14.9</okhttp_version>
|
||||
|
||||
|
|
@ -152,7 +152,7 @@
|
|||
<nacos_version>2.2.4</nacos_version>
|
||||
<sentinel.version>1.8.6</sentinel.version>
|
||||
<seata.version>1.6.1</seata.version>
|
||||
<grpc.version>1.57.2</grpc.version>
|
||||
<grpc.version>1.58.0</grpc.version>
|
||||
<grpc_contrib_verdion>0.8.1</grpc_contrib_verdion>
|
||||
<jprotoc_version>1.2.2</jprotoc_version>
|
||||
<!-- Log libs -->
|
||||
|
|
@ -177,7 +177,7 @@
|
|||
|
||||
<jaxb_version>2.2.7</jaxb_version>
|
||||
<activation_version>1.2.0</activation_version>
|
||||
<test_container_version>1.18.3</test_container_version>
|
||||
<test_container_version>1.19.0</test_container_version>
|
||||
<etcd_launcher_version>0.7.6</etcd_launcher_version>
|
||||
<hessian_lite_version>3.2.13</hessian_lite_version>
|
||||
<swagger_version>1.6.11</swagger_version>
|
||||
|
|
|
|||
|
|
@ -190,6 +190,13 @@
|
|||
</dependency>
|
||||
|
||||
<!-- metrics -->
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics-event</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics-api</artifactId>
|
||||
|
|
@ -697,6 +704,7 @@
|
|||
<include>org.apache.dubbo:dubbo-metadata-report-nacos</include>
|
||||
<include>org.apache.dubbo:dubbo-metadata-report-redis</include>
|
||||
<include>org.apache.dubbo:dubbo-metadata-report-zookeeper</include>
|
||||
<include>org.apache.dubbo:dubbo-metrics-event</include>
|
||||
<include>org.apache.dubbo:dubbo-metrics-api</include>
|
||||
<include>org.apache.dubbo:dubbo-metrics-default</include>
|
||||
<include>org.apache.dubbo:dubbo-metrics-registry</include>
|
||||
|
|
|
|||
|
|
@ -251,6 +251,11 @@
|
|||
<artifactId>dubbo-metrics-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics-event</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics-default</artifactId>
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package org.apache.dubbo.validation.filter;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.extension.Activate;
|
||||
import org.apache.dubbo.common.utils.ConfigUtils;
|
||||
import org.apache.dubbo.rpc.AsyncRpcResult;
|
||||
|
|
@ -82,8 +83,7 @@ public class ValidationFilter implements Filter {
|
|||
*/
|
||||
@Override
|
||||
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
|
||||
if (validation != null && !invocation.getMethodName().startsWith("$")
|
||||
&& ConfigUtils.isNotEmpty(invoker.getUrl().getMethodParameter(invocation.getMethodName(), VALIDATION_KEY))) {
|
||||
if (needValidate(invoker.getUrl(), invocation.getMethodName())) {
|
||||
try {
|
||||
Validator validator = validation.getValidator(invoker.getUrl());
|
||||
if (validator != null) {
|
||||
|
|
@ -98,4 +98,8 @@ public class ValidationFilter implements Filter {
|
|||
return invoker.invoke(invocation);
|
||||
}
|
||||
|
||||
private boolean needValidate(URL url, String methodName) {
|
||||
return validation != null && !methodName.startsWith("$") && ConfigUtils.isNotEmpty(url.getMethodParameter(methodName, VALIDATION_KEY));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import org.apache.dubbo.common.bytecode.ClassGenerator;
|
|||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.common.utils.ReflectUtils;
|
||||
import org.apache.dubbo.common.utils.StringUtils;
|
||||
import org.apache.dubbo.validation.MethodValidated;
|
||||
import org.apache.dubbo.validation.Validator;
|
||||
|
||||
|
|
@ -57,6 +58,7 @@ import java.lang.annotation.Annotation;
|
|||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
|
@ -89,7 +91,7 @@ public class JValidator implements Validator {
|
|||
this.clazz = ReflectUtils.forName(url.getServiceInterface());
|
||||
String jvalidation = url.getParameter("jvalidation");
|
||||
ValidatorFactory factory;
|
||||
if (jvalidation != null && jvalidation.length() > 0) {
|
||||
if (StringUtils.isNotEmpty(jvalidation)) {
|
||||
factory = Validation.byProvider((Class) ReflectUtils.forName(jvalidation)).configure().buildValidatorFactory();
|
||||
} else {
|
||||
factory = Validation.buildDefaultValidatorFactory();
|
||||
|
|
@ -111,8 +113,9 @@ public class JValidator implements Validator {
|
|||
parameterClass = generateMethodParameterClass(clazz, method, parameterClassName);
|
||||
}
|
||||
Object parameterBean = parameterClass.getDeclaredConstructor().newInstance();
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
Field field = parameterClass.getField(method.getName() + "Argument" + i);
|
||||
Parameter[] parameters = method.getParameters();
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
Field field = parameterClass.getField(parameters[i].getName());
|
||||
field.set(parameterBean, args[i]);
|
||||
}
|
||||
return parameterBean;
|
||||
|
|
@ -129,10 +132,9 @@ public class JValidator implements Validator {
|
|||
* @param method invoke method
|
||||
* @param parameterClassName generated parameterClassName
|
||||
* @return Class<?> generated methodParameterClass
|
||||
* @throws Exception
|
||||
*/
|
||||
private static Class<?> generateMethodParameterClass(Class<?> clazz, Method method, String parameterClassName)
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
ClassPool pool = ClassGenerator.getClassPool(clazz.getClassLoader());
|
||||
synchronized (parameterClassName.intern()) {
|
||||
CtClass ctClass = null;
|
||||
|
|
@ -144,28 +146,26 @@ public class JValidator implements Validator {
|
|||
if (null == ctClass) {
|
||||
ctClass = pool.makeClass(parameterClassName);
|
||||
ClassFile classFile = ctClass.getClassFile();
|
||||
classFile.setVersionToJava5();
|
||||
ctClass.addConstructor(CtNewConstructor.defaultConstructor(pool.getCtClass(parameterClassName)));
|
||||
// parameter fields
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
Parameter[] parameters = method.getParameters();
|
||||
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
Class<?> type = parameterTypes[i];
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
Annotation[] annotations = parameterAnnotations[i];
|
||||
AnnotationsAttribute attribute = new AnnotationsAttribute(classFile.getConstPool(), AnnotationsAttribute.visibleTag);
|
||||
for (Annotation annotation : annotations) {
|
||||
if (annotation.annotationType().isAnnotationPresent(Constraint.class)) {
|
||||
javassist.bytecode.annotation.Annotation ja = new javassist.bytecode.annotation.Annotation(
|
||||
classFile.getConstPool(), pool.getCtClass(annotation.annotationType().getName()));
|
||||
classFile.getConstPool(), pool.getCtClass(annotation.annotationType().getName()));
|
||||
Method[] members = annotation.annotationType().getMethods();
|
||||
for (Method member : members) {
|
||||
if (Modifier.isPublic(member.getModifiers())
|
||||
&& member.getParameterTypes().length == 0
|
||||
&& member.getDeclaringClass() == annotation.annotationType()) {
|
||||
&& member.getParameterTypes().length == 0
|
||||
&& member.getDeclaringClass() == annotation.annotationType()) {
|
||||
Object value = member.invoke(annotation);
|
||||
if (null != value) {
|
||||
MemberValue memberValue = createMemberValue(
|
||||
classFile.getConstPool(), pool.get(member.getReturnType().getName()), value);
|
||||
classFile.getConstPool(), pool.get(member.getReturnType().getName()), value);
|
||||
ja.addMemberValue(member.getName(), memberValue);
|
||||
}
|
||||
}
|
||||
|
|
@ -173,12 +173,14 @@ public class JValidator implements Validator {
|
|||
attribute.addAnnotation(ja);
|
||||
}
|
||||
}
|
||||
String fieldName = method.getName() + "Argument" + i;
|
||||
Parameter parameter = parameters[i];
|
||||
Class<?> type = parameter.getType();
|
||||
String fieldName = parameter.getName();
|
||||
CtField ctField = CtField.make("public " + type.getCanonicalName() + " " + fieldName + ";", pool.getCtClass(parameterClassName));
|
||||
ctField.getFieldInfo().addAttribute(attribute);
|
||||
ctClass.addField(ctField);
|
||||
}
|
||||
return ctClass.toClass(clazz.getClassLoader(), null);
|
||||
return pool.toClass(ctClass, clazz, clazz.getClassLoader(), clazz.getProtectionDomain());
|
||||
} else {
|
||||
return Class.forName(parameterClassName, true, clazz.getClassLoader());
|
||||
}
|
||||
|
|
@ -187,13 +189,16 @@ public class JValidator implements Validator {
|
|||
|
||||
private static String generateMethodParameterClassName(Class<?> clazz, Method method) {
|
||||
StringBuilder builder = new StringBuilder().append(clazz.getName())
|
||||
.append('_')
|
||||
.append(toUpperMethoName(method.getName()))
|
||||
.append("Parameter");
|
||||
.append('_')
|
||||
.append(toUpperMethodName(method.getName()))
|
||||
.append("Parameter");
|
||||
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
for (Class<?> parameterType : parameterTypes) {
|
||||
builder.append('_').append(parameterType.getName());
|
||||
// In order to ensure that the parameter class can be generated correctly,
|
||||
// replace "." with "_" to make the package name of the generated parameter class
|
||||
// consistent with the package name of the actual parameter class.
|
||||
builder.append('_').append(parameterType.getName().replace(".", "_"));
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
|
|
@ -201,19 +206,17 @@ public class JValidator implements Validator {
|
|||
|
||||
private static boolean hasConstraintParameter(Method method) {
|
||||
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
|
||||
if (parameterAnnotations != null && parameterAnnotations.length > 0) {
|
||||
for (Annotation[] annotations : parameterAnnotations) {
|
||||
for (Annotation annotation : annotations) {
|
||||
if (annotation.annotationType().isAnnotationPresent(Constraint.class)) {
|
||||
return true;
|
||||
}
|
||||
for (Annotation[] annotations : parameterAnnotations) {
|
||||
for (Annotation annotation : annotations) {
|
||||
if (annotation.annotationType().isAnnotationPresent(Constraint.class)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String toUpperMethoName(String methodName) {
|
||||
private static String toUpperMethodName(String methodName) {
|
||||
return methodName.substring(0, 1).toUpperCase() + methodName.substring(1);
|
||||
}
|
||||
|
||||
|
|
@ -263,7 +266,7 @@ public class JValidator implements Validator {
|
|||
if (methodClass != null) {
|
||||
groups.add(methodClass);
|
||||
}
|
||||
Set<ConstraintViolation<?>> violations = new HashSet<>();
|
||||
|
||||
Method method = clazz.getMethod(methodName, parameterTypes);
|
||||
Class<?>[] methodClasses;
|
||||
if (method.isAnnotationPresent(MethodValidated.class)) {
|
||||
|
|
@ -275,15 +278,16 @@ public class JValidator implements Validator {
|
|||
groups.add(1, clazz);
|
||||
|
||||
// convert list to array
|
||||
Class<?>[] classgroups = groups.toArray(new Class[groups.size()]);
|
||||
Class<?>[] classGroups = groups.toArray(new Class[0]);
|
||||
|
||||
Set<ConstraintViolation<?>> violations = new HashSet<>();
|
||||
Object parameterBean = getMethodParameterBean(clazz, method, arguments);
|
||||
if (parameterBean != null) {
|
||||
violations.addAll(validator.validate(parameterBean, classgroups));
|
||||
violations.addAll(validator.validate(parameterBean, classGroups));
|
||||
}
|
||||
|
||||
for (Object arg : arguments) {
|
||||
validate(violations, arg, classgroups);
|
||||
validate(violations, arg, classGroups);
|
||||
}
|
||||
|
||||
if (!violations.isEmpty()) {
|
||||
|
|
@ -294,7 +298,7 @@ public class JValidator implements Validator {
|
|||
|
||||
private Class<?> methodClass(String methodName) {
|
||||
Class<?> methodClass = null;
|
||||
String methodClassName = clazz.getName() + "$" + toUpperMethoName(methodName);
|
||||
String methodClassName = clazz.getName() + "$" + toUpperMethodName(methodName);
|
||||
Class<?> cached = methodClassMap.get(methodClassName);
|
||||
if (cached != null) {
|
||||
return cached == clazz ? null : cached;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import org.apache.dubbo.common.bytecode.ClassGenerator;
|
|||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.common.utils.ReflectUtils;
|
||||
import org.apache.dubbo.common.utils.StringUtils;
|
||||
import org.apache.dubbo.validation.MethodValidated;
|
||||
import org.apache.dubbo.validation.Validator;
|
||||
|
||||
|
|
@ -57,6 +58,7 @@ import java.lang.annotation.Annotation;
|
|||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
|
@ -89,7 +91,7 @@ public class JValidatorNew implements Validator {
|
|||
this.clazz = ReflectUtils.forName(url.getServiceInterface());
|
||||
String jvalidation = url.getParameter("jvalidationNew");
|
||||
ValidatorFactory factory;
|
||||
if (jvalidation != null && jvalidation.length() > 0) {
|
||||
if (StringUtils.isNotEmpty(jvalidation)) {
|
||||
factory = Validation.byProvider((Class) ReflectUtils.forName(jvalidation)).configure().buildValidatorFactory();
|
||||
} else {
|
||||
factory = Validation.buildDefaultValidatorFactory();
|
||||
|
|
@ -111,8 +113,9 @@ public class JValidatorNew implements Validator {
|
|||
parameterClass = generateMethodParameterClass(clazz, method, parameterClassName);
|
||||
}
|
||||
Object parameterBean = parameterClass.getDeclaredConstructor().newInstance();
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
Field field = parameterClass.getField(method.getName() + "Argument" + i);
|
||||
Parameter[] parameters = method.getParameters();
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
Field field = parameterClass.getField(parameters[i].getName());
|
||||
field.set(parameterBean, args[i]);
|
||||
}
|
||||
return parameterBean;
|
||||
|
|
@ -129,10 +132,9 @@ public class JValidatorNew implements Validator {
|
|||
* @param method invoke method
|
||||
* @param parameterClassName generated parameterClassName
|
||||
* @return Class<?> generated methodParameterClass
|
||||
* @throws Exception
|
||||
*/
|
||||
private static Class<?> generateMethodParameterClass(Class<?> clazz, Method method, String parameterClassName)
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
ClassPool pool = ClassGenerator.getClassPool(clazz.getClassLoader());
|
||||
synchronized (parameterClassName.intern()) {
|
||||
CtClass ctClass = null;
|
||||
|
|
@ -144,28 +146,26 @@ public class JValidatorNew implements Validator {
|
|||
if (null == ctClass) {
|
||||
ctClass = pool.makeClass(parameterClassName);
|
||||
ClassFile classFile = ctClass.getClassFile();
|
||||
classFile.setVersionToJava5();
|
||||
ctClass.addConstructor(CtNewConstructor.defaultConstructor(pool.getCtClass(parameterClassName)));
|
||||
// parameter fields
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
Parameter[] parameters = method.getParameters();
|
||||
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
Class<?> type = parameterTypes[i];
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
Annotation[] annotations = parameterAnnotations[i];
|
||||
AnnotationsAttribute attribute = new AnnotationsAttribute(classFile.getConstPool(), AnnotationsAttribute.visibleTag);
|
||||
for (Annotation annotation : annotations) {
|
||||
if (annotation.annotationType().isAnnotationPresent(Constraint.class)) {
|
||||
javassist.bytecode.annotation.Annotation ja = new javassist.bytecode.annotation.Annotation(
|
||||
classFile.getConstPool(), pool.getCtClass(annotation.annotationType().getName()));
|
||||
classFile.getConstPool(), pool.getCtClass(annotation.annotationType().getName()));
|
||||
Method[] members = annotation.annotationType().getMethods();
|
||||
for (Method member : members) {
|
||||
if (Modifier.isPublic(member.getModifiers())
|
||||
&& member.getParameterTypes().length == 0
|
||||
&& member.getDeclaringClass() == annotation.annotationType()) {
|
||||
&& member.getParameterTypes().length == 0
|
||||
&& member.getDeclaringClass() == annotation.annotationType()) {
|
||||
Object value = member.invoke(annotation);
|
||||
if (null != value) {
|
||||
MemberValue memberValue = createMemberValue(
|
||||
classFile.getConstPool(), pool.get(member.getReturnType().getName()), value);
|
||||
classFile.getConstPool(), pool.get(member.getReturnType().getName()), value);
|
||||
ja.addMemberValue(member.getName(), memberValue);
|
||||
}
|
||||
}
|
||||
|
|
@ -173,12 +173,14 @@ public class JValidatorNew implements Validator {
|
|||
attribute.addAnnotation(ja);
|
||||
}
|
||||
}
|
||||
String fieldName = method.getName() + "Argument" + i;
|
||||
Parameter parameter = parameters[i];
|
||||
Class<?> type = parameter.getType();
|
||||
String fieldName = parameter.getName();
|
||||
CtField ctField = CtField.make("public " + type.getCanonicalName() + " " + fieldName + ";", pool.getCtClass(parameterClassName));
|
||||
ctField.getFieldInfo().addAttribute(attribute);
|
||||
ctClass.addField(ctField);
|
||||
}
|
||||
return ctClass.toClass(clazz.getClassLoader(), null);
|
||||
return pool.toClass(ctClass, clazz, clazz.getClassLoader(), clazz.getProtectionDomain());
|
||||
} else {
|
||||
return Class.forName(parameterClassName, true, clazz.getClassLoader());
|
||||
}
|
||||
|
|
@ -187,13 +189,16 @@ public class JValidatorNew implements Validator {
|
|||
|
||||
private static String generateMethodParameterClassName(Class<?> clazz, Method method) {
|
||||
StringBuilder builder = new StringBuilder().append(clazz.getName())
|
||||
.append('_')
|
||||
.append(toUpperMethoName(method.getName()))
|
||||
.append("Parameter");
|
||||
.append('_')
|
||||
.append(toUpperMethodName(method.getName()))
|
||||
.append("Parameter");
|
||||
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
for (Class<?> parameterType : parameterTypes) {
|
||||
builder.append('_').append(parameterType.getName());
|
||||
// In order to ensure that the parameter class can be generated correctly,
|
||||
// replace "." with "_" to make the package name of the generated parameter class
|
||||
// consistent with the package name of the actual parameter class.
|
||||
builder.append('_').append(parameterType.getName().replace(".", "_"));
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
|
|
@ -201,19 +206,17 @@ public class JValidatorNew implements Validator {
|
|||
|
||||
private static boolean hasConstraintParameter(Method method) {
|
||||
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
|
||||
if (parameterAnnotations.length > 0) {
|
||||
for (Annotation[] annotations : parameterAnnotations) {
|
||||
for (Annotation annotation : annotations) {
|
||||
if (annotation.annotationType().isAnnotationPresent(Constraint.class)) {
|
||||
return true;
|
||||
}
|
||||
for (Annotation[] annotations : parameterAnnotations) {
|
||||
for (Annotation annotation : annotations) {
|
||||
if (annotation.annotationType().isAnnotationPresent(Constraint.class)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String toUpperMethoName(String methodName) {
|
||||
private static String toUpperMethodName(String methodName) {
|
||||
return methodName.substring(0, 1).toUpperCase() + methodName.substring(1);
|
||||
}
|
||||
|
||||
|
|
@ -263,7 +266,7 @@ public class JValidatorNew implements Validator {
|
|||
if (methodClass != null) {
|
||||
groups.add(methodClass);
|
||||
}
|
||||
Set<ConstraintViolation<?>> violations = new HashSet<>();
|
||||
|
||||
Method method = clazz.getMethod(methodName, parameterTypes);
|
||||
Class<?>[] methodClasses;
|
||||
if (method.isAnnotationPresent(MethodValidated.class)) {
|
||||
|
|
@ -275,15 +278,16 @@ public class JValidatorNew implements Validator {
|
|||
groups.add(1, clazz);
|
||||
|
||||
// convert list to array
|
||||
Class<?>[] classgroups = groups.toArray(new Class[groups.size()]);
|
||||
Class<?>[] classGroups = groups.toArray(new Class[0]);
|
||||
|
||||
Set<ConstraintViolation<?>> violations = new HashSet<>();
|
||||
Object parameterBean = getMethodParameterBean(clazz, method, arguments);
|
||||
if (parameterBean != null) {
|
||||
violations.addAll(validator.validate(parameterBean, classgroups));
|
||||
violations.addAll(validator.validate(parameterBean, classGroups));
|
||||
}
|
||||
|
||||
for (Object arg : arguments) {
|
||||
validate(violations, arg, classgroups);
|
||||
validate(violations, arg, classGroups);
|
||||
}
|
||||
|
||||
if (!violations.isEmpty()) {
|
||||
|
|
@ -294,7 +298,7 @@ public class JValidatorNew implements Validator {
|
|||
|
||||
private Class<?> methodClass(String methodName) {
|
||||
Class<?> methodClass = null;
|
||||
String methodClassName = clazz.getName() + "$" + toUpperMethoName(methodName);
|
||||
String methodClassName = clazz.getName() + "$" + toUpperMethodName(methodName);
|
||||
Class<?> cached = methodClassMap.get(methodClassName);
|
||||
if (cached != null) {
|
||||
return cached == clazz ? null : cached;
|
||||
|
|
|
|||
|
|
@ -17,17 +17,24 @@
|
|||
package org.apache.dubbo.validation.support.jvalidation;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.validation.support.jvalidation.mock.JValidatorTestTarget;
|
||||
import org.apache.dubbo.validation.support.jvalidation.mock.ValidationParameter;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import javax.validation.ValidationException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
class JValidatorTest {
|
||||
@Test
|
||||
void testItWithNonExistMethod() {
|
||||
|
|
@ -72,7 +79,7 @@ class JValidatorTest {
|
|||
void testItWithCollectionArg() throws Exception {
|
||||
URL url = URL.valueOf("test://test:11/org.apache.dubbo.validation.support.jvalidation.mock.JValidatorTestTarget");
|
||||
JValidator jValidator = new JValidator(url);
|
||||
jValidator.validate("someMethod4", new Class<?>[]{List.class}, new Object[]{Arrays.asList("parameter")});
|
||||
jValidator.validate("someMethod4", new Class<?>[]{List.class}, new Object[]{Collections.singletonList("parameter")});
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -83,4 +90,83 @@ class JValidatorTest {
|
|||
map.put("key", "value");
|
||||
jValidator.validate("someMethod5", new Class<?>[]{Map.class}, new Object[]{map});
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testItWithPrimitiveArg() {
|
||||
Assertions.assertThrows(ValidationException.class, () -> {
|
||||
URL url = URL.valueOf("test://test:11/org.apache.dubbo.validation.support.jvalidation.mock.JValidatorTestTarget");
|
||||
JValidator jValidator = new JValidator(url);
|
||||
jValidator.validate("someMethod6", new Class<?>[]{Integer.class, String.class, Long.class}, new Object[]{null, null, null});
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testItWithPrimitiveArgWithProvidedMessage() {
|
||||
URL url = URL.valueOf("test://test:11/org.apache.dubbo.validation.support.jvalidation.mock.JValidatorTestTarget");
|
||||
JValidator jValidator = new JValidator(url);
|
||||
try {
|
||||
jValidator.validate("someMethod6", new Class<?>[]{Integer.class, String.class, Long.class}, new Object[]{null, "", null});
|
||||
Assertions.fail();
|
||||
} catch (Exception e) {
|
||||
assertThat(e.getMessage(), containsString("string must not be blank"));
|
||||
assertThat(e.getMessage(), containsString("longValue must not be null"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testItWithPartialParameterValidation() {
|
||||
URL url = URL.valueOf("test://test:11/org.apache.dubbo.validation.support.jvalidation.mock.JValidatorTestTarget");
|
||||
JValidator jValidator = new JValidator(url);
|
||||
try {
|
||||
jValidator.validate("someMethod6", new Class<?>[]{Integer.class, String.class, Long.class}, new Object[]{null, "", null});
|
||||
Assertions.fail();
|
||||
} catch (Exception e) {
|
||||
assertThat(e, instanceOf(ConstraintViolationException.class));
|
||||
ConstraintViolationException e1 = (ConstraintViolationException) e;
|
||||
assertThat(e1.getConstraintViolations().size(), is(2));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testItWithNestedParameterValidationWithNullParam() {
|
||||
Assertions.assertThrows(ValidationException.class, () -> {
|
||||
URL url = URL.valueOf("test://test:11/org.apache.dubbo.validation.support.jvalidation.mock.JValidatorTestTarget");
|
||||
JValidator jValidator = new JValidator(url);
|
||||
jValidator.validate("someMethod7", new Class<?>[]{JValidatorTestTarget.BaseParam.class}, new Object[]{null});
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testItWithNestedParameterValidationWithNullNestedParam() {
|
||||
URL url = URL.valueOf("test://test:11/org.apache.dubbo.validation.support.jvalidation.mock.JValidatorTestTarget");
|
||||
JValidator jValidator = new JValidator(url);
|
||||
try {
|
||||
JValidatorTestTarget.BaseParam<JValidatorTestTarget.Param> param = new JValidatorTestTarget.BaseParam<>();
|
||||
jValidator.validate("someMethod7", new Class<?>[]{JValidatorTestTarget.BaseParam.class}, new Object[]{param});
|
||||
Assertions.fail();
|
||||
} catch (Exception e) {
|
||||
assertThat(e, instanceOf(ConstraintViolationException.class));
|
||||
ConstraintViolationException e1 = (ConstraintViolationException) e;
|
||||
assertThat(e1.getConstraintViolations().size(), is(1));
|
||||
assertThat(e1.getMessage(), containsString("body must not be null"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testItWithNestedParameterValidationWithNullNestedParams() {
|
||||
URL url = URL.valueOf("test://test:11/org.apache.dubbo.validation.support.jvalidation.mock.JValidatorTestTarget");
|
||||
JValidator jValidator = new JValidator(url);
|
||||
try {
|
||||
JValidatorTestTarget.BaseParam<JValidatorTestTarget.Param> param = new JValidatorTestTarget.BaseParam<>();
|
||||
param.setBody(new JValidatorTestTarget.Param());
|
||||
jValidator.validate("someMethod7", new Class<?>[]{JValidatorTestTarget.BaseParam.class}, new Object[]{param});
|
||||
Assertions.fail();
|
||||
} catch (Exception e) {
|
||||
assertThat(e, instanceOf(ConstraintViolationException.class));
|
||||
ConstraintViolationException e1 = (ConstraintViolationException) e;
|
||||
assertThat(e1.getConstraintViolations().size(), is(1));
|
||||
assertThat(e1.getMessage(), containsString("name must not be null"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ package org.apache.dubbo.validation.support.jvalidation.mock;
|
|||
|
||||
import org.apache.dubbo.validation.MethodValidated;
|
||||
|
||||
import org.hibernate.validator.constraints.NotBlank;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -35,7 +38,42 @@ public interface JValidatorTestTarget {
|
|||
|
||||
void someMethod5(Map<String, String> map);
|
||||
|
||||
void someMethod6(Integer intValue,
|
||||
@NotBlank(message = "string must not be blank") String string,
|
||||
@NotNull(message = "longValue must not be null") Long longValue);
|
||||
|
||||
void someMethod7(@NotNull BaseParam<Param> baseParam);
|
||||
|
||||
@interface Test2 {
|
||||
}
|
||||
|
||||
class BaseParam<T> {
|
||||
|
||||
@Valid
|
||||
@NotNull(message = "body must not be null")
|
||||
private T body;
|
||||
|
||||
public T getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public void setBody(T body) {
|
||||
this.body = body;
|
||||
}
|
||||
}
|
||||
|
||||
class Param {
|
||||
|
||||
@NotNull(message = "name must not be null")
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,11 @@
|
|||
<artifactId>dubbo-common</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics-event</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-rpc-api</artifactId>
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ public class TimeWindowCounter {
|
|||
|
||||
private final LongAdderSlidingWindow slidingWindow;
|
||||
|
||||
public TimeWindowCounter(int bucketNum, int timeWindowSeconds) {
|
||||
public TimeWindowCounter(int bucketNum, long timeWindowSeconds) {
|
||||
this.slidingWindow = new LongAdderSlidingWindow(bucketNum, TimeUnit.SECONDS.toMillis(timeWindowSeconds));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -89,6 +89,12 @@ public abstract class CombMetricsCollector<E extends TimeCounterEvent> extends A
|
|||
this.stats.incrementMethodKey(wrapper, methodMetric, size);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void init(Invocation invocation, MetricsKeyWrapper wrapper) {
|
||||
this.stats.initMethodKey(wrapper, invocation);
|
||||
}
|
||||
|
||||
protected List<MetricSample> export(MetricsCategory category) {
|
||||
return stats.export(category);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,5 +30,7 @@ public interface MethodMetricsCollector<E extends TimeCounterEvent> extends Metr
|
|||
void increment(MethodMetric methodMetric, MetricsKeyWrapper wrapper, int size);
|
||||
|
||||
void addMethodRt(Invocation invocation, String registryOpType, Long responseTime);
|
||||
|
||||
void init(Invocation invocation, MetricsKeyWrapper wrapper);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
package org.apache.dubbo.metrics.collector;
|
||||
|
||||
import org.apache.dubbo.common.extension.SPI;
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.event.TimeCounterEvent;
|
||||
import org.apache.dubbo.metrics.listener.MetricsLifeListener;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
|
|
@ -42,4 +43,6 @@ public interface MetricsCollector<E extends TimeCounterEvent> extends MetricsLif
|
|||
*/
|
||||
List<MetricSample> collect();
|
||||
|
||||
default void initMetrics(MetricsEvent event) {};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,6 +112,10 @@ public abstract class BaseStatComposite implements MetricsExport {
|
|||
methodStatComposite.incrementMethodKey(metricsKeyWrapper, methodMetric, size);
|
||||
}
|
||||
|
||||
public void initMethodKey(MetricsKeyWrapper metricsKeyWrapper, Invocation invocation) {
|
||||
methodStatComposite.initMethodKey(metricsKeyWrapper, invocation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MetricSample> export(MetricsCategory category) {
|
||||
List<MetricSample> list = new ArrayList<>();
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ 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.AbstractMetricsExport;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -40,9 +41,11 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||
* the key will not be displayed when exporting (to be optimized)
|
||||
*/
|
||||
public class MethodStatComposite extends AbstractMetricsExport {
|
||||
private boolean serviceLevel;
|
||||
|
||||
public MethodStatComposite(ApplicationModel applicationModel) {
|
||||
super(applicationModel);
|
||||
this.serviceLevel = MethodMetric.isServiceLevel(getApplicationModel());
|
||||
}
|
||||
|
||||
private final Map<MetricsKeyWrapper, Map<MethodMetric, AtomicLong>> methodNumStats = new ConcurrentHashMap<>();
|
||||
|
|
@ -54,6 +57,14 @@ public class MethodStatComposite extends AbstractMetricsExport {
|
|||
metricsKeyWrappers.forEach(appKey -> methodNumStats.put(appKey, new ConcurrentHashMap<>()));
|
||||
}
|
||||
|
||||
public void initMethodKey(MetricsKeyWrapper wrapper, Invocation invocation) {
|
||||
if (!methodNumStats.containsKey(wrapper)) {
|
||||
return;
|
||||
}
|
||||
|
||||
methodNumStats.get(wrapper).computeIfAbsent(new MethodMetric(getApplicationModel(), invocation, serviceLevel), k -> new AtomicLong(0L));
|
||||
}
|
||||
|
||||
public void incrementMethodKey(MetricsKeyWrapper wrapper, MethodMetric methodMetric, int size) {
|
||||
if (!methodNumStats.containsKey(wrapper)) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -50,9 +50,11 @@ import java.util.stream.Collectors;
|
|||
*/
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public class RtStatComposite extends AbstractMetricsExport {
|
||||
private boolean serviceLevel;
|
||||
|
||||
public RtStatComposite(ApplicationModel applicationModel) {
|
||||
super(applicationModel);
|
||||
this.serviceLevel = MethodMetric.isServiceLevel(getApplicationModel());
|
||||
}
|
||||
|
||||
private final Map<String, List<LongContainer<? extends Number>>> rtStats = new ConcurrentHashMap<>();
|
||||
|
|
@ -168,7 +170,7 @@ public class RtStatComposite extends AbstractMetricsExport {
|
|||
List<Action> actions;
|
||||
actions = new LinkedList<>();
|
||||
for (LongContainer container : rtStats.get(registryOpType)) {
|
||||
MethodMetric key = new MethodMetric(getApplicationModel(), invocation);
|
||||
MethodMetric key = new MethodMetric(getApplicationModel(), invocation, serviceLevel);
|
||||
Number current = (Number) container.get(key);
|
||||
if (current == null) {
|
||||
container.putIfAbsent(key, container.getInitFunc().apply(key));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.event;
|
||||
import org.apache.dubbo.metrics.MetricsConstants;
|
||||
import org.apache.dubbo.metrics.model.MethodMetric;
|
||||
import org.apache.dubbo.metrics.model.MetricsSupport;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsLevel;
|
||||
import org.apache.dubbo.metrics.model.key.TypeWrapper;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SERVICE;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS;
|
||||
|
||||
public class MetricsInitEvent extends TimeCounterEvent {
|
||||
|
||||
private static final TypeWrapper METRIC_EVENT = new TypeWrapper(MetricsLevel.SERVICE, METRIC_REQUESTS);
|
||||
|
||||
public MetricsInitEvent(ApplicationModel source,TypeWrapper typeWrapper) {
|
||||
super(source,typeWrapper);
|
||||
}
|
||||
|
||||
public static MetricsInitEvent toMetricsInitEvent(ApplicationModel applicationModel, Invocation invocation, boolean serviceLevel) {
|
||||
MethodMetric methodMetric = new MethodMetric(applicationModel, invocation, serviceLevel);
|
||||
MetricsInitEvent initEvent = new MetricsInitEvent(applicationModel, METRIC_EVENT);
|
||||
initEvent.putAttachment(MetricsConstants.INVOCATION, invocation);
|
||||
initEvent.putAttachment(MetricsConstants.METHOD_METRICS, methodMetric);
|
||||
initEvent.putAttachment(ATTACHMENT_KEY_SERVICE, MetricsSupport.getInterfaceName(invocation));
|
||||
initEvent.putAttachment(MetricsConstants.INVOCATION_SIDE, MetricsSupport.getSide(invocation));
|
||||
return initEvent;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -40,9 +40,6 @@ public class SimpleMetricsEventMulticaster implements MetricsEventMulticaster {
|
|||
@Override
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public void publishEvent(MetricsEvent event) {
|
||||
if (event instanceof EmptyEvent) {
|
||||
return;
|
||||
}
|
||||
if (validateIfApplicationConfigExist(event)) return;
|
||||
for (MetricsListener listener : listeners) {
|
||||
if (listener.isSupport(event)) {
|
||||
|
|
@ -74,9 +71,6 @@ public class SimpleMetricsEventMulticaster implements MetricsEventMulticaster {
|
|||
@SuppressWarnings({"rawtypes"})
|
||||
private void publishTimeEvent(MetricsEvent event, Consumer<MetricsLifeListener> consumer) {
|
||||
if (validateIfApplicationConfigExist(event)) return;
|
||||
if (event instanceof EmptyEvent) {
|
||||
return;
|
||||
}
|
||||
if (event instanceof TimeCounterEvent) {
|
||||
((TimeCounterEvent) event).getTimePair().end();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,12 +17,17 @@
|
|||
|
||||
package org.apache.dubbo.metrics.model;
|
||||
|
||||
import org.apache.dubbo.common.utils.StringUtils;
|
||||
import org.apache.dubbo.config.MetricsConfig;
|
||||
import org.apache.dubbo.config.context.ConfigManager;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsLevel;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.apache.dubbo.rpc.support.RpcUtils;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_GROUP_KEY;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_VERSION_KEY;
|
||||
|
|
@ -36,12 +41,31 @@ public class MethodMetric extends ServiceKeyMetric {
|
|||
private String group;
|
||||
private String version;
|
||||
|
||||
public MethodMetric(ApplicationModel applicationModel, Invocation invocation) {
|
||||
|
||||
public MethodMetric(ApplicationModel applicationModel, Invocation invocation, boolean serviceLevel) {
|
||||
super(applicationModel, MetricsSupport.getInterfaceName(invocation));
|
||||
this.methodName = RpcUtils.getMethodName(invocation);
|
||||
this.side = MetricsSupport.getSide(invocation);
|
||||
this.group = MetricsSupport.getGroup(invocation);
|
||||
this.version = MetricsSupport.getVersion(invocation);
|
||||
this.methodName = serviceLevel ? null : RpcUtils.getMethodName(invocation);
|
||||
}
|
||||
|
||||
|
||||
public static boolean isServiceLevel(ApplicationModel applicationModel) {
|
||||
if(applicationModel == null){
|
||||
return false;
|
||||
}
|
||||
ConfigManager applicationConfigManager = applicationModel.getApplicationConfigManager();
|
||||
if (applicationConfigManager == null) {
|
||||
return false;
|
||||
}
|
||||
Optional<MetricsConfig> metrics = applicationConfigManager.getMetrics();
|
||||
if (!metrics.isPresent()) {
|
||||
return false;
|
||||
}
|
||||
String rpcLevel = metrics.map(MetricsConfig::getRpcLevel).orElse(MetricsLevel.METHOD.name());
|
||||
rpcLevel = StringUtils.isBlank(rpcLevel) ? MetricsLevel.METHOD.name() : rpcLevel;
|
||||
return MetricsLevel.SERVICE.name().equalsIgnoreCase(rpcLevel);
|
||||
}
|
||||
|
||||
public String getGroup() {
|
||||
|
|
@ -82,13 +106,13 @@ public class MethodMetric extends ServiceKeyMetric {
|
|||
@Override
|
||||
public String toString() {
|
||||
return "MethodMetric{" +
|
||||
"applicationName='" + getApplicationName() + '\'' +
|
||||
", side='" + side + '\'' +
|
||||
", interfaceName='" + getServiceKey() + '\'' +
|
||||
", methodName='" + methodName + '\'' +
|
||||
", group='" + group + '\'' +
|
||||
", version='" + version + '\'' +
|
||||
'}';
|
||||
"applicationName='" + getApplicationName() + '\'' +
|
||||
", side='" + side + '\'' +
|
||||
", interfaceName='" + getServiceKey() + '\'' +
|
||||
", methodName='" + methodName + '\'' +
|
||||
", group='" + group + '\'' +
|
||||
", version='" + version + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -100,6 +124,7 @@ public class MethodMetric extends ServiceKeyMetric {
|
|||
}
|
||||
|
||||
private volatile int hashCode = 0;
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (hashCode == 0) {
|
||||
|
|
|
|||
|
|
@ -222,6 +222,11 @@ public class MetricsSupport {
|
|||
collector.increment(event.getAttachmentValue(METHOD_METRICS), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
|
||||
}
|
||||
|
||||
|
||||
public static void init(MetricsKey metricsKey, MetricsPlaceValue placeType, MethodMetricsCollector<TimeCounterEvent> collector, MetricsEvent event) {
|
||||
collector.init(event.getAttachmentValue(INVOCATION), new MetricsKeyWrapper(metricsKey, placeType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Dec method num
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,176 +0,0 @@
|
|||
/*
|
||||
* 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.model.key;
|
||||
|
||||
/**
|
||||
* Please follow a unified naming format as follows:
|
||||
* dubbo_type_action_unit_otherfun
|
||||
*/
|
||||
public enum MetricsKey {
|
||||
APPLICATION_METRIC_INFO("application.info.total", "Total Application Info"),
|
||||
|
||||
CONFIGCENTER_METRIC_TOTAL("configcenter.total", "Config Changed Total"),
|
||||
|
||||
// provider metrics key
|
||||
METRIC_REQUESTS("requests.total", "Total Requests"),
|
||||
METRIC_REQUESTS_SUCCEED("requests.succeed.total", "Total Succeed Requests"),
|
||||
METRIC_REQUEST_BUSINESS_FAILED("requests.business.failed.total", "Total Failed Business Requests"),
|
||||
|
||||
METRIC_REQUESTS_PROCESSING("requests.processing.total", "Processing Requests"),
|
||||
METRIC_REQUESTS_TIMEOUT("requests.timeout.total", "Total Timeout Failed Requests"),
|
||||
METRIC_REQUESTS_LIMIT("requests.limit.total", "Total Limit Failed Requests"),
|
||||
METRIC_REQUESTS_FAILED("requests.unknown.failed.total", "Total Unknown Failed Requests"),
|
||||
METRIC_REQUESTS_TOTAL_FAILED("requests.failed.total", "Total Failed Requests"),
|
||||
METRIC_REQUESTS_NETWORK_FAILED("requests.failed.network.total", "Total network Failed Requests"),
|
||||
METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED("requests.failed.service.unavailable.total", "Total Service Unavailable Failed Requests"),
|
||||
METRIC_REQUESTS_CODEC_FAILED("requests.failed.codec.total", "Total Codec Failed Requests"),
|
||||
|
||||
METRIC_REQUESTS_TOTAL_AGG("requests.total.aggregate", "Aggregated Total Requests"),
|
||||
METRIC_REQUESTS_SUCCEED_AGG("requests.succeed.aggregate", "Aggregated Succeed Requests"),
|
||||
METRIC_REQUESTS_FAILED_AGG("requests.failed.aggregate", "Aggregated Failed Requests"),
|
||||
METRIC_REQUEST_BUSINESS_FAILED_AGG("requests.business.failed.aggregate", "Aggregated Business Failed Requests"),
|
||||
METRIC_REQUESTS_TIMEOUT_AGG("requests.timeout.failed.aggregate", "Aggregated timeout Failed Requests"),
|
||||
METRIC_REQUESTS_LIMIT_AGG("requests.limit.aggregate", "Aggregated limit Requests"),
|
||||
METRIC_REQUESTS_TOTAL_FAILED_AGG("requests.failed.total.aggregate", "Aggregated failed total Requests"),
|
||||
METRIC_REQUESTS_NETWORK_FAILED_AGG("requests.failed.network.total.aggregate", "Aggregated failed network total Requests"),
|
||||
METRIC_REQUESTS_CODEC_FAILED_AGG("requests.failed.codec.total.aggregate", "Aggregated failed codec total Requests"),
|
||||
METRIC_REQUESTS_TOTAL_SERVICE_UNAVAILABLE_FAILED_AGG("requests.failed.service.unavailable.total.aggregate", "Aggregated failed codec total Requests"),
|
||||
|
||||
METRIC_QPS("qps.total", "Query Per Seconds"),
|
||||
METRIC_RT_LAST("rt.milliseconds.last", "Last Response Time"),
|
||||
METRIC_RT_MIN("rt.milliseconds.min", "Min Response Time"),
|
||||
METRIC_RT_MAX("rt.milliseconds.max", "Max Response Time"),
|
||||
METRIC_RT_SUM("rt.milliseconds.sum", "Sum Response Time"),
|
||||
METRIC_RT_AVG("rt.milliseconds.avg", "Average Response Time"),
|
||||
METRIC_RT_P99("rt.milliseconds.p99", "Response Time P99"),
|
||||
METRIC_RT_P95("rt.milliseconds.p95", "Response Time P95"),
|
||||
METRIC_RT_P90("rt.milliseconds.p90", "Response Time P90"),
|
||||
METRIC_RT_P50("rt.milliseconds.p50", "Response Time P50"),
|
||||
METRIC_RT_MIN_AGG("rt.milliseconds.min.aggregate", "Aggregated Min Response"),
|
||||
METRIC_RT_MAX_AGG("rt.milliseconds.max.aggregate", "Aggregated Max Response"),
|
||||
METRIC_RT_AVG_AGG("rt.milliseconds.avg.aggregate", "Aggregated Avg Response"),
|
||||
|
||||
// register metrics key
|
||||
REGISTER_METRIC_REQUESTS("registry.register.requests.total", "Total Register Requests"),
|
||||
REGISTER_METRIC_REQUESTS_SUCCEED("registry.register.requests.succeed.total", "Succeed Register Requests"),
|
||||
REGISTER_METRIC_REQUESTS_FAILED("registry.register.requests.failed.total", "Failed Register Requests"),
|
||||
METRIC_RT_HISTOGRAM("rt.milliseconds.histogram", "Response Time Histogram"),
|
||||
|
||||
|
||||
GENERIC_METRIC_REQUESTS("requests.total", "Total %s Requests"),
|
||||
GENERIC_METRIC_REQUESTS_SUCCEED("requests.succeed.total", "Succeed %s Requests"),
|
||||
GENERIC_METRIC_REQUESTS_FAILED("requests.failed.total", "Failed %s Requests"),
|
||||
|
||||
// subscribe metrics key
|
||||
SUBSCRIBE_METRIC_NUM("registry.subscribe.num.total", "Total Subscribe Num"),
|
||||
SUBSCRIBE_METRIC_NUM_SUCCEED("registry.subscribe.num.succeed.total", "Succeed Subscribe Num"),
|
||||
SUBSCRIBE_METRIC_NUM_FAILED("registry.subscribe.num.failed.total", "Failed Subscribe Num"),
|
||||
|
||||
// directory metrics key
|
||||
DIRECTORY_METRIC_NUM_ALL("registry.directory.num.all", "All Directory Urls"),
|
||||
DIRECTORY_METRIC_NUM_VALID("registry.directory.num.valid.total", "Valid Directory Urls"),
|
||||
DIRECTORY_METRIC_NUM_TO_RECONNECT("registry.directory.num.to_reconnect.total", "ToReconnect Directory Urls"),
|
||||
DIRECTORY_METRIC_NUM_DISABLE("registry.directory.num.disable.total", "Disable Directory Urls"),
|
||||
|
||||
NOTIFY_METRIC_REQUESTS("registry.notify.requests.total", "Total Notify Requests"),
|
||||
NOTIFY_METRIC_NUM_LAST("registry.notify.num.last", "Last Notify Nums"),
|
||||
|
||||
THREAD_POOL_CORE_SIZE("thread.pool.core.size", "Thread Pool Core Size"),
|
||||
THREAD_POOL_LARGEST_SIZE("thread.pool.largest.size", "Thread Pool Largest Size"),
|
||||
THREAD_POOL_MAX_SIZE("thread.pool.max.size", "Thread Pool Max Size"),
|
||||
THREAD_POOL_ACTIVE_SIZE("thread.pool.active.size", "Thread Pool Active Size"),
|
||||
THREAD_POOL_THREAD_COUNT("thread.pool.thread.count", "Thread Pool Thread Count"),
|
||||
THREAD_POOL_QUEUE_SIZE("thread.pool.queue.size", "Thread Pool Queue Size"),
|
||||
THREAD_POOL_THREAD_REJECT_COUNT("thread.pool.reject.thread.count", "Thread Pool Reject Thread Count"),
|
||||
|
||||
// metadata push metrics key
|
||||
METADATA_PUSH_METRIC_NUM("metadata.push.num.total", "Total Push Num"),
|
||||
METADATA_PUSH_METRIC_NUM_SUCCEED("metadata.push.num.succeed.total", "Succeed Push Num"),
|
||||
METADATA_PUSH_METRIC_NUM_FAILED("metadata.push.num.failed.total", "Failed Push Num"),
|
||||
|
||||
// metadata subscribe metrics key
|
||||
METADATA_SUBSCRIBE_METRIC_NUM("metadata.subscribe.num.total", "Total Metadata Subscribe Num"),
|
||||
METADATA_SUBSCRIBE_METRIC_NUM_SUCCEED("metadata.subscribe.num.succeed.total", "Succeed Metadata Subscribe Num"),
|
||||
METADATA_SUBSCRIBE_METRIC_NUM_FAILED("metadata.subscribe.num.failed.total", "Failed Metadata Subscribe Num"),
|
||||
|
||||
// register service metrics key
|
||||
SERVICE_REGISTER_METRIC_REQUESTS("registry.total", "Total Service-Level Register Requests"),
|
||||
SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED("registry.succeed.total", "Succeed Service-Level Register Requests"),
|
||||
SERVICE_REGISTER_METRIC_REQUESTS_FAILED("registry.failed.total", "Failed Service-Level Register Requests"),
|
||||
|
||||
// subscribe metrics key
|
||||
SERVICE_SUBSCRIBE_METRIC_NUM("registry.subscribe.service.num.total", "Total Service-Level Subscribe Num"),
|
||||
SERVICE_SUBSCRIBE_METRIC_NUM_SUCCEED("registry.subscribe.service.num.succeed.total", "Succeed Service-Level Num"),
|
||||
SERVICE_SUBSCRIBE_METRIC_NUM_FAILED("registry.subscribe.service.num.failed.total", "Failed Service-Level Num"),
|
||||
// store provider metadata service key
|
||||
STORE_PROVIDER_METADATA("metadata.store.provider.total", "Store Provider Metadata"),
|
||||
|
||||
STORE_PROVIDER_METADATA_SUCCEED("metadata.store.provider.succeed.total", "Succeed Store Provider Metadata"),
|
||||
|
||||
STORE_PROVIDER_METADATA_FAILED("metadata.store.provider.failed.total", "Failed Store Provider Metadata"),
|
||||
METADATA_GIT_COMMITID_METRIC("git.commit.id", "Git Commit Id Metrics"),
|
||||
|
||||
// consumer metrics key
|
||||
INVOKER_NO_AVAILABLE_COUNT("consumer.invoker.no.available.count", "Request Throw No Invoker Available Exception Count"),
|
||||
|
||||
// count the number of occurrences of each error code
|
||||
ERROR_CODE_COUNT("dubbo.error.code.count","The Count Of Occurrences for Each Error Code"),
|
||||
|
||||
// netty metrics key
|
||||
NETTY_ALLOCATOR_HEAP_MEMORY_USED("netty.allocator.memory.used", "Netty Allocator Memory Used"),
|
||||
NETTY_ALLOCATOR_DIRECT_MEMORY_USED("netty.allocator.direct.memory.used", "Netty Allocator Direct Memory Used"),
|
||||
NETTY_ALLOCATOR_PINNED_DIRECT_MEMORY("netty.allocator.pinned.direct.memory", "Netty Allocator Pinned Direct Memory"),
|
||||
NETTY_ALLOCATOR_PINNED_HEAP_MEMORY("netty.allocator.pinned.heap.memory", "Netty Allocator Pinned Heap Memory"),
|
||||
NETTY_ALLOCATOR_HEAP_ARENAS_NUM("netty.allocator.heap.arenas.num", "Netty Allocator Heap Arenas Num"),
|
||||
NETTY_ALLOCATOR_DIRECT_ARENAS_NUM("netty.allocator.direct.arenas.num", "Netty Allocator Direct Arenas Num"),
|
||||
NETTY_ALLOCATOR_NORMAL_CACHE_SIZE("netty.allocator.normal.cache.size", "Netty Allocator Normal Cache Size"),
|
||||
NETTY_ALLOCATOR_SMALL_CACHE_SIZE("netty.allocator.small.cache.size", "Netty Allocator Small Cache Size"),
|
||||
NETTY_ALLOCATOR_THREAD_LOCAL_CACHES_NUM("netty.allocator.thread.local.caches.num", "Netty Allocator Thread Local Caches Num"),
|
||||
NETTY_ALLOCATOR_CHUNK_SIZE("netty.allocator.chunk.size", "Netty Allocator Chunk Size"),
|
||||
;
|
||||
|
||||
private String nameSuffix;
|
||||
private String description;
|
||||
|
||||
public final String getName() {
|
||||
return "dubbo." + nameSuffix;
|
||||
}
|
||||
|
||||
public final String getNameByType(String type) {
|
||||
return "dubbo." + type + "." + nameSuffix;
|
||||
}
|
||||
|
||||
public static MetricsKey getMetricsByName(String name){
|
||||
for (MetricsKey metricsKey : MetricsKey.values()) {
|
||||
if (metricsKey.getName().equals(name)) {
|
||||
return metricsKey;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public final String getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
|
||||
MetricsKey(String nameSuffix, String description) {
|
||||
this.nameSuffix = nameSuffix;
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
|
|
@ -85,7 +85,7 @@ public class MetricsKeyWrapper {
|
|||
return metricsKey.getName();
|
||||
}
|
||||
try {
|
||||
return metricsKey.getNameByType(getType());
|
||||
return String.format(metricsKey.getName(), getType());
|
||||
} catch (Exception ignore) {
|
||||
return metricsKey.getName();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,16 +58,6 @@ public class SimpleMetricsEventMulticasterTest {
|
|||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testPublishEvent() {
|
||||
|
||||
// emptyEvent do nothing
|
||||
MetricsEvent emptyEvent = EmptyEvent.instance();
|
||||
eventMulticaster.publishEvent(emptyEvent);
|
||||
Assertions.assertSame(obj, objects[0]);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPublishFinishEvent() {
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
package org.apache.dubbo.metrics;
|
||||
|
||||
import org.apache.dubbo.common.constants.CommonConstants;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsLevel;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
|
||||
|
|
@ -69,4 +70,28 @@ public interface DefaultConstants {
|
|||
new MetricsKeyWrapper(METRIC_REQUESTS_CODEC_FAILED, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)),
|
||||
new MetricsKeyWrapper(METRIC_REQUESTS_CODEC_FAILED, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD))
|
||||
);
|
||||
|
||||
List<MetricsKey> INIT_AGG_METHOD_KEYS = Arrays.asList(
|
||||
MetricsKey.METRIC_REQUESTS_TOTAL_AGG,
|
||||
MetricsKey.METRIC_REQUESTS_SUCCEED_AGG,
|
||||
MetricsKey.METRIC_REQUESTS_FAILED_AGG,
|
||||
MetricsKey.METRIC_REQUEST_BUSINESS_FAILED_AGG,
|
||||
MetricsKey.METRIC_REQUESTS_TIMEOUT_AGG,
|
||||
MetricsKey.METRIC_REQUESTS_LIMIT_AGG,
|
||||
MetricsKey.METRIC_REQUESTS_TOTAL_FAILED_AGG,
|
||||
MetricsKey.METRIC_REQUESTS_NETWORK_FAILED_AGG,
|
||||
MetricsKey.METRIC_REQUESTS_CODEC_FAILED_AGG,
|
||||
MetricsKey.METRIC_REQUESTS_TOTAL_SERVICE_UNAVAILABLE_FAILED_AGG
|
||||
);
|
||||
|
||||
List<MetricsKey> INIT_DEFAULT_METHOD_KEYS = Arrays.asList(
|
||||
MetricsKey.METRIC_REQUESTS,
|
||||
MetricsKey.METRIC_REQUESTS_PROCESSING,
|
||||
MetricsKey.METRIC_REQUESTS_FAILED_AGG,
|
||||
MetricsKey.METRIC_REQUESTS_SUCCEED,
|
||||
MetricsKey.METRIC_REQUESTS_TOTAL_FAILED,
|
||||
MetricsKey.METRIC_REQUEST_BUSINESS_FAILED
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,9 +43,11 @@ import java.util.Map;
|
|||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
|
||||
import static org.apache.dubbo.metrics.DefaultConstants.INIT_AGG_METHOD_KEYS;
|
||||
import static org.apache.dubbo.metrics.DefaultConstants.METRIC_THROWABLE;
|
||||
import static org.apache.dubbo.metrics.model.MetricsCategory.QPS;
|
||||
import static org.apache.dubbo.metrics.model.MetricsCategory.REQUESTS;
|
||||
|
|
@ -75,6 +77,7 @@ public class AggregateMetricsCollector implements MetricsCollector<RequestEvent>
|
|||
|
||||
private final ConcurrentMap<MethodMetric, TimeWindowAggregator> rtAgr = new ConcurrentHashMap<>();
|
||||
|
||||
private boolean serviceLevel;
|
||||
|
||||
public AggregateMetricsCollector(ApplicationModel applicationModel) {
|
||||
this.applicationModel = applicationModel;
|
||||
|
|
@ -95,6 +98,7 @@ public class AggregateMetricsCollector implements MetricsCollector<RequestEvent>
|
|||
this.enableRt = Optional.ofNullable(aggregation.getEnableRt()).orElse(true);
|
||||
this.enableRequest = Optional.ofNullable(aggregation.getEnableRequest()).orElse(true);
|
||||
}
|
||||
this.serviceLevel = MethodMetric.isServiceLevel(applicationModel);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -124,7 +128,7 @@ public class AggregateMetricsCollector implements MetricsCollector<RequestEvent>
|
|||
if (enableQps) {
|
||||
MethodMetric metric = calcWindowCounter(event, MetricsKey.METRIC_REQUESTS);
|
||||
TimeWindowCounter qpsCounter = ConcurrentHashMapUtils.computeIfAbsent(qps, metric,
|
||||
methodMetric -> new TimeWindowCounter(bucketNum, qpsTimeWindowMillSeconds));
|
||||
methodMetric -> new TimeWindowCounter(bucketNum, TimeUnit.MILLISECONDS.toSeconds(qpsTimeWindowMillSeconds)));
|
||||
qpsCounter.increment();
|
||||
}
|
||||
}
|
||||
|
|
@ -156,7 +160,7 @@ public class AggregateMetricsCollector implements MetricsCollector<RequestEvent>
|
|||
}
|
||||
|
||||
private void onRTEvent(RequestEvent event) {
|
||||
MethodMetric metric = new MethodMetric(applicationModel, event.getAttachmentValue(MetricsConstants.INVOCATION));
|
||||
MethodMetric metric = new MethodMetric(applicationModel, event.getAttachmentValue(MetricsConstants.INVOCATION), serviceLevel);
|
||||
long responseTime = event.getTimePair().calc();
|
||||
if (enableRt) {
|
||||
TimeWindowQuantile quantile = ConcurrentHashMapUtils.computeIfAbsent(rt, metric,
|
||||
|
|
@ -175,7 +179,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, event.getAttachmentValue(MetricsConstants.INVOCATION));
|
||||
MethodMetric metric = new MethodMetric(applicationModel, event.getAttachmentValue(MetricsConstants.INVOCATION), serviceLevel);
|
||||
|
||||
ConcurrentMap<MethodMetric, TimeWindowCounter> counter = methodTypeCounter.computeIfAbsent(metricsKeyWrapper, k -> new ConcurrentHashMap<>());
|
||||
|
||||
|
|
@ -188,7 +192,7 @@ public class AggregateMetricsCollector implements MetricsCollector<RequestEvent>
|
|||
@Override
|
||||
public List<MetricSample> collect() {
|
||||
List<MetricSample> list = new ArrayList<>();
|
||||
if (!isCollectEnabled()){
|
||||
if (!isCollectEnabled()) {
|
||||
return list;
|
||||
}
|
||||
collectRequests(list);
|
||||
|
|
@ -262,4 +266,47 @@ public class AggregateMetricsCollector implements MetricsCollector<RequestEvent>
|
|||
applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class).getEventMulticaster().addListener(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void initMetrics(MetricsEvent event) {
|
||||
MethodMetric metric = new MethodMetric(applicationModel, event.getAttachmentValue(MetricsConstants.INVOCATION), serviceLevel);
|
||||
if (enableQps) {
|
||||
initMethodMetric(event);
|
||||
initQpsMetric(metric);
|
||||
}
|
||||
if (enableRt) {
|
||||
initRtMetric(metric);
|
||||
}
|
||||
if (enableRtPxx) {
|
||||
initRtAgrMetric(metric);
|
||||
}
|
||||
}
|
||||
|
||||
public void initMethodMetric(MetricsEvent event) {
|
||||
INIT_AGG_METHOD_KEYS.stream().forEach(key -> initWindowCounter(event, key));
|
||||
}
|
||||
|
||||
public void initQpsMetric(MethodMetric metric) {
|
||||
ConcurrentHashMapUtils.computeIfAbsent(qps, metric, methodMetric -> new TimeWindowCounter(bucketNum, timeWindowSeconds));
|
||||
}
|
||||
|
||||
public void initRtMetric(MethodMetric metric) {
|
||||
ConcurrentHashMapUtils.computeIfAbsent(rt, metric, k -> new TimeWindowQuantile(DEFAULT_COMPRESSION, bucketNum, timeWindowSeconds));
|
||||
}
|
||||
|
||||
public void initRtAgrMetric(MethodMetric metric) {
|
||||
ConcurrentHashMapUtils.computeIfAbsent(rtAgr, metric, k -> new TimeWindowAggregator(bucketNum, timeWindowSeconds));
|
||||
}
|
||||
|
||||
public void initWindowCounter(MetricsEvent event, MetricsKey targetKey) {
|
||||
|
||||
MetricsKeyWrapper metricsKeyWrapper = new MetricsKeyWrapper(targetKey, MetricsPlaceValue.of(event.getAttachmentValue(MetricsConstants.INVOCATION_SIDE), MetricsLevel.SERVICE));
|
||||
|
||||
MethodMetric metric = new MethodMetric(applicationModel, event.getAttachmentValue(MetricsConstants.INVOCATION), serviceLevel);
|
||||
|
||||
ConcurrentMap<MethodMetric, TimeWindowCounter> counter = methodTypeCounter.computeIfAbsent(metricsKeyWrapper, k -> new ConcurrentHashMap<>());
|
||||
|
||||
ConcurrentHashMapUtils.computeIfAbsent(counter, metric, methodMetric -> new TimeWindowCounter(bucketNum, timeWindowSeconds));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ package org.apache.dubbo.metrics.collector;
|
|||
import org.apache.dubbo.common.constants.CommonConstants;
|
||||
import org.apache.dubbo.common.extension.Activate;
|
||||
import org.apache.dubbo.metrics.DefaultConstants;
|
||||
import org.apache.dubbo.metrics.MetricsConstants;
|
||||
import org.apache.dubbo.metrics.collector.sample.ErrorCodeSampler;
|
||||
import org.apache.dubbo.metrics.collector.sample.MetricsSampler;
|
||||
import org.apache.dubbo.metrics.collector.sample.SimpleMetricsCountSampler;
|
||||
|
|
@ -30,9 +31,12 @@ import org.apache.dubbo.metrics.data.MethodStatComposite;
|
|||
import org.apache.dubbo.metrics.data.RtStatComposite;
|
||||
import org.apache.dubbo.metrics.event.DefaultSubDispatcher;
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.event.MetricsInitEvent;
|
||||
import org.apache.dubbo.metrics.event.RequestEvent;
|
||||
import org.apache.dubbo.metrics.event.TimeCounterEvent;
|
||||
import org.apache.dubbo.metrics.model.ApplicationMetric;
|
||||
import org.apache.dubbo.metrics.model.MetricsCategory;
|
||||
import org.apache.dubbo.metrics.model.MetricsSupport;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsLevel;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
|
||||
import org.apache.dubbo.metrics.model.sample.CounterMetricSample;
|
||||
|
|
@ -41,9 +45,12 @@ import org.apache.dubbo.rpc.model.ApplicationModel;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static org.apache.dubbo.metrics.DefaultConstants.INIT_DEFAULT_METHOD_KEYS;
|
||||
import static org.apache.dubbo.metrics.model.MetricsCategory.APPLICATION;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.APPLICATION_METRIC_INFO;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link MetricsCollector}
|
||||
|
|
@ -55,6 +62,8 @@ public class DefaultMetricsCollector extends CombMetricsCollector<RequestEvent>
|
|||
|
||||
private volatile boolean threadpoolCollectEnabled = false;
|
||||
|
||||
private volatile boolean metricsInitEnabled = true;
|
||||
|
||||
private final ThreadPoolMetricsSampler threadPoolSampler = new ThreadPoolMetricsSampler(this);
|
||||
|
||||
private final ErrorCodeSampler errorCodeSampler;
|
||||
|
|
@ -65,6 +74,11 @@ public class DefaultMetricsCollector extends CombMetricsCollector<RequestEvent>
|
|||
|
||||
private final List<MetricsSampler> samplers = new ArrayList<>();
|
||||
|
||||
private final List<MetricsCollector> collectors = new ArrayList<>();
|
||||
|
||||
private final AtomicBoolean initialized = new AtomicBoolean();
|
||||
|
||||
|
||||
public DefaultMetricsCollector(ApplicationModel applicationModel) {
|
||||
super(new BaseStatComposite(applicationModel) {
|
||||
@Override
|
||||
|
|
@ -120,6 +134,14 @@ public class DefaultMetricsCollector extends CombMetricsCollector<RequestEvent>
|
|||
this.threadpoolCollectEnabled = threadpoolCollectEnabled;
|
||||
}
|
||||
|
||||
public boolean isMetricsInitEnabled() {
|
||||
return metricsInitEnabled;
|
||||
}
|
||||
|
||||
public void setMetricsInitEnabled(boolean metricsInitEnabled) {
|
||||
this.metricsInitEnabled = metricsInitEnabled;
|
||||
}
|
||||
|
||||
public void collectApplication() {
|
||||
this.setApplicationName(applicationModel.getApplicationName());
|
||||
applicationSampler.inc(applicationName, MetricsEvent.Type.APPLICATION_INFO);
|
||||
|
|
@ -146,7 +168,29 @@ public class DefaultMetricsCollector extends CombMetricsCollector<RequestEvent>
|
|||
|
||||
@Override
|
||||
public boolean isSupport(MetricsEvent event) {
|
||||
return event instanceof RequestEvent;
|
||||
return event instanceof RequestEvent || event instanceof MetricsInitEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(TimeCounterEvent event) {
|
||||
if(event instanceof MetricsInitEvent){
|
||||
if (!metricsInitEnabled) {
|
||||
return;
|
||||
}
|
||||
if(initialized.compareAndSet(false,true)) {
|
||||
collectors.addAll(applicationModel.getBeanFactory().getBeansOfType(MetricsCollector.class));
|
||||
}
|
||||
collectors.stream().forEach(collector->collector.initMetrics(event));
|
||||
return;
|
||||
}
|
||||
super.onEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initMetrics(MetricsEvent event) {
|
||||
MetricsPlaceValue dynamicPlaceType = MetricsPlaceValue.of(event.getAttachmentValue(MetricsConstants.INVOCATION_SIDE), MetricsLevel.METHOD);
|
||||
INIT_DEFAULT_METHOD_KEYS.stream().forEach(key->MetricsSupport.init(key, dynamicPlaceType, (MethodMetricsCollector) this, event));
|
||||
MetricsSupport.init(METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD), (MethodMetricsCollector) this, event);
|
||||
}
|
||||
|
||||
public SimpleMetricsCountSampler<String, MetricsEvent.Type, ApplicationMetric> applicationSampler = new SimpleMetricsCountSampler<String, MetricsEvent.Type, ApplicationMetric>() {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ public class HistogramMetricsCollector extends AbstractMetricsListener<RequestEv
|
|||
|
||||
private static final Integer[] DEFAULT_BUCKETS_MS = new Integer[]{100, 300, 500, 1000, 3000, 5000, 10000};
|
||||
|
||||
private boolean serviceLevel;
|
||||
|
||||
public HistogramMetricsCollector(ApplicationModel applicationModel) {
|
||||
this.applicationModel = applicationModel;
|
||||
|
||||
|
|
@ -68,6 +70,7 @@ public class HistogramMetricsCollector extends AbstractMetricsListener<RequestEv
|
|||
}
|
||||
|
||||
metricRegister = new HistogramMetricRegister(MetricsGlobalRegistry.getCompositeRegistry(applicationModel), histogram);
|
||||
this.serviceLevel = MethodMetric.isServiceLevel(applicationModel);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -92,7 +95,7 @@ public class HistogramMetricsCollector extends AbstractMetricsListener<RequestEv
|
|||
|
||||
private void onRTEvent(RequestEvent event) {
|
||||
if (metricRegister != null) {
|
||||
MethodMetric metric = new MethodMetric(applicationModel, event.getAttachmentValue(MetricsConstants.INVOCATION));
|
||||
MethodMetric metric = new MethodMetric(applicationModel, event.getAttachmentValue(MetricsConstants.INVOCATION), serviceLevel);
|
||||
long responseTime = event.getTimePair().calc();
|
||||
|
||||
HistogramMetricSample sample = new HistogramMetricSample(MetricsKey.METRIC_RT_HISTOGRAM.getNameByType(metric.getSide()),
|
||||
|
|
|
|||
|
|
@ -34,10 +34,10 @@ public class MetricThreadPoolExhaustedListener implements ThreadPoolExhaustedLis
|
|||
public MetricThreadPoolExhaustedListener(String threadPoolExecutorName,ThreadRejectMetricsCountSampler sampler) {
|
||||
this.threadPoolExecutorName=threadPoolExecutorName;
|
||||
this.threadRejectMetricsCountSampler=sampler;
|
||||
this.threadRejectMetricsCountSampler.addMetricName(threadPoolExecutorName);
|
||||
}
|
||||
@Override
|
||||
public void onEvent(ThreadPoolExhaustedEvent event) {
|
||||
threadRejectMetricsCountSampler.addMetricName(threadPoolExecutorName);
|
||||
threadRejectMetricsCountSampler.inc(threadPoolExecutorName,threadPoolExecutorName);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,8 +56,8 @@ public class RequestEvent extends TimeCounterEvent {
|
|||
|
||||
public static RequestEvent toRequestEvent(ApplicationModel applicationModel, String appName,
|
||||
MetricsDispatcher metricsDispatcher, DefaultMetricsCollector collector,
|
||||
Invocation invocation, String side) {
|
||||
MethodMetric methodMetric = new MethodMetric(applicationModel, invocation);
|
||||
Invocation invocation, String side, boolean serviceLevel) {
|
||||
MethodMetric methodMetric = new MethodMetric(applicationModel, invocation, serviceLevel);
|
||||
RequestEvent requestEvent = new RequestEvent(applicationModel, appName, metricsDispatcher, collector, REQUEST_EVENT);
|
||||
requestEvent.putAttachment(MetricsConstants.INVOCATION, invocation);
|
||||
requestEvent.putAttachment(MetricsConstants.METHOD_METRICS, methodMetric);
|
||||
|
|
@ -80,13 +80,13 @@ public class RequestEvent extends TimeCounterEvent {
|
|||
/**
|
||||
* Acts on MetricsClusterFilter to monitor exceptions that occur before request execution
|
||||
*/
|
||||
public static RequestEvent toRequestErrorEvent(ApplicationModel applicationModel, String appName, MetricsDispatcher metricsDispatcher, Invocation invocation, String side, int code) {
|
||||
public static RequestEvent toRequestErrorEvent(ApplicationModel applicationModel, String appName, MetricsDispatcher metricsDispatcher, Invocation invocation, String side, int code, boolean serviceLevel) {
|
||||
RequestEvent event = new RequestEvent(applicationModel, appName, metricsDispatcher, null, REQUEST_ERROR_EVENT);
|
||||
event.putAttachment(ATTACHMENT_KEY_SERVICE, MetricsSupport.getInterfaceName(invocation));
|
||||
event.putAttachment(MetricsConstants.INVOCATION_SIDE, side);
|
||||
event.putAttachment(MetricsConstants.INVOCATION, invocation);
|
||||
event.putAttachment(MetricsConstants.INVOCATION_REQUEST_ERROR, code);
|
||||
event.putAttachment(MetricsConstants.METHOD_METRICS, new MethodMetric(applicationModel, invocation));
|
||||
event.putAttachment(MetricsConstants.METHOD_METRICS, new MethodMetric(applicationModel, invocation, serviceLevel));
|
||||
return event;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
|
|||
import org.apache.dubbo.metrics.event.MetricsDispatcher;
|
||||
import org.apache.dubbo.metrics.event.MetricsEventBus;
|
||||
import org.apache.dubbo.metrics.event.RequestEvent;
|
||||
import org.apache.dubbo.metrics.model.MethodMetric;
|
||||
import org.apache.dubbo.metrics.model.MetricsSupport;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
|
|
@ -45,6 +46,7 @@ public class MetricsFilter implements ScopeModelAware {
|
|||
private String appName;
|
||||
private MetricsDispatcher metricsDispatcher;
|
||||
private DefaultMetricsCollector defaultMetricsCollector;
|
||||
private boolean serviceLevel;
|
||||
|
||||
@Override
|
||||
public void setApplicationModel(ApplicationModel applicationModel) {
|
||||
|
|
@ -53,6 +55,7 @@ public class MetricsFilter implements ScopeModelAware {
|
|||
this.appName = applicationModel.tryGetApplicationName();
|
||||
this.metricsDispatcher = applicationModel.getBeanFactory().getBean(MetricsDispatcher.class);
|
||||
this.defaultMetricsCollector = applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class);
|
||||
serviceLevel = MethodMetric.isServiceLevel(applicationModel);
|
||||
}
|
||||
|
||||
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
|
||||
|
|
@ -63,7 +66,7 @@ public class MetricsFilter implements ScopeModelAware {
|
|||
if (rpcMetricsEnable) {
|
||||
try {
|
||||
RequestEvent requestEvent = RequestEvent.toRequestEvent(applicationModel, appName, metricsDispatcher,
|
||||
defaultMetricsCollector, invocation, isProvider ? PROVIDER : CONSUMER);
|
||||
defaultMetricsCollector, invocation, isProvider ? PROVIDER : CONSUMER, serviceLevel);
|
||||
MetricsEventBus.before(requestEvent);
|
||||
invocation.put(METRIC_FILTER_EVENT, requestEvent);
|
||||
} catch (Throwable t) {
|
||||
|
|
|
|||
|
|
@ -17,26 +17,26 @@
|
|||
|
||||
package org.apache.dubbo.metrics.report;
|
||||
|
||||
import io.micrometer.core.instrument.FunctionCounter;
|
||||
import io.micrometer.core.instrument.binder.MeterBinder;
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
|
||||
import org.apache.dubbo.common.lang.ShutdownHookCallbacks;
|
||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.metrics.MetricsGlobalRegistry;
|
||||
import org.apache.dubbo.common.utils.NamedThreadFactory;
|
||||
import org.apache.dubbo.metrics.MetricsGlobalRegistry;
|
||||
import org.apache.dubbo.metrics.collector.AggregateMetricsCollector;
|
||||
import org.apache.dubbo.metrics.collector.MetricsCollector;
|
||||
import org.apache.dubbo.metrics.collector.HistogramMetricsCollector;
|
||||
import org.apache.dubbo.metrics.collector.MetricsCollector;
|
||||
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.rpc.model.ApplicationModel;
|
||||
|
||||
import io.micrometer.core.instrument.FunctionCounter;
|
||||
import io.micrometer.core.instrument.Gauge;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.Tag;
|
||||
import io.micrometer.core.instrument.binder.MeterBinder;
|
||||
import io.micrometer.core.instrument.binder.jvm.ClassLoaderMetrics;
|
||||
import io.micrometer.core.instrument.binder.jvm.JvmGcMetrics;
|
||||
import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics;
|
||||
|
|
@ -53,6 +53,7 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_METRICS_COLLECTOR_EXCEPTION;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.ENABLE_COLLECTOR_SYNC_KEY;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.ENABLE_JVM_METRICS_KEY;
|
||||
|
||||
/**
|
||||
|
|
@ -140,9 +141,12 @@ public abstract class AbstractMetricsReporter implements MetricsReporter {
|
|||
}
|
||||
|
||||
private void scheduleMetricsCollectorSyncJob() {
|
||||
NamedThreadFactory threadFactory = new NamedThreadFactory("metrics-collector-sync-job", true);
|
||||
collectorSyncJobExecutor = Executors.newScheduledThreadPool(1, threadFactory);
|
||||
collectorSyncJobExecutor.scheduleWithFixedDelay(this::refreshData, DEFAULT_SCHEDULE_INITIAL_DELAY, DEFAULT_SCHEDULE_PERIOD, TimeUnit.SECONDS);
|
||||
boolean enableCollectorSync = url.getParameter(ENABLE_COLLECTOR_SYNC_KEY, true);
|
||||
if (enableCollectorSync) {
|
||||
NamedThreadFactory threadFactory = new NamedThreadFactory("metrics-collector-sync-job", true);
|
||||
collectorSyncJobExecutor = Executors.newScheduledThreadPool(1, threadFactory);
|
||||
collectorSyncJobExecutor.scheduleWithFixedDelay(this::refreshData, DEFAULT_SCHEDULE_INITIAL_DELAY, DEFAULT_SCHEDULE_PERIOD, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
|
|||
import org.apache.dubbo.metrics.event.MetricsDispatcher;
|
||||
import org.apache.dubbo.metrics.event.MetricsEventBus;
|
||||
import org.apache.dubbo.metrics.event.RequestEvent;
|
||||
import org.apache.dubbo.metrics.model.MethodMetric;
|
||||
import org.apache.dubbo.rpc.BaseFilter;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
|
|
@ -42,6 +43,7 @@ public class MetricsClusterFilter implements ClusterFilter, BaseFilter.Listener,
|
|||
private DefaultMetricsCollector collector;
|
||||
private String appName;
|
||||
private MetricsDispatcher metricsDispatcher;
|
||||
private boolean serviceLevel;
|
||||
|
||||
@Override
|
||||
public void setApplicationModel(ApplicationModel applicationModel) {
|
||||
|
|
@ -49,6 +51,7 @@ public class MetricsClusterFilter implements ClusterFilter, BaseFilter.Listener,
|
|||
this.collector = applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class);
|
||||
this.appName = applicationModel.tryGetApplicationName();
|
||||
this.metricsDispatcher = applicationModel.getBeanFactory().getBean(MetricsDispatcher.class);
|
||||
this.serviceLevel = MethodMetric.isServiceLevel(applicationModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -73,7 +76,7 @@ public class MetricsClusterFilter implements ClusterFilter, BaseFilter.Listener,
|
|||
if (t instanceof RpcException) {
|
||||
RpcException e = (RpcException) t;
|
||||
if (e.isForbidden()) {
|
||||
MetricsEventBus.publish(RequestEvent.toRequestErrorEvent(applicationModel, appName, metricsDispatcher, invocation, CONSUMER_SIDE, e.getCode()));
|
||||
MetricsEventBus.publish(RequestEvent.toRequestErrorEvent(applicationModel, appName, metricsDispatcher, invocation, CONSUMER_SIDE, e.getCode(), serviceLevel));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ import org.apache.dubbo.metrics.model.MethodMetric;
|
|||
import org.apache.dubbo.metrics.model.MetricsSupport;
|
||||
import org.apache.dubbo.metrics.model.TimePair;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsLevel;
|
||||
import org.apache.dubbo.metrics.model.key.TypeWrapper;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
|
|
@ -90,7 +89,7 @@ class AggregateMetricsCollectorTest {
|
|||
|
||||
public MethodMetric getTestMethodMetric() {
|
||||
|
||||
MethodMetric methodMetric = new MethodMetric(applicationModel, invocation);
|
||||
MethodMetric methodMetric = new MethodMetric(applicationModel, invocation, MethodMetric.isServiceLevel(applicationModel));
|
||||
methodMetric.setGroup("TestGroup");
|
||||
methodMetric.setVersion("1.0.0");
|
||||
methodMetric.setSide("PROVIDER");
|
||||
|
|
@ -141,8 +140,8 @@ class AggregateMetricsCollectorTest {
|
|||
@Test
|
||||
void testListener() {
|
||||
AggregateMetricsCollector metricsCollector = new AggregateMetricsCollector(applicationModel);
|
||||
RequestEvent event = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation));
|
||||
RequestEvent beforeEvent = RequestEvent.toRequestErrorEvent(applicationModel, null, null, invocation, MetricsSupport.getSide(invocation), RpcException.FORBIDDEN_EXCEPTION);
|
||||
RequestEvent event = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation), MethodMetric.isServiceLevel(applicationModel));
|
||||
RequestEvent beforeEvent = RequestEvent.toRequestErrorEvent(applicationModel, null, null, invocation, MetricsSupport.getSide(invocation), RpcException.FORBIDDEN_EXCEPTION, MethodMetric.isServiceLevel(applicationModel));
|
||||
|
||||
Assertions.assertTrue(metricsCollector.isSupport(event));
|
||||
Assertions.assertTrue(metricsCollector.isSupport(beforeEvent));
|
||||
|
|
@ -200,7 +199,8 @@ class AggregateMetricsCollectorTest {
|
|||
|
||||
when(applicationModel.getApplicationConfigManager()).thenReturn(configManager);
|
||||
when(applicationModel.getBeanFactory()).thenReturn(beanFactory);
|
||||
when(beanFactory.getBean(DefaultMetricsCollector.class)).thenReturn(new DefaultMetricsCollector(applicationModel));
|
||||
DefaultMetricsCollector defaultMetricsCollector = new DefaultMetricsCollector(applicationModel);
|
||||
when(beanFactory.getBean(DefaultMetricsCollector.class)).thenReturn(defaultMetricsCollector);
|
||||
when(configManager.getMetrics()).thenReturn(Optional.of(metricsConfig));
|
||||
when(metricsConfig.getAggregation()).thenReturn(aggregationConfig);
|
||||
when(aggregationConfig.getEnabled()).thenReturn(Boolean.TRUE);
|
||||
|
|
@ -249,7 +249,7 @@ class AggregateMetricsCollectorTest {
|
|||
rtList.add(30L);
|
||||
|
||||
for (Long requestTime: rtList) {
|
||||
RequestEvent requestEvent = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation));
|
||||
RequestEvent requestEvent = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation), MethodMetric.isServiceLevel(applicationModel));
|
||||
TestRequestEvent testRequestEvent = new TestRequestEvent(requestEvent.getSource(), requestEvent.getTypeWrapper());
|
||||
testRequestEvent.putAttachment(MetricsConstants.INVOCATION, invocation);
|
||||
testRequestEvent.putAttachment(ATTACHMENT_KEY_SERVICE, MetricsSupport.getInterfaceName(invocation));
|
||||
|
|
@ -299,7 +299,7 @@ class AggregateMetricsCollectorTest {
|
|||
double manualP99 = requestTimes.get((int) Math.round(p99Index));
|
||||
|
||||
for (Long requestTime : requestTimes) {
|
||||
RequestEvent requestEvent = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation));
|
||||
RequestEvent requestEvent = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation), MethodMetric.isServiceLevel(applicationModel));
|
||||
TestRequestEvent testRequestEvent = new TestRequestEvent(requestEvent.getSource(), requestEvent.getTypeWrapper());
|
||||
testRequestEvent.putAttachment(MetricsConstants.INVOCATION, invocation);
|
||||
testRequestEvent.putAttachment(ATTACHMENT_KEY_SERVICE, MetricsSupport.getInterfaceName(invocation));
|
||||
|
|
|
|||
|
|
@ -19,18 +19,21 @@ package org.apache.dubbo.metrics.collector;
|
|||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.constants.CommonConstants;
|
||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.config.ApplicationConfig;
|
||||
import org.apache.dubbo.metrics.MetricsConstants;
|
||||
import org.apache.dubbo.metrics.TestMetricsInvoker;
|
||||
import org.apache.dubbo.metrics.event.MetricsDispatcher;
|
||||
import org.apache.dubbo.metrics.event.RequestEvent;
|
||||
import org.apache.dubbo.metrics.filter.MetricsFilter;
|
||||
import org.apache.dubbo.metrics.model.MethodMetric;
|
||||
import org.apache.dubbo.metrics.model.MetricsSupport;
|
||||
import org.apache.dubbo.metrics.model.ServiceKeyMetric;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsLevel;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
|
||||
import org.apache.dubbo.metrics.model.key.TypeWrapper;
|
||||
import org.apache.dubbo.metrics.model.sample.CounterMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
|
|
@ -112,8 +115,8 @@ class DefaultCollectorTest {
|
|||
@Test
|
||||
void testListener() {
|
||||
DefaultMetricsCollector metricsCollector = new DefaultMetricsCollector(applicationModel);
|
||||
RequestEvent event = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation));
|
||||
RequestEvent beforeEvent = RequestEvent.toRequestErrorEvent(applicationModel, null, null, invocation, MetricsSupport.getSide(invocation), RpcException.FORBIDDEN_EXCEPTION);
|
||||
RequestEvent event = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation), MethodMetric.isServiceLevel(applicationModel));
|
||||
RequestEvent beforeEvent = RequestEvent.toRequestErrorEvent(applicationModel, null, null, invocation, MetricsSupport.getSide(invocation), RpcException.FORBIDDEN_EXCEPTION, MethodMetric.isServiceLevel(applicationModel));
|
||||
|
||||
Assertions.assertTrue(metricsCollector.isSupport(event));
|
||||
Assertions.assertTrue(metricsCollector.isSupport(beforeEvent));
|
||||
|
|
@ -134,6 +137,9 @@ class DefaultCollectorTest {
|
|||
DefaultMetricsCollector collector = applicationModel.getBeanFactory().getOrRegisterBean(DefaultMetricsCollector.class);
|
||||
collector.setCollectEnabled(true);
|
||||
|
||||
ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(DefaultCollectorTest.class);
|
||||
logger.warn("0-99","","","Test error code message.");
|
||||
|
||||
metricsFilter.invoke(new TestMetricsInvoker(side), invocation);
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
|
|
@ -150,8 +156,8 @@ class DefaultCollectorTest {
|
|||
|
||||
// push finish rt +1
|
||||
List<MetricSample> metricSamples = collector.collect();
|
||||
//num(total+success+processing) + rt(5) = 8
|
||||
Assertions.assertEquals(8, metricSamples.size());
|
||||
//num(total+success+processing) + rt(5) + error code = 9
|
||||
Assertions.assertEquals(metricSamples.size(),9);
|
||||
List<String> metricsNames = metricSamples.stream().map(MetricSample::getName).collect(Collectors.toList());
|
||||
// No error will contain total+success+processing
|
||||
String REQUESTS = new MetricsKeyWrapper(METRIC_REQUESTS, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey();
|
||||
|
|
@ -192,8 +198,8 @@ class DefaultCollectorTest {
|
|||
long c2 = eventObj.getTimePair().calc();
|
||||
metricSamples = collector.collect();
|
||||
|
||||
// num(total+success+error+total_error+processing) + rt(5) = 5
|
||||
Assertions.assertEquals(10, metricSamples.size());
|
||||
// num(total+success+error+total_error+processing) + rt(5) + error code = 11
|
||||
Assertions.assertEquals(11, metricSamples.size());
|
||||
|
||||
String TIMEOUT = new MetricsKeyWrapper(METRIC_REQUESTS_TIMEOUT, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey();
|
||||
String TOTAL_FAILED = new MetricsKeyWrapper(METRIC_REQUESTS_TOTAL_FAILED, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* 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.collector;
|
||||
import org.apache.dubbo.common.constants.CommonConstants;
|
||||
import org.apache.dubbo.config.ApplicationConfig;
|
||||
import org.apache.dubbo.config.MetricsConfig;
|
||||
import org.apache.dubbo.config.nested.AggregationConfig;
|
||||
import org.apache.dubbo.metrics.aggregate.TimeWindowCounter;
|
||||
import org.apache.dubbo.metrics.event.MetricsEventBus;
|
||||
import org.apache.dubbo.metrics.event.MetricsInitEvent;
|
||||
import org.apache.dubbo.metrics.model.MethodMetric;
|
||||
import org.apache.dubbo.metrics.model.ServiceKeyMetric;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsLevel;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
|
||||
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.rpc.RpcInvocation;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.apache.dubbo.rpc.model.FrameworkModel;
|
||||
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.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.dubbo.metrics.DefaultConstants.INIT_AGG_METHOD_KEYS;
|
||||
import static org.apache.dubbo.metrics.DefaultConstants.INIT_DEFAULT_METHOD_KEYS;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS;
|
||||
import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_PROCESSING;
|
||||
|
||||
class InitServiceMetricsTest {
|
||||
|
||||
private ApplicationModel applicationModel;
|
||||
|
||||
private String interfaceName;
|
||||
private String methodName;
|
||||
private String group;
|
||||
private String version;
|
||||
|
||||
private String side;
|
||||
|
||||
private DefaultMetricsCollector defaultCollector;
|
||||
|
||||
private AggregateMetricsCollector aggregateMetricsCollector;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
FrameworkModel frameworkModel = FrameworkModel.defaultModel();
|
||||
applicationModel = frameworkModel.newApplication();
|
||||
ApplicationConfig config = new ApplicationConfig();
|
||||
config.setName("MockMetrics");
|
||||
|
||||
MetricsConfig metricsConfig = new MetricsConfig();
|
||||
AggregationConfig aggregationConfig = new AggregationConfig();
|
||||
aggregationConfig.setEnabled(true);
|
||||
aggregationConfig.setBucketNum(12);
|
||||
aggregationConfig.setTimeWindowSeconds(120);
|
||||
metricsConfig.setAggregation(aggregationConfig);
|
||||
|
||||
applicationModel.getApplicationConfigManager().setMetrics(metricsConfig);
|
||||
applicationModel.getApplicationConfigManager().setApplication(config);
|
||||
|
||||
defaultCollector = applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class);
|
||||
defaultCollector.setCollectEnabled(true);
|
||||
|
||||
aggregateMetricsCollector = applicationModel.getBeanFactory().getOrRegisterBean(AggregateMetricsCollector.class);
|
||||
aggregateMetricsCollector.setCollectEnabled(true);
|
||||
|
||||
interfaceName = "org.apache.dubbo.MockInterface";
|
||||
methodName = "mockMethod";
|
||||
group = "mockGroup";
|
||||
version = "1.0.0";
|
||||
side = CommonConstants.PROVIDER_SIDE;
|
||||
|
||||
String serviceKey=group+"/"+interfaceName+":"+version;
|
||||
|
||||
String protocolServiceKey=serviceKey+":dubbo";
|
||||
|
||||
RpcInvocation invocation = new RpcInvocation(serviceKey,null,methodName,interfaceName, protocolServiceKey, null, null,null,null,null,null);
|
||||
MetricsEventBus.publish(MetricsInitEvent.toMetricsInitEvent(applicationModel,invocation, MethodMetric.isServiceLevel(applicationModel)));
|
||||
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void teardown() {
|
||||
applicationModel.destroy();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testMetricsInitEvent() {
|
||||
|
||||
List<MetricSample> metricSamples = defaultCollector.collect();
|
||||
//INIT_DEFAULT_METHOD_KEYS.size() = 6
|
||||
Assertions.assertEquals(INIT_DEFAULT_METHOD_KEYS.size(), metricSamples.size());
|
||||
List<String> metricsNames = metricSamples.stream().map(MetricSample::getName).collect(Collectors.toList());
|
||||
|
||||
String REQUESTS = new MetricsKeyWrapper(METRIC_REQUESTS, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey();
|
||||
String PROCESSING = new MetricsKeyWrapper(METRIC_REQUESTS_PROCESSING, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey();
|
||||
Assertions.assertTrue(metricsNames.contains(REQUESTS));
|
||||
Assertions.assertTrue(metricsNames.contains(PROCESSING));
|
||||
for (MetricSample metricSample : metricSamples) {
|
||||
if (metricSample instanceof GaugeMetricSample) {
|
||||
GaugeMetricSample<?> gaugeMetricSample = (GaugeMetricSample<?>) metricSample;
|
||||
Object objVal = gaugeMetricSample.getValue();
|
||||
if (objVal instanceof Map) {
|
||||
Map<ServiceKeyMetric, AtomicLong> value = (Map<ServiceKeyMetric, AtomicLong>) objVal;
|
||||
Assertions.assertTrue(value.values().stream().allMatch(atomicLong -> atomicLong.intValue() == 0));
|
||||
}
|
||||
} else {
|
||||
AtomicLong value = (AtomicLong) ((CounterMetricSample<?>) metricSample).getValue();
|
||||
Assertions.assertEquals(0, value.intValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
List<MetricSample> samples = aggregateMetricsCollector.collect();
|
||||
//INIT_AGG_METHOD_KEYS.size(10) + qps(1) + rt(4) +rtAgr(3)= 18
|
||||
Assertions.assertEquals(INIT_AGG_METHOD_KEYS.size()+ 1+ 4+ 3, samples.size());
|
||||
|
||||
for (MetricSample metricSample : samples) {
|
||||
if (metricSample instanceof GaugeMetricSample) {
|
||||
GaugeMetricSample<?> gaugeMetricSample = (GaugeMetricSample<?>) metricSample;
|
||||
Object objVal = gaugeMetricSample.getValue();
|
||||
if (objVal instanceof TimeWindowCounter) {
|
||||
Assertions.assertEquals(0.0,((TimeWindowCounter) objVal).get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -19,7 +19,9 @@ package org.apache.dubbo.metrics.metrics.model;
|
|||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.config.ApplicationConfig;
|
||||
import org.apache.dubbo.config.MetricsConfig;
|
||||
import org.apache.dubbo.metrics.model.MethodMetric;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsLevel;
|
||||
import org.apache.dubbo.rpc.RpcContext;
|
||||
import org.apache.dubbo.rpc.RpcInvocation;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
|
@ -72,7 +74,7 @@ class MethodMetricTest {
|
|||
|
||||
@Test
|
||||
void test() {
|
||||
MethodMetric metric = new MethodMetric(applicationModel, invocation);
|
||||
MethodMetric metric = new MethodMetric(applicationModel, invocation, MethodMetric.isServiceLevel(applicationModel));
|
||||
Assertions.assertEquals(metric.getServiceKey(), interfaceName);
|
||||
Assertions.assertEquals(metric.getMethodName(), methodName);
|
||||
Assertions.assertEquals(metric.getGroup(), group);
|
||||
|
|
@ -88,4 +90,24 @@ class MethodMetricTest {
|
|||
Assertions.assertEquals(tags.get(TAG_GROUP_KEY), group);
|
||||
Assertions.assertEquals(tags.get(TAG_VERSION_KEY), version);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testServiceMetrics() {
|
||||
MetricsConfig metricConfig = new MetricsConfig();
|
||||
applicationModel.getApplicationConfigManager().setMetrics(metricConfig);
|
||||
metricConfig.setRpcLevel(MetricsLevel.SERVICE.name());
|
||||
MethodMetric metric = new MethodMetric(applicationModel, invocation, MethodMetric.isServiceLevel(applicationModel));
|
||||
Assertions.assertEquals(metric.getServiceKey(), interfaceName);
|
||||
Assertions.assertNull(metric.getMethodName(), methodName);
|
||||
Assertions.assertEquals(metric.getGroup(), group);
|
||||
Assertions.assertEquals(metric.getVersion(), version);
|
||||
|
||||
Map<String, String> tags = metric.getTags();
|
||||
Assertions.assertEquals(tags.get(TAG_APPLICATION_NAME), applicationModel.getApplicationName());
|
||||
|
||||
Assertions.assertEquals(tags.get(TAG_INTERFACE_KEY), interfaceName);
|
||||
Assertions.assertNull(tags.get(TAG_METHOD_KEY));
|
||||
Assertions.assertEquals(tags.get(TAG_GROUP_KEY), group);
|
||||
Assertions.assertEquals(tags.get(TAG_VERSION_KEY), version);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
<!--
|
||||
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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics</artifactId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>dubbo-metrics-event</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>The metrics event-related api module of dubbo project</description>
|
||||
<properties>
|
||||
<skip_maven_deploy>false</skip_maven_deploy>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-common</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
@ -19,7 +19,6 @@ package org.apache.dubbo.metrics.event;
|
|||
|
||||
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
|
||||
import org.apache.dubbo.metrics.exception.MetricsNeverHappenException;
|
||||
import org.apache.dubbo.metrics.model.MethodMetric;
|
||||
import org.apache.dubbo.metrics.model.key.TypeWrapper;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
|
|
@ -33,13 +32,13 @@ import java.util.Map;
|
|||
public abstract class MetricsEvent {
|
||||
|
||||
/**
|
||||
* Metric object. (eg. {@link MethodMetric})
|
||||
* Metric object. (eg. MethodMetric)
|
||||
*/
|
||||
protected transient final ApplicationModel source;
|
||||
private boolean available = true;
|
||||
private final TypeWrapper typeWrapper;
|
||||
private final String appName;
|
||||
private final MetricsDispatcher metricsDispatcher;
|
||||
private final MetricsEventMulticaster metricsEventMulticaster;
|
||||
|
||||
private final Map<String, Object> attachments = new IdentityHashMap<>(8);
|
||||
|
||||
|
|
@ -47,7 +46,7 @@ public abstract class MetricsEvent {
|
|||
this(source, null, null, typeWrapper);
|
||||
}
|
||||
|
||||
public MetricsEvent(ApplicationModel source, String appName, MetricsDispatcher metricsDispatcher, TypeWrapper typeWrapper) {
|
||||
public MetricsEvent(ApplicationModel source, String appName, MetricsEventMulticaster metricsEventMulticaster, TypeWrapper typeWrapper) {
|
||||
this.typeWrapper = typeWrapper;
|
||||
if (source == null) {
|
||||
this.source = ApplicationModel.defaultModel();
|
||||
|
|
@ -56,20 +55,20 @@ public abstract class MetricsEvent {
|
|||
} else {
|
||||
this.source = source;
|
||||
}
|
||||
if (metricsDispatcher == null) {
|
||||
if (metricsEventMulticaster == null) {
|
||||
if (this.source.isDestroyed()) {
|
||||
this.metricsDispatcher = null;
|
||||
this.metricsEventMulticaster = null;
|
||||
} else {
|
||||
ScopeBeanFactory beanFactory = this.source.getBeanFactory();
|
||||
if (beanFactory.isDestroyed()) {
|
||||
this.metricsDispatcher = null;
|
||||
this.metricsEventMulticaster = null;
|
||||
} else {
|
||||
MetricsDispatcher dispatcher = beanFactory.getBean(MetricsDispatcher.class);
|
||||
this.metricsDispatcher = dispatcher;
|
||||
MetricsEventMulticaster dispatcher = beanFactory.getBean(MetricsEventMulticaster.class);
|
||||
this.metricsEventMulticaster = dispatcher;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.metricsDispatcher = metricsDispatcher;
|
||||
this.metricsEventMulticaster = metricsEventMulticaster;
|
||||
}
|
||||
if (appName == null) {
|
||||
this.appName = this.source.tryGetApplicationName();
|
||||
|
|
@ -115,8 +114,8 @@ public abstract class MetricsEvent {
|
|||
return source;
|
||||
}
|
||||
|
||||
public MetricsDispatcher getMetricsDispatcher() {
|
||||
return metricsDispatcher;
|
||||
public MetricsEventMulticaster getMetricsEventMulticaster() {
|
||||
return metricsEventMulticaster;
|
||||
}
|
||||
|
||||
public String appName() {
|
||||
|
|
@ -42,7 +42,7 @@ public class MetricsEventBus {
|
|||
if (event.getSource() == null) {
|
||||
return;
|
||||
}
|
||||
MetricsDispatcher dispatcher = event.getMetricsDispatcher();
|
||||
MetricsEventMulticaster dispatcher = event.getMetricsEventMulticaster();
|
||||
Optional.ofNullable(dispatcher).ifPresent(d -> {
|
||||
tryInvoke(() -> d.publishEvent(event));
|
||||
});
|
||||
|
|
@ -106,13 +106,14 @@ public class MetricsEventBus {
|
|||
* eventSaveRunner saves the event, so that the calculation rt is introverted
|
||||
*/
|
||||
public static void before(MetricsEvent event) {
|
||||
MetricsDispatcher dispatcher = validate(event);
|
||||
MetricsEventMulticaster dispatcher = validate(event);
|
||||
|
||||
if (dispatcher == null) return;
|
||||
tryInvoke(() -> dispatcher.publishEvent(event));
|
||||
}
|
||||
|
||||
public static void after(MetricsEvent event, Object result) {
|
||||
MetricsDispatcher dispatcher = validate(event);
|
||||
MetricsEventMulticaster dispatcher = validate(event);
|
||||
if (dispatcher == null) return;
|
||||
tryInvoke(() -> {
|
||||
event.customAfterPost(result);
|
||||
|
|
@ -121,13 +122,13 @@ public class MetricsEventBus {
|
|||
}
|
||||
|
||||
public static void error(MetricsEvent event) {
|
||||
MetricsDispatcher dispatcher = validate(event);
|
||||
MetricsEventMulticaster dispatcher = validate(event);
|
||||
if (dispatcher == null) return;
|
||||
tryInvoke(() -> dispatcher.publishErrorEvent((TimeCounterEvent) event));
|
||||
}
|
||||
|
||||
private static MetricsDispatcher validate(MetricsEvent event) {
|
||||
MetricsDispatcher dispatcher = event.getMetricsDispatcher();
|
||||
private static MetricsEventMulticaster validate(MetricsEvent event) {
|
||||
MetricsEventMulticaster dispatcher = event.getMetricsEventMulticaster();
|
||||
if (dispatcher == null) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ public abstract class TimeCounterEvent extends MetricsEvent {
|
|||
this.timePair = TimePair.start();
|
||||
}
|
||||
|
||||
public TimeCounterEvent(ApplicationModel source, String appName, MetricsDispatcher metricsDispatcher, TypeWrapper typeWrapper) {
|
||||
public TimeCounterEvent(ApplicationModel source, String appName,MetricsEventMulticaster metricsDispatcher, TypeWrapper typeWrapper) {
|
||||
super(source, appName, metricsDispatcher, typeWrapper);
|
||||
this.timePair = TimePair.start();
|
||||
}
|
||||
|
|
@ -35,5 +35,4 @@ public interface MetricsListener<E extends MetricsEvent> {
|
|||
*/
|
||||
void onEvent(E event);
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* 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.model.key;
|
||||
|
||||
public enum MetricsKey {
|
||||
APPLICATION_METRIC_INFO("dubbo.application.info.total", "Total Application Info"),
|
||||
|
||||
CONFIGCENTER_METRIC_TOTAL("dubbo.configcenter.total", "Config Changed Total"),
|
||||
|
||||
// provider metrics key
|
||||
METRIC_REQUESTS("dubbo.%s.requests.total", "Total Requests"),
|
||||
METRIC_REQUESTS_SUCCEED("dubbo.%s.requests.succeed.total", "Total Succeed Requests"),
|
||||
METRIC_REQUEST_BUSINESS_FAILED("dubbo.%s.requests.business.failed.total", "Total Failed Business Requests"),
|
||||
|
||||
METRIC_REQUESTS_PROCESSING("dubbo.%s.requests.processing.total", "Processing Requests"),
|
||||
METRIC_REQUESTS_TIMEOUT("dubbo.%s.requests.timeout.total", "Total Timeout Failed Requests"),
|
||||
METRIC_REQUESTS_LIMIT("dubbo.%s.requests.limit.total", "Total Limit Failed Requests"),
|
||||
METRIC_REQUESTS_FAILED("dubbo.%s.requests.unknown.failed.total", "Total Unknown Failed Requests"),
|
||||
METRIC_REQUESTS_TOTAL_FAILED("dubbo.%s.requests.failed.total", "Total Failed Requests"),
|
||||
METRIC_REQUESTS_NETWORK_FAILED("dubbo.%s.requests.failed.network.total", "Total network Failed Requests"),
|
||||
METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED("dubbo.%s.requests.failed.service.unavailable.total", "Total Service Unavailable Failed Requests"),
|
||||
METRIC_REQUESTS_CODEC_FAILED("dubbo.%s.requests.failed.codec.total", "Total Codec Failed Requests"),
|
||||
|
||||
METRIC_REQUESTS_TOTAL_AGG("dubbo.%s.requests.total.aggregate", "Aggregated Total Requests"),
|
||||
METRIC_REQUESTS_SUCCEED_AGG("dubbo.%s.requests.succeed.aggregate", "Aggregated Succeed Requests"),
|
||||
METRIC_REQUESTS_FAILED_AGG("dubbo.%s.requests.failed.aggregate", "Aggregated Failed Requests"),
|
||||
METRIC_REQUEST_BUSINESS_FAILED_AGG("dubbo.%s.requests.business.failed.aggregate", "Aggregated Business Failed Requests"),
|
||||
METRIC_REQUESTS_TIMEOUT_AGG("dubbo.%s.requests.timeout.failed.aggregate", "Aggregated timeout Failed Requests"),
|
||||
METRIC_REQUESTS_LIMIT_AGG("dubbo.%s.requests.limit.aggregate", "Aggregated limit Requests"),
|
||||
METRIC_REQUESTS_TOTAL_FAILED_AGG("dubbo.%s.requests.failed.total.aggregate", "Aggregated failed total Requests"),
|
||||
METRIC_REQUESTS_NETWORK_FAILED_AGG("dubbo.%s.requests.failed.network.total.aggregate", "Aggregated failed network total Requests"),
|
||||
METRIC_REQUESTS_CODEC_FAILED_AGG("dubbo.%s.requests.failed.codec.total.aggregate", "Aggregated failed codec total Requests"),
|
||||
METRIC_REQUESTS_TOTAL_SERVICE_UNAVAILABLE_FAILED_AGG("dubbo.%s.requests.failed.service.unavailable.total.aggregate", "Aggregated failed codec total Requests"),
|
||||
|
||||
METRIC_QPS("dubbo.%s.qps.total", "Query Per Seconds"),
|
||||
METRIC_RT_LAST("dubbo.%s.rt.milliseconds.last", "Last Response Time"),
|
||||
METRIC_RT_MIN("dubbo.%s.rt.milliseconds.min", "Min Response Time"),
|
||||
METRIC_RT_MAX("dubbo.%s.rt.milliseconds.max", "Max Response Time"),
|
||||
METRIC_RT_SUM("dubbo.%s.rt.milliseconds.sum", "Sum Response Time"),
|
||||
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"),
|
||||
METRIC_RT_MIN_AGG("dubbo.%s.rt.min.milliseconds.aggregate", "Aggregated Min Response"),
|
||||
METRIC_RT_MAX_AGG("dubbo.%s.rt.max.milliseconds.aggregate", "Aggregated Max Response"),
|
||||
METRIC_RT_AVG_AGG("dubbo.%s.rt.avg.milliseconds.aggregate", "Aggregated Avg Response"),
|
||||
|
||||
// register metrics key
|
||||
REGISTER_METRIC_REQUESTS("dubbo.registry.register.requests.total", "Total Register Requests"),
|
||||
REGISTER_METRIC_REQUESTS_SUCCEED("dubbo.registry.register.requests.succeed.total", "Succeed Register Requests"),
|
||||
REGISTER_METRIC_REQUESTS_FAILED("dubbo.registry.register.requests.failed.total", "Failed Register Requests"),
|
||||
METRIC_RT_HISTOGRAM("dubbo.%s.rt.milliseconds.histogram", "Response Time Histogram"),
|
||||
|
||||
|
||||
GENERIC_METRIC_REQUESTS("dubbo.%s.requests.total", "Total %s Requests"),
|
||||
GENERIC_METRIC_REQUESTS_SUCCEED("dubbo.%s.requests.succeed.total", "Succeed %s Requests"),
|
||||
GENERIC_METRIC_REQUESTS_FAILED("dubbo.%s.requests.failed.total", "Failed %s Requests"),
|
||||
|
||||
// subscribe metrics key
|
||||
SUBSCRIBE_METRIC_NUM("dubbo.registry.subscribe.num.total", "Total Subscribe Num"),
|
||||
SUBSCRIBE_METRIC_NUM_SUCCEED("dubbo.registry.subscribe.num.succeed.total", "Succeed Subscribe Num"),
|
||||
SUBSCRIBE_METRIC_NUM_FAILED("dubbo.registry.subscribe.num.failed.total", "Failed Subscribe Num"),
|
||||
|
||||
// directory metrics key
|
||||
DIRECTORY_METRIC_NUM_ALL("dubbo.registry.directory.num.all", "All Directory Urls"),
|
||||
DIRECTORY_METRIC_NUM_VALID("dubbo.registry.directory.num.valid.total", "Valid Directory Urls"),
|
||||
DIRECTORY_METRIC_NUM_TO_RECONNECT("dubbo.registry.directory.num.to_reconnect.total", "ToReconnect Directory Urls"),
|
||||
DIRECTORY_METRIC_NUM_DISABLE("dubbo.registry.directory.num.disable.total", "Disable Directory Urls"),
|
||||
|
||||
NOTIFY_METRIC_REQUESTS("dubbo.registry.notify.requests.total", "Total Notify Requests"),
|
||||
NOTIFY_METRIC_NUM_LAST("dubbo.registry.notify.num.last", "Last Notify Nums"),
|
||||
|
||||
THREAD_POOL_CORE_SIZE("dubbo.thread.pool.core.size", "Thread Pool Core Size"),
|
||||
THREAD_POOL_LARGEST_SIZE("dubbo.thread.pool.largest.size", "Thread Pool Largest Size"),
|
||||
THREAD_POOL_MAX_SIZE("dubbo.thread.pool.max.size", "Thread Pool Max Size"),
|
||||
THREAD_POOL_ACTIVE_SIZE("dubbo.thread.pool.active.size", "Thread Pool Active Size"),
|
||||
THREAD_POOL_THREAD_COUNT("dubbo.thread.pool.thread.count", "Thread Pool Thread Count"),
|
||||
THREAD_POOL_QUEUE_SIZE("dubbo.thread.pool.queue.size", "Thread Pool Queue Size"),
|
||||
THREAD_POOL_THREAD_REJECT_COUNT("dubbo.thread.pool.reject.thread.count", "Thread Pool Reject Thread Count"),
|
||||
|
||||
// metadata push metrics key
|
||||
METADATA_PUSH_METRIC_NUM("dubbo.metadata.push.num.total", "Total Push Num"),
|
||||
METADATA_PUSH_METRIC_NUM_SUCCEED("dubbo.metadata.push.num.succeed.total", "Succeed Push Num"),
|
||||
METADATA_PUSH_METRIC_NUM_FAILED("dubbo.metadata.push.num.failed.total", "Failed Push Num"),
|
||||
|
||||
// metadata subscribe metrics key
|
||||
METADATA_SUBSCRIBE_METRIC_NUM("dubbo.metadata.subscribe.num.total", "Total Metadata Subscribe Num"),
|
||||
METADATA_SUBSCRIBE_METRIC_NUM_SUCCEED("dubbo.metadata.subscribe.num.succeed.total", "Succeed Metadata Subscribe Num"),
|
||||
METADATA_SUBSCRIBE_METRIC_NUM_FAILED("dubbo.metadata.subscribe.num.failed.total", "Failed Metadata Subscribe Num"),
|
||||
|
||||
// register service metrics key
|
||||
SERVICE_REGISTER_METRIC_REQUESTS("dubbo.registry.register.service.total", "Total Service-Level Register Requests"),
|
||||
SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED("dubbo.registry.register.service.succeed.total", "Succeed Service-Level Register Requests"),
|
||||
SERVICE_REGISTER_METRIC_REQUESTS_FAILED("dubbo.registry.register.service.failed.total", "Failed Service-Level Register Requests"),
|
||||
|
||||
// subscribe metrics key
|
||||
SERVICE_SUBSCRIBE_METRIC_NUM("dubbo.registry.subscribe.service.num.total", "Total Service-Level Subscribe Num"),
|
||||
SERVICE_SUBSCRIBE_METRIC_NUM_SUCCEED("dubbo.registry.subscribe.service.num.succeed.total", "Succeed Service-Level Num"),
|
||||
SERVICE_SUBSCRIBE_METRIC_NUM_FAILED("dubbo.registry.subscribe.service.num.failed.total", "Failed Service-Level Num"),
|
||||
// store provider metadata service key
|
||||
STORE_PROVIDER_METADATA("dubbo.metadata.store.provider.total", "Store Provider Metadata"),
|
||||
|
||||
STORE_PROVIDER_METADATA_SUCCEED("dubbo.metadata.store.provider.succeed.total", "Succeed Store Provider Metadata"),
|
||||
|
||||
STORE_PROVIDER_METADATA_FAILED("dubbo.metadata.store.provider.failed.total", "Failed Store Provider Metadata"),
|
||||
METADATA_GIT_COMMITID_METRIC("git.commit.id", "Git Commit Id Metrics"),
|
||||
|
||||
// consumer metrics key
|
||||
INVOKER_NO_AVAILABLE_COUNT("dubbo.consumer.invoker.no.available.count", "Request Throw No Invoker Available Exception Count"),
|
||||
|
||||
// count the number of occurrences of each error code
|
||||
ERROR_CODE_COUNT("dubbo.error.code.count","The Count Of Occurrences for Each Error Code"),
|
||||
|
||||
// netty metrics key
|
||||
NETTY_ALLOCATOR_HEAP_MEMORY_USED("netty.allocator.memory.used", "Netty Allocator Memory Used"),
|
||||
NETTY_ALLOCATOR_DIRECT_MEMORY_USED("netty.allocator.direct.memory.used", "Netty Allocator Direct Memory Used"),
|
||||
NETTY_ALLOCATOR_PINNED_DIRECT_MEMORY("netty.allocator.pinned.direct.memory", "Netty Allocator Pinned Direct Memory"),
|
||||
NETTY_ALLOCATOR_PINNED_HEAP_MEMORY("netty.allocator.pinned.heap.memory", "Netty Allocator Pinned Heap Memory"),
|
||||
NETTY_ALLOCATOR_HEAP_ARENAS_NUM("netty.allocator.heap.arenas.num", "Netty Allocator Heap Arenas Num"),
|
||||
NETTY_ALLOCATOR_DIRECT_ARENAS_NUM("netty.allocator.direct.arenas.num", "Netty Allocator Direct Arenas Num"),
|
||||
NETTY_ALLOCATOR_NORMAL_CACHE_SIZE("netty.allocator.normal.cache.size", "Netty Allocator Normal Cache Size"),
|
||||
NETTY_ALLOCATOR_SMALL_CACHE_SIZE("netty.allocator.small.cache.size", "Netty Allocator Small Cache Size"),
|
||||
NETTY_ALLOCATOR_THREAD_LOCAL_CACHES_NUM("netty.allocator.thread.local.caches.num", "Netty Allocator Thread Local Caches Num"),
|
||||
NETTY_ALLOCATOR_CHUNK_SIZE("netty.allocator.chunk.size", "Netty Allocator Chunk Size"),
|
||||
;
|
||||
|
||||
private String name;
|
||||
private String description;
|
||||
|
||||
public final String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public final String getNameByType(String type) {
|
||||
return String.format(name, type);
|
||||
}
|
||||
|
||||
public static MetricsKey getMetricsByName(String name){
|
||||
for (MetricsKey metricsKey : MetricsKey.values()) {
|
||||
if (metricsKey.getName().equals(name)) {
|
||||
return metricsKey;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public final String getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
MetricsKey(String name, String description) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
|
|
@ -25,7 +25,6 @@ import org.apache.dubbo.config.nested.AggregationConfig;
|
|||
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.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;
|
||||
|
|
@ -222,9 +221,9 @@ public class RegistryMetricsTest {
|
|||
}
|
||||
List<MetricSample> samples = collector.collect();
|
||||
|
||||
GaugeMetricSample<?> succeedRequests = getSample(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED.getNameByType(RegistryMetricsConstants.OP_TYPE_REGISTER_SERVICE.getType()), samples);
|
||||
GaugeMetricSample<?> failedRequests = getSample(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_FAILED.getNameByType(RegistryMetricsConstants.OP_TYPE_REGISTER_SERVICE.getType()), samples);
|
||||
GaugeMetricSample<?> totalRequests = getSample(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS.getNameByType(RegistryMetricsConstants.OP_TYPE_REGISTER_SERVICE.getType()), samples);
|
||||
GaugeMetricSample<?> succeedRequests = getSample(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED.getName(), samples);
|
||||
GaugeMetricSample<?> failedRequests = getSample(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_FAILED.getName(), samples);
|
||||
GaugeMetricSample<?> totalRequests = getSample(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS.getName(), samples);
|
||||
|
||||
Assertions.assertEquals(5L, succeedRequests.applyAsLong());
|
||||
Assertions.assertEquals(5L, failedRequests.applyAsLong());
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<modules>
|
||||
<module>dubbo-metrics-api</module>
|
||||
<module>dubbo-metrics-event</module>
|
||||
<module>dubbo-metrics-default</module>
|
||||
<module>dubbo-metrics-registry</module>
|
||||
<module>dubbo-metrics-metadata</module>
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-parent</artifactId>
|
||||
<artifactId>dubbo-plugin</artifactId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
@ -35,6 +35,6 @@
|
|||
<artifactId>dubbo-common</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue