<#743 add phase runtimes to action details> Pull r...
# flyte-github
a
#743 add phase runtimes to action details Pull request opened by dansola Test on this run: https://demo.hosted.unionai.cloud/v2/domain/development/project/daniel/runs/rhn8t2tsh8q5r577797b Script:
Copy code
def test_phase_transitions(run_name: str, action_name: str):
    """Test phase transition functionality with a real action."""
    print(f"Fetching action: run={run_name}, action={action_name}")
    print("-" * 80)

    # Get action details directly (ActionDetails.get is sync via @syncify)
    details = ActionDetails.get(run_name=run_name, name=action_name)
    print(f"✓ Got action: {action_name}")
    print(f"  Phase: {details.phase}")
    print()

    print(f"✓ Got action details")
    print(f"  Total runtime: {details.runtime.total_seconds():.2f}s")
    print(f"  Attempts: {details.attempts}")
    print()

    # Test the new functionality
    print("=" * 80)
    print("TESTING NEW PHASE TRANSITION FUNCTIONALITY")
    print("=" * 80)
    print()

    # Test 1: Get phase transitions
    print("1. Testing get_phase_transitions():")
    transitions = details.get_phase_transitions()
    if transitions:
        print(f"   ✓ Found {len(transitions)} phase transitions:")
        for t in transitions:
            duration_sec = t.duration.total_seconds()
            end_str = t.end_time.isoformat() if t.end_time else "ongoing"
            print(f"     - {t.phase.value:25s} {duration_sec:8.2f}s  ({t.start_time.isoformat()} -> {end_str})")
    else:
        print("   ⚠ No phase transitions found (might be an older action or local execution)")
    print()

    # Test 2: Phase durations property
    print("2. Testing phase_durations property:")
    durations = details.phase_durations
    if durations:
        print(f"   ✓ Found {len(durations)} phases:")
        for phase, duration in durations.items():
            print(f"     - {phase.value}: {duration.total_seconds():.2f}s")
    else:
        print("   ⚠ No phase durations available")
    print()

    # Test 3: Individual phase properties
    print("3. Testing individual phase properties:")
    phase_checks = [
        ("queued_time", details.queued_time),
        ("waiting_for_resources_time", details.waiting_for_resources_time),
        ("initializing_time", details.initializing_time),
        ("running_time", details.running_time),
    ]

    for prop_name, value in phase_checks:
        if value is not None:
            print(f"   ✓ {prop_name:30s} = {value.total_seconds():8.2f}s")
        else:
            print(f"   - {prop_name:30s} = None (phase not encountered)")
    print()

    # Test 4: Rich representation
    print("4. Testing rich representation (shows phase_breakdown):")
    print("-" * 80)
    print(details)
    print("-" * 80)
    print()

    # Verify totals match
    if durations:
        total_from_phases = sum(d.total_seconds() for d in durations.values())
        total_runtime = details.runtime.total_seconds()
        diff = abs(total_from_phases - total_runtime)
        print(f"5. Verification:")
        print(f"   Total from phases: {total_from_phases:.2f}s")
        print(f"   Total runtime:     {total_runtime:.2f}s")
        print(f"   Difference:        {diff:.2f}s")
        if diff < 1.0:  # Allow 1s difference due to rounding
            print("   ✓ Totals match!")
        else:
            print("   ⚠ Totals don't match exactly (might be expected depending on phase transitions)")

    print()
    print("=" * 80)
    print("✓ ALL TESTS COMPLETED")
    print("=" * 80)
