feat(project-setup): add CLI entry point and __main__.py

This commit is contained in:
2026-09-28 18:52:32 +04:00
parent 352bc16ba5
commit dac3aeaafb
2 changed files with 103 additions and 0 deletions
+97
View File
@@ -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()