This is an automated email from the ASF dual-hosted git repository. ningjiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-java-chassis.git
commit f9ca59a17c5c6e1a5617992eca7510c02e3b4b10 Author: zhengyangyong <[email protected]> AuthorDate: Sat Feb 24 19:45:57 2018 +0800 SCB-327 minor refactor and improve performance Signed-off-by: zhengyangyong <[email protected]> --- .../demo/perf/PerfMetricsFilePublisher.java | 14 ++-- .../foundation/common/event/EventBus.java | 16 ++-- .../foundation/common/event/TestEventBus.java | 4 +- .../metrics/health/HealthCheckerManager.java | 27 ++++--- .../foundation/metrics/publish/Metric.java | 32 ++++---- .../foundation/metrics/publish/MetricNode.java | 92 +++++++++++++--------- .../foundation/metrics/publish/MetricsLoader.java | 2 +- .../metrics/health/TestHealthCheckerManager.java | 14 +--- .../foundation/metrics/publish/TestMetricNode.java | 4 +- .../metrics/publish/TestMetricsLoader.java | 2 +- .../metrics/core/AbstractInvocationMetrics.java | 73 +++++++++++++++++ .../metrics/core/ConsumerInvocationMetrics.java | 33 ++++++++ .../metrics/core/InvocationMetricsManager.java | 85 ++++++++++++++++++++ .../servicecomb/metrics/core/MonitorManager.java | 18 ++--- .../metrics/core/ProducerInvocationMetrics.java | 37 +++++++++ .../event/InvocationFinishedEventListener.java | 37 ++------- .../InvocationStartExecutionEventListener.java | 10 +-- .../core/event/InvocationStartedEventListener.java | 9 +-- .../core/publish/HealthCheckerPublisher.java | 23 +----- .../metrics/core/TestHealthCheckerPublisher.java | 7 +- 20 files changed, 365 insertions(+), 174 deletions(-) diff --git a/demo/perf/src/main/java/org/apache/servicecomb/demo/perf/PerfMetricsFilePublisher.java b/demo/perf/src/main/java/org/apache/servicecomb/demo/perf/PerfMetricsFilePublisher.java index 537577e..cbbd1d8 100644 --- a/demo/perf/src/main/java/org/apache/servicecomb/demo/perf/PerfMetricsFilePublisher.java +++ b/demo/perf/src/main/java/org/apache/servicecomb/demo/perf/PerfMetricsFilePublisher.java @@ -73,13 +73,13 @@ public class PerfMetricsFilePublisher { MetricNode treeNode = loader .getMetricTree(MetricsConst.SERVICECOMB_INVOCATION, MetricsConst.TAG_ROLE, MetricsConst.TAG_OPERATION, MetricsConst.TAG_STATUS); - if (treeNode != null && treeNode.getChildren().size() != 0) { - MetricNode consumerNode = treeNode.getChildren().get(String.valueOf(InvocationType.CONSUMER).toLowerCase()); + if (treeNode != null && treeNode.getChildrenCount() != 0) { + MetricNode consumerNode = treeNode.getChildren(String.valueOf(InvocationType.CONSUMER).toLowerCase()); if (consumerNode != null) { sb.append("consumer:\n"); sb.append(" tps latency(ms) status operation\n"); - for (Entry<String, MetricNode> operationNode : consumerNode.getChildren().entrySet()) { - for (Entry<String, MetricNode> statusNode : operationNode.getValue().getChildren().entrySet()) { + for (Entry<String, MetricNode> operationNode : consumerNode.getChildren()) { + for (Entry<String, MetricNode> statusNode : operationNode.getValue().getChildren()) { sb.append(String.format(" %-7.0f %-11.3f %-9s %s\n", statusNode.getValue() .getFirstMatchMetricValue(MetricsConst.TAG_STAGE, MetricsConst.STAGE_TOTAL, @@ -92,12 +92,12 @@ public class PerfMetricsFilePublisher { } } - MetricNode producerNode = treeNode.getChildren().get(String.valueOf(InvocationType.PRODUCER).toLowerCase()); + MetricNode producerNode = treeNode.getChildren(String.valueOf(InvocationType.PRODUCER).toLowerCase()); if (producerNode != null) { sb.append("producer:\n"); sb.append(" tps latency(ms) queue(ms) execute(ms) status operation\n"); - for (Entry<String, MetricNode> operationNode : producerNode.getChildren().entrySet()) { - for (Entry<String, MetricNode> statusNode : operationNode.getValue().getChildren().entrySet()) { + for (Entry<String, MetricNode> operationNode : producerNode.getChildren()) { + for (Entry<String, MetricNode> statusNode : operationNode.getValue().getChildren()) { sb.append(String.format(" %-7.0f %-11.3f %-9.3f %-11.3f %-7s %s\n", statusNode.getValue() .getFirstMatchMetricValue(MetricsConst.TAG_STAGE, MetricsConst.STAGE_TOTAL, diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventBus.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventBus.java index 603cdfe..df0a52b 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventBus.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventBus.java @@ -24,8 +24,12 @@ import java.util.concurrent.CopyOnWriteArrayList; import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class EventBus { + private static final Logger LOGGER = LoggerFactory.getLogger(EventBus.class); + private final Map<Class, List<EventListener>> allEventListeners = new ConcurrentHashMapEx<>(); private static final EventBus INSTANCE = new EventBus(); @@ -37,19 +41,21 @@ public class EventBus { private EventBus() { List<EventListener> listeners = SPIServiceUtils.getAllService(EventListener.class); for (EventListener listener : listeners) { - this.registerEventListener(listener.getEventClass(), listener); + this.registerEventListener(listener); + LOGGER.info("EventBus register " + listener.getClass().getName() + + " for process " + listener.getEventClass().getName()); } } - public <T> void registerEventListener(Class<T> cls, EventListener<T> eventListener) { + public <T> void registerEventListener(EventListener<T> eventListener) { List<EventListener> eventListeners = allEventListeners - .computeIfAbsent(cls, f -> new CopyOnWriteArrayList<>()); + .computeIfAbsent(eventListener.getEventClass(), f -> new CopyOnWriteArrayList<>()); eventListeners.add(eventListener); } - public <T> void unregisterEventListener(Class<T> cls, EventListener<T> eventListener) { + public <T> void unregisterEventListener(EventListener<T> eventListener) { List<EventListener> eventListeners = allEventListeners - .computeIfAbsent(cls, f -> new CopyOnWriteArrayList<>()); + .computeIfAbsent(eventListener.getEventClass(), f -> new CopyOnWriteArrayList<>()); if (eventListeners.contains(eventListener)) { eventListeners.remove(eventListener); } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventBus.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventBus.java index d373a6b..d404508 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventBus.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventBus.java @@ -43,7 +43,7 @@ public class TestEventBus { } }; - EventBus.getInstance().registerEventListener(String.class, listener); + EventBus.getInstance().registerEventListener(listener); EventBus.getInstance().triggerEvent("xxx"); await().atMost(1, TimeUnit.SECONDS) @@ -52,7 +52,7 @@ public class TestEventBus { eventReceived.set(false); - EventBus.getInstance().unregisterEventListener(String.class, listener); + EventBus.getInstance().unregisterEventListener(listener); EventBus.getInstance().triggerEvent("xxx"); Thread.sleep(1000); Assert.assertFalse(eventReceived.get()); diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/health/HealthCheckerManager.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/health/HealthCheckerManager.java index 249f129..5e635f3 100644 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/health/HealthCheckerManager.java +++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/health/HealthCheckerManager.java @@ -17,31 +17,40 @@ package org.apache.servicecomb.foundation.metrics.health; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; +import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; + public class HealthCheckerManager { private final Map<String, HealthChecker> healthCheckers; - public HealthCheckerManager() { + private static final HealthCheckerManager INSTANCE = new HealthCheckerManager(); + + public static HealthCheckerManager getInstance() { + return INSTANCE; + } + + private HealthCheckerManager() { this.healthCheckers = new ConcurrentHashMap<>(); + List<HealthChecker> checkers = SPIServiceUtils.getAllService(HealthChecker.class); + for (HealthChecker checker : checkers) { + register(checker); + } } public void register(HealthChecker checker) { healthCheckers.put(checker.getName(), checker); } - public Map<String, HealthCheckResult> check() { - return healthCheckers.entrySet().stream().collect(Collectors.toMap(Entry::getKey, e -> e.getValue().check())); + public void unregister(String name) { + healthCheckers.remove(name); } - public HealthCheckResult check(String name) { - HealthChecker checker = healthCheckers.get(name); - if (checker != null) { - return checker.check(); - } - return null; + public Map<String, HealthCheckResult> check() { + return healthCheckers.entrySet().stream().collect(Collectors.toMap(Entry::getKey, e -> e.getValue().check())); } } diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/Metric.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/Metric.java index 5402054..0c1ce87 100644 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/Metric.java +++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/Metric.java @@ -34,8 +34,15 @@ public class Metric { return name; } - public Map<String, String> getTags() { - return tags; + public Metric(String id, double value) { + String[] nameAndTag = id.split("\\("); + this.tags = new HashMap<>(); + String[] tagAnValues = nameAndTag[1].split("[=,)]"); + for (int i = 0; i < tagAnValues.length; i += 2) { + this.tags.put(tagAnValues[i], tagAnValues[i + 1]); + } + this.name = nameAndTag[0]; + this.value = value; } public double getValue() { @@ -51,24 +58,21 @@ public class Metric { return value; } - public Metric(String id, double value) { - String[] nameAndTag = id.split("\\("); - this.tags = new HashMap<>(); - String[] tagAnValues = nameAndTag[1].split("[=,)]"); - for (int i = 0; i < tagAnValues.length; i += 2) { - this.tags.put(tagAnValues[i], tagAnValues[i + 1]); - } - this.name = nameAndTag[0]; - this.value = value; + public boolean containsTagKey(String tagKey) { + return tags.containsKey(tagKey); + } + + public String getTagValue(String tagKey) { + return tags.get(tagKey); } - public boolean containTag(String tagKey, String tagValue) { + public boolean containsTag(String tagKey, String tagValue) { return tags.containsKey(tagKey) && tagValue.equals(tags.get(tagKey)); } - public boolean containTag(String... tags) { + public boolean containsTag(String... tags) { for (int i = 0; i < tags.length; i += 2) { - if (!containTag(tags[i], tags[i + 1])) { + if (!containsTag(tags[i], tags[i + 1])) { return false; } } diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MetricNode.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MetricNode.java index 6042de6..1d47366 100644 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MetricNode.java +++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MetricNode.java @@ -27,6 +27,8 @@ import java.util.concurrent.TimeUnit; import org.apache.servicecomb.foundation.metrics.MetricsConst; +import com.google.common.collect.Lists; + public class MetricNode { private final String tagKey; @@ -34,12 +36,53 @@ public class MetricNode { private final Map<String, MetricNode> children; - public List<Metric> getMetrics() { + public MetricNode(Iterable<Metric> metrics, String... groupTagKeys) { + if (groupTagKeys == null || groupTagKeys.length == 0) { + this.tagKey = null; + this.metrics = Lists.newArrayList(metrics); + this.children = null; + } else { + this.tagKey = groupTagKeys[0]; + this.metrics = null; + this.children = new HashMap<>(); + Map<String, List<Metric>> groups = groupByTag(metrics, this.tagKey); + if (groupTagKeys.length == 1) { + for (Entry<String, List<Metric>> group : groups.entrySet()) { + this.children.put(group.getKey(), new MetricNode(null, group.getValue(), null)); + } + } else { + for (Entry<String, List<Metric>> group : groups.entrySet()) { + this.children.put(group.getKey(), + new MetricNode(group.getValue(), Arrays.copyOfRange(groupTagKeys, 1, groupTagKeys.length))); + } + } + } + } + + private MetricNode(String tagKey, List<Metric> metrics, Map<String, MetricNode> children) { + this.tagKey = tagKey; + this.metrics = metrics; + this.children = children; + } + + public Iterable<Metric> getMetrics() { return metrics; } - public Map<String, MetricNode> getChildren() { - return children; + public int getMetricCount() { + return metrics.size(); + } + + public Iterable<Entry<String, MetricNode>> getChildren() { + return children.entrySet(); + } + + public MetricNode getChildren(String tagValue) { + return children.get(tagValue); + } + + public int getChildrenCount() { + return children.size(); } public MetricNode getChildrenNode(String tagValue) { @@ -48,7 +91,7 @@ public class MetricNode { public Double getFirstMatchMetricValue(String tagKey, String tagValue) { for (Metric metric : this.metrics) { - if (metric.containTag(tagKey, tagValue)) { + if (metric.containsTag(tagKey, tagValue)) { return metric.getValue(); } } @@ -57,7 +100,7 @@ public class MetricNode { public Double getFirstMatchMetricValue(TimeUnit unit, String tagKey, String tagValue) { for (Metric metric : this.metrics) { - if (metric.containTag(tagKey, tagValue)) { + if (metric.containsTag(tagKey, tagValue)) { return metric.getValue(unit); } } @@ -66,7 +109,7 @@ public class MetricNode { public Double getFirstMatchMetricValue(String... tags) { for (Metric metric : this.metrics) { - if (metric.containTag(tags)) { + if (metric.containsTag(tags)) { return metric.getValue(); } } @@ -75,7 +118,7 @@ public class MetricNode { public Double getFirstMatchMetricValue(TimeUnit unit, String... tags) { for (Metric metric : this.metrics) { - if (metric.containTag(tags)) { + if (metric.containsTag(tags)) { return metric.getValue(unit); } } @@ -90,40 +133,11 @@ public class MetricNode { return getFirstMatchMetricValue(unit, MetricsConst.TAG_STATISTIC, statisticValue); } - public MetricNode(List<Metric> metrics, String... groupTagKeys) { - if (groupTagKeys == null || groupTagKeys.length == 0) { - this.tagKey = null; - this.metrics = metrics; - this.children = null; - } else { - this.tagKey = groupTagKeys[0]; - this.metrics = null; - this.children = new HashMap<>(); - Map<String, List<Metric>> groups = groupByTag(metrics, this.tagKey); - if (groupTagKeys.length == 1) { - for (Entry<String, List<Metric>> group : groups.entrySet()) { - this.children.put(group.getKey(), new MetricNode(null, group.getValue(), null)); - } - } else { - for (Entry<String, List<Metric>> group : groups.entrySet()) { - this.children.put(group.getKey(), - new MetricNode(group.getValue(), Arrays.copyOfRange(groupTagKeys, 1, groupTagKeys.length))); - } - } - } - } - - private MetricNode(String tagKey, List<Metric> metrics, Map<String, MetricNode> children) { - this.tagKey = tagKey; - this.metrics = metrics; - this.children = children; - } - - private Map<String, List<Metric>> groupByTag(List<Metric> metrics, String tagKey) { + private Map<String, List<Metric>> groupByTag(Iterable<Metric> metrics, String tagKey) { Map<String, List<Metric>> groups = new HashMap<>(); for (Metric metric : metrics) { - if (metric.getTags().containsKey(tagKey)) { - groups.computeIfAbsent(metric.getTags().get(tagKey), g -> new ArrayList<>()).add(metric); + if (metric.containsTagKey(tagKey)) { + groups.computeIfAbsent(metric.getTagValue(tagKey), g -> new ArrayList<>()).add(metric); } } return groups; diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MetricsLoader.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MetricsLoader.java index ff0040e..6d3a396 100644 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MetricsLoader.java +++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MetricsLoader.java @@ -52,7 +52,7 @@ public class MetricsLoader { public double getFirstMatchMetricValue(String name, String tagKey, String tagValue) { if (metrics.containsKey(name)) { for (Metric metric : this.metrics.get(name)) { - if (metric.containTag(tagKey, tagValue)) { + if (metric.containsTag(tagKey, tagValue)) { return metric.getValue(); } } diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/health/TestHealthCheckerManager.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/health/TestHealthCheckerManager.java index c37d7c7..bcc3a35 100644 --- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/health/TestHealthCheckerManager.java +++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/health/TestHealthCheckerManager.java @@ -26,9 +26,7 @@ public class TestHealthCheckerManager { @Test public void testRegistry() { - HealthCheckerManager manager = new HealthCheckerManager(); - - manager.register(new HealthChecker() { + HealthCheckerManager.getInstance().register(new HealthChecker() { @Override public String getName() { return "test"; @@ -40,16 +38,10 @@ public class TestHealthCheckerManager { } }); - Map<String, HealthCheckResult> results = manager.check(); - + Map<String, HealthCheckResult> results = HealthCheckerManager.getInstance().check(); Assert.assertEquals(1, results.size()); - HealthCheckResult result = manager.check().get("test"); - Assert.assertEquals(false, result.isHealthy()); - Assert.assertEquals("bad", result.getInformation()); - Assert.assertEquals("bad call", result.getExtraData()); - - result = manager.check("test"); + HealthCheckResult result = HealthCheckerManager.getInstance().check().get("test"); Assert.assertEquals(false, result.isHealthy()); Assert.assertEquals("bad", result.getInformation()); Assert.assertEquals("bad call", result.getExtraData()); diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/TestMetricNode.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/TestMetricNode.java index 09fc2ec..7468030 100644 --- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/TestMetricNode.java +++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/TestMetricNode.java @@ -44,7 +44,7 @@ public class TestMetricNode { MetricNode node_k1 = node.getChildrenNode("1"); //check metrics list - Assert.assertEquals(3, node_k1.getMetrics().size()); + Assert.assertEquals(3, node_k1.getMetricCount()); //check getFirstMatchMetricValue with single Tag Assert.assertEquals(100, node_k1.getFirstMatchMetricValue("K2", "2"), 0); @@ -64,6 +64,6 @@ public class TestMetricNode { //check generate new MetricNode from existed MetricNode MetricNode newNode = new MetricNode(node_k1.getMetrics(), "K2", "K3"); - Assert.assertEquals(1, newNode.getChildrenNode("2").getChildrenNode("3").getMetrics().size(), 0); + Assert.assertEquals(1, newNode.getChildrenNode("2").getChildrenNode("3").getMetricCount(), 0); } } \ No newline at end of file diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/TestMetricsLoader.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/TestMetricsLoader.java index 8c7a6a2..b650819 100644 --- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/TestMetricsLoader.java +++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/TestMetricsLoader.java @@ -40,6 +40,6 @@ public class TestMetricsLoader { MetricsLoader loader = new MetricsLoader(metrics); Assert.assertEquals(200.0, loader.getFirstMatchMetricValue("X", "K3", "30"), 0); MetricNode node = loader.getMetricTree("X", "K1"); - Assert.assertEquals(2, node.getChildren().size()); + Assert.assertEquals(2, node.getChildrenCount()); } } diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/AbstractInvocationMetrics.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/AbstractInvocationMetrics.java new file mode 100644 index 0000000..104aa64 --- /dev/null +++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/AbstractInvocationMetrics.java @@ -0,0 +1,73 @@ +/* + * 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.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.servicecomb.foundation.metrics.MetricsConst; + +import com.netflix.servo.monitor.Counter; +import com.netflix.servo.monitor.MaxGauge; +import com.netflix.servo.monitor.StepCounter; +import com.netflix.servo.monitor.Timer; + +abstract class AbstractInvocationMetrics { + private final Counter tps; + + private final Counter count; + + private final Map<String, Timer> averageLatencies; + + private final Map<String, MaxGauge> maxLatencies; + + AbstractInvocationMetrics(String... tags) { + String[] tagsWithStage = ArrayUtils.addAll(tags, MetricsConst.TAG_STAGE, MetricsConst.STAGE_TOTAL); + this.tps = MonitorManager.getInstance().getCounter(StepCounter::new, MetricsConst.SERVICECOMB_INVOCATION, + ArrayUtils.addAll(tagsWithStage, MetricsConst.TAG_STATISTIC, "tps")); + this.count = MonitorManager.getInstance().getCounter(MetricsConst.SERVICECOMB_INVOCATION, + ArrayUtils.addAll(tagsWithStage, MetricsConst.TAG_STATISTIC, "count")); + + this.averageLatencies = new HashMap<>(); + this.maxLatencies = new HashMap<>(); + this.addLatencyMonitors(MetricsConst.STAGE_TOTAL, tags); + } + + void updateCallMonitors() { + tps.increment(); + count.increment(); + } + + void updateLatencyMonitors(String stage, long value, TimeUnit unit) { + averageLatencies.get(stage).record(value, unit); + maxLatencies.get(stage).update(unit.toMillis(value)); + } + + void addLatencyMonitors(String stage, String... tags) { + String[] tagsWithStageAndUnit = ArrayUtils + .addAll(tags, MetricsConst.TAG_STAGE, stage, MetricsConst.TAG_UNIT, String.valueOf(TimeUnit.MILLISECONDS)); + this.averageLatencies.put(stage, MonitorManager.getInstance() + .getTimer(MetricsConst.SERVICECOMB_INVOCATION, + ArrayUtils.addAll(tagsWithStageAndUnit, MetricsConst.TAG_STATISTIC, "latency"))); + this.maxLatencies.put(stage, MonitorManager.getInstance() + .getMaxGauge(MetricsConst.SERVICECOMB_INVOCATION, + ArrayUtils.addAll(tagsWithStageAndUnit, MetricsConst.TAG_STATISTIC, "max"))); + } +} diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ConsumerInvocationMetrics.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ConsumerInvocationMetrics.java new file mode 100644 index 0000000..c370f79 --- /dev/null +++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ConsumerInvocationMetrics.java @@ -0,0 +1,33 @@ +/* + * 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.concurrent.TimeUnit; + +import org.apache.servicecomb.foundation.metrics.MetricsConst; + +public class ConsumerInvocationMetrics extends AbstractInvocationMetrics { + public ConsumerInvocationMetrics(String... tags) { + super(tags); + } + + public void update(long totalElapsedNanoTime) { + this.updateCallMonitors(); + this.updateLatencyMonitors(MetricsConst.STAGE_TOTAL, totalElapsedNanoTime, TimeUnit.NANOSECONDS); + } +} diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/InvocationMetricsManager.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/InvocationMetricsManager.java new file mode 100644 index 0000000..887cc71 --- /dev/null +++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/InvocationMetricsManager.java @@ -0,0 +1,85 @@ +/* + * 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.Map; + +import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; +import org.apache.servicecomb.foundation.metrics.MetricsConst; +import org.apache.servicecomb.swagger.invocation.InvocationType; + +import com.netflix.servo.monitor.Counter; + +public class InvocationMetricsManager { + + //invocationName -> statusCode -> ConsumerInvocationMetrics + private final Map<String, Map<Integer, ConsumerInvocationMetrics>> consumerMetrics; + + //invocationName -> statusCode -> ProducerInvocationMetrics + private final Map<String, Map<Integer, ProducerInvocationMetrics>> producerMetrics; + + //invocationName -> Counter + private final Map<String, Counter> waitInQueueCounters; + + private static final InvocationMetricsManager INSTANCE = new InvocationMetricsManager(); + + public static InvocationMetricsManager getInstance() { + return INSTANCE; + } + + private InvocationMetricsManager() { + this.consumerMetrics = new ConcurrentHashMapEx<>(); + this.producerMetrics = new ConcurrentHashMapEx<>(); + this.waitInQueueCounters = new ConcurrentHashMapEx<>(); + } + + public void incrementWaitInQueue(String invocationName) { + updateWaitInQueue(invocationName, 1); + } + + public void decrementWaitInQueue(String invocationName) { + updateWaitInQueue(invocationName, -1); + } + + private void updateWaitInQueue(String invocationName, long value) { + waitInQueueCounters.computeIfAbsent(invocationName, + f -> MonitorManager.getInstance().getCounter( + MetricsConst.SERVICECOMB_INVOCATION, MetricsConst.TAG_OPERATION, invocationName, + MetricsConst.TAG_STAGE, MetricsConst.STAGE_QUEUE, + MetricsConst.TAG_ROLE, String.valueOf(InvocationType.PRODUCER).toLowerCase(), + MetricsConst.TAG_STATISTIC, "waitInQueue")).increment(value); + } + + public void updateProducer(String invocationName, int statusCode, long inQueueNanoTime, long executionElapsedNanoTime, + long totalElapsedNanoTime) { + producerMetrics.computeIfAbsent(invocationName, f -> new ConcurrentHashMapEx<>()) + .computeIfAbsent(statusCode, f -> new ProducerInvocationMetrics( + MetricsConst.TAG_OPERATION, invocationName, + MetricsConst.TAG_ROLE, String.valueOf(InvocationType.PRODUCER).toLowerCase(), + MetricsConst.TAG_STATUS, String.valueOf(statusCode))) + .update(inQueueNanoTime, executionElapsedNanoTime, totalElapsedNanoTime); + } + + public void updateConsumer(String invocationName, int statusCode, long totalElapsedNanoTime) { + consumerMetrics.computeIfAbsent(invocationName, f -> new ConcurrentHashMapEx<>()) + .computeIfAbsent(statusCode, f -> new ConsumerInvocationMetrics( + MetricsConst.TAG_OPERATION, invocationName, + MetricsConst.TAG_ROLE, String.valueOf(InvocationType.CONSUMER).toLowerCase(), + MetricsConst.TAG_STATUS, String.valueOf(statusCode))).update(totalElapsedNanoTime); + } +} diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MonitorManager.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MonitorManager.java index 76ac3ba..d983216 100644 --- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MonitorManager.java +++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MonitorManager.java @@ -17,14 +17,13 @@ package org.apache.servicecomb.metrics.core; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.SortedMap; import java.util.TreeMap; import java.util.concurrent.Callable; +import java.util.function.Function; import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; import org.apache.servicecomb.foundation.metrics.MetricsConst; @@ -41,7 +40,6 @@ import com.netflix.servo.monitor.MaxGauge; import com.netflix.servo.monitor.Monitor; import com.netflix.servo.monitor.MonitorConfig; import com.netflix.servo.monitor.MonitorConfig.Builder; -import com.netflix.servo.monitor.StepCounter; import com.netflix.servo.monitor.Timer; import com.netflix.servo.tag.Tag; import com.netflix.servo.tag.TagList; @@ -50,8 +48,6 @@ public class MonitorManager { private final Map<String, Counter> counters; - private final Map<String, Counter> stepCounters; - private final Map<String, MaxGauge> maxGauges; private final Map<String, Gauge> gauges; @@ -68,7 +64,6 @@ public class MonitorManager { private MonitorManager() { this.counters = new ConcurrentHashMapEx<>(); - this.stepCounters = new ConcurrentHashMapEx<>(); this.maxGauges = new ConcurrentHashMapEx<>(); this.gauges = new ConcurrentHashMapEx<>(); this.timers = new ConcurrentHashMapEx<>(); @@ -90,9 +85,9 @@ public class MonitorManager { }); } - public Counter getStepCounter(String name, String... tags) { - return stepCounters.computeIfAbsent(getMonitorKey(name, tags), f -> { - Counter counter = new StepCounter(getConfig(name, tags)); + public Counter getCounter(Function<MonitorConfig, Counter> function, String name, String... tags) { + return counters.computeIfAbsent(getMonitorKey(name, tags), f -> { + Counter counter = function.apply(getConfig(name, tags)); basicMonitorRegistry.register(counter); return counter; }); @@ -124,8 +119,7 @@ public class MonitorManager { public Map<String, Double> measure() { Map<String, Double> measurements = new HashMap<>(); - List<Monitor> monitors = new ArrayList<>(basicMonitorRegistry.getRegisteredMonitors()); - for (Monitor monitor : monitors) { + for (Monitor monitor : basicMonitorRegistry.getRegisteredMonitors()) { measurements.put(getMonitorKey(monitor.getConfig()), ((Number) monitor.getValue(0)).doubleValue()); } @@ -157,7 +151,7 @@ public class MonitorManager { return name; } - private static String getMonitorKey(MonitorConfig config) { + private String getMonitorKey(MonitorConfig config) { TagList tags = config.getTags(); StringBuilder tagPart = new StringBuilder("("); for (Tag tag : tags) { diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ProducerInvocationMetrics.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ProducerInvocationMetrics.java new file mode 100644 index 0000000..c869be0 --- /dev/null +++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ProducerInvocationMetrics.java @@ -0,0 +1,37 @@ +/* + * 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.concurrent.TimeUnit; + +import org.apache.servicecomb.foundation.metrics.MetricsConst; + +public class ProducerInvocationMetrics extends AbstractInvocationMetrics { + public ProducerInvocationMetrics(String... tags) { + super(tags); + this.addLatencyMonitors(MetricsConst.STAGE_QUEUE, tags); + this.addLatencyMonitors(MetricsConst.STAGE_EXECUTION, tags); + } + + public void update(long inQueueNanoTime, long executionElapsedNanoTime, long totalElapsedNanoTime) { + this.updateCallMonitors(); + this.updateLatencyMonitors(MetricsConst.STAGE_QUEUE, inQueueNanoTime, TimeUnit.NANOSECONDS); + this.updateLatencyMonitors(MetricsConst.STAGE_EXECUTION, executionElapsedNanoTime, TimeUnit.NANOSECONDS); + this.updateLatencyMonitors(MetricsConst.STAGE_TOTAL, totalElapsedNanoTime, TimeUnit.NANOSECONDS); + } +} diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/event/InvocationFinishedEventListener.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/event/InvocationFinishedEventListener.java index 02e218e..51edc6b 100644 --- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/event/InvocationFinishedEventListener.java +++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/event/InvocationFinishedEventListener.java @@ -17,13 +17,9 @@ package org.apache.servicecomb.metrics.core.event; -import java.util.concurrent.TimeUnit; - -import org.apache.commons.lang3.ArrayUtils; import org.apache.servicecomb.core.metrics.InvocationFinishedEvent; import org.apache.servicecomb.foundation.common.event.EventListener; -import org.apache.servicecomb.foundation.metrics.MetricsConst; -import org.apache.servicecomb.metrics.core.MonitorManager; +import org.apache.servicecomb.metrics.core.InvocationMetricsManager; import org.apache.servicecomb.swagger.invocation.InvocationType; public class InvocationFinishedEventListener implements EventListener<InvocationFinishedEvent> { @@ -34,33 +30,12 @@ public class InvocationFinishedEventListener implements EventListener<Invocation @Override public void process(InvocationFinishedEvent data) { - String[] tags = new String[] {MetricsConst.TAG_OPERATION, data.getOperationName(), - MetricsConst.TAG_ROLE, String.valueOf(data.getInvocationType()).toLowerCase(), - MetricsConst.TAG_STATUS, String.valueOf(data.getStatusCode())}; - this.updateLatency(MetricsConst.STAGE_TOTAL, data.getTotalElapsedNanoTime(), tags); - this.updateCount(tags); if (InvocationType.PRODUCER.equals(data.getInvocationType())) { - this.updateLatency(MetricsConst.STAGE_QUEUE, data.getInQueueNanoTime(), tags); - this.updateLatency(MetricsConst.STAGE_EXECUTION, data.getExecutionElapsedNanoTime(), tags); + InvocationMetricsManager.getInstance().updateProducer(data.getOperationName(), data.getStatusCode(), + data.getInQueueNanoTime(), data.getExecutionElapsedNanoTime(), data.getTotalElapsedNanoTime()); + } else { + InvocationMetricsManager.getInstance().updateConsumer(data.getOperationName(), data.getStatusCode(), + data.getTotalElapsedNanoTime()); } } - - private void updateLatency(String stage, long value, String... basicTags) { - String[] tags = ArrayUtils - .addAll(basicTags, MetricsConst.TAG_STAGE, stage, MetricsConst.TAG_UNIT, String.valueOf(TimeUnit.MILLISECONDS)); - MonitorManager.getInstance() - .getTimer(MetricsConst.SERVICECOMB_INVOCATION, ArrayUtils.addAll(tags, MetricsConst.TAG_STATISTIC, "latency")) - .record(value, TimeUnit.NANOSECONDS); - MonitorManager.getInstance() - .getMaxGauge(MetricsConst.SERVICECOMB_INVOCATION, ArrayUtils.addAll(tags, MetricsConst.TAG_STATISTIC, "max")) - .update(TimeUnit.NANOSECONDS.toMillis(value)); - } - - private void updateCount(String... basicTags) { - String[] tags = ArrayUtils.addAll(basicTags, MetricsConst.TAG_STAGE, MetricsConst.STAGE_TOTAL); - MonitorManager.getInstance().getStepCounter(MetricsConst.SERVICECOMB_INVOCATION, - ArrayUtils.addAll(tags, MetricsConst.TAG_STATISTIC, "tps")).increment(); - MonitorManager.getInstance().getCounter(MetricsConst.SERVICECOMB_INVOCATION, - ArrayUtils.addAll(tags, MetricsConst.TAG_STATISTIC, "count")).increment(); - } } diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/event/InvocationStartExecutionEventListener.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/event/InvocationStartExecutionEventListener.java index ba6becc..89ff1b5 100644 --- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/event/InvocationStartExecutionEventListener.java +++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/event/InvocationStartExecutionEventListener.java @@ -19,9 +19,7 @@ package org.apache.servicecomb.metrics.core.event; import org.apache.servicecomb.core.metrics.InvocationStartExecutionEvent; import org.apache.servicecomb.foundation.common.event.EventListener; -import org.apache.servicecomb.foundation.metrics.MetricsConst; -import org.apache.servicecomb.metrics.core.MonitorManager; -import org.apache.servicecomb.swagger.invocation.InvocationType; +import org.apache.servicecomb.metrics.core.InvocationMetricsManager; public class InvocationStartExecutionEventListener implements EventListener<InvocationStartExecutionEvent> { @Override @@ -31,10 +29,6 @@ public class InvocationStartExecutionEventListener implements EventListener<Invo @Override public void process(InvocationStartExecutionEvent data) { - MonitorManager.getInstance().getCounter(MetricsConst.SERVICECOMB_INVOCATION, - MetricsConst.TAG_OPERATION, data.getOperationName(), - MetricsConst.TAG_STAGE, MetricsConst.STAGE_QUEUE, - MetricsConst.TAG_ROLE, String.valueOf(InvocationType.PRODUCER).toLowerCase(), - MetricsConst.TAG_STATISTIC, "waitInQueue").increment(-1); + InvocationMetricsManager.getInstance().decrementWaitInQueue(data.getOperationName()); } } diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/event/InvocationStartedEventListener.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/event/InvocationStartedEventListener.java index 69dc087..117387b 100644 --- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/event/InvocationStartedEventListener.java +++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/event/InvocationStartedEventListener.java @@ -19,8 +19,7 @@ package org.apache.servicecomb.metrics.core.event; import org.apache.servicecomb.core.metrics.InvocationStartedEvent; import org.apache.servicecomb.foundation.common.event.EventListener; -import org.apache.servicecomb.foundation.metrics.MetricsConst; -import org.apache.servicecomb.metrics.core.MonitorManager; +import org.apache.servicecomb.metrics.core.InvocationMetricsManager; import org.apache.servicecomb.swagger.invocation.InvocationType; public class InvocationStartedEventListener implements EventListener<InvocationStartedEvent> { @@ -32,11 +31,7 @@ public class InvocationStartedEventListener implements EventListener<InvocationS @Override public void process(InvocationStartedEvent data) { if (InvocationType.PRODUCER.equals(data.getInvocationType())) { - MonitorManager.getInstance().getCounter(MetricsConst.SERVICECOMB_INVOCATION, - MetricsConst.TAG_OPERATION, data.getOperationName(), - MetricsConst.TAG_STAGE, MetricsConst.STAGE_QUEUE, - MetricsConst.TAG_ROLE, String.valueOf(InvocationType.PRODUCER).toLowerCase(), - MetricsConst.TAG_STATISTIC, "waitInQueue").increment(); + InvocationMetricsManager.getInstance().incrementWaitInQueue(data.getOperationName()); } } } diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/HealthCheckerPublisher.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/HealthCheckerPublisher.java index 0d566ee..17679a3 100644 --- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/HealthCheckerPublisher.java +++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/HealthCheckerPublisher.java @@ -32,29 +32,10 @@ import org.springframework.web.bind.annotation.RequestMethod; @RestSchema(schemaId = "healthEndpoint") @RequestMapping(path = "/health") public class HealthCheckerPublisher { - - private HealthCheckerManager manager; - - public HealthCheckerPublisher() { - init(new HealthCheckerManager()); - } - - public HealthCheckerPublisher(HealthCheckerManager manager) { - init(manager); - } - - private void init(HealthCheckerManager manager) { - this.manager = manager; - List<HealthChecker> checkers = SPIServiceUtils.getAllService(HealthChecker.class); - for (HealthChecker checker : checkers) { - this.manager.register(checker); - } - } - @RequestMapping(path = "/", method = RequestMethod.GET) @CrossOrigin public boolean checkHealth() { - Map<String, HealthCheckResult> results = manager.check(); + Map<String, HealthCheckResult> results = HealthCheckerManager.getInstance().check(); for (HealthCheckResult result : results.values()) { if (!result.isHealthy()) { return false; @@ -66,6 +47,6 @@ public class HealthCheckerPublisher { @RequestMapping(path = "/detail", method = RequestMethod.GET) @CrossOrigin public Map<String, HealthCheckResult> checkHealthDetails() { - return manager.check(); + return HealthCheckerManager.getInstance().check(); } } diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestHealthCheckerPublisher.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestHealthCheckerPublisher.java index 794c0dd..037d3cd 100644 --- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestHealthCheckerPublisher.java +++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestHealthCheckerPublisher.java @@ -30,8 +30,7 @@ public class TestHealthCheckerPublisher { @Test public void test() { - HealthCheckerManager manager = new HealthCheckerManager(); - manager.register(new HealthChecker() { + HealthCheckerManager.getInstance().register(new HealthChecker() { @Override public String getName() { return "test"; @@ -43,7 +42,7 @@ public class TestHealthCheckerPublisher { } }); - manager.register(new HealthChecker() { + HealthCheckerManager.getInstance().register(new HealthChecker() { @Override public String getName() { return "test2"; @@ -55,7 +54,7 @@ public class TestHealthCheckerPublisher { } }); - HealthCheckerPublisher publisher = new HealthCheckerPublisher(manager); + HealthCheckerPublisher publisher = new HealthCheckerPublisher(); Assert.assertEquals(false, publisher.checkHealth()); -- To stop receiving notification emails like this one, please contact [email protected].
