Skip to content

Commit c54292f

Browse files
authored
Check for None result in gRPC (#3380) (#3381)
1 parent d6f6c60 commit c54292f

File tree

3 files changed

+32
-1
lines changed

3 files changed

+32
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2424
([#3419](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3419))
2525
- `opentelemetry-instrumentation` don't print duplicated conflict log error message
2626
([#3432](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3432))
27+
- `opentelemetry-instrumentation-grpc` Check for None result in gRPC
28+
([#3380](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3381))
2729

2830
## Version 1.32.0/0.53b0 (2025-04-10)
2931

instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ def _intercept(self, request, metadata, client_info, invoker):
165165
span.record_exception(exc)
166166
raise exc
167167
finally:
168-
if not result:
168+
if result is None:
169169
span.end()
170170
return self._trace_result(span, rpc_info, result)
171171

instrumentation/opentelemetry-instrumentation-grpc/tests/test_client_interceptor.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
# limitations under the License.
1414
# pylint:disable=cyclic-import
1515

16+
from unittest import mock
17+
1618
import grpc
1719

1820
import opentelemetry.instrumentation.grpc
@@ -26,6 +28,7 @@
2628
)
2729
from opentelemetry.instrumentation.utils import suppress_instrumentation
2830
from opentelemetry.propagate import get_global_textmap, set_global_textmap
31+
from opentelemetry.sdk.trace import Span as SdkSpan
2932
from opentelemetry.semconv.trace import SpanAttributes
3033
from opentelemetry.test.mock_textmap import MockTextMapPropagator
3134
from opentelemetry.test.test_base import TestBase
@@ -269,6 +272,32 @@ def test_error_stream_stream(self):
269272
trace.StatusCode.ERROR,
270273
)
271274

275+
def test_client_interceptor_falsy_response(
276+
self,
277+
):
278+
"""ensure that client interceptor closes the span only once even if the response is falsy."""
279+
280+
with mock.patch.object(SdkSpan, "end") as span_end_mock:
281+
tracer_provider, _exporter = self.create_tracer_provider()
282+
tracer = tracer_provider.get_tracer(__name__)
283+
284+
interceptor = OpenTelemetryClientInterceptor(tracer)
285+
286+
def invoker(_request, _metadata):
287+
return {}
288+
289+
request = Request(client_id=1, request_data="data")
290+
interceptor.intercept_unary(
291+
request,
292+
{},
293+
_UnaryClientInfo(
294+
full_method="/GRPCTestServer/SimpleMethod",
295+
timeout=None,
296+
),
297+
invoker=invoker,
298+
)
299+
self.assertEqual(span_end_mock.call_count, 1)
300+
272301
def test_client_interceptor_trace_context_propagation(
273302
self,
274303
): # pylint: disable=no-self-use

0 commit comments

Comments
 (0)