| # Copyright 2026 The Fuchsia Authors. All rights reserved. | |
| # Use of this source code is governed by a BSD-style license that can be | |
| # found in the LICENSE file. | |
| import json | |
| from typing import Any | |
| from worktree import WorktreeState | |
| from worktree_metrics import WorktreeMetricsTracker | |
| from worktree_pool import WorktreePool | |
| def _format_duration(seconds: float) -> str: | |
| total_sec = int(seconds) | |
| hours = total_sec // 3600 | |
| minutes = (total_sec % 3600) // 60 | |
| if hours > 0: | |
| return f"{hours}h {minutes}m" | |
| return f"{minutes}m {total_sec % 60}s" | |
| def run(args: Any, pool: WorktreePool) -> None: | |
| worktrees = pool.get_worktrees() | |
| total_count = len(worktrees) | |
| leased_count = sum( | |
| 1 for wt in worktrees if wt.get_state() == WorktreeState.LEASED | |
| ) | |
| built_recently_count = sum( | |
| 1 for wt in worktrees if wt.is_built_recently(max_age_days=7) | |
| ) | |
| not_built_recently_count = total_count - built_recently_count | |
| tracker = WorktreeMetricsTracker(pool.jiri_root, pool.fuchsia_dir) | |
| summary = tracker.get_summary( | |
| current_total=total_count, | |
| current_leased=leased_count, | |
| current_built_recently=built_recently_count, | |
| current_not_built_recently=not_built_recently_count, | |
| ) | |
| if getattr(args, "json", False): | |
| print(json.dumps(summary, indent=2)) | |
| return | |
| dur_str = _format_duration(summary["period_duration_sec"]) | |
| next_snap_str = _format_duration(summary["seconds_until_next_snapshot"]) | |
| print("=== fx worktree metrics ===") | |
| print(f"Measurement Window: {dur_str} (24h rolling period)") | |
| print(f"Next Snapshot Upload: in {next_snap_str}\n") | |
| print( | |
| f"{'Category':<18} {'Current':<9} {'Avg (Time-Weighted)':<21} {'Min':<6} {'Peak (Max)':<10}" | |
| ) | |
| print("-" * 68) | |
| category_labels = ( | |
| ("total", "Total"), | |
| ("leased", "Leased"), | |
| ("built_recently", "BuiltRecently"), | |
| ("not_built_recently", "NotBuiltRecently"), | |
| ) | |
| for cat, label in category_labels: | |
| cur = summary["current"][cat] | |
| avg = summary["average"][cat] | |
| mn = summary["min"][cat] | |
| mx = summary["max"][cat] | |
| print(f"{label:<18} {cur:<9} {avg:<21.2f} {mn:<6} {mx:<10}") |