예제 #1
0
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
예제 #2
0
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
예제 #3
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