From e6d4ec43b99461c58ff97b50fc5ddf37516dedf4 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Fri, 14 Jun 2024 15:49:30 -0400 Subject: [PATCH] Log tbs from non-RAE `._invoke()`-RPC-task errors `RemoteActorError`s show this by default in their `.__repr__()`, and we obvi capture and embed the src traceback in an `Error` msg prior to transit, but for logging it's also handy to see the tb of any set `Context._remote_error` on console especially when trying to decipher remote error details at their origin actor. Also improve the log message description using `ctx.repr_state` and show any `ctx.outcome`. --- tractor/_rpc.py | 47 ++++++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/tractor/_rpc.py b/tractor/_rpc.py index fa61577..c9eb845 100644 --- a/tractor/_rpc.py +++ b/tractor/_rpc.py @@ -26,6 +26,7 @@ from contextlib import ( from functools import partial import inspect from pprint import pformat +import traceback from typing import ( Any, Callable, @@ -47,6 +48,7 @@ from ._context import ( ) from ._exceptions import ( ContextCancelled, + RemoteActorError, ModuleNotExposed, MsgTypeError, TransportClosed, @@ -198,7 +200,8 @@ async def _invoke_non_context( raise ipc_err else: log.exception( - f'Failed to respond to runtime RPC request for\n\n' + f'Failed to ack runtime RPC request\n\n' + f'{func} x=> {ctx.chan}\n\n' f'{ack}\n' ) @@ -415,7 +418,6 @@ async def _errors_relayed_via_ipc( async def _invoke( - actor: Actor, cid: str, chan: Channel, @@ -691,10 +693,6 @@ async def _invoke( boxed_type=trio.Cancelled, canceller=canceller, ) - # does this matter other then for - # consistentcy/testing? |_ no user code should be - # in this scope at this point.. - # ctx._local_error = ctxc raise ctxc # XXX: do we ever trigger this block any more? @@ -715,6 +713,11 @@ async def _invoke( # always set this (child) side's exception as the # local error on the context ctx._local_error: BaseException = scope_error + # ^-TODO-^ question, + # does this matter other then for + # consistentcy/testing? + # |_ no user code should be in this scope at this point + # AND we already set this in the block below? # if a remote error was set then likely the # exception group was raised due to that, so @@ -741,22 +744,32 @@ async def _invoke( logmeth: Callable = log.runtime merr: Exception|None = ctx.maybe_error - descr_str: str = 'with final result `{repr(ctx.outcome)}`' - message: str = ( - f'IPC context terminated {descr_str}\n\n' + message: str = 'IPC context terminated ' + descr_str: str = ( + f'after having {ctx.repr_state!r}\n' ) if merr: - descr_str: str = ( - f'with ctx having {ctx.repr_state!r}\n' - f'{ctx.repr_outcome()}\n' - ) + + logmeth: Callable = log.error if isinstance(merr, ContextCancelled): logmeth: Callable = log.runtime - else: - logmeth: Callable = log.error - message += f'\n{merr!r}\n' - logmeth(message) + if not isinstance(merr, RemoteActorError): + tb_str: str = ''.join(traceback.format_exception(merr)) + descr_str += ( + f'\n{merr!r}\n' # needed? + f'{tb_str}\n' + ) + else: + descr_str += f'\n{merr!r}\n' + else: + descr_str += f'\nand final result {ctx.outcome!r}\n' + + logmeth( + message + + + descr_str + ) async def try_ship_error_to_remote(