This is an automated email from the ASF dual-hosted git repository.
vatsrahul1001 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 860233f3c72 Fix missing HTTP access logs when api-server omits the
core app (#72026)
860233f3c72 is described below
commit 860233f3c72dcc3637c43c64223e57e078c84d55
Author: manish1337 <[email protected]>
AuthorDate: Wed Sep 9 19:19:34 2026 +0530
Fix missing HTTP access logs when api-server omits the core app (#72026)
* 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
---------
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 55ec201b9ee..524cb32cac2 100644
--- a/airflow-core/src/airflow/api_fastapi/app.py
+++ b/airflow-core/src/airflow/api_fastapi/app.py
@@ -29,6 +29,7 @@ from starlette.middleware import Middleware
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,
@@ -152,6 +153,8 @@ def create_app(apps: str = "all") -> FastAPI:
init_error_handlers(app)
init_middlewares(app)
+ init_access_logging(app)
+
init_config(app)
return app
@@ -219,6 +222,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 8ceea05828b..eac48ccbd7c 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/app.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/app.py
@@ -175,7 +175,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)
@@ -183,9 +182,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 26e505021da..19174592e65 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
from tests_common.test_utils.config import conf_vars
@@ -88,6 +89,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.