You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by wu...@apache.org on 2018/04/08 15:14:51 UTC

[incubator-servicecomb-java-chassis] 06/09: SCB-422 convert threadPool measurements to publish model

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 <wu...@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
wujimin@apache.org.