Loguru: Issue while adding Request ID in flask

Created on 10 Jun 2020  路  4Comments  路  Source: Delgan/loguru

Request ID is stored in flask.g.request_id argument in flask's before_request. I am facing issue in logging this request id through "format" variable of the loguru for each and every request.

question

Most helpful comment

Well, you need to make use of the extra dict. You can setup your handler like that:

logger.add(sys.stderr, format="{time} - {level} - {extra[request_id]} - {message}")
logger.configure(extra={"request_id": None})  # Set global default value

Then, when you get access to the actual request_id value you need to bind() it to the logger:

def before_request():
    logger = logger.bind(request_id=flask.g.request_id)
    logger.info("Preparing the request...")  # The "request_id" will appear in the logged message

Alternatively, you can use a format function so that the request_id can be retrieved dynamically at each logging call:

def formatter(record):
    record["extra"]["request_id"] = flask.g.getattr("request_id", None)
    return "{time} - {level} - {extra[request_id]} - {message}\n{exception}"

logger.add(sys.stderr, format=formatter)

Related and possibly useful functions are patch() and contextualize().

All 4 comments

Well, you need to make use of the extra dict. You can setup your handler like that:

logger.add(sys.stderr, format="{time} - {level} - {extra[request_id]} - {message}")
logger.configure(extra={"request_id": None})  # Set global default value

Then, when you get access to the actual request_id value you need to bind() it to the logger:

def before_request():
    logger = logger.bind(request_id=flask.g.request_id)
    logger.info("Preparing the request...")  # The "request_id" will appear in the logged message

Alternatively, you can use a format function so that the request_id can be retrieved dynamically at each logging call:

def formatter(record):
    record["extra"]["request_id"] = flask.g.getattr("request_id", None)
    return "{time} - {level} - {extra[request_id]} - {message}\n{exception}"

logger.add(sys.stderr, format=formatter)

Related and possibly useful functions are patch() and contextualize().

Thanks @Delgan for thee quick reply.

While trying out the first option i.e. binding request_id in before_request function, its available in the same file, but when we log the same request from other file, global default value (None) is getting printed.

Also, in before_request function its not able to reference the logger that we imported at the top. So we have to add a test_request_context and import one more time.

Problem with the formatter function was - AttributeError: '_AppCtxGlobals' object has no attribute 'getattr'

Appreciate all your help.

While trying out the first option i.e. binding request_id in before_request function, its available in the same file, but when we log the same request from other file, global default value (None) is getting printed.

Yeah, only the logger returned by logger.bind() got access to the request_id value. If you are using the logger in another file, you need to pass the request_id to the other file and call bind() again. Alternatively, you can use contextualize() like this:

def do_request():
    with logger.contextualize(request_id=flask.g.request_id):
        call_method_in_another_file()

I'm not sure this is suitable for use with before_request(), so the workaround using a dynamic format is probably better.

Also, in before_request function its not able to reference the logger that we imported at the top. So we have to add a test_request_context and import one more time.

Are you referring to the UnboundLocalError? This can be fixed by using logger_ = logger.bind(request_id=flask.g.request_id) for example (sorry, I should have thought of that).

Problem with the formatter function was - AttributeError: '_AppCtxGlobals' object has no attribute 'getattr'

My bad. It should be record["extra"]["request_id"] = getattr(flask.g, "request_id", None) instead.

Thanks @Delgan for the immediate response.

The formatter method helped me solve the issue. I had to use "with app.test_request_context():" for the method as it threw "RuntimeError: Working outside of application context." And "with app.app_context():" couldn't solve the issue.

Thanks a lot once again
Problem Solved

Was this page helpful?
0 / 5 - 0 ratings

Related issues

HarveySummers picture HarveySummers  路  4Comments

lvar picture lvar  路  6Comments

BarryThrill picture BarryThrill  路  6Comments

jonathanhle picture jonathanhle  路  3Comments

lgvaz picture lgvaz  路  6Comments