This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git

commit 229b3c2d40ae595a881cd7835fcb1f60b925a226
Author: wujimin <wuji...@huawei.com>
AuthorDate: Mon Nov 12 16:52:36 2018 +0800

    [SCB-1021] publish vertx client/server meters to log
---
 demo/perf/src/main/resources/microservice.yaml     |   6 +-
 .../test/scaffolding/log/LogCollector.java         |   4 +
 .../AbstractMeasurementNodeLogPublisher.java       |  40 +++++
 .../metrics/core/publish/DefaultLogPublisher.java  |  26 ++-
 .../core/publish/EndpointsLogPublisher.java        |  78 +++++++++
 .../metrics/core/publish/PublishModelFactory.java  |   8 +
 .../metrics/core/TestVertxMetersInitializer.java   | 174 +++++++++++++++++++++
 7 files changed, 332 insertions(+), 4 deletions(-)

diff --git a/demo/perf/src/main/resources/microservice.yaml 
b/demo/perf/src/main/resources/microservice.yaml
index ffa9c23..d460f19 100644
--- a/demo/perf/src/main/resources/microservice.yaml
+++ b/demo/perf/src/main/resources/microservice.yaml
@@ -38,10 +38,12 @@ servicecomb:
     client:
       thread-count: 8
   references:
-    transport: rest
+    transport: highway
   metrics:
     window_time: 1000
-    publisher.defaultLog.enabled: true
+    publisher.defaultLog:
+      enabled: true
+      endpoints.client.detail.enabled: true
 
 sync-count: 10
 async-count: 20
diff --git 
a/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/log/LogCollector.java
 
b/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/log/LogCollector.java
index 53359e3..026408a 100644
--- 
a/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/log/LogCollector.java
+++ 
b/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/log/LogCollector.java
@@ -61,4 +61,8 @@ public class LogCollector {
   public void teardown() {
     Logger.getRootLogger().removeAppender(appender);
   }
+
+  public void clear() {
+    events = new ArrayList<>();
+  }
 }
diff --git 
a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/AbstractMeasurementNodeLogPublisher.java
 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/AbstractMeasurementNodeLogPublisher.java
new file mode 100644
index 0000000..960c7b6
--- /dev/null
+++ 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/AbstractMeasurementNodeLogPublisher.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.metrics.core.publish;
+
+import 
org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNode;
+import 
org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
+
+public abstract class AbstractMeasurementNodeLogPublisher {
+  protected StringBuilder sb;
+
+  protected MeasurementNode measurementNode;
+
+  private boolean exists;
+
+  public AbstractMeasurementNodeLogPublisher(MeasurementTree tree, 
StringBuilder sb, String... childNames) {
+    this.sb = sb;
+    measurementNode = tree.findChild(childNames);
+    exists = measurementNode != null && 
!measurementNode.getMeasurements().isEmpty();
+  }
+
+  public boolean isExists() {
+    return exists;
+  }
+
+  public abstract void print(boolean printDetail);
+}
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 8259ff9..75a6642 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
@@ -30,6 +30,7 @@ import 
org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNo
 import 
org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
 import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.apache.servicecomb.foundation.vertx.VertxUtils;
+import org.apache.servicecomb.metrics.core.VertxMetersInitializer;
 import 
org.apache.servicecomb.metrics.core.meter.invocation.MeterInvocationConst;
 import org.apache.servicecomb.metrics.core.meter.os.NetMeter;
 import org.apache.servicecomb.metrics.core.meter.os.OsMeter;
