mirror of https://github.com/alibaba/nacos.git
				
				
				
			[ISSUE#13183] Add client metrics switch. (#13191)
	
		
			
	
		
	
	
		
			
				
	
				Continuous Integration / ci (8, ubuntu-latest) (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				Integration Test / test (11, ubuntu-latest) (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				Integration Test / test (11.0.3, ubuntu-latest) (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				Integration Test / test (8, ubuntu-latest) (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				Integration Test / test (8.0.192, ubuntu-latest) (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				PUSH-CI / Build dist tar (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				PUSH-CI / Docker images (centos, 8) (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				PUSH-CI / Deploy nacos (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				PUSH-CI / Java e2e Test (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				PUSH-CI / GO E2E Test (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				PUSH-CI / Cpp E2E Test (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				PUSH-CI / Csharp E2E Test (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				PUSH-CI / Nodejs E2E Test (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				PUSH-CI / Python E2E Test (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				PUSH-CI / Clean (push) Has been cancelled
				
					Details
				
			
		
	
				
					
				
			
				
	
				Continuous Integration / ci (8, ubuntu-latest) (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				Integration Test / test (11, ubuntu-latest) (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				Integration Test / test (11.0.3, ubuntu-latest) (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				Integration Test / test (8, ubuntu-latest) (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				Integration Test / test (8.0.192, ubuntu-latest) (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				PUSH-CI / Build dist tar (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				PUSH-CI / Docker images (centos, 8) (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				PUSH-CI / Deploy nacos (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				PUSH-CI / Java e2e Test (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				PUSH-CI / GO E2E Test (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				PUSH-CI / Cpp E2E Test (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				PUSH-CI / Csharp E2E Test (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				PUSH-CI / Nodejs E2E Test (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				PUSH-CI / Python E2E Test (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				PUSH-CI / Clean (push) Has been cancelled
				
					Details
				
			
		
	This commit is contained in:
		
							parent
							
								
									83e145bcb5
								
							
						
					
					
						commit
						551c203c8c
					
				|  | @ -130,4 +130,9 @@ public class PropertyKeyConst { | ||||||
|         public static final String ALIBABA_ALIWARE_ENDPOINT_URL = "ALIBABA_ALIWARE_ENDPOINT_URL"; |         public static final String ALIBABA_ALIWARE_ENDPOINT_URL = "ALIBABA_ALIWARE_ENDPOINT_URL"; | ||||||
|     } |     } | ||||||
|      |      | ||||||
| } |     /** | ||||||
|  |      * Client Metric Switch. | ||||||
|  |      */ | ||||||
|  |     public static final String ENABLE_CLIENT_METRICS = "enableClientMetrics"; | ||||||
|  |      | ||||||
|  | } | ||||||
|  | @ -151,6 +151,8 @@ public class ClientWorker implements Closeable { | ||||||
|      |      | ||||||
|     private static final int THREAD_MULTIPLE = 1; |     private static final int THREAD_MULTIPLE = 1; | ||||||
|      |      | ||||||
|  |     private boolean enableClientMetrics = true; | ||||||
|  |      | ||||||
|     /** |     /** | ||||||
|      * index(taskId)-> total cache count for this taskId. |      * index(taskId)-> total cache count for this taskId. | ||||||
|      */ |      */ | ||||||
|  | @ -298,7 +300,13 @@ public class ClientWorker implements Closeable { | ||||||
|         } |         } | ||||||
|         LOGGER.info("[{}] [unsubscribe] {}", agent.getName(), groupKey); |         LOGGER.info("[{}] [unsubscribe] {}", agent.getName(), groupKey); | ||||||
|          |          | ||||||
|         MetricsMonitor.getListenConfigCountMonitor().set(cacheMap.get().size()); |         if (enableClientMetrics) { | ||||||
|  |             try { | ||||||
|  |                 MetricsMonitor.getListenConfigCountMonitor().set(cacheMap.get().size()); | ||||||
|  |             } catch (Throwable t) { | ||||||
|  |                 LOGGER.error("Failed to update metrics for listen config count", t); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     /** |     /** | ||||||
|  | @ -373,7 +381,13 @@ public class ClientWorker implements Closeable { | ||||||
|          |          | ||||||
|         LOGGER.info("[{}] [subscribe] {}", this.agent.getName(), key); |         LOGGER.info("[{}] [subscribe] {}", this.agent.getName(), key); | ||||||
|          |          | ||||||
|         MetricsMonitor.getListenConfigCountMonitor().set(cacheMap.get().size()); |         if (enableClientMetrics) { | ||||||
|  |             try { | ||||||
|  |                 MetricsMonitor.getListenConfigCountMonitor().set(cacheMap.get().size()); | ||||||
|  |             } catch (Throwable t) { | ||||||
|  |                 LOGGER.error("Failed to update metrics for listen config count", t); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|          |          | ||||||
|         return cache; |         return cache; | ||||||
|     } |     } | ||||||
|  | @ -420,7 +434,13 @@ public class ClientWorker implements Closeable { | ||||||
|         } |         } | ||||||
|         LOGGER.info("[{}] [subscribe] {}", agent.getName(), key); |         LOGGER.info("[{}] [subscribe] {}", agent.getName(), key); | ||||||
|          |          | ||||||
|         MetricsMonitor.getListenConfigCountMonitor().set(cacheMap.get().size()); |         if (enableClientMetrics) { | ||||||
|  |             try { | ||||||
|  |                 MetricsMonitor.getListenConfigCountMonitor().set(cacheMap.get().size()); | ||||||
|  |             } catch (Throwable t) { | ||||||
|  |                 LOGGER.error("Failed to update metrics for listen config count", t); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|          |          | ||||||
|         return cache; |         return cache; | ||||||
|     } |     } | ||||||
|  | @ -523,6 +543,8 @@ public class ClientWorker implements Closeable { | ||||||
|          |          | ||||||
|         this.enableRemoteSyncConfig = Boolean.parseBoolean( |         this.enableRemoteSyncConfig = Boolean.parseBoolean( | ||||||
|                 properties.getProperty(PropertyKeyConst.ENABLE_REMOTE_SYNC_CONFIG)); |                 properties.getProperty(PropertyKeyConst.ENABLE_REMOTE_SYNC_CONFIG)); | ||||||
|  |         this.enableClientMetrics = Boolean.parseBoolean( | ||||||
|  |                 properties.getProperty(PropertyKeyConst.ENABLE_CLIENT_METRICS, "true")); | ||||||
|         initAppLabels(properties.getProperties(SourceType.PROPERTIES)); |         initAppLabels(properties.getProperties(SourceType.PROPERTIES)); | ||||||
|     } |     } | ||||||
|      |      | ||||||
|  |  | ||||||
|  | @ -57,6 +57,8 @@ public class ServiceInfoHolder implements Closeable { | ||||||
|      |      | ||||||
|     private String notifierEventScope; |     private String notifierEventScope; | ||||||
|      |      | ||||||
|  |     private boolean enableClientMetrics = true; | ||||||
|  |      | ||||||
|     public ServiceInfoHolder(String namespace, String notifierEventScope, NacosClientProperties properties) { |     public ServiceInfoHolder(String namespace, String notifierEventScope, NacosClientProperties properties) { | ||||||
|         cacheDir = CacheDirUtil.initCacheDir(namespace, properties); |         cacheDir = CacheDirUtil.initCacheDir(namespace, properties); | ||||||
|         instancesDiffer = new InstancesDiffer(); |         instancesDiffer = new InstancesDiffer(); | ||||||
|  | @ -68,6 +70,8 @@ public class ServiceInfoHolder implements Closeable { | ||||||
|         this.failoverReactor = new FailoverReactor(this, notifierEventScope); |         this.failoverReactor = new FailoverReactor(this, notifierEventScope); | ||||||
|         this.pushEmptyProtection = isPushEmptyProtect(properties); |         this.pushEmptyProtection = isPushEmptyProtect(properties); | ||||||
|         this.notifierEventScope = notifierEventScope; |         this.notifierEventScope = notifierEventScope; | ||||||
|  |         this.enableClientMetrics = Boolean.parseBoolean( | ||||||
|  |                 properties.getProperty(PropertyKeyConst.ENABLE_CLIENT_METRICS, "true")); | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     private boolean isLoadCacheAtStart(NacosClientProperties properties) { |     private boolean isLoadCacheAtStart(NacosClientProperties properties) { | ||||||
|  | @ -136,7 +140,15 @@ public class ServiceInfoHolder implements Closeable { | ||||||
|         if (StringUtils.isBlank(serviceInfo.getJsonFromServer())) { |         if (StringUtils.isBlank(serviceInfo.getJsonFromServer())) { | ||||||
|             serviceInfo.setJsonFromServer(JacksonUtils.toJson(serviceInfo)); |             serviceInfo.setJsonFromServer(JacksonUtils.toJson(serviceInfo)); | ||||||
|         } |         } | ||||||
|         MetricsMonitor.getServiceInfoMapSizeMonitor().set(serviceInfoMap.size()); |          | ||||||
|  |         if (enableClientMetrics) { | ||||||
|  |             try { | ||||||
|  |                 MetricsMonitor.getServiceInfoMapSizeMonitor().set(serviceInfoMap.size()); | ||||||
|  |             } catch (Throwable t) { | ||||||
|  |                 NAMING_LOGGER.error("Failed to update metrics for service info map size", t); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         if (diff.hasDifferent()) { |         if (diff.hasDifferent()) { | ||||||
|             NAMING_LOGGER.info("current ips:({}) service: {} -> {}", serviceInfo.ipCount(), serviceKey, |             NAMING_LOGGER.info("current ips:({}) service: {} -> {}", serviceInfo.ipCount(), serviceKey, | ||||||
|                     JacksonUtils.toJson(serviceInfo.getHosts())); |                     JacksonUtils.toJson(serviceInfo.getHosts())); | ||||||
|  |  | ||||||
|  | @ -16,6 +16,7 @@ | ||||||
| 
 | 
 | ||||||
| package com.alibaba.nacos.client.naming.remote.gprc; | package com.alibaba.nacos.client.naming.remote.gprc; | ||||||
| 
 | 
 | ||||||
|  | import com.alibaba.nacos.api.PropertyKeyConst; | ||||||
| import com.alibaba.nacos.api.ability.constant.AbilityKey; | import com.alibaba.nacos.api.ability.constant.AbilityKey; | ||||||
| import com.alibaba.nacos.api.ability.constant.AbilityStatus; | import com.alibaba.nacos.api.ability.constant.AbilityStatus; | ||||||
| import com.alibaba.nacos.api.common.Constants; | import com.alibaba.nacos.api.common.Constants; | ||||||
|  | @ -94,6 +95,8 @@ public class NamingGrpcClientProxy extends AbstractNamingClientProxy { | ||||||
|      |      | ||||||
|     private final NamingGrpcRedoService redoService; |     private final NamingGrpcRedoService redoService; | ||||||
|      |      | ||||||
|  |     private boolean enableClientMetrics = true; | ||||||
|  |      | ||||||
|     public NamingGrpcClientProxy(String namespaceId, SecurityProxy securityProxy, ServerListFactory serverListFactory, |     public NamingGrpcClientProxy(String namespaceId, SecurityProxy securityProxy, ServerListFactory serverListFactory, | ||||||
|             NacosClientProperties properties, ServiceInfoHolder serviceInfoHolder) throws NacosException { |             NacosClientProperties properties, ServiceInfoHolder serviceInfoHolder) throws NacosException { | ||||||
|         super(securityProxy); |         super(securityProxy); | ||||||
|  | @ -108,6 +111,8 @@ public class NamingGrpcClientProxy extends AbstractNamingClientProxy { | ||||||
|                 .createGrpcClientConfig(properties.asProperties(), labels); |                 .createGrpcClientConfig(properties.asProperties(), labels); | ||||||
|         this.rpcClient = RpcClientFactory.createClient(uuid, ConnectionType.GRPC, grpcClientConfig); |         this.rpcClient = RpcClientFactory.createClient(uuid, ConnectionType.GRPC, grpcClientConfig); | ||||||
|         this.redoService = new NamingGrpcRedoService(this, properties); |         this.redoService = new NamingGrpcRedoService(this, properties); | ||||||
|  |         this.enableClientMetrics = Boolean.parseBoolean( | ||||||
|  |                 properties.getProperty(PropertyKeyConst.ENABLE_CLIENT_METRICS, "true")); | ||||||
|         NAMING_LOGGER.info("Create naming rpc client for uuid->{}", uuid); |         NAMING_LOGGER.info("Create naming rpc client for uuid->{}", uuid); | ||||||
|         start(serverListFactory, serviceInfoHolder); |         start(serverListFactory, serviceInfoHolder); | ||||||
|     } |     } | ||||||
|  | @ -478,13 +483,21 @@ public class NamingGrpcClientProxy extends AbstractNamingClientProxy { | ||||||
|      * @param response  The response object containing registration result information, or null if registration failed. |      * @param response  The response object containing registration result information, or null if registration failed. | ||||||
|      */ |      */ | ||||||
|     private void recordRequestFailedMetrics(AbstractNamingRequest request, Exception exception, Response response) { |     private void recordRequestFailedMetrics(AbstractNamingRequest request, Exception exception, Response response) { | ||||||
|         if (Objects.isNull(response)) { |         if (!enableClientMetrics) { | ||||||
|             MetricsMonitor.getNamingRequestFailedMonitor(request.getClass().getSimpleName(), MONITOR_LABEL_NONE, |             return; | ||||||
|                     MONITOR_LABEL_NONE, exception.getClass().getSimpleName()).inc(); |         } | ||||||
|         } else { |          | ||||||
|             MetricsMonitor.getNamingRequestFailedMonitor(request.getClass().getSimpleName(), |         try { | ||||||
|                     String.valueOf(response.getResultCode()), String.valueOf(response.getErrorCode()), |             if (Objects.isNull(response)) { | ||||||
|                     MONITOR_LABEL_NONE).inc(); |                 MetricsMonitor.getNamingRequestFailedMonitor(request.getClass().getSimpleName(), MONITOR_LABEL_NONE, | ||||||
|  |                         MONITOR_LABEL_NONE, exception.getClass().getSimpleName()).inc(); | ||||||
|  |             } else { | ||||||
|  |                 MetricsMonitor.getNamingRequestFailedMonitor(request.getClass().getSimpleName(), | ||||||
|  |                         String.valueOf(response.getResultCode()), String.valueOf(response.getErrorCode()), | ||||||
|  |                         MONITOR_LABEL_NONE).inc(); | ||||||
|  |             } | ||||||
|  |         } catch (Throwable t) { | ||||||
|  |             NAMING_LOGGER.warn("Fail to record metrics for request {}", request.getClass().getSimpleName(), t); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|      |      | ||||||
|  |  | ||||||
|  | @ -108,6 +108,8 @@ public class NamingHttpClientProxy extends AbstractNamingClientProxy { | ||||||
|      |      | ||||||
|     private int serverPort = DEFAULT_SERVER_PORT; |     private int serverPort = DEFAULT_SERVER_PORT; | ||||||
|      |      | ||||||
|  |     private boolean enableClientMetrics = true; | ||||||
|  |      | ||||||
|     public NamingHttpClientProxy(String namespaceId, SecurityProxy securityProxy, NamingServerListManager serverListManager, |     public NamingHttpClientProxy(String namespaceId, SecurityProxy securityProxy, NamingServerListManager serverListManager, | ||||||
|             NacosClientProperties properties) { |             NacosClientProperties properties) { | ||||||
|         super(securityProxy); |         super(securityProxy); | ||||||
|  | @ -116,6 +118,8 @@ public class NamingHttpClientProxy extends AbstractNamingClientProxy { | ||||||
|         this.namespaceId = namespaceId; |         this.namespaceId = namespaceId; | ||||||
|         this.maxRetry = ConvertUtils.toInt(properties.getProperty(PropertyKeyConst.NAMING_REQUEST_DOMAIN_RETRY_COUNT, |         this.maxRetry = ConvertUtils.toInt(properties.getProperty(PropertyKeyConst.NAMING_REQUEST_DOMAIN_RETRY_COUNT, | ||||||
|                 String.valueOf(UtilAndComs.REQUEST_DOMAIN_RETRY_COUNT))); |                 String.valueOf(UtilAndComs.REQUEST_DOMAIN_RETRY_COUNT))); | ||||||
|  |         this.enableClientMetrics = Boolean.parseBoolean( | ||||||
|  |                 properties.getProperty(PropertyKeyConst.ENABLE_CLIENT_METRICS, "true")); | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     @Override |     @Override | ||||||
|  | @ -431,8 +435,15 @@ public class NamingHttpClientProxy extends AbstractNamingClientProxy { | ||||||
|                     Query.newInstance().initParams(params), body, method, String.class); |                     Query.newInstance().initParams(params), body, method, String.class); | ||||||
|             end = System.currentTimeMillis(); |             end = System.currentTimeMillis(); | ||||||
|              |              | ||||||
|             MetricsMonitor.getNamingRequestMonitor(method, url, String.valueOf(restResult.getCode())) |             if (enableClientMetrics) { | ||||||
|                     .observe(end - start); |                 try { | ||||||
|  |                     MetricsMonitor.getNamingRequestMonitor(method, url, String.valueOf(restResult.getCode())) | ||||||
|  |                             .observe(end - start); | ||||||
|  |                 } catch (Throwable t) { | ||||||
|  |                     NAMING_LOGGER.error("Failed to record metrics. Method: {}, URL: {}, HTTP Status Code: {}", | ||||||
|  |                             method, url, restResult.getCode(), t); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|              |              | ||||||
|             if (restResult.ok()) { |             if (restResult.ok()) { | ||||||
|                 return restResult.getData(); |                 return restResult.getData(); | ||||||
|  |  | ||||||
|  | @ -36,6 +36,7 @@ import com.alibaba.nacos.client.config.common.GroupKey; | ||||||
| import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager; | import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager; | ||||||
| import com.alibaba.nacos.client.config.filter.impl.ConfigResponse; | import com.alibaba.nacos.client.config.filter.impl.ConfigResponse; | ||||||
| import com.alibaba.nacos.client.env.NacosClientProperties; | import com.alibaba.nacos.client.env.NacosClientProperties; | ||||||
|  | import com.alibaba.nacos.client.monitor.MetricsMonitor; | ||||||
| import com.alibaba.nacos.common.remote.ConnectionType; | import com.alibaba.nacos.common.remote.ConnectionType; | ||||||
| import com.alibaba.nacos.common.remote.client.RpcClient; | import com.alibaba.nacos.common.remote.client.RpcClient; | ||||||
| import com.alibaba.nacos.common.remote.client.RpcClientFactory; | import com.alibaba.nacos.common.remote.client.RpcClientFactory; | ||||||
|  | @ -43,6 +44,7 @@ import com.alibaba.nacos.common.remote.client.grpc.GrpcClientConfig; | ||||||
| import com.alibaba.nacos.common.utils.JacksonUtils; | import com.alibaba.nacos.common.utils.JacksonUtils; | ||||||
| import com.alibaba.nacos.common.utils.MD5Utils; | import com.alibaba.nacos.common.utils.MD5Utils; | ||||||
| import com.fasterxml.jackson.databind.JsonNode; | import com.fasterxml.jackson.databind.JsonNode; | ||||||
|  | import io.prometheus.client.Gauge; | ||||||
| import org.junit.jupiter.api.AfterEach; | import org.junit.jupiter.api.AfterEach; | ||||||
| import org.junit.jupiter.api.BeforeEach; | import org.junit.jupiter.api.BeforeEach; | ||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
|  | @ -51,10 +53,12 @@ import org.mockito.Mock; | ||||||
| import org.mockito.MockedStatic; | import org.mockito.MockedStatic; | ||||||
| import org.mockito.Mockito; | import org.mockito.Mockito; | ||||||
| import org.mockito.junit.jupiter.MockitoExtension; | import org.mockito.junit.jupiter.MockitoExtension; | ||||||
|  | import org.slf4j.Logger; | ||||||
| 
 | 
 | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.lang.reflect.Field; | import java.lang.reflect.Field; | ||||||
| import java.lang.reflect.Method; | import java.lang.reflect.Method; | ||||||
|  | import java.lang.reflect.Modifier; | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
| import java.util.Collections; | import java.util.Collections; | ||||||
|  | @ -77,7 +81,11 @@ import static org.mockito.ArgumentMatchers.anyLong; | ||||||
| import static org.mockito.ArgumentMatchers.anyString; | import static org.mockito.ArgumentMatchers.anyString; | ||||||
| import static org.mockito.ArgumentMatchers.eq; | import static org.mockito.ArgumentMatchers.eq; | ||||||
| import static org.mockito.Mockito.doReturn; | import static org.mockito.Mockito.doReturn; | ||||||
|  | import static org.mockito.Mockito.doThrow; | ||||||
|  | import static org.mockito.Mockito.mock; | ||||||
|  | import static org.mockito.Mockito.never; | ||||||
| import static org.mockito.Mockito.times; | import static org.mockito.Mockito.times; | ||||||
|  | import static org.mockito.Mockito.verify; | ||||||
| 
 | 
 | ||||||
| @ExtendWith(MockitoExtension.class) | @ExtendWith(MockitoExtension.class) | ||||||
| class ClientWorkerTest { | class ClientWorkerTest { | ||||||
|  | @ -95,8 +103,11 @@ class ClientWorkerTest { | ||||||
|      |      | ||||||
|     private ClientWorker clientWorkerSpy; |     private ClientWorker clientWorkerSpy; | ||||||
|      |      | ||||||
|  |     @Mock | ||||||
|  |     private Logger logger; | ||||||
|  |      | ||||||
|     @BeforeEach |     @BeforeEach | ||||||
|     void before() { |     void before() throws Exception { | ||||||
|         rpcClientFactoryMockedStatic = Mockito.mockStatic(RpcClientFactory.class); |         rpcClientFactoryMockedStatic = Mockito.mockStatic(RpcClientFactory.class); | ||||||
|          |          | ||||||
|         rpcClientFactoryMockedStatic.when( |         rpcClientFactoryMockedStatic.when( | ||||||
|  | @ -107,7 +118,7 @@ class ClientWorkerTest { | ||||||
|         Properties properties = new Properties(); |         Properties properties = new Properties(); | ||||||
|         properties.put(PropertyKeyConst.NAMESPACE, TEST_NAMESPACE); |         properties.put(PropertyKeyConst.NAMESPACE, TEST_NAMESPACE); | ||||||
|         ConfigFilterChainManager filter = new ConfigFilterChainManager(properties); |         ConfigFilterChainManager filter = new ConfigFilterChainManager(properties); | ||||||
|         ConfigServerListManager serverListManager = Mockito.mock(ConfigServerListManager.class); |         ConfigServerListManager serverListManager = mock(ConfigServerListManager.class); | ||||||
|         final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(properties); |         final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(properties); | ||||||
|         try { |         try { | ||||||
|             clientWorker = new ClientWorker(filter, serverListManager, nacosClientProperties); |             clientWorker = new ClientWorker(filter, serverListManager, nacosClientProperties); | ||||||
|  | @ -115,6 +126,14 @@ class ClientWorkerTest { | ||||||
|             throw new RuntimeException(e); |             throw new RuntimeException(e); | ||||||
|         } |         } | ||||||
|         clientWorkerSpy = Mockito.spy(clientWorker); |         clientWorkerSpy = Mockito.spy(clientWorker); | ||||||
|  |          | ||||||
|  |         Field loggerField = ClientWorker.class.getDeclaredField("LOGGER"); | ||||||
|  |         loggerField.setAccessible(true); | ||||||
|  |          | ||||||
|  |         Field modifiersField = Field.class.getDeclaredField("modifiers"); | ||||||
|  |         modifiersField.setAccessible(true); | ||||||
|  |         modifiersField.setInt(loggerField, loggerField.getModifiers() & ~Modifier.FINAL); | ||||||
|  |         loggerField.set(null, logger); | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     @AfterEach |     @AfterEach | ||||||
|  | @ -775,4 +794,176 @@ class ClientWorkerTest { | ||||||
|         boolean result = clientWorker.removeConfig("a", "b", "c", "tag"); |         boolean result = clientWorker.removeConfig("a", "b", "c", "tag"); | ||||||
|         assertFalse(result); |         assertFalse(result); | ||||||
|     } |     } | ||||||
|  |      | ||||||
|  |     @Test | ||||||
|  |     void testRemoveCacheWithMetricsEnabled() throws Exception { | ||||||
|  |         String dataId = "testDataId"; | ||||||
|  |         String group = "testGroup"; | ||||||
|  |         String tenant = "testTenant"; | ||||||
|  |          | ||||||
|  |         Properties prop = new Properties(); | ||||||
|  |         prop.put("enableClientMetrics", "true"); | ||||||
|  |         ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties()); | ||||||
|  |         ConfigServerListManager agent = mock(ConfigServerListManager.class); | ||||||
|  |          | ||||||
|  |         final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop); | ||||||
|  |         final ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties); | ||||||
|  |          | ||||||
|  |         Gauge.Child mockGaugeChild = mock(Gauge.Child.class); | ||||||
|  |         try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) { | ||||||
|  |             mockedMetricsMonitor.when(MetricsMonitor::getListenConfigCountMonitor).thenReturn(mockGaugeChild); | ||||||
|  |              | ||||||
|  |             clientWorker.removeCache(dataId, group, tenant); | ||||||
|  |              | ||||||
|  |             verify(mockGaugeChild, times(1)).set(0); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     @Test | ||||||
|  |     void testRemoveCacheWithMetricsDisabled() throws Exception { | ||||||
|  |         String dataId = "testDataId"; | ||||||
|  |         String group = "testGroup"; | ||||||
|  |         String tenant = "testTenant"; | ||||||
|  |          | ||||||
|  |         Properties prop = new Properties(); | ||||||
|  |         prop.put(PropertyKeyConst.ENABLE_CLIENT_METRICS, "false"); | ||||||
|  |         ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties()); | ||||||
|  |         ConfigServerListManager agent = mock(ConfigServerListManager.class); | ||||||
|  |          | ||||||
|  |         final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop); | ||||||
|  |         final ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties); | ||||||
|  |         clientWorkerSpy = Mockito.spy(clientWorker); | ||||||
|  |          | ||||||
|  |         Gauge.Child mockGaugeChild = mock(Gauge.Child.class); | ||||||
|  |         try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) { | ||||||
|  |             mockedMetricsMonitor.when(MetricsMonitor::getListenConfigCountMonitor).thenReturn(mockGaugeChild); | ||||||
|  |              | ||||||
|  |             clientWorker.removeCache(dataId, group, tenant); | ||||||
|  |              | ||||||
|  |             verify(mockGaugeChild, times(0)).set(0); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     @Test | ||||||
|  |     void testRemoveCacheWithDefaultClientMetricsEnabled() throws Exception { | ||||||
|  |         String dataId = "testDataId"; | ||||||
|  |         String group = "testGroup"; | ||||||
|  |         String tenant = "testTenant"; | ||||||
|  |          | ||||||
|  |         Properties prop = new Properties(); | ||||||
|  |         ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties()); | ||||||
|  |         ConfigServerListManager agent = mock(ConfigServerListManager.class); | ||||||
|  |          | ||||||
|  |         final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop); | ||||||
|  |         final ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties); | ||||||
|  |          | ||||||
|  |         Gauge.Child mockGaugeChild = mock(Gauge.Child.class); | ||||||
|  |         try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) { | ||||||
|  |             mockedMetricsMonitor.when(MetricsMonitor::getListenConfigCountMonitor).thenReturn(mockGaugeChild); | ||||||
|  |              | ||||||
|  |             clientWorker.removeCache(dataId, group, tenant); | ||||||
|  |              | ||||||
|  |             verify(mockGaugeChild, times(1)).set(0); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     @Test | ||||||
|  |     void testMetricsMonitorSetThrowsException() throws NacosException { | ||||||
|  |         String dataId = "testDataId"; | ||||||
|  |         String group = "testGroup"; | ||||||
|  |         String tenant = "testTenant"; | ||||||
|  |          | ||||||
|  |         Properties prop = new Properties(); | ||||||
|  |         prop.put(PropertyKeyConst.ENABLE_CLIENT_METRICS, "true"); | ||||||
|  |         ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties()); | ||||||
|  |         ConfigServerListManager agent = mock(ConfigServerListManager.class); | ||||||
|  |          | ||||||
|  |         final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop); | ||||||
|  |         final ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties); | ||||||
|  |         clientWorkerSpy = Mockito.spy(clientWorker); | ||||||
|  |          | ||||||
|  |         Gauge.Child mockGaugeChild = mock(Gauge.Child.class); | ||||||
|  |         try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) { | ||||||
|  |             mockedMetricsMonitor.when(MetricsMonitor::getListenConfigCountMonitor).thenReturn(mockGaugeChild); | ||||||
|  |              | ||||||
|  |             RuntimeException exception = new RuntimeException("Mocked exception"); | ||||||
|  |             doThrow(exception).when(mockGaugeChild).set(0); | ||||||
|  |              | ||||||
|  |             clientWorker.removeCache(dataId, group, tenant); | ||||||
|  |              | ||||||
|  |             String groupKey = GroupKey.getKeyTenant(dataId, group, tenant); | ||||||
|  |              | ||||||
|  |             verify(logger, times(1)).info("[{}] [unsubscribe] {}", null, groupKey); | ||||||
|  |             verify(logger, times(1)).error("Failed to update metrics for listen config count", exception); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     @Test | ||||||
|  |     public void testAddCacheDataIfAbsentEnableClientMetricsTrue() throws NacosException { | ||||||
|  |         String dataId = "testDataId"; | ||||||
|  |         String group = "testGroup"; | ||||||
|  |         String tenant = "testTenant"; | ||||||
|  |          | ||||||
|  |         Properties prop = new Properties(); | ||||||
|  |         prop.put(PropertyKeyConst.ENABLE_CLIENT_METRICS, "true"); | ||||||
|  |         ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties()); | ||||||
|  |         ConfigServerListManager agent = mock(ConfigServerListManager.class); | ||||||
|  |          | ||||||
|  |         NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop); | ||||||
|  |         ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties); | ||||||
|  |          | ||||||
|  |         Gauge.Child mockGaugeChild = mock(Gauge.Child.class); | ||||||
|  |         try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) { | ||||||
|  |             mockedMetricsMonitor.when(MetricsMonitor::getListenConfigCountMonitor).thenReturn(mockGaugeChild); | ||||||
|  |     | ||||||
|  |             clientWorker.addCacheDataIfAbsent(dataId, group, tenant); | ||||||
|  | 
 | ||||||
|  |             verify(mockGaugeChild, times(1)).set(1); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     @Test | ||||||
|  |     public void testAddCacheDataIfAbsentEnableClientMetricsFalse() throws NacosException { | ||||||
|  | 
 | ||||||
|  |         String dataId = "testDataId"; | ||||||
|  |         String group = "testGroup"; | ||||||
|  |         String tenant = "testTenant"; | ||||||
|  |          | ||||||
|  |         Properties prop = new Properties(); | ||||||
|  |         prop.put(PropertyKeyConst.ENABLE_CLIENT_METRICS, "false"); | ||||||
|  |         ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties()); | ||||||
|  |         ConfigServerListManager agent = mock(ConfigServerListManager.class); | ||||||
|  |          | ||||||
|  |         NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop); | ||||||
|  |         ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties); | ||||||
|  |          | ||||||
|  |         try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) { | ||||||
|  |             clientWorker.addCacheDataIfAbsent(dataId, group, tenant); | ||||||
|  |              | ||||||
|  |             mockedMetricsMonitor.verify(MetricsMonitor::getListenConfigCountMonitor, never()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     @Test | ||||||
|  |     public void testAddCacheDataIfAbsentEnableClientMetricsNotSet() throws NacosException { | ||||||
|  |         String dataId = "testDataId"; | ||||||
|  |         String group = "testGroup"; | ||||||
|  |         String tenant = "testTenant"; | ||||||
|  |          | ||||||
|  |         Properties prop = new Properties(); | ||||||
|  |         ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties()); | ||||||
|  |         ConfigServerListManager agent = mock(ConfigServerListManager.class); | ||||||
|  |          | ||||||
|  |         NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop); | ||||||
|  |         ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties); | ||||||
|  |          | ||||||
|  |         Gauge.Child mockGaugeChild = mock(Gauge.Child.class); | ||||||
|  |         try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) { | ||||||
|  |             mockedMetricsMonitor.when(MetricsMonitor::getListenConfigCountMonitor).thenReturn(mockGaugeChild); | ||||||
|  |              | ||||||
|  |             clientWorker.addCacheDataIfAbsent(dataId, group, tenant); | ||||||
|  |              | ||||||
|  |             verify(mockGaugeChild, times(1)).set(1); | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -23,21 +23,31 @@ import com.alibaba.nacos.api.exception.NacosException; | ||||||
| import com.alibaba.nacos.api.naming.pojo.Instance; | import com.alibaba.nacos.api.naming.pojo.Instance; | ||||||
| import com.alibaba.nacos.api.naming.pojo.ServiceInfo; | import com.alibaba.nacos.api.naming.pojo.ServiceInfo; | ||||||
| import com.alibaba.nacos.client.env.NacosClientProperties; | import com.alibaba.nacos.client.env.NacosClientProperties; | ||||||
|  | import com.alibaba.nacos.client.monitor.MetricsMonitor; | ||||||
| import com.alibaba.nacos.client.naming.backups.FailoverReactor; | import com.alibaba.nacos.client.naming.backups.FailoverReactor; | ||||||
|  | import io.prometheus.client.Gauge; | ||||||
| import org.junit.jupiter.api.AfterEach; | import org.junit.jupiter.api.AfterEach; | ||||||
| import org.junit.jupiter.api.BeforeEach; | import org.junit.jupiter.api.BeforeEach; | ||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
|  | import org.mockito.MockedStatic; | ||||||
|  | import org.mockito.Mockito; | ||||||
| 
 | 
 | ||||||
| import java.lang.reflect.Field; | import java.lang.reflect.Field; | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  | import java.util.Properties; | ||||||
| import java.util.concurrent.ScheduledExecutorService; | import java.util.concurrent.ScheduledExecutorService; | ||||||
| 
 | 
 | ||||||
| import static org.junit.jupiter.api.Assertions.assertEquals; | import static org.junit.jupiter.api.Assertions.assertEquals; | ||||||
| import static org.junit.jupiter.api.Assertions.assertFalse; | import static org.junit.jupiter.api.Assertions.assertFalse; | ||||||
| import static org.junit.jupiter.api.Assertions.assertNull; | import static org.junit.jupiter.api.Assertions.assertNull; | ||||||
| import static org.junit.jupiter.api.Assertions.assertTrue; | import static org.junit.jupiter.api.Assertions.assertTrue; | ||||||
|  | import static org.mockito.ArgumentMatchers.anyInt; | ||||||
|  | import static org.mockito.Mockito.doThrow; | ||||||
| import static org.mockito.Mockito.mock; | import static org.mockito.Mockito.mock; | ||||||
|  | import static org.mockito.Mockito.never; | ||||||
|  | import static org.mockito.Mockito.times; | ||||||
|  | import static org.mockito.Mockito.verify; | ||||||
| import static org.mockito.Mockito.when; | import static org.mockito.Mockito.when; | ||||||
| 
 | 
 | ||||||
| class ServiceInfoHolderTest { | class ServiceInfoHolderTest { | ||||||
|  | @ -91,6 +101,102 @@ class ServiceInfoHolderTest { | ||||||
|         assertEquals(info2, actual2); |         assertEquals(info2, actual2); | ||||||
|     } |     } | ||||||
|      |      | ||||||
|  |     @Test | ||||||
|  |     void testProcessServiceInfoEnableClientMetricsTrue() { | ||||||
|  |         ServiceInfoHolder holder = createServiceInfoHolder(true); | ||||||
|  |         ServiceInfo info = new ServiceInfo("a@@b@@c"); | ||||||
|  |         Instance instance1 = createInstance("1.1.1.1", 1); | ||||||
|  |         Instance instance2 = createInstance("1.1.1.2", 2); | ||||||
|  |         List<Instance> hosts = new ArrayList<>(); | ||||||
|  |         hosts.add(instance1); | ||||||
|  |         hosts.add(instance2); | ||||||
|  |         info.setHosts(hosts); | ||||||
|  |          | ||||||
|  |         Gauge.Child mockGaugeChild = mock(Gauge.Child.class); | ||||||
|  |         try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) { | ||||||
|  |             mockedMetricsMonitor.when(MetricsMonitor::getServiceInfoMapSizeMonitor).thenReturn(mockGaugeChild); | ||||||
|  |              | ||||||
|  |             holder.processServiceInfo(info); | ||||||
|  |              | ||||||
|  |             verify(mockGaugeChild, times(1)).set(1); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     @Test | ||||||
|  |     void testProcessServiceInfoEnableClientMetricsFalse() { | ||||||
|  |         ServiceInfoHolder holder = createServiceInfoHolder(false); | ||||||
|  |         ServiceInfo info = new ServiceInfo("a@@b@@c"); | ||||||
|  |         Instance instance1 = createInstance("1.1.1.1", 1); | ||||||
|  |         Instance instance2 = createInstance("1.1.1.2", 2); | ||||||
|  |         List<Instance> hosts = new ArrayList<>(); | ||||||
|  |         hosts.add(instance1); | ||||||
|  |         hosts.add(instance2); | ||||||
|  |         info.setHosts(hosts); | ||||||
|  |          | ||||||
|  |         try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) { | ||||||
|  |             holder.processServiceInfo(info); | ||||||
|  |              | ||||||
|  |             mockedMetricsMonitor.verify(MetricsMonitor::getServiceInfoMapSizeMonitor, never()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     @Test | ||||||
|  |     void testProcessServiceInfoEnableClientMetricsNotSet() { | ||||||
|  |         ServiceInfoHolder holder = createServiceInfoHolder(null); | ||||||
|  |         ServiceInfo info = new ServiceInfo("a@@b@@c"); | ||||||
|  |         Instance instance1 = createInstance("1.1.1.1", 1); | ||||||
|  |         Instance instance2 = createInstance("1.1.1.2", 2); | ||||||
|  |         List<Instance> hosts = new ArrayList<>(); | ||||||
|  |         hosts.add(instance1); | ||||||
|  |         hosts.add(instance2); | ||||||
|  |          | ||||||
|  |         info.setHosts(hosts); | ||||||
|  |          | ||||||
|  |         Gauge.Child mockGaugeChild = mock(Gauge.Child.class); | ||||||
|  |         try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) { | ||||||
|  |             mockedMetricsMonitor.when(MetricsMonitor::getServiceInfoMapSizeMonitor).thenReturn(mockGaugeChild); | ||||||
|  |              | ||||||
|  |             holder.processServiceInfo(info); | ||||||
|  |              | ||||||
|  |             verify(mockGaugeChild, times(1)).set(1); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     @Test | ||||||
|  |     void testProcessServiceInfoSetThrowsException() { | ||||||
|  |         ServiceInfoHolder holder = createServiceInfoHolder(true); | ||||||
|  |         ServiceInfo info = new ServiceInfo("a@@b@@c"); | ||||||
|  |         Instance instance1 = createInstance("1.1.1.1", 1); | ||||||
|  |         Instance instance2 = createInstance("1.1.1.2", 2); | ||||||
|  |         List<Instance> hosts = new ArrayList<>(); | ||||||
|  |         hosts.add(instance1); | ||||||
|  |         hosts.add(instance2); | ||||||
|  |         info.setHosts(hosts); | ||||||
|  |          | ||||||
|  |         Gauge.Child mockGaugeChild = mock(Gauge.Child.class); | ||||||
|  |         RuntimeException exception = new RuntimeException("Mocked exception"); | ||||||
|  |          | ||||||
|  |         try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) { | ||||||
|  |             mockedMetricsMonitor.when(MetricsMonitor::getServiceInfoMapSizeMonitor).thenReturn(mockGaugeChild); | ||||||
|  |             doThrow(exception).when(mockGaugeChild).set(anyInt()); | ||||||
|  |              | ||||||
|  |             ServiceInfo actual2 = holder.processServiceInfo(info); | ||||||
|  |              | ||||||
|  |             assertEquals(info, actual2); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     private ServiceInfoHolder createServiceInfoHolder(Boolean enableClientMetrics) { | ||||||
|  |         Properties properties = new Properties(); | ||||||
|  |         if (enableClientMetrics != null) { | ||||||
|  |             properties.put(PropertyKeyConst.ENABLE_CLIENT_METRICS, String.valueOf(enableClientMetrics)); | ||||||
|  |         } | ||||||
|  |         NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties); | ||||||
|  |         String namespace = "test-namespace"; | ||||||
|  |         String notifierEventScope = "scope-001"; | ||||||
|  |         return new ServiceInfoHolder(namespace, notifierEventScope, clientProperties); | ||||||
|  |     } | ||||||
|  |      | ||||||
|     private Instance createInstance(String ip, int port) { |     private Instance createInstance(String ip, int port) { | ||||||
|         Instance instance = new Instance(); |         Instance instance = new Instance(); | ||||||
|         instance.setIp(ip); |         instance.setIp(ip); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue