go.opentelemetry.io/contrib/instrumentation/github.com/Shopify/sarama/otelsarama@v0.43.0/dispatcher.go (about) 1 // Copyright The OpenTelemetry Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package otelsarama // import "go.opentelemetry.io/contrib/instrumentation/github.com/Shopify/sarama/otelsarama" 16 17 import ( 18 "context" 19 "fmt" 20 "strconv" 21 22 "github.com/Shopify/sarama" 23 24 "go.opentelemetry.io/otel/attribute" 25 semconv "go.opentelemetry.io/otel/semconv/v1.17.0" 26 "go.opentelemetry.io/otel/trace" 27 ) 28 29 type consumerMessagesDispatcher interface { 30 Messages() <-chan *sarama.ConsumerMessage 31 } 32 33 type consumerMessagesDispatcherWrapper struct { 34 d consumerMessagesDispatcher 35 messages chan *sarama.ConsumerMessage 36 37 cfg config 38 } 39 40 func newConsumerMessagesDispatcherWrapper(d consumerMessagesDispatcher, cfg config) *consumerMessagesDispatcherWrapper { 41 return &consumerMessagesDispatcherWrapper{ 42 d: d, 43 messages: make(chan *sarama.ConsumerMessage), 44 cfg: cfg, 45 } 46 } 47 48 // Messages returns the read channel for the messages that are returned by 49 // the broker. 50 func (w *consumerMessagesDispatcherWrapper) Messages() <-chan *sarama.ConsumerMessage { 51 return w.messages 52 } 53 54 func (w *consumerMessagesDispatcherWrapper) Run() { 55 msgs := w.d.Messages() 56 57 for msg := range msgs { 58 // Extract a span context from message to link. 59 carrier := NewConsumerMessageCarrier(msg) 60 parentSpanContext := w.cfg.Propagators.Extract(context.Background(), carrier) 61 62 // Create a span. 63 attrs := []attribute.KeyValue{ 64 semconv.MessagingSystem("kafka"), 65 semconv.MessagingDestinationKindTopic, 66 semconv.MessagingDestinationName(msg.Topic), 67 semconv.MessagingOperationReceive, 68 semconv.MessagingMessageID(strconv.FormatInt(msg.Offset, 10)), 69 semconv.MessagingKafkaSourcePartition(int(msg.Partition)), 70 } 71 opts := []trace.SpanStartOption{ 72 trace.WithAttributes(attrs...), 73 trace.WithSpanKind(trace.SpanKindConsumer), 74 } 75 newCtx, span := w.cfg.Tracer.Start(parentSpanContext, fmt.Sprintf("%s receive", msg.Topic), opts...) 76 77 // Inject current span context, so consumers can use it to propagate span. 78 w.cfg.Propagators.Inject(newCtx, carrier) 79 80 // Send messages back to user. 81 w.messages <- msg 82 83 span.End() 84 } 85 close(w.messages) 86 }