From ed4355203c92af03871012c9419a24961a8278c3 Mon Sep 17 00:00:00 2001 From: awomanofsin <1115668298@qq.com> Date: Mon, 19 Apr 2021 16:09:29 +0800 Subject: [PATCH 1/4] add by wangting --- plugins/inputs/all/all.go | 2 + .../huawei_dialin/huawei-grpc-dialin.pb.go | 760 ++++++++++++++++++ .../huawei_dialin/huawei-grpc-dialin.proto | 39 + .../huawei_telemetry_dialin.go | 251 ++++++ .../huawei_telemetry_dialin_test.go | 161 ++++ .../huawei_dialout/huawei-grpc-dialout.pb.go | 326 ++++++++ .../huawei_dialout/huawei-grpc-dialout.proto | 13 + .../huawei_telemetry_dialout.go | 306 +++++++ plugins/parsers/registry.go | 2 +- .../processors/metric_match/metric_match.go | 125 +++ 10 files changed, 1984 insertions(+), 1 deletion(-) create mode 100644 plugins/inputs/huawei_telemetry_dialin/huawei_dialin/huawei-grpc-dialin.pb.go create mode 100644 plugins/inputs/huawei_telemetry_dialin/huawei_dialin/huawei-grpc-dialin.proto create mode 100644 plugins/inputs/huawei_telemetry_dialin/huawei_telemetry_dialin.go create mode 100644 plugins/inputs/huawei_telemetry_dialin/huawei_telemetry_dialin_test.go create mode 100644 plugins/inputs/huawei_telemetry_dialout/huawei_dialout/huawei-grpc-dialout.pb.go create mode 100644 plugins/inputs/huawei_telemetry_dialout/huawei_dialout/huawei-grpc-dialout.proto create mode 100644 plugins/inputs/huawei_telemetry_dialout/huawei_telemetry_dialout.go create mode 100644 plugins/processors/metric_match/metric_match.go diff --git a/plugins/inputs/all/all.go b/plugins/inputs/all/all.go index e20d43479344e..222ed466410f3 100644 --- a/plugins/inputs/all/all.go +++ b/plugins/inputs/all/all.go @@ -59,6 +59,8 @@ import ( _ "github.com/influxdata/telegraf/plugins/inputs/http" _ "github.com/influxdata/telegraf/plugins/inputs/http_listener_v2" _ "github.com/influxdata/telegraf/plugins/inputs/http_response" + _ "github.com/influxdata/telegraf/plugins/inputs/huawei_telemetry_dialin" + _ "github.com/influxdata/telegraf/plugins/inputs/huawei_telemetry_dialout" _ "github.com/influxdata/telegraf/plugins/inputs/httpjson" _ "github.com/influxdata/telegraf/plugins/inputs/icinga2" _ "github.com/influxdata/telegraf/plugins/inputs/infiniband" diff --git a/plugins/inputs/huawei_telemetry_dialin/huawei_dialin/huawei-grpc-dialin.pb.go b/plugins/inputs/huawei_telemetry_dialin/huawei_dialin/huawei-grpc-dialin.pb.go new file mode 100644 index 0000000000000..fa79fa44595e6 --- /dev/null +++ b/plugins/inputs/huawei_telemetry_dialin/huawei_dialin/huawei-grpc-dialin.pb.go @@ -0,0 +1,760 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0-devel +// protoc v3.15.8 +// source: huawei-grpc-dialin.proto + +package dialin + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + 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) +) + +type Path struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` //Subscribed sensor-path. + Depth uint32 `protobuf:"varint,2,opt,name=depth,proto3" json:"depth,omitempty"` //Sampling depth of the subscribed sensor-path. The value 1 indicates the current level, and the value 2 indicates the current level and its sub-level, and so on. +} + +func (x *Path) Reset() { + *x = Path{} + if protoimpl.UnsafeEnabled { + mi := &file_huawei_grpc_dialin_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Path) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Path) ProtoMessage() {} + +func (x *Path) ProtoReflect() protoreflect.Message { + mi := &file_huawei_grpc_dialin_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 Path.ProtoReflect.Descriptor instead. +func (*Path) Descriptor() ([]byte, []int) { + return file_huawei_grpc_dialin_proto_rawDescGZIP(), []int{0} +} + +func (x *Path) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +func (x *Path) GetDepth() uint32 { + if x != nil { + return x.Depth + } + return 0 +} + +type SubsArgs struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId uint64 `protobuf:"varint,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` //Request ID, which is transferred by the invoker. + Encoding uint32 `protobuf:"varint,2,opt,name=encoding,proto3" json:"encoding,omitempty"` //Encoding type. Currently, the value can only be 0,indicating GPB encoding. 1 : json + Path []*Path `protobuf:"bytes,5,rep,name=path,proto3" json:"path,omitempty"` //Subscribed path structure. + SampleInterval uint64 `protobuf:"varint,6,opt,name=sample_interval,json=sampleInterval,proto3" json:"sample_interval,omitempty"` //Sampling interval. + HeartbeatInterval uint64 `protobuf:"varint,7,opt,name=heartbeat_interval,json=heartbeatInterval,proto3" json:"heartbeat_interval,omitempty"` //Redundancy suppression interval. This parameter is valid only when suppress_redundant is set to 1. + // Types that are assignable to Suppress: + // *SubsArgs_SuppressRedundant + // *SubsArgs_DelayTime + Suppress isSubsArgs_Suppress `protobuf_oneof:"Suppress"` +} + +func (x *SubsArgs) Reset() { + *x = SubsArgs{} + if protoimpl.UnsafeEnabled { + mi := &file_huawei_grpc_dialin_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SubsArgs) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubsArgs) ProtoMessage() {} + +func (x *SubsArgs) ProtoReflect() protoreflect.Message { + mi := &file_huawei_grpc_dialin_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 SubsArgs.ProtoReflect.Descriptor instead. +func (*SubsArgs) Descriptor() ([]byte, []int) { + return file_huawei_grpc_dialin_proto_rawDescGZIP(), []int{1} +} + +func (x *SubsArgs) GetRequestId() uint64 { + if x != nil { + return x.RequestId + } + return 0 +} + +func (x *SubsArgs) GetEncoding() uint32 { + if x != nil { + return x.Encoding + } + return 0 +} + +func (x *SubsArgs) GetPath() []*Path { + if x != nil { + return x.Path + } + return nil +} + +func (x *SubsArgs) GetSampleInterval() uint64 { + if x != nil { + return x.SampleInterval + } + return 0 +} + +func (x *SubsArgs) GetHeartbeatInterval() uint64 { + if x != nil { + return x.HeartbeatInterval + } + return 0 +} + +func (m *SubsArgs) GetSuppress() isSubsArgs_Suppress { + if m != nil { + return m.Suppress + } + return nil +} + +func (x *SubsArgs) GetSuppressRedundant() bool { + if x, ok := x.GetSuppress().(*SubsArgs_SuppressRedundant); ok { + return x.SuppressRedundant + } + return false +} + +func (x *SubsArgs) GetDelayTime() uint64 { + if x, ok := x.GetSuppress().(*SubsArgs_DelayTime); ok { + return x.DelayTime + } + return 0 +} + +type isSubsArgs_Suppress interface { + isSubsArgs_Suppress() +} + +type SubsArgs_SuppressRedundant struct { + SuppressRedundant bool `protobuf:"varint,8,opt,name=suppress_redundant,json=suppressRedundant,proto3,oneof"` //Redundancy suppression. The sampled data is not reported if the data content remains unchanged. 0: disabled, 1: enabled. +} + +type SubsArgs_DelayTime struct { + DelayTime uint64 `protobuf:"varint,9,opt,name=delay_time,json=delayTime,proto3,oneof"` //Delay time, which ranges from 100 to 60000, in ms. After data changes, the new data is reported after a specified delay. The new changes during the delay are accumulated. This parameter is used to prevent a large amount of data from being reported during service flapping. +} + +func (*SubsArgs_SuppressRedundant) isSubsArgs_Suppress() {} + +func (*SubsArgs_DelayTime) isSubsArgs_Suppress() {} + +type SubsReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SubscriptionId uint32 `protobuf:"varint,1,opt,name=subscription_id,json=subscriptionId,proto3" json:"subscription_id,omitempty"` //If the subscribing is successful, the subscription ID is returned. If the subscribing fails, 0 is returned. + RequestId uint64 `protobuf:"varint,2,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` //ID of the subscribing request. + ResponseCode string `protobuf:"bytes,3,opt,name=response_code,json=responseCode,proto3" json:"response_code,omitempty"` //Return code. The value 200 indicates a success. + // Types that are assignable to MessageData: + // *SubsReply_Message + // *SubsReply_MessageJson + MessageData isSubsReply_MessageData `protobuf_oneof:"MessageData"` +} + +func (x *SubsReply) Reset() { + *x = SubsReply{} + if protoimpl.UnsafeEnabled { + mi := &file_huawei_grpc_dialin_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SubsReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubsReply) ProtoMessage() {} + +func (x *SubsReply) ProtoReflect() protoreflect.Message { + mi := &file_huawei_grpc_dialin_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 SubsReply.ProtoReflect.Descriptor instead. +func (*SubsReply) Descriptor() ([]byte, []int) { + return file_huawei_grpc_dialin_proto_rawDescGZIP(), []int{2} +} + +func (x *SubsReply) GetSubscriptionId() uint32 { + if x != nil { + return x.SubscriptionId + } + return 0 +} + +func (x *SubsReply) GetRequestId() uint64 { + if x != nil { + return x.RequestId + } + return 0 +} + +func (x *SubsReply) GetResponseCode() string { + if x != nil { + return x.ResponseCode + } + return "" +} + +func (m *SubsReply) GetMessageData() isSubsReply_MessageData { + if m != nil { + return m.MessageData + } + return nil +} + +func (x *SubsReply) GetMessage() []byte { + if x, ok := x.GetMessageData().(*SubsReply_Message); ok { + return x.Message + } + return nil +} + +func (x *SubsReply) GetMessageJson() string { + if x, ok := x.GetMessageData().(*SubsReply_MessageJson); ok { + return x.MessageJson + } + return "" +} + +type isSubsReply_MessageData interface { + isSubsReply_MessageData() +} + +type SubsReply_Message struct { + Message []byte `protobuf:"bytes,4,opt,name=message,proto3,oneof"` //Sampled data in GPB encoding format is carried. +} + +type SubsReply_MessageJson struct { + MessageJson string `protobuf:"bytes,5,opt,name=message_json,json=messageJson,proto3,oneof"` //Sampled data in JSON encoding format is carried. +} + +func (*SubsReply_Message) isSubsReply_MessageData() {} + +func (*SubsReply_MessageJson) isSubsReply_MessageData() {} + +type CancelArgs struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId uint64 `protobuf:"varint,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` //Request ID, which is transferred by the invoker. + SubscriptionId uint32 `protobuf:"varint,2,opt,name=subscription_id,json=subscriptionId,proto3" json:"subscription_id,omitempty"` //ID of the subscription to be canceled. +} + +func (x *CancelArgs) Reset() { + *x = CancelArgs{} + if protoimpl.UnsafeEnabled { + mi := &file_huawei_grpc_dialin_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CancelArgs) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CancelArgs) ProtoMessage() {} + +func (x *CancelArgs) ProtoReflect() protoreflect.Message { + mi := &file_huawei_grpc_dialin_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 CancelArgs.ProtoReflect.Descriptor instead. +func (*CancelArgs) Descriptor() ([]byte, []int) { + return file_huawei_grpc_dialin_proto_rawDescGZIP(), []int{3} +} + +func (x *CancelArgs) GetRequestId() uint64 { + if x != nil { + return x.RequestId + } + return 0 +} + +func (x *CancelArgs) GetSubscriptionId() uint32 { + if x != nil { + return x.SubscriptionId + } + return 0 +} + +type CancelReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId uint64 `protobuf:"varint,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` //Request ID, which is transferred by the invoker. + ResponseCode string `protobuf:"bytes,2,opt,name=response_code,json=responseCode,proto3" json:"response_code,omitempty"` //Return code. The value 200 indicates a success. + Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` //Error description. +} + +func (x *CancelReply) Reset() { + *x = CancelReply{} + if protoimpl.UnsafeEnabled { + mi := &file_huawei_grpc_dialin_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CancelReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CancelReply) ProtoMessage() {} + +func (x *CancelReply) ProtoReflect() protoreflect.Message { + mi := &file_huawei_grpc_dialin_proto_msgTypes[4] + 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 CancelReply.ProtoReflect.Descriptor instead. +func (*CancelReply) Descriptor() ([]byte, []int) { + return file_huawei_grpc_dialin_proto_rawDescGZIP(), []int{4} +} + +func (x *CancelReply) GetRequestId() uint64 { + if x != nil { + return x.RequestId + } + return 0 +} + +func (x *CancelReply) GetResponseCode() string { + if x != nil { + return x.ResponseCode + } + return "" +} + +func (x *CancelReply) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +var File_huawei_grpc_dialin_proto protoreflect.FileDescriptor + +var file_huawei_grpc_dialin_proto_rawDesc = []byte{ + 0x0a, 0x18, 0x68, 0x75, 0x61, 0x77, 0x65, 0x69, 0x2d, 0x67, 0x72, 0x70, 0x63, 0x2d, 0x64, 0x69, + 0x61, 0x6c, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x68, 0x75, 0x61, 0x77, + 0x65, 0x69, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x69, 0x6e, 0x22, 0x30, 0x0a, 0x04, 0x50, 0x61, 0x74, + 0x68, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x22, 0xa4, 0x02, 0x0a, 0x08, + 0x53, 0x75, 0x62, 0x73, 0x41, 0x72, 0x67, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x63, 0x6f, 0x64, + 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x65, 0x6e, 0x63, 0x6f, 0x64, + 0x69, 0x6e, 0x67, 0x12, 0x27, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x13, 0x2e, 0x68, 0x75, 0x61, 0x77, 0x65, 0x69, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x69, + 0x6e, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x27, 0x0a, 0x0f, + 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x2d, 0x0a, 0x12, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, + 0x61, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x11, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x76, 0x61, 0x6c, 0x12, 0x2f, 0x0a, 0x12, 0x73, 0x75, 0x70, 0x70, 0x72, 0x65, 0x73, 0x73, + 0x5f, 0x72, 0x65, 0x64, 0x75, 0x6e, 0x64, 0x61, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, + 0x48, 0x00, 0x52, 0x11, 0x73, 0x75, 0x70, 0x70, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x64, 0x75, + 0x6e, 0x64, 0x61, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0a, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x09, 0x64, 0x65, 0x6c, + 0x61, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x42, 0x0a, 0x0a, 0x08, 0x53, 0x75, 0x70, 0x70, 0x72, 0x65, + 0x73, 0x73, 0x22, 0xc8, 0x01, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, + 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x73, 0x75, 0x62, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, + 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, + 0x00, 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4a, 0x73, 0x6f, 0x6e, 0x42, 0x0d, + 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x44, 0x61, 0x74, 0x61, 0x22, 0x54, 0x0a, + 0x0a, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x72, 0x67, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x75, + 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x22, 0x6b, 0x0a, 0x0b, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x65, 0x70, + 0x6c, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, + 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x63, 0x6f, + 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x32, 0x97, 0x01, 0x0a, 0x0e, 0x67, 0x52, 0x50, 0x43, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4f, + 0x70, 0x65, 0x72, 0x12, 0x42, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, + 0x12, 0x17, 0x2e, 0x68, 0x75, 0x61, 0x77, 0x65, 0x69, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x69, 0x6e, + 0x2e, 0x53, 0x75, 0x62, 0x73, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x18, 0x2e, 0x68, 0x75, 0x61, 0x77, + 0x65, 0x69, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x69, 0x6e, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x52, 0x65, + 0x70, 0x6c, 0x79, 0x22, 0x00, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x06, 0x43, 0x61, 0x6e, 0x63, 0x65, + 0x6c, 0x12, 0x19, 0x2e, 0x68, 0x75, 0x61, 0x77, 0x65, 0x69, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x69, + 0x6e, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x1a, 0x2e, 0x68, + 0x75, 0x61, 0x77, 0x65, 0x69, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x69, 0x6e, 0x2e, 0x43, 0x61, 0x6e, + 0x63, 0x65, 0x6c, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x16, 0x5a, 0x14, 0x68, 0x75, + 0x61, 0x77, 0x65, 0x69, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x69, 0x6e, 0x2f, 0x64, 0x69, 0x61, 0x6c, + 0x69, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_huawei_grpc_dialin_proto_rawDescOnce sync.Once + file_huawei_grpc_dialin_proto_rawDescData = file_huawei_grpc_dialin_proto_rawDesc +) + +func file_huawei_grpc_dialin_proto_rawDescGZIP() []byte { + file_huawei_grpc_dialin_proto_rawDescOnce.Do(func() { + file_huawei_grpc_dialin_proto_rawDescData = protoimpl.X.CompressGZIP(file_huawei_grpc_dialin_proto_rawDescData) + }) + return file_huawei_grpc_dialin_proto_rawDescData +} + +var file_huawei_grpc_dialin_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_huawei_grpc_dialin_proto_goTypes = []interface{}{ + (*Path)(nil), // 0: huawei_dialin.Path + (*SubsArgs)(nil), // 1: huawei_dialin.SubsArgs + (*SubsReply)(nil), // 2: huawei_dialin.SubsReply + (*CancelArgs)(nil), // 3: huawei_dialin.CancelArgs + (*CancelReply)(nil), // 4: huawei_dialin.CancelReply +} +var file_huawei_grpc_dialin_proto_depIdxs = []int32{ + 0, // 0: huawei_dialin.SubsArgs.path:type_name -> huawei_dialin.Path + 1, // 1: huawei_dialin.gRPCConfigOper.Subscribe:input_type -> huawei_dialin.SubsArgs + 3, // 2: huawei_dialin.gRPCConfigOper.Cancel:input_type -> huawei_dialin.CancelArgs + 2, // 3: huawei_dialin.gRPCConfigOper.Subscribe:output_type -> huawei_dialin.SubsReply + 4, // 4: huawei_dialin.gRPCConfigOper.Cancel:output_type -> huawei_dialin.CancelReply + 3, // [3:5] is the sub-list for method output_type + 1, // [1:3] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_huawei_grpc_dialin_proto_init() } +func file_huawei_grpc_dialin_proto_init() { + if File_huawei_grpc_dialin_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_huawei_grpc_dialin_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Path); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_huawei_grpc_dialin_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SubsArgs); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_huawei_grpc_dialin_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SubsReply); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_huawei_grpc_dialin_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CancelArgs); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_huawei_grpc_dialin_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CancelReply); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_huawei_grpc_dialin_proto_msgTypes[1].OneofWrappers = []interface{}{ + (*SubsArgs_SuppressRedundant)(nil), + (*SubsArgs_DelayTime)(nil), + } + file_huawei_grpc_dialin_proto_msgTypes[2].OneofWrappers = []interface{}{ + (*SubsReply_Message)(nil), + (*SubsReply_MessageJson)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_huawei_grpc_dialin_proto_rawDesc, + NumEnums: 0, + NumMessages: 5, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_huawei_grpc_dialin_proto_goTypes, + DependencyIndexes: file_huawei_grpc_dialin_proto_depIdxs, + MessageInfos: file_huawei_grpc_dialin_proto_msgTypes, + }.Build() + File_huawei_grpc_dialin_proto = out.File + file_huawei_grpc_dialin_proto_rawDesc = nil + file_huawei_grpc_dialin_proto_goTypes = nil + file_huawei_grpc_dialin_proto_depIdxs = nil +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConnInterface + +// 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.SupportPackageIsVersion6 + +// GRPCConfigOperClient is the client API for GRPCConfigOper service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type GRPCConfigOperClient interface { + Subscribe(ctx context.Context, in *SubsArgs, opts ...grpc.CallOption) (GRPCConfigOper_SubscribeClient, error) + Cancel(ctx context.Context, in *CancelArgs, opts ...grpc.CallOption) (*CancelReply, error) +} + +type gRPCConfigOperClient struct { + cc grpc.ClientConnInterface +} + +func NewGRPCConfigOperClient(cc grpc.ClientConnInterface) GRPCConfigOperClient { + return &gRPCConfigOperClient{cc} +} + +func (c *gRPCConfigOperClient) Subscribe(ctx context.Context, in *SubsArgs, opts ...grpc.CallOption) (GRPCConfigOper_SubscribeClient, error) { + stream, err := c.cc.NewStream(ctx, &_GRPCConfigOper_serviceDesc.Streams[0], "/huawei_dialin.gRPCConfigOper/Subscribe", opts...) + if err != nil { + return nil, err + } + x := &gRPCConfigOperSubscribeClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type GRPCConfigOper_SubscribeClient interface { + Recv() (*SubsReply, error) + grpc.ClientStream +} + +type gRPCConfigOperSubscribeClient struct { + grpc.ClientStream +} + +func (x *gRPCConfigOperSubscribeClient) Recv() (*SubsReply, error) { + m := new(SubsReply) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *gRPCConfigOperClient) Cancel(ctx context.Context, in *CancelArgs, opts ...grpc.CallOption) (*CancelReply, error) { + out := new(CancelReply) + err := c.cc.Invoke(ctx, "/huawei_dialin.gRPCConfigOper/Cancel", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// GRPCConfigOperServer is the server API for GRPCConfigOper service. +type GRPCConfigOperServer interface { + Subscribe(*SubsArgs, GRPCConfigOper_SubscribeServer) error + Cancel(context.Context, *CancelArgs) (*CancelReply, error) +} + +// UnimplementedGRPCConfigOperServer can be embedded to have forward compatible implementations. +type UnimplementedGRPCConfigOperServer struct { +} + +func (*UnimplementedGRPCConfigOperServer) Subscribe(*SubsArgs, GRPCConfigOper_SubscribeServer) error { + return status.Errorf(codes.Unimplemented, "method Subscribe not implemented") +} +func (*UnimplementedGRPCConfigOperServer) Cancel(context.Context, *CancelArgs) (*CancelReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method Cancel not implemented") +} + +func RegisterGRPCConfigOperServer(s *grpc.Server, srv GRPCConfigOperServer) { + s.RegisterService(&_GRPCConfigOper_serviceDesc, srv) +} + +func _GRPCConfigOper_Subscribe_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(SubsArgs) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GRPCConfigOperServer).Subscribe(m, &gRPCConfigOperSubscribeServer{stream}) +} + +type GRPCConfigOper_SubscribeServer interface { + Send(*SubsReply) error + grpc.ServerStream +} + +type gRPCConfigOperSubscribeServer struct { + grpc.ServerStream +} + +func (x *gRPCConfigOperSubscribeServer) Send(m *SubsReply) error { + return x.ServerStream.SendMsg(m) +} + +func _GRPCConfigOper_Cancel_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CancelArgs) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GRPCConfigOperServer).Cancel(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/huawei_dialin.gRPCConfigOper/Cancel", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GRPCConfigOperServer).Cancel(ctx, req.(*CancelArgs)) + } + return interceptor(ctx, in, info, handler) +} + +var _GRPCConfigOper_serviceDesc = grpc.ServiceDesc{ + ServiceName: "huawei_dialin.gRPCConfigOper", + HandlerType: (*GRPCConfigOperServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Cancel", + Handler: _GRPCConfigOper_Cancel_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "Subscribe", + Handler: _GRPCConfigOper_Subscribe_Handler, + ServerStreams: true, + }, + }, + Metadata: "huawei-grpc-dialin.proto", +} diff --git a/plugins/inputs/huawei_telemetry_dialin/huawei_dialin/huawei-grpc-dialin.proto b/plugins/inputs/huawei_telemetry_dialin/huawei_dialin/huawei-grpc-dialin.proto new file mode 100644 index 0000000000000..feecd67c5187e --- /dev/null +++ b/plugins/inputs/huawei_telemetry_dialin/huawei_dialin/huawei-grpc-dialin.proto @@ -0,0 +1,39 @@ +syntax = "proto3"; //The .proto file version is defined as v3. +package huawei_dialin; //The package name is huawei_dialin. +service gRPCConfigOper { //The service name is gRPCConfigOper. + rpc Subscribe (SubsArgs) returns (stream SubsReply) {}; //The method is Subscribe, and the server stream mode is used, providing the dynamic subscription method. The input parameter SubsArgs contains subscribing parameters. + rpc Cancel (CancelArgs) returns (CancelReply) {}; //The method is Cancel, and the query and response mode is used, providing the method of canceling dynamic subscription. The input parameter CancelArgs contains unsubscribing parameters. +} +message Path { //Path message structure. + string path = 1; //Subscribed sensor-path. + uint32 depth = 2; //Sampling depth of the subscribed sensor-path. The value 1 indicates the current level, and the value 2 indicates the current level and its sub-level, and so on. +} +message SubsArgs { //Subscribing request parameter. + uint64 request_id = 1; //Request ID, which is transferred by the invoker. + uint32 encoding = 2; //Encoding type. Currently, the value can only be 0,indicating GPB encoding. 1 : json + repeated Path path = 5; //Subscribed path structure. + uint64 sample_interval = 6; //Sampling interval. + uint64 heartbeat_interval = 7; //Redundancy suppression interval. This parameter is valid only when suppress_redundant is set to 1. + oneof Suppress { + bool suppress_redundant = 8; //Redundancy suppression. The sampled data is not reported if the data content remains unchanged. 0: disabled, 1: enabled. + uint64 delay_time = 9; //Delay time, which ranges from 100 to 60000, in ms. After data changes, the new data is reported after a specified delay. The new changes during the delay are accumulated. This parameter is used to prevent a large amount of data from being reported during service flapping. + } +message SubsReply { //Subscribing response parameter. + uint32 subscription_id = 1; //If the subscribing is successful, the subscription ID is returned. If the subscribing fails, 0 is returned. + uint64 request_id = 2; //ID of the subscribing request. + string response_code = 3; //Return code. The value 200 indicates a success. + oneof MessageData { + bytes message = 4; //Sampled data in GPB encoding format is carried. + string message_json = 5; //Sampled data in JSON encoding format is carried. + } +} +message CancelArgs { //Unsubscribing request parameter. + uint64 request_id = 1; //Request ID, which is transferred by the invoker. + uint32 subscription_id = 2; //ID of the subscription to be canceled. +} +message CancelReply { //Unsubscribing response parameter. + uint64 request_id = 1; //Request ID, which is transferred by the invoker. + string response_code = 2; //Return code. The value 200 indicates a success. + string message = 3; //Error description. +} +} \ No newline at end of file diff --git a/plugins/inputs/huawei_telemetry_dialin/huawei_telemetry_dialin.go b/plugins/inputs/huawei_telemetry_dialin/huawei_telemetry_dialin.go new file mode 100644 index 0000000000000..90865e2814e86 --- /dev/null +++ b/plugins/inputs/huawei_telemetry_dialin/huawei_telemetry_dialin.go @@ -0,0 +1,251 @@ +package huawei_telemetry_dialin + +import ( + "context" + "encoding/hex" + "fmt" + "github.com/influxdata/telegraf" + internaltls "github.com/influxdata/telegraf/plugins/common/tls" + "github.com/influxdata/telegraf/plugins/inputs" + "github.com/influxdata/telegraf/plugins/inputs/huawei_telemetry_dialin/huawei_dialin" + "github.com/influxdata/telegraf/plugins/parsers" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/metadata" + "log" + "net" + "os" + "sync" +) + +type Path struct { + Depth int + Path string +} + +type aaa struct { + Password string + Username string +} + +type router struct { + Paths []Path + Aaa aaa + Address string + Encoding string + Sample_interval int + Request_id int + // GRPC TLS settings + internaltls.ClientConfig +} + +// HuaweiTelemetryDialin plugin VRPs +type HuaweiTelemetryDialin struct { + // Common configuration + Routers []router `toml:"routers"` + Transport string + MaxMsgSize int `toml:"max_msg_size"` + Aliases map[string]string `toml:"aliases"` + EmbeddedTags []string `toml:"embedded_tags"` + Log telegraf.Logger + + // Internal listener / client handle + grpcServer *grpc.Server + listener net.Listener + + // Internal state + aliases map[string]string + warned map[string]struct{} + extraTags map[string]map[string]struct{} + mutex sync.Mutex + acc telegraf.Accumulator + wg sync.WaitGroup +} + +// Start the Huawei Dialin service wt git +func (dialin *HuaweiTelemetryDialin) Start(acc telegraf.Accumulator) error { + dialin.acc = acc + // init parser + parseGpb, err := parsers.NewHuaweiGrpcGpbParser() + parseJson, err := parsers.NewHuaweiGrpcJsonParser() + if err != nil { + dialin.acc.AddError(fmt.Errorf("DialIn Parser Init error: %s", err)) + return err + } + for _, routerDialinConfig := range dialin.Routers { + dialin.wg.Add(1) + go dialin.singleSubscribe(routerDialinConfig, parseGpb, parseJson) + } + return nil +} + +// create subscribe args from config of huawei_telemetry_dialin in telegraf.conf +func createSubArgs(router router) *huawei_dialin.SubsArgs { + + var paths []*huawei_dialin.Path + + if len(router.Paths) <= 0 { + return nil + } + + for _, path := range router.Paths { + paths = append(paths, &huawei_dialin.Path{ + Path: path.Path, + Depth: uint32(path.Depth), + }) + } + + encoding := 0 + if router.Encoding == "json" { + encoding = 1 + } + return &huawei_dialin.SubsArgs{ + RequestId: uint64(router.Request_id), + Encoding: uint32(encoding), + Path: paths, + SampleInterval: uint64(router.Sample_interval), + HeartbeatInterval: 0, + Suppress: nil, + } +} + +func (dialin *HuaweiTelemetryDialin) singleSubscribe(dialinConfig router, parserGpb, parserJson parsers.Parser) { + var opts []grpc.DialOption + tlsConfig, errTls := dialinConfig.ClientConfig.TLSConfig() + if errTls != nil { + dialin.Log.Errorf("E! [single Subscribe] tlsConfig %s", errTls) + dialin.stop() + } else if tlsConfig != nil { + // tls + tlsConfig.ServerName = dialinConfig.ServerName + creds := credentials.NewTLS(tlsConfig) + opts = append(opts, grpc.WithTransportCredentials(creds)) + } else { + // no tls + opts = append(opts, grpc.WithInsecure()) + } + conn, err := grpc.Dial(dialinConfig.Address, opts...) + if err != nil { + dialin.Log.Errorf("E! [single Subscribe] invalid Huawei Dialin remoteServer:ng TLS PEM %s,device address : %s, request_id:%s", dialin.Transport, dialinConfig.Address, dialinConfig.Request_id) + return + } + defer conn.Close() + client := huawei_dialin.NewGRPCConfigOperClient(conn) + var cancel context.CancelFunc + var ctx context.Context + ctx, cancel = context.WithCancel(context.Background()) + if dialinConfig.Aaa.Username != "" && dialinConfig.Aaa.Password != "" { + // input aaa as context + ctx = metadata.AppendToOutgoingContext(context.TODO(), "username", dialinConfig.Aaa.Username, "password", dialinConfig.Aaa.Password) + } else { + dialin.Log.Errorf("E! [single Subscribe] no aaa configuration checked , device address : %s, request_id:%s", dialinConfig.Address, dialinConfig.Request_id) + } + stream, err := client.Subscribe(ctx, createSubArgs(dialinConfig)) + if err != nil { + cancel() + dialin.Log.Errorf("E! [single Subscribe] Huawei Dialin connection failed %s request_id %s, connection error %v", dialinConfig.Address, dialinConfig.Request_id, err) + return + } + if stream != nil { + for { + packet, err := stream.Recv() + if err != nil || packet == nil { + dialin.Log.Errorf("E! [single Subscribe] Huawei Dialin device address %s, request_id %s, stream recv() %t", dialinConfig.Address, dialinConfig.Request_id, err) + return + } + isData := checkValidData(packet) + if isData { + var metrics []telegraf.Metric + var errParse error + if len(packet.GetMessage()) != 0 { + dialin.Log.Debugf("data gpb %s", hex.EncodeToString(packet.GetMessage())) + metrics, errParse = parserGpb.Parse(packet.GetMessage()) + if errParse != nil { + dialin.Log.Errorf("E! [Huawei Dialin] device address %s , request_id %s,Packet Parse%t", dialinConfig.Address, dialinConfig.Request_id, errParse) + return + } + } + if len(packet.GetMessageJson()) != 0 { + dialin.Log.Debugf("data str %s", packet.GetMessageJson()) + metrics, errParse = parserJson.Parse([]byte(packet.GetMessageJson())) + if errParse != nil { + dialin.Log.Errorf("E! [Huawei Dialin] device address %s ,request_id %s, Packet Json Parse %t", dialinConfig.Address, dialinConfig.Request_id, errParse) + return + } + } + for _, metric := range metrics { + dialin.acc.AddMetric(metric) + } + } else { + dialin.Log.Errorf("the %s [request_id %s] reply with packet :\n %s ", dialinConfig.Address, dialinConfig.Request_id, packet) + } + } + } + dialin.wg.Done() +} + +// Stop Client Subscribe, Close connection +func (dialin *HuaweiTelemetryDialin) Stop() { + dialin.wg.Wait() +} + +const sampleConfig = ` +## Address and port to host telemetry listener + service_address = "10.0.0.1:57000" + + ## Enable TLS; grpc transport only. + # tls_cert = "/etc/telegraf/cert.pem" + # tls_key = "/etc/telegraf/key.pem" + + ## Enable TLS client authentication and define allowed CA certificates; grpc + ## transport only. + # tls_allowed_cacerts = ["/etc/telegraf/clientca.pem"] + + ## Define (for certain nested telemetry measurements with embedded tags) which fields are tags + + ## Define aliases to map telemetry encoding paths to simple measurement names + ` + +// SampleConfig of plugin +func (dialin *HuaweiTelemetryDialin) SampleConfig() string { + return sampleConfig +} + +// Description of plugin +func (dialin *HuaweiTelemetryDialin) Description() string { + return "Huawei model-driven telemetry (MDT) input plugin for dialin" +} + +// Gather plugin measurements (unused) +func (dialin *HuaweiTelemetryDialin) Gather(_ telegraf.Accumulator) error { + return nil +} + +// check if the telemetry is valid +func checkValidData(reply *huawei_dialin.SubsReply) bool { + respCode := reply.ResponseCode + if respCode == "" { + return true + } + // return error + if respCode != "200" && respCode != "" { + return false + } + // respCode is "ok" doesn't mean this message is a telemetry data message ,just an answer message + if respCode == "ok" { + return false + } + return false +} + +func init() { + inputs.Add("huawei_telemetry_dialin", func() telegraf.Input { + return &HuaweiTelemetryDialin{} + }) +} + +func (dialin *HuaweiTelemetryDialin) stop() { + log.SetOutput(os.Stderr) + log.Printf("I! telegraf stopped because error.") + os.Exit(1) +} \ No newline at end of file diff --git a/plugins/inputs/huawei_telemetry_dialin/huawei_telemetry_dialin_test.go b/plugins/inputs/huawei_telemetry_dialin/huawei_telemetry_dialin_test.go new file mode 100644 index 0000000000000..b49e6da063d79 --- /dev/null +++ b/plugins/inputs/huawei_telemetry_dialin/huawei_telemetry_dialin_test.go @@ -0,0 +1,161 @@ +package huawei_telemetry_dialin + +import ( + "context" + "github.com/influxdata/telegraf/plugins/inputs/huawei_telemetry_dialin/huawei_dialin" + "log" + "net" + "testing" + + telemetry "github.com/cisco-ie/nx-telemetry-proto/telemetry_bis" + "github.com/golang/protobuf/proto" + "github.com/influxdata/telegraf/testutil" + "github.com/stretchr/testify/require" + "google.golang.org/grpc" +) + +func (dialin *HuaweiTelemetryDialin) Subscribe(stream huawei_dialin.GRPCConfigOper_SubscribeServer) error { + return nil +} + +func TestHuaweiTelemetryDialin_Start(t *testing.T) { + // 1. prepare telemetry struct data, and marshal to []byte + // 2. start one grpc server with huawei-grpc-dialin.proto in go routine + // + // 3. one go routine opened to run Start() in huawei_telemetry_dialin.go + // 4. + // start the mock dialin server + // initialize test object + hin := &HuaweiTelemetryDialin{Log: testutil.Logger{}, Transport: "grpc"} + acc := &testutil.Accumulator{} + // listen on address with transport + transport := "grpc" + address := "127.0.0.1:5431" + listener, err := net.Listen(transport, address) + if err != nil { + log.Fatalf("net.Listen err: %v", err) + } + grpcServer := grpc.NewServer() + // registry our service on grpc server + huawei_dialin.RegisterGRPCConfigOperServer(grpcServer, hin) + // Use the server Serve() method and our port information area to block and wait until the process is killed or Stop() is called + err = grpcServer.Serve(listener) + if err != nil { + log.Fatalf("grpcServer.Serve err: %v", err) + } + + // test the dialin client by testing Start + errStart := hin.Start(acc) + // error is expected since we are passing in dummy transport + require.Error(t, errStart) + + telemetry := &telemetry.Telemetry{ + MsgTimestamp: 1543236572000, + EncodingPath: "type:model/some/path", + NodeId: &telemetry.Telemetry_NodeIdStr{NodeIdStr: "hostname"}, + Subscription: &telemetry.Telemetry_SubscriptionIdStr{SubscriptionIdStr: "subscription"}, + DataGpbkv: []*telemetry.TelemetryField{ + { + Fields: []*telemetry.TelemetryField{ + { + Name: "keys", + Fields: []*telemetry.TelemetryField{ + { + Name: "name", + ValueByType: &telemetry.TelemetryField_StringValue{StringValue: "str"}, + }, + { + Name: "uint64", + ValueByType: &telemetry.TelemetryField_Uint64Value{Uint64Value: 1234}, + }, + }, + }, + { + Name: "content", + Fields: []*telemetry.TelemetryField{ + { + Name: "bool", + ValueByType: &telemetry.TelemetryField_BoolValue{BoolValue: true}, + }, + }, + }, + }, + }, + { + Fields: []*telemetry.TelemetryField{ + { + Name: "keys", + Fields: []*telemetry.TelemetryField{ + { + Name: "name", + ValueByType: &telemetry.TelemetryField_StringValue{StringValue: "str2"}, + }, + }, + }, + { + Name: "content", + Fields: []*telemetry.TelemetryField{ + { + Name: "bool", + ValueByType: &telemetry.TelemetryField_BoolValue{BoolValue: false}, + }, + }, + }, + }, + }, + }, + } + data, _ := proto.Marshal(telemetry) + + hin.handleTelemetry(data) + require.Empty(t, acc.Errors) + + tags := map[string]string{"path": "type:model/some/path", "name": "str", "uint64": "1234", "source": "hostname", "subscription": "subscription"} + fields := map[string]interface{}{"bool": true} + acc.AssertContainsTaggedFields(t, "alias", fields, tags) + + tags = map[string]string{"path": "type:model/some/path", "name": "str2", "source": "hostname", "subscription": "subscription"} + fields = map[string]interface{}{"bool": false} + acc.AssertContainsTaggedFields(t, "alias", fields, tags) +} + +func mockTelemetryMessage() *telemetry.Telemetry { + return &telemetry.Telemetry{ + MsgTimestamp: 1543236572000, + EncodingPath: "type:model/some/path", + NodeId: &telemetry.Telemetry_NodeIdStr{NodeIdStr: "hostname"}, + Subscription: &telemetry.Telemetry_SubscriptionIdStr{SubscriptionIdStr: "subscription"}, + DataGpbkv: []*telemetry.TelemetryField{ + { + Fields: []*telemetry.TelemetryField{ + { + Name: "keys", + Fields: []*telemetry.TelemetryField{ + { + Name: "name", + ValueByType: &telemetry.TelemetryField_StringValue{StringValue: "str"}, + }, + }, + }, + { + Name: "content", + Fields: []*telemetry.TelemetryField{ + { + Name: "value", + ValueByType: &telemetry.TelemetryField_Sint64Value{Sint64Value: -1}, + }, + }, + }, + }, + }, + }, + } +} + +func (dialin *HuaweiTelemetryDialin) Subscribe(args *huawei_dialin.SubsArgs, server huawei_dialin.GRPCConfigOper_SubscribeServer) error { + panic("implement me") +} + +func (dialin *HuaweiTelemetryDialin) Cancel(ctx context.Context, args *huawei_dialin.CancelArgs) (*huawei_dialin.CancelReply, error) { + panic("implement me") +} diff --git a/plugins/inputs/huawei_telemetry_dialout/huawei_dialout/huawei-grpc-dialout.pb.go b/plugins/inputs/huawei_telemetry_dialout/huawei_dialout/huawei-grpc-dialout.pb.go new file mode 100644 index 0000000000000..f71077eb50520 --- /dev/null +++ b/plugins/inputs/huawei_telemetry_dialout/huawei_dialout/huawei-grpc-dialout.pb.go @@ -0,0 +1,326 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0-devel +// protoc v3.15.8 +// source: huawei-grpc-dialout.proto + +package huawei_dialout + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + 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) +) + +type ServiceArgs struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ReqId int64 `protobuf:"varint,1,opt,name=ReqId,proto3" json:"ReqId,omitempty"` //Request ID. + // Types that are assignable to MessageData: + // *ServiceArgs_Data + // *ServiceArgs_DataJson + MessageData isServiceArgs_MessageData `protobuf_oneof:"MessageData"` + Errors string `protobuf:"bytes,3,opt,name=errors,proto3" json:"errors,omitempty"` //Error description. +} + +func (x *ServiceArgs) Reset() { + *x = ServiceArgs{} + if protoimpl.UnsafeEnabled { + mi := &file_huawei_grpc_dialout_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ServiceArgs) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServiceArgs) ProtoMessage() {} + +func (x *ServiceArgs) ProtoReflect() protoreflect.Message { + mi := &file_huawei_grpc_dialout_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 ServiceArgs.ProtoReflect.Descriptor instead. +func (*ServiceArgs) Descriptor() ([]byte, []int) { + return file_huawei_grpc_dialout_proto_rawDescGZIP(), []int{0} +} + +func (x *ServiceArgs) GetReqId() int64 { + if x != nil { + return x.ReqId + } + return 0 +} + +func (m *ServiceArgs) GetMessageData() isServiceArgs_MessageData { + if m != nil { + return m.MessageData + } + return nil +} + +func (x *ServiceArgs) GetData() []byte { + if x, ok := x.GetMessageData().(*ServiceArgs_Data); ok { + return x.Data + } + return nil +} + +func (x *ServiceArgs) GetDataJson() string { + if x, ok := x.GetMessageData().(*ServiceArgs_DataJson); ok { + return x.DataJson + } + return "" +} + +func (x *ServiceArgs) GetErrors() string { + if x != nil { + return x.Errors + } + return "" +} + +type isServiceArgs_MessageData interface { + isServiceArgs_MessageData() +} + +type ServiceArgs_Data struct { + Data []byte `protobuf:"bytes,2,opt,name=data,proto3,oneof"` //Sampled data in GPB encoding format is carried. +} + +type ServiceArgs_DataJson struct { + DataJson string `protobuf:"bytes,4,opt,name=data_json,json=dataJson,proto3,oneof"` //Sampled data in JSON encoding format is carried. +} + +func (*ServiceArgs_Data) isServiceArgs_MessageData() {} + +func (*ServiceArgs_DataJson) isServiceArgs_MessageData() {} + +var File_huawei_grpc_dialout_proto protoreflect.FileDescriptor + +var file_huawei_grpc_dialout_proto_rawDesc = []byte{ + 0x0a, 0x19, 0x68, 0x75, 0x61, 0x77, 0x65, 0x69, 0x2d, 0x67, 0x72, 0x70, 0x63, 0x2d, 0x64, 0x69, + 0x61, 0x6c, 0x6f, 0x75, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x68, 0x75, 0x61, + 0x77, 0x65, 0x69, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x75, 0x74, 0x22, 0x7f, 0x0a, 0x0b, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x72, 0x67, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x52, 0x65, + 0x71, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x52, 0x65, 0x71, 0x49, 0x64, + 0x12, 0x14, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, + 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1d, 0x0a, 0x09, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6a, + 0x73, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x64, 0x61, 0x74, + 0x61, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x42, 0x0d, 0x0a, + 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x44, 0x61, 0x74, 0x61, 0x32, 0x60, 0x0a, 0x0f, + 0x67, 0x52, 0x50, 0x43, 0x44, 0x61, 0x74, 0x61, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x4d, 0x0a, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x12, 0x1b, + 0x2e, 0x68, 0x75, 0x61, 0x77, 0x65, 0x69, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x75, 0x74, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x1b, 0x2e, 0x68, 0x75, + 0x61, 0x77, 0x65, 0x69, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x75, 0x74, 0x2e, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x41, 0x72, 0x67, 0x73, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x17, + 0x5a, 0x15, 0x68, 0x75, 0x61, 0x77, 0x65, 0x69, 0x2f, 0x68, 0x75, 0x61, 0x77, 0x65, 0x69, 0x5f, + 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x75, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_huawei_grpc_dialout_proto_rawDescOnce sync.Once + file_huawei_grpc_dialout_proto_rawDescData = file_huawei_grpc_dialout_proto_rawDesc +) + +func file_huawei_grpc_dialout_proto_rawDescGZIP() []byte { + file_huawei_grpc_dialout_proto_rawDescOnce.Do(func() { + file_huawei_grpc_dialout_proto_rawDescData = protoimpl.X.CompressGZIP(file_huawei_grpc_dialout_proto_rawDescData) + }) + return file_huawei_grpc_dialout_proto_rawDescData +} + +var file_huawei_grpc_dialout_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_huawei_grpc_dialout_proto_goTypes = []interface{}{ + (*ServiceArgs)(nil), // 0: huawei_dialout.serviceArgs +} +var file_huawei_grpc_dialout_proto_depIdxs = []int32{ + 0, // 0: huawei_dialout.gRPCDataservice.dataPublish:input_type -> huawei_dialout.serviceArgs + 0, // 1: huawei_dialout.gRPCDataservice.dataPublish:output_type -> huawei_dialout.serviceArgs + 1, // [1:2] is the sub-list for method output_type + 0, // [0:1] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_huawei_grpc_dialout_proto_init() } +func file_huawei_grpc_dialout_proto_init() { + if File_huawei_grpc_dialout_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_huawei_grpc_dialout_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ServiceArgs); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_huawei_grpc_dialout_proto_msgTypes[0].OneofWrappers = []interface{}{ + (*ServiceArgs_Data)(nil), + (*ServiceArgs_DataJson)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_huawei_grpc_dialout_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_huawei_grpc_dialout_proto_goTypes, + DependencyIndexes: file_huawei_grpc_dialout_proto_depIdxs, + MessageInfos: file_huawei_grpc_dialout_proto_msgTypes, + }.Build() + File_huawei_grpc_dialout_proto = out.File + file_huawei_grpc_dialout_proto_rawDesc = nil + file_huawei_grpc_dialout_proto_goTypes = nil + file_huawei_grpc_dialout_proto_depIdxs = nil +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConnInterface + +// 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.SupportPackageIsVersion6 + +// GRPCDataserviceClient is the client API for GRPCDataservice service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type GRPCDataserviceClient interface { + DataPublish(ctx context.Context, opts ...grpc.CallOption) (GRPCDataservice_DataPublishClient, error) +} + +type gRPCDataserviceClient struct { + cc grpc.ClientConnInterface +} + +func NewGRPCDataserviceClient(cc grpc.ClientConnInterface) GRPCDataserviceClient { + return &gRPCDataserviceClient{cc} +} + +func (c *gRPCDataserviceClient) DataPublish(ctx context.Context, opts ...grpc.CallOption) (GRPCDataservice_DataPublishClient, error) { + stream, err := c.cc.NewStream(ctx, &_GRPCDataservice_serviceDesc.Streams[0], "/huawei_dialout.gRPCDataservice/dataPublish", opts...) + if err != nil { + return nil, err + } + x := &gRPCDataserviceDataPublishClient{stream} + return x, nil +} + +type GRPCDataservice_DataPublishClient interface { + Send(*ServiceArgs) error + Recv() (*ServiceArgs, error) + grpc.ClientStream +} + +type gRPCDataserviceDataPublishClient struct { + grpc.ClientStream +} + +func (x *gRPCDataserviceDataPublishClient) Send(m *ServiceArgs) error { + return x.ClientStream.SendMsg(m) +} + +func (x *gRPCDataserviceDataPublishClient) Recv() (*ServiceArgs, error) { + m := new(ServiceArgs) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// GRPCDataserviceServer is the server API for GRPCDataservice service. +type GRPCDataserviceServer interface { + DataPublish(GRPCDataservice_DataPublishServer) error +} + +// UnimplementedGRPCDataserviceServer can be embedded to have forward compatible implementations. +type UnimplementedGRPCDataserviceServer struct { +} + +func (*UnimplementedGRPCDataserviceServer) DataPublish(GRPCDataservice_DataPublishServer) error { + return status.Errorf(codes.Unimplemented, "method DataPublish not implemented") +} + +func RegisterGRPCDataserviceServer(s *grpc.Server, srv GRPCDataserviceServer) { + s.RegisterService(&_GRPCDataservice_serviceDesc, srv) +} + +func _GRPCDataservice_DataPublish_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(GRPCDataserviceServer).DataPublish(&gRPCDataserviceDataPublishServer{stream}) +} + +type GRPCDataservice_DataPublishServer interface { + Send(*ServiceArgs) error + Recv() (*ServiceArgs, error) + grpc.ServerStream +} + +type gRPCDataserviceDataPublishServer struct { + grpc.ServerStream +} + +func (x *gRPCDataserviceDataPublishServer) Send(m *ServiceArgs) error { + return x.ServerStream.SendMsg(m) +} + +func (x *gRPCDataserviceDataPublishServer) Recv() (*ServiceArgs, error) { + m := new(ServiceArgs) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var _GRPCDataservice_serviceDesc = grpc.ServiceDesc{ + ServiceName: "huawei_dialout.gRPCDataservice", + HandlerType: (*GRPCDataserviceServer)(nil), + Methods: []grpc.MethodDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "dataPublish", + Handler: _GRPCDataservice_DataPublish_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "huawei-grpc-dialout.proto", +} diff --git a/plugins/inputs/huawei_telemetry_dialout/huawei_dialout/huawei-grpc-dialout.proto b/plugins/inputs/huawei_telemetry_dialout/huawei_dialout/huawei-grpc-dialout.proto new file mode 100644 index 0000000000000..2724004a77ff0 --- /dev/null +++ b/plugins/inputs/huawei_telemetry_dialout/huawei_dialout/huawei-grpc-dialout.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; //The .proto file version is defined as v3. +package huawei_dialout; //The package name is huawei_dialout. +service gRPCDataservice { //The service name is gRPCDataservice. + rpc dataPublish(stream serviceArgs) returns(stream serviceArgs) {}; //The method name is dataPublish, providing the data push method. The working mode is bidirectional stream mode. The input parameter is the serviceArgs data flow. +} +message serviceArgs { //Message format description. + int64 ReqId = 1; //Request ID. + oneof MessageData { + bytes data = 2; //Sampled data in GPB encoding format is carried. + string data_json = 4; //Sampled data in JSON encoding format is carried. + } + string errors = 3; //Error description. +} \ No newline at end of file diff --git a/plugins/inputs/huawei_telemetry_dialout/huawei_telemetry_dialout.go b/plugins/inputs/huawei_telemetry_dialout/huawei_telemetry_dialout.go new file mode 100644 index 0000000000000..4a6606d1276d8 --- /dev/null +++ b/plugins/inputs/huawei_telemetry_dialout/huawei_telemetry_dialout.go @@ -0,0 +1,306 @@ +package huawei_telemetry_dialout + +import ( + "bytes" + "crypto/tls" + "encoding/binary" + "encoding/hex" + "fmt" + "github.com/influxdata/telegraf" + internaltls "github.com/influxdata/telegraf/plugins/common/tls" + "github.com/influxdata/telegraf/plugins/inputs" + dialout "github.com/influxdata/telegraf/plugins/inputs/huawei_telemetry_dialout/huawei_dialout" + "github.com/influxdata/telegraf/plugins/parsers" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" // Register GRPC gzip decoder to support compressed telemetry + _ "google.golang.org/grpc/encoding/gzip" + "google.golang.org/grpc/peer" + "io" + "log" + "net" + "os" + "sync" +) + +const ( + // Maximum telemetry payload size (in bytes) to accept for GRPC dialout transport + tcpMaxMsgLen uint32 = 0 +) + +// HuaweiTelemetryDialout plugin VRPs +type HuaweiTelemetryDialout struct { + // Common configuration + Transport string + ServiceAddress string `toml:"service_address"` + MaxMsgSize int `toml:"max_msg_size"` + Aliases map[string]string `toml:"aliases"` + EmbeddedTags []string `toml:"embedded_tags"` + Log telegraf.Logger + // GRPC TLS settings + internaltls.ServerConfig + + // Internal listener / client handle + grpcServer *grpc.Server + listener net.Listener + + // Internal state + aliases map[string]string + warned map[string]struct{} + extraTags map[string]map[string]struct{} + metrics []telegraf.Metric + mutex sync.Mutex + acc telegraf.Accumulator + wg sync.WaitGroup +} + +// Start the Huawei Telemetry dialout service +func (c *HuaweiTelemetryDialout) Start(acc telegraf.Accumulator) error { + var err error + c.acc = acc + c.listener, err = net.Listen("tcp", c.ServiceAddress) + if err != nil { + return err + } + switch c.Transport { + case "grpc": + // set tls and max size of packet + var opts []grpc.ServerOption + tlsConfig, err := c.ServerConfig.TLSConfig() + + if err != nil { + c.listener.Close() + return err + } else if tlsConfig != nil { + tlsConfig.ClientAuth = tls.RequestClientCert + opts = append(opts, grpc.Creds(credentials.NewTLS(tlsConfig))) + } + + if c.MaxMsgSize > 0 { + opts = append(opts, grpc.MaxRecvMsgSize(c.MaxMsgSize)) + } + // create grpc server + c.grpcServer = grpc.NewServer(opts...) + // Register the server with the method that receives the data + dialout.RegisterGRPCDataserviceServer(c.grpcServer, c) + + c.wg.Add(1) + go func() { + // Listen on the ServiceAddress port + c.grpcServer.Serve(c.listener) + c.wg.Done() + }() + + default: + c.listener.Close() + return fmt.Errorf("invalid Huawei transport: %s", c.Transport) + } + + return nil +} + +// AcceptTCPDialoutClients defines the TCP dialout server main routine +func (c *HuaweiTelemetryDialout) acceptTCPClientsddd() { + // Keep track of all active connections, so we can close them if necessary + var mutex sync.Mutex + clients := make(map[net.Conn]struct{}) + + for { + conn, err := c.listener.Accept() + if neterr, ok := err.(*net.OpError); ok && (neterr.Timeout() || neterr.Temporary()) { + continue + } else if err != nil { + break // Stop() will close the connection so Accept() will fail here + } + + mutex.Lock() + clients[conn] = struct{}{} + mutex.Unlock() + + // Individual client connection routine + c.wg.Add(1) + go func() { + c.Log.Debugf("Accepted Huawei MDT TCP dialout connection from %s", conn.RemoteAddr()) + if err := c.handleTCPClient(conn); err != nil { + c.acc.AddError(err) + } + c.Log.Debugf("Closed Huawei MDT TCP dialout connection from %s", conn.RemoteAddr()) + + mutex.Lock() + delete(clients, conn) + mutex.Unlock() + + conn.Close() + c.wg.Done() + }() + } + + // Close all remaining client connections + mutex.Lock() + for client := range clients { + if err := client.Close(); err != nil { + c.Log.Errorf("Failed to close TCP dialout client: %v", err) + } + } + mutex.Unlock() +} + +// Handle a TCP telemetry client +func (c *HuaweiTelemetryDialout) handleTCPClient(conn net.Conn) error { + // TCP Dialout telemetry framing header + var hdr struct { + MsgType uint16 + MsgEncap uint16 + MsgHdrVersion uint16 + MsgFlags uint16 + MsgLen uint32 + } + + var payload bytes.Buffer + + for { + // Read and validate dialout telemetry header + if err := binary.Read(conn, binary.BigEndian, &hdr); err != nil { + return err + } + + maxMsgSize := tcpMaxMsgLen + if c.MaxMsgSize > 0 { + maxMsgSize = uint32(c.MaxMsgSize) + } + + if hdr.MsgLen > maxMsgSize { + return fmt.Errorf("dialout packet too long: %v", hdr.MsgLen) + } else if hdr.MsgFlags != 0 { + return fmt.Errorf("invalid dialout flags: %v", hdr.MsgFlags) + } + + // Read and handle telemetry packet + payload.Reset() + if size, err := payload.ReadFrom(io.LimitReader(conn, int64(hdr.MsgLen))); size != int64(hdr.MsgLen) { + if err != nil { + return err + } + return fmt.Errorf("TCP dialout premature EOF") + } + } +} + +// implement the rpc method of huawei-grpc-dialout.proto +func (c *HuaweiTelemetryDialout) DataPublish(stream dialout.GRPCDataservice_DataPublishServer) error { + peer, peerOK := peer.FromContext(stream.Context()) + if peerOK { + c.Log.Debugf("Accepted Huawei GRPC dialout connection from %s", peer.Addr) + } + // init parser + parseGpb, err := parsers.NewHuaweiGrpcGpbParser() + parseJson, err := parsers.NewHuaweiGrpcJsonParser() + if err != nil { + c.acc.AddError(fmt.Errorf("Dialout Parser Init error: %s, %v", err)) + return err + } + //var chunkBuffer bytes.Buffer + for { + packet, err := stream.Recv() + if err != nil { + if err != io.EOF { + c.acc.AddError(fmt.Errorf("GRPC dialout receive error: %s, %v", c.listener.Addr(), err)) + } + break + } + + if len(packet.Errors) != 0 { + c.acc.AddError(fmt.Errorf("GRPC dialout error: %s", packet.Errors)) + break + } + + var metrics []telegraf.Metric + var errParse error + // gpb encoding + if len(packet.GetData()) != 0 { + c.Log.Debugf("data gpb %s", hex.EncodeToString(packet.GetData())) + metrics, errParse = parseGpb.Parse(packet.GetData()) + if errParse != nil { + c.acc.AddError(errParse) + c.stop() + return fmt.Errorf("[input.huawei_telemetry_dialout] error when parse grpc stream %t", errParse) + } + } + // json encoding + + if len(packet.GetDataJson()) != 0 { + c.Log.Debugf("data str %s", packet.GetDataJson()) + metrics, errParse = parseJson.Parse([]byte(packet.GetDataJson())) + if errParse != nil { + c.acc.AddError(errParse) + c.stop() + return fmt.Errorf("[input.huawei_telemetry_dialout] error when parse grpc stream %t", errParse) + } + } + for _, metric := range metrics { + c.acc.AddMetric(metric) + } + } + if peerOK { + c.Log.Debugf("Closed Huawei GRPC dialout connection from %s", peer.Addr) + } + return nil +} + +func (c *HuaweiTelemetryDialout) Address() net.Addr { + return c.listener.Addr() +} + +// Stop listener and cleanup +func (c *HuaweiTelemetryDialout) Stop() { + if c.grpcServer != nil { + // Stop server and terminate all running dialout routines + c.grpcServer.Stop() + } + if c.listener != nil { + c.listener.Close() + } + c.wg.Wait() +} +const sampleConfig = ` + ## Address and port to host telemetry listener + service_address = "10.0.0.1:57000" + + ## Enable TLS; + # tls_cert = "/etc/telegraf/cert.pem" + # tls_key = "/etc/telegraf/key.pem" + + ## Enable TLS client authentication and define allowed CA certificates; grpc + ## transport only. + # tls_allowed_cacerts = ["/etc/telegraf/clientca.pem"] + + ## Define (for certain nested telemetry measurements with embedded tags) which fields are tags + + ## Define aliases to map telemetry encoding paths to simple measurement names +` + +// SampleConfig of plugin +func (c *HuaweiTelemetryDialout) SampleConfig() string { + return sampleConfig +} + +// Description of plugin +func (c *HuaweiTelemetryDialout) Description() string { + return "Huawei Telemetry For Huawei Router" +} + +// Gather plugin measurements (unused) +func (c *HuaweiTelemetryDialout) Gather(_ telegraf.Accumulator) error { + return nil +} + +func init() { + inputs.Add("huawei_telemetry_dialout", func() telegraf.Input { + return &HuaweiTelemetryDialout{} + }) +} + +func (c *HuaweiTelemetryDialout) stop() { + log.SetOutput(os.Stderr) + log.Printf("I! telegraf stopped because error.") + os.Exit(1) +} diff --git a/plugins/parsers/registry.go b/plugins/parsers/registry.go index 54edf3300b612..76e889ffdbfaf 100644 --- a/plugins/parsers/registry.go +++ b/plugins/parsers/registry.go @@ -349,4 +349,4 @@ func NewPrometheusParser(defaultTags map[string]string) (Parser, error) { return &prometheus.Parser{ DefaultTags: defaultTags, }, nil -} +} \ No newline at end of file diff --git a/plugins/processors/metric_match/metric_match.go b/plugins/processors/metric_match/metric_match.go new file mode 100644 index 0000000000000..c29e37d6a3c45 --- /dev/null +++ b/plugins/processors/metric_match/metric_match.go @@ -0,0 +1,125 @@ +package grpc + +import ( + "github.com/influxdata/telegraf" + "github.com/influxdata/telegraf/models" + "github.com/influxdata/telegraf/plugins/processors" + "github.com/influxdata/telegraf/selfstat" + "log" + "os" + "reflect" + "strconv" + "strings" +) + +const sampleConfig = `` +const sensorPathKey = "sensor_path" +const TelemetryKey = "telemetry" + +type MetricMatch struct { + Tag map[string][]string `toml:"tag"` + FieldFilter map[string][]string `toml:"field_filter"` + Log telegraf.Logger +} + +func (m *MetricMatch) SampleConfig() string { + return sampleConfig +} + +func (m *MetricMatch) Description() string { + return "metric match" +} + +func (m *MetricMatch) Apply(in ...telegraf.Metric) []telegraf.Metric { + + // get telemetry header field_filter and tag + headerFilter := m.FieldFilter[TelemetryKey] + headerTag := m.Tag[TelemetryKey] + var res []telegraf.Metric + // remove and filter field + for _, eachMetric := range in { + sensorPath, ok := eachMetric.GetField(sensorPathKey) + if ok { + fieldFilters := m.FieldFilter[sensorPath.(string)] + if len(fieldFilters) == 0 { + m.Log.Warnf("the %s 's field filters is empty...", sensorPath) + } + fieldFilters = append(fieldFilters, headerFilter...) + for _, filter := range fieldFilters { + if ok, matchKeys := matchField(filter, eachMetric.FieldList()); ok { + for _, realKey := range matchKeys { + eachMetric.RemoveField(realKey) + } + } + } + } + } + // field to tag + for _, eachMetric := range in { + sensorPath, ok := eachMetric.GetField(sensorPathKey) + if ok { + tags := m.Tag[sensorPath.(string)] + if len(tags) == 0 { + m.Log.Warnf("the %s 's tag is empty...", sensorPath) + } + tags = append(tags, headerTag...) + for _, tag := range tags { + if ok, matchKeys := matchField(tag, eachMetric.FieldList()); ok { + for _, realKey := range matchKeys { + value, ok := eachMetric.GetField(realKey) + if ok { + typeOfV := reflect.TypeOf(value) + if typeOfV.Name() != "string" { + if typeOfV.Name() != "int64" { + m.Log.Errorf("wrong with metric tag [%s %s], it's type is %s", sensorPath.(string), tag, typeOfV.Name()) + m.stop() + } else { + value = strconv.FormatInt(value.(int64), 10) + } + } + eachMetric.AddTag(realKey, value.(string)) + eachMetric.RemoveField(tag) + } + } + } + } + } + res = append(res, eachMetric) + } + + return res +} + +func matchField(key string, fields []*telegraf.Field) (bool, []string) { + var matches []string + for _, field := range fields { + if strings.HasSuffix(field.Key, key) { + matches = append(matches, field.Key) + } + } + if len(matches) > 0 { + return true, matches + } else { + return false, matches + } +} + +func init() { + processors.Add("metric_match", func() telegraf.Processor { + tags := map[string]string{"processor": "metric_match"} + grpcRegister := selfstat.Register("metric_match", "errors", tags) + logger := models.NewLogger("processors", "metric_match", "") + logger.OnErr(func() { + grpcRegister.Incr(1) + }) + return &MetricMatch{ + Log: logger, + } + }) +} + +func (c *MetricMatch) stop() { + log.SetOutput(os.Stderr) + log.Printf("I! telegraf stopped because error.") + os.Exit(1) +} \ No newline at end of file From 10ade1ce82805206397718d8999e8a1b0c5c37a8 Mon Sep 17 00:00:00 2001 From: awomanofsin <1115668298@qq.com> Date: Mon, 19 Apr 2021 17:23:47 +0800 Subject: [PATCH 2/4] telegraf plugins for huawei telemetry --- .../huawei_dialin/huawei-grpc-dialin.proto | 2 +- .../huawei_telemetry_dialin.go | 2 +- plugins/parsers/huawei_grpc_gpb/parser.go | 345 +++++ .../parsers/huawei_grpc_gpb/parser_test.go | 117 ++ .../telemetry_proto/HuaweiTelemetry.go | 95 ++ .../telemetry_proto/huawei-telemetry.pb.go | 1234 +++++++++++++++++ .../telemetry_proto/huawei-telemetry.proto | 81 ++ .../huawei_cpudefend.pb.go.txt | 0 .../telemetry_proto/huawei_ifm/a.go | 3 + plugins/parsers/huawei_grpc_json/parser.go | 294 ++++ plugins/parsers/registry.go | 29 +- 11 files changed, 2199 insertions(+), 3 deletions(-) create mode 100644 plugins/parsers/huawei_grpc_gpb/parser.go create mode 100644 plugins/parsers/huawei_grpc_gpb/parser_test.go create mode 100644 plugins/parsers/huawei_grpc_gpb/telemetry_proto/HuaweiTelemetry.go create mode 100644 plugins/parsers/huawei_grpc_gpb/telemetry_proto/huawei-telemetry.pb.go create mode 100644 plugins/parsers/huawei_grpc_gpb/telemetry_proto/huawei-telemetry.proto create mode 100644 plugins/parsers/huawei_grpc_gpb/telemetry_proto/huawei_cpudefend/huawei_cpudefend.pb.go.txt create mode 100644 plugins/parsers/huawei_grpc_gpb/telemetry_proto/huawei_ifm/a.go create mode 100644 plugins/parsers/huawei_grpc_json/parser.go diff --git a/plugins/inputs/huawei_telemetry_dialin/huawei_dialin/huawei-grpc-dialin.proto b/plugins/inputs/huawei_telemetry_dialin/huawei_dialin/huawei-grpc-dialin.proto index feecd67c5187e..0ce2727a3f9b2 100644 --- a/plugins/inputs/huawei_telemetry_dialin/huawei_dialin/huawei-grpc-dialin.proto +++ b/plugins/inputs/huawei_telemetry_dialin/huawei_dialin/huawei-grpc-dialin.proto @@ -18,6 +18,7 @@ message SubsArgs { //Subscribing request parameter. bool suppress_redundant = 8; //Redundancy suppression. The sampled data is not reported if the data content remains unchanged. 0: disabled, 1: enabled. uint64 delay_time = 9; //Delay time, which ranges from 100 to 60000, in ms. After data changes, the new data is reported after a specified delay. The new changes during the delay are accumulated. This parameter is used to prevent a large amount of data from being reported during service flapping. } +} message SubsReply { //Subscribing response parameter. uint32 subscription_id = 1; //If the subscribing is successful, the subscription ID is returned. If the subscribing fails, 0 is returned. uint64 request_id = 2; //ID of the subscribing request. @@ -36,4 +37,3 @@ message CancelReply { //Unsubscribing response parameter. string response_code = 2; //Return code. The value 200 indicates a success. string message = 3; //Error description. } -} \ No newline at end of file diff --git a/plugins/inputs/huawei_telemetry_dialin/huawei_telemetry_dialin.go b/plugins/inputs/huawei_telemetry_dialin/huawei_telemetry_dialin.go index 90865e2814e86..d51b8dcc14faa 100644 --- a/plugins/inputs/huawei_telemetry_dialin/huawei_telemetry_dialin.go +++ b/plugins/inputs/huawei_telemetry_dialin/huawei_telemetry_dialin.go @@ -7,7 +7,7 @@ import ( "github.com/influxdata/telegraf" internaltls "github.com/influxdata/telegraf/plugins/common/tls" "github.com/influxdata/telegraf/plugins/inputs" - "github.com/influxdata/telegraf/plugins/inputs/huawei_telemetry_dialin/huawei_dialin" + huawei_dialin "github.com/influxdata/telegraf/plugins/inputs/huawei_telemetry_dialin/huawei_dialin" "github.com/influxdata/telegraf/plugins/parsers" "google.golang.org/grpc" "google.golang.org/grpc/credentials" diff --git a/plugins/parsers/huawei_grpc_gpb/parser.go b/plugins/parsers/huawei_grpc_gpb/parser.go new file mode 100644 index 0000000000000..ca18b92a89f56 --- /dev/null +++ b/plugins/parsers/huawei_grpc_gpb/parser.go @@ -0,0 +1,345 @@ +package huawei_grpc_gpb + +import ( + "encoding/json" + "errors" + "fmt" + "github.com/influxdata/telegraf" + "github.com/influxdata/telegraf/metric" + telemetry "github.com/influxdata/telegraf/plugins/parsers/huawei_grpc_gpb/telemetry_proto" + "google.golang.org/protobuf/encoding/protojson" + "math" + "strings" + "time" + + "google.golang.org/protobuf/proto" + "log" + "strconv" +) + +const ( + KeySeperator = "." // A nested delimiter for Tag or Field + MsgTimeStampKeyName = "timestamp" + JsonMsgKeyName = "data_str" + GpbMsgKeyName = "data_gpb" + RowKeyName = "row" + TimeFormat = "2006-01-02 15:04:05" // time.RFC3339 + SensorPathKey = "sensor_path" +) + +type Parser struct { + Log telegraf.Logger +} + +func (p *Parser) Parse(buf []byte) ([]telegraf.Metric, error) { + telem_header := &telemetry.Telemetry{} + p.Log.Debugf("telemetry header : %s \n", telem_header) + errParse := proto.Unmarshal(buf, telem_header) + if errParse != nil { + return nil, errParse + } + dataGpb := telem_header.GetDataGpb() + if dataGpb != nil { + // get protoPath + protoPath := telem_header.ProtoPath + // trans telemetry header into map[string]interface{} + headerMap, errToMap := protoMsgToMap(telem_header) + if errToMap != nil { + return nil, errToMap + } + rows := dataGpb.GetRow() + var rowsInMaps []map[string]interface{} + var rowMsgs []proto.Message + // Service layer decoding + for _, row := range rows { + contentMsg, errGetType := telemetry.GetTypeByProtoPath(protoPath, telemetry.DEFAULT_VERSION) + if errGetType != nil { + p.Log.Errorf("E! [grpc parser] get type according protoPath: %v", errGetType) + return nil, errGetType + } + errDecode := proto.Unmarshal(row.Content, contentMsg) + + rowMap, errToMap := protoMsgToMap(contentMsg) + if errToMap != nil { + return nil, errToMap + } + rowMap[MsgTimeStampKeyName] = row.Timestamp + rowsInMaps = append(rowsInMaps, rowMap) + rowMsgs = append(rowMsgs, contentMsg) + if errDecode != nil { + return nil, errDecode + } + } + p.debugLog(telem_header, rowMsgs) + metrics, err := p.flattenProtoMsg(headerMap, rowsInMaps, "") + return metrics, err + } + return nil, nil +} + +func (p *Parser) debugLog(header *telemetry.Telemetry, rows []proto.Message) { + headerStr, err := json.MarshalIndent(header, "", " ") + if err == nil { + p.Log.Debugf("==================================== data start msg_timestamp: %v================================\n", header.MsgTimestamp) + p.Log.Debugf("header is : \n%s", headerStr) + } else { + p.Log.Debugf("error when log header") + } + p.Log.Debugf("rows are : \n") + for _, row := range rows { + rowStr, err := json.MarshalIndent(row, "", " ") + if err == nil { + p.Log.Debugf("%s", rowStr) + } else { + p.Log.Debugf("error when log rows") + } + } + p.Log.Debugf("==================================== data end ================================\n") +} + +// Convert the Proto Message to a Map +func protoMsgToMap(protoMsg proto.Message) (map[string]interface{}, error) { + // trans proto.Message into map[string]interface{}] + protoToJson := protojson.MarshalOptions{ + UseEnumNumbers: false, + UseProtoNames: true, + } + pb, errToJson := protoToJson.Marshal(protoMsg) + if errToJson != nil { + return nil, fmt.Errorf("[grpc parser] proto message decode to json: %v", errToJson) + } + var msgMap map[string]interface{} + errToMap := json.Unmarshal(pb, &msgMap) + if errToMap != nil { + return nil, fmt.Errorf("[grpc parser] proto message decodec to json: %v", errToMap) + } + return msgMap, nil +} + +func (p *Parser) ParseLine(line string) (telegraf.Metric, error) { + panic("implement me") +} + +func (p *Parser) SetDefaultTags(tags map[string]string) { + panic("implement me") +} + +func New() (*Parser, error) { + return &Parser{}, nil +} + +type KVStruct struct { + Fields map[string]interface{} +} + +func (kv *KVStruct) FullFlattenStruct(fieldname string, + v interface{}, + convertString bool, + convertBool bool) error { + if kv.Fields == nil { + kv.Fields = make(map[string]interface{}) + } + switch t := v.(type) { + case map[string]interface{}: + for k, v := range t { + fieldKey := k + if fieldname != "" { + fieldKey = fieldname + KeySeperator + fieldKey + } + err := kv.FullFlattenStruct(fieldKey, v, convertString, convertBool) + if err != nil { + return err + } + } + case []interface{}: + for i, v := range t { + fieldKey := strconv.Itoa(i) + if fieldname != "" { + fieldKey = fieldname + KeySeperator + fieldKey + } + err := kv.FullFlattenStruct(fieldKey, v, convertString, convertBool) + if err != nil { + return nil + } + } + case float64: + kv.Fields[fieldname] = v.(float64) + case float32: + kv.Fields[fieldname] = v.(float32) + case uint64: + kv.Fields[fieldname] = v.(uint64) + case uint32: + kv.Fields[fieldname] = v.(uint32) + case int64: + kv.Fields[fieldname] = v.(int64) + case int32: + kv.Fields[fieldname] = v.(int32) + case string: + isNum, num := convertToNum(v.(string)) + if isNum { + kv.Fields[fieldname] = num + } else { + kv.Fields[fieldname] = v.(string) + if convertString { + kv.Fields[fieldname] = v.(string) + } else { + return nil + } + } + case bool: + if convertBool { + kv.Fields[fieldname] = v.(bool) + } else { + return nil + } + case nil: + return nil + default: + return fmt.Errorf("key Value Flattener : got unexpected type %T with value %v (%s)", t, t, fieldname) + + } + return nil +} + +// check if the data is num and return as +func convertToNum(str string) (bool, int64) { + num, err := strconv.ParseInt(str, 10, 64) + if err != nil { + return false, 0 + } else { + return true, num + } +} + +func (p *Parser) flattenProtoMsg(telemetryHeader map[string]interface{}, rowsDecodec []map[string]interface{}, startFieldName string) ([]telegraf.Metric, error) { + kvHeader := KVStruct{} + errHeader := kvHeader.FullFlattenStruct("", telemetryHeader, true, true) + if errHeader != nil { + return nil, errHeader + } + + //// debug start + //p.Log.Debugf("D! -------------------------------------Header START-----------------------------------------\n") + //for k, v := range kvHeader.Fields { + // p.Log.Debugf("D! k: %s, v: %v ", k, v) + //} + //p.Log.Debugf("D! ------------------------------------- Header END -----------------------------------------\n") + //// debug end + + var metrics []telegraf.Metric + // one row into one metric + for _, rowDecodec := range rowsDecodec { + kvWithRow := KVStruct{} + errRows := kvWithRow.FullFlattenStruct(startFieldName, rowDecodec, true, true) + if errRows != nil { + return nil, errRows + } + fields, tm, errMerge := p.mergeMaps(kvHeader.Fields, kvWithRow.Fields) + if errMerge != nil { + return nil, errMerge + } + metric, err := metric.New(telemetryHeader[SensorPathKey].(string), nil, fields, tm) + if err != nil { + return nil, err + } + // debug start + //p.Log.Debugf("D! -------------------------------------Fields START time is %v-----------------------------------------\n", metric.Time()) + //for k, v := range metric.Fields() { + // p.Log.Debugf("k: %s, v: %v ", k, v) + //} + //p.Log.Debugf("D! ------------------------------------- Fields END -----------------------------------------\n") + // debug end + + metrics = append(metrics, metric) + } + return metrics, nil +} + +func (p *Parser) mergeMaps(maps ...map[string]interface{}) (map[string]interface{}, time.Time, error) { + res := make(map[string]interface{}) + timestamp := time.Time{} + for _, m := range maps { + for k, v := range m { + if strings.HasSuffix(k, "time") || strings.HasSuffix(k, MsgTimeStampKeyName) { + timeStruct, timeStr, errCal := calTimeByStamp(v) + if errCal != nil { + return nil, time.Time{}, fmt.Errorf("E! [grpc parser] when calculate time, key name is %s, time is %t, error is %v", k, v, errCal) + } + if k == MsgTimeStampKeyName { + timestamp = timeStruct + p.Log.Debugf("D! the row timestamp is %s\n", timestamp.Format(TimeFormat)) + continue + } + if timeStr != "" { + res[k] = timeStr + continue + } + } + res[k] = v + } + } + return res, timestamp, nil +} + +// timestamp transfer into time +// ten bit timestamp with second, 13 bit timestamp with second +// time.Unix(s,ns) +func calTimeByStamp(v interface{}) (time.Time, string, error) { + var sec int64 + var nsec int64 + switch v.(type) { + case float64: + vInFloat64 := v.(float64) + if vInFloat64 < math.Pow10(11) { + sec = int64(vInFloat64) + nsec = 0 + } + if vInFloat64 > math.Pow10(12) { + sec = int64(vInFloat64 / 1000) + nsec = (int64(vInFloat64) % 1000) * 1000 * 1000 + } + case int64: + vInInt64 := v.(int64) + if float64(vInInt64) < math.Pow10(11) { + sec = vInInt64 + nsec = 0 + } + if float64(vInInt64) > math.Pow10(12) { + sec = vInInt64 / 1000 + nsec = (vInInt64 % 1000) * 1000 * 1000 + } + case uint64: + vInUint64 := v.(uint64) + if float64(vInUint64) < math.Pow10(11) { + sec = int64(vInUint64) + nsec = 0 + } + if float64(vInUint64) > math.Pow10(12) { + sec = int64(vInUint64 / 1000) + nsec = int64((vInUint64 % 1000) * 1000 * 1000) + } + case string: + if strings.Index(v.(string), ":") > -1 { + return time.Time{}, v.(string), nil + } + timeInNum, errToNum := strconv.ParseUint(v.(string), 10, 64) + if errToNum != nil { + log.Printf("E! [grpc.parser.calTimeByStamp] v: %t , error : %v", v, errToNum) + } else { + if float64(timeInNum) < math.Pow10(11) { + sec = int64(timeInNum) + nsec = 0 + } + if float64(timeInNum) > math.Pow10(12) { + sec = int64(timeInNum / 1000) + nsec = int64((timeInNum % 1000) * 1000 * 1000) + } + } + } + + if sec == 0 { + return time.Time{}, "", errors.New("calculate error") + } + time := time.Unix(sec, nsec) + return time, time.Format(TimeFormat), nil +} diff --git a/plugins/parsers/huawei_grpc_gpb/parser_test.go b/plugins/parsers/huawei_grpc_gpb/parser_test.go new file mode 100644 index 0000000000000..50a51a2c7c7b4 --- /dev/null +++ b/plugins/parsers/huawei_grpc_gpb/parser_test.go @@ -0,0 +1,117 @@ +package huawei_grpc_gpb + +import ( + "fmt" + "github.com/golang/protobuf/proto" + "github.com/influxdata/telegraf/plugins/common/telemetry_proto" + "github.com/influxdata/telegraf/plugins/common/telemetry_proto/huawei_ifm" + "github.com/influxdata/telegraf/testutil" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func marshalTelemIfm(index uint64) ([]byte , error) { + ifmByte, err := marshalIfm(index) + //var testN uint32 = 23 + //debugByte, err := marshalDebug(testN) + if err == nil { + row := &telemetry.TelemetryRowGPB{ + //Content: debugByte, + Content: ifmByte, + Timestamp: uint64(1614160758), + //ifmByte, + } + rows := []*telemetry.TelemetryRowGPB{row} + gpbTable := telemetry.TelemetryGPBTable{ + Row: rows, + Delete: nil, + Generator: nil, + } + //telemetryGPBTable := &telemetry.TelemetryGPBTable{} + //teleStructTest := &telemetry.Telemetry{ + // SensorPath: "sensormine", + //} + teleStruct := &telemetry.Telemetry{ + NodeIdStr: "nodeid", + SubscriptionIdStr: "xx", + SensorPath: "huawei-ifm:ifm/interfaces/interface", + //SensorPath: "huawei-debug:debug/interfaces/interface", + ProtoPath: "huawei_ifm.Ifm", + CollectionId: index, + CollectionStartTime: 0, + MsgTimestamp: uint64(1614160758), + DataGpb: &gpbTable, + CollectionEndTime: 0, + CurrentPeriod: 0, + ExceptDesc: "desc", + ProductName: "pro", + Encoding: 0, + DataStr: "dd", + NeId: "ss233333333333333333", + SoftwareVersion: "20.1", + } + + return proto.Marshal(teleStruct) + } + return nil,nil +} + +func marshalIfm (index uint64) ([]byte, error){ + ipv4ConflictEnable := huawei_ifm.Ifm_Global_Ipv4ConflictEnable{PreemptEnable: true} + ipv6ConflictEnable := huawei_ifm.Ifm_Global_Ipv6ConflictEnable{PreemptEnable: false} + fimIfmGlobal := huawei_ifm.Ifm_Global_FimIfmGlobal{ + TrunkDelaysendTime: 110, + } + global := huawei_ifm.Ifm_Global { + StatisticInterval: 388, + Ipv4IgnorePrimarySub: false, + Ipv4ConflictEnable: &ipv4ConflictEnable, + Ipv6ConflictEnable: &ipv6ConflictEnable, + FimIfmGlobal: &fimIfmGlobal, + FimTrunkLocalfwd: nil, + VeGroups: nil, + } + len := 2 + intefs := [2]*huawei_ifm.Ifm_Interfaces_Interface{} + for j := 1; j<=len;j++ { + interface2 := huawei_ifm.Ifm_Interfaces_Interface{ + Name: "interface"+strconv.Itoa(int(index)), + Index: uint32(j), + Position: "huaweiggg2", + ParentName: "nanjinghuawei2", + Number: "2234", + Description: "woyonglaiceshi2", + AggregationName: "", + IsL2Switch: false, + MacAddress: "45sddfs5wr12", + VsName: "vsss2", + } + intefs[j-1]=&interface2 + } + interfaces := huawei_ifm.Ifm_Interfaces{Interface: intefs[0:]} + ifm := &huawei_ifm.Ifm{ + Global: &global, + Interfaces: &interfaces, + Damp: nil, + AutoRecoveryTimes: nil, + StaticDimensionRanges: nil, + Ipv4InterfaceCount: nil, + RemoteInterfaces: nil, + HdlcDamp: nil, + } + return proto.Marshal(ifm) +} + +func TestDataPublish(t *testing.T) { + telebyte, err := marshalTelemIfm(uint64(1)) + if err != nil { + fmt.Println("ERR to connect: "+strconv.Itoa((1))) + } + tes := testutil.Logger{} + parser := &Parser{Log:tes} + metrics, err := parser.Parse([]byte(telebyte)) + require.NoError(t, err) + assert.Equal(t, "huawei-ifm:ifm/interfaces/interface", metrics[0].Name()) +} \ No newline at end of file diff --git a/plugins/parsers/huawei_grpc_gpb/telemetry_proto/HuaweiTelemetry.go b/plugins/parsers/huawei_grpc_gpb/telemetry_proto/HuaweiTelemetry.go new file mode 100644 index 0000000000000..ab7db46ed636c --- /dev/null +++ b/plugins/parsers/huawei_grpc_gpb/telemetry_proto/HuaweiTelemetry.go @@ -0,0 +1,95 @@ +package telemetry + +import ( + "fmt" + "github.com/influxdata/telegraf/plugins/parsers/huawei_grpc_gpb/telemetry_proto/huawei_debug" + "github.com/influxdata/telegraf/plugins/parsers/huawei_grpc_gpb/telemetry_proto/huawei_ifm" + "google.golang.org/protobuf/proto" + "reflect" +) + +// struct reflect.Type set +type ProtoTypes struct { + typeSet []reflect.Type // Array can not repeat +} + +// the key struct in map +type PathKey struct { + ProtoPath string + Version string +} + +// proto key value +type ProtoOrganizeType int + +const ( + // proto type mark represents huawei, put them under one proto, and encaps them into type + PROTO_HUAWEI_TYPE = 0 + PROTO_IETF_TYPE = 1 +) + +const ( + DEFAULT_VERSION = "1.0" +) + +// get all ProtoPath +func GetProtoPaths() []*PathKey { + paths := make([]*PathKey, len(pathTypeMap)) + i := 0 + for key := range pathTypeMap { + path := key + paths[i] = &path + i++ + } + return paths +} +// +// get reflect.Type set pointer by protokey +func GetProtoTypeSetByKey(p *PathKey) *ProtoTypes { + set := &ProtoTypes{ + typeSet: pathTypeMap[*p], + } + if set.typeSet == nil { + return nil + } + return set +} + +// +// get protoPath with protoPath and version +func GetTypeByProtoPath(protoPath string, version string) (proto.Message, error) { + if version == "" { + version = DEFAULT_VERSION + } + mapping := GetProtoTypeSetByKey( + &PathKey{ + ProtoPath: protoPath, + Version: DEFAULT_VERSION}) + if mapping == nil { + return nil, fmt.Errorf("the proto type is nil , protoPath is %s", protoPath) + } + typeInMap := mapping.GetTypesByProtoOrg(PROTO_HUAWEI_TYPE) // using reflect + elem := typeInMap.Elem() + reflectType := reflect.New(elem) + contentType := reflectType.Interface().(proto.Message) + return contentType, nil +} + +// +// get proto type by proto +func (p *ProtoTypes) GetTypesByProtoOrg(orgType ProtoOrganizeType) reflect.Type { + varTypes := p.typeSet + if varTypes == nil { + return nil + } + if len(varTypes) > int(orgType) { + return varTypes[orgType] + } + return nil +} + +// one map key: protoPath + version, value : reflect[] +var pathTypeMap = map[PathKey][]reflect.Type{PathKey{ + ProtoPath: "huawei_ifm.Ifm", Version: "1.0"}: []reflect.Type{reflect.TypeOf((*huawei_ifm.Ifm)(nil))}, + PathKey{ProtoPath: "huawei_debug.Debug", Version: "1.0"}: []reflect.Type{reflect.TypeOf((*huawei_debug.Debug)(nil))}, +} diff --git a/plugins/parsers/huawei_grpc_gpb/telemetry_proto/huawei-telemetry.pb.go b/plugins/parsers/huawei_grpc_gpb/telemetry_proto/huawei-telemetry.pb.go new file mode 100644 index 0000000000000..b6c812cf761ae --- /dev/null +++ b/plugins/parsers/huawei_grpc_gpb/telemetry_proto/huawei-telemetry.pb.go @@ -0,0 +1,1234 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0-devel +// protoc v3.15.8 +// source: huawei-telemetry.proto + +package telemetry + +import ( + 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) +) + +type Telemetry_Encoding int32 + +const ( + Telemetry_Encoding_GPB Telemetry_Encoding = 0 //GPB encoding format. + Telemetry_Encoding_JSON Telemetry_Encoding = 1 //JSON encoding format. +) + +// Enum value maps for Telemetry_Encoding. +var ( + Telemetry_Encoding_name = map[int32]string{ + 0: "Encoding_GPB", + 1: "Encoding_JSON", + } + Telemetry_Encoding_value = map[string]int32{ + "Encoding_GPB": 0, + "Encoding_JSON": 1, + } +) + +func (x Telemetry_Encoding) Enum() *Telemetry_Encoding { + p := new(Telemetry_Encoding) + *p = x + return p +} + +func (x Telemetry_Encoding) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Telemetry_Encoding) Descriptor() protoreflect.EnumDescriptor { + return file_huawei_telemetry_proto_enumTypes[0].Descriptor() +} + +func (Telemetry_Encoding) Type() protoreflect.EnumType { + return &file_huawei_telemetry_proto_enumTypes[0] +} + +func (x Telemetry_Encoding) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Telemetry_Encoding.Descriptor instead. +func (Telemetry_Encoding) EnumDescriptor() ([]byte, []int) { + return file_huawei_telemetry_proto_rawDescGZIP(), []int{0, 0} +} + +type TelemetrySelfDefinedEvent_ThresholdRelation int32 + +const ( + TelemetrySelfDefinedEvent_ThresholdRelation_INVALID TelemetrySelfDefinedEvent_ThresholdRelation = 0 //The relationship between thresholds is not configured. + TelemetrySelfDefinedEvent_ThresholdRelation_AND TelemetrySelfDefinedEvent_ThresholdRelation = 1 //The relationship between thresholds is And. + TelemetrySelfDefinedEvent_ThresholdRelation_OR TelemetrySelfDefinedEvent_ThresholdRelation = 2 //The relationship between thresholds is Or. +) + +// Enum value maps for TelemetrySelfDefinedEvent_ThresholdRelation. +var ( + TelemetrySelfDefinedEvent_ThresholdRelation_name = map[int32]string{ + 0: "ThresholdRelation_INVALID", + 1: "ThresholdRelation_AND", + 2: "ThresholdRelation_OR", + } + TelemetrySelfDefinedEvent_ThresholdRelation_value = map[string]int32{ + "ThresholdRelation_INVALID": 0, + "ThresholdRelation_AND": 1, + "ThresholdRelation_OR": 2, + } +) + +func (x TelemetrySelfDefinedEvent_ThresholdRelation) Enum() *TelemetrySelfDefinedEvent_ThresholdRelation { + p := new(TelemetrySelfDefinedEvent_ThresholdRelation) + *p = x + return p +} + +func (x TelemetrySelfDefinedEvent_ThresholdRelation) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (TelemetrySelfDefinedEvent_ThresholdRelation) Descriptor() protoreflect.EnumDescriptor { + return file_huawei_telemetry_proto_enumTypes[1].Descriptor() +} + +func (TelemetrySelfDefinedEvent_ThresholdRelation) Type() protoreflect.EnumType { + return &file_huawei_telemetry_proto_enumTypes[1] +} + +func (x TelemetrySelfDefinedEvent_ThresholdRelation) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use TelemetrySelfDefinedEvent_ThresholdRelation.Descriptor instead. +func (TelemetrySelfDefinedEvent_ThresholdRelation) EnumDescriptor() ([]byte, []int) { + return file_huawei_telemetry_proto_rawDescGZIP(), []int{7, 0} +} + +type TelemetryThreshold_ThresholdOpType int32 + +const ( + TelemetryThreshold_ThresholdOpType_EQ TelemetryThreshold_ThresholdOpType = 0 //The actual value in the data sent equals to the configured data threshold. + TelemetryThreshold_ThresholdOpType_GT TelemetryThreshold_ThresholdOpType = 1 //The actual value in the data sent is greater than the configured data threshold. + TelemetryThreshold_ThresholdOpType_GE TelemetryThreshold_ThresholdOpType = 2 //The actual value in the data sent is greater than or equals to the configured data threshold. + TelemetryThreshold_ThresholdOpType_LT TelemetryThreshold_ThresholdOpType = 3 //The actual value in the data sent is less than the configured data threshold. + TelemetryThreshold_ThresholdOpType_LE TelemetryThreshold_ThresholdOpType = 4 //The actual value in the data sent is less than or equals to the configured data threshold. +) + +// Enum value maps for TelemetryThreshold_ThresholdOpType. +var ( + TelemetryThreshold_ThresholdOpType_name = map[int32]string{ + 0: "ThresholdOpType_EQ", + 1: "ThresholdOpType_GT", + 2: "ThresholdOpType_GE", + 3: "ThresholdOpType_LT", + 4: "ThresholdOpType_LE", + } + TelemetryThreshold_ThresholdOpType_value = map[string]int32{ + "ThresholdOpType_EQ": 0, + "ThresholdOpType_GT": 1, + "ThresholdOpType_GE": 2, + "ThresholdOpType_LT": 3, + "ThresholdOpType_LE": 4, + } +) + +func (x TelemetryThreshold_ThresholdOpType) Enum() *TelemetryThreshold_ThresholdOpType { + p := new(TelemetryThreshold_ThresholdOpType) + *p = x + return p +} + +func (x TelemetryThreshold_ThresholdOpType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (TelemetryThreshold_ThresholdOpType) Descriptor() protoreflect.EnumDescriptor { + return file_huawei_telemetry_proto_enumTypes[2].Descriptor() +} + +func (TelemetryThreshold_ThresholdOpType) Type() protoreflect.EnumType { + return &file_huawei_telemetry_proto_enumTypes[2] +} + +func (x TelemetryThreshold_ThresholdOpType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use TelemetryThreshold_ThresholdOpType.Descriptor instead. +func (TelemetryThreshold_ThresholdOpType) EnumDescriptor() ([]byte, []int) { + return file_huawei_telemetry_proto_rawDescGZIP(), []int{9, 0} +} + +type Telemetry struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeIdStr string `protobuf:"bytes,1,opt,name=node_id_str,json=nodeIdStr,proto3" json:"node_id_str,omitempty"` //Device name. + SubscriptionIdStr string `protobuf:"bytes,2,opt,name=subscription_id_str,json=subscriptionIdStr,proto3" json:"subscription_id_str,omitempty"` //Subscription name during static subscription configuration. + SensorPath string `protobuf:"bytes,3,opt,name=sensor_path,json=sensorPath,proto3" json:"sensor_path,omitempty"` //Subscription path. + ProtoPath string `protobuf:"bytes,13,opt,name=proto_path,json=protoPath,proto3" json:"proto_path,omitempty"` //Message path for the sampling path in the proto file. + CollectionId uint64 `protobuf:"varint,4,opt,name=collection_id,json=collectionId,proto3" json:"collection_id,omitempty"` //Sampling round. + CollectionStartTime uint64 `protobuf:"varint,5,opt,name=collection_start_time,json=collectionStartTime,proto3" json:"collection_start_time,omitempty"` //Start time of a sampling round. + MsgTimestamp uint64 `protobuf:"varint,6,opt,name=msg_timestamp,json=msgTimestamp,proto3" json:"msg_timestamp,omitempty"` //Timestamp when the current message is generated. + DataGpb *TelemetryGPBTable `protobuf:"bytes,7,opt,name=data_gpb,json=dataGpb,proto3" json:"data_gpb,omitempty"` //Indicates that the data carried is defined in TelemetryGPBTable. + CollectionEndTime uint64 `protobuf:"varint,8,opt,name=collection_end_time,json=collectionEndTime,proto3" json:"collection_end_time,omitempty"` //End time of a sampling round. + CurrentPeriod uint32 `protobuf:"varint,9,opt,name=current_period,json=currentPeriod,proto3" json:"current_period,omitempty"` //Sampling precision, in milliseconds. + ExceptDesc string `protobuf:"bytes,10,opt,name=except_desc,json=exceptDesc,proto3" json:"except_desc,omitempty"` //Exception description. It is used to report exception information when a sampling exception occurs. + ProductName string `protobuf:"bytes,11,opt,name=product_name,json=productName,proto3" json:"product_name,omitempty"` //Product name. + Encoding Telemetry_Encoding `protobuf:"varint,12,opt,name=encoding,proto3,enum=telemetry.Telemetry_Encoding" json:"encoding,omitempty"` //Data encoding format. If the GPB encoding format is used, the data_gpb field is valid. Otherwise, the data_str field is valid. + DataStr string `protobuf:"bytes,14,opt,name=data_str,json=dataStr,proto3" json:"data_str,omitempty"` //This field is valid only when a non-GPB encoding format is used. + NeId string `protobuf:"bytes,15,opt,name=ne_id,json=neId,proto3" json:"ne_id,omitempty"` //Unique ID of an NE. In the gateway scenario, this parameter is used to identify the NE to which data belongs. + SoftwareVersion string `protobuf:"bytes,16,opt,name=software_version,json=softwareVersion,proto3" json:"software_version,omitempty"` //Software version number. +} + +func (x *Telemetry) Reset() { + *x = Telemetry{} + if protoimpl.UnsafeEnabled { + mi := &file_huawei_telemetry_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Telemetry) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Telemetry) ProtoMessage() {} + +func (x *Telemetry) ProtoReflect() protoreflect.Message { + mi := &file_huawei_telemetry_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 Telemetry.ProtoReflect.Descriptor instead. +func (*Telemetry) Descriptor() ([]byte, []int) { + return file_huawei_telemetry_proto_rawDescGZIP(), []int{0} +} + +func (x *Telemetry) GetNodeIdStr() string { + if x != nil { + return x.NodeIdStr + } + return "" +} + +func (x *Telemetry) GetSubscriptionIdStr() string { + if x != nil { + return x.SubscriptionIdStr + } + return "" +} + +func (x *Telemetry) GetSensorPath() string { + if x != nil { + return x.SensorPath + } + return "" +} + +func (x *Telemetry) GetProtoPath() string { + if x != nil { + return x.ProtoPath + } + return "" +} + +func (x *Telemetry) GetCollectionId() uint64 { + if x != nil { + return x.CollectionId + } + return 0 +} + +func (x *Telemetry) GetCollectionStartTime() uint64 { + if x != nil { + return x.CollectionStartTime + } + return 0 +} + +func (x *Telemetry) GetMsgTimestamp() uint64 { + if x != nil { + return x.MsgTimestamp + } + return 0 +} + +func (x *Telemetry) GetDataGpb() *TelemetryGPBTable { + if x != nil { + return x.DataGpb + } + return nil +} + +func (x *Telemetry) GetCollectionEndTime() uint64 { + if x != nil { + return x.CollectionEndTime + } + return 0 +} + +func (x *Telemetry) GetCurrentPeriod() uint32 { + if x != nil { + return x.CurrentPeriod + } + return 0 +} + +func (x *Telemetry) GetExceptDesc() string { + if x != nil { + return x.ExceptDesc + } + return "" +} + +func (x *Telemetry) GetProductName() string { + if x != nil { + return x.ProductName + } + return "" +} + +func (x *Telemetry) GetEncoding() Telemetry_Encoding { + if x != nil { + return x.Encoding + } + return Telemetry_Encoding_GPB +} + +func (x *Telemetry) GetDataStr() string { + if x != nil { + return x.DataStr + } + return "" +} + +func (x *Telemetry) GetNeId() string { + if x != nil { + return x.NeId + } + return "" +} + +func (x *Telemetry) GetSoftwareVersion() string { + if x != nil { + return x.SoftwareVersion + } + return "" +} + +type TelemetryGPBTable struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Row []*TelemetryRowGPB `protobuf:"bytes,1,rep,name=row,proto3" json:"row,omitempty"` //Array definition. Its member is TelemetryRowGPB structure. + Delete []*DataPath `protobuf:"bytes,2,rep,name=delete,proto3" json:"delete,omitempty"` //Delete the data path. + Generator *Generator `protobuf:"bytes,3,opt,name=generator,proto3" json:"generator,omitempty"` //Data source description. This applies to the OnChange+ service that requires high reliability. +} + +func (x *TelemetryGPBTable) Reset() { + *x = TelemetryGPBTable{} + if protoimpl.UnsafeEnabled { + mi := &file_huawei_telemetry_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TelemetryGPBTable) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TelemetryGPBTable) ProtoMessage() {} + +func (x *TelemetryGPBTable) ProtoReflect() protoreflect.Message { + mi := &file_huawei_telemetry_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 TelemetryGPBTable.ProtoReflect.Descriptor instead. +func (*TelemetryGPBTable) Descriptor() ([]byte, []int) { + return file_huawei_telemetry_proto_rawDescGZIP(), []int{1} +} + +func (x *TelemetryGPBTable) GetRow() []*TelemetryRowGPB { + if x != nil { + return x.Row + } + return nil +} + +func (x *TelemetryGPBTable) GetDelete() []*DataPath { + if x != nil { + return x.Delete + } + return nil +} + +func (x *TelemetryGPBTable) GetGenerator() *Generator { + if x != nil { + return x.Generator + } + return nil +} + +type Generator struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + GeneratorId uint64 `protobuf:"varint,1,opt,name=generator_id,json=generatorId,proto3" json:"generator_id,omitempty"` //Data source ID. Multiple data sources can provide data concurrently and maintain their own reliability. + GeneratorSn uint32 `protobuf:"varint,2,opt,name=generator_sn,json=generatorSn,proto3" json:"generator_sn,omitempty"` //Message sequence number. The sequence numbers of messages sent by each data source must be consecutive. If the sequence numbers are not consecutive, data out-of-synchronization occurs, the collector should support automatic disconnection and reconnection in this case. The value ranges from 0 to 0xFFFFFFFF and can be reversed. + GeneratorSync bool `protobuf:"varint,3,opt,name=generator_sync,json=generatorSync,proto3" json:"generator_sync,omitempty"` //Data source synchronization Indicates whether to perform OnChange full data synchronization. In addition, if the value is true and no data is contained, the synchronization is complete. +} + +func (x *Generator) Reset() { + *x = Generator{} + if protoimpl.UnsafeEnabled { + mi := &file_huawei_telemetry_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Generator) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Generator) ProtoMessage() {} + +func (x *Generator) ProtoReflect() protoreflect.Message { + mi := &file_huawei_telemetry_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 Generator.ProtoReflect.Descriptor instead. +func (*Generator) Descriptor() ([]byte, []int) { + return file_huawei_telemetry_proto_rawDescGZIP(), []int{2} +} + +func (x *Generator) GetGeneratorId() uint64 { + if x != nil { + return x.GeneratorId + } + return 0 +} + +func (x *Generator) GetGeneratorSn() uint32 { + if x != nil { + return x.GeneratorSn + } + return 0 +} + +func (x *Generator) GetGeneratorSync() bool { + if x != nil { + return x.GeneratorSync + } + return false +} + +type TelemetryRowGPB struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Timestamp uint64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` //Timestamp of the current sampling instance. + Content []byte `protobuf:"bytes,11,opt,name=content,proto3" json:"content,omitempty"` //Sampling instance data carried. The sensor_path field must be considered to determine which .proto file is used for encoding. +} + +func (x *TelemetryRowGPB) Reset() { + *x = TelemetryRowGPB{} + if protoimpl.UnsafeEnabled { + mi := &file_huawei_telemetry_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TelemetryRowGPB) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TelemetryRowGPB) ProtoMessage() {} + +func (x *TelemetryRowGPB) ProtoReflect() protoreflect.Message { + mi := &file_huawei_telemetry_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 TelemetryRowGPB.ProtoReflect.Descriptor instead. +func (*TelemetryRowGPB) Descriptor() ([]byte, []int) { + return file_huawei_telemetry_proto_rawDescGZIP(), []int{3} +} + +func (x *TelemetryRowGPB) GetTimestamp() uint64 { + if x != nil { + return x.Timestamp + } + return 0 +} + +func (x *TelemetryRowGPB) GetContent() []byte { + if x != nil { + return x.Content + } + return nil +} + +type DataPath struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Timestamp uint64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` //Timestamp of the current sampling instance. + Path *Path `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"` //A data tree node that contains only the data path and key field information. +} + +func (x *DataPath) Reset() { + *x = DataPath{} + if protoimpl.UnsafeEnabled { + mi := &file_huawei_telemetry_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DataPath) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DataPath) ProtoMessage() {} + +func (x *DataPath) ProtoReflect() protoreflect.Message { + mi := &file_huawei_telemetry_proto_msgTypes[4] + 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 DataPath.ProtoReflect.Descriptor instead. +func (*DataPath) Descriptor() ([]byte, []int) { + return file_huawei_telemetry_proto_rawDescGZIP(), []int{4} +} + +func (x *DataPath) GetTimestamp() uint64 { + if x != nil { + return x.Timestamp + } + return 0 +} + +func (x *DataPath) GetPath() *Path { + if x != nil { + return x.Path + } + return nil +} + +type Path struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Node []*PathElem `protobuf:"bytes,1,rep,name=node,proto3" json:"node,omitempty"` //A data tree node that contains only the data path and key field information. +} + +func (x *Path) Reset() { + *x = Path{} + if protoimpl.UnsafeEnabled { + mi := &file_huawei_telemetry_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Path) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Path) ProtoMessage() {} + +func (x *Path) ProtoReflect() protoreflect.Message { + mi := &file_huawei_telemetry_proto_msgTypes[5] + 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 Path.ProtoReflect.Descriptor instead. +func (*Path) Descriptor() ([]byte, []int) { + return file_huawei_telemetry_proto_rawDescGZIP(), []int{5} +} + +func (x *Path) GetNode() []*PathElem { + if x != nil { + return x.Node + } + return nil +} + +type PathElem struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` //Data tree node name + Key map[string]string `protobuf:"bytes,2,rep,name=key,proto3" json:"key,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` //Key field name and value mapping table of the data tree node +} + +func (x *PathElem) Reset() { + *x = PathElem{} + if protoimpl.UnsafeEnabled { + mi := &file_huawei_telemetry_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PathElem) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PathElem) ProtoMessage() {} + +func (x *PathElem) ProtoReflect() protoreflect.Message { + mi := &file_huawei_telemetry_proto_msgTypes[6] + 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 PathElem.ProtoReflect.Descriptor instead. +func (*PathElem) Descriptor() ([]byte, []int) { + return file_huawei_telemetry_proto_rawDescGZIP(), []int{6} +} + +func (x *PathElem) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *PathElem) GetKey() map[string]string { + if x != nil { + return x.Key + } + return nil +} + +type TelemetrySelfDefinedEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` //Sampling path that triggers the customized event, which describes the method of parsing the content. + ProtoPath string `protobuf:"bytes,13,opt,name=proto_path,json=protoPath,proto3" json:"proto_path,omitempty"` //Message path for the sampling path in the proto file. + Level uint32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` //Level of the user-defined event. + Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` //Description of the user-defined event. + FieldName string `protobuf:"bytes,4,opt,name=fieldName,proto3" json:"fieldName,omitempty"` //Name of the field that triggers the customized event. + FieldValue uint32 `protobuf:"varint,5,opt,name=fieldValue,proto3" json:"fieldValue,omitempty"` //Value of the field that triggers the customized event. + DataThreshold *TelemetrySelfDefineThresTable `protobuf:"bytes,6,opt,name=data_threshold,json=dataThreshold,proto3" json:"data_threshold,omitempty"` //Threshold filter criteria when the customized event is triggered. + ThresholdRelation TelemetrySelfDefinedEvent_ThresholdRelation `protobuf:"varint,7,opt,name=thresholdRelation,proto3,enum=telemetry.TelemetrySelfDefinedEvent_ThresholdRelation" json:"thresholdRelation,omitempty"` //Relationship between threshold filter criteria when the customized event is triggered. + Content []byte `protobuf:"bytes,8,opt,name=content,proto3" json:"content,omitempty"` //Sampled data that triggers the customized event. +} + +func (x *TelemetrySelfDefinedEvent) Reset() { + *x = TelemetrySelfDefinedEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_huawei_telemetry_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TelemetrySelfDefinedEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TelemetrySelfDefinedEvent) ProtoMessage() {} + +func (x *TelemetrySelfDefinedEvent) ProtoReflect() protoreflect.Message { + mi := &file_huawei_telemetry_proto_msgTypes[7] + 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 TelemetrySelfDefinedEvent.ProtoReflect.Descriptor instead. +func (*TelemetrySelfDefinedEvent) Descriptor() ([]byte, []int) { + return file_huawei_telemetry_proto_rawDescGZIP(), []int{7} +} + +func (x *TelemetrySelfDefinedEvent) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +func (x *TelemetrySelfDefinedEvent) GetProtoPath() string { + if x != nil { + return x.ProtoPath + } + return "" +} + +func (x *TelemetrySelfDefinedEvent) GetLevel() uint32 { + if x != nil { + return x.Level + } + return 0 +} + +func (x *TelemetrySelfDefinedEvent) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *TelemetrySelfDefinedEvent) GetFieldName() string { + if x != nil { + return x.FieldName + } + return "" +} + +func (x *TelemetrySelfDefinedEvent) GetFieldValue() uint32 { + if x != nil { + return x.FieldValue + } + return 0 +} + +func (x *TelemetrySelfDefinedEvent) GetDataThreshold() *TelemetrySelfDefineThresTable { + if x != nil { + return x.DataThreshold + } + return nil +} + +func (x *TelemetrySelfDefinedEvent) GetThresholdRelation() TelemetrySelfDefinedEvent_ThresholdRelation { + if x != nil { + return x.ThresholdRelation + } + return TelemetrySelfDefinedEvent_ThresholdRelation_INVALID +} + +func (x *TelemetrySelfDefinedEvent) GetContent() []byte { + if x != nil { + return x.Content + } + return nil +} + +type TelemetrySelfDefineThresTable struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Row []*TelemetryThreshold `protobuf:"bytes,1,rep,name=row,proto3" json:"row,omitempty"` //Multiple thresholds are included. +} + +func (x *TelemetrySelfDefineThresTable) Reset() { + *x = TelemetrySelfDefineThresTable{} + if protoimpl.UnsafeEnabled { + mi := &file_huawei_telemetry_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TelemetrySelfDefineThresTable) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TelemetrySelfDefineThresTable) ProtoMessage() {} + +func (x *TelemetrySelfDefineThresTable) ProtoReflect() protoreflect.Message { + mi := &file_huawei_telemetry_proto_msgTypes[8] + 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 TelemetrySelfDefineThresTable.ProtoReflect.Descriptor instead. +func (*TelemetrySelfDefineThresTable) Descriptor() ([]byte, []int) { + return file_huawei_telemetry_proto_rawDescGZIP(), []int{8} +} + +func (x *TelemetrySelfDefineThresTable) GetRow() []*TelemetryThreshold { + if x != nil { + return x.Row + } + return nil +} + +type TelemetryThreshold struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ThresholdValue uint32 `protobuf:"varint,1,opt,name=thresholdValue,proto3" json:"thresholdValue,omitempty"` //Delivered threshold. + ThresholdOpType TelemetryThreshold_ThresholdOpType `protobuf:"varint,2,opt,name=thresholdOpType,proto3,enum=telemetry.TelemetryThreshold_ThresholdOpType" json:"thresholdOpType,omitempty"` //Threshold on the device. +} + +func (x *TelemetryThreshold) Reset() { + *x = TelemetryThreshold{} + if protoimpl.UnsafeEnabled { + mi := &file_huawei_telemetry_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TelemetryThreshold) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TelemetryThreshold) ProtoMessage() {} + +func (x *TelemetryThreshold) ProtoReflect() protoreflect.Message { + mi := &file_huawei_telemetry_proto_msgTypes[9] + 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 TelemetryThreshold.ProtoReflect.Descriptor instead. +func (*TelemetryThreshold) Descriptor() ([]byte, []int) { + return file_huawei_telemetry_proto_rawDescGZIP(), []int{9} +} + +func (x *TelemetryThreshold) GetThresholdValue() uint32 { + if x != nil { + return x.ThresholdValue + } + return 0 +} + +func (x *TelemetryThreshold) GetThresholdOpType() TelemetryThreshold_ThresholdOpType { + if x != nil { + return x.ThresholdOpType + } + return TelemetryThreshold_ThresholdOpType_EQ +} + +var File_huawei_telemetry_proto protoreflect.FileDescriptor + +var file_huawei_telemetry_proto_rawDesc = []byte{ + 0x0a, 0x16, 0x68, 0x75, 0x61, 0x77, 0x65, 0x69, 0x2d, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, + 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, + 0x74, 0x72, 0x79, 0x22, 0xb4, 0x05, 0x0a, 0x09, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, + 0x79, 0x12, 0x1e, 0x0a, 0x0b, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x5f, 0x73, 0x74, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x53, 0x74, + 0x72, 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x69, 0x64, 0x5f, 0x73, 0x74, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, + 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x53, 0x74, + 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x74, 0x68, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x50, 0x61, + 0x74, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x5f, 0x70, 0x61, 0x74, 0x68, + 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x61, 0x74, + 0x68, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x73, + 0x67, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x0c, 0x6d, 0x73, 0x67, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, + 0x37, 0x0a, 0x08, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x67, 0x70, 0x62, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x65, + 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x47, 0x50, 0x42, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, + 0x07, 0x64, 0x61, 0x74, 0x61, 0x47, 0x70, 0x62, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x6f, 0x6c, 0x6c, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x12, + 0x1f, 0x0a, 0x0b, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x44, 0x65, 0x73, 0x63, + 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x18, + 0x0c, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, + 0x79, 0x2e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x45, 0x6e, 0x63, 0x6f, + 0x64, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x19, + 0x0a, 0x08, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x74, 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x64, 0x61, 0x74, 0x61, 0x53, 0x74, 0x72, 0x12, 0x13, 0x0a, 0x05, 0x6e, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x29, + 0x0a, 0x10, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, + 0x72, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x2f, 0x0a, 0x08, 0x45, 0x6e, 0x63, + 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x10, 0x0a, 0x0c, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, + 0x67, 0x5f, 0x47, 0x50, 0x42, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x45, 0x6e, 0x63, 0x6f, 0x64, + 0x69, 0x6e, 0x67, 0x5f, 0x4a, 0x53, 0x4f, 0x4e, 0x10, 0x01, 0x22, 0xa2, 0x01, 0x0a, 0x11, 0x54, + 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x47, 0x50, 0x42, 0x54, 0x61, 0x62, 0x6c, 0x65, + 0x12, 0x2c, 0x0a, 0x03, 0x72, 0x6f, 0x77, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, + 0x74, 0x72, 0x79, 0x52, 0x6f, 0x77, 0x47, 0x50, 0x42, 0x52, 0x03, 0x72, 0x6f, 0x77, 0x12, 0x2b, + 0x0a, 0x06, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x50, + 0x61, 0x74, 0x68, 0x52, 0x06, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x32, 0x0a, 0x09, 0x67, + 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, + 0x61, 0x74, 0x6f, 0x72, 0x52, 0x09, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x22, + 0x78, 0x0a, 0x09, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x21, 0x0a, 0x0c, + 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x0b, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x12, + 0x21, 0x0a, 0x0c, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, + 0x53, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, + 0x73, 0x79, 0x6e, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x67, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x79, 0x6e, 0x63, 0x22, 0x49, 0x0a, 0x0f, 0x54, 0x65, 0x6c, + 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x52, 0x6f, 0x77, 0x47, 0x50, 0x42, 0x12, 0x1c, 0x0a, 0x09, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x22, 0x4d, 0x0a, 0x08, 0x44, 0x61, 0x74, 0x61, 0x50, 0x61, 0x74, 0x68, + 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x23, + 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, + 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x70, + 0x61, 0x74, 0x68, 0x22, 0x2f, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x27, 0x0a, 0x04, 0x6e, + 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x45, 0x6c, 0x65, 0x6d, 0x52, 0x04, + 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x86, 0x01, 0x0a, 0x08, 0x50, 0x61, 0x74, 0x68, 0x45, 0x6c, 0x65, + 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x50, + 0x61, 0x74, 0x68, 0x45, 0x6c, 0x65, 0x6d, 0x2e, 0x4b, 0x65, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x1a, 0x36, 0x0a, 0x08, 0x4b, 0x65, 0x79, 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, 0xfe, 0x03, + 0x0a, 0x19, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x53, 0x65, 0x6c, 0x66, 0x44, + 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, + 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, + 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x0d, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x61, 0x74, 0x68, 0x12, 0x14, + 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, + 0x65, 0x76, 0x65, 0x6c, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, + 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4f, 0x0a, 0x0e, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x74, 0x68, 0x72, + 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x74, + 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, + 0x72, 0x79, 0x53, 0x65, 0x6c, 0x66, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x54, 0x68, 0x72, 0x65, + 0x73, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x0d, 0x64, 0x61, 0x74, 0x61, 0x54, 0x68, 0x72, 0x65, + 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x64, 0x0a, 0x11, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, + 0x6c, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x36, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x65, 0x6c, + 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x53, 0x65, 0x6c, 0x66, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, + 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, + 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, + 0x6f, 0x6c, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x67, 0x0a, 0x11, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, + 0x6c, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x19, 0x54, 0x68, + 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x54, 0x68, 0x72, + 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x41, + 0x4e, 0x44, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, + 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x4f, 0x52, 0x10, 0x02, 0x22, 0x50, + 0x0a, 0x1d, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x53, 0x65, 0x6c, 0x66, 0x44, + 0x65, 0x66, 0x69, 0x6e, 0x65, 0x54, 0x68, 0x72, 0x65, 0x73, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, + 0x2f, 0x0a, 0x03, 0x72, 0x6f, 0x77, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, + 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, + 0x72, 0x79, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x52, 0x03, 0x72, 0x6f, 0x77, + 0x22, 0xa1, 0x02, 0x0a, 0x12, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x54, 0x68, + 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x26, 0x0a, 0x0e, 0x74, 0x68, 0x72, 0x65, 0x73, + 0x68, 0x6f, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x0e, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, + 0x57, 0x0a, 0x0f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x4f, 0x70, 0x54, 0x79, + 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x6d, + 0x65, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x54, 0x68, + 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x2e, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, + 0x64, 0x4f, 0x70, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, + 0x6c, 0x64, 0x4f, 0x70, 0x54, 0x79, 0x70, 0x65, 0x22, 0x89, 0x01, 0x0a, 0x0f, 0x54, 0x68, 0x72, + 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x4f, 0x70, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, + 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x4f, 0x70, 0x54, 0x79, 0x70, 0x65, 0x5f, + 0x45, 0x51, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, + 0x64, 0x4f, 0x70, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x47, 0x54, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, + 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x4f, 0x70, 0x54, 0x79, 0x70, 0x65, 0x5f, + 0x47, 0x45, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, + 0x64, 0x4f, 0x70, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x54, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, + 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x4f, 0x70, 0x54, 0x79, 0x70, 0x65, 0x5f, + 0x4c, 0x45, 0x10, 0x04, 0x42, 0x12, 0x5a, 0x10, 0x68, 0x75, 0x61, 0x77, 0x65, 0x69, 0x2f, 0x74, + 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_huawei_telemetry_proto_rawDescOnce sync.Once + file_huawei_telemetry_proto_rawDescData = file_huawei_telemetry_proto_rawDesc +) + +func file_huawei_telemetry_proto_rawDescGZIP() []byte { + file_huawei_telemetry_proto_rawDescOnce.Do(func() { + file_huawei_telemetry_proto_rawDescData = protoimpl.X.CompressGZIP(file_huawei_telemetry_proto_rawDescData) + }) + return file_huawei_telemetry_proto_rawDescData +} + +var file_huawei_telemetry_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_huawei_telemetry_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_huawei_telemetry_proto_goTypes = []interface{}{ + (Telemetry_Encoding)(0), // 0: telemetry.Telemetry.Encoding + (TelemetrySelfDefinedEvent_ThresholdRelation)(0), // 1: telemetry.TelemetrySelfDefinedEvent.ThresholdRelation + (TelemetryThreshold_ThresholdOpType)(0), // 2: telemetry.TelemetryThreshold.ThresholdOpType + (*Telemetry)(nil), // 3: telemetry.Telemetry + (*TelemetryGPBTable)(nil), // 4: telemetry.TelemetryGPBTable + (*Generator)(nil), // 5: telemetry.Generator + (*TelemetryRowGPB)(nil), // 6: telemetry.TelemetryRowGPB + (*DataPath)(nil), // 7: telemetry.DataPath + (*Path)(nil), // 8: telemetry.Path + (*PathElem)(nil), // 9: telemetry.PathElem + (*TelemetrySelfDefinedEvent)(nil), // 10: telemetry.TelemetrySelfDefinedEvent + (*TelemetrySelfDefineThresTable)(nil), // 11: telemetry.TelemetrySelfDefineThresTable + (*TelemetryThreshold)(nil), // 12: telemetry.TelemetryThreshold + nil, // 13: telemetry.PathElem.KeyEntry +} +var file_huawei_telemetry_proto_depIdxs = []int32{ + 4, // 0: telemetry.Telemetry.data_gpb:type_name -> telemetry.TelemetryGPBTable + 0, // 1: telemetry.Telemetry.encoding:type_name -> telemetry.Telemetry.Encoding + 6, // 2: telemetry.TelemetryGPBTable.row:type_name -> telemetry.TelemetryRowGPB + 7, // 3: telemetry.TelemetryGPBTable.delete:type_name -> telemetry.DataPath + 5, // 4: telemetry.TelemetryGPBTable.generator:type_name -> telemetry.Generator + 8, // 5: telemetry.DataPath.path:type_name -> telemetry.Path + 9, // 6: telemetry.Path.node:type_name -> telemetry.PathElem + 13, // 7: telemetry.PathElem.key:type_name -> telemetry.PathElem.KeyEntry + 11, // 8: telemetry.TelemetrySelfDefinedEvent.data_threshold:type_name -> telemetry.TelemetrySelfDefineThresTable + 1, // 9: telemetry.TelemetrySelfDefinedEvent.thresholdRelation:type_name -> telemetry.TelemetrySelfDefinedEvent.ThresholdRelation + 12, // 10: telemetry.TelemetrySelfDefineThresTable.row:type_name -> telemetry.TelemetryThreshold + 2, // 11: telemetry.TelemetryThreshold.thresholdOpType:type_name -> telemetry.TelemetryThreshold.ThresholdOpType + 12, // [12:12] is the sub-list for method output_type + 12, // [12:12] is the sub-list for method input_type + 12, // [12:12] is the sub-list for extension type_name + 12, // [12:12] is the sub-list for extension extendee + 0, // [0:12] is the sub-list for field type_name +} + +func init() { file_huawei_telemetry_proto_init() } +func file_huawei_telemetry_proto_init() { + if File_huawei_telemetry_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_huawei_telemetry_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Telemetry); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_huawei_telemetry_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TelemetryGPBTable); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_huawei_telemetry_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Generator); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_huawei_telemetry_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TelemetryRowGPB); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_huawei_telemetry_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DataPath); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_huawei_telemetry_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Path); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_huawei_telemetry_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PathElem); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_huawei_telemetry_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TelemetrySelfDefinedEvent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_huawei_telemetry_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TelemetrySelfDefineThresTable); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_huawei_telemetry_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TelemetryThreshold); 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_huawei_telemetry_proto_rawDesc, + NumEnums: 3, + NumMessages: 11, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_huawei_telemetry_proto_goTypes, + DependencyIndexes: file_huawei_telemetry_proto_depIdxs, + EnumInfos: file_huawei_telemetry_proto_enumTypes, + MessageInfos: file_huawei_telemetry_proto_msgTypes, + }.Build() + File_huawei_telemetry_proto = out.File + file_huawei_telemetry_proto_rawDesc = nil + file_huawei_telemetry_proto_goTypes = nil + file_huawei_telemetry_proto_depIdxs = nil +} diff --git a/plugins/parsers/huawei_grpc_gpb/telemetry_proto/huawei-telemetry.proto b/plugins/parsers/huawei_grpc_gpb/telemetry_proto/huawei-telemetry.proto new file mode 100644 index 0000000000000..64260484dc48b --- /dev/null +++ b/plugins/parsers/huawei_grpc_gpb/telemetry_proto/huawei-telemetry.proto @@ -0,0 +1,81 @@ +syntax = "proto3"; //The .proto file version is defined as v3. +package telemetry; //The package name is telemetry. +message Telemetry { //Telemetry message structure definition. + string node_id_str = 1; //Device name. + string subscription_id_str = 2; //Subscription name during static subscription configuration. + string sensor_path = 3; //Subscription path. + string proto_path = 13; //Message path for the sampling path in the proto file. + uint64 collection_id = 4; //Sampling round. + uint64 collection_start_time = 5; //Start time of a sampling round. + uint64 msg_timestamp = 6; //Timestamp when the current message is generated. + TelemetryGPBTable data_gpb = 7; //Indicates that the data carried is defined in TelemetryGPBTable. + uint64 collection_end_time = 8; //End time of a sampling round. + uint32 current_period = 9; //Sampling precision, in milliseconds. + string except_desc = 10; //Exception description. It is used to report exception information when a sampling exception occurs. + string product_name = 11; //Product name. + enum Encoding { + Encoding_GPB = 0; //GPB encoding format. + Encoding_JSON = 1; //JSON encoding format. + }; + Encoding encoding =12; //Data encoding format. If the GPB encoding format is used, the data_gpb field is valid. Otherwise, the data_str field is valid. + string data_str = 14; //This field is valid only when a non-GPB encoding format is used. + string ne_id = 15; //Unique ID of an NE. In the gateway scenario, this parameter is used to identify the NE to which data belongs. + string software_version = 16; //Software version number. +} +message TelemetryGPBTable { //TelemetryGPBTable message structure definition. + repeated TelemetryRowGPB row = 1; //Array definition. Its member is TelemetryRowGPB structure. + repeated DataPath delete = 2; //Delete the data path. + Generator generator = 3; //Data source description. This applies to the OnChange+ service that requires high reliability. +} +message Generator { + uint64 generator_id = 1; //Data source ID. Multiple data sources can provide data concurrently and maintain their own reliability. + uint32 generator_sn = 2; //Message sequence number. The sequence numbers of messages sent by each data source must be consecutive. If the sequence numbers are not consecutive, data out-of-synchronization occurs, the collector should support automatic disconnection and reconnection in this case. The value ranges from 0 to 0xFFFFFFFF and can be reversed. + bool generator_sync = 3; //Data source synchronization Indicates whether to perform OnChange full data synchronization. In addition, if the value is true and no data is contained, the synchronization is complete. +} +message TelemetryRowGPB { + uint64 timestamp = 1; //Timestamp of the current sampling instance. + bytes content = 11; //Sampling instance data carried. The sensor_path field must be considered to determine which .proto file is used for encoding. +} +message DataPath { + uint64 timestamp = 1; //Timestamp of the current sampling instance. + Path path = 2; //A data tree node that contains only the data path and key field information. +} +message Path { + repeated PathElem node = 1; //A data tree node that contains only the data path and key field information. +} +message PathElem { + string name = 1; //Data tree node name + map key = 2; //Key field name and value mapping table of the data tree node +} + +message TelemetrySelfDefinedEvent { + string path = 1; //Sampling path that triggers the customized event, which describes the method of parsing the content. + string proto_path = 13; //Message path for the sampling path in the proto file. + uint32 level = 2; //Level of the user-defined event. + string description = 3; //Description of the user-defined event. + string fieldName = 4; //Name of the field that triggers the customized event. + uint32 fieldValue = 5; //Value of the field that triggers the customized event. + TelemetrySelfDefineThresTable data_threshold = 6; //Threshold filter criteria when the customized event is triggered. + enum ThresholdRelation { + ThresholdRelation_INVALID = 0; //The relationship between thresholds is not configured. + ThresholdRelation_AND = 1; //The relationship between thresholds is And. + ThresholdRelation_OR = 2; //The relationship between thresholds is Or. + } + ThresholdRelation thresholdRelation = 7; //Relationship between threshold filter criteria when the customized event is triggered. + bytes content = 8; //Sampled data that triggers the customized event. +} +message TelemetrySelfDefineThresTable { + repeated TelemetryThreshold row = 1; //Multiple thresholds are included. +} +message TelemetryThreshold { + uint32 thresholdValue = 1; //Delivered threshold. + enum ThresholdOpType { + ThresholdOpType_EQ = 0; //The actual value in the data sent equals to the configured data threshold. + ThresholdOpType_GT = 1; //The actual value in the data sent is greater than the configured data threshold. + ThresholdOpType_GE = 2; //The actual value in the data sent is greater than or equals to the configured data threshold. + ThresholdOpType_LT = 3; //The actual value in the data sent is less than the configured data threshold. + ThresholdOpType_LE = 4; //The actual value in the data sent is less than or equals to the configured data threshold. + } + ThresholdOpType thresholdOpType = 2; //Threshold on the device. + +} \ No newline at end of file diff --git a/plugins/parsers/huawei_grpc_gpb/telemetry_proto/huawei_cpudefend/huawei_cpudefend.pb.go.txt b/plugins/parsers/huawei_grpc_gpb/telemetry_proto/huawei_cpudefend/huawei_cpudefend.pb.go.txt new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/plugins/parsers/huawei_grpc_gpb/telemetry_proto/huawei_ifm/a.go b/plugins/parsers/huawei_grpc_gpb/telemetry_proto/huawei_ifm/a.go new file mode 100644 index 0000000000000..20cc456a8b7b1 --- /dev/null +++ b/plugins/parsers/huawei_grpc_gpb/telemetry_proto/huawei_ifm/a.go @@ -0,0 +1,3 @@ +//go:generate protoc --go_out=plugins=grpc:. huawei-ifm.proto + +package huawei_ifm diff --git a/plugins/parsers/huawei_grpc_json/parser.go b/plugins/parsers/huawei_grpc_json/parser.go new file mode 100644 index 0000000000000..9db5cd0a9e0b4 --- /dev/null +++ b/plugins/parsers/huawei_grpc_json/parser.go @@ -0,0 +1,294 @@ +package huawei_grpc_json + +import ( + "encoding/json" + "errors" + "fmt" + "github.com/influxdata/telegraf" + "github.com/influxdata/telegraf/filter" + "github.com/influxdata/telegraf/metric" + telemetry "github.com/influxdata/telegraf/plugins/parsers/huawei_grpc_gpb/telemetry_proto" + "math" + "strings" + "time" + + "google.golang.org/protobuf/proto" + "log" + "strconv" +) + +const ( + KeySeperator = "." // the key separator of tag or field + MsgTimeStampKeyName = "timestamp" + JsonMsgKeyName = "data_str" + RowKeyName = "row" + TimeFormat = "2006-01-02 15:04:05" // time.RFC3339 + SensorPathKey = "sensor_path" +) + +type Parser struct { + metricName string + tagKeys []string + stringFields filter.Filter + nameKey string + query string + timeKey string + timeFormat string + timezone string + defaultTags map[string]string + strict bool + Mark string + Log telegraf.Logger +} + +func (p *Parser) Parse(buf []byte) ([]telegraf.Metric, error) { + // parse header firstly + var msgMap map[string]interface{} + errToMap := json.Unmarshal(buf, &msgMap) + if errToMap != nil { + return nil, fmt.Errorf("[grpc ParseJson] proto message decodec to map: %v", errToMap) + } + + // parse row + var msgsInMaps []map[string]interface{} + rowsTemp := msgMap[JsonMsgKeyName].(map[string]interface{})[RowKeyName].([]interface{}) + for _, data := range rowsTemp { + msgsInMaps = append(msgsInMaps, data.(map[string]interface{})) + } + // remove key : data_str + delete(msgMap, JsonMsgKeyName) + metrics, err := p.flattenProtoMsg(msgMap, msgsInMaps, "") // JsonMsgKeyName+KeySeperator+RowKeyName="data_str.json" + return metrics, err +} +func (p *Parser) debugLog(header *telemetry.Telemetry, rows []proto.Message) { + headerStr, err := json.MarshalIndent(header, "", " ") + if err == nil { + p.Log.Debugf("==================================== data start msg_timestamp: %v================================\n", header.MsgTimestamp) + p.Log.Debugf("header is : \n%s", headerStr) + } else { + p.Log.Debugf("error when log header") + } + p.Log.Debugf("rows are : \n") + for _, row := range rows { + rowStr, err := json.MarshalIndent(row, "", " ") + if err == nil { + p.Log.Debugf("%s", rowStr) + } else { + p.Log.Debugf("error when log rows") + } + } + p.Log.Debugf("==================================== data end ================================\n") +} + +func (p *Parser) ParseLine(line string) (telegraf.Metric, error) { + panic("implement me") +} + +func (p *Parser) SetDefaultTags(tags map[string]string) { + panic("implement me") +} + +func New() (*Parser, error) { + return &Parser{}, nil +} + +type KVStruct struct { + Fields map[string]interface{} +} + +func (kv *KVStruct) FullFlattenStruct(fieldname string, + v interface{}, + convertString bool, + convertBool bool) error { + if kv.Fields == nil { + kv.Fields = make(map[string]interface{}) + } + switch t := v.(type) { + case map[string]interface{}: + for k, v := range t { + fieldKey := k + if fieldname != "" { + fieldKey = fieldname + KeySeperator + fieldKey + } + err := kv.FullFlattenStruct(fieldKey, v, convertString, convertBool) + if err != nil { + return err + } + } + case []interface{}: + for i, v := range t { + fieldKey := strconv.Itoa(i) + if fieldname != "" { + fieldKey = fieldname + KeySeperator + fieldKey + } + err := kv.FullFlattenStruct(fieldKey, v, convertString, convertBool) + if err != nil { + return nil + } + } + case float64: + kv.Fields[fieldname] = t + case float32: + kv.Fields[fieldname] = v.(float32) + case uint64: + kv.Fields[fieldname] = v.(uint64) + case uint32: + kv.Fields[fieldname] = v.(uint32) + case int64: + kv.Fields[fieldname] = v.(int64) + case int32: + kv.Fields[fieldname] = v.(int32) + case string: + if convertString { + kv.Fields[fieldname] = v.(string) + } else { + return nil + } + case bool: + if convertBool { + kv.Fields[fieldname] = v.(bool) + } else { + return nil + } + case nil: + return nil + default: + return fmt.Errorf("key Value Flattener : got unexpected type %T with value %v (%s)", t, t, fieldname) + + } + return nil +} + +func (p *Parser) flattenProtoMsg(telemetryHeader map[string]interface{}, rowsDecodec []map[string]interface{}, startFieldName string) ([]telegraf.Metric, error) { + kvHeader := KVStruct{} + errHeader := kvHeader.FullFlattenStruct("", telemetryHeader, true, true) + if errHeader != nil { + return nil, errHeader + } + + //// debug start + //p.Log.Debugf("D! -------------------------------------Header START-----------------------------------------\n") + //for k, v := range kvHeader.Fields { + // p.Log.Debugf("D! k: %s, v: %v ", k, v) + //} + //p.Log.Debugf("D! ------------------------------------- Header END -----------------------------------------\n") + //// debug end + + var metrics []telegraf.Metric + // one row one metric + for _, rowDecodec := range rowsDecodec { + kvWithRow := KVStruct{} + errRows := kvWithRow.FullFlattenStruct(startFieldName, rowDecodec, true, true) + if errRows != nil { + return nil, errRows + } + fields, tm, errMerge := p.mergeMaps(kvHeader.Fields, kvWithRow.Fields) + if errMerge != nil { + return nil, errMerge + } + metric, err := metric.New(telemetryHeader[SensorPathKey].(string), nil, fields, tm) + if err != nil { + return nil, err + } + // debug start + //p.Log.Debugf("D! -------------------------------------Fields START time is %v-----------------------------------------\n", metric.Time()) + //for k, v := range metric.Fields() { + // p.Log.Debugf("k: %s, v: %v ", k, v) + //} + //p.Log.Debugf("D! ------------------------------------- Fields END -----------------------------------------\n") + // debug end + + metrics = append(metrics, metric) + } + return metrics, nil +} + +// merge map,extract timestamp +func (p *Parser) mergeMaps(maps ...map[string]interface{}) (map[string]interface{}, time.Time, error) { + res := make(map[string]interface{}) + timestamp := time.Time{} + for _, m := range maps { + for k, v := range m { + if strings.HasSuffix(k, "time") || strings.HasSuffix(k, MsgTimeStampKeyName) { + timeStruct, timeStr, errCal := calTimeByStamp(v) + if errCal != nil { + return nil, time.Time{}, fmt.Errorf("E! [grpc parser] when calculate time, key name is %s, time is %t, error is %v", k, v, errCal) + } + if k == MsgTimeStampKeyName { + timestamp = timeStruct + p.Log.Debugf("D! the row timestamp is %s\n", timestamp.Format(TimeFormat)) + continue + } + if timeStr != "" { + res[k] = timeStr + continue + } + } + res[k] = v + } + } + return res, timestamp, nil +} + +// timestamp transfer into time +// ten bit timestamp with second, 13 bit timestamp with second +// time.Unix(s,ns) +func calTimeByStamp(v interface{}) (time.Time, string, error) { + var sec int64 + var nsec int64 + switch v.(type) { + case float64: + vInFloat64 := v.(float64) + if vInFloat64 < math.Pow10(11) { + sec = int64(vInFloat64) + nsec = 0 + } + if vInFloat64 > math.Pow10(12) { + sec = int64(vInFloat64 / 1000) + nsec = (int64(vInFloat64) % 1000) * 1000 * 1000 + } + case int64: + vInInt64 := v.(int64) + if float64(vInInt64) < math.Pow10(11) { + sec = vInInt64 + nsec = 0 + } + if float64(vInInt64) > math.Pow10(12) { + sec = vInInt64 / 1000 + nsec = (vInInt64 % 1000) * 1000 * 1000 + } + case uint64: + vInUint64 := v.(uint64) + if float64(vInUint64) < math.Pow10(11) { + sec = int64(vInUint64) + nsec = 0 + } + if float64(vInUint64) > math.Pow10(12) { + sec = int64(vInUint64 / 1000) + nsec = int64((vInUint64 % 1000) * 1000 * 1000) + } + case string: + if strings.Index(v.(string), ":") > -1 { + return time.Time{}, v.(string), nil + } + timeInNum, errToNum := strconv.ParseUint(v.(string), 10, 64) + if errToNum != nil { + log.Printf("E! [grpc.parser.calTimeByStamp] v: %t , error : %v", v, errToNum) + } else { + if float64(timeInNum) < math.Pow10(11) { + sec = int64(timeInNum) + nsec = 0 + } + if float64(timeInNum) > math.Pow10(12) { + sec = int64(timeInNum / 1000) + nsec = int64((timeInNum % 1000) * 1000 * 1000) + } + } + } + + if sec == 0 { + return time.Time{}, "", errors.New("calculate error") + } + time := time.Unix(sec, nsec) + return time, time.Format(TimeFormat), nil +} diff --git a/plugins/parsers/registry.go b/plugins/parsers/registry.go index 76e889ffdbfaf..2e38c97c34070 100644 --- a/plugins/parsers/registry.go +++ b/plugins/parsers/registry.go @@ -2,7 +2,7 @@ package parsers import ( "fmt" - + "github.com/influxdata/telegraf/models" "github.com/influxdata/telegraf" "github.com/influxdata/telegraf/plugins/parsers/collectd" "github.com/influxdata/telegraf/plugins/parsers/csv" @@ -10,6 +10,8 @@ import ( "github.com/influxdata/telegraf/plugins/parsers/form_urlencoded" "github.com/influxdata/telegraf/plugins/parsers/graphite" "github.com/influxdata/telegraf/plugins/parsers/grok" + "github.com/influxdata/telegraf/plugins/parsers/huawei_grpc_gpb" + "github.com/influxdata/telegraf/plugins/parsers/huawei_grpc_json" "github.com/influxdata/telegraf/plugins/parsers/influx" "github.com/influxdata/telegraf/plugins/parsers/json" "github.com/influxdata/telegraf/plugins/parsers/logfmt" @@ -17,6 +19,7 @@ import ( "github.com/influxdata/telegraf/plugins/parsers/prometheus" "github.com/influxdata/telegraf/plugins/parsers/value" "github.com/influxdata/telegraf/plugins/parsers/wavefront" + "github.com/influxdata/telegraf/selfstat" ) type ParserFunc func() (Parser, error) @@ -349,4 +352,28 @@ func NewPrometheusParser(defaultTags map[string]string) (Parser, error) { return &prometheus.Parser{ DefaultTags: defaultTags, }, nil +} +func NewHuaweiGrpcGpbParser() (Parser, error) { + tags := map[string]string{"parsers": "huawei_grpc_gpb_parser"} + grpcRegister := selfstat.Register("huawei_grpc_gpb_parser", "errors", tags) + logger := models.NewLogger("parsers", "huawei_grpc_gpb_parser", "") + logger.OnErr(func() { + grpcRegister.Incr(1) + }) + parser, err := huawei_grpc_gpb.New() + if err != nil { + return nil, err + } + models.SetLoggerOnPlugin(parser, logger) + return parser, err +} + +func NewHuaweiGrpcJsonParser() (Parser, error) { + tags := map[string]string{"parsers": "huawei_grpc_json_parser"} + grpcRegister := selfstat.Register("huawei_grpc_json_parser", "errors", tags) + logger := models.NewLogger("parsers", "huawei_grpc_json_parser", "") + logger.OnErr(func() {grpcRegister.Incr(1)}) + parser, err := huawei_grpc_json.New() + models.SetLoggerOnPlugin(parser, logger) + return parser, err } \ No newline at end of file From aa3325396957347cb016fbbbdc8c5a007f4cbfde Mon Sep 17 00:00:00 2001 From: happay-coder <1115668298@qq.com> Date: Fri, 23 Apr 2021 14:32:48 +0800 Subject: [PATCH 3/4] Update HuaweiTelemetry.go --- .../parsers/huawei_grpc_gpb/telemetry_proto/HuaweiTelemetry.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/parsers/huawei_grpc_gpb/telemetry_proto/HuaweiTelemetry.go b/plugins/parsers/huawei_grpc_gpb/telemetry_proto/HuaweiTelemetry.go index ab7db46ed636c..54f411f3925c7 100644 --- a/plugins/parsers/huawei_grpc_gpb/telemetry_proto/HuaweiTelemetry.go +++ b/plugins/parsers/huawei_grpc_gpb/telemetry_proto/HuaweiTelemetry.go @@ -2,7 +2,6 @@ package telemetry import ( "fmt" - "github.com/influxdata/telegraf/plugins/parsers/huawei_grpc_gpb/telemetry_proto/huawei_debug" "github.com/influxdata/telegraf/plugins/parsers/huawei_grpc_gpb/telemetry_proto/huawei_ifm" "google.golang.org/protobuf/proto" "reflect" @@ -91,5 +90,4 @@ func (p *ProtoTypes) GetTypesByProtoOrg(orgType ProtoOrganizeType) reflect.Type // one map key: protoPath + version, value : reflect[] var pathTypeMap = map[PathKey][]reflect.Type{PathKey{ ProtoPath: "huawei_ifm.Ifm", Version: "1.0"}: []reflect.Type{reflect.TypeOf((*huawei_ifm.Ifm)(nil))}, - PathKey{ProtoPath: "huawei_debug.Debug", Version: "1.0"}: []reflect.Type{reflect.TypeOf((*huawei_debug.Debug)(nil))}, } From 2bde99d595012aaef811665020d1a9ce6653e883 Mon Sep 17 00:00:00 2001 From: happay-coder <1115668298@qq.com> Date: Fri, 23 Apr 2021 14:33:24 +0800 Subject: [PATCH 4/4] Update all.go --- plugins/processors/all/all.go | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/processors/all/all.go b/plugins/processors/all/all.go index faf6de1e25661..eb6f5b1686a2e 100644 --- a/plugins/processors/all/all.go +++ b/plugins/processors/all/all.go @@ -27,4 +27,5 @@ import ( _ "github.com/influxdata/telegraf/plugins/processors/template" _ "github.com/influxdata/telegraf/plugins/processors/topk" _ "github.com/influxdata/telegraf/plugins/processors/unpivot" + _ "github.com/influxdata/telegraf/plugins/processors/metric_match" )