Skip to content

Commit ed72afb

Browse files
opentelemetry-instrumentation-boto3sqs: avoid KeyError when all messages in send_message_batch fail (#4746)
* opentelemetry-instrumentation-boto3sqs: avoid KeyError when all messages in send_message_batch fail * opentelemetry-instrumentation-boto3sqs: add changelog fragment --------- Co-authored-by: Emídio <9735060+emdneto@users.noreply.github.com>
1 parent 8886ef5 commit ed72afb

3 files changed

Lines changed: 75 additions & 1 deletion

File tree

.changelog/4746.fixed

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
`opentelemetry-instrumentation-boto3sqs`: handle missing `Successful` key in `send_message_batch` response when all messages fail

instrumentation/opentelemetry-instrumentation-boto3sqs/src/opentelemetry/instrumentation/boto3sqs/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ def send_batch_wrapper(wrapped, instance, args, kwargs):
267267
entry["MessageAttributes"], setter=boto3sqs_setter
268268
)
269269
retval = wrapped(*args, **kwargs)
270-
for successful_messages in retval["Successful"]:
270+
for successful_messages in retval.get("Successful", []):
271271
message_identifier = successful_messages["Id"]
272272
message_span = ids_to_spans.get(message_identifier)
273273
if message_span:

instrumentation/opentelemetry-instrumentation-boto3sqs/tests/test_boto3sqs_instrumentation.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,79 @@ def test_send_message(self):
282282
)
283283
self._assert_injected_span(message_attrs, span)
284284

285+
def test_send_message_batch(self):
286+
expected_message_ids = {"1": "msg-1", "2": "msg-2"}
287+
mock_response = {
288+
"Successful": [
289+
{"Id": "1", "MessageId": "msg-1", "MD5OfMessageBody": "11"},
290+
{"Id": "2", "MessageId": "msg-2", "MD5OfMessageBody": "22"},
291+
],
292+
"Failed": [],
293+
}
294+
entries = [
295+
{"Id": "1", "MessageBody": "hello 1"},
296+
{"Id": "2", "MessageBody": "hello 2"},
297+
]
298+
299+
with self._mocked_endpoint(mock_response):
300+
self._client.send_message_batch(
301+
QueueUrl=self._queue_url, Entries=entries
302+
)
303+
304+
spans = self.get_finished_spans()
305+
self.assertEqual(2, len(spans))
306+
spans_by_entry_id = {
307+
span.attributes[SpanAttributes.MESSAGING_CONVERSATION_ID]: span
308+
for span in spans
309+
}
310+
for entry in entries:
311+
entry_id = entry["Id"]
312+
span = spans_by_entry_id[entry_id]
313+
self.assertEqual(f"{self._queue_name} send", span.name)
314+
self.assertEqual(SpanKind.PRODUCER, span.kind)
315+
self.assertEqual(
316+
{
317+
SpanAttributes.MESSAGING_CONVERSATION_ID: entry_id,
318+
SpanAttributes.MESSAGING_MESSAGE_ID: expected_message_ids[
319+
entry_id
320+
],
321+
**self._default_span_attrs(),
322+
},
323+
span.attributes,
324+
)
325+
self._assert_injected_span(entry["MessageAttributes"], span)
326+
327+
def test_send_message_batch_all_failed(self):
328+
mock_response = {
329+
"Failed": [
330+
{
331+
"Id": "1",
332+
"SenderFault": True,
333+
"Code": "InvalidParameterValue",
334+
"Message": "boom",
335+
}
336+
]
337+
}
338+
entries = [{"Id": "1", "MessageBody": "hello 1"}]
339+
340+
with self._mocked_endpoint(mock_response):
341+
self._client.send_message_batch(
342+
QueueUrl=self._queue_url, Entries=entries
343+
)
344+
345+
span = self._get_only_span()
346+
self.assertEqual(f"{self._queue_name} send", span.name)
347+
self.assertEqual(SpanKind.PRODUCER, span.kind)
348+
self.assertEqual(
349+
{
350+
SpanAttributes.MESSAGING_CONVERSATION_ID: "1",
351+
**self._default_span_attrs(),
352+
},
353+
span.attributes,
354+
)
355+
self.assertNotIn(SpanAttributes.MESSAGING_MESSAGE_ID, span.attributes)
356+
self._assert_injected_span(entries[0]["MessageAttributes"], span)
357+
285358
def test_receive_message(self):
286359
msg_def = {
287360
"1": {"receipt": "01", "trace_id": 10, "span_id": 1},

0 commit comments

Comments
 (0)