import logging import flask_restx as restx class LoggingTest(object): def test_namespace_loggers_log_to_flask_app_logger(self, app, client, caplog): # capture Flask app logs caplog.set_level(logging.INFO, logger=app.logger.name) api = restx.Api(app) ns1 = api.namespace("ns1", path="/ns1") ns2 = api.namespace("ns2", path="/ns2") @ns1.route("/") class Ns1(restx.Resource): def get(self): ns1.logger.info("hello from ns1") pass @ns2.route("/") class Ns2(restx.Resource): def get(self): ns2.logger.info("hello from ns2") pass # debug log not shown client.get("/ns1/") matching = [r for r in caplog.records if r.message == "hello from ns1"] assert len(matching) == 1 # info log shown client.get("/ns2/") matching = [r for r in caplog.records if r.message == "hello from ns2"] assert len(matching) == 1 def test_defaults_to_app_level(self, app, client, caplog): caplog.set_level(logging.INFO, logger=app.logger.name) api = restx.Api(app) ns1 = api.namespace("ns1", path="/ns1") ns2 = api.namespace("ns2", path="/ns2") @ns1.route("/") class Ns1(restx.Resource): def get(self): ns1.logger.debug("hello from ns1") pass @ns2.route("/") class Ns2(restx.Resource): def get(self): ns2.logger.info("hello from ns2") pass # debug log not shown client.get("/ns1/") matching = [r for r in caplog.records if r.message == "hello from ns1"] assert len(matching) == 0 # info log shown client.get("/ns2/") matching = [r for r in caplog.records if r.message == "hello from ns2"] assert len(matching) == 1 def test_override_app_level(self, app, client, caplog): caplog.set_level(logging.DEBUG, logger=app.logger.name) api = restx.Api(app) ns1 = api.namespace("ns1", path="/ns1") ns1.logger.setLevel(logging.DEBUG) ns2 = api.namespace("ns2", path="/ns2") ns2.logger.setLevel(logging.INFO) @ns1.route("/") class Ns1(restx.Resource): def get(self): ns1.logger.debug("hello from ns1") pass @ns2.route("/") class Ns2(restx.Resource): def get(self): ns2.logger.debug("hello from ns2") pass # debug log shown from ns1 client.get("/ns1/") matching = [r for r in caplog.records if r.message == "hello from ns1"] assert len(matching) == 1 # debug not shown from ns2 client.get("/ns2/") matching = [r for r in caplog.records if r.message == "hello from ns2"] assert len(matching) == 0 def test_namespace_additional_handler(self, app, client, caplog, tmp_path): caplog.set_level(logging.INFO, logger=app.logger.name) log_file = tmp_path / "v1.log" api = restx.Api(app) ns1 = api.namespace("ns1", path="/ns1") # set up a file handler for ns1 only # FileHandler only supports Path object on Python >= 3.6 -> cast to str fh = logging.FileHandler(str(log_file)) ns1.logger.addHandler(fh) ns2 = api.namespace("ns2", path="/ns2") @ns1.route("/") class Ns1(restx.Resource): def get(self): ns1.logger.info("hello from ns1") pass @ns2.route("/") class Ns2(restx.Resource): def get(self): ns2.logger.info("hello from ns2") pass # ns1 logs go to stdout and log_file client.get("/ns1/") matching = [r for r in caplog.records if r.message == "hello from ns1"] assert len(matching) == 1 with log_file.open() as f: assert "hello from ns1" in f.read() # ns2 logs go to stdout only client.get("/ns2/") matching = [r for r in caplog.records if r.message == "hello from ns2"] assert len(matching) == 1 with log_file.open() as f: assert "hello from ns1" in f.read()