You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2019/03/01 14:14:06 UTC

[incubator-skywalking] branch master updated: Envoy metrics receiver plugin protos (#2304)

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

wusheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-skywalking.git


The following commit(s) were added to refs/heads/master by this push:
     new b8a414e  Envoy metrics receiver plugin protos (#2304)
b8a414e is described below

commit b8a414edf5dc297d75860b8321a79e5df6e10cab
Author: Dhi Aurrahman <di...@tetrate.io>
AuthorDate: Fri Mar 1 21:13:59 2019 +0700

    Envoy metrics receiver plugin protos (#2304)
    
    * Add envoy metrics service protos
    
    This patch imports protos from envoyproxy/data-plane-api and
    prometheus/client_model to enable metrics service service feature in
    SkyWalking OAP.
    
    Signed-off-by: Dhi Aurrahman <di...@tetrate.io>
    
    * Add Envoy related docs
    
    Signed-off-by: Dhi Aurrahman <di...@tetrate.io>
    
    * Update the LICENSE to include new protos license
    
    From:
    - envoyproxy/data-plane-api
    - prometheus/client_model
    
    Signed-off-by: Dhi Aurrahman <di...@tetrate.io>
    
    * Add a complete config.yaml example
    
    Signed-off-by: Dhi Aurrahman <di...@tetrate.io>
    
    * Add note on Envoy dynamic config
    
    Signed-off-by: Dhi Aurrahman <di...@tetrate.io>
    
    * Add protoc-gen-validate license
    
    Signed-off-by: Dhi Aurrahman <di...@tetrate.io>
    
    * Add samples
    
    Signed-off-by: Dhi Aurrahman <di...@tetrate.io>
    
    * Make CI and license right.
    
    * Update README.md
    
    @dhi typo :P
    
    * Update README.md
    
    Another typo :P
    
    * Delete metrics.json
    
    metrics.json is included in identify.json and not be linked in document.
---
 LICENSE                                            |   4 +
 README.md                                          |  17 +-
 apm-dist/release-docs/LICENSE                      |   5 +-
 docs/en/setup/README.md                            |   5 +-
 docs/en/setup/envoy/README.md                      |  44 ++
 docs/en/setup/envoy/config.yaml                    |  76 ++
 docs/en/setup/envoy/identify.json                  | 695 +++++++++++++++++++
 .../envoy-metrics-receiver-plugin/pom.xml          |  76 ++
 .../src/main/proto/envoy/api/v2/core/base.proto    |  80 +++
 .../envoy/service/metrics/v2/metrics_service.proto |  43 ++
 .../src/main/proto/envoy/type/percent.proto        |  52 ++
 .../src/main/proto/gogoproto/gogo.proto            | 136 ++++
 .../proto/prometheus/client_model/metrics.proto    |  82 +++
 .../src/main/proto/validate/validate.proto         | 763 +++++++++++++++++++++
 oap-server/server-receiver-plugin/pom.xml          |   1 +
 pom.xml                                            |   4 +
 16 files changed, 2072 insertions(+), 11 deletions(-)

diff --git a/LICENSE b/LICENSE
index 7ab1aa1..945dc24 100644
--- a/LICENSE
+++ b/LICENSE
@@ -217,6 +217,10 @@ The text of each license is the standard Apache 2.0 license.
 
    proto files from istio/istio: https://github.com/istio/istio  Apache 2.0
    proto files from istio/api: https://github.com/istio/api      Apache 2.0
+   proto files from envoyproxy/data-plane-api: https://github.com/envoyproxy/data-plane-api  Apache 2.0
+   proto files from prometheus/client_model: https://github.com/prometheus/client_model Apache 2.0
+   proto files from lyft/protoc-gen-validate: https://github.com/lyft/protoc-gen-validate Apache 2.0
+   proto files from
 
 
 ========================================================================
diff --git a/README.md b/README.md
index 56dc7db..1eb53a2 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@ Apache SkyWalking
 
 <img src="http://skywalking.apache.org/assets/logo.svg" alt="Sky Walking logo" height="90px" align="right" />
 
-**SkyWalking**: an APM(application performance monitor) system, especially designed for 
+**SkyWalking**: an APM(application performance monitor) system, especially designed for
 microservices, cloud native and container-based (Docker, Kubernetes, Mesos) architectures.
 
 [![GitHub stars](https://img.shields.io/github/stars/apache/incubator-skywalking.svg?style=for-the-badge&label=Stars&logo=github)](https://github.com/apache/incubator-skywalking)
@@ -17,7 +17,7 @@ microservices, cloud native and container-based (Docker, Kubernetes, Mesos) arch
 
 # Abstract
 **SkyWalking** is an open source APM system, including monitoring, tracing, diagnosing capabilities for distributed system
-in Cloud Native architecture. 
+in Cloud Native architecture.
 The core features are following.
 
 - Service, service instance, endpoint metrics analysis
@@ -34,15 +34,16 @@ The core features are following.
 <img src="http://skywalking.apache.org/assets/frame.jpeg"/>
 
 SkyWalking supports to collect telemetry (traces and metrics) data from multiple sources
-and multiple formats, 
-including 
+and multiple formats,
+including
 1. Java, .NET Core, NodeJS and PHP auto-instrument agents in SkyWalking format
 1. Istio telemetry format
-1. Zipkin v1/v2 formats
+1. Zipkin v1/v2 format
+1. Envoy metrics format (the metric entries itself is prometheus client [metric family](https://github.com/prometheus/client_model/blob/fd36f4220a901265f90734c3183c5f0c91daa0b8/metrics.proto#L77))
 
 
 # Document
-- [6.x Documents](docs/README.md). 
+- [6.x Documents](docs/README.md).
 
 
 # Downloads
@@ -50,7 +51,7 @@ Please head to the [releases page](http://skywalking.apache.org/downloads/) to d
 
 
 # Code of conduct
-This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. 
+This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code.
 Please report unacceptable behavior to dev@skywalking.apache.org .
 
 # Live Demo
@@ -103,7 +104,7 @@ SkyWalking enriches the <a href="https://landscape.cncf.io/landscape=observabili
 </p>
 
 <p align="center">
-<a href="https://openapm.io"><img src="https://openapm.io/static/media/openapm_logo.svg" width="100"/></a> 
+<a href="https://openapm.io"><img src="https://openapm.io/static/media/openapm_logo.svg" width="100"/></a>
   <br/>Our project enriches the <a href="https://openapm.io">OpenAPM Landscape!</a>
 </p>
 
diff --git a/apm-dist/release-docs/LICENSE b/apm-dist/release-docs/LICENSE
index b1faa2b..29c56f3 100644
--- a/apm-dist/release-docs/LICENSE
+++ b/apm-dist/release-docs/LICENSE
@@ -307,6 +307,9 @@ The text of each license is the standard Apache 2.0 license.
     consul-client 1.2.6: https://github.com/rickfast/consul-client, Apache 2.0
     okhttp 3.9.0: https://github.com/square/okhttp, Apache 2.0
     prometheus client_java 0.6.0: https://github.com/prometheus/client_java, Apache 2.0
+    proto files from envoyproxy/data-plane-api: https://github.com/envoyproxy/data-plane-api  Apache 2.0
+    proto files from prometheus/client_model: https://github.com/prometheus/client_model Apache 2.0
+    proto files from lyft/protoc-gen-validate: https://github.com/lyft/protoc-gen-validate Apache 2.0
 
 ========================================================================
 MIT licenses
@@ -336,7 +339,7 @@ The text of each license is also included at licenses/LICENSE-[project].txt.
     Google: protobuf-java 3.4.0: https://github.com/google/protobuf/blob/master/java/pom.xml , BSD-3-Clause
     Google: protobuf-java-util 3.4.0: https://github.com/google/protobuf/blob/master/java/pom.xml , BSD-3-Clause
     reflectasm 1.11.3: https://github.com/EsotericSoftware/reflectasm , BSD-3-Clause
-    
+
     gogo-protobuf, proto files: https://github.com/gogo/protobuf  BSD-2-Clause
 
 ========================================================================
diff --git a/docs/en/setup/README.md b/docs/en/setup/README.md
index 4fa79a5..640e77c 100644
--- a/docs/en/setup/README.md
+++ b/docs/en/setup/README.md
@@ -8,7 +8,7 @@ Setup based on which kind of probes are you going to use. If you don't understan
 ## Download official releases
 - Backend, UI and Java agent are Apache official release, you could find them at [Apache SkyWalking DOWNLOAD page](http://skywalking.apache.org/downloads/).
 
-## Language agents in Service 
+## Language agents in Service
 
 - [Java agent](service-agent/java-agent/README.md). Introduce how to install java agent to your service, without change any codes.
 
@@ -21,7 +21,8 @@ You could go to their project repositories to find out the releases and how to u
 ## On Service Mesh
   - Istio
     - [SkyWalking on Istio](istio/README.md). Introduce how to use Istio Mixer bypass Adapter to work with SkyWalking.
-    
+  - [Envoy Proxy](https://www.envoyproxy.io/)
+    - [Sending metrics to Skywalking from Envoy](envoy/README.md). How to send metrics from Envoy to SkyWalking using [Metrics service](https://www.envoyproxy.io/docs/envoy/latest/api-v2/config/metrics/v2/metrics_service.proto.html).
 
 ## Setup backend
 Follow [backend and UI setup document](backend/backend-ui-setup.md) to understand and config the backend for different
diff --git a/docs/en/setup/envoy/README.md b/docs/en/setup/envoy/README.md
new file mode 100644
index 0000000..b2b598f
--- /dev/null
+++ b/docs/en/setup/envoy/README.md
@@ -0,0 +1,44 @@
+# Configuring Envoy to send metrics to SkyWalking
+
+In order to let Envoy to send metrics to SkyWalking, we need to feed Envoy with a configuration which contains `stats_sinks` that includes `envoy.metrics_service`.
+This `envoy.metrics_service` should be configured as a [`config.grpc_service`](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/core/grpc_service.proto#envoy-api-msg-core-grpcservice) entry.
+
+The interesting parts of the config is shown in the config below:
+
+```yaml
+stats_sinks:
+  - name: envoy.metrics_service
+    config:
+      grpc_service:
+        # Note: we can use google_grpc implementation as well.
+        envoy_grpc:
+          cluster_name: skywalking_service
+
+static_resources:
+  ...
+  clusters:
+  - name: skywalking_service
+    connect_timeout: 5s
+    type: LOGICAL_DNS
+    http2_protocol_options: {}
+    dns_lookup_family: V4_ONLY
+    lb_policy: ROUND_ROBIN
+    load_assignment:
+      cluster_name: service_stats
+      endpoints:
+      - lb_endpoints:
+        - endpoint:
+            address:
+              socket_address:
+                address: skywalking
+                # This is the port where SkyWalking serving the Envoy Metrics Service gRPC stream.
+                port_value: 11800
+```
+
+A more complete static configuration, can be observed here [config.yaml].
+
+Note that Envoy can also be configured dynamically through [xDS Protocol](https://github.com/envoyproxy/data-plane-api/blob/master/XDS_PROTOCOL.md).
+
+# Metrics data
+
+Some of the Envoy statitics are listed in this [list](https://www.envoyproxy.io/docs/envoy/latest/configuration/statistics). While a sample data that contains idetifier can be found [here](identify.json), while the metrics only can be observed [here](https://www.envoyproxy.io/docs/envoy/latest/configuration/statistics).
diff --git a/docs/en/setup/envoy/config.yaml b/docs/en/setup/envoy/config.yaml
new file mode 100644
index 0000000..5095b1a
--- /dev/null
+++ b/docs/en/setup/envoy/config.yaml
@@ -0,0 +1,76 @@
+admin:
+  access_log_path: /tmp/admin_access.log
+  address:
+    socket_address:
+      protocol: TCP
+      address: 127.0.0.1
+      port_value: 9901
+stats_sinks:
+  - name: envoy.metrics_service
+    config:
+      grpc_service:
+        envoy_grpc:
+          cluster_name: service_skywalking
+
+static_resources:
+  listeners:
+  - name: listener_0
+    address:
+      socket_address:
+        protocol: TCP
+        address: 0.0.0.0
+        port_value: 10000
+    filter_chains:
+    - filters:
+      - name: envoy.http_connection_manager
+        typed_config:
+          "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager
+          stat_prefix: ingress_http
+          route_config:
+            name: local_route
+            virtual_hosts:
+            - name: local_service
+              domains: ["*"]
+              routes:
+              - match:
+                  prefix: "/"
+                route:
+                  host_rewrite: www.google.com
+                  cluster: service_google
+          http_filters:
+          - name: envoy.router
+  clusters:
+  - name: service_skywalking
+    connect_timeout: 5s
+    type: LOGICAL_DNS
+    http2_protocol_options: {}
+    # Comment out the following line to test on v6 networks
+    dns_lookup_family: V4_ONLY
+    lb_policy: ROUND_ROBIN
+    load_assignment:
+      cluster_name: service_skywalking
+      endpoints:
+      - lb_endpoints:
+        - endpoint:
+            address:
+              socket_address:
+                address: skywalking
+                port_value: 11800
+
+  - name: service_google
+    connect_timeout: 5s
+    type: LOGICAL_DNS
+    # Comment out the following line to test on v6 networks
+    dns_lookup_family: V4_ONLY
+    lb_policy: ROUND_ROBIN
+    load_assignment:
+      cluster_name: service_google
+      endpoints:
+      - lb_endpoints:
+        - endpoint:
+            address:
+              socket_address:
+                address: www.google.com
+                port_value: 443
+    tls_context:
+      sni: www.google.com
diff --git a/docs/en/setup/envoy/identify.json b/docs/en/setup/envoy/identify.json
new file mode 100644
index 0000000..f439824
--- /dev/null
+++ b/docs/en/setup/envoy/identify.json
@@ -0,0 +1,695 @@
+{
+  "identifier": {
+    "node": {
+      "buildVersion": "e8ecf08f92941c4a2a892efc9b7dd672cfbb3fe8/1.10.0-dev/Modified/DEBUG/BoringSSL"
+    }
+  },
+  "envoyMetrics": [
+    {
+      "name": "cluster.service_google.membership_change",
+      "metric": [
+        {
+          "counter": {
+            "value": 1
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_google.update_attempt",
+      "metric": [
+        {
+          "counter": {
+            "value": 60
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_google.update_success",
+      "metric": [
+        {
+          "counter": {
+            "value": 60
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.upstream_rq_pending_total",
+      "metric": [
+        {
+          "counter": {
+            "value": 59
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.internal.upstream_rq_completed",
+      "metric": [
+        {
+          "counter": {
+            "value": 59
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.internal.upstream_rq_5xx",
+      "metric": [
+        {
+          "counter": {
+            "value": 59
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.upstream_rq_503",
+      "metric": [
+        {
+          "counter": {
+            "value": 59
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.upstream_rq_5xx",
+      "metric": [
+        {
+          "counter": {
+            "value": 59
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.update_attempt",
+      "metric": [
+        {
+          "counter": {
+            "value": 61
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.upstream_cx_tx_bytes_total",
+      "metric": [
+        {
+          "counter": {
+            "value": 2080
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.upstream_cx_destroy_remote_with_active_rq",
+      "metric": [
+        {
+          "counter": {
+            "value": 1
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.upstream_cx_total",
+      "metric": [
+        {
+          "counter": {
+            "value": 59
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.membership_change",
+      "metric": [
+        {
+          "counter": {
+            "value": 1
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.upstream_cx_rx_bytes_total",
+      "metric": [
+        {
+          "counter": {
+            "value": 48
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.upstream_cx_destroy_with_active_rq",
+      "metric": [
+        {
+          "counter": {
+            "value": 1
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.internal.upstream_rq_503",
+      "metric": [
+        {
+          "counter": {
+            "value": 59
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.upstream_rq_completed",
+      "metric": [
+        {
+          "counter": {
+            "value": 59
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.update_success",
+      "metric": [
+        {
+          "counter": {
+            "value": 61
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.upstream_cx_http2_total",
+      "metric": [
+        {
+          "counter": {
+            "value": 59
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.upstream_rq_total",
+      "metric": [
+        {
+          "counter": {
+            "value": 1
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.upstream_rq_pending_failure_eject",
+      "metric": [
+        {
+          "counter": {
+            "value": 59
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.upstream_cx_connect_fail",
+      "metric": [
+        {
+          "counter": {
+            "value": 58
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "http.async-client.rq_total",
+      "metric": [
+        {
+          "counter": {
+            "value": 59
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "listener_manager.listener_added",
+      "metric": [
+        {
+          "counter": {
+            "value": 1
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "listener_manager.listener_create_success",
+      "metric": [
+        {
+          "counter": {
+            "value": 4
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster_manager.cluster_added",
+      "metric": [
+        {
+          "counter": {
+            "value": 2
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "runtime.deprecated_feature_use",
+      "metric": [
+        {
+          "counter": {
+            "value": 18
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_google.membership_degraded",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {},
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_google.membership_healthy",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {
+            "value": 1
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_google.membership_total",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {
+            "value": 1
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.membership_total",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {
+            "value": 1
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.membership_healthy",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {
+            "value": 1
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.membership_degraded",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {},
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.upstream_rq_active",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {},
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.upstream_rq_pending_active",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {},
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.circuit_breakers.default.rq_open",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {},
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.upstream_cx_active",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {},
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.circuit_breakers.default.rq_pending_open",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {},
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.upstream_cx_rx_bytes_buffered",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {},
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "server.parent_connections",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {},
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "server.total_connections",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {},
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "server.concurrency",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {
+            "value": 4
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "server.memory_allocated",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {
+            "value": 4238160
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "server.hot_restart_epoch",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {},
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "server.days_until_first_cert_expiring",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {
+            "value": 2147483647
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "listener_manager.total_listeners_active",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {
+            "value": 1
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster_manager.active_clusters",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {
+            "value": 2
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "listener_manager.total_listeners_warming",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {},
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster_manager.warming_clusters",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {},
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "server.version",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {
+            "value": 15265008
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "server.uptime",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {
+            "value": 301
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "server.live",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {
+            "value": 1
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "server.memory_heap_size",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {
+            "value": 5242880
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "runtime.num_keys",
+      "type": "GAUGE",
+      "metric": [
+        {
+          "gauge": {},
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.upstream_cx_length_ms",
+      "type": "SUMMARY",
+      "metric": [
+        {
+          "summary": {
+            "quantile": [
+              {},
+              {
+                "quantile": 0.25
+              },
+              {
+                "quantile": 0.5
+              },
+              {
+                "quantile": 0.75
+              },
+              {
+                "quantile": 0.9
+              },
+              {
+                "quantile": 0.95
+              },
+              {
+                "quantile": 0.99
+              },
+              {
+                "quantile": 0.995
+              },
+              {
+                "quantile": 0.999
+              },
+              {
+                "quantile": 1
+              }
+            ]
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    },
+    {
+      "name": "cluster.service_stats.upstream_cx_connect_ms",
+      "type": "SUMMARY",
+      "metric": [
+        {
+          "summary": {
+            "quantile": [
+              {
+                "value": "NaN"
+              },
+              {
+                "quantile": 0.25,
+                "value": "NaN"
+              },
+              {
+                "quantile": 0.5,
+                "value": "NaN"
+              },
+              {
+                "quantile": 0.75,
+                "value": "NaN"
+              },
+              {
+                "quantile": 0.9,
+                "value": "NaN"
+              },
+              {
+                "quantile": 0.95,
+                "value": "NaN"
+              },
+              {
+                "quantile": 0.99,
+                "value": "NaN"
+              },
+              {
+                "quantile": 0.995,
+                "value": "NaN"
+              },
+              {
+                "quantile": 0.999,
+                "value": "NaN"
+              },
+              {
+                "quantile": 1,
+                "value": "NaN"
+              }
+            ]
+          },
+          "timestampMs": "1551412080125"
+        }
+      ]
+    }
+  ]
+}
diff --git a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/pom.xml b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/pom.xml
new file mode 100644
index 0000000..2baf0cf
--- /dev/null
+++ b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/pom.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>server-receiver-plugin</artifactId>
+        <groupId>org.apache.skywalking</groupId>
+        <version>6.1.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>envoy-metrics-receiver-plugin</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>skywalking-mesh-receiver-plugin</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <version>2.4.3</version>
+                <configuration>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.xolstice.maven.plugins</groupId>
+                <artifactId>protobuf-maven-plugin</artifactId>
+                <version>0.5.0</version>
+                <configuration>
+                    <!--
+                      The version of protoc must match protobuf-java. If you don't depend on
+                      protobuf-java directly, you will be transitively depending on the
+                      protobuf-java version that grpc depends on.
+                    -->
+                    <protocArtifact>com.google.protobuf:protoc:3.3.0:exe:${os.detected.classifier}
+                    </protocArtifact>
+                    <pluginId>grpc-java</pluginId>
+                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.8.0:exe:${os.detected.classifier}
+                    </pluginArtifact>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>compile</goal>
+                            <goal>compile-custom</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/proto/envoy/api/v2/core/base.proto b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/proto/envoy/api/v2/core/base.proto
new file mode 100644
index 0000000..3be09cd
--- /dev/null
+++ b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/proto/envoy/api/v2/core/base.proto
@@ -0,0 +1,80 @@
+syntax = "proto3";
+
+package envoy.api.v2.core;
+
+option java_outer_classname = "BaseProto";
+option java_multiple_files = true;
+option java_package = "io.envoyproxy.envoy.api.v2.core";
+option go_package = "core";
+
+import "google/protobuf/any.proto";
+import "google/protobuf/struct.proto";
+import "google/protobuf/wrappers.proto";
+
+import "validate/validate.proto";
+import "gogoproto/gogo.proto";
+
+import "envoy/type/percent.proto";
+
+option (gogoproto.equal_all) = true;
+
+// [#protodoc-title: Common types]
+
+// Identifies location of where either Envoy runs or where upstream hosts run.
+message Locality {
+  // Region this :ref:`zone <envoy_api_field_core.Locality.zone>` belongs to.
+  string region = 1;
+
+  // Defines the local service zone where Envoy is running. Though optional, it
+  // should be set if discovery service routing is used and the discovery
+  // service exposes :ref:`zone data <envoy_api_field_endpoint.LocalityLbEndpoints.locality>`,
+  // either in this message or via :option:`--service-zone`. The meaning of zone
+  // is context dependent, e.g. `Availability Zone (AZ)
+  // <https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html>`_
+  // on AWS, `Zone <https://cloud.google.com/compute/docs/regions-zones/>`_ on
+  // GCP, etc.
+  string zone = 2;
+
+  // When used for locality of upstream hosts, this field further splits zone
+  // into smaller chunks of sub-zones so they can be load balanced
+  // independently.
+  string sub_zone = 3;
+}
+
+// Identifies a specific Envoy instance. The node identifier is presented to the
+// management server, which may use this identifier to distinguish per Envoy
+// configuration for serving.
+message Node {
+  // An opaque node identifier for the Envoy node. This also provides the local
+  // service node name. It should be set if any of the following features are
+  // used: :ref:`statsd <arch_overview_statistics>`, :ref:`CDS
+  // <config_cluster_manager_cds>`, and :ref:`HTTP tracing
+  // <arch_overview_tracing>`, either in this message or via
+  // :option:`--service-node`.
+  string id = 1;
+
+  // Defines the local service cluster name where Envoy is running. Though
+  // optional, it should be set if any of the following features are used:
+  // :ref:`statsd <arch_overview_statistics>`, :ref:`health check cluster
+  // verification <envoy_api_field_core.HealthCheck.HttpHealthCheck.service_name>`,
+  // :ref:`runtime override directory <envoy_api_msg_config.bootstrap.v2.Runtime>`,
+  // :ref:`user agent addition
+  // <envoy_api_field_config.filter.network.http_connection_manager.v2.HttpConnectionManager.add_user_agent>`,
+  // :ref:`HTTP global rate limiting <config_http_filters_rate_limit>`,
+  // :ref:`CDS <config_cluster_manager_cds>`, and :ref:`HTTP tracing
+  // <arch_overview_tracing>`, either in this message or via
+  // :option:`--service-cluster`.
+  string cluster = 2;
+
+  // Opaque metadata extending the node identifier. Envoy will pass this
+  // directly to the management server.
+  google.protobuf.Struct metadata = 3;
+
+  // Locality specifying where the Envoy instance is running.
+  Locality locality = 4;
+
+  // This is motivated by informing a management server during canary which
+  // version of Envoy is being tested in a heterogeneous fleet. This will be set
+  // by Envoy in management server RPCs.
+  string build_version = 5;
+}
diff --git a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/proto/envoy/service/metrics/v2/metrics_service.proto b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/proto/envoy/service/metrics/v2/metrics_service.proto
new file mode 100644
index 0000000..75f8ee3
--- /dev/null
+++ b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/proto/envoy/service/metrics/v2/metrics_service.proto
@@ -0,0 +1,43 @@
+syntax = "proto3";
+
+package envoy.service.metrics.v2;
+
+option java_outer_classname = "MetricsServiceProto";
+option java_multiple_files = true;
+option java_package = "io.envoyproxy.envoy.service.metrics.v2";
+option go_package = "v2";
+option java_generic_services = true;
+
+import "envoy/api/v2/core/base.proto";
+
+// This line is different from the definition in https://github.com/envoyproxy/data-plane-api to let
+// the dependency structure clearer.
+import "prometheus/client_model/metrics.proto";
+
+import "validate/validate.proto";
+
+// Service for streaming metrics to server that consumes the metrics data. It uses Prometheus metric
+// data model as a standard to represent metrics information.
+service MetricsService {
+  // Envoy will connect and send StreamMetricsMessage messages forever. It does not expect any
+  // response to be sent as nothing would be done in the case of failure.
+  rpc StreamMetrics(stream StreamMetricsMessage) returns (StreamMetricsResponse) {
+  }
+}
+
+message StreamMetricsResponse {
+}
+
+message StreamMetricsMessage {
+  message Identifier {
+    // The node sending metrics over the stream.
+    envoy.api.v2.core.Node node = 1 [(validate.rules).message.required = true];
+  }
+
+  // Identifier data effectively is a structured metadata. As a performance optimization this will
+  // only be sent in the first message on the stream.
+  Identifier identifier = 1;
+
+  // A list of metric entries
+  repeated io.prometheus.client.MetricFamily envoy_metrics = 2;
+}
diff --git a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/proto/envoy/type/percent.proto b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/proto/envoy/type/percent.proto
new file mode 100644
index 0000000..551e93b
--- /dev/null
+++ b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/proto/envoy/type/percent.proto
@@ -0,0 +1,52 @@
+syntax = "proto3";
+
+package envoy.type;
+
+option java_outer_classname = "PercentProto";
+option java_multiple_files = true;
+option java_package = "io.envoyproxy.envoy.type";
+
+import "validate/validate.proto";
+import "gogoproto/gogo.proto";
+
+option (gogoproto.equal_all) = true;
+
+// [#protodoc-title: Percent]
+
+// Identifies a percentage, in the range [0.0, 100.0].
+message Percent {
+  double value = 1 [(validate.rules).double = {gte: 0, lte: 100}];
+}
+
+// A fractional percentage is used in cases in which for performance reasons performing floating
+// point to integer conversions during randomness calculations is undesirable. The message includes
+// both a numerator and denominator that together determine the final fractional value.
+//
+// * **Example**: 1/100 = 1%.
+// * **Example**: 3/10000 = 0.03%.
+message FractionalPercent {
+  // Specifies the numerator. Defaults to 0.
+  uint32 numerator = 1;
+
+  // Fraction percentages support several fixed denominator values.
+  enum DenominatorType {
+    // 100.
+    //
+    // **Example**: 1/100 = 1%.
+    HUNDRED = 0;
+
+    // 10,000.
+    //
+    // **Example**: 1/10000 = 0.01%.
+    TEN_THOUSAND = 1;
+
+    // 1,000,000.
+    //
+    // **Example**: 1/1000000 = 0.0001%.
+    MILLION = 2;
+  }
+
+  // Specifies the denominator. If the denominator specified is less than the numerator, the final
+  // fractional percentage is capped at 1 (100%).
+  DenominatorType denominator = 2 [(validate.rules).enum.defined_only = true];
+}
diff --git a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/proto/gogoproto/gogo.proto b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/proto/gogoproto/gogo.proto
new file mode 100644
index 0000000..ceb5f3c
--- /dev/null
+++ b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/proto/gogoproto/gogo.proto
@@ -0,0 +1,136 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+package gogoproto;
+
+import "google/protobuf/descriptor.proto";
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "GoGoProtos";
+option go_package = "github.com/gogo/protobuf/gogoproto";
+
+extend google.protobuf.EnumOptions {
+	optional bool goproto_enum_prefix = 62001;
+	optional bool goproto_enum_stringer = 62021;
+	optional bool enum_stringer = 62022;
+	optional string enum_customname = 62023;
+	optional bool enumdecl = 62024;
+}
+
+extend google.protobuf.EnumValueOptions {
+	optional string enumvalue_customname = 66001;
+}
+
+extend google.protobuf.FileOptions {
+	optional bool goproto_getters_all = 63001;
+	optional bool goproto_enum_prefix_all = 63002;
+	optional bool goproto_stringer_all = 63003;
+	optional bool verbose_equal_all = 63004;
+	optional bool face_all = 63005;
+	optional bool gostring_all = 63006;
+	optional bool populate_all = 63007;
+	optional bool stringer_all = 63008;
+	optional bool onlyone_all = 63009;
+
+	optional bool equal_all = 63013;
+	optional bool description_all = 63014;
+	optional bool testgen_all = 63015;
+	optional bool benchgen_all = 63016;
+	optional bool marshaler_all = 63017;
+	optional bool unmarshaler_all = 63018;
+	optional bool stable_marshaler_all = 63019;
+
+	optional bool sizer_all = 63020;
+
+	optional bool goproto_enum_stringer_all = 63021;
+	optional bool enum_stringer_all = 63022;
+
+	optional bool unsafe_marshaler_all = 63023;
+	optional bool unsafe_unmarshaler_all = 63024;
+
+	optional bool goproto_extensions_map_all = 63025;
+	optional bool goproto_unrecognized_all = 63026;
+	optional bool gogoproto_import = 63027;
+	optional bool protosizer_all = 63028;
+	optional bool compare_all = 63029;
+	optional bool typedecl_all = 63030;
+	optional bool enumdecl_all = 63031;
+
+	optional bool goproto_registration = 63032;
+	optional bool messagename_all = 63033;
+}
+
+extend google.protobuf.MessageOptions {
+	optional bool goproto_getters = 64001;
+	optional bool goproto_stringer = 64003;
+	optional bool verbose_equal = 64004;
+	optional bool face = 64005;
+	optional bool gostring = 64006;
+	optional bool populate = 64007;
+	optional bool stringer = 67008;
+	optional bool onlyone = 64009;
+
+	optional bool equal = 64013;
+	optional bool description = 64014;
+	optional bool testgen = 64015;
+	optional bool benchgen = 64016;
+	optional bool marshaler = 64017;
+	optional bool unmarshaler = 64018;
+	optional bool stable_marshaler = 64019;
+
+	optional bool sizer = 64020;
+
+	optional bool unsafe_marshaler = 64023;
+	optional bool unsafe_unmarshaler = 64024;
+
+	optional bool goproto_extensions_map = 64025;
+	optional bool goproto_unrecognized = 64026;
+
+	optional bool protosizer = 64028;
+	optional bool compare = 64029;
+
+	optional bool typedecl = 64030;
+
+	optional bool messagename = 64033;
+}
+
+extend google.protobuf.FieldOptions {
+	optional bool nullable = 65001;
+	optional bool embed = 65002;
+	optional string customtype = 65003;
+	optional string customname = 65004;
+	optional string jsontag = 65005;
+	optional string moretags = 65006;
+	optional string casttype = 65007;
+	optional string castkey = 65008;
+	optional string castvalue = 65009;
+
+	optional bool stdtime = 65010;
+	optional bool stdduration = 65011;
+}
diff --git a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/proto/prometheus/client_model/metrics.proto b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/proto/prometheus/client_model/metrics.proto
new file mode 100644
index 0000000..31633b3
--- /dev/null
+++ b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/proto/prometheus/client_model/metrics.proto
@@ -0,0 +1,82 @@
+// Copyright 2013 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto2";
+
+package io.prometheus.client;
+option java_package = "io.prometheus.client";
+option go_package = "github.com/prometheus/client_model/go;io_prometheus_client";
+
+message LabelPair {
+  optional string name  = 1;
+  optional string value = 2;
+}
+
+enum MetricType {
+  COUNTER    = 0;
+  GAUGE      = 1;
+  SUMMARY    = 2;
+  UNTYPED    = 3;
+  HISTOGRAM  = 4;
+}
+
+message Gauge {
+  optional double value = 1;
+}
+
+message Counter {
+  optional double value = 1;
+}
+
+message Quantile {
+  optional double quantile = 1;
+  optional double value    = 2;
+}
+
+message Summary {
+  optional uint64   sample_count = 1;
+  optional double   sample_sum   = 2;
+  repeated Quantile quantile     = 3;
+}
+
+message Untyped {
+  optional double value = 1;
+}
+
+message Histogram {
+  optional uint64 sample_count = 1;
+  optional double sample_sum   = 2;
+  repeated Bucket bucket       = 3; // Ordered in increasing order of upper_bound, +Inf bucket is optional.
+}
+
+message Bucket {
+  optional uint64 cumulative_count = 1; // Cumulative in increasing order.
+  optional double upper_bound = 2;      // Inclusive.
+}
+
+message Metric {
+  repeated LabelPair label        = 1;
+  optional Gauge     gauge        = 2;
+  optional Counter   counter      = 3;
+  optional Summary   summary      = 4;
+  optional Untyped   untyped      = 5;
+  optional Histogram histogram    = 7;
+  optional int64     timestamp_ms = 6;
+}
+
+message MetricFamily {
+  optional string     name   = 1;
+  optional string     help   = 2;
+  optional MetricType type   = 3;
+  repeated Metric     metric = 4;
+}
diff --git a/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/proto/validate/validate.proto b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/proto/validate/validate.proto
new file mode 100644
index 0000000..1c5e04a
--- /dev/null
+++ b/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/proto/validate/validate.proto
@@ -0,0 +1,763 @@
+syntax = "proto2";
+package validate;
+
+option go_package = "github.com/lyft/protoc-gen-validate/validate";
+option java_package = "com.lyft.pgv.validate";
+
+import "google/protobuf/descriptor.proto";
+import "google/protobuf/duration.proto";
+import "google/protobuf/timestamp.proto";
+
+// Validation rules applied at the message level
+extend google.protobuf.MessageOptions {
+    // Disabled nullifies any validation rules for this message, including any
+    // message fields associated with it that do support validation.
+    optional bool disabled = 919191;
+}
+
+// Validation rules applied at the oneof level
+extend google.protobuf.OneofOptions {
+    // Required ensures that exactly one the field options in a oneof is set;
+    // validation fails if no fields in the oneof are set.
+    optional bool required = 919191;
+}
+
+// Validation rules applied at the field level
+extend google.protobuf.FieldOptions {
+    // Rules specify the validations to be performed on this field. By default,
+    // no validation is performed against a field.
+    optional FieldRules rules = 919191;
+}
+
+// FieldRules encapsulates the rules for each type of field. Depending on the
+// field, the correct set should be used to ensure proper validations.
+message FieldRules {
+    oneof type {
+        // Scalar Field Types
+        FloatRules    float    = 1;
+        DoubleRules   double   = 2;
+        Int32Rules    int32    = 3;
+        Int64Rules    int64    = 4;
+        UInt32Rules   uint32   = 5;
+        UInt64Rules   uint64   = 6;
+        SInt32Rules   sint32   = 7;
+        SInt64Rules   sint64   = 8;
+        Fixed32Rules  fixed32  = 9;
+        Fixed64Rules  fixed64  = 10;
+        SFixed32Rules sfixed32 = 11;
+        SFixed64Rules sfixed64 = 12;
+        BoolRules     bool     = 13;
+        StringRules   string   = 14;
+        BytesRules    bytes    = 15;
+
+        // Complex Field Types
+        EnumRules     enum     = 16;
+        MessageRules  message  = 17;
+        RepeatedRules repeated = 18;
+        MapRules      map      = 19;
+
+        // Well-Known Field Types
+        AnyRules       any       = 20;
+        DurationRules  duration  = 21;
+        TimestampRules timestamp = 22;
+    }
+}
+
+// FloatRules describes the constraints applied to `float` values
+message FloatRules {
+    // Const specifies that this field must be exactly the specified value
+    optional float const = 1;
+
+    // Lt specifies that this field must be less than the specified value,
+    // exclusive
+    optional float lt = 2;
+
+    // Lte specifies that this field must be less than or equal to the
+    // specified value, inclusive
+    optional float lte = 3;
+
+    // Gt specifies that this field must be greater than the specified value,
+    // exclusive. If the value of Gt is larger than a specified Lt or Lte, the
+    // range is reversed.
+    optional float gt = 4;
+
+    // Gte specifies that this field must be greater than or equal to the
+    // specified value, inclusive. If the value of Gte is larger than a
+    // specified Lt or Lte, the range is reversed.
+    optional float gte = 5;
+
+    // In specifies that this field must be equal to one of the specified
+    // values
+    repeated float in = 6;
+
+    // NotIn specifies that this field cannot be equal to one of the specified
+    // values
+    repeated float not_in = 7;
+}
+
+// DoubleRules describes the constraints applied to `double` values
+message DoubleRules {
+    // Const specifies that this field must be exactly the specified value
+    optional double const = 1;
+
+    // Lt specifies that this field must be less than the specified value,
+    // exclusive
+    optional double lt = 2;
+
+    // Lte specifies that this field must be less than or equal to the
+    // specified value, inclusive
+    optional double lte = 3;
+
+    // Gt specifies that this field must be greater than the specified value,
+    // exclusive. If the value of Gt is larger than a specified Lt or Lte, the
+    // range is reversed.
+    optional double gt = 4;
+
+    // Gte specifies that this field must be greater than or equal to the
+    // specified value, inclusive. If the value of Gte is larger than a
+    // specified Lt or Lte, the range is reversed.
+    optional double gte = 5;
+
+    // In specifies that this field must be equal to one of the specified
+    // values
+    repeated double in = 6;
+
+    // NotIn specifies that this field cannot be equal to one of the specified
+    // values
+    repeated double not_in = 7;
+}
+
+// Int32Rules describes the constraints applied to `int32` values
+message Int32Rules {
+    // Const specifies that this field must be exactly the specified value
+    optional int32 const = 1;
+
+    // Lt specifies that this field must be less than the specified value,
+    // exclusive
+    optional int32 lt = 2;
+
+    // Lte specifies that this field must be less than or equal to the
+    // specified value, inclusive
+    optional int32 lte = 3;
+
+    // Gt specifies that this field must be greater than the specified value,
+    // exclusive. If the value of Gt is larger than a specified Lt or Lte, the
+    // range is reversed.
+    optional int32 gt = 4;
+
+    // Gte specifies that this field must be greater than or equal to the
+    // specified value, inclusive. If the value of Gte is larger than a
+    // specified Lt or Lte, the range is reversed.
+    optional int32 gte = 5;
+
+    // In specifies that this field must be equal to one of the specified
+    // values
+    repeated int32 in = 6;
+
+    // NotIn specifies that this field cannot be equal to one of the specified
+    // values
+    repeated int32 not_in = 7;
+}
+
+// Int64Rules describes the constraints applied to `int64` values
+message Int64Rules {
+    // Const specifies that this field must be exactly the specified value
+    optional int64 const = 1;
+
+    // Lt specifies that this field must be less than the specified value,
+    // exclusive
+    optional int64 lt = 2;
+
+    // Lte specifies that this field must be less than or equal to the
+    // specified value, inclusive
+    optional int64 lte = 3;
+
+    // Gt specifies that this field must be greater than the specified value,
+    // exclusive. If the value of Gt is larger than a specified Lt or Lte, the
+    // range is reversed.
+    optional int64 gt = 4;
+
+    // Gte specifies that this field must be greater than or equal to the
+    // specified value, inclusive. If the value of Gte is larger than a
+    // specified Lt or Lte, the range is reversed.
+    optional int64 gte = 5;
+
+    // In specifies that this field must be equal to one of the specified
+    // values
+    repeated int64 in = 6;
+
+    // NotIn specifies that this field cannot be equal to one of the specified
+    // values
+    repeated int64 not_in = 7;
+}
+
+// UInt32Rules describes the constraints applied to `uint32` values
+message UInt32Rules {
+    // Const specifies that this field must be exactly the specified value
+    optional uint32 const = 1;
+
+    // Lt specifies that this field must be less than the specified value,
+    // exclusive
+    optional uint32 lt = 2;
+
+    // Lte specifies that this field must be less than or equal to the
+    // specified value, inclusive
+    optional uint32 lte = 3;
+
+    // Gt specifies that this field must be greater than the specified value,
+    // exclusive. If the value of Gt is larger than a specified Lt or Lte, the
+    // range is reversed.
+    optional uint32 gt = 4;
+
+    // Gte specifies that this field must be greater than or equal to the
+    // specified value, inclusive. If the value of Gte is larger than a
+    // specified Lt or Lte, the range is reversed.
+    optional uint32 gte = 5;
+
+    // In specifies that this field must be equal to one of the specified
+    // values
+    repeated uint32 in = 6;
+
+    // NotIn specifies that this field cannot be equal to one of the specified
+    // values
+    repeated uint32 not_in = 7;
+}
+
+// UInt64Rules describes the constraints applied to `uint64` values
+message UInt64Rules {
+    // Const specifies that this field must be exactly the specified value
+    optional uint64 const = 1;
+
+    // Lt specifies that this field must be less than the specified value,
+    // exclusive
+    optional uint64 lt = 2;
+
+    // Lte specifies that this field must be less than or equal to the
+    // specified value, inclusive
+    optional uint64 lte = 3;
+
+    // Gt specifies that this field must be greater than the specified value,
+    // exclusive. If the value of Gt is larger than a specified Lt or Lte, the
+    // range is reversed.
+    optional uint64 gt = 4;
+
+    // Gte specifies that this field must be greater than or equal to the
+    // specified value, inclusive. If the value of Gte is larger than a
+    // specified Lt or Lte, the range is reversed.
+    optional uint64 gte = 5;
+
+    // In specifies that this field must be equal to one of the specified
+    // values
+    repeated uint64 in = 6;
+
+    // NotIn specifies that this field cannot be equal to one of the specified
+    // values
+    repeated uint64 not_in = 7;
+}
+
+// SInt32Rules describes the constraints applied to `sint32` values
+message SInt32Rules {
+    // Const specifies that this field must be exactly the specified value
+    optional sint32 const = 1;
+
+    // Lt specifies that this field must be less than the specified value,
+    // exclusive
+    optional sint32 lt = 2;
+
+    // Lte specifies that this field must be less than or equal to the
+    // specified value, inclusive
+    optional sint32 lte = 3;
+
+    // Gt specifies that this field must be greater than the specified value,
+    // exclusive. If the value of Gt is larger than a specified Lt or Lte, the
+    // range is reversed.
+    optional sint32 gt = 4;
+
+    // Gte specifies that this field must be greater than or equal to the
+    // specified value, inclusive. If the value of Gte is larger than a
+    // specified Lt or Lte, the range is reversed.
+    optional sint32 gte = 5;
+
+    // In specifies that this field must be equal to one of the specified
+    // values
+    repeated sint32 in = 6;
+
+    // NotIn specifies that this field cannot be equal to one of the specified
+    // values
+    repeated sint32 not_in = 7;
+}
+
+// SInt64Rules describes the constraints applied to `sint64` values
+message SInt64Rules {
+    // Const specifies that this field must be exactly the specified value
+    optional sint64 const = 1;
+
+    // Lt specifies that this field must be less than the specified value,
+    // exclusive
+    optional sint64 lt = 2;
+
+    // Lte specifies that this field must be less than or equal to the
+    // specified value, inclusive
+    optional sint64 lte = 3;
+
+    // Gt specifies that this field must be greater than the specified value,
+    // exclusive. If the value of Gt is larger than a specified Lt or Lte, the
+    // range is reversed.
+    optional sint64 gt = 4;
+
+    // Gte specifies that this field must be greater than or equal to the
+    // specified value, inclusive. If the value of Gte is larger than a
+    // specified Lt or Lte, the range is reversed.
+    optional sint64 gte = 5;
+
+    // In specifies that this field must be equal to one of the specified
+    // values
+    repeated sint64 in = 6;
+
+    // NotIn specifies that this field cannot be equal to one of the specified
+    // values
+    repeated sint64 not_in = 7;
+}
+
+// Fixed32Rules describes the constraints applied to `fixed32` values
+message Fixed32Rules {
+    // Const specifies that this field must be exactly the specified value
+    optional fixed32 const = 1;
+
+    // Lt specifies that this field must be less than the specified value,
+    // exclusive
+    optional fixed32 lt = 2;
+
+    // Lte specifies that this field must be less than or equal to the
+    // specified value, inclusive
+    optional fixed32 lte = 3;
+
+    // Gt specifies that this field must be greater than the specified value,
+    // exclusive. If the value of Gt is larger than a specified Lt or Lte, the
+    // range is reversed.
+    optional fixed32 gt = 4;
+
+    // Gte specifies that this field must be greater than or equal to the
+    // specified value, inclusive. If the value of Gte is larger than a
+    // specified Lt or Lte, the range is reversed.
+    optional fixed32 gte = 5;
+
+    // In specifies that this field must be equal to one of the specified
+    // values
+    repeated fixed32 in = 6;
+
+    // NotIn specifies that this field cannot be equal to one of the specified
+    // values
+    repeated fixed32 not_in = 7;
+}
+
+// Fixed64Rules describes the constraints applied to `fixed64` values
+message Fixed64Rules {
+    // Const specifies that this field must be exactly the specified value
+    optional fixed64 const = 1;
+
+    // Lt specifies that this field must be less than the specified value,
+    // exclusive
+    optional fixed64 lt = 2;
+
+    // Lte specifies that this field must be less than or equal to the
+    // specified value, inclusive
+    optional fixed64 lte = 3;
+
+    // Gt specifies that this field must be greater than the specified value,
+    // exclusive. If the value of Gt is larger than a specified Lt or Lte, the
+    // range is reversed.
+    optional fixed64 gt = 4;
+
+    // Gte specifies that this field must be greater than or equal to the
+    // specified value, inclusive. If the value of Gte is larger than a
+    // specified Lt or Lte, the range is reversed.
+    optional fixed64 gte = 5;
+
+    // In specifies that this field must be equal to one of the specified
+    // values
+    repeated fixed64 in = 6;
+
+    // NotIn specifies that this field cannot be equal to one of the specified
+    // values
+    repeated fixed64 not_in = 7;
+}
+
+// SFixed32Rules describes the constraints applied to `sfixed32` values
+message SFixed32Rules {
+    // Const specifies that this field must be exactly the specified value
+    optional sfixed32 const = 1;
+
+    // Lt specifies that this field must be less than the specified value,
+    // exclusive
+    optional sfixed32 lt = 2;
+
+    // Lte specifies that this field must be less than or equal to the
+    // specified value, inclusive
+    optional sfixed32 lte = 3;
+
+    // Gt specifies that this field must be greater than the specified value,
+    // exclusive. If the value of Gt is larger than a specified Lt or Lte, the
+    // range is reversed.
+    optional sfixed32 gt = 4;
+
+    // Gte specifies that this field must be greater than or equal to the
+    // specified value, inclusive. If the value of Gte is larger than a
+    // specified Lt or Lte, the range is reversed.
+    optional sfixed32 gte = 5;
+
+    // In specifies that this field must be equal to one of the specified
+    // values
+    repeated sfixed32 in = 6;
+
+    // NotIn specifies that this field cannot be equal to one of the specified
+    // values
+    repeated sfixed32 not_in = 7;
+}
+
+// SFixed64Rules describes the constraints applied to `sfixed64` values
+message SFixed64Rules {
+    // Const specifies that this field must be exactly the specified value
+    optional sfixed64 const = 1;
+
+    // Lt specifies that this field must be less than the specified value,
+    // exclusive
+    optional sfixed64 lt = 2;
+
+    // Lte specifies that this field must be less than or equal to the
+    // specified value, inclusive
+    optional sfixed64 lte = 3;
+
+    // Gt specifies that this field must be greater than the specified value,
+    // exclusive. If the value of Gt is larger than a specified Lt or Lte, the
+    // range is reversed.
+    optional sfixed64 gt = 4;
+
+    // Gte specifies that this field must be greater than or equal to the
+    // specified value, inclusive. If the value of Gte is larger than a
+    // specified Lt or Lte, the range is reversed.
+    optional sfixed64 gte = 5;
+
+    // In specifies that this field must be equal to one of the specified
+    // values
+    repeated sfixed64 in = 6;
+
+    // NotIn specifies that this field cannot be equal to one of the specified
+    // values
+    repeated sfixed64 not_in = 7;
+}
+
+// BoolRules describes the constraints applied to `bool` values
+message BoolRules {
+    // Const specifies that this field must be exactly the specified value
+    optional bool const = 1;
+}
+
+// StringRules describe the constraints applied to `string` values
+message StringRules {
+    // Const specifies that this field must be exactly the specified value
+    optional string const = 1;
+
+    // Len specifies that this field must be the specified number of
+    // characters (Unicode code points). Note that the number of
+    // characters may differ from the number of bytes in the string.
+    optional uint64 len = 19;
+
+    // MinLen specifies that this field must be the specified number of
+    // characters (Unicode code points) at a minimum. Note that the number of
+    // characters may differ from the number of bytes in the string.
+    optional uint64 min_len = 2;
+
+    // MaxLen specifies that this field must be the specified number of
+    // characters (Unicode code points) at a maximum. Note that the number of
+    // characters may differ from the number of bytes in the string.
+    optional uint64 max_len = 3;
+
+    // LenBytes specifies that this field must be the specified number of bytes
+    // at a minimum
+    optional uint64 len_bytes = 20;
+
+    // MinBytes specifies that this field must be the specified number of bytes
+    // at a minimum
+    optional uint64 min_bytes = 4;
+
+    // MaxBytes specifies that this field must be the specified number of bytes
+    // at a maximum
+    optional uint64 max_bytes = 5;
+
+    // Pattern specifes that this field must match against the specified
+    // regular expression (RE2 syntax). The included expression should elide
+    // any delimiters.
+    optional string pattern  = 6;
+
+    // Prefix specifies that this field must have the specified substring at
+    // the beginning of the string.
+    optional string prefix   = 7;
+
+    // Suffix specifies that this field must have the specified substring at
+    // the end of the string.
+    optional string suffix   = 8;
+
+    // Contains specifies that this field must have the specified substring
+    // anywhere in the string.
+    optional string contains = 9;
+
+    // In specifies that this field must be equal to one of the specified
+    // values
+    repeated string in     = 10;
+
+    // NotIn specifies that this field cannot be equal to one of the specified
+    // values
+    repeated string not_in = 11;
+
+    // WellKnown rules provide advanced constraints against common string
+    // patterns
+    oneof well_known {
+        // Email specifies that the field must be a valid email address as
+        // defined by RFC 5322
+        bool email    = 12;
+
+        // Hostname specifies that the field must be a valid hostname as
+        // defined by RFC 1034. This constraint does not support
+        // internationalized domain names (IDNs).
+        bool hostname = 13;
+
+        // Ip specifies that the field must be a valid IP (v4 or v6) address.
+        // Valid IPv6 addresses should not include surrounding square brackets.
+        bool ip       = 14;
+
+        // Ipv4 specifies that the field must be a valid IPv4 address.
+        bool ipv4     = 15;
+
+        // Ipv6 specifies that the field must be a valid IPv6 address. Valid
+        // IPv6 addresses should not include surrounding square brackets.
+        bool ipv6     = 16;
+
+        // Uri specifies that the field must be a valid, absolute URI as defined
+        // by RFC 3986
+        bool uri      = 17;
+
+        // UriRef specifies that the field must be a valid URI as defined by RFC
+        // 3986 and may be relative or absolute.
+        bool uri_ref  = 18;
+    }
+}
+
+// BytesRules describe the constraints applied to `bytes` values
+message BytesRules {
+    // Const specifies that this field must be exactly the specified value
+    optional bytes const = 1;
+
+    // Len specifies that this field must be the specified number of bytes
+    optional uint64 len = 13;
+
+    // MinLen specifies that this field must be the specified number of bytes
+    // at a minimum
+    optional uint64 min_len = 2;
+
+    // MaxLen specifies that this field must be the specified number of bytes
+    // at a maximum
+    optional uint64 max_len = 3;
+
+    // Pattern specifes that this field must match against the specified
+    // regular expression (RE2 syntax). The included expression should elide
+    // any delimiters.
+    optional string pattern  = 4;
+
+    // Prefix specifies that this field must have the specified bytes at the
+    // beginning of the string.
+    optional bytes  prefix   = 5;
+
+    // Suffix specifies that this field must have the specified bytes at the
+    // end of the string.
+    optional bytes  suffix   = 6;
+
+    // Contains specifies that this field must have the specified bytes
+    // anywhere in the string.
+    optional bytes  contains = 7;
+
+    // In specifies that this field must be equal to one of the specified
+    // values
+    repeated bytes in     = 8;
+
+    // NotIn specifies that this field cannot be equal to one of the specified
+    // values
+    repeated bytes not_in = 9;
+
+    // WellKnown rules provide advanced constraints against common byte
+    // patterns
+    oneof well_known {
+        // Ip specifies that the field must be a valid IP (v4 or v6) address in
+        // byte format
+        bool ip   = 10;
+
+        // Ipv4 specifies that the field must be a valid IPv4 address in byte
+        // format
+        bool ipv4 = 11;
+
+        // Ipv6 specifies that the field must be a valid IPv6 address in byte
+        // format
+        bool ipv6 = 12;
+    }
+}
+
+// EnumRules describe the constraints applied to enum values
+message EnumRules {
+    // Const specifies that this field must be exactly the specified value
+    optional int32 const        = 1;
+
+    // DefinedOnly specifies that this field must be only one of the defined
+    // values for this enum, failing on any undefined value.
+    optional bool  defined_only = 2;
+
+    // In specifies that this field must be equal to one of the specified
+    // values
+    repeated int32 in           = 3;
+
+    // NotIn specifies that this field cannot be equal to one of the specified
+    // values
+    repeated int32 not_in       = 4;
+}
+
+// MessageRules describe the constraints applied to embedded message values.
+// For message-type fields, validation is performed recursively.
+message MessageRules {
+    // Skip specifies that the validation rules of this field should not be
+    // evaluated
+    optional bool skip     = 1;
+
+    // Required specifies that this field must be set
+    optional bool required = 2;
+}
+
+// RepeatedRules describe the constraints applied to `repeated` values
+message RepeatedRules {
+    // MinItems specifies that this field must have the specified number of
+    // items at a minimum
+    optional uint64 min_items = 1;
+
+    // MaxItems specifies that this field must have the specified number of
+    // items at a maximum
+    optional uint64 max_items = 2;
+
+    // Unique specifies that all elements in this field must be unique. This
+    // contraint is only applicable to scalar and enum types (messages are not
+    // supported).
+    optional bool   unique    = 3;
+
+    // Items specifies the contraints to be applied to each item in the field.
+    // Repeated message fields will still execute validation against each item
+    // unless skip is specified here.
+    optional FieldRules items = 4;
+}
+
+// MapRules describe the constraints applied to `map` values
+message MapRules {
+    // MinPairs specifies that this field must have the specified number of
+    // KVs at a minimum
+    optional uint64 min_pairs = 1;
+
+    // MaxPairs specifies that this field must have the specified number of
+    // KVs at a maximum
+    optional uint64 max_pairs = 2;
+
+    // NoSparse specifies values in this field cannot be unset. This only
+    // applies to map's with message value types.
+    optional bool no_sparse = 3;
+
+    // Keys specifies the constraints to be applied to each key in the field.
+    optional FieldRules keys   = 4;
+
+    // Values specifies the constraints to be applied to the value of each key
+    // in the field. Message values will still have their validations evaluated
+    // unless skip is specified here.
+    optional FieldRules values = 5;
+}
+
+// AnyRules describe constraints applied exclusively to the
+// `google.protobuf.Any` well-known type
+message AnyRules {
+    // Required specifies that this field must be set
+    optional bool required = 1;
+
+    // In specifies that this field's `type_url` must be equal to one of the
+    // specified values.
+    repeated string in     = 2;
+
+    // NotIn specifies that this field's `type_url` must not be equal to any of
+    // the specified values.
+    repeated string not_in = 3;
+}
+
+// DurationRules describe the constraints applied exclusively to the
+// `google.protobuf.Duration` well-known type
+message DurationRules {
+    // Required specifies that this field must be set
+    optional bool required = 1;
+
+    // Const specifies that this field must be exactly the specified value
+    optional google.protobuf.Duration const = 2;
+
+    // Lt specifies that this field must be less than the specified value,
+    // exclusive
+    optional google.protobuf.Duration lt = 3;
+
+    // Lt specifies that this field must be less than the specified value,
+    // inclusive
+    optional google.protobuf.Duration lte = 4;
+
+    // Gt specifies that this field must be greater than the specified value,
+    // exclusive
+    optional google.protobuf.Duration gt = 5;
+
+    // Gte specifies that this field must be greater than the specified value,
+    // inclusive
+    optional google.protobuf.Duration gte = 6;
+
+    // In specifies that this field must be equal to one of the specified
+    // values
+    repeated google.protobuf.Duration in = 7;
+
+    // NotIn specifies that this field cannot be equal to one of the specified
+    // values
+    repeated google.protobuf.Duration not_in = 8;
+}
+
+// TimestampRules describe the constraints applied exclusively to the
+// `google.protobuf.Timestamp` well-known type
+message TimestampRules {
+    // Required specifies that this field must be set
+    optional bool required = 1;
+
+    // Const specifies that this field must be exactly the specified value
+    optional google.protobuf.Timestamp const = 2;
+
+    // Lt specifies that this field must be less than the specified value,
+    // exclusive
+    optional google.protobuf.Timestamp lt = 3;
+
+    // Lte specifies that this field must be less than the specified value,
+    // inclusive
+    optional google.protobuf.Timestamp lte = 4;
+
+    // Gt specifies that this field must be greater than the specified value,
+    // exclusive
+    optional google.protobuf.Timestamp gt = 5;
+
+    // Gte specifies that this field must be greater than the specified value,
+    // inclusive
+    optional google.protobuf.Timestamp gte = 6;
+
+    // LtNow specifies that this must be less than the current time. LtNow
+    // can only be used with the Within rule.
+    optional bool lt_now  = 7;
+
+    // GtNow specifies that this must be greater than the current time. GtNow
+    // can only be used with the Within rule.
+    optional bool gt_now  = 8;
+
+    // Within specifies that this field must be within this duration of the
+    // current time. This constraint can be used alone or with the LtNow and
+    // GtNow rules.
+    optional google.protobuf.Duration within = 9;
+}
diff --git a/oap-server/server-receiver-plugin/pom.xml b/oap-server/server-receiver-plugin/pom.xml
index 624d17f..20ce315 100644
--- a/oap-server/server-receiver-plugin/pom.xml
+++ b/oap-server/server-receiver-plugin/pom.xml
@@ -34,6 +34,7 @@
         <module>skywalking-istio-telemetry-receiver-plugin</module>
         <module>skywalking-register-receiver-plugin</module>
         <module>skywalking-jvm-receiver-plugin</module>
+        <module>envoy-metrics-receiver-plugin</module>
     </modules>
 
     <dependencies>
diff --git a/pom.xml b/pom.xml
index 4384eba..8467606 100644
--- a/pom.xml
+++ b/pom.xml
@@ -319,6 +319,10 @@
 
                         <!-- Proto files of Istio and gogoproto projects -->
                         <exclude>**/src/main/proto/gogoproto/gogo.proto</exclude>
+                        <exclude>**/src/main/proto/envoy/**</exclude>
+                        <exclude>**/src/main/proto/google/protobuf/*.proto</exclude>
+                        <exclude>**/src/main/proto/prometheus/client_model/metrics.proto</exclude>
+                        <exclude>**/src/main/proto/validate/validate.proto</exclude>
                         <!-- Maven Wrapper generated files -->
                         <exclude>.mvn/wrapper/maven-wrapper.properties</exclude>
                     </excludes>