diff --git a/src/dvsim/cli/admin.py b/src/dvsim/cli/admin.py index 754588fe..93279f6d 100644 --- a/src/dvsim/cli/admin.py +++ b/src/dvsim/cli/admin.py @@ -10,6 +10,8 @@ import click +from dvsim.instrumentation.report.profile import RenderProfile + @click.group() @click.version_option(version("dvsim")) @@ -62,7 +64,7 @@ def dashboard_gen(json_path: Path, output_dir: Path, base_url: str | None) -> No @cli.group() def report() -> None: - """Reporting helper commands.""" + """Reporting helper commands.""" # noqa: D401 @report.command("gen") @@ -91,5 +93,28 @@ def report_gen(json_path: Path, output_dir: Path) -> None: ) +@report.command( + "instrumentation", short_help="Generate an instrumentation report from existing metrics." +) +@click.argument( + "json_path", + type=click.Path(exists=True, file_okay=True, dir_okay=False, path_type=Path), +) +@click.argument("output_dir", type=click.Path(file_okay=False, dir_okay=True, path_type=Path)) +@click.option( + "--profile", + type=click.Choice([e.value for e in RenderProfile], case_sensitive=False), + help="Set the rendering profile to control the detail vs. report optimization", +) +def instrumentation_report_gen(json_path: Path, output_dir: Path, profile: str | None) -> None: + """Generate an instrumentation report from an existing metrics JSON.""" + from dvsim.instrumentation.records import InstrumentationResults # noqa: PLC0415 + from dvsim.instrumentation.runtime import gen_html_report # noqa: PLC0415 + + render_profile = None if profile is None else RenderProfile(profile) + results = InstrumentationResults.model_validate_json(json_path.read_text(encoding="utf-8")) + gen_html_report(results, profile=render_profile, outdir=output_dir) + + if __name__ == "__main__": sys.exit(cli()) diff --git a/src/dvsim/cli/run.py b/src/dvsim/cli/run.py index 3398555e..73dee12c 100644 --- a/src/dvsim/cli/run.py +++ b/src/dvsim/cli/run.py @@ -32,7 +32,8 @@ from pathlib import Path from dvsim.flow.factory import make_cfg -from dvsim.instrumentation import InstrumentationFactory, set_instrumentation +from dvsim.instrumentation.factory import InstrumentationFactory +from dvsim.instrumentation.runtime import set_instrumentation from dvsim.job.deploy import RunTest from dvsim.launcher.base import Launcher from dvsim.launcher.lsf import LsfLauncher diff --git a/src/dvsim/flow/base.py b/src/dvsim/flow/base.py index c11ac747..4345a31b 100644 --- a/src/dvsim/flow/base.py +++ b/src/dvsim/flow/base.py @@ -16,7 +16,7 @@ import hjson -from dvsim import instrumentation +import dvsim.instrumentation.runtime as instrumentation from dvsim.flow.hjson import set_target_attribute from dvsim.job.data import CompletedJobStatus, JobSpec, WorkspaceConfig from dvsim.job.status import JobStatus diff --git a/src/dvsim/instrumentation/__init__.py b/src/dvsim/instrumentation/__init__.py index 7f6fd9e0..cdc4d087 100644 --- a/src/dvsim/instrumentation/__init__.py +++ b/src/dvsim/instrumentation/__init__.py @@ -3,36 +3,3 @@ # SPDX-License-Identifier: Apache-2.0 """DVSim Scheduler Instrumentation.""" - -from dvsim.instrumentation.base import InstrumentationAggregator, SchedulerInstrumentation -from dvsim.instrumentation.factory import InstrumentationFactory -from dvsim.instrumentation.records import ( - InstrumentationMetrics, - InstrumentationResults, - JobMetrics, - SchedulerMetrics, -) -from dvsim.instrumentation.runtime import ( - flush, - gen_html_report, - get, - get_report, - set_instrumentation, - set_report_path, -) - -__all__ = ( - "InstrumentationAggregator", - "InstrumentationFactory", - "InstrumentationMetrics", - "InstrumentationResults", - "JobMetrics", - "SchedulerInstrumentation", - "SchedulerMetrics", - "flush", - "gen_html_report", - "get", - "get_report", - "set_instrumentation", - "set_report_path", -) diff --git a/src/dvsim/instrumentation/report/__init__.py b/src/dvsim/instrumentation/report/__init__.py index 624c1e31..435b8f45 100644 --- a/src/dvsim/instrumentation/report/__init__.py +++ b/src/dvsim/instrumentation/report/__init__.py @@ -3,17 +3,3 @@ # SPDX-License-Identifier: Apache-2.0 """DVSim Scheduler Instrumentation report.""" - -from dvsim.instrumentation.report.base import ( - InstrumentationVisualizer, - RenderProfile, - render_html_report, -) -from dvsim.instrumentation.report.registry import ReportVisualizationRegistry - -__all__ = ( - "InstrumentationVisualizer", - "RenderProfile", - "ReportVisualizationRegistry", - "render_html_report", -) diff --git a/src/dvsim/instrumentation/report/base.py b/src/dvsim/instrumentation/report/base.py index 36d1d52b..f455f552 100644 --- a/src/dvsim/instrumentation/report/base.py +++ b/src/dvsim/instrumentation/report/base.py @@ -5,7 +5,6 @@ """DVSim scheduler instrumentation reporting & visualizations.""" from collections.abc import Iterable, Mapping, Sequence -from enum import Enum from pathlib import Path from typing import Any, Protocol, TypeVar @@ -14,8 +13,8 @@ import plotly.offline from typing_extensions import Self -from dvsim.instrumentation import InstrumentationResults -from dvsim.instrumentation.records import JobInstrumentationMetadata +from dvsim.instrumentation.records import InstrumentationResults, JobInstrumentationMetadata +from dvsim.instrumentation.report.profile import RenderProfile from dvsim.logging import log from dvsim.report.artifacts import ReportArtifacts, render_static_content from dvsim.templates.render import render_template @@ -46,14 +45,6 @@ } -class RenderProfile(Enum): - """Levels of visualization rendering detail, which impact report size & responsiveness.""" - - NORMAL = "normal" - HIGH = "high" - FULL = "full" - - class InstrumentationVisualizer(Protocol): """Builder & renderer for HTML instrumentation visualizations.""" diff --git a/src/dvsim/instrumentation/report/breakdown.py b/src/dvsim/instrumentation/report/breakdown.py index f1a7dd94..bbc858f3 100644 --- a/src/dvsim/instrumentation/report/breakdown.py +++ b/src/dvsim/instrumentation/report/breakdown.py @@ -10,8 +10,7 @@ import plotly.graph_objects as go from plotly.subplots import make_subplots -from dvsim.instrumentation import InstrumentationResults -from dvsim.instrumentation.records import JobInstrumentationResults +from dvsim.instrumentation.records import InstrumentationResults, JobInstrumentationResults from dvsim.instrumentation.report.base import ( DEFAULT_VISUALIZATION_HEIGHT_PX, PLOTLY_TIMING_AXIS_CONFIG, diff --git a/src/dvsim/instrumentation/report/longest.py b/src/dvsim/instrumentation/report/longest.py index 051cb5e7..926fc7e7 100644 --- a/src/dvsim/instrumentation/report/longest.py +++ b/src/dvsim/instrumentation/report/longest.py @@ -12,9 +12,9 @@ import plotly.graph_objects as go from typing_extensions import Self -from dvsim.instrumentation import InstrumentationResults from dvsim.instrumentation.records import ( ConcreteJobTimingMetrics, + InstrumentationResults, JobInstrumentationMetadata, JobInstrumentationResults, ) @@ -22,11 +22,11 @@ DEFAULT_VISUALIZATION_HEIGHT_PX, PLOTLY_TIMING_AXIS_CONFIG, InstrumentationVisualizer, - RenderProfile, get_default_color_map, make_job_metadata_hover, render_plotly_figure, ) +from dvsim.instrumentation.report.profile import RenderProfile from dvsim.job.status import JobStatus from dvsim.logging import log from dvsim.utils import format_time_metric, ordinal_suffix diff --git a/src/dvsim/instrumentation/report/profile.py b/src/dvsim/instrumentation/report/profile.py new file mode 100644 index 00000000..3039696e --- /dev/null +++ b/src/dvsim/instrumentation/report/profile.py @@ -0,0 +1,15 @@ +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +"""DVSim scheduler instrumentation reporting rendering profiles/levels.""" + +from enum import Enum + + +class RenderProfile(Enum): + """Levels of visualization rendering detail, which impact report size & responsiveness.""" + + NORMAL = "normal" + HIGH = "high" + FULL = "full" diff --git a/src/dvsim/instrumentation/report/registry.py b/src/dvsim/instrumentation/report/registry.py index d02a8d0f..df43a336 100644 --- a/src/dvsim/instrumentation/report/registry.py +++ b/src/dvsim/instrumentation/report/registry.py @@ -6,7 +6,7 @@ from typing import ClassVar -from dvsim.instrumentation.report.base import InstrumentationVisualizer, RenderProfile +from dvsim.instrumentation.report.base import InstrumentationVisualizer from dvsim.instrumentation.report.breakdown import BlockVariantBreakdown, ToolBreakdown from dvsim.instrumentation.report.longest import ( LongestByBlockChart, @@ -15,6 +15,7 @@ LongestTestsByBlockChart, LongestTestsByToolChart, ) +from dvsim.instrumentation.report.profile import RenderProfile from dvsim.instrumentation.report.timelines import ParallelismChart, TimelineBarChart from dvsim.instrumentation.report.usage import ToolUsageLineGraph diff --git a/src/dvsim/instrumentation/report/timelines.py b/src/dvsim/instrumentation/report/timelines.py index db21ef5f..9683375e 100644 --- a/src/dvsim/instrumentation/report/timelines.py +++ b/src/dvsim/instrumentation/report/timelines.py @@ -24,17 +24,16 @@ from matplotlib.ticker import MaxNLocator from typing_extensions import Self, override -from dvsim.instrumentation import InstrumentationResults -from dvsim.instrumentation.records import ConcreteJobTimingMetrics +from dvsim.instrumentation.records import ConcreteJobTimingMetrics, InstrumentationResults from dvsim.instrumentation.report.base import ( DEFAULT_VISUALIZATION_HEIGHT_PX, PLOTLY_TIMING_AXIS_CONFIG, InstrumentationVisualizer, - RenderProfile, get_default_color_map, make_job_metadata_hover, render_plotly_figure, ) +from dvsim.instrumentation.report.profile import RenderProfile from dvsim.logging import log from dvsim.utils import format_time_as_hms as format_time from dvsim.utils import format_time_metric diff --git a/src/dvsim/instrumentation/report/usage.py b/src/dvsim/instrumentation/report/usage.py index 6b54ee2f..0e5f23b3 100644 --- a/src/dvsim/instrumentation/report/usage.py +++ b/src/dvsim/instrumentation/report/usage.py @@ -10,8 +10,11 @@ import plotly.graph_objects as go from plotly.graph_objs import Figure -from dvsim.instrumentation import InstrumentationResults -from dvsim.instrumentation.records import ConcreteJobTimingMetrics, JobInstrumentationResults +from dvsim.instrumentation.records import ( + ConcreteJobTimingMetrics, + InstrumentationResults, + JobInstrumentationResults, +) from dvsim.instrumentation.report.base import ( DEFAULT_VISUALIZATION_HEIGHT_PX, PLOTLY_TIMING_AXIS_CONFIG, diff --git a/src/dvsim/instrumentation/runtime.py b/src/dvsim/instrumentation/runtime.py index 2ee25ef6..baf532a7 100644 --- a/src/dvsim/instrumentation/runtime.py +++ b/src/dvsim/instrumentation/runtime.py @@ -7,11 +7,9 @@ from pathlib import Path from dvsim.instrumentation.base import InstrumentationAggregator, InstrumentationResults -from dvsim.instrumentation.report import ( - RenderProfile, - ReportVisualizationRegistry, - render_html_report, -) +from dvsim.instrumentation.report.base import render_html_report +from dvsim.instrumentation.report.profile import RenderProfile +from dvsim.instrumentation.report.registry import ReportVisualizationRegistry from dvsim.logging import log __all__ = ( diff --git a/src/dvsim/scheduler/runner.py b/src/dvsim/scheduler/runner.py index 587f5c8e..0244fff3 100644 --- a/src/dvsim/scheduler/runner.py +++ b/src/dvsim/scheduler/runner.py @@ -6,7 +6,7 @@ from collections.abc import Iterable -from dvsim import instrumentation +import dvsim.instrumentation.runtime as instrumentation from dvsim.job.data import CompletedJobStatus, JobSpec from dvsim.runtime.backend import RuntimeBackend from dvsim.runtime.fake import FakePolicy, FakeRuntimeBackend