@@ -18,7 +18,6 @@ import (
18
18
"context"
19
19
20
20
"github.com/Shopify/sarama"
21
- "github.com/google/uuid"
22
21
"google.golang.org/grpc/codes"
23
22
24
23
"go.opentelemetry.io/otel/api/kv"
@@ -83,7 +82,6 @@ type asyncProducer struct {
83
82
input chan * sarama.ProducerMessage
84
83
successes chan * sarama.ProducerMessage
85
84
errors chan * sarama.ProducerError
86
- close chan closeType
87
85
closeErr chan error
88
86
}
89
87
@@ -104,16 +102,25 @@ func (p *asyncProducer) Errors() <-chan *sarama.ProducerError {
104
102
105
103
// AsyncClose async close producer.
106
104
func (p * asyncProducer ) AsyncClose () {
107
- p .close <- closeAsync
105
+ p .input <- & sarama.ProducerMessage {
106
+ Metadata : closeAsync ,
107
+ }
108
108
}
109
109
110
110
// Close shuts down the producer and waits for any buffered messages to be
111
111
// flushed.
112
112
func (p * asyncProducer ) Close () error {
113
- p .close <- closeSync
113
+ p .input <- & sarama.ProducerMessage {
114
+ Metadata : closeSync ,
115
+ }
114
116
return <- p .closeErr
115
117
}
116
118
119
+ type producerMessageContext struct {
120
+ span trace.Span
121
+ metadataBackup interface {}
122
+ }
123
+
117
124
// WrapAsyncProducer wraps a sarama.AsyncProducer so that all produced messages
118
125
// are traced. It requires the underlying sarama Config so we can know whether
119
126
// or not successes will be returned.
@@ -131,30 +138,45 @@ func WrapAsyncProducer(serviceName string, saramaConfig *sarama.Config, p sarama
131
138
input : make (chan * sarama.ProducerMessage ),
132
139
successes : make (chan * sarama.ProducerMessage ),
133
140
errors : make (chan * sarama.ProducerError ),
134
- close : make (chan closeType ),
135
141
closeErr : make (chan error ),
136
142
}
137
143
go func () {
138
- spans := make (map [interface {}]trace. Span )
144
+ producerMessageContexts := make (map [interface {}]producerMessageContext )
139
145
defer close (wrapped .successes )
140
146
defer close (wrapped .errors )
141
147
for {
142
148
select {
143
- case t := <- wrapped .close :
144
- switch t {
145
- case closeSync :
146
- go func () {
147
- wrapped .closeErr <- p .Close ()
148
- }()
149
- case closeAsync :
150
- p .AsyncClose ()
151
- }
152
149
case msg := <- wrapped .input :
153
- msg .Metadata = uuid .New ()
150
+ // Shut down if message metadata is a close type.
151
+ // Sarama will close after dispatching every message.
152
+ // So wrapper should follow this mechanism by adding a special message at
153
+ // the end of the input channel.
154
+ if ct , ok := msg .Metadata .(closeType ); ok {
155
+ switch ct {
156
+ case closeSync :
157
+ go func () {
158
+ wrapped .closeErr <- p .Close ()
159
+ }()
160
+ case closeAsync :
161
+ p .AsyncClose ()
162
+ }
163
+ continue
164
+ }
165
+
154
166
span := startProducerSpan (cfg , saramaConfig .Version , msg )
167
+
168
+ // Create message context, backend message metadata
169
+ mc := producerMessageContext {
170
+ metadataBackup : msg .Metadata ,
171
+ span : span ,
172
+ }
173
+
174
+ // Specific metadata with span id
175
+ msg .Metadata = span .SpanContext ().SpanID
176
+
155
177
p .Input () <- msg
156
178
if saramaConfig .Producer .Return .Successes {
157
- spans [msg .Metadata ] = span
179
+ producerMessageContexts [msg .Metadata ] = mc
158
180
} else {
159
181
// If returning successes isn't enabled, we just finish the
160
182
// span right away because there's no way to know when it will
@@ -167,9 +189,12 @@ func WrapAsyncProducer(serviceName string, saramaConfig *sarama.Config, p sarama
167
189
return
168
190
}
169
191
key := msg .Metadata
170
- if span , ok := spans [key ]; ok {
171
- delete (spans , key )
172
- finishProducerSpan (span , msg .Partition , msg .Offset , nil )
192
+ if mc , ok := producerMessageContexts [key ]; ok {
193
+ delete (producerMessageContexts , key )
194
+ finishProducerSpan (mc .span , msg .Partition , msg .Offset , nil )
195
+
196
+ // Restore message metadata
197
+ msg .Metadata = mc .metadataBackup
173
198
}
174
199
wrapped .successes <- msg
175
200
case err , ok := <- p .Errors ():
@@ -178,9 +203,9 @@ func WrapAsyncProducer(serviceName string, saramaConfig *sarama.Config, p sarama
178
203
return
179
204
}
180
205
key := err .Msg .Metadata
181
- if span , ok := spans [key ]; ok {
182
- delete (spans , key )
183
- finishProducerSpan (span , err .Msg .Partition , err .Msg .Offset , err .Err )
206
+ if mc , ok := producerMessageContexts [key ]; ok {
207
+ delete (producerMessageContexts , key )
208
+ finishProducerSpan (mc . span , err .Msg .Partition , err .Msg .Offset , err .Err )
184
209
}
185
210
wrapped .errors <- err
186
211
}
0 commit comments