feat(project-setup): add CLI entry point and __main__.py
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
CLI entry point for disk-checker.
|
||||
|
||||
Usage:
|
||||
python -m disk_checker scan_latency.csv
|
||||
disk-checker scan_latency.csv --metric read_clat --unit ms
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from disk_checker.core.extractor import load_latency_csv
|
||||
from disk_checker.core.helpers import percentile_table
|
||||
from disk_checker.plotting.plots import generate_plot
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Plot fio json+ wide-format latency CSV."
|
||||
)
|
||||
parser.add_argument("csv", help="CSV from fio_jsonplus_clat2csv")
|
||||
parser.add_argument("--metric", default=None,
|
||||
help="Metric to plot (e.g. read_clat). "
|
||||
"If omitted, the metric with the most I/Os is used.")
|
||||
parser.add_argument("--all-metrics", action="store_true",
|
||||
help="Plot every metric that has data")
|
||||
parser.add_argument("--unit", choices=["ns", "us", "ms", "s"], default="us",
|
||||
help="X-axis latency unit (default: us)")
|
||||
parser.add_argument("--log-y", action="store_true")
|
||||
parser.add_argument("--log-x", action="store_true")
|
||||
parser.add_argument("--cdf", action="store_true",
|
||||
help="Add a CDF subplot below the histogram")
|
||||
parser.add_argument("--cdf-only", action="store_true")
|
||||
parser.add_argument("--normalize", action="store_true",
|
||||
help="Normalize histogram to a probability density")
|
||||
parser.add_argument("--percentiles", default="50,90,99,99.9,99.99")
|
||||
parser.add_argument("--no-percentiles", action="store_true")
|
||||
parser.add_argument("--output", "-o", default=None)
|
||||
parser.add_argument("--dpi", type=int, default=150)
|
||||
parser.add_argument("--title", default="")
|
||||
parser.add_argument("--show", action="store_true")
|
||||
args = parser.parse_args()
|
||||
|
||||
if not Path(args.csv).is_file():
|
||||
sys.exit(f"error: file not found: {args.csv}")
|
||||
|
||||
df = load_latency_csv(args.csv)
|
||||
if df.empty:
|
||||
sys.exit("error: no latency data in CSV")
|
||||
|
||||
available = sorted(df["metric"].unique())
|
||||
print("Metrics with data:", ", ".join(available))
|
||||
|
||||
if args.all_metrics:
|
||||
metrics = available
|
||||
elif args.metric:
|
||||
if args.metric not in available:
|
||||
sys.exit(f"error: metric {args.metric!r} not in {available}")
|
||||
metrics = [args.metric]
|
||||
else:
|
||||
totals = df.groupby("metric")["count"].sum().sort_values(ascending=False)
|
||||
metrics = [totals.index[0]]
|
||||
print(f"Auto-selected metric: {metrics[0]}")
|
||||
|
||||
output = args.output or f"{Path(args.csv).stem}_latency.png"
|
||||
generate_plot(
|
||||
df=df,
|
||||
metrics=metrics,
|
||||
output_path=Path(output),
|
||||
unit=args.unit,
|
||||
log_y=args.log_y,
|
||||
log_x=args.log_x,
|
||||
normalize=args.normalize,
|
||||
show_cdf=args.cdf,
|
||||
cdf_only=args.cdf_only,
|
||||
title=args.title,
|
||||
dpi=args.dpi,
|
||||
)
|
||||
print(f"Saved plot to {output}")
|
||||
|
||||
if not args.no_percentiles:
|
||||
try:
|
||||
pcts = [float(x) for x in args.percentiles.split(",") if x.strip()]
|
||||
except ValueError:
|
||||
sys.exit("error: --percentiles must be comma-separated numbers")
|
||||
for m in metrics:
|
||||
print(percentile_table(df, m, args.unit, pcts))
|
||||
|
||||
if args.show:
|
||||
import matplotlib.pyplot as plt
|
||||
plt.show()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,6 @@
|
||||
"""Allow running disk-checker as a module: python -m disk_checker"""
|
||||
|
||||
from disk_checker.scripts.cli import main
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user