diff --git a/handlers/handler-performance-stats/pom.xml b/handlers/handler-performance-stats/pom.xml
new file mode 100644
index 00000000000..23a3504d3d0
--- /dev/null
+++ b/handlers/handler-performance-stats/pom.xml
@@ -0,0 +1,38 @@
+
+
+
+ 4.0.0
+
+ io.servicecomb
+ handlers
+ 0.1.0-m3-SNAPSHOT
+
+ cse-handler-performance-stats
+
+
+ io.servicecomb
+ java-chassis-core
+
+
+ io.servicecomb
+ foundation-metrics
+
+
+ com.netflix.hystrix
+ hystrix-core
+
+
+ com.huawei.paas.cse
+ foundation-auth
+ 0.1
+
+
+
\ No newline at end of file
diff --git a/handlers/handler-performance-stats/src/main/java/com/huawei/paas/cse/handler/stats/PerfStatsHandler.java b/handlers/handler-performance-stats/src/main/java/com/huawei/paas/cse/handler/stats/PerfStatsHandler.java
new file mode 100644
index 00000000000..05783b4f907
--- /dev/null
+++ b/handlers/handler-performance-stats/src/main/java/com/huawei/paas/cse/handler/stats/PerfStatsHandler.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2017 Huawei Technologies Co., Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.huawei.paas.cse.handler.stats;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.servicecomb.core.Invocation;
+import io.servicecomb.core.handler.impl.AbstractHandler;
+import io.servicecomb.foundation.metrics.Metrics;
+import io.servicecomb.foundation.metrics.performance.PerfStatContext;
+import io.servicecomb.foundation.metrics.performance.PerfStatSuccFail;
+import io.servicecomb.swagger.invocation.AsyncResponse;
+import io.servicecomb.swagger.invocation.exception.InvocationException;
+
+/**
+ * 统计成功、失败的tps、时延等等参数
+ * @author
+ * @version [版本号, 2016年12月5日]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+public class PerfStatsHandler extends AbstractHandler {
+ private static final Logger LOGGER = LoggerFactory.getLogger(PerfStatsHandler.class);
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception {
+ String name = invocation.getOperationMeta().getMicroserviceQualifiedName();
+ // 先确认是否需要跟踪?
+ if (!isNeedPerfStat(name)) {
+ invocation.next(asyncResp);
+ return;
+ }
+
+ PerfStatContext context = new PerfStatContext();
+
+ // TODO:
+ // 1.如果能确定是放在exceptionHandler前面,则这里不必catch
+ // 2.作为handler,框架上的异常场景统计不到
+ // 3.这里只统计了调用的tps,而业务层的消息数,如何感知支撑?
+ // 使用标准的metrics方案,可以解决这些问题
+ try {
+ invocation.next(resp -> {
+ asyncResp.handle(resp);
+
+ onStat(invocation, resp.isSuccessed(), context);
+ });
+ } catch (Throwable e) {
+ if (!InvocationException.class.isInstance(e)) {
+ LOGGER.error("invoke failed,", e);
+ }
+ onStat(invocation, false, context);
+ asyncResp.fail(invocation.getInvocationType(), e);
+ }
+ }
+
+ protected void onStat(Invocation invocation, boolean isSucc, PerfStatContext context) {
+ context.setMsgCount(1);
+
+ // 统计标识带上transport名称,方便识别场景
+ String statName = invocation.getInvocationQualifiedName();
+
+ // TODO:同优先级的,后加入的应该在最后
+ PerfStatSuccFail stat = Metrics.getOrCreateLocalPerfStat(statName, 0);
+ stat.add(isSucc, context);
+ }
+
+ // TODO:由客户端带过来?不应该要求两端都配置?
+ /**
+ * <一句话功能简述>
+ * <功能详细描述>
+ * @param name
+ * @return
+ */
+ private boolean isNeedPerfStat(String name) {
+ return true;
+ }
+
+}
diff --git a/handlers/handler-performance-stats/src/main/java/com/huawei/paas/cse/handler/stats/monitor/DataFactory.java b/handlers/handler-performance-stats/src/main/java/com/huawei/paas/cse/handler/stats/monitor/DataFactory.java
new file mode 100644
index 00000000000..3bd1a755061
--- /dev/null
+++ b/handlers/handler-performance-stats/src/main/java/com/huawei/paas/cse/handler/stats/monitor/DataFactory.java
@@ -0,0 +1,189 @@
+package com.huawei.paas.cse.handler.stats.monitor;
+
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+import java.lang.management.MemoryUsage;
+import java.lang.management.OperatingSystemMXBean;
+import java.lang.management.ThreadMXBean;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.util.EntityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.huawei.paas.foundation.auth.AuthHeaderUtils;
+import com.huawei.paas.foundation.auth.HttpClientFactory;
+import com.netflix.config.DynamicBooleanProperty;
+import com.netflix.config.DynamicPropertyFactory;
+import com.netflix.config.DynamicStringProperty;
+import com.netflix.hystrix.HystrixCommandMetrics;
+
+import io.netty.util.concurrent.DefaultThreadFactory;
+import io.servicecomb.serviceregistry.RegistryUtils;
+import io.vertx.core.json.Json;
+
+/**
+ * 数据生成工厂,启动一个线程池,定时发送数据
+ * @author w00293972
+ */
+class DataFactory {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(DataFactory.class);
+ private static final int CORE_SIZE = 1;
+ private static final int SLEEP_MINI_TIME = 1;
+ private static final int SLEEP_MAX_TIME = 10;
+ private static final int DELAY_TIME_MILLISECONDS = 1000;
+
+ private static final String SSL_KEY = "mc.consumer";
+ private boolean hasStart = false;
+ private boolean firestError = true;
+
+ private static DataFactory INSTANCE = new DataFactory();
+
+ private ScheduledExecutorService executorService = null;
+
+ private DataFactory() {
+ ThreadFactory tf = new DefaultThreadFactory("cse-monitor-datafactory");
+ executorService = Executors.newScheduledThreadPool(CORE_SIZE, tf);
+ }
+
+ public static DataFactory getInstance() {
+ return INSTANCE;
+ }
+
+ /**
+ * 开启数据上报
+ */
+ void start() {
+ if (!hasStart) {
+ LOGGER.info("Start collect monitor data, send to Monitor Sender!");
+ executorService.scheduleWithFixedDelay(() -> {
+ int elapsedTime = sendData(getData());
+ delayTime(elapsedTime);
+ }, DELAY_TIME_MILLISECONDS, DELAY_TIME_MILLISECONDS, TimeUnit.MILLISECONDS);
+ hasStart = true;
+ }
+ }
+
+ private void delayTime(int elapsedTime) {
+ int sleepTime = elapsedTime / 1000;
+ try {
+ if (sleepTime < SLEEP_MINI_TIME) {
+ return;
+ }
+ if (sleepTime > SLEEP_MAX_TIME) {
+ sleepTime = SLEEP_MAX_TIME;
+ }
+ Thread.sleep(sleepTime * 1000);
+ } catch (InterruptedException e) {
+ LOGGER.error("Sleep delay time error");
+ }
+ }
+
+ /**
+ * 发送数据
+ * @param monitorData
+ */
+ int sendData(MonitorData monitorData) {
+ if (!getEnableMonitor()) {
+ return 0;
+ }
+ HttpClient monitorClient = HttpClientFactory.getOrCreateHttpClient(SSL_KEY);
+ HttpPost httpPost = new HttpPost(getServerUrl() + "/csemonitor/v1/metric?service=" + monitorData.getName());
+ httpPost.addHeader("Content-Type", "application/json");
+ Map akskHeaders = AuthHeaderUtils.getInstance().genAuthHeaders();
+ for (Map.Entry header : akskHeaders.entrySet()) {
+ httpPost.setHeader(header.getKey(), header.getValue());
+ }
+ HttpEntity entity;
+ long startTime = System.currentTimeMillis();
+ try {
+ entity = new StringEntity(Json.encode(monitorData));
+ httpPost.setEntity(entity);
+ HttpResponse response = monitorClient.execute(httpPost);
+ LOGGER.debug(response.getStatusLine().toString());
+ EntityUtils.consume(response.getEntity());
+ } catch (IOException e) {
+ if (firestError) {
+ LOGGER.error("Upload monitor data error!");
+ firestError = false;
+ }
+ }
+ long endTime = System.currentTimeMillis();
+ int time = (int) (endTime - startTime);
+ return time;
+ }
+
+ /**
+ * 构造数据
+ * @return 监控数据
+ */
+ MonitorData getData() {
+ Collection instances = HystrixCommandMetrics.getInstances();
+ MonitorData monitorData = new MonitorData();
+ monitorData.setName(RegistryUtils.getMicroservice().getServiceName());
+ monitorData.setInstance(RegistryUtils.getMicroserviceInstance().getHostName());
+ exactProcessInfo(monitorData);
+ if (instances == null || instances.isEmpty()) {
+ return monitorData;
+ }
+ for (HystrixCommandMetrics instance : instances) {
+ monitorData.appendInterfaceInfo(instance);
+ }
+ return monitorData;
+ }
+
+ private void exactProcessInfo(MonitorData monitorData) {
+ MemoryMXBean memBean = ManagementFactory.getMemoryMXBean();
+ MemoryUsage memoryHeapUsage = memBean.getHeapMemoryUsage();
+ MemoryUsage memoryNonHeapUsage = memBean.getNonHeapMemoryUsage();
+ ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
+ int threadCount = threadBean.getThreadCount();
+ OperatingSystemMXBean osMxBean = ManagementFactory.getOperatingSystemMXBean();
+ // this method only work well on Unix operation system
+ double cpu = osMxBean.getSystemLoadAverage();
+ monitorData.setCpu(cpu);
+ monitorData.setThreadCount(threadCount);
+ Map memoryInfo = new HashMap<>();
+ memoryInfo.put("heapInit", memoryHeapUsage.getInit());
+ memoryInfo.put("heapMax", memoryHeapUsage.getMax());
+ memoryInfo.put("heapCommit", memoryHeapUsage.getCommitted());
+ memoryInfo.put("heapUsed", memoryHeapUsage.getUsed());
+ memoryInfo.put("nonHeapInit", memoryNonHeapUsage.getInit());
+ memoryInfo.put("nonHeapCommit", memoryNonHeapUsage.getCommitted());
+ memoryInfo.put("nonHeapUsed", memoryNonHeapUsage.getUsed());
+ monitorData.setMemory(memoryInfo);
+ }
+
+ /**
+ * 获取数据上报地址
+ * @return
+ */
+ public String getServerUrl() {
+ DynamicStringProperty property = DynamicPropertyFactory.getInstance()
+ .getStringProperty("cse.monitor.client.serverUri", "https://cse-dashbord-service:30109");
+ return property.getValue();
+ }
+
+ /**
+ * 获取是否上报数据
+ * @return
+ */
+ public boolean getEnableMonitor() {
+ DynamicBooleanProperty property = DynamicPropertyFactory.getInstance()
+ .getBooleanProperty("cse.monitor.client.enable", true);
+ return property.getValue();
+ }
+}
diff --git a/handlers/handler-performance-stats/src/main/java/com/huawei/paas/cse/handler/stats/monitor/MonitorData.java b/handlers/handler-performance-stats/src/main/java/com/huawei/paas/cse/handler/stats/monitor/MonitorData.java
new file mode 100644
index 00000000000..b6990752d46
--- /dev/null
+++ b/handlers/handler-performance-stats/src/main/java/com/huawei/paas/cse/handler/stats/monitor/MonitorData.java
@@ -0,0 +1,377 @@
+package com.huawei.paas.cse.handler.stats.monitor;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import com.netflix.hystrix.HystrixCommandMetrics;
+import com.netflix.hystrix.HystrixEventType;
+
+/**
+ * 监控上报的数据,每次上报一条数据
+ * @author w00293972
+ */
+public class MonitorData {
+ private static final double PERCENTAGE_995 = 99.5;
+ private static final double PERCENTAGE_99 = 99;
+ private static final double PERCENTAGE_90 = 90;
+ private static final double PERCENTAGE_75 = 75;
+ private static final double PERCENTAGE_50 = 50;
+ private static final double PERCENTAGE_25 = 25;
+ private static final double PERCENTAGE_5 = 5;
+ private static final int SCALE_VAL = 1;
+ /**
+ * 服务名称
+ */
+ private String name;
+ /**
+ * 服务实例名称
+ */
+ private String instance;
+
+ private int thread;
+ private double cpu;
+ private Map memory;
+
+ /**
+ * 接口相关监控数据
+ */
+ private List interfaces = new ArrayList<>();
+
+ /**
+ * 用户自定义的一些变量
+ */
+ private Map customs;
+
+ public void appendInterfaceInfo(HystrixCommandMetrics metrics) {
+ InterfaceInfo interfaceInfo = new InterfaceInfo();
+ int windowTime = metrics.getProperties().metricsRollingStatisticalWindowInMilliseconds().get() / 1000;
+ HystrixEventType[] events = {HystrixEventType.SUCCESS, HystrixEventType.FAILURE};
+ long rollingTotal = 0;
+ long cumulativeTotal = 0;
+
+ for (HystrixEventType event : events) {
+ long val = metrics.getRollingCount(event);
+ long cumVal = metrics.getCumulativeCount(event);
+ rollingTotal += val;
+ cumulativeTotal += cumVal;
+ }
+ long successCount = metrics.getRollingCount(HystrixEventType.SUCCESS);
+ long failureCount = metrics.getRollingCount(HystrixEventType.FAILURE);
+ long semRejectCount = metrics.getRollingCount(HystrixEventType.SEMAPHORE_REJECTED);
+ long threadRejectCount = metrics.getRollingCount(HystrixEventType.THREAD_POOL_REJECTED);
+ long timeoutCount = metrics.getRollingCount(HystrixEventType.TIMEOUT);
+
+ int latency = metrics.getExecutionTimeMean();
+ int latency995 = metrics.getExecutionTimePercentile(PERCENTAGE_995);
+ int latency99 = metrics.getExecutionTimePercentile(PERCENTAGE_99);
+ int latency90 = metrics.getExecutionTimePercentile(PERCENTAGE_90);
+ int latency75 = metrics.getExecutionTimePercentile(PERCENTAGE_75);
+ int latency50 = metrics.getExecutionTimePercentile(PERCENTAGE_50);
+ int latency25 = metrics.getExecutionTimePercentile(PERCENTAGE_25);
+ int latency5 = metrics.getExecutionTimePercentile(PERCENTAGE_5);
+
+ interfaceInfo.setName(metrics.getCommandKey().name());
+ interfaceInfo.setCircuitBreakerOpen(metrics.getProperties().circuitBreakerEnabled().get());
+ interfaceInfo.setFailure(failureCount);
+ interfaceInfo.setSemaphoreRejected(semRejectCount);
+ interfaceInfo.setThreadPoolRejected(threadRejectCount);
+ interfaceInfo.setCountTimeout(timeoutCount);
+ interfaceInfo.setDesc(metrics.getCommandKey().name());
+ interfaceInfo.setLatency(latency);
+ interfaceInfo.setL25(latency25);
+ interfaceInfo.setL5(latency5);
+ interfaceInfo.setL50(latency50);
+ interfaceInfo.setL75(latency75);
+ interfaceInfo.setL90(latency90);
+ interfaceInfo.setL99(latency99);
+ interfaceInfo.setL995(latency995);
+ interfaceInfo.setTotal(cumulativeTotal);
+ double qpsVal = ((double) rollingTotal) / windowTime;
+ BigDecimal b = new BigDecimal(qpsVal);
+ BigDecimal qps = b.setScale(SCALE_VAL, RoundingMode.HALF_DOWN);
+ interfaceInfo.setQps(qps.doubleValue());
+ if (rollingTotal == 0) {
+ interfaceInfo.setRate(100);
+ } else {
+ interfaceInfo.setRate(((double) successCount) / rollingTotal);
+ }
+ interfaces.add(interfaceInfo);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getInstance() {
+ return instance;
+ }
+
+ public void setInstance(String instance) {
+ this.instance = instance;
+ }
+
+ public List getInterfaces() {
+ return interfaces;
+ }
+
+ public Map getCustoms() {
+ return customs;
+ }
+
+ public void setCustoms(Map customs) {
+ this.customs = customs;
+ }
+
+ public double getCpu() {
+ return cpu;
+ }
+
+ public void setCpu(double cpu) {
+ this.cpu = cpu;
+ }
+
+ public int getThreadCount() {
+ return thread;
+ }
+
+ public void setThreadCount(int threadCount) {
+ this.thread = threadCount;
+ }
+
+ public Map getMemory() {
+ return memory;
+ }
+
+ public void setMemory(Map memory) {
+ this.memory = memory;
+ }
+
+ /**
+ * 接口相关监控数据
+ * @author w00293972
+ */
+ public class InterfaceInfo {
+ /**
+ * 接口名称
+ */
+ private String name;
+ /**
+ * 接口描述
+ */
+ private String desc;
+ /**
+ * 每秒请求量,单位个
+ */
+ private double qps;
+ /**
+ * 时延,单位毫秒
+ */
+ private int latency;
+
+ private int l995;
+
+ private int l99;
+
+ private int l90;
+
+ private int l75;
+
+ private int l50;
+
+ private int l25;
+
+ private int l5;
+ /**
+ * 成功率,百分比
+ */
+ private double rate;
+ /**
+ * 请求总量
+ */
+ private long total;
+ /**
+ * 当前熔断状态
+ */
+ private boolean isCircuitBreakerOpen;
+ /**
+ * 失败总个数
+ */
+ private long failure;
+ /**
+ * 总短路个数
+ */
+ private long shortCircuited;
+ /**
+ * 总信号量拒绝个数
+ */
+ private long semaphoreRejected;
+ /**
+ * 总线程池拒绝个数
+ */
+ private long threadPoolRejected;
+ /**
+ * 总超时个数
+ */
+ private long countTimeout;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDesc() {
+ return desc;
+ }
+
+ public void setDesc(String desc) {
+ this.desc = desc;
+ }
+
+ public double getQps() {
+ return qps;
+ }
+
+ public void setQps(double qps) {
+ this.qps = qps;
+ }
+
+ public int getLatency() {
+ return latency;
+ }
+
+ public void setLatency(int latency) {
+ this.latency = latency;
+ }
+
+ public int getL995() {
+ return l995;
+ }
+
+ public void setL995(int l995) {
+ this.l995 = l995;
+ }
+
+ public int getL99() {
+ return l99;
+ }
+
+ public void setL99(int l99) {
+ this.l99 = l99;
+ }
+
+ public int getL90() {
+ return l90;
+ }
+
+ public void setL90(int l90) {
+ this.l90 = l90;
+ }
+
+ public int getL75() {
+ return l75;
+ }
+
+ public void setL75(int l75) {
+ this.l75 = l75;
+ }
+
+ public int getL50() {
+ return l50;
+ }
+
+ public void setL50(int l50) {
+ this.l50 = l50;
+ }
+
+ public int getL25() {
+ return l25;
+ }
+
+ public void setL25(int l25) {
+ this.l25 = l25;
+ }
+
+ public int getL5() {
+ return l5;
+ }
+
+ public void setL5(int l5) {
+ this.l5 = l5;
+ }
+
+ public double getRate() {
+ return rate;
+ }
+
+ public void setRate(double rate) {
+ this.rate = rate;
+ }
+
+ public long getTotal() {
+ return total;
+ }
+
+ public void setTotal(long total) {
+ this.total = total;
+ }
+
+ public boolean isCircuitBreakerOpen() {
+ return isCircuitBreakerOpen;
+ }
+
+ public void setCircuitBreakerOpen(boolean isCircuitBreakerOpen) {
+ this.isCircuitBreakerOpen = isCircuitBreakerOpen;
+ }
+
+ public long getFailure() {
+ return failure;
+ }
+
+ public void setFailure(long failure) {
+ this.failure = failure;
+ }
+
+ public long getShortCircuited() {
+ return shortCircuited;
+ }
+
+ public void setShortCircuited(long shortCircuited) {
+ this.shortCircuited = shortCircuited;
+ }
+
+ public long getSemaphoreRejected() {
+ return semaphoreRejected;
+ }
+
+ public void setSemaphoreRejected(long semaphoreRejected) {
+ this.semaphoreRejected = semaphoreRejected;
+ }
+
+ public long getThreadPoolRejected() {
+ return threadPoolRejected;
+ }
+
+ public void setThreadPoolRejected(long threadPoolRejected) {
+ this.threadPoolRejected = threadPoolRejected;
+ }
+
+ public long getCountTimeout() {
+ return countTimeout;
+ }
+
+ public void setCountTimeout(long countTimeout) {
+ this.countTimeout = countTimeout;
+ }
+
+ }
+}
diff --git a/handlers/handler-performance-stats/src/main/java/com/huawei/paas/cse/handler/stats/monitor/MonitorStarter.java b/handlers/handler-performance-stats/src/main/java/com/huawei/paas/cse/handler/stats/monitor/MonitorStarter.java
new file mode 100644
index 00000000000..f36f2114c32
--- /dev/null
+++ b/handlers/handler-performance-stats/src/main/java/com/huawei/paas/cse/handler/stats/monitor/MonitorStarter.java
@@ -0,0 +1,12 @@
+package com.huawei.paas.cse.handler.stats.monitor;
+
+/**
+ * 启动器,确保DataFactory只能启动一次
+ * @author w00293972
+ */
+public class MonitorStarter {
+
+ public void start() {
+ DataFactory.getInstance().start();
+ }
+}
diff --git a/handlers/handler-performance-stats/src/main/resources/META-INF/spring/services.bean.xml b/handlers/handler-performance-stats/src/main/resources/META-INF/spring/services.bean.xml
new file mode 100644
index 00000000000..38e2fc4a120
--- /dev/null
+++ b/handlers/handler-performance-stats/src/main/resources/META-INF/spring/services.bean.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/handlers/handler-performance-stats/src/main/resources/config/cse.handler.xml b/handlers/handler-performance-stats/src/main/resources/config/cse.handler.xml
new file mode 100644
index 00000000000..4e9276c8380
--- /dev/null
+++ b/handlers/handler-performance-stats/src/main/resources/config/cse.handler.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/handlers/handler-performance-stats/src/test/java/com/huawei/paas/cse/handler/stats/TestPerfStatsHandler.java b/handlers/handler-performance-stats/src/test/java/com/huawei/paas/cse/handler/stats/TestPerfStatsHandler.java
new file mode 100644
index 00000000000..1bed773e196
--- /dev/null
+++ b/handlers/handler-performance-stats/src/test/java/com/huawei/paas/cse/handler/stats/TestPerfStatsHandler.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2017 Huawei Technologies Co., Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.huawei.paas.cse.handler.stats;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import io.servicecomb.core.Invocation;
+import io.servicecomb.core.definition.OperationMeta;
+import io.servicecomb.foundation.metrics.performance.PerfStatContext;
+import io.servicecomb.swagger.invocation.AsyncResponse;
+
+public class TestPerfStatsHandler {
+
+ PerfStatsHandler perfStatsHandler = null;
+
+ Invocation invocation = null;
+
+ AsyncResponse asyncResp = null;
+
+ PerfStatContext perfStatContext = null;
+
+ @Before
+ public void setUp() throws Exception {
+ perfStatsHandler = new PerfStatsHandler();
+ invocation = Mockito.mock(Invocation.class);
+ asyncResp = Mockito.mock(AsyncResponse.class);
+ perfStatContext = new PerfStatContext();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ perfStatsHandler = null;
+ invocation = null;
+ asyncResp = null;
+ perfStatContext = null;
+ }
+
+ @Test
+ public void testHandle() {
+ boolean status = false;
+ Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class));
+ try {
+ perfStatsHandler.handle(invocation, asyncResp);
+ } catch (Exception e) {
+ status = true;
+ }
+ Assert.assertFalse(status);
+ }
+
+ @Test
+ public void testOnStat() {
+ Mockito.when(invocation.getInvocationQualifiedName()).thenReturn("statName");
+ perfStatsHandler.onStat(invocation, false, perfStatContext);
+ Assert.assertEquals(1, perfStatContext.getMsgCount());
+ }
+}
diff --git a/handlers/handler-performance-stats/src/test/java/com/huawei/paas/cse/handler/stats/monitor/DataFactoryTest.java b/handlers/handler-performance-stats/src/test/java/com/huawei/paas/cse/handler/stats/monitor/DataFactoryTest.java
new file mode 100644
index 00000000000..a08940a3232
--- /dev/null
+++ b/handlers/handler-performance-stats/src/test/java/com/huawei/paas/cse/handler/stats/monitor/DataFactoryTest.java
@@ -0,0 +1,189 @@
+package com.huawei.paas.cse.handler.stats.monitor;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequest;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.HttpContext;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.huawei.paas.cse.handler.stats.monitor.MonitorData.InterfaceInfo;
+import com.huawei.paas.foundation.auth.HttpClientFactory;
+import com.netflix.hystrix.HystrixCommandMetrics;
+import com.netflix.hystrix.HystrixCommandProperties;
+import com.netflix.hystrix.HystrixEventType;
+import com.netflix.hystrix.strategy.properties.HystrixProperty;
+
+import io.servicecomb.serviceregistry.RegistryUtils;
+import io.servicecomb.serviceregistry.api.registry.Microservice;
+import mockit.Expectations;
+import mockit.Mock;
+import mockit.MockUp;
+import mockit.Mocked;
+
+@SuppressWarnings("deprecation")
+public class DataFactoryTest {
+
+ @Test
+ public void testStart() {
+ Constructor>[] cs = HttpClientFactory.class.getDeclaredConstructors();
+ for (Constructor> c : cs) {
+ c.setAccessible(true);
+ try {
+ c.newInstance();
+ } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
+ | InvocationTargetException e) {
+ e.printStackTrace();
+ }
+ }
+
+ new MockUp () {
+ @Mock
+ public Microservice getMicroservice() {
+ return new Microservice();
+ }
+ };
+
+ DataFactory.getInstance().start();
+ MonitorData data = DataFactory.getInstance().getData();
+ Assert.assertNotNull(DataFactory.getInstance().getServerUrl());
+ Assert.assertNotNull(data);
+ }
+
+ @Test
+ public void testSendData(@Mocked HystrixCommandMetrics metric, @Mocked HttpClient httpClient, @Mocked CloseableHttpResponse resp, @Mocked HystrixCommandProperties properties,
+ @Mocked HystrixProperty mill) throws IOException {
+
+ HttpClient client = new CloseableHttpClient() {
+ int times = 0;
+ @Override
+ public CloseableHttpResponse execute(HttpUriRequest request)
+ throws IOException, ClientProtocolException {
+ if (times == 0) {
+ times ++;
+ return resp;
+ }
+ else {
+ throw new IOException();
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ }
+
+ @Override
+ public HttpParams getParams() {
+ return null;
+ }
+
+ @Override
+ public ClientConnectionManager getConnectionManager() {
+ return null;
+ }
+
+ @Override
+ protected CloseableHttpResponse doExecute(HttpHost target, HttpRequest request, HttpContext context)
+ throws IOException, ClientProtocolException {
+ return null;
+ }
+ };
+ new MockUp() {
+ @Mock
+ public HttpClient getOrCreateHttpClient(String key) {
+ return client;
+ }
+ };
+ Collection metrics = new ArrayList();
+ metrics.add(metric);
+ new MockUp () {
+ @Mock
+ public Collection getInstances() {
+ return null;
+ }
+ };
+ //第一次模拟异常情况发布
+ DataFactory.getInstance().sendData(new MonitorData());
+ //第二次模拟正常情况
+ int time = DataFactory.getInstance().sendData(new MonitorData());
+ Assert.assertTrue(time >= 0);
+ }
+
+ @Test
+ public void testMonitorData(@Mocked HystrixCommandMetrics metrics, @Mocked HystrixCommandProperties properties,
+ @Mocked HystrixProperty mill, @Mocked HystrixCommandMetrics metricssecond) {
+ HystrixProperty circuit = new HystrixProperty() {
+ @Override
+ public Boolean get() {
+ return true;
+ }
+ };
+ new Expectations() {
+ {
+ metrics.getProperties();
+ result = properties;
+ properties.metricsRollingStatisticalWindowInMilliseconds();
+ result = mill;
+ mill.get();
+ result = 10000;
+ properties.circuitBreakerEnabled();
+ result = circuit;
+ metrics.getCumulativeCount(HystrixEventType.SUCCESS);
+ result = 110;
+ metrics.getRollingCount(HystrixEventType.SUCCESS);
+ result = 11;
+
+ metricssecond.getProperties();
+ result = properties;
+ properties.metricsRollingStatisticalWindowInMilliseconds();
+ result = mill;
+ mill.get();
+ result = 10000;
+ properties.circuitBreakerEnabled();
+ result = circuit;
+ metricssecond.getCumulativeCount(HystrixEventType.SUCCESS);
+ result = 110;
+ metricssecond.getRollingCount(HystrixEventType.SUCCESS);
+ result = 0;
+ }
+ };
+ MonitorData data = new MonitorData();
+ data.setName("test");
+ data.setInstance("hello");
+ data.setCustoms(new HashMap<>());
+ data.appendInterfaceInfo(metrics);
+ data.appendInterfaceInfo(metricssecond);
+ data.getCustoms();
+ data.getInstance();
+ InterfaceInfo info = data.getInterfaces().get(0);
+ info.setShortCircuited(1);
+ Method[] methods = info.getClass().getDeclaredMethods();
+ for (Method m : methods) {
+ if (m.getName().startsWith("get") || m.getName().startsWith("is")) {
+ try {
+ m.invoke(info);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ Assert.assertEquals("test", data.getName());
+ Assert.assertEquals(2, data.getInterfaces().size());
+ }
+
+}
diff --git a/handlers/handler-performance-stats/src/test/java/com/huawei/paas/cse/handler/stats/monitor/MonitorStarterTest.java b/handlers/handler-performance-stats/src/test/java/com/huawei/paas/cse/handler/stats/monitor/MonitorStarterTest.java
new file mode 100644
index 00000000000..4858ed863a7
--- /dev/null
+++ b/handlers/handler-performance-stats/src/test/java/com/huawei/paas/cse/handler/stats/monitor/MonitorStarterTest.java
@@ -0,0 +1,13 @@
+package com.huawei.paas.cse.handler.stats.monitor;
+
+import org.junit.Test;
+
+public class MonitorStarterTest {
+
+ @Test
+ public void testStart() {
+ MonitorStarter starter = new MonitorStarter();
+ starter.start();
+ }
+
+}