You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by li...@apache.org on 2020/10/10 09:40:41 UTC

[skywalking-agent-test-tool] branch meter_agent_test created (now 1c66e63)

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

liuhan pushed a change to branch meter_agent_test
in repository https://gitbox.apache.org/repos/asf/skywalking-agent-test-tool.git.


      at 1c66e63  Add meter mock collector and validate

This branch includes the following new commits:

     new 1c66e63  Add meter mock collector and validate

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[skywalking-agent-test-tool] 01/01: Add meter mock collector and validate

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

liuhan pushed a commit to branch meter_agent_test
in repository https://gitbox.apache.org/repos/asf/skywalking-agent-test-tool.git

commit 1c66e63bfbb0fd67a057d6ef154d652abbfdcb89
Author: Mrproliu <mr...@lagou.com>
AuthorDate: Sat Oct 10 17:40:24 2020 +0800

    Add meter mock collector and validate
---
 mock-collector/pom.xml                             |   2 +-
 .../skywalking/plugin/test/mockcollector/Main.java |   5 +-
 .../plugin/test/mockcollector/entity/Meter.java    |  65 ++++++++++++
 .../plugin/test/mockcollector/entity/MeterId.java  |  97 +++++++++++++++++
 .../entity/{ValidateData.java => MeterItem.java}   |  33 +++---
 .../entity/{ValidateData.java => MeterItems.java}  |  28 ++---
 .../mockcollector/entity/MeterItemsSerializer.java |  47 +++++++++
 .../test/mockcollector/entity/ValidateData.java    |   8 ++
 .../entity/ValidateDataSerializer.java             |   2 +
 .../mockcollector/mock/MockMeterReportService.java |  52 ++++++++++
 .../test/mockcollector/util/MeterHandler.java      |  76 ++++++++++++++
 .../agent/tool/validator/assertor/DataAssert.java  |   1 +
 .../agent/tool/validator/assertor/MeterAssert.java |  68 ++++++++++++
 .../tool/validator/assertor/MeterItemsAssert.java  |  64 ++++++++++++
 .../assertor/element/GreatThanAssertor.java        |   2 +-
 .../assertor/element/GreetEqualAssertor.java       |   2 +-
 .../exception/HistogramSizeNotEqualsException.java |  39 +++++++
 .../MeterAssertFailedException.java}               |  33 +++---
 .../MeterItemNotFoundException.java}               |  23 ++---
 .../MeterNotFoundException.java}                   |  31 +++---
 .../exception/MeterSizeNotEqualsException.java     |  38 +++++++
 .../tool/validator/entity/BucketAndValue.java      |  32 +++---
 .../test/agent/tool/validator/entity/Data.java     |  10 +-
 .../agent/tool/validator/entity/DataForRead.java   |  18 ++++
 .../test/agent/tool/validator/entity/Meter.java    |  50 +++++++++
 .../test/agent/tool/validator/entity/MeterId.java  | 115 +++++++++++++++++++++
 .../agent/tool/validator/entity/MeterItem.java     |  57 ++++++++++
 27 files changed, 912 insertions(+), 86 deletions(-)

diff --git a/mock-collector/pom.xml b/mock-collector/pom.xml
index eb4f75e..20fca71 100644
--- a/mock-collector/pom.xml
+++ b/mock-collector/pom.xml
@@ -34,7 +34,7 @@
     <url>http://maven.apache.org</url>
 
     <properties>
-        <protocol.version>7e563891f3cfaf5c19ad086434af93aaab996719</protocol.version>
+        <protocol.version>9933e2d17078c2bf07cd1c8d5ef36d52b5cbb917</protocol.version>
         <protocol.workingDirectory>${project.basedir}/target/protocol</protocol.workingDirectory>
         <protocol.repos>https://github.com/apache/skywalking-data-collect-protocol.git</protocol.repos>
         <protobuf-maven-plugin.version>0.6.1</protobuf-maven-plugin.version>
diff --git a/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/Main.java b/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/Main.java
index 0660196..2ba7756 100644
--- a/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/Main.java
+++ b/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/Main.java
@@ -19,10 +19,10 @@ package org.apache.skywalking.plugin.test.mockcollector;
 
 import io.grpc.netty.NettyServerBuilder;
 import io.netty.channel.local.LocalAddress;
-import java.net.InetSocketAddress;
 import org.apache.skywalking.plugin.test.mockcollector.mock.MockCLRMetricReportService;
 import org.apache.skywalking.plugin.test.mockcollector.mock.MockJVMMetricReportService;
 import org.apache.skywalking.plugin.test.mockcollector.mock.MockManagementService;
+import org.apache.skywalking.plugin.test.mockcollector.mock.MockMeterReportService;
 import org.apache.skywalking.plugin.test.mockcollector.mock.MockTraceSegmentService;
 import org.apache.skywalking.plugin.test.mockcollector.mock.rest.MockManagementServiceKeepAliveHandler;
 import org.apache.skywalking.plugin.test.mockcollector.mock.rest.MockManagementServiceReportPropertiesHandler;
