explodinglabs/jsonrpcserver

[4.1.3] Local uncaught exceptions are not propagated inside JSON-RPC handlers

MasterGroosha opened this issue · 4 comments

Hello. I have a logs.py file with the following code:

import sys
import logging


def setup_log():
    logging.basicConfig(level=logging.INFO)
    _logger = logging.getLogger("myapp")
    fh = logging.FileHandler("log.txt")
    fh.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
    _logger.addHandler(fh)
    sys.excepthook = foo


def foo(exctype, value, tb):
    logger = logging.getLogger("myapp")
    logger.error("Unhandled exception", exc_info=(exctype, value, tb))

And this code does work fine. When in my main file I write something like this:

if __name__ == "__main__":
   raise ValueError("text")

I see this exception in "log.txt" file

However, when I do the same in JSON-RPC handlers:

@method
async def MyRpcMethod(token: str):
   raise ValueError("text")

I get nothing on my server-side. What could be the problem? Is it possible somehow to use such "uncaught exceptions handler" with json-rpc?

bcb commented

I believe sys.excepthook is only called on unhandled exceptions, and jsonrpcserver does handle exceptions, so this could be your problem.

@bcb thank you for the quick answer! I'm not too familiar with your library, is there any way to keep some exceptions locally rather than return them to the caller?

bcb commented

There are two loggers:

jsonrpcserver.dispatcher.request
jsonrpcserver.dispatcher.response

All you need to do is add handlers to them.

Here's a full example (using StreamHandler):

import logging

from flask import Flask, request, Response
from jsonrpcserver import method, dispatch


app = Flask(__name__)

# Request handler
request_logger = logging.getLogger("jsonrpcserver.dispatcher.request")
request_handler = logging.StreamHandler()
request_logger.addHandler(request_handler)
request_logger.setLevel(logging.INFO)

# Response handler
response_logger = logging.getLogger("jsonrpcserver.dispatcher.response")
response_handler = logging.StreamHandler()
response_logger.addHandler(response_handler)
response_logger.setLevel(logging.INFO)


@method
def ping():
    return "pong"


@app.route("/", methods=["POST"])
def index():
    response = dispatch(request.get_data().decode())
    return Response(str(response), response.http_status, mimetype="application/json")


if __name__ == "__main__":
    app.run()

@bcb thanks a lot! This is really helpful!