Merge branch '3.2' into 3.3
# Conflicts: # dubbo-dependencies-bom/pom.xml
This commit is contained in:
commit
0f61286a78
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -109,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() {
|
||||
}
|
||||
|
||||
|
|
@ -139,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ 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;
|
||||
|
|
@ -560,11 +561,12 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
|
|||
}
|
||||
|
||||
private void initServiceMethodMetrics(URL url) {
|
||||
String [] methods = Optional.ofNullable(url.getParameter(METHODS_KEY)).map(i->i.split(",")).orElse( new String[]{});
|
||||
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));
|
||||
});
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -1120,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">
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@
|
|||
<plugin>
|
||||
<groupId>org.graalvm.buildtools</groupId>
|
||||
<artifactId>native-maven-plugin</artifactId>
|
||||
<version>0.9.25</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.25</version>
|
||||
<version>0.9.27</version>
|
||||
<configuration>
|
||||
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
|
||||
<metadataRepository>
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
<skip_maven_deploy>true</skip_maven_deploy>
|
||||
<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.3</micrometer-core.version>
|
||||
<micrometer-core.version>1.11.4</micrometer-core.version>
|
||||
</properties>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@
|
|||
<spring_version>5.3.25</spring_version>
|
||||
<spring_security_version>5.8.6</spring_security_version>
|
||||
<javassist_version>3.29.2-GA</javassist_version>
|
||||
<bytebuddy.version>1.14.7</bytebuddy.version>
|
||||
<bytebuddy.version>1.14.8</bytebuddy.version>
|
||||
<netty_version>3.2.10.Final</netty_version>
|
||||
<netty4_version>4.1.97.Final</netty4_version>
|
||||
<mina_version>2.2.1</mina_version>
|
||||
|
|
@ -114,7 +114,7 @@
|
|||
<cxf_version>3.5.5</cxf_version>
|
||||
<thrift_version>0.19.0</thrift_version>
|
||||
<hessian_version>4.0.66</hessian_version>
|
||||
<protobuf-java_version>3.24.2</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.52.v20230823</jetty_version>
|
||||
|
|
@ -133,14 +133,14 @@
|
|||
<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 -->
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,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<>();
|
||||
|
|
@ -59,7 +61,8 @@ public class MethodStatComposite extends AbstractMetricsExport {
|
|||
if (!methodNumStats.containsKey(wrapper)) {
|
||||
return;
|
||||
}
|
||||
methodNumStats.get(wrapper).computeIfAbsent(new MethodMetric(getApplicationModel(), invocation), k -> new AtomicLong(0L));
|
||||
|
||||
methodNumStats.get(wrapper).computeIfAbsent(new MethodMetric(getApplicationModel(), invocation, serviceLevel), k -> new AtomicLong(0L));
|
||||
}
|
||||
|
||||
public void incrementMethodKey(MetricsKeyWrapper wrapper, MethodMetric methodMetric, int size) {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -1,36 +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.event;
|
||||
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
/**
|
||||
* EmptyEvent, do nothing.
|
||||
*/
|
||||
public class EmptyEvent extends MetricsEvent {
|
||||
|
||||
private static final EmptyEvent empty = new EmptyEvent(null);
|
||||
|
||||
private EmptyEvent(ApplicationModel source) {
|
||||
super(source, null);
|
||||
}
|
||||
|
||||
public static EmptyEvent instance() {
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
|
@ -34,8 +34,8 @@ public class MetricsInitEvent extends TimeCounterEvent {
|
|||
super(source,typeWrapper);
|
||||
}
|
||||
|
||||
public static MetricsInitEvent toMetricsInitEvent(ApplicationModel applicationModel, Invocation invocation) {
|
||||
MethodMetric methodMetric = new MethodMetric(applicationModel, invocation);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -40,10 +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)) {
|
||||
|
|
@ -75,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) {
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ 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;
|
||||
|
|
@ -56,7 +57,7 @@ import static org.apache.dubbo.metrics.model.MetricsCategory.RT;
|
|||
* Aggregation metrics collector implementation of {@link MetricsCollector}.
|
||||
* This collector only enabled when metrics aggregation config is enabled.
|
||||
*/
|
||||
public class AggregateMetricsCollector implements MetricsCollector<RequestEvent>{
|
||||
public class AggregateMetricsCollector implements MetricsCollector<RequestEvent> {
|
||||
private int bucketNum = DEFAULT_BUCKET_NUM;
|
||||
private int timeWindowSeconds = DEFAULT_TIME_WINDOW_SECONDS;
|
||||
private int qpsTimeWindowMillSeconds = DEFAULT_QPS_TIME_WINDOW_MILL_SECONDS;
|
||||
|
|
@ -76,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;
|
||||
|
|
@ -96,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -125,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();
|
||||
}
|
||||
}
|
||||
|
|
@ -157,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,
|
||||
|
|
@ -176,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<>());
|
||||
|
||||
|
|
@ -189,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);
|
||||
|
|
@ -266,7 +269,7 @@ public class AggregateMetricsCollector implements MetricsCollector<RequestEvent>
|
|||
|
||||
@Override
|
||||
public void initMetrics(MetricsEvent event) {
|
||||
MethodMetric metric = new MethodMetric(applicationModel, event.getAttachmentValue(MetricsConstants.INVOCATION));
|
||||
MethodMetric metric = new MethodMetric(applicationModel, event.getAttachmentValue(MetricsConstants.INVOCATION), serviceLevel);
|
||||
if (enableQps) {
|
||||
initMethodMetric(event);
|
||||
initQpsMetric(metric);
|
||||
|
|
@ -279,27 +282,27 @@ public class AggregateMetricsCollector implements MetricsCollector<RequestEvent>
|
|||
}
|
||||
}
|
||||
|
||||
public void initMethodMetric(MetricsEvent event){
|
||||
INIT_AGG_METHOD_KEYS.stream().forEach(key->initWindowCounter(event,key));
|
||||
public void initMethodMetric(MetricsEvent event) {
|
||||
INIT_AGG_METHOD_KEYS.stream().forEach(key -> initWindowCounter(event, key));
|
||||
}
|
||||
|
||||
public void initQpsMetric(MethodMetric metric){
|
||||
public void initQpsMetric(MethodMetric metric) {
|
||||
ConcurrentHashMapUtils.computeIfAbsent(qps, metric, methodMetric -> new TimeWindowCounter(bucketNum, timeWindowSeconds));
|
||||
}
|
||||
|
||||
public void initRtMetric(MethodMetric metric){
|
||||
public void initRtMetric(MethodMetric metric) {
|
||||
ConcurrentHashMapUtils.computeIfAbsent(rt, metric, k -> new TimeWindowQuantile(DEFAULT_COMPRESSION, bucketNum, timeWindowSeconds));
|
||||
}
|
||||
|
||||
public void initRtAgrMetric(MethodMetric metric){
|
||||
public void initRtAgrMetric(MethodMetric metric) {
|
||||
ConcurrentHashMapUtils.computeIfAbsent(rtAgr, metric, k -> new TimeWindowAggregator(bucketNum, timeWindowSeconds));
|
||||
}
|
||||
|
||||
public void initWindowCounter(MetricsEvent event, MetricsKey targetKey){
|
||||
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));
|
||||
MethodMetric metric = new MethodMetric(applicationModel, event.getAttachmentValue(MetricsConstants.INVOCATION), serviceLevel);
|
||||
|
||||
ConcurrentMap<MethodMetric, TimeWindowCounter> counter = methodTypeCounter.computeIfAbsent(metricsKeyWrapper, k -> new ConcurrentHashMap<>());
|
||||
|
||||
|
|
|
|||
|
|
@ -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()),
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -27,13 +27,13 @@ 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;
|
||||
|
|
@ -115,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));
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ 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;
|
||||
|
|
@ -96,7 +97,7 @@ class InitServiceMetricsTest {
|
|||
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));
|
||||
MetricsEventBus.publish(MetricsInitEvent.toMetricsInitEvent(applicationModel,invocation, MethodMetric.isServiceLevel(applicationModel)));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ public class DefaultFuture extends CompletableFuture<Object> {
|
|||
|
||||
private String getTimeoutMessage(boolean scan) {
|
||||
long nowTimestamp = System.currentTimeMillis();
|
||||
return (sent > 0 ? "Waiting server-side response timeout" : "Sending request timeout in client-side")
|
||||
return (sent > 0 && sent - start < timeout ? "Waiting server-side response timeout" : "Sending request timeout in client-side")
|
||||
+ (scan ? " by scan timer" : "") + ". start time: "
|
||||
+ (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date(start))) + ", end time: "
|
||||
+ (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date(nowTimestamp))) + ","
|
||||
|
|
|
|||
|
|
@ -86,6 +86,43 @@ class DefaultFutureTest {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* for example, it will print like this:
|
||||
* before a future is created, time is : 2023-09-03 18:20:14.535
|
||||
* after a future is timeout, time is : 2023-09-03 18:20:14.669
|
||||
* <p>
|
||||
* The exception info print like:
|
||||
* Sending request timeout in client-side by scan timer.
|
||||
* start time: 2023-09-03 18:20:14.544, end time: 2023-09-03 18:20:14.598...
|
||||
*/
|
||||
@Test
|
||||
public void clientTimeoutSend() throws Exception {
|
||||
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
|
||||
System.out.println("before a future is create , time is : " + LocalDateTime.now().format(formatter));
|
||||
// timeout after 5 milliseconds.
|
||||
Channel channel = new MockedChannel();
|
||||
Request request = new Request(10);
|
||||
DefaultFuture f = DefaultFuture.newFuture(channel, request, 5, null);
|
||||
System.gc(); // events such as Full GC will increase the time required to send messages.
|
||||
|
||||
// mark the future is sent
|
||||
DefaultFuture.sent(channel, request);
|
||||
while (!f.isDone()) {
|
||||
// spin
|
||||
Thread.sleep(100);
|
||||
}
|
||||
System.out.println("after a future is timeout , time is : " + LocalDateTime.now().format(formatter));
|
||||
|
||||
// get operate will throw a timeout exception, because the future is timeout.
|
||||
try {
|
||||
f.get();
|
||||
} catch (Exception e) {
|
||||
Assertions.assertTrue(e.getCause() instanceof TimeoutException, "catch exception is not timeout exception!");
|
||||
System.out.println(e.getMessage());
|
||||
Assertions.assertTrue(e.getMessage().startsWith(e.getCause().getClass().getCanonicalName() + ": Sending request timeout in client-side"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* for example, it will print like this:
|
||||
* before a future is create , time is : 2018-06-21 15:11:31
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ public class ExceptionFilter implements Filter, Filter.Listener {
|
|||
}
|
||||
// directly throw if it's JDK exception
|
||||
String className = exception.getClass().getName();
|
||||
if (className.startsWith("java.") || className.startsWith("javax.")) {
|
||||
if (className.startsWith("java.") || className.startsWith("javax.") || className.startsWith("jakarta.")) {
|
||||
return;
|
||||
}
|
||||
// directly throw if it's dubbo exception
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ public abstract class AbstractInvoker<T> implements Invoker<T> {
|
|||
/**
|
||||
* {@link Node} destroy
|
||||
*/
|
||||
private boolean destroyed = false;
|
||||
private volatile boolean destroyed = false;
|
||||
|
||||
/**
|
||||
* Whether set future to Thread Local when invocation mode is sync
|
||||
|
|
|
|||
|
|
@ -229,6 +229,9 @@ public abstract class AbstractServerCall implements ServerCall, ServerStream.Lis
|
|||
@Override
|
||||
public final void onCancelByRemote(TriRpcStatus status) {
|
||||
closed = true;
|
||||
if (listener == null) {
|
||||
return;
|
||||
}
|
||||
cancellationContext.cancel(status.cause);
|
||||
listener.onCancel(status);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,9 +38,9 @@
|
|||
</modules>
|
||||
|
||||
<properties>
|
||||
<micrometer.version>1.11.3</micrometer.version>
|
||||
<micrometer-tracing.version>1.1.4</micrometer-tracing.version>
|
||||
<opentelemetry.version>1.29.0</opentelemetry.version>
|
||||
<micrometer.version>1.11.4</micrometer.version>
|
||||
<micrometer-tracing.version>1.1.5</micrometer-tracing.version>
|
||||
<opentelemetry.version>1.30.1</opentelemetry.version>
|
||||
<zipkin-reporter.version>2.16.4</zipkin-reporter.version>
|
||||
<prometheus-client.version>0.16.0</prometheus-client.version>
|
||||
</properties>
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
<!-- Fix the bug of log4j refer:https://github.com/apache/logging-log4j2/pull/608 -->
|
||||
<log4j2_version>2.20.0</log4j2_version>
|
||||
<!-- Spring boot buddy is lower than the delivery dependency package version and can only show the defined dependency version -->
|
||||
<byte-buddy.version>1.14.7</byte-buddy.version>
|
||||
<byte-buddy.version>1.14.8</byte-buddy.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ public class IstioCitadelCertificateSigner implements XdsCertificateSigner {
|
|||
|
||||
IstioCertificateServiceGrpc.IstioCertificateServiceStub stub = IstioCertificateServiceGrpc.newStub(channel);
|
||||
|
||||
stub = MetadataUtils.attachHeaders(stub, header);
|
||||
stub = stub.withInterceptors(MetadataUtils.newAttachHeadersInterceptor(header));
|
||||
|
||||
CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
StringBuffer publicKeyBuilder = new StringBuffer();
|
||||
|
|
|
|||
Loading…
Reference in New Issue