Add event report command (#88)

diff --git a/.gitmodules b/.gitmodules
index 3405629..d7de06d 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
 [submodule "query-protocol"]
 	path = query-protocol
-	url = http://github.com/apache/skywalking-query-protocol/
\ No newline at end of file
+	url = http://github.com/apache/skywalking-query-protocol/
+[submodule "data-collect-protocol"]
+	path = data-collect-protocol
+	url = https://github.com/apache/skywalking-data-collect-protocol.git
diff --git a/Makefile b/Makefile
index 24dc586..cd5b01a 100644
--- a/Makefile
+++ b/Makefile
@@ -28,6 +28,7 @@
 GO_PATH = $$($(GO) env GOPATH)
 GO_BUILD = $(GO) build
 GO_GET = $(GO) get
+GO_INSTALL = $(GO) install
 GO_TEST = $(GO) test
 GO_LINT = $(GO_PATH)/bin/golangci-lint
 GO_LICENSER = $(GO_PATH)/bin/go-licenser
@@ -38,6 +39,10 @@
 GO_BUILD_FLAGS = -v
 GO_BUILD_LDFLAGS = -X main.version=$(VERSION)
 GQL_GEN = $(GO_PATH)/bin/gqlgen
+PROTOC = protoc
+
+GEN_CODE_PATH = gen-codes
+COLLECT_PROTOCOL_MODULE = skywalking/network
 
 PLATFORMS := windows linux darwin
 os = $(word 1, $@)
@@ -54,6 +59,9 @@
 	$(GO_LINT) version || curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GO_PATH)/bin
 	$(GO_LICENSER) -version || GO111MODULE=off $(GO_GET) -u github.com/elastic/go-licenser
 	$(GQL_GEN) version || GO111MODULE=off $(GO_GET) -u github.com/99designs/gqlgen
+	$(PROTOC) --version || sh scripts/install_protoc.sh
+	$(GO_INSTALL) google.golang.org/protobuf/cmd/protoc-gen-go
+	$(GO_INSTALL) google.golang.org/grpc/cmd/protoc-gen-go-grpc
 
 deps: tools
 	$(GO_GET) -v -t -d ./...
@@ -66,6 +74,14 @@
 		&& ../scripts/build-header.sh assets.gen.go \
 		&& cd ..
 
+.PHONY: proto-gen
+proto-gen: tools
+	$(PROTOC) -I=data-collect-protocol --go_out=$(GEN_CODE_PATH) --go-grpc_out=$(GEN_CODE_PATH) data-collect-protocol/common/*.proto data-collect-protocol/event/*.proto
+	cd $(GEN_CODE_PATH)/$(COLLECT_PROTOCOL_MODULE) \
+		&& $(GO) mod init $(COLLECT_PROTOCOL_MODULE) \
+		&& $(GO) mod tidy
+	-scripts/build-header.sh $(GEN_CODE_PATH)/$(COLLECT_PROTOCOL_MODULE)/event/v3/Event_grpc.pb.go
+
 gqlgen: tools
 	echo 'scalar Long' > query-protocol/schema.graphqls
 	$(GQL_GEN) generate
@@ -94,7 +110,7 @@
 
 .PHONY: license
 license: clean tools
-	$(GO_LICENSER) -d -licensor='Apache Software Foundation (ASF)' .
+	$(GO_LICENSER) -d -exclude=$(GEN_CODE_PATH) -licensor='Apache Software Foundation (ASF)' .
 
 .PHONY: verify
 verify: clean license lint test
diff --git a/README.md b/README.md
index 2d43437..8f101cd 100644
--- a/README.md
+++ b/README.md
@@ -85,6 +85,7 @@
 | `--config` | from where the default options values will be loaded | `~/.skywalking.yml`, example can be found [here](examples/.skywalking.yaml) |
 | `--debug` | enable debug mode, will print more detailed information at runtime | `false` |
 | `--base-url` | base url of GraphQL backend | `http://127.0.0.1:12800/graphql` |
+| `--grpcAddr` | The address of gRPC endpoint | `127.0.0.1:11800` |
 | `--username` | username of `Basic` authorization | `` |
 | `--password` | password of `Basic` authorization | `` |
 | `--authorization` | authorization header, can be something like `Basic base64<username:password>` or `Bearer jwt-token`, if `authorization` is set, `username` and `password` are ignored | `` |
@@ -377,6 +378,30 @@
 
 </details>
 
+### `event`
+
+#### `report`
+
+<details>
+
+<summary>event report --uuid=uuid --service=service --name=name --message=message --startTime=startTime [--endTime=endTime] [--instance=instance] [--endpoint=endpoint] [--type=type] [parameters...]</summary>
+
+`event report` reports an event to OAP server via gRPC.
+
+| argument | description | default |
+| :--- | :--- | :--- |
+| `uuid` | The unique ID of the event. |  |
+| `service` | The service of the event occurred on. |  |
+| `instance` | The service instance of the event occurred on. |  |
+| `endpoint` | The endpoint of the event occurred on. |  |
+| `name` | The name of the event. For example, 'Reboot' and 'Upgrade' etc. |  |
+| `type` | The type of the event, could be `Normal` or `Error`. | `Normal` |
+| `message` | The detail of the event. This should be a one-line message that briefly describes why the event is reported. |  |
+| `startTime` | The start time (in milliseconds) of the event, measured between the current time and midnight, January 1, 1970 UTC. |  |
+| `endTime` | The end time (in milliseconds) of the event, measured between the current time and midnight, January 1, 1970 UTC. |  |
+
+</details>
+
 # Use Cases
 
 <details>
diff --git a/cmd/swctl/main.go b/cmd/swctl/main.go
index 712fbcb..679e62a 100644
--- a/cmd/swctl/main.go
+++ b/cmd/swctl/main.go
@@ -21,25 +21,22 @@
 	"io/ioutil"
 	"os"
 
-	"github.com/apache/skywalking-cli/internal/commands/healthcheck"
-	"github.com/apache/skywalking-cli/internal/commands/trace"
-
 	"github.com/apache/skywalking-cli/internal/commands/dashboard"
-
-	"github.com/apache/skywalking-cli/internal/commands/metrics"
-
 	"github.com/apache/skywalking-cli/internal/commands/endpoint"
+	"github.com/apache/skywalking-cli/internal/commands/event"
+	"github.com/apache/skywalking-cli/internal/commands/healthcheck"
 	"github.com/apache/skywalking-cli/internal/commands/install"
 	"github.com/apache/skywalking-cli/internal/commands/instance"
+	"github.com/apache/skywalking-cli/internal/commands/interceptor"
+	"github.com/apache/skywalking-cli/internal/commands/metrics"
+	"github.com/apache/skywalking-cli/internal/commands/service"
+	"github.com/apache/skywalking-cli/internal/commands/trace"
+	"github.com/apache/skywalking-cli/internal/logger"
+	"github.com/apache/skywalking-cli/pkg/util"
 
 	"github.com/sirupsen/logrus"
 	"github.com/urfave/cli"
 	"github.com/urfave/cli/altsrc"
-
-	"github.com/apache/skywalking-cli/internal/commands/interceptor"
-	"github.com/apache/skywalking-cli/internal/commands/service"
-	"github.com/apache/skywalking-cli/internal/logger"
-	"github.com/apache/skywalking-cli/pkg/util"
 )
 
 var log *logrus.Logger
@@ -67,6 +64,12 @@
 			Value:    "http://127.0.0.1:12800/graphql",
 		}),
 		altsrc.NewStringFlag(cli.StringFlag{
+			Name:     "grpcAddr",
+			Usage:    "`host:port` to connect",
+			Value:    "127.0.0.1:11800",
+			Required: false,
+		}),
+		altsrc.NewStringFlag(cli.StringFlag{
 			Name:     "username",
 			Required: false,
 			Usage:    "username of basic authorization",
@@ -112,6 +115,7 @@
 		healthcheck.Command,
 		dashboard.Command,
 		install.Command,
+		event.Command,
 	}
 
 	app.Before = interceptor.BeforeChain([]cli.BeforeFunc{
diff --git a/data-collect-protocol b/data-collect-protocol
new file mode 160000
index 0000000..03963bf
--- /dev/null
+++ b/data-collect-protocol
@@ -0,0 +1 @@
+Subproject commit 03963bfecba88e9bd477535e8f8698675a6ebdfa
diff --git a/examples/.skywalking.yaml b/examples/.skywalking.yaml
index 04355cd..6e3319b 100644
--- a/examples/.skywalking.yaml
+++ b/examples/.skywalking.yaml
@@ -16,5 +16,6 @@
 # under the License.
 
 base-url: http://demo.skywalking.apache.org/graphql
+grpcAddr: 127.0.0.1:11800
 username: basic-auth-username
 password: basic-auth-password
diff --git a/gen-codes/skywalking/network/common/v3/Common.pb.go b/gen-codes/skywalking/network/common/v3/Common.pb.go
new file mode 100644
index 0000000..a3c545d
--- /dev/null
+++ b/gen-codes/skywalking/network/common/v3/Common.pb.go
@@ -0,0 +1,441 @@
+//
+// 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.
+//
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.25.0
+// 	protoc        v3.14.0
+// source: common/Common.proto
+
+package v3
+
+import (
+	proto "github.com/golang/protobuf/proto"
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
+)
+
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+// This is a compile-time assertion that a sufficiently up-to-date version
+// of the legacy proto package is being used.
+const _ = proto.ProtoPackageIsVersion4
+
+// In most cases, detect point should be `server` or `client`.
+// Even in service mesh, this means `server`/`client` side sidecar
+// `proxy` is reserved only.
+type DetectPoint int32
+
+const (
+	DetectPoint_client DetectPoint = 0
+	DetectPoint_server DetectPoint = 1
+	DetectPoint_proxy  DetectPoint = 2
+)
+
+// Enum value maps for DetectPoint.
+var (
+	DetectPoint_name = map[int32]string{
+		0: "client",
+		1: "server",
+		2: "proxy",
+	}
+	DetectPoint_value = map[string]int32{
+		"client": 0,
+		"server": 1,
+		"proxy":  2,
+	}
+)
+
+func (x DetectPoint) Enum() *DetectPoint {
+	p := new(DetectPoint)
+	*p = x
+	return p
+}
+
+func (x DetectPoint) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (DetectPoint) Descriptor() protoreflect.EnumDescriptor {
+	return file_common_Common_proto_enumTypes[0].Descriptor()
+}
+
+func (DetectPoint) Type() protoreflect.EnumType {
+	return &file_common_Common_proto_enumTypes[0]
+}
+
+func (x DetectPoint) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use DetectPoint.Descriptor instead.
+func (DetectPoint) EnumDescriptor() ([]byte, []int) {
+	return file_common_Common_proto_rawDescGZIP(), []int{0}
+}
+
+type KeyStringValuePair struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Key   string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
+	Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
+}
+
+func (x *KeyStringValuePair) Reset() {
+	*x = KeyStringValuePair{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_common_Common_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *KeyStringValuePair) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*KeyStringValuePair) ProtoMessage() {}
+
+func (x *KeyStringValuePair) ProtoReflect() protoreflect.Message {
+	mi := &file_common_Common_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use KeyStringValuePair.ProtoReflect.Descriptor instead.
+func (*KeyStringValuePair) Descriptor() ([]byte, []int) {
+	return file_common_Common_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *KeyStringValuePair) GetKey() string {
+	if x != nil {
+		return x.Key
+	}
+	return ""
+}
+
+func (x *KeyStringValuePair) GetValue() string {
+	if x != nil {
+		return x.Value
+	}
+	return ""
+}
+
+type CPU struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	UsagePercent float64 `protobuf:"fixed64,2,opt,name=usagePercent,proto3" json:"usagePercent,omitempty"`
+}
+
+func (x *CPU) Reset() {
+	*x = CPU{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_common_Common_proto_msgTypes[1]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *CPU) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CPU) ProtoMessage() {}
+
+func (x *CPU) ProtoReflect() protoreflect.Message {
+	mi := &file_common_Common_proto_msgTypes[1]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use CPU.ProtoReflect.Descriptor instead.
+func (*CPU) Descriptor() ([]byte, []int) {
+	return file_common_Common_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *CPU) GetUsagePercent() float64 {
+	if x != nil {
+		return x.UsagePercent
+	}
+	return 0
+}
+
+type Commands struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Commands []*Command `protobuf:"bytes,1,rep,name=commands,proto3" json:"commands,omitempty"`
+}
+
+func (x *Commands) Reset() {
+	*x = Commands{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_common_Common_proto_msgTypes[2]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *Commands) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Commands) ProtoMessage() {}
+
+func (x *Commands) ProtoReflect() protoreflect.Message {
+	mi := &file_common_Common_proto_msgTypes[2]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use Commands.ProtoReflect.Descriptor instead.
+func (*Commands) Descriptor() ([]byte, []int) {
+	return file_common_Common_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *Commands) GetCommands() []*Command {
+	if x != nil {
+		return x.Commands
+	}
+	return nil
+}
+
+type Command struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Command string                `protobuf:"bytes,1,opt,name=command,proto3" json:"command,omitempty"`
+	Args    []*KeyStringValuePair `protobuf:"bytes,2,rep,name=args,proto3" json:"args,omitempty"`
+}
+
+func (x *Command) Reset() {
+	*x = Command{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_common_Common_proto_msgTypes[3]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *Command) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Command) ProtoMessage() {}
+
+func (x *Command) ProtoReflect() protoreflect.Message {
+	mi := &file_common_Common_proto_msgTypes[3]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use Command.ProtoReflect.Descriptor instead.
+func (*Command) Descriptor() ([]byte, []int) {
+	return file_common_Common_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *Command) GetCommand() string {
+	if x != nil {
+		return x.Command
+	}
+	return ""
+}
+
+func (x *Command) GetArgs() []*KeyStringValuePair {
+	if x != nil {
+		return x.Args
+	}
+	return nil
+}
+
+var File_common_Common_proto protoreflect.FileDescriptor
+
+var file_common_Common_proto_rawDesc = []byte{
+	0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x73, 0x6b, 0x79, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e,
+	0x67, 0x2e, 0x76, 0x33, 0x22, 0x3c, 0x0a, 0x12, 0x4b, 0x65, 0x79, 0x53, 0x74, 0x72, 0x69, 0x6e,
+	0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x50, 0x61, 0x69, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
+	0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05,
+	0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c,
+	0x75, 0x65, 0x22, 0x29, 0x0a, 0x03, 0x43, 0x50, 0x55, 0x12, 0x22, 0x0a, 0x0c, 0x75, 0x73, 0x61,
+	0x67, 0x65, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52,
+	0x0c, 0x75, 0x73, 0x61, 0x67, 0x65, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x22, 0x3e, 0x0a,
+	0x08, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x12, 0x32, 0x0a, 0x08, 0x63, 0x6f, 0x6d,
+	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x6b,
+	0x79, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x33, 0x2e, 0x43, 0x6f, 0x6d, 0x6d,
+	0x61, 0x6e, 0x64, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x22, 0x5a, 0x0a,
+	0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d,
+	0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
+	0x6e, 0x64, 0x12, 0x35, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
+	0x32, 0x21, 0x2e, 0x73, 0x6b, 0x79, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x33,
+	0x2e, 0x4b, 0x65, 0x79, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x50,
+	0x61, 0x69, 0x72, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x2a, 0x30, 0x0a, 0x0b, 0x44, 0x65, 0x74,
+	0x65, 0x63, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x0a, 0x0a, 0x06, 0x63, 0x6c, 0x69, 0x65,
+	0x6e, 0x74, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x10, 0x01,
+	0x12, 0x09, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x10, 0x02, 0x42, 0x6d, 0x0a, 0x2b, 0x6f,
+	0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x73, 0x6b, 0x79, 0x77, 0x61, 0x6c,
+	0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x70, 0x6d, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b,
+	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x33, 0x50, 0x01, 0x5a, 0x1c, 0x73, 0x6b,
+	0x79, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b,
+	0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x76, 0x33, 0xaa, 0x02, 0x1d, 0x53, 0x6b, 0x79,
+	0x57, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x50,
+	0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x56, 0x33, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x33,
+}
+
+var (
+	file_common_Common_proto_rawDescOnce sync.Once
+	file_common_Common_proto_rawDescData = file_common_Common_proto_rawDesc
+)
+
+func file_common_Common_proto_rawDescGZIP() []byte {
+	file_common_Common_proto_rawDescOnce.Do(func() {
+		file_common_Common_proto_rawDescData = protoimpl.X.CompressGZIP(file_common_Common_proto_rawDescData)
+	})
+	return file_common_Common_proto_rawDescData
+}
+
+var file_common_Common_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
+var file_common_Common_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
+var file_common_Common_proto_goTypes = []interface{}{
+	(DetectPoint)(0),           // 0: skywalking.v3.DetectPoint
+	(*KeyStringValuePair)(nil), // 1: skywalking.v3.KeyStringValuePair
+	(*CPU)(nil),                // 2: skywalking.v3.CPU
+	(*Commands)(nil),           // 3: skywalking.v3.Commands
+	(*Command)(nil),            // 4: skywalking.v3.Command
+}
+var file_common_Common_proto_depIdxs = []int32{
+	4, // 0: skywalking.v3.Commands.commands:type_name -> skywalking.v3.Command
+	1, // 1: skywalking.v3.Command.args:type_name -> skywalking.v3.KeyStringValuePair
+	2, // [2:2] is the sub-list for method output_type
+	2, // [2:2] is the sub-list for method input_type
+	2, // [2:2] is the sub-list for extension type_name
+	2, // [2:2] is the sub-list for extension extendee
+	0, // [0:2] is the sub-list for field type_name
+}
+
+func init() { file_common_Common_proto_init() }
+func file_common_Common_proto_init() {
+	if File_common_Common_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_common_Common_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*KeyStringValuePair); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_common_Common_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CPU); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_common_Common_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Commands); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_common_Common_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Command); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_common_Common_proto_rawDesc,
+			NumEnums:      1,
+			NumMessages:   4,
+			NumExtensions: 0,
+			NumServices:   0,
+		},
+		GoTypes:           file_common_Common_proto_goTypes,
+		DependencyIndexes: file_common_Common_proto_depIdxs,
+		EnumInfos:         file_common_Common_proto_enumTypes,
+		MessageInfos:      file_common_Common_proto_msgTypes,
+	}.Build()
+	File_common_Common_proto = out.File
+	file_common_Common_proto_rawDesc = nil
+	file_common_Common_proto_goTypes = nil
+	file_common_Common_proto_depIdxs = nil
+}
diff --git a/gen-codes/skywalking/network/event/v3/Event.pb.go b/gen-codes/skywalking/network/event/v3/Event.pb.go
new file mode 100644
index 0000000..4812e3d
--- /dev/null
+++ b/gen-codes/skywalking/network/event/v3/Event.pb.go
@@ -0,0 +1,411 @@
+//
+// 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.
+//
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.25.0
+// 	protoc        v3.14.0
+// source: event/Event.proto
+
+package v3
+
+import (
+	proto "github.com/golang/protobuf/proto"
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	v3 "skywalking/network/common/v3"
+	sync "sync"
+)
+
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+// This is a compile-time assertion that a sufficiently up-to-date version
+// of the legacy proto package is being used.
+const _ = proto.ProtoPackageIsVersion4
+
+type Type int32
+
+const (
+	Type_Normal Type = 0
+	Type_Error  Type = 1
+)
+
+// Enum value maps for Type.
+var (
+	Type_name = map[int32]string{
+		0: "Normal",
+		1: "Error",
+	}
+	Type_value = map[string]int32{
+		"Normal": 0,
+		"Error":  1,
+	}
+)
+
+func (x Type) Enum() *Type {
+	p := new(Type)
+	*p = x
+	return p
+}
+
+func (x Type) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (Type) Descriptor() protoreflect.EnumDescriptor {
+	return file_event_Event_proto_enumTypes[0].Descriptor()
+}
+
+func (Type) Type() protoreflect.EnumType {
+	return &file_event_Event_proto_enumTypes[0]
+}
+
+func (x Type) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use Type.Descriptor instead.
+func (Type) EnumDescriptor() ([]byte, []int) {
+	return file_event_Event_proto_rawDescGZIP(), []int{0}
+}
+
+type Event struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	// Unique ID of the event. Because an event may span a long period of time, the UUID is necessary to associate the
+	// start time with the end time of the same event.
+	Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"`
+	// The source object that the event occurs on.
+	Source *Source `protobuf:"bytes,2,opt,name=source,proto3" json:"source,omitempty"`
+	// The name of the event. For example, `Reboot`, `Upgrade` etc.
+	Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
+	// The type of the event. This field is friendly for UI visualization, where events of type `Normal` are considered as normal operations,
+	// while `Error` is considered as unexpected operations, such as `Crash` events, therefore we can mark them with different colors to be easier identified.
+	Type Type `protobuf:"varint,4,opt,name=type,proto3,enum=skywalking.v3.Type" json:"type,omitempty"`
+	// The detail of the event that describes why this event happened. This should be a one-line message that briefly describes why the event is reported.
+	// Examples of an `Upgrade` event may be something like `Upgrade from ${from_version} to ${to_version}`.
+	// It's NOT encouraged to include the detailed logs of this event, such as the exception stack trace.
+	Message string `protobuf:"bytes,5,opt,name=message,proto3" json:"message,omitempty"`
+	// The parameters in the `message` field.
+	Parameters map[string]string `protobuf:"bytes,6,rep,name=parameters,proto3" json:"parameters,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	// The start time (in milliseconds) of the event, measured between the current time and midnight, January 1, 1970 UTC.
+	// This field is mandatory when an event occurs.
+	StartTime int64 `protobuf:"varint,7,opt,name=startTime,proto3" json:"startTime,omitempty"`
+	// The end time (in milliseconds) of the event. , measured between the current time and midnight, January 1, 1970 UTC.
+	// This field may be empty if the event has not stopped yet, otherwise it should be a valid timestamp after `startTime`.
+	EndTime int64 `protobuf:"varint,8,opt,name=endTime,proto3" json:"endTime,omitempty"`
+}
+
+func (x *Event) Reset() {
+	*x = Event{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_event_Event_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *Event) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Event) ProtoMessage() {}
+
+func (x *Event) ProtoReflect() protoreflect.Message {
+	mi := &file_event_Event_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use Event.ProtoReflect.Descriptor instead.
+func (*Event) Descriptor() ([]byte, []int) {
+	return file_event_Event_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *Event) GetUuid() string {
+	if x != nil {
+		return x.Uuid
+	}
+	return ""
+}
+
+func (x *Event) GetSource() *Source {
+	if x != nil {
+		return x.Source
+	}
+	return nil
+}
+
+func (x *Event) GetName() string {
+	if x != nil {
+		return x.Name
+	}
+	return ""
+}
+
+func (x *Event) GetType() Type {
+	if x != nil {
+		return x.Type
+	}
+	return Type_Normal
+}
+
+func (x *Event) GetMessage() string {
+	if x != nil {
+		return x.Message
+	}
+	return ""
+}
+
+func (x *Event) GetParameters() map[string]string {
+	if x != nil {
+		return x.Parameters
+	}
+	return nil
+}
+
+func (x *Event) GetStartTime() int64 {
+	if x != nil {
+		return x.StartTime
+	}
+	return 0
+}
+
+func (x *Event) GetEndTime() int64 {
+	if x != nil {
+		return x.EndTime
+	}
+	return 0
+}
+
+// If the event occurs on a service ONLY, the `service` field is mandatory, the serviceInstance field and endpoint field are optional;
+// If the event occurs on a service instance, the `service` and `serviceInstance` are mandatory and endpoint is optional;
+// If the event occurs on an endpoint, `service` and `endpoint` are mandatory, `serviceInstance` is optional;
+type Source struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Service         string `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"`
+	ServiceInstance string `protobuf:"bytes,2,opt,name=serviceInstance,proto3" json:"serviceInstance,omitempty"`
+	Endpoint        string `protobuf:"bytes,3,opt,name=endpoint,proto3" json:"endpoint,omitempty"`
+}
+
+func (x *Source) Reset() {
+	*x = Source{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_event_Event_proto_msgTypes[1]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *Source) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Source) ProtoMessage() {}
+
+func (x *Source) ProtoReflect() protoreflect.Message {
+	mi := &file_event_Event_proto_msgTypes[1]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use Source.ProtoReflect.Descriptor instead.
+func (*Source) Descriptor() ([]byte, []int) {
+	return file_event_Event_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *Source) GetService() string {
+	if x != nil {
+		return x.Service
+	}
+	return ""
+}
+
+func (x *Source) GetServiceInstance() string {
+	if x != nil {
+		return x.ServiceInstance
+	}
+	return ""
+}
+
+func (x *Source) GetEndpoint() string {
+	if x != nil {
+		return x.Endpoint
+	}
+	return ""
+}
+
+var File_event_Event_proto protoreflect.FileDescriptor
+
+var file_event_Event_proto_rawDesc = []byte{
+	0x0a, 0x11, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x73, 0x6b, 0x79, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x2e,
+	0x76, 0x33, 0x1a, 0x13, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x43, 0x6f, 0x6d, 0x6d, 0x6f,
+	0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xde, 0x02, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e,
+	0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x2d, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x6b, 0x79, 0x77, 0x61, 0x6c, 0x6b, 0x69,
+	0x6e, 0x67, 0x2e, 0x76, 0x33, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f,
+	0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65,
+	0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x73, 0x6b, 0x79, 0x77, 0x61, 0x6c, 0x6b,
+	0x69, 0x6e, 0x67, 0x2e, 0x76, 0x33, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70,
+	0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x44, 0x0a, 0x0a, 0x70,
+	0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32,
+	0x24, 0x2e, 0x73, 0x6b, 0x79, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x33, 0x2e,
+	0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73,
+	0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72,
+	0x73, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x07,
+	0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12,
+	0x18, 0x0a, 0x07, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03,
+	0x52, 0x07, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x1a, 0x3d, 0x0a, 0x0f, 0x50, 0x61, 0x72,
+	0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
+	0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14,
+	0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76,
+	0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x68, 0x0a, 0x06, 0x53, 0x6f, 0x75, 0x72,
+	0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x28, 0x0a, 0x0f,
+	0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e,
+	0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69,
+	0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69,
+	0x6e, 0x74, 0x2a, 0x1d, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x6f,
+	0x72, 0x6d, 0x61, 0x6c, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10,
+	0x01, 0x32, 0x4c, 0x0a, 0x0c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
+	0x65, 0x12, 0x3c, 0x0a, 0x07, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x12, 0x14, 0x2e, 0x73,
+	0x6b, 0x79, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x33, 0x2e, 0x45, 0x76, 0x65,
+	0x6e, 0x74, 0x1a, 0x17, 0x2e, 0x73, 0x6b, 0x79, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x2e,
+	0x76, 0x33, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x22, 0x00, 0x28, 0x01, 0x42,
+	0x6b, 0x0a, 0x2a, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x73, 0x6b,
+	0x79, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x70, 0x6d, 0x2e, 0x6e, 0x65, 0x74,
+	0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x33, 0x50, 0x01, 0x5a,
+	0x1b, 0x73, 0x6b, 0x79, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x6e, 0x65, 0x74, 0x77,
+	0x6f, 0x72, 0x6b, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x76, 0x33, 0xaa, 0x02, 0x1d, 0x53,
+	0x6b, 0x79, 0x57, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72,
+	0x6b, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x56, 0x33, 0x62, 0x06, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+	file_event_Event_proto_rawDescOnce sync.Once
+	file_event_Event_proto_rawDescData = file_event_Event_proto_rawDesc
+)
+
+func file_event_Event_proto_rawDescGZIP() []byte {
+	file_event_Event_proto_rawDescOnce.Do(func() {
+		file_event_Event_proto_rawDescData = protoimpl.X.CompressGZIP(file_event_Event_proto_rawDescData)
+	})
+	return file_event_Event_proto_rawDescData
+}
+
+var file_event_Event_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
+var file_event_Event_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
+var file_event_Event_proto_goTypes = []interface{}{
+	(Type)(0),           // 0: skywalking.v3.Type
+	(*Event)(nil),       // 1: skywalking.v3.Event
+	(*Source)(nil),      // 2: skywalking.v3.Source
+	nil,                 // 3: skywalking.v3.Event.ParametersEntry
+	(*v3.Commands)(nil), // 4: skywalking.v3.Commands
+}
+var file_event_Event_proto_depIdxs = []int32{
+	2, // 0: skywalking.v3.Event.source:type_name -> skywalking.v3.Source
+	0, // 1: skywalking.v3.Event.type:type_name -> skywalking.v3.Type
+	3, // 2: skywalking.v3.Event.parameters:type_name -> skywalking.v3.Event.ParametersEntry
+	1, // 3: skywalking.v3.EventService.collect:input_type -> skywalking.v3.Event
+	4, // 4: skywalking.v3.EventService.collect:output_type -> skywalking.v3.Commands
+	4, // [4:5] is the sub-list for method output_type
+	3, // [3:4] is the sub-list for method input_type
+	3, // [3:3] is the sub-list for extension type_name
+	3, // [3:3] is the sub-list for extension extendee
+	0, // [0:3] is the sub-list for field type_name
+}
+
+func init() { file_event_Event_proto_init() }
+func file_event_Event_proto_init() {
+	if File_event_Event_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_event_Event_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Event); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_event_Event_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Source); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_event_Event_proto_rawDesc,
+			NumEnums:      1,
+			NumMessages:   3,
+			NumExtensions: 0,
+			NumServices:   1,
+		},
+		GoTypes:           file_event_Event_proto_goTypes,
+		DependencyIndexes: file_event_Event_proto_depIdxs,
+		EnumInfos:         file_event_Event_proto_enumTypes,
+		MessageInfos:      file_event_Event_proto_msgTypes,
+	}.Build()
+	File_event_Event_proto = out.File
+	file_event_Event_proto_rawDesc = nil
+	file_event_Event_proto_goTypes = nil
+	file_event_Event_proto_depIdxs = nil
+}
diff --git a/gen-codes/skywalking/network/event/v3/Event_grpc.pb.go b/gen-codes/skywalking/network/event/v3/Event_grpc.pb.go
new file mode 100644
index 0000000..45865b0
--- /dev/null
+++ b/gen-codes/skywalking/network/event/v3/Event_grpc.pb.go
@@ -0,0 +1,155 @@
+// Licensed to 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. Apache Software Foundation (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.
+
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+
+package v3
+
+import (
+	context "context"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+	v3 "skywalking/network/common/v3"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion7
+
+// EventServiceClient is the client API for EventService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type EventServiceClient interface {
+	// When reporting an event, you typically call the collect function twice, one for starting of the event and the other one for ending of the event, with the same UUID.
+	// There are also cases where you have both start time and end time already, for example, when exporting events from a 3rd-party system,
+	// the start time and end time are already known so that you can call the collect function only once.
+	Collect(ctx context.Context, opts ...grpc.CallOption) (EventService_CollectClient, error)
+}
+
+type eventServiceClient struct {
+	cc grpc.ClientConnInterface
+}
+
+func NewEventServiceClient(cc grpc.ClientConnInterface) EventServiceClient {
+	return &eventServiceClient{cc}
+}
+
+func (c *eventServiceClient) Collect(ctx context.Context, opts ...grpc.CallOption) (EventService_CollectClient, error) {
+	stream, err := c.cc.NewStream(ctx, &_EventService_serviceDesc.Streams[0], "/skywalking.v3.EventService/collect", opts...)
+	if err != nil {
+		return nil, err
+	}
+	x := &eventServiceCollectClient{stream}
+	return x, nil
+}
+
+type EventService_CollectClient interface {
+	Send(*Event) error
+	CloseAndRecv() (*v3.Commands, error)
+	grpc.ClientStream
+}
+
+type eventServiceCollectClient struct {
+	grpc.ClientStream
+}
+
+func (x *eventServiceCollectClient) Send(m *Event) error {
+	return x.ClientStream.SendMsg(m)
+}
+
+func (x *eventServiceCollectClient) CloseAndRecv() (*v3.Commands, error) {
+	if err := x.ClientStream.CloseSend(); err != nil {
+		return nil, err
+	}
+	m := new(v3.Commands)
+	if err := x.ClientStream.RecvMsg(m); err != nil {
+		return nil, err
+	}
+	return m, nil
+}
+
+// EventServiceServer is the server API for EventService service.
+// All implementations must embed UnimplementedEventServiceServer
+// for forward compatibility
+type EventServiceServer interface {
+	// When reporting an event, you typically call the collect function twice, one for starting of the event and the other one for ending of the event, with the same UUID.
+	// There are also cases where you have both start time and end time already, for example, when exporting events from a 3rd-party system,
+	// the start time and end time are already known so that you can call the collect function only once.
+	Collect(EventService_CollectServer) error
+	mustEmbedUnimplementedEventServiceServer()
+}
+
+// UnimplementedEventServiceServer must be embedded to have forward compatible implementations.
+type UnimplementedEventServiceServer struct {
+}
+
+func (UnimplementedEventServiceServer) Collect(EventService_CollectServer) error {
+	return status.Errorf(codes.Unimplemented, "method Collect not implemented")
+}
+func (UnimplementedEventServiceServer) mustEmbedUnimplementedEventServiceServer() {}
+
+// UnsafeEventServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to EventServiceServer will
+// result in compilation errors.
+type UnsafeEventServiceServer interface {
+	mustEmbedUnimplementedEventServiceServer()
+}
+
+func RegisterEventServiceServer(s grpc.ServiceRegistrar, srv EventServiceServer) {
+	s.RegisterService(&_EventService_serviceDesc, srv)
+}
+
+func _EventService_Collect_Handler(srv interface{}, stream grpc.ServerStream) error {
+	return srv.(EventServiceServer).Collect(&eventServiceCollectServer{stream})
+}
+
+type EventService_CollectServer interface {
+	SendAndClose(*v3.Commands) error
+	Recv() (*Event, error)
+	grpc.ServerStream
+}
+
+type eventServiceCollectServer struct {
+	grpc.ServerStream
+}
+
+func (x *eventServiceCollectServer) SendAndClose(m *v3.Commands) error {
+	return x.ServerStream.SendMsg(m)
+}
+
+func (x *eventServiceCollectServer) Recv() (*Event, error) {
+	m := new(Event)
+	if err := x.ServerStream.RecvMsg(m); err != nil {
+		return nil, err
+	}
+	return m, nil
+}
+
+var _EventService_serviceDesc = grpc.ServiceDesc{
+	ServiceName: "skywalking.v3.EventService",
+	HandlerType: (*EventServiceServer)(nil),
+	Methods:     []grpc.MethodDesc{},
+	Streams: []grpc.StreamDesc{
+		{
+			StreamName:    "collect",
+			Handler:       _EventService_Collect_Handler,
+			ClientStreams: true,
+		},
+	},
+	Metadata: "event/Event.proto",
+}
diff --git a/gen-codes/skywalking/network/go.mod b/gen-codes/skywalking/network/go.mod
new file mode 100644
index 0000000..3ec3f7e
--- /dev/null
+++ b/gen-codes/skywalking/network/go.mod
@@ -0,0 +1,9 @@
+module skywalking/network
+
+go 1.13
+
+require (
+	github.com/golang/protobuf v1.4.3
+	google.golang.org/grpc v1.35.0
+	google.golang.org/protobuf v1.25.0
+)
diff --git a/gen-codes/skywalking/network/go.sum b/gen-codes/skywalking/network/go.sum
new file mode 100644
index 0000000..8f0da6e
--- /dev/null
+++ b/gen-codes/skywalking/network/go.sum
@@ -0,0 +1,85 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
+github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.35.0 h1:TwIQcH3es+MojMVojxxfQ3l3OF2KzlRxML2xZq0kRo8=
+google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/go.mod b/go.mod
index c343c33..9d2e276 100644
--- a/go.mod
+++ b/go.mod
@@ -2,6 +2,8 @@
 
 go 1.13
 
+replace skywalking/network v1.0.0 => ./gen-codes/skywalking/network
+
 require (
 	github.com/apache/skywalking-swck v0.0.0-20210107023854-d15ef19f8317
 	github.com/ghodss/yaml v1.0.0
@@ -14,9 +16,9 @@
 	github.com/sirupsen/logrus v1.7.0
 	github.com/spf13/viper v1.7.0
 	github.com/urfave/cli v1.22.1
-	google.golang.org/grpc v1.27.0
-	google.golang.org/protobuf v1.25.0 // indirect
+	google.golang.org/grpc v1.35.0
 	gopkg.in/yaml.v2 v2.4.0
 	k8s.io/apimachinery v0.19.3
 	sigs.k8s.io/controller-runtime v0.7.0-alpha.6
+	skywalking/network v1.0.0
 )
diff --git a/go.sum b/go.sum
index fd471f3..53a8333 100644
--- a/go.sum
+++ b/go.sum
@@ -72,6 +72,7 @@
 github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
 github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
 github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
 github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
@@ -103,7 +104,9 @@
 github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
 github.com/emicklei/go-restful v2.14.3+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
 github.com/emicklei/go-restful-swagger12 v0.0.0-20201014110547-68ccff494617/go.mod h1:qr0VowGBT4CS4Q8vFF8BSeKz34PuqKGxs/L0IAQA9DQ=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses=
@@ -206,6 +209,8 @@
 github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
 github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
 github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
+github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -227,6 +232,8 @@
 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
 github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
 github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
@@ -708,9 +715,12 @@
 google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
 google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
 google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg=
 google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.35.0 h1:TwIQcH3es+MojMVojxxfQ3l3OF2KzlRxML2xZq0kRo8=
+google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
diff --git a/internal/commands/event/event.go b/internal/commands/event/event.go
new file mode 100644
index 0000000..3c11d1e
--- /dev/null
+++ b/internal/commands/event/event.go
@@ -0,0 +1,30 @@
+// Licensed to 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. Apache Software Foundation (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 event
+
+import (
+	"github.com/urfave/cli"
+)
+
+var Command = cli.Command{
+	Name:  "event",
+	Usage: "Event related sub-command",
+	Subcommands: []cli.Command{
+		reportCommand,
+	},
+}
diff --git a/internal/commands/event/report.go b/internal/commands/event/report.go
new file mode 100644
index 0000000..8038361
--- /dev/null
+++ b/internal/commands/event/report.go
@@ -0,0 +1,119 @@
+// Licensed to 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. Apache Software Foundation (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 event
+
+import (
+	"github.com/apache/skywalking-cli/internal/commands/interceptor"
+	"github.com/apache/skywalking-cli/internal/logger"
+	"github.com/apache/skywalking-cli/internal/model"
+	"github.com/apache/skywalking-cli/pkg/display"
+	"github.com/apache/skywalking-cli/pkg/display/displayable"
+	"github.com/apache/skywalking-cli/pkg/grpc"
+
+	"github.com/urfave/cli"
+
+	event "skywalking/network/event/v3"
+)
+
+var reportCommand = cli.Command{
+	Name:      "report",
+	Aliases:   []string{"r"},
+	Usage:     "Report an event to OAP server via gRPC",
+	ArgsUsage: "[parameters...]",
+	Flags: []cli.Flag{
+		cli.StringFlag{
+			Name:     "uuid",
+			Usage:    "Unique `ID` of the event.",
+			Required: true,
+		},
+		cli.StringFlag{
+			Name:     "service",
+			Usage:    "The service of the event occurred on.",
+			Required: true,
+		},
+		cli.StringFlag{
+			Name:     "instance",
+			Usage:    "The service instance of the event occurred on.",
+			Required: false,
+		},
+		cli.StringFlag{
+			Name:     "endpoint",
+			Usage:    "The endpoint of the event occurred on",
+			Required: false,
+		},
+		cli.StringFlag{
+			Name:     "name",
+			Usage:    "The name of the event. For example, 'Reboot' and 'Upgrade' etc.",
+			Required: true,
+		},
+		cli.GenericFlag{
+			Name:  "type",
+			Usage: "The type of the event.",
+			Value: &model.EventTypeEnumValue{
+				Enum:     []event.Type{event.Type_Normal, event.Type_Error},
+				Default:  event.Type_Normal,
+				Selected: event.Type_Normal,
+			},
+		},
+		cli.StringFlag{
+			Name:     "message",
+			Usage:    "The detail of the event. This should be a one-line message that briefly describes why the event is reported.",
+			Required: true,
+		},
+		cli.Int64Flag{
+			Name:     "startTime",
+			Usage:    "The start time (in milliseconds) of the event, measured between the current time and midnight, January 1, 1970 UTC.",
+			Required: true,
+		},
+		cli.Int64Flag{
+			Name:     "endTime",
+			Usage:    "The end time (in milliseconds) of the event, measured between the current time and midnight, January 1, 1970 UTC.",
+			Required: false,
+		},
+	},
+	Action: func(ctx *cli.Context) error {
+		parameters, err := interceptor.ParseParameters(ctx.Args())
+		if err != nil {
+			return err
+		}
+
+		event := event.Event{
+			Uuid: ctx.String("uuid"),
+			Source: &event.Source{
+				Service:         ctx.String("service"),
+				ServiceInstance: ctx.String("instance"),
+				Endpoint:        ctx.String("endpoint"),
+			},
+			Name:       ctx.String("name"),
+			Type:       ctx.Generic("type").(*model.EventTypeEnumValue).Selected,
+			Message:    ctx.String("message"),
+			Parameters: parameters,
+			StartTime:  ctx.Int64("startTime"),
+			EndTime:    ctx.Int64("endTime"),
+		}
+
+		reply, err := grpc.ReportEvent(ctx.GlobalString("grpcAddr"), &event)
+		if err != nil {
+			logger.Log.Fatalln(err)
+			return err
+		}
+
+		logger.Log.Println("Report the event successfully, whose uuid is ", ctx.String("uuid"))
+		return display.Display(ctx, &displayable.Displayable{Data: reply})
+	},
+}
diff --git a/internal/commands/healthcheck/healthcheck.go b/internal/commands/healthcheck/healthcheck.go
index 12ab088..27a20a6 100644
--- a/internal/commands/healthcheck/healthcheck.go
+++ b/internal/commands/healthcheck/healthcheck.go
@@ -36,12 +36,6 @@
 			Usage:    "Check gRPC by HealthCheck service",
 			Required: false,
 		},
-		cli.StringFlag{
-			Name:     "grpcAddr",
-			Usage:    "`host:port` to connect",
-			Value:    "127.0.0.1:11800",
-			Required: false,
-		},
 		cli.BoolFlag{
 			Name:     "grpcTLS",
 			Usage:    "use TLS for gRPC",
@@ -62,7 +56,7 @@
 		if !ctx.BoolT("grpc") {
 			return nil
 		}
-		retCode := healthcheck.HealthCheck(ctx.String("grpcAddr"), ctx.Bool("grpcTLS"))
+		retCode := healthcheck.HealthCheck(ctx.GlobalString("grpcAddr"), ctx.Bool("grpcTLS"))
 		if retCode != 0 {
 			return cli.NewExitError("gRPC: failed to check health", retCode)
 		}
diff --git a/internal/commands/interceptor/event.go b/internal/commands/interceptor/event.go
new file mode 100644
index 0000000..2e30cf0
--- /dev/null
+++ b/internal/commands/interceptor/event.go
@@ -0,0 +1,44 @@
+// Licensed to 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. Apache Software Foundation (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 interceptor
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/urfave/cli"
+)
+
+// ParseParameters parses parameters of the event message from args.
+func ParseParameters(paras cli.Args) (map[string]string, error) {
+	ret := make(map[string]string, len(paras))
+
+	for _, para := range paras {
+		sepIndex := strings.Index(para, "=")
+		// To make sure that len(k) > 0 && len(v) > 0
+		if len(para) >= 3 && sepIndex >= 1 && sepIndex < len(para)-1 {
+			k := para[:sepIndex]
+			v := para[sepIndex+1:]
+			ret[k] = v
+		} else {
+			return nil, fmt.Errorf("%s is not a vaild parameter, should like `key=value`", para)
+		}
+	}
+
+	return ret, nil
+}
diff --git a/internal/commands/interceptor/event_test.go b/internal/commands/interceptor/event_test.go
new file mode 100644
index 0000000..6d86437
--- /dev/null
+++ b/internal/commands/interceptor/event_test.go
@@ -0,0 +1,78 @@
+// Licensed to 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. Apache Software Foundation (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 interceptor
+
+import (
+	"reflect"
+	"testing"
+
+	"github.com/urfave/cli"
+)
+
+func TestParseParameters(t *testing.T) {
+	tests := []struct {
+		name    string
+		args    cli.Args
+		want    map[string]string
+		wantErr bool
+	}{
+		{
+			name:    "no parameters",
+			args:    cli.Args([]string{}),
+			want:    map[string]string{},
+			wantErr: false,
+		},
+		{
+			name: "all parameters are invalid",
+			args: cli.Args([]string{
+				"key",
+				"key=",
+				"=value",
+				"=",
+			}),
+			want:    nil,
+			wantErr: true,
+		},
+		{
+			name: "all parameters are valid",
+			args: cli.Args([]string{
+				"key=value",
+				"k=v===",
+				"kk=====",
+			}),
+			want: map[string]string{
+				"key": "value",
+				"k":   "v===",
+				"kk":  "====",
+			},
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, err := ParseParameters(tt.args)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("ParseParameters() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("ParseParameters() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/internal/model/type.go b/internal/model/type.go
new file mode 100644
index 0000000..74523d0
--- /dev/null
+++ b/internal/model/type.go
@@ -0,0 +1,52 @@
+// Licensed to 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. Apache Software Foundation (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 model
+
+import (
+	"fmt"
+	"strings"
+
+	event "skywalking/network/event/v3"
+)
+
+// EventTypeEnumValue defines the values domain of --type option.
+type EventTypeEnumValue struct {
+	Enum     []event.Type
+	Default  event.Type
+	Selected event.Type
+}
+
+// Set the --type value, from raw string to EventTypeEnumValue.
+func (s *EventTypeEnumValue) Set(value string) error {
+	for _, enum := range s.Enum {
+		if strings.EqualFold(enum.String(), value) {
+			s.Selected = enum
+			return nil
+		}
+	}
+	types := make([]string, len(event.Type_name))
+	for index := range event.Type_name {
+		types[index] = event.Type_name[index]
+	}
+	return fmt.Errorf("allowed types are %s", strings.Join(types, ", "))
+}
+
+// String representation of the event type.
+func (s EventTypeEnumValue) String() string {
+	return s.Selected.String()
+}
diff --git a/pkg/grpc/grpc.go b/pkg/grpc/grpc.go
new file mode 100644
index 0000000..a0188a8
--- /dev/null
+++ b/pkg/grpc/grpc.go
@@ -0,0 +1,51 @@
+// Licensed to 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. Apache Software Foundation (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 grpc
+
+import (
+	"context"
+	"time"
+
+	common "skywalking/network/common/v3"
+	event "skywalking/network/event/v3"
+
+	"google.golang.org/grpc"
+)
+
+// ReportEvent creates a grpc client and report an event.
+func ReportEvent(addr string, e *event.Event) (*common.Commands, error) {
+	conn, err := grpc.Dial(addr, grpc.WithInsecure())
+	if err != nil {
+		return nil, err
+	}
+	defer conn.Close()
+
+	rpcCtx, rpcCancel := context.WithTimeout(context.Background(), time.Second)
+	defer rpcCancel()
+
+	client := event.NewEventServiceClient(conn)
+	stream, err := client.Collect(rpcCtx)
+	if err != nil {
+		return nil, err
+	}
+
+	if err := stream.Send(e); err != nil {
+		return nil, err
+	}
+	return stream.CloseAndRecv()
+}
diff --git a/scripts/install_protoc.sh b/scripts/install_protoc.sh
new file mode 100644
index 0000000..b49cd99
--- /dev/null
+++ b/scripts/install_protoc.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+
+#
+# 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.
+#
+
+
+if [[ "$(uname)" == "Darwin" || "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]];then
+  echo "sorry, please install protoc by yourself."
+  exit 1
+fi
+
+PROTOC_ZIP=protoc-3.14.0-linux-x86_64.zip
+curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v3.14.0/$PROTOC_ZIP
+sudo unzip -o $PROTOC_ZIP -d /usr/local bin/protoc
+sudo chmod 755  /usr/local/bin/protoc
+rm -f $PROTOC_ZIP
+
+echo `protoc --version`
\ No newline at end of file