diff --git a/CHANGELOG.md b/CHANGELOG.md index 91aaf9a7bc..9b5c1b9bfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +- `opentelemetry-exporter-otlp-proto-grpc`: add detailed error message to the otlp grpc exporter + ([#5184](https://github.com/open-telemetry/opentelemetry-python/pull/5184)) - Apply fixes for `UP` ruff rule ([#5133](https://github.com/open-telemetry/opentelemetry-python/pull/5133)) - Switch to SPDX license headers and add CI enforcement 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 b3a4463b98..ad691799f4 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 @@ -507,10 +507,13 @@ def _export( or self._shutdown ): logger.error( - "Failed to export %s to %s, error code: %s", + "Failed to export %s to %s, error code: %s%s", self._exporting, self._endpoint, error.code(), # type: ignore [reportAttributeAccessIssue] + f", details: {error.details()}" + if error.details() + else "", exc_info=error.code() == StatusCode.UNKNOWN, # type: ignore [reportAttributeAccessIssue] ) result.error = error @@ -519,11 +522,14 @@ def _export( } return self._result.FAILURE # type: ignore [reportReturnType] logger.warning( - "Transient error %s encountered while exporting %s to %s, retrying in %.2fs.", + "Transient error %s encountered while exporting %s to %s, retrying in %.2fs.%s", error.code(), # type: ignore [reportAttributeAccessIssue] self._exporting, self._endpoint, backoff_seconds, + f" Details: {error.details()}" + if error.details() + else "", ) shutdown = self._shutdown_in_progress.wait(backoff_seconds) if shutdown: diff --git a/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_exporter_mixin.py b/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_exporter_mixin.py index 8736a6dc56..a125dfbc6d 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_exporter_mixin.py +++ b/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_exporter_mixin.py @@ -108,10 +108,12 @@ def __init__( export_result: StatusCode, optional_retry_nanos: int | None = None, optional_export_sleep: float | None = None, + optional_details: str | None = None, ): self.export_result = export_result self.optional_export_sleep = optional_export_sleep self.optional_retry_nanos = optional_retry_nanos + self.optional_details = optional_details self.num_requests = 0 # pylint: disable=invalid-name,unused-argument @@ -132,6 +134,8 @@ def Export(self, request, context): ), ) ) + if self.optional_details: + context.set_details(self.optional_details) context.set_code(self.export_result) return ExportTraceServiceResponse() @@ -589,7 +593,7 @@ def test_timeout_set_correctly(self): ) after = time.time() self.assertEqual( - "Failed to export traces to localhost:4317, error code: StatusCode.DEADLINE_EXCEEDED", + "Failed to export traces to localhost:4317, error code: StatusCode.DEADLINE_EXCEEDED, details: Deadline Exceeded", warning.records[-1].message, ) self.assertEqual(mock_trace_service.num_requests, 2) @@ -617,7 +621,8 @@ def test_permanent_failure(self): with self.assertLogs(level=WARNING) as warning: add_TraceServiceServicer_to_server( TraceServiceServicerWithExportParams( - StatusCode.ALREADY_EXISTS + StatusCode.ALREADY_EXISTS, + optional_details="resource already exists", ), self.server, ) @@ -626,7 +631,7 @@ def test_permanent_failure(self): ) self.assertEqual( warning.records[-1].message, - "Failed to export traces to localhost:4317, error code: StatusCode.ALREADY_EXISTS", + "Failed to export traces to localhost:4317, error code: StatusCode.ALREADY_EXISTS, details: resource already exists", ) metrics_data = self.metric_reader.get_metrics_data()