You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ni...@apache.org on 2018/01/24 01:21:38 UTC

[incubator-servicecomb-java-chassis] 01/10: SCB-150 add success/failed dimension for call count and tps

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 37a2d03a0c523b3dd7c65bbebff6d0e39973dd5d
Author: zhengyangyong <ya...@huawei.com>
AuthorDate: Thu Jan 11 14:14:09 2018 +0800

    SCB-150 add success/failed dimension for call count and tps
    
    Signed-off-by: zhengyangyong <ya...@huawei.com>
---
 metrics/metrics-common/pom.xml                     |  4 +-
 .../metrics/common/DoubleMetricValue.java          | 60 ++++++++++++++++++++
 .../metrics/common/LongMetricValue.java            | 60 ++++++++++++++++++++
 .../io/servicecomb/metrics/common/MetricValue.java | 65 ++++++++++++++++++++++
 .../servicecomb/metrics/common/CallMetric.java     | 37 +++++++-----
 .../servicecomb/metrics/core/MetricsDimension.java | 39 +++++++++++++
 .../metrics/core/monitor/CallMonitor.java          | 65 ++++++++++++++++++----
 7 files changed, 304 insertions(+), 26 deletions(-)

diff --git a/metrics/metrics-common/pom.xml b/metrics/metrics-common/pom.xml
index 21dddbd..5987595 100644
--- a/metrics/metrics-common/pom.xml
+++ b/metrics/metrics-common/pom.xml
@@ -31,8 +31,8 @@
 
   <dependencies>
     <dependency>
-      <groupId>com.fasterxml.jackson.core</groupId>
-      <artifactId>jackson-databind</artifactId>
+      <groupId>io.servicecomb</groupId>
+      <artifactId>foundation-common</artifactId>
     </dependency>
   </dependencies>
 
