""" TaskID-Based Reports tab UI component. """ import streamlit as st from src.services.report import ( aggregate_tasks_by_ids, export_comparison_to_markdown, export_to_markdown, prepare_chart_data, prepare_comparison_chart_data, ) from src.services.report.chart_renderer import ( render_comparison_charts, render_single_spu_charts, ) from src.services.report.data_aggregator import compare_workflow_data from src.services.report.models import SPUComparisonReport @st.fragment def render_tab4(): """TaskID-Based Reports tab - wrapped in fragment for isolation.""" st.header("TaskID-Based Performance Reports") st.info( "Generate reports by aggregating specific test tasks. " "Tasks must have matching TiDB SPU, TiDB Count, Cluster " "Version, and TiProxy status. Different workload types " "are allowed." ) # Part 1: Aggregate Tasks st.subheader("Single Report") st.markdown( "Enter task IDs (comma-separated) from the Task Status tab " "to generate an aggregated report." ) task_ids_input = st.text_input( "Task IDs", placeholder="e.g., 123, 456, 789", key="aggregate_task_ids", ) col_btn1, col_btn2 = st.columns([1, 5]) with col_btn1: generate_aggregate_btn = st.button( "Generate Report", key="gen_aggregate_report" ) with col_btn2: st.empty() if generate_aggregate_btn and task_ids_input: # Parse task IDs try: task_ids = [int(x.strip()) for x in task_ids_input.split(",") if x.strip()] if not task_ids: st.error("Please enter at least one task ID") else: with st.spinner("Generating aggregated report..."): try: report_data = aggregate_tasks_by_ids(task_ids) if report_data: markdown_content = export_to_markdown( report_data, output_path=None ) chart_data = prepare_chart_data(report_data) st.session_state.task_aggregate_report = markdown_content st.session_state.task_aggregate_chart_data = chart_data st.session_state.task_aggregate_report_data = report_data st.session_state.task_aggregate_ids = task_ids_input st.success( f"Report generated successfully " f"for {len(task_ids)} tasks!" ) else: st.error( f"No data found for task IDs: " f"{task_ids_input}" ) except ValueError as e: st.error(f"Validation error: {str(e)}") except ValueError: st.error( "Invalid task ID format. Please enter comma-separated " "numbers (e.g., 123, 456, 789)" ) # Display aggregated report if "task_aggregate_report" in st.session_state: st.markdown("---") # Render charts first if "task_aggregate_chart_data" in st.session_state: render_single_spu_charts( st.session_state.task_aggregate_chart_data, st.session_state.task_aggregate_report_data.spu_identifier, ) st.markdown("---") st.markdown("### Aggregated Report Preview") # Download button st.download_button( label="Download Report (Markdown)", data=st.session_state.task_aggregate_report, file_name=f"task_aggregate_report.md", mime="text/markdown", ) # Render markdown st.markdown(st.session_state.task_aggregate_report) st.markdown("---") # Part 2: Compare Tasks st.subheader("Comparison Report") st.markdown( "Enter two groups of task IDs to compare their aggregated " "performance." ) col_task1, col_task2 = st.columns(2) with col_task1: task_ids_1_input = st.text_input( "Task IDs Group 1", placeholder="e.g., 123, 456", key="compare_task_ids_1", ) with col_task2: task_ids_2_input = st.text_input( "Task IDs Group 2", placeholder="e.g., 789, 101", key="compare_task_ids_2", ) col_btn3, col_btn4 = st.columns([1, 5]) with col_btn3: generate_task_compare_btn = st.button( "Generate Comparison", key="gen_task_compare_report" ) with col_btn4: st.empty() if generate_task_compare_btn and task_ids_1_input and task_ids_2_input: try: # Parse task IDs for both groups task_ids_1 = [ int(x.strip()) for x in task_ids_1_input.split(",") if x.strip() ] task_ids_2 = [ int(x.strip()) for x in task_ids_2_input.split(",") if x.strip() ] if not task_ids_1 or not task_ids_2: st.error("Please enter at least one task ID for each group") else: with st.spinner("Generating comparison report..."): try: # Aggregate both groups report_1 = aggregate_tasks_by_ids(task_ids_1) report_2 = aggregate_tasks_by_ids(task_ids_2) if report_1 and report_2: # Create comparison report wf_types_1 = {wf.workflow_type for wf in report_1.workflows} wf_types_2 = {wf.workflow_type for wf in report_2.workflows} common_workflow_types = list( wf_types_1.intersection(wf_types_2) ) comparisons = [] for wf_type in common_workflow_types: comparison = compare_workflow_data( report_1, report_2, wf_type ) if comparison: comparisons.append(comparison) comparison_report = SPUComparisonReport( spu_1=report_1, spu_2=report_2, comparisons=comparisons, ) markdown_content = export_comparison_to_markdown( comparison_report, output_path=None ) chart_data = prepare_comparison_chart_data( comparison_report ) st.session_state.task_comparison_report = markdown_content st.session_state.task_comparison_chart_data = chart_data st.session_state.task_comparison_ids_1 = task_ids_1_input st.session_state.task_comparison_ids_2 = task_ids_2_input # Store SPU identifiers for chart legend st.session_state.task_comparison_spu_1 = ( report_1.spu_identifier ) st.session_state.task_comparison_spu_2 = ( report_2.spu_identifier ) st.success("Comparison report generated successfully!") elif not report_1: st.error(f"No data found for Group 1: {task_ids_1_input}") elif not report_2: st.error(f"No data found for Group 2: {task_ids_2_input}") except ValueError as e: st.error(f"Validation error: {str(e)}") except ValueError: st.error( "Invalid task ID format. Please enter comma-separated " "numbers for both groups" ) # Display task comparison report if "task_comparison_report" in st.session_state: st.markdown("---") # Render charts first if "task_comparison_chart_data" in st.session_state: # Use SPU identifiers for legend if available, otherwise fall back to task IDs spu1_name = st.session_state.get( "task_comparison_spu_1", f"Group 1 (Tasks: {st.session_state.task_comparison_ids_1})", ) spu2_name = st.session_state.get( "task_comparison_spu_2", f"Group 2 (Tasks: {st.session_state.task_comparison_ids_2})", ) render_comparison_charts( st.session_state.task_comparison_chart_data, spu1_name, spu2_name, ) st.markdown("---") st.markdown("### Task Comparison Report Preview") # Download button st.download_button( label="Download Comparison Report (Markdown)", data=st.session_state.task_comparison_report, file_name=f"task_comparison_report.md", mime="text/markdown", ) # Render markdown st.markdown(st.session_state.task_comparison_report)