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 b44106b876225f8650d167f85bb52908cbb81835
Author: zhengyangyong <[email protected]>
AuthorDate: Tue Jan 16 16:35:02 2018 +0800

    SCB-12 Support Custom Metrics implement
    
    Signed-off-by: zhengyangyong <[email protected]>
---
 .../servicecomb/metrics/common/RegistryMetric.java | 23 ++++--
 .../metrics/core/custom/CounterService.java        | 28 ++++++++
 .../metrics/core/custom/DefaultCounterService.java | 71 +++++++++++++++++++
 .../metrics/core/custom/DefaultGaugeService.java   | 43 ++++++++++++
 .../core/custom/DefaultWindowCounterService.java   | 49 +++++++++++++
 .../metrics/core/custom/GaugeService.java          | 22 ++++++
 .../metrics/core/custom/WindowCounter.java         | 82 ++++++++++++++++++++++
 .../metrics/core/custom/WindowCounterService.java  | 22 ++++++
 .../metrics/core/monitor/RegistryMonitor.java      | 24 ++++++-
 .../metrics/core/TestCustomMetrics.java            | 79 +++++++++++++++++++++
 .../metrics/core/TestEventAndRunner.java           |  6 +-
 .../metrics/core/TestHealthCheckerManager.java     | 16 +++++
 .../servicecomb/metrics/core/TestPublisher.java    |  6 +-
 .../metrics/prometheus/MetricsCollector.java       |  5 ++
 samples/custom-business-metrics/pom.xml            | 56 +++++++++++++++
 .../metrics/custom/CustomMetricsApplication.java   | 30 ++++++++
 .../samples/metrics/custom/ShopDemoService.java    | 70 ++++++++++++++++++
 .../servicecomb/samples/mwf/TestWriteFile.java     |  3 +-
 samples/pom.xml                                    |  1 +
 19 files changed, 624 insertions(+), 12 deletions(-)

diff --git 
a/metrics/metrics-common/src/main/java/org/apache/servicecomb/metrics/common/RegistryMetric.java
 
