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 eb4de3fe627f5950aa8b41a4f8fa3155be5d72b1 Author: wujimin <wuji...@huawei.com> AuthorDate: Mon Apr 2 11:31:20 2018 +0800 SCB-422 convert threadPool measurements to publish model --- .../metrics/publish/spectator/MeasurementTree.java | 3 +- .../publish/spectator/TestMeasurementTree.java | 3 +- .../ThreadPoolMonitorPublishModelFactory.java | 98 ++++++++++++++++++++++ .../metrics/core/publish/PublishModelFactory.java | 10 ++- ...java => TestInvocationPublishModelFactory.java} | 59 +++++++------ .../metrics/core/publish/TestPublishUtils.java | 15 +++- .../publish/TestThreadPoolPublishModelFactory.java | 78 +++++++++++++++++ 7 files changed, 232 insertions(+), 34 deletions(-) diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java index 056bba6..1a07720 100644 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java +++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java @@ -45,12 +45,13 @@ public class MeasurementTree extends MeasurementNode { public void from(Iterable<Measurement> measurements, MeasurementGroupConfig groupConfig) { for (Measurement measurement : measurements) { Id id = measurement.id(); + MeasurementNode node = addChild(id.name(), measurement); + List<TagFinder> tagFinders = groupConfig.findTagFinders(id.name()); if (tagFinders == null) { continue; } - MeasurementNode node = addChild(id.name(), measurement); for (TagFinder tagFinder : tagFinders) { Tag tag = tagFinder.find(id.tags()); if (tag == null) { diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java index a3eb50d..e568c67 100644 --- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java +++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java @@ -65,11 +65,12 @@ public class TestMeasurementTree { MeasurementGroupConfig config = new MeasurementGroupConfig("id", "g1", "g2", Statistic.count.key()); tree.from(registry.iterator(), config); - Assert.assertEquals(1, tree.getChildren().size()); + Assert.assertEquals(2, tree.getChildren().size()); MeasurementNode node = tree.findChild("id", "g1v", "g2v"); Assert.assertEquals(2d, node.findChild(Statistic.count.value()).getMeasurements().get(0).value(), 0); Assert.assertEquals(12d, node.findChild(Statistic.totalTime.value()).getMeasurements().get(0).value(), 0); + Assert.assertEquals(0d, tree.findChild("id_notCare").summary(), 0); } @Test diff --git a/metrics/metrics-core/src/main/java/com/netflix/spectator/api/patterns/ThreadPoolMonitorPublishModelFactory.java b/metrics/metrics-core/src/main/java/com/netflix/spectator/api/patterns/ThreadPoolMonitorPublishModelFactory.java new file mode 100644 index 0000000..0ffb5a1 --- /dev/null +++ b/metrics/metrics-core/src/main/java/com/netflix/spectator/api/patterns/ThreadPoolMonitorPublishModelFactory.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.netflix.spectator.api.patterns; + +import java.util.Map; + +import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNode; +import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree; +import org.apache.servicecomb.metrics.core.publish.model.ThreadPoolPublishModel; + +import com.netflix.spectator.api.Measurement; +import com.netflix.spectator.api.Utils; + +public class ThreadPoolMonitorPublishModelFactory { + interface Setter { + void set(ThreadPoolPublishModel model, Measurement measurement); + } + + private MeasurementTree tree; + + private Map<String, ThreadPoolPublishModel> threadPools; + + public ThreadPoolMonitorPublishModelFactory(MeasurementTree tree, + Map<String, ThreadPoolPublishModel> threadPools) { + this.tree = tree; + this.threadPools = threadPools; + } + + public static void create(MeasurementTree tree, + Map<String, ThreadPoolPublishModel> threadPools) { + new ThreadPoolMonitorPublishModelFactory(tree, threadPools).create(); + } + + public void create() { + readMeasurement(ThreadPoolMonitor.TASK_COUNT, + (model, measurement) -> { + model.setAvgTaskCount(measurement.value()); + }); + readMeasurement(ThreadPoolMonitor.COMPLETED_TASK_COUNT, + (model, measurement) -> { + model.setAvgCompletedTaskCount(measurement.value()); + }); + readMeasurement(ThreadPoolMonitor.CURRENT_THREADS_BUSY, + (model, measurement) -> { + model.setCurrentThreadsBusy((int) measurement.value()); + }); + readMeasurement(ThreadPoolMonitor.MAX_THREADS, + (model, measurement) -> { + model.setMaxThreads((int) measurement.value()); + }); + readMeasurement(ThreadPoolMonitor.POOL_SIZE, + (model, measurement) -> { + model.setPoolSize((int) measurement.value()); + }); + readMeasurement(ThreadPoolMonitor.CORE_POOL_SIZE, + (model, measurement) -> { + model.setCorePoolSize((int) measurement.value()); + }); + readMeasurement(ThreadPoolMonitor.QUEUE_SIZE, + (model, measurement) -> { + model.setQueueSize((int) measurement.value()); + }); + } + + protected void readMeasurement(String name, Setter setter) { + MeasurementNode node = tree.findChild(name); + if (node == null) { + return; + } + + for (Measurement measurement : node.getMeasurements()) { + String threadPoolName = Utils.getTagValue(measurement.id(), ThreadPoolMonitor.ID_TAG_NAME); + if (threadPoolName == null) { + continue; + } + + ThreadPoolPublishModel model = threadPools.computeIfAbsent(threadPoolName, tpn -> { + return new ThreadPoolPublishModel(); + }); + + setter.set(model, measurement); + } + } +} diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java index 7d03573..8c311bf 100644 --- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java +++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java @@ -27,6 +27,7 @@ import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPer import org.apache.servicecomb.swagger.invocation.InvocationType; import com.netflix.spectator.api.Meter; +import com.netflix.spectator.api.patterns.ThreadPoolMonitorPublishModelFactory; public class PublishModelFactory { private MeasurementTree tree; @@ -52,6 +53,7 @@ public class PublishModelFactory { MeterInvocationConst.TAG_STATUS, MeterInvocationConst.TAG_STAGE, MeterInvocationConst.TAG_STATISTIC); + return groupConfig; } @@ -80,13 +82,13 @@ public class PublishModelFactory { public DefaultPublishModel createDefaultPublishModel() { DefaultPublishModel model = new DefaultPublishModel(); - model - .getConsumer() + model.getConsumer() .setOperationPerfGroups(generateOperationPerfGroups(tree, InvocationType.CONSUMER.name())); - model - .getProducer() + model.getProducer() .setOperationPerfGroups(generateOperationPerfGroups(tree, InvocationType.PRODUCER.name())); + ThreadPoolMonitorPublishModelFactory.create(tree, model.getThreadPools()); + return model; } } diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishModelFactory.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java similarity index 56% rename from metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishModelFactory.java rename to metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java index 4135cf0..3452b02 100644 --- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishModelFactory.java +++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java @@ -16,14 +16,14 @@ */ package org.apache.servicecomb.metrics.core.publish; -import java.util.List; - import org.apache.servicecomb.core.Const; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.foundation.common.utils.JsonUtils; -import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig; -import org.apache.servicecomb.metrics.core.DefaultMetricsInitializer; +import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; +import org.apache.servicecomb.foundation.metrics.MetricsInitializer; +import org.apache.servicecomb.metrics.core.DefaultRegistryInitializer; +import org.apache.servicecomb.metrics.core.InvocationMetersInitializer; import org.apache.servicecomb.metrics.core.publish.model.DefaultPublishModel; import org.apache.servicecomb.swagger.invocation.InvocationType; import org.apache.servicecomb.swagger.invocation.Response; @@ -33,19 +33,25 @@ import org.junit.Test; import com.fasterxml.jackson.core.JsonProcessingException; import com.google.common.collect.Lists; import com.google.common.eventbus.EventBus; -import com.netflix.spectator.api.CompositeRegistry; import com.netflix.spectator.api.DefaultRegistry; import com.netflix.spectator.api.ManualClock; -import com.netflix.spectator.api.Meter; import com.netflix.spectator.api.Registry; -import com.netflix.spectator.api.SpectatorUtils; import mockit.Expectations; import mockit.Mock; import mockit.MockUp; import mockit.Mocked; -public class TestPublishModelFactory { +public class TestInvocationPublishModelFactory { + EventBus eventBus = new EventBus(); + + Registry registry = new DefaultRegistry(new ManualClock()); + + @Mocked + DefaultRegistryInitializer defaultRegistryInitializer; + + InvocationMetersInitializer invocationMetersInitializer = new InvocationMetersInitializer(); + @Mocked Invocation invocation; @@ -56,28 +62,29 @@ public class TestPublishModelFactory { @Test public void createDefaultPublishModel() throws JsonProcessingException { - Registry registry = prepareRegistry(); - List<Meter> meters = Lists.newArrayList(registry); - PublishModelFactory factory = new PublishModelFactory(meters); + new Expectations(SPIServiceUtils.class) { + { + SPIServiceUtils.getTargetService(MetricsInitializer.class, DefaultRegistryInitializer.class); + result = defaultRegistryInitializer; + defaultRegistryInitializer.getRegistry(); + result = registry; + } + }; + invocationMetersInitializer.init(null, eventBus, null); + prepareInvocation(); + + PublishModelFactory factory = new PublishModelFactory(Lists.newArrayList(registry.iterator())); DefaultPublishModel model = factory.createDefaultPublishModel(); Assert.assertEquals( - "{\"consumer\":{\"operationPerfGroups\":{\"groups\":{\"rest\":{\"200\":{\"transport\":\"rest\",\"status\":\"200\",\"operationPerfs\":[{\"operation\":\"m.s.o\",\"stages\":{\"total\":{\"tps\":1,\"msTotalTime\":10000.0,\"msMaxLatency\":0.0}}}],\"summary\":{\"operation\":\"\",\"stages\":{\"total\":{\"tps\":1,\"msTotalTime\":10000.0,\"msMaxLatency\":0.0}}}}}}}},\"producer\":{\"operationPerfGroups\":{\"groups\":{\"rest\":{\"200\":{\"transport\":\"rest\",\"status\":\"200\",\"operationPe [...] - JsonUtils.writeValueAsString(model)); + "{\"operationPerfGroups\":{\"groups\":{\"rest\":{\"200\":{\"transport\":\"rest\",\"status\":\"200\",\"operationPerfs\":[{\"operation\":\"m.s.o\",\"stages\":{\"total\":{\"tps\":1,\"msTotalTime\":10000.0,\"msMaxLatency\":0.0}}}],\"summary\":{\"operation\":\"\",\"stages\":{\"total\":{\"tps\":1,\"msTotalTime\":10000.0,\"msMaxLatency\":0.0}}}}}}}}", + JsonUtils.writeValueAsString(model.getConsumer())); + Assert.assertEquals( + "{\"operationPerfGroups\":{\"groups\":{\"rest\":{\"200\":{\"transport\":\"rest\",\"status\":\"200\",\"operationPerfs\":[{\"operation\":\"m.s.o\",\"stages\":{\"execution\":{\"tps\":1,\"msTotalTime\":5000.0,\"msMaxLatency\":0.0},\"total\":{\"tps\":1,\"msTotalTime\":10000.0,\"msMaxLatency\":0.0},\"queue\":{\"tps\":1,\"msTotalTime\":5000.0,\"msMaxLatency\":0.0}}}],\"summary\":{\"operation\":\"\",\"stages\":{\"execution\":{\"tps\":1,\"msTotalTime\":5000.0,\"msMaxLatency\":0.0},\"total [...] + JsonUtils.writeValueAsString(model.getProducer())); } - protected Registry prepareRegistry() { - CompositeRegistry globalRegistry = SpectatorUtils.createCompositeRegistry(null); - Registry registry = new DefaultRegistry(new ManualClock()); - EventBus eventBus = new EventBus(); - - DefaultMetricsInitializer metricsInitializer = new DefaultMetricsInitializer() { - protected Registry createRegistry(MetricsBootstrapConfig config) { - return registry; - }; - }; - metricsInitializer.init(globalRegistry, eventBus, new MetricsBootstrapConfig()); - + protected void prepareInvocation() { new MockUp<System>() { @Mock long nanoTime() { @@ -125,7 +132,5 @@ public class TestPublishModelFactory { invocationType = InvocationType.PRODUCER; eventBus.post(finishEvent); - - return registry; } } diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishUtils.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishUtils.java index 29ddcc6..68bd8f1 100644 --- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishUtils.java +++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishUtils.java @@ -16,14 +16,16 @@ */ package org.apache.servicecomb.metrics.core.publish; +import java.util.HashMap; import java.util.Map; import javax.ws.rs.core.Response.Status; import org.apache.servicecomb.core.Const; import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNode; +import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree; import org.apache.servicecomb.metrics.core.meter.invocation.MeterInvocationConst; -import org.apache.servicecomb.metrics.core.publish.PublishUtils; +import org.apache.servicecomb.metrics.core.publish.model.ThreadPoolPublishModel; import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerf; import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerfGroup; import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerfGroups; @@ -32,6 +34,8 @@ import org.apache.servicecomb.metrics.core.publish.model.invocation.Utils; import org.junit.Assert; import org.junit.Test; +import com.netflix.spectator.api.patterns.ThreadPoolMonitorPublishModelFactory; + public class TestPublishUtils { String op = "op"; @@ -72,4 +76,13 @@ public class TestPublishUtils { Assert.assertEquals(1000, perfInfo.calcMsLatency(), 0); Assert.assertEquals(100000, perfInfo.getMsMaxLatency(), 0); } + + @Test + public void createThreadPoolPublishModels_empty() { + Map<String, ThreadPoolPublishModel> threadPools = new HashMap<>(); + + ThreadPoolMonitorPublishModelFactory.create(new MeasurementTree(), threadPools); + + Assert.assertTrue(threadPools.isEmpty()); + } } diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestThreadPoolPublishModelFactory.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestThreadPoolPublishModelFactory.java new file mode 100644 index 0000000..7f000f0 --- /dev/null +++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestThreadPoolPublishModelFactory.java @@ -0,0 +1,78 @@ +/* + * 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.publish; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.RunnableScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; + +import org.apache.servicecomb.foundation.common.utils.JsonUtils; +import org.apache.servicecomb.metrics.core.publish.model.DefaultPublishModel; +import org.junit.Assert; +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.google.common.collect.Lists; +import com.google.common.eventbus.EventBus; +import com.netflix.spectator.api.DefaultRegistry; +import com.netflix.spectator.api.ManualClock; +import com.netflix.spectator.api.Registry; +import com.netflix.spectator.api.patterns.ThreadPoolMonitor; + +import mockit.Expectations; +import mockit.Mock; +import mockit.MockUp; +import mockit.Mocked; + +public class TestThreadPoolPublishModelFactory { + protected EventBus eventBus = new EventBus(); + + protected Registry registry = new DefaultRegistry(new ManualClock()); + + @Mocked + ThreadPoolExecutor threadPoolExecutor; + + @Mocked + BlockingQueue<Runnable> queue; + + @Test + public void createDefaultPublishModel() throws JsonProcessingException { + new Expectations() { + { + threadPoolExecutor.getQueue(); + result = queue; + queue.size(); + result = 10d; + } + }; + new MockUp<ScheduledThreadPoolExecutor>() { + @Mock + void delayedExecute(RunnableScheduledFuture<?> task) { + + } + }; + ThreadPoolMonitor.attach(registry, threadPoolExecutor, "test"); + + PublishModelFactory factory = new PublishModelFactory(Lists.newArrayList(registry.iterator())); + DefaultPublishModel model = factory.createDefaultPublishModel(); + + Assert.assertEquals( + "{\"test\":{\"avgTaskCount\":0.0,\"avgCompletedTaskCount\":0.0,\"currentThreadsBusy\":0,\"maxThreads\":0,\"poolSize\":0,\"corePoolSize\":0,\"queueSize\":10}}", + JsonUtils.writeValueAsString(model.getThreadPools())); + } +} -- To stop receiving notification emails like this one, please contact wuji...@apache.org.