open-telemetry / open-telemetry/opentelemetry-python-contrib

grpc: invoke callable hooks that do not expose __name__

Open
#5,054 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
1.1k
Forks
1.1k
Avg merge
4d 15h
Merged PRs (30d)
16

Description

Applications registering callable objects or ordinary functools.partial objects as gRPC client hooks silently lose all hook-provided span enrichment and receive an erroneous callback-failure log on every call. The RPC itself still runs. Named functions and bound methods are unaffected.

At instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_client.py:68:

_safe_invoke evaluates function_name = function.__name__ before function(*args) inside the same try block. A callable instance implementing call but not name raises AttributeError at the first statement. The handler logs that error and never invokes the hook. Both _call_request_hook and _call_response_hook explicitly accept any callable at lines 164-172, so this metadata lookup imposes an unintended extra requirement. _BaseAioClientInterceptor inherits these methods in _aio_client.py:46, affecting both sync and async clients. Existing hook tests supply ordinary functions, which all have name.

Proposed fix

Make callback-name lookup optional in _client.py so missing name does not prevent invocation, retaining the existing exception boundary and fallback label. Extend tests/test_client_interceptor_hooks.py and tests/test_aio_client_interceptor_hooks.py with callable-object and partial hooks, successful span enrichment, and throwing-callable coverage. Keep the change scoped to gRPC rather than refactoring other packages' similarly named helpers. Add a root fixed changelog fragment after contribution prerequisites are resolved.

How to see it

Unexecuted, unambiguous Python execution trace. Define Hook with call that appends its arguments to a list and no name attribute. Construct OpenTelemetryClientInterceptor with this object as request_hook and response_hook, and call its two hook dispatch methods with sentinel span and message objects. callable returns True, then _safe_invoke raises AttributeError before call; the list stays empty instead of containing both calls. Test the same inherited dispatch on an aio interceptor. As public-path regression coverage, register callable-object and partial request hooks with GrpcInstrumentorClient and GrpcAioInstrumentorClient using the existing local test server; assert the hook's expected span attribute is present and no callback error is logged. A throwing callable should still be invoked once, logged, and prevented from breaking the RPC. These assertions fail before the fix and pass after it.

If this looks right I can push fix/grpc-callable-hooks on anxkhn/opentelemetry-python-contrib instead of opening a pull request first.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at _safe_invoke in instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/_client.py and run the existing hook tests. Extend tests/test_client_interceptor_hooks.py and tests/test_aio_client_interceptor_hooks.py for callable objects, partial hooks, and throwing callables, including span enrichment and logging behavior. Verify the public instrumentor paths with the local test server and add the required root changelog fragment.

Written by the indexing model from the issue text.

Assessment

Tech stack
grpc, python
Domain
api, testing
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.