This is an automated email from the ASF dual-hosted git repository. wujimin pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-java-chassis.git
commit eb9587a43dde767082e272ee6aa3fe6efe4b1999 Author: wujimin <wuji...@huawei.com> AuthorDate: Mon Apr 2 11:28:38 2018 +0800 SCB-422 init threadPool meters from schema operations --- .../core/executor/FixedThreadExecutor.java | 4 + .../metrics/core/ThreadPoolMetersInitializer.java | 99 +++++++++++++ ...rvicecomb.foundation.metrics.MetricsInitializer | 1 + .../core/TestThreadPoolMetersInitializer.java | 162 +++++++++++++++++++++ 4 files changed, 266 insertions(+) diff --git a/core/src/main/java/org/apache/servicecomb/core/executor/FixedThreadExecutor.java b/core/src/main/java/org/apache/servicecomb/core/executor/FixedThreadExecutor.java index e70cc1b..2600ebb 100644 --- a/core/src/main/java/org/apache/servicecomb/core/executor/FixedThreadExecutor.java +++ b/core/src/main/java/org/apache/servicecomb/core/executor/FixedThreadExecutor.java @@ -58,6 +58,10 @@ public class FixedThreadExecutor implements Executor { } } + public List<Executor> getExecutorList() { + return executorList; + } + @Override public void execute(Runnable command) { long threadId = Thread.currentThread().getId(); diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java new file mode 100644 index 0000000..7d9b1f2 --- /dev/null +++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java @@ -0,0 +1,99 @@ +/* + * 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.servicecomb.metrics.core; + +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; + +import org.apache.servicecomb.core.CseContext; +import org.apache.servicecomb.core.definition.MicroserviceMeta; +import org.apache.servicecomb.core.definition.MicroserviceMetaManager; +import org.apache.servicecomb.core.definition.OperationMeta; +import org.apache.servicecomb.core.executor.FixedThreadExecutor; +import org.apache.servicecomb.foundation.common.utils.BeanUtils; +import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; +import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig; +import org.apache.servicecomb.foundation.metrics.MetricsInitializer; + +import com.google.common.eventbus.EventBus; +import com.netflix.spectator.api.CompositeRegistry; +import com.netflix.spectator.api.Registry; +import com.netflix.spectator.api.patterns.ThreadPoolMonitor; + +public class ThreadPoolMetersInitializer implements MetricsInitializer { + private Registry registry; + + @Override + public void init(CompositeRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) { + DefaultRegistryInitializer defaultRegistryInitializer = + SPIServiceUtils.getTargetService(MetricsInitializer.class, DefaultRegistryInitializer.class); + registry = defaultRegistryInitializer.getRegistry(); + + createThreadPoolMeters(); + } + + public void createThreadPoolMeters() { + Map<Executor, Executor> operationExecutors = collectionOperationExecutors(); + // currently, all operation executors come from bean + Map<String, Executor> beanExecutors = BeanUtils.getContext().getBeansOfType(Executor.class); + + for (Entry<String, Executor> entry : beanExecutors.entrySet()) { + Executor executor = entry.getValue(); + if (!operationExecutors.containsKey(executor)) { + continue; + } + + if (FixedThreadExecutor.class.isInstance(executor)) { + createThreadPoolMeters(entry.getKey(), (FixedThreadExecutor) executor); + continue; + } + + createThreadPoolMeters(entry.getKey(), executor); + } + } + + protected Map<Executor, Executor> collectionOperationExecutors() { + Map<Executor, Executor> operationExecutors = new IdentityHashMap<>(); + + MicroserviceMetaManager microserviceMetaManager = CseContext.getInstance().getMicroserviceMetaManager(); + for (MicroserviceMeta microserviceMeta : microserviceMetaManager.values()) { + for (OperationMeta operationMeta : microserviceMeta.getOperations()) { + operationExecutors.put(operationMeta.getExecutor(), operationMeta.getExecutor()); + } + } + + return operationExecutors; + } + + protected void createThreadPoolMeters(String threadPoolName, FixedThreadExecutor fixedThreadExecutor) { + for (int idx = 0; idx < fixedThreadExecutor.getExecutorList().size(); idx++) { + Executor executor = fixedThreadExecutor.getExecutorList().get(idx); + createThreadPoolMeters(threadPoolName + "-group" + idx, executor); + } + } + + protected void createThreadPoolMeters(String threadPoolName, Executor executor) { + if (!ThreadPoolExecutor.class.isInstance(executor)) { + return; + } + + ThreadPoolMonitor.attach(registry, (ThreadPoolExecutor) executor, threadPoolName); + } +} diff --git a/metrics/metrics-core/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.metrics.MetricsInitializer b/metrics/metrics-core/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.metrics.MetricsInitializer index ecd13da..c4ed8e7 100644 --- a/metrics/metrics-core/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.metrics.MetricsInitializer +++ b/metrics/metrics-core/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.metrics.MetricsInitializer @@ -17,5 +17,6 @@ org.apache.servicecomb.metrics.core.DefaultRegistryInitializer org.apache.servicecomb.metrics.core.InvocationMetersInitializer +org.apache.servicecomb.metrics.core.ThreadPoolMetersInitializer org.apache.servicecomb.metrics.core.publish.DefaultLogPublisher org.apache.servicecomb.metrics.core.publish.MetricsRestPublisher \ No newline at end of file diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestThreadPoolMetersInitializer.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestThreadPoolMetersInitializer.java new file mode 100644 index 0000000..116e059 --- /dev/null +++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestThreadPoolMetersInitializer.java @@ -0,0 +1,162 @@ +/* + * 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.servicecomb.metrics.core; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Executor; +import java.util.concurrent.RunnableScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; + +import org.apache.servicecomb.core.CseContext; +import org.apache.servicecomb.core.definition.MicroserviceMeta; +import org.apache.servicecomb.core.definition.MicroserviceMetaManager; +import org.apache.servicecomb.core.definition.OperationMeta; +import org.apache.servicecomb.core.executor.FixedThreadExecutor; +import org.apache.servicecomb.foundation.common.utils.BeanUtils; +import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; +import org.apache.servicecomb.foundation.metrics.MetricsInitializer; +import org.hamcrest.Matchers; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.context.ApplicationContext; + +import com.netflix.spectator.api.DefaultRegistry; +import com.netflix.spectator.api.ManualClock; +import com.netflix.spectator.api.Registry; + +import mockit.Expectations; +import mockit.Mock; +import mockit.MockUp; +import mockit.Mocked; + +public class TestThreadPoolMetersInitializer { + Registry registry = new DefaultRegistry(new ManualClock()); + + ThreadPoolMetersInitializer threadPoolMetersInitializer = new ThreadPoolMetersInitializer(); + + @Mocked + DefaultRegistryInitializer defaultRegistryInitializer; + + @Mocked + ThreadPoolExecutor threadPoolExecutor; + + @Mocked + BlockingQueue<Runnable> queue; + + @Mocked + FixedThreadExecutor fixedThreadExecutor; + + @Mocked + Executor executor; + + @Mocked + ApplicationContext applicationContext; + + @Mocked + MicroserviceMetaManager microserviceMetaManager; + + @Mocked + MicroserviceMeta microserviceMeta; + + @Mocked + OperationMeta operationMetaExecutor; + + @Mocked + OperationMeta operationMetaSameExecutor; + + @Mocked + OperationMeta operationMetaFixedThreadExecutor; + + @Test + public void init() { + new Expectations(SPIServiceUtils.class) { + { + SPIServiceUtils.getTargetService(MetricsInitializer.class, DefaultRegistryInitializer.class); + result = defaultRegistryInitializer; + defaultRegistryInitializer.getRegistry(); + result = registry; + } + }; + + Map<String, Executor> beanExecutors = new HashMap<>(); + beanExecutors.put("executor", executor); + beanExecutors.put("fixedThreadExecutor", fixedThreadExecutor); + beanExecutors.put("threadPoolExecutor", threadPoolExecutor); + new Expectations(BeanUtils.class) { + { + BeanUtils.getContext(); + result = applicationContext; + applicationContext.getBeansOfType(Executor.class); + result = beanExecutors; + } + }; + + new Expectations(CseContext.getInstance()) { + { + CseContext.getInstance().getMicroserviceMetaManager(); + result = microserviceMetaManager; + microserviceMetaManager.values(); + result = Arrays.asList(microserviceMeta); + microserviceMeta.getOperations(); + result = Arrays.asList(operationMetaExecutor, operationMetaSameExecutor, operationMetaFixedThreadExecutor); + operationMetaExecutor.getExecutor(); + result = executor; + operationMetaSameExecutor.getExecutor(); + result = executor; + operationMetaFixedThreadExecutor.getExecutor(); + result = fixedThreadExecutor; + + fixedThreadExecutor.getExecutorList(); + result = Arrays.asList(threadPoolExecutor); + + threadPoolExecutor.getQueue(); + result = queue; + queue.size(); + result = 10d; + } + }; + + new MockUp<ScheduledThreadPoolExecutor>() { + @Mock + void delayedExecute(RunnableScheduledFuture<?> task) { + + } + }; + + threadPoolMetersInitializer.init(null, null, null); + + List<String> result = new ArrayList<>(); + registry.iterator().forEachRemaining(meter -> { + result.add(meter.measure().toString()); + }); + + Assert.assertThat(result, + Matchers.containsInAnyOrder("[Measurement(threadpool.maxThreads:id=fixedThreadExecutor-group0,0,0.0)]", + "[Measurement(threadpool.completedTaskCount:id=fixedThreadExecutor-group0,0,0.0)]", + "[Measurement(threadpool.currentThreadsBusy:id=fixedThreadExecutor-group0,0,0.0)]", + "[Measurement(threadpool.corePoolSize:id=fixedThreadExecutor-group0,0,0.0)]", + "[Measurement(threadpool.poolSize:id=fixedThreadExecutor-group0,0,0.0)]", + "[Measurement(threadpool.queueSize:id=fixedThreadExecutor-group0,0,10.0)]", + "[Measurement(threadpool.taskCount:id=fixedThreadExecutor-group0,0,0.0)]")); + } +} -- To stop receiving notification emails like this one, please contact wuji...@apache.org.