Implementation:Apache Airflow Trace Utilities
| Knowledge Sources | |
|---|---|
| Domains | Observability, Tracing |
| Last Updated | 2026-02-08 21:00 GMT |
Overview
Utility functions for trace context parsing and datetime conversion, providing datetime_to_nano(), parse_traceparent(), and parse_tracestate() for W3C Trace Context support.
Description
The trace utilities module provides three essential helper functions for Airflow's distributed tracing subsystem:
- datetime_to_nano(): Converts a Python datetime object to nanosecond-precision integer timestamps as required by OpenTelemetry span timestamps. Handles both timezone-aware and naive datetime objects (naive datetimes are treated as UTC).
- parse_traceparent(): Parses a W3C Trace Context
traceparentheader string (format:version-trace_id-parent_id-flags) into its component fields. This enables Airflow to participate in distributed traces initiated by external systems. - parse_tracestate(): Parses a W3C Trace Context
tracestateheader string (format:vendor1=value1,vendor2=value2) into a dictionary of vendor-specific trace state values.
The module also defines constants TRACE_ID (0) and SPAN_ID (16) used as index offsets for trace context parsing operations.
Usage
These utilities are used internally by the OTel tracer implementation and any code that needs to propagate or parse W3C trace context headers across process boundaries.
Code Reference
Source Location
- Repository: Apache Airflow
- File: shared/observability/src/airflow_shared/observability/traces/utils.py (62 lines)
Signature
TRACE_ID = 0
SPAN_ID = 16
def datetime_to_nano(datetime) -> int | None:
"""Convert datetime to nanoseconds.
Handles both timezone-aware and naive datetimes.
Naive datetimes are treated as UTC via calendar.timegm().
"""
...
def parse_traceparent(traceparent_str: str | None = None) -> dict:
"""Parse traceparent string: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01.
Returns dict with keys: version, trace_id, parent_id, flags.
"""
...
def parse_tracestate(tracestate_str: str | None = None) -> dict:
"""Parse tracestate string: rojo=00f067aa0ba902b7,congo=t61rcWkgMzE.
Returns dict of vendor key-value pairs.
"""
...
Import
from airflow_shared.observability.traces.utils import datetime_to_nano, parse_traceparent, parse_tracestate
I/O Contract
datetime_to_nano
| Name | Type | Required | Description |
|---|---|---|---|
| datetime | datetime.datetime | Yes | The datetime to convert (None returns None) |
Returns: int | None -- Nanosecond timestamp, or None if input is None.
parse_traceparent
| Name | Type | Required | Description |
|---|---|---|---|
| traceparent_str | str or None | No | W3C traceparent header value |
Returns: dict -- Keys: version, trace_id, parent_id, flags. Empty dict if input is None.
Raises: ValueError if the string does not contain exactly 4 dash-separated tokens.
parse_tracestate
| Name | Type | Required | Description |
|---|---|---|---|
| tracestate_str | str or None | No | W3C tracestate header value |
Returns: dict -- Vendor key-value pairs. Empty dict if input is None or empty.
Usage Examples
Converting Datetime to Nanoseconds
from datetime import datetime, timezone
from airflow_shared.observability.traces.utils import datetime_to_nano
# Timezone-aware datetime
dt = datetime(2024, 1, 15, 12, 0, 0, tzinfo=timezone.utc)
nano = datetime_to_nano(dt)
# Returns: 1705320000000000000
# Naive datetime (treated as UTC)
dt_naive = datetime(2024, 1, 15, 12, 0, 0)
nano = datetime_to_nano(dt_naive)
# Returns: 1705320000000000000
# None input
result = datetime_to_nano(None)
# Returns: None
Parsing W3C Trace Context
from airflow_shared.observability.traces.utils import parse_traceparent, parse_tracestate
# Parse traceparent header
tp = parse_traceparent("00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01")
# Returns: {
# "version": "00",
# "trace_id": "0af7651916cd43dd8448eb211c80319c",
# "parent_id": "b7ad6b7169203331",
# "flags": "01"
# }
# Parse tracestate header
ts = parse_tracestate("rojo=00f067aa0ba902b7,congo=t61rcWkgMzE")
# Returns: {"rojo": "00f067aa0ba902b7", "congo": "t61rcWkgMzE"}
Datetime Conversion Logic
The datetime_to_nano function handles two cases:
| Input Type | Conversion Method | Rationale |
|---|---|---|
| Naive datetime (no tzinfo) | calendar.timegm(dt.timetuple()) + dt.microsecond / 1e6 |
Treated as UTC; timegm avoids local timezone assumptions |
| Aware datetime (has tzinfo) | dt.timestamp() |
Uses Python's built-in timezone-aware conversion |
The result is multiplied by 1e9 and cast to int to produce nanosecond precision as required by OpenTelemetry span timestamps.