From d679bf41e59c5919556335b6cfa2b066af1d6a1a Mon Sep 17 00:00:00 2001 From: Michael Cardy Date: Tue, 21 Mar 2023 13:24:52 -0400 Subject: [PATCH 01/10] Added new unmarshaller for egress spans SOL-88023 --- receiver/solacereceiver/model/README.md | 5 +- .../model/egress/v1/egress_v1.pb.go | 1351 +++++++++++++++++ receiver/solacereceiver/model/egress_v1.proto | 191 +++ .../model/{ => receive}/v1/receive_v1.pb.go | 37 +- receiver/solacereceiver/unmarshaller.go | 122 +- receiver/solacereceiver/unmarshaller_test.go | 212 +-- 6 files changed, 1761 insertions(+), 157 deletions(-) create mode 100644 receiver/solacereceiver/model/egress/v1/egress_v1.pb.go create mode 100644 receiver/solacereceiver/model/egress_v1.proto rename receiver/solacereceiver/model/{ => receive}/v1/receive_v1.pb.go (98%) diff --git a/receiver/solacereceiver/model/README.md b/receiver/solacereceiver/model/README.md index 89668dae29e45..53e15c8852237 100644 --- a/receiver/solacereceiver/model/README.md +++ b/receiver/solacereceiver/model/README.md @@ -4,6 +4,7 @@ The model directory contains the protobuf models used for payload unmarshalling To generate the V1 model from the model directory: ``` -protoc --go_out=../ --go_opt=paths=import --go_opt=Mreceive_v1.proto=model/v1 receive_v1.proto -goimports -w v1/ +protoc --go_out=../ --go_opt=paths=import --go_opt=Mreceive_v1.proto=model/receive/v1 receive_v1.proto +protoc --go_out=../ --go_opt=paths=import --go_opt=Megress_v1.proto=model/egress/v1 egress_v1.proto +goimports -w . ``` diff --git a/receiver/solacereceiver/model/egress/v1/egress_v1.pb.go b/receiver/solacereceiver/model/egress/v1/egress_v1.pb.go new file mode 100644 index 0000000000000..1b45106b0cadd --- /dev/null +++ b/receiver/solacereceiver/model/egress/v1/egress_v1.pb.go @@ -0,0 +1,1351 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.0 +// protoc v3.19.4 +// source: egress_v1.proto + +package v1 + +import ( + reflect "reflect" + sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +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 SpanData_SendSpan_Outcome int32 + +const ( + SpanData_SendSpan_ACCEPTED SpanData_SendSpan_Outcome = 0 + SpanData_SendSpan_REJECTED SpanData_SendSpan_Outcome = 1 + SpanData_SendSpan_RELEASED SpanData_SendSpan_Outcome = 2 + SpanData_SendSpan_DELIVERY_FAILED SpanData_SendSpan_Outcome = 3 + SpanData_SendSpan_FLOW_UNBOUND SpanData_SendSpan_Outcome = 4 + SpanData_SendSpan_TRANSACTION_COMMIT SpanData_SendSpan_Outcome = 5 + SpanData_SendSpan_TRANSACTION_COMMIT_FAILED SpanData_SendSpan_Outcome = 6 + SpanData_SendSpan_TRANSACTION_ROLLBACK SpanData_SendSpan_Outcome = 7 +) + +// Enum value maps for SpanData_SendSpan_Outcome. +var ( + SpanData_SendSpan_Outcome_name = map[int32]string{ + 0: "ACCEPTED", + 1: "REJECTED", + 2: "RELEASED", + 3: "DELIVERY_FAILED", + 4: "FLOW_UNBOUND", + 5: "TRANSACTION_COMMIT", + 6: "TRANSACTION_COMMIT_FAILED", + 7: "TRANSACTION_ROLLBACK", + } + SpanData_SendSpan_Outcome_value = map[string]int32{ + "ACCEPTED": 0, + "REJECTED": 1, + "RELEASED": 2, + "DELIVERY_FAILED": 3, + "FLOW_UNBOUND": 4, + "TRANSACTION_COMMIT": 5, + "TRANSACTION_COMMIT_FAILED": 6, + "TRANSACTION_ROLLBACK": 7, + } +) + +func (x SpanData_SendSpan_Outcome) Enum() *SpanData_SendSpan_Outcome { + p := new(SpanData_SendSpan_Outcome) + *p = x + return p +} + +func (x SpanData_SendSpan_Outcome) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SpanData_SendSpan_Outcome) Descriptor() protoreflect.EnumDescriptor { + return file_egress_v1_proto_enumTypes[0].Descriptor() +} + +func (SpanData_SendSpan_Outcome) Type() protoreflect.EnumType { + return &file_egress_v1_proto_enumTypes[0] +} + +func (x SpanData_SendSpan_Outcome) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SpanData_SendSpan_Outcome.Descriptor instead. +func (SpanData_SendSpan_Outcome) EnumDescriptor() ([]byte, []int) { + return file_egress_v1_proto_rawDescGZIP(), []int{0, 1, 0} +} + +type SpanData_DeleteSpan_Reason int32 + +const ( + SpanData_DeleteSpan_TTL_EXPIRY SpanData_DeleteSpan_Reason = 0 + SpanData_DeleteSpan_MAX_REDELIVERIES_EXCEEDED SpanData_DeleteSpan_Reason = 1 + SpanData_DeleteSpan_ENQUEUE_FAILURE SpanData_DeleteSpan_Reason = 2 + SpanData_DeleteSpan_ADMIN_MESSAGE_DELETE SpanData_DeleteSpan_Reason = 3 + SpanData_DeleteSpan_ADMIN_QUEUE_DELETE SpanData_DeleteSpan_Reason = 4 +) + +// Enum value maps for SpanData_DeleteSpan_Reason. +var ( + SpanData_DeleteSpan_Reason_name = map[int32]string{ + 0: "TTL_EXPIRY", + 1: "MAX_REDELIVERIES_EXCEEDED", + 2: "ENQUEUE_FAILURE", + 3: "ADMIN_MESSAGE_DELETE", + 4: "ADMIN_QUEUE_DELETE", + } + SpanData_DeleteSpan_Reason_value = map[string]int32{ + "TTL_EXPIRY": 0, + "MAX_REDELIVERIES_EXCEEDED": 1, + "ENQUEUE_FAILURE": 2, + "ADMIN_MESSAGE_DELETE": 3, + "ADMIN_QUEUE_DELETE": 4, + } +) + +func (x SpanData_DeleteSpan_Reason) Enum() *SpanData_DeleteSpan_Reason { + p := new(SpanData_DeleteSpan_Reason) + *p = x + return p +} + +func (x SpanData_DeleteSpan_Reason) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SpanData_DeleteSpan_Reason) Descriptor() protoreflect.EnumDescriptor { + return file_egress_v1_proto_enumTypes[1].Descriptor() +} + +func (SpanData_DeleteSpan_Reason) Type() protoreflect.EnumType { + return &file_egress_v1_proto_enumTypes[1] +} + +func (x SpanData_DeleteSpan_Reason) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SpanData_DeleteSpan_Reason.Descriptor instead. +func (SpanData_DeleteSpan_Reason) EnumDescriptor() ([]byte, []int) { + return file_egress_v1_proto_rawDescGZIP(), []int{0, 2, 0} +} + +type SpanData_TransactionEvent_Type int32 + +const ( + // COMMIT and ROLLBACK are always initiated by either a CLIENT or ADMIN. + // The initiator is ADMIN when the management interface is used to + // to perform a heuristic commit or rollback. + SpanData_TransactionEvent_COMMIT SpanData_TransactionEvent_Type = 0 + SpanData_TransactionEvent_ROLLBACK SpanData_TransactionEvent_Type = 1 + // PREPARE and END can only occur with a CLIENT initiator, and spans for + // these operations are only generated if the operation fails. Therefore, + // the error_description of the TransactionEvent will always be present + // for END and PREPARE. + SpanData_TransactionEvent_END SpanData_TransactionEvent_Type = 2 + SpanData_TransactionEvent_PREPARE SpanData_TransactionEvent_Type = 3 + // The initiator of a SESSION_TIMEOUT is always BROKER. All messages + // received as part of the transaction are discarded. + SpanData_TransactionEvent_SESSION_TIMEOUT SpanData_TransactionEvent_Type = 4 + // The initiator of ROLLBACK_ONLY is always BROKER. The first such event + // in a transaction always has an error_description in the span, + // indicating there was a problem processing the message when it was + // received, and the message is being discarded. This also transitions + // the transaction itself to a "rollback only" state, which causes + // all subsequent messages received as part of the transaction to also + // be discarded. Spans generated by these subsequent discards will not + // have the span's error_description set, but all ROLLBACK_ONLY + // transaction events will have an error_description set, which indicate + // the transaction's error. + // + // Since the only record of these messages in the context of the + // transaction has been discarded, no further span can be generated in + // the context of a client, admin, or session timeout operation. When a + // subsequent operation such as rollback or commit occurs on a + // transaction marked rollback only, only messages received prior to the + // error triggering the transition to rollback only will generate + // receive spans. + SpanData_TransactionEvent_ROLLBACK_ONLY SpanData_TransactionEvent_Type = 5 +) + +// Enum value maps for SpanData_TransactionEvent_Type. +var ( + SpanData_TransactionEvent_Type_name = map[int32]string{ + 0: "COMMIT", + 1: "ROLLBACK", + 2: "END", + 3: "PREPARE", + 4: "SESSION_TIMEOUT", + 5: "ROLLBACK_ONLY", + } + SpanData_TransactionEvent_Type_value = map[string]int32{ + "COMMIT": 0, + "ROLLBACK": 1, + "END": 2, + "PREPARE": 3, + "SESSION_TIMEOUT": 4, + "ROLLBACK_ONLY": 5, + } +) + +func (x SpanData_TransactionEvent_Type) Enum() *SpanData_TransactionEvent_Type { + p := new(SpanData_TransactionEvent_Type) + *p = x + return p +} + +func (x SpanData_TransactionEvent_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SpanData_TransactionEvent_Type) Descriptor() protoreflect.EnumDescriptor { + return file_egress_v1_proto_enumTypes[2].Descriptor() +} + +func (SpanData_TransactionEvent_Type) Type() protoreflect.EnumType { + return &file_egress_v1_proto_enumTypes[2] +} + +func (x SpanData_TransactionEvent_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SpanData_TransactionEvent_Type.Descriptor instead. +func (SpanData_TransactionEvent_Type) EnumDescriptor() ([]byte, []int) { + return file_egress_v1_proto_rawDescGZIP(), []int{0, 3, 0} +} + +type SpanData_TransactionEvent_Initiator int32 + +const ( + SpanData_TransactionEvent_CLIENT SpanData_TransactionEvent_Initiator = 0 + SpanData_TransactionEvent_ADMIN SpanData_TransactionEvent_Initiator = 1 + SpanData_TransactionEvent_BROKER SpanData_TransactionEvent_Initiator = 2 +) + +// Enum value maps for SpanData_TransactionEvent_Initiator. +var ( + SpanData_TransactionEvent_Initiator_name = map[int32]string{ + 0: "CLIENT", + 1: "ADMIN", + 2: "BROKER", + } + SpanData_TransactionEvent_Initiator_value = map[string]int32{ + "CLIENT": 0, + "ADMIN": 1, + "BROKER": 2, + } +) + +func (x SpanData_TransactionEvent_Initiator) Enum() *SpanData_TransactionEvent_Initiator { + p := new(SpanData_TransactionEvent_Initiator) + *p = x + return p +} + +func (x SpanData_TransactionEvent_Initiator) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SpanData_TransactionEvent_Initiator) Descriptor() protoreflect.EnumDescriptor { + return file_egress_v1_proto_enumTypes[3].Descriptor() +} + +func (SpanData_TransactionEvent_Initiator) Type() protoreflect.EnumType { + return &file_egress_v1_proto_enumTypes[3] +} + +func (x SpanData_TransactionEvent_Initiator) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SpanData_TransactionEvent_Initiator.Descriptor instead. +func (SpanData_TransactionEvent_Initiator) EnumDescriptor() ([]byte, []int) { + return file_egress_v1_proto_rawDescGZIP(), []int{0, 3, 1} +} + +// Messages with the following topic contain a message matching this +// specification: +// _telemetry/broker/trace/egress/v1[/additional/topic/levels] +// Note that the topic allows for additional topic levels to be added in the +// future. Receiving clients must not assume there are no additional topic +// levels. +// +// This message describes telemetry data that a Solace PubSub+ broker captures +// in the egress portion of its data path. +// +// Fields with names that end in "time_unix_nano" are 64-bit timestamps, in +// nanoseconds, since midnight, Jan. 1, 1970 UTC. +type SpanData struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + EgressSpans []*SpanData_EgressSpan `protobuf:"bytes,1,rep,name=egress_spans,json=egressSpans,proto3" json:"egress_spans,omitempty"` + // The router-name of the broker generating this message at the time the + // message was generated. + RouterName string `protobuf:"bytes,2,opt,name=router_name,json=routerName,proto3" json:"router_name,omitempty"` + // The broker's message-vpn name. This field may be removed in the future + // without a major version change since the field is specified as optional. + // + // Rather than rely on this field, receiving clients should obtain the VPN + // by using an SMF API to extract the VPN_NAME_IN_USE from the API's Session + // object. The message_vpn_name of all messages received from via an SMF + // API's session will match the session's VPN_NAME_IN_USE. + MessageVpnName *string `protobuf:"bytes,3,opt,name=message_vpn_name,json=messageVpnName,proto3,oneof" json:"message_vpn_name,omitempty"` +} + +func (x *SpanData) Reset() { + *x = SpanData{} + if protoimpl.UnsafeEnabled { + mi := &file_egress_v1_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SpanData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SpanData) ProtoMessage() {} + +func (x *SpanData) ProtoReflect() protoreflect.Message { + mi := &file_egress_v1_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 SpanData.ProtoReflect.Descriptor instead. +func (*SpanData) Descriptor() ([]byte, []int) { + return file_egress_v1_proto_rawDescGZIP(), []int{0} +} + +func (x *SpanData) GetEgressSpans() []*SpanData_EgressSpan { + if x != nil { + return x.EgressSpans + } + return nil +} + +func (x *SpanData) GetRouterName() string { + if x != nil { + return x.RouterName + } + return "" +} + +func (x *SpanData) GetMessageVpnName() string { + if x != nil && x.MessageVpnName != nil { + return *x.MessageVpnName + } + return "" +} + +type SpanData_EgressSpan struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // 16-byte globally unique trace ID. Any two spans with the same trace ID + // are part of the same trace. + TraceId []byte `protobuf:"bytes,1,opt,name=trace_id,json=traceId,proto3" json:"trace_id,omitempty"` + // 8-byte span ID, unique within the scope of a trace. + SpanId []byte `protobuf:"bytes,2,opt,name=span_id,json=spanId,proto3" json:"span_id,omitempty"` + // If not present, this is a root span. If present, this is an 8-byte span + // ID of the parent span. + ParentSpanId []byte `protobuf:"bytes,3,opt,name=parent_span_id,json=parentSpanId,proto3,oneof" json:"parent_span_id,omitempty"` + // The start and end timestamps of the receive span. The start of the span + // is when Guaranteed Messaging processing begins in the broker. + StartTimeUnixNano int64 `protobuf:"fixed64,4,opt,name=start_time_unix_nano,json=startTimeUnixNano,proto3" json:"start_time_unix_nano,omitempty"` + EndTimeUnixNano int64 `protobuf:"fixed64,5,opt,name=end_time_unix_nano,json=endTimeUnixNano,proto3" json:"end_time_unix_nano,omitempty"` + TransactionEvent *SpanData_TransactionEvent `protobuf:"bytes,6,opt,name=transaction_event,json=transactionEvent,proto3,oneof" json:"transaction_event,omitempty"` + ErrorDescription *string `protobuf:"bytes,7,opt,name=error_description,json=errorDescription,proto3,oneof" json:"error_description,omitempty"` + // Types that are assignable to TypeData: + // *SpanData_EgressSpan_SendSpan + // *SpanData_EgressSpan_DeleteSpan + TypeData isSpanData_EgressSpan_TypeData `protobuf_oneof:"type_data"` +} + +func (x *SpanData_EgressSpan) Reset() { + *x = SpanData_EgressSpan{} + if protoimpl.UnsafeEnabled { + mi := &file_egress_v1_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SpanData_EgressSpan) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SpanData_EgressSpan) ProtoMessage() {} + +func (x *SpanData_EgressSpan) ProtoReflect() protoreflect.Message { + mi := &file_egress_v1_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 SpanData_EgressSpan.ProtoReflect.Descriptor instead. +func (*SpanData_EgressSpan) Descriptor() ([]byte, []int) { + return file_egress_v1_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *SpanData_EgressSpan) GetTraceId() []byte { + if x != nil { + return x.TraceId + } + return nil +} + +func (x *SpanData_EgressSpan) GetSpanId() []byte { + if x != nil { + return x.SpanId + } + return nil +} + +func (x *SpanData_EgressSpan) GetParentSpanId() []byte { + if x != nil { + return x.ParentSpanId + } + return nil +} + +func (x *SpanData_EgressSpan) GetStartTimeUnixNano() int64 { + if x != nil { + return x.StartTimeUnixNano + } + return 0 +} + +func (x *SpanData_EgressSpan) GetEndTimeUnixNano() int64 { + if x != nil { + return x.EndTimeUnixNano + } + return 0 +} + +func (x *SpanData_EgressSpan) GetTransactionEvent() *SpanData_TransactionEvent { + if x != nil { + return x.TransactionEvent + } + return nil +} + +func (x *SpanData_EgressSpan) GetErrorDescription() string { + if x != nil && x.ErrorDescription != nil { + return *x.ErrorDescription + } + return "" +} + +func (m *SpanData_EgressSpan) GetTypeData() isSpanData_EgressSpan_TypeData { + if m != nil { + return m.TypeData + } + return nil +} + +func (x *SpanData_EgressSpan) GetSendSpan() *SpanData_SendSpan { + if x, ok := x.GetTypeData().(*SpanData_EgressSpan_SendSpan); ok { + return x.SendSpan + } + return nil +} + +func (x *SpanData_EgressSpan) GetDeleteSpan() *SpanData_DeleteSpan { + if x, ok := x.GetTypeData().(*SpanData_EgressSpan_DeleteSpan); ok { + return x.DeleteSpan + } + return nil +} + +type isSpanData_EgressSpan_TypeData interface { + isSpanData_EgressSpan_TypeData() +} + +type SpanData_EgressSpan_SendSpan struct { + SendSpan *SpanData_SendSpan `protobuf:"bytes,8,opt,name=send_span,json=sendSpan,proto3,oneof"` +} + +type SpanData_EgressSpan_DeleteSpan struct { + DeleteSpan *SpanData_DeleteSpan `protobuf:"bytes,9,opt,name=delete_span,json=deleteSpan,proto3,oneof"` +} + +func (*SpanData_EgressSpan_SendSpan) isSpanData_EgressSpan_TypeData() {} + +func (*SpanData_EgressSpan_DeleteSpan) isSpanData_EgressSpan_TypeData() {} + +// This message contains information unique to a SendSpan. +type SpanData_SendSpan struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The name of the queue or topic endpoint the message is being delivered + // from. + // + // Types that are assignable to Source: + // *SpanData_SendSpan_QueueName + // *SpanData_SendSpan_TopicEndpointName + Source isSpanData_SendSpan_Source `protobuf_oneof:"source"` + QueueTemporary bool `protobuf:"varint,3,opt,name=queue_temporary,json=queueTemporary,proto3" json:"queue_temporary,omitempty"` + Outcome SpanData_SendSpan_Outcome `protobuf:"varint,4,opt,name=outcome,proto3,enum=solace.messaging.proto.broker.trace.egress.v1.SpanData_SendSpan_Outcome" json:"outcome,omitempty"` + ReplayedMsg bool `protobuf:"varint,5,opt,name=replayed_msg,json=replayedMsg,proto3" json:"replayed_msg,omitempty"` + ConsumerClientUsername string `protobuf:"bytes,6,opt,name=consumer_client_username,json=consumerClientUsername,proto3" json:"consumer_client_username,omitempty"` + ConsumerClientName string `protobuf:"bytes,7,opt,name=consumer_client_name,json=consumerClientName,proto3" json:"consumer_client_name,omitempty"` + Protocol string `protobuf:"bytes,8,opt,name=protocol,proto3" json:"protocol,omitempty"` + ProtocolVersion *string `protobuf:"bytes,9,opt,name=protocol_version,json=protocolVersion,proto3,oneof" json:"protocol_version,omitempty"` +} + +func (x *SpanData_SendSpan) Reset() { + *x = SpanData_SendSpan{} + if protoimpl.UnsafeEnabled { + mi := &file_egress_v1_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SpanData_SendSpan) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SpanData_SendSpan) ProtoMessage() {} + +func (x *SpanData_SendSpan) ProtoReflect() protoreflect.Message { + mi := &file_egress_v1_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 SpanData_SendSpan.ProtoReflect.Descriptor instead. +func (*SpanData_SendSpan) Descriptor() ([]byte, []int) { + return file_egress_v1_proto_rawDescGZIP(), []int{0, 1} +} + +func (m *SpanData_SendSpan) GetSource() isSpanData_SendSpan_Source { + if m != nil { + return m.Source + } + return nil +} + +func (x *SpanData_SendSpan) GetQueueName() string { + if x, ok := x.GetSource().(*SpanData_SendSpan_QueueName); ok { + return x.QueueName + } + return "" +} + +func (x *SpanData_SendSpan) GetTopicEndpointName() string { + if x, ok := x.GetSource().(*SpanData_SendSpan_TopicEndpointName); ok { + return x.TopicEndpointName + } + return "" +} + +func (x *SpanData_SendSpan) GetQueueTemporary() bool { + if x != nil { + return x.QueueTemporary + } + return false +} + +func (x *SpanData_SendSpan) GetOutcome() SpanData_SendSpan_Outcome { + if x != nil { + return x.Outcome + } + return SpanData_SendSpan_ACCEPTED +} + +func (x *SpanData_SendSpan) GetReplayedMsg() bool { + if x != nil { + return x.ReplayedMsg + } + return false +} + +func (x *SpanData_SendSpan) GetConsumerClientUsername() string { + if x != nil { + return x.ConsumerClientUsername + } + return "" +} + +func (x *SpanData_SendSpan) GetConsumerClientName() string { + if x != nil { + return x.ConsumerClientName + } + return "" +} + +func (x *SpanData_SendSpan) GetProtocol() string { + if x != nil { + return x.Protocol + } + return "" +} + +func (x *SpanData_SendSpan) GetProtocolVersion() string { + if x != nil && x.ProtocolVersion != nil { + return *x.ProtocolVersion + } + return "" +} + +type isSpanData_SendSpan_Source interface { + isSpanData_SendSpan_Source() +} + +type SpanData_SendSpan_QueueName struct { + QueueName string `protobuf:"bytes,1,opt,name=queue_name,json=queueName,proto3,oneof"` +} + +type SpanData_SendSpan_TopicEndpointName struct { + TopicEndpointName string `protobuf:"bytes,2,opt,name=topic_endpoint_name,json=topicEndpointName,proto3,oneof"` +} + +func (*SpanData_SendSpan_QueueName) isSpanData_SendSpan_Source() {} + +func (*SpanData_SendSpan_TopicEndpointName) isSpanData_SendSpan_Source() {} + +// This message contains data unique to delete spans generated in egress. +// The only implemented delete span currently implemented is the +// ENQUEUE_FAILURE reason. Other values are defined to allow their +// implementation to be added in the future without automatically requiring +// a change to the spec. +type SpanData_DeleteSpan struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The name of the queue or topic endpoint the message is being deleted + // from. + // + // Types that are assignable to Source: + // *SpanData_DeleteSpan_QueueName + // *SpanData_DeleteSpan_TopicEndpointName + Source isSpanData_DeleteSpan_Source `protobuf_oneof:"source"` + QueueTemporary bool `protobuf:"varint,3,opt,name=queue_temporary,json=queueTemporary,proto3" json:"queue_temporary,omitempty"` + Reason SpanData_DeleteSpan_Reason `protobuf:"varint,4,opt,name=reason,proto3,enum=solace.messaging.proto.broker.trace.egress.v1.SpanData_DeleteSpan_Reason" json:"reason,omitempty"` +} + +func (x *SpanData_DeleteSpan) Reset() { + *x = SpanData_DeleteSpan{} + if protoimpl.UnsafeEnabled { + mi := &file_egress_v1_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SpanData_DeleteSpan) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SpanData_DeleteSpan) ProtoMessage() {} + +func (x *SpanData_DeleteSpan) ProtoReflect() protoreflect.Message { + mi := &file_egress_v1_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 SpanData_DeleteSpan.ProtoReflect.Descriptor instead. +func (*SpanData_DeleteSpan) Descriptor() ([]byte, []int) { + return file_egress_v1_proto_rawDescGZIP(), []int{0, 2} +} + +func (m *SpanData_DeleteSpan) GetSource() isSpanData_DeleteSpan_Source { + if m != nil { + return m.Source + } + return nil +} + +func (x *SpanData_DeleteSpan) GetQueueName() string { + if x, ok := x.GetSource().(*SpanData_DeleteSpan_QueueName); ok { + return x.QueueName + } + return "" +} + +func (x *SpanData_DeleteSpan) GetTopicEndpointName() string { + if x, ok := x.GetSource().(*SpanData_DeleteSpan_TopicEndpointName); ok { + return x.TopicEndpointName + } + return "" +} + +func (x *SpanData_DeleteSpan) GetQueueTemporary() bool { + if x != nil { + return x.QueueTemporary + } + return false +} + +func (x *SpanData_DeleteSpan) GetReason() SpanData_DeleteSpan_Reason { + if x != nil { + return x.Reason + } + return SpanData_DeleteSpan_TTL_EXPIRY +} + +type isSpanData_DeleteSpan_Source interface { + isSpanData_DeleteSpan_Source() +} + +type SpanData_DeleteSpan_QueueName struct { + QueueName string `protobuf:"bytes,1,opt,name=queue_name,json=queueName,proto3,oneof"` +} + +type SpanData_DeleteSpan_TopicEndpointName struct { + TopicEndpointName string `protobuf:"bytes,2,opt,name=topic_endpoint_name,json=topicEndpointName,proto3,oneof"` +} + +func (*SpanData_DeleteSpan_QueueName) isSpanData_DeleteSpan_Source() {} + +func (*SpanData_DeleteSpan_TopicEndpointName) isSpanData_DeleteSpan_Source() {} + +// When a span has a transaction event, it indicates the span occurs as part +// of processing a transaction, and includes the *current* state of of the +// transaction when the event was generated. The state can change as +// subsequent events occur as part of the transaction. +type SpanData_TransactionEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TimeUnixNano int64 `protobuf:"fixed64,1,opt,name=time_unix_nano,json=timeUnixNano,proto3" json:"time_unix_nano,omitempty"` + Type SpanData_TransactionEvent_Type `protobuf:"varint,2,opt,name=type,proto3,enum=solace.messaging.proto.broker.trace.egress.v1.SpanData_TransactionEvent_Type" json:"type,omitempty"` + Initiator SpanData_TransactionEvent_Initiator `protobuf:"varint,3,opt,name=initiator,proto3,enum=solace.messaging.proto.broker.trace.egress.v1.SpanData_TransactionEvent_Initiator" json:"initiator,omitempty"` + // Types that are assignable to TransactionId: + // *SpanData_TransactionEvent_Xid_ + // *SpanData_TransactionEvent_LocalId + TransactionId isSpanData_TransactionEvent_TransactionId `protobuf_oneof:"transaction_id"` + ErrorDescription *string `protobuf:"bytes,6,opt,name=error_description,json=errorDescription,proto3,oneof" json:"error_description,omitempty"` +} + +func (x *SpanData_TransactionEvent) Reset() { + *x = SpanData_TransactionEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_egress_v1_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SpanData_TransactionEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SpanData_TransactionEvent) ProtoMessage() {} + +func (x *SpanData_TransactionEvent) ProtoReflect() protoreflect.Message { + mi := &file_egress_v1_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 SpanData_TransactionEvent.ProtoReflect.Descriptor instead. +func (*SpanData_TransactionEvent) Descriptor() ([]byte, []int) { + return file_egress_v1_proto_rawDescGZIP(), []int{0, 3} +} + +func (x *SpanData_TransactionEvent) GetTimeUnixNano() int64 { + if x != nil { + return x.TimeUnixNano + } + return 0 +} + +func (x *SpanData_TransactionEvent) GetType() SpanData_TransactionEvent_Type { + if x != nil { + return x.Type + } + return SpanData_TransactionEvent_COMMIT +} + +func (x *SpanData_TransactionEvent) GetInitiator() SpanData_TransactionEvent_Initiator { + if x != nil { + return x.Initiator + } + return SpanData_TransactionEvent_CLIENT +} + +func (m *SpanData_TransactionEvent) GetTransactionId() isSpanData_TransactionEvent_TransactionId { + if m != nil { + return m.TransactionId + } + return nil +} + +func (x *SpanData_TransactionEvent) GetXid() *SpanData_TransactionEvent_Xid { + if x, ok := x.GetTransactionId().(*SpanData_TransactionEvent_Xid_); ok { + return x.Xid + } + return nil +} + +func (x *SpanData_TransactionEvent) GetLocalId() *SpanData_TransactionEvent_LocalTransactionId { + if x, ok := x.GetTransactionId().(*SpanData_TransactionEvent_LocalId); ok { + return x.LocalId + } + return nil +} + +func (x *SpanData_TransactionEvent) GetErrorDescription() string { + if x != nil && x.ErrorDescription != nil { + return *x.ErrorDescription + } + return "" +} + +type isSpanData_TransactionEvent_TransactionId interface { + isSpanData_TransactionEvent_TransactionId() +} + +type SpanData_TransactionEvent_Xid_ struct { + Xid *SpanData_TransactionEvent_Xid `protobuf:"bytes,4,opt,name=xid,proto3,oneof"` +} + +type SpanData_TransactionEvent_LocalId struct { + LocalId *SpanData_TransactionEvent_LocalTransactionId `protobuf:"bytes,5,opt,name=local_id,json=localId,proto3,oneof"` +} + +func (*SpanData_TransactionEvent_Xid_) isSpanData_TransactionEvent_TransactionId() {} + +func (*SpanData_TransactionEvent_LocalId) isSpanData_TransactionEvent_TransactionId() {} + +type SpanData_TransactionEvent_Xid struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + FormatId int32 `protobuf:"varint,1,opt,name=format_id,json=formatId,proto3" json:"format_id,omitempty"` + BranchQualifier []byte `protobuf:"bytes,2,opt,name=branch_qualifier,json=branchQualifier,proto3" json:"branch_qualifier,omitempty"` + GlobalId []byte `protobuf:"bytes,3,opt,name=global_id,json=globalId,proto3" json:"global_id,omitempty"` +} + +func (x *SpanData_TransactionEvent_Xid) Reset() { + *x = SpanData_TransactionEvent_Xid{} + if protoimpl.UnsafeEnabled { + mi := &file_egress_v1_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SpanData_TransactionEvent_Xid) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SpanData_TransactionEvent_Xid) ProtoMessage() {} + +func (x *SpanData_TransactionEvent_Xid) ProtoReflect() protoreflect.Message { + mi := &file_egress_v1_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 SpanData_TransactionEvent_Xid.ProtoReflect.Descriptor instead. +func (*SpanData_TransactionEvent_Xid) Descriptor() ([]byte, []int) { + return file_egress_v1_proto_rawDescGZIP(), []int{0, 3, 0} +} + +func (x *SpanData_TransactionEvent_Xid) GetFormatId() int32 { + if x != nil { + return x.FormatId + } + return 0 +} + +func (x *SpanData_TransactionEvent_Xid) GetBranchQualifier() []byte { + if x != nil { + return x.BranchQualifier + } + return nil +} + +func (x *SpanData_TransactionEvent_Xid) GetGlobalId() []byte { + if x != nil { + return x.GlobalId + } + return nil +} + +type SpanData_TransactionEvent_LocalTransactionId struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TransactionId uint32 `protobuf:"varint,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + SessionId uint32 `protobuf:"varint,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + SessionName string `protobuf:"bytes,3,opt,name=session_name,json=sessionName,proto3" json:"session_name,omitempty"` +} + +func (x *SpanData_TransactionEvent_LocalTransactionId) Reset() { + *x = SpanData_TransactionEvent_LocalTransactionId{} + if protoimpl.UnsafeEnabled { + mi := &file_egress_v1_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SpanData_TransactionEvent_LocalTransactionId) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SpanData_TransactionEvent_LocalTransactionId) ProtoMessage() {} + +func (x *SpanData_TransactionEvent_LocalTransactionId) ProtoReflect() protoreflect.Message { + mi := &file_egress_v1_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 SpanData_TransactionEvent_LocalTransactionId.ProtoReflect.Descriptor instead. +func (*SpanData_TransactionEvent_LocalTransactionId) Descriptor() ([]byte, []int) { + return file_egress_v1_proto_rawDescGZIP(), []int{0, 3, 1} +} + +func (x *SpanData_TransactionEvent_LocalTransactionId) GetTransactionId() uint32 { + if x != nil { + return x.TransactionId + } + return 0 +} + +func (x *SpanData_TransactionEvent_LocalTransactionId) GetSessionId() uint32 { + if x != nil { + return x.SessionId + } + return 0 +} + +func (x *SpanData_TransactionEvent_LocalTransactionId) GetSessionName() string { + if x != nil { + return x.SessionName + } + return "" +} + +var File_egress_v1_proto protoreflect.FileDescriptor + +var file_egress_v1_proto_rawDesc = []byte{ + 0x0a, 0x0f, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x76, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x12, 0x2d, 0x73, 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, + 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x76, 0x31, + 0x22, 0xb2, 0x16, 0x0a, 0x08, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x65, 0x0a, + 0x0c, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x70, 0x61, 0x6e, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x73, 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, 0x6f, + 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x45, 0x67, 0x72, + 0x65, 0x73, 0x73, 0x53, 0x70, 0x61, 0x6e, 0x52, 0x0b, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, + 0x70, 0x61, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, + 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2d, 0x0a, 0x10, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x5f, 0x76, 0x70, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, + 0x00, 0x52, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x56, 0x70, 0x6e, 0x4e, 0x61, 0x6d, + 0x65, 0x88, 0x01, 0x01, 0x1a, 0x8b, 0x05, 0x0a, 0x0a, 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, + 0x70, 0x61, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x74, 0x72, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x17, + 0x0a, 0x07, 0x73, 0x70, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x06, 0x73, 0x70, 0x61, 0x6e, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x0e, 0x70, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x5f, 0x73, 0x70, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x48, + 0x01, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x70, 0x61, 0x6e, 0x49, 0x64, 0x88, + 0x01, 0x01, 0x12, 0x2f, 0x0a, 0x14, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, + 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x10, + 0x52, 0x11, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x78, 0x4e, + 0x61, 0x6e, 0x6f, 0x12, 0x2b, 0x0a, 0x12, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, + 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x18, 0x05, 0x20, 0x01, 0x28, 0x10, 0x52, + 0x0f, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x78, 0x4e, 0x61, 0x6e, 0x6f, + 0x12, 0x7a, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x48, 0x2e, 0x73, 0x6f, + 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, 0x63, + 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, + 0x44, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x02, 0x52, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x30, 0x0a, 0x11, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x10, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x5f, + 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x73, 0x70, 0x61, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x40, 0x2e, 0x73, 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, 0x6f, 0x6b, 0x65, + 0x72, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x53, + 0x70, 0x61, 0x6e, 0x48, 0x00, 0x52, 0x08, 0x73, 0x65, 0x6e, 0x64, 0x53, 0x70, 0x61, 0x6e, 0x12, + 0x65, 0x0a, 0x0b, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x5f, 0x73, 0x70, 0x61, 0x6e, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x73, 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, + 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, 0x73, + 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x48, 0x00, 0x52, 0x0a, 0x64, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x42, 0x0b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x64, + 0x61, 0x74, 0x61, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, + 0x70, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x14, 0x0a, 0x12, + 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x1a, 0x92, 0x05, 0x0a, 0x08, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x70, 0x61, 0x6e, 0x12, + 0x1f, 0x0a, 0x0a, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x71, 0x75, 0x65, 0x75, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x30, 0x0a, 0x13, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, + 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, + 0x11, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x74, 0x65, 0x6d, 0x70, + 0x6f, 0x72, 0x61, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x71, 0x75, 0x65, + 0x75, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x12, 0x62, 0x0a, 0x07, 0x6f, + 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x48, 0x2e, 0x73, + 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, + 0x63, 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, + 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x70, 0x61, 0x6e, 0x2e, 0x4f, + 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x12, + 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x64, 0x5f, 0x6d, 0x73, 0x67, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x64, 0x4d, + 0x73, 0x67, 0x12, 0x38, 0x0a, 0x18, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x43, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x14, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6d, 0x65, 0x72, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, + 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x2e, 0x0a, 0x10, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x22, 0xab, 0x01, 0x0a, 0x07, 0x4f, + 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x4a, 0x45, 0x43, 0x54, 0x45, 0x44, + 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x4c, 0x45, 0x41, 0x53, 0x45, 0x44, 0x10, 0x02, + 0x12, 0x13, 0x0a, 0x0f, 0x44, 0x45, 0x4c, 0x49, 0x56, 0x45, 0x52, 0x59, 0x5f, 0x46, 0x41, 0x49, + 0x4c, 0x45, 0x44, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, + 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, 0x54, 0x52, 0x41, 0x4e, 0x53, + 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x05, 0x12, + 0x1d, 0x0a, 0x19, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, + 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x06, 0x12, 0x18, + 0x0a, 0x14, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x4f, + 0x4c, 0x4c, 0x42, 0x41, 0x43, 0x4b, 0x10, 0x07, 0x42, 0x08, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0xf5, 0x02, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x12, 0x1f, 0x0a, 0x0a, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x71, 0x75, + 0x65, 0x75, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x13, 0x74, 0x6f, 0x70, 0x69, 0x63, + 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x11, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x45, 0x6e, 0x64, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x71, 0x75, 0x65, + 0x75, 0x65, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, + 0x72, 0x79, 0x12, 0x61, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x49, 0x2e, 0x73, 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, 0x6f, 0x6b, + 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, + 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x2e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x52, 0x06, 0x72, + 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x7e, 0x0a, 0x06, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, + 0x0e, 0x0a, 0x0a, 0x54, 0x54, 0x4c, 0x5f, 0x45, 0x58, 0x50, 0x49, 0x52, 0x59, 0x10, 0x00, 0x12, + 0x1d, 0x0a, 0x19, 0x4d, 0x41, 0x58, 0x5f, 0x52, 0x45, 0x44, 0x45, 0x4c, 0x49, 0x56, 0x45, 0x52, + 0x49, 0x45, 0x53, 0x5f, 0x45, 0x58, 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x01, 0x12, 0x13, + 0x0a, 0x0f, 0x45, 0x4e, 0x51, 0x55, 0x45, 0x55, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, + 0x45, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x5f, 0x4d, 0x45, 0x53, + 0x53, 0x41, 0x47, 0x45, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x03, 0x12, 0x16, 0x0a, + 0x12, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x5f, 0x51, 0x55, 0x45, 0x55, 0x45, 0x5f, 0x44, 0x45, 0x4c, + 0x45, 0x54, 0x45, 0x10, 0x04, 0x42, 0x08, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x1a, + 0xbe, 0x07, 0x0a, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x6e, 0x69, + 0x78, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x10, 0x52, 0x0c, 0x74, 0x69, + 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x78, 0x4e, 0x61, 0x6e, 0x6f, 0x12, 0x61, 0x0a, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4d, 0x2e, 0x73, 0x6f, 0x6c, 0x61, 0x63, + 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x65, + 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, + 0x61, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x70, 0x0a, + 0x09, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x52, 0x2e, 0x73, 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, + 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x69, + 0x61, 0x74, 0x6f, 0x72, 0x52, 0x09, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x12, + 0x60, 0x0a, 0x03, 0x78, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x4c, 0x2e, 0x73, + 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, + 0x63, 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, + 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x58, 0x69, 0x64, 0x48, 0x00, 0x52, 0x03, 0x78, 0x69, + 0x64, 0x12, 0x78, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x5b, 0x2e, 0x73, 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, 0x6f, + 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, + 0x48, 0x00, 0x52, 0x07, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x11, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x10, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x44, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x1a, 0x6a, 0x0a, + 0x03, 0x58, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x49, + 0x64, 0x12, 0x29, 0x0a, 0x10, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x71, 0x75, 0x61, 0x6c, + 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x62, 0x72, 0x61, + 0x6e, 0x63, 0x68, 0x51, 0x75, 0x61, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, + 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x08, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x64, 0x1a, 0x7d, 0x0a, 0x12, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, + 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x5e, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, + 0x52, 0x4f, 0x4c, 0x4c, 0x42, 0x41, 0x43, 0x4b, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x45, 0x4e, + 0x44, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x10, 0x03, + 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x49, 0x4d, 0x45, + 0x4f, 0x55, 0x54, 0x10, 0x04, 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x4f, 0x4c, 0x4c, 0x42, 0x41, 0x43, + 0x4b, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x05, 0x22, 0x2e, 0x0a, 0x09, 0x49, 0x6e, 0x69, 0x74, + 0x69, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x10, + 0x00, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, + 0x42, 0x52, 0x4f, 0x4b, 0x45, 0x52, 0x10, 0x02, 0x42, 0x10, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x70, 0x6e, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_egress_v1_proto_rawDescOnce sync.Once + file_egress_v1_proto_rawDescData = file_egress_v1_proto_rawDesc +) + +func file_egress_v1_proto_rawDescGZIP() []byte { + file_egress_v1_proto_rawDescOnce.Do(func() { + file_egress_v1_proto_rawDescData = protoimpl.X.CompressGZIP(file_egress_v1_proto_rawDescData) + }) + return file_egress_v1_proto_rawDescData +} + +var file_egress_v1_proto_enumTypes = make([]protoimpl.EnumInfo, 4) +var file_egress_v1_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_egress_v1_proto_goTypes = []interface{}{ + (SpanData_SendSpan_Outcome)(0), // 0: solace.messaging.proto.broker.trace.egress.v1.SpanData.SendSpan.Outcome + (SpanData_DeleteSpan_Reason)(0), // 1: solace.messaging.proto.broker.trace.egress.v1.SpanData.DeleteSpan.Reason + (SpanData_TransactionEvent_Type)(0), // 2: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.Type + (SpanData_TransactionEvent_Initiator)(0), // 3: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.Initiator + (*SpanData)(nil), // 4: solace.messaging.proto.broker.trace.egress.v1.SpanData + (*SpanData_EgressSpan)(nil), // 5: solace.messaging.proto.broker.trace.egress.v1.SpanData.EgressSpan + (*SpanData_SendSpan)(nil), // 6: solace.messaging.proto.broker.trace.egress.v1.SpanData.SendSpan + (*SpanData_DeleteSpan)(nil), // 7: solace.messaging.proto.broker.trace.egress.v1.SpanData.DeleteSpan + (*SpanData_TransactionEvent)(nil), // 8: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent + (*SpanData_TransactionEvent_Xid)(nil), // 9: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.Xid + (*SpanData_TransactionEvent_LocalTransactionId)(nil), // 10: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.LocalTransactionId +} +var file_egress_v1_proto_depIdxs = []int32{ + 5, // 0: solace.messaging.proto.broker.trace.egress.v1.SpanData.egress_spans:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.EgressSpan + 8, // 1: solace.messaging.proto.broker.trace.egress.v1.SpanData.EgressSpan.transaction_event:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent + 6, // 2: solace.messaging.proto.broker.trace.egress.v1.SpanData.EgressSpan.send_span:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.SendSpan + 7, // 3: solace.messaging.proto.broker.trace.egress.v1.SpanData.EgressSpan.delete_span:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.DeleteSpan + 0, // 4: solace.messaging.proto.broker.trace.egress.v1.SpanData.SendSpan.outcome:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.SendSpan.Outcome + 1, // 5: solace.messaging.proto.broker.trace.egress.v1.SpanData.DeleteSpan.reason:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.DeleteSpan.Reason + 2, // 6: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.type:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.Type + 3, // 7: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.initiator:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.Initiator + 9, // 8: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.xid:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.Xid + 10, // 9: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.local_id:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.LocalTransactionId + 10, // [10:10] is the sub-list for method output_type + 10, // [10:10] is the sub-list for method input_type + 10, // [10:10] is the sub-list for extension type_name + 10, // [10:10] is the sub-list for extension extendee + 0, // [0:10] is the sub-list for field type_name +} + +func init() { file_egress_v1_proto_init() } +func file_egress_v1_proto_init() { + if File_egress_v1_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_egress_v1_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SpanData); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_egress_v1_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SpanData_EgressSpan); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_egress_v1_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SpanData_SendSpan); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_egress_v1_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SpanData_DeleteSpan); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_egress_v1_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SpanData_TransactionEvent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_egress_v1_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SpanData_TransactionEvent_Xid); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_egress_v1_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SpanData_TransactionEvent_LocalTransactionId); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_egress_v1_proto_msgTypes[0].OneofWrappers = []interface{}{} + file_egress_v1_proto_msgTypes[1].OneofWrappers = []interface{}{ + (*SpanData_EgressSpan_SendSpan)(nil), + (*SpanData_EgressSpan_DeleteSpan)(nil), + } + file_egress_v1_proto_msgTypes[2].OneofWrappers = []interface{}{ + (*SpanData_SendSpan_QueueName)(nil), + (*SpanData_SendSpan_TopicEndpointName)(nil), + } + file_egress_v1_proto_msgTypes[3].OneofWrappers = []interface{}{ + (*SpanData_DeleteSpan_QueueName)(nil), + (*SpanData_DeleteSpan_TopicEndpointName)(nil), + } + file_egress_v1_proto_msgTypes[4].OneofWrappers = []interface{}{ + (*SpanData_TransactionEvent_Xid_)(nil), + (*SpanData_TransactionEvent_LocalId)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_egress_v1_proto_rawDesc, + NumEnums: 4, + NumMessages: 7, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_egress_v1_proto_goTypes, + DependencyIndexes: file_egress_v1_proto_depIdxs, + EnumInfos: file_egress_v1_proto_enumTypes, + MessageInfos: file_egress_v1_proto_msgTypes, + }.Build() + File_egress_v1_proto = out.File + file_egress_v1_proto_rawDesc = nil + file_egress_v1_proto_goTypes = nil + file_egress_v1_proto_depIdxs = nil +} diff --git a/receiver/solacereceiver/model/egress_v1.proto b/receiver/solacereceiver/model/egress_v1.proto new file mode 100644 index 0000000000000..798b3e6564a89 --- /dev/null +++ b/receiver/solacereceiver/model/egress_v1.proto @@ -0,0 +1,191 @@ +syntax = "proto3"; + +package solace.messaging.proto.broker.trace.egress.v1; + +// Messages with the following topic contain a message matching this +// specification: +// _telemetry/broker/trace/egress/v1[/additional/topic/levels] +// Note that the topic allows for additional topic levels to be added in the +// future. Receiving clients must not assume there are no additional topic +// levels. +// +// This message describes telemetry data that a Solace PubSub+ broker captures +// in the egress portion of its data path. +// +// Fields with names that end in "time_unix_nano" are 64-bit timestamps, in +// nanoseconds, since midnight, Jan. 1, 1970 UTC. +// +message SpanData { + + repeated EgressSpan egress_spans = 1; + + // The router-name of the broker generating this message at the time the + // message was generated. + string router_name = 2; + + // The broker's message-vpn name. This field may be removed in the future + // without a major version change since the field is specified as optional. + // + // Rather than rely on this field, receiving clients should obtain the VPN + // by using an SMF API to extract the VPN_NAME_IN_USE from the API's Session + // object. The message_vpn_name of all messages received from via an SMF + // API's session will match the session's VPN_NAME_IN_USE. + optional string message_vpn_name = 3; + + message EgressSpan { + // 16-byte globally unique trace ID. Any two spans with the same trace ID + // are part of the same trace. + bytes trace_id = 1; + + // 8-byte span ID, unique within the scope of a trace. + bytes span_id = 2; + + // If not present, this is a root span. If present, this is an 8-byte span + // ID of the parent span. + optional bytes parent_span_id = 3; + + // The start and end timestamps of the receive span. The start of the span + // is when Guaranteed Messaging processing begins in the broker. + sfixed64 start_time_unix_nano = 4; + sfixed64 end_time_unix_nano = 5; + + optional TransactionEvent transaction_event = 6; + optional string error_description = 7; + + oneof type_data { + SendSpan send_span = 8; + DeleteSpan delete_span = 9; + } + } + + // This message contains information unique to a SendSpan. + message SendSpan { + + // The name of the queue or topic endpoint the message is being delivered + // from. + oneof source { + string queue_name = 1; + string topic_endpoint_name = 2; + } + + bool queue_temporary = 3; + + Outcome outcome = 4; + + bool replayed_msg = 5; + + string consumer_client_username = 6; + string consumer_client_name = 7; + string protocol = 8; + optional string protocol_version = 9; + + enum Outcome { + ACCEPTED = 0; + REJECTED = 1; + RELEASED = 2; + DELIVERY_FAILED = 3; + FLOW_UNBOUND = 4; + TRANSACTION_COMMIT = 5; + TRANSACTION_COMMIT_FAILED = 6; + TRANSACTION_ROLLBACK = 7; + } + } + + // This message contains data unique to delete spans generated in egress. + // The only implemented delete span currently implemented is the + // ENQUEUE_FAILURE reason. Other values are defined to allow their + // implementation to be added in the future without automatically requiring + // a change to the spec. + message DeleteSpan { + // The name of the queue or topic endpoint the message is being deleted + // from. + oneof source { + string queue_name = 1; + string topic_endpoint_name = 2; + } + + bool queue_temporary = 3; + + Reason reason = 4; + + enum Reason { + TTL_EXPIRY = 0; + MAX_REDELIVERIES_EXCEEDED = 1; + ENQUEUE_FAILURE = 2; + ADMIN_MESSAGE_DELETE = 3; + ADMIN_QUEUE_DELETE = 4; + } + } + + // When a span has a transaction event, it indicates the span occurs as part + // of processing a transaction, and includes the *current* state of of the + // transaction when the event was generated. The state can change as + // subsequent events occur as part of the transaction. + message TransactionEvent { + sfixed64 time_unix_nano = 1; + enum Type { + // COMMIT and ROLLBACK are always initiated by either a CLIENT or ADMIN. + // The initiator is ADMIN when the management interface is used to + // to perform a heuristic commit or rollback. + COMMIT = 0; + ROLLBACK = 1; + // PREPARE and END can only occur with a CLIENT initiator, and spans for + // these operations are only generated if the operation fails. Therefore, + // the error_description of the TransactionEvent will always be present + // for END and PREPARE. + END = 2; + PREPARE = 3; + + // The initiator of a SESSION_TIMEOUT is always BROKER. All messages + // received as part of the transaction are discarded. + SESSION_TIMEOUT = 4; + + // The initiator of ROLLBACK_ONLY is always BROKER. The first such event + // in a transaction always has an error_description in the span, + // indicating there was a problem processing the message when it was + // received, and the message is being discarded. This also transitions + // the transaction itself to a "rollback only" state, which causes + // all subsequent messages received as part of the transaction to also + // be discarded. Spans generated by these subsequent discards will not + // have the span's error_description set, but all ROLLBACK_ONLY + // transaction events will have an error_description set, which indicate + // the transaction's error. + // + // Since the only record of these messages in the context of the + // transaction has been discarded, no further span can be generated in + // the context of a client, admin, or session timeout operation. When a + // subsequent operation such as rollback or commit occurs on a + // transaction marked rollback only, only messages received prior to the + // error triggering the transition to rollback only will generate + // receive spans. + ROLLBACK_ONLY = 5; + } + Type type = 2; + + enum Initiator { + CLIENT = 0; + ADMIN = 1; + BROKER = 2; + } + Initiator initiator = 3; + + message Xid { + int32 format_id = 1; + bytes branch_qualifier = 2; + bytes global_id = 3; + } + + message LocalTransactionId { + uint32 transaction_id = 1; + uint32 session_id = 2; + string session_name = 3; + } + + oneof transaction_id { + Xid xid = 4; + LocalTransactionId local_id = 5; + } + + optional string error_description = 6; + } +} diff --git a/receiver/solacereceiver/model/v1/receive_v1.pb.go b/receiver/solacereceiver/model/receive/v1/receive_v1.pb.go similarity index 98% rename from receiver/solacereceiver/model/v1/receive_v1.pb.go rename to receiver/solacereceiver/model/receive/v1/receive_v1.pb.go index 6c0d90b50dfeb..993bbf6e5428d 100644 --- a/receiver/solacereceiver/model/v1/receive_v1.pb.go +++ b/receiver/solacereceiver/model/receive/v1/receive_v1.pb.go @@ -204,17 +204,12 @@ func (SpanData_TransactionEvent_Initiator) EnumDescriptor() ([]byte, []int) { return file_receive_v1_proto_rawDescGZIP(), []int{0, 2, 1} } -// Version 1.0 +// A message will be compatible with this specification if its topic matches: +// _telemetry/broker/trace/receive/v1[/additional/topic/levels] // -// Messages with a topic of matching the following topic contain a v1.x -// specification of this message. -// #telemetry/broker/trace/receive/v1[/ enqueue` messagingDestinationTypeEventKey = "messaging.solace.destination_type" @@ -343,10 +381,10 @@ func (u *brokerTraceReceiveUnmarshallerV1) mapEnqueueEvent(enqueueEvent *model_v var destinationName string var destinationType string switch casted := enqueueEvent.Dest.(type) { - case *model_v1.SpanData_EnqueueEvent_TopicEndpointName: + case *receive_v1.SpanData_EnqueueEvent_TopicEndpointName: destinationName = casted.TopicEndpointName destinationType = topicEndpointKind - case *model_v1.SpanData_EnqueueEvent_QueueName: + case *receive_v1.SpanData_EnqueueEvent_QueueName: destinationName = casted.QueueName destinationType = queueKind default: @@ -366,7 +404,7 @@ func (u *brokerTraceReceiveUnmarshallerV1) mapEnqueueEvent(enqueueEvent *model_v } // mapTransactionEvent maps a SpanData_TransactionEvent to a ClientSpan.Event -func (u *brokerTraceReceiveUnmarshallerV1) mapTransactionEvent(transactionEvent *model_v1.SpanData_TransactionEvent, clientSpanEvents ptrace.SpanEventSlice) { +func (u *brokerTraceReceiveUnmarshallerV1) mapTransactionEvent(transactionEvent *receive_v1.SpanData_TransactionEvent, clientSpanEvents ptrace.SpanEventSlice) { const ( transactionInitiatorEventKey = "messaging.solace.transaction_initiator" transactionIDEventKey = "messaging.solace.transaction_id" @@ -378,17 +416,17 @@ func (u *brokerTraceReceiveUnmarshallerV1) mapTransactionEvent(transactionEvent // map the transaction type to a name var name string switch transactionEvent.GetType() { - case model_v1.SpanData_TransactionEvent_COMMIT: + case receive_v1.SpanData_TransactionEvent_COMMIT: name = "commit" - case model_v1.SpanData_TransactionEvent_ROLLBACK: + case receive_v1.SpanData_TransactionEvent_ROLLBACK: name = "rollback" - case model_v1.SpanData_TransactionEvent_END: + case receive_v1.SpanData_TransactionEvent_END: name = "end" - case model_v1.SpanData_TransactionEvent_PREPARE: + case receive_v1.SpanData_TransactionEvent_PREPARE: name = "prepare" - case model_v1.SpanData_TransactionEvent_SESSION_TIMEOUT: + case receive_v1.SpanData_TransactionEvent_SESSION_TIMEOUT: name = "session_timeout" - case model_v1.SpanData_TransactionEvent_ROLLBACK_ONLY: + case receive_v1.SpanData_TransactionEvent_ROLLBACK_ONLY: name = "rollback_only" default: // Set the name to the unknown transaction event type to ensure forward compat. @@ -402,11 +440,11 @@ func (u *brokerTraceReceiveUnmarshallerV1) mapTransactionEvent(transactionEvent // map initiator enums to expected initiator strings var initiator string switch transactionEvent.GetInitiator() { - case model_v1.SpanData_TransactionEvent_CLIENT: + case receive_v1.SpanData_TransactionEvent_CLIENT: initiator = "client" - case model_v1.SpanData_TransactionEvent_ADMIN: + case receive_v1.SpanData_TransactionEvent_ADMIN: initiator = "administrator" - case model_v1.SpanData_TransactionEvent_BROKER: + case receive_v1.SpanData_TransactionEvent_BROKER: initiator = "broker" default: initiator = fmt.Sprintf("Unknown Transaction Initiator (%s)", transactionEvent.GetInitiator().String()) @@ -421,11 +459,11 @@ func (u *brokerTraceReceiveUnmarshallerV1) mapTransactionEvent(transactionEvent // map the transaction type/id transactionID := transactionEvent.GetTransactionId() switch casted := transactionID.(type) { - case *model_v1.SpanData_TransactionEvent_LocalId: + case *receive_v1.SpanData_TransactionEvent_LocalId: clientEvent.Attributes().PutInt(transactionIDEventKey, int64(casted.LocalId.TransactionId)) clientEvent.Attributes().PutStr(transactedSessionNameEventKey, casted.LocalId.SessionName) clientEvent.Attributes().PutInt(transactedSessionIDEventKey, int64(casted.LocalId.SessionId)) - case *model_v1.SpanData_TransactionEvent_Xid_: + case *receive_v1.SpanData_TransactionEvent_Xid_: // format xxxxxxxx-yyyyyyyy-zzzzzzzz where x is FormatID (hex rep of int32), y is BranchQualifier and z is GlobalID, hex encoded. xidString := fmt.Sprintf("%08x", casted.Xid.FormatId) + "-" + hex.EncodeToString(casted.Xid.BranchQualifier) + "-" + hex.EncodeToString(casted.Xid.GlobalId) @@ -492,37 +530,37 @@ func (u *brokerTraceReceiveUnmarshallerV1) insertUserProperty(toMap pcommon.Map, ) k := userPropertiesAttrKeyPrefix + key switch v := value.(type) { - case *model_v1.SpanData_UserPropertyValue_NullValue: + case *receive_v1.SpanData_UserPropertyValue_NullValue: toMap.PutEmpty(k) - case *model_v1.SpanData_UserPropertyValue_BoolValue: + case *receive_v1.SpanData_UserPropertyValue_BoolValue: toMap.PutBool(k, v.BoolValue) - case *model_v1.SpanData_UserPropertyValue_DoubleValue: + case *receive_v1.SpanData_UserPropertyValue_DoubleValue: toMap.PutDouble(k, v.DoubleValue) - case *model_v1.SpanData_UserPropertyValue_ByteArrayValue: + case *receive_v1.SpanData_UserPropertyValue_ByteArrayValue: toMap.PutEmptyBytes(k).FromRaw(v.ByteArrayValue) - case *model_v1.SpanData_UserPropertyValue_FloatValue: + case *receive_v1.SpanData_UserPropertyValue_FloatValue: toMap.PutDouble(k, float64(v.FloatValue)) - case *model_v1.SpanData_UserPropertyValue_Int8Value: + case *receive_v1.SpanData_UserPropertyValue_Int8Value: toMap.PutInt(k, int64(v.Int8Value)) - case *model_v1.SpanData_UserPropertyValue_Int16Value: + case *receive_v1.SpanData_UserPropertyValue_Int16Value: toMap.PutInt(k, int64(v.Int16Value)) - case *model_v1.SpanData_UserPropertyValue_Int32Value: + case *receive_v1.SpanData_UserPropertyValue_Int32Value: toMap.PutInt(k, int64(v.Int32Value)) - case *model_v1.SpanData_UserPropertyValue_Int64Value: + case *receive_v1.SpanData_UserPropertyValue_Int64Value: toMap.PutInt(k, v.Int64Value) - case *model_v1.SpanData_UserPropertyValue_Uint8Value: + case *receive_v1.SpanData_UserPropertyValue_Uint8Value: toMap.PutInt(k, int64(v.Uint8Value)) - case *model_v1.SpanData_UserPropertyValue_Uint16Value: + case *receive_v1.SpanData_UserPropertyValue_Uint16Value: toMap.PutInt(k, int64(v.Uint16Value)) - case *model_v1.SpanData_UserPropertyValue_Uint32Value: + case *receive_v1.SpanData_UserPropertyValue_Uint32Value: toMap.PutInt(k, int64(v.Uint32Value)) - case *model_v1.SpanData_UserPropertyValue_Uint64Value: + case *receive_v1.SpanData_UserPropertyValue_Uint64Value: toMap.PutInt(k, int64(v.Uint64Value)) - case *model_v1.SpanData_UserPropertyValue_StringValue: + case *receive_v1.SpanData_UserPropertyValue_StringValue: toMap.PutStr(k, v.StringValue) - case *model_v1.SpanData_UserPropertyValue_DestinationValue: + case *receive_v1.SpanData_UserPropertyValue_DestinationValue: toMap.PutStr(k, v.DestinationValue) - case *model_v1.SpanData_UserPropertyValue_CharacterValue: + case *receive_v1.SpanData_UserPropertyValue_CharacterValue: toMap.PutStr(k, string(rune(v.CharacterValue))) default: u.logger.Warn(fmt.Sprintf("Unknown user property type: %T", v)) diff --git a/receiver/solacereceiver/unmarshaller_test.go b/receiver/solacereceiver/unmarshaller_test.go index ce00b4cfd216b..d998a5aa5f60a 100644 --- a/receiver/solacereceiver/unmarshaller_test.go +++ b/receiver/solacereceiver/unmarshaller_test.go @@ -15,6 +15,7 @@ package solacereceiver import ( + "encoding/hex" "errors" "fmt" "testing" @@ -27,9 +28,28 @@ import ( "go.uber.org/zap" "google.golang.org/protobuf/proto" - model_v1 "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/solacereceiver/model/v1" + egress_v1 "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/solacereceiver/model/egress/v1" + receive_v1 "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/solacereceiver/model/receive/v1" ) +func TestPrintPayload(t *testing.T) { + data := &egress_v1.SpanData{} + vpnName := "default" + data.MessageVpnName = &vpnName + data.RouterName = "vmr-133-53" + // data.EgressSpans = []*egress_v1.SpanData_EgressSpan{ + // { + // TraceId: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2}, + // SpanId: []byte{1, 2, 3, 4, 5, 6, 7, 8}, + // ParentSpanId: []byte{1, 2, 3, 4, 5, 6, 7, 8}, + // TypeData: &egress_v1.SpanData_EgressSpan_SendSpan{}, + // }, + // } + bytes, err := proto.Marshal(data) + assert.NoError(t, err) + fmt.Println(hex.Dump(bytes)) +} + // Validate entire unmarshal flow func TestSolaceMessageUnmarshallerUnmarshal(t *testing.T) { validReceiveTopicVersion := "_telemetry/broker/trace/receive/v1" @@ -122,7 +142,7 @@ func TestSolaceMessageUnmarshallerUnmarshal(t *testing.T) { replyToTopic = "someReplyToTopic" topic = "someTopic" ) - validData, err := proto.Marshal(&model_v1.SpanData{ + validData, err := proto.Marshal(&receive_v1.SpanData{ TraceId: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, SpanId: []byte{7, 6, 5, 4, 3, 2, 1, 0}, StartTimeUnixNano: 1234567890, @@ -134,7 +154,7 @@ func TestSolaceMessageUnmarshallerUnmarshal(t *testing.T) { ProtocolVersion: &protocolVersion, ApplicationMessageId: &applicationMessageID, CorrelationId: &correlationID, - DeliveryMode: model_v1.SpanData_DIRECT, + DeliveryMode: receive_v1.SpanData_DIRECT, BinaryAttachmentSize: 1000, XmlAttachmentSize: 200, MetadataSize: 34, @@ -154,29 +174,29 @@ func TestSolaceMessageUnmarshallerUnmarshal(t *testing.T) { PeerPort: 12345, BrokerReceiveTimeUnixNano: 1357924680, DroppedApplicationMessageProperties: false, - UserProperties: map[string]*model_v1.SpanData_UserPropertyValue{ + UserProperties: map[string]*receive_v1.SpanData_UserPropertyValue{ "special_key": { - Value: &model_v1.SpanData_UserPropertyValue_BoolValue{ + Value: &receive_v1.SpanData_UserPropertyValue_BoolValue{ BoolValue: true, }, }, }, - EnqueueEvents: []*model_v1.SpanData_EnqueueEvent{ + EnqueueEvents: []*receive_v1.SpanData_EnqueueEvent{ { - Dest: &model_v1.SpanData_EnqueueEvent_QueueName{QueueName: "somequeue"}, + Dest: &receive_v1.SpanData_EnqueueEvent_QueueName{QueueName: "somequeue"}, TimeUnixNano: 123456789, }, { - Dest: &model_v1.SpanData_EnqueueEvent_TopicEndpointName{TopicEndpointName: "sometopic"}, + Dest: &receive_v1.SpanData_EnqueueEvent_TopicEndpointName{TopicEndpointName: "sometopic"}, TimeUnixNano: 2345678, }, }, - TransactionEvent: &model_v1.SpanData_TransactionEvent{ + TransactionEvent: &receive_v1.SpanData_TransactionEvent{ TimeUnixNano: 123456789, - Type: model_v1.SpanData_TransactionEvent_SESSION_TIMEOUT, - Initiator: model_v1.SpanData_TransactionEvent_CLIENT, - TransactionId: &model_v1.SpanData_TransactionEvent_LocalId{ - LocalId: &model_v1.SpanData_TransactionEvent_LocalTransactionId{ + Type: receive_v1.SpanData_TransactionEvent_SESSION_TIMEOUT, + Initiator: receive_v1.SpanData_TransactionEvent_CLIENT, + TransactionId: &receive_v1.SpanData_TransactionEvent_LocalId{ + LocalId: &receive_v1.SpanData_TransactionEvent_LocalTransactionId{ TransactionId: 12345, SessionId: 67890, SessionName: "my-session-name", @@ -295,13 +315,13 @@ func TestUnmarshallerMapResourceSpan(t *testing.T) { ) tests := []struct { name string - spanData *model_v1.SpanData + spanData *receive_v1.SpanData want map[string]interface{} expectedUnmarshallingErrors interface{} }{ { name: "Maps All Fields When Present", - spanData: &model_v1.SpanData{ + spanData: &receive_v1.SpanData{ RouterName: routerName, MessageVpnName: &vpnName, SolosVersion: version, @@ -314,7 +334,7 @@ func TestUnmarshallerMapResourceSpan(t *testing.T) { }, { name: "Does Not Map Fields When Not Present", - spanData: &model_v1.SpanData{}, + spanData: &receive_v1.SpanData{}, want: map[string]interface{}{ "service.version": "", "service.name": "", @@ -338,13 +358,13 @@ func TestUnmarshallerMapClientSpanData(t *testing.T) { someTraceState := "some trace status" tests := []struct { name string - data *model_v1.SpanData + data *receive_v1.SpanData want func(ptrace.Span) }{ // no trace state no status no parent span { name: "Without Optional Fields", - data: &model_v1.SpanData{ + data: &receive_v1.SpanData{ TraceId: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, SpanId: []byte{7, 6, 5, 4, 3, 2, 1, 0}, StartTimeUnixNano: 1234567890, @@ -364,7 +384,7 @@ func TestUnmarshallerMapClientSpanData(t *testing.T) { // trace state status and parent span { name: "With Optional Fields", - data: &model_v1.SpanData{ + data: &receive_v1.SpanData{ TraceId: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, SpanId: []byte{7, 6, 5, 4, 3, 2, 1, 0}, StartTimeUnixNano: 1234567890, @@ -414,13 +434,13 @@ func TestUnmarshallerMapClientSpanAttributes(t *testing.T) { tests := []struct { name string - spanData *model_v1.SpanData + spanData *receive_v1.SpanData want map[string]interface{} expectedUnmarshallingErrors interface{} }{ { name: "With All Valid Attributes", - spanData: &model_v1.SpanData{ + spanData: &receive_v1.SpanData{ Protocol: "MQTT", ProtocolVersion: &protocolVersion, ApplicationMessageId: &applicationMessageID, @@ -431,7 +451,7 @@ func TestUnmarshallerMapClientSpanAttributes(t *testing.T) { ClientUsername: "someClientUsername", ClientName: "someClient1234", ReplyToTopic: &replyToTopic, - DeliveryMode: model_v1.SpanData_PERSISTENT, + DeliveryMode: receive_v1.SpanData_PERSISTENT, Topic: "someTopic", ReplicationGroupMessageId: []byte{0x01, 0x00, 0x01, 0x04, 0x09, 0x10, 0x19, 0x24, 0x31, 0x40, 0x51, 0x64, 0x79, 0x90, 0xa9, 0xc4, 0xe1}, Priority: &priority, @@ -446,9 +466,9 @@ func TestUnmarshallerMapClientSpanAttributes(t *testing.T) { BrokerReceiveTimeUnixNano: 1357924680, DroppedApplicationMessageProperties: false, Baggage: &baggageString, - UserProperties: map[string]*model_v1.SpanData_UserPropertyValue{ + UserProperties: map[string]*receive_v1.SpanData_UserPropertyValue{ "special_key": { - Value: &model_v1.SpanData_UserPropertyValue_BoolValue{ + Value: &receive_v1.SpanData_UserPropertyValue_BoolValue{ BoolValue: true, }, }, @@ -488,7 +508,7 @@ func TestUnmarshallerMapClientSpanAttributes(t *testing.T) { }, { name: "With Only Required Fields", - spanData: &model_v1.SpanData{ + spanData: &receive_v1.SpanData{ Protocol: "MQTT", BinaryAttachmentSize: 1000, XmlAttachmentSize: 200, @@ -496,7 +516,7 @@ func TestUnmarshallerMapClientSpanAttributes(t *testing.T) { ClientUsername: "someClientUsername", ClientName: "someClient1234", Topic: "someTopic", - DeliveryMode: model_v1.SpanData_NON_PERSISTENT, + DeliveryMode: receive_v1.SpanData_NON_PERSISTENT, DmqEligible: true, DroppedEnqueueEventsSuccess: 42, DroppedEnqueueEventsFailed: 24, @@ -506,7 +526,7 @@ func TestUnmarshallerMapClientSpanAttributes(t *testing.T) { PeerPort: 12345, BrokerReceiveTimeUnixNano: 1357924680, DroppedApplicationMessageProperties: true, - UserProperties: map[string]*model_v1.SpanData_UserPropertyValue{ + UserProperties: map[string]*receive_v1.SpanData_UserPropertyValue{ "special_key": nil, }, }, @@ -532,7 +552,7 @@ func TestUnmarshallerMapClientSpanAttributes(t *testing.T) { }, { name: "With Some Invalid Fields", - spanData: &model_v1.SpanData{ + spanData: &receive_v1.SpanData{ Protocol: "MQTT", BinaryAttachmentSize: 1000, XmlAttachmentSize: 200, @@ -540,7 +560,7 @@ func TestUnmarshallerMapClientSpanAttributes(t *testing.T) { ClientUsername: "someClientUsername", ClientName: "someClient1234", Topic: "someTopic", - DeliveryMode: model_v1.SpanData_DeliveryMode(1000), + DeliveryMode: receive_v1.SpanData_DeliveryMode(1000), DmqEligible: true, DroppedEnqueueEventsSuccess: 42, DroppedEnqueueEventsFailed: 24, @@ -549,7 +569,7 @@ func TestUnmarshallerMapClientSpanAttributes(t *testing.T) { BrokerReceiveTimeUnixNano: 1357924680, DroppedApplicationMessageProperties: true, Baggage: &invalidBaggageString, - UserProperties: map[string]*model_v1.SpanData_UserPropertyValue{ + UserProperties: map[string]*receive_v1.SpanData_UserPropertyValue{ "special_key": nil, }, }, @@ -590,21 +610,21 @@ func TestUnmarshallerEvents(t *testing.T) { someErrorString := "some error" tests := []struct { name string - spanData *model_v1.SpanData + spanData *receive_v1.SpanData populateExpectedSpan func(span ptrace.Span) unmarshallingErrors interface{} }{ { // don't expect any events when none are present in the span data name: "No Events", - spanData: &model_v1.SpanData{}, + spanData: &receive_v1.SpanData{}, populateExpectedSpan: func(span ptrace.Span) {}, }, { // when an enqueue event is present, expect it to be added to the span events name: "Enqueue Event Queue", - spanData: &model_v1.SpanData{ - EnqueueEvents: []*model_v1.SpanData_EnqueueEvent{ + spanData: &receive_v1.SpanData{ + EnqueueEvents: []*receive_v1.SpanData_EnqueueEvent{ { - Dest: &model_v1.SpanData_EnqueueEvent_QueueName{QueueName: "somequeue"}, + Dest: &receive_v1.SpanData_EnqueueEvent_QueueName{QueueName: "somequeue"}, TimeUnixNano: 123456789, }, }, @@ -618,10 +638,10 @@ func TestUnmarshallerEvents(t *testing.T) { }, { // when a topic endpoint enqueue event is present, expect it to be added to the span events name: "Enqueue Event Topic Endpoint", - spanData: &model_v1.SpanData{ - EnqueueEvents: []*model_v1.SpanData_EnqueueEvent{ + spanData: &receive_v1.SpanData{ + EnqueueEvents: []*receive_v1.SpanData_EnqueueEvent{ { - Dest: &model_v1.SpanData_EnqueueEvent_TopicEndpointName{TopicEndpointName: "sometopic"}, + Dest: &receive_v1.SpanData_EnqueueEvent_TopicEndpointName{TopicEndpointName: "sometopic"}, TimeUnixNano: 123456789, ErrorDescription: &someErrorString, RejectsAllEnqueues: true, @@ -638,14 +658,14 @@ func TestUnmarshallerEvents(t *testing.T) { }, { // when a both a queue and topic endpoint enqueue event is present, expect it to be added to the span events name: "Enqueue Event Queue and Topic Endpoint", - spanData: &model_v1.SpanData{ - EnqueueEvents: []*model_v1.SpanData_EnqueueEvent{ + spanData: &receive_v1.SpanData{ + EnqueueEvents: []*receive_v1.SpanData_EnqueueEvent{ { - Dest: &model_v1.SpanData_EnqueueEvent_QueueName{QueueName: "somequeue"}, + Dest: &receive_v1.SpanData_EnqueueEvent_QueueName{QueueName: "somequeue"}, TimeUnixNano: 123456789, }, { - Dest: &model_v1.SpanData_EnqueueEvent_TopicEndpointName{TopicEndpointName: "sometopic"}, + Dest: &receive_v1.SpanData_EnqueueEvent_TopicEndpointName{TopicEndpointName: "sometopic"}, TimeUnixNano: 2345678, }, }, @@ -663,8 +683,8 @@ func TestUnmarshallerEvents(t *testing.T) { }, { // when an enqueue event does not have a valid dest (ie. nil) name: "Enqueue Event no Dest", - spanData: &model_v1.SpanData{ - EnqueueEvents: []*model_v1.SpanData_EnqueueEvent{ + spanData: &receive_v1.SpanData{ + EnqueueEvents: []*receive_v1.SpanData_EnqueueEvent{ { Dest: nil, TimeUnixNano: 123456789, @@ -676,13 +696,13 @@ func TestUnmarshallerEvents(t *testing.T) { }, { // Local Transaction name: "Local Transaction Event", - spanData: &model_v1.SpanData{ - TransactionEvent: &model_v1.SpanData_TransactionEvent{ + spanData: &receive_v1.SpanData{ + TransactionEvent: &receive_v1.SpanData_TransactionEvent{ TimeUnixNano: 123456789, - Type: model_v1.SpanData_TransactionEvent_COMMIT, - Initiator: model_v1.SpanData_TransactionEvent_CLIENT, - TransactionId: &model_v1.SpanData_TransactionEvent_LocalId{ - LocalId: &model_v1.SpanData_TransactionEvent_LocalTransactionId{ + Type: receive_v1.SpanData_TransactionEvent_COMMIT, + Initiator: receive_v1.SpanData_TransactionEvent_CLIENT, + TransactionId: &receive_v1.SpanData_TransactionEvent_LocalId{ + LocalId: &receive_v1.SpanData_TransactionEvent_LocalTransactionId{ TransactionId: 12345, SessionId: 67890, SessionName: "my-session-name", @@ -701,13 +721,13 @@ func TestUnmarshallerEvents(t *testing.T) { }, { // XA transaction name: "XA Transaction Event", - spanData: &model_v1.SpanData{ - TransactionEvent: &model_v1.SpanData_TransactionEvent{ + spanData: &receive_v1.SpanData{ + TransactionEvent: &receive_v1.SpanData_TransactionEvent{ TimeUnixNano: 123456789, - Type: model_v1.SpanData_TransactionEvent_END, - Initiator: model_v1.SpanData_TransactionEvent_ADMIN, - TransactionId: &model_v1.SpanData_TransactionEvent_Xid_{ - Xid: &model_v1.SpanData_TransactionEvent_Xid{ + Type: receive_v1.SpanData_TransactionEvent_END, + Initiator: receive_v1.SpanData_TransactionEvent_ADMIN, + TransactionId: &receive_v1.SpanData_TransactionEvent_Xid_{ + Xid: &receive_v1.SpanData_TransactionEvent_Xid{ FormatId: 123, BranchQualifier: []byte{0, 8, 20, 254}, GlobalId: []byte{128, 64, 32, 16, 8, 4, 2, 1, 0}, @@ -724,13 +744,13 @@ func TestUnmarshallerEvents(t *testing.T) { }, { // XA Transaction with no branch qualifier or global ID and with an error name: "XA Transaction Event with nil fields and error", - spanData: &model_v1.SpanData{ - TransactionEvent: &model_v1.SpanData_TransactionEvent{ + spanData: &receive_v1.SpanData{ + TransactionEvent: &receive_v1.SpanData_TransactionEvent{ TimeUnixNano: 123456789, - Type: model_v1.SpanData_TransactionEvent_PREPARE, - Initiator: model_v1.SpanData_TransactionEvent_BROKER, - TransactionId: &model_v1.SpanData_TransactionEvent_Xid_{ - Xid: &model_v1.SpanData_TransactionEvent_Xid{ + Type: receive_v1.SpanData_TransactionEvent_PREPARE, + Initiator: receive_v1.SpanData_TransactionEvent_BROKER, + TransactionId: &receive_v1.SpanData_TransactionEvent_Xid_{ + Xid: &receive_v1.SpanData_TransactionEvent_Xid{ FormatId: 123, BranchQualifier: nil, GlobalId: nil, @@ -749,10 +769,10 @@ func TestUnmarshallerEvents(t *testing.T) { }, { // Type of transaction not handled name: "Unknown Transaction Type and no ID", - spanData: &model_v1.SpanData{ - TransactionEvent: &model_v1.SpanData_TransactionEvent{ + spanData: &receive_v1.SpanData{ + TransactionEvent: &receive_v1.SpanData_TransactionEvent{ TimeUnixNano: 123456789, - Type: model_v1.SpanData_TransactionEvent_Type(12345), + Type: receive_v1.SpanData_TransactionEvent_Type(12345), }, }, populateExpectedSpan: func(span ptrace.Span) { @@ -764,11 +784,11 @@ func TestUnmarshallerEvents(t *testing.T) { }, { // Type of ID not handled, type of initiator not handled name: "Unknown Transaction Initiator and no ID", - spanData: &model_v1.SpanData{ - TransactionEvent: &model_v1.SpanData_TransactionEvent{ + spanData: &receive_v1.SpanData{ + TransactionEvent: &receive_v1.SpanData_TransactionEvent{ TimeUnixNano: 123456789, - Type: model_v1.SpanData_TransactionEvent_ROLLBACK, - Initiator: model_v1.SpanData_TransactionEvent_Initiator(12345), + Type: receive_v1.SpanData_TransactionEvent_ROLLBACK, + Initiator: receive_v1.SpanData_TransactionEvent_Initiator(12345), TransactionId: nil, }, }, @@ -781,24 +801,24 @@ func TestUnmarshallerEvents(t *testing.T) { }, { // when a both a queue and topic endpoint enqueue event is present, expect it to be added to the span events name: "Multiple Events", - spanData: &model_v1.SpanData{ - EnqueueEvents: []*model_v1.SpanData_EnqueueEvent{ + spanData: &receive_v1.SpanData{ + EnqueueEvents: []*receive_v1.SpanData_EnqueueEvent{ { - Dest: &model_v1.SpanData_EnqueueEvent_QueueName{QueueName: "somequeue"}, + Dest: &receive_v1.SpanData_EnqueueEvent_QueueName{QueueName: "somequeue"}, TimeUnixNano: 123456789, }, { - Dest: &model_v1.SpanData_EnqueueEvent_TopicEndpointName{TopicEndpointName: "sometopic"}, + Dest: &receive_v1.SpanData_EnqueueEvent_TopicEndpointName{TopicEndpointName: "sometopic"}, TimeUnixNano: 2345678, RejectsAllEnqueues: true, }, }, - TransactionEvent: &model_v1.SpanData_TransactionEvent{ + TransactionEvent: &receive_v1.SpanData_TransactionEvent{ TimeUnixNano: 123456789, - Type: model_v1.SpanData_TransactionEvent_ROLLBACK_ONLY, - Initiator: model_v1.SpanData_TransactionEvent_CLIENT, - TransactionId: &model_v1.SpanData_TransactionEvent_LocalId{ - LocalId: &model_v1.SpanData_TransactionEvent_LocalTransactionId{ + Type: receive_v1.SpanData_TransactionEvent_ROLLBACK_ONLY, + Initiator: receive_v1.SpanData_TransactionEvent_CLIENT, + TransactionId: &receive_v1.SpanData_TransactionEvent_LocalId{ + LocalId: &receive_v1.SpanData_TransactionEvent_LocalTransactionId{ TransactionId: 12345, SessionId: 67890, SessionName: "my-session-name", @@ -986,124 +1006,124 @@ func TestUnmarshallerInsertUserProperty(t *testing.T) { validate func(val pcommon.Value) }{ { - &model_v1.SpanData_UserPropertyValue_NullValue{}, + &receive_v1.SpanData_UserPropertyValue_NullValue{}, pcommon.ValueTypeEmpty, nil, }, { - &model_v1.SpanData_UserPropertyValue_BoolValue{BoolValue: true}, + &receive_v1.SpanData_UserPropertyValue_BoolValue{BoolValue: true}, pcommon.ValueTypeBool, func(val pcommon.Value) { assert.Equal(t, true, val.Bool()) }, }, { - &model_v1.SpanData_UserPropertyValue_DoubleValue{DoubleValue: 12.34}, + &receive_v1.SpanData_UserPropertyValue_DoubleValue{DoubleValue: 12.34}, pcommon.ValueTypeDouble, func(val pcommon.Value) { assert.Equal(t, float64(12.34), val.Double()) }, }, { - &model_v1.SpanData_UserPropertyValue_ByteArrayValue{ByteArrayValue: []byte{1, 2, 3, 4}}, + &receive_v1.SpanData_UserPropertyValue_ByteArrayValue{ByteArrayValue: []byte{1, 2, 3, 4}}, pcommon.ValueTypeBytes, func(val pcommon.Value) { assert.Equal(t, []byte{1, 2, 3, 4}, val.Bytes().AsRaw()) }, }, { - &model_v1.SpanData_UserPropertyValue_FloatValue{FloatValue: 12.34}, + &receive_v1.SpanData_UserPropertyValue_FloatValue{FloatValue: 12.34}, pcommon.ValueTypeDouble, func(val pcommon.Value) { assert.Equal(t, float64(float32(12.34)), val.Double()) }, }, { - &model_v1.SpanData_UserPropertyValue_Int8Value{Int8Value: 8}, + &receive_v1.SpanData_UserPropertyValue_Int8Value{Int8Value: 8}, pcommon.ValueTypeInt, func(val pcommon.Value) { assert.Equal(t, int64(8), val.Int()) }, }, { - &model_v1.SpanData_UserPropertyValue_Int16Value{Int16Value: 16}, + &receive_v1.SpanData_UserPropertyValue_Int16Value{Int16Value: 16}, pcommon.ValueTypeInt, func(val pcommon.Value) { assert.Equal(t, int64(16), val.Int()) }, }, { - &model_v1.SpanData_UserPropertyValue_Int32Value{Int32Value: 32}, + &receive_v1.SpanData_UserPropertyValue_Int32Value{Int32Value: 32}, pcommon.ValueTypeInt, func(val pcommon.Value) { assert.Equal(t, int64(32), val.Int()) }, }, { - &model_v1.SpanData_UserPropertyValue_Int64Value{Int64Value: 64}, + &receive_v1.SpanData_UserPropertyValue_Int64Value{Int64Value: 64}, pcommon.ValueTypeInt, func(val pcommon.Value) { assert.Equal(t, int64(64), val.Int()) }, }, { - &model_v1.SpanData_UserPropertyValue_Uint8Value{Uint8Value: 8}, + &receive_v1.SpanData_UserPropertyValue_Uint8Value{Uint8Value: 8}, pcommon.ValueTypeInt, func(val pcommon.Value) { assert.Equal(t, int64(8), val.Int()) }, }, { - &model_v1.SpanData_UserPropertyValue_Uint16Value{Uint16Value: 16}, + &receive_v1.SpanData_UserPropertyValue_Uint16Value{Uint16Value: 16}, pcommon.ValueTypeInt, func(val pcommon.Value) { assert.Equal(t, int64(16), val.Int()) }, }, { - &model_v1.SpanData_UserPropertyValue_Uint32Value{Uint32Value: 32}, + &receive_v1.SpanData_UserPropertyValue_Uint32Value{Uint32Value: 32}, pcommon.ValueTypeInt, func(val pcommon.Value) { assert.Equal(t, int64(32), val.Int()) }, }, { - &model_v1.SpanData_UserPropertyValue_Uint64Value{Uint64Value: 64}, + &receive_v1.SpanData_UserPropertyValue_Uint64Value{Uint64Value: 64}, pcommon.ValueTypeInt, func(val pcommon.Value) { assert.Equal(t, int64(64), val.Int()) }, }, { - &model_v1.SpanData_UserPropertyValue_StringValue{StringValue: "hello world"}, + &receive_v1.SpanData_UserPropertyValue_StringValue{StringValue: "hello world"}, pcommon.ValueTypeStr, func(val pcommon.Value) { assert.Equal(t, "hello world", val.Str()) }, }, { - &model_v1.SpanData_UserPropertyValue_DestinationValue{DestinationValue: "some_dest"}, + &receive_v1.SpanData_UserPropertyValue_DestinationValue{DestinationValue: "some_dest"}, pcommon.ValueTypeStr, func(val pcommon.Value) { assert.Equal(t, "some_dest", val.Str()) }, }, { - &model_v1.SpanData_UserPropertyValue_CharacterValue{CharacterValue: 0x61}, + &receive_v1.SpanData_UserPropertyValue_CharacterValue{CharacterValue: 0x61}, pcommon.ValueTypeStr, func(val pcommon.Value) { assert.Equal(t, "a", val.Str()) }, }, { - &model_v1.SpanData_UserPropertyValue_CharacterValue{CharacterValue: 0xe68080}, + &receive_v1.SpanData_UserPropertyValue_CharacterValue{CharacterValue: 0xe68080}, pcommon.ValueTypeStr, func(val pcommon.Value) { assert.Equal(t, string(rune(0xe68080)), val.Str()) }, }, { - &model_v1.SpanData_UserPropertyValue_CharacterValue{CharacterValue: 0xf09f92a9}, + &receive_v1.SpanData_UserPropertyValue_CharacterValue{CharacterValue: 0xf09f92a9}, pcommon.ValueTypeStr, func(val pcommon.Value) { assert.Equal(t, string(rune(emojiVal)), val.Str()) From 4458ac6b2675a3dc67e9190dc934d31f8d87712c Mon Sep 17 00:00:00 2001 From: Michael Cardy Date: Tue, 4 Apr 2023 08:48:15 -0400 Subject: [PATCH 02/10] Refactored unmarshaller separating out receive and egress, added egress SOL-86715 --- .../model/egress/v1/egress_v1.pb.go | 604 ++++-------- receiver/solacereceiver/model/egress_v1.proto | 51 +- receiver/solacereceiver/observability.go | 11 + receiver/solacereceiver/observability_test.go | 1 + receiver/solacereceiver/unmarshaller.go | 507 +--------- .../solacereceiver/unmarshaller_egress.go | 227 +++++ .../unmarshaller_egress_test.go | 583 +++++++++++ .../solacereceiver/unmarshaller_receive.go | 415 ++++++++ .../unmarshaller_receive_test.go | 843 ++++++++++++++++ receiver/solacereceiver/unmarshaller_test.go | 920 ++---------------- 10 files changed, 2414 insertions(+), 1748 deletions(-) create mode 100644 receiver/solacereceiver/unmarshaller_egress.go create mode 100644 receiver/solacereceiver/unmarshaller_egress_test.go create mode 100644 receiver/solacereceiver/unmarshaller_receive.go create mode 100644 receiver/solacereceiver/unmarshaller_receive_test.go diff --git a/receiver/solacereceiver/model/egress/v1/egress_v1.pb.go b/receiver/solacereceiver/model/egress/v1/egress_v1.pb.go index 1b45106b0cadd..eff5062d30222 100644 --- a/receiver/solacereceiver/model/egress/v1/egress_v1.pb.go +++ b/receiver/solacereceiver/model/egress/v1/egress_v1.pb.go @@ -85,61 +85,6 @@ func (SpanData_SendSpan_Outcome) EnumDescriptor() ([]byte, []int) { return file_egress_v1_proto_rawDescGZIP(), []int{0, 1, 0} } -type SpanData_DeleteSpan_Reason int32 - -const ( - SpanData_DeleteSpan_TTL_EXPIRY SpanData_DeleteSpan_Reason = 0 - SpanData_DeleteSpan_MAX_REDELIVERIES_EXCEEDED SpanData_DeleteSpan_Reason = 1 - SpanData_DeleteSpan_ENQUEUE_FAILURE SpanData_DeleteSpan_Reason = 2 - SpanData_DeleteSpan_ADMIN_MESSAGE_DELETE SpanData_DeleteSpan_Reason = 3 - SpanData_DeleteSpan_ADMIN_QUEUE_DELETE SpanData_DeleteSpan_Reason = 4 -) - -// Enum value maps for SpanData_DeleteSpan_Reason. -var ( - SpanData_DeleteSpan_Reason_name = map[int32]string{ - 0: "TTL_EXPIRY", - 1: "MAX_REDELIVERIES_EXCEEDED", - 2: "ENQUEUE_FAILURE", - 3: "ADMIN_MESSAGE_DELETE", - 4: "ADMIN_QUEUE_DELETE", - } - SpanData_DeleteSpan_Reason_value = map[string]int32{ - "TTL_EXPIRY": 0, - "MAX_REDELIVERIES_EXCEEDED": 1, - "ENQUEUE_FAILURE": 2, - "ADMIN_MESSAGE_DELETE": 3, - "ADMIN_QUEUE_DELETE": 4, - } -) - -func (x SpanData_DeleteSpan_Reason) Enum() *SpanData_DeleteSpan_Reason { - p := new(SpanData_DeleteSpan_Reason) - *p = x - return p -} - -func (x SpanData_DeleteSpan_Reason) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (SpanData_DeleteSpan_Reason) Descriptor() protoreflect.EnumDescriptor { - return file_egress_v1_proto_enumTypes[1].Descriptor() -} - -func (SpanData_DeleteSpan_Reason) Type() protoreflect.EnumType { - return &file_egress_v1_proto_enumTypes[1] -} - -func (x SpanData_DeleteSpan_Reason) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use SpanData_DeleteSpan_Reason.Descriptor instead. -func (SpanData_DeleteSpan_Reason) EnumDescriptor() ([]byte, []int) { - return file_egress_v1_proto_rawDescGZIP(), []int{0, 2, 0} -} - type SpanData_TransactionEvent_Type int32 const ( @@ -209,11 +154,11 @@ func (x SpanData_TransactionEvent_Type) String() string { } func (SpanData_TransactionEvent_Type) Descriptor() protoreflect.EnumDescriptor { - return file_egress_v1_proto_enumTypes[2].Descriptor() + return file_egress_v1_proto_enumTypes[1].Descriptor() } func (SpanData_TransactionEvent_Type) Type() protoreflect.EnumType { - return &file_egress_v1_proto_enumTypes[2] + return &file_egress_v1_proto_enumTypes[1] } func (x SpanData_TransactionEvent_Type) Number() protoreflect.EnumNumber { @@ -222,7 +167,7 @@ func (x SpanData_TransactionEvent_Type) Number() protoreflect.EnumNumber { // Deprecated: Use SpanData_TransactionEvent_Type.Descriptor instead. func (SpanData_TransactionEvent_Type) EnumDescriptor() ([]byte, []int) { - return file_egress_v1_proto_rawDescGZIP(), []int{0, 3, 0} + return file_egress_v1_proto_rawDescGZIP(), []int{0, 2, 0} } type SpanData_TransactionEvent_Initiator int32 @@ -258,11 +203,11 @@ func (x SpanData_TransactionEvent_Initiator) String() string { } func (SpanData_TransactionEvent_Initiator) Descriptor() protoreflect.EnumDescriptor { - return file_egress_v1_proto_enumTypes[3].Descriptor() + return file_egress_v1_proto_enumTypes[2].Descriptor() } func (SpanData_TransactionEvent_Initiator) Type() protoreflect.EnumType { - return &file_egress_v1_proto_enumTypes[3] + return &file_egress_v1_proto_enumTypes[2] } func (x SpanData_TransactionEvent_Initiator) Number() protoreflect.EnumNumber { @@ -271,7 +216,7 @@ func (x SpanData_TransactionEvent_Initiator) Number() protoreflect.EnumNumber { // Deprecated: Use SpanData_TransactionEvent_Initiator.Descriptor instead. func (SpanData_TransactionEvent_Initiator) EnumDescriptor() ([]byte, []int) { - return file_egress_v1_proto_rawDescGZIP(), []int{0, 3, 1} + return file_egress_v1_proto_rawDescGZIP(), []int{0, 2, 1} } // Messages with the following topic contain a message matching this @@ -303,6 +248,9 @@ type SpanData struct { // object. The message_vpn_name of all messages received from via an SMF // API's session will match the session's VPN_NAME_IN_USE. MessageVpnName *string `protobuf:"bytes,3,opt,name=message_vpn_name,json=messageVpnName,proto3,oneof" json:"message_vpn_name,omitempty"` + // The SolOS version of the broker generating the message. All elements of + // egress_spans will always have been created by the same broker version. + SolosVersion string `protobuf:"bytes,4,opt,name=solos_version,json=solosVersion,proto3" json:"solos_version,omitempty"` } func (x *SpanData) Reset() { @@ -358,6 +306,13 @@ func (x *SpanData) GetMessageVpnName() string { return "" } +func (x *SpanData) GetSolosVersion() string { + if x != nil { + return x.SolosVersion + } + return "" +} + type SpanData_EgressSpan struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -379,7 +334,6 @@ type SpanData_EgressSpan struct { ErrorDescription *string `protobuf:"bytes,7,opt,name=error_description,json=errorDescription,proto3,oneof" json:"error_description,omitempty"` // Types that are assignable to TypeData: // *SpanData_EgressSpan_SendSpan - // *SpanData_EgressSpan_DeleteSpan TypeData isSpanData_EgressSpan_TypeData `protobuf_oneof:"type_data"` } @@ -478,13 +432,6 @@ func (x *SpanData_EgressSpan) GetSendSpan() *SpanData_SendSpan { return nil } -func (x *SpanData_EgressSpan) GetDeleteSpan() *SpanData_DeleteSpan { - if x, ok := x.GetTypeData().(*SpanData_EgressSpan_DeleteSpan); ok { - return x.DeleteSpan - } - return nil -} - type isSpanData_EgressSpan_TypeData interface { isSpanData_EgressSpan_TypeData() } @@ -493,14 +440,8 @@ type SpanData_EgressSpan_SendSpan struct { SendSpan *SpanData_SendSpan `protobuf:"bytes,8,opt,name=send_span,json=sendSpan,proto3,oneof"` } -type SpanData_EgressSpan_DeleteSpan struct { - DeleteSpan *SpanData_DeleteSpan `protobuf:"bytes,9,opt,name=delete_span,json=deleteSpan,proto3,oneof"` -} - func (*SpanData_EgressSpan_SendSpan) isSpanData_EgressSpan_TypeData() {} -func (*SpanData_EgressSpan_DeleteSpan) isSpanData_EgressSpan_TypeData() {} - // This message contains information unique to a SendSpan. type SpanData_SendSpan struct { state protoimpl.MessageState @@ -514,13 +455,12 @@ type SpanData_SendSpan struct { // *SpanData_SendSpan_QueueName // *SpanData_SendSpan_TopicEndpointName Source isSpanData_SendSpan_Source `protobuf_oneof:"source"` - QueueTemporary bool `protobuf:"varint,3,opt,name=queue_temporary,json=queueTemporary,proto3" json:"queue_temporary,omitempty"` - Outcome SpanData_SendSpan_Outcome `protobuf:"varint,4,opt,name=outcome,proto3,enum=solace.messaging.proto.broker.trace.egress.v1.SpanData_SendSpan_Outcome" json:"outcome,omitempty"` - ReplayedMsg bool `protobuf:"varint,5,opt,name=replayed_msg,json=replayedMsg,proto3" json:"replayed_msg,omitempty"` - ConsumerClientUsername string `protobuf:"bytes,6,opt,name=consumer_client_username,json=consumerClientUsername,proto3" json:"consumer_client_username,omitempty"` - ConsumerClientName string `protobuf:"bytes,7,opt,name=consumer_client_name,json=consumerClientName,proto3" json:"consumer_client_name,omitempty"` - Protocol string `protobuf:"bytes,8,opt,name=protocol,proto3" json:"protocol,omitempty"` - ProtocolVersion *string `protobuf:"bytes,9,opt,name=protocol_version,json=protocolVersion,proto3,oneof" json:"protocol_version,omitempty"` + Outcome SpanData_SendSpan_Outcome `protobuf:"varint,3,opt,name=outcome,proto3,enum=solace.messaging.proto.broker.trace.egress.v1.SpanData_SendSpan_Outcome" json:"outcome,omitempty"` + ReplayedMsg bool `protobuf:"varint,4,opt,name=replayed_msg,json=replayedMsg,proto3" json:"replayed_msg,omitempty"` + ConsumerClientUsername string `protobuf:"bytes,5,opt,name=consumer_client_username,json=consumerClientUsername,proto3" json:"consumer_client_username,omitempty"` + ConsumerClientName string `protobuf:"bytes,6,opt,name=consumer_client_name,json=consumerClientName,proto3" json:"consumer_client_name,omitempty"` + Protocol string `protobuf:"bytes,7,opt,name=protocol,proto3" json:"protocol,omitempty"` + ProtocolVersion *string `protobuf:"bytes,8,opt,name=protocol_version,json=protocolVersion,proto3,oneof" json:"protocol_version,omitempty"` } func (x *SpanData_SendSpan) Reset() { @@ -576,13 +516,6 @@ func (x *SpanData_SendSpan) GetTopicEndpointName() string { return "" } -func (x *SpanData_SendSpan) GetQueueTemporary() bool { - if x != nil { - return x.QueueTemporary - } - return false -} - func (x *SpanData_SendSpan) GetOutcome() SpanData_SendSpan_Outcome { if x != nil { return x.Outcome @@ -641,110 +574,6 @@ func (*SpanData_SendSpan_QueueName) isSpanData_SendSpan_Source() {} func (*SpanData_SendSpan_TopicEndpointName) isSpanData_SendSpan_Source() {} -// This message contains data unique to delete spans generated in egress. -// The only implemented delete span currently implemented is the -// ENQUEUE_FAILURE reason. Other values are defined to allow their -// implementation to be added in the future without automatically requiring -// a change to the spec. -type SpanData_DeleteSpan struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The name of the queue or topic endpoint the message is being deleted - // from. - // - // Types that are assignable to Source: - // *SpanData_DeleteSpan_QueueName - // *SpanData_DeleteSpan_TopicEndpointName - Source isSpanData_DeleteSpan_Source `protobuf_oneof:"source"` - QueueTemporary bool `protobuf:"varint,3,opt,name=queue_temporary,json=queueTemporary,proto3" json:"queue_temporary,omitempty"` - Reason SpanData_DeleteSpan_Reason `protobuf:"varint,4,opt,name=reason,proto3,enum=solace.messaging.proto.broker.trace.egress.v1.SpanData_DeleteSpan_Reason" json:"reason,omitempty"` -} - -func (x *SpanData_DeleteSpan) Reset() { - *x = SpanData_DeleteSpan{} - if protoimpl.UnsafeEnabled { - mi := &file_egress_v1_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SpanData_DeleteSpan) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SpanData_DeleteSpan) ProtoMessage() {} - -func (x *SpanData_DeleteSpan) ProtoReflect() protoreflect.Message { - mi := &file_egress_v1_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 SpanData_DeleteSpan.ProtoReflect.Descriptor instead. -func (*SpanData_DeleteSpan) Descriptor() ([]byte, []int) { - return file_egress_v1_proto_rawDescGZIP(), []int{0, 2} -} - -func (m *SpanData_DeleteSpan) GetSource() isSpanData_DeleteSpan_Source { - if m != nil { - return m.Source - } - return nil -} - -func (x *SpanData_DeleteSpan) GetQueueName() string { - if x, ok := x.GetSource().(*SpanData_DeleteSpan_QueueName); ok { - return x.QueueName - } - return "" -} - -func (x *SpanData_DeleteSpan) GetTopicEndpointName() string { - if x, ok := x.GetSource().(*SpanData_DeleteSpan_TopicEndpointName); ok { - return x.TopicEndpointName - } - return "" -} - -func (x *SpanData_DeleteSpan) GetQueueTemporary() bool { - if x != nil { - return x.QueueTemporary - } - return false -} - -func (x *SpanData_DeleteSpan) GetReason() SpanData_DeleteSpan_Reason { - if x != nil { - return x.Reason - } - return SpanData_DeleteSpan_TTL_EXPIRY -} - -type isSpanData_DeleteSpan_Source interface { - isSpanData_DeleteSpan_Source() -} - -type SpanData_DeleteSpan_QueueName struct { - QueueName string `protobuf:"bytes,1,opt,name=queue_name,json=queueName,proto3,oneof"` -} - -type SpanData_DeleteSpan_TopicEndpointName struct { - TopicEndpointName string `protobuf:"bytes,2,opt,name=topic_endpoint_name,json=topicEndpointName,proto3,oneof"` -} - -func (*SpanData_DeleteSpan_QueueName) isSpanData_DeleteSpan_Source() {} - -func (*SpanData_DeleteSpan_TopicEndpointName) isSpanData_DeleteSpan_Source() {} - // When a span has a transaction event, it indicates the span occurs as part // of processing a transaction, and includes the *current* state of of the // transaction when the event was generated. The state can change as @@ -767,7 +596,7 @@ type SpanData_TransactionEvent struct { func (x *SpanData_TransactionEvent) Reset() { *x = SpanData_TransactionEvent{} if protoimpl.UnsafeEnabled { - mi := &file_egress_v1_proto_msgTypes[4] + mi := &file_egress_v1_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -780,7 +609,7 @@ func (x *SpanData_TransactionEvent) String() string { func (*SpanData_TransactionEvent) ProtoMessage() {} func (x *SpanData_TransactionEvent) ProtoReflect() protoreflect.Message { - mi := &file_egress_v1_proto_msgTypes[4] + mi := &file_egress_v1_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -793,7 +622,7 @@ func (x *SpanData_TransactionEvent) ProtoReflect() protoreflect.Message { // Deprecated: Use SpanData_TransactionEvent.ProtoReflect.Descriptor instead. func (*SpanData_TransactionEvent) Descriptor() ([]byte, []int) { - return file_egress_v1_proto_rawDescGZIP(), []int{0, 3} + return file_egress_v1_proto_rawDescGZIP(), []int{0, 2} } func (x *SpanData_TransactionEvent) GetTimeUnixNano() int64 { @@ -874,7 +703,7 @@ type SpanData_TransactionEvent_Xid struct { func (x *SpanData_TransactionEvent_Xid) Reset() { *x = SpanData_TransactionEvent_Xid{} if protoimpl.UnsafeEnabled { - mi := &file_egress_v1_proto_msgTypes[5] + mi := &file_egress_v1_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -887,7 +716,7 @@ func (x *SpanData_TransactionEvent_Xid) String() string { func (*SpanData_TransactionEvent_Xid) ProtoMessage() {} func (x *SpanData_TransactionEvent_Xid) ProtoReflect() protoreflect.Message { - mi := &file_egress_v1_proto_msgTypes[5] + mi := &file_egress_v1_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -900,7 +729,7 @@ func (x *SpanData_TransactionEvent_Xid) ProtoReflect() protoreflect.Message { // Deprecated: Use SpanData_TransactionEvent_Xid.ProtoReflect.Descriptor instead. func (*SpanData_TransactionEvent_Xid) Descriptor() ([]byte, []int) { - return file_egress_v1_proto_rawDescGZIP(), []int{0, 3, 0} + return file_egress_v1_proto_rawDescGZIP(), []int{0, 2, 0} } func (x *SpanData_TransactionEvent_Xid) GetFormatId() int32 { @@ -937,7 +766,7 @@ type SpanData_TransactionEvent_LocalTransactionId struct { func (x *SpanData_TransactionEvent_LocalTransactionId) Reset() { *x = SpanData_TransactionEvent_LocalTransactionId{} if protoimpl.UnsafeEnabled { - mi := &file_egress_v1_proto_msgTypes[6] + mi := &file_egress_v1_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -950,7 +779,7 @@ func (x *SpanData_TransactionEvent_LocalTransactionId) String() string { func (*SpanData_TransactionEvent_LocalTransactionId) ProtoMessage() {} func (x *SpanData_TransactionEvent_LocalTransactionId) ProtoReflect() protoreflect.Message { - mi := &file_egress_v1_proto_msgTypes[6] + mi := &file_egress_v1_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -963,7 +792,7 @@ func (x *SpanData_TransactionEvent_LocalTransactionId) ProtoReflect() protorefle // Deprecated: Use SpanData_TransactionEvent_LocalTransactionId.ProtoReflect.Descriptor instead. func (*SpanData_TransactionEvent_LocalTransactionId) Descriptor() ([]byte, []int) { - return file_egress_v1_proto_rawDescGZIP(), []int{0, 3, 1} + return file_egress_v1_proto_rawDescGZIP(), []int{0, 2, 1} } func (x *SpanData_TransactionEvent_LocalTransactionId) GetTransactionId() uint32 { @@ -994,7 +823,7 @@ var file_egress_v1_proto_rawDesc = []byte{ 0x6f, 0x12, 0x2d, 0x73, 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x76, 0x31, - 0x22, 0xb2, 0x16, 0x0a, 0x08, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x65, 0x0a, + 0x22, 0xcf, 0x12, 0x0a, 0x08, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x65, 0x0a, 0x0c, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x70, 0x61, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x73, 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, 0x6f, @@ -1006,174 +835,144 @@ var file_egress_v1_proto_rawDesc = []byte{ 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2d, 0x0a, 0x10, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x70, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x56, 0x70, 0x6e, 0x4e, 0x61, 0x6d, - 0x65, 0x88, 0x01, 0x01, 0x1a, 0x8b, 0x05, 0x0a, 0x0a, 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, - 0x70, 0x61, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x74, 0x72, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x17, - 0x0a, 0x07, 0x73, 0x70, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x06, 0x73, 0x70, 0x61, 0x6e, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x0e, 0x70, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x5f, 0x73, 0x70, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x48, - 0x01, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x70, 0x61, 0x6e, 0x49, 0x64, 0x88, - 0x01, 0x01, 0x12, 0x2f, 0x0a, 0x14, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x10, - 0x52, 0x11, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x78, 0x4e, - 0x61, 0x6e, 0x6f, 0x12, 0x2b, 0x0a, 0x12, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, - 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x18, 0x05, 0x20, 0x01, 0x28, 0x10, 0x52, - 0x0f, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x78, 0x4e, 0x61, 0x6e, 0x6f, - 0x12, 0x7a, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x48, 0x2e, 0x73, 0x6f, - 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, 0x63, - 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, - 0x44, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x02, 0x52, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x30, 0x0a, 0x11, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x10, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x5f, - 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x73, 0x70, 0x61, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x40, 0x2e, 0x73, 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x65, 0x88, 0x01, 0x01, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x6f, 0x6c, 0x6f, 0x73, 0x5f, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x6f, 0x6c, + 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0xa4, 0x04, 0x0a, 0x0a, 0x45, 0x67, + 0x72, 0x65, 0x73, 0x73, 0x53, 0x70, 0x61, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x72, 0x61, 0x63, + 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x74, 0x72, 0x61, 0x63, + 0x65, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x70, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x70, 0x61, 0x6e, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x0e, + 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x70, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0c, 0x48, 0x01, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x70, + 0x61, 0x6e, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x2f, 0x0a, 0x14, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x10, 0x52, 0x11, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, + 0x55, 0x6e, 0x69, 0x78, 0x4e, 0x61, 0x6e, 0x6f, 0x12, 0x2b, 0x0a, 0x12, 0x65, 0x6e, 0x64, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x10, 0x52, 0x0f, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x55, 0x6e, 0x69, + 0x78, 0x4e, 0x61, 0x6e, 0x6f, 0x12, 0x7a, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x48, 0x2e, 0x73, 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, + 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x02, 0x52, 0x10, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x88, 0x01, + 0x01, 0x12, 0x30, 0x0a, 0x11, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x10, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x88, 0x01, 0x01, 0x12, 0x5f, 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x73, 0x70, 0x61, 0x6e, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x73, 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x65, 0x67, 0x72, + 0x65, 0x73, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, + 0x53, 0x65, 0x6e, 0x64, 0x53, 0x70, 0x61, 0x6e, 0x48, 0x00, 0x52, 0x08, 0x73, 0x65, 0x6e, 0x64, + 0x53, 0x70, 0x61, 0x6e, 0x42, 0x0b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x64, 0x61, 0x74, + 0x61, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x70, 0x61, + 0x6e, 0x5f, 0x69, 0x64, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x1a, 0xe9, 0x04, 0x0a, 0x08, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x70, 0x61, 0x6e, 0x12, 0x1f, 0x0a, + 0x0a, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x00, 0x52, 0x09, 0x71, 0x75, 0x65, 0x75, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x30, + 0x0a, 0x13, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x11, 0x74, + 0x6f, 0x70, 0x69, 0x63, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x62, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x48, 0x2e, 0x73, 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x53, - 0x70, 0x61, 0x6e, 0x48, 0x00, 0x52, 0x08, 0x73, 0x65, 0x6e, 0x64, 0x53, 0x70, 0x61, 0x6e, 0x12, - 0x65, 0x0a, 0x0b, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x5f, 0x73, 0x70, 0x61, 0x6e, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x73, 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, - 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, 0x73, - 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x48, 0x00, 0x52, 0x0a, 0x64, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x42, 0x0b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x64, - 0x61, 0x74, 0x61, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, - 0x70, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x14, 0x0a, 0x12, - 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x1a, 0x92, 0x05, 0x0a, 0x08, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x70, 0x61, 0x6e, 0x12, - 0x1f, 0x0a, 0x0a, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x71, 0x75, 0x65, 0x75, 0x65, 0x4e, 0x61, 0x6d, 0x65, - 0x12, 0x30, 0x0a, 0x13, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, - 0x11, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4e, 0x61, - 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x74, 0x65, 0x6d, 0x70, - 0x6f, 0x72, 0x61, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x71, 0x75, 0x65, - 0x75, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x12, 0x62, 0x0a, 0x07, 0x6f, - 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x48, 0x2e, 0x73, - 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, - 0x63, 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, - 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x70, 0x61, 0x6e, 0x2e, 0x4f, - 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x12, - 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x64, 0x5f, 0x6d, 0x73, 0x67, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x64, 0x4d, - 0x73, 0x67, 0x12, 0x38, 0x0a, 0x18, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x63, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x43, 0x6c, - 0x69, 0x65, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x14, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6d, 0x65, 0x72, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, - 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x2e, 0x0a, 0x10, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x22, 0xab, 0x01, 0x0a, 0x07, 0x4f, - 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x4a, 0x45, 0x43, 0x54, 0x45, 0x44, - 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x4c, 0x45, 0x41, 0x53, 0x45, 0x44, 0x10, 0x02, - 0x12, 0x13, 0x0a, 0x0f, 0x44, 0x45, 0x4c, 0x49, 0x56, 0x45, 0x52, 0x59, 0x5f, 0x46, 0x41, 0x49, - 0x4c, 0x45, 0x44, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x55, 0x4e, - 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, 0x54, 0x52, 0x41, 0x4e, 0x53, - 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x05, 0x12, - 0x1d, 0x0a, 0x19, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, - 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x06, 0x12, 0x18, - 0x0a, 0x14, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x4f, - 0x4c, 0x4c, 0x42, 0x41, 0x43, 0x4b, 0x10, 0x07, 0x42, 0x08, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0xf5, 0x02, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x12, 0x1f, 0x0a, 0x0a, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x71, 0x75, - 0x65, 0x75, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x13, 0x74, 0x6f, 0x70, 0x69, 0x63, - 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x11, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x45, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x71, 0x75, 0x65, - 0x75, 0x65, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, - 0x72, 0x79, 0x12, 0x61, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x49, 0x2e, 0x73, 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, 0x6f, 0x6b, - 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, - 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x2e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x52, 0x06, 0x72, - 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x7e, 0x0a, 0x06, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, - 0x0e, 0x0a, 0x0a, 0x54, 0x54, 0x4c, 0x5f, 0x45, 0x58, 0x50, 0x49, 0x52, 0x59, 0x10, 0x00, 0x12, - 0x1d, 0x0a, 0x19, 0x4d, 0x41, 0x58, 0x5f, 0x52, 0x45, 0x44, 0x45, 0x4c, 0x49, 0x56, 0x45, 0x52, - 0x49, 0x45, 0x53, 0x5f, 0x45, 0x58, 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x01, 0x12, 0x13, - 0x0a, 0x0f, 0x45, 0x4e, 0x51, 0x55, 0x45, 0x55, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, - 0x45, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x5f, 0x4d, 0x45, 0x53, - 0x53, 0x41, 0x47, 0x45, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x03, 0x12, 0x16, 0x0a, - 0x12, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x5f, 0x51, 0x55, 0x45, 0x55, 0x45, 0x5f, 0x44, 0x45, 0x4c, - 0x45, 0x54, 0x45, 0x10, 0x04, 0x42, 0x08, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x1a, - 0xbe, 0x07, 0x0a, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x6e, 0x69, - 0x78, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x10, 0x52, 0x0c, 0x74, 0x69, - 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x78, 0x4e, 0x61, 0x6e, 0x6f, 0x12, 0x61, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4d, 0x2e, 0x73, 0x6f, 0x6c, 0x61, 0x63, - 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x65, - 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, - 0x61, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x70, 0x0a, - 0x09, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x52, 0x2e, 0x73, 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x70, 0x61, 0x6e, 0x2e, 0x4f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x52, 0x07, 0x6f, 0x75, 0x74, + 0x63, 0x6f, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x64, + 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x72, 0x65, 0x70, 0x6c, + 0x61, 0x79, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x12, 0x38, 0x0a, 0x18, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6d, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6d, 0x65, 0x72, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x30, 0x0a, 0x14, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x63, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x12, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, + 0x2e, 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x22, + 0xab, 0x01, 0x0a, 0x07, 0x4f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x41, + 0x43, 0x43, 0x45, 0x50, 0x54, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x4a, + 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x4c, 0x45, 0x41, + 0x53, 0x45, 0x44, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x44, 0x45, 0x4c, 0x49, 0x56, 0x45, 0x52, + 0x59, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x46, 0x4c, + 0x4f, 0x57, 0x5f, 0x55, 0x4e, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, + 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, + 0x49, 0x54, 0x10, 0x05, 0x12, 0x1d, 0x0a, 0x19, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, + 0x44, 0x10, 0x06, 0x12, 0x18, 0x0a, 0x14, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x52, 0x4f, 0x4c, 0x4c, 0x42, 0x41, 0x43, 0x4b, 0x10, 0x07, 0x42, 0x08, 0x0a, + 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0xbe, 0x07, 0x0a, + 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x6e, + 0x61, 0x6e, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x10, 0x52, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x55, + 0x6e, 0x69, 0x78, 0x4e, 0x61, 0x6e, 0x6f, 0x12, 0x61, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4d, 0x2e, 0x73, 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, + 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, + 0x73, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x54, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, + 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x70, 0x0a, 0x09, 0x69, 0x6e, + 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x52, 0x2e, + 0x73, 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x72, + 0x61, 0x63, 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, + 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, + 0x72, 0x52, 0x09, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x60, 0x0a, 0x03, + 0x78, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x4c, 0x2e, 0x73, 0x6f, 0x6c, 0x61, + 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, + 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, + 0x74, 0x61, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x2e, 0x58, 0x69, 0x64, 0x48, 0x00, 0x52, 0x03, 0x78, 0x69, 0x64, 0x12, 0x78, + 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x5b, 0x2e, 0x73, 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x69, - 0x61, 0x74, 0x6f, 0x72, 0x52, 0x09, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x12, - 0x60, 0x0a, 0x03, 0x78, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x4c, 0x2e, 0x73, - 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, - 0x63, 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, - 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x58, 0x69, 0x64, 0x48, 0x00, 0x52, 0x03, 0x78, 0x69, - 0x64, 0x12, 0x78, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x5b, 0x2e, 0x73, 0x6f, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x62, 0x72, 0x6f, - 0x6b, 0x65, 0x72, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x48, 0x00, 0x52, 0x07, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x11, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x10, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x44, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x1a, 0x6a, 0x0a, - 0x03, 0x58, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x49, - 0x64, 0x12, 0x29, 0x0a, 0x10, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x71, 0x75, 0x61, 0x6c, - 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x62, 0x72, 0x61, - 0x6e, 0x63, 0x68, 0x51, 0x75, 0x61, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, - 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x08, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x64, 0x1a, 0x7d, 0x0a, 0x12, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, - 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x5e, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, - 0x52, 0x4f, 0x4c, 0x4c, 0x42, 0x41, 0x43, 0x4b, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x45, 0x4e, - 0x44, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x10, 0x03, - 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x49, 0x4d, 0x45, - 0x4f, 0x55, 0x54, 0x10, 0x04, 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x4f, 0x4c, 0x4c, 0x42, 0x41, 0x43, - 0x4b, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x05, 0x22, 0x2e, 0x0a, 0x09, 0x49, 0x6e, 0x69, 0x74, - 0x69, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x10, - 0x00, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, - 0x42, 0x52, 0x4f, 0x4b, 0x45, 0x52, 0x10, 0x02, 0x42, 0x10, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x70, 0x6e, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x48, 0x00, 0x52, + 0x07, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x11, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x10, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x44, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x1a, 0x6a, 0x0a, 0x03, 0x58, 0x69, + 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x49, 0x64, 0x12, 0x29, + 0x0a, 0x10, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x66, 0x69, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, + 0x51, 0x75, 0x61, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x6c, 0x6f, + 0x62, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x67, 0x6c, + 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x64, 0x1a, 0x7d, 0x0a, 0x12, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x54, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x5e, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, + 0x06, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x4f, 0x4c, + 0x4c, 0x42, 0x41, 0x43, 0x4b, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x45, 0x4e, 0x44, 0x10, 0x02, + 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x10, 0x03, 0x12, 0x13, 0x0a, + 0x0f, 0x53, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, + 0x10, 0x04, 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x4f, 0x4c, 0x4c, 0x42, 0x41, 0x43, 0x4b, 0x5f, 0x4f, + 0x4e, 0x4c, 0x59, 0x10, 0x05, 0x22, 0x2e, 0x0a, 0x09, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, + 0x6f, 0x72, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x09, + 0x0a, 0x05, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x42, 0x52, 0x4f, + 0x4b, 0x45, 0x52, 0x10, 0x02, 0x42, 0x10, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x13, 0x0a, + 0x11, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x70, 0x6e, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1188,37 +987,33 @@ func file_egress_v1_proto_rawDescGZIP() []byte { return file_egress_v1_proto_rawDescData } -var file_egress_v1_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_egress_v1_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_egress_v1_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_egress_v1_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_egress_v1_proto_goTypes = []interface{}{ (SpanData_SendSpan_Outcome)(0), // 0: solace.messaging.proto.broker.trace.egress.v1.SpanData.SendSpan.Outcome - (SpanData_DeleteSpan_Reason)(0), // 1: solace.messaging.proto.broker.trace.egress.v1.SpanData.DeleteSpan.Reason - (SpanData_TransactionEvent_Type)(0), // 2: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.Type - (SpanData_TransactionEvent_Initiator)(0), // 3: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.Initiator - (*SpanData)(nil), // 4: solace.messaging.proto.broker.trace.egress.v1.SpanData - (*SpanData_EgressSpan)(nil), // 5: solace.messaging.proto.broker.trace.egress.v1.SpanData.EgressSpan - (*SpanData_SendSpan)(nil), // 6: solace.messaging.proto.broker.trace.egress.v1.SpanData.SendSpan - (*SpanData_DeleteSpan)(nil), // 7: solace.messaging.proto.broker.trace.egress.v1.SpanData.DeleteSpan - (*SpanData_TransactionEvent)(nil), // 8: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent - (*SpanData_TransactionEvent_Xid)(nil), // 9: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.Xid - (*SpanData_TransactionEvent_LocalTransactionId)(nil), // 10: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.LocalTransactionId + (SpanData_TransactionEvent_Type)(0), // 1: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.Type + (SpanData_TransactionEvent_Initiator)(0), // 2: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.Initiator + (*SpanData)(nil), // 3: solace.messaging.proto.broker.trace.egress.v1.SpanData + (*SpanData_EgressSpan)(nil), // 4: solace.messaging.proto.broker.trace.egress.v1.SpanData.EgressSpan + (*SpanData_SendSpan)(nil), // 5: solace.messaging.proto.broker.trace.egress.v1.SpanData.SendSpan + (*SpanData_TransactionEvent)(nil), // 6: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent + (*SpanData_TransactionEvent_Xid)(nil), // 7: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.Xid + (*SpanData_TransactionEvent_LocalTransactionId)(nil), // 8: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.LocalTransactionId } var file_egress_v1_proto_depIdxs = []int32{ - 5, // 0: solace.messaging.proto.broker.trace.egress.v1.SpanData.egress_spans:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.EgressSpan - 8, // 1: solace.messaging.proto.broker.trace.egress.v1.SpanData.EgressSpan.transaction_event:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent - 6, // 2: solace.messaging.proto.broker.trace.egress.v1.SpanData.EgressSpan.send_span:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.SendSpan - 7, // 3: solace.messaging.proto.broker.trace.egress.v1.SpanData.EgressSpan.delete_span:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.DeleteSpan - 0, // 4: solace.messaging.proto.broker.trace.egress.v1.SpanData.SendSpan.outcome:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.SendSpan.Outcome - 1, // 5: solace.messaging.proto.broker.trace.egress.v1.SpanData.DeleteSpan.reason:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.DeleteSpan.Reason - 2, // 6: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.type:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.Type - 3, // 7: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.initiator:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.Initiator - 9, // 8: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.xid:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.Xid - 10, // 9: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.local_id:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.LocalTransactionId - 10, // [10:10] is the sub-list for method output_type - 10, // [10:10] is the sub-list for method input_type - 10, // [10:10] is the sub-list for extension type_name - 10, // [10:10] is the sub-list for extension extendee - 0, // [0:10] is the sub-list for field type_name + 4, // 0: solace.messaging.proto.broker.trace.egress.v1.SpanData.egress_spans:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.EgressSpan + 6, // 1: solace.messaging.proto.broker.trace.egress.v1.SpanData.EgressSpan.transaction_event:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent + 5, // 2: solace.messaging.proto.broker.trace.egress.v1.SpanData.EgressSpan.send_span:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.SendSpan + 0, // 3: solace.messaging.proto.broker.trace.egress.v1.SpanData.SendSpan.outcome:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.SendSpan.Outcome + 1, // 4: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.type:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.Type + 2, // 5: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.initiator:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.Initiator + 7, // 6: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.xid:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.Xid + 8, // 7: solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.local_id:type_name -> solace.messaging.proto.broker.trace.egress.v1.SpanData.TransactionEvent.LocalTransactionId + 8, // [8:8] is the sub-list for method output_type + 8, // [8:8] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name } func init() { file_egress_v1_proto_init() } @@ -1264,18 +1059,6 @@ func file_egress_v1_proto_init() { } } file_egress_v1_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SpanData_DeleteSpan); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_egress_v1_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SpanData_TransactionEvent); i { case 0: return &v.state @@ -1287,7 +1070,7 @@ func file_egress_v1_proto_init() { return nil } } - file_egress_v1_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + file_egress_v1_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SpanData_TransactionEvent_Xid); i { case 0: return &v.state @@ -1299,7 +1082,7 @@ func file_egress_v1_proto_init() { return nil } } - file_egress_v1_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_egress_v1_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SpanData_TransactionEvent_LocalTransactionId); i { case 0: return &v.state @@ -1315,17 +1098,12 @@ func file_egress_v1_proto_init() { file_egress_v1_proto_msgTypes[0].OneofWrappers = []interface{}{} file_egress_v1_proto_msgTypes[1].OneofWrappers = []interface{}{ (*SpanData_EgressSpan_SendSpan)(nil), - (*SpanData_EgressSpan_DeleteSpan)(nil), } file_egress_v1_proto_msgTypes[2].OneofWrappers = []interface{}{ (*SpanData_SendSpan_QueueName)(nil), (*SpanData_SendSpan_TopicEndpointName)(nil), } file_egress_v1_proto_msgTypes[3].OneofWrappers = []interface{}{ - (*SpanData_DeleteSpan_QueueName)(nil), - (*SpanData_DeleteSpan_TopicEndpointName)(nil), - } - file_egress_v1_proto_msgTypes[4].OneofWrappers = []interface{}{ (*SpanData_TransactionEvent_Xid_)(nil), (*SpanData_TransactionEvent_LocalId)(nil), } @@ -1334,8 +1112,8 @@ func file_egress_v1_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_egress_v1_proto_rawDesc, - NumEnums: 4, - NumMessages: 7, + NumEnums: 3, + NumMessages: 6, NumExtensions: 0, NumServices: 0, }, diff --git a/receiver/solacereceiver/model/egress_v1.proto b/receiver/solacereceiver/model/egress_v1.proto index 798b3e6564a89..9780ac683e7a0 100644 --- a/receiver/solacereceiver/model/egress_v1.proto +++ b/receiver/solacereceiver/model/egress_v1.proto @@ -9,7 +9,7 @@ package solace.messaging.proto.broker.trace.egress.v1; // future. Receiving clients must not assume there are no additional topic // levels. // -// This message describes telemetry data that a Solace PubSub+ broker captures +// This message describes telemetry data that a Solace PubSub+ broker captures // in the egress portion of its data path. // // Fields with names that end in "time_unix_nano" are 64-bit timestamps, in @@ -32,6 +32,10 @@ message SpanData { // API's session will match the session's VPN_NAME_IN_USE. optional string message_vpn_name = 3; + // The SolOS version of the broker generating the message. All elements of + // egress_spans will always have been created by the same broker version. + string solos_version = 4; + message EgressSpan { // 16-byte globally unique trace ID. Any two spans with the same trace ID // are part of the same trace. @@ -54,7 +58,6 @@ message SpanData { oneof type_data { SendSpan send_span = 8; - DeleteSpan delete_span = 9; } } @@ -68,16 +71,14 @@ message SpanData { string topic_endpoint_name = 2; } - bool queue_temporary = 3; + Outcome outcome = 3; - Outcome outcome = 4; + bool replayed_msg = 4; - bool replayed_msg = 5; - - string consumer_client_username = 6; - string consumer_client_name = 7; - string protocol = 8; - optional string protocol_version = 9; + string consumer_client_username = 5; + string consumer_client_name = 6; + string protocol = 7; + optional string protocol_version = 8; enum Outcome { ACCEPTED = 0; @@ -91,32 +92,6 @@ message SpanData { } } - // This message contains data unique to delete spans generated in egress. - // The only implemented delete span currently implemented is the - // ENQUEUE_FAILURE reason. Other values are defined to allow their - // implementation to be added in the future without automatically requiring - // a change to the spec. - message DeleteSpan { - // The name of the queue or topic endpoint the message is being deleted - // from. - oneof source { - string queue_name = 1; - string topic_endpoint_name = 2; - } - - bool queue_temporary = 3; - - Reason reason = 4; - - enum Reason { - TTL_EXPIRY = 0; - MAX_REDELIVERIES_EXCEEDED = 1; - ENQUEUE_FAILURE = 2; - ADMIN_MESSAGE_DELETE = 3; - ADMIN_QUEUE_DELETE = 4; - } - } - // When a span has a transaction event, it indicates the span occurs as part // of processing a transaction, and includes the *current* state of of the // transaction when the event was generated. The state can change as @@ -150,7 +125,7 @@ message SpanData { // have the span's error_description set, but all ROLLBACK_ONLY // transaction events will have an error_description set, which indicate // the transaction's error. - // + // // Since the only record of these messages in the context of the // transaction has been discarded, no further span can be generated in // the context of a client, admin, or session timeout operation. When a @@ -161,7 +136,7 @@ message SpanData { ROLLBACK_ONLY = 5; } Type type = 2; - + enum Initiator { CLIENT = 0; ADMIN = 1; diff --git a/receiver/solacereceiver/observability.go b/receiver/solacereceiver/observability.go index 6bf043b0fddf4..71771dd577399 100644 --- a/receiver/solacereceiver/observability.go +++ b/receiver/solacereceiver/observability.go @@ -61,6 +61,7 @@ type opencensusMetrics struct { flowControlRecentRetries *stats.Int64Measure flowControlTotal *stats.Int64Measure flowControlSingleSuccess *stats.Int64Measure + droppedEgressSpans *stats.Int64Measure } views struct { failedReconnections *view.View @@ -75,6 +76,7 @@ type opencensusMetrics struct { flowControlRecentRetries *view.View flowControlTotal *view.View flowControlSingleSuccess *view.View + droppedEgressSpans *view.View } } @@ -100,6 +102,8 @@ func newOpenCensusMetrics(instanceName string) (*opencensusMetrics, error) { m.stats.flowControlTotal = stats.Int64(prefix+"receiver_flow_control_total", "Number of times the receiver instance became flow controlled", stats.UnitDimensionless) m.stats.flowControlSingleSuccess = stats.Int64(prefix+"receiver_flow_control_with_single_successful_retry", "Number of times the receiver instance became flow controlled and resolved situations after the first retry", stats.UnitDimensionless) + m.stats.droppedEgressSpans = stats.Int64(prefix+"dropped_egress_spans", "Number of dropped egress spans", stats.UnitDimensionless) + m.views.failedReconnections = fromMeasure(m.stats.failedReconnections, view.Count()) m.views.recoverableUnmarshallingErrors = fromMeasure(m.stats.recoverableUnmarshallingErrors, view.Count()) m.views.fatalUnmarshallingErrors = fromMeasure(m.stats.fatalUnmarshallingErrors, view.Count()) @@ -114,6 +118,8 @@ func newOpenCensusMetrics(instanceName string) (*opencensusMetrics, error) { m.views.flowControlTotal = fromMeasure(m.stats.flowControlTotal, view.Count()) m.views.flowControlSingleSuccess = fromMeasure(m.stats.flowControlSingleSuccess, view.Count()) + m.views.droppedEgressSpans = fromMeasure(m.stats.droppedEgressSpans, view.Count()) + err := view.Register( m.views.failedReconnections, m.views.recoverableUnmarshallingErrors, @@ -127,6 +133,7 @@ func newOpenCensusMetrics(instanceName string) (*opencensusMetrics, error) { m.views.flowControlRecentRetries, m.views.flowControlTotal, m.views.flowControlSingleSuccess, + m.views.droppedEgressSpans, ) if err != nil { return nil, err @@ -202,3 +209,7 @@ func (m *opencensusMetrics) recordFlowControlTotal() { func (m *opencensusMetrics) recordFlowControlSingleSuccess() { stats.Record(context.Background(), m.stats.flowControlSingleSuccess.M(1)) } + +func (m *opencensusMetrics) recordDroppedEgressSpan() { + stats.Record(context.Background(), m.stats.droppedEgressSpans.M(1)) +} diff --git a/receiver/solacereceiver/observability_test.go b/receiver/solacereceiver/observability_test.go index 97e9e005920c3..3852b65e43d94 100644 --- a/receiver/solacereceiver/observability_test.go +++ b/receiver/solacereceiver/observability_test.go @@ -53,6 +53,7 @@ func TestRecordMetrics(t *testing.T) { }, metrics.views.flowControlRecentRetries, metrics.stats.flowControlRecentRetries, 3, 5}, {metrics.recordFlowControlTotal, metrics.views.flowControlTotal, metrics.stats.flowControlTotal, 3, 3}, {metrics.recordFlowControlSingleSuccess, metrics.views.flowControlSingleSuccess, metrics.stats.flowControlSingleSuccess, 3, 3}, + {metrics.recordDroppedEgressSpan, metrics.views.droppedEgressSpans, metrics.stats.droppedEgressSpans, 3, 3}, } for _, tc := range testCases { t.Run(tc.m.Name(), func(t *testing.T) { diff --git a/receiver/solacereceiver/unmarshaller.go b/receiver/solacereceiver/unmarshaller.go index 97ad8f1cb1fab..d21b451e8e926 100644 --- a/receiver/solacereceiver/unmarshaller.go +++ b/receiver/solacereceiver/unmarshaller.go @@ -15,20 +15,12 @@ package solacereceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/solacereceiver" import ( - "encoding/hex" "errors" - "fmt" - "net" "strings" "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/ptrace" - "go.opentelemetry.io/otel/baggage" "go.uber.org/zap" - "google.golang.org/protobuf/proto" - - egress_v1 "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/solacereceiver/model/egress/v1" - receive_v1 "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/solacereceiver/model/receive/v1" ) // tracesUnmarshaller deserializes the message body. @@ -110,463 +102,66 @@ func (u *solaceTracesUnmarshaller) unmarshal(message *inboundMessage) (ptrace.Tr return ptrace.Traces{}, errUnknownTopic } -type brokerTraceEgressUnmarshallerV1 struct { - logger *zap.Logger - metrics *opencensusMetrics -} - -func (u *brokerTraceEgressUnmarshallerV1) unmarshal(message *inboundMessage) (ptrace.Traces, error) { - spanData, err := u.unmarshalToSpanData(message) - if err != nil { - return ptrace.Traces{}, err - } - u.logger.Error(spanData.String()) - traces := ptrace.NewTraces() - return traces, nil -} - -func (u *brokerTraceEgressUnmarshallerV1) unmarshalToSpanData(message *inboundMessage) (*egress_v1.SpanData, error) { - var data = message.GetData() - if len(data) == 0 { - return nil, errEmptyPayload - } - var spanData egress_v1.SpanData - if err := proto.Unmarshal(data, &spanData); err != nil { - return nil, err - } - return &spanData, nil -} +// common helper functions used by all unmarshallers -type brokerTraceReceiveUnmarshallerV1 struct { - logger *zap.Logger - metrics *opencensusMetrics -} +// Endpoint types +const ( + queueKind = "queue" + topicEndpointKind = "topic-endpoint" +) -// unmarshal implements tracesUnmarshaller.unmarshal -func (u *brokerTraceReceiveUnmarshallerV1) unmarshal(message *inboundMessage) (ptrace.Traces, error) { - spanData, err := u.unmarshalToSpanData(message) - if err != nil { - return ptrace.Traces{}, err - } - traces := ptrace.NewTraces() - u.populateTraces(spanData, traces) - return traces, nil -} +// Transaction event keys +const ( + transactionInitiatorEventKey = "messaging.solace.transaction_initiator" + transactionIDEventKey = "messaging.solace.transaction_id" + transactedSessionNameEventKey = "messaging.solace.transacted_session_name" + transactedSessionIDEventKey = "messaging.solace.transacted_session_id" + transactionErrorMessageEventKey = "messaging.solace.transaction_error_message" + transactionXIDEventKey = "messaging.solace.transaction_xid" +) -// unmarshalToSpanData will consume an solaceMessage and unmarshal it into a SpanData. -// Returns an error if one occurred. -func (u *brokerTraceReceiveUnmarshallerV1) unmarshalToSpanData(message *inboundMessage) (*receive_v1.SpanData, error) { - var data = message.GetData() - if len(data) == 0 { - return nil, errEmptyPayload - } - var spanData receive_v1.SpanData - if err := proto.Unmarshal(data, &spanData); err != nil { - return nil, err - } - return &spanData, nil -} +// span keys +const ( + protocolAttrKey = "messaging.protocol" + protocolVersionAttrKey = "messaging.protocol_version" + messageIDAttrKey = "messaging.message_id" + conversationIDAttrKey = "messaging.conversation_id" + payloadSizeBytesAttrKey = "messaging.message_payload_size_bytes" + destinationAttrKey = "messaging.destination" + clientUsernameAttrKey = "messaging.solace.client_username" + clientNameAttrKey = "messaging.solace.client_name" + replicationGroupMessageIDAttrKey = "messaging.solace.replication_group_message_id" + priorityAttrKey = "messaging.solace.priority" + ttlAttrKey = "messaging.solace.ttl" + dmqEligibleAttrKey = "messaging.solace.dmq_eligible" + droppedEnqueueEventsSuccessAttrKey = "messaging.solace.dropped_enqueue_events_success" + droppedEnqueueEventsFailedAttrKey = "messaging.solace.dropped_enqueue_events_failed" + replyToAttrKey = "messaging.solace.reply_to_topic" + receiveTimeAttrKey = "messaging.solace.broker_receive_time_unix_nano" + droppedUserPropertiesAttrKey = "messaging.solace.dropped_application_message_properties" + deliveryModeAttrKey = "messaging.solace.delivery_mode" + hostIPAttrKey = "net.host.ip" + hostPortAttrKey = "net.host.port" + peerIPAttrKey = "net.peer.ip" + peerPortAttrKey = "net.peer.port" +) -// createSpan will create a new Span from the given traces and map the given SpanData to the span. -// This will set all required fields such as name version, trace and span ID, parent span ID (if applicable), -// timestamps, errors and states. -func (u *brokerTraceReceiveUnmarshallerV1) populateTraces(spanData *receive_v1.SpanData, traces ptrace.Traces) { - // Append new resource span and map any attributes - resourceSpan := traces.ResourceSpans().AppendEmpty() - u.mapResourceSpanAttributes(spanData, resourceSpan.Resource().Attributes()) - instrLibrarySpans := resourceSpan.ScopeSpans().AppendEmpty() - // Create a new span - clientSpan := instrLibrarySpans.Spans().AppendEmpty() - // map the basic span data - u.mapClientSpanData(spanData, clientSpan) - // map all span attributes - u.mapClientSpanAttributes(spanData, clientSpan.Attributes()) - // map all events - u.mapEvents(spanData, clientSpan) -} +// constant attributes +const ( + systemAttrKey = "messaging.system" + systemAttrValue = "SolacePubSub+" + operationAttrKey = "messaging.operation" +) -func (u *brokerTraceReceiveUnmarshallerV1) mapResourceSpanAttributes(spanData *receive_v1.SpanData, attrMap pcommon.Map) { +func setResourceSpanAttributes(attrMap pcommon.Map, routerName, version string, messageVpnName *string) { const ( routerNameAttrKey = "service.name" messageVpnNameAttrKey = "service.instance.id" solosVersionAttrKey = "service.version" ) - attrMap.PutStr(routerNameAttrKey, spanData.RouterName) - if spanData.MessageVpnName != nil { - attrMap.PutStr(messageVpnNameAttrKey, *spanData.MessageVpnName) - } - attrMap.PutStr(solosVersionAttrKey, spanData.SolosVersion) -} - -func (u *brokerTraceReceiveUnmarshallerV1) mapClientSpanData(spanData *receive_v1.SpanData, clientSpan ptrace.Span) { - const clientSpanName = "(topic) receive" - - // client span constants - clientSpan.SetName(clientSpanName) - // SPAN_KIND_CONSUMER == 5 - clientSpan.SetKind(5) - - // map trace ID - var traceID [16]byte - copy(traceID[:16], spanData.TraceId) - clientSpan.SetTraceID(traceID) - // map span ID - var spanID [8]byte - copy(spanID[:8], spanData.SpanId) - clientSpan.SetSpanID(spanID) - // conditional parent-span-id - if len(spanData.ParentSpanId) == 8 { - var parentSpanID [8]byte - copy(parentSpanID[:8], spanData.ParentSpanId) - clientSpan.SetParentSpanID(parentSpanID) - } - - // timestamps - clientSpan.SetStartTimestamp(pcommon.Timestamp(spanData.GetStartTimeUnixNano())) - clientSpan.SetEndTimestamp(pcommon.Timestamp(spanData.GetEndTimeUnixNano())) - // status - if spanData.ErrorDescription != "" { - clientSpan.Status().SetCode(ptrace.StatusCodeError) - clientSpan.Status().SetMessage(spanData.ErrorDescription) - } - // trace state - if spanData.TraceState != nil { - clientSpan.TraceState().FromRaw(*spanData.TraceState) - } -} - -// mapAttributes takes a set of attributes from SpanData and maps them to ClientSpan.Attributes(). -// Will also copy any user properties stored in the SpanData with a best effort approach. -func (u *brokerTraceReceiveUnmarshallerV1) mapClientSpanAttributes(spanData *receive_v1.SpanData, attrMap pcommon.Map) { - // constant attributes - const ( - systemAttrKey = "messaging.system" - systemAttrValue = "SolacePubSub+" - operationAttrKey = "messaging.operation" - operationAttrValue = "receive" - ) - attrMap.PutStr(systemAttrKey, systemAttrValue) - attrMap.PutStr(operationAttrKey, operationAttrValue) - // attributes from spanData - const ( - protocolAttrKey = "messaging.protocol" - protocolVersionAttrKey = "messaging.protocol_version" - messageIDAttrKey = "messaging.message_id" - conversationIDAttrKey = "messaging.conversation_id" - payloadSizeBytesAttrKey = "messaging.message_payload_size_bytes" - destinationAttrKey = "messaging.destination" - clientUsernameAttrKey = "messaging.solace.client_username" - clientNameAttrKey = "messaging.solace.client_name" - replicationGroupMessageIDAttrKey = "messaging.solace.replication_group_message_id" - priorityAttrKey = "messaging.solace.priority" - ttlAttrKey = "messaging.solace.ttl" - dmqEligibleAttrKey = "messaging.solace.dmq_eligible" - droppedEnqueueEventsSuccessAttrKey = "messaging.solace.dropped_enqueue_events_success" - droppedEnqueueEventsFailedAttrKey = "messaging.solace.dropped_enqueue_events_failed" - replyToAttrKey = "messaging.solace.reply_to_topic" - receiveTimeAttrKey = "messaging.solace.broker_receive_time_unix_nano" - droppedUserPropertiesAttrKey = "messaging.solace.dropped_application_message_properties" - deliveryModeAttrKey = "messaging.solace.delivery_mode" - hostIPAttrKey = "net.host.ip" - hostPortAttrKey = "net.host.port" - peerIPAttrKey = "net.peer.ip" - peerPortAttrKey = "net.peer.port" - ) - attrMap.PutStr(protocolAttrKey, spanData.Protocol) - if spanData.ProtocolVersion != nil { - attrMap.PutStr(protocolVersionAttrKey, *spanData.ProtocolVersion) - } - if spanData.ApplicationMessageId != nil { - attrMap.PutStr(messageIDAttrKey, *spanData.ApplicationMessageId) - } - if spanData.CorrelationId != nil { - attrMap.PutStr(conversationIDAttrKey, *spanData.CorrelationId) - } - attrMap.PutInt(payloadSizeBytesAttrKey, int64(spanData.BinaryAttachmentSize+spanData.XmlAttachmentSize+spanData.MetadataSize)) - attrMap.PutStr(clientUsernameAttrKey, spanData.ClientUsername) - attrMap.PutStr(clientNameAttrKey, spanData.ClientName) - attrMap.PutInt(receiveTimeAttrKey, spanData.BrokerReceiveTimeUnixNano) - attrMap.PutStr(destinationAttrKey, spanData.Topic) - - var deliveryMode string - switch spanData.DeliveryMode { - case receive_v1.SpanData_DIRECT: - deliveryMode = "direct" - case receive_v1.SpanData_NON_PERSISTENT: - deliveryMode = "non_persistent" - case receive_v1.SpanData_PERSISTENT: - deliveryMode = "persistent" - default: - deliveryMode = fmt.Sprintf("Unknown Delivery Mode (%s)", spanData.DeliveryMode.String()) - u.logger.Warn(fmt.Sprintf("Received span with unknown delivery mode %s", spanData.DeliveryMode)) - u.metrics.recordRecoverableUnmarshallingError() - } - attrMap.PutStr(deliveryModeAttrKey, deliveryMode) - - rgmid := u.rgmidToString(spanData.ReplicationGroupMessageId) - if len(rgmid) > 0 { - attrMap.PutStr(replicationGroupMessageIDAttrKey, rgmid) - } - - if spanData.Priority != nil { - attrMap.PutInt(priorityAttrKey, int64(*spanData.Priority)) - } - if spanData.Ttl != nil { - attrMap.PutInt(ttlAttrKey, *spanData.Ttl) - } - if spanData.ReplyToTopic != nil { - attrMap.PutStr(replyToAttrKey, *spanData.ReplyToTopic) - } - attrMap.PutBool(dmqEligibleAttrKey, spanData.DmqEligible) - attrMap.PutInt(droppedEnqueueEventsSuccessAttrKey, int64(spanData.DroppedEnqueueEventsSuccess)) - attrMap.PutInt(droppedEnqueueEventsFailedAttrKey, int64(spanData.DroppedEnqueueEventsFailed)) - - // The IPs are now optional meaning we will not incluude them if they are zero length - hostIPLen := len(spanData.HostIp) - if hostIPLen == 4 || hostIPLen == 16 { - attrMap.PutStr(hostIPAttrKey, net.IP(spanData.HostIp).String()) - attrMap.PutInt(hostPortAttrKey, int64(spanData.HostPort)) - } else { - u.logger.Debug("Host ip not included", zap.Int("length", hostIPLen)) - } - - peerIPLen := len(spanData.PeerIp) - if peerIPLen == 4 || peerIPLen == 16 { - attrMap.PutStr(peerIPAttrKey, net.IP(spanData.PeerIp).String()) - attrMap.PutInt(peerPortAttrKey, int64(spanData.PeerPort)) - } else { - u.logger.Debug("Peer IP not included", zap.Int("length", peerIPLen)) - } - - if spanData.Baggage != nil { - err := u.unmarshalBaggage(attrMap, *spanData.Baggage) - if err != nil { - u.logger.Warn("Received malformed baggage string in span data") - u.metrics.recordRecoverableUnmarshallingError() - } - } - - attrMap.PutBool(droppedUserPropertiesAttrKey, spanData.DroppedApplicationMessageProperties) - for key, value := range spanData.UserProperties { - if value != nil { - u.insertUserProperty(attrMap, key, value.Value) - } - } -} - -// mapEvents maps all events contained in SpanData to relevant events within clientSpan.Events() -func (u *brokerTraceReceiveUnmarshallerV1) mapEvents(spanData *receive_v1.SpanData, clientSpan ptrace.Span) { - // handle enqueue events - for _, enqueueEvent := range spanData.EnqueueEvents { - u.mapEnqueueEvent(enqueueEvent, clientSpan.Events()) - } - - // handle transaction events - if transactionEvent := spanData.TransactionEvent; transactionEvent != nil { - u.mapTransactionEvent(transactionEvent, clientSpan.Events()) - } -} - -// mapEnqueueEvent maps a SpanData_EnqueueEvent to a ClientSpan.Event -func (u *brokerTraceReceiveUnmarshallerV1) mapEnqueueEvent(enqueueEvent *receive_v1.SpanData_EnqueueEvent, clientSpanEvents ptrace.SpanEventSlice) { - const ( - enqueueEventSuffix = " enqueue" // Final should be ` enqueue` - messagingDestinationTypeEventKey = "messaging.solace.destination_type" - statusMessageEventKey = "messaging.solace.enqueue_error_message" - rejectsAllEnqueuesKey = "messaging.solace.rejects_all_enqueues" - partitionNumberKey = "messaging.solace.partition_number" - queueKind = "queue" - topicEndpointKind = "topic-endpoint" - ) - var destinationName string - var destinationType string - switch casted := enqueueEvent.Dest.(type) { - case *receive_v1.SpanData_EnqueueEvent_TopicEndpointName: - destinationName = casted.TopicEndpointName - destinationType = topicEndpointKind - case *receive_v1.SpanData_EnqueueEvent_QueueName: - destinationName = casted.QueueName - destinationType = queueKind - default: - u.logger.Warn(fmt.Sprintf("Unknown destination type %T", casted)) - u.metrics.recordRecoverableUnmarshallingError() - return - } - clientEvent := clientSpanEvents.AppendEmpty() - clientEvent.SetName(destinationName + enqueueEventSuffix) - clientEvent.SetTimestamp(pcommon.Timestamp(enqueueEvent.TimeUnixNano)) - clientEvent.Attributes().EnsureCapacity(3) - clientEvent.Attributes().PutStr(messagingDestinationTypeEventKey, destinationType) - clientEvent.Attributes().PutBool(rejectsAllEnqueuesKey, enqueueEvent.RejectsAllEnqueues) - if enqueueEvent.ErrorDescription != nil { - clientEvent.Attributes().PutStr(statusMessageEventKey, enqueueEvent.GetErrorDescription()) - } - if enqueueEvent.PartitionNumber != nil { - clientEvent.Attributes().PutInt(partitionNumberKey, int64(*enqueueEvent.PartitionNumber)) - } -} - -// mapTransactionEvent maps a SpanData_TransactionEvent to a ClientSpan.Event -func (u *brokerTraceReceiveUnmarshallerV1) mapTransactionEvent(transactionEvent *receive_v1.SpanData_TransactionEvent, clientSpanEvents ptrace.SpanEventSlice) { - const ( - transactionInitiatorEventKey = "messaging.solace.transaction_initiator" - transactionIDEventKey = "messaging.solace.transaction_id" - transactedSessionNameEventKey = "messaging.solace.transacted_session_name" - transactedSessionIDEventKey = "messaging.solace.transacted_session_id" - transactionErrorMessageEventKey = "messaging.solace.transaction_error_message" - transactionXIDEventKey = "messaging.solace.transaction_xid" - ) - // map the transaction type to a name - var name string - switch transactionEvent.GetType() { - case receive_v1.SpanData_TransactionEvent_COMMIT: - name = "commit" - case receive_v1.SpanData_TransactionEvent_ROLLBACK: - name = "rollback" - case receive_v1.SpanData_TransactionEvent_END: - name = "end" - case receive_v1.SpanData_TransactionEvent_PREPARE: - name = "prepare" - case receive_v1.SpanData_TransactionEvent_SESSION_TIMEOUT: - name = "session_timeout" - case receive_v1.SpanData_TransactionEvent_ROLLBACK_ONLY: - name = "rollback_only" - default: - // Set the name to the unknown transaction event type to ensure forward compat. - name = fmt.Sprintf("Unknown Transaction Event (%s)", transactionEvent.GetType().String()) - u.logger.Warn(fmt.Sprintf("Received span with unknown transaction event %s", transactionEvent.GetType())) - u.metrics.recordRecoverableUnmarshallingError() - } - clientEvent := clientSpanEvents.AppendEmpty() - clientEvent.SetName(name) - clientEvent.SetTimestamp(pcommon.Timestamp(transactionEvent.TimeUnixNano)) - // map initiator enums to expected initiator strings - var initiator string - switch transactionEvent.GetInitiator() { - case receive_v1.SpanData_TransactionEvent_CLIENT: - initiator = "client" - case receive_v1.SpanData_TransactionEvent_ADMIN: - initiator = "administrator" - case receive_v1.SpanData_TransactionEvent_BROKER: - initiator = "broker" - default: - initiator = fmt.Sprintf("Unknown Transaction Initiator (%s)", transactionEvent.GetInitiator().String()) - u.logger.Warn(fmt.Sprintf("Received span with unknown transaction initiator %s", transactionEvent.GetInitiator())) - u.metrics.recordRecoverableUnmarshallingError() - } - clientEvent.Attributes().PutStr(transactionInitiatorEventKey, initiator) - // conditionally set the error description if one occurred, otherwise omit - if transactionEvent.ErrorDescription != nil { - clientEvent.Attributes().PutStr(transactionErrorMessageEventKey, transactionEvent.GetErrorDescription()) - } - // map the transaction type/id - transactionID := transactionEvent.GetTransactionId() - switch casted := transactionID.(type) { - case *receive_v1.SpanData_TransactionEvent_LocalId: - clientEvent.Attributes().PutInt(transactionIDEventKey, int64(casted.LocalId.TransactionId)) - clientEvent.Attributes().PutStr(transactedSessionNameEventKey, casted.LocalId.SessionName) - clientEvent.Attributes().PutInt(transactedSessionIDEventKey, int64(casted.LocalId.SessionId)) - case *receive_v1.SpanData_TransactionEvent_Xid_: - // format xxxxxxxx-yyyyyyyy-zzzzzzzz where x is FormatID (hex rep of int32), y is BranchQualifier and z is GlobalID, hex encoded. - xidString := fmt.Sprintf("%08x", casted.Xid.FormatId) + "-" + - hex.EncodeToString(casted.Xid.BranchQualifier) + "-" + hex.EncodeToString(casted.Xid.GlobalId) - clientEvent.Attributes().PutStr(transactionXIDEventKey, xidString) - default: - u.logger.Warn(fmt.Sprintf("Unknown transaction ID type %T", transactionID)) - u.metrics.recordRecoverableUnmarshallingError() - } -} - -func (u *brokerTraceReceiveUnmarshallerV1) rgmidToString(rgmid []byte) string { - // rgmid[0] is the version of the rgmid - if len(rgmid) != 17 || rgmid[0] != 1 { - // may be cases where the rgmid is empty or nil, len(rgmid) will return 0 if nil - if len(rgmid) > 0 { - u.logger.Warn("Received invalid length or version for rgmid", zap.Int8("version", int8(rgmid[0])), zap.Int("length", len(rgmid))) - u.metrics.recordRecoverableUnmarshallingError() - } - return hex.EncodeToString(rgmid) - } - rgmidEncoded := make([]byte, 32) - hex.Encode(rgmidEncoded, rgmid[1:]) - // format: rmid1:aaaaa-bbbbbbbbbbb-cccccccc-dddddddd - rgmidString := "rmid1:" + string(rgmidEncoded[0:5]) + "-" + string(rgmidEncoded[5:16]) + "-" + string(rgmidEncoded[16:24]) + "-" + string(rgmidEncoded[24:32]) - return rgmidString -} - -// unmarshalBaggage will unmarshal a baggage string -// See spec https://github.com/open-telemetry/opentelemetry-go/blob/v1.11.1/baggage/baggage.go -func (u *brokerTraceReceiveUnmarshallerV1) unmarshalBaggage(toMap pcommon.Map, baggageString string) error { - const ( - baggageValuePrefix = "messaging.solace.message.baggage." - baggageMetadataPrefix = "messaging.solace.message.baggage_metadata." - propertyDelimiter = ";" - ) - bg, err := baggage.Parse(baggageString) - if err != nil { - return err - } - // we got a valid baggage string, assume everything else is valid - for _, member := range bg.Members() { - toMap.PutStr(baggageValuePrefix+member.Key(), member.Value()) - // member.Properties copies, we should cache - properties := member.Properties() - if len(properties) > 0 { - // Re-encode the properties and save them as a parameter - var propertyString strings.Builder - propertyString.WriteString(properties[0].String()) - for i := 1; i < len(properties); i++ { - propertyString.WriteString(propertyDelimiter + properties[i].String()) - } - toMap.PutStr(baggageMetadataPrefix+member.Key(), propertyString.String()) - } - } - return nil -} - -// insertUserProperty will instert a user property value with the given key to an attribute if possible. -// Since AttributeMap only supports int64 integer types, uint64 data may be misrepresented. -func (u *brokerTraceReceiveUnmarshallerV1) insertUserProperty(toMap pcommon.Map, key string, value interface{}) { - const ( - // userPropertiesPrefixAttrKey is the key used to prefix all user properties - userPropertiesAttrKeyPrefix = "messaging.solace.user_properties." - ) - k := userPropertiesAttrKeyPrefix + key - switch v := value.(type) { - case *receive_v1.SpanData_UserPropertyValue_NullValue: - toMap.PutEmpty(k) - case *receive_v1.SpanData_UserPropertyValue_BoolValue: - toMap.PutBool(k, v.BoolValue) - case *receive_v1.SpanData_UserPropertyValue_DoubleValue: - toMap.PutDouble(k, v.DoubleValue) - case *receive_v1.SpanData_UserPropertyValue_ByteArrayValue: - toMap.PutEmptyBytes(k).FromRaw(v.ByteArrayValue) - case *receive_v1.SpanData_UserPropertyValue_FloatValue: - toMap.PutDouble(k, float64(v.FloatValue)) - case *receive_v1.SpanData_UserPropertyValue_Int8Value: - toMap.PutInt(k, int64(v.Int8Value)) - case *receive_v1.SpanData_UserPropertyValue_Int16Value: - toMap.PutInt(k, int64(v.Int16Value)) - case *receive_v1.SpanData_UserPropertyValue_Int32Value: - toMap.PutInt(k, int64(v.Int32Value)) - case *receive_v1.SpanData_UserPropertyValue_Int64Value: - toMap.PutInt(k, v.Int64Value) - case *receive_v1.SpanData_UserPropertyValue_Uint8Value: - toMap.PutInt(k, int64(v.Uint8Value)) - case *receive_v1.SpanData_UserPropertyValue_Uint16Value: - toMap.PutInt(k, int64(v.Uint16Value)) - case *receive_v1.SpanData_UserPropertyValue_Uint32Value: - toMap.PutInt(k, int64(v.Uint32Value)) - case *receive_v1.SpanData_UserPropertyValue_Uint64Value: - toMap.PutInt(k, int64(v.Uint64Value)) - case *receive_v1.SpanData_UserPropertyValue_StringValue: - toMap.PutStr(k, v.StringValue) - case *receive_v1.SpanData_UserPropertyValue_DestinationValue: - toMap.PutStr(k, v.DestinationValue) - case *receive_v1.SpanData_UserPropertyValue_CharacterValue: - toMap.PutStr(k, string(rune(v.CharacterValue))) - default: - u.logger.Warn(fmt.Sprintf("Unknown user property type: %T", v)) - u.metrics.recordRecoverableUnmarshallingError() + attrMap.PutStr(routerNameAttrKey, routerName) + attrMap.PutStr(solosVersionAttrKey, version) + if messageVpnName != nil { + attrMap.PutStr(messageVpnNameAttrKey, *messageVpnName) } } diff --git a/receiver/solacereceiver/unmarshaller_egress.go b/receiver/solacereceiver/unmarshaller_egress.go new file mode 100644 index 0000000000000..faf95f61b3ca0 --- /dev/null +++ b/receiver/solacereceiver/unmarshaller_egress.go @@ -0,0 +1,227 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package solacereceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/solacereceiver" + +import ( + "encoding/hex" + "fmt" + + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/ptrace" + "go.uber.org/zap" + "google.golang.org/protobuf/proto" + + egress_v1 "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/solacereceiver/model/egress/v1" +) + +type brokerTraceEgressUnmarshallerV1 struct { + logger *zap.Logger + metrics *opencensusMetrics +} + +func (u *brokerTraceEgressUnmarshallerV1) unmarshal(message *inboundMessage) (ptrace.Traces, error) { + spanData, err := u.unmarshalToSpanData(message) + if err != nil { + return ptrace.Traces{}, err + } + u.logger.Error(spanData.String()) + traces := ptrace.NewTraces() + u.populateTraces(spanData, traces) + return traces, nil +} + +func (u *brokerTraceEgressUnmarshallerV1) unmarshalToSpanData(message *inboundMessage) (*egress_v1.SpanData, error) { + var data = message.GetData() + if len(data) == 0 { + return nil, errEmptyPayload + } + var spanData egress_v1.SpanData + if err := proto.Unmarshal(data, &spanData); err != nil { + return nil, err + } + return &spanData, nil +} + +func (u *brokerTraceEgressUnmarshallerV1) populateTraces(spanData *egress_v1.SpanData, traces ptrace.Traces) { + // Append new resource span and map any attributes + resourceSpan := traces.ResourceSpans().AppendEmpty() + u.mapResourceSpanAttributes(spanData, resourceSpan.Resource().Attributes()) + instrLibrarySpans := resourceSpan.ScopeSpans().AppendEmpty() + for _, egressSpanData := range spanData.EgressSpans { + u.mapEgressSpan(egressSpanData, instrLibrarySpans.Spans()) + } +} + +func (u *brokerTraceEgressUnmarshallerV1) mapResourceSpanAttributes(spanData *egress_v1.SpanData, attrMap pcommon.Map) { + setResourceSpanAttributes(attrMap, spanData.RouterName, spanData.SolosVersion, spanData.MessageVpnName) +} + +func (u *brokerTraceEgressUnmarshallerV1) mapEgressSpan(spanData *egress_v1.SpanData_EgressSpan, clientSpans ptrace.SpanSlice) { + if spanData.GetSendSpan() != nil { + clientSpan := clientSpans.AppendEmpty() + clientSpan.SetName("") + clientSpan.SetKind(ptrace.SpanKindProducer) + u.mapEgressSpanCommon(spanData, clientSpan) + u.mapSendSpanAttributes(spanData.GetSendSpan(), clientSpan.Attributes()) + if transactionEvent := spanData.GetTransactionEvent(); transactionEvent != nil { + u.mapTransactionEvent(transactionEvent, clientSpan.Events().AppendEmpty()) + } + } else { + // unknown span type, drop the span + u.logger.Warn("Received egress span with unknown span type, is the collector out of date?") + u.metrics.recordDroppedEgressSpan() + } +} + +func (u *brokerTraceEgressUnmarshallerV1) mapEgressSpanCommon(spanData *egress_v1.SpanData_EgressSpan, clientSpan ptrace.Span) { + var traceID [16]byte + copy(traceID[:16], spanData.TraceId) + clientSpan.SetTraceID(traceID) + var spanID [8]byte + copy(spanID[:8], spanData.SpanId) + clientSpan.SetSpanID(spanID) + // conditional parent-span-id + if len(spanData.ParentSpanId) == 8 { + var parentSpanID [8]byte + copy(parentSpanID[:8], spanData.ParentSpanId) + clientSpan.SetParentSpanID(parentSpanID) + } + // timestamps + clientSpan.SetStartTimestamp(pcommon.Timestamp(spanData.GetStartTimeUnixNano())) + clientSpan.SetEndTimestamp(pcommon.Timestamp(spanData.GetEndTimeUnixNano())) + // status + if spanData.ErrorDescription != nil { + clientSpan.Status().SetCode(ptrace.StatusCodeError) + clientSpan.Status().SetMessage(*spanData.ErrorDescription) + } +} + +func (u *brokerTraceEgressUnmarshallerV1) mapSendSpanAttributes(sendSpan *egress_v1.SpanData_SendSpan, attributes pcommon.Map) { + const ( + sourceNameKey = "messaging.source.name" + sourceKindKey = "messaging.source.kind" + replayedKey = "messaging.solace.message_replayed" + outcomeKey = "messaging.solace.send_operation.outcome" + ) + const ( + sendSpanOperation = "send" + ) + attributes.PutStr(systemAttrKey, systemAttrValue) + attributes.PutStr(operationAttrKey, sendSpanOperation) + attributes.PutStr(protocolAttrKey, sendSpan.Protocol) + if sendSpan.ProtocolVersion != nil { + attributes.PutStr(protocolVersionAttrKey, *sendSpan.ProtocolVersion) + } + // we don't fatal out when we don't have a valid kind, instead just log and increment stats + switch casted := sendSpan.Source.(type) { + case *egress_v1.SpanData_SendSpan_TopicEndpointName: + attributes.PutStr(sourceNameKey, casted.TopicEndpointName) + attributes.PutStr(sourceKindKey, topicEndpointKind) + case *egress_v1.SpanData_SendSpan_QueueName: + attributes.PutStr(sourceNameKey, casted.QueueName) + attributes.PutStr(sourceKindKey, queueKind) + default: + u.logger.Warn(fmt.Sprintf("Unknown source type %T", casted)) + u.metrics.recordRecoverableUnmarshallingError() + } + + attributes.PutStr(clientUsernameAttrKey, sendSpan.ConsumerClientUsername) + attributes.PutStr(clientNameAttrKey, sendSpan.ConsumerClientName) + attributes.PutBool(replayedKey, sendSpan.ReplayedMsg) + + var outcome string + switch sendSpan.Outcome { + case egress_v1.SpanData_SendSpan_ACCEPTED: + outcome = "accepted" + case egress_v1.SpanData_SendSpan_REJECTED: + outcome = "rejected" + case egress_v1.SpanData_SendSpan_RELEASED: + outcome = "released" + case egress_v1.SpanData_SendSpan_DELIVERY_FAILED: + outcome = "delivery failed" + case egress_v1.SpanData_SendSpan_FLOW_UNBOUND: + outcome = "flow unbound" + case egress_v1.SpanData_SendSpan_TRANSACTION_COMMIT: + outcome = "transaction commit" + case egress_v1.SpanData_SendSpan_TRANSACTION_COMMIT_FAILED: + outcome = "transaction commit failed" + case egress_v1.SpanData_SendSpan_TRANSACTION_ROLLBACK: + outcome = "transaction rollback" + } + attributes.PutStr(outcomeKey, outcome) +} + +// maps a transaction event. We cannot reuse the code in receive unmarshaller since +// the protobuf model is different and the return type for things like type and initiator would not work in an interface +func (u *brokerTraceEgressUnmarshallerV1) mapTransactionEvent(transactionEvent *egress_v1.SpanData_TransactionEvent, clientEvent ptrace.SpanEvent) { + // map the transaction type to a name + var name string + switch transactionEvent.GetType() { + case egress_v1.SpanData_TransactionEvent_COMMIT: + name = "commit" + case egress_v1.SpanData_TransactionEvent_ROLLBACK: + name = "rollback" + case egress_v1.SpanData_TransactionEvent_END: + name = "end" + case egress_v1.SpanData_TransactionEvent_PREPARE: + name = "prepare" + case egress_v1.SpanData_TransactionEvent_SESSION_TIMEOUT: + name = "session_timeout" + case egress_v1.SpanData_TransactionEvent_ROLLBACK_ONLY: + name = "rollback_only" + default: + // Set the name to the unknown transaction event type to ensure forward compat. + name = fmt.Sprintf("Unknown Transaction Event (%s)", transactionEvent.GetType().String()) + u.logger.Warn(fmt.Sprintf("Received span with unknown transaction event %s", transactionEvent.GetType())) + u.metrics.recordRecoverableUnmarshallingError() + } + clientEvent.SetName(name) + clientEvent.SetTimestamp(pcommon.Timestamp(transactionEvent.TimeUnixNano)) + // map initiator enums to expected initiator strings + var initiator string + switch transactionEvent.GetInitiator() { + case egress_v1.SpanData_TransactionEvent_CLIENT: + initiator = "client" + case egress_v1.SpanData_TransactionEvent_ADMIN: + initiator = "administrator" + case egress_v1.SpanData_TransactionEvent_BROKER: + initiator = "broker" + default: + initiator = fmt.Sprintf("Unknown Transaction Initiator (%s)", transactionEvent.GetInitiator().String()) + u.logger.Warn(fmt.Sprintf("Received span with unknown transaction initiator %s", transactionEvent.GetInitiator())) + u.metrics.recordRecoverableUnmarshallingError() + } + clientEvent.Attributes().PutStr(transactionInitiatorEventKey, initiator) + // conditionally set the error description if one occurred, otherwise omit + if transactionEvent.ErrorDescription != nil { + clientEvent.Attributes().PutStr(transactionErrorMessageEventKey, transactionEvent.GetErrorDescription()) + } + // map the transaction type/id + transactionID := transactionEvent.GetTransactionId() + switch casted := transactionID.(type) { + case *egress_v1.SpanData_TransactionEvent_LocalId: + clientEvent.Attributes().PutInt(transactionIDEventKey, int64(casted.LocalId.TransactionId)) + clientEvent.Attributes().PutStr(transactedSessionNameEventKey, casted.LocalId.SessionName) + clientEvent.Attributes().PutInt(transactedSessionIDEventKey, int64(casted.LocalId.SessionId)) + case *egress_v1.SpanData_TransactionEvent_Xid_: + // format xxxxxxxx-yyyyyyyy-zzzzzzzz where x is FormatID (hex rep of int32), y is BranchQualifier and z is GlobalID, hex encoded. + xidString := fmt.Sprintf("%08x", casted.Xid.FormatId) + "-" + + hex.EncodeToString(casted.Xid.BranchQualifier) + "-" + hex.EncodeToString(casted.Xid.GlobalId) + clientEvent.Attributes().PutStr(transactionXIDEventKey, xidString) + default: + u.logger.Warn(fmt.Sprintf("Unknown transaction ID type %T", transactionID)) + u.metrics.recordRecoverableUnmarshallingError() + } +} diff --git a/receiver/solacereceiver/unmarshaller_egress_test.go b/receiver/solacereceiver/unmarshaller_egress_test.go new file mode 100644 index 0000000000000..ab85469eee69d --- /dev/null +++ b/receiver/solacereceiver/unmarshaller_egress_test.go @@ -0,0 +1,583 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package solacereceiver + +import ( + "fmt" + "testing" + + "github.com/Azure/go-amqp" + "github.com/stretchr/testify/assert" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/ptrace" + "go.uber.org/zap" + + egress_v1 "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/solacereceiver/model/egress/v1" +) + +// msgWithAdditionalSpan is an EgressSpanMsg with one EgressSpan of type 1 (future proofing) +// Used to test that if we receive a oneof that does not support our given trace then we will be able to handle it. +// We must do this with protobuf data since we must ensure that the protobuf library handles this case as expected when unmarshalling. +var msgWithAdditionalSpan = []byte{10, 48, 10, 16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 18, 8, 1, 2, 3, 4, 5, 6, 7, 8, 26, 8, 1, 2, 3, 4, 5, 6, 7, 8, 74, 8, 32, 3, 10, 4, 116, 101, 115, 116, 18, 10, 118, 109, 114, 45, 49, 51, 51, 45, 53, 51, 26, 7, 100, 101, 102, 97, 117, 108, 116} + +func TestMsgWithUnknownOneof(t *testing.T) { + unmarshallerV1 := newTestEgressV1Unmarshaller(t) + spanData, err := unmarshallerV1.unmarshalToSpanData(amqp.NewMessage(msgWithAdditionalSpan)) + assert.NoError(t, err) + // expect one egress span + assert.Len(t, spanData.EgressSpans, 1) + assert.Nil(t, spanData.EgressSpans[0].GetSendSpan()) +} + +func TestEgressUnmarshallerMapResourceSpan(t *testing.T) { + var ( + routerName = "someRouterName" + vpnName = "someVpnName" + version = "10.0.0" + ) + tests := []struct { + name string + spanData *egress_v1.SpanData + want map[string]interface{} + expectedUnmarshallingErrors interface{} + }{ + { + name: "Maps All Fields When Present", + spanData: &egress_v1.SpanData{ + RouterName: routerName, + MessageVpnName: &vpnName, + SolosVersion: version, + }, + want: map[string]interface{}{ + "service.name": routerName, + "service.instance.id": vpnName, + "service.version": version, + }, + }, + { + name: "Does Not Map Fields When Not Present", + spanData: &egress_v1.SpanData{}, + want: map[string]interface{}{ + "service.version": "", + "service.name": "", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + u := newTestEgressV1Unmarshaller(t) + actual := pcommon.NewMap() + u.mapResourceSpanAttributes(tt.spanData, actual) + assert.Equal(t, tt.want, actual.AsRaw()) + validateMetric(t, u.metrics.views.recoverableUnmarshallingErrors, tt.expectedUnmarshallingErrors) + }) + } +} + +var ( + protocolVersion = "5.0" + protocolVersion2 = "1.0" + protocolVersion3 = "3.0" + someError = "someErrorOccurred" + someOtherError = "someOtherErrorOccurred" +) + +// validEgressSpans is valid data used as test data +var validEgressSpans = map[*egress_v1.SpanData_EgressSpan]ptrace.Span{ + { + TraceId: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + SpanId: []byte{7, 6, 5, 4, 3, 2, 1, 0}, + StartTimeUnixNano: 234567890, + EndTimeUnixNano: 234567890, + TypeData: &egress_v1.SpanData_EgressSpan_SendSpan{ + SendSpan: &egress_v1.SpanData_SendSpan{ + Protocol: "SMF", + ProtocolVersion: &protocolVersion3, + ConsumerClientUsername: "clientUsername", + ConsumerClientName: "clientName", + Source: &egress_v1.SpanData_SendSpan_QueueName{ + QueueName: "someQueue", + }, + Outcome: egress_v1.SpanData_SendSpan_FLOW_UNBOUND, + ReplayedMsg: false, + }, + }, + }: func() ptrace.Span { + span := ptrace.NewSpan() + span.SetTraceID([16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}) + span.SetSpanID([8]byte{7, 6, 5, 4, 3, 2, 1, 0}) + span.SetStartTimestamp(234567890) + span.SetEndTimestamp(234567890) + span.SetKind(4) + spanAttrs := span.Attributes() + spanAttrs.PutStr("messaging.system", "SolacePubSub+") + spanAttrs.PutStr("messaging.operation", "send") + spanAttrs.PutStr("messaging.protocol", "SMF") + spanAttrs.PutStr("messaging.protocol_version", "3.0") + spanAttrs.PutStr("messaging.source.name", "someQueue") + spanAttrs.PutStr("messaging.source.kind", "queue") + spanAttrs.PutStr("messaging.solace.client_username", "clientUsername") + spanAttrs.PutStr("messaging.solace.client_name", "clientName") + spanAttrs.PutBool("messaging.solace.message_replayed", false) + spanAttrs.PutStr("messaging.solace.send_operation.outcome", "flow unbound") + return span + }(), + { + TraceId: []byte{1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + SpanId: []byte{7, 6, 5, 4, 3, 2, 1, 1}, + StartTimeUnixNano: 1234567890, + EndTimeUnixNano: 2234567890, + ErrorDescription: &someError, + TypeData: &egress_v1.SpanData_EgressSpan_SendSpan{ + SendSpan: &egress_v1.SpanData_SendSpan{ + Protocol: "MQTT", + ProtocolVersion: &protocolVersion, + ConsumerClientUsername: "someClientUsername", + ConsumerClientName: "someClient1234", + Source: &egress_v1.SpanData_SendSpan_QueueName{ + QueueName: "queueName", + }, + Outcome: egress_v1.SpanData_SendSpan_ACCEPTED, + ReplayedMsg: false, + }, + }, + TransactionEvent: &egress_v1.SpanData_TransactionEvent{ + TimeUnixNano: 123456789, + Type: egress_v1.SpanData_TransactionEvent_SESSION_TIMEOUT, + Initiator: egress_v1.SpanData_TransactionEvent_BROKER, + TransactionId: &egress_v1.SpanData_TransactionEvent_LocalId{ + LocalId: &egress_v1.SpanData_TransactionEvent_LocalTransactionId{ + TransactionId: 12345, + SessionId: 67890, + SessionName: "my-session-name", + }, + }, + ErrorDescription: &someOtherError, + }, + }: func() ptrace.Span { + span := ptrace.NewSpan() + span.SetTraceID([16]byte{1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}) + span.SetSpanID([8]byte{7, 6, 5, 4, 3, 2, 1, 1}) + span.SetStartTimestamp(1234567890) + span.SetEndTimestamp(2234567890) + span.SetKind(4) + span.Status().SetCode(ptrace.StatusCodeError) + span.Status().SetMessage("someErrorOccurred") + spanAttrs := span.Attributes() + spanAttrs.PutStr("messaging.system", "SolacePubSub+") + spanAttrs.PutStr("messaging.operation", "send") + spanAttrs.PutStr("messaging.protocol", "MQTT") + spanAttrs.PutStr("messaging.protocol_version", "5.0") + spanAttrs.PutStr("messaging.source.name", "queueName") + spanAttrs.PutStr("messaging.source.kind", "queue") + spanAttrs.PutStr("messaging.solace.client_username", "someClientUsername") + spanAttrs.PutStr("messaging.solace.client_name", "someClient1234") + spanAttrs.PutBool("messaging.solace.message_replayed", false) + spanAttrs.PutStr("messaging.solace.send_operation.outcome", "accepted") + txnEvent := span.Events().AppendEmpty() + txnEvent.SetName("session_timeout") + txnEvent.SetTimestamp(123456789) + txnEventAttrs := txnEvent.Attributes() + txnEventAttrs.PutStr("messaging.solace.transaction_initiator", "broker") + txnEventAttrs.PutInt("messaging.solace.transaction_id", 12345) + txnEventAttrs.PutStr("messaging.solace.transacted_session_name", "my-session-name") + txnEventAttrs.PutInt("messaging.solace.transacted_session_id", 67890) + txnEventAttrs.PutStr("messaging.solace.transaction_error_message", "someOtherErrorOccurred") + return span + }(), + { + TraceId: []byte{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}, + SpanId: []byte{0, 1, 2, 3, 4, 5, 6, 7}, + ParentSpanId: []byte{7, 6, 5, 4, 3, 2, 1, 0}, + StartTimeUnixNano: 4234567890, + EndTimeUnixNano: 5234567890, + TypeData: &egress_v1.SpanData_EgressSpan_SendSpan{ + SendSpan: &egress_v1.SpanData_SendSpan{ + Protocol: "AMQP", + ProtocolVersion: &protocolVersion2, + ConsumerClientUsername: "someOtherClientUsername", + ConsumerClientName: "someOtherClient1234", + Source: &egress_v1.SpanData_SendSpan_TopicEndpointName{ + TopicEndpointName: "topicEndpointName", + }, + Outcome: egress_v1.SpanData_SendSpan_REJECTED, + ReplayedMsg: true, + }, + }, + TransactionEvent: &egress_v1.SpanData_TransactionEvent{ + TimeUnixNano: 223456789, + Type: egress_v1.SpanData_TransactionEvent_END, + Initiator: egress_v1.SpanData_TransactionEvent_CLIENT, + TransactionId: &egress_v1.SpanData_TransactionEvent_Xid_{ + Xid: &egress_v1.SpanData_TransactionEvent_Xid{ + FormatId: 123, + BranchQualifier: []byte{0, 8, 20, 254}, + GlobalId: []byte{128, 64, 32, 16, 8, 4, 2, 1, 0}, + }, + }, + }, + }: func() ptrace.Span { + // second send span + span := ptrace.NewSpan() + span.SetTraceID([16]byte{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}) + span.SetSpanID([8]byte{0, 1, 2, 3, 4, 5, 6, 7}) + span.SetParentSpanID([8]byte{7, 6, 5, 4, 3, 2, 1, 0}) + span.SetStartTimestamp(4234567890) + span.SetEndTimestamp(5234567890) + span.SetKind(4) + spanAttrs := span.Attributes() + spanAttrs.PutStr("messaging.system", "SolacePubSub+") + spanAttrs.PutStr("messaging.operation", "send") + spanAttrs.PutStr("messaging.protocol", "AMQP") + spanAttrs.PutStr("messaging.protocol_version", "1.0") + spanAttrs.PutStr("messaging.source.name", "topicEndpointName") + spanAttrs.PutStr("messaging.source.kind", "topic-endpoint") + spanAttrs.PutStr("messaging.solace.client_username", "someOtherClientUsername") + spanAttrs.PutStr("messaging.solace.client_name", "someOtherClient1234") + spanAttrs.PutBool("messaging.solace.message_replayed", true) + spanAttrs.PutStr("messaging.solace.send_operation.outcome", "rejected") + txnEvent := span.Events().AppendEmpty() + txnEvent.SetName("end") + txnEvent.SetTimestamp(223456789) + txnAttrs := txnEvent.Attributes() + txnAttrs.PutStr("messaging.solace.transaction_initiator", "client") + txnAttrs.PutStr("messaging.solace.transaction_xid", "0000007b-000814fe-804020100804020100") + return span + }(), +} + +func TestEgressUnmarshallerEgressSpan(t *testing.T) { + type testCase struct { + name string + spanData *egress_v1.SpanData_EgressSpan + want *ptrace.Span + expectedUnmarshallingErrors interface{} + } + tests := []testCase{ + { + name: "No typed span", + spanData: &egress_v1.SpanData_EgressSpan{ + TraceId: []byte{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}, + SpanId: []byte{0, 1, 2, 3, 4, 5, 6, 7}, + ParentSpanId: []byte{7, 6, 5, 4, 3, 2, 1, 0}, + StartTimeUnixNano: 4234567890, + EndTimeUnixNano: 5234567890, + // no typed span type + }, + }, + } + var i = 1 + for spanDataRef, wantRef := range validEgressSpans { + name := "valid span " + fmt.Sprint(i) + i++ + want := wantRef + spanData := spanDataRef + tests = append(tests, testCase{ + name: name, + spanData: spanData, + want: &want, + }) + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + u := newTestEgressV1Unmarshaller(t) + actual := ptrace.NewSpanSlice() + u.mapEgressSpan(tt.spanData, actual) + if tt.want != nil { + assert.Equal(t, 1, actual.Len()) + compareSpans(t, *tt.want, actual.At(0)) + } else { + assert.Equal(t, 0, actual.Len()) + validateMetric(t, u.metrics.views.droppedEgressSpans, 1) + } + validateMetric(t, u.metrics.views.recoverableUnmarshallingErrors, tt.expectedUnmarshallingErrors) + }) + } +} + +func TestEgressUnmarshallerSendSpanAttributes(t *testing.T) { + // creates a base attribute map that additional data can be added to + // does not include outcome or source. Attributes will override all fields in base + getAttributes := func(attributes map[string]interface{}) map[string]interface{} { + base := map[string]interface{}{ + "messaging.system": "SolacePubSub+", + "messaging.operation": "send", + "messaging.protocol": "MQTT", + "messaging.protocol_version": "5.0", + "messaging.solace.client_username": "someUser", + "messaging.solace.client_name": "someName", + "messaging.solace.message_replayed": false, + "messaging.solace.send_operation.outcome": "accepted", + } + for key, val := range attributes { + base[key] = val + } + return base + } + // sets the common fields from getAttributes + getSendSpan := func(base *egress_v1.SpanData_SendSpan) *egress_v1.SpanData_SendSpan { + protocolVersion := "5.0" + base.Protocol = "MQTT" + base.ProtocolVersion = &protocolVersion + base.ConsumerClientUsername = "someUser" + base.ConsumerClientName = "someName" + return base + } + tests := []struct { + name string + spanData *egress_v1.SpanData_SendSpan + want map[string]interface{} + expectedUnmarshallingErrors interface{} + }{ + { + name: "With Queue source", + spanData: getSendSpan(&egress_v1.SpanData_SendSpan{ + Source: &egress_v1.SpanData_SendSpan_QueueName{ + QueueName: "someQueue", + }, + }), + want: getAttributes(map[string]interface{}{ + "messaging.source.name": "someQueue", + "messaging.source.kind": "queue", + }), + }, + { + name: "With Topic Endpoint source", + spanData: getSendSpan(&egress_v1.SpanData_SendSpan{ + Source: &egress_v1.SpanData_SendSpan_TopicEndpointName{ + TopicEndpointName: "someTopic", + }, + }), + want: getAttributes(map[string]interface{}{ + "messaging.source.name": "someTopic", + "messaging.source.kind": "topic-endpoint", + }), + }, + { + name: "With Unknown Endpoint source", + spanData: getSendSpan(&egress_v1.SpanData_SendSpan{}), + want: getAttributes(map[string]interface{}{}), + expectedUnmarshallingErrors: 1, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + u := newTestEgressV1Unmarshaller(t) + actual := pcommon.NewMap() + u.mapSendSpanAttributes(tt.spanData, actual) + assert.Equal(t, tt.want, actual.AsRaw()) + validateMetric(t, u.metrics.views.recoverableUnmarshallingErrors, tt.expectedUnmarshallingErrors) + }) + } + // test the various outcomes + outcomes := map[egress_v1.SpanData_SendSpan_Outcome]string{ + egress_v1.SpanData_SendSpan_ACCEPTED: "accepted", + egress_v1.SpanData_SendSpan_REJECTED: "rejected", + egress_v1.SpanData_SendSpan_RELEASED: "released", + egress_v1.SpanData_SendSpan_DELIVERY_FAILED: "delivery failed", + egress_v1.SpanData_SendSpan_FLOW_UNBOUND: "flow unbound", + egress_v1.SpanData_SendSpan_TRANSACTION_COMMIT: "transaction commit", + egress_v1.SpanData_SendSpan_TRANSACTION_COMMIT_FAILED: "transaction commit failed", + egress_v1.SpanData_SendSpan_TRANSACTION_ROLLBACK: "transaction rollback", + } + for outcomeKey, outcomeName := range outcomes { + t.Run("With outcome "+outcomeName, func(t *testing.T) { + u := newTestEgressV1Unmarshaller(t) + expected := getAttributes(map[string]interface{}{ + "messaging.source.name": "someQueue", + "messaging.source.kind": "queue", + "messaging.solace.send_operation.outcome": outcomeName, + }) + spanData := getSendSpan(&egress_v1.SpanData_SendSpan{ + Source: &egress_v1.SpanData_SendSpan_QueueName{ + QueueName: "someQueue", + }, + Outcome: outcomeKey, + }) + actual := pcommon.NewMap() + u.mapSendSpanAttributes(spanData, actual) + assert.Equal(t, expected, actual.AsRaw()) + }) + } +} + +func TestEgressUnmarshallerTransactionEvent(t *testing.T) { + someErrorString := "some error" + tests := []struct { + name string + spanData *egress_v1.SpanData_TransactionEvent + populateExpectedSpan func(span ptrace.Span) + unmarshallingErrors interface{} + }{ + { // Local Transaction + name: "Local Transaction Event", + spanData: &egress_v1.SpanData_TransactionEvent{ + TimeUnixNano: 123456789, + Type: egress_v1.SpanData_TransactionEvent_COMMIT, + Initiator: egress_v1.SpanData_TransactionEvent_CLIENT, + TransactionId: &egress_v1.SpanData_TransactionEvent_LocalId{ + LocalId: &egress_v1.SpanData_TransactionEvent_LocalTransactionId{ + TransactionId: 12345, + SessionId: 67890, + SessionName: "my-session-name", + }, + }, + }, + populateExpectedSpan: func(span ptrace.Span) { + populateEvent(t, span, "commit", 123456789, map[string]interface{}{ + "messaging.solace.transaction_initiator": "client", + "messaging.solace.transaction_id": 12345, + "messaging.solace.transacted_session_name": "my-session-name", + "messaging.solace.transacted_session_id": 67890, + }) + }, + }, + { + name: "Local Transaction Event with Session Timeout", + spanData: &egress_v1.SpanData_TransactionEvent{ + TimeUnixNano: 123456789, + Type: egress_v1.SpanData_TransactionEvent_SESSION_TIMEOUT, + Initiator: egress_v1.SpanData_TransactionEvent_CLIENT, + TransactionId: &egress_v1.SpanData_TransactionEvent_LocalId{ + LocalId: &egress_v1.SpanData_TransactionEvent_LocalTransactionId{ + TransactionId: 12345, + SessionId: 67890, + SessionName: "my-session-name", + }, + }, + }, + populateExpectedSpan: func(span ptrace.Span) { + populateEvent(t, span, "session_timeout", 123456789, map[string]interface{}{ + "messaging.solace.transaction_initiator": "client", + "messaging.solace.transaction_id": 12345, + "messaging.solace.transacted_session_name": "my-session-name", + "messaging.solace.transacted_session_id": 67890, + }) + }, + }, + { + name: "Local Transaction Event with Rollback Only", + spanData: &egress_v1.SpanData_TransactionEvent{ + TimeUnixNano: 123456789, + Type: egress_v1.SpanData_TransactionEvent_ROLLBACK_ONLY, + Initiator: egress_v1.SpanData_TransactionEvent_CLIENT, + TransactionId: &egress_v1.SpanData_TransactionEvent_LocalId{ + LocalId: &egress_v1.SpanData_TransactionEvent_LocalTransactionId{ + TransactionId: 12345, + SessionId: 67890, + SessionName: "my-session-name", + }, + }, + }, + populateExpectedSpan: func(span ptrace.Span) { + populateEvent(t, span, "rollback_only", 123456789, map[string]interface{}{ + "messaging.solace.transaction_initiator": "client", + "messaging.solace.transaction_id": 12345, + "messaging.solace.transacted_session_name": "my-session-name", + "messaging.solace.transacted_session_id": 67890, + }) + }, + }, + { // XA transaction + name: "XA Transaction Event", + spanData: &egress_v1.SpanData_TransactionEvent{ + TimeUnixNano: 123456789, + Type: egress_v1.SpanData_TransactionEvent_END, + Initiator: egress_v1.SpanData_TransactionEvent_ADMIN, + TransactionId: &egress_v1.SpanData_TransactionEvent_Xid_{ + Xid: &egress_v1.SpanData_TransactionEvent_Xid{ + FormatId: 123, + BranchQualifier: []byte{0, 8, 20, 254}, + GlobalId: []byte{128, 64, 32, 16, 8, 4, 2, 1, 0}, + }, + }, + }, + populateExpectedSpan: func(span ptrace.Span) { + populateEvent(t, span, "end", 123456789, map[string]interface{}{ + "messaging.solace.transaction_initiator": "administrator", + "messaging.solace.transaction_xid": "0000007b-000814fe-804020100804020100", + }) + }, + }, + { // XA Transaction with no branch qualifier or global ID and with an error + name: "XA Transaction Event with nil fields and error", + spanData: &egress_v1.SpanData_TransactionEvent{ + TimeUnixNano: 123456789, + Type: egress_v1.SpanData_TransactionEvent_PREPARE, + Initiator: egress_v1.SpanData_TransactionEvent_BROKER, + TransactionId: &egress_v1.SpanData_TransactionEvent_Xid_{ + Xid: &egress_v1.SpanData_TransactionEvent_Xid{ + FormatId: 123, + BranchQualifier: nil, + GlobalId: nil, + }, + }, + ErrorDescription: &someErrorString, + }, + populateExpectedSpan: func(span ptrace.Span) { + populateEvent(t, span, "prepare", 123456789, map[string]interface{}{ + "messaging.solace.transaction_initiator": "broker", + "messaging.solace.transaction_xid": "0000007b--", + "messaging.solace.transaction_error_message": someErrorString, + }) + }, + }, + { // Type of transaction not handled + name: "Unknown Transaction Type and no ID", + spanData: &egress_v1.SpanData_TransactionEvent{ + TimeUnixNano: 123456789, + Type: egress_v1.SpanData_TransactionEvent_Type(12345), + }, + populateExpectedSpan: func(span ptrace.Span) { + populateEvent(t, span, "Unknown Transaction Event (12345)", 123456789, map[string]interface{}{ + "messaging.solace.transaction_initiator": "client", + }) + }, + unmarshallingErrors: 2, + }, + { // Type of ID not handled, type of initiator not handled + name: "Unknown Transaction Initiator and no ID", + spanData: &egress_v1.SpanData_TransactionEvent{ + TimeUnixNano: 123456789, + Type: egress_v1.SpanData_TransactionEvent_ROLLBACK, + Initiator: egress_v1.SpanData_TransactionEvent_Initiator(12345), + TransactionId: nil, + }, + populateExpectedSpan: func(span ptrace.Span) { + populateEvent(t, span, "rollback", 123456789, map[string]interface{}{ + "messaging.solace.transaction_initiator": "Unknown Transaction Initiator (12345)", + }) + }, + unmarshallingErrors: 2, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + u := newTestEgressV1Unmarshaller(t) + expected := ptrace.NewTraces().ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty().Spans().AppendEmpty() + tt.populateExpectedSpan(expected) + actual := ptrace.NewTraces().ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty().Spans().AppendEmpty() + u.mapTransactionEvent(tt.spanData, actual.Events().AppendEmpty()) + // order is nondeterministic for attributes, so we must sort to get a valid comparison + compareSpans(t, expected, actual) + validateMetric(t, u.metrics.views.recoverableUnmarshallingErrors, tt.unmarshallingErrors) + }) + } +} + +func newTestEgressV1Unmarshaller(t *testing.T) *brokerTraceEgressUnmarshallerV1 { + m := newTestMetrics(t) + return &brokerTraceEgressUnmarshallerV1{zap.NewNop(), m} +} diff --git a/receiver/solacereceiver/unmarshaller_receive.go b/receiver/solacereceiver/unmarshaller_receive.go new file mode 100644 index 0000000000000..979ae310046d2 --- /dev/null +++ b/receiver/solacereceiver/unmarshaller_receive.go @@ -0,0 +1,415 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package solacereceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/solacereceiver" + +import ( + "encoding/hex" + "fmt" + "net" + "strings" + + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/ptrace" + "go.opentelemetry.io/otel/baggage" + "go.uber.org/zap" + "google.golang.org/protobuf/proto" + + receive_v1 "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/solacereceiver/model/receive/v1" +) + +type brokerTraceReceiveUnmarshallerV1 struct { + logger *zap.Logger + metrics *opencensusMetrics +} + +// unmarshal implements tracesUnmarshaller.unmarshal +func (u *brokerTraceReceiveUnmarshallerV1) unmarshal(message *inboundMessage) (ptrace.Traces, error) { + spanData, err := u.unmarshalToSpanData(message) + if err != nil { + return ptrace.Traces{}, err + } + traces := ptrace.NewTraces() + u.populateTraces(spanData, traces) + return traces, nil +} + +// unmarshalToSpanData will consume an solaceMessage and unmarshal it into a SpanData. +// Returns an error if one occurred. +func (u *brokerTraceReceiveUnmarshallerV1) unmarshalToSpanData(message *inboundMessage) (*receive_v1.SpanData, error) { + var data = message.GetData() + if len(data) == 0 { + return nil, errEmptyPayload + } + var spanData receive_v1.SpanData + if err := proto.Unmarshal(data, &spanData); err != nil { + return nil, err + } + return &spanData, nil +} + +// createSpan will create a new Span from the given traces and map the given SpanData to the span. +// This will set all required fields such as name version, trace and span ID, parent span ID (if applicable), +// timestamps, errors and states. +func (u *brokerTraceReceiveUnmarshallerV1) populateTraces(spanData *receive_v1.SpanData, traces ptrace.Traces) { + // Append new resource span and map any attributes + resourceSpan := traces.ResourceSpans().AppendEmpty() + u.mapResourceSpanAttributes(spanData, resourceSpan.Resource().Attributes()) + instrLibrarySpans := resourceSpan.ScopeSpans().AppendEmpty() + // Create a new span + clientSpan := instrLibrarySpans.Spans().AppendEmpty() + // map the basic span data + u.mapClientSpanData(spanData, clientSpan) + // map all span attributes + u.mapClientSpanAttributes(spanData, clientSpan.Attributes()) + // map all events + u.mapEvents(spanData, clientSpan) +} + +func (u *brokerTraceReceiveUnmarshallerV1) mapResourceSpanAttributes(spanData *receive_v1.SpanData, attrMap pcommon.Map) { + setResourceSpanAttributes(attrMap, spanData.RouterName, spanData.SolosVersion, spanData.MessageVpnName) +} + +func (u *brokerTraceReceiveUnmarshallerV1) mapClientSpanData(spanData *receive_v1.SpanData, clientSpan ptrace.Span) { + const clientSpanName = "(topic) receive" + + // client span constants + clientSpan.SetName(clientSpanName) + // SPAN_KIND_CONSUMER == 5 + clientSpan.SetKind(ptrace.SpanKindConsumer) + + // map trace ID + var traceID [16]byte + copy(traceID[:16], spanData.TraceId) + clientSpan.SetTraceID(traceID) + // map span ID + var spanID [8]byte + copy(spanID[:8], spanData.SpanId) + clientSpan.SetSpanID(spanID) + // conditional parent-span-id + if len(spanData.ParentSpanId) == 8 { + var parentSpanID [8]byte + copy(parentSpanID[:8], spanData.ParentSpanId) + clientSpan.SetParentSpanID(parentSpanID) + } + + // timestamps + clientSpan.SetStartTimestamp(pcommon.Timestamp(spanData.GetStartTimeUnixNano())) + clientSpan.SetEndTimestamp(pcommon.Timestamp(spanData.GetEndTimeUnixNano())) + // status + if spanData.ErrorDescription != "" { + clientSpan.Status().SetCode(ptrace.StatusCodeError) + clientSpan.Status().SetMessage(spanData.ErrorDescription) + } + // trace state + if spanData.TraceState != nil { + clientSpan.TraceState().FromRaw(*spanData.TraceState) + } +} + +// mapAttributes takes a set of attributes from SpanData and maps them to ClientSpan.Attributes(). +// Will also copy any user properties stored in the SpanData with a best effort approach. +func (u *brokerTraceReceiveUnmarshallerV1) mapClientSpanAttributes(spanData *receive_v1.SpanData, attrMap pcommon.Map) { + // receive operation + const operationAttrValue = "receive" + attrMap.PutStr(systemAttrKey, systemAttrValue) + attrMap.PutStr(operationAttrKey, operationAttrValue) + + attrMap.PutStr(protocolAttrKey, spanData.Protocol) + if spanData.ProtocolVersion != nil { + attrMap.PutStr(protocolVersionAttrKey, *spanData.ProtocolVersion) + } + if spanData.ApplicationMessageId != nil { + attrMap.PutStr(messageIDAttrKey, *spanData.ApplicationMessageId) + } + if spanData.CorrelationId != nil { + attrMap.PutStr(conversationIDAttrKey, *spanData.CorrelationId) + } + attrMap.PutInt(payloadSizeBytesAttrKey, int64(spanData.BinaryAttachmentSize+spanData.XmlAttachmentSize+spanData.MetadataSize)) + attrMap.PutStr(clientUsernameAttrKey, spanData.ClientUsername) + attrMap.PutStr(clientNameAttrKey, spanData.ClientName) + attrMap.PutInt(receiveTimeAttrKey, spanData.BrokerReceiveTimeUnixNano) + attrMap.PutStr(destinationAttrKey, spanData.Topic) + + var deliveryMode string + switch spanData.DeliveryMode { + case receive_v1.SpanData_DIRECT: + deliveryMode = "direct" + case receive_v1.SpanData_NON_PERSISTENT: + deliveryMode = "non_persistent" + case receive_v1.SpanData_PERSISTENT: + deliveryMode = "persistent" + default: + deliveryMode = fmt.Sprintf("Unknown Delivery Mode (%s)", spanData.DeliveryMode.String()) + u.logger.Warn(fmt.Sprintf("Received span with unknown delivery mode %s", spanData.DeliveryMode)) + u.metrics.recordRecoverableUnmarshallingError() + } + attrMap.PutStr(deliveryModeAttrKey, deliveryMode) + + rgmid := u.rgmidToString(spanData.ReplicationGroupMessageId) + if len(rgmid) > 0 { + attrMap.PutStr(replicationGroupMessageIDAttrKey, rgmid) + } + + if spanData.Priority != nil { + attrMap.PutInt(priorityAttrKey, int64(*spanData.Priority)) + } + if spanData.Ttl != nil { + attrMap.PutInt(ttlAttrKey, *spanData.Ttl) + } + if spanData.ReplyToTopic != nil { + attrMap.PutStr(replyToAttrKey, *spanData.ReplyToTopic) + } + attrMap.PutBool(dmqEligibleAttrKey, spanData.DmqEligible) + attrMap.PutInt(droppedEnqueueEventsSuccessAttrKey, int64(spanData.DroppedEnqueueEventsSuccess)) + attrMap.PutInt(droppedEnqueueEventsFailedAttrKey, int64(spanData.DroppedEnqueueEventsFailed)) + + // The IPs are now optional meaning we will not incluude them if they are zero length + hostIPLen := len(spanData.HostIp) + if hostIPLen == 4 || hostIPLen == 16 { + attrMap.PutStr(hostIPAttrKey, net.IP(spanData.HostIp).String()) + attrMap.PutInt(hostPortAttrKey, int64(spanData.HostPort)) + } else { + u.logger.Debug("Host ip not included", zap.Int("length", hostIPLen)) + } + + peerIPLen := len(spanData.PeerIp) + if peerIPLen == 4 || peerIPLen == 16 { + attrMap.PutStr(peerIPAttrKey, net.IP(spanData.PeerIp).String()) + attrMap.PutInt(peerPortAttrKey, int64(spanData.PeerPort)) + } else { + u.logger.Debug("Peer IP not included", zap.Int("length", peerIPLen)) + } + + if spanData.Baggage != nil { + err := u.unmarshalBaggage(attrMap, *spanData.Baggage) + if err != nil { + u.logger.Warn("Received malformed baggage string in span data") + u.metrics.recordRecoverableUnmarshallingError() + } + } + + attrMap.PutBool(droppedUserPropertiesAttrKey, spanData.DroppedApplicationMessageProperties) + for key, value := range spanData.UserProperties { + if value != nil { + u.insertUserProperty(attrMap, key, value.Value) + } + } +} + +// mapEvents maps all events contained in SpanData to relevant events within clientSpan.Events() +func (u *brokerTraceReceiveUnmarshallerV1) mapEvents(spanData *receive_v1.SpanData, clientSpan ptrace.Span) { + // handle enqueue events + for _, enqueueEvent := range spanData.EnqueueEvents { + u.mapEnqueueEvent(enqueueEvent, clientSpan.Events()) + } + + // handle transaction events + if transactionEvent := spanData.TransactionEvent; transactionEvent != nil { + u.mapTransactionEvent(transactionEvent, clientSpan.Events().AppendEmpty()) + } +} + +// mapEnqueueEvent maps a SpanData_EnqueueEvent to a ClientSpan.Event +func (u *brokerTraceReceiveUnmarshallerV1) mapEnqueueEvent(enqueueEvent *receive_v1.SpanData_EnqueueEvent, clientSpanEvents ptrace.SpanEventSlice) { + const ( + enqueueEventSuffix = " enqueue" // Final should be ` enqueue` + messagingDestinationTypeEventKey = "messaging.solace.destination_type" + statusMessageEventKey = "messaging.solace.enqueue_error_message" + rejectsAllEnqueuesKey = "messaging.solace.rejects_all_enqueues" + partitionNumberKey = "messaging.solace.partition_number" + ) + var destinationName string + var destinationType string + switch casted := enqueueEvent.Dest.(type) { + case *receive_v1.SpanData_EnqueueEvent_TopicEndpointName: + destinationName = casted.TopicEndpointName + destinationType = topicEndpointKind + case *receive_v1.SpanData_EnqueueEvent_QueueName: + destinationName = casted.QueueName + destinationType = queueKind + default: + u.logger.Warn(fmt.Sprintf("Unknown destination type %T", casted)) + u.metrics.recordRecoverableUnmarshallingError() + return + } + clientEvent := clientSpanEvents.AppendEmpty() + clientEvent.SetName(destinationName + enqueueEventSuffix) + clientEvent.SetTimestamp(pcommon.Timestamp(enqueueEvent.TimeUnixNano)) + clientEvent.Attributes().EnsureCapacity(3) + clientEvent.Attributes().PutStr(messagingDestinationTypeEventKey, destinationType) + clientEvent.Attributes().PutBool(rejectsAllEnqueuesKey, enqueueEvent.RejectsAllEnqueues) + if enqueueEvent.ErrorDescription != nil { + clientEvent.Attributes().PutStr(statusMessageEventKey, enqueueEvent.GetErrorDescription()) + } + if enqueueEvent.PartitionNumber != nil { + clientEvent.Attributes().PutInt(partitionNumberKey, int64(*enqueueEvent.PartitionNumber)) + } +} + +// mapTransactionEvent maps a SpanData_TransactionEvent to a ClientSpan.Event +func (u *brokerTraceReceiveUnmarshallerV1) mapTransactionEvent(transactionEvent *receive_v1.SpanData_TransactionEvent, clientEvent ptrace.SpanEvent) { + // map the transaction type to a name + var name string + switch transactionEvent.GetType() { + case receive_v1.SpanData_TransactionEvent_COMMIT: + name = "commit" + case receive_v1.SpanData_TransactionEvent_ROLLBACK: + name = "rollback" + case receive_v1.SpanData_TransactionEvent_END: + name = "end" + case receive_v1.SpanData_TransactionEvent_PREPARE: + name = "prepare" + case receive_v1.SpanData_TransactionEvent_SESSION_TIMEOUT: + name = "session_timeout" + case receive_v1.SpanData_TransactionEvent_ROLLBACK_ONLY: + name = "rollback_only" + default: + // Set the name to the unknown transaction event type to ensure forward compat. + name = fmt.Sprintf("Unknown Transaction Event (%s)", transactionEvent.GetType().String()) + u.logger.Warn(fmt.Sprintf("Received span with unknown transaction event %s", transactionEvent.GetType())) + u.metrics.recordRecoverableUnmarshallingError() + } + clientEvent.SetName(name) + clientEvent.SetTimestamp(pcommon.Timestamp(transactionEvent.TimeUnixNano)) + // map initiator enums to expected initiator strings + var initiator string + switch transactionEvent.GetInitiator() { + case receive_v1.SpanData_TransactionEvent_CLIENT: + initiator = "client" + case receive_v1.SpanData_TransactionEvent_ADMIN: + initiator = "administrator" + case receive_v1.SpanData_TransactionEvent_BROKER: + initiator = "broker" + default: + initiator = fmt.Sprintf("Unknown Transaction Initiator (%s)", transactionEvent.GetInitiator().String()) + u.logger.Warn(fmt.Sprintf("Received span with unknown transaction initiator %s", transactionEvent.GetInitiator())) + u.metrics.recordRecoverableUnmarshallingError() + } + clientEvent.Attributes().PutStr(transactionInitiatorEventKey, initiator) + // conditionally set the error description if one occurred, otherwise omit + if transactionEvent.ErrorDescription != nil { + clientEvent.Attributes().PutStr(transactionErrorMessageEventKey, transactionEvent.GetErrorDescription()) + } + // map the transaction type/id + transactionID := transactionEvent.GetTransactionId() + switch casted := transactionID.(type) { + case *receive_v1.SpanData_TransactionEvent_LocalId: + clientEvent.Attributes().PutInt(transactionIDEventKey, int64(casted.LocalId.TransactionId)) + clientEvent.Attributes().PutStr(transactedSessionNameEventKey, casted.LocalId.SessionName) + clientEvent.Attributes().PutInt(transactedSessionIDEventKey, int64(casted.LocalId.SessionId)) + case *receive_v1.SpanData_TransactionEvent_Xid_: + // format xxxxxxxx-yyyyyyyy-zzzzzzzz where x is FormatID (hex rep of int32), y is BranchQualifier and z is GlobalID, hex encoded. + xidString := fmt.Sprintf("%08x", casted.Xid.FormatId) + "-" + + hex.EncodeToString(casted.Xid.BranchQualifier) + "-" + hex.EncodeToString(casted.Xid.GlobalId) + clientEvent.Attributes().PutStr(transactionXIDEventKey, xidString) + default: + u.logger.Warn(fmt.Sprintf("Unknown transaction ID type %T", transactionID)) + u.metrics.recordRecoverableUnmarshallingError() + } +} + +func (u *brokerTraceReceiveUnmarshallerV1) rgmidToString(rgmid []byte) string { + // rgmid[0] is the version of the rgmid + if len(rgmid) != 17 || rgmid[0] != 1 { + // may be cases where the rgmid is empty or nil, len(rgmid) will return 0 if nil + if len(rgmid) > 0 { + u.logger.Warn("Received invalid length or version for rgmid", zap.Int8("version", int8(rgmid[0])), zap.Int("length", len(rgmid))) + u.metrics.recordRecoverableUnmarshallingError() + } + return hex.EncodeToString(rgmid) + } + rgmidEncoded := make([]byte, 32) + hex.Encode(rgmidEncoded, rgmid[1:]) + // format: rmid1:aaaaa-bbbbbbbbbbb-cccccccc-dddddddd + rgmidString := "rmid1:" + string(rgmidEncoded[0:5]) + "-" + string(rgmidEncoded[5:16]) + "-" + string(rgmidEncoded[16:24]) + "-" + string(rgmidEncoded[24:32]) + return rgmidString +} + +// unmarshalBaggage will unmarshal a baggage string +// See spec https://github.com/open-telemetry/opentelemetry-go/blob/v1.11.1/baggage/baggage.go +func (u *brokerTraceReceiveUnmarshallerV1) unmarshalBaggage(toMap pcommon.Map, baggageString string) error { + const ( + baggageValuePrefix = "messaging.solace.message.baggage." + baggageMetadataPrefix = "messaging.solace.message.baggage_metadata." + propertyDelimiter = ";" + ) + bg, err := baggage.Parse(baggageString) + if err != nil { + return err + } + // we got a valid baggage string, assume everything else is valid + for _, member := range bg.Members() { + toMap.PutStr(baggageValuePrefix+member.Key(), member.Value()) + // member.Properties copies, we should cache + properties := member.Properties() + if len(properties) > 0 { + // Re-encode the properties and save them as a parameter + var propertyString strings.Builder + propertyString.WriteString(properties[0].String()) + for i := 1; i < len(properties); i++ { + propertyString.WriteString(propertyDelimiter + properties[i].String()) + } + toMap.PutStr(baggageMetadataPrefix+member.Key(), propertyString.String()) + } + } + return nil +} + +// insertUserProperty will instert a user property value with the given key to an attribute if possible. +// Since AttributeMap only supports int64 integer types, uint64 data may be misrepresented. +func (u *brokerTraceReceiveUnmarshallerV1) insertUserProperty(toMap pcommon.Map, key string, value interface{}) { + const ( + // userPropertiesPrefixAttrKey is the key used to prefix all user properties + userPropertiesAttrKeyPrefix = "messaging.solace.user_properties." + ) + k := userPropertiesAttrKeyPrefix + key + switch v := value.(type) { + case *receive_v1.SpanData_UserPropertyValue_NullValue: + toMap.PutEmpty(k) + case *receive_v1.SpanData_UserPropertyValue_BoolValue: + toMap.PutBool(k, v.BoolValue) + case *receive_v1.SpanData_UserPropertyValue_DoubleValue: + toMap.PutDouble(k, v.DoubleValue) + case *receive_v1.SpanData_UserPropertyValue_ByteArrayValue: + toMap.PutEmptyBytes(k).FromRaw(v.ByteArrayValue) + case *receive_v1.SpanData_UserPropertyValue_FloatValue: + toMap.PutDouble(k, float64(v.FloatValue)) + case *receive_v1.SpanData_UserPropertyValue_Int8Value: + toMap.PutInt(k, int64(v.Int8Value)) + case *receive_v1.SpanData_UserPropertyValue_Int16Value: + toMap.PutInt(k, int64(v.Int16Value)) + case *receive_v1.SpanData_UserPropertyValue_Int32Value: + toMap.PutInt(k, int64(v.Int32Value)) + case *receive_v1.SpanData_UserPropertyValue_Int64Value: + toMap.PutInt(k, v.Int64Value) + case *receive_v1.SpanData_UserPropertyValue_Uint8Value: + toMap.PutInt(k, int64(v.Uint8Value)) + case *receive_v1.SpanData_UserPropertyValue_Uint16Value: + toMap.PutInt(k, int64(v.Uint16Value)) + case *receive_v1.SpanData_UserPropertyValue_Uint32Value: + toMap.PutInt(k, int64(v.Uint32Value)) + case *receive_v1.SpanData_UserPropertyValue_Uint64Value: + toMap.PutInt(k, int64(v.Uint64Value)) + case *receive_v1.SpanData_UserPropertyValue_StringValue: + toMap.PutStr(k, v.StringValue) + case *receive_v1.SpanData_UserPropertyValue_DestinationValue: + toMap.PutStr(k, v.DestinationValue) + case *receive_v1.SpanData_UserPropertyValue_CharacterValue: + toMap.PutStr(k, string(rune(v.CharacterValue))) + default: + u.logger.Warn(fmt.Sprintf("Unknown user property type: %T", v)) + u.metrics.recordRecoverableUnmarshallingError() + } +} diff --git a/receiver/solacereceiver/unmarshaller_receive_test.go b/receiver/solacereceiver/unmarshaller_receive_test.go new file mode 100644 index 0000000000000..d6bd020d7306d --- /dev/null +++ b/receiver/solacereceiver/unmarshaller_receive_test.go @@ -0,0 +1,843 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package solacereceiver + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/ptrace" + "go.uber.org/zap" + + receive_v1 "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/solacereceiver/model/receive/v1" +) + +func TestReceiveUnmarshallerMapResourceSpan(t *testing.T) { + var ( + routerName = "someRouterName" + vpnName = "someVpnName" + version = "10.0.0" + ) + tests := []struct { + name string + spanData *receive_v1.SpanData + want map[string]interface{} + expectedUnmarshallingErrors interface{} + }{ + { + name: "Maps All Fields When Present", + spanData: &receive_v1.SpanData{ + RouterName: routerName, + MessageVpnName: &vpnName, + SolosVersion: version, + }, + want: map[string]interface{}{ + "service.name": routerName, + "service.instance.id": vpnName, + "service.version": version, + }, + }, + { + name: "Does Not Map Fields When Not Present", + spanData: &receive_v1.SpanData{}, + want: map[string]interface{}{ + "service.version": "", + "service.name": "", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + u := newTestReceiveV1Unmarshaller(t) + actual := pcommon.NewMap() + u.mapResourceSpanAttributes(tt.spanData, actual) + assert.Equal(t, tt.want, actual.AsRaw()) + validateMetric(t, u.metrics.views.recoverableUnmarshallingErrors, tt.expectedUnmarshallingErrors) + }) + } +} + +// Tests the received span to traces mappings +// Includes all required opentelemetry fields such as trace ID, span ID, etc. +func TestReceiveUnmarshallerMapClientSpanData(t *testing.T) { + someTraceState := "some trace status" + tests := []struct { + name string + data *receive_v1.SpanData + want func(ptrace.Span) + }{ + // no trace state no status no parent span + { + name: "Without Optional Fields", + data: &receive_v1.SpanData{ + TraceId: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + SpanId: []byte{7, 6, 5, 4, 3, 2, 1, 0}, + StartTimeUnixNano: 1234567890, + EndTimeUnixNano: 2234567890, + }, + want: func(span ptrace.Span) { + span.SetTraceID([16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}) + span.SetSpanID([8]byte{7, 6, 5, 4, 3, 2, 1, 0}) + span.SetStartTimestamp(1234567890) + span.SetEndTimestamp(2234567890) + // expect some constants + span.SetKind(5) + span.SetName("(topic) receive") + span.Status().SetCode(ptrace.StatusCodeUnset) + }, + }, + // trace state status and parent span + { + name: "With Optional Fields", + data: &receive_v1.SpanData{ + TraceId: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + SpanId: []byte{7, 6, 5, 4, 3, 2, 1, 0}, + StartTimeUnixNano: 1234567890, + EndTimeUnixNano: 2234567890, + ParentSpanId: []byte{15, 14, 13, 12, 11, 10, 9, 8}, + TraceState: &someTraceState, + ErrorDescription: "some error", + }, + want: func(span ptrace.Span) { + span.SetTraceID([16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}) + span.SetSpanID([8]byte{7, 6, 5, 4, 3, 2, 1, 0}) + span.SetStartTimestamp(1234567890) + span.SetEndTimestamp(2234567890) + span.SetParentSpanID([8]byte{15, 14, 13, 12, 11, 10, 9, 8}) + span.TraceState().FromRaw(someTraceState) + span.Status().SetCode(ptrace.StatusCodeError) + span.Status().SetMessage("some error") + // expect some constants + span.SetKind(5) + span.SetName("(topic) receive") + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + u := newTestReceiveV1Unmarshaller(t) + actual := ptrace.NewTraces().ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty().Spans().AppendEmpty() + u.mapClientSpanData(tt.data, actual) + expected := ptrace.NewTraces().ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty().Spans().AppendEmpty() + tt.want(expected) + assert.Equal(t, expected, actual) + }) + } +} + +func TestReceiveUnmarshallerMapClientSpanAttributes(t *testing.T) { + var ( + protocolVersion = "5.0" + applicationMessageID = "someMessageID" + correlationID = "someConversationID" + replyToTopic = "someReplyToTopic" + baggageString = `someKey=someVal;someProp=someOtherThing,someOtherKey=someOtherVal;someProp=NewProp123;someOtherProp=AnotherProp192` + invalidBaggageString = `someKey"=someVal;someProp=someOtherThing` + priority = uint32(1) + ttl = int64(86000) + ) + + tests := []struct { + name string + spanData *receive_v1.SpanData + want map[string]interface{} + expectedUnmarshallingErrors interface{} + }{ + { + name: "With All Valid Attributes", + spanData: &receive_v1.SpanData{ + Protocol: "MQTT", + ProtocolVersion: &protocolVersion, + ApplicationMessageId: &applicationMessageID, + CorrelationId: &correlationID, + BinaryAttachmentSize: 1000, + XmlAttachmentSize: 200, + MetadataSize: 34, + ClientUsername: "someClientUsername", + ClientName: "someClient1234", + ReplyToTopic: &replyToTopic, + DeliveryMode: receive_v1.SpanData_PERSISTENT, + Topic: "someTopic", + ReplicationGroupMessageId: []byte{0x01, 0x00, 0x01, 0x04, 0x09, 0x10, 0x19, 0x24, 0x31, 0x40, 0x51, 0x64, 0x79, 0x90, 0xa9, 0xc4, 0xe1}, + Priority: &priority, + Ttl: &ttl, + DmqEligible: true, + DroppedEnqueueEventsSuccess: 42, + DroppedEnqueueEventsFailed: 24, + HostIp: []byte{1, 2, 3, 4}, + HostPort: 55555, + PeerIp: []byte{35, 69, 4, 37, 44, 161, 0, 0, 0, 0, 5, 103, 86, 115, 35, 181}, + PeerPort: 12345, + BrokerReceiveTimeUnixNano: 1357924680, + DroppedApplicationMessageProperties: false, + Baggage: &baggageString, + UserProperties: map[string]*receive_v1.SpanData_UserPropertyValue{ + "special_key": { + Value: &receive_v1.SpanData_UserPropertyValue_BoolValue{ + BoolValue: true, + }, + }, + }, + }, + want: map[string]interface{}{ + "messaging.system": "SolacePubSub+", + "messaging.operation": "receive", + "messaging.protocol": "MQTT", + "messaging.protocol_version": "5.0", + "messaging.message_id": "someMessageID", + "messaging.conversation_id": "someConversationID", + "messaging.message_payload_size_bytes": int64(1234), + "messaging.destination": "someTopic", + "messaging.solace.client_username": "someClientUsername", + "messaging.solace.client_name": "someClient1234", + "messaging.solace.replication_group_message_id": "rmid1:00010-40910192431-40516479-90a9c4e1", + "messaging.solace.priority": int64(1), + "messaging.solace.ttl": int64(86000), + "messaging.solace.dmq_eligible": true, + "messaging.solace.dropped_enqueue_events_success": int64(42), + "messaging.solace.dropped_enqueue_events_failed": int64(24), + "messaging.solace.reply_to_topic": "someReplyToTopic", + "messaging.solace.delivery_mode": "persistent", + "net.host.ip": "1.2.3.4", + "net.host.port": int64(55555), + "net.peer.ip": "2345:425:2ca1::567:5673:23b5", + "net.peer.port": int64(12345), + "messaging.solace.user_properties.special_key": true, + "messaging.solace.broker_receive_time_unix_nano": int64(1357924680), + "messaging.solace.dropped_application_message_properties": false, + "messaging.solace.message.baggage.someKey": "someVal", + "messaging.solace.message.baggage_metadata.someKey": "someProp=someOtherThing", + "messaging.solace.message.baggage.someOtherKey": `someOtherVal`, + "messaging.solace.message.baggage_metadata.someOtherKey": "someProp=NewProp123;someOtherProp=AnotherProp192", + }, + }, + { + name: "With Only Required Fields", + spanData: &receive_v1.SpanData{ + Protocol: "MQTT", + BinaryAttachmentSize: 1000, + XmlAttachmentSize: 200, + MetadataSize: 34, + ClientUsername: "someClientUsername", + ClientName: "someClient1234", + Topic: "someTopic", + DeliveryMode: receive_v1.SpanData_NON_PERSISTENT, + DmqEligible: true, + DroppedEnqueueEventsSuccess: 42, + DroppedEnqueueEventsFailed: 24, + HostIp: []byte{1, 2, 3, 4}, + HostPort: 55555, + PeerIp: []byte{35, 69, 4, 37, 44, 161, 0, 0, 0, 0, 5, 103, 86, 115, 35, 181}, + PeerPort: 12345, + BrokerReceiveTimeUnixNano: 1357924680, + DroppedApplicationMessageProperties: true, + UserProperties: map[string]*receive_v1.SpanData_UserPropertyValue{ + "special_key": nil, + }, + }, + want: map[string]interface{}{ + "messaging.system": "SolacePubSub+", + "messaging.operation": "receive", + "messaging.protocol": "MQTT", + "messaging.message_payload_size_bytes": int64(1234), + "messaging.destination": "someTopic", + "messaging.solace.client_username": "someClientUsername", + "messaging.solace.client_name": "someClient1234", + "messaging.solace.dmq_eligible": true, + "messaging.solace.delivery_mode": "non_persistent", + "messaging.solace.dropped_enqueue_events_success": int64(42), + "messaging.solace.dropped_enqueue_events_failed": int64(24), + "net.host.ip": "1.2.3.4", + "net.host.port": int64(55555), + "net.peer.ip": "2345:425:2ca1::567:5673:23b5", + "net.peer.port": int64(12345), + "messaging.solace.broker_receive_time_unix_nano": int64(1357924680), + "messaging.solace.dropped_application_message_properties": true, + }, + }, + { + name: "With Some Invalid Fields", + spanData: &receive_v1.SpanData{ + Protocol: "MQTT", + BinaryAttachmentSize: 1000, + XmlAttachmentSize: 200, + MetadataSize: 34, + ClientUsername: "someClientUsername", + ClientName: "someClient1234", + Topic: "someTopic", + DeliveryMode: receive_v1.SpanData_DeliveryMode(1000), + DmqEligible: true, + DroppedEnqueueEventsSuccess: 42, + DroppedEnqueueEventsFailed: 24, + HostPort: 55555, + PeerPort: 12345, + BrokerReceiveTimeUnixNano: 1357924680, + DroppedApplicationMessageProperties: true, + Baggage: &invalidBaggageString, + UserProperties: map[string]*receive_v1.SpanData_UserPropertyValue{ + "special_key": nil, + }, + }, + // we no longer expect the port when the IP is not present + want: map[string]interface{}{ + "messaging.system": "SolacePubSub+", + "messaging.operation": "receive", + "messaging.protocol": "MQTT", + "messaging.message_payload_size_bytes": int64(1234), + "messaging.destination": "someTopic", + "messaging.solace.client_username": "someClientUsername", + "messaging.solace.client_name": "someClient1234", + "messaging.solace.dmq_eligible": true, + "messaging.solace.delivery_mode": "Unknown Delivery Mode (1000)", + "messaging.solace.dropped_enqueue_events_success": int64(42), + "messaging.solace.dropped_enqueue_events_failed": int64(24), + "messaging.solace.broker_receive_time_unix_nano": int64(1357924680), + "messaging.solace.dropped_application_message_properties": true, + }, + // Invalid delivery mode, missing IPs, invalid baggage string + expectedUnmarshallingErrors: 2, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + u := newTestReceiveV1Unmarshaller(t) + actual := pcommon.NewMap() + u.mapClientSpanAttributes(tt.spanData, actual) + assert.Equal(t, tt.want, actual.AsRaw()) + validateMetric(t, u.metrics.views.recoverableUnmarshallingErrors, tt.expectedUnmarshallingErrors) + }) + } +} + +// Validate that all event types are properly handled and appended into the span data +func TestReceiveUnmarshallerEvents(t *testing.T) { + someErrorString := "some error" + somePartitionNumber := uint32(345) + tests := []struct { + name string + spanData *receive_v1.SpanData + populateExpectedSpan func(span ptrace.Span) + unmarshallingErrors interface{} + }{ + { // don't expect any events when none are present in the span data + name: "No Events", + spanData: &receive_v1.SpanData{}, + populateExpectedSpan: func(span ptrace.Span) {}, + }, + { // when an enqueue event is present, expect it to be added to the span events + name: "Enqueue Event Queue", + spanData: &receive_v1.SpanData{ + EnqueueEvents: []*receive_v1.SpanData_EnqueueEvent{ + { + Dest: &receive_v1.SpanData_EnqueueEvent_QueueName{QueueName: "somequeue"}, + TimeUnixNano: 123456789, + PartitionNumber: &somePartitionNumber, + }, + }, + }, + populateExpectedSpan: func(span ptrace.Span) { + populateEvent(t, span, "somequeue enqueue", 123456789, map[string]interface{}{ + "messaging.solace.destination_type": "queue", + "messaging.solace.rejects_all_enqueues": false, + "messaging.solace.partition_number": 345, + }) + }, + }, + { // when a topic endpoint enqueue event is present, expect it to be added to the span events + name: "Enqueue Event Topic Endpoint", + spanData: &receive_v1.SpanData{ + EnqueueEvents: []*receive_v1.SpanData_EnqueueEvent{ + { + Dest: &receive_v1.SpanData_EnqueueEvent_TopicEndpointName{TopicEndpointName: "sometopic"}, + TimeUnixNano: 123456789, + ErrorDescription: &someErrorString, + RejectsAllEnqueues: true, + }, + }, + }, + populateExpectedSpan: func(span ptrace.Span) { + populateEvent(t, span, "sometopic enqueue", 123456789, map[string]interface{}{ + "messaging.solace.destination_type": "topic-endpoint", + "messaging.solace.enqueue_error_message": someErrorString, + "messaging.solace.rejects_all_enqueues": true, + }) + }, + }, + { // when a both a queue and topic endpoint enqueue event is present, expect it to be added to the span events + name: "Enqueue Event Queue and Topic Endpoint", + spanData: &receive_v1.SpanData{ + EnqueueEvents: []*receive_v1.SpanData_EnqueueEvent{ + { + Dest: &receive_v1.SpanData_EnqueueEvent_QueueName{QueueName: "somequeue"}, + TimeUnixNano: 123456789, + }, + { + Dest: &receive_v1.SpanData_EnqueueEvent_TopicEndpointName{TopicEndpointName: "sometopic"}, + TimeUnixNano: 2345678, + }, + }, + }, + populateExpectedSpan: func(span ptrace.Span) { + populateEvent(t, span, "somequeue enqueue", 123456789, map[string]interface{}{ + "messaging.solace.destination_type": "queue", + "messaging.solace.rejects_all_enqueues": false, + }) + populateEvent(t, span, "sometopic enqueue", 2345678, map[string]interface{}{ + "messaging.solace.destination_type": "topic-endpoint", + "messaging.solace.rejects_all_enqueues": false, + }) + }, + }, + { // when an enqueue event does not have a valid dest (ie. nil) + name: "Enqueue Event no Dest", + spanData: &receive_v1.SpanData{ + EnqueueEvents: []*receive_v1.SpanData_EnqueueEvent{ + { + Dest: nil, + TimeUnixNano: 123456789, + }, + }, + }, + populateExpectedSpan: func(span ptrace.Span) {}, + unmarshallingErrors: 1, + }, + { // Local Transaction + name: "Local Transaction Event", + spanData: &receive_v1.SpanData{ + TransactionEvent: &receive_v1.SpanData_TransactionEvent{ + TimeUnixNano: 123456789, + Type: receive_v1.SpanData_TransactionEvent_COMMIT, + Initiator: receive_v1.SpanData_TransactionEvent_CLIENT, + TransactionId: &receive_v1.SpanData_TransactionEvent_LocalId{ + LocalId: &receive_v1.SpanData_TransactionEvent_LocalTransactionId{ + TransactionId: 12345, + SessionId: 67890, + SessionName: "my-session-name", + }, + }, + }, + }, + populateExpectedSpan: func(span ptrace.Span) { + populateEvent(t, span, "commit", 123456789, map[string]interface{}{ + "messaging.solace.transaction_initiator": "client", + "messaging.solace.transaction_id": 12345, + "messaging.solace.transacted_session_name": "my-session-name", + "messaging.solace.transacted_session_id": 67890, + }) + }, + }, + { // XA transaction + name: "XA Transaction Event", + spanData: &receive_v1.SpanData{ + TransactionEvent: &receive_v1.SpanData_TransactionEvent{ + TimeUnixNano: 123456789, + Type: receive_v1.SpanData_TransactionEvent_END, + Initiator: receive_v1.SpanData_TransactionEvent_ADMIN, + TransactionId: &receive_v1.SpanData_TransactionEvent_Xid_{ + Xid: &receive_v1.SpanData_TransactionEvent_Xid{ + FormatId: 123, + BranchQualifier: []byte{0, 8, 20, 254}, + GlobalId: []byte{128, 64, 32, 16, 8, 4, 2, 1, 0}, + }, + }, + }, + }, + populateExpectedSpan: func(span ptrace.Span) { + populateEvent(t, span, "end", 123456789, map[string]interface{}{ + "messaging.solace.transaction_initiator": "administrator", + "messaging.solace.transaction_xid": "0000007b-000814fe-804020100804020100", + }) + }, + }, + { // XA Transaction with no branch qualifier or global ID and with an error + name: "XA Transaction Event with nil fields and error", + spanData: &receive_v1.SpanData{ + TransactionEvent: &receive_v1.SpanData_TransactionEvent{ + TimeUnixNano: 123456789, + Type: receive_v1.SpanData_TransactionEvent_PREPARE, + Initiator: receive_v1.SpanData_TransactionEvent_BROKER, + TransactionId: &receive_v1.SpanData_TransactionEvent_Xid_{ + Xid: &receive_v1.SpanData_TransactionEvent_Xid{ + FormatId: 123, + BranchQualifier: nil, + GlobalId: nil, + }, + }, + ErrorDescription: &someErrorString, + }, + }, + populateExpectedSpan: func(span ptrace.Span) { + populateEvent(t, span, "prepare", 123456789, map[string]interface{}{ + "messaging.solace.transaction_initiator": "broker", + "messaging.solace.transaction_xid": "0000007b--", + "messaging.solace.transaction_error_message": someErrorString, + }) + }, + }, + { // Type of transaction not handled + name: "Unknown Transaction Type and no ID", + spanData: &receive_v1.SpanData{ + TransactionEvent: &receive_v1.SpanData_TransactionEvent{ + TimeUnixNano: 123456789, + Type: receive_v1.SpanData_TransactionEvent_Type(12345), + }, + }, + populateExpectedSpan: func(span ptrace.Span) { + populateEvent(t, span, "Unknown Transaction Event (12345)", 123456789, map[string]interface{}{ + "messaging.solace.transaction_initiator": "client", + }) + }, + unmarshallingErrors: 2, + }, + { // Type of ID not handled, type of initiator not handled + name: "Unknown Transaction Initiator and no ID", + spanData: &receive_v1.SpanData{ + TransactionEvent: &receive_v1.SpanData_TransactionEvent{ + TimeUnixNano: 123456789, + Type: receive_v1.SpanData_TransactionEvent_ROLLBACK, + Initiator: receive_v1.SpanData_TransactionEvent_Initiator(12345), + TransactionId: nil, + }, + }, + populateExpectedSpan: func(span ptrace.Span) { + populateEvent(t, span, "rollback", 123456789, map[string]interface{}{ + "messaging.solace.transaction_initiator": "Unknown Transaction Initiator (12345)", + }) + }, + unmarshallingErrors: 2, + }, + { // when a both a queue and topic endpoint enqueue event is present, expect it to be added to the span events + name: "Multiple Events", + spanData: &receive_v1.SpanData{ + EnqueueEvents: []*receive_v1.SpanData_EnqueueEvent{ + { + Dest: &receive_v1.SpanData_EnqueueEvent_QueueName{QueueName: "somequeue"}, + TimeUnixNano: 123456789, + }, + { + Dest: &receive_v1.SpanData_EnqueueEvent_TopicEndpointName{TopicEndpointName: "sometopic"}, + TimeUnixNano: 2345678, + RejectsAllEnqueues: true, + }, + }, + TransactionEvent: &receive_v1.SpanData_TransactionEvent{ + TimeUnixNano: 123456789, + Type: receive_v1.SpanData_TransactionEvent_ROLLBACK_ONLY, + Initiator: receive_v1.SpanData_TransactionEvent_CLIENT, + TransactionId: &receive_v1.SpanData_TransactionEvent_LocalId{ + LocalId: &receive_v1.SpanData_TransactionEvent_LocalTransactionId{ + TransactionId: 12345, + SessionId: 67890, + SessionName: "my-session-name", + }, + }, + }, + }, + populateExpectedSpan: func(span ptrace.Span) { + populateEvent(t, span, "somequeue enqueue", 123456789, map[string]interface{}{ + "messaging.solace.destination_type": "queue", + "messaging.solace.rejects_all_enqueues": false, + }) + populateEvent(t, span, "sometopic enqueue", 2345678, map[string]interface{}{ + "messaging.solace.destination_type": "topic-endpoint", + "messaging.solace.rejects_all_enqueues": true, + }) + populateEvent(t, span, "rollback_only", 123456789, map[string]interface{}{ + "messaging.solace.transaction_initiator": "client", + "messaging.solace.transaction_id": 12345, + "messaging.solace.transacted_session_name": "my-session-name", + "messaging.solace.transacted_session_id": 67890, + }) + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + u := newTestReceiveV1Unmarshaller(t) + expected := ptrace.NewTraces().ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty().Spans().AppendEmpty() + tt.populateExpectedSpan(expected) + actual := ptrace.NewTraces().ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty().Spans().AppendEmpty() + u.mapEvents(tt.spanData, actual) + // order is nondeterministic for attributes, so we must sort to get a valid comparison + compareSpans(t, expected, actual) + validateMetric(t, u.metrics.views.recoverableUnmarshallingErrors, tt.unmarshallingErrors) + }) + } +} + +func TestReceiveUnmarshallerRGMID(t *testing.T) { + tests := []struct { + name string + in []byte + expected string + numErr interface{} + }{ + { + name: "Valid RGMID", + in: []byte{0x01, 0x00, 0x01, 0x04, 0x09, 0x10, 0x19, 0x24, 0x31, 0x40, 0x51, 0x64, 0x79, 0x90, 0xa9, 0xc4, 0xe1}, + expected: "rmid1:00010-40910192431-40516479-90a9c4e1", + }, + { + name: "Bad RGMID Version", + in: []byte{0x02, 0x00, 0x01, 0x04, 0x09, 0x10, 0x19, 0x24, 0x31, 0x40, 0x51, 0x64, 0x79, 0x90, 0xa9, 0xc4, 0xe1}, + expected: "0200010409101924314051647990a9c4e1", // expect default behavior of hex dump + numErr: 1, + }, + { + name: "Bad RGMID length", + in: []byte{0x00, 0x01, 0x04, 0x09, 0x10, 0x19, 0x24, 0x31, 0x40, 0x51, 0x64, 0x79, 0x90, 0xa9, 0xc4, 0xe1}, + expected: "00010409101924314051647990a9c4e1", // expect default behavior of hex dump + numErr: 1, + }, + { + name: "Nil RGMID", + in: nil, + expected: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + u := newTestReceiveV1Unmarshaller(t) + actual := u.rgmidToString(tt.in) + assert.Equal(t, tt.expected, actual) + validateMetric(t, u.metrics.views.recoverableUnmarshallingErrors, tt.numErr) + }) + } +} + +func TestReceiveUnmarshallerReceiveBaggageString(t *testing.T) { + testCases := []struct { + name string + baggage string + expected func(pcommon.Map) + errStr string + }{ + { + name: "Valid baggage", + baggage: `someKey=someVal`, + expected: func(m pcommon.Map) { + assert.NoError(t, m.FromRaw(map[string]interface{}{ + "messaging.solace.message.baggage.someKey": "someVal", + })) + }, + }, + { + name: "Valid baggage with properties", + baggage: `someKey=someVal;someProp=someOtherThing,someOtherKey=someOtherVal;someProp=NewProp123;someOtherProp=AnotherProp192`, + expected: func(m pcommon.Map) { + assert.NoError(t, m.FromRaw(map[string]interface{}{ + "messaging.solace.message.baggage.someKey": "someVal", + "messaging.solace.message.baggage_metadata.someKey": "someProp=someOtherThing", + "messaging.solace.message.baggage.someOtherKey": `someOtherVal`, + "messaging.solace.message.baggage_metadata.someOtherKey": "someProp=NewProp123;someOtherProp=AnotherProp192", + })) + }, + }, + { + name: "Invalid baggage", + baggage: `someKey"=someVal;someProp=someOtherThing`, + errStr: "invalid key", + }, + } + for _, testCase := range testCases { + t.Run(fmt.Sprintf("%T", testCase.name), func(t *testing.T) { + actual := pcommon.NewMap() + u := newTestReceiveV1Unmarshaller(t) + err := u.unmarshalBaggage(actual, testCase.baggage) + if testCase.errStr == "" { + assert.Nil(t, err) + } else { + assert.ErrorContains(t, err, testCase.errStr) + } + if testCase.expected != nil { + expected := pcommon.NewMap() + testCase.expected(expected) + assert.Equal(t, expected.AsRaw(), actual.AsRaw()) + } else { + // assert we didn't add anything if we don't have a result map + assert.Equal(t, 0, actual.Len()) + } + }) + } +} + +func TestReceiveUnmarshallerInsertUserProperty(t *testing.T) { + emojiVal := 0xf09f92a9 + testCases := []struct { + data interface{} + expectedType pcommon.ValueType + validate func(val pcommon.Value) + }{ + { + &receive_v1.SpanData_UserPropertyValue_NullValue{}, + pcommon.ValueTypeEmpty, + nil, + }, + { + &receive_v1.SpanData_UserPropertyValue_BoolValue{BoolValue: true}, + pcommon.ValueTypeBool, + func(val pcommon.Value) { + assert.Equal(t, true, val.Bool()) + }, + }, + { + &receive_v1.SpanData_UserPropertyValue_DoubleValue{DoubleValue: 12.34}, + pcommon.ValueTypeDouble, + func(val pcommon.Value) { + assert.Equal(t, float64(12.34), val.Double()) + }, + }, + { + &receive_v1.SpanData_UserPropertyValue_ByteArrayValue{ByteArrayValue: []byte{1, 2, 3, 4}}, + pcommon.ValueTypeBytes, + func(val pcommon.Value) { + assert.Equal(t, []byte{1, 2, 3, 4}, val.Bytes().AsRaw()) + }, + }, + { + &receive_v1.SpanData_UserPropertyValue_FloatValue{FloatValue: 12.34}, + pcommon.ValueTypeDouble, + func(val pcommon.Value) { + assert.Equal(t, float64(float32(12.34)), val.Double()) + }, + }, + { + &receive_v1.SpanData_UserPropertyValue_Int8Value{Int8Value: 8}, + pcommon.ValueTypeInt, + func(val pcommon.Value) { + assert.Equal(t, int64(8), val.Int()) + }, + }, + { + &receive_v1.SpanData_UserPropertyValue_Int16Value{Int16Value: 16}, + pcommon.ValueTypeInt, + func(val pcommon.Value) { + assert.Equal(t, int64(16), val.Int()) + }, + }, + { + &receive_v1.SpanData_UserPropertyValue_Int32Value{Int32Value: 32}, + pcommon.ValueTypeInt, + func(val pcommon.Value) { + assert.Equal(t, int64(32), val.Int()) + }, + }, + { + &receive_v1.SpanData_UserPropertyValue_Int64Value{Int64Value: 64}, + pcommon.ValueTypeInt, + func(val pcommon.Value) { + assert.Equal(t, int64(64), val.Int()) + }, + }, + { + &receive_v1.SpanData_UserPropertyValue_Uint8Value{Uint8Value: 8}, + pcommon.ValueTypeInt, + func(val pcommon.Value) { + assert.Equal(t, int64(8), val.Int()) + }, + }, + { + &receive_v1.SpanData_UserPropertyValue_Uint16Value{Uint16Value: 16}, + pcommon.ValueTypeInt, + func(val pcommon.Value) { + assert.Equal(t, int64(16), val.Int()) + }, + }, + { + &receive_v1.SpanData_UserPropertyValue_Uint32Value{Uint32Value: 32}, + pcommon.ValueTypeInt, + func(val pcommon.Value) { + assert.Equal(t, int64(32), val.Int()) + }, + }, + { + &receive_v1.SpanData_UserPropertyValue_Uint64Value{Uint64Value: 64}, + pcommon.ValueTypeInt, + func(val pcommon.Value) { + assert.Equal(t, int64(64), val.Int()) + }, + }, + { + &receive_v1.SpanData_UserPropertyValue_StringValue{StringValue: "hello world"}, + pcommon.ValueTypeStr, + func(val pcommon.Value) { + assert.Equal(t, "hello world", val.Str()) + }, + }, + { + &receive_v1.SpanData_UserPropertyValue_DestinationValue{DestinationValue: "some_dest"}, + pcommon.ValueTypeStr, + func(val pcommon.Value) { + assert.Equal(t, "some_dest", val.Str()) + }, + }, + { + &receive_v1.SpanData_UserPropertyValue_CharacterValue{CharacterValue: 0x61}, + pcommon.ValueTypeStr, + func(val pcommon.Value) { + assert.Equal(t, "a", val.Str()) + }, + }, + { + &receive_v1.SpanData_UserPropertyValue_CharacterValue{CharacterValue: 0xe68080}, + pcommon.ValueTypeStr, + func(val pcommon.Value) { + assert.Equal(t, string(rune(0xe68080)), val.Str()) + }, + }, + { + &receive_v1.SpanData_UserPropertyValue_CharacterValue{CharacterValue: 0xf09f92a9}, + pcommon.ValueTypeStr, + func(val pcommon.Value) { + assert.Equal(t, string(rune(emojiVal)), val.Str()) + }, + }, + } + + unmarshaller := &brokerTraceReceiveUnmarshallerV1{ + logger: zap.NewNop(), + } + for _, testCase := range testCases { + t.Run(fmt.Sprintf("%T", testCase.data), func(t *testing.T) { + const key = "some-property" + attributeMap := pcommon.NewMap() + unmarshaller.insertUserProperty(attributeMap, key, testCase.data) + actual, ok := attributeMap.Get("messaging.solace.user_properties." + key) + require.True(t, ok) + assert.Equal(t, testCase.expectedType, actual.Type()) + if testCase.validate != nil { + testCase.validate(actual) + } + }) + } +} + +func TestSolaceMessageReceiveUnmarshallerV1InsertUserPropertyUnsupportedType(t *testing.T) { + u := newTestReceiveV1Unmarshaller(t) + const key = "some-property" + attributeMap := pcommon.NewMap() + u.insertUserProperty(attributeMap, key, "invalid data type") + _, ok := attributeMap.Get("messaging.solace.user_properties." + key) + assert.False(t, ok) + validateMetric(t, u.metrics.views.recoverableUnmarshallingErrors, 1) +} + +func newTestReceiveV1Unmarshaller(t *testing.T) *brokerTraceReceiveUnmarshallerV1 { + m := newTestMetrics(t) + return &brokerTraceReceiveUnmarshallerV1{zap.NewNop(), m} +} diff --git a/receiver/solacereceiver/unmarshaller_test.go b/receiver/solacereceiver/unmarshaller_test.go index f45ae924c010b..87a8f342a2746 100644 --- a/receiver/solacereceiver/unmarshaller_test.go +++ b/receiver/solacereceiver/unmarshaller_test.go @@ -15,9 +15,7 @@ package solacereceiver import ( - "encoding/hex" "errors" - "fmt" "testing" "github.com/Azure/go-amqp" @@ -32,27 +30,10 @@ import ( receive_v1 "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/solacereceiver/model/receive/v1" ) -func TestPrintPayload(t *testing.T) { - data := &egress_v1.SpanData{} - vpnName := "default" - data.MessageVpnName = &vpnName - data.RouterName = "vmr-133-53" - // data.EgressSpans = []*egress_v1.SpanData_EgressSpan{ - // { - // TraceId: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2}, - // SpanId: []byte{1, 2, 3, 4, 5, 6, 7, 8}, - // ParentSpanId: []byte{1, 2, 3, 4, 5, 6, 7, 8}, - // TypeData: &egress_v1.SpanData_EgressSpan_SendSpan{}, - // }, - // } - bytes, err := proto.Marshal(data) - assert.NoError(t, err) - fmt.Println(hex.Dump(bytes)) -} - // Validate entire unmarshal flow func TestSolaceMessageUnmarshallerUnmarshal(t *testing.T) { validReceiveTopicVersion := "_telemetry/broker/trace/receive/v1" + validEgressTopicVersion := "_telemetry/broker/trace/egress/v1" invalidReceiveTopicVersion := "_telemetry/broker/trace/receive/v2" invalidTelemetryTopic := "_telemetry/broker/trace/somethingNew" invalidTopicString := "some unknown topic string that won't be valid" @@ -107,7 +88,7 @@ func TestSolaceMessageUnmarshallerUnmarshal(t *testing.T) { err: errUnknownTopic, }, { - name: "Empty Message Data", + name: "Empty Message Data with Receive topic", message: &amqp.Message{ Data: [][]byte{{}}, Properties: &amqp.MessageProperties{ @@ -117,7 +98,7 @@ func TestSolaceMessageUnmarshallerUnmarshal(t *testing.T) { err: errEmptyPayload, }, { - name: "Invalid Message Data", + name: "Invalid Message Data with Receive topic", message: &amqp.Message{ Data: [][]byte{{1, 2, 3, 4, 5}}, Properties: &amqp.MessageProperties{ @@ -127,7 +108,27 @@ func TestSolaceMessageUnmarshallerUnmarshal(t *testing.T) { err: errors.New("cannot parse invalid wire-format data"), }, { - name: "Valid Message Data", + name: "Empty Message Data with Egress topic", + message: &amqp.Message{ + Data: [][]byte{{}}, + Properties: &amqp.MessageProperties{ + To: &validEgressTopicVersion, + }, + }, + err: errEmptyPayload, + }, + { + name: "Invalid Message Data with Egress topic", + message: &amqp.Message{ + Data: [][]byte{{1, 2, 3, 4, 5}}, + Properties: &amqp.MessageProperties{ + To: &validEgressTopicVersion, + }, + }, + err: errors.New("cannot parse invalid wire-format data"), + }, + { + name: "Valid Receive Message Data", message: &amqp.Message{ Data: [][]byte{func() []byte { // TODO capture binary data of this directly, ie. real world data. @@ -274,6 +275,54 @@ func TestSolaceMessageUnmarshallerUnmarshal(t *testing.T) { return &traces }(), }, + { + name: "Valid Egress Message Data", + message: &amqp.Message{ + Data: [][]byte{func() []byte { + // TODO capture binary data of this directly, ie. real world data. + var ( + routerName = "someRouterName" + vpnName = "someVpnName" + ) + validData, err := proto.Marshal(&egress_v1.SpanData{ + RouterName: routerName, + MessageVpnName: &vpnName, + SolosVersion: "10.0.0", + EgressSpans: func() []*egress_v1.SpanData_EgressSpan { + spans := make([]*egress_v1.SpanData_EgressSpan, len(validEgressSpans)) + i := 0 + for spanRef := range validEgressSpans { + span := spanRef + spans[i] = span + i++ + } + return spans + }(), + }) + require.NoError(t, err) + return validData + }()}, + Properties: &amqp.MessageProperties{ + To: &validEgressTopicVersion, + }, + }, + want: func() *ptrace.Traces { + traces := ptrace.NewTraces() + resource := traces.ResourceSpans().AppendEmpty() + populateAttributes(t, resource.Resource().Attributes(), map[string]interface{}{ + "service.name": "someRouterName", + "service.instance.id": "someVpnName", + "service.version": "10.0.0", + }) + instrumentation := resource.ScopeSpans().AppendEmpty() + // first send span + for _, span := range validEgressSpans { + newSpan := instrumentation.Spans().AppendEmpty() + span.CopyTo(newSpan) + } + return &traces + }(), + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -296,10 +345,12 @@ func TestSolaceMessageUnmarshallerUnmarshal(t *testing.T) { expectedInstrumentation := expectedResource.ScopeSpans().At(0) instrumentation := resource.ScopeSpans().At(0) assert.Equal(t, expectedInstrumentation.Scope(), instrumentation.Scope()) - require.Equal(t, 1, instrumentation.Spans().Len()) - expectedSpan := expectedInstrumentation.Spans().At(0) - span := instrumentation.Spans().At(0) - compareSpans(t, expectedSpan, span) + require.Equal(t, expectedInstrumentation.Spans().Len(), instrumentation.Spans().Len()) + for i := 0; i < expectedInstrumentation.Spans().Len(); i++ { + expectedSpan := expectedInstrumentation.Spans().At(i) + span := instrumentation.Spans().At(i) + compareSpans(t, expectedSpan, span) + } } else { assert.Equal(t, ptrace.Traces{}, traces) } @@ -307,558 +358,7 @@ func TestSolaceMessageUnmarshallerUnmarshal(t *testing.T) { } } -func TestUnmarshallerMapResourceSpan(t *testing.T) { - var ( - routerName = "someRouterName" - vpnName = "someVpnName" - version = "10.0.0" - ) - tests := []struct { - name string - spanData *receive_v1.SpanData - want map[string]interface{} - expectedUnmarshallingErrors interface{} - }{ - { - name: "Maps All Fields When Present", - spanData: &receive_v1.SpanData{ - RouterName: routerName, - MessageVpnName: &vpnName, - SolosVersion: version, - }, - want: map[string]interface{}{ - "service.name": routerName, - "service.instance.id": vpnName, - "service.version": version, - }, - }, - { - name: "Does Not Map Fields When Not Present", - spanData: &receive_v1.SpanData{}, - want: map[string]interface{}{ - "service.version": "", - "service.name": "", - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - u := newTestV1Unmarshaller(t) - actual := pcommon.NewMap() - u.mapResourceSpanAttributes(tt.spanData, actual) - assert.Equal(t, tt.want, actual.AsRaw()) - validateMetric(t, u.metrics.views.recoverableUnmarshallingErrors, tt.expectedUnmarshallingErrors) - }) - } -} - -// Tests the received span to traces mappings -// Includes all required opentelemetry fields such as trace ID, span ID, etc. -func TestUnmarshallerMapClientSpanData(t *testing.T) { - someTraceState := "some trace status" - tests := []struct { - name string - data *receive_v1.SpanData - want func(ptrace.Span) - }{ - // no trace state no status no parent span - { - name: "Without Optional Fields", - data: &receive_v1.SpanData{ - TraceId: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - SpanId: []byte{7, 6, 5, 4, 3, 2, 1, 0}, - StartTimeUnixNano: 1234567890, - EndTimeUnixNano: 2234567890, - }, - want: func(span ptrace.Span) { - span.SetTraceID([16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}) - span.SetSpanID([8]byte{7, 6, 5, 4, 3, 2, 1, 0}) - span.SetStartTimestamp(1234567890) - span.SetEndTimestamp(2234567890) - // expect some constants - span.SetKind(5) - span.SetName("(topic) receive") - span.Status().SetCode(ptrace.StatusCodeUnset) - }, - }, - // trace state status and parent span - { - name: "With Optional Fields", - data: &receive_v1.SpanData{ - TraceId: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - SpanId: []byte{7, 6, 5, 4, 3, 2, 1, 0}, - StartTimeUnixNano: 1234567890, - EndTimeUnixNano: 2234567890, - ParentSpanId: []byte{15, 14, 13, 12, 11, 10, 9, 8}, - TraceState: &someTraceState, - ErrorDescription: "some error", - }, - want: func(span ptrace.Span) { - span.SetTraceID([16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}) - span.SetSpanID([8]byte{7, 6, 5, 4, 3, 2, 1, 0}) - span.SetStartTimestamp(1234567890) - span.SetEndTimestamp(2234567890) - span.SetParentSpanID([8]byte{15, 14, 13, 12, 11, 10, 9, 8}) - span.TraceState().FromRaw(someTraceState) - span.Status().SetCode(ptrace.StatusCodeError) - span.Status().SetMessage("some error") - // expect some constants - span.SetKind(5) - span.SetName("(topic) receive") - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - u := newTestV1Unmarshaller(t) - actual := ptrace.NewTraces().ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty().Spans().AppendEmpty() - u.mapClientSpanData(tt.data, actual) - expected := ptrace.NewTraces().ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty().Spans().AppendEmpty() - tt.want(expected) - assert.Equal(t, expected, actual) - }) - } -} - -func TestUnmarshallerMapClientSpanAttributes(t *testing.T) { - var ( - protocolVersion = "5.0" - applicationMessageID = "someMessageID" - correlationID = "someConversationID" - replyToTopic = "someReplyToTopic" - baggageString = `someKey=someVal;someProp=someOtherThing,someOtherKey=someOtherVal;someProp=NewProp123;someOtherProp=AnotherProp192` - invalidBaggageString = `someKey"=someVal;someProp=someOtherThing` - priority = uint32(1) - ttl = int64(86000) - ) - - tests := []struct { - name string - spanData *receive_v1.SpanData - want map[string]interface{} - expectedUnmarshallingErrors interface{} - }{ - { - name: "With All Valid Attributes", - spanData: &receive_v1.SpanData{ - Protocol: "MQTT", - ProtocolVersion: &protocolVersion, - ApplicationMessageId: &applicationMessageID, - CorrelationId: &correlationID, - BinaryAttachmentSize: 1000, - XmlAttachmentSize: 200, - MetadataSize: 34, - ClientUsername: "someClientUsername", - ClientName: "someClient1234", - ReplyToTopic: &replyToTopic, - DeliveryMode: receive_v1.SpanData_PERSISTENT, - Topic: "someTopic", - ReplicationGroupMessageId: []byte{0x01, 0x00, 0x01, 0x04, 0x09, 0x10, 0x19, 0x24, 0x31, 0x40, 0x51, 0x64, 0x79, 0x90, 0xa9, 0xc4, 0xe1}, - Priority: &priority, - Ttl: &ttl, - DmqEligible: true, - DroppedEnqueueEventsSuccess: 42, - DroppedEnqueueEventsFailed: 24, - HostIp: []byte{1, 2, 3, 4}, - HostPort: 55555, - PeerIp: []byte{35, 69, 4, 37, 44, 161, 0, 0, 0, 0, 5, 103, 86, 115, 35, 181}, - PeerPort: 12345, - BrokerReceiveTimeUnixNano: 1357924680, - DroppedApplicationMessageProperties: false, - Baggage: &baggageString, - UserProperties: map[string]*receive_v1.SpanData_UserPropertyValue{ - "special_key": { - Value: &receive_v1.SpanData_UserPropertyValue_BoolValue{ - BoolValue: true, - }, - }, - }, - }, - want: map[string]interface{}{ - "messaging.system": "SolacePubSub+", - "messaging.operation": "receive", - "messaging.protocol": "MQTT", - "messaging.protocol_version": "5.0", - "messaging.message_id": "someMessageID", - "messaging.conversation_id": "someConversationID", - "messaging.message_payload_size_bytes": int64(1234), - "messaging.destination": "someTopic", - "messaging.solace.client_username": "someClientUsername", - "messaging.solace.client_name": "someClient1234", - "messaging.solace.replication_group_message_id": "rmid1:00010-40910192431-40516479-90a9c4e1", - "messaging.solace.priority": int64(1), - "messaging.solace.ttl": int64(86000), - "messaging.solace.dmq_eligible": true, - "messaging.solace.dropped_enqueue_events_success": int64(42), - "messaging.solace.dropped_enqueue_events_failed": int64(24), - "messaging.solace.reply_to_topic": "someReplyToTopic", - "messaging.solace.delivery_mode": "persistent", - "net.host.ip": "1.2.3.4", - "net.host.port": int64(55555), - "net.peer.ip": "2345:425:2ca1::567:5673:23b5", - "net.peer.port": int64(12345), - "messaging.solace.user_properties.special_key": true, - "messaging.solace.broker_receive_time_unix_nano": int64(1357924680), - "messaging.solace.dropped_application_message_properties": false, - "messaging.solace.message.baggage.someKey": "someVal", - "messaging.solace.message.baggage_metadata.someKey": "someProp=someOtherThing", - "messaging.solace.message.baggage.someOtherKey": `someOtherVal`, - "messaging.solace.message.baggage_metadata.someOtherKey": "someProp=NewProp123;someOtherProp=AnotherProp192", - }, - }, - { - name: "With Only Required Fields", - spanData: &receive_v1.SpanData{ - Protocol: "MQTT", - BinaryAttachmentSize: 1000, - XmlAttachmentSize: 200, - MetadataSize: 34, - ClientUsername: "someClientUsername", - ClientName: "someClient1234", - Topic: "someTopic", - DeliveryMode: receive_v1.SpanData_NON_PERSISTENT, - DmqEligible: true, - DroppedEnqueueEventsSuccess: 42, - DroppedEnqueueEventsFailed: 24, - HostIp: []byte{1, 2, 3, 4}, - HostPort: 55555, - PeerIp: []byte{35, 69, 4, 37, 44, 161, 0, 0, 0, 0, 5, 103, 86, 115, 35, 181}, - PeerPort: 12345, - BrokerReceiveTimeUnixNano: 1357924680, - DroppedApplicationMessageProperties: true, - UserProperties: map[string]*receive_v1.SpanData_UserPropertyValue{ - "special_key": nil, - }, - }, - want: map[string]interface{}{ - "messaging.system": "SolacePubSub+", - "messaging.operation": "receive", - "messaging.protocol": "MQTT", - "messaging.message_payload_size_bytes": int64(1234), - "messaging.destination": "someTopic", - "messaging.solace.client_username": "someClientUsername", - "messaging.solace.client_name": "someClient1234", - "messaging.solace.dmq_eligible": true, - "messaging.solace.delivery_mode": "non_persistent", - "messaging.solace.dropped_enqueue_events_success": int64(42), - "messaging.solace.dropped_enqueue_events_failed": int64(24), - "net.host.ip": "1.2.3.4", - "net.host.port": int64(55555), - "net.peer.ip": "2345:425:2ca1::567:5673:23b5", - "net.peer.port": int64(12345), - "messaging.solace.broker_receive_time_unix_nano": int64(1357924680), - "messaging.solace.dropped_application_message_properties": true, - }, - }, - { - name: "With Some Invalid Fields", - spanData: &receive_v1.SpanData{ - Protocol: "MQTT", - BinaryAttachmentSize: 1000, - XmlAttachmentSize: 200, - MetadataSize: 34, - ClientUsername: "someClientUsername", - ClientName: "someClient1234", - Topic: "someTopic", - DeliveryMode: receive_v1.SpanData_DeliveryMode(1000), - DmqEligible: true, - DroppedEnqueueEventsSuccess: 42, - DroppedEnqueueEventsFailed: 24, - HostPort: 55555, - PeerPort: 12345, - BrokerReceiveTimeUnixNano: 1357924680, - DroppedApplicationMessageProperties: true, - Baggage: &invalidBaggageString, - UserProperties: map[string]*receive_v1.SpanData_UserPropertyValue{ - "special_key": nil, - }, - }, - // we no longer expect the port when the IP is not present - want: map[string]interface{}{ - "messaging.system": "SolacePubSub+", - "messaging.operation": "receive", - "messaging.protocol": "MQTT", - "messaging.message_payload_size_bytes": int64(1234), - "messaging.destination": "someTopic", - "messaging.solace.client_username": "someClientUsername", - "messaging.solace.client_name": "someClient1234", - "messaging.solace.dmq_eligible": true, - "messaging.solace.delivery_mode": "Unknown Delivery Mode (1000)", - "messaging.solace.dropped_enqueue_events_success": int64(42), - "messaging.solace.dropped_enqueue_events_failed": int64(24), - "messaging.solace.broker_receive_time_unix_nano": int64(1357924680), - "messaging.solace.dropped_application_message_properties": true, - }, - // Invalid delivery mode, missing IPs, invalid baggage string - expectedUnmarshallingErrors: 2, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - u := newTestV1Unmarshaller(t) - actual := pcommon.NewMap() - u.mapClientSpanAttributes(tt.spanData, actual) - assert.Equal(t, tt.want, actual.AsRaw()) - validateMetric(t, u.metrics.views.recoverableUnmarshallingErrors, tt.expectedUnmarshallingErrors) - }) - } -} - -// Validate that all event types are properly handled and appended into the span data -func TestUnmarshallerEvents(t *testing.T) { - someErrorString := "some error" - somePartitionNumber := uint32(345) - tests := []struct { - name string - spanData *receive_v1.SpanData - populateExpectedSpan func(span ptrace.Span) - unmarshallingErrors interface{} - }{ - { // don't expect any events when none are present in the span data - name: "No Events", - spanData: &receive_v1.SpanData{}, - populateExpectedSpan: func(span ptrace.Span) {}, - }, - { // when an enqueue event is present, expect it to be added to the span events - name: "Enqueue Event Queue", - spanData: &receive_v1.SpanData{ - EnqueueEvents: []*receive_v1.SpanData_EnqueueEvent{ - { - Dest: &receive_v1.SpanData_EnqueueEvent_QueueName{QueueName: "somequeue"}, - TimeUnixNano: 123456789, - PartitionNumber: &somePartitionNumber, - }, - }, - }, - populateExpectedSpan: func(span ptrace.Span) { - populateEvent(t, span, "somequeue enqueue", 123456789, map[string]interface{}{ - "messaging.solace.destination_type": "queue", - "messaging.solace.rejects_all_enqueues": false, - "messaging.solace.partition_number": 345, - }) - }, - }, - { // when a topic endpoint enqueue event is present, expect it to be added to the span events - name: "Enqueue Event Topic Endpoint", - spanData: &receive_v1.SpanData{ - EnqueueEvents: []*receive_v1.SpanData_EnqueueEvent{ - { - Dest: &receive_v1.SpanData_EnqueueEvent_TopicEndpointName{TopicEndpointName: "sometopic"}, - TimeUnixNano: 123456789, - ErrorDescription: &someErrorString, - RejectsAllEnqueues: true, - }, - }, - }, - populateExpectedSpan: func(span ptrace.Span) { - populateEvent(t, span, "sometopic enqueue", 123456789, map[string]interface{}{ - "messaging.solace.destination_type": "topic-endpoint", - "messaging.solace.enqueue_error_message": someErrorString, - "messaging.solace.rejects_all_enqueues": true, - }) - }, - }, - { // when a both a queue and topic endpoint enqueue event is present, expect it to be added to the span events - name: "Enqueue Event Queue and Topic Endpoint", - spanData: &receive_v1.SpanData{ - EnqueueEvents: []*receive_v1.SpanData_EnqueueEvent{ - { - Dest: &receive_v1.SpanData_EnqueueEvent_QueueName{QueueName: "somequeue"}, - TimeUnixNano: 123456789, - }, - { - Dest: &receive_v1.SpanData_EnqueueEvent_TopicEndpointName{TopicEndpointName: "sometopic"}, - TimeUnixNano: 2345678, - }, - }, - }, - populateExpectedSpan: func(span ptrace.Span) { - populateEvent(t, span, "somequeue enqueue", 123456789, map[string]interface{}{ - "messaging.solace.destination_type": "queue", - "messaging.solace.rejects_all_enqueues": false, - }) - populateEvent(t, span, "sometopic enqueue", 2345678, map[string]interface{}{ - "messaging.solace.destination_type": "topic-endpoint", - "messaging.solace.rejects_all_enqueues": false, - }) - }, - }, - { // when an enqueue event does not have a valid dest (ie. nil) - name: "Enqueue Event no Dest", - spanData: &receive_v1.SpanData{ - EnqueueEvents: []*receive_v1.SpanData_EnqueueEvent{ - { - Dest: nil, - TimeUnixNano: 123456789, - }, - }, - }, - populateExpectedSpan: func(span ptrace.Span) {}, - unmarshallingErrors: 1, - }, - { // Local Transaction - name: "Local Transaction Event", - spanData: &receive_v1.SpanData{ - TransactionEvent: &receive_v1.SpanData_TransactionEvent{ - TimeUnixNano: 123456789, - Type: receive_v1.SpanData_TransactionEvent_COMMIT, - Initiator: receive_v1.SpanData_TransactionEvent_CLIENT, - TransactionId: &receive_v1.SpanData_TransactionEvent_LocalId{ - LocalId: &receive_v1.SpanData_TransactionEvent_LocalTransactionId{ - TransactionId: 12345, - SessionId: 67890, - SessionName: "my-session-name", - }, - }, - }, - }, - populateExpectedSpan: func(span ptrace.Span) { - populateEvent(t, span, "commit", 123456789, map[string]interface{}{ - "messaging.solace.transaction_initiator": "client", - "messaging.solace.transaction_id": 12345, - "messaging.solace.transacted_session_name": "my-session-name", - "messaging.solace.transacted_session_id": 67890, - }) - }, - }, - { // XA transaction - name: "XA Transaction Event", - spanData: &receive_v1.SpanData{ - TransactionEvent: &receive_v1.SpanData_TransactionEvent{ - TimeUnixNano: 123456789, - Type: receive_v1.SpanData_TransactionEvent_END, - Initiator: receive_v1.SpanData_TransactionEvent_ADMIN, - TransactionId: &receive_v1.SpanData_TransactionEvent_Xid_{ - Xid: &receive_v1.SpanData_TransactionEvent_Xid{ - FormatId: 123, - BranchQualifier: []byte{0, 8, 20, 254}, - GlobalId: []byte{128, 64, 32, 16, 8, 4, 2, 1, 0}, - }, - }, - }, - }, - populateExpectedSpan: func(span ptrace.Span) { - populateEvent(t, span, "end", 123456789, map[string]interface{}{ - "messaging.solace.transaction_initiator": "administrator", - "messaging.solace.transaction_xid": "0000007b-000814fe-804020100804020100", - }) - }, - }, - { // XA Transaction with no branch qualifier or global ID and with an error - name: "XA Transaction Event with nil fields and error", - spanData: &receive_v1.SpanData{ - TransactionEvent: &receive_v1.SpanData_TransactionEvent{ - TimeUnixNano: 123456789, - Type: receive_v1.SpanData_TransactionEvent_PREPARE, - Initiator: receive_v1.SpanData_TransactionEvent_BROKER, - TransactionId: &receive_v1.SpanData_TransactionEvent_Xid_{ - Xid: &receive_v1.SpanData_TransactionEvent_Xid{ - FormatId: 123, - BranchQualifier: nil, - GlobalId: nil, - }, - }, - ErrorDescription: &someErrorString, - }, - }, - populateExpectedSpan: func(span ptrace.Span) { - populateEvent(t, span, "prepare", 123456789, map[string]interface{}{ - "messaging.solace.transaction_initiator": "broker", - "messaging.solace.transaction_xid": "0000007b--", - "messaging.solace.transaction_error_message": someErrorString, - }) - }, - }, - { // Type of transaction not handled - name: "Unknown Transaction Type and no ID", - spanData: &receive_v1.SpanData{ - TransactionEvent: &receive_v1.SpanData_TransactionEvent{ - TimeUnixNano: 123456789, - Type: receive_v1.SpanData_TransactionEvent_Type(12345), - }, - }, - populateExpectedSpan: func(span ptrace.Span) { - populateEvent(t, span, "Unknown Transaction Event (12345)", 123456789, map[string]interface{}{ - "messaging.solace.transaction_initiator": "client", - }) - }, - unmarshallingErrors: 2, - }, - { // Type of ID not handled, type of initiator not handled - name: "Unknown Transaction Initiator and no ID", - spanData: &receive_v1.SpanData{ - TransactionEvent: &receive_v1.SpanData_TransactionEvent{ - TimeUnixNano: 123456789, - Type: receive_v1.SpanData_TransactionEvent_ROLLBACK, - Initiator: receive_v1.SpanData_TransactionEvent_Initiator(12345), - TransactionId: nil, - }, - }, - populateExpectedSpan: func(span ptrace.Span) { - populateEvent(t, span, "rollback", 123456789, map[string]interface{}{ - "messaging.solace.transaction_initiator": "Unknown Transaction Initiator (12345)", - }) - }, - unmarshallingErrors: 2, - }, - { // when a both a queue and topic endpoint enqueue event is present, expect it to be added to the span events - name: "Multiple Events", - spanData: &receive_v1.SpanData{ - EnqueueEvents: []*receive_v1.SpanData_EnqueueEvent{ - { - Dest: &receive_v1.SpanData_EnqueueEvent_QueueName{QueueName: "somequeue"}, - TimeUnixNano: 123456789, - }, - { - Dest: &receive_v1.SpanData_EnqueueEvent_TopicEndpointName{TopicEndpointName: "sometopic"}, - TimeUnixNano: 2345678, - RejectsAllEnqueues: true, - }, - }, - TransactionEvent: &receive_v1.SpanData_TransactionEvent{ - TimeUnixNano: 123456789, - Type: receive_v1.SpanData_TransactionEvent_ROLLBACK_ONLY, - Initiator: receive_v1.SpanData_TransactionEvent_CLIENT, - TransactionId: &receive_v1.SpanData_TransactionEvent_LocalId{ - LocalId: &receive_v1.SpanData_TransactionEvent_LocalTransactionId{ - TransactionId: 12345, - SessionId: 67890, - SessionName: "my-session-name", - }, - }, - }, - }, - populateExpectedSpan: func(span ptrace.Span) { - populateEvent(t, span, "somequeue enqueue", 123456789, map[string]interface{}{ - "messaging.solace.destination_type": "queue", - "messaging.solace.rejects_all_enqueues": false, - }) - populateEvent(t, span, "sometopic enqueue", 2345678, map[string]interface{}{ - "messaging.solace.destination_type": "topic-endpoint", - "messaging.solace.rejects_all_enqueues": true, - }) - populateEvent(t, span, "rollback_only", 123456789, map[string]interface{}{ - "messaging.solace.transaction_initiator": "client", - "messaging.solace.transaction_id": 12345, - "messaging.solace.transacted_session_name": "my-session-name", - "messaging.solace.transacted_session_id": 67890, - }) - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - u := newTestV1Unmarshaller(t) - expected := ptrace.NewTraces().ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty().Spans().AppendEmpty() - tt.populateExpectedSpan(expected) - actual := ptrace.NewTraces().ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty().Spans().AppendEmpty() - u.mapEvents(tt.spanData, actual) - // order is nondeterministic for attributes, so we must sort to get a valid comparison - compareSpans(t, expected, actual) - validateMetric(t, u.metrics.views.recoverableUnmarshallingErrors, tt.unmarshallingErrors) - }) - } -} +// common helpers func compareSpans(t *testing.T, expected, actual ptrace.Span) { assert.Equal(t, expected.Attributes().AsRaw(), actual.Attributes().AsRaw()) @@ -903,265 +403,3 @@ func populateAttributes(t *testing.T, attrMap pcommon.Map, attributes map[string } } } - -func TestUnmarshallerRGMID(t *testing.T) { - tests := []struct { - name string - in []byte - expected string - numErr interface{} - }{ - { - name: "Valid RGMID", - in: []byte{0x01, 0x00, 0x01, 0x04, 0x09, 0x10, 0x19, 0x24, 0x31, 0x40, 0x51, 0x64, 0x79, 0x90, 0xa9, 0xc4, 0xe1}, - expected: "rmid1:00010-40910192431-40516479-90a9c4e1", - }, - { - name: "Bad RGMID Version", - in: []byte{0x02, 0x00, 0x01, 0x04, 0x09, 0x10, 0x19, 0x24, 0x31, 0x40, 0x51, 0x64, 0x79, 0x90, 0xa9, 0xc4, 0xe1}, - expected: "0200010409101924314051647990a9c4e1", // expect default behavior of hex dump - numErr: 1, - }, - { - name: "Bad RGMID length", - in: []byte{0x00, 0x01, 0x04, 0x09, 0x10, 0x19, 0x24, 0x31, 0x40, 0x51, 0x64, 0x79, 0x90, 0xa9, 0xc4, 0xe1}, - expected: "00010409101924314051647990a9c4e1", // expect default behavior of hex dump - numErr: 1, - }, - { - name: "Nil RGMID", - in: nil, - expected: "", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - u := newTestV1Unmarshaller(t) - actual := u.rgmidToString(tt.in) - assert.Equal(t, tt.expected, actual) - validateMetric(t, u.metrics.views.recoverableUnmarshallingErrors, tt.numErr) - }) - } -} - -func TestUnmarshallerBaggageString(t *testing.T) { - testCases := []struct { - name string - baggage string - expected func(pcommon.Map) - errStr string - }{ - { - name: "Valid baggage", - baggage: `someKey=someVal`, - expected: func(m pcommon.Map) { - assert.NoError(t, m.FromRaw(map[string]interface{}{ - "messaging.solace.message.baggage.someKey": "someVal", - })) - }, - }, - { - name: "Valid baggage with properties", - baggage: `someKey=someVal;someProp=someOtherThing,someOtherKey=someOtherVal;someProp=NewProp123;someOtherProp=AnotherProp192`, - expected: func(m pcommon.Map) { - assert.NoError(t, m.FromRaw(map[string]interface{}{ - "messaging.solace.message.baggage.someKey": "someVal", - "messaging.solace.message.baggage_metadata.someKey": "someProp=someOtherThing", - "messaging.solace.message.baggage.someOtherKey": `someOtherVal`, - "messaging.solace.message.baggage_metadata.someOtherKey": "someProp=NewProp123;someOtherProp=AnotherProp192", - })) - }, - }, - { - name: "Invalid baggage", - baggage: `someKey"=someVal;someProp=someOtherThing`, - errStr: "invalid key", - }, - } - for _, testCase := range testCases { - t.Run(fmt.Sprintf("%T", testCase.name), func(t *testing.T) { - actual := pcommon.NewMap() - u := newTestV1Unmarshaller(t) - err := u.unmarshalBaggage(actual, testCase.baggage) - if testCase.errStr == "" { - assert.Nil(t, err) - } else { - assert.ErrorContains(t, err, testCase.errStr) - } - if testCase.expected != nil { - expected := pcommon.NewMap() - testCase.expected(expected) - assert.Equal(t, expected.AsRaw(), actual.AsRaw()) - } else { - // assert we didn't add anything if we don't have a result map - assert.Equal(t, 0, actual.Len()) - } - }) - } -} - -func TestUnmarshallerInsertUserProperty(t *testing.T) { - emojiVal := 0xf09f92a9 - testCases := []struct { - data interface{} - expectedType pcommon.ValueType - validate func(val pcommon.Value) - }{ - { - &receive_v1.SpanData_UserPropertyValue_NullValue{}, - pcommon.ValueTypeEmpty, - nil, - }, - { - &receive_v1.SpanData_UserPropertyValue_BoolValue{BoolValue: true}, - pcommon.ValueTypeBool, - func(val pcommon.Value) { - assert.Equal(t, true, val.Bool()) - }, - }, - { - &receive_v1.SpanData_UserPropertyValue_DoubleValue{DoubleValue: 12.34}, - pcommon.ValueTypeDouble, - func(val pcommon.Value) { - assert.Equal(t, float64(12.34), val.Double()) - }, - }, - { - &receive_v1.SpanData_UserPropertyValue_ByteArrayValue{ByteArrayValue: []byte{1, 2, 3, 4}}, - pcommon.ValueTypeBytes, - func(val pcommon.Value) { - assert.Equal(t, []byte{1, 2, 3, 4}, val.Bytes().AsRaw()) - }, - }, - { - &receive_v1.SpanData_UserPropertyValue_FloatValue{FloatValue: 12.34}, - pcommon.ValueTypeDouble, - func(val pcommon.Value) { - assert.Equal(t, float64(float32(12.34)), val.Double()) - }, - }, - { - &receive_v1.SpanData_UserPropertyValue_Int8Value{Int8Value: 8}, - pcommon.ValueTypeInt, - func(val pcommon.Value) { - assert.Equal(t, int64(8), val.Int()) - }, - }, - { - &receive_v1.SpanData_UserPropertyValue_Int16Value{Int16Value: 16}, - pcommon.ValueTypeInt, - func(val pcommon.Value) { - assert.Equal(t, int64(16), val.Int()) - }, - }, - { - &receive_v1.SpanData_UserPropertyValue_Int32Value{Int32Value: 32}, - pcommon.ValueTypeInt, - func(val pcommon.Value) { - assert.Equal(t, int64(32), val.Int()) - }, - }, - { - &receive_v1.SpanData_UserPropertyValue_Int64Value{Int64Value: 64}, - pcommon.ValueTypeInt, - func(val pcommon.Value) { - assert.Equal(t, int64(64), val.Int()) - }, - }, - { - &receive_v1.SpanData_UserPropertyValue_Uint8Value{Uint8Value: 8}, - pcommon.ValueTypeInt, - func(val pcommon.Value) { - assert.Equal(t, int64(8), val.Int()) - }, - }, - { - &receive_v1.SpanData_UserPropertyValue_Uint16Value{Uint16Value: 16}, - pcommon.ValueTypeInt, - func(val pcommon.Value) { - assert.Equal(t, int64(16), val.Int()) - }, - }, - { - &receive_v1.SpanData_UserPropertyValue_Uint32Value{Uint32Value: 32}, - pcommon.ValueTypeInt, - func(val pcommon.Value) { - assert.Equal(t, int64(32), val.Int()) - }, - }, - { - &receive_v1.SpanData_UserPropertyValue_Uint64Value{Uint64Value: 64}, - pcommon.ValueTypeInt, - func(val pcommon.Value) { - assert.Equal(t, int64(64), val.Int()) - }, - }, - { - &receive_v1.SpanData_UserPropertyValue_StringValue{StringValue: "hello world"}, - pcommon.ValueTypeStr, - func(val pcommon.Value) { - assert.Equal(t, "hello world", val.Str()) - }, - }, - { - &receive_v1.SpanData_UserPropertyValue_DestinationValue{DestinationValue: "some_dest"}, - pcommon.ValueTypeStr, - func(val pcommon.Value) { - assert.Equal(t, "some_dest", val.Str()) - }, - }, - { - &receive_v1.SpanData_UserPropertyValue_CharacterValue{CharacterValue: 0x61}, - pcommon.ValueTypeStr, - func(val pcommon.Value) { - assert.Equal(t, "a", val.Str()) - }, - }, - { - &receive_v1.SpanData_UserPropertyValue_CharacterValue{CharacterValue: 0xe68080}, - pcommon.ValueTypeStr, - func(val pcommon.Value) { - assert.Equal(t, string(rune(0xe68080)), val.Str()) - }, - }, - { - &receive_v1.SpanData_UserPropertyValue_CharacterValue{CharacterValue: 0xf09f92a9}, - pcommon.ValueTypeStr, - func(val pcommon.Value) { - assert.Equal(t, string(rune(emojiVal)), val.Str()) - }, - }, - } - - unmarshaller := &brokerTraceReceiveUnmarshallerV1{ - logger: zap.NewNop(), - } - for _, testCase := range testCases { - t.Run(fmt.Sprintf("%T", testCase.data), func(t *testing.T) { - const key = "some-property" - attributeMap := pcommon.NewMap() - unmarshaller.insertUserProperty(attributeMap, key, testCase.data) - actual, ok := attributeMap.Get("messaging.solace.user_properties." + key) - require.True(t, ok) - assert.Equal(t, testCase.expectedType, actual.Type()) - if testCase.validate != nil { - testCase.validate(actual) - } - }) - } -} - -func TestSolaceMessageUnmarshallerV1InsertUserPropertyUnsupportedType(t *testing.T) { - u := newTestV1Unmarshaller(t) - const key = "some-property" - attributeMap := pcommon.NewMap() - u.insertUserProperty(attributeMap, key, "invalid data type") - _, ok := attributeMap.Get("messaging.solace.user_properties." + key) - assert.False(t, ok) - validateMetric(t, u.metrics.views.recoverableUnmarshallingErrors, 1) -} - -func newTestV1Unmarshaller(t *testing.T) *brokerTraceReceiveUnmarshallerV1 { - m := newTestMetrics(t) - return &brokerTraceReceiveUnmarshallerV1{zap.NewNop(), m} -} From 32c1f4561dbe153577792d371ea7a5c52de7ace6 Mon Sep 17 00:00:00 2001 From: Michael Cardy Date: Tue, 4 Apr 2023 10:38:17 -0400 Subject: [PATCH 03/10] Set the send span name to send SOL-88033 --- .../solacereceiver/unmarshaller_egress.go | 22 ++++++++--- .../unmarshaller_egress_test.go | 39 +++++++++++-------- receiver/solacereceiver/unmarshaller_test.go | 6 +++ 3 files changed, 45 insertions(+), 22 deletions(-) diff --git a/receiver/solacereceiver/unmarshaller_egress.go b/receiver/solacereceiver/unmarshaller_egress.go index faf95f61b3ca0..3165e6c7fcaf7 100644 --- a/receiver/solacereceiver/unmarshaller_egress.go +++ b/receiver/solacereceiver/unmarshaller_egress.go @@ -71,10 +71,8 @@ func (u *brokerTraceEgressUnmarshallerV1) mapResourceSpanAttributes(spanData *eg func (u *brokerTraceEgressUnmarshallerV1) mapEgressSpan(spanData *egress_v1.SpanData_EgressSpan, clientSpans ptrace.SpanSlice) { if spanData.GetSendSpan() != nil { clientSpan := clientSpans.AppendEmpty() - clientSpan.SetName("") - clientSpan.SetKind(ptrace.SpanKindProducer) u.mapEgressSpanCommon(spanData, clientSpan) - u.mapSendSpanAttributes(spanData.GetSendSpan(), clientSpan.Attributes()) + u.mapSendSpan(spanData.GetSendSpan(), clientSpan) if transactionEvent := spanData.GetTransactionEvent(); transactionEvent != nil { u.mapTransactionEvent(transactionEvent, clientSpan.Events().AppendEmpty()) } @@ -108,7 +106,7 @@ func (u *brokerTraceEgressUnmarshallerV1) mapEgressSpanCommon(spanData *egress_v } } -func (u *brokerTraceEgressUnmarshallerV1) mapSendSpanAttributes(sendSpan *egress_v1.SpanData_SendSpan, attributes pcommon.Map) { +func (u *brokerTraceEgressUnmarshallerV1) mapSendSpan(sendSpan *egress_v1.SpanData_SendSpan, span ptrace.Span) { const ( sourceNameKey = "messaging.source.name" sourceKindKey = "messaging.source.kind" @@ -117,7 +115,14 @@ func (u *brokerTraceEgressUnmarshallerV1) mapSendSpanAttributes(sendSpan *egress ) const ( sendSpanOperation = "send" + sendNameSuffix = " send" + unknownSendName = "(unknown)" + anonymousSendName = "(anonymous)" ) + // hard coded to producer span + span.SetKind(ptrace.SpanKindProducer) + + attributes := span.Attributes() attributes.PutStr(systemAttrKey, systemAttrValue) attributes.PutStr(operationAttrKey, sendSpanOperation) attributes.PutStr(protocolAttrKey, sendSpan.Protocol) @@ -125,17 +130,22 @@ func (u *brokerTraceEgressUnmarshallerV1) mapSendSpanAttributes(sendSpan *egress attributes.PutStr(protocolVersionAttrKey, *sendSpan.ProtocolVersion) } // we don't fatal out when we don't have a valid kind, instead just log and increment stats + var name string switch casted := sendSpan.Source.(type) { case *egress_v1.SpanData_SendSpan_TopicEndpointName: - attributes.PutStr(sourceNameKey, casted.TopicEndpointName) + name = casted.TopicEndpointName + attributes.PutStr(sourceNameKey, name) attributes.PutStr(sourceKindKey, topicEndpointKind) case *egress_v1.SpanData_SendSpan_QueueName: - attributes.PutStr(sourceNameKey, casted.QueueName) + name = casted.QueueName + attributes.PutStr(sourceNameKey, name) attributes.PutStr(sourceKindKey, queueKind) default: u.logger.Warn(fmt.Sprintf("Unknown source type %T", casted)) u.metrics.recordRecoverableUnmarshallingError() + name = unknownSendName } + span.SetName(name + sendNameSuffix) attributes.PutStr(clientUsernameAttrKey, sendSpan.ConsumerClientUsername) attributes.PutStr(clientNameAttrKey, sendSpan.ConsumerClientName) diff --git a/receiver/solacereceiver/unmarshaller_egress_test.go b/receiver/solacereceiver/unmarshaller_egress_test.go index ab85469eee69d..d9277cf116cf2 100644 --- a/receiver/solacereceiver/unmarshaller_egress_test.go +++ b/receiver/solacereceiver/unmarshaller_egress_test.go @@ -116,6 +116,7 @@ var validEgressSpans = map[*egress_v1.SpanData_EgressSpan]ptrace.Span{ }, }: func() ptrace.Span { span := ptrace.NewSpan() + span.SetName("someQueue send") span.SetTraceID([16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}) span.SetSpanID([8]byte{7, 6, 5, 4, 3, 2, 1, 0}) span.SetStartTimestamp(234567890) @@ -168,6 +169,7 @@ var validEgressSpans = map[*egress_v1.SpanData_EgressSpan]ptrace.Span{ }, }: func() ptrace.Span { span := ptrace.NewSpan() + span.SetName("queueName send") span.SetTraceID([16]byte{1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}) span.SetSpanID([8]byte{7, 6, 5, 4, 3, 2, 1, 1}) span.SetStartTimestamp(1234567890) @@ -231,6 +233,7 @@ var validEgressSpans = map[*egress_v1.SpanData_EgressSpan]ptrace.Span{ }: func() ptrace.Span { // second send span span := ptrace.NewSpan() + span.SetName("topicEndpointName send") span.SetTraceID([16]byte{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}) span.SetSpanID([8]byte{0, 1, 2, 3, 4, 5, 6, 7}) span.SetParentSpanID([8]byte{7, 6, 5, 4, 3, 2, 1, 0}) @@ -310,7 +313,7 @@ func TestEgressUnmarshallerEgressSpan(t *testing.T) { func TestEgressUnmarshallerSendSpanAttributes(t *testing.T) { // creates a base attribute map that additional data can be added to // does not include outcome or source. Attributes will override all fields in base - getAttributes := func(attributes map[string]interface{}) map[string]interface{} { + getSpan := func(attributes map[string]interface{}, name string) ptrace.Span { base := map[string]interface{}{ "messaging.system": "SolacePubSub+", "messaging.operation": "send", @@ -324,7 +327,11 @@ func TestEgressUnmarshallerSendSpanAttributes(t *testing.T) { for key, val := range attributes { base[key] = val } - return base + span := ptrace.NewSpan() + span.Attributes().FromRaw(base) + span.SetName(name) + span.SetKind(ptrace.SpanKindProducer) + return span } // sets the common fields from getAttributes getSendSpan := func(base *egress_v1.SpanData_SendSpan) *egress_v1.SpanData_SendSpan { @@ -338,7 +345,7 @@ func TestEgressUnmarshallerSendSpanAttributes(t *testing.T) { tests := []struct { name string spanData *egress_v1.SpanData_SendSpan - want map[string]interface{} + want ptrace.Span expectedUnmarshallingErrors interface{} }{ { @@ -348,10 +355,10 @@ func TestEgressUnmarshallerSendSpanAttributes(t *testing.T) { QueueName: "someQueue", }, }), - want: getAttributes(map[string]interface{}{ + want: getSpan(map[string]interface{}{ "messaging.source.name": "someQueue", "messaging.source.kind": "queue", - }), + }, "someQueue send"), }, { name: "With Topic Endpoint source", @@ -360,24 +367,24 @@ func TestEgressUnmarshallerSendSpanAttributes(t *testing.T) { TopicEndpointName: "someTopic", }, }), - want: getAttributes(map[string]interface{}{ + want: getSpan(map[string]interface{}{ "messaging.source.name": "someTopic", "messaging.source.kind": "topic-endpoint", - }), + }, "someTopic send"), }, { name: "With Unknown Endpoint source", spanData: getSendSpan(&egress_v1.SpanData_SendSpan{}), - want: getAttributes(map[string]interface{}{}), + want: getSpan(map[string]interface{}{}, "(unknown) send"), expectedUnmarshallingErrors: 1, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { u := newTestEgressV1Unmarshaller(t) - actual := pcommon.NewMap() - u.mapSendSpanAttributes(tt.spanData, actual) - assert.Equal(t, tt.want, actual.AsRaw()) + actual := ptrace.NewSpan() + u.mapSendSpan(tt.spanData, actual) + compareSpans(t, tt.want, actual) validateMetric(t, u.metrics.views.recoverableUnmarshallingErrors, tt.expectedUnmarshallingErrors) }) } @@ -395,20 +402,20 @@ func TestEgressUnmarshallerSendSpanAttributes(t *testing.T) { for outcomeKey, outcomeName := range outcomes { t.Run("With outcome "+outcomeName, func(t *testing.T) { u := newTestEgressV1Unmarshaller(t) - expected := getAttributes(map[string]interface{}{ + expected := getSpan(map[string]interface{}{ "messaging.source.name": "someQueue", "messaging.source.kind": "queue", "messaging.solace.send_operation.outcome": outcomeName, - }) + }, "someQueue send") spanData := getSendSpan(&egress_v1.SpanData_SendSpan{ Source: &egress_v1.SpanData_SendSpan_QueueName{ QueueName: "someQueue", }, Outcome: outcomeKey, }) - actual := pcommon.NewMap() - u.mapSendSpanAttributes(spanData, actual) - assert.Equal(t, expected, actual.AsRaw()) + actual := ptrace.NewSpan() + u.mapSendSpan(spanData, actual) + compareSpans(t, expected, actual) }) } } diff --git a/receiver/solacereceiver/unmarshaller_test.go b/receiver/solacereceiver/unmarshaller_test.go index 87a8f342a2746..695025d47b22a 100644 --- a/receiver/solacereceiver/unmarshaller_test.go +++ b/receiver/solacereceiver/unmarshaller_test.go @@ -361,6 +361,12 @@ func TestSolaceMessageUnmarshallerUnmarshal(t *testing.T) { // common helpers func compareSpans(t *testing.T, expected, actual ptrace.Span) { + assert.Equal(t, expected.Name(), actual.Name()) + assert.Equal(t, expected.TraceID(), actual.TraceID()) + assert.Equal(t, expected.SpanID(), actual.SpanID()) + assert.Equal(t, expected.ParentSpanID(), actual.ParentSpanID()) + assert.Equal(t, expected.StartTimestamp(), actual.StartTimestamp()) + assert.Equal(t, expected.EndTimestamp(), actual.EndTimestamp()) assert.Equal(t, expected.Attributes().AsRaw(), actual.Attributes().AsRaw()) require.Equal(t, expected.Events().Len(), actual.Events().Len()) for i := 0; i < expected.Events().Len(); i++ { From 106eb26a4020dad6779cd2ab4658ad7671ae6149 Mon Sep 17 00:00:00 2001 From: Michael Cardy Date: Tue, 4 Apr 2023 12:33:20 -0400 Subject: [PATCH 04/10] Updates for latest architecture changes Use send.outcome instead of send_operation.outcome Use (anonymous) in send span name when given an anonymous topic endpoint or queue SOL-88025 --- .../solacereceiver/unmarshaller_egress.go | 39 +++++++++++-- .../unmarshaller_egress_test.go | 58 +++++++++++++------ 2 files changed, 75 insertions(+), 22 deletions(-) diff --git a/receiver/solacereceiver/unmarshaller_egress.go b/receiver/solacereceiver/unmarshaller_egress.go index 3165e6c7fcaf7..ba0eebc930e99 100644 --- a/receiver/solacereceiver/unmarshaller_egress.go +++ b/receiver/solacereceiver/unmarshaller_egress.go @@ -17,6 +17,7 @@ package solacereceiver // import "github.com/open-telemetry/opentelemetry-collec import ( "encoding/hex" "fmt" + "strings" "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/ptrace" @@ -111,7 +112,7 @@ func (u *brokerTraceEgressUnmarshallerV1) mapSendSpan(sendSpan *egress_v1.SpanDa sourceNameKey = "messaging.source.name" sourceKindKey = "messaging.source.kind" replayedKey = "messaging.solace.message_replayed" - outcomeKey = "messaging.solace.send_operation.outcome" + outcomeKey = "messaging.solace.send.outcome" ) const ( sendSpanOperation = "send" @@ -133,12 +134,20 @@ func (u *brokerTraceEgressUnmarshallerV1) mapSendSpan(sendSpan *egress_v1.SpanDa var name string switch casted := sendSpan.Source.(type) { case *egress_v1.SpanData_SendSpan_TopicEndpointName: - name = casted.TopicEndpointName - attributes.PutStr(sourceNameKey, name) + if isAnonymousTopicEndpoint(casted.TopicEndpointName) { + name = anonymousSendName + } else { + name = casted.TopicEndpointName + } + attributes.PutStr(sourceNameKey, casted.TopicEndpointName) attributes.PutStr(sourceKindKey, topicEndpointKind) case *egress_v1.SpanData_SendSpan_QueueName: - name = casted.QueueName - attributes.PutStr(sourceNameKey, name) + if isAnonymousQueue(casted.QueueName) { + name = anonymousSendName + } else { + name = casted.QueueName + } + attributes.PutStr(sourceNameKey, casted.QueueName) attributes.PutStr(sourceKindKey, queueKind) default: u.logger.Warn(fmt.Sprintf("Unknown source type %T", casted)) @@ -235,3 +244,23 @@ func (u *brokerTraceEgressUnmarshallerV1) mapTransactionEvent(transactionEvent * u.metrics.recordRecoverableUnmarshallingError() } } + +func isAnonymousQueue(name string) bool { + // all anonymous queues start with the prefix #P2P/QTMP + const anonymousQueuePrefix = "#P2P/QTMP" + return strings.HasPrefix(name, anonymousQueuePrefix) +} + +func isAnonymousTopicEndpoint(name string) bool { + // all anonymous topic endpoints are made up of hex strings of length 32 + if len(name) != 32 { + return false + } + for _, c := range []byte(name) { // []byte casting is more efficient in this loop + // check if we are outside 0-9 AND outside a-f + if (c < '0' || c > '9') && (c < 'a' || c > 'f') { + return false + } + } + return true +} diff --git a/receiver/solacereceiver/unmarshaller_egress_test.go b/receiver/solacereceiver/unmarshaller_egress_test.go index d9277cf116cf2..0cb8142959b71 100644 --- a/receiver/solacereceiver/unmarshaller_egress_test.go +++ b/receiver/solacereceiver/unmarshaller_egress_test.go @@ -132,7 +132,7 @@ var validEgressSpans = map[*egress_v1.SpanData_EgressSpan]ptrace.Span{ spanAttrs.PutStr("messaging.solace.client_username", "clientUsername") spanAttrs.PutStr("messaging.solace.client_name", "clientName") spanAttrs.PutBool("messaging.solace.message_replayed", false) - spanAttrs.PutStr("messaging.solace.send_operation.outcome", "flow unbound") + spanAttrs.PutStr("messaging.solace.send.outcome", "flow unbound") return span }(), { @@ -187,7 +187,7 @@ var validEgressSpans = map[*egress_v1.SpanData_EgressSpan]ptrace.Span{ spanAttrs.PutStr("messaging.solace.client_username", "someClientUsername") spanAttrs.PutStr("messaging.solace.client_name", "someClient1234") spanAttrs.PutBool("messaging.solace.message_replayed", false) - spanAttrs.PutStr("messaging.solace.send_operation.outcome", "accepted") + spanAttrs.PutStr("messaging.solace.send.outcome", "accepted") txnEvent := span.Events().AppendEmpty() txnEvent.SetName("session_timeout") txnEvent.SetTimestamp(123456789) @@ -250,7 +250,7 @@ var validEgressSpans = map[*egress_v1.SpanData_EgressSpan]ptrace.Span{ spanAttrs.PutStr("messaging.solace.client_username", "someOtherClientUsername") spanAttrs.PutStr("messaging.solace.client_name", "someOtherClient1234") spanAttrs.PutBool("messaging.solace.message_replayed", true) - spanAttrs.PutStr("messaging.solace.send_operation.outcome", "rejected") + spanAttrs.PutStr("messaging.solace.send.outcome", "rejected") txnEvent := span.Events().AppendEmpty() txnEvent.SetName("end") txnEvent.SetTimestamp(223456789) @@ -315,14 +315,14 @@ func TestEgressUnmarshallerSendSpanAttributes(t *testing.T) { // does not include outcome or source. Attributes will override all fields in base getSpan := func(attributes map[string]interface{}, name string) ptrace.Span { base := map[string]interface{}{ - "messaging.system": "SolacePubSub+", - "messaging.operation": "send", - "messaging.protocol": "MQTT", - "messaging.protocol_version": "5.0", - "messaging.solace.client_username": "someUser", - "messaging.solace.client_name": "someName", - "messaging.solace.message_replayed": false, - "messaging.solace.send_operation.outcome": "accepted", + "messaging.system": "SolacePubSub+", + "messaging.operation": "send", + "messaging.protocol": "MQTT", + "messaging.protocol_version": "5.0", + "messaging.solace.client_username": "someUser", + "messaging.solace.client_name": "someName", + "messaging.solace.message_replayed": false, + "messaging.solace.send.outcome": "accepted", } for key, val := range attributes { base[key] = val @@ -364,13 +364,37 @@ func TestEgressUnmarshallerSendSpanAttributes(t *testing.T) { name: "With Topic Endpoint source", spanData: getSendSpan(&egress_v1.SpanData_SendSpan{ Source: &egress_v1.SpanData_SendSpan_TopicEndpointName{ - TopicEndpointName: "someTopic", + TopicEndpointName: "0123456789abcdef0123456789abcdeg", }, }), want: getSpan(map[string]interface{}{ - "messaging.source.name": "someTopic", + "messaging.source.name": "0123456789abcdef0123456789abcdeg", "messaging.source.kind": "topic-endpoint", - }, "someTopic send"), + }, "0123456789abcdef0123456789abcdeg send"), + }, + { + name: "With Anonymous Queue source", + spanData: getSendSpan(&egress_v1.SpanData_SendSpan{ + Source: &egress_v1.SpanData_SendSpan_QueueName{ + QueueName: "#P2P/QTMP/myQueue", + }, + }), + want: getSpan(map[string]interface{}{ + "messaging.source.name": "#P2P/QTMP/myQueue", + "messaging.source.kind": "queue", + }, "(anonymous) send"), + }, + { + name: "With Anonymous Topic Endpoint source", + spanData: getSendSpan(&egress_v1.SpanData_SendSpan{ + Source: &egress_v1.SpanData_SendSpan_TopicEndpointName{ + TopicEndpointName: "0123456789abcdef0123456789abcdef", + }, + }), + want: getSpan(map[string]interface{}{ + "messaging.source.name": "0123456789abcdef0123456789abcdef", + "messaging.source.kind": "topic-endpoint", + }, "(anonymous) send"), }, { name: "With Unknown Endpoint source", @@ -403,9 +427,9 @@ func TestEgressUnmarshallerSendSpanAttributes(t *testing.T) { t.Run("With outcome "+outcomeName, func(t *testing.T) { u := newTestEgressV1Unmarshaller(t) expected := getSpan(map[string]interface{}{ - "messaging.source.name": "someQueue", - "messaging.source.kind": "queue", - "messaging.solace.send_operation.outcome": outcomeName, + "messaging.source.name": "someQueue", + "messaging.source.kind": "queue", + "messaging.solace.send.outcome": outcomeName, }, "someQueue send") spanData := getSendSpan(&egress_v1.SpanData_SendSpan{ Source: &egress_v1.SpanData_SendSpan_QueueName{ From 4cba0adc3b56eedf14b001807dcf5b8683671e3d Mon Sep 17 00:00:00 2001 From: Michael Cardy Date: Wed, 12 Apr 2023 09:38:10 -0400 Subject: [PATCH 05/10] Don't error log each trace SOL-92755 --- receiver/solacereceiver/unmarshaller_egress.go | 1 - 1 file changed, 1 deletion(-) diff --git a/receiver/solacereceiver/unmarshaller_egress.go b/receiver/solacereceiver/unmarshaller_egress.go index ba0eebc930e99..904b8c95e69db 100644 --- a/receiver/solacereceiver/unmarshaller_egress.go +++ b/receiver/solacereceiver/unmarshaller_egress.go @@ -37,7 +37,6 @@ func (u *brokerTraceEgressUnmarshallerV1) unmarshal(message *inboundMessage) (pt if err != nil { return ptrace.Traces{}, err } - u.logger.Error(spanData.String()) traces := ptrace.NewTraces() u.populateTraces(spanData, traces) return traces, nil From 11693575ed9aeb77a8ffa9b2c0a42a5c3a9959c7 Mon Sep 17 00:00:00 2001 From: Michael Cardy Date: Fri, 14 Apr 2023 13:43:46 -0400 Subject: [PATCH 06/10] Increment span count based on number of received spans, not span messages SOL-92890 --- receiver/solacereceiver/observability.go | 4 ++-- receiver/solacereceiver/observability_test.go | 4 +++- receiver/solacereceiver/receiver.go | 2 +- receiver/solacereceiver/receiver_test.go | 22 ++++++++++++++++--- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/receiver/solacereceiver/observability.go b/receiver/solacereceiver/observability.go index 71771dd577399..791e11a437b94 100644 --- a/receiver/solacereceiver/observability.go +++ b/receiver/solacereceiver/observability.go @@ -180,8 +180,8 @@ func (m *opencensusMetrics) recordReceivedSpanMessages() { } // recordReportedSpans increments the metric that records the number of spans reported to the next consumer -func (m *opencensusMetrics) recordReportedSpans() { - stats.Record(context.Background(), m.stats.reportedSpans.M(1)) +func (m *opencensusMetrics) recordReportedSpans(amount int64) { + stats.Record(context.Background(), m.stats.reportedSpans.M(amount)) } // recordReceiverStatus sets the metric that records the current state of the receiver to the given state diff --git a/receiver/solacereceiver/observability_test.go b/receiver/solacereceiver/observability_test.go index 3852b65e43d94..f0e7535f8d7e3 100644 --- a/receiver/solacereceiver/observability_test.go +++ b/receiver/solacereceiver/observability_test.go @@ -40,7 +40,9 @@ func TestRecordMetrics(t *testing.T) { {metrics.recordFatalUnmarshallingError, metrics.views.fatalUnmarshallingErrors, metrics.stats.fatalUnmarshallingErrors, 3, 3}, {metrics.recordDroppedSpanMessages, metrics.views.droppedSpanMessages, metrics.stats.droppedSpanMessages, 3, 3}, {metrics.recordReceivedSpanMessages, metrics.views.receivedSpanMessages, metrics.stats.receivedSpanMessages, 3, 3}, - {metrics.recordReportedSpans, metrics.views.reportedSpans, metrics.stats.reportedSpans, 3, 3}, + {func() { + metrics.recordReportedSpans(2) + }, metrics.views.reportedSpans, metrics.stats.reportedSpans, 3, 6}, {func() { metrics.recordReceiverStatus(receiverStateTerminated) }, metrics.views.receiverStatus, metrics.stats.receiverStatus, 3, int(receiverStateTerminated)}, diff --git a/receiver/solacereceiver/receiver.go b/receiver/solacereceiver/receiver.go index 5a32aa865392c..e1e59fd3fc529 100644 --- a/receiver/solacereceiver/receiver.go +++ b/receiver/solacereceiver/receiver.go @@ -258,7 +258,7 @@ flowControlLoop: } } else { // no forward error - s.metrics.recordReportedSpans() + s.metrics.recordReportedSpans(int64(traces.SpanCount())) break flowControlLoop } } diff --git a/receiver/solacereceiver/receiver_test.go b/receiver/solacereceiver/receiver_test.go index 4bfb7626aafef..264eff25ce4a9 100644 --- a/receiver/solacereceiver/receiver_test.go +++ b/receiver/solacereceiver/receiver_test.go @@ -57,10 +57,18 @@ func TestReceiveMessage(t *testing.T) { expectedErr error // validate constraints after the fact validation func(t *testing.T, receiver *solaceTracesReceiver) + // traces provided by the trace function + traces ptrace.Traces }{ { // no errors, expect no error, validate metrics name: "Receive Message Success", validation: validateMetrics(1, nil, nil, 1), + traces: newTestTracesWithSpans(1), + }, + { // no errors, expect no error, validate metrics + name: "Receive Message Multiple Traces Success", + validation: validateMetrics(1, nil, nil, 3), + traces: newTestTracesWithSpans(3), }, { // fail at receiveMessage and expect the error name: "Receive Messages Error", @@ -102,7 +110,6 @@ func TestReceiveMessage(t *testing.T) { } msg := &inboundMessage{} - trace := ptrace.NewTraces() // populate mock messagingService and unmarshaller functions, expecting them each to be called at most once var receiveMessagesCalled, ackCalled, nackCalled, unmarshalCalled bool @@ -136,7 +143,7 @@ func TestReceiveMessage(t *testing.T) { if testCase.unmarshalErr != nil { return ptrace.Traces{}, testCase.unmarshalErr } - return trace, nil + return testCase.traces, nil } err := receiver.receiveMessage(context.Background(), messagingService) @@ -164,7 +171,7 @@ func TestReceiveMessagesTerminateWithCtxDone(t *testing.T) { receiveMessagesCalled := false ctx, cancel := context.WithCancel(context.Background()) msg := &inboundMessage{} - trace := ptrace.NewTraces() + trace := newTestTracesWithSpans(1) messagingService.receiveMessageFunc = func(ctx context.Context) (*inboundMessage, error) { assert.False(t, receiveMessagesCalled) receiveMessagesCalled = true @@ -614,3 +621,12 @@ func (m *mockUnmarshaller) unmarshal(message *inboundMessage) (ptrace.Traces, er } panic("did not expect unmarshal to be called") } + +func newTestTracesWithSpans(spanCount int) ptrace.Traces { + traces := ptrace.NewTraces() + spans := traces.ResourceSpans().AppendEmpty().ScopeSpans().AppendEmpty() + for i := 0; i < spanCount; i++ { + spans.Spans().AppendEmpty() + } + return traces +} From a3cc08147bfa2e1d3e685e6146268ae2852837f0 Mon Sep 17 00:00:00 2001 From: Michael Cardy Date: Fri, 14 Apr 2023 13:48:09 -0400 Subject: [PATCH 07/10] Fixed reference error causing failing unit test --- receiver/solacereceiver/unmarshaller_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/receiver/solacereceiver/unmarshaller_test.go b/receiver/solacereceiver/unmarshaller_test.go index 695025d47b22a..0ec9f9424b37e 100644 --- a/receiver/solacereceiver/unmarshaller_test.go +++ b/receiver/solacereceiver/unmarshaller_test.go @@ -316,7 +316,8 @@ func TestSolaceMessageUnmarshallerUnmarshal(t *testing.T) { }) instrumentation := resource.ScopeSpans().AppendEmpty() // first send span - for _, span := range validEgressSpans { + for _, spanRef := range validEgressSpans { + span := spanRef newSpan := instrumentation.Spans().AppendEmpty() span.CopyTo(newSpan) } From 4ab1ab00c1c3330f5bbcbc56f9db2bb974e08285 Mon Sep 17 00:00:00 2001 From: Michael Cardy Date: Fri, 26 May 2023 09:09:07 -0400 Subject: [PATCH 08/10] Fixed failing unit tests after merge --- .../unmarshaller_egress_test.go | 316 +++++++++--------- receiver/solacereceiver/unmarshaller_test.go | 6 +- 2 files changed, 166 insertions(+), 156 deletions(-) diff --git a/receiver/solacereceiver/unmarshaller_egress_test.go b/receiver/solacereceiver/unmarshaller_egress_test.go index 0cb8142959b71..76a053dded3dd 100644 --- a/receiver/solacereceiver/unmarshaller_egress_test.go +++ b/receiver/solacereceiver/unmarshaller_egress_test.go @@ -95,170 +95,180 @@ var ( ) // validEgressSpans is valid data used as test data -var validEgressSpans = map[*egress_v1.SpanData_EgressSpan]ptrace.Span{ +var validEgressSpans = []struct { + in *egress_v1.SpanData_EgressSpan + out ptrace.Span +}{ { - TraceId: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - SpanId: []byte{7, 6, 5, 4, 3, 2, 1, 0}, - StartTimeUnixNano: 234567890, - EndTimeUnixNano: 234567890, - TypeData: &egress_v1.SpanData_EgressSpan_SendSpan{ - SendSpan: &egress_v1.SpanData_SendSpan{ - Protocol: "SMF", - ProtocolVersion: &protocolVersion3, - ConsumerClientUsername: "clientUsername", - ConsumerClientName: "clientName", - Source: &egress_v1.SpanData_SendSpan_QueueName{ - QueueName: "someQueue", + &egress_v1.SpanData_EgressSpan{ + TraceId: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + SpanId: []byte{7, 6, 5, 4, 3, 2, 1, 0}, + StartTimeUnixNano: 234567890, + EndTimeUnixNano: 234567890, + TypeData: &egress_v1.SpanData_EgressSpan_SendSpan{ + SendSpan: &egress_v1.SpanData_SendSpan{ + Protocol: "SMF", + ProtocolVersion: &protocolVersion3, + ConsumerClientUsername: "clientUsername", + ConsumerClientName: "clientName", + Source: &egress_v1.SpanData_SendSpan_QueueName{ + QueueName: "someQueue", + }, + Outcome: egress_v1.SpanData_SendSpan_FLOW_UNBOUND, + ReplayedMsg: false, }, - Outcome: egress_v1.SpanData_SendSpan_FLOW_UNBOUND, - ReplayedMsg: false, }, }, - }: func() ptrace.Span { - span := ptrace.NewSpan() - span.SetName("someQueue send") - span.SetTraceID([16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}) - span.SetSpanID([8]byte{7, 6, 5, 4, 3, 2, 1, 0}) - span.SetStartTimestamp(234567890) - span.SetEndTimestamp(234567890) - span.SetKind(4) - spanAttrs := span.Attributes() - spanAttrs.PutStr("messaging.system", "SolacePubSub+") - spanAttrs.PutStr("messaging.operation", "send") - spanAttrs.PutStr("messaging.protocol", "SMF") - spanAttrs.PutStr("messaging.protocol_version", "3.0") - spanAttrs.PutStr("messaging.source.name", "someQueue") - spanAttrs.PutStr("messaging.source.kind", "queue") - spanAttrs.PutStr("messaging.solace.client_username", "clientUsername") - spanAttrs.PutStr("messaging.solace.client_name", "clientName") - spanAttrs.PutBool("messaging.solace.message_replayed", false) - spanAttrs.PutStr("messaging.solace.send.outcome", "flow unbound") - return span - }(), + func() ptrace.Span { + span := ptrace.NewSpan() + span.SetName("someQueue send") + span.SetTraceID([16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}) + span.SetSpanID([8]byte{7, 6, 5, 4, 3, 2, 1, 0}) + span.SetStartTimestamp(234567890) + span.SetEndTimestamp(234567890) + span.SetKind(4) + spanAttrs := span.Attributes() + spanAttrs.PutStr("messaging.system", "SolacePubSub+") + spanAttrs.PutStr("messaging.operation", "send") + spanAttrs.PutStr("messaging.protocol", "SMF") + spanAttrs.PutStr("messaging.protocol_version", "3.0") + spanAttrs.PutStr("messaging.source.name", "someQueue") + spanAttrs.PutStr("messaging.source.kind", "queue") + spanAttrs.PutStr("messaging.solace.client_username", "clientUsername") + spanAttrs.PutStr("messaging.solace.client_name", "clientName") + spanAttrs.PutBool("messaging.solace.message_replayed", false) + spanAttrs.PutStr("messaging.solace.send.outcome", "flow unbound") + return span + }(), + }, { - TraceId: []byte{1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - SpanId: []byte{7, 6, 5, 4, 3, 2, 1, 1}, - StartTimeUnixNano: 1234567890, - EndTimeUnixNano: 2234567890, - ErrorDescription: &someError, - TypeData: &egress_v1.SpanData_EgressSpan_SendSpan{ - SendSpan: &egress_v1.SpanData_SendSpan{ - Protocol: "MQTT", - ProtocolVersion: &protocolVersion, - ConsumerClientUsername: "someClientUsername", - ConsumerClientName: "someClient1234", - Source: &egress_v1.SpanData_SendSpan_QueueName{ - QueueName: "queueName", + &egress_v1.SpanData_EgressSpan{ + TraceId: []byte{1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + SpanId: []byte{7, 6, 5, 4, 3, 2, 1, 1}, + StartTimeUnixNano: 1234567890, + EndTimeUnixNano: 2234567890, + ErrorDescription: &someError, + TypeData: &egress_v1.SpanData_EgressSpan_SendSpan{ + SendSpan: &egress_v1.SpanData_SendSpan{ + Protocol: "MQTT", + ProtocolVersion: &protocolVersion, + ConsumerClientUsername: "someClientUsername", + ConsumerClientName: "someClient1234", + Source: &egress_v1.SpanData_SendSpan_QueueName{ + QueueName: "queueName", + }, + Outcome: egress_v1.SpanData_SendSpan_ACCEPTED, + ReplayedMsg: false, }, - Outcome: egress_v1.SpanData_SendSpan_ACCEPTED, - ReplayedMsg: false, }, - }, - TransactionEvent: &egress_v1.SpanData_TransactionEvent{ - TimeUnixNano: 123456789, - Type: egress_v1.SpanData_TransactionEvent_SESSION_TIMEOUT, - Initiator: egress_v1.SpanData_TransactionEvent_BROKER, - TransactionId: &egress_v1.SpanData_TransactionEvent_LocalId{ - LocalId: &egress_v1.SpanData_TransactionEvent_LocalTransactionId{ - TransactionId: 12345, - SessionId: 67890, - SessionName: "my-session-name", + TransactionEvent: &egress_v1.SpanData_TransactionEvent{ + TimeUnixNano: 123456789, + Type: egress_v1.SpanData_TransactionEvent_SESSION_TIMEOUT, + Initiator: egress_v1.SpanData_TransactionEvent_BROKER, + TransactionId: &egress_v1.SpanData_TransactionEvent_LocalId{ + LocalId: &egress_v1.SpanData_TransactionEvent_LocalTransactionId{ + TransactionId: 12345, + SessionId: 67890, + SessionName: "my-session-name", + }, }, + ErrorDescription: &someOtherError, }, - ErrorDescription: &someOtherError, - }, - }: func() ptrace.Span { - span := ptrace.NewSpan() - span.SetName("queueName send") - span.SetTraceID([16]byte{1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}) - span.SetSpanID([8]byte{7, 6, 5, 4, 3, 2, 1, 1}) - span.SetStartTimestamp(1234567890) - span.SetEndTimestamp(2234567890) - span.SetKind(4) - span.Status().SetCode(ptrace.StatusCodeError) - span.Status().SetMessage("someErrorOccurred") - spanAttrs := span.Attributes() - spanAttrs.PutStr("messaging.system", "SolacePubSub+") - spanAttrs.PutStr("messaging.operation", "send") - spanAttrs.PutStr("messaging.protocol", "MQTT") - spanAttrs.PutStr("messaging.protocol_version", "5.0") - spanAttrs.PutStr("messaging.source.name", "queueName") - spanAttrs.PutStr("messaging.source.kind", "queue") - spanAttrs.PutStr("messaging.solace.client_username", "someClientUsername") - spanAttrs.PutStr("messaging.solace.client_name", "someClient1234") - spanAttrs.PutBool("messaging.solace.message_replayed", false) - spanAttrs.PutStr("messaging.solace.send.outcome", "accepted") - txnEvent := span.Events().AppendEmpty() - txnEvent.SetName("session_timeout") - txnEvent.SetTimestamp(123456789) - txnEventAttrs := txnEvent.Attributes() - txnEventAttrs.PutStr("messaging.solace.transaction_initiator", "broker") - txnEventAttrs.PutInt("messaging.solace.transaction_id", 12345) - txnEventAttrs.PutStr("messaging.solace.transacted_session_name", "my-session-name") - txnEventAttrs.PutInt("messaging.solace.transacted_session_id", 67890) - txnEventAttrs.PutStr("messaging.solace.transaction_error_message", "someOtherErrorOccurred") - return span - }(), + }, func() ptrace.Span { + span := ptrace.NewSpan() + span.SetName("queueName send") + span.SetTraceID([16]byte{1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}) + span.SetSpanID([8]byte{7, 6, 5, 4, 3, 2, 1, 1}) + span.SetStartTimestamp(1234567890) + span.SetEndTimestamp(2234567890) + span.SetKind(4) + span.Status().SetCode(ptrace.StatusCodeError) + span.Status().SetMessage("someErrorOccurred") + spanAttrs := span.Attributes() + spanAttrs.PutStr("messaging.system", "SolacePubSub+") + spanAttrs.PutStr("messaging.operation", "send") + spanAttrs.PutStr("messaging.protocol", "MQTT") + spanAttrs.PutStr("messaging.protocol_version", "5.0") + spanAttrs.PutStr("messaging.source.name", "queueName") + spanAttrs.PutStr("messaging.source.kind", "queue") + spanAttrs.PutStr("messaging.solace.client_username", "someClientUsername") + spanAttrs.PutStr("messaging.solace.client_name", "someClient1234") + spanAttrs.PutBool("messaging.solace.message_replayed", false) + spanAttrs.PutStr("messaging.solace.send.outcome", "accepted") + txnEvent := span.Events().AppendEmpty() + txnEvent.SetName("session_timeout") + txnEvent.SetTimestamp(123456789) + txnEventAttrs := txnEvent.Attributes() + txnEventAttrs.PutStr("messaging.solace.transaction_initiator", "broker") + txnEventAttrs.PutInt("messaging.solace.transaction_id", 12345) + txnEventAttrs.PutStr("messaging.solace.transacted_session_name", "my-session-name") + txnEventAttrs.PutInt("messaging.solace.transacted_session_id", 67890) + txnEventAttrs.PutStr("messaging.solace.transaction_error_message", "someOtherErrorOccurred") + return span + }(), + }, { - TraceId: []byte{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}, - SpanId: []byte{0, 1, 2, 3, 4, 5, 6, 7}, - ParentSpanId: []byte{7, 6, 5, 4, 3, 2, 1, 0}, - StartTimeUnixNano: 4234567890, - EndTimeUnixNano: 5234567890, - TypeData: &egress_v1.SpanData_EgressSpan_SendSpan{ - SendSpan: &egress_v1.SpanData_SendSpan{ - Protocol: "AMQP", - ProtocolVersion: &protocolVersion2, - ConsumerClientUsername: "someOtherClientUsername", - ConsumerClientName: "someOtherClient1234", - Source: &egress_v1.SpanData_SendSpan_TopicEndpointName{ - TopicEndpointName: "topicEndpointName", + &egress_v1.SpanData_EgressSpan{ + TraceId: []byte{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}, + SpanId: []byte{0, 1, 2, 3, 4, 5, 6, 7}, + ParentSpanId: []byte{7, 6, 5, 4, 3, 2, 1, 0}, + StartTimeUnixNano: 4234567890, + EndTimeUnixNano: 5234567890, + TypeData: &egress_v1.SpanData_EgressSpan_SendSpan{ + SendSpan: &egress_v1.SpanData_SendSpan{ + Protocol: "AMQP", + ProtocolVersion: &protocolVersion2, + ConsumerClientUsername: "someOtherClientUsername", + ConsumerClientName: "someOtherClient1234", + Source: &egress_v1.SpanData_SendSpan_TopicEndpointName{ + TopicEndpointName: "topicEndpointName", + }, + Outcome: egress_v1.SpanData_SendSpan_REJECTED, + ReplayedMsg: true, }, - Outcome: egress_v1.SpanData_SendSpan_REJECTED, - ReplayedMsg: true, }, - }, - TransactionEvent: &egress_v1.SpanData_TransactionEvent{ - TimeUnixNano: 223456789, - Type: egress_v1.SpanData_TransactionEvent_END, - Initiator: egress_v1.SpanData_TransactionEvent_CLIENT, - TransactionId: &egress_v1.SpanData_TransactionEvent_Xid_{ - Xid: &egress_v1.SpanData_TransactionEvent_Xid{ - FormatId: 123, - BranchQualifier: []byte{0, 8, 20, 254}, - GlobalId: []byte{128, 64, 32, 16, 8, 4, 2, 1, 0}, + TransactionEvent: &egress_v1.SpanData_TransactionEvent{ + TimeUnixNano: 223456789, + Type: egress_v1.SpanData_TransactionEvent_END, + Initiator: egress_v1.SpanData_TransactionEvent_CLIENT, + TransactionId: &egress_v1.SpanData_TransactionEvent_Xid_{ + Xid: &egress_v1.SpanData_TransactionEvent_Xid{ + FormatId: 123, + BranchQualifier: []byte{0, 8, 20, 254}, + GlobalId: []byte{128, 64, 32, 16, 8, 4, 2, 1, 0}, + }, }, }, - }, - }: func() ptrace.Span { - // second send span - span := ptrace.NewSpan() - span.SetName("topicEndpointName send") - span.SetTraceID([16]byte{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}) - span.SetSpanID([8]byte{0, 1, 2, 3, 4, 5, 6, 7}) - span.SetParentSpanID([8]byte{7, 6, 5, 4, 3, 2, 1, 0}) - span.SetStartTimestamp(4234567890) - span.SetEndTimestamp(5234567890) - span.SetKind(4) - spanAttrs := span.Attributes() - spanAttrs.PutStr("messaging.system", "SolacePubSub+") - spanAttrs.PutStr("messaging.operation", "send") - spanAttrs.PutStr("messaging.protocol", "AMQP") - spanAttrs.PutStr("messaging.protocol_version", "1.0") - spanAttrs.PutStr("messaging.source.name", "topicEndpointName") - spanAttrs.PutStr("messaging.source.kind", "topic-endpoint") - spanAttrs.PutStr("messaging.solace.client_username", "someOtherClientUsername") - spanAttrs.PutStr("messaging.solace.client_name", "someOtherClient1234") - spanAttrs.PutBool("messaging.solace.message_replayed", true) - spanAttrs.PutStr("messaging.solace.send.outcome", "rejected") - txnEvent := span.Events().AppendEmpty() - txnEvent.SetName("end") - txnEvent.SetTimestamp(223456789) - txnAttrs := txnEvent.Attributes() - txnAttrs.PutStr("messaging.solace.transaction_initiator", "client") - txnAttrs.PutStr("messaging.solace.transaction_xid", "0000007b-000814fe-804020100804020100") - return span - }(), + }, func() ptrace.Span { + // second send span + span := ptrace.NewSpan() + span.SetName("topicEndpointName send") + span.SetTraceID([16]byte{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}) + span.SetSpanID([8]byte{0, 1, 2, 3, 4, 5, 6, 7}) + span.SetParentSpanID([8]byte{7, 6, 5, 4, 3, 2, 1, 0}) + span.SetStartTimestamp(4234567890) + span.SetEndTimestamp(5234567890) + span.SetKind(4) + spanAttrs := span.Attributes() + spanAttrs.PutStr("messaging.system", "SolacePubSub+") + spanAttrs.PutStr("messaging.operation", "send") + spanAttrs.PutStr("messaging.protocol", "AMQP") + spanAttrs.PutStr("messaging.protocol_version", "1.0") + spanAttrs.PutStr("messaging.source.name", "topicEndpointName") + spanAttrs.PutStr("messaging.source.kind", "topic-endpoint") + spanAttrs.PutStr("messaging.solace.client_username", "someOtherClientUsername") + spanAttrs.PutStr("messaging.solace.client_name", "someOtherClient1234") + spanAttrs.PutBool("messaging.solace.message_replayed", true) + spanAttrs.PutStr("messaging.solace.send.outcome", "rejected") + txnEvent := span.Events().AppendEmpty() + txnEvent.SetName("end") + txnEvent.SetTimestamp(223456789) + txnAttrs := txnEvent.Attributes() + txnAttrs.PutStr("messaging.solace.transaction_initiator", "client") + txnAttrs.PutStr("messaging.solace.transaction_xid", "0000007b-000814fe-804020100804020100") + return span + }(), + }, } func TestEgressUnmarshallerEgressSpan(t *testing.T) { @@ -282,11 +292,11 @@ func TestEgressUnmarshallerEgressSpan(t *testing.T) { }, } var i = 1 - for spanDataRef, wantRef := range validEgressSpans { + for _, dataRef := range validEgressSpans { name := "valid span " + fmt.Sprint(i) i++ - want := wantRef - spanData := spanDataRef + want := dataRef.out + spanData := dataRef.in tests = append(tests, testCase{ name: name, spanData: spanData, diff --git a/receiver/solacereceiver/unmarshaller_test.go b/receiver/solacereceiver/unmarshaller_test.go index 6f1643e107ad0..fef0fa8eddf0d 100644 --- a/receiver/solacereceiver/unmarshaller_test.go +++ b/receiver/solacereceiver/unmarshaller_test.go @@ -280,8 +280,8 @@ func TestSolaceMessageUnmarshallerUnmarshal(t *testing.T) { EgressSpans: func() []*egress_v1.SpanData_EgressSpan { spans := make([]*egress_v1.SpanData_EgressSpan, len(validEgressSpans)) i := 0 - for spanRef := range validEgressSpans { - span := spanRef + for _, spanRef := range validEgressSpans { + span := spanRef.in spans[i] = span i++ } @@ -306,7 +306,7 @@ func TestSolaceMessageUnmarshallerUnmarshal(t *testing.T) { instrumentation := resource.ScopeSpans().AppendEmpty() // first send span for _, spanRef := range validEgressSpans { - span := spanRef + span := spanRef.out newSpan := instrumentation.Spans().AppendEmpty() span.CopyTo(newSpan) } From 73e2f3233306eb10b35a69737e2f71d507b2a272 Mon Sep 17 00:00:00 2001 From: Michael Cardy Date: Fri, 26 May 2023 09:11:31 -0400 Subject: [PATCH 09/10] Added changelog --- .chloggen/solace-send-spans.yaml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .chloggen/solace-send-spans.yaml diff --git a/.chloggen/solace-send-spans.yaml b/.chloggen/solace-send-spans.yaml new file mode 100644 index 0000000000000..b1ddcb7821e9d --- /dev/null +++ b/.chloggen/solace-send-spans.yaml @@ -0,0 +1,20 @@ +# Use this changelog template to create an entry for release notes. +# If your change doesn't affect end users, such as a test fix or a tooling change, +# you should instead start your pull request title with [chore] or use the "Skip Changelog" label. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: enhancement + +# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver) +component: solacereceiver + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: "Updated solacereceiver to handle new features of Solace PubSub+ 10.4.1" + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [22809] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: From 1311b295be83d4b3600465cc44cb4b4d01cc5dd2 Mon Sep 17 00:00:00 2001 From: Michael Cardy Date: Fri, 26 May 2023 10:18:08 -0400 Subject: [PATCH 10/10] Fixed make lint errors New copyright too --- receiver/solacereceiver/unmarshaller.go | 18 ++++++++++-------- receiver/solacereceiver/unmarshaller_egress.go | 13 +------------ .../solacereceiver/unmarshaller_egress_test.go | 17 +++-------------- .../solacereceiver/unmarshaller_receive.go | 13 +------------ .../unmarshaller_receive_test.go | 13 +------------ 5 files changed, 16 insertions(+), 58 deletions(-) diff --git a/receiver/solacereceiver/unmarshaller.go b/receiver/solacereceiver/unmarshaller.go index 54cbb307bbdd4..2793a63a7197b 100644 --- a/receiver/solacereceiver/unmarshaller.go +++ b/receiver/solacereceiver/unmarshaller.go @@ -76,12 +76,14 @@ func (u *solaceTracesUnmarshaller) unmarshal(message *inboundMessage) (ptrace.Tr } // otherwise we are an unknown version u.logger.Error("Received message with unsupported receive span version, an upgrade is required", zap.String("topic", *message.Properties.To)) - } else if strings.HasPrefix(topic[len(topicPrefix):], egressSpanPrefix) { - if strings.HasSuffix(topic, v1Suffix) { - return u.egressUnmarshallerV1.unmarshal(message) + } else { // make lint happy, wants two boolean expressions to be written as a switch?! + if strings.HasPrefix(topic[len(topicPrefix):], egressSpanPrefix) { + if strings.HasSuffix(topic, v1Suffix) { + return u.egressUnmarshallerV1.unmarshal(message) + } + } else { + u.logger.Error("Received message with unsupported topic, an upgrade is required", zap.String("topic", *message.Properties.To)) } - } else { - u.logger.Error("Received message with unsupported topic, an upgrade is required", zap.String("topic", *message.Properties.To)) } // if we don't know the type, we must upgrade return ptrace.Traces{}, errUpgradeRequired @@ -137,9 +139,9 @@ const ( // constant attributes const ( - systemAttrKey = "messaging.system" - systemAttrValue = "SolacePubSub+" - operationAttrKey = "messaging.operation" + systemAttrKey = "messaging.system" + systemAttrValue = "SolacePubSub+" + operationAttrKey = "messaging.operation" ) func setResourceSpanAttributes(attrMap pcommon.Map, routerName, version string, messageVpnName *string) { diff --git a/receiver/solacereceiver/unmarshaller_egress.go b/receiver/solacereceiver/unmarshaller_egress.go index 904b8c95e69db..068d209b77d2a 100644 --- a/receiver/solacereceiver/unmarshaller_egress.go +++ b/receiver/solacereceiver/unmarshaller_egress.go @@ -1,16 +1,5 @@ // Copyright The OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 package solacereceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/solacereceiver" diff --git a/receiver/solacereceiver/unmarshaller_egress_test.go b/receiver/solacereceiver/unmarshaller_egress_test.go index 76a053dded3dd..65545fdf741ba 100644 --- a/receiver/solacereceiver/unmarshaller_egress_test.go +++ b/receiver/solacereceiver/unmarshaller_egress_test.go @@ -1,17 +1,5 @@ // Copyright The OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - +// SPDX-License-Identifier: Apache-2.0 package solacereceiver import ( @@ -338,7 +326,8 @@ func TestEgressUnmarshallerSendSpanAttributes(t *testing.T) { base[key] = val } span := ptrace.NewSpan() - span.Attributes().FromRaw(base) + err := span.Attributes().FromRaw(base) + assert.NoError(t, err) span.SetName(name) span.SetKind(ptrace.SpanKindProducer) return span diff --git a/receiver/solacereceiver/unmarshaller_receive.go b/receiver/solacereceiver/unmarshaller_receive.go index 979ae310046d2..e3e29da79b6af 100644 --- a/receiver/solacereceiver/unmarshaller_receive.go +++ b/receiver/solacereceiver/unmarshaller_receive.go @@ -1,16 +1,5 @@ // Copyright The OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 package solacereceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/solacereceiver" diff --git a/receiver/solacereceiver/unmarshaller_receive_test.go b/receiver/solacereceiver/unmarshaller_receive_test.go index d6bd020d7306d..b4ed5312821ca 100644 --- a/receiver/solacereceiver/unmarshaller_receive_test.go +++ b/receiver/solacereceiver/unmarshaller_receive_test.go @@ -1,16 +1,5 @@ // Copyright The OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 package solacereceiver