server.py 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. import sentry_sdk
  2. from sentry_sdk.consts import OP
  3. from sentry_sdk.integrations import DidNotEnable
  4. from sentry_sdk.integrations.grpc.consts import SPAN_ORIGIN
  5. from sentry_sdk.tracing import TransactionSource
  6. from typing import TYPE_CHECKING
  7. if TYPE_CHECKING:
  8. from typing import Callable, Optional
  9. from google.protobuf.message import Message
  10. try:
  11. import grpc
  12. from grpc import ServicerContext, HandlerCallDetails, RpcMethodHandler
  13. except ImportError:
  14. raise DidNotEnable("grpcio is not installed")
  15. class ServerInterceptor(grpc.ServerInterceptor): # type: ignore
  16. def __init__(
  17. self: "ServerInterceptor",
  18. find_name: "Optional[Callable[[ServicerContext], str]]" = None,
  19. ) -> None:
  20. self._custom_find_name = find_name
  21. super().__init__()
  22. def intercept_service(
  23. self: "ServerInterceptor",
  24. continuation: "Callable[[HandlerCallDetails], RpcMethodHandler]",
  25. handler_call_details: "HandlerCallDetails",
  26. ) -> "RpcMethodHandler":
  27. handler = continuation(handler_call_details)
  28. if not handler or not handler.unary_unary:
  29. return handler
  30. method_name = handler_call_details.method
  31. custom_find_name = self._custom_find_name
  32. def behavior(request: "Message", context: "ServicerContext") -> "Message":
  33. with sentry_sdk.isolation_scope():
  34. name = custom_find_name(context) if custom_find_name else method_name
  35. if name:
  36. metadata = dict(context.invocation_metadata())
  37. transaction = sentry_sdk.continue_trace(
  38. metadata,
  39. op=OP.GRPC_SERVER,
  40. name=name,
  41. source=TransactionSource.CUSTOM,
  42. origin=SPAN_ORIGIN,
  43. )
  44. with sentry_sdk.start_transaction(transaction=transaction):
  45. try:
  46. return handler.unary_unary(request, context)
  47. except BaseException as e:
  48. raise e
  49. else:
  50. return handler.unary_unary(request, context)
  51. return grpc.unary_unary_rpc_method_handler(
  52. behavior,
  53. request_deserializer=handler.request_deserializer,
  54. response_serializer=handler.response_serializer,
  55. )