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/03/31 07:17:22 UTC

[incubator-servicecomb-java-chassis] 04/07: SCB-384 convert 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 1866b58dcc138187dbcfcce7935ccf1707e43168
Author: wujimin <wu...@huawei.com>
AuthorDate: Fri Mar 23 16:44:43 2018 +0800

    SCB-384 convert measurements to publish model
---
 .../metrics/core/publish/PublishModelFactory.java  |  92 +++++++++++++++
 .../metrics/core/publish/PublishUtils.java         |  74 ++++++++++++
 .../core/publish/TestPublishModelFactory.java      | 131 +++++++++++++++++++++
 .../metrics/core/publish/TestPublishUtils.java     |  75 ++++++++++++
 4 files changed, 372 insertions(+)

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
new file mode 100644
index 0000000..7d03573
--- /dev/null
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java
@@ -0,0 +1,92 @@
+/*
+ * 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.List;
+
+import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementGroupConfig;
+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.model.DefaultPublishModel;
+import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerfGroups;
+import org.apache.servicecomb.swagger.invocation.InvocationType;
+
+import com.netflix.spectator.api.Meter;
+
+public class PublishModelFactory {
+  private MeasurementTree tree;
+
+  public PublishModelFactory(List<Meter> meters) {
+    tree = createMeasurementTree(meters);
+  }
+
+  protected MeasurementTree createMeasurementTree(List<Meter> meters) {
+    MeasurementGroupConfig groupConfig = createMeasurementGroupConfig();
+
+    MeasurementTree tree = new MeasurementTree();
+    tree.from(meters.iterator(), groupConfig);
+    return tree;
+  }
+
+  protected MeasurementGroupConfig createMeasurementGroupConfig() {
+    MeasurementGroupConfig groupConfig = new MeasurementGroupConfig();
+    groupConfig.addGroup(MeterInvocationConst.INVOCATION_NAME,
+        MeterInvocationConst.TAG_ROLE,
+        MeterInvocationConst.TAG_TRANSPORT,
+        MeterInvocationConst.TAG_OPERATION,
+        MeterInvocationConst.TAG_STATUS,
+        MeterInvocationConst.TAG_STAGE,
+        MeterInvocationConst.TAG_STATISTIC);
+    return groupConfig;
+  }
+
+  protected OperationPerfGroups generateOperationPerfGroups(MeasurementTree tree, String invocationTypeName) {
+    MeasurementNode node = tree.findChild(MeterInvocationConst.INVOCATION_NAME, invocationTypeName);
+    if (node == null) {
+      return null;
+    }
+
+    OperationPerfGroups groups = new OperationPerfGroups();
+
+    // group by transport
+    for (MeasurementNode transportNode : node.getChildren().values()) {
+      // group by operation
+      for (MeasurementNode operationNode : transportNode.getChildren().values()) {
+        // group by status
+        for (MeasurementNode statusNode : operationNode.getChildren().values()) {
+          PublishUtils.addOperationPerfGroups(groups, transportNode.getName(), operationNode.getName(), statusNode);
+        }
+      }
+    }
+
+    return groups;
+  }
+
+  public DefaultPublishModel createDefaultPublishModel() {
+    DefaultPublishModel model = new DefaultPublishModel();
+
+    model
+        .getConsumer()
+        .setOperationPerfGroups(generateOperationPerfGroups(tree, InvocationType.CONSUMER.name()));
+    model
+        .getProducer()
+        .setOperationPerfGroups(generateOperationPerfGroups(tree, InvocationType.PRODUCER.name()));
+
+    return model;
+  }
+}
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishUtils.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishUtils.java
new file mode 100644
index 0000000..16680c7
--- /dev/null
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishUtils.java
@@ -0,0 +1,74 @@
+/*
+ * 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.HashMap;
+import java.util.Map;
+
+import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNode;
+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;
+import org.apache.servicecomb.metrics.core.publish.model.invocation.PerfInfo;
+
+import com.netflix.spectator.api.Statistic;
+
+public final class PublishUtils {
+  private PublishUtils() {
+  }
+
+  public static PerfInfo createPerfInfo(MeasurementNode stageNode) {
+    PerfInfo perfInfo = new PerfInfo();
+
+    perfInfo.setTps((int) stageNode.findChild(Statistic.count.name()).summary());
+    perfInfo.setMsTotalTime(stageNode.findChild(Statistic.totalTime.name()).summary() * 1000);
+    // when UT with DefaultRegistry, there is no max value
+    MeasurementNode maxNode = stageNode.findChild(Statistic.max.name());
+    if (maxNode != null) {
+      perfInfo.setMsMaxLatency(maxNode.summary() * 1000);
+    }
+
+    return perfInfo;
+  }
+
+  public static OperationPerf createOperationPerf(String operation, MeasurementNode statusNode) {
+    OperationPerf operationPerf = new OperationPerf();
+
+    operationPerf.setOperation(operation);
+    for (MeasurementNode stageNode : statusNode.getChildren().values()) {
+      PerfInfo perfInfo = createPerfInfo(stageNode);
+      operationPerf.getStages().put(stageNode.getName(), perfInfo);
+    }
+
+    return operationPerf;
+  }
+
+  public static void addOperationPerfGroups(OperationPerfGroups operationPerfGroups, String transport, String operation,
+      MeasurementNode statusNode) {
+    Map<String, OperationPerfGroup> statusMap = operationPerfGroups
+        .getGroups()
+        .computeIfAbsent(transport, tn -> {
+          return new HashMap<>();
+        });
+    OperationPerfGroup group = statusMap.computeIfAbsent(statusNode.getName(), status -> {
+      return new OperationPerfGroup(transport, status);
+    });
+
+    OperationPerf operationPerf = createOperationPerf(operation, statusNode);
+    group.addOperationPerf(operationPerf);
+  }
+}
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/TestPublishModelFactory.java
new file mode 100644
index 0000000..4135cf0
--- /dev/null
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishModelFactory.java
@@ -0,0 +1,131 @@
+/*
+ * 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.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.metrics.core.publish.model.DefaultPublishModel;
+import org.apache.servicecomb.swagger.invocation.InvocationType;
+import org.apache.servicecomb.swagger.invocation.Response;
+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.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 {
+  @Mocked
+  Invocation invocation;
+
+  @Mocked
+  Response response;
+
+  InvocationType invocationType;
+
+  @Test
+  public void createDefaultPublishModel() throws JsonProcessingException {
+    Registry registry = prepareRegistry();
+    List<Meter> meters = Lists.newArrayList(registry);
+    PublishModelFactory factory = new PublishModelFactory(meters);
+    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));
+  }
+
+  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());
+
+    new MockUp<System>() {
+      @Mock
+      long nanoTime() {
+        return 10;
+      }
+    };
+
+    invocationType = InvocationType.CONSUMER;
+    new MockUp<Invocation>() {
+      @Mock
+      InvocationType getInvocationType() {
+        return invocationType;
+      }
+
+      @Mock
+      boolean isConsumer() {
+        return InvocationType.CONSUMER.equals(invocationType);
+      }
+
+      @Mock
+      String getRealTransportName() {
+        return Const.RESTFUL;
+      }
+
+      @Mock
+      String getMicroserviceQualifiedName() {
+        return "m.s.o";
+      }
+
+      @Mock
+      long getStartExecutionTime() {
+        return 5;
+      }
+    };
+
+
+    new Expectations() {
+      {
+        response.getStatusCode();
+        result = 200;
+      }
+    };
+    InvocationFinishEvent finishEvent = new InvocationFinishEvent(invocation, response);
+    eventBus.post(finishEvent);
+
+    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
new file mode 100644
index 0000000..29ddcc6
--- /dev/null
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishUtils.java
@@ -0,0 +1,75 @@
+/*
+ * 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.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.metrics.core.meter.invocation.MeterInvocationConst;
+import org.apache.servicecomb.metrics.core.publish.PublishUtils;
+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;
+import org.apache.servicecomb.metrics.core.publish.model.invocation.PerfInfo;
+import org.apache.servicecomb.metrics.core.publish.model.invocation.Utils;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestPublishUtils {
+  String op = "op";
+
+  @Test
+  public void createPerfInfo() {
+    MeasurementNode stageNode = Utils.createStageNode(MeterInvocationConst.STAGE_TOTAL, 10, 10, 100);
+
+    PerfInfo perf = PublishUtils.createPerfInfo(stageNode);
+
+    Assert.assertEquals(10, perf.getTps());
+    Assert.assertEquals(1000, perf.calcMsLatency(), 0);
+    Assert.assertEquals(100000, perf.getMsMaxLatency(), 0);
+  }
+
+  @Test
+  public void createOperationPerf() {
+    OperationPerf opPerf = Utils.createOperationPerf(op);
+
+    PerfInfo perfInfo = opPerf.findStage(MeterInvocationConst.STAGE_TOTAL);
+    Assert.assertEquals(10, perfInfo.getTps());
+    Assert.assertEquals(1000, perfInfo.calcMsLatency(), 0);
+    Assert.assertEquals(100000, perfInfo.getMsMaxLatency(), 0);
+  }
+
+  @Test
+  public void addOperationPerfGroups() {
+    OperationPerfGroups groups = new OperationPerfGroups();
+    PublishUtils.addOperationPerfGroups(groups,
+        Const.RESTFUL,
+        op,
+        Utils.createStatusNode(Status.OK.name(), Utils.totalStageNode));
+
+    Map<String, OperationPerfGroup> statusMap = groups.getGroups().get(Const.RESTFUL);
+    OperationPerfGroup group = statusMap.get(Status.OK.name());
+
+    PerfInfo perfInfo = group.getSummary().findStage(MeterInvocationConst.STAGE_TOTAL);
+    Assert.assertEquals(10, perfInfo.getTps());
+    Assert.assertEquals(1000, perfInfo.calcMsLatency(), 0);
+    Assert.assertEquals(100000, perfInfo.getMsMaxLatency(), 0);
+  }
+}

-- 
To stop receiving notification emails like this one, please contact
wujimin@apache.org.