diff --git a/metrics/metrics-common/src/main/java/io/servicecomb/metrics/common/DoubleMetricValue.java b/metrics/metrics-common/src/main/java/io/servicecomb/metrics/common/DoubleMetricValue.java
new file mode 100644
index 0000000..c116562
--- /dev/null
+++ b/metrics/metrics-common/src/main/java/io/servicecomb/metrics/common/DoubleMetricValue.java
@@ -0,0 +1,60 @@
+/*
+ * 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 io.servicecomb.metrics.common;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import io.servicecomb.foundation.common.exceptions.ServiceCombException;
+
+public class DoubleMetricValue extends MetricValue<Double> {
+  public DoubleMetricValue(Double value, Map<String, String> dimensions) {
+    super(value, dimensions);
+  }
+
+  public DoubleMetricValue(@JsonProperty("key") String key,
+      @JsonProperty("value") Double value,
+      @JsonProperty("dimensions") Map<String, String> dimensions) {
+    super(key, value, dimensions);
+  }
+
+  public DoubleMetricValue merge(DoubleMetricValue value) {
+    if (this.getKey().equals(value.getKey())) {
+      return new DoubleMetricValue(this.getKey(), this.getValue() + value.getValue(), this.getDimensions());
+    }
+    throw new ServiceCombException("unable merge different key values,source key :" + value.getKey() +
+        " target key :" + this.getKey());
+  }
+
+  public static List<DoubleMetricValue> merge(List<DoubleMetricValue> source, List<DoubleMetricValue> target) {
+    Map<String, DoubleMetricValue> finalValues = new HashMap<>();
+    for (DoubleMetricValue t : target) {
+      finalValues.put(t.getKey(), t);
+    }
+    for (DoubleMetricValue s : source) {
+      if (finalValues.containsKey(s.getKey())) {
+        finalValues.put(s.getKey(), finalValues.get(s.getKey()).merge(s));
+      }
+    }
+    return new ArrayList<>(finalValues.values());
+  }
+}
diff --git a/metrics/metrics-common/src/main/java/io/servicecomb/metrics/common/LongMetricValue.java b/metrics/metrics-common/src/main/java/io/servicecomb/metrics/common/LongMetricValue.java
new file mode 100644
index 0000000..eb0ac8d
--- /dev/null
+++ b/metrics/metrics-common/src/main/java/io/servicecomb/metrics/common/LongMetricValue.java
@@ -0,0 +1,60 @@
+/*
+ * 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 io.servicecomb.metrics.common;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import io.servicecomb.foundation.common.exceptions.ServiceCombException;
+
+public class LongMetricValue extends MetricValue<Long> {
+  public LongMetricValue(Long value, Map<String, String> dimensions) {
+    super(value, dimensions);
+  }
+
+  public LongMetricValue(@JsonProperty("key") String key,
+      @JsonProperty("value") Long value,
+      @JsonProperty("dimensions") Map<String, String> dimensions) {
+    super(key, value, dimensions);
+  }
+
+  public LongMetricValue merge(LongMetricValue value) {
+    if (this.getKey().equals(value.getKey())) {
+      return new LongMetricValue(this.getKey(), this.getValue() + value.getValue(), this.getDimensions());
+    }
+    throw new ServiceCombException("unable merge different key values,source key :" + value.getKey() +
+        " target key :" + this.getKey());
+  }
+
+  public static List<LongMetricValue> merge(List<LongMetricValue> source, List<LongMetricValue> target) {
+    Map<String, LongMetricValue> finalValues = new HashMap<>();
+    for (LongMetricValue t : target) {
+      finalValues.put(t.getKey(), t);
+    }
+    for (LongMetricValue s : source) {
+      if (finalValues.containsKey(s.getKey())) {
+        finalValues.put(s.getKey(), finalValues.get(s.getKey()).merge(s));
+      }
+    }
+    return new ArrayList<>(finalValues.values());
+  }
+}
diff --git a/metrics/metrics-common/src/main/java/io/servicecomb/metrics/common/MetricValue.java b/metrics/metrics-common/src/main/java/io/servicecomb/metrics/common/MetricValue.java
new file mode 100644
index 0000000..c368aba
--- /dev/null
+++ b/metrics/metrics-common/src/main/java/io/servicecomb/metrics/common/MetricValue.java
@@ -0,0 +1,65 @@
+/*
+ * 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 io.servicecomb.metrics.common;
+
+import java.util.Arrays;
+import java.util.Map;
+
+public class MetricValue<T extends Number> {
+  private final String key;
+
+  private final T value;
+
+  private final Map<String, String> dimensions;
+
+  public String getKey() {
+    return key;
+  }
+
+  public T getValue() {
+    return value;
+  }
+
+  public Map<String, String> getDimensions() {
+    return dimensions;
+  }
+
+  public MetricValue(T value, Map<String, String> dimensions) {
+    String finalKey = "{}";
+    if (dimensions != null && dimensions.size() != 0) {
+      String[] keys = dimensions.keySet().toArray(new String[0]);
+      Arrays.sort(keys);
+      StringBuilder builder = new StringBuilder("{");
+      for (String key : keys) {
+        builder.append(String.format("%s=%s,", key, dimensions.get(key)));
+      }
+      builder.deleteCharAt(dimensions.size() - 1);
+      builder.append("}");
+      finalKey = builder.toString();
+    }
+    this.key = finalKey;
+    this.value = value;
+    this.dimensions = dimensions;
+  }
+
+  public MetricValue(String key, T value, Map<String, String> dimensions) {
+    this.key = key;
+    this.value = value;
+    this.dimensions = dimensions;
+  }
+}
diff --git a/metrics/metrics-common/src/main/java/org/apache/servicecomb/metrics/common/CallMetric.java b/metrics/metrics-common/src/main/java/org/apache/servicecomb/metrics/common/CallMetric.java
index 5e0d63b..a65ee92 100644
--- a/metrics/metrics-common/src/main/java/org/apache/servicecomb/metrics/common/CallMetric.java
+++ b/metrics/metrics-common/src/main/java/org/apache/servicecomb/metrics/common/CallMetric.java
@@ -17,7 +17,9 @@
 
 package org.apache.servicecomb.metrics.common;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
@@ -25,37 +27,44 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 public class CallMetric {
   private final String prefix;
 
-  private final long total;
+  private final List<LongMetricValue> totalValues;
 
-  private final double tps;
+  private final List<DoubleMetricValue> tpsValues;
 
-  public long getTotal() {
-    return total;
+  public List<LongMetricValue> getTotalValues() {
+    return totalValues;
   }
 
-  public double getTps() {
-    return tps;
+  public List<DoubleMetricValue> getTpsValues() {
+    return tpsValues;
   }
 
   public CallMetric(String prefix) {
-    this(prefix, 0, 0);
+    this(prefix, new ArrayList<>(), new ArrayList<>());
   }
 
-  public CallMetric(@JsonProperty("prefix") String prefix, @JsonProperty("total") long total,
-      @JsonProperty("tps") double tps) {
+  public CallMetric(@JsonProperty("prefix") String prefix,
+      @JsonProperty("totalValues") List<LongMetricValue> totalValues,
+      @JsonProperty("tpsValues") List<DoubleMetricValue> tpsValues) {
     this.prefix = prefix;
-    this.total = total;
-    this.tps = tps;
+    this.totalValues = totalValues;
+    this.tpsValues = tpsValues;
   }
 
   public CallMetric merge(CallMetric metric) {
-    return new CallMetric(this.prefix, this.total + metric.total, this.tps + metric.tps);
+    return new CallMetric(this.prefix,
+        LongMetricValue.merge(metric.getTotalValues(), this.getTotalValues()),
+        DoubleMetricValue.merge(metric.getTpsValues(), this.getTpsValues()));
   }
 
   public Map<String, Number> toMap() {
     Map<String, Number> metrics = new HashMap<>();
-    metrics.put(prefix + ".total", total);
-    metrics.put(prefix + ".tps", tps);
+    for (MetricValue totalValue : totalValues) {
+      metrics.put(prefix + ".total." + totalValue.getKey(), totalValue.getValue());
+    }
+    for (MetricValue tpsValue : tpsValues) {
+      metrics.put(prefix + ".tps." + tpsValue.getKey(), tpsValue.getValue());
+    }
     return metrics;
   }
 }
diff --git a/metrics/metrics-core/src/main/java/io/servicecomb/metrics/core/MetricsDimension.java b/metrics/metrics-core/src/main/java/io/servicecomb/metrics/core/MetricsDimension.java
new file mode 100644
index 0000000..bf9170f
--- /dev/null
+++ b/metrics/metrics-core/src/main/java/io/servicecomb/metrics/core/MetricsDimension.java
@@ -0,0 +1,39 @@
+/*
+ * 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 io.servicecomb.metrics.core;
+
+import io.servicecomb.foundation.common.exceptions.ServiceCombException;
+
+public class MetricsDimension {
+  public static final String DIMENSION_STATUS = "Status";
+
+  public static final String DIMENSION_STATUS_ALL = "all";
+
+  public static final String DIMENSION_STATUS_SUCCESS = "success";
+
+  public static final String DIMENSION_STATUS_FAILED = "failed";
+
+  public static String[] getDimensionOptions(String dimension) {
+    if (DIMENSION_STATUS.equals(dimension)) {
+      return new String[] {MetricsDimension.DIMENSION_STATUS_ALL,
+          MetricsDimension.DIMENSION_STATUS_SUCCESS,
+          MetricsDimension.DIMENSION_STATUS_FAILED};
+    }
+    throw new ServiceCombException("illegal dimension key : " + dimension);
+  }
+}
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/monitor/CallMonitor.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/monitor/CallMonitor.java
index 1e68201..7174e33 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/monitor/CallMonitor.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/monitor/CallMonitor.java
@@ -19,37 +19,82 @@ package org.apache.servicecomb.metrics.core.monitor;
 
 import org.apache.servicecomb.metrics.common.CallMetric;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 import com.netflix.servo.monitor.BasicCounter;
 import com.netflix.servo.monitor.MonitorConfig;
 import com.netflix.servo.monitor.StepCounter;
+import com.netflix.servo.tag.Tag;
+import com.netflix.servo.tag.TagList;
+
+import io.servicecomb.metrics.common.CallMetric;
+import io.servicecomb.metrics.common.DoubleMetricValue;
+import io.servicecomb.metrics.common.LongMetricValue;
+import io.servicecomb.metrics.core.MetricsDimension;
 
 public class CallMonitor {
   private final String prefix;
 
-  private final BasicCounter total;
+  private final List<BasicCounter> totalCounters;
 
-  private final StepCounter tps;
+  private final List<StepCounter> tpsCounters;
 
-  public CallMonitor(String prefix) {
+  public CallMonitor(String prefix, String... dimensions) {
     this.prefix = prefix;
-    this.total = new BasicCounter(MonitorConfig.builder(prefix + ".total").build());
-    this.tps = new StepCounter(MonitorConfig.builder(prefix + ".tps").build());
+    this.totalCounters = new ArrayList<>();
+    this.tpsCounters = new ArrayList<>();
+    if (dimensions.length == 0) {
+      this.totalCounters.add(new BasicCounter(MonitorConfig.builder(prefix + ".total").build()));
+      this.tpsCounters.add(new StepCounter(MonitorConfig.builder(prefix + ".tps").build()));
+    } else {
+      for (String dimension : dimensions) {
+        for (String option : MetricsDimension.getDimensionOptions(dimension)) {
+          this.totalCounters
+              .add(new BasicCounter(MonitorConfig.builder(prefix + ".total").withTag(dimension, option).build()));
+          this.tpsCounters
+              .add(new StepCounter(MonitorConfig.builder(prefix + ".tps").withTag(dimension, option).build()));
+        }
+      }
+    }
   }
 
   public void increment() {
-    total.increment();
-    tps.increment();
+    for (int i = 0; i < totalCounters.size(); i++) {
+      totalCounters.get(i).increment();
+      tpsCounters.get(i).increment();
+    }
   }
 
   public CallMetric toMetric(int windowTimeIndex) {
-    return new CallMetric(this.prefix, total.getValue(windowTimeIndex).longValue(),
-        this.adjustValue(tps.getValue(windowTimeIndex).doubleValue()));
+    List<LongMetricValue> totalValues = new ArrayList<>();
+    List<DoubleMetricValue> tpsValues = new ArrayList<>();
+    for (int i = 0; i < totalCounters.size(); i++) {
+      totalValues.add(new LongMetricValue(totalCounters.get(i).getValue(windowTimeIndex).longValue(),
+          convertTags(totalCounters.get(i).getConfig().getTags())));
+      tpsValues.add(new DoubleMetricValue(adjustValue(tpsCounters.get(i).getValue(windowTimeIndex).doubleValue()),
+          convertTags(tpsCounters.get(i).getConfig().getTags())));
+    }
+    return new CallMetric(this.prefix, totalValues, tpsValues);
   }
 
   //for time-related monitor type, if stop poll value over one window time,
   //the value may return -1 because servo can't known precise value of previous step
   //so must change to return 0
-  public double adjustValue(double value) {
+  private double adjustValue(double value) {
     return value < 0 ? 0 : value;
   }
+
+  private Map<String, String> convertTags(TagList tags) {
+    if (tags.size() != 0) {
+      Map<String, String> tagMap = new HashMap<>();
+      for (Tag tag : tags) {
+        tagMap.put(tag.getKey(), tag.getValue());
+      }
+      return tagMap;
+    }
+    return null;
+  }
 }

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