diff --git a/CHANGELOG.md b/CHANGELOG.md index 614f240d4e..75311a835d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +- `opentelemetry-exporter-otlp-proto-grpc`: Log grpc error details when grpc request fails ([#5143](https://github.com/open-telemetry/opentelemetry-python/pull/5143)). - `opentelemetry-sdk`: add `additional_properties` support to generated config models via custom `datamodel-codegen` template, enabling plugin/custom component names to flow through typed dataclasses ([#5131](https://github.com/open-telemetry/opentelemetry-python/pull/5131)) - Fix incorrect code example in `create_tracer()` docstring 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 3627db7058..89f44ce56b 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 @@ -499,10 +499,11 @@ 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, error details: %s", self._exporting, self._endpoint, error.code(), # type: ignore [reportAttributeAccessIssue] + error.details(), exc_info=error.code() == StatusCode.UNKNOWN, # type: ignore [reportAttributeAccessIssue] ) result.error = error @@ -511,11 +512,12 @@ 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. Error details: %s", error.code(), # type: ignore [reportAttributeAccessIssue] self._exporting, self._endpoint, backoff_seconds, + error.details(), ) 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 87bd72c555..7011912639 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 @@ -117,11 +117,13 @@ def __init__( export_result: StatusCode, optional_retry_nanos: Optional[int] = None, optional_export_sleep: Optional[float] = None, + optional_error_details: Optional[str] = None, ): self.export_result = export_result self.optional_export_sleep = optional_export_sleep self.optional_retry_nanos = optional_retry_nanos self.num_requests = 0 + self.optional_error_details = optional_error_details # pylint: disable=invalid-name,unused-argument def Export(self, request, context): @@ -142,6 +144,8 @@ def Export(self, request, context): ) ) context.set_code(self.export_result) + if self.optional_error_details: + context.set_details(self.optional_error_details) return ExportTraceServiceResponse() @@ -578,7 +582,9 @@ def test_retry_not_made_if_would_exceed_timeout(self): ) def test_timeout_set_correctly(self): mock_trace_service = TraceServiceServicerWithExportParams( - StatusCode.UNAVAILABLE, optional_export_sleep=0.25 + StatusCode.UNAVAILABLE, + optional_export_sleep=0.25, + optional_error_details="Could not finish in time.", ) add_TraceServiceServicer_to_server( mock_trace_service, @@ -598,7 +604,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, error details: Deadline Exceeded", warning.records[-1].message, ) self.assertEqual(mock_trace_service.num_requests, 2) @@ -626,7 +632,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_error_details="This already exists.", ), self.server, ) @@ -635,7 +642,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, error details: This already exists.", ) metrics_data = self.metric_reader.get_metrics_data()