Skip to content

statsd_ipv6=True does not enable IPv6 for StatsD metrics because ipv6 is passed as maxudpsize #69451

Closed

Description

@ykuc

Under which category would you file this issue?

Airflow Core

Apache Airflow version

3.2.2

What happened and how to reproduce it?

airflow_shared.observability.metrics.statsd_logger.get_statsd_logger() calls the StatsD client as:

statsd = stats_class(host, port, prefix, ipv6)
What happened

We run Airflow in an IPv6-only Kubernetes environment and send Airflow metrics to a StatsD endpoint.

Even with IPv6 StatsD support enabled:

AIRFLOW__METRICS__STATSD_ON=True
AIRFLOW__METRICS__STATSD_HOST=
AIRFLOW__METRICS__STATSD_PORT=8125
AIRFLOW__METRICS__STATSD_PREFIX=airflow
AIRFLOW__METRICS__STATSD_IPV6=True

Airflow components, for example workers, fail to configure the StatsD metrics client and fall back to NoStatsLogger.

Example log:

{
"logger": "airflow._shared.observability.metrics.stats",
"timestamp": "2026-07-03T18:45:26.741537Z",
"level": "ERROR",
"loc": "stats.py:108",
"message": "Could not configure StatsClient: [Errno -5] No address associated with hostname, using NoStatsLogger instead."
}

As a result, metrics from the affected Airflow component are not emitted.

What I think should happen

When AIRFLOW__METRICS__STATSD_IPV6=True / [metrics] statsd_ipv6 = True is set, Airflow should initialize the default statsd.StatsClient with ipv6=True, so the StatsD host is resolved using IPv6.

Metrics should be sent successfully to an IPv6-only StatsD endpoint.

Probable root cause

The probable issue is in:

airflow_shared/observability/metrics/statsd_logger.py

Current code calls the StatsD client positionally:

statsd = stats_class(host, port, prefix, ipv6)

However, the default statsd.StatsClient constructor has this signature:

StatsClient(
host="localhost",
port=8125,
prefix=None,
maxudpsize=512,
ipv6=False,
)

So Airflow's ipv6 value is passed as the fourth positional argument, which means it lands in maxudpsize, not in ipv6.

Effectively:

stats_class(host, port, prefix, True)

becomes:

StatsClient(
host=host,
port=port,
prefix=prefix,
maxudpsize=True,
ipv6=False,
)

Therefore statsd_ipv6=True never actually enables IPv6 sockets for the default StatsD client.

How to reproduce

Use an IPv6-only hostname for statsd_host, for example a Kubernetes Service that only resolves to an AAAA record.

Set:

AIRFLOW__METRICS__STATSD_ON=True
AIRFLOW__METRICS__STATSD_HOST=
AIRFLOW__METRICS__STATSD_PORT=8125
AIRFLOW__METRICS__STATSD_PREFIX=airflow
AIRFLOW__METRICS__STATSD_IPV6=True

Start an Airflow component that initializes metrics, for example a worker.

Expected: StatsD client is initialized with IPv6 enabled.

Actual: Airflow logs:

Could not configure StatsClient: [Errno -5] No address associated with hostname, using NoStatsLogger instead.

and metrics are not emitted.

This can also be demonstrated with a custom test StatsD client that records received constructor arguments: the ipv6 value is passed as the fourth positional argument instead of the ipv6 keyword argument.

Workaround

We are currently working around this by overriding the StatsD client:

  • name: AIRFLOW__METRICS__STATSD_CUSTOM_CLIENT_PATH
    value: "settings.metrics.ipv6_statsd_client.IPv6StatsClient"

The custom client detects the Airflow positional-argument behavior and forwards ipv6=True to the parent statsd.StatsClient as a keyword argument:

class IPv6StatsClient(statsd.StatsClient):
def init(
self,
host: str = "localhost",
port: int = 8125,
prefix: str | None = None,
maxudpsize: int = 512,
ipv6: bool = False,
) -> None:
# Airflow passes ipv6 as the 4th positional argument,
# which lands in maxudpsize for statsd.StatsClient.
if isinstance(maxudpsize, bool):
ipv6 = maxudpsize
maxudpsize = 512

    super().__init__(
        host=host,
        port=port,
        prefix=prefix,
        maxudpsize=maxudpsize,
        ipv6=True,
    )

This workaround confirms that the same StatsD endpoint works once the underlying statsd.StatsClient is initialized with IPv6 enabled.

Suggested fix

Pass arguments to the StatsD client by keyword instead of positionally:

statsd = stats_class(
host=host,
port=port,
prefix=prefix,
ipv6=ipv6,
)

This should make [metrics] statsd_ipv6 = True work as documented for the default statsd.StatsClient.

A regression test could assert that when ipv6=True is passed to get_statsd_logger(), the configured StatsD client receives ipv6=True as the ipv6 argument, not as maxudpsize.

Related context

This appears related to the previous IPv6 StatsD support change:

#42625

That PR added an option to enable IPv6 address resolution for the StatsD host, but the current positional call appears to prevent the option from taking effect with the default statsd.StatsClient.

What you think should happen instead?

No response

Operating System

No response

Deployment

None

Apache Airflow Provider(s)

No response

Versions of Apache Airflow Providers

No response

Official Helm Chart version

1.22.0 (latest released)

Kubernetes Version

No response

Helm Chart configuration

No response

Docker Image customizations

No response

Anything else?

No response

Are you willing to submit PR?

  • Yes I am willing to submit a PR!

Code of Conduct

Activity

  1. added
    kind:bugThis is a clearly a bug
    needs-triagelabel for new issues that we didn't triage yet
    on Jul 6, 2026
  2. boring-cyborg commented on Jul 6, 2026

    @boring-cyborg

    Thanks for opening your first issue here! Be sure to follow the issue template! If you are willing to raise PR to address this issue please do so, no need to wait for approval.

  3. ykuc commented on Jul 6, 2026

    @ykuc
    ContributorAuthor

    I will make mr in some days

  4. vismaytiwari commented on Jul 8, 2026

    @vismaytiwari

    hey @ykuc , Would you mind, if I open PR on this?
    will wait for your confirmation,
    Thanks.

  5. ykuc commented on Jul 8, 2026

    @ykuc
    ContributorAuthor

    Hi @vismaytiwari ,
    Thanks, but I had already made these changes locally before your message. I just hadn’t committed them or opened an MR yet.

  6. eladkal commented on Jul 29, 2026

    @eladkal
    Contributor

    Fixed in #69632

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions