You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by GitBox <gi...@apache.org> on 2018/10/10 04:05:04 UTC

[GitHub] liubao68 closed pull request #944: [SCB-950] modify consumer producer metrics and add edge metrics

liubao68 closed pull request #944: [SCB-950] modify consumer producer metrics and add edge metrics
URL: https://github.com/apache/incubator-servicecomb-java-chassis/pull/944
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationStageTrace.java b/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationStageTrace.java
index 6cf6aa26d..193644cc5 100644
--- a/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationStageTrace.java
+++ b/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationStageTrace.java
@@ -268,7 +268,7 @@ public void finish() {
   }
 
   private double calc(long finish, long start) {
-    if (finish == 0) {
+    if (finish == 0 || start == 0) {
       return Double.NaN;
     }
 
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/InvocationMetersInitializer.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/InvocationMetersInitializer.java
index e040ec228..72a05ef72 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/InvocationMetersInitializer.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/InvocationMetersInitializer.java
@@ -23,6 +23,7 @@
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
 import org.apache.servicecomb.metrics.core.meter.ConsumerMeters;
+import org.apache.servicecomb.metrics.core.meter.EdgeMeters;
 import org.apache.servicecomb.metrics.core.meter.ProducerMeters;
 import org.apache.servicecomb.metrics.core.meter.invocation.AbstractInvocationMeters;
 
@@ -37,6 +38,8 @@
 
   private ProducerMeters producerMeters;
 
+  private EdgeMeters edgeMeters;
+
   @Override
   public void init(CompositeRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
     DefaultRegistryInitializer defaultRegistryInitializer =
@@ -45,13 +48,18 @@ public void init(CompositeRegistry globalRegistry, EventBus eventBus, MetricsBoo
 
     consumerMeters = new ConsumerMeters(registry);
     producerMeters = new ProducerMeters(registry);
+    edgeMeters = new EdgeMeters(registry);
 
     eventBus.register(this);
   }
 
   protected AbstractInvocationMeters findInvocationMeters(Invocation invocation) {
     if (invocation.isConsumer()) {
-      return consumerMeters.getInvocationMeters();
+      if (invocation.isEdge()) {
+        return edgeMeters.getInvocationMeters();
+      } else {
+        return consumerMeters.getInvocationMeters();
+      }
     }
     return producerMeters.getInvocationMeters();
   }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/EdgeMeters.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/EdgeMeters.java
new file mode 100644
index 000000000..b04a031ae
--- /dev/null
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/EdgeMeters.java
@@ -0,0 +1,19 @@
+package org.apache.servicecomb.metrics.core.meter;
+
+import org.apache.servicecomb.metrics.core.meter.invocation.AbstractInvocationMeters;
+import org.apache.servicecomb.metrics.core.meter.invocation.EdgeInvocationMeters;
+
+import com.netflix.spectator.api.Registry;
+
+public class EdgeMeters {
+  private AbstractInvocationMeters invocationMeters;
+
+
+  public EdgeMeters(Registry registry) {
+    this.invocationMeters = new EdgeInvocationMeters(registry);
+  }
+
+  public AbstractInvocationMeters getInvocationMeters() {
+    return invocationMeters;
+  }
+}
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java
index b05200f94..dd0851e3f 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java
@@ -27,14 +27,41 @@
 import com.netflix.spectator.api.Timer;
 
 public abstract class AbstractInvocationMeter {
+  //total time
   private Timer totalTimer;
 
+  // prepare time
+  private Timer prepareTimer;
+
+  // handler request
+  private Timer handlersRequestTimer;
+
+  // handler response
+  private Timer handlersResponseTimer;
+
   public AbstractInvocationMeter(Registry registry, Id id, Invocation invocation, Response response) {
+
     totalTimer = registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_TOTAL));
+    prepareTimer = registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_PREPARE));
+    handlersRequestTimer =
+        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_HANDLERS_REQUEST));
+    handlersResponseTimer =
+        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_HANDLERS_RESPONSE));
   }
 
   public void onInvocationFinish(InvocationFinishEvent event) {
-    totalTimer.record(event.getNanoCurrent() - event.getInvocation().getInvocationStageTrace().getStart(),
+
+    totalTimer.record((long) event.getInvocation().getInvocationStageTrace().calcTotalTime(),
         TimeUnit.NANOSECONDS);
+
+    handlersRequestTimer
+        .record((long) event.getInvocation().getInvocationStageTrace().calcHandlersRequestTime(),
+            TimeUnit.NANOSECONDS);
+    handlersResponseTimer
+        .record((long) event.getInvocation().getInvocationStageTrace().calcHandlersResponseTime(),
+            TimeUnit.NANOSECONDS);
+    prepareTimer
+        .record((long) event.getInvocation().getInvocationStageTrace().calcInvocationPrepareTime(),
+            TimeUnit.NANOSECONDS);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeters.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeters.java
index 43df8382b..179cd5a4e 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeters.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeters.java
@@ -42,8 +42,16 @@ public AbstractInvocationMeters(Registry registry) {
   protected AbstractInvocationMeter getOrCreateMeters(Invocation invocation, Response response) {
     // build string key is faster then use Id to locate timer directly
     StringBuilder keyBuilder = new StringBuilder(maxKeyLen);
+    String invocationName;
+    //check edge
+    if (invocation.isConsumer() && invocation.isEdge()) {
+      invocationName = MeterInvocationConst.EDGE_INVOCATION_NAME;
+    } else {
+      invocationName = invocation.getInvocationType().name();
+    }
+
     keyBuilder
-        .append(invocation.getInvocationType().name())
+        .append(invocationName)
         .append(invocation.getRealTransportName())
         .append(invocation.getMicroserviceQualifiedName())
         .append(response.getStatusCode());
@@ -54,7 +62,7 @@ protected AbstractInvocationMeter getOrCreateMeters(Invocation invocation, Respo
     return metersMap.computeIfAbsent(keyBuilder.toString(), k -> {
       Id id = registry.createId(MeterInvocationConst.INVOCATION_NAME,
           MeterInvocationConst.TAG_ROLE,
-          invocation.getInvocationType().name(),
+          invocationName,
           MeterInvocationConst.TAG_TRANSPORT,
           invocation.getRealTransportName(),
           MeterInvocationConst.TAG_OPERATION,
@@ -66,6 +74,8 @@ protected AbstractInvocationMeter getOrCreateMeters(Invocation invocation, Respo
     });
   }
 
+
+
   protected abstract AbstractInvocationMeter createMeter(Id id, Invocation invocation,
       Response response);
 
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeter.java
index 0f473a072..e8e0d3802 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeter.java
@@ -16,14 +16,70 @@
  */
 package org.apache.servicecomb.metrics.core.meter.invocation;
 
+import java.util.concurrent.TimeUnit;
+
 import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.event.InvocationFinishEvent;
+import org.apache.servicecomb.core.invocation.InvocationStageTrace;
 import org.apache.servicecomb.swagger.invocation.Response;
 
 import com.netflix.spectator.api.Id;
 import com.netflix.spectator.api.Registry;
+import com.netflix.spectator.api.Timer;
 
 public class ConsumerInvocationMeter extends AbstractInvocationMeter {
+
+  private Timer clientFiltersRequestTimer;
+
+  private Timer consumerSendRequestTimer;
+
+  private Timer consumerGetConnectionTimer;
+
+  private Timer consumerWriteToBufTimer;
+
+  private Timer consumerWaitResponseTimer;
+
+  private Timer consumerWakeConsumerTimer;
+
+  private Timer clientFiltersResponseTimer;
+
+
   public ConsumerInvocationMeter(Registry registry, Id id, Invocation invocation, Response response) {
     super(registry, id, invocation, response);
+    clientFiltersRequestTimer =
+        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_CLIENT_FILTERS_REQUEST));
+    consumerSendRequestTimer =
+        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_CONSUMER_SEND_REQUEST));
+    consumerGetConnectionTimer =
+        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_CONSUMER_GET_CONNECTION));
+    consumerWriteToBufTimer =
+        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_CONSUMER_WRITE_TO_BUF));
+    consumerWakeConsumerTimer =
+        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_CONSUMER_WAKE_CONSUMER));
+    clientFiltersResponseTimer =
+        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_CLIENT_FILTERS_RESPONSE));
+    consumerWaitResponseTimer =
+        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_CONSUMER_WAIT_RESPONSE));
+  }
+
+  @Override
+  public void onInvocationFinish(InvocationFinishEvent event) {
+    super.onInvocationFinish(event);
+    InvocationStageTrace invocationStageTrace = event.getInvocation().getInvocationStageTrace();
+
+    clientFiltersRequestTimer.record((long) invocationStageTrace.calcClientFiltersRequestTime(),
+        TimeUnit.NANOSECONDS);
+    consumerSendRequestTimer.record((long) invocationStageTrace.calcSendRequestTime(),
+        TimeUnit.NANOSECONDS);
+    consumerGetConnectionTimer.record((long) invocationStageTrace.calcGetConnectionTime(),
+        TimeUnit.NANOSECONDS);
+    consumerWriteToBufTimer.record((long) invocationStageTrace.calcWriteToBufferTime(),
+        TimeUnit.NANOSECONDS);
+    consumerWaitResponseTimer.record((long) invocationStageTrace.calcReceiveResponseTime(),
+        TimeUnit.NANOSECONDS);
+    consumerWakeConsumerTimer.record((long) invocationStageTrace.calcWakeConsumer(),
+        TimeUnit.NANOSECONDS);
+    clientFiltersResponseTimer.record((long) invocationStageTrace.calcClientFiltersResponseTime(),
+        TimeUnit.NANOSECONDS);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeter.java
new file mode 100644
index 000000000..ce32457e4
--- /dev/null
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeter.java
@@ -0,0 +1,50 @@
+package org.apache.servicecomb.metrics.core.meter.invocation;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.event.InvocationFinishEvent;
+import org.apache.servicecomb.core.invocation.InvocationStageTrace;
+import org.apache.servicecomb.swagger.invocation.Response;
+
+import com.netflix.spectator.api.Id;
+import com.netflix.spectator.api.Registry;
+import com.netflix.spectator.api.Timer;
+
+public class EdgeInvocationMeter extends ConsumerInvocationMeter {
+
+  private Timer executorQueueTimer;
+
+  private Timer serverFiltersRequestTimer;
+
+  private Timer serverFiltersResponseTimer;
+
+  private Timer sendResponseTimer;
+
+  public EdgeInvocationMeter(Registry registry, Id id, Invocation invocation, Response response) {
+    super(registry, id, invocation, response);
+    executorQueueTimer =
+        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_EXECUTOR_QUEUE));
+
+    serverFiltersRequestTimer =
+        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_SERVER_FILTERS_REQUEST));
+    serverFiltersResponseTimer =
+        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_SERVER_FILTERS_RESPONSE));
+    sendResponseTimer =
+        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_PRODUCER_SEND_RESPONSE));
+  }
+
+  @Override
+  public void onInvocationFinish(InvocationFinishEvent event) {
+    super.onInvocationFinish(event);
+    InvocationStageTrace invocationStageTrace = event.getInvocation().getInvocationStageTrace();
+
+    executorQueueTimer.record((long) invocationStageTrace.calcThreadPoolQueueTime(),
+        TimeUnit.NANOSECONDS);
+
+    serverFiltersRequestTimer.record((long) invocationStageTrace.calcServerFiltersRequestTime(), TimeUnit.NANOSECONDS);
+    serverFiltersResponseTimer
+        .record((long) invocationStageTrace.calcServerFiltersResponseTime(), TimeUnit.NANOSECONDS);
+    sendResponseTimer.record((long) invocationStageTrace.calcSendResponseTime(), TimeUnit.NANOSECONDS);
+  }
+}
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeters.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeters.java
new file mode 100644
index 000000000..f962a1527
--- /dev/null
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeters.java
@@ -0,0 +1,18 @@
+package org.apache.servicecomb.metrics.core.meter.invocation;
+
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.swagger.invocation.Response;
+
+import com.netflix.spectator.api.Id;
+import com.netflix.spectator.api.Registry;
+
+public class EdgeInvocationMeters extends ConsumerInvocationMeters {
+  public EdgeInvocationMeters(Registry registry) {
+    super(registry);
+  }
+
+  @Override
+  protected AbstractInvocationMeter createMeter(Id id, Invocation invocation, Response response) {
+    return new EdgeInvocationMeter(registry, id, invocation, response);
+  }
+}
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java
index 3d208c3cc..b4e12d2ae 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java
@@ -36,7 +36,39 @@
 
   final String STAGE_TOTAL = "total";
 
