Skip to content

Commit

Permalink
Fix warning message for OTLP gRPC exporter mixin (#2781)
Browse files Browse the repository at this point in the history
* Fix warning message for OTLP gRPC exporter mixin

Fixes #2780

* Refactor export parameter type

* Add changelog entry

* Use fixed warning messages for traces and metrics

* Use subclass-specific error messages

* Fix test cases

* Fix lint
  • Loading branch information
ocelotl authored Jul 7, 2022
1 parent dbcec9f commit fe26ada
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 11 deletions.
6 changes: 2 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased](https://github.com/open-telemetry/opentelemetry-python/compare/v1.12.0rc2-0.32b0...HEAD)


- Fix OTLP gRPC exporter warning message
([#2781](https://github.com/open-telemetry/opentelemetry-python/pull/2781))
- Fix tracing decorator with late configuration
([#2754](https://github.com/open-telemetry/opentelemetry-python/pull/2754))


## [1.12.0rc2-0.32b0](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v1.12.0rc2-0.32b0) - 2022-07-04



- Fix instrument name and unit regexes
([#2796](https://github.com/open-telemetry/opentelemetry-python/pull/2796))
- Add optional sessions parameter to all Exporters leveraging requests.Session
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,7 @@ def export(self, batch: Sequence[LogData]) -> LogExportResult:

def shutdown(self) -> None:
pass

@property
def _exporting(self) -> str:
return "logs"
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

"""OTLP Exporter"""

import logging
from logging import getLogger
from abc import ABC, abstractmethod
from collections.abc import Sequence
from os import environ
Expand All @@ -23,6 +23,7 @@
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
from google.rpc.error_details_pb2 import RetryInfo
Expand Down Expand Up @@ -52,8 +53,9 @@
)
from opentelemetry.sdk.resources import Resource as SDKResource
from opentelemetry.util.re import parse_headers
from opentelemetry.sdk.metrics.export import MetricsData

logger = logging.getLogger(__name__)
logger = getLogger(__name__)
SDKDataT = TypeVar("SDKDataT")
ResourceDataT = TypeVar("ResourceDataT")
TypingResourceT = TypeVar("TypingResourceT")
Expand Down Expand Up @@ -277,8 +279,19 @@ def _translate_attributes(self, attributes) -> TypingSequence[KeyValue]:
logger.exception(error)
return output

def _export(self, data: TypingSequence[SDKDataT]) -> ExportResultT:

def _export(
self, data: Union[TypingSequence[ReadableSpan], MetricsData]
) -> ExportResultT:

# FIXME remove this check if the export type for traces
# gets updated to a class that represents the proto
# TracesData and use the code below instead.
# logger.warning(
# "Transient error %s encountered while exporting %s, retrying in %ss.",
# error.code(),
# data.__class__.__name__,
# delay,
# )
max_value = 64
# expo returns a generator that yields delay values which grow
# exponentially. Once delay is greater than max_value, the yielded
Expand Down Expand Up @@ -321,15 +334,20 @@ def _export(self, data: TypingSequence[SDKDataT]) -> ExportResultT:
)

logger.warning(
"Transient error %s encountered while exporting span batch, retrying in %ss.",
(
"Transient error %s encountered while exporting "
"%s, retrying in %ss."
),
error.code(),
self._exporting,
delay,
)
sleep(delay)
continue
else:
logger.error(
"Failed to export span batch, error code: %s",
"Failed to export %s, error code: %s",
self._exporting,
error.code(),
)

Expand All @@ -342,3 +360,12 @@ def _export(self, data: TypingSequence[SDKDataT]) -> ExportResultT:

def shutdown(self) -> None:
pass

@property
@abstractmethod
def _exporting(self) -> str:
"""
Returns a string that describes the overall exporter, to be used in
warning messages.
"""
pass
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,7 @@ def export(

def shutdown(self, timeout_millis: float = 30_000, **kwargs) -> None:
pass

@property
def _exporting(self) -> str:
return "metrics"
Original file line number Diff line number Diff line change
Expand Up @@ -289,3 +289,7 @@ def _translate_data(

def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult:
return self._export(spans)

@property
def _exporting(self):
return "traces"
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ def setUp(self):
def tearDown(self):
self.server.stop(None)

def test_exporting(self):
# pylint: disable=protected-access
self.assertEqual(self.exporter._exporting, "logs")

@patch(
"opentelemetry.exporter.otlp.proto.grpc.exporter.ssl_channel_credentials"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,10 @@ def setUp(self):
def tearDown(self):
self.server.stop(None)

def test_exporting(self):
# pylint: disable=protected-access
self.assertEqual(self.exporter._exporting, "metrics")

@patch(
"opentelemetry.exporter.otlp.proto.grpc.exporter.ssl_channel_credentials"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,21 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from logging import WARNING
from types import MethodType
from typing import Sequence
from unittest import TestCase
from unittest.mock import patch
from unittest.mock import Mock, patch

from grpc import Compression

from opentelemetry.exporter.otlp.proto.grpc.exporter import (
ExportServiceRequestT,
InvalidCompressionValueException,
OTLPExporterMixin,
RpcError,
SDKDataT,
StatusCode,
environ_to_compression,
)

Expand Down Expand Up @@ -47,3 +55,61 @@ def test_environ_to_compression(self):
)
with self.assertRaises(InvalidCompressionValueException):
environ_to_compression("test_invalid")

@patch("opentelemetry.exporter.otlp.proto.grpc.exporter.expo")
def test_export_warning(self, mock_expo):

mock_expo.configure_mock(**{"return_value": [0]})

rpc_error = RpcError()

def code(self):
return None

rpc_error.code = MethodType(code, rpc_error)

class OTLPMockExporter(OTLPExporterMixin):

_result = Mock()
_stub = Mock(
**{"return_value": Mock(**{"Export.side_effect": rpc_error})}
)

def _translate_data(
self, data: Sequence[SDKDataT]
) -> ExportServiceRequestT:
pass

@property
def _exporting(self) -> str:
return "mock"

otlp_mock_exporter = OTLPMockExporter()

with self.assertLogs(level=WARNING) as warning:
# pylint: disable=protected-access
otlp_mock_exporter._export(Mock())
self.assertEqual(
warning.records[0].message,
"Failed to export mock, error code: None",
)

def code(self): # pylint: disable=function-redefined
return StatusCode.CANCELLED

def trailing_metadata(self):
return {}

rpc_error.code = MethodType(code, rpc_error)
rpc_error.trailing_metadata = MethodType(trailing_metadata, rpc_error)

with self.assertLogs(level=WARNING) as warning:
# pylint: disable=protected-access
otlp_mock_exporter._export([])
self.assertEqual(
warning.records[0].message,
(
"Transient error StatusCode.CANCELLED encountered "
"while exporting mock, retrying in 0s."
),
)
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ def setUp(self):
def tearDown(self):
self.server.stop(None)

def test_exporting(self):
# pylint: disable=protected-access
self.assertEqual(self.exporter._exporting, "traces")

@patch.dict(
"os.environ",
{
Expand Down

0 comments on commit fe26ada

Please sign in to comment.