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

potiuk 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 724aaade2f6 Bump structlog>=26.1.0 and croniter>=6.2.2 to fix memory 
leaks (#70694)
724aaade2f6 is described below

commit 724aaade2f6209924125a46304e036434e41caa4
Author: Jason(Zhe-You) Liu <[email protected]>
AuthorDate: Thu Jul 30 17:51:57 2026 +0800

    Bump structlog>=26.1.0 and croniter>=6.2.2 to fix memory leaks (#70694)
    
    * Bump structlog>=26.1.0 and croniter>=6.1.0 to fix memory leaks
    
    * Raise croniter floor to 6.2.2 and drop obsolete structlog workarounds
---
 airflow-core/pyproject.toml                        |  4 ++--
 airflow-ctl/pyproject.toml                         |  2 +-
 shared/dagnode/pyproject.toml                      |  2 +-
 shared/listeners/pyproject.toml                    |  2 +-
 shared/logging/pyproject.toml                      |  2 +-
 .../src/airflow_shared/logging/structlog.py        | 28 ++++------------------
 shared/observability/pyproject.toml                |  2 +-
 shared/providers_discovery/pyproject.toml          |  2 +-
 task-sdk/pyproject.toml                            |  2 +-
 uv.lock                                            | 18 +++++++-------
 10 files changed, 23 insertions(+), 41 deletions(-)

diff --git a/airflow-core/pyproject.toml b/airflow-core/pyproject.toml
index 45a73e1633d..0657e4f9231 100644
--- a/airflow-core/pyproject.toml
+++ b/airflow-core/pyproject.toml
@@ -85,7 +85,7 @@ dependencies = [
     "cadwyn>=6.1.1",
     "colorlog>=6.8.2",
     "cron-descriptor>=1.2.24",
-    "croniter>=2.0.2",
+    "croniter>=6.2.2",
     # Cryptography could be upgraded to 46.0.5, but it does not have overlap 
with earlier versions
     # Of Airflow which were limited to <46.0.0 also earlier provider versions 
will not be compatible with newer
     # airflow if we do not have overlapping version. We could set minimum 
version to 46.0.0 when we drop
@@ -161,7 +161,7 @@ dependencies = [
     # Start of shared logging dependencies
     "msgspec>=0.19.0",
     "pygtrie>=2.5.0",
-    "structlog>=25.4.0",
+    "structlog>=26.1.0",
     # End of shared logging dependencies
     # Start of shared configuration dependencies
     "pyyaml>=6.0.3",
diff --git a/airflow-ctl/pyproject.toml b/airflow-ctl/pyproject.toml
index 170b637cf85..2b788c987e4 100644
--- a/airflow-ctl/pyproject.toml
+++ b/airflow-ctl/pyproject.toml
@@ -39,7 +39,7 @@ dependencies = [
     "pydantic>=2.11.0", # https://github.com/apache/airflow/issues/56482
     "pyyaml>=6.0.3",
     "rich-argparse>=1.0.0",
-    "structlog>=25.4.0",
+    "structlog>=26.1.0",
     "uuid6>=2024.7.10",
     "tabulate>=0.9.0",
     "tenacity>=9.1.4",
diff --git a/shared/dagnode/pyproject.toml b/shared/dagnode/pyproject.toml
index 01189ccc765..e0870ea887a 100644
--- a/shared/dagnode/pyproject.toml
+++ b/shared/dagnode/pyproject.toml
@@ -24,7 +24,7 @@ classifiers = [
 ]
 
 dependencies = [
-    "structlog>=25.4.0",
+    "structlog>=26.1.0",
 ]
 
 [dependency-groups]
diff --git a/shared/listeners/pyproject.toml b/shared/listeners/pyproject.toml
index f798410c131..92688eb466e 100644
--- a/shared/listeners/pyproject.toml
+++ b/shared/listeners/pyproject.toml
@@ -26,7 +26,7 @@ classifiers = [
 dependencies = [
     "opentelemetry-api>=1.27.0",
     "pluggy>=1.5.0",
-    "structlog>=25.4.0",
+    "structlog>=26.1.0",
 ]
 
 [dependency-groups]
diff --git a/shared/logging/pyproject.toml b/shared/logging/pyproject.toml
index 22c3a6541a6..99ee05dbf14 100644
--- a/shared/logging/pyproject.toml
+++ b/shared/logging/pyproject.toml
@@ -26,7 +26,7 @@ classifiers = [
 dependencies = [
     "msgspec>=0.19.0",
     "pygtrie>=2.5.0",
-    "structlog>=25.4.0",
+    "structlog>=26.1.0",
 ]
 
 [dependency-groups]
diff --git a/shared/logging/src/airflow_shared/logging/structlog.py 
b/shared/logging/src/airflow_shared/logging/structlog.py
index 1c4341e99e5..b13be191445 100644
--- a/shared/logging/src/airflow_shared/logging/structlog.py
+++ b/shared/logging/src/airflow_shared/logging/structlog.py
@@ -24,7 +24,6 @@ import logging
 import os
 import re
 import sys
-import weakref
 from collections.abc import Callable, Iterable, Mapping, Sequence
 from functools import cache, cached_property
 from pathlib import Path
@@ -254,25 +253,19 @@ def make_filtering_logger() -> Callable[..., 
BindableLogger]:
     return maker
 
 
-# structlog >= 26.1.0 added a `name` slot + kwarg to BytesLogger
-# (hynek/structlog#786). Detect it once so we can avoid a redundant slot and
-# forward `name` through the parent init. The same detection is applied to
-# WriteLogger so the analogous upstream change lands without a regression.
-_BYTES_LOGGER_HAS_NAME = "name" in getattr(structlog.BytesLogger, "__slots__", 
())
+# structlog >= 26.1.0 (our floor) gave BytesLogger a `name` slot + kwarg
+# (hynek/structlog#786), but WriteLogger has not received the analogous change
+# yet. Detect it so the upstream addition lands without a regression.
 _WRITE_LOGGER_HAS_NAME = "name" in getattr(structlog.WriteLogger, "__slots__", 
())
 
 
 class NamedBytesLogger(structlog.BytesLogger):
-    __slots__ = () if _BYTES_LOGGER_HAS_NAME else ("name",)
+    __slots__ = ()
 
     def __init__(self, name: str | None = None, file: BinaryIO | None = None):
         if file is not None:
             file = make_file_io_non_caching(file)
-        if _BYTES_LOGGER_HAS_NAME:
-            super().__init__(file, name=name)  # type: ignore[call-arg]
-        else:
-            super().__init__(file)
-            self.name = name
+        super().__init__(file, name=name)
 
 
 class NamedWriteLogger(structlog.WriteLogger):
@@ -644,17 +637,6 @@ def configure_logging(
             text_output = cast("TextIO", output)
         logger_factory = LoggerFactory(NamedWriteLogger, io=text_output)
 
-    # Replace structlog's WRITE_LOCKS dict with a WeakKeyDictionary so entries
-    # for closed file descriptors are garbage-collected instead of leaking.
-    # TODO: drop once structlog ships the upstream fix (tracked for 26.1.0).
-    try:
-        from structlog import _output as _structlog_output
-
-        if isinstance(_structlog_output.WRITE_LOCKS, dict):
-            _structlog_output.WRITE_LOCKS = weakref.WeakKeyDictionary()  # 
type: ignore[assignment]
-    except Exception:
-        pass
-
     structlog.configure(
         processors=shared_pre_chain + [for_structlog],
         cache_logger_on_first_use=cache_logger_on_first_use,
diff --git a/shared/observability/pyproject.toml 
b/shared/observability/pyproject.toml
index f75a9d369f4..ed0dae24fd1 100644
--- a/shared/observability/pyproject.toml
+++ b/shared/observability/pyproject.toml
@@ -26,7 +26,7 @@ classifiers = [
 dependencies = [
     "opentelemetry-api>=1.27.0",
     "pendulum>=3.1.0",
-    "structlog>=25.4.0",
+    "structlog>=26.1.0",
     "methodtools>=0.4.7",
 ]
 
diff --git a/shared/providers_discovery/pyproject.toml 
b/shared/providers_discovery/pyproject.toml
index 75dc5ab041e..a4aa7ba6a97 100644
--- a/shared/providers_discovery/pyproject.toml
+++ b/shared/providers_discovery/pyproject.toml
@@ -27,7 +27,7 @@ dependencies = [
     "packaging>=25.0",
     "pendulum>=3.1.0",
     "jsonschema>=4.19.1",
-    "structlog>=25.4.0",
+    "structlog>=26.1.0",
     "pygtrie>=2.5.0",
     "methodtools>=0.4.7",
     'importlib_metadata>=6.5;python_version<"3.12"',
diff --git a/task-sdk/pyproject.toml b/task-sdk/pyproject.toml
index 34a43329247..bb8f7e2c3f4 100644
--- a/task-sdk/pyproject.toml
+++ b/task-sdk/pyproject.toml
@@ -60,7 +60,7 @@ dependencies = [
     "msgspec>=0.19.0",
     "python-dateutil>=2.7.0",
     "psutil>=6.1.0",
-    "structlog>=25.4.0",
+    "structlog>=26.1.0",
     "greenback>=1.2.1",
     "tenacity>=8.3.0",
     # Start of shared timezones dependencies
diff --git a/uv.lock b/uv.lock
index 7120d1597ab..f8a31f62196 100644
--- a/uv.lock
+++ b/uv.lock
@@ -2079,7 +2079,7 @@ requires-dist = [
     { name = "cadwyn", specifier = ">=6.1.1" },
     { name = "colorlog", specifier = ">=6.8.2" },
     { name = "cron-descriptor", specifier = ">=1.2.24" },
-    { name = "croniter", specifier = ">=2.0.2" },
+    { name = "croniter", specifier = ">=6.2.2" },
     { name = "cryptography", specifier = ">=44.0.3" },
     { name = "deprecated", specifier = ">=1.2.13" },
     { name = "dill", specifier = ">=0.2.2" },
@@ -2133,7 +2133,7 @@ requires-dist = [
     { name = "sqlalchemy", extras = ["asyncio"], specifier = ">=2.0.50" },
     { name = "starlette", specifier = ">=1.0.1" },
     { name = "statsd", marker = "extra == 'statsd'", specifier = ">=3.3.0" },
-    { name = "structlog", specifier = ">=25.4.0" },
+    { name = "structlog", specifier = ">=26.1.0" },
     { name = "svcs", specifier = ">=25.1.0" },
     { name = "tabulate", specifier = ">=0.9.0" },
     { name = "tenacity", specifier = ">=8.3.0" },
@@ -2215,7 +2215,7 @@ requires-dist = [
     { name = "pydantic", specifier = ">=2.11.0" },
     { name = "pyyaml", specifier = ">=6.0.3" },
     { name = "rich-argparse", specifier = ">=1.0.0" },
-    { name = "structlog", specifier = ">=25.4.0" },
+    { name = "structlog", specifier = ">=26.1.0" },
     { name = "tabulate", specifier = ">=0.9.0" },
     { name = "tenacity", specifier = ">=9.1.4" },
     { name = "uuid6", specifier = ">=2024.7.10" },
@@ -8567,7 +8567,7 @@ mypy = [
 ]
 
 [package.metadata]
-requires-dist = [{ name = "structlog", specifier = ">=25.4.0" }]
+requires-dist = [{ name = "structlog", specifier = ">=26.1.0" }]
 
 [package.metadata.requires-dev]
 dev = [{ name = "apache-airflow-devel-common", editable = "devel-common" }]
@@ -8597,7 +8597,7 @@ mypy = [
 requires-dist = [
     { name = "opentelemetry-api", specifier = ">=1.27.0" },
     { name = "pluggy", specifier = ">=1.5.0" },
-    { name = "structlog", specifier = ">=25.4.0" },
+    { name = "structlog", specifier = ">=26.1.0" },
 ]
 
 [package.metadata.requires-dev]
@@ -8630,7 +8630,7 @@ mypy = [
 requires-dist = [
     { name = "msgspec", specifier = ">=0.19.0" },
     { name = "pygtrie", specifier = ">=2.5.0" },
-    { name = "structlog", specifier = ">=25.4.0" },
+    { name = "structlog", specifier = ">=26.1.0" },
 ]
 
 [package.metadata.requires-dev]
@@ -8712,7 +8712,7 @@ requires-dist = [
     { name = "opentelemetry-proto", marker = "extra == 'otel'", specifier = 
">=1.27.0,<9999" },
     { name = "pendulum", specifier = ">=3.1.0" },
     { name = "statsd", marker = "extra == 'statsd'", specifier = ">=3.3.0" },
-    { name = "structlog", specifier = ">=25.4.0" },
+    { name = "structlog", specifier = ">=26.1.0" },
 ]
 provides-extras = ["otel", "statsd", "datadog", "all"]
 
@@ -8791,7 +8791,7 @@ requires-dist = [
     { name = "packaging", specifier = ">=25.0" },
     { name = "pendulum", specifier = ">=3.1.0" },
     { name = "pygtrie", specifier = ">=2.5.0" },
-    { name = "structlog", specifier = ">=25.4.0" },
+    { name = "structlog", specifier = ">=26.1.0" },
 ]
 
 [package.metadata.requires-dev]
@@ -9053,7 +9053,7 @@ requires-dist = [
     { name = "sentry-sdk", marker = "extra == 'sentry'", specifier = 
">=2.30.0" },
     { name = "statsd", marker = "extra == 'all'", specifier = ">=3.3.0" },
     { name = "statsd", marker = "extra == 'statsd'", specifier = ">=3.3.0" },
-    { name = "structlog", specifier = ">=25.4.0" },
+    { name = "structlog", specifier = ">=26.1.0" },
     { name = "tenacity", specifier = ">=8.3.0" },
     { name = "typing-extensions", specifier = ">=4.14.1" },
 ]

Reply via email to