b/metrics/metrics-common/src/main/java/org/apache/servicecomb/metrics/common/RegistryMetric.java
index a2ac66e..d838628 100644
--- 
a/metrics/metrics-common/src/main/java/org/apache/servicecomb/metrics/common/RegistryMetric.java
+++ 
b/metrics/metrics-common/src/main/java/org/apache/servicecomb/metrics/common/RegistryMetric.java
@@ -23,11 +23,13 @@ import java.util.Map;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class RegistryMetric {
-  private InstanceMetric instanceMetric;
+  private final InstanceMetric instanceMetric;
 
-  private Map<String, ConsumerInvocationMetric> consumerMetrics;
+  private final Map<String, ConsumerInvocationMetric> consumerMetrics;
 
-  private Map<String, ProducerInvocationMetric> producerMetrics;
+  private final Map<String, ProducerInvocationMetric> producerMetrics;
+
+  private final Map<String, Number> customMetrics;
 
   public InstanceMetric getInstanceMetric() {
     return instanceMetric;
@@ -41,19 +43,27 @@ public class RegistryMetric {
     return producerMetrics;
   }
 
+  public Map<String, Number> getCustomMetrics() {
+    return customMetrics;
+  }
+
   public RegistryMetric(@JsonProperty("instanceMetric") InstanceMetric 
instanceMetric,
       @JsonProperty("consumerMetrics") Map<String, ConsumerInvocationMetric> 
consumerMetrics,
-      @JsonProperty("producerMetrics") Map<String, ProducerInvocationMetric> 
producerMetrics) {
+      @JsonProperty("producerMetrics") Map<String, ProducerInvocationMetric> 
producerMetrics,
+      @JsonProperty("customMetrics") Map<String, Number> customMetrics) {
     this.consumerMetrics = consumerMetrics;
     this.producerMetrics = producerMetrics;
     this.instanceMetric = instanceMetric;
+    this.customMetrics = customMetrics;
   }
 
   public RegistryMetric(SystemMetric systemMetric,
       Map<String, ConsumerInvocationMetric> consumerMetrics,
-      Map<String, ProducerInvocationMetric> producerMetrics) {
+      Map<String, ProducerInvocationMetric> producerMetrics,
+      Map<String, Number> customMetrics) {
     this.consumerMetrics = consumerMetrics;
     this.producerMetrics = producerMetrics;
+    this.customMetrics = customMetrics;
 
     ConsumerInvocationMetric instanceConsumerInvocationMetric = new 
ConsumerInvocationMetric("instance",
         MetricsConst.INSTANCE_CONSUMER_PREFIX,
@@ -79,8 +89,7 @@ public class RegistryMetric {
   }
 
   public Map<String, Number> toMap() {
-    Map<String, Number> metrics = new HashMap<>();
-    metrics.putAll(instanceMetric.toMap());
+    Map<String, Number> metrics = new HashMap<>(instanceMetric.toMap());
     for (ConsumerInvocationMetric metric : consumerMetrics.values()) {
       metrics.putAll(metric.toMap());
     }
diff --git 
a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/custom/CounterService.java
 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/custom/CounterService.java
new file mode 100644
index 0000000..2dc8aa1
--- /dev/null
+++ 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/custom/CounterService.java
@@ -0,0 +1,28 @@
+/*
+ * 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.custom;
+
+public interface CounterService {
+  void increment(String name);
+
+  void increment(String name, long value);
+
+  void decrement(String name);
+
+  void reset(String name);
+}
diff --git 
a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/custom/DefaultCounterService.java
 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/custom/DefaultCounterService.java
new file mode 100644
index 0000000..f9b9210
--- /dev/null
+++ 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/custom/DefaultCounterService.java
@@ -0,0 +1,71 @@
+/*
+ * 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.custom;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
+import org.springframework.stereotype.Component;
+
+import com.netflix.servo.monitor.BasicCounter;
+import com.netflix.servo.monitor.MonitorConfig;
+
+@Component
+public class DefaultCounterService implements CounterService {
+
+  private final Map<String, BasicCounter> counters;
+
+  public DefaultCounterService() {
+    this.counters = new ConcurrentHashMapEx<>();
+  }
+
+  @Override
+  public void increment(String name) {
+    getCounter(name).increment();
+  }
+
+  @Override
+  public void increment(String name, long value) {
+    getCounter(name).increment(value);
+  }
+
+  @Override
+  public void decrement(String name) {
+    getCounter(name).increment(-1);
+  }
+
+  @Override
+  public void reset(String name) {
+    counters.remove(name);
+    this.increment(name, 0);
+  }
+
+  private BasicCounter getCounter(String name) {
+    return counters.computeIfAbsent(name, n -> new 
BasicCounter(MonitorConfig.builder(n).build()));
+  }
+
+  public Map<String, Number> toMetrics() {
+    Map<String, Number> metrics = new HashMap<>();
+    for (Entry<String, BasicCounter> counter : counters.entrySet()) {
+      metrics.put(counter.getKey(), counter.getValue().getValue());
+    }
+    return metrics;
+  }
+}
diff --git 
a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/custom/DefaultGaugeService.java
 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/custom/DefaultGaugeService.java
new file mode 100644
index 0000000..edb9aff
--- /dev/null
+++ 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/custom/DefaultGaugeService.java
@@ -0,0 +1,43 @@
+/*
+ * 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.custom;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
+import org.springframework.stereotype.Component;
+
+@Component
+public class DefaultGaugeService implements GaugeService {
+
+  private final Map<String, Number> gauges;
+
+  public DefaultGaugeService() {
+    this.gauges = new ConcurrentHashMapEx<>();
+  }
+
+  @Override
+  public void update(String name, Number value) {
+    this.gauges.put(name, value);
+  }
+
+  public Map<String, Number> toMetrics() {
+    return new HashMap<>(gauges);
+  }
+}
diff --git 
a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/custom/DefaultWindowCounterService.java
 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/custom/DefaultWindowCounterService.java
new file mode 100644
index 0000000..227fd85
--- /dev/null
+++ 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/custom/DefaultWindowCounterService.java
@@ -0,0 +1,49 @@
+/*
+ * 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.custom;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
+import org.springframework.stereotype.Component;
+
+@Component
+public class DefaultWindowCounterService implements WindowCounterService {
+
+  private final Map<String, WindowCounter> counters;
+
+  public DefaultWindowCounterService() {
+    this.counters = new ConcurrentHashMapEx<>();
+  }
+
+  @Override
+  public void record(String name, long value) {
+    WindowCounter counter = counters.computeIfAbsent(name, WindowCounter::new);
+    counter.update(value);
+  }
+
+  public Map<String, Number> toMetrics(int windowTimeIndex) {
+    Map<String, Number> metrics = new HashMap<>();
+    for (Entry<String, WindowCounter> counter : counters.entrySet()) {
+      metrics.putAll(counter.getValue().toMetric(windowTimeIndex));
+    }
+    return metrics;
+  }
+}
diff --git 
a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/custom/GaugeService.java
 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/custom/GaugeService.java
new file mode 100644
index 0000000..0b7c526
--- /dev/null
+++ 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/custom/GaugeService.java
@@ -0,0 +1,22 @@
+/*
+ * 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.custom;
+
+public interface GaugeService {
+  void update(String name, Number value);
+}
diff --git 
a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/custom/WindowCounter.java
 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/custom/WindowCounter.java
new file mode 100644
index 0000000..7c7bd2b
--- /dev/null
+++ 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/custom/WindowCounter.java
@@ -0,0 +1,82 @@
+/*
+ * 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.custom;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.netflix.servo.monitor.MaxGauge;
+import com.netflix.servo.monitor.MinGauge;
+import com.netflix.servo.monitor.MonitorConfig;
+import com.netflix.servo.monitor.StepCounter;
+
+public class WindowCounter {
+  private final String name;
+
+  private final StepCounter total;
+
+  private final StepCounter count;
+
+  private final MinGauge min;
+
+  private final MaxGauge max;
+
+  public WindowCounter(String name) {
+    this.name = name;
+    total = new StepCounter(MonitorConfig.builder(name).build());
+    count = new StepCounter(MonitorConfig.builder(name).build());
+    min = new MinGauge(MonitorConfig.builder(name).build());
+    max = new MaxGauge(MonitorConfig.builder(name).build());
+  }
+
+  public void update(long value) {
+    if (value > 0) {
+      total.increment(value);
+      count.increment();
+      max.update(value);
+      min.update(value);
+    }
+  }
+
+  public Map<String, Number> toMetric(int windowTimeIndex) {
+    Map<String, Number> metrics = new HashMap<>();
+    metrics.put(name + ".total", 
this.adjustValue(total.getCount(windowTimeIndex)));
+    metrics.put(name + ".count", 
this.adjustValue(count.getCount(windowTimeIndex)));
+    metrics.put(name + ".max", 
this.adjustValue(max.getValue(windowTimeIndex)));
+    metrics.put(name + ".min", 
this.adjustValue(min.getValue(windowTimeIndex)));
+    double value = count.getCount(windowTimeIndex) == 0 ? 0 :
+        (double) this.total.getCount(windowTimeIndex) / (double) 
this.count.getCount(windowTimeIndex);
+    metrics.put(name + ".average", value);
+    metrics.put(name + ".tps", 
this.adjustValue(total.getValue(windowTimeIndex).doubleValue()));
+    return metrics;
+  }
+
+  //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
+  private long adjustValue(long value) {
+    return value < 0 ? 0 : value;
+  }
+
+  //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
+  private double adjustValue(double value) {
+    return value < 0 ? 0 : value;
+  }
+}
diff --git 
a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/custom/WindowCounterService.java
 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/custom/WindowCounterService.java
new file mode 100644
index 0000000..4a15947
--- /dev/null
+++ 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/custom/WindowCounterService.java
@@ -0,0 +1,22 @@
+/*
+ * 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.custom;
+
+public interface WindowCounterService {
+  void record(String name, long value);
+}
diff --git 
a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/monitor/RegistryMonitor.java
 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/monitor/RegistryMonitor.java
index 7a105de..7cdb1db 100644
--- 
a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/monitor/RegistryMonitor.java
+++ 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/monitor/RegistryMonitor.java
@@ -24,6 +24,9 @@ import 
org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
 import org.apache.servicecomb.metrics.common.ConsumerInvocationMetric;
 import org.apache.servicecomb.metrics.common.ProducerInvocationMetric;
 import org.apache.servicecomb.metrics.common.RegistryMetric;
+import org.apache.servicecomb.metrics.core.custom.DefaultCounterService;
+import org.apache.servicecomb.metrics.core.custom.DefaultGaugeService;
+import org.apache.servicecomb.metrics.core.custom.DefaultWindowCounterService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
@@ -36,9 +39,20 @@ public class RegistryMonitor {
 
   private final Map<String, ProducerInvocationMonitor> 
producerInvocationMonitors;
 
+  private final DefaultCounterService counterService;
+
+  private final DefaultGaugeService gaugeService;
+
+  private final DefaultWindowCounterService windowCounterService;
+
   @Autowired
-  public RegistryMonitor(SystemMonitor systemMonitor) {
+  public RegistryMonitor(SystemMonitor systemMonitor,
+      DefaultCounterService counterService, DefaultGaugeService gaugeService,
+      DefaultWindowCounterService windowCounterService) {
     this.systemMonitor = systemMonitor;
+    this.counterService = counterService;
+    this.gaugeService = gaugeService;
+    this.windowCounterService = windowCounterService;
     this.consumerInvocationMonitors = new ConcurrentHashMapEx<>();
     this.producerInvocationMonitors = new ConcurrentHashMapEx<>();
   }
@@ -60,6 +74,12 @@ public class RegistryMonitor {
     for (ProducerInvocationMonitor monitor : 
this.producerInvocationMonitors.values()) {
       producerInvocationMetrics.put(monitor.getOperationName(), 
monitor.toMetric(windowTimeIndex));
     }
-    return new RegistryMetric(systemMonitor.toMetric(), 
consumerInvocationMetrics, producerInvocationMetrics);
+
+    Map<String, Number> customMetrics = new 
HashMap<>(counterService.toMetrics());
+    customMetrics.putAll(gaugeService.toMetrics());
+    customMetrics.putAll(windowCounterService.toMetrics(windowTimeIndex));
+
+    return new RegistryMetric(systemMonitor.toMetric(), 
consumerInvocationMetrics, producerInvocationMetrics,
+        customMetrics);
   }
 }
diff --git 
a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestCustomMetrics.java
 
b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestCustomMetrics.java
new file mode 100644
index 0000000..c9ccc23
--- /dev/null
+++ 
b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestCustomMetrics.java
@@ -0,0 +1,79 @@
+/*
+ * 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 org.apache.servicecomb.metrics.common.RegistryMetric;
+import org.apache.servicecomb.metrics.core.custom.DefaultCounterService;
+import org.apache.servicecomb.metrics.core.custom.DefaultGaugeService;
+import org.apache.servicecomb.metrics.core.custom.DefaultWindowCounterService;
+import org.apache.servicecomb.metrics.core.monitor.DefaultSystemMonitor;
+import org.apache.servicecomb.metrics.core.monitor.RegistryMonitor;
+import org.apache.servicecomb.metrics.core.monitor.SystemMonitor;
+import org.apache.servicecomb.metrics.core.publish.DefaultDataSource;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestCustomMetrics {
+
+  @Test
+  public void testCustom() throws InterruptedException {
+    SystemMonitor systemMonitor = new DefaultSystemMonitor();
+    DefaultCounterService counterService = new DefaultCounterService();
+    DefaultGaugeService gaugeService = new DefaultGaugeService();
+    DefaultWindowCounterService windowCounterService = new 
DefaultWindowCounterService();
+
+    RegistryMonitor registryMonitor = new RegistryMonitor(systemMonitor, 
counterService, gaugeService,
+        windowCounterService);
+    DefaultDataSource dataSource = new DefaultDataSource(registryMonitor, 
"1000,2000,3000,3000,2000,1000");
+
+    counterService.increment("C1");
+    counterService.increment("C1");
+    counterService.decrement("C1");
+
+    counterService.increment("C2", 99);
+    counterService.reset("C2");
+
+    counterService.increment("C3", 20);
+
+    gaugeService.update("G1", 100);
+    gaugeService.update("G1", 200);
+    gaugeService.update("G2", 150);
+
+    windowCounterService.record("W1", 1);
+    windowCounterService.record("W1", 2);
+    windowCounterService.record("W1", 3);
+
+    //sim lease one window time
+    Thread.sleep(1000);
+
+    RegistryMetric metric = dataSource.getRegistryMetric(1000);
+
+    Assert.assertEquals(1, metric.getCustomMetrics().get("C1").intValue());
+    Assert.assertEquals(0, metric.getCustomMetrics().get("C2").intValue());
+    Assert.assertEquals(20, metric.getCustomMetrics().get("C3").intValue());
+    Assert.assertEquals(200, metric.getCustomMetrics().get("G1").intValue());
+    Assert.assertEquals(150, metric.getCustomMetrics().get("G2").intValue());
+
+    Assert.assertEquals(6, 
metric.getCustomMetrics().get("W1.total").doubleValue(), 0);
+    Assert.assertEquals(3, 
metric.getCustomMetrics().get("W1.count").doubleValue(), 0);
+    Assert.assertEquals(6, 
metric.getCustomMetrics().get("W1.tps").doubleValue(), 0);
+    Assert.assertEquals(2, 
metric.getCustomMetrics().get("W1.average").doubleValue(), 0);
+    Assert.assertEquals(1, 
metric.getCustomMetrics().get("W1.min").doubleValue(), 0);
+    Assert.assertEquals(3, 
metric.getCustomMetrics().get("W1.max").doubleValue(), 0);
+  }
+}
diff --git 
a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestEventAndRunner.java
 
b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestEventAndRunner.java
index 85cf463..db400d1 100644
--- 
a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestEventAndRunner.java
+++ 
b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestEventAndRunner.java
@@ -35,6 +35,9 @@ import 
org.apache.servicecomb.core.metrics.InvocationStartedEvent;
 import org.apache.servicecomb.foundation.common.utils.EventUtils;
 import org.apache.servicecomb.metrics.common.MetricsDimension;
 import org.apache.servicecomb.metrics.common.RegistryMetric;
+import org.apache.servicecomb.metrics.core.custom.DefaultCounterService;
+import org.apache.servicecomb.metrics.core.custom.DefaultGaugeService;
+import org.apache.servicecomb.metrics.core.custom.DefaultWindowCounterService;
 import org.apache.servicecomb.metrics.core.event.DefaultEventListenerManager;
 import 
org.apache.servicecomb.metrics.core.event.dimension.StatusConvertorFactory;
 import org.apache.servicecomb.metrics.core.monitor.DefaultSystemMonitor;
@@ -68,7 +71,8 @@ public class TestEventAndRunner {
     when(nonHeap.getUsed()).thenReturn(800L);
 
     DefaultSystemMonitor systemMonitor = new 
DefaultSystemMonitor(systemMXBean, threadMXBean, memoryMXBean);
-    RegistryMonitor monitor = new RegistryMonitor(systemMonitor);
+    RegistryMonitor monitor = new RegistryMonitor(systemMonitor, new 
DefaultCounterService(), new DefaultGaugeService(),
+        new DefaultWindowCounterService());
     DefaultDataSource dataSource = new DefaultDataSource(monitor, 
"1000,2000,3000");
 
     List<Long> intervals = dataSource.getAppliedWindowTime();
diff --git 
a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestHealthCheckerManager.java
 
b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestHealthCheckerManager.java
index f98ee52..1d25569 100644
--- 
a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestHealthCheckerManager.java
+++ 
b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestHealthCheckerManager.java
@@ -72,6 +72,19 @@ public class TestHealthCheckerManager {
     checkers.add(new DefaultMicroserviceHealthChecker());
 
     HealthCheckerManager manager = new DefaultHealthCheckerManager(checkers);
+
+    manager.register(new HealthChecker() {
+      @Override
+      public String getName() {
+        return "test";
+      }
+
+      @Override
+      public HealthCheckResult check() {
+        return new HealthCheckResult(false, "bad", "bad");
+      }
+    });
+
     Map<String, HealthCheckResult> results = manager.check();
 
     Assert.assertTrue(results.get("default").isHealthy());
@@ -84,5 +97,8 @@ public class TestHealthCheckerManager {
     Assert.assertTrue(data.getInstanceId().equals("001"));
     Assert.assertTrue(data.getHostName().equals("localhost"));
     Assert.assertTrue(data.getEndpoints().equals("127.0.0.1,192.168.0.100"));
+
+    HealthCheckResult result = manager.check("test");
+    Assert.assertTrue(!result.isHealthy());
   }
 }
diff --git 
a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestPublisher.java
 
b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestPublisher.java
index 55bd705..1586b46 100644
--- 
a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestPublisher.java
+++ 
b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestPublisher.java
@@ -24,6 +24,9 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.servicecomb.metrics.common.RegistryMetric;
+import org.apache.servicecomb.metrics.core.custom.DefaultCounterService;
+import org.apache.servicecomb.metrics.core.custom.DefaultGaugeService;
+import org.apache.servicecomb.metrics.core.custom.DefaultWindowCounterService;
 import org.apache.servicecomb.metrics.core.monitor.DefaultSystemMonitor;
 import org.apache.servicecomb.metrics.core.monitor.RegistryMonitor;
 import org.apache.servicecomb.metrics.core.monitor.SystemMonitor;
@@ -37,7 +40,8 @@ public class TestPublisher {
   @Test
   public void test() {
     SystemMonitor systemMonitor = new DefaultSystemMonitor();
-    RegistryMonitor registryMonitor = new RegistryMonitor(systemMonitor);
+    RegistryMonitor registryMonitor = new RegistryMonitor(systemMonitor, new 
DefaultCounterService(),
+        new DefaultGaugeService(), new DefaultWindowCounterService());
     DefaultDataSource dataSource = new DefaultDataSource(registryMonitor, 
"1000,2000,3000,3000,2000,1000");
     DefaultMetricsPublisher publisher = new 
DefaultMetricsPublisher(dataSource);
 
diff --git 
a/metrics/metrics-integration/metrics-prometheus/src/main/java/org/apache/servicecomb/metrics/prometheus/MetricsCollector.java
 
b/metrics/metrics-integration/metrics-prometheus/src/main/java/org/apache/servicecomb/metrics/prometheus/MetricsCollector.java
index 932863e..0b576fb 100644
--- 
a/metrics/metrics-integration/metrics-prometheus/src/main/java/org/apache/servicecomb/metrics/prometheus/MetricsCollector.java
+++ 
b/metrics/metrics-integration/metrics-prometheus/src/main/java/org/apache/servicecomb/metrics/prometheus/MetricsCollector.java
@@ -78,6 +78,11 @@ public class MetricsCollector extends Collector implements 
Collector.Describable
           .add(new MetricFamilySamples("Consumer Side", Type.UNTYPED, 
"Consumer Side Metrics", consumerSamples));
     }
 
+    if (registryMetric.getCustomMetrics().size() != 0) {
+      familySamples.add(getFamilySamples("User Custom", 
registryMetric.getCustomMetrics()));
+    }
+
+
     if (registryMetric.getProducerMetrics().size() != 0) {
       List<Sample> producerSamples = new ArrayList<>();
       for (ProducerInvocationMetric metric : 
registryMetric.getProducerMetrics().values()) {
diff --git a/samples/custom-business-metrics/pom.xml 
b/samples/custom-business-metrics/pom.xml
new file mode 100644
index 0000000..90b60da
--- /dev/null
+++ b/samples/custom-business-metrics/pom.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+  <parent>
+    <artifactId>samples</artifactId>
+    <groupId>org.apache.servicecomb.samples</groupId>
+    <version>0.6.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>custom-business-metrics</artifactId>
+  <name>Java Chassis::Samples::Custom Business Metrics</name>
+
+
+  <dependencies>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>spring-boot-starter-provider</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.hibernate</groupId>
+      <artifactId>hibernate-validator</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>metrics-core</artifactId>
+    </dependency>
+  </dependencies>
+
+
+</project>
\ No newline at end of file
diff --git 
a/samples/custom-business-metrics/src/main/java/org/apache/servicecomb/samples/metrics/custom/CustomMetricsApplication.java
 
b/samples/custom-business-metrics/src/main/java/org/apache/servicecomb/samples/metrics/custom/CustomMetricsApplication.java
new file mode 100644
index 0000000..3826c99
--- /dev/null
+++ 
b/samples/custom-business-metrics/src/main/java/org/apache/servicecomb/samples/metrics/custom/CustomMetricsApplication.java
@@ -0,0 +1,30 @@
+/*
+ * 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.samples.metrics.custom;
+
+import org.apache.servicecomb.springboot.starter.provider.EnableServiceComb;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+@EnableServiceComb
+public class CustomMetricsApplication {
+  public static void main(String[] args) {
+    SpringApplication.run(CustomMetricsApplication.class, args);
+  }
+}
diff --git 
a/samples/custom-business-metrics/src/main/java/org/apache/servicecomb/samples/metrics/custom/ShopDemoService.java
 
b/samples/custom-business-metrics/src/main/java/org/apache/servicecomb/samples/metrics/custom/ShopDemoService.java
new file mode 100644
index 0000000..f9f9986
--- /dev/null
+++ 
b/samples/custom-business-metrics/src/main/java/org/apache/servicecomb/samples/metrics/custom/ShopDemoService.java
@@ -0,0 +1,70 @@
+/*
+ * 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.samples.metrics.custom;
+
+import org.apache.servicecomb.metrics.core.custom.CounterService;
+import org.apache.servicecomb.metrics.core.custom.GaugeService;
+import org.apache.servicecomb.metrics.core.custom.WindowCounterService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ShopDemoService {
+
+  private final CounterService counterService;
+
+  private final GaugeService gaugeService;
+
+  private final WindowCounterService windowCounterService;
+
+  //autowire metrics service
+  @Autowired
+  public ShopDemoService(CounterService counterService, GaugeService 
gaugeService,
+      WindowCounterService windowCounterService) {
+    this.counterService = counterService;
+    this.gaugeService = gaugeService;
+    this.windowCounterService = windowCounterService;
+  }
+
+  public void login(String name, String password) {
+    counterService.increment("Active User");
+  }
+
+  public void logout(String session) {
+    counterService.decrement("Active User");
+  }
+
+  public void order(String orderInfo) throws InterruptedException {
+    long start = System.currentTimeMillis();
+    //sim  do order process
+    Thread.sleep(100);
+
+    //sim record order process time
+    windowCounterService.record("Order Latency", System.currentTimeMillis() - 
start);
+
+    windowCounterService.record("Order Count", 1);
+    //only support long
+    windowCounterService.record("Order Amount", 66);
+  }
+
+  public void discount(double value) {
+    //make a discount to Levis Jeans
+
+    gaugeService.update("Levis Jeans", value);
+  }
+}
diff --git 
a/samples/metrics-write-file-sample/metrics-write-file/src/test/java/org/apache/servicecomb/samples/mwf/TestWriteFile.java
 
b/samples/metrics-write-file-sample/metrics-write-file/src/test/java/org/apache/servicecomb/samples/mwf/TestWriteFile.java
index d550f77..63a46d2 100644
--- 
a/samples/metrics-write-file-sample/metrics-write-file/src/test/java/org/apache/servicecomb/samples/mwf/TestWriteFile.java
+++ 
b/samples/metrics-write-file-sample/metrics-write-file/src/test/java/org/apache/servicecomb/samples/mwf/TestWriteFile.java
@@ -155,7 +155,8 @@ public class TestWriteFile {
         new CallMetric("B2", Collections.singletonList(new 
LongMetricValue("B2", 100L, new HashMap<>())),
             Collections.singletonList(new DoubleMetricValue("B2", 888.66666, 
new HashMap<>())))));
 
-    RegistryMetric metric = new RegistryMetric(systemMetric, 
consumerInvocationMetricMap, new HashMap<>());
+    RegistryMetric metric = new RegistryMetric(systemMetric, 
consumerInvocationMetricMap, new HashMap<>(),
+        new HashMap<>());
 
     DataSource dataSource = Mockito.mock(DataSource.class);
     Mockito.when(dataSource.getRegistryMetric()).thenReturn(metric);
diff --git a/samples/pom.xml b/samples/pom.xml
index 0590c43..2c60a7c 100644
--- a/samples/pom.xml
+++ b/samples/pom.xml
@@ -37,6 +37,7 @@
     <module>metrics-write-file-sample</module>
     <module>metrics-extend-healthcheck</module>
     <module>config-apollo-sample</module>
+    <module>custom-business-metrics</module>
   </modules>
 
   <dependencyManagement>

-- 
To stop receiving notification emails like this one, please contact
[email protected].

Reply via email to