@@ -54,6 +55,9 @@ public class DefaultLogPublisher implements 
MetricsInitializer {
 
   public static final String ENABLED = 
"servicecomb.metrics.publisher.defaultLog.enabled";
 
+  // for a client, maybe will connect to too many endpoints, so default not 
print detail, just print summary
+  public static final String ENDPOINTS_CLIENT_DETAIL_ENABLED = 
"servicecomb.metrics.publisher.defaultLog.endpoints.client.detail.enabled";
+
   //sample
   private static final String SIMPLE_HEADER = "%s:\n  simple:\n"
       + "    status          tps      latency             operation\n";
@@ -107,7 +111,7 @@ public class DefaultLogPublisher implements 
MetricsInitializer {
     DefaultPublishModel model = factory.createDefaultPublishModel();
 
     printOsLog(factory.getTree(), sb);
-    printVertxMetrics(sb);
+    printVertxMetrics(factory.getTree(), sb);
     printThreadPoolMetrics(model, sb);
 
     printConsumerLog(model, sb);
@@ -410,7 +414,7 @@ public class DefaultLogPublisher implements 
MetricsInitializer {
     return sb;
   }
 
-  protected void printVertxMetrics(StringBuilder sb) {
+  protected void printVertxMetrics(MeasurementTree tree, StringBuilder sb) {
     appendLine(sb, "vertx:");
 
     appendLine(sb, "  instances:");
@@ -420,6 +424,24 @@ public class DefaultLogPublisher implements 
MetricsInitializer {
           entry.getKey(),
           entry.getValue().getEventLoopContextCreatedCount());
     }
+
+    EndpointsLogPublisher client = new EndpointsLogPublisher(tree, sb, 
VertxMetersInitializer.ENDPOINTS_CLINET,
+        "client.endpoints", "remote");
+    EndpointsLogPublisher server = new EndpointsLogPublisher(tree, sb, 
VertxMetersInitializer.ENDPOINTS_SERVER,
+        "server.endpoints", "listen");
+    if (client.isExists() || server.isExists()) {
+      appendLine(sb, "  transport:");
+      if (client.isExists()) {
+        client.print(DynamicPropertyFactory
+            .getInstance()
+            .getBooleanProperty(ENDPOINTS_CLIENT_DETAIL_ENABLED, false)
+            .get());
+      }
+
+      if (server.isExists()) {
+        server.print(true);
+      }
+    }
   }
 
   private static String getDetailsFromPerf(PerfInfo perfInfo) {
diff --git 
a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/EndpointsLogPublisher.java
 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/EndpointsLogPublisher.java
new file mode 100644
index 0000000..5fcf601
--- /dev/null
+++ 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/EndpointsLogPublisher.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.metrics.core.publish;
+
+import static 
org.apache.servicecomb.foundation.common.utils.StringBuilderUtils.appendLine;
+
+import org.apache.servicecomb.foundation.common.net.NetUtils;
+import 
org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNode;
+import 
org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
+import org.apache.servicecomb.metrics.core.VertxMetersInitializer;
+import org.apache.servicecomb.metrics.core.meter.vertx.EndpointMeter;
+
+public class EndpointsLogPublisher extends AbstractMeasurementNodeLogPublisher 
{
+  private final String title;
+
+  private final String endpointTitle;
+
+  public EndpointsLogPublisher(MeasurementTree tree, StringBuilder sb, String 
meterName, String title,
+      String endpointTitle) {
+    super(tree, sb, VertxMetersInitializer.VERTX_ENDPOINTS, meterName);
+    this.title = title;
+    this.endpointTitle = endpointTitle;
+  }
+
+  @Override
+  public void print(boolean printDetail) {
+    appendLine(sb, "    %s:", title);
+    appendLine(sb, "      %-21s connectCount    disconnectCount connections    
 send         receive",
+        endpointTitle);
+
+    double connect = 0;
+    double disconnect = 0;
+    double connections = 0;
+    double readSize = 0;
+    double writeSize = 0;
+    for (MeasurementNode address : measurementNode.getChildren().values()) {
+      connect += address.findChild(EndpointMeter.CONNECT_COUNT).summary();
+      disconnect += 
address.findChild(EndpointMeter.DISCONNECT_COUNT).summary();
+      connections += address.findChild(EndpointMeter.CONNECTIONS).summary();
+      readSize += address.findChild(EndpointMeter.BYTES_READ).summary();
+      writeSize += address.findChild(EndpointMeter.BYTES_WRITTEN).summary();
+
+      if (printDetail) {
+        appendLine(sb, "      %-21s %-15.0f %-15.0f %-15.0f %-12s %-12s",
+            address.getName(),
+            address.findChild(EndpointMeter.CONNECT_COUNT).summary(),
+            address.findChild(EndpointMeter.DISCONNECT_COUNT).summary(),
+            address.findChild(EndpointMeter.CONNECTIONS).summary(),
+            NetUtils.humanReadableBytes((long) 
address.findChild(EndpointMeter.BYTES_WRITTEN).summary()),
+            NetUtils.humanReadableBytes((long) 
address.findChild(EndpointMeter.BYTES_READ).summary())
+        );
+      }
+    }
+
+    appendLine(sb, "      %-21s %-15.0f %-15.0f %-15.0f %-12s %-12s",
+        "(summary)",
+        connect,
+        disconnect,
+        connections,
+        NetUtils.humanReadableBytes((long) writeSize),
+        NetUtils.humanReadableBytes((long) readSize)
+    );
+  }
+}
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 d12d0eb..9b94ba3 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
@@ -22,9 +22,11 @@ import 
org.apache.servicecomb.foundation.metrics.publish.spectator.DefaultTagFin
 import 
org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementGroupConfig;
 import 
org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNode;
 import 
org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
+import org.apache.servicecomb.metrics.core.VertxMetersInitializer;
 import 
org.apache.servicecomb.metrics.core.meter.invocation.MeterInvocationConst;
 import org.apache.servicecomb.metrics.core.meter.os.NetMeter;
 import org.apache.servicecomb.metrics.core.meter.os.OsMeter;
+import org.apache.servicecomb.metrics.core.meter.vertx.EndpointMeter;
 import org.apache.servicecomb.metrics.core.publish.model.DefaultPublishModel;
 import 
org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerfGroups;
 import org.apache.servicecomb.swagger.invocation.InvocationType;
@@ -60,12 +62,18 @@ public class PublishModelFactory {
         MeterInvocationConst.TAG_STATUS,
         MeterInvocationConst.TAG_STAGE,
         MeterInvocationConst.TAG_STATISTIC);
+
     //os config
     groupConfig.addGroup(OsMeter.OS_NAME,
         OsMeter.OS_TYPE,
         new DefaultTagFinder(NetMeter.INTERFACE, true),
         NetMeter.STATISTIC);
 
+    groupConfig.addGroup(VertxMetersInitializer.VERTX_ENDPOINTS,
+        VertxMetersInitializer.ENDPOINTS_TYPE,
+        EndpointMeter.ADDRESS,
+        EndpointMeter.STATISTIC);
+
     return groupConfig;
   }
 
diff --git 
a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestVertxMetersInitializer.java
 
b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestVertxMetersInitializer.java
new file mode 100644
index 0000000..16c316c
--- /dev/null
+++ 
b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestVertxMetersInitializer.java
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.metrics.core;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.servicecomb.core.transport.AbstractTransport;
+import org.apache.servicecomb.core.transport.TransportVertxFactory;
+import org.apache.servicecomb.foundation.metrics.PolledEvent;
+import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
+import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
+import org.apache.servicecomb.foundation.test.scaffolding.log.LogCollector;
+import org.apache.servicecomb.foundation.vertx.VertxUtils;
+import org.apache.servicecomb.metrics.core.publish.DefaultLogPublisher;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+import com.google.common.eventbus.EventBus;
+import com.netflix.spectator.api.DefaultRegistry;
+import com.netflix.spectator.api.ManualClock;
+import com.netflix.spectator.api.Measurement;
+import com.netflix.spectator.api.Meter;
+import com.netflix.spectator.api.Registry;
+
+import io.vertx.core.AbstractVerticle;
+import io.vertx.core.DeploymentOptions;
+import io.vertx.core.Future;
+import io.vertx.core.http.HttpClient;
+import io.vertx.core.http.HttpServer;
+import io.vertx.ext.web.Router;
+import mockit.Expectations;
+
+public class TestVertxMetersInitializer {
+  GlobalRegistry globalRegistry = new GlobalRegistry(new ManualClock());
+
+  Registry registry = new DefaultRegistry(globalRegistry.getClock());
+
+  EventBus eventBus = new EventBus();
+
+  TransportVertxFactory transportVertxFactory;
+
+  VertxMetersInitializer vertxMetersInitializer = new VertxMetersInitializer();
+
+  DefaultLogPublisher logPublisher = new DefaultLogPublisher();
+
+  static int port;
+
+  static String body = "body";
+
+  public static class TestServerVerticle extends AbstractVerticle {
+    @Override
+    public void start(Future<Void> startFuture) {
+      Router mainRouter = Router.router(vertx);
+      mainRouter.route("/").handler(context -> {
+        context.response().end(context.getBody());
+      });
+
+      HttpServer server = vertx.createHttpServer();
+      server.requestHandler(mainRouter::accept);
+      server.listen(0, "0.0.0.0", ar -> {
+        if (ar.succeeded()) {
+          port = ar.result().actualPort();
+          startFuture.complete();
+          return;
+        }
+
+        startFuture.fail(ar.cause());
+      });
+    }
+  }
+
+  public static class TestClientVerticle extends AbstractVerticle {
+    @Override
+    public void start(Future<Void> startFuture) {
+      HttpClient client = vertx.createHttpClient();
+      client.post(port, "127.0.0.1", "/").handler(resp -> {
+        startFuture.complete();
+      }).end(body);
+    }
+  }
+
+  @Before
+  public void setup() {
+    VertxUtils.blockCloseVertxByName("transport");
+  }
+
+  @After
+  public void teardown() {
+    VertxUtils.blockCloseVertxByName("transport");
+  }
+
+  @Test
+  public void init() throws InterruptedException {
+    transportVertxFactory = new TransportVertxFactory();
+    new Expectations(AbstractTransport.class) {
+      {
+        AbstractTransport.getTransportVertxFactory();
+        result = transportVertxFactory;
+      }
+    };
+
+    globalRegistry.add(registry);
+    vertxMetersInitializer.init(globalRegistry, eventBus, null);
+    logPublisher.init(null, eventBus, null);
+    VertxUtils
+        .blockDeploy(transportVertxFactory.getTransportVertx(), 
TestServerVerticle.class, new DeploymentOptions());
+    VertxUtils
+        .blockDeploy(transportVertxFactory.getTransportVertx(), 
TestClientVerticle.class, new DeploymentOptions());
+
+    globalRegistry.poll(1);
+    List<Meter> meters = Lists.newArrayList(registry.iterator());
+    List<Measurement> measurements = new ArrayList<>();
+    for (Meter meter : meters) {
+      meter.measure().forEach(measurements::add);
+    }
+
+    LogCollector logCollector = new LogCollector();
+
+    testLog(logCollector, meters, measurements, true);
+    logCollector.clear();
+    testLog(logCollector, meters, measurements, false);
+
+    logCollector.teardown();
+  }
+
+  private void testLog(LogCollector logCollector, List<Meter> meters, 
List<Measurement> measurements,
+      boolean printDetail) {
+    
ArchaiusUtils.setProperty(DefaultLogPublisher.ENDPOINTS_CLIENT_DETAIL_ENABLED, 
String.valueOf(printDetail));
+    logPublisher.onPolledEvent(new PolledEvent(meters, measurements));
+
+    StringBuilder sb = new StringBuilder();
+    logCollector.getEvents().forEach(event -> 
sb.append(event.getMessage()).append("\n"));
+    String actual = sb.toString();
+    int idx = actual.indexOf("vertx:\n");
+    actual = actual.substring(idx);
+
+    String expect = "vertx:\n"
+        + "  instances:\n"
+        + "    name       eventLoopContext-created\n"
+        + "    transport  4\n"
+        + "  transport:\n"
+        + "    client.endpoints:\n"
+        + "      remote                connectCount    disconnectCount 
connections     send         receive\n";
+    if (printDetail) {
+      expect += String.format(
+          "      127.0.0.1:%-5s       1               0               1        
       4 B          21 B        \n",
+          port);
+    }
+    expect += "      (summary)             1               0               1   
            4 B          21 B        \n"
+        + "    server.endpoints:\n"
+        + "      listen                connectCount    disconnectCount 
connections     send         receive\n"
+        + "      0.0.0.0:0             1               0               1       
        21 B         4 B         \n"
+        + "      (summary)             1               0               1       
        21 B         4 B         \n\n";
+    Assert.assertEquals(expect, actual);
+  }
+}

Reply via email to