def test_request_instrumentation(client_and_log_handler): """Test if a request log is written""" api_client, _ = client_and_log_handler request_logger = logging.getLogger("fastapi-request-logger") handler = FormattedMessageCollectorHandler() request_logger.addHandler(handler) response = api_client.get("/log/levels/debug") assert response.status_code == 200 assert len(handler.messages) == 1
def test_excluded_from_request_instrumentation(client_and_log_handler): """Test if endpoints can be excluded from the request log""" api_client, _ = client_and_log_handler request_logger = logging.getLogger("fastapi-request-logger") handler = FormattedMessageCollectorHandler() request_logger.addHandler(handler) response = api_client.get("/no-request-instrumentation") assert response.status_code == 200 assert len(handler.messages) == 0
def client_and_log_handler(): import json_logging # Init app app = fastapi.FastAPI() # Init std logging logger = logging.getLogger(LOGGER_NAME) logger.setLevel(logging.DEBUG) handler = FormattedMessageCollectorHandler() logger.addHandler(handler) # Add json_logging json_logging.init_fastapi(enable_json=True) json_logging.init_request_instrument( app, exclude_url_patterns=["^/no-request-instrumentation"]) # Prepare test endpoints @app.get("/log/levels/debug") async def log_debug(): logger.debug("debug message") return {} @app.get("/log/levels/info") async def log_info(): logger.info("info message") return {} @app.get("/log/levels/error") async def log_error(): logger.error("error message") return {} @app.get("/log/extra_property") async def extra_property(): logger.info( "test log statement with extra props", extra={ "props": { "extra_property": "extra_value" }, "tags": ["app:name"], "extra_property": "extra_value2" }, ) return {} @app.get("/log/extra_property_no_props") async def extra_property_no_props(): logger.info( "test log statement with extra and no 'props' property", extra={ "tags": ["app:name"], "extra_property": "extra_value2" }, ) return {} @app.get("/log/exception") async def log_exception(): try: raise RuntimeError() except BaseException as e: logger.exception("Error occurred", exc_info=e) return {} @app.get("/get-correlation-id") async def get_correlation_id(): return {'correlation_id': json_logging.get_correlation_id()} @app.get('/no-request-instrumentation') async def excluded_from_request_instrumentation(): return {} test_client = fastapi.testclient.TestClient(app) yield test_client, handler # Tear down test environment logger.removeHandler(handler) undo_imports_from_package( "json_logging") # Necessary because of json-logging's global state