Skip to content

fix(agentex): build valid OTLP metrics URLs#346

Merged
scale-sf merged 2 commits into
mainfrom
fix/otlp-metrics-dd-agent-host-url
Jul 7, 2026
Merged

fix(agentex): build valid OTLP metrics URLs#346
scale-sf merged 2 commits into
mainfrom
fix/otlp-metrics-dd-agent-host-url

Conversation

@scale-sf

@scale-sf scale-sf commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

  • fix worker OTLP metrics URL construction for normal DD_AGENT_HOST values like localhost, service names, and IPv4 literals
  • keep IPv6 literals bracketed and preserve explicit ports
  • add focused unit coverage for metrics URL construction

Closes #313. Supersedes stale external PR #323 with the same underlying fix on a fresh branch.

Tests

  • uv run ruff check agentex/src/temporal/run_worker.py agentex/tests/unit/temporal/test_run_worker_metrics_url.py
  • uv run --package agentex-backend --group test pytest agentex/tests/unit/temporal/test_run_worker_metrics_url.py -m unit -q
  • uv run --package agentex-backend --group test pytest agentex/tests/unit/temporal -m unit -q
  • Runtime repro with temporalio 1.23.0: old http://[{DD_AGENT_HOST}]:4317 URLs reject localhost, datadog-agent, and 10.0.0.5 with Invalid OTel URL: invalid IPv6 address; build_metrics_url(...) outputs are accepted by Runtime(telemetry=TelemetryConfig(metrics=OpenTelemetryConfig(url=...))).

Greptile Summary

Fixes the OTLP metrics URL construction for Temporal workers by replacing the broken http://[{DD_AGENT_HOST}]:4317 string interpolation with a dedicated build_metrics_url function that correctly handles all common DD_AGENT_HOST shapes and adds focused unit tests for each case.

  • build_metrics_url correctly handles plain hostnames, IPv4 literals, bare IPv6 addresses (brackets them), pre-bracketed IPv6 (including the previously-identified empty-trailing-port edge case "[::1]:", now covered by a test), and explicit ports for all host types.
  • One unguarded edge case remains: a malformed input that begins with "[" but has no closing "]" bypasses the inner parsing block and is then double-bracketed by the final colon-presence check, producing an invalid URL like http://[[::1]:4317.

Confidence Score: 5/5

Safe to merge — the fix correctly resolves the invalid IPv6-bracket wrapping for all realistic DD_AGENT_HOST values and is well-covered by the new unit tests.

The core bug (wrapping every host in IPv6 brackets) is definitively fixed and tested across all meaningful host shapes. The one unguarded path — a malformed input that begins with an unclosed bracket — is an unrealistic operator configuration and does not affect production behaviour.

No files require special attention; the logic in run_worker.py is straightforward and the test file covers all realistic cases.

Important Files Changed

Filename Overview
agentex/src/temporal/run_worker.py Replaces the broken http://[{DD_AGENT_HOST}]:4317 template with build_metrics_url, correctly handling plain hostnames, IPv4, bare IPv6 (brackets them), pre-bracketed IPv6 (strips and re-brackets), and explicit ports. One edge case remains: a malformed input like "[::1" (missing closing bracket) bypasses the inner block and then gets double-bracketed by the trailing guard, producing an invalid URL.
agentex/tests/unit/temporal/test_run_worker_metrics_url.py New unit tests covering None/empty input, plain hostnames, IPv4, bare IPv6, pre-bracketed IPv6 (including the previously-reported "[::1]:" empty-port case), and explicit-port variants. No tests for the malformed "[::1" (missing closing bracket) case.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[build_metrics_url] --> B{host_url falsy?}
    B -- Yes --> C[return None]
    B -- No --> D[host = host_url.strip]
    D --> E{host empty?}
    E -- Yes --> C
    E -- No --> F[port = 4317 default]
    F --> G{host starts with bracket?}
    G -- Yes --> H[find closing bracket]
    H --> I{bracket found?}
    I -- Yes --> J[parse rest after bracket]
    J --> K{rest starts with colon?}
    K -- Yes --> L[port = rest after colon or default]
    K -- No --> M[port stays default]
    L --> N[host = inner IPv6 address]
    M --> N
    I -- No --> O[host unchanged with leading bracket - BUG PATH]
    G -- No --> P{exactly one colon in host?}
    P -- Yes --> Q[split host and port]
    P -- No --> R[host unchanged]
    Q --> S{colon in host?}
    N --> S
    O --> S
    R --> S
    S -- Yes --> T[wrap host in brackets]
    S -- No --> U[return http://host:port]
    T --> U
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[build_metrics_url] --> B{host_url falsy?}
    B -- Yes --> C[return None]
    B -- No --> D[host = host_url.strip]
    D --> E{host empty?}
    E -- Yes --> C
    E -- No --> F[port = 4317 default]
    F --> G{host starts with bracket?}
    G -- Yes --> H[find closing bracket]
    H --> I{bracket found?}
    I -- Yes --> J[parse rest after bracket]
    J --> K{rest starts with colon?}
    K -- Yes --> L[port = rest after colon or default]
    K -- No --> M[port stays default]
    L --> N[host = inner IPv6 address]
    M --> N
    I -- No --> O[host unchanged with leading bracket - BUG PATH]
    G -- No --> P{exactly one colon in host?}
    P -- Yes --> Q[split host and port]
    P -- No --> R[host unchanged]
    Q --> S{colon in host?}
    N --> S
    O --> S
    R --> S
    S -- Yes --> T[wrap host in brackets]
    S -- No --> U[return http://host:port]
    T --> U
Loading

Reviews (2): Last reviewed commit: "fix(agentex): default empty OTLP metrics..." | Re-trigger Greptile

@scale-sf scale-sf requested a review from a team as a code owner July 6, 2026 19:18
Comment thread agentex/src/temporal/run_worker.py Outdated

@smoreinis smoreinis left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@scale-sf scale-sf merged commit 38f917b into main Jul 7, 2026
49 of 52 checks passed
@scale-sf scale-sf deleted the fix/otlp-metrics-dd-agent-host-url branch July 7, 2026 19:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]: run_worker wraps DD_AGENT_HOST in IPv6 brackets, producing an invalid OTLP metrics URL that crashes the worker

2 participants