Refactor _compute_metrics to improve longest job duration calculation and handle None values in due dates
This commit is contained in:
+26
-20
@@ -178,15 +178,14 @@ def _compute_metrics(
|
|||||||
avg_duration_today = (sum(durations_today) / len(durations_today)) if durations_today else None
|
avg_duration_today = (sum(durations_today) / len(durations_today)) if durations_today else None
|
||||||
|
|
||||||
longest_today = None
|
longest_today = None
|
||||||
|
longest_today_seconds = 0.0
|
||||||
if today_jobs:
|
if today_jobs:
|
||||||
finished_today = [
|
for j in today_jobs:
|
||||||
j for j in today_jobs if j.start_datetime and j.finish_datetime
|
if j.start_datetime and j.finish_datetime:
|
||||||
]
|
secs = (j.finish_datetime - j.start_datetime).total_seconds()
|
||||||
if finished_today:
|
if longest_today is None or secs > longest_today_seconds:
|
||||||
longest_today = max(
|
longest_today = j
|
||||||
finished_today,
|
longest_today_seconds = secs
|
||||||
key=lambda j: (j.finish_datetime - j.start_datetime).total_seconds(),
|
|
||||||
)
|
|
||||||
|
|
||||||
# On-time = job started within 15 min of due_datetime (when both known)
|
# On-time = job started within 15 min of due_datetime (when both known)
|
||||||
on_time = late = 0
|
on_time = late = 0
|
||||||
@@ -222,8 +221,8 @@ def _compute_metrics(
|
|||||||
# --- Upcoming today ---
|
# --- Upcoming today ---
|
||||||
upcoming_today = sorted(
|
upcoming_today = sorted(
|
||||||
(j for j in today_jobs
|
(j for j in today_jobs
|
||||||
if j.start_datetime is None and j.due_datetime and j.due_datetime >= now),
|
if j.start_datetime is None and j.due_datetime is not None and j.due_datetime >= now),
|
||||||
key=lambda j: j.due_datetime,
|
key=lambda j: j.due_datetime or datetime.max,
|
||||||
)[:5]
|
)[:5]
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -248,8 +247,7 @@ def _compute_metrics(
|
|||||||
"avg_duration_today": _fmt_duration(avg_duration_today) if avg_duration_today is not None else None,
|
"avg_duration_today": _fmt_duration(avg_duration_today) if avg_duration_today is not None else None,
|
||||||
"longest_today_name": longest_today.name if longest_today else None,
|
"longest_today_name": longest_today.name if longest_today else None,
|
||||||
"longest_today_duration": (
|
"longest_today_duration": (
|
||||||
_fmt_duration((longest_today.finish_datetime - longest_today.start_datetime).total_seconds())
|
_fmt_duration(longest_today_seconds) if longest_today else None
|
||||||
if longest_today else None
|
|
||||||
),
|
),
|
||||||
"on_time_rate_today": on_time_rate_today,
|
"on_time_rate_today": on_time_rate_today,
|
||||||
"on_time": on_time,
|
"on_time": on_time,
|
||||||
@@ -269,8 +267,11 @@ def _compute_metrics(
|
|||||||
"name": j.name,
|
"name": j.name,
|
||||||
"as_at": j.as_at_date.isoformat(),
|
"as_at": j.as_at_date.isoformat(),
|
||||||
"reason": j.status_reason or "—",
|
"reason": j.status_reason or "—",
|
||||||
"when": (j.finish_datetime or j.start_datetime).isoformat(timespec="minutes")
|
"when": (
|
||||||
if (j.finish_datetime or j.start_datetime) else "",
|
_when.isoformat(timespec="minutes")
|
||||||
|
if (_when := j.finish_datetime or j.start_datetime) is not None
|
||||||
|
else ""
|
||||||
|
),
|
||||||
}
|
}
|
||||||
for j in recent_failures
|
for j in recent_failures
|
||||||
],
|
],
|
||||||
@@ -278,7 +279,7 @@ def _compute_metrics(
|
|||||||
{
|
{
|
||||||
"id": j.id,
|
"id": j.id,
|
||||||
"name": j.name,
|
"name": j.name,
|
||||||
"due": j.due_datetime.strftime("%H:%M"),
|
"due": j.due_datetime.strftime("%H:%M") if j.due_datetime else "",
|
||||||
}
|
}
|
||||||
for j in upcoming_today
|
for j in upcoming_today
|
||||||
],
|
],
|
||||||
@@ -449,11 +450,16 @@ async def job_detail_view(request: Request, job_id: int):
|
|||||||
lateness_str = f"{_fmt_duration(delta)} late"
|
lateness_str = f"{_fmt_duration(delta)} late"
|
||||||
|
|
||||||
# Aggregate stats across history
|
# Aggregate stats across history
|
||||||
finished_related = [j for j in related if j.start_datetime and j.finish_datetime]
|
finished_related = [
|
||||||
avg_dur = (
|
j for j in related
|
||||||
sum((j.finish_datetime - j.start_datetime).total_seconds() for j in finished_related)
|
if j.start_datetime is not None and j.finish_datetime is not None
|
||||||
/ len(finished_related)
|
]
|
||||||
) if finished_related else None
|
finished_durations = [
|
||||||
|
(j.finish_datetime - j.start_datetime).total_seconds()
|
||||||
|
for j in finished_related
|
||||||
|
if j.start_datetime is not None and j.finish_datetime is not None
|
||||||
|
]
|
||||||
|
avg_dur = (sum(finished_durations) / len(finished_durations)) if finished_durations else None
|
||||||
success_count = sum(1 for j in related if j.status == "completed")
|
success_count = sum(1 for j in related if j.status == "completed")
|
||||||
fail_count = sum(1 for j in related if j.status == "failed")
|
fail_count = sum(1 for j in related if j.status == "failed")
|
||||||
finished_count = success_count + fail_count
|
finished_count = success_count + fail_count
|
||||||
|
|||||||
Reference in New Issue
Block a user