@@ -1161,87 +1161,95 @@ def get_cached_mlflow_url():
11611161
11621162 time .sleep (poll )
11631163 else :
1164- # Terminal experience with rich library
1165- try :
1166- from rich .live import Live
1167- from rich .panel import Panel
1168- from rich .progress import Progress , SpinnerColumn , TextColumn , TimeElapsedColumn
1169- from rich .console import Group
1170- from rich .status import Status
1171- from rich .style import Style
1172-
1173- progress = Progress (
1174- SpinnerColumn ("bouncingBar" ),
1175- TextColumn ("{task.description}" ),
1176- TimeElapsedColumn (),
1177- )
1178- progress .add_task (f"Waiting for PipelineExecution to reach [bold]{ target_status } [/bold] status..." )
1179- status = Status ("Current status:" )
1180-
1181- with Live (
1182- Panel (
1183- Group (progress , status ),
1184- title = "Wait Log Panel" ,
1185- border_style = Style (color = "blue" ),
1186- ),
1187- transient = True ,
1188- ):
1189- while True :
1190- self .refresh ()
1191- current_status = self .status .overall_status
1192- status .update (f"Current status: [bold]{ current_status } [/bold]" )
1193-
1194- if target_status == current_status :
1195- logger .info (f"Final Resource Status: [bold]{ current_status } [/bold]" )
1196- return
1197-
1198- if "failed" in current_status .lower ():
1199- from sagemaker .core .utils .exceptions import FailedStatusError
1200- raise FailedStatusError (
1201- resource_type = "PipelineExecution" ,
1202- status = current_status ,
1203- reason = self .status .failure_reason ,
1204- )
1205-
1206- if timeout is not None and time .time () - start_time >= timeout :
1207- from sagemaker .core .utils .exceptions import TimeoutExceededError
1208- raise TimeoutExceededError (
1209- resource_type = "EvaluationJob" ,
1210- status = current_status ,
1211- message = "Your evaluation job is still running. Call .refresh() to check its current status." ,
1212- )
1213-
1214- time .sleep (poll )
1215- except ImportError :
1216- # Fallback to simple print-based progress if rich is not available
1217- logger .info (f"Waiting for PipelineExecution to reach { target_status } status..." )
1218- while True :
1219- self .refresh ()
1220- current_status = self .status .overall_status
1221- elapsed = time .time () - start_time
1222- print (f"Current status: { current_status } (Elapsed: { elapsed :.1f} s)" )
1223-
1224- if target_status == current_status :
1225- logger .info (f"Final Resource Status: { current_status } " )
1226- return
1227-
1228- if "failed" in current_status .lower ():
1229- from sagemaker .core .utils .exceptions import FailedStatusError
1230- raise FailedStatusError (
1231- resource_type = "PipelineExecution" ,
1232- status = current_status ,
1233- reason = self .status .failure_reason ,
1234- )
1235-
1236- if timeout is not None and elapsed >= timeout :
1237- from sagemaker .core .utils .exceptions import TimeoutExceededError
1238- raise TimeoutExceededError (
1239- resource_type = "EvaluationJob" ,
1240- status = current_status ,
1241- message = "Your evaluation job is still running. Call .refresh() to check its current status." ,
1242- )
1243-
1244- time .sleep (poll )
1164+ # Terminal experience - plain print matching training format
1165+ pipeline_name = None
1166+ if self .arn :
1167+ arn_parts = self .arn .split ('/' )
1168+ if len (arn_parts ) >= 3 :
1169+ pipeline_name = arn_parts [- 3 ]
1170+ print (f"\n Evaluation started: { self .name } " , flush = True )
1171+ if pipeline_name :
1172+ print (f"Pipeline: { pipeline_name } " , flush = True )
1173+ print (f"Execution ARN: { self .arn } " , flush = True )
1174+
1175+ while True :
1176+ self .refresh ()
1177+ current_status = self .status .overall_status
1178+ elapsed = time .time () - start_time
1179+
1180+ # Print step transitions (matching training format)
1181+ if self .status .step_details :
1182+ print ("\n --------------------------------------\n " , flush = True )
1183+ print ("Status Transitions:" , flush = True )
1184+ for step in self .status .step_details :
1185+ duration = ""
1186+ check = ""
1187+ if step .start_time and step .end_time :
1188+ try :
1189+ from datetime import datetime
1190+ start_dt = datetime .fromisoformat (step .start_time .replace ('Z' , '+00:00' ))
1191+ end_dt = datetime .fromisoformat (step .end_time .replace ('Z' , '+00:00' ))
1192+ duration = f"({ (end_dt - start_dt ).total_seconds ():.1f} s)"
1193+ except Exception :
1194+ pass
1195+ check = "✓"
1196+ elif step .start_time :
1197+ try :
1198+ from datetime import datetime , timezone
1199+ start_dt = datetime .fromisoformat (step .start_time .replace ('Z' , '+00:00' ))
1200+ running_secs = (datetime .now (timezone .utc ) - start_dt ).total_seconds ()
1201+ duration = f"(Running... { running_secs :.0f} s)"
1202+ except Exception :
1203+ duration = "(Running...)"
1204+ check = "⋯"
1205+
1206+ step_msg = f" { check } { step .display_name or step .name } : { step .status } { duration } "
1207+ print (step_msg , flush = True )
1208+ if step .job_arn and ('executing' in step .status .lower () or 'failed' in step .status .lower ()):
1209+ print (f" Job ARN: { step .job_arn } " , flush = True )
1210+
1211+ print (f"\n Status: { current_status } (Elapsed: { elapsed :.1f} s)" , flush = True )
1212+
1213+ if target_status == current_status :
1214+ if self .s3_output_path :
1215+ print (f"\n Results S3: { self .s3_output_path } " , flush = True )
1216+ return
1217+
1218+ if "failed" in current_status .lower ():
1219+ if self .status .failure_reason :
1220+ print (f"\n Failure reason: { self .status .failure_reason } " , flush = True )
1221+ if self .status .step_details :
1222+ for step in self .status .step_details :
1223+ if 'failed' in step .status .lower ():
1224+ print (f"\n Failed step: { step .display_name or step .name } " , flush = True )
1225+ if step .failure_reason :
1226+ print (f"Failure reason: { step .failure_reason } " , flush = True )
1227+ if step .job_arn :
1228+ print (f"Job ARN: { step .job_arn } " , flush = True )
1229+ job_name = step .job_arn .split ('/' )[- 1 ] if '/' in step .job_arn else ''
1230+ if job_name :
1231+ print (f"Log group: /aws/sagemaker/TrainingJobs" , flush = True )
1232+ print (f"Log stream prefix: { job_name } " , flush = True )
1233+ from sagemaker .train .common_utils .metrics_visualizer import get_cloudwatch_logs_url
1234+ cw_url = get_cloudwatch_logs_url (step .job_arn )
1235+ if cw_url :
1236+ print (f"CloudWatch Logs: { cw_url } " , flush = True )
1237+ from sagemaker .core .utils .exceptions import FailedStatusError
1238+ raise FailedStatusError (
1239+ resource_type = "PipelineExecution" ,
1240+ status = current_status ,
1241+ reason = self .status .failure_reason ,
1242+ )
1243+
1244+ if timeout is not None and time .time () - start_time >= timeout :
1245+ from sagemaker .core .utils .exceptions import TimeoutExceededError
1246+ raise TimeoutExceededError (
1247+ resource_type = "EvaluationJob" ,
1248+ status = current_status ,
1249+ message = "Your evaluation job is still running. Call .refresh() to check its current status." ,
1250+ )
1251+
1252+ time .sleep (poll )
12451253
12461254 def _enrich_with_step_details (
12471255 self ,
0 commit comments