@@ -36,6 +36,8 @@ import org.apache.skywalking.plugin.test.mockcollector.service.ReceiveDataServic
 import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.servlet.ServletContextHandler;
 
+import java.net.InetSocketAddress;
+
 public class Main {
     public static void main(String[] args) throws Exception {
         // Mock GRPC Collector
@@ -46,6 +48,7 @@ public class Main {
                           .addService(new MockJVMMetricReportService())
                           .addService(new MockManagementService())
                           .addService(new MockTraceSegmentService())
+                          .addService(new MockMeterReportService())
                           .build()
                           .start();
 
diff --git a/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/Meter.java b/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/Meter.java
new file mode 100644
index 0000000..ee9e467
--- /dev/null
+++ b/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/Meter.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.skywalking.plugin.test.mockcollector.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.ToString;
+
+import java.util.List;
+
+@ToString
+@Builder
+@AllArgsConstructor
+@Getter
+public class Meter {
+    private MeterId meterId;
+    private Double singleValue;
+    private List<BucketAndValue> histogram;
+
+    public static class BucketAndValue {
+        private double bucket;
+        private long count;
+
+        public BucketAndValue(double bucket, long count) {
+            this.bucket = bucket;
+            this.count = count;
+        }
+
+        public double getBucket() {
+            return bucket;
+        }
+
+        public long getCount() {
+            return count;
+        }
+    }
+
+    public MeterId getMeterId() {
+        return meterId;
+    }
+
+    public Double getSingleValue() {
+        return singleValue;
+    }
+
+    public List<BucketAndValue> getHistogram() {
+        return histogram;
+    }
+}
diff --git a/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/MeterId.java b/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/MeterId.java
new file mode 100644
index 0000000..038744a
--- /dev/null
+++ b/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/MeterId.java
@@ -0,0 +1,97 @@
+/*
+ * 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.skywalking.plugin.test.mockcollector.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.ToString;
+
+import java.util.List;
+import java.util.Objects;
+
+@ToString
+@Builder
+@AllArgsConstructor
+@Getter
+public class MeterId {
+    private String name;
+    private List<Tag> tags;
+
+    /**
+     * Using name/value pair as the tag, also it will {@link Comparable} when we sort all of tags
+     */
+    public static class Tag implements Comparable<Tag> {
+        private String name;
+        private String value;
+
+        public Tag(String name, String value) {
+            this.name = name;
+            this.value = value;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public String getValue() {
+            return value;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            Tag tag = (Tag) o;
+            return Objects.equals(name, tag.name) &&
+                Objects.equals(value, tag.value);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(name, value);
+        }
+
+        @Override
+        public int compareTo(Tag o) {
+            return this.name.compareTo(o.name);
+        }
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public List<Tag> getTags() {
+        return tags;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        MeterId meterId = (MeterId) o;
+        return Objects.equals(name, meterId.name) &&
+            Objects.equals(tags, meterId.tags);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(name, tags);
+    }
+}
diff --git a/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/ValidateData.java b/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/MeterItem.java
similarity index 51%
copy from mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/ValidateData.java
copy to mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/MeterItem.java
index 12eb61d..fcf0b63 100644
--- a/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/ValidateData.java
+++ b/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/MeterItem.java
@@ -6,30 +6,39 @@
  * (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
+ *      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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
  */
 
 package org.apache.skywalking.plugin.test.mockcollector.entity;
 
-public class ValidateData {
-    public static ValidateData INSTANCE = new ValidateData();
-    private SegmentItems segmentItem;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
 
-    private  ValidateData() {
-        segmentItem = new SegmentItems();
+public class MeterItem {
+    private String serviceName;
+    private Map<MeterId, Meter> meters;
+
+    public MeterItem(String serviceName) {
+        this.serviceName = serviceName;
+        meters = new HashMap<>();
+    }
+
+    public void addMeter(Meter meter) {
+        meters.put(meter.getMeterId(), meter);
     }
 
-    public synchronized SegmentItems getSegmentItem() {
-        return segmentItem;
+    public String getServiceName() {
+        return serviceName;
     }
 
-    public synchronized void clearData() {
-        INSTANCE.segmentItem = new SegmentItems();
+    public Collection<Meter> getMeters() {
+        return meters.values();
     }
 }
diff --git a/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/ValidateData.java b/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/MeterItems.java
similarity index 52%
copy from mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/ValidateData.java
copy to mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/MeterItems.java
index 12eb61d..33f71c1 100644
--- a/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/ValidateData.java
+++ b/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/MeterItems.java
@@ -6,30 +6,34 @@
  * (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
+ *      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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
  */
 
 package org.apache.skywalking.plugin.test.mockcollector.entity;
 
-public class ValidateData {
-    public static ValidateData INSTANCE = new ValidateData();
-    private SegmentItems segmentItem;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
-    private  ValidateData() {
-        segmentItem = new SegmentItems();
+public class MeterItems {
+    private Map<String, MeterItem> meterItems;
+
+    public MeterItems() {
+        this.meterItems = new ConcurrentHashMap<>();
     }
 
-    public synchronized SegmentItems getSegmentItem() {
-        return segmentItem;
+    public MeterItems addMeter(String serviceName, Meter meter) {
+        final MeterItem item = meterItems.computeIfAbsent(serviceName, (name) -> new MeterItem(name));
+        item.addMeter(meter);
+        return this;
     }
 
-    public synchronized void clearData() {
-        INSTANCE.segmentItem = new SegmentItems();
+    public Map<String, MeterItem> getMeterItems() {
+        return meterItems;
     }
 }
diff --git a/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/MeterItemsSerializer.java b/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/MeterItemsSerializer.java
new file mode 100644
index 0000000..c7a5852
--- /dev/null
+++ b/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/MeterItemsSerializer.java
@@ -0,0 +1,47 @@
+/*
+ * 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.skywalking.plugin.test.mockcollector.entity;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+
+import java.lang.reflect.Type;
+
+public class MeterItemsSerializer implements JsonSerializer<MeterItems> {
+    @Override
+    public JsonElement serialize(MeterItems meterItems, Type type, JsonSerializationContext jsonSerializationContext) {
+        final JsonArray serviceMeterItems = new JsonArray();
+        meterItems.getMeterItems().forEach((serviceName, meterItem) -> {
+            final JsonObject meterJson = new JsonObject();
+            meterJson.addProperty("serviceName", serviceName);
+            meterJson.addProperty("meterSize", meterItem.getMeters().size());
+            final JsonArray meters = new JsonArray();
+            meterItem.getMeters().forEach(meter -> {
+                meters.add(new Gson().toJsonTree(meter));
+            });
+            meterJson.add("meters", meters);;
+            serviceMeterItems.add(meterJson);
+        });
+
+        return serviceMeterItems;
+    }
+}
diff --git a/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/ValidateData.java b/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/ValidateData.java
index 12eb61d..1d9e1a6 100644
--- a/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/ValidateData.java
+++ b/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/ValidateData.java
@@ -20,9 +20,11 @@ package org.apache.skywalking.plugin.test.mockcollector.entity;
 public class ValidateData {
     public static ValidateData INSTANCE = new ValidateData();
     private SegmentItems segmentItem;
+    private MeterItems meterItems;
 
     private  ValidateData() {
         segmentItem = new SegmentItems();
+        meterItems = new MeterItems();
     }
 
     public synchronized SegmentItems getSegmentItem() {
@@ -31,5 +33,11 @@ public class ValidateData {
 
     public synchronized void clearData() {
         INSTANCE.segmentItem = new SegmentItems();
+        INSTANCE.meterItems = new MeterItems();
     }
+
+    public synchronized MeterItems getMeterItems() {
+        return meterItems;
+    }
+
 }
diff --git a/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/ValidateDataSerializer.java b/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/ValidateDataSerializer.java
index ee98785..926fd21 100644
--- a/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/ValidateDataSerializer.java
+++ b/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/ValidateDataSerializer.java
@@ -29,10 +29,12 @@ public class ValidateDataSerializer implements JsonSerializer<ValidateData> {
     @Override
     public JsonElement serialize(ValidateData src, Type typeOfSrc, JsonSerializationContext context) {
         Gson gson = new GsonBuilder().registerTypeAdapter(SegmentItems.class, new SegmentItemsSerializer())
+                                     .registerTypeAdapter(MeterItems.class, new MeterItemsSerializer())
                                      .create();
 
         JsonObject jsonObject = new JsonObject();
         jsonObject.add("segmentItems", gson.toJsonTree(src.getSegmentItem()));
+        jsonObject.add("meterItems", gson.toJsonTree(src.getMeterItems()));
         return jsonObject;
     }
 }
diff --git a/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/mock/MockMeterReportService.java b/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/mock/MockMeterReportService.java
new file mode 100644
index 0000000..e191499
--- /dev/null
+++ b/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/mock/MockMeterReportService.java
@@ -0,0 +1,52 @@
+/*
+ * 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.skywalking.plugin.test.mockcollector.mock;
+
+import io.grpc.stub.StreamObserver;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.apm.network.common.v3.Commands;
+import org.apache.skywalking.apm.network.language.agent.v3.MeterData;
+import org.apache.skywalking.apm.network.language.agent.v3.MeterReportServiceGrpc;
+import org.apache.skywalking.plugin.test.mockcollector.util.MeterHandler;
+
+@Slf4j
+public class MockMeterReportService extends MeterReportServiceGrpc.MeterReportServiceImplBase {
+
+    @Override
+    public StreamObserver<MeterData> collect(StreamObserver<Commands> responseObserver) {
+        final MeterHandler.Parser parser = MeterHandler.createParser();
+        return new StreamObserver<MeterData>() {
+            @Override
+            public void onNext(MeterData meterData) {
+                parser.parse(meterData);
+            }
+
+            @Override
+            public void onError(Throwable throwable) {
+                log.error(throwable.getMessage(), throwable);
+                responseObserver.onCompleted();
+            }
+
+            @Override
+            public void onCompleted() {
+                responseObserver.onNext(Commands.newBuilder().build());
+                responseObserver.onCompleted();
+            }
+        };
+    }
+}
diff --git a/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/util/MeterHandler.java b/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/util/MeterHandler.java
new file mode 100644
index 0000000..a99389a
--- /dev/null
+++ b/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/util/MeterHandler.java
@@ -0,0 +1,76 @@
+/*
+ * 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.skywalking.plugin.test.mockcollector.util;
+
+import org.apache.skywalking.apm.network.language.agent.v3.Label;
+import org.apache.skywalking.apm.network.language.agent.v3.MeterData;
+import org.apache.skywalking.apm.network.language.agent.v3.MeterHistogram;
+import org.apache.skywalking.apm.network.language.agent.v3.MeterSingleValue;
+import org.apache.skywalking.plugin.test.mockcollector.entity.Meter;
+import org.apache.skywalking.plugin.test.mockcollector.entity.MeterId;
+import org.apache.skywalking.plugin.test.mockcollector.entity.ValidateData;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class MeterHandler {
+
+    public static Parser createParser() {
+        return new Parser();
+    }
+
+    public static class Parser {
+        private String serviceName;
+
+        public void parse(MeterData meterData) {
+            final Meter.MeterBuilder builder = Meter.builder();
+
+            switch (meterData.getMetricCase()) {
+                case SINGLEVALUE:
+                    final MeterSingleValue singleValue = meterData.getSingleValue();
+                    builder.meterId(MeterId.builder()
+                        .name(singleValue.getName())
+                        .tags(parseTags(singleValue.getLabelsList()))
+                        .build());
+                    builder.singleValue(singleValue.getValue());
+                    break;
+                case HISTOGRAM:
+                    final MeterHistogram histogram = meterData.getHistogram();
+                    builder.meterId(MeterId.builder()
+                        .name(histogram.getName())
+                        .tags(parseTags(histogram.getLabelsList()))
+                        .build());
+                    builder.histogram(histogram.getValuesList().stream()
+                        .map(b -> new Meter.BucketAndValue(b.getBucket(), b.getCount())).collect(Collectors.toList()));
+                    break;
+                case METRIC_NOT_SET:
+                    return;
+            }
+
+            final Meter meter = builder.build();
+            if (meterData.getService() != null && meterData.getService().length() > 0) {
+                serviceName = meterData.getService();
+            }
+            ValidateData.INSTANCE.getMeterItems().addMeter(serviceName, meter);
+        }
+
+        private List<MeterId.Tag> parseTags(List<Label> labels) {
+            return labels.stream().map(l -> new MeterId.Tag(l.getName(), l.getValue())).collect(Collectors.toList());
+        }
+    }
+}
diff --git a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/DataAssert.java b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/DataAssert.java
index fff1a99..b31e69a 100644
--- a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/DataAssert.java
+++ b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/DataAssert.java
@@ -28,6 +28,7 @@ public class DataAssert {
         log.info("excepted data:\n{}", new GsonBuilder().setPrettyPrinting().create().toJson(excepted));
         log.info("actual data:\n{}", new GsonBuilder().setPrettyPrinting().create().toJson(actual));
         SegmentItemsAssert.assertEquals(excepted.segmentItems(), actual.segmentItems());
+        MeterItemsAssert.assertEquals(excepted.meterItems(), actual.meterItems());
         log.info("{} assert successful.", "segment items");
     }
 }
diff --git a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/MeterAssert.java b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/MeterAssert.java
new file mode 100644
index 0000000..4f5bbcb
--- /dev/null
+++ b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/MeterAssert.java
@@ -0,0 +1,68 @@
+/*
+ * 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.skywalking.plugin.test.agent.tool.validator.assertor;
+
+import org.apache.skywalking.plugin.test.agent.tool.validator.assertor.exception.HistogramSizeNotEqualsException;
+import org.apache.skywalking.plugin.test.agent.tool.validator.assertor.exception.MeterAssertFailedException;
+import org.apache.skywalking.plugin.test.agent.tool.validator.assertor.exception.MeterNotFoundException;
+import org.apache.skywalking.plugin.test.agent.tool.validator.entity.BucketAndValue;
+import org.apache.skywalking.plugin.test.agent.tool.validator.entity.Meter;
+import org.apache.skywalking.plugin.test.agent.tool.validator.entity.MeterItem;
+import org.apache.skywalking.plugin.test.agent.tool.validator.exception.AssertFailedException;
+
+import java.util.Objects;
+
+public class MeterAssert {
+
+    public static void assertEquals(MeterItem expected, MeterItem actual) {
+        for (Meter meter : expected.getMeters()) {
+            Meter actualMeter = findMeter(actual, meter);
+            if (actualMeter == null) {
+                throw new MeterNotFoundException(meter);
+            }
+
+            try {
+                meterDataEquals(meter, actualMeter);
+            } catch (AssertFailedException e) {
+                throw new MeterAssertFailedException(e, meter.getMeterId());
+            }
+        }
+    }
+
+    private static Meter findMeter(MeterItem actual, Meter expectedMeter) {
+        return actual.getMeters().stream().filter(s -> Objects.equals(s.getMeterId(), expectedMeter.getMeterId())).findFirst().orElse(null);
+    }
+
+    private static void meterDataEquals(Meter excepted, Meter actual) {
+        if (excepted.getSingleValue() != null) {
+            ExpressParser.parse(excepted.getSingleValue()).assertValue("single value", actual.getSingleValue());
+        } else {
+            if (excepted.getHistogram().size() != actual.getHistogram().size()) {
+                throw new HistogramSizeNotEqualsException(excepted, actual.getHistogram().size());
+            }
+
+            for (int bucketIndex = 0; bucketIndex < excepted.getHistogram().size(); bucketIndex++) {
+                final BucketAndValue exceptedBucket = excepted.getHistogram().get(bucketIndex);
+                final BucketAndValue actualBucket = actual.getHistogram().get(bucketIndex);
+
+                ExpressParser.parse(exceptedBucket.getBucket()).assertValue("histogram bucket", actualBucket.getBucket());
+                ExpressParser.parse(exceptedBucket.getCount()).assertValue("histogram count[" + actualBucket.getBucket() + "]", actualBucket.getCount());
+            }
+        }
+    }
+}
diff --git a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/MeterItemsAssert.java b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/MeterItemsAssert.java
new file mode 100644
index 0000000..1fc792d
--- /dev/null
+++ b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/MeterItemsAssert.java
@@ -0,0 +1,64 @@
+/*
+ * 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.skywalking.plugin.test.agent.tool.validator.assertor;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.plugin.test.agent.tool.validator.assertor.exception.MeterItemNotFoundException;
+import org.apache.skywalking.plugin.test.agent.tool.validator.assertor.exception.MeterSizeNotEqualsException;
+import org.apache.skywalking.plugin.test.agent.tool.validator.assertor.exception.ValueAssertFailedException;
+import org.apache.skywalking.plugin.test.agent.tool.validator.entity.MeterItem;
+
+import java.util.List;
+
+@Slf4j
+public class MeterItemsAssert {
+
+    public static void assertEquals(List<MeterItem> excepted, List<MeterItem> actual) {
+        for (MeterItem item : excepted) {
+            MeterItem actualMeterItem = findMeterItem(actual, item);
+            try {
+                assertMeterSize(item.getMeterSize(), actualMeterItem.getMeterSize());
+            } catch (ValueAssertFailedException e) {
+                throw new MeterSizeNotEqualsException(
+                    item.getServiceName(), item.getMeterSize(), actualMeterItem.getMeterSize());
+            }
+
+            MeterAssert.assertEquals(item, actualMeterItem);
+        }
+    }
+
+    private static void assertMeterSize(String expected, String actual) {
+        if (expected == null) {
+            return;
+        }
+        ExpressParser.parse(expected).assertValue("meter size", actual);
+    }
+
+    /**
+     * Find same service meter item
+     */
+    private static MeterItem findMeterItem(List<MeterItem> actual, MeterItem expected) {
+        for (MeterItem segmentItem : actual) {
+            if (expected.getServiceName().equals(segmentItem.getServiceName())) {
+                return segmentItem;
+            }
+        }
+
+        throw new MeterItemNotFoundException(expected.getServiceName());
+    }
+}
diff --git a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/element/GreatThanAssertor.java b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/element/GreatThanAssertor.java
index ca2fecd..b5638b1 100644
--- a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/element/GreatThanAssertor.java
+++ b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/element/GreatThanAssertor.java
@@ -27,7 +27,7 @@ public class GreatThanAssertor extends ElementAssertor {
 
     @Override
     public void assertValue(String desc, String actualValue) {
-        if (Long.parseLong(actualValue) <= Long.parseLong(exceptedValue)) {
+        if (Double.parseDouble(actualValue) <= Double.parseDouble(exceptedValue)) {
             throw new ValueAssertFailedException(desc, " gt " + exceptedValue, actualValue);
         }
     }
diff --git a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/element/GreetEqualAssertor.java b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/element/GreetEqualAssertor.java
index 8c97fd6..0aae8c6 100644
--- a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/element/GreetEqualAssertor.java
+++ b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/element/GreetEqualAssertor.java
@@ -27,7 +27,7 @@ public class GreetEqualAssertor extends ElementAssertor {
 
     @Override
     public void assertValue(String desc, String actualValue) {
-        if (Long.parseLong(actualValue) < Long.parseLong(exceptedValue)) {
+        if (Double.parseDouble(actualValue) < Double.parseDouble(exceptedValue)) {
             throw new ValueAssertFailedException(desc, " ge " + exceptedValue, actualValue);
         }
     }
diff --git a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/exception/HistogramSizeNotEqualsException.java b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/exception/HistogramSizeNotEqualsException.java
new file mode 100644
index 0000000..55ad439
--- /dev/null
+++ b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/exception/HistogramSizeNotEqualsException.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.skywalking.plugin.test.agent.tool.validator.assertor.exception;
+
+import org.apache.skywalking.plugin.test.agent.tool.validator.entity.Meter;
+import org.apache.skywalking.plugin.test.agent.tool.validator.exception.AssertFailedException;
+
+public class HistogramSizeNotEqualsException extends AssertFailedException {
+    private final Meter exceptedMeter;
+    private final int actualSize;
+
+    public HistogramSizeNotEqualsException(Meter exceptedMeter, int actualSize) {
+        this.exceptedMeter = exceptedMeter;
+        this.actualSize = actualSize;
+    }
+
+    @Override
+    public String getCauseMessage() {
+        return String.format("HistogramSizeNotEqualsException:\nmeter id:%s\nexpected:%s\nactual:%s\n",
+            exceptedMeter.getMeterId(),
+            exceptedMeter.getHistogram().size(),
+            actualSize);
+    }
+}
diff --git a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/DataAssert.java b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/exception/MeterAssertFailedException.java
similarity index 50%
copy from validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/DataAssert.java
copy to validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/exception/MeterAssertFailedException.java
index fff1a99..492afce 100644
--- a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/DataAssert.java
+++ b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/exception/MeterAssertFailedException.java
@@ -6,28 +6,33 @@
  * (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
+ *      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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
  */
 
-package org.apache.skywalking.plugin.test.agent.tool.validator.assertor;
+package org.apache.skywalking.plugin.test.agent.tool.validator.assertor.exception;
 
-import com.google.gson.GsonBuilder;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.skywalking.plugin.test.agent.tool.validator.entity.Data;
+import org.apache.skywalking.plugin.test.agent.tool.validator.entity.MeterId;
+import org.apache.skywalking.plugin.test.agent.tool.validator.exception.AssertFailedException;
 
-@Slf4j
-public class DataAssert {
+public class MeterAssertFailedException extends AssertFailedException {
+    private final AssertFailedException e;
+    private final MeterId meterId;
 
-    public static void assertEquals(Data excepted, Data actual) {
-        log.info("excepted data:\n{}", new GsonBuilder().setPrettyPrinting().create().toJson(excepted));
-        log.info("actual data:\n{}", new GsonBuilder().setPrettyPrinting().create().toJson(actual));
-        SegmentItemsAssert.assertEquals(excepted.segmentItems(), actual.segmentItems());
-        log.info("{} assert successful.", "segment items");
+    public MeterAssertFailedException(AssertFailedException e, MeterId meterId) {
+        this.e = e;
+        this.meterId = meterId;
+    }
+
+    @Override
+    public String getCauseMessage() {
+        return String.format("MeterAssertFailedException:\nmeter id:%s\nreason:%s\n",
+            meterId,
+            e.getCauseMessage());
     }
 }
diff --git a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/element/GreatThanAssertor.java b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/exception/MeterItemNotFoundException.java
similarity index 52%
copy from validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/element/GreatThanAssertor.java
copy to validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/exception/MeterItemNotFoundException.java
index ca2fecd..d6055c4 100644
--- a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/element/GreatThanAssertor.java
+++ b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/exception/MeterItemNotFoundException.java
@@ -6,29 +6,28 @@
  * (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
+ *      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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
  */
 
-package org.apache.skywalking.plugin.test.agent.tool.validator.assertor.element;
+package org.apache.skywalking.plugin.test.agent.tool.validator.assertor.exception;
 
-import org.apache.skywalking.plugin.test.agent.tool.validator.assertor.exception.ValueAssertFailedException;
+import org.apache.skywalking.plugin.test.agent.tool.validator.exception.AssertFailedException;
 
-public class GreatThanAssertor extends ElementAssertor {
+public class MeterItemNotFoundException extends AssertFailedException {
+    private final String serviceName;
 
-    public GreatThanAssertor(String exceptedValue) {
-        super(exceptedValue);
+    public MeterItemNotFoundException(String serviceName) {
+        this.serviceName = serviceName;
     }
 
     @Override
-    public void assertValue(String desc, String actualValue) {
-        if (Long.parseLong(actualValue) <= Long.parseLong(exceptedValue)) {
-            throw new ValueAssertFailedException(desc, " gt " + exceptedValue, actualValue);
-        }
+    public String getCauseMessage() {
+        return String.format("MeterItemNotFoundException\nexpected: %s\nactual: %s", serviceName, "Not Found");
     }
 }
diff --git a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/DataAssert.java b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/exception/MeterNotFoundException.java
similarity index 52%
copy from validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/DataAssert.java
copy to validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/exception/MeterNotFoundException.java
index fff1a99..4947331 100644
--- a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/DataAssert.java
+++ b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/exception/MeterNotFoundException.java
@@ -6,28 +6,31 @@
  * (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
+ *      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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
  */
 
-package org.apache.skywalking.plugin.test.agent.tool.validator.assertor;
+package org.apache.skywalking.plugin.test.agent.tool.validator.assertor.exception;
 
-import com.google.gson.GsonBuilder;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.skywalking.plugin.test.agent.tool.validator.entity.Data;
+import org.apache.skywalking.plugin.test.agent.tool.validator.entity.Meter;
+import org.apache.skywalking.plugin.test.agent.tool.validator.exception.AssertFailedException;
 
-@Slf4j
-public class DataAssert {
+public class MeterNotFoundException extends AssertFailedException {
+    private Meter expectedMeter;
 
-    public static void assertEquals(Data excepted, Data actual) {
-        log.info("excepted data:\n{}", new GsonBuilder().setPrettyPrinting().create().toJson(excepted));
-        log.info("actual data:\n{}", new GsonBuilder().setPrettyPrinting().create().toJson(actual));
-        SegmentItemsAssert.assertEquals(excepted.segmentItems(), actual.segmentItems());
-        log.info("{} assert successful.", "segment items");
+    public MeterNotFoundException(Meter expectedMeter) {
+        this.expectedMeter = expectedMeter;
+    }
+
+    @Override
+    public String getCauseMessage() {
+        return String.format("MeterNotFoundException:\nexpected meter id:%sactual: %s",
+            expectedMeter.getMeterId(),
+            "Not Found");
     }
 }
diff --git a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/exception/MeterSizeNotEqualsException.java b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/exception/MeterSizeNotEqualsException.java
new file mode 100644
index 0000000..61c738c
--- /dev/null
+++ b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/assertor/exception/MeterSizeNotEqualsException.java
@@ -0,0 +1,38 @@
+/*
+ * 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.skywalking.plugin.test.agent.tool.validator.assertor.exception;
+
+import org.apache.skywalking.plugin.test.agent.tool.validator.exception.AssertFailedException;
+
+public class MeterSizeNotEqualsException extends AssertFailedException {
+    private final String serviceName;
+    private final String expected;
+    private final String actual;
+
+    public MeterSizeNotEqualsException(String serviceName, String expected, String actual) {
+        this.serviceName = serviceName;
+        this.expected = expected;
+        this.actual = actual;
+    }
+
+    @Override
+    public String getCauseMessage() {
+        return String.format(
+            "MeterSizeNotEqualsException:\t%s\nexpected:\t%s\nactual:\t\t%s\n", serviceName, expected, actual);
+    }
+}
diff --git a/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/ValidateData.java b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/entity/BucketAndValue.java
similarity index 52%
copy from mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/ValidateData.java
copy to validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/entity/BucketAndValue.java
index 12eb61d..6c27aae 100644
--- a/mock-collector/src/main/java/org/apache/skywalking/plugin/test/mockcollector/entity/ValidateData.java
+++ b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/entity/BucketAndValue.java
@@ -6,30 +6,34 @@
  * (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
+ *      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.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
  */
 
-package org.apache.skywalking.plugin.test.mockcollector.entity;
+package org.apache.skywalking.plugin.test.agent.tool.validator.entity;
 
-public class ValidateData {
-    public static ValidateData INSTANCE = new ValidateData();
-    private SegmentItems segmentItem;
+public class BucketAndValue {
+    private String bucket;
+    private String count;
 
-    private  ValidateData() {
-        segmentItem = new SegmentItems();
+    public String getBucket() {
+        return bucket;
     }
 
-    public synchronized SegmentItems getSegmentItem() {
-        return segmentItem;
+    public void setBucket(String bucket) {
+        this.bucket = bucket;
     }
 
-    public synchronized void clearData() {
-        INSTANCE.segmentItem = new SegmentItems();
+    public String getCount() {
+        return count;
     }
-}
+
+    public void setCount(String count) {
+        this.count = count;
+    }
+}
\ No newline at end of file
diff --git a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/entity/Data.java b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/entity/Data.java
index 79e0f4b..09ed7ee 100644
--- a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/entity/Data.java
+++ b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/entity/Data.java
@@ -17,18 +17,20 @@
 
 package org.apache.skywalking.plugin.test.agent.tool.validator.entity;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.util.List;
 import org.apache.skywalking.plugin.test.agent.tool.validator.exception.IllegalDataFileException;
 import org.yaml.snakeyaml.TypeDescription;
 import org.yaml.snakeyaml.Yaml;
 import org.yaml.snakeyaml.constructor.Constructor;
 import org.yaml.snakeyaml.representer.Representer;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.List;
+
 public interface Data {
     List<SegmentItem> segmentItems();
+    List<MeterItem> meterItems();
 
     class Loader {
         public static Data loadData(String fileName, File file) {
diff --git a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/entity/DataForRead.java b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/entity/DataForRead.java
index 8ddf94b..33142cf 100644
--- a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/entity/DataForRead.java
+++ b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/entity/DataForRead.java
@@ -22,6 +22,7 @@ import java.util.List;
 
 public class DataForRead implements Data {
     private List<SegmentItemForRead> segmentItems;
+    private List<MeterItem> meterItems;
 
     public List<SegmentItemForRead> getSegmentItems() {
         return segmentItems;
@@ -31,6 +32,14 @@ public class DataForRead implements Data {
         this.segmentItems = segmentItems;
     }
 
+    public List<MeterItem> getMeterItems() {
+        return meterItems;
+    }
+
+    public void setMeterItems(List<MeterItem> meterItems) {
+        this.meterItems = meterItems;
+    }
+
     @Override
     public List<SegmentItem> segmentItems() {
         if (this.segmentItems == null) {
@@ -40,4 +49,13 @@ public class DataForRead implements Data {
         return new ArrayList<>(this.segmentItems);
     }
 
+    @Override
+    public List<MeterItem> meterItems() {
+        if (this.meterItems == null) {
+            return null;
+        }
+
+        return new ArrayList<>(this.meterItems);
+    }
+
 }
diff --git a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/entity/Meter.java b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/entity/Meter.java
new file mode 100644
index 0000000..63c97f3
--- /dev/null
+++ b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/entity/Meter.java
@@ -0,0 +1,50 @@
+/*
+ * 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.skywalking.plugin.test.agent.tool.validator.entity;
+
+import java.util.List;
+
+public class Meter {
+    private MeterId meterId;
+    private String singleValue;
+    private List<BucketAndValue> histogram;
+
+    public MeterId getMeterId() {
+        return meterId;
+    }
+
+    public void setMeterId(MeterId meterId) {
+        this.meterId = meterId;
+    }
+
+    public String getSingleValue() {
+        return singleValue;
+    }
+
+    public void setSingleValue(String singleValue) {
+        this.singleValue = singleValue;
+    }
+
+    public List<BucketAndValue> getHistogram() {
+        return histogram;
+    }
+
+    public void setHistogram(List<BucketAndValue> histogram) {
+        this.histogram = histogram;
+    }
+}
diff --git a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/entity/MeterId.java b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/entity/MeterId.java
new file mode 100644
index 0000000..2fbd3f7
--- /dev/null
+++ b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/entity/MeterId.java
@@ -0,0 +1,115 @@
+/*
+ * 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.skywalking.plugin.test.agent.tool.validator.entity;
+
+import java.util.List;
+import java.util.Objects;
+
+public class MeterId {
+    private String name;
+    private List<Tag> tags;
+
+    /**
+     * Using name/value pair as the tag, also it will {@link Comparable} when we sort all of tags
+     */
+    public static class Tag implements Comparable<Tag> {
+        private String name;
+        private String value;
+
+        public String getName() {
+            return name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+
+        public String getValue() {
+            return value;
+        }
+
+        public void setValue(String value) {
+            this.value = value;
+        }
+
+        @Override
+        public int compareTo(Tag o) {
+            return this.name.compareTo(o.name);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            Tag tag = (Tag) o;
+            return Objects.equals(name, tag.name) &&
+                Objects.equals(value, tag.value);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(name, value);
+        }
+
+        @Override
+        public String toString() {
+            return "{" +
+                "name='" + name + '\'' +
+                ", value='" + value + '\'' +
+                '}';
+        }
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public List<Tag> getTags() {
+        return tags;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public void setTags(List<Tag> tags) {
+        this.tags = tags;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        MeterId meterId = (MeterId) o;
+        return Objects.equals(name, meterId.name) &&
+            Objects.equals(tags, meterId.tags);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(name, tags);
+    }
+
+    @Override
+    public String toString() {
+        return "MeterId{" +
+            "name='" + name + '\'' +
+            ", tags=" + tags +
+            '}';
+    }
+}
diff --git a/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/entity/MeterItem.java b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/entity/MeterItem.java
new file mode 100644
index 0000000..6c6e221
--- /dev/null
+++ b/validator/src/main/java/org/apache/skywalking/plugin/test/agent/tool/validator/entity/MeterItem.java
@@ -0,0 +1,57 @@
+/*
+ * 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.skywalking.plugin.test.agent.tool.validator.entity;
+
+import java.util.List;
+
+public class MeterItem {
+    private String serviceName;
+    private String meterSize;
+    private List<Meter> meters;
+
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    public void setServiceName(String serviceName) {
+        this.serviceName = serviceName;
+    }
+
+    public String getMeterSize() {
+        return meterSize;
+    }
+
+    public void setMeterSize(String meterSize) {
+        this.meterSize = meterSize;
+    }
+
+    public List<Meter> getMeters() {
+        return meters;
+    }
+
+    public void setMeters(List<Meter> meters) {
+        this.meters = meters;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder message = new StringBuilder(String.format("\nMeter Item[%s]", serviceName));
+        message.append(String.format(" - meter size:\t\t%s\n", meterSize));
+        return message.toString();
+    }
+}