Skip to content

Commit ba409d4

Browse files
committed
enhance rpc expose interface
1 parent addb8a0 commit ba409d4

File tree

1 file changed

+36
-11
lines changed

1 file changed

+36
-11
lines changed

packages/service-library/src/servicelib/rabbitmq/_rpc_router.py

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,48 +6,73 @@
66
from typing import Any, TypeVar
77

88
from models_library.rabbitmq_basic_types import RPCMethodName
9-
from pydantic import SecretStr
109

1110
from ..logging_utils import log_context
1211
from ._errors import RPCServerError
1312

1413
DecoratedCallable = TypeVar("DecoratedCallable", bound=Callable[..., Any])
1514

15+
# NOTE: this is equivalent to http access logs
1616
_logger = logging.getLogger("rpc.access")
1717

18-
_RPC_CUSTOM_ENCODER: dict[Any, Callable[[Any], Any]] = {
19-
SecretStr: SecretStr.get_secret_value
20-
}
18+
19+
def _create_func_msg(func, args: list[Any], kwargs: dict[str, Any]) -> str:
20+
msg = f"{func.__name__}("
21+
22+
if args_msg := ", ".join(map(str, args)):
23+
msg += args_msg
24+
25+
if kwargs_msg := ", ".join({f"{name}={value}" for name, value in kwargs.items()}):
26+
if args:
27+
msg += ", "
28+
msg += kwargs_msg
29+
30+
return f"{msg})"
2131

2232

2333
@dataclass
2434
class RPCRouter:
2535
routes: dict[RPCMethodName, Callable] = field(default_factory=dict)
2636

27-
def expose(self) -> Callable[[DecoratedCallable], DecoratedCallable]:
28-
def decorator(func: DecoratedCallable) -> DecoratedCallable:
37+
def expose(
38+
self,
39+
*,
40+
reraise_if_error_type: tuple[type[Exception], ...] | None = None,
41+
) -> Callable[[DecoratedCallable], DecoratedCallable]:
42+
def _decorator(func: DecoratedCallable) -> DecoratedCallable:
2943
@functools.wraps(func)
30-
async def wrapper(*args, **kwargs):
44+
async def _wrapper(*args, **kwargs):
45+
3146
with log_context(
47+
# NOTE: this is intentionally analogous to the http access log traces.
48+
# To change log-level use getLogger("rpc.access").set_level(...)
3249
_logger,
3350
logging.INFO,
34-
msg=f"calling {func.__name__} with {args}, {kwargs}",
51+
msg=f"RPC call {_create_func_msg(func, args, kwargs)}",
52+
log_duration=True,
3553
):
3654
try:
3755
return await func(*args, **kwargs)
56+
3857
except asyncio.CancelledError:
3958
_logger.debug("call was cancelled")
4059
raise
60+
4161
except Exception as exc: # pylint: disable=broad-except
62+
if reraise_if_error_type and isinstance(
63+
exc, reraise_if_error_type
64+
):
65+
raise
66+
4267
_logger.exception("Unhandled exception:")
4368
# NOTE: we do not return internal exceptions over RPC
4469
raise RPCServerError(
4570
method_name=func.__name__,
46-
exc_type=f"{type(exc)}",
71+
exc_type=f"{exc.__class__.__module__}.{exc.__class__.__name__}",
4772
msg=f"{exc}",
4873
) from None
4974

50-
self.routes[RPCMethodName(func.__name__)] = wrapper
75+
self.routes[RPCMethodName(func.__name__)] = _wrapper
5176
return func
5277

53-
return decorator
78+
return _decorator

0 commit comments

Comments
 (0)