+  final String STAGE_PREPARE = "prepare";
+
   final String STAGE_EXECUTOR_QUEUE = "queue";
 
   final String STAGE_EXECUTION = "execution";
+
+  final String EDGE_INVOCATION_NAME = "EDGE";
+
+  final String STAGE_HANDLERS_REQUEST = "handlers_request";
+
+  final String STAGE_HANDLERS_RESPONSE = "handlers_response";
+
+  // producer only
+  final String STAGE_SERVER_FILTERS_REQUEST = "server_filters_request";
+
+  final String STAGE_SERVER_FILTERS_RESPONSE = "server_filters_response";
+
+  final String STAGE_PRODUCER_SEND_RESPONSE = "producer_send_response";
+
+  //consumer only
+
+  final String STAGE_CLIENT_FILTERS_REQUEST = "client_filters_request";
+
+  final String STAGE_CONSUMER_SEND_REQUEST = "consumer_send_request";
+
+  final String STAGE_CONSUMER_GET_CONNECTION = "consumer_get_connection";
+
+  final String STAGE_CONSUMER_WRITE_TO_BUF = "consumer_write_to_buf";
+
+  final String STAGE_CONSUMER_WAIT_RESPONSE = "consumer_wait_response";
+
+  final String STAGE_CONSUMER_WAKE_CONSUMER = "consumer_wake_consumer";
+
+  final String STAGE_CLIENT_FILTERS_RESPONSE = "client_filters_response";
+
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeter.java
index a8835c758..cb525d73c 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeter.java
@@ -20,6 +20,7 @@
 
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.event.InvocationFinishEvent;
+import org.apache.servicecomb.core.invocation.InvocationStageTrace;
 import org.apache.servicecomb.swagger.invocation.Response;
 
 import com.netflix.spectator.api.Id;
@@ -31,6 +32,13 @@
 
   private Timer executionTimer;
 
+  private Timer serverFiltersRequestTimer;
+
+  private Timer serverFiltersResponseTimer;
+
+  private Timer sendResponseTimer;
+
+
   public ProducerInvocationMeter(Registry registry, Id id, Invocation invocation, Response response) {
     super(registry, id, invocation, response);
 
@@ -38,17 +46,27 @@ public ProducerInvocationMeter(Registry registry, Id id, Invocation invocation,
         registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_EXECUTOR_QUEUE));
     executionTimer =
         registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_EXECUTION));
+    serverFiltersRequestTimer =
+        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_SERVER_FILTERS_REQUEST));
+    serverFiltersResponseTimer =
+        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_SERVER_FILTERS_RESPONSE));
+    sendResponseTimer =
+        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_PRODUCER_SEND_RESPONSE));
   }
 
   @Override
   public void onInvocationFinish(InvocationFinishEvent event) {
     super.onInvocationFinish(event);
 
-    Invocation invocation = event.getInvocation();
-    executorQueueTimer.record(
-        invocation.getInvocationStageTrace().getStartExecution() - invocation.getInvocationStageTrace().getStart(),
-        TimeUnit.NANOSECONDS);
-    executionTimer.record(event.getNanoCurrent() - invocation.getInvocationStageTrace().getStartExecution(),
+    InvocationStageTrace invocationStageTrace = event.getInvocation().getInvocationStageTrace();
+
+    executorQueueTimer.record((long) invocationStageTrace.calcThreadPoolQueueTime(),
         TimeUnit.NANOSECONDS);
+    executionTimer.record((long) invocationStageTrace.calcBusinessTime(), TimeUnit.NANOSECONDS);
+
+    serverFiltersRequestTimer.record((long) invocationStageTrace.calcServerFiltersRequestTime(), TimeUnit.NANOSECONDS);
+    serverFiltersResponseTimer
+        .record((long) invocationStageTrace.calcServerFiltersResponseTime(), TimeUnit.NANOSECONDS);
+    sendResponseTimer.record((long) invocationStageTrace.calcSendResponseTime(), TimeUnit.NANOSECONDS);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java
index 64861c735..e9575fc65 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java
@@ -47,6 +47,30 @@
 
   public static final String ENABLED = "servicecomb.metrics.publisher.defaultLog.enabled";
 
+  //sample
+  private static final String SIMPLE_HEADER = "%s:\n  simple:\n"
+      + "    status          tps           latency                                    operation\n";
+
+  private static final String FIRST_LINE_SIMPLE_FORMAT = "    %-15s %-13s %-42s %s\n";
+
+  private static final String SIMPLE_FORMAT = "                    %-13s %-42s %s\n";
+
+  //details
+  private static final String PRODUCER_DETAILS_FORMAT =
+      "        prepare: %-22s queue       : %-22s filtersReq : %-22s handlersReq: %s\n"
+          + "        execute: %-22s handlersResp: %-22s filtersResp: %-22s sendResp   : %s\n";
+
+  private static final String CONSUMER_DETAILS_FORMAT =
+      "        prepare          : %-22s handlersReq : %-22s clientFiltersReq: %-22s sendReq     : %s\n"
+          + "        getConnect       : %-22s writeBuf    : %-22s waitResp        : %-22s wakeConsumer: %s\n"
+          + "        clientFiltersResp: %-22s handlersResp: %s\n";
+
+  private static final String EDGE_DETAILS_FORMAT =
+      "        prepare          : %-22s queue       : %-22s serverFiltersReq : %-22s handlersReq : %s\n"
+          + "        clientFiltersReq : %-22s sendReq     : %-22s getConnect       : %-22s writeBuf    : %s\n"
+          + "        waitResp         : %-22s wakeConsumer: %-22s clientFiltersResp: %-22s handlersResp: %s\n"
+          + "        serverFiltersResp: %-22s sendResp    : %s\n";
+
   @Override
   public void init(CompositeRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
     if (!DynamicPropertyFactory.getInstance()
@@ -81,6 +105,7 @@ protected void printLog(List<Meter> meters) {
 
     printConsumerLog(model, sb);
     printProducerLog(model, sb);
+    printEdgeLog(model, sb);
 
     LOGGER.info(sb.toString());
   }
@@ -106,81 +131,231 @@ protected void printThreadPoolMetrics(DefaultPublishModel model, StringBuilder s
     }
   }
 
+  protected void printEdgeLog(DefaultPublishModel model, StringBuilder sb) {
+    OperationPerfGroups edgePerf = model.getEdge().getOperationPerfGroups();
+    if (edgePerf == null) {
+      return;
+    }
+    sb.append(String.format(SIMPLE_HEADER, "edge"));
+
+    StringBuilder detailsBuilder = new StringBuilder();
+    //print sample
+    for (Map<String, OperationPerfGroup> statusMap : edgePerf.getGroups().values()) {
+      for (OperationPerfGroup perfGroup : statusMap.values()) {
+        //append sample
+        sb.append(printSamplePerf(perfGroup));
+        //append details
+        detailsBuilder.append(printEdgeDetailsPerf(perfGroup));
+      }
+    }
+
+    sb.append("  details:\n")
+        .append(detailsBuilder);
+  }
+
+
   protected void printConsumerLog(DefaultPublishModel model, StringBuilder sb) {
     OperationPerfGroups consumerPerf = model.getConsumer().getOperationPerfGroups();
     if (consumerPerf == null) {
       return;
     }
 
-    sb.append("consumer:\n");
-    printConsumerPerfLog(consumerPerf, sb);
-  }
+    sb.append(String.format(SIMPLE_HEADER, "consumer"));
 
-  protected void printConsumerPerfLog(OperationPerfGroups consumerPerf, StringBuilder sb) {
-    sb.append("  tps     latency(ms) max-latency(ms) operation\n");
+    StringBuilder detailsBuilder = new StringBuilder();
+    //print sample
     for (Map<String, OperationPerfGroup> statusMap : consumerPerf.getGroups().values()) {
       for (OperationPerfGroup perfGroup : statusMap.values()) {
-        sb.append("  ")
-            .append(perfGroup.getTransport())
-            .append(".")
-            .append(perfGroup.getStatus())
-            .append(":\n");
-        for (OperationPerf operationPerf : perfGroup.getOperationPerfs()) {
-          printConsumerOperationPerf(operationPerf, sb);
-        }
-
-        printConsumerOperationPerf(perfGroup.getSummary(), sb);
+        //append sample
+        sb.append(printSamplePerf(perfGroup));
+        //append details
+        detailsBuilder.append(printConsumerDetailsPerf(perfGroup));
       }
     }
+    sb.append("  details:\n")
+        .append(detailsBuilder);
   }
 
-  protected void printConsumerOperationPerf(OperationPerf operationPerf, StringBuilder sb) {
-    PerfInfo stageTotal = operationPerf.findStage(MeterInvocationConst.STAGE_TOTAL);
-    sb.append(String.format("  %-7d %-11.3f %-15.3f %s\n",
-        stageTotal.getTps(),
-        stageTotal.calcMsLatency(),
-        stageTotal.getMsMaxLatency(),
-        operationPerf.getOperation()));
-  }
 
   protected void printProducerLog(DefaultPublishModel model, StringBuilder sb) {
     OperationPerfGroups producerPerf = model.getProducer().getOperationPerfGroups();
+
     if (producerPerf == null) {
       return;
     }
-
-    sb.append("producer:\n");
-    sb.append(
-        "  tps     latency(ms) max-latency(ms) queue(ms) max-queue(ms) execute(ms) max-execute(ms) operation\n");
+    sb.append(String.format(SIMPLE_HEADER, "producer"));
+    // use detailsBuilder, we can traverse the map only once
+    StringBuilder detailsBuilder = new StringBuilder();
+    //print sample
     for (Map<String, OperationPerfGroup> statusMap : producerPerf.getGroups().values()) {
       for (OperationPerfGroup perfGroup : statusMap.values()) {
-        sb.append("  ")
-            .append(perfGroup.getTransport())
-            .append(".")
-            .append(perfGroup.getStatus())
-            .append(":\n");
-        for (OperationPerf operationPerf : perfGroup.getOperationPerfs()) {
-          printProducerOperationPerf(operationPerf, sb);
-        }
-
-        printProducerOperationPerf(perfGroup.getSummary(), sb);
+        //append sample
+        sb.append(printSamplePerf(perfGroup));
+        //append details
+        detailsBuilder.append(printProducerDetailsPerf(perfGroup));
+      }
+    }
+    //print details
+    sb.append("  details:\n")
+        .append(detailsBuilder);
+  }
+
+
+  private StringBuilder printSamplePerf(OperationPerfGroup perfGroup) {
+    StringBuilder sb = new StringBuilder();
+    for (int i = 0; i < perfGroup.getOperationPerfs().size(); i++) {
+      OperationPerf operationPerf = perfGroup.getOperationPerfs().get(i);
+      PerfInfo stageTotal = operationPerf.findStage(MeterInvocationConst.STAGE_TOTAL);
+      if (i == 0) {
+        // first line
+        String status = perfGroup.getTransport() + "." + perfGroup.getStatus();
+        sb.append(String.format(FIRST_LINE_SIMPLE_FORMAT, status, stageTotal.getTps(),
+            getDetailsFromPerf(stageTotal), operationPerf.getOperation()));
+      } else {
+        sb.append(String
+            .format(SIMPLE_FORMAT, stageTotal.getTps(), getDetailsFromPerf(stageTotal), operationPerf.getOperation()));
       }
     }
+    //print summary
+    OperationPerf summaryOperation = perfGroup.getSummary();
+    PerfInfo stageSummaryTotal = summaryOperation.findStage(MeterInvocationConst.STAGE_TOTAL);
+    sb.append(
+        String.format(SIMPLE_FORMAT, stageSummaryTotal.getTps(), getDetailsFromPerf(stageSummaryTotal), "(summary)"));
+    return sb;
+  }
+
+  private StringBuilder printProducerDetailsPerf(OperationPerfGroup perfGroup) {
+    StringBuilder sb = new StringBuilder();
+    //append rest.200:
+    sb.append("    ")
+        .append(perfGroup.getTransport())
+        .append(".")
+        .append(perfGroup.getStatus())
+        .append(":\n");
+    PerfInfo prepare, queue, filtersReq, handlersReq, execute, handlersResp, filtersResp, sendResp;
+    for (OperationPerf operationPerf : perfGroup.getOperationPerfs()) {
+
+      prepare = operationPerf.findStage(MeterInvocationConst.STAGE_PREPARE);
+      queue = operationPerf.findStage(MeterInvocationConst.STAGE_EXECUTOR_QUEUE);
+      filtersReq = operationPerf.findStage(MeterInvocationConst.STAGE_SERVER_FILTERS_REQUEST);
+      handlersReq = operationPerf.findStage(MeterInvocationConst.STAGE_HANDLERS_REQUEST);
+      execute = operationPerf.findStage(MeterInvocationConst.STAGE_EXECUTION);
+      handlersResp = operationPerf.findStage(MeterInvocationConst.STAGE_HANDLERS_RESPONSE);
+      filtersResp = operationPerf.findStage(MeterInvocationConst.STAGE_SERVER_FILTERS_RESPONSE);
+      sendResp = operationPerf.findStage(MeterInvocationConst.STAGE_PRODUCER_SEND_RESPONSE);
+
+      sb.append("      ")
+          .append(operationPerf.getOperation())
+          .append(":\n")
+          .append(String.format(PRODUCER_DETAILS_FORMAT,
+              getDetailsFromPerf(prepare),
+              getDetailsFromPerf(queue),
+              getDetailsFromPerf(filtersReq),
+              getDetailsFromPerf(handlersReq),
+              getDetailsFromPerf(execute),
+              getDetailsFromPerf(handlersResp),
+              getDetailsFromPerf(filtersResp),
+              getDetailsFromPerf(sendResp)
+          ));
+    }
+
+    return sb;
+  }
+
+  private StringBuilder printConsumerDetailsPerf(OperationPerfGroup perfGroup) {
+    StringBuilder sb = new StringBuilder();
+    //append rest.200:
+    sb.append("    ")
+        .append(perfGroup.getTransport())
+        .append(".")
+        .append(perfGroup.getStatus())
+        .append(":\n");
+
+    PerfInfo prepare, handlersReq, clientFiltersReq, sendReq, getConnect, writeBuf,
+        waitResp, wakeConsumer, clientFiltersResp, handlersResp;
+    for (OperationPerf operationPerf : perfGroup.getOperationPerfs()) {
+
+      prepare = operationPerf.findStage(MeterInvocationConst.STAGE_PREPARE);
+      handlersReq = operationPerf.findStage(MeterInvocationConst.STAGE_HANDLERS_REQUEST);
+      clientFiltersReq = operationPerf.findStage(MeterInvocationConst.STAGE_CLIENT_FILTERS_REQUEST);
+      sendReq = operationPerf.findStage(MeterInvocationConst.STAGE_CONSUMER_SEND_REQUEST);
+      getConnect = operationPerf.findStage(MeterInvocationConst.STAGE_CONSUMER_GET_CONNECTION);
+      writeBuf = operationPerf.findStage(MeterInvocationConst.STAGE_CONSUMER_WRITE_TO_BUF);
+      waitResp = operationPerf.findStage(MeterInvocationConst.STAGE_CONSUMER_WAIT_RESPONSE);
+      wakeConsumer = operationPerf.findStage(MeterInvocationConst.STAGE_CONSUMER_WAKE_CONSUMER);
+      clientFiltersResp = operationPerf.findStage(MeterInvocationConst.STAGE_CLIENT_FILTERS_RESPONSE);
+      handlersResp = operationPerf.findStage(MeterInvocationConst.STAGE_HANDLERS_RESPONSE);
+
+      sb.append("      ")
+          .append(operationPerf.getOperation())
+          .append(":\n")
+          .append(String.format(CONSUMER_DETAILS_FORMAT,
+              getDetailsFromPerf(prepare),
+              getDetailsFromPerf(handlersReq),
+              getDetailsFromPerf(clientFiltersReq),
+              getDetailsFromPerf(sendReq),
+              getDetailsFromPerf(getConnect),
+              getDetailsFromPerf(writeBuf),
+              getDetailsFromPerf(waitResp),
+              getDetailsFromPerf(wakeConsumer),
+              getDetailsFromPerf(clientFiltersResp),
+              getDetailsFromPerf(handlersResp)
+          ));
+    }
+
+    return sb;
   }
 
-  protected void printProducerOperationPerf(OperationPerf operationPerf, StringBuilder sb) {
-    PerfInfo stageTotal = operationPerf.findStage(MeterInvocationConst.STAGE_TOTAL);
-    PerfInfo stageQueue = operationPerf.findStage(MeterInvocationConst.STAGE_EXECUTOR_QUEUE);
-    PerfInfo stageExecution = operationPerf.findStage(MeterInvocationConst.STAGE_EXECUTION);
-    sb.append(String.format("  %-7d %-11.3f %-15.3f %-9.3f %-13.3f %-11.3f %-15.3f %s\n",
-        stageTotal.getTps(),
-        stageTotal.calcMsLatency(),
-        stageTotal.getMsMaxLatency(),
-        stageQueue.calcMsLatency(),
-        stageQueue.getMsMaxLatency(),
-        stageExecution.calcMsLatency(),
-        stageExecution.getMsMaxLatency(),
-        operationPerf.getOperation()));
+  private StringBuilder printEdgeDetailsPerf(OperationPerfGroup perfGroup) {
+    StringBuilder sb = new StringBuilder();
+    //append rest.200:
+    sb.append("    ")
+        .append(perfGroup.getTransport())
+        .append(".")
+        .append(perfGroup.getStatus())
+        .append(":\n");
+
+    PerfInfo prepare, queue, serverFiltersReq, handlersReq, clientFiltersReq, sendReq, getConnect, writeBuf,
+        waitResp, wakeConsumer, clientFiltersResp, handlersResp, serverFiltersResp, sendResp;
+    for (OperationPerf operationPerf : perfGroup.getOperationPerfs()) {
+
+      prepare = operationPerf.findStage(MeterInvocationConst.STAGE_PREPARE);
+      queue = operationPerf.findStage(MeterInvocationConst.STAGE_EXECUTOR_QUEUE);
+      serverFiltersReq = operationPerf.findStage(MeterInvocationConst.STAGE_SERVER_FILTERS_REQUEST);
+      handlersReq = operationPerf.findStage(MeterInvocationConst.STAGE_HANDLERS_REQUEST);
+      clientFiltersReq = operationPerf.findStage(MeterInvocationConst.STAGE_CLIENT_FILTERS_REQUEST);
+      sendReq = operationPerf.findStage(MeterInvocationConst.STAGE_CONSUMER_SEND_REQUEST);
+      getConnect = operationPerf.findStage(MeterInvocationConst.STAGE_CONSUMER_GET_CONNECTION);
+      writeBuf = operationPerf.findStage(MeterInvocationConst.STAGE_CONSUMER_WRITE_TO_BUF);
+      waitResp = operationPerf.findStage(MeterInvocationConst.STAGE_CONSUMER_WAIT_RESPONSE);
+      wakeConsumer = operationPerf.findStage(MeterInvocationConst.STAGE_CONSUMER_WAKE_CONSUMER);
+      clientFiltersResp = operationPerf.findStage(MeterInvocationConst.STAGE_CLIENT_FILTERS_RESPONSE);
+      handlersResp = operationPerf.findStage(MeterInvocationConst.STAGE_HANDLERS_RESPONSE);
+      serverFiltersResp = operationPerf.findStage(MeterInvocationConst.STAGE_SERVER_FILTERS_RESPONSE);
+      sendResp = operationPerf.findStage(MeterInvocationConst.STAGE_PRODUCER_SEND_RESPONSE);
+
+      sb.append("      ")
+          .append(operationPerf.getOperation())
+          .append(":\n")
+          .append(String.format(EDGE_DETAILS_FORMAT,
+              getDetailsFromPerf(prepare),
+              getDetailsFromPerf(queue),
+              getDetailsFromPerf(serverFiltersReq),
+              getDetailsFromPerf(handlersReq),
+              getDetailsFromPerf(clientFiltersReq),
+              getDetailsFromPerf(sendReq),
+              getDetailsFromPerf(getConnect),
+              getDetailsFromPerf(writeBuf),
+              getDetailsFromPerf(waitResp),
+              getDetailsFromPerf(wakeConsumer),
+              getDetailsFromPerf(clientFiltersResp),
+              getDetailsFromPerf(handlersResp),
+              getDetailsFromPerf(serverFiltersResp),
+              getDetailsFromPerf(sendResp)
+          ));
+    }
+
+    return sb;
   }
 
   protected void printVertxMetrics(StringBuilder sb) {
@@ -192,4 +367,12 @@ protected void printVertxMetrics(StringBuilder sb) {
           entry.getValue().getEventLoopContextCreatedCount()));
     }
   }
+
+  private static String getDetailsFromPerf(PerfInfo perfInfo) {
+    String result = "";
+    if (perfInfo != null) {
+      result = String.format("%.3f/%.3f", perfInfo.calcMsLatency(), perfInfo.getMsMaxLatency());
+    }
+    return result;
+  }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java
index 8c311bfe2..58ef4ef83 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java
@@ -84,8 +84,12 @@ public DefaultPublishModel createDefaultPublishModel() {
 
     model.getConsumer()
         .setOperationPerfGroups(generateOperationPerfGroups(tree, InvocationType.CONSUMER.name()));
+
     model.getProducer()
         .setOperationPerfGroups(generateOperationPerfGroups(tree, InvocationType.PRODUCER.name()));
+    //edge
+    model.getEdge()
+        .setOperationPerfGroups(generateOperationPerfGroups(tree, MeterInvocationConst.EDGE_INVOCATION_NAME));
 
     ThreadPoolMonitorPublishModelFactory.create(tree, model.getThreadPools());
 
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/model/DefaultPublishModel.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/model/DefaultPublishModel.java
index b33ab5810..825158801 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/model/DefaultPublishModel.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/model/DefaultPublishModel.java
@@ -24,6 +24,8 @@
 
   private ProducerPublishModel producer = new ProducerPublishModel();
 
+  private EdgePublishModel edge = new EdgePublishModel();
+
   private Map<String, ThreadPoolPublishModel> threadPools = new HashMap<>();
 
   public ConsumerPublishModel getConsumer() {
@@ -38,6 +40,14 @@ public ProducerPublishModel getProducer() {
     return producer;
   }
 
+  public EdgePublishModel getEdge() {
+    return edge;
+  }
+
+  public void setEdge(EdgePublishModel edge) {
+    this.edge = edge;
+  }
+
   public void setProducer(ProducerPublishModel producer) {
     this.producer = producer;
   }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/model/EdgePublishModel.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/model/EdgePublishModel.java
new file mode 100644
index 000000000..ee309293e
--- /dev/null
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/model/EdgePublishModel.java
@@ -0,0 +1,15 @@
+package org.apache.servicecomb.metrics.core.publish.model;
+
+import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerfGroups;
+
+public class EdgePublishModel extends ConsumerPublishModel {
+  private OperationPerfGroups operationPerfGroups;
+
+  public OperationPerfGroups getOperationPerfGroups() {
+    return operationPerfGroups;
+  }
+
+  public void setOperationPerfGroups(OperationPerfGroups operationPerfGroups) {
+    this.operationPerfGroups = operationPerfGroups;
+  }
+}
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java
index bc6f8771c..4bc556eb0 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java
@@ -16,6 +16,8 @@
  */
 package org.apache.servicecomb.metrics.core;
 
+import static org.junit.Assert.assertEquals;
+
 import org.apache.servicecomb.core.Const;
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.event.InvocationFinishEvent;
@@ -26,7 +28,6 @@
 import org.apache.servicecomb.metrics.core.meter.invocation.MeterInvocationConst;
 import org.apache.servicecomb.swagger.invocation.InvocationType;
 import org.apache.servicecomb.swagger.invocation.Response;
-import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -79,12 +80,110 @@ public void consumerInvocation(@Mocked InvocationFinishEvent event) {
         result = Const.RESTFUL;
         invocation.getMicroserviceQualifiedName();
         result = "m.s.o";
-        invocation.getInvocationStageTrace().getStart();
-        result = 1;
+        invocation.getInvocationStageTrace().calcTotalTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcClientFiltersRequestTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcSendRequestTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcGetConnectionTime();
+        result = 4;
+        invocation.getInvocationStageTrace().calcWriteToBufferTime();
+        result = 5;
+        invocation.getInvocationStageTrace().calcWakeConsumer();
+        result = 9;
+        invocation.getInvocationStageTrace().calcReceiveResponseTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcClientFiltersResponseTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcInvocationPrepareTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcHandlersRequestTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcHandlersResponseTime();
+        result = 9;
+
+        event.getInvocation();
+        result = invocation;
+      }
+    };
+
+    eventBus.post(event);
+    eventBus.post(event);
+
+    MeasurementTree tree = new MeasurementTree();
+    tree.from(registry.iterator(), new MeasurementGroupConfig(MeterInvocationConst.INVOCATION_NAME));
+    assertEquals(
+        "[Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_wait_response:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_wait_response:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_write_to_buf:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_write_to_buf:statistic=totalTime:status=0:transport=rest,0,10.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=client_filters_request:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=client_filters_request:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=total:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=total:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=client_filters_response:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=client_filters_response:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_send_request:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_send_request:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=handlers_request:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=handlers_request:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=handlers_response:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=handlers_response:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_wake_consumer:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_wake_consumer:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_get_connection:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_get_connection:statistic=totalTime:status=0:transport=rest,0,8.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=prepare:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=prepare:statistic=totalTime:status=0:transport=rest,0,18.0)]"
+        ,
+        tree.findChild(MeterInvocationConst.INVOCATION_NAME).getMeasurements().toString());
+  }
+
+  @Test
+  public void edgeInvocation(@Mocked InvocationFinishEvent event) {
+    new Expectations() {
+      {
+        invocation.isConsumer();
+        result = true;
+        invocation.isEdge();
+        result = true;
+        invocation.getRealTransportName();
+        result = Const.RESTFUL;
+        invocation.getMicroserviceQualifiedName();
+        result = "m.s.o";
+        invocation.getInvocationStageTrace().calcTotalTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcThreadPoolQueueTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcClientFiltersRequestTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcSendRequestTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcGetConnectionTime();
+        result = 4;
+        invocation.getInvocationStageTrace().calcWriteToBufferTime();
+        result = 5;
+        invocation.getInvocationStageTrace().calcWakeConsumer();
+        result = 9;
+        invocation.getInvocationStageTrace().calcReceiveResponseTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcClientFiltersResponseTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcInvocationPrepareTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcHandlersRequestTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcHandlersResponseTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcSendResponseTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcServerFiltersRequestTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcServerFiltersResponseTime();
+        result = 9;
         event.getInvocation();
         result = invocation;
-        event.getNanoCurrent();
-        result = 10;
       }
     };
 
@@ -93,9 +192,38 @@ public void consumerInvocation(@Mocked InvocationFinishEvent event) {
 
     MeasurementTree tree = new MeasurementTree();
     tree.from(registry.iterator(), new MeasurementGroupConfig(MeterInvocationConst.INVOCATION_NAME));
-    Assert.assertEquals(
-        "[Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=total:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=total:statistic=totalTime:status=0:transport=rest,0,18.0)]",
+    assertEquals(
+        "[Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_send_request:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_send_request:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=server_filters_response:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=server_filters_response:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=total:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=total:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=handlers_request:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=handlers_request:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_wake_consumer:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_wake_consumer:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=client_filters_response:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=client_filters_response:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=producer_send_response:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=producer_send_response:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_write_to_buf:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_write_to_buf:statistic=totalTime:status=0:transport=rest,0,10.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=server_filters_request:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=server_filters_request:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=queue:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=queue:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=prepare:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=prepare:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_get_connection:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_get_connection:statistic=totalTime:status=0:transport=rest,0,8.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_wait_response:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_wait_response:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=handlers_response:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=handlers_response:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=client_filters_request:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=client_filters_request:statistic=totalTime:status=0:transport=rest,0,18.0)]"
+        ,
         tree.findChild(MeterInvocationConst.INVOCATION_NAME).getMeasurements().toString());
   }
 
@@ -111,12 +239,24 @@ public void producerInvocation(@Mocked InvocationFinishEvent event) {
         result = Const.RESTFUL;
         invocation.getMicroserviceQualifiedName();
         result = "m.s.o";
-        invocation.getInvocationStageTrace().getStart();
-        result = 1;
-        invocation.getInvocationStageTrace().getStartExecution();
-        result = 3;
-        event.getNanoCurrent();
-        result = 10;
+        invocation.getInvocationStageTrace().calcTotalTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcInvocationPrepareTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcHandlersRequestTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcHandlersResponseTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcThreadPoolQueueTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcBusinessTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcServerFiltersRequestTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcServerFiltersResponseTime();
+        result = 9;
+        invocation.getInvocationStageTrace().calcSendResponseTime();
+        result = 9;
         event.getInvocation();
         result = invocation;
       }
@@ -127,13 +267,26 @@ public void producerInvocation(@Mocked InvocationFinishEvent event) {
 
     MeasurementTree tree = new MeasurementTree();
     tree.from(registry.iterator(), new MeasurementGroupConfig(MeterInvocationConst.INVOCATION_NAME));
-    Assert.assertEquals(
+    assertEquals(
         "[Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=execution:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=execution:statistic=totalTime:status=0:transport=rest,0,14.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=execution:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=prepare:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=prepare:statistic=totalTime:status=0:transport=rest,0,18.0), "
             + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=total:statistic=count:status=0:transport=rest,0,2.0), "
             + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=total:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=handlers_request:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=handlers_request:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=handlers_response:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=handlers_response:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=producer_send_response:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=producer_send_response:statistic=totalTime:status=0:transport=rest,0,18.0), "
             + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=queue:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=queue:statistic=totalTime:status=0:transport=rest,0,4.0)]",
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=queue:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=server_filters_request:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=server_filters_request:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=server_filters_response:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=server_filters_response:statistic=totalTime:status=0:transport=rest,0,18.0)]"
+        ,
         tree.findChild(MeterInvocationConst.INVOCATION_NAME).getMeasurements().toString());
   }
 }
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestDefaultLogPublisher.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestDefaultLogPublisher.java
index 4f9ff27f9..2accd3473 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestDefaultLogPublisher.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestDefaultLogPublisher.java
@@ -148,6 +148,19 @@ public void onPolledEvent(@Mocked VertxImplEx vertxImplEx) {
     operationPerf.getStages().put(MeterInvocationConst.STAGE_TOTAL, perfTotal);
     operationPerf.getStages().put(MeterInvocationConst.STAGE_EXECUTOR_QUEUE, perfTotal);
     operationPerf.getStages().put(MeterInvocationConst.STAGE_EXECUTION, perfTotal);
+    operationPerf.getStages().put(MeterInvocationConst.STAGE_PREPARE, perfTotal);
+    operationPerf.getStages().put(MeterInvocationConst.STAGE_HANDLERS_REQUEST, perfTotal);
+    operationPerf.getStages().put(MeterInvocationConst.STAGE_HANDLERS_RESPONSE, perfTotal);
+    operationPerf.getStages().put(MeterInvocationConst.STAGE_CLIENT_FILTERS_REQUEST, perfTotal);
+    operationPerf.getStages().put(MeterInvocationConst.STAGE_CLIENT_FILTERS_RESPONSE, perfTotal);
+    operationPerf.getStages().put(MeterInvocationConst.STAGE_CONSUMER_SEND_REQUEST, perfTotal);
+    operationPerf.getStages().put(MeterInvocationConst.STAGE_PRODUCER_SEND_RESPONSE, perfTotal);
+    operationPerf.getStages().put(MeterInvocationConst.STAGE_CONSUMER_GET_CONNECTION, perfTotal);
+    operationPerf.getStages().put(MeterInvocationConst.STAGE_CONSUMER_WRITE_TO_BUF, perfTotal);
+    operationPerf.getStages().put(MeterInvocationConst.STAGE_CONSUMER_WAIT_RESPONSE, perfTotal);
+    operationPerf.getStages().put(MeterInvocationConst.STAGE_CONSUMER_WAKE_CONSUMER, perfTotal);
+    operationPerf.getStages().put(MeterInvocationConst.STAGE_SERVER_FILTERS_REQUEST, perfTotal);
+    operationPerf.getStages().put(MeterInvocationConst.STAGE_SERVER_FILTERS_RESPONSE, perfTotal);
 
     OperationPerfGroup operationPerfGroup = new OperationPerfGroup(Const.RESTFUL, Status.OK.name());
     operationPerfGroup.addOperationPerf(operationPerf);
@@ -182,16 +195,26 @@ DefaultPublishModel createDefaultPublishModel() {
             "  corePoolSize maxThreads poolSize currentThreadsBusy queueSize taskCount completedTaskCount name\n" +
             "  0            0          0        0                  0         0.0       0.0                test\n" +
             "consumer:\n" +
-            "  tps     latency(ms) max-latency(ms) operation\n" +
-            "  rest.OK:\n" +
-            "  10      10.000      0.000           op\n" +
-            "  10      10.000      0.000           \n" +
-            "producer:\n" +
-            "  tps     latency(ms) max-latency(ms) queue(ms) max-queue(ms) execute(ms) max-execute(ms) operation\n" +
-            "  rest.OK:\n" +
-            "  10      10.000      0.000           10.000    0.000         10.000      0.000           op\n" +
-            "  10      10.000      0.000           10.000    0.000         10.000      0.000           \n" +
-            "",
+            "  simple:\n"
+            + "    status          tps           latency                                    operation\n"
+            + "    rest.OK         10            10.000/0.000                               op\n"
+            + "                    10            10.000/0.000                               (summary)\n"
+            + "  details:\n"
+            + "    rest.OK:\n"
+            + "      op:\n"
+            + "        prepare          : 10.000/0.000           handlersReq : 10.000/0.000           clientFiltersReq: 10.000/0.000           sendReq     : 10.000/0.000\n"
+            + "        getConnect       : 10.000/0.000           writeBuf    : 10.000/0.000           waitResp        : 10.000/0.000           wakeConsumer: 10.000/0.000\n"
+            + "        clientFiltersResp: 10.000/0.000           handlersResp: 10.000/0.000\n"
+            + "producer:\n"
+            + "  simple:\n"
+            + "    status          tps           latency                                    operation\n"
+            + "    rest.OK         10            10.000/0.000                               op\n"
+            + "                    10            10.000/0.000                               (summary)\n"
+            + "  details:\n"
+            + "    rest.OK:\n"
+            + "      op:\n"
+            + "        prepare: 10.000/0.000           queue       : 10.000/0.000           filtersReq : 10.000/0.000           handlersReq: 10.000/0.000\n"
+            + "        execute: 10.000/0.000           handlersResp: 10.000/0.000           filtersResp: 10.000/0.000           sendResp   : 10.000/0.000\n",
         event.getMessage());
   }
 }
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java
index 1b0d14a58..e284533fc 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java
@@ -81,17 +81,33 @@ public void createDefaultPublishModel() throws JsonProcessingException {
     DefaultPublishModel model = factory.createDefaultPublishModel();
 
     Assert.assertEquals(
-        "{\"operationPerfGroups\":{\"groups\":{\"rest\":{\"200\":{\"transport\":\"rest\",\"status\":\"200\",\"operationPerfs\":[{\"operation\":\"m.s.o\",\"stages\":{\"total\":{\"tps\":1,\"msTotalTime\":10000.0,\"msMaxLatency\":0.0}}}],\"summary\":{\"operation\":\"\",\"stages\":{\"total\":{\"tps\":1,\"msTotalTime\":10000.0,\"msMaxLatency\":0.0}}}}}}}}",
+        "{\"operationPerfGroups\":{\"groups\":{\"rest\":{\"200\":{\"transport\":\"rest\",\"status\":\"200\",\"operationPerfs\":[{\"operation\":\"m.s.o\",\"stages\":{\"client_filters_request\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"prepare\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"consumer_send_request\":{\"tps\":1,\"msTotalTime\":2000.0,\"msMaxLatency\":0.0},\"total\":{\"tps\":1,\"msTotalTime\":14000.0,\"msMaxLatency\":0.0},\"handlers_request\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"consumer_wait_response\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"client_filters_response\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"handlers_response\":{\"tps\":1,\"msTotalTime\":3000.0,\"msMaxLatency\":0.0},\"consumer_get_connection\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"consumer_wake_consumer\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"consumer_write_to_buf\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0}}}],\"summary\":{\"operation\":\"\",\"stages\":{\"prepare\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"client_filters_request\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"total\":{\"tps\":1,\"msTotalTime\":14000.0,\"msMaxLatency\":0.0},\"consumer_send_request\":{\"tps\":1,\"msTotalTime\":2000.0,\"msMaxLatency\":0.0},\"handlers_request\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"handlers_response\":{\"tps\":1,\"msTotalTime\":3000.0,\"msMaxLatency\":0.0},\"client_filters_response\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"consumer_wait_response\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"consumer_get_connection\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"consumer_write_to_buf\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"consumer_wake_consumer\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0}}}}}}}}",
         JsonUtils.writeValueAsString(model.getConsumer()));
     Assert.assertEquals(
-        "{\"operationPerfGroups\":{\"groups\":{\"rest\":{\"200\":{\"transport\":\"rest\",\"status\":\"200\",\"operationPerfs\":[{\"operation\":\"m.s.o\",\"stages\":{\"execution\":{\"tps\":1,\"msTotalTime\":5000.0,\"msMaxLatency\":0.0},\"total\":{\"tps\":1,\"msTotalTime\":10000.0,\"msMaxLatency\":0.0},\"queue\":{\"tps\":1,\"msTotalTime\":5000.0,\"msMaxLatency\":0.0}}}],\"summary\":{\"operation\":\"\",\"stages\":{\"execution\":{\"tps\":1,\"msTotalTime\":5000.0,\"msMaxLatency\":0.0},\"total\":{\"tps\":1,\"msTotalTime\":10000.0,\"msMaxLatency\":0.0},\"queue\":{\"tps\":1,\"msTotalTime\":5000.0,\"msMaxLatency\":0.0}}}}}}}}",
+        "{\"operationPerfGroups\":{\"groups\":{\"rest\":{\"200\":{\"transport\":\"rest\",\"status\":\"200\",\"operationPerfs\":[{\"operation\":\"m.s.o\",\"stages\":{\"server_filters_request\":{\"tps\":1,\"msTotalTime\":0.0,\"msMaxLatency\":0.0},\"prepare\":{\"tps\":1,\"msTotalTime\":5000.0,\"msMaxLatency\":0.0},\"execution\":{\"tps\":1,\"msTotalTime\":3000.0,\"msMaxLatency\":0.0},\"producer_send_response\":{\"tps\":1,\"msTotalTime\":2000.0,\"msMaxLatency\":0.0},\"total\":{\"tps\":1,\"msTotalTime\":14000.0,\"msMaxLatency\":0.0},\"handlers_request\":{\"tps\":1,\"msTotalTime\":6000.0,\"msMaxLatency\":0.0},\"handlers_response\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"queue\":{\"tps\":0,\"msTotalTime\":0.0,\"msMaxLatency\":0.0},\"server_filters_response\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0}}}],\"summary\":{\"operation\":\"\",\"stages\":{\"server_filters_request\":{\"tps\":1,\"msTotalTime\":0.0,\"msMaxLatency\":0.0},\"execution\":{\"tps\":1,\"msTotalTime\":3000.0,\"msMaxLatency\":0.0},\"prepare\":{\"tps\":1,\"msTotalTime\":5000.0,\"msMaxLatency\":0.0},\"total\":{\"tps\":1,\"msTotalTime\":14000.0,\"msMaxLatency\":0.0},\"producer_send_response\":{\"tps\":1,\"msTotalTime\":2000.0,\"msMaxLatency\":0.0},\"handlers_request\":{\"tps\":1,\"msTotalTime\":6000.0,\"msMaxLatency\":0.0},\"handlers_response\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"queue\":{\"tps\":0,\"msTotalTime\":0.0,\"msMaxLatency\":0.0},\"server_filters_response\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0}}}}}}}}",
         JsonUtils.writeValueAsString(model.getProducer()));
   }
 
   protected void prepareInvocation() {
-    Deencapsulation.setField(invocationStageTrace, "start", 0L);
-    Deencapsulation.setField(invocationStageTrace, "finish", 10L);
+
+    Deencapsulation.setField(invocationStageTrace, "start", 1L);
+    Deencapsulation.setField(invocationStageTrace, "startHandlersRequest", 2L);
+    Deencapsulation.setField(invocationStageTrace, "startClientFiltersRequest", 3L);
+    Deencapsulation.setField(invocationStageTrace, "startSend", 4L);
+    Deencapsulation.setField(invocationStageTrace, "finishGetConnection", 5L);
+    Deencapsulation.setField(invocationStageTrace, "finishWriteToBuffer", 6L);
+    Deencapsulation.setField(invocationStageTrace, "finishReceiveResponse", 7L);
+    Deencapsulation.setField(invocationStageTrace, "startClientFiltersResponse", 8L);
+    Deencapsulation.setField(invocationStageTrace, "finishClientFiltersResponse", 9L);
+    Deencapsulation.setField(invocationStageTrace, "finishHandlersResponse", 14L);
+    Deencapsulation.setField(invocationStageTrace, "finish", 15L);
     Deencapsulation.setField(invocationStageTrace, "startExecution", 5L);
+    Deencapsulation.setField(invocationStageTrace, "startSchedule", 6L);
+    Deencapsulation.setField(invocationStageTrace, "startBusinessMethod", 8L);
+    Deencapsulation.setField(invocationStageTrace, "finishBusiness", 11L);
+    Deencapsulation.setField(invocationStageTrace, "finishHandlersResponse", 12L);
+    Deencapsulation.setField(invocationStageTrace, "finishServerFiltersResponse", 13L);
+    Deencapsulation.setField(invocationStageTrace, "invocation", invocation);
 
     invocationType = InvocationType.CONSUMER;
     new MockUp<Invocation>() {


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services