Skip to content

Conversation

@VegetarianOrc
Copy link
Contributor

@VegetarianOrc VegetarianOrc commented Nov 19, 2025

What was changed

  • Add NexusOperationInboundInterceptor
  • Add translation from NexusOperationInboundInterceptor to nexusrpc.handler.NexusOperationMiddleware
  • Add OpenTelemetry support for Nexus operations.

Checklist

Pairs with nexus-rpc/sdk-python#33

How was this tested:

  • Unit test added to verify that interceptors function as expected when calling Nexus operations.
  • Unit test added to verify that the OpenTelemetry interceptor produces the correct spans when calling Nexus operations.



class _NexusOperationHandlerForInterceptor(
nexusrpc.handler.MiddlewareSafeOperationHandler[Any, Any]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that I think about it, I wonder if there is any value in MiddlewareSafeOperationHandler accepting generics itself. Won't it basically always be [Any, Any]?. I think we should consider removing those over in the Nexus SDK.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

100% agreed here. Went ahead and made the change

cast,
)

import nexusrpc.handler
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does both import nexusrpc.handler and from nexusrpc.handler import X. Should decide which approach. I personally prefer import nexusrpc.handler and qualify at use site.

updated_context_carrier, add_to_outbound.headers
)

def _completed_span_nexus(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if you can just add a add_to_outbound_string_headers: Optional[_InputWithStringHeaders] = None to the existing method instead of making a new one. Same for adding a input_string_headers: Optional[_InputWithStringHeaders] = None to _start_as_current_span instead of a new method (maybe, didn't check here). Doesn't matter too much, but does keep the most of the logic centralized knowing the only difference is input type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Appreciate the suggestion here as this is what felt the worst to me. I originally was hoping to make it add_to_outbound: Optional[_InputWithHeaders | _InputWithStringHeaders] but it didn't seem like I could do a runtime check against which one it was. After your suggestion though, I realized that the defaulted kwarg is the same amount of extra runtime checks as the union would be and still allow keeping the logic centralized. LMK what you think of the new setup.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks much clearer to me

Copy link
Member

@cretz cretz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (not approving to let @tconley1428 look and since it's draft)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants