This is an automated email from the ASF dual-hosted git repository.

vatsrahul1001 pushed a commit to branch v3-3-test
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/v3-3-test by this push:
     new 7e13aaa1be5 [v3-3-test] Fix missing HTTP access logs when api-server 
omits the core app (#72026) (#72808)
7e13aaa1be5 is described below

commit 7e13aaa1be52a5457ef46a4e9e879079c74c5879
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Thu Sep 10 13:29:00 2026 +0530

    [v3-3-test] Fix missing HTTP access logs when api-server omits the core app 
(#72026) (#72808)
    
    * Fix missing HTTP access logs when api-server omits the core app
    
    An api-server started without the core app -- for example `--apps 
execution`,
    the shape used to run the Task Execution API as its own deployment -- served
    requests but recorded none of them. That leaves the component every running 
task
    depends on for heartbeats, state transitions and XComs with no per-request
    telemetry, which is the primary signal for diagnosing heartbeat stalls.
    
    Both server backends disable their own access logger, and the built-in 
access
    loggers are muted in the logging config, all on the premise that
    HttpAccessLogMiddleware handles access logging. That premise only held 
while the
    middleware was installed by the core app branch, so no configuration could
    recover the records. Installing it for every apps selection makes the 
premise
    true again instead of adding a fourth conditional that would give 
execution-only
    deployments a different log format from every other deployment.
    
    * Lock in HttpAccessLog outermost ordering with a positional assertion
    
    * Trim redundant caveat from init_middlewares ordering note
    
    ---------
    (cherry picked from commit 860233f3c72dcc3637c43c64223e57e078c84d55)
    
    Co-authored-by: manish1337 <[email protected]>
    Co-authored-by: pierrejeambrun <[email protected]>
---
 airflow-core/src/airflow/api_fastapi/app.py          |  8 ++++++++
 airflow-core/src/airflow/api_fastapi/core_api/app.py |  8 +++-----
 airflow-core/tests/unit/api_fastapi/test_app.py      | 13 +++++++++++++
 3 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/airflow-core/src/airflow/api_fastapi/app.py 
b/airflow-core/src/airflow/api_fastapi/app.py
index 233965bd56e..d180cb7ca17 100644
--- a/airflow-core/src/airflow/api_fastapi/app.py
+++ b/airflow-core/src/airflow/api_fastapi/app.py
@@ -28,6 +28,7 @@ from fastapi.routing import Mount
 
 from airflow.api_fastapi.common.dagbag import create_dag_bag
 from airflow.api_fastapi.common.exceptions import init_error_handlers
+from airflow.api_fastapi.common.http_access_log import HttpAccessLogMiddleware
 from airflow.api_fastapi.core_api.app import (
     init_config,
     init_flask_plugins,
@@ -151,6 +152,8 @@ def create_app(apps: str = "all") -> FastAPI:
         init_error_handlers(app)
         init_middlewares(app)
 
+    init_access_logging(app)
+
     init_config(app)
 
     return app
@@ -218,6 +221,11 @@ def get_auth_manager() -> BaseAuthManager:
     return _AuthManagerState.instance
 
 
+def init_access_logging(app: FastAPI) -> None:
+    """Install the access log middleware, the only producer of access 
records."""
+    app.add_middleware(HttpAccessLogMiddleware)
+
+
 def init_plugins(app: FastAPI) -> None:
     """Integrate FastAPI app, middlewares and UI plugins."""
     from airflow import plugins_manager
diff --git a/airflow-core/src/airflow/api_fastapi/core_api/app.py 
b/airflow-core/src/airflow/api_fastapi/core_api/app.py
index 961f13fbc71..63280e1ba81 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/app.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/app.py
@@ -173,7 +173,6 @@ def init_config(app: FastAPI) -> None:
 def init_middlewares(app: FastAPI) -> None:
     from airflow.api_fastapi.app import get_auth_manager
     from airflow.api_fastapi.auth.middlewares.refresh_token import 
JWTRefreshMiddleware
-    from airflow.api_fastapi.common.http_access_log import 
HttpAccessLogMiddleware
 
     app.add_middleware(JWTRefreshMiddleware)
 
@@ -181,9 +180,8 @@ def init_middlewares(app: FastAPI) -> None:
         app.add_middleware(middleware_cls, **middleware_kwargs)
 
     # GZipMiddleware must be inside HttpAccessLogMiddleware so that access 
logs capture
-    # the full end-to-end duration including compression time.
+    # the full end-to-end duration including compression time. 
HttpAccessLogMiddleware is
+    # installed by ``init_access_logging`` in ``create_app``, which runs after 
this
+    # function — do not reorder those calls.
     # See https://github.com/apache/airflow/issues/60165
     app.add_middleware(GZipMiddleware, minimum_size=1024, compresslevel=5)
-    # HttpAccessLogMiddleware must be outermost (added last) so it times the 
full
-    # request lifecycle including all inner middleware.
-    app.add_middleware(HttpAccessLogMiddleware)
diff --git a/airflow-core/tests/unit/api_fastapi/test_app.py 
b/airflow-core/tests/unit/api_fastapi/test_app.py
index 9fd9a3edad1..5c65fb772c6 100644
--- a/airflow-core/tests/unit/api_fastapi/test_app.py
+++ b/airflow-core/tests/unit/api_fastapi/test_app.py
@@ -24,6 +24,7 @@ from fastapi import FastAPI
 
 import airflow.api_fastapi.app as app_module
 import airflow.plugins_manager as plugins_manager
+from airflow.api_fastapi.common.http_access_log import HttpAccessLogMiddleware
 
 pytestmark = pytest.mark.db_test
 
@@ -86,6 +87,18 @@ def test_all_apps(mock_create_task_exec_api, 
mock_init_plugins, mock_init_views,
     mock_create_task_exec_api.assert_called_once_with()
 
 
[email protected]("apps", ["all", "core", "execution"])
+def 
test_access_log_middleware_installed_outermost_for_every_apps_selection(apps, 
client):
+    """Both server backends disable their own access logger, so a selection 
that skips this
+    middleware has no access logging at all. It must also stay outermost so it 
times the full
+    request including inner middlewares (GZip compression in particular — see 
#60165); the
+    test default config has no CORS so index 0 is HttpAccessLogMiddleware."""
+    installed = [m.cls for m in client(apps=apps).app.user_middleware]
+
+    assert installed.count(HttpAccessLogMiddleware) == 1
+    assert installed[0] is HttpAccessLogMiddleware
+
+
 def test_catch_all_route_last(client):
     """
     Ensure the catch all route that returns the initial html is the last route 
in the fastapi app.

Reply via email to