diff --git a/.chloggen/solace-baggage.yaml b/.chloggen/solace-baggage.yaml new file mode 100644 index 000000000000..cbcde122d2d0 --- /dev/null +++ b/.chloggen/solace-baggage.yaml @@ -0,0 +1,16 @@ +# 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: Added baggage unmarshalling support (introduced in Solace PubSub+ Event Broker 10.2.1) + +# One or more tracking issues related to the change +issues: [16570] + +# (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: diff --git a/.chloggen/solace-flowctrl.yaml b/.chloggen/solace-flowctrl.yaml new file mode 100644 index 000000000000..6f6e62ae41aa --- /dev/null +++ b/.chloggen/solace-flowctrl.yaml @@ -0,0 +1,16 @@ +# 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: Added configurable retry interval for flow control scenarios + +# One or more tracking issues related to the change +issues: [16570] + +# (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: diff --git a/receiver/solacereceiver/README.md b/receiver/solacereceiver/README.md index f5f1ff2be5da..abc7b8b0d2ff 100644 --- a/receiver/solacereceiver/README.md +++ b/receiver/solacereceiver/README.md @@ -2,7 +2,7 @@ | Status | | |--------------------------|-----------| -| Stability | [alpha] | +| Stability | [beta] | | Supported pipeline types | traces | | Distributions | [contrib] | @@ -47,6 +47,9 @@ The configuration parameters are: - username (The username to use; required for sasl_xauth2 authentication) - bearer (The bearer token in plain text; required for sasl_xauth2 authentication) - sasl_external (SASL External required to be used for TLS client cert authentication. When this authentication type is chosen then tls cert_file and key_file are required) +- flow_control (Configures the behaviour to use when temporary errors are encountered from the next component) + - delayed_retry (Default flow control strategy. Sets the flow control strategy to delayed retry which will wait before trying to push the message to the next component again) + - delay (The delay, e.g. 10ms, to wait before retrying. Default is 10ms) ### Examples: Simple single node configuration with SASL plain authentication (TLS enabled by default) @@ -92,5 +95,5 @@ service: receivers: [solace/primary,solace/backup] ``` -[alpha]:https://github.com/open-telemetry/opentelemetry-collector#alpha +[beta]:https://github.com/open-telemetry/opentelemetry-collector#beta [contrib]:https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib diff --git a/receiver/solacereceiver/config.go b/receiver/solacereceiver/config.go index 77921da3b48f..844262634074 100644 --- a/receiver/solacereceiver/config.go +++ b/receiver/solacereceiver/config.go @@ -17,6 +17,7 @@ package solacereceiver // import "github.com/open-telemetry/opentelemetry-collec import ( "errors" "strings" + "time" "go.opentelemetry.io/collector/config" "go.opentelemetry.io/collector/config/configtls" @@ -28,10 +29,12 @@ const ( ) var ( - errMissingAuthDetails = errors.New("authentication details are required, either for plain user name password or XOAUTH2 or client certificate") - errMissingQueueName = errors.New("queue definition is required, queue definition has format queue://") - errMissingPlainTextParams = errors.New("missing plain text auth params: Username, Password") - errMissingXauth2Params = errors.New("missing xauth2 text auth params: Username, Bearer") + errMissingAuthDetails = errors.New("authentication details are required, either for plain user name password or XOAUTH2 or client certificate") + errMissingQueueName = errors.New("queue definition is required, queue definition has format queue://") + errMissingPlainTextParams = errors.New("missing plain text auth params: Username, Password") + errMissingXauth2Params = errors.New("missing xauth2 text auth params: Username, Bearer") + errMissingFlowControl = errors.New("missing flow control configuration: DelayedRetry must be selected") + errInvalidDelayedRetryDelay = errors.New("delayed_retry.delay must > 0") ) // Config defines configuration for Solace receiver. @@ -49,6 +52,8 @@ type Config struct { TLS configtls.TLSClientSetting `mapstructure:"tls,omitempty"` Auth Authentication `mapstructure:"auth"` + + Flow FlowControl `mapstructure:"flow_control"` } // Validate checks the receiver configuration is valid @@ -59,6 +64,11 @@ func (cfg *Config) Validate() error { if len(strings.TrimSpace(cfg.Queue)) == 0 { return errMissingQueueName } + if cfg.Flow.DelayedRetry == nil { + return errMissingFlowControl + } else if cfg.Flow.DelayedRetry.Delay <= 0 { + return errInvalidDelayedRetryDelay + } return nil } @@ -84,3 +94,13 @@ type SaslXAuth2Config struct { // SaslExternalConfig defines the configuration for the SASL External used in conjunction with TLS client authentication. type SaslExternalConfig struct { } + +// FlowControl defines the configuration for what to do in backpressure scenarios, e.g. memorylimiter errors +type FlowControl struct { + DelayedRetry *FlowControlDelayedRetry `mapstructure:"delayed_retry"` +} + +// FlowControlDelayedRetry represents the strategy of waiting for a defined amount of time (in time.Duration) and attempt redelivery +type FlowControlDelayedRetry struct { + Delay time.Duration `mapstructure:"delay"` +} diff --git a/receiver/solacereceiver/config_test.go b/receiver/solacereceiver/config_test.go index 3e1ac776ec6f..e83b7939d1dd 100644 --- a/receiver/solacereceiver/config_test.go +++ b/receiver/solacereceiver/config_test.go @@ -17,6 +17,7 @@ package solacereceiver // import "github.com/open-telemetry/opentelemetry-collec import ( "path/filepath" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -54,6 +55,11 @@ func TestLoadConfig(t *testing.T) { Insecure: false, InsecureSkipVerify: false, }, + Flow: FlowControl{ + DelayedRetry: &FlowControlDelayedRetry{ + Delay: 1 * time.Second, + }, + }, }, }, { @@ -99,6 +105,27 @@ func TestConfigValidateMissingQueue(t *testing.T) { assert.Equal(t, errMissingQueueName, err) } +func TestConfigValidateMissingFlowControl(t *testing.T) { + cfg := createDefaultConfig().(*Config) + cfg.Queue = "someQueue" + cfg.Auth.PlainText = &SaslPlainTextConfig{"Username", "Password"} + // this should never happen in reality, test validation anyway + cfg.Flow.DelayedRetry = nil + err := cfg.Validate() + assert.Equal(t, errMissingFlowControl, err) +} + +func TestConfigValidateInvalidFlowControlDelayedRetryDelay(t *testing.T) { + cfg := createDefaultConfig().(*Config) + cfg.Queue = "someQueue" + cfg.Auth.PlainText = &SaslPlainTextConfig{"Username", "Password"} + cfg.Flow.DelayedRetry = &FlowControlDelayedRetry{ + Delay: -30 * time.Second, + } + err := cfg.Validate() + assert.Equal(t, errInvalidDelayedRetryDelay, err) +} + func TestConfigValidateSuccess(t *testing.T) { successCases := map[string]func(*Config){ "With Plaintext Auth": func(c *Config) { diff --git a/receiver/solacereceiver/factory.go b/receiver/solacereceiver/factory.go index fcccf3b1148b..ed1ffacfced3 100644 --- a/receiver/solacereceiver/factory.go +++ b/receiver/solacereceiver/factory.go @@ -16,6 +16,7 @@ package solacereceiver // import "github.com/open-telemetry/opentelemetry-collec import ( "context" + "time" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config" @@ -54,6 +55,11 @@ func createDefaultConfig() component.Config { InsecureSkipVerify: false, Insecure: false, }, + Flow: FlowControl{ + DelayedRetry: &FlowControlDelayedRetry{ + Delay: 10 * time.Millisecond, + }, + }, } } diff --git a/receiver/solacereceiver/go.mod b/receiver/solacereceiver/go.mod index 016868ec85e1..a03bbf016dd3 100644 --- a/receiver/solacereceiver/go.mod +++ b/receiver/solacereceiver/go.mod @@ -25,6 +25,7 @@ require ( go.opentelemetry.io/collector/confmap v0.0.0-20221201172708-2bdff61fa52a go.opentelemetry.io/collector/consumer v0.66.1-0.20221202005155-1c54042beb70 go.opentelemetry.io/collector/pdata v0.66.1-0.20221202005155-1c54042beb70 + go.opentelemetry.io/otel v1.11.1 go.uber.org/atomic v1.10.0 go.uber.org/zap v1.24.0 google.golang.org/protobuf v1.28.1 @@ -45,7 +46,6 @@ require ( github.com/pelletier/go-toml v1.9.3 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect go.opentelemetry.io/collector/featuregate v0.66.1-0.20221202005155-1c54042beb70 // indirect - go.opentelemetry.io/otel v1.11.1 // indirect go.opentelemetry.io/otel/metric v0.33.0 // indirect go.opentelemetry.io/otel/trace v1.11.1 // indirect go.uber.org/multierr v1.8.0 // indirect diff --git a/receiver/solacereceiver/model/receive_v1.proto b/receiver/solacereceiver/model/receive_v1.proto index f63284a713bf..8c9cf69c2dad 100755 --- a/receiver/solacereceiver/model/receive_v1.proto +++ b/receiver/solacereceiver/model/receive_v1.proto @@ -2,17 +2,12 @@ syntax = "proto3"; package solace.messaging.proto.broker.trace.receive.v1; -// 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[/ optional string trace_state = 17; + // A baggage string formatted as described here: + // https://www.w3.org/TR/baggage/#x3-2-1-1-baggage-string + // This string may be truncated if the complete string, as received, would + // cause the broker's limit for application message properties to be exceeded. + // See dropped_application_message_properties for more details. + optional string baggage = 39; + // 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 = 3; @@ -151,13 +156,15 @@ message SpanData { map user_properties = 14; // Application message properties refers to the collection of: + // * trace_state // * application_message_id // * correlation_id + // * baggage // * user_properties - // If dropped_application_message_properties is true, not all application - // message properties in the original message were captured in the fields - // above because limits were exceeded. The broker supports up to a total of - // 8KiB of application message properties. + // The broker supports up to a total of 8KiB of application message + // properties. If the total amount of application message properties in the + // message being traced exceeds this limit, this flag is used to indicate + // some properties were dropped. bool dropped_application_message_properties = 37; // If present, this indicates the message is being rejected to the publisher @@ -333,13 +340,21 @@ message SpanData { // destination, but it is not being enqueued due to the description. optional string error_description = 4; - // This will never be set when there is not an error_desription present. - // If this is set, it indicates that all other non-errored enqueue events - // part of this span are rejected. In other words, regardless of what some - // enqueue events may indicate, the message is not enqueued to any - // destinations. When this is set, the span's error_description is always - // set and the span's error_description is always sent to the publisher in - // the rejection message. + // This flag being set on one or more enqueue events for a message implies + // that the message is not enqueued to any destination, regardless of the + // presence of successful enqueue events in the span. + // + // This will never be set when there is not an error_description present. If + // this is set, it indicates that the error described by error_description + // is a cause for the message to be rejected. + // + // Rejected non-transacted messages cause the message to be nacked to the + // publisher and rejected transacted messages result in a change in + // transacted session state that will cause a future commit attempt to fail. + // + // The cause for message rejection indicated to the client in either a + // message nack or commit failure response is the error_description of the + // first enqueue event that has this flag set. bool rejects_all_enqueues = 5; } -} +} \ No newline at end of file diff --git a/receiver/solacereceiver/model/v1/receive_v1.pb.go b/receiver/solacereceiver/model/v1/receive_v1.pb.go index f75d216bfefe..6f2b5bc0fcd5 100644 --- a/receiver/solacereceiver/model/v1/receive_v1.pb.go +++ b/receiver/solacereceiver/model/v1/receive_v1.pb.go @@ -228,7 +228,7 @@ func (SpanData_TransactionEvent_Initiator) EnumDescriptor() ([]byte, []int) { // Special priority is given to fields that can be repeated. // - Field numbers 16+ are used for other attributes. // -// Next available field ID: 39 +// Next available field ID: 40 // type SpanData struct { state protoimpl.MessageState @@ -242,8 +242,16 @@ type SpanData struct { 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,16,opt,name=parent_span_id,json=parentSpanId,proto3,oneof" json:"parent_span_id,omitempty"` - TraceState *string `protobuf:"bytes,17,opt,name=trace_state,json=traceState,proto3,oneof" json:"trace_state,omitempty"` + ParentSpanId []byte `protobuf:"bytes,16,opt,name=parent_span_id,json=parentSpanId,proto3,oneof" json:"parent_span_id,omitempty"` + // tracestate string value, as per + // + TraceState *string `protobuf:"bytes,17,opt,name=trace_state,json=traceState,proto3,oneof" json:"trace_state,omitempty"` + // A baggage string formatted as described here: + // https://www.w3.org/TR/baggage/#x3-2-1-1-baggage-string + // This string may be truncated if the complete string, as received, would + // cause the broker's limit for application message properties to be exceeded. + // See dropped_application_message_properties for more details. + Baggage *string `protobuf:"bytes,39,opt,name=baggage,proto3,oneof" json:"baggage,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,3,opt,name=start_time_unix_nano,json=startTimeUnixNano,proto3" json:"start_time_unix_nano,omitempty"` @@ -335,13 +343,15 @@ type SpanData struct { // captured. UserProperties map[string]*SpanData_UserPropertyValue `protobuf:"bytes,14,rep,name=user_properties,json=userProperties,proto3" json:"user_properties,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // Application message properties refers to the collection of: + // * trace_state // * application_message_id // * correlation_id + // * baggage // * user_properties - // If dropped_application_message_properties is true, not all application - // message properties in the original message were captured in the fields - // above because limits were exceeded. The broker supports up to a total of - // 8KiB of application message properties. + // The broker supports up to a total of 8KiB of application message + // properties. If the total amount of application message properties in the + // message being traced exceeds this limit, this flag is used to indicate + // some properties were dropped. DroppedApplicationMessageProperties bool `protobuf:"varint,37,opt,name=dropped_application_message_properties,json=droppedApplicationMessageProperties,proto3" json:"dropped_application_message_properties,omitempty"` // If present, this indicates the message is being rejected to the publisher // and matches the error string provided back to the publisher as an error. @@ -428,6 +438,13 @@ func (x *SpanData) GetTraceState() string { return "" } +func (x *SpanData) GetBaggage() string { + if x != nil && x.Baggage != nil { + return *x.Baggage + } + return "" +} + func (x *SpanData) GetStartTimeUnixNano() int64 { if x != nil { return x.StartTimeUnixNano @@ -1334,7 +1351,7 @@ var file_receive_v1_proto_rawDesc = []byte{ 0x74, 0x6f, 0x12, 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, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x2e, - 0x76, 0x31, 0x22, 0xbc, 0x20, 0x0a, 0x08, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, + 0x76, 0x31, 0x22, 0xe7, 0x20, 0x0a, 0x08, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 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, @@ -1343,258 +1360,261 @@ var file_receive_v1_proto_rawDesc = []byte{ 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x70, 0x61, 0x6e, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x24, 0x0a, 0x0b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0a, 0x74, 0x72, 0x61, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, - 0x65, 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, 0x03, 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, 0x04, 0x20, 0x01, 0x28, - 0x10, 0x52, 0x0f, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x78, 0x4e, 0x61, - 0x6e, 0x6f, 0x12, 0x40, 0x0a, 0x1d, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x63, - 0x65, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x6e, - 0x61, 0x6e, 0x6f, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x10, 0x52, 0x19, 0x62, 0x72, 0x6f, 0x6b, 0x65, - 0x72, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x78, - 0x4e, 0x61, 0x6e, 0x6f, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x29, 0x0a, 0x0e, 0x72, 0x65, - 0x70, 0x6c, 0x79, 0x5f, 0x74, 0x6f, 0x5f, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x12, 0x20, 0x01, - 0x28, 0x09, 0x48, 0x02, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x54, 0x6f, 0x54, 0x6f, 0x70, - 0x69, 0x63, 0x88, 0x01, 0x01, 0x12, 0x6a, 0x0a, 0x0d, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, - 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x45, 0x2e, 0x73, + 0x65, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x62, 0x61, 0x67, 0x67, 0x61, 0x67, 0x65, 0x18, + 0x27, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x07, 0x62, 0x61, 0x67, 0x67, 0x61, 0x67, 0x65, + 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, 0x03, 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, 0x04, 0x20, 0x01, 0x28, 0x10, + 0x52, 0x0f, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x78, 0x4e, 0x61, 0x6e, + 0x6f, 0x12, 0x40, 0x0a, 0x1d, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x63, 0x65, + 0x69, 0x76, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x6e, 0x61, + 0x6e, 0x6f, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x10, 0x52, 0x19, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, + 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x78, 0x4e, + 0x61, 0x6e, 0x6f, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x29, 0x0a, 0x0e, 0x72, 0x65, 0x70, + 0x6c, 0x79, 0x5f, 0x74, 0x6f, 0x5f, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x12, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x03, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x54, 0x6f, 0x54, 0x6f, 0x70, 0x69, + 0x63, 0x88, 0x01, 0x01, 0x12, 0x6a, 0x0a, 0x0d, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, + 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x45, 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, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, + 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x4d, 0x6f, + 0x64, 0x65, 0x52, 0x0c, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x4d, 0x6f, 0x64, 0x65, + 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x14, 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, 0x15, 0x20, 0x01, 0x28, 0x09, 0x48, 0x04, 0x52, 0x0e, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x56, 0x70, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, + 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x6f, 0x6c, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x26, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x6f, 0x6c, 0x6f, 0x73, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x17, 0x0a, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x06, 0x68, 0x6f, 0x73, 0x74, 0x49, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x68, 0x6f, 0x73, 0x74, + 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x68, 0x6f, 0x73, + 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x69, 0x70, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x65, 0x65, 0x72, 0x49, 0x70, 0x12, 0x1b, + 0x0a, 0x09, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x08, 0x70, 0x65, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x44, 0x0a, 0x1c, 0x72, + 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, + 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x16, 0x20, 0x01, 0x28, + 0x0c, 0x48, 0x05, 0x52, 0x19, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x88, 0x01, + 0x01, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x17, 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, 0x18, 0x20, 0x01, 0x28, 0x09, 0x48, 0x06, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x21, 0x0a, + 0x0c, 0x64, 0x6d, 0x71, 0x5f, 0x65, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x6c, 0x65, 0x18, 0x19, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0b, 0x64, 0x6d, 0x71, 0x45, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x6c, 0x65, + 0x12, 0x1f, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x1a, 0x20, 0x01, + 0x28, 0x0d, 0x48, 0x07, 0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x88, 0x01, + 0x01, 0x12, 0x15, 0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x03, 0x48, 0x08, + 0x52, 0x03, 0x74, 0x74, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x34, 0x0a, 0x16, 0x62, 0x69, 0x6e, 0x61, + 0x72, 0x79, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x69, + 0x7a, 0x65, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x14, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, + 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x2e, + 0x0a, 0x13, 0x78, 0x6d, 0x6c, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, + 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x78, 0x6d, 0x6c, + 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x23, + 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, + 0x1e, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x53, + 0x69, 0x7a, 0x65, 0x12, 0x39, 0x0a, 0x16, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x1f, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x09, 0x52, 0x14, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x2a, + 0x0a, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x48, 0x0a, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x75, 0x0a, 0x0f, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x0e, 0x20, + 0x03, 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, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x55, 0x73, + 0x65, 0x72, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, + 0x73, 0x12, 0x53, 0x0a, 0x26, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x61, 0x70, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x25, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x23, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x70, + 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x21, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x10, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x7b, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x22, 0x20, 0x01, 0x28, 0x0b, 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, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 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, 0x0b, 0x52, 0x10, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x88, 0x01, 0x01, + 0x12, 0x6c, 0x0a, 0x0e, 0x65, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 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, 0x72, + 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, + 0x74, 0x61, 0x2e, 0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, + 0x0d, 0x65, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x43, + 0x0a, 0x1e, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x71, 0x75, 0x65, 0x75, + 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x18, 0x23, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x1b, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x45, + 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x53, 0x75, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x12, 0x41, 0x0a, 0x1d, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x65, + 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x66, 0x61, + 0x69, 0x6c, 0x65, 0x64, 0x18, 0x24, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x1a, 0x64, 0x72, 0x6f, 0x70, + 0x70, 0x65, 0x64, 0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, + 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x1a, 0x8d, 0x01, 0x0a, 0x13, 0x55, 0x73, 0x65, 0x72, 0x50, + 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x60, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x4a, 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, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, + 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0xec, 0x04, 0x0a, 0x11, 0x55, 0x73, 0x65, 0x72, 0x50, + 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0a, + 0x6e, 0x75, 0x6c, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x48, 0x00, 0x52, 0x09, 0x6e, 0x75, 0x6c, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, + 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x08, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, + 0x0a, 0x0b, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, 0x0b, 0x75, 0x69, 0x6e, 0x74, 0x31, + 0x36, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, + 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, 0x0b, + 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x75, + 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x04, 0x48, 0x00, 0x52, 0x0b, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x1f, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x11, 0x48, 0x00, 0x52, 0x09, 0x69, 0x6e, 0x74, 0x38, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x21, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x11, 0x48, 0x00, 0x52, 0x0a, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x11, 0x48, 0x00, 0x52, 0x0a, 0x69, 0x6e, 0x74, + 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x36, 0x34, + 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x12, 0x48, 0x00, 0x52, 0x0a, + 0x69, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x29, 0x0a, 0x0f, 0x63, 0x68, + 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, 0x0e, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x73, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x29, 0x0a, 0x0f, 0x62, 0x79, + 0x74, 0x65, 0x41, 0x72, 0x72, 0x61, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0d, 0x20, + 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0e, 0x62, 0x79, 0x74, 0x65, 0x41, 0x72, 0x72, 0x61, 0x79, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0b, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x5f, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x02, 0x48, 0x00, 0x52, 0x0a, 0x66, 0x6c, + 0x6f, 0x61, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x64, 0x6f, 0x75, 0x62, + 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x01, 0x48, 0x00, + 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2d, 0x0a, + 0x11, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x10, 0x64, 0x65, 0x73, 0x74, + 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x07, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0xc2, 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, 0x62, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4e, + 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, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 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, 0x71, 0x0a, 0x09, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, + 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x53, 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, 0x72, 0x65, + 0x63, 0x65, 0x69, 0x76, 0x65, 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, 0x61, 0x0a, 0x03, 0x78, 0x69, 0x64, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 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, 0x72, 0x65, 0x63, 0x65, 0x69, + 0x76, 0x65, 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, 0x79, 0x0a, 0x08, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x5c, 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, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, - 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x4d, - 0x6f, 0x64, 0x65, 0x52, 0x0c, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x4d, 0x6f, 0x64, - 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x14, 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, 0x15, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x0e, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x56, 0x70, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x88, 0x01, - 0x01, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x6f, 0x6c, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x26, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x6f, 0x6c, 0x6f, 0x73, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, - 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x17, 0x0a, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x06, 0x68, 0x6f, 0x73, 0x74, 0x49, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x68, 0x6f, 0x73, - 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x68, 0x6f, - 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x69, - 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x65, 0x65, 0x72, 0x49, 0x70, 0x12, - 0x1b, 0x0a, 0x09, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x08, 0x70, 0x65, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x44, 0x0a, 0x1c, - 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x16, 0x20, 0x01, - 0x28, 0x0c, 0x48, 0x04, 0x52, 0x19, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x88, - 0x01, 0x01, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x17, - 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, 0x18, 0x20, 0x01, 0x28, 0x09, 0x48, 0x05, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x21, - 0x0a, 0x0c, 0x64, 0x6d, 0x71, 0x5f, 0x65, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x6c, 0x65, 0x18, 0x19, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x64, 0x6d, 0x71, 0x45, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x6c, - 0x65, 0x12, 0x1f, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x1a, 0x20, - 0x01, 0x28, 0x0d, 0x48, 0x06, 0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x88, - 0x01, 0x01, 0x12, 0x15, 0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x03, 0x48, - 0x07, 0x52, 0x03, 0x74, 0x74, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x34, 0x0a, 0x16, 0x62, 0x69, 0x6e, - 0x61, 0x72, 0x79, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x73, - 0x69, 0x7a, 0x65, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x14, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x12, - 0x2e, 0x0a, 0x13, 0x78, 0x6d, 0x6c, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, - 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x78, 0x6d, - 0x6c, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x12, - 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x69, 0x7a, 0x65, - 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x53, 0x69, 0x7a, 0x65, 0x12, 0x39, 0x0a, 0x16, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x1f, - 0x20, 0x01, 0x28, 0x09, 0x48, 0x08, 0x52, 0x14, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, - 0x2a, 0x0a, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x48, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x75, 0x0a, 0x0f, 0x75, - 0x73, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x0e, - 0x20, 0x03, 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, 0x72, 0x65, 0x63, 0x65, 0x69, - 0x76, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x55, - 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, - 0x65, 0x73, 0x12, 0x53, 0x0a, 0x26, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x61, 0x70, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x25, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x23, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x72, 0x6f, - 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x21, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x10, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x7b, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x22, 0x20, 0x01, 0x28, 0x0b, 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, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 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, 0x0a, 0x52, 0x10, 0x74, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x88, 0x01, - 0x01, 0x12, 0x6c, 0x0a, 0x0e, 0x65, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 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, - 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, - 0x61, 0x74, 0x61, 0x2e, 0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x52, 0x0d, 0x65, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, - 0x43, 0x0a, 0x1e, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x71, 0x75, 0x65, - 0x75, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x18, 0x23, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x1b, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, - 0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x53, 0x75, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x12, 0x41, 0x0a, 0x1d, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, - 0x65, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x66, - 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x24, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x1a, 0x64, 0x72, 0x6f, - 0x70, 0x70, 0x65, 0x64, 0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x73, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x1a, 0x8d, 0x01, 0x0a, 0x13, 0x55, 0x73, 0x65, 0x72, - 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x60, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x4a, 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, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x50, - 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0xec, 0x04, 0x0a, 0x11, 0x55, 0x73, 0x65, 0x72, - 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, - 0x0a, 0x6e, 0x75, 0x6c, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x48, 0x00, 0x52, 0x09, 0x6e, 0x75, 0x6c, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, - 0x0a, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x21, 0x0a, 0x0b, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, 0x0b, 0x75, 0x69, 0x6e, 0x74, - 0x31, 0x36, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x33, - 0x32, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, - 0x0b, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, - 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x04, 0x48, 0x00, 0x52, 0x0b, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x12, 0x1f, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x11, 0x48, 0x00, 0x52, 0x09, 0x69, 0x6e, 0x74, 0x38, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x11, 0x48, 0x00, 0x52, 0x0a, 0x69, 0x6e, 0x74, 0x31, 0x36, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x11, 0x48, 0x00, 0x52, 0x0a, 0x69, 0x6e, - 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x36, - 0x34, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x12, 0x48, 0x00, 0x52, - 0x0a, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x29, 0x0a, 0x0f, 0x63, - 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0b, - 0x20, 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, 0x0e, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, - 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, - 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x29, 0x0a, 0x0f, 0x62, - 0x79, 0x74, 0x65, 0x41, 0x72, 0x72, 0x61, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0d, - 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0e, 0x62, 0x79, 0x74, 0x65, 0x41, 0x72, 0x72, 0x61, - 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0b, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x5f, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x02, 0x48, 0x00, 0x52, 0x0a, 0x66, - 0x6c, 0x6f, 0x61, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x64, 0x6f, 0x75, - 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x01, 0x48, - 0x00, 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2d, - 0x0a, 0x11, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x10, 0x64, 0x65, 0x73, - 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x07, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0xc2, 0x07, 0x0a, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x74, + 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, 0x1a, 0x89, 0x02, 0x0a, 0x0c, 0x45, + 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 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, 0x62, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x4e, 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, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 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, 0x71, 0x0a, 0x09, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, - 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x53, 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, 0x72, - 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 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, 0x61, 0x0a, 0x03, 0x78, 0x69, 0x64, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 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, 0x72, 0x65, 0x63, 0x65, - 0x69, 0x76, 0x65, 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, 0x79, 0x0a, 0x08, 0x6c, - 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x5c, 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, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 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, 0x1a, 0x89, 0x02, 0x0a, 0x0c, - 0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 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, 0x1f, 0x0a, 0x0a, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x02, 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, 0x03, 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, 0x30, 0x0a, 0x11, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x64, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 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, 0x12, 0x30, 0x0a, 0x14, 0x72, 0x65, 0x6a, 0x65, 0x63, - 0x74, 0x73, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x65, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x73, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x41, 0x6c, - 0x6c, 0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x73, 0x42, 0x06, 0x0a, 0x04, 0x64, 0x65, 0x73, - 0x74, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x64, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x0a, 0x0c, 0x44, 0x65, 0x6c, 0x69, 0x76, - 0x65, 0x72, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x45, 0x52, 0x53, 0x49, - 0x53, 0x54, 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4e, 0x4f, 0x4e, 0x5f, 0x50, - 0x45, 0x52, 0x53, 0x49, 0x53, 0x54, 0x45, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x44, - 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x02, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x70, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x5f, 0x73, 0x70, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x74, - 0x72, 0x61, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x72, - 0x65, 0x70, 0x6c, 0x79, 0x5f, 0x74, 0x6f, 0x5f, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x42, 0x13, 0x0a, - 0x11, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x70, 0x6e, 0x5f, 0x6e, 0x61, - 0x6d, 0x65, 0x42, 0x1f, 0x0a, 0x1d, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x5f, 0x69, 0x64, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, - 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x72, 0x69, - 0x6f, 0x72, 0x69, 0x74, 0x79, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x74, 0x74, 0x6c, 0x42, 0x19, 0x0a, - 0x17, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x63, 0x6f, 0x72, - 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 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, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x12, 0x1f, 0x0a, 0x0a, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x02, 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, 0x03, 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, 0x30, 0x0a, 0x11, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 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, 0x12, 0x30, 0x0a, 0x14, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, + 0x73, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x65, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x73, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x41, 0x6c, 0x6c, + 0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x73, 0x42, 0x06, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x74, + 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x0a, 0x0c, 0x44, 0x65, 0x6c, 0x69, 0x76, 0x65, + 0x72, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x45, 0x52, 0x53, 0x49, 0x53, + 0x54, 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4e, 0x4f, 0x4e, 0x5f, 0x50, 0x45, + 0x52, 0x53, 0x49, 0x53, 0x54, 0x45, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x49, + 0x52, 0x45, 0x43, 0x54, 0x10, 0x02, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x5f, 0x73, 0x70, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x74, 0x72, + 0x61, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x62, 0x61, + 0x67, 0x67, 0x61, 0x67, 0x65, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x5f, + 0x74, 0x6f, 0x5f, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x70, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x1f, 0x0a, + 0x1d, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x67, 0x72, + 0x6f, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x42, 0x13, + 0x0a, 0x11, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, + 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x74, 0x74, 0x6c, 0x42, 0x19, 0x0a, 0x17, 0x5f, 0x61, 0x70, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x5f, 0x69, 0x64, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 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, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/receiver/solacereceiver/observability.go b/receiver/solacereceiver/observability.go index 3ad93ce87a2c..6bf043b0fddf 100644 --- a/receiver/solacereceiver/observability.go +++ b/receiver/solacereceiver/observability.go @@ -40,6 +40,13 @@ const ( receiverStateTerminated ) +type flowControlState uint8 + +const ( + flowControlStateClear flowControlState = iota + flowControlStateControlled +) + type opencensusMetrics struct { stats struct { failedReconnections *stats.Int64Measure @@ -50,6 +57,10 @@ type opencensusMetrics struct { reportedSpans *stats.Int64Measure receiverStatus *stats.Int64Measure needUpgrade *stats.Int64Measure + flowControlStatus *stats.Int64Measure + flowControlRecentRetries *stats.Int64Measure + flowControlTotal *stats.Int64Measure + flowControlSingleSuccess *stats.Int64Measure } views struct { failedReconnections *view.View @@ -60,6 +71,10 @@ type opencensusMetrics struct { reportedSpans *view.View receiverStatus *view.View needUpgrade *view.View + flowControlStatus *view.View + flowControlRecentRetries *view.View + flowControlTotal *view.View + flowControlSingleSuccess *view.View } } @@ -80,6 +95,11 @@ func newOpenCensusMetrics(instanceName string) (*opencensusMetrics, error) { m.stats.receiverStatus = stats.Int64(prefix+"receiver_status", "Indicates the status of the receiver as an enum. 0 = starting, 1 = connecting, 2 = connected, 3 = disabled (often paired with needs_upgrade), 4 = terminating, 5 = terminated", stats.UnitDimensionless) m.stats.needUpgrade = stats.Int64(prefix+"need_upgrade", "Indicates with value 1 that receiver requires an upgrade and is not compatible with messages received from a broker", stats.UnitDimensionless) + m.stats.flowControlStatus = stats.Int64(prefix+"receiver_flow_control_status", "Indicates the flow control status of the receiver. 0 = not flow controlled, 1 = currently flow controlled", stats.UnitDimensionless) + m.stats.flowControlRecentRetries = stats.Int64(prefix+"receiver_flow_control_recent_retries", "Most recent/current retry count when flow controlled", stats.UnitDimensionless) + 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.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()) @@ -89,6 +109,11 @@ func newOpenCensusMetrics(instanceName string) (*opencensusMetrics, error) { m.views.receiverStatus = fromMeasure(m.stats.receiverStatus, view.LastValue()) m.views.needUpgrade = fromMeasure(m.stats.needUpgrade, view.LastValue()) + m.views.flowControlStatus = fromMeasure(m.stats.flowControlStatus, view.LastValue()) + m.views.flowControlRecentRetries = fromMeasure(m.stats.flowControlRecentRetries, view.LastValue()) + m.views.flowControlTotal = fromMeasure(m.stats.flowControlTotal, view.Count()) + m.views.flowControlSingleSuccess = fromMeasure(m.stats.flowControlSingleSuccess, view.Count()) + err := view.Register( m.views.failedReconnections, m.views.recoverableUnmarshallingErrors, @@ -98,6 +123,10 @@ func newOpenCensusMetrics(instanceName string) (*opencensusMetrics, error) { m.views.reportedSpans, m.views.receiverStatus, m.views.needUpgrade, + m.views.flowControlStatus, + m.views.flowControlRecentRetries, + m.views.flowControlTotal, + m.views.flowControlSingleSuccess, ) if err != nil { return nil, err @@ -157,3 +186,19 @@ func (m *opencensusMetrics) recordReceiverStatus(status receiverState) { func (m *opencensusMetrics) recordNeedUpgrade() { stats.Record(context.Background(), m.stats.needUpgrade.M(1)) } + +func (m *opencensusMetrics) recordFlowControlStatus(status flowControlState) { + stats.Record(context.Background(), m.stats.flowControlStatus.M(int64(status))) +} + +func (m *opencensusMetrics) recordFlowControlRecentRetries(retries int64) { + stats.Record(context.Background(), m.stats.flowControlRecentRetries.M(retries)) +} + +func (m *opencensusMetrics) recordFlowControlTotal() { + stats.Record(context.Background(), m.stats.flowControlTotal.M(1)) +} + +func (m *opencensusMetrics) recordFlowControlSingleSuccess() { + stats.Record(context.Background(), m.stats.flowControlSingleSuccess.M(1)) +} diff --git a/receiver/solacereceiver/observability_test.go b/receiver/solacereceiver/observability_test.go index 33cc770d4408..97e9e005920c 100644 --- a/receiver/solacereceiver/observability_test.go +++ b/receiver/solacereceiver/observability_test.go @@ -45,6 +45,14 @@ func TestRecordMetrics(t *testing.T) { metrics.recordReceiverStatus(receiverStateTerminated) }, metrics.views.receiverStatus, metrics.stats.receiverStatus, 3, int(receiverStateTerminated)}, {metrics.recordNeedUpgrade, metrics.views.needUpgrade, metrics.stats.needUpgrade, 3, 1}, + {func() { + metrics.recordFlowControlStatus(flowControlStateControlled) + }, metrics.views.flowControlStatus, metrics.stats.flowControlStatus, 3, 1}, + {func() { + metrics.recordFlowControlRecentRetries(5) + }, 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}, } for _, tc := range testCases { t.Run(tc.m.Name(), func(t *testing.T) { diff --git a/receiver/solacereceiver/receiver.go b/receiver/solacereceiver/receiver.go index ca5322217217..47820a022298 100644 --- a/receiver/solacereceiver/receiver.go +++ b/receiver/solacereceiver/receiver.go @@ -17,6 +17,7 @@ package solacereceiver // import "github.com/open-telemetry/opentelemetry-collec import ( "context" "errors" + "fmt" "sync" "time" @@ -89,6 +90,7 @@ func newTracesReceiver(config *Config, set component.ReceiverCreateSettings, nex // Start implements component.Receiver::Start func (s *solaceTracesReceiver) Start(_ context.Context, _ component.Host) error { s.metrics.recordReceiverStatus(receiverStateStarting) + s.metrics.recordFlowControlStatus(flowControlStateClear) var cancelableContext context.Context cancelableContext, s.cancel = context.WithCancel(context.Background()) @@ -158,7 +160,7 @@ reconnectionLoop: if err := s.receiveMessages(ctx, service); err != nil { s.settings.Logger.Debug("Encountered error while receiving messages", zap.Error(err)) - if errors.Is(err, errUnknownTraceMessgeVersion) { + if errors.Is(err, errUpgradeRequired) { s.metrics.recordNeedUpgrade() disable = true return @@ -207,8 +209,10 @@ func (s *solaceTracesReceiver) receiveMessage(ctx context.Context, service messa // only set the disposition action after we have received a message successfully disposition := service.accept defer func() { // on return of receiveMessage, we want to either ack or nack the message - if actionErr := disposition(ctx, msg); err == nil && actionErr != nil { - err = actionErr + if disposition != nil { + if actionErr := disposition(ctx, msg); err == nil && actionErr != nil { + err = actionErr + } } }() // message received successfully @@ -218,26 +222,57 @@ func (s *solaceTracesReceiver) receiveMessage(ctx context.Context, service messa if unmarshalErr != nil { s.settings.Logger.Error("Encountered error while unmarshalling message", zap.Error(unmarshalErr)) s.metrics.recordFatalUnmarshallingError() - if errors.Is(unmarshalErr, errUnknownTraceMessgeVersion) { + if errors.Is(unmarshalErr, errUpgradeRequired) { disposition = service.failed // if we don't know the version, reject the trace message since we will disable the receiver return unmarshalErr } s.metrics.recordDroppedSpanMessages() // if the error is some other unmarshalling error, we will ack the message and drop the content return nil // don't propagate error, but don't continue forwarding traces } - // forward to next consumer. Forwarding errors are not fatal so are not propagated to the caller. - // Temporary consumer errors will lead to redelivered messages, permanent will be accepted - forwardErr := s.nextConsumer.ConsumeTraces(ctx, traces) - if forwardErr != nil { - if !consumererror.IsPermanent(forwardErr) { // reject the message if the error is not permanent so we can retry, don't increment dropped span messages - s.settings.Logger.Warn("Encountered temporary error while forwarding traces to next receiver, will allow redelivery", zap.Error(forwardErr)) - disposition = service.failed - } else { // error is permanent, we want to accept the message and increment the number of dropped messages - s.settings.Logger.Warn("Encountered permanent error while forwarding traces to next receiver, will swallow trace", zap.Error(forwardErr)) - s.metrics.recordDroppedSpanMessages() + + var flowControlCount int64 +flowControlLoop: + for { + // forward to next consumer. Forwarding errors are not fatal so are not propagated to the caller. + // Temporary consumer errors will lead to redelivered messages, permanent will be accepted + forwardErr := s.nextConsumer.ConsumeTraces(ctx, traces) + if forwardErr != nil { + if !consumererror.IsPermanent(forwardErr) { + s.settings.Logger.Info("Encountered temporary error while forwarding traces to next receiver, will allow redelivery", zap.Error(forwardErr)) + // handle flow control metrics + if flowControlCount == 0 { + s.metrics.recordFlowControlStatus(flowControlStateControlled) + } + flowControlCount++ + s.metrics.recordFlowControlRecentRetries(flowControlCount) + // Backpressure scenario. For now, we are only delayed retry, eventually we may need to handle this + delayTimer := time.NewTimer(s.config.Flow.DelayedRetry.Delay) + select { + case <-delayTimer.C: + continue flowControlLoop + case <-ctx.Done(): + s.settings.Logger.Info("Context was cancelled while attempting redelivery, exiting") + disposition = nil // do not make any network requests, we are shutting down + return fmt.Errorf("delayed retry interrupted by shutdown request") + } + } else { // error is permanent, we want to accept the message and increment the number of dropped messages + s.settings.Logger.Warn("Encountered permanent error while forwarding traces to next receiver, will swallow trace", zap.Error(forwardErr)) + s.metrics.recordDroppedSpanMessages() + break flowControlLoop + } + } else { + // no forward error + s.metrics.recordReportedSpans() + break flowControlLoop + } + } + // Make sure to clear the stats no matter what, unless we were interrupted in which case we should preserve the last state + if flowControlCount != 0 { + s.metrics.recordFlowControlStatus(flowControlStateClear) + s.metrics.recordFlowControlTotal() + if flowControlCount == 1 { + s.metrics.recordFlowControlSingleSuccess() } - } else { - s.metrics.recordReportedSpans() } return nil } diff --git a/receiver/solacereceiver/receiver_test.go b/receiver/solacereceiver/receiver_test.go index b866a81220fa..446873f454cd 100644 --- a/receiver/solacereceiver/receiver_test.go +++ b/receiver/solacereceiver/receiver_test.go @@ -17,12 +17,15 @@ package solacereceiver // import "github.com/open-telemetry/opentelemetry-collec import ( "context" "errors" + "fmt" "sync" "testing" "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumererror" "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/pdata/ptrace" @@ -66,13 +69,13 @@ func TestReceiveMessage(t *testing.T) { }, { // unmarshal error expecting the error to be swallowed, the message to be acknowledged, stats incremented name: "Unmarshal Error", - unmarshalErr: errUnknownTraceMessgeType, + unmarshalErr: errUnknownTopic, validation: validateMetrics(1, 1, 1, nil), }, { // unmarshal error with wrong version expecting error to be propagated, message to be rejected name: "Unmarshal Version Error", - unmarshalErr: errUnknownTraceMessgeVersion, - expectedErr: errUnknownTraceMessgeVersion, + unmarshalErr: errUpgradeRequired, + expectedErr: errUpgradeRequired, expectNack: true, validation: validateMetrics(1, nil, 1, nil), }, @@ -81,12 +84,6 @@ func TestReceiveMessage(t *testing.T) { nextConsumer: consumertest.NewErr(consumererror.NewPermanent(errors.New("a permanent error"))), validation: validateMetrics(1, 1, nil, nil), }, - { // expect forward to error and message to be rejected with nack, no error returned - name: "Forward Temporary Error", - nextConsumer: consumertest.NewErr(errors.New("a temporary error")), - expectNack: true, - validation: validateMetrics(1, nil, nil, nil), - }, { // expect forward to error and message to be swallowed with ack which fails returning an error name: "Forward Permanent Error with Ack Error", nextConsumer: consumertest.NewErr(consumererror.NewPermanent(errors.New("a permanent error"))), @@ -94,14 +91,6 @@ func TestReceiveMessage(t *testing.T) { expectedErr: someError, validation: validateMetrics(1, 1, nil, nil), }, - { // expect forward to error and message to be rejected with nack, no error returned - name: "Forward Temporary Error with Nack Error", - nextConsumer: consumertest.NewErr(errors.New("a temporary error")), - expectNack: true, - nackErr: someError, - expectedErr: someError, - validation: validateMetrics(1, nil, nil, nil), - }, } for _, testCase := range cases { @@ -206,6 +195,7 @@ func TestReceiverLifecycle(t *testing.T) { dialCalled := make(chan struct{}) messagingService.dialFunc = func() error { validateMetric(t, receiver.metrics.views.receiverStatus, receiverStateConnecting) + validateMetric(t, receiver.metrics.views.flowControlStatus, flowControlStateClear) close(dialCalled) return nil } @@ -293,7 +283,7 @@ func TestReceiverUnmarshalVersionFailureExpectingDisable(t *testing.T) { nackCalled := make(chan struct{}) closeDone := make(chan struct{}) unmarshaller.unmarshalFunc = func(msg *inboundMessage) (ptrace.Traces, error) { - return ptrace.Traces{}, errUnknownTraceMessgeVersion + return ptrace.Traces{}, errUpgradeRequired } msgService.dialFunc = func() error { // after we receive an unmarshalling version error, we should not call dial again @@ -339,6 +329,192 @@ func TestReceiverUnmarshalVersionFailureExpectingDisable(t *testing.T) { validateMetric(t, receiver.metrics.views.receiverStatus, receiverStateTerminated) } +func TestReceiverFlowControlDelayedRetry(t *testing.T) { + someError := consumererror.NewPermanent(fmt.Errorf("some error")) + testCases := []struct { + name string + nextConsumer consumer.Traces + validation func(*testing.T, *opencensusMetrics) + }{ + { + name: "Without error", + nextConsumer: consumertest.NewNop(), + }, + { + name: "With error", + nextConsumer: consumertest.NewErr(someError), + validation: func(t *testing.T, metrics *opencensusMetrics) { + validateMetric(t, metrics.views.droppedSpanMessages, 1) + }, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + receiver, messagingService, unmarshaller := newReceiver(t) + delay := 5 * time.Millisecond + receiver.config.Flow.DelayedRetry.Delay = delay + var err error + // we want to return an error at first, then set the next consumer to a noop consumer + receiver.nextConsumer, err = consumer.NewTraces(func(ctx context.Context, ld ptrace.Traces) error { + receiver.nextConsumer = tc.nextConsumer + return fmt.Errorf("Some temporary error") + }) + require.NoError(t, err) + + // populate mock messagingService and unmarshaller functions, expecting them each to be called at most once + var ackCalled bool + messagingService.ackFunc = func(ctx context.Context, msg *inboundMessage) error { + assert.False(t, ackCalled) + ackCalled = true + return nil + } + messagingService.receiveMessageFunc = func(ctx context.Context) (*inboundMessage, error) { + return &inboundMessage{}, nil + } + unmarshaller.unmarshalFunc = func(msg *inboundMessage) (ptrace.Traces, error) { + return ptrace.NewTraces(), nil + } + + receiveMessageComplete := make(chan error, 1) + go func() { + receiveMessageComplete <- receiver.receiveMessage(context.Background(), messagingService) + }() + select { + case <-time.After(delay / 2): + // success + case <-receiveMessageComplete: + require.Fail(t, "Did not expect receiveMessage to return before delay interval") + } + // Check that we are currently flow controlled + validateMetric(t, receiver.metrics.views.flowControlStatus, flowControlStateControlled) + // since we set the next consumer to a noop, this should succeed + select { + case <-time.After(delay): + require.Fail(t, "receiveMessage did not return after delay interval") + case err := <-receiveMessageComplete: + assert.NoError(t, err) + } + assert.True(t, ackCalled) + if tc.validation != nil { + tc.validation(t, receiver.metrics) + } + validateMetric(t, receiver.metrics.views.flowControlRecentRetries, 1) + validateMetric(t, receiver.metrics.views.flowControlStatus, flowControlStateClear) + validateMetric(t, receiver.metrics.views.flowControlTotal, 1) + validateMetric(t, receiver.metrics.views.flowControlSingleSuccess, 1) + }) + } +} + +func TestReceiverFlowControlDelayedRetryInterrupt(t *testing.T) { + receiver, messagingService, unmarshaller := newReceiver(t) + // we won't wait 10 seconds since we will interrupt well before + receiver.config.Flow.DelayedRetry.Delay = 10 * time.Second + var err error + // we want to return an error at first, then set the next consumer to a noop consumer + receiver.nextConsumer, err = consumer.NewTraces(func(ctx context.Context, ld ptrace.Traces) error { + // if we are called again, fatal + receiver.nextConsumer, err = consumer.NewTraces(func(ctx context.Context, ld ptrace.Traces) error { + require.Fail(t, "Did not expect next consumer to be called again") + return nil + }) + require.NoError(t, err) + return fmt.Errorf("Some temporary error") + }) + require.NoError(t, err) + + // populate mock messagingService and unmarshaller functions, expecting them each to be called at most once + messagingService.receiveMessageFunc = func(ctx context.Context) (*inboundMessage, error) { + return &inboundMessage{}, nil + } + unmarshaller.unmarshalFunc = func(msg *inboundMessage) (ptrace.Traces, error) { + return ptrace.NewTraces(), nil + } + + ctx, cancel := context.WithCancel(context.Background()) + receiveMessageComplete := make(chan error, 1) + go func() { + receiveMessageComplete <- receiver.receiveMessage(ctx, messagingService) + }() + select { + case <-time.After(2 * time.Millisecond): + // success + case <-receiveMessageComplete: + require.Fail(t, "Did not expect receiveMessage to return before delay interval") + } + cancel() + // since we set the next consumer to a noop, this should succeed + select { + case <-time.After(2 * time.Millisecond): + require.Fail(t, "receiveMessage did not return after some time") + case err := <-receiveMessageComplete: + assert.ErrorContains(t, err, "delayed retry interrupted by shutdown request") + } +} + +func TestReceiverFlowControlDelayedRetryMultipleRetries(t *testing.T) { + receiver, messagingService, unmarshaller := newReceiver(t) + // we won't wait 10 seconds since we will interrupt well before + retryInterval := 2 * time.Millisecond + var retryCount int64 = 5 + receiver.config.Flow.DelayedRetry.Delay = retryInterval + var err error + var currentRetries int64 + // we want to return an error at first, then set the next consumer to a noop consumer + receiver.nextConsumer, err = consumer.NewTraces(func(ctx context.Context, ld ptrace.Traces) error { + if currentRetries > 0 { + validateMetric(t, receiver.metrics.views.flowControlRecentRetries, currentRetries) + } + currentRetries++ + if currentRetries == retryCount { + receiver.nextConsumer, err = consumer.NewTraces(func(ctx context.Context, ld ptrace.Traces) error { + return nil + }) + } + require.NoError(t, err) + return fmt.Errorf("Some temporary error") + }) + require.NoError(t, err) + + // populate mock messagingService and unmarshaller functions, expecting them each to be called at most once + var ackCalled bool + messagingService.ackFunc = func(ctx context.Context, msg *inboundMessage) error { + assert.False(t, ackCalled) + ackCalled = true + return nil + } + messagingService.receiveMessageFunc = func(ctx context.Context) (*inboundMessage, error) { + return &inboundMessage{}, nil + } + unmarshaller.unmarshalFunc = func(msg *inboundMessage) (ptrace.Traces, error) { + return ptrace.NewTraces(), nil + } + + receiveMessageComplete := make(chan error, 1) + go func() { + receiveMessageComplete <- receiver.receiveMessage(context.Background(), messagingService) + }() + select { + case <-time.After(retryInterval * time.Duration(retryCount) / 2): + // success + case <-receiveMessageComplete: + require.Fail(t, "Did not expect receiveMessage to return before delay interval") + } + validateMetric(t, receiver.metrics.views.flowControlStatus, flowControlStateControlled) + // since we set the next consumer to a noop, this should succeed + select { + case <-time.After(2 * retryInterval * time.Duration(retryCount)): + require.Fail(t, "receiveMessage did not return after some time") + case err := <-receiveMessageComplete: + assert.NoError(t, err) + } + assert.True(t, ackCalled) + validateMetric(t, receiver.metrics.views.flowControlRecentRetries, retryCount) + validateMetric(t, receiver.metrics.views.flowControlStatus, flowControlStateClear) + validateMetric(t, receiver.metrics.views.flowControlTotal, 1) + validateMetric(t, receiver.metrics.views.flowControlSingleSuccess, nil) +} + func newReceiver(t *testing.T) (*solaceTracesReceiver, *mockMessagingService, *mockUnmarshaller) { unmarshaller := &mockUnmarshaller{} service := &mockMessagingService{} @@ -347,8 +523,14 @@ func newReceiver(t *testing.T) (*solaceTracesReceiver, *mockMessagingService, *m } metrics := newTestMetrics(t) receiver := &solaceTracesReceiver{ - settings: componenttest.NewNopReceiverCreateSettings(), - config: &Config{}, + settings: componenttest.NewNopReceiverCreateSettings(), + config: &Config{ + Flow: FlowControl{ + DelayedRetry: &FlowControlDelayedRetry{ + Delay: 10 * time.Millisecond, + }, + }, + }, nextConsumer: consumertest.NewNop(), metrics: metrics, unmarshaller: unmarshaller, diff --git a/receiver/solacereceiver/testdata/config.yaml b/receiver/solacereceiver/testdata/config.yaml index 62cc71d30981..3935d3d5aa4d 100644 --- a/receiver/solacereceiver/testdata/config.yaml +++ b/receiver/solacereceiver/testdata/config.yaml @@ -6,6 +6,9 @@ solace/primary: password: otel01$ queue: queue://#trace-profile123 max_unacknowledged: 1234 + flow_control: + delayed_retry: + delay: 1s solace/backup: auth: diff --git a/receiver/solacereceiver/unmarshaller.go b/receiver/solacereceiver/unmarshaller.go index 45bbfd9986c8..9ef6c48e7c6a 100644 --- a/receiver/solacereceiver/unmarshaller.go +++ b/receiver/solacereceiver/unmarshaller.go @@ -23,6 +23,7 @@ import ( "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" @@ -42,7 +43,7 @@ func newTracesUnmarshaller(logger *zap.Logger, metrics *opencensusMetrics) trace logger: logger, metrics: metrics, // v1 unmarshaller is implemented by solaceMessageUnmarshallerV1 - v1: &solaceMessageUnmarshallerV1{ + receiveUnmarshallerV1: &brokerTraceReceiveUnmarshallerV1{ logger: logger, metrics: metrics, }, @@ -51,50 +52,60 @@ func newTracesUnmarshaller(logger *zap.Logger, metrics *opencensusMetrics) trace // solaceTracesUnmarshaller implements tracesUnmarshaller. type solaceTracesUnmarshaller struct { - logger *zap.Logger - metrics *opencensusMetrics - v1 tracesUnmarshaller + logger *zap.Logger + metrics *opencensusMetrics + receiveUnmarshallerV1 tracesUnmarshaller } var ( - errUnknownTraceMessgeVersion = errors.New("unsupported trace message version") - errUnknownTraceMessgeType = errors.New("bad trace message") - errEmptyPayload = errors.New("no binary attachment") + errUpgradeRequired = errors.New("unsupported trace message, upgrade required") + errUnknownTopic = errors.New("unknown topic") + errEmptyPayload = errors.New("no binary attachment") ) // unmarshal will unmarshal an *solaceMessage into ptrace.Traces. // It will make a decision based on the version of the message which unmarshalling strategy to use. -// For now, only v1 messages are used. +// For now, only receive v1 messages are used. func (u *solaceTracesUnmarshaller) unmarshal(message *inboundMessage) (ptrace.Traces, error) { const ( - topicPrefix = "_telemetry/broker/trace/receive/v" - topicPrefixV1 = topicPrefix + "1" + topicPrefix = "_telemetry/" + receiveSpanPrefix = "broker/trace/receive/" + v1Suffix = "v1" ) - if message.Properties != nil && message.Properties.To != nil { - if strings.HasPrefix(*message.Properties.To, topicPrefixV1) { - return u.v1.unmarshal(message) - } - if strings.HasPrefix(*message.Properties.To, topicPrefix) { - // unknown version - u.logger.Error("Received message with unsupported version topic", zap.String("topic", *message.Properties.To)) - return ptrace.Traces{}, errUnknownTraceMessgeVersion + if message.Properties == nil || message.Properties.To == nil { + // no topic + u.logger.Error("Received message with no topic") + return ptrace.Traces{}, errUnknownTopic + } + var topic string = *message.Properties.To + // Multiplex the topic string. For now we only have a single type handled + if strings.HasPrefix(topic, topicPrefix) { + // we are a telemetry strng + if strings.HasPrefix(topic[len(topicPrefix):], receiveSpanPrefix) { + // we are handling a receive span, validate the version is v1 + if strings.HasSuffix(topic, v1Suffix) { + return u.receiveUnmarshallerV1.unmarshal(message) + } + // 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 { + u.logger.Error("Received message with unsupported topic, an upgrade is required", zap.String("topic", *message.Properties.To)) } - // unknown topic - u.logger.Error("Received message with unknown topic", zap.String("topic", *message.Properties.To)) - return ptrace.Traces{}, errUnknownTraceMessgeType + // if we don't know the type, we must upgrade + return ptrace.Traces{}, errUpgradeRequired } - // no topic - u.logger.Error("Received message with no topic") - return ptrace.Traces{}, errUnknownTraceMessgeType + // unknown topic, do not require an upgrade + u.logger.Error("Received message with unknown topic", zap.String("topic", *message.Properties.To)) + return ptrace.Traces{}, errUnknownTopic } -type solaceMessageUnmarshallerV1 struct { +type brokerTraceReceiveUnmarshallerV1 struct { logger *zap.Logger metrics *opencensusMetrics } // unmarshal implements tracesUnmarshaller.unmarshal -func (u *solaceMessageUnmarshallerV1) unmarshal(message *inboundMessage) (ptrace.Traces, error) { +func (u *brokerTraceReceiveUnmarshallerV1) unmarshal(message *inboundMessage) (ptrace.Traces, error) { spanData, err := u.unmarshalToSpanData(message) if err != nil { return ptrace.Traces{}, err @@ -106,7 +117,7 @@ func (u *solaceMessageUnmarshallerV1) unmarshal(message *inboundMessage) (ptrace // unmarshalToSpanData will consume an solaceMessage and unmarshal it into a SpanData. // Returns an error if one occurred. -func (u *solaceMessageUnmarshallerV1) unmarshalToSpanData(message *inboundMessage) (*model_v1.SpanData, error) { +func (u *brokerTraceReceiveUnmarshallerV1) unmarshalToSpanData(message *inboundMessage) (*model_v1.SpanData, error) { var data = message.GetData() if len(data) == 0 { return nil, errEmptyPayload @@ -121,7 +132,7 @@ func (u *solaceMessageUnmarshallerV1) unmarshalToSpanData(message *inboundMessag // 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 *solaceMessageUnmarshallerV1) populateTraces(spanData *model_v1.SpanData, traces ptrace.Traces) { +func (u *brokerTraceReceiveUnmarshallerV1) populateTraces(spanData *model_v1.SpanData, traces ptrace.Traces) { // Append new resource span and map any attributes resourceSpan := traces.ResourceSpans().AppendEmpty() u.mapResourceSpanAttributes(spanData, resourceSpan.Resource().Attributes()) @@ -136,7 +147,7 @@ func (u *solaceMessageUnmarshallerV1) populateTraces(spanData *model_v1.SpanData u.mapEvents(spanData, clientSpan) } -func (u *solaceMessageUnmarshallerV1) mapResourceSpanAttributes(spanData *model_v1.SpanData, attrMap pcommon.Map) { +func (u *brokerTraceReceiveUnmarshallerV1) mapResourceSpanAttributes(spanData *model_v1.SpanData, attrMap pcommon.Map) { const ( routerNameAttrKey = "service.name" messageVpnNameAttrKey = "service.instance.id" @@ -149,7 +160,7 @@ func (u *solaceMessageUnmarshallerV1) mapResourceSpanAttributes(spanData *model_ attrMap.PutStr(solosVersionAttrKey, spanData.SolosVersion) } -func (u *solaceMessageUnmarshallerV1) mapClientSpanData(spanData *model_v1.SpanData, clientSpan ptrace.Span) { +func (u *brokerTraceReceiveUnmarshallerV1) mapClientSpanData(spanData *model_v1.SpanData, clientSpan ptrace.Span) { const clientSpanName = "(topic) receive" // client span constants @@ -188,7 +199,7 @@ func (u *solaceMessageUnmarshallerV1) mapClientSpanData(spanData *model_v1.SpanD // 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 *solaceMessageUnmarshallerV1) mapClientSpanAttributes(spanData *model_v1.SpanData, attrMap pcommon.Map) { +func (u *brokerTraceReceiveUnmarshallerV1) mapClientSpanAttributes(spanData *model_v1.SpanData, attrMap pcommon.Map) { // constant attributes const ( systemAttrKey = "messaging.system" @@ -290,6 +301,14 @@ func (u *solaceMessageUnmarshallerV1) mapClientSpanAttributes(spanData *model_v1 } attrMap.PutInt(peerPortAttrKey, int64(spanData.PeerPort)) + 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 { @@ -299,7 +318,7 @@ func (u *solaceMessageUnmarshallerV1) mapClientSpanAttributes(spanData *model_v1 } // mapEvents maps all events contained in SpanData to relevant events within clientSpan.Events() -func (u *solaceMessageUnmarshallerV1) mapEvents(spanData *model_v1.SpanData, clientSpan ptrace.Span) { +func (u *brokerTraceReceiveUnmarshallerV1) mapEvents(spanData *model_v1.SpanData, clientSpan ptrace.Span) { // handle enqueue events for _, enqueueEvent := range spanData.EnqueueEvents { u.mapEnqueueEvent(enqueueEvent, clientSpan.Events()) @@ -312,7 +331,7 @@ func (u *solaceMessageUnmarshallerV1) mapEvents(spanData *model_v1.SpanData, cli } // mapEnqueueEvent maps a SpanData_EnqueueEvent to a ClientSpan.Event -func (u *solaceMessageUnmarshallerV1) mapEnqueueEvent(enqueueEvent *model_v1.SpanData_EnqueueEvent, clientSpanEvents ptrace.SpanEventSlice) { +func (u *brokerTraceReceiveUnmarshallerV1) mapEnqueueEvent(enqueueEvent *model_v1.SpanData_EnqueueEvent, clientSpanEvents ptrace.SpanEventSlice) { const ( enqueueEventSuffix = " enqueue" // Final should be ` enqueue` messagingDestinationTypeEventKey = "messaging.solace.destination_type" @@ -347,7 +366,7 @@ func (u *solaceMessageUnmarshallerV1) mapEnqueueEvent(enqueueEvent *model_v1.Spa } // mapTransactionEvent maps a SpanData_TransactionEvent to a ClientSpan.Event -func (u *solaceMessageUnmarshallerV1) mapTransactionEvent(transactionEvent *model_v1.SpanData_TransactionEvent, clientSpanEvents ptrace.SpanEventSlice) { +func (u *brokerTraceReceiveUnmarshallerV1) mapTransactionEvent(transactionEvent *model_v1.SpanData_TransactionEvent, clientSpanEvents ptrace.SpanEventSlice) { const ( transactionInitiatorEventKey = "messaging.solace.transaction_initiator" transactionIDEventKey = "messaging.solace.transaction_id" @@ -417,7 +436,7 @@ func (u *solaceMessageUnmarshallerV1) mapTransactionEvent(transactionEvent *mode } } -func (u *solaceMessageUnmarshallerV1) rgmidToString(rgmid []byte) string { +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 @@ -434,9 +453,39 @@ func (u *solaceMessageUnmarshallerV1) rgmidToString(rgmid []byte) string { 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 *solaceMessageUnmarshallerV1) insertUserProperty(toMap pcommon.Map, key string, value interface{}) { +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." diff --git a/receiver/solacereceiver/unmarshaller_test.go b/receiver/solacereceiver/unmarshaller_test.go index 5ddfedea003c..fd30126837d1 100644 --- a/receiver/solacereceiver/unmarshaller_test.go +++ b/receiver/solacereceiver/unmarshaller_test.go @@ -32,8 +32,9 @@ import ( // Validate entire unmarshal flow func TestSolaceMessageUnmarshallerUnmarshal(t *testing.T) { - validTopicVersion := "_telemetry/broker/trace/receive/v1" - invalidTopicVersion := "_telemetry/broker/trace/receive/v2" + validReceiveTopicVersion := "_telemetry/broker/trace/receive/v1" + invalidReceiveTopicVersion := "_telemetry/broker/trace/receive/v2" + invalidTelemetryTopic := "_telemetry/broker/trace/somethingNew" invalidTopicString := "some unknown topic string that won't be valid" tests := []struct { @@ -49,23 +50,32 @@ func TestSolaceMessageUnmarshallerUnmarshal(t *testing.T) { To: &invalidTopicString, }, }, - err: errUnknownTraceMessgeType, + err: errUnknownTopic, }, { name: "Bad Topic Version", message: &inboundMessage{ Properties: &amqp.MessageProperties{ - To: &invalidTopicVersion, + To: &invalidReceiveTopicVersion, }, }, - err: errUnknownTraceMessgeVersion, + err: errUpgradeRequired, + }, + { + name: "Unknown Telemetry Topic", + message: &inboundMessage{ + Properties: &amqp.MessageProperties{ + To: &invalidTelemetryTopic, + }, + }, + err: errUpgradeRequired, }, { name: "No Message Properties", message: &inboundMessage{ Properties: nil, }, - err: errUnknownTraceMessgeType, + err: errUnknownTopic, }, { name: "No Topic String", @@ -74,14 +84,14 @@ func TestSolaceMessageUnmarshallerUnmarshal(t *testing.T) { To: nil, }, }, - err: errUnknownTraceMessgeType, + err: errUnknownTopic, }, { name: "Empty Message Data", message: &amqp.Message{ Data: [][]byte{{}}, Properties: &amqp.MessageProperties{ - To: &validTopicVersion, + To: &validReceiveTopicVersion, }, }, err: errEmptyPayload, @@ -91,7 +101,7 @@ func TestSolaceMessageUnmarshallerUnmarshal(t *testing.T) { message: &amqp.Message{ Data: [][]byte{{1, 2, 3, 4, 5}}, Properties: &amqp.MessageProperties{ - To: &validTopicVersion, + To: &validReceiveTopicVersion, }, }, err: errors.New("cannot parse invalid wire-format data"), @@ -178,7 +188,7 @@ func TestSolaceMessageUnmarshallerUnmarshal(t *testing.T) { return validData }()}, Properties: &amqp.MessageProperties{ - To: &validTopicVersion, + To: &validReceiveTopicVersion, }, }, want: func() *ptrace.Traces { @@ -396,6 +406,8 @@ func TestUnmarshallerMapClientSpanAttributes(t *testing.T) { 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) ) @@ -433,6 +445,7 @@ func TestUnmarshallerMapClientSpanAttributes(t *testing.T) { PeerPort: 12345, BrokerReceiveTimeUnixNano: 1357924680, DroppedApplicationMessageProperties: false, + Baggage: &baggageString, UserProperties: map[string]*model_v1.SpanData_UserPropertyValue{ "special_key": { Value: &model_v1.SpanData_UserPropertyValue_BoolValue{ @@ -467,6 +480,10 @@ func TestUnmarshallerMapClientSpanAttributes(t *testing.T) { "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", }, }, { @@ -531,6 +548,7 @@ func TestUnmarshallerMapClientSpanAttributes(t *testing.T) { PeerPort: 12345, BrokerReceiveTimeUnixNano: 1357924680, DroppedApplicationMessageProperties: true, + Baggage: &invalidBaggageString, UserProperties: map[string]*model_v1.SpanData_UserPropertyValue{ "special_key": nil, }, @@ -552,7 +570,8 @@ func TestUnmarshallerMapClientSpanAttributes(t *testing.T) { "messaging.solace.broker_receive_time_unix_nano": int64(1357924680), "messaging.solace.dropped_application_message_properties": true, }, - expectedUnmarshallingErrors: 3, + // Invalid delivery mode, missing IPs, invalid baggage string + expectedUnmarshallingErrors: 4, }, } for _, tt := range tests { @@ -898,6 +917,62 @@ func TestUnmarshallerRGMID(t *testing.T) { } } +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.Sort(), actual.Sort()) + } 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 { @@ -1031,7 +1106,7 @@ func TestUnmarshallerInsertUserProperty(t *testing.T) { }, } - unmarshaller := &solaceMessageUnmarshallerV1{ + unmarshaller := &brokerTraceReceiveUnmarshallerV1{ logger: zap.NewNop(), } for _, testCase := range testCases { @@ -1059,7 +1134,7 @@ func TestSolaceMessageUnmarshallerV1InsertUserPropertyUnsupportedType(t *testing validateMetric(t, u.metrics.views.recoverableUnmarshallingErrors, 1) } -func newTestV1Unmarshaller(t *testing.T) *solaceMessageUnmarshallerV1 { +func newTestV1Unmarshaller(t *testing.T) *brokerTraceReceiveUnmarshallerV1 { m := newTestMetrics(t) - return &solaceMessageUnmarshallerV1{zap.NewNop(), m} + return &brokerTraceReceiveUnmarshallerV1{zap.NewNop(), m} }