From 1d3405a86f8538ae41213a08f7d510727f012631 Mon Sep 17 00:00:00 2001 From: harshit chourasiya Date: Mon, 21 Apr 2025 07:25:59 +0000 Subject: [PATCH 1/3] Aggregated Metrics implemented --- report/trends_report_web/index.html | 1 + report/trends_report_web/index.js | 75 +++++++++++++++++++++++++++++ report/trends_report_web/style.css | 20 ++++++++ report/web.py | 19 ++++++-- 4 files changed, 112 insertions(+), 3 deletions(-) diff --git a/report/trends_report_web/index.html b/report/trends_report_web/index.html index cf968fa9c0..a1d6e4e33a 100644 --- a/report/trends_report_web/index.html +++ b/report/trends_report_web/index.html @@ -68,6 +68,7 @@

Tags

Overview

+

Projects

diff --git a/report/trends_report_web/index.js b/report/trends_report_web/index.js index 25b5063379..64867a6c7f 100644 --- a/report/trends_report_web/index.js +++ b/report/trends_report_web/index.js @@ -351,6 +351,74 @@ class Page { container.append(chart); } + // ── new method to sum/average across all filtered experiments ───────────── + computeAggregates() { + let totalRuns = 0; + let totalCoverage = 0; + let totalCrashes = 0; + let totalCrashCases = 0; + let totalExecTime = 0; + + for (let name of this.filteredNames) { + const rpt = this.reports.get(name).accumulated_results; + totalRuns += rpt.total_runs; + totalCoverage += rpt.total_coverage; + totalCrashes += rpt.crashes; + totalCrashCases += rpt.crash_cases; + totalExecTime += (this.reports.get(name).execution_time || 0); + } + + return { + avgCoverage: totalRuns + ? (totalCoverage / totalRuns) * 100 + : 0, + crashes: totalCrashes, + crashCases: totalCrashCases, + avgExecTime: this.filteredNames.length + ? (totalExecTime / this.filteredNames.length) + : 0 + }; + } + + // ── Build the separate "Aggregated Metrics 📊" table ───────────── + updateAggregatedMetrics() { + const agg = this.computeAggregates(); + const container = document.querySelector('#aggregated-metrics'); + container.replaceChildren(); + + // Heading + const title = document.createElement('h3'); + title.innerText = 'Aggregated Metrics 📊'; + container.appendChild(title); + + // Table + const table = document.createElement('table'); + const thead = document.createElement('thead'); + const tbody = document.createElement('tbody'); + table.appendChild(thead); + table.appendChild(tbody); + container.appendChild(table); + + // Header row + const headerRow = document.createElement('tr'); + for (let h of ['Total Crashes', 'Total Crash Cases', 'Average Coverage', 'Execution Time']) { + const th = document.createElement('th'); + th.innerText = h; + headerRow.appendChild(th); + } + thead.appendChild(headerRow); + + // Data row + const dataRow = document.createElement('tr'); + dataRow.innerHTML = ` + ${agg.crashes} + ${agg.crashCases} + ${agg.avgCoverage.toFixed(2)}% + ${agg.avgExecTime.toFixed(1)}s + `; + tbody.appendChild(dataRow); + } + // updateOverviewTable updates the data table showing the coverage data for // the selected project. updateOverviewTable() { @@ -361,8 +429,12 @@ class Page { const table = document.createElement('table'); const thead = document.createElement('thead'); const tbody = document.createElement('tbody'); + const tfoot = document.createElement('tfoot'); + tfoot.id = 'overview-aggregate'; + table.appendChild(thead); table.appendChild(tbody); + table.appendChild(tfoot); tableContainer.appendChild(table); @@ -409,6 +481,9 @@ class Page { lineCoverageDiff.innerText = `${lineCoverageDiffVal}%`; tr.appendChild(lineCoverageDiff); } + + // ── inject the Total/Avg row into our new ───────────── + this.updateAggregatedMetrics(); } // updateOverviewCoverageChart configures Plot to chart the coverage gain of different diff --git a/report/trends_report_web/style.css b/report/trends_report_web/style.css index 0796c238a9..604b5c7e19 100644 --- a/report/trends_report_web/style.css +++ b/report/trends_report_web/style.css @@ -113,6 +113,26 @@ button { margin-left: 5px; } +/* + *aggregated metrics + */ + +#aggregated-metrics { + margin: 1rem 0; +} +#aggregated-metrics table { + width: auto; + border-collapse: collapse; +} +#aggregated-metrics th, +#aggregated-metrics td { + padding: 0.5rem 1rem; + border: 1px solid #ddd; +} +#aggregated-metrics h3 { + margin-bottom: 0.5rem; +} + /* * Projects */ diff --git a/report/web.py b/report/web.py index 05784fa3a0..df92c24f19 100644 --- a/report/web.py +++ b/report/web.py @@ -199,7 +199,11 @@ def generate(self): self._write_index_html(benchmarks, accumulated_results, time_results, projects, samples_with_bugs, coverage_language_gains) - self._write_index_json(benchmarks) + self._write_index_json( + benchmarks, + accumulated_results=accumulated_results, + time_results=time_results, + projects=projects) def _write(self, output_path: str, content: str): """Utility write to filesystem function.""" @@ -232,9 +236,18 @@ def _write_index_html(self, benchmarks: List[Benchmark], coverage_language_gains=coverage_language_gains) self._write('index.html', rendered) - def _write_index_json(self, benchmarks: List[Benchmark]): + def _write_index_json(self, + benchmarks: List[Benchmark], + accumulated_results: AccumulatedResult, + time_results: dict[str, Any], + projects: list[Project]): """Generate the report index.json and write to filesystem.""" - rendered = self._jinja.render('index.json', benchmarks=benchmarks) + rendered = self._jinja.render( + 'index.json', + benchmarks=benchmarks, + accumulated_results=accumulated_results, + time_results=time_results, + projects=projects) self._write('index.json', rendered) def _write_benchmark_index(self, benchmark: Benchmark, samples: List[Sample], From 9dae373d0be17d8f7a84d289adac2b2b37c1ffae Mon Sep 17 00:00:00 2001 From: harshit chourasiya Date: Mon, 21 Apr 2025 12:29:45 +0000 Subject: [PATCH 2/3] new index.json for our Aggregated Metrics --- report/common.py | 2 ++ report/templates/index.json | 7 +++++++ report/web.py | 18 +++++++++++++++--- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/report/common.py b/report/common.py index 20669b8203..adb1e94cfb 100644 --- a/report/common.py +++ b/report/common.py @@ -74,6 +74,8 @@ class Benchmark: project: str = '' function: str = '' language: str = '' + accumulated_results: AccumulatedResult = dataclasses.field(default_factory=AccumulatedResult) + execution_time: float = 0.0 @dataclasses.dataclass diff --git a/report/templates/index.json b/report/templates/index.json index 20ebd6e2a8..af22a01e5c 100644 --- a/report/templates/index.json +++ b/report/templates/index.json @@ -12,6 +12,13 @@ {% if benchmark.result.max_coverage_diff_report %} ,"max_line_coverage_diff_report": "{{ benchmark.result.max_coverage_diff_report }}" {%- endif %} + ,"accumulated_results": { + "total_runs": {{ benchmark.accumulated_results.total_runs }}, + "total_coverage": {{ benchmark.accumulated_results.total_coverage }}, + "crashes": {{ benchmark.accumulated_results.crashes }}, + "crash_cases": {{ benchmark.accumulated_results.crash_cases }} + } + ,"execution_time": {{ benchmark.execution_time }} }{% if not loop.last %},{% endif %} {% endfor %} ] diff --git a/report/web.py b/report/web.py index df92c24f19..908ee60122 100644 --- a/report/web.py +++ b/report/web.py @@ -191,12 +191,24 @@ def generate(self): sample_targets = self._results.get_targets(benchmark.id, sample.id) self._write_benchmark_sample(benchmark, sample, sample_targets) + time_results = self.read_timings() + + # 3) Enrich each benchmark with its own aggregated metrics and execution time + for bm in benchmarks: + # a) per-benchmark accumulated results + bm.accumulated_results = self._results.get_macro_insights([bm]) + # b) parse total_run_time "HH:MM:SS(.sss)" into seconds + rt_str = time_results.get('total_run_time', '0:00:00') + try: + h, m, s = rt_str.split(':') + bm.execution_time = int(h) * 3600 + int(m) * 60 + float(s) + except Exception: + bm.execution_time = 0.0 + accumulated_results = self._results.get_macro_insights(benchmarks) projects = self._results.get_project_summary(benchmarks) coverage_language_gains = self._results.get_coverage_language_gains() - time_results = self.read_timings() - self._write_index_html(benchmarks, accumulated_results, time_results, projects, samples_with_bugs, coverage_language_gains) self._write_index_json( @@ -236,7 +248,7 @@ def _write_index_html(self, benchmarks: List[Benchmark], coverage_language_gains=coverage_language_gains) self._write('index.html', rendered) - def _write_index_json(self, + def _write_index_json(self, benchmarks: List[Benchmark], accumulated_results: AccumulatedResult, time_results: dict[str, Any], From 29510dba684e78706423dbac08d2688c87ff7444 Mon Sep 17 00:00:00 2001 From: harshtech123 Date: Wed, 30 Apr 2025 12:34:29 +0530 Subject: [PATCH 3/3] presubmit --- report/common.py | 3 ++- report/web.py | 26 +++++++++++--------------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/report/common.py b/report/common.py index adb1e94cfb..693037ffee 100644 --- a/report/common.py +++ b/report/common.py @@ -74,7 +74,8 @@ class Benchmark: project: str = '' function: str = '' language: str = '' - accumulated_results: AccumulatedResult = dataclasses.field(default_factory=AccumulatedResult) + accumulated_results: AccumulatedResult = dataclasses.field( + default_factory=AccumulatedResult) execution_time: float = 0.0 diff --git a/report/web.py b/report/web.py index 908ee60122..be8d8f2a51 100644 --- a/report/web.py +++ b/report/web.py @@ -211,11 +211,10 @@ def generate(self): self._write_index_html(benchmarks, accumulated_results, time_results, projects, samples_with_bugs, coverage_language_gains) - self._write_index_json( - benchmarks, - accumulated_results=accumulated_results, - time_results=time_results, - projects=projects) + self._write_index_json(benchmarks, + accumulated_results=accumulated_results, + time_results=time_results, + projects=projects) def _write(self, output_path: str, content: str): """Utility write to filesystem function.""" @@ -248,18 +247,15 @@ def _write_index_html(self, benchmarks: List[Benchmark], coverage_language_gains=coverage_language_gains) self._write('index.html', rendered) - def _write_index_json(self, - benchmarks: List[Benchmark], + def _write_index_json(self, benchmarks: List[Benchmark], accumulated_results: AccumulatedResult, - time_results: dict[str, Any], - projects: list[Project]): + time_results: dict[str, Any], projects: list[Project]): """Generate the report index.json and write to filesystem.""" - rendered = self._jinja.render( - 'index.json', - benchmarks=benchmarks, - accumulated_results=accumulated_results, - time_results=time_results, - projects=projects) + rendered = self._jinja.render('index.json', + benchmarks=benchmarks, + accumulated_results=accumulated_results, + time_results=time_results, + projects=projects) self._write('index.json', rendered) def _write_benchmark_index(self, benchmark: Benchmark, samples: List[Sample],