Skip to content

opentelemetry-instrumentation-grpc: Client unary call throws NotImplementedError #3915

@marinarasub

Description

@marinarasub

Describe your environment

OS: Windows 10
Python version: 3.13.1
Package version: opentelemetry-instrumentation-grpc 0.59b0

What happened?

Unlike the sync version, add_done_callback is not implemented for grpc aio client unary-unary call response.

File "C:\***\.venv\Lib\site-packages\opentelemetry\instrumentation\grpc\_aio_client.py", line 117, in _wrap_    call.add_done_callback(
    ~~~~~~~~~~~~~~~~~~~~~~^
        _unary_done_callback(
        ^^^^^^^^^^^^^^^^^^^^^
            span, code, details, self._call_response_hook
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        )
        ^
    )
    ^
  File "C:\***\.venv\Lib\site-packages\grpc\aio\_interceptor.py", line 1063, in add_done_callback                                                                                                                           allback
    raise NotImplementedError()
NotImplementedError

Steps to Reproduce

  1. Install opentelemetry-instrumentation-grpc
  2. Globally instrument in code with
from opentelemetry.instrumentation.grpc import GrpcAioInstrumentorClient, GrpcInstrumentorClient
GrpcAioInstrumentorClient().instrument()
GrpcInstrumentorClient().instrument()
  1. Add a client interceptor which finishes client call (ie call = await continuation(...); return await call)
  2. Use grpc client and make a client call through on any method (I used grpc.aio.insecure_channel)

Expected Result

No opentelemetry instrumentation exception during client call

Actual Result

Exception from opentelemetry instrumentation

Additional context

I think this only happens b/c I have a custom interceptor which awaits the call object, and the finished call is passed to the opentelemetry interceptor instead of the pending call. The sync version (UnaryOutcome) just directly calls the callback in add_done_callback:
https://github.com/grpc/grpc/blob/master/src/python/grpcio/grpc/_interceptor.py#L185

Grpc Issue:
grpc/grpc#40998
Maybe wait for fix on grpc side, but also since the call can either be an awaitable Call object or the actual response, maybe we can do something like:

if isinstance(call, grpc.aio.UnaryUnaryCall):
    call.add_done_callback(... self._call_response_hook)
else:
    self._call_response_hook(...)
...
return call

https://github.com/grpc/grpc/blob/f0ea80fa6adecc10df9d852897493bd4ca393a15/src/python/grpcio/grpc/aio/_interceptor.py#L1044
Perhaps also add a catch-all try block to skip trace so that users don't break if there is an issue between instrumentation and grpc library

Would you like to implement a fix?

None

Tip

React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions