From e4b63ef537b9fa8e9b913beaada788c408b442ab Mon Sep 17 00:00:00 2001 From: isra17 Date: Thu, 22 Sep 2022 19:14:40 -0400 Subject: [PATCH] Fix otlp exporter error handling misusing backoff.expo --- .../exporter/otlp/proto/grpc/exporter.py | 26 ++++++++++++++----- .../tests/test_otlp_trace_exporter.py | 10 +++---- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py b/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py index 4405bcad68b..b7f83f0cd6b 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py +++ b/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py @@ -19,13 +19,23 @@ from collections.abc import Sequence from os import environ from time import sleep -from typing import Any, Callable, Dict, Generic, List, Optional, Tuple, Union +from typing import ( + Any, + Callable, + Dict, + Generic, + List, + Optional, + Tuple, + Union, + Iterator, +) from typing import Sequence as TypingSequence from typing import TypeVar from urllib.parse import urlparse from opentelemetry.sdk.trace import ReadableSpan -from backoff import expo +import backoff from google.rpc.error_details_pb2 import RetryInfo from grpc import ( ChannelCredentials, @@ -68,6 +78,12 @@ } +def _expo(*, max_value: int) -> Iterator[int]: + gen = backoff.expo() + gen.send(None) + return gen + + class InvalidCompressionValueException(Exception): def __init__(self, environ_key: str, environ_value: str): super().__init__( @@ -293,11 +309,10 @@ def _export( # delay, # ) max_value = 64 - # expo returns a generator that yields delay values which grow + # _expo returns a generator that yields delay values which grow # exponentially. Once delay is greater than max_value, the yielded # value will remain constant. - for delay in expo(max_value=max_value): - + for delay in _expo(max_value=max_value): if delay == max_value: return self._result.FAILURE @@ -311,7 +326,6 @@ def _export( return self._result.SUCCESS except RpcError as error: - if error.code() in [ StatusCode.CANCELLED, StatusCode.DEADLINE_EXCEEDED, diff --git a/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_trace_exporter.py b/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_trace_exporter.py index a5cb4e699a6..07a2c8c4d57 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_trace_exporter.py +++ b/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_trace_exporter.py @@ -436,11 +436,8 @@ def test_otlp_headers(self, mock_ssl_channel, mock_secure): # pylint: disable=protected-access self.assertIsNone(exporter._headers, None) - @patch("opentelemetry.exporter.otlp.proto.grpc.exporter.expo") @patch("opentelemetry.exporter.otlp.proto.grpc.exporter.sleep") - def test_unavailable(self, mock_sleep, mock_expo): - - mock_expo.configure_mock(**{"return_value": [1]}) + def test_unavailable(self, mock_sleep): add_TraceServiceServicer_to_server( TraceServiceServicerUNAVAILABLE(), self.server @@ -448,7 +445,10 @@ def test_unavailable(self, mock_sleep, mock_expo): self.assertEqual( self.exporter.export([self.span]), SpanExportResult.FAILURE ) - mock_sleep.assert_called_with(1) + self.assertEqual( + mock_sleep.call_args_list, + [((1,),), ((2,),), ((4,),), ((8,),), ((16,),), ((32,),)], + ) @patch("opentelemetry.exporter.otlp.proto.grpc.exporter.expo") @patch("opentelemetry.exporter.otlp.proto.grpc.exporter.sleep")