Result: ``` Fetching action: run=rhn8t2tsh8q5r577797b, action=a0 -------------------------------------------------------------------------------- ✓ Got action: a0 Phase: ActionPhase.SUCCEEDED ✓ Got action details Total runtime: 32.17s Attempts: 1 ================================================================================ TESTING NEW PHASE TRANSITION FUNCTIONALITY ================================================================================ 1. Testing get_phase_transitions(): ✓ Found 4 phase transitions: - waiting_for_resources 4.15s (2026-02-25T161117.895057+00:00 -> 2026-02-25T161122.040876+00:00) - queued 0.04s (2026-02-25T161122.040876+00:00 -> 2026-02-25T161122.076044+00:00) - running 28.27s (2026-02-25T161122.076044+00:00 -> 2026-02-25T161150.342616+00:00) - succeeded 0.00s (2026-02-25T161150.342616+00:00 -> 2026-02-25T161150.342616+00:00) 2. Testing phase_durations property: ✓ Found 4 phases: - waiting_for_resources: 4.15s - queued: 0.04s - running: 28.27s - succeeded: 0.00s 3. Testing individual phase properties: ✓ queued_time = 0.04s ✓ waiting_for_resources_time = 4.15s - initializing_time = None (phase not encountered) ✓ running_time = 28.27s 4. Testing rich representation (shows phase_breakdown): -------------------------------------------------------------------------------- ActionDetails( name='rhn8t2tsh8q5r577797b', start_time='2026-02-25T161117.831931+00:00', end_time='2026-02-25T161150+00:00', run_time='32 secs', phase='ACTION_PHASE_SUCCEEDED', error='NA', task='flyte_v2.flyte_workflow', task_type='actor', task_version='0a4a8514cee73446310d19f03a499ec3', attempts=[phase: ACTION_PHASE_SUCCEEDED start_time { seconds: 1772035877 nanos: 895057472 } end_time { seconds: 1772035910 nanos: 342616457 } attempt: 1 log_info { uri: "https://us-east-2.console.aws.amazon.com/cloudwatch/home?region=us-east-2#logsV2:log-groups/log-group/$252Funion$252Fcluster-oc-production$252Ftask/log-events/kube.namespace-daniel-development.pod-flyte-v2-5d469e4d87e6.cont-flyte-v2-5d469e4d87e6$3Fstart$3D1772035882040$26end$3D1772035910342" name: "Cloudwatch Logs" ready: true } outputs { output_uri: "s3://union-oc-production-demo/metadata/v2/demo/daniel/development/rhn8t2tsh8q5r577797b/a0/1/outputs.pb" } logs_available: true cluster_events { occurred_at { seconds: 1772035877 nanos: 895057472 } message: "no workers available" } cluster_events { occurred_at { seconds: 1772035882 nanos: 40876163 } message: "task offered to worker flyte-v2-5d469e4d87e6" } phase_transitions { phase: ACTION_PHASE_WAITING_FOR_RESOURCES start_time { seconds: 1772035877 nanos: 895057472 } end_time { seconds: 1772035882 nanos: 40876163 } } phase_transitions { phase: ACTION_PHASE_QUEUED start_time { seconds: 1772035882 nanos: 40876163 } end_time { seconds: 1772035882 nanos: 76044300 } } phase_transitions { phase: ACTION_PHASE_RUNNING start_time { seconds: 1772035882 nanos: 76044300 } end_time { seconds: 1772035910 nanos: 342616457 } } phase_transitions { phase: ACTION_PHASE_SUCCEEDED start_time { seconds: 1772035910 nanos: 342616457 } end_time { seconds: 1772035910 nanos: 342616457 } } cluster: "oc-production" log_context { pods { namespace: "daniel-development" pod_name: "flyte-v2-5d469e4d87e6" containers { container_name: "flyte-v2-5d469e4d87e6" process { container_start_time { seconds: 1772035882 nanos: 40813663 } container_end_time { seconds: 1772035910 nanos: 342561206 } } } primary_container_name: "flyte-v2-5d469e4d87e6" } primary_pod_name: "flyte-v2-5d469e4d87e6" } ], error='NA', phase='ACTION_PHASE_SUCCEEDED', group='', parent='', phase_breakdown={ 'waiting_for_resources': '4.15s', 'queued': '0.04s', 'running': '28.27s', 'succeeded': '0.00s' } ) -------------------------------------------------------------------------------- 5. Verification: Total from phases: 32.45s Total runtime: 32.17s Difference… flyteorg/flyte-sdk