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 ac7a9f7483d Add log_timestamp_format config option for component log 
timestamps (#63321)
ac7a9f7483d is described below

commit ac7a9f7483d32fa3506f77967a7c359ae4ce5765
Author: Shubham Gondane <[email protected]>
AuthorDate: Wed Mar 11 05:42:03 2026 -0700

    Add log_timestamp_format config option for component log timestamps (#63321)
    
    * Add log_timestamp_format config option for component log timestamps
    
    * Add strftime to spelling wordlist
---
 airflow-core/src/airflow/config_templates/config.yml   | 15 ++++++++++++++-
 airflow-core/src/airflow/logging_config.py             |  1 +
 docs/spelling_wordlist.txt                             |  1 +
 shared/logging/src/airflow_shared/logging/structlog.py |  8 +++++++-
 shared/logging/tests/logging/test_structlog.py         | 10 ++++++++++
 5 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/airflow-core/src/airflow/config_templates/config.yml 
b/airflow-core/src/airflow/config_templates/config.yml
index 2d70e625c15..d398f54ddfd 100644
--- a/airflow-core/src/airflow/config_templates/config.yml
+++ b/airflow-core/src/airflow/config_templates/config.yml
@@ -917,11 +917,24 @@ logging:
       description: |
         Determines the formatter class used by Airflow for structuring its log 
messages
         The default formatter class is timezone-aware, which means that 
timestamps attached to log entries
-        will be adjusted to reflect the local timezone of the Airflow instance
+        will be adjusted to reflect the local timezone of the Airflow instance.
+        Note: This setting does NOT affect component logs (scheduler, 
api-server, triggerer, etc.) since
+        those use structlog directly. Use ``log_timestamp_format`` to control 
timestamps for those logs.
       version_added: 2.3.4
       type: string
       example: ~
       default: "airflow.utils.log.timezone_aware.TimezoneAware"
+    log_timestamp_format:
+      description: |
+        Timestamp format for component logs (scheduler, api-server, triggerer, 
etc.).
+        Use ``iso`` for ISO 8601 format (default), or a Python strftime format 
string
+        such as ``%Y-%m-%d %H:%M:%S``.
+        Note: This setting only applies to component logs rendered via 
structlog.
+        Task/DAG logs use ``log_format`` instead.
+      version_added: 3.0.4
+      type: string
+      example: "%Y-%m-%d %H:%M:%S"
+      default: "iso"
     secret_mask_adapter:
       description: |
         An import path to a function to add adaptations of each secret added 
with
diff --git a/airflow-core/src/airflow/logging_config.py 
b/airflow-core/src/airflow/logging_config.py
index b0aa945e6b4..da15d0c246a 100644
--- a/airflow-core/src/airflow/logging_config.py
+++ b/airflow-core/src/airflow/logging_config.py
@@ -120,6 +120,7 @@ def configure_logging():
             namespace_log_levels=conf.get("logging", "namespace_levels", 
fallback=None),
             stdlib_config=logging_config,
             log_format=log_fmt,
+            log_timestamp_format=conf.get("logging", "log_timestamp_format", 
fallback="iso"),
             callsite_parameters=callsite_params,
             colors=colors,
         )
diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt
index 8dc6d26e91e..fab58efe027 100644
--- a/docs/spelling_wordlist.txt
+++ b/docs/spelling_wordlist.txt
@@ -1510,6 +1510,7 @@ StoredInfoType
 storedInfoType
 str
 Streamable
+strftime
 Stringified
 stringified
 Struct
diff --git a/shared/logging/src/airflow_shared/logging/structlog.py 
b/shared/logging/src/airflow_shared/logging/structlog.py
index a4fe4ec384c..5464d578a10 100644
--- a/shared/logging/src/airflow_shared/logging/structlog.py
+++ b/shared/logging/src/airflow_shared/logging/structlog.py
@@ -230,6 +230,7 @@ def structlog_processors(
     log_format: str = "",
     colors: bool = True,
     callsite_parameters: tuple[CallsiteParameter, ...] = (),
+    log_timestamp_format: str = "iso",
 ):
     """
     Create the correct list of structlog processors for the given config.
@@ -245,7 +246,7 @@ def structlog_processors(
 
     :meta private:
     """
-    timestamper = structlog.processors.MaybeTimeStamper(fmt="iso")
+    timestamper = 
structlog.processors.MaybeTimeStamper(fmt=log_timestamp_format)
 
     # Processors shared between stdlib handlers and structlog processors
     shared_processors: list[structlog.typing.Processor] = [
@@ -387,6 +388,7 @@ def configure_logging(
     json_output: bool = False,
     log_level: str = "DEBUG",
     log_format: str = "",
+    log_timestamp_format: str = "iso",
     stdlib_config: dict | None = None,
     extra_processors: Sequence[Processor] | None = None,
     callsite_parameters: Iterable[CallsiteParameter] | None = None,
@@ -404,6 +406,9 @@ def configure_logging(
     :param json_output: Set to true to write all logs as JSON (one per line)
     :param log_level: The default log level to use for most logs
     :param log_format: A percent-style log format to write non JSON logs with.
+    :param log_timestamp_format: Timestamp format for component logs. Use 
``"iso"`` for ISO 8601 format
+        (the default), or a strftime format string such as ``"%Y-%m-%d 
%H:%M:%S"``. Note: this only
+        applies to component logs rendered via structlog (scheduler, 
api-server, triggerer, etc.).
     :param output: Where to write the logs to. If ``json_output`` is true this 
must be a binary stream
     :param colors: Whether to use colors for non-JSON logs. This only works if 
standard out is a TTY (that is,
         an interactive session), unless overridden by environment variables 
described below.
@@ -465,6 +470,7 @@ def configure_logging(
         log_format=log_format,
         colors=colors,
         callsite_parameters=tuple(callsite_parameters or ()),
+        log_timestamp_format=log_timestamp_format,
     )
     shared_pre_chain += list(extra_processors)
     pre_chain: list[structlog.typing.Processor] = 
[structlog.stdlib.add_logger_name] + shared_pre_chain
diff --git a/shared/logging/tests/logging/test_structlog.py 
b/shared/logging/tests/logging/test_structlog.py
index 5637ad4333d..42d1e715aef 100644
--- a/shared/logging/tests/logging/test_structlog.py
+++ b/shared/logging/tests/logging/test_structlog.py
@@ -206,6 +206,16 @@ def test_precent_fmt_force_no_colors(
     )
 
 
+def test_log_timestamp_format(structlog_config):
+    """Test that log_timestamp_format controls the timestamp format in 
component logs."""
+    with structlog_config(colors=False, log_timestamp_format="%Y-%m-%d 
%H:%M:%S") as sio:
+        logger = structlog.get_logger("my.logger")
+        logger.info("Hello")
+
+    written = sio.getvalue()
+    assert "1985-10-26 00:00:00" in written
+
+
 @pytest.mark.parametrize(
     ("get_logger", "config_kwargs", "log_kwargs", "expected_kwargs"),
     [

Reply via email to