[CI][Bugfix] Fix the error in generating the performance data table and add a fallback mechanism that prevents the result file from being generated when test case execution fails. (#2839)
Signed-off-by: wangyu <410167048@qq.com> Signed-off-by: wangyu <53896905+yenuo26@users.noreply.github.com>
This commit is contained in:
1 parent
bbd6a443ed
commit
a3ecde98e0
9 files changed
+394
-31
No files matched your search
@@ -110,8 +110,12 @@ steps:
|
||||
timeout_in_minutes: 180
|
||||
commands:
|
||||
- export BENCHMARK_DIR=tests/dfx/perf/results
|
||||
- pytest -s -v tests/dfx/perf/scripts/run_benchmark.py --test-config-file tests/dfx/perf/tests/test_qwen_omni.json
|
||||
- buildkite-agent artifact upload "tests/dfx/perf/results/*.json"
|
||||
- |
|
||||
set +e
|
||||
pytest -s -v tests/dfx/perf/scripts/run_benchmark.py --test-config-file tests/dfx/perf/tests/test_qwen_omni.json
|
||||
EXIT=$$?
|
||||
buildkite-agent artifact upload "tests/dfx/perf/results/*.json"
|
||||
exit $$EXIT
|
||||
agents:
|
||||
queue: "mithril-h100-pool"
|
||||
plugins:
|
||||
@@ -177,8 +181,12 @@ steps:
|
||||
commands:
|
||||
- export BENCHMARK_DIR=tests/dfx/perf/results
|
||||
- export VLLM_ALLOW_LONG_MAX_MODEL_LEN="1"
|
||||
- pytest -s -v tests/dfx/perf/scripts/run_benchmark.py --test-config-file tests/dfx/perf/tests/test_tts.json
|
||||
- buildkite-agent artifact upload "tests/dfx/perf/results/*.json"
|
||||
- |
|
||||
set +e
|
||||
pytest -s -v tests/dfx/perf/scripts/run_benchmark.py --test-config-file tests/dfx/perf/tests/test_tts.json
|
||||
EXIT=$$?
|
||||
buildkite-agent artifact upload "tests/dfx/perf/results/*.json"
|
||||
exit $$EXIT
|
||||
agents:
|
||||
queue: "mithril-h100-pool"
|
||||
plugins:
|
||||
@@ -398,6 +406,46 @@ steps:
|
||||
path: /mnt/hf-cache
|
||||
type: DirectoryOrCreate
|
||||
|
||||
- label: ":full_moon: Diffusion X2I(&A&T) · Accuracy Test"
|
||||
timeout_in_minutes: 180
|
||||
commands:
|
||||
- pytest -s -v tests/e2e/accuracy/test_qwen_image*.py --run-level advanced_model
|
||||
agents:
|
||||
queue: "mithril-h100-pool"
|
||||
plugins:
|
||||
- kubernetes:
|
||||
podSpec:
|
||||
containers:
|
||||
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
|
||||
resources:
|
||||
limits:
|
||||
nvidia.com/gpu: 1
|
||||
volumeMounts:
|
||||
- name: devshm
|
||||
mountPath: /dev/shm
|
||||
- name: hf-cache
|
||||
mountPath: /root/.cache/huggingface
|
||||
env:
|
||||
- name: HF_HOME
|
||||
value: /root/.cache/huggingface
|
||||
- name: VLLM_HTTP_TIMEOUT_KEEP_ALIVE
|
||||
value: "120"
|
||||
- name: HF_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: hf-token-secret
|
||||
key: token
|
||||
nodeSelector:
|
||||
node.kubernetes.io/instance-type: gpu-h100-sxm
|
||||
volumes:
|
||||
- name: devshm
|
||||
emptyDir:
|
||||
medium: Memory
|
||||
- name: hf-cache
|
||||
hostPath:
|
||||
path: /mnt/hf-cache
|
||||
type: DirectoryOrCreate
|
||||
|
||||
- label: ":full_moon: Diffusion X2I(&A&T) · Perf Test"
|
||||
key: nightly-diffusion-x2iat-performance
|
||||
timeout_in_minutes: 180
|
||||
@@ -417,11 +465,9 @@ steps:
|
||||
EXIT3=$$?
|
||||
pytest -s -v tests/dfx/perf/scripts/run_diffusion_benchmark.py --test-config-file tests/dfx/perf/tests/test_qwen_image_layered_vllm_omni.json
|
||||
EXIT4=$$?
|
||||
if [ $$EXIT1 -eq 0 ] || [ $$EXIT2 -eq 0 ] || [ $$EXIT3 -eq 0 ] || [ $$EXIT4 -eq 0 ]; then
|
||||
buildkite-agent artifact upload "tests/dfx/perf/results/diffusion_result_*.json"
|
||||
buildkite-agent artifact upload "tests/dfx/perf/results/logs/*.log"
|
||||
fi
|
||||
exit $$((EXIT1 | EXIT2 | EXIT3))
|
||||
buildkite-agent artifact upload "tests/dfx/perf/results/diffusion_result_*.json"
|
||||
buildkite-agent artifact upload "tests/dfx/perf/results/logs/*.log"
|
||||
exit $$((EXIT1 | EXIT2 | EXIT3 | EXIT4))
|
||||
agents:
|
||||
queue: "mithril-h100-pool"
|
||||
plugins:
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
[
|
||||
{
|
||||
"test_name": null,
|
||||
"backend": null,
|
||||
"timestamp": null,
|
||||
"server_params": {
|
||||
"model": null,
|
||||
"serve_args": {
|
||||
"enable-diffusion-pipeline-profiler": false
|
||||
}
|
||||
},
|
||||
"benchmark_params": {
|
||||
"name": null,
|
||||
"dataset": null,
|
||||
"task": null,
|
||||
"width": 0,
|
||||
"height": 0,
|
||||
"num-inference-steps": 0,
|
||||
"num-prompts": 0,
|
||||
"max-concurrency": 0,
|
||||
"num-input-images": 0,
|
||||
"enable-negative-prompt": false,
|
||||
"baseline": {
|
||||
"throughput_qps": 0,
|
||||
"latency_mean": 0,
|
||||
"peak_memory_mb_max": 0,
|
||||
"peak_memory_mb_mean": 0
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"duration": 0,
|
||||
"completed_requests": 0,
|
||||
"failed_requests": 0,
|
||||
"throughput_qps": 0,
|
||||
"latency_mean": 0,
|
||||
"latency_median": 0,
|
||||
"latency_p99": 0,
|
||||
"latency_p95": 0,
|
||||
"latency_p50": 0,
|
||||
"peak_memory_mb_max": 0,
|
||||
"peak_memory_mb_mean": 0,
|
||||
"peak_memory_mb_median": 0,
|
||||
"stage_durations_mean": {},
|
||||
"stage_durations_p50": {},
|
||||
"stage_durations_p99": {},
|
||||
"backend": null,
|
||||
"model": null,
|
||||
"dataset": null,
|
||||
"task": null
|
||||
},
|
||||
"log_file": null,
|
||||
"Model": null,
|
||||
"Framework": null,
|
||||
"Hardware": null,
|
||||
"Deployment": null,
|
||||
"Task": null,
|
||||
"Dataset": null,
|
||||
"resolution": null,
|
||||
"Parallelism": null,
|
||||
"max_concurrency": 0,
|
||||
"Cache": null,
|
||||
"Quantization": null,
|
||||
"offload": null,
|
||||
"compile": null,
|
||||
"Attn_backend": null,
|
||||
"num_inference_steps": 0,
|
||||
"completed": 0,
|
||||
"failed": 0,
|
||||
"throughput_qps": 0,
|
||||
"latency_mean": 0,
|
||||
"latency_median": 0,
|
||||
"latency_p99": 0,
|
||||
"latency_p95": 0,
|
||||
"latency_p50": 0,
|
||||
"peak_memory_mb_max": 0,
|
||||
"peak_memory_mb_mean": 0,
|
||||
"peak_memory_mb_median": 0,
|
||||
"stage_durations_mean": {},
|
||||
"stage_durations_p50": {},
|
||||
"stage_durations_p99": {},
|
||||
"commit_sha": null,
|
||||
"build_id": null,
|
||||
"build_url": null,
|
||||
"source_file": null
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"date": null,
|
||||
"endpoint_type": null,
|
||||
"backend": null,
|
||||
"label": null,
|
||||
"model_id": null,
|
||||
"tokenizer_id": null,
|
||||
"num_prompts": 0,
|
||||
"request_rate": null,
|
||||
"burstiness": 0,
|
||||
"max_concurrency": 0,
|
||||
"duration": 0,
|
||||
"completed": 0,
|
||||
"failed": 0,
|
||||
"total_input_tokens": 0,
|
||||
"total_output_tokens": 0,
|
||||
"request_throughput": 0,
|
||||
"request_goodput": null,
|
||||
"output_throughput": 0,
|
||||
"total_token_throughput": 0,
|
||||
"total_audio_duration_s": 0,
|
||||
"total_audio_frames": 0,
|
||||
"audio_throughput": 0,
|
||||
"max_output_tokens_per_s": 0,
|
||||
"max_concurrent_requests": 0,
|
||||
"rtfx": 0,
|
||||
"mean_ttft_ms": 0,
|
||||
"median_ttft_ms": 0,
|
||||
"p99_ttft_ms": 0,
|
||||
"mean_tpot_ms": 0,
|
||||
"median_tpot_ms": 0,
|
||||
"p99_tpot_ms": 0,
|
||||
"mean_itl_ms": 0,
|
||||
"median_itl_ms": 0,
|
||||
"p99_itl_ms": 0,
|
||||
"mean_e2el_ms": 0,
|
||||
"median_e2el_ms": 0,
|
||||
"p99_e2el_ms": 0,
|
||||
"mean_audio_rtf": 0,
|
||||
"median_audio_rtf": 0,
|
||||
"p99_audio_rtf": 0,
|
||||
"mean_audio_ttfp_ms": 0,
|
||||
"median_audio_ttfp_ms": 0,
|
||||
"p99_audio_ttfp_ms": 0,
|
||||
"mean_audio_duration_s": 0,
|
||||
"median_audio_duration_s": 0,
|
||||
"p99_audio_duration_s": 0,
|
||||
"baseline": {
|
||||
"mean_ttft_ms": 0,
|
||||
"mean_audio_ttfp_ms": 0,
|
||||
"mean_audio_rtf": 0
|
||||
},
|
||||
"random_input_len": 0,
|
||||
"random_output_len": 0
|
||||
}
|
||||
@@ -45,6 +45,8 @@ if CONFIG_FILE_PATH is None:
|
||||
CONFIG_FILE_PATH = _DEFAULT_CONFIG_FILE
|
||||
|
||||
BENCHMARK_CONFIGS = load_configs(CONFIG_FILE_PATH)
|
||||
OMNI_RESULT_TEMPLATE_PATH = Path(__file__).parent / "result_omni_template.json"
|
||||
|
||||
|
||||
STAGE_CONFIGS_DIR = Path(__file__).parent.parent / "stage_configs"
|
||||
test_params = create_unique_server_params(BENCHMARK_CONFIGS, STAGE_CONFIGS_DIR)
|
||||
@@ -64,7 +66,7 @@ def omni_server(request):
|
||||
|
||||
print(f"Starting OmniServer with test: {test_name}, model: {model}")
|
||||
|
||||
server_args = ["--stage-init-timeout", "300", "--init-timeout", "900"]
|
||||
server_args = ["--stage-init-timeout", "600", "--init-timeout", "900"]
|
||||
if stage_config_path:
|
||||
server_args = ["--stage-configs-path", stage_config_path] + server_args
|
||||
with OmniServer(model, server_args) as server:
|
||||
@@ -141,8 +143,17 @@ def run_benchmark(
|
||||
result_dir = "./"
|
||||
|
||||
result_path = os.path.join(result_dir, result_filename)
|
||||
with open(result_path, encoding="utf-8") as f:
|
||||
result = json.load(f)
|
||||
if not os.path.exists(result_path):
|
||||
with open(OMNI_RESULT_TEMPLATE_PATH, encoding="utf-8") as f:
|
||||
template_result: dict[str, Any] = json.load(f)
|
||||
Path(result_path).parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(result_path, "w", encoding="utf-8") as f:
|
||||
json.dump(template_result, f, ensure_ascii=False, indent=2)
|
||||
print(f"Benchmark result file not generated, fallback to template: {result_path}")
|
||||
result = template_result
|
||||
else:
|
||||
with open(result_path, encoding="utf-8") as f:
|
||||
result = json.load(f)
|
||||
|
||||
if baseline_config:
|
||||
result["baseline"] = _baseline_thresholds_for_step(
|
||||
|
||||
@@ -52,6 +52,7 @@ BENCHMARK_SCRIPT = str(
|
||||
_SESSION_TIMESTAMP = datetime.now().strftime("%Y%m%d-%H%M%S")
|
||||
_RESULT_LOCK = threading.Lock()
|
||||
_BRANCHPOINT_COMMIT_SHA: str | None = None
|
||||
DIFFUSION_RESULT_TEMPLATE_PATH = Path(__file__).parent / "diffusion_result_template.json"
|
||||
|
||||
|
||||
def _get_config_file_from_argv() -> str | None:
|
||||
@@ -563,10 +564,17 @@ def run_benchmark(
|
||||
|
||||
if process.returncode != 0:
|
||||
tmp_result_file.unlink(missing_ok=True)
|
||||
raise RuntimeError(f"Benchmark script exited with code {process.returncode}")
|
||||
print(f"ERROR:Benchmark script exited with code {process.returncode}")
|
||||
|
||||
if not tmp_result_file.exists():
|
||||
raise FileNotFoundError(f"Benchmark result file not found: {tmp_result_file}")
|
||||
with open(DIFFUSION_RESULT_TEMPLATE_PATH, encoding="utf-8") as f:
|
||||
template_payload = json.load(f)
|
||||
# Template schema is fixed and owned by this repo:
|
||||
# ``diffusion_result_template.json`` is a one-item list and metrics live at [0]["result"].
|
||||
template_metrics: dict[str, Any] = template_payload[0]["result"]
|
||||
with open(tmp_result_file, "w", encoding="utf-8") as f:
|
||||
json.dump(template_metrics, f, ensure_ascii=False, indent=2)
|
||||
print(f"Benchmark result file not generated, fallback to template: {tmp_result_file}")
|
||||
|
||||
try:
|
||||
with open(tmp_result_file, encoding="utf-8") as f:
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import importlib.util
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from openpyxl import load_workbook
|
||||
|
||||
pytestmark = [pytest.mark.core_model, pytest.mark.cpu]
|
||||
|
||||
|
||||
def _load_excel_module():
|
||||
repo_root = Path(__file__).resolve().parents[1]
|
||||
module_path = repo_root / "tools" / "nightly" / "generate_nightly_perf_excel.py"
|
||||
spec = importlib.util.spec_from_file_location("generate_nightly_perf_excel", module_path)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules[spec.name] = module
|
||||
spec.loader.exec_module(module)
|
||||
return module
|
||||
|
||||
|
||||
def _cell_value_by_header(ws, header_name: str, row_idx: int = 2):
|
||||
headers = [c.value for c in ws[1]]
|
||||
col_idx = headers.index(header_name) + 1
|
||||
return ws.cell(row=row_idx, column=col_idx).value
|
||||
|
||||
|
||||
def test_generate_excel_report_with_perf_templates(tmp_path: Path):
|
||||
module = _load_excel_module()
|
||||
repo_root = Path(__file__).resolve().parents[1]
|
||||
perf_scripts_dir = repo_root / "tests" / "dfx" / "perf" / "scripts"
|
||||
|
||||
omni_template_path = perf_scripts_dir / "result_omni_template.json"
|
||||
diffusion_template_path = perf_scripts_dir / "diffusion_result_template.json"
|
||||
|
||||
omni_record = json.loads(omni_template_path.read_text(encoding="utf-8"))
|
||||
diffusion_records = json.loads(diffusion_template_path.read_text(encoding="utf-8"))
|
||||
|
||||
input_dir = tmp_path / "input"
|
||||
diffusion_input_dir = tmp_path / "diffusion_input"
|
||||
input_dir.mkdir()
|
||||
diffusion_input_dir.mkdir()
|
||||
|
||||
# Keep file names compatible with parser conventions in generate_nightly_perf_excel.py
|
||||
omni_result_file = input_dir / "result_test_perf_random_1_4_in2500_out900_20260415-185642.json"
|
||||
diffusion_result_file = diffusion_input_dir / "diffusion_result_qwen_image_edit_20260415-193200.json"
|
||||
omni_result_file.write_text(json.dumps(omni_record, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
diffusion_result_file.write_text(json.dumps(diffusion_records, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
|
||||
output_file = tmp_path / "nightly_perf.xlsx"
|
||||
module.generate_excel_report(
|
||||
input_dir=str(input_dir),
|
||||
diffusion_input_dir=str(diffusion_input_dir),
|
||||
output_file=str(output_file),
|
||||
commit_sha="test_commit_sha",
|
||||
build_id="test_build_id",
|
||||
build_url="https://example.com/build/123",
|
||||
)
|
||||
|
||||
assert output_file.exists()
|
||||
|
||||
wb = load_workbook(output_file)
|
||||
assert set(wb.sheetnames) >= {"omni_summary", "diffusion_summary", "omni_raw", "diffusion_raw"}
|
||||
|
||||
ws_omni_raw = wb["omni_raw"]
|
||||
baseline_cell = _cell_value_by_header(ws_omni_raw, "baseline")
|
||||
assert baseline_cell == json.dumps(omni_record["baseline"], ensure_ascii=False, sort_keys=True)
|
||||
|
||||
ws_omni_summary = wb["omni_summary"]
|
||||
assert _cell_value_by_header(ws_omni_summary, "commit_sha") == "test_commit_sha"
|
||||
assert _cell_value_by_header(ws_omni_summary, "build_id") == "test_build_id"
|
||||
@@ -0,0 +1,54 @@
|
||||
import importlib.util
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
pytestmark = [pytest.mark.core_model, pytest.mark.cpu]
|
||||
|
||||
|
||||
def _load_html_module():
|
||||
repo_root = Path(__file__).resolve().parents[1]
|
||||
module_path = repo_root / "tools" / "nightly" / "generate_nightly_perf_html.py"
|
||||
spec = importlib.util.spec_from_file_location("generate_nightly_perf_html", module_path)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules[spec.name] = module
|
||||
spec.loader.exec_module(module)
|
||||
return module
|
||||
|
||||
|
||||
def test_generate_html_report_with_perf_templates(tmp_path: Path):
|
||||
module = _load_html_module()
|
||||
repo_root = Path(__file__).resolve().parents[1]
|
||||
perf_scripts_dir = repo_root / "tests" / "dfx" / "perf" / "scripts"
|
||||
|
||||
omni_template_path = perf_scripts_dir / "result_omni_template.json"
|
||||
diffusion_template_path = perf_scripts_dir / "diffusion_result_template.json"
|
||||
|
||||
omni_record = json.loads(omni_template_path.read_text(encoding="utf-8"))
|
||||
diffusion_records = json.loads(diffusion_template_path.read_text(encoding="utf-8"))
|
||||
|
||||
input_dir = tmp_path / "input"
|
||||
diffusion_input_dir = tmp_path / "diffusion_input"
|
||||
input_dir.mkdir()
|
||||
diffusion_input_dir.mkdir()
|
||||
|
||||
omni_result_file = input_dir / "result_test_perf_random_1_4_in2500_out900_20260415-185642.json"
|
||||
diffusion_result_file = diffusion_input_dir / "diffusion_result_qwen_image_edit_20260415-193200.json"
|
||||
omni_result_file.write_text(json.dumps(omni_record, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
diffusion_result_file.write_text(json.dumps(diffusion_records, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
|
||||
output_file = tmp_path / "nightly_perf_v2.html"
|
||||
module.generate_html_report(
|
||||
input_dir=str(input_dir),
|
||||
diffusion_input_dir=str(diffusion_input_dir),
|
||||
output_file=str(output_file),
|
||||
)
|
||||
|
||||
assert output_file.exists()
|
||||
html = output_file.read_text(encoding="utf-8")
|
||||
assert "Nightly Performance Report" in html
|
||||
assert "Omni records <strong>1</strong>" in html
|
||||
assert f"Diffusion records <strong>{len(diffusion_records)}</strong>" in html
|
||||
assert "const DIFF_DATA =" in html
|
||||
@@ -665,6 +665,21 @@ def _to_float_if_numeric(value: Any) -> Any:
|
||||
return value
|
||||
|
||||
|
||||
def _to_excel_compatible(value: Any) -> Any:
|
||||
"""Convert non-scalar objects to JSON string for openpyxl cell values."""
|
||||
if isinstance(value, (dict, list, tuple)):
|
||||
try:
|
||||
return json.dumps(value, ensure_ascii=False, sort_keys=True)
|
||||
except (TypeError, ValueError):
|
||||
return str(value)
|
||||
if isinstance(value, set):
|
||||
try:
|
||||
return json.dumps(sorted(value), ensure_ascii=False)
|
||||
except (TypeError, ValueError):
|
||||
return str(value)
|
||||
return value
|
||||
|
||||
|
||||
def _write_sheet(
|
||||
ws,
|
||||
columns: Sequence[str],
|
||||
@@ -680,6 +695,7 @@ def _write_sheet(
|
||||
v = record.get(col)
|
||||
if col in numeric_set:
|
||||
v = _to_float_if_numeric(v)
|
||||
v = _to_excel_compatible(v)
|
||||
row_values.append(v)
|
||||
ws.append(row_values)
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ from typing import Any
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
_RESULT_JSON_PREFIX = "result_test_"
|
||||
_DIFFUSION_JSON_PREFIX = "diffusion_perf_"
|
||||
_DIFFUSION_JSON_PREFIXES = ("diffusion_perf_", "diffusion_result_")
|
||||
DEFAULT_INPUT_DIR = os.getenv("DEFAULT_INPUT_DIR") or "tests"
|
||||
DEFAULT_OUTPUT_DIR = os.getenv("DEFAULT_OUTPUT_DIR") or "tests"
|
||||
DEFAULT_DIFFUSION_INPUT_DIR = os.getenv("DIFFUSION_BENCHMARK_DIR")
|
||||
@@ -51,7 +51,7 @@ def _default_diffusion_input_dir(input_dir: str) -> str:
|
||||
return DEFAULT_DIFFUSION_INPUT_DIR if DEFAULT_DIFFUSION_INPUT_DIR else input_dir
|
||||
|
||||
|
||||
def _load_json_file(path: str) -> dict[str, Any] | None:
|
||||
def _load_json_file(path: str) -> dict[str, Any] | list[Any] | None:
|
||||
try:
|
||||
with open(path, encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
@@ -59,8 +59,8 @@ def _load_json_file(path: str) -> dict[str, Any] | None:
|
||||
LOGGER.warning("failed to load json '%s': %s", path, exc)
|
||||
return None
|
||||
|
||||
if not isinstance(data, dict):
|
||||
LOGGER.warning("json root in '%s' is not an object, skip", path)
|
||||
if not isinstance(data, (dict, list)):
|
||||
LOGGER.warning("json root in '%s' is not an object or list, skip", path)
|
||||
return None
|
||||
|
||||
return data
|
||||
@@ -170,9 +170,10 @@ def _iter_omni_json_records(input_dir: str) -> Iterable[dict[str, Any]]:
|
||||
|
||||
def _parse_diffusion_from_filename(filename: str) -> dict[str, Any]:
|
||||
name, ext = os.path.splitext(filename)
|
||||
if ext != ".json" or not name.startswith(_DIFFUSION_JSON_PREFIX):
|
||||
if ext != ".json" or not any(name.startswith(prefix) for prefix in _DIFFUSION_JSON_PREFIXES):
|
||||
return {}
|
||||
core = name[len(_DIFFUSION_JSON_PREFIX) :]
|
||||
matched_prefix = next(prefix for prefix in _DIFFUSION_JSON_PREFIXES if name.startswith(prefix))
|
||||
core = name[len(matched_prefix) :]
|
||||
parts = core.split("_")
|
||||
if len(parts) < 2:
|
||||
return {}
|
||||
@@ -195,7 +196,7 @@ def _iter_diffusion_json_records(input_dir: str) -> Iterable[dict[str, Any]]:
|
||||
return
|
||||
|
||||
for entry in sorted(os.listdir(input_dir)):
|
||||
if not entry.endswith(".json") or not entry.startswith(_DIFFUSION_JSON_PREFIX):
|
||||
if not entry.endswith(".json") or not any(entry.startswith(prefix) for prefix in _DIFFUSION_JSON_PREFIXES):
|
||||
continue
|
||||
full_path = os.path.join(input_dir, entry)
|
||||
if not os.path.isfile(full_path):
|
||||
@@ -204,17 +205,32 @@ def _iter_diffusion_json_records(input_dir: str) -> Iterable[dict[str, Any]]:
|
||||
if data is None:
|
||||
continue
|
||||
|
||||
record: dict[str, Any] = dict(data)
|
||||
filename_meta = _parse_diffusion_from_filename(os.path.basename(full_path))
|
||||
if "date" not in record or not record.get("date"):
|
||||
record["date"] = filename_meta.get("date") or datetime.now(
|
||||
timezone.utc,
|
||||
).strftime("%Y%m%d-%H%M%S")
|
||||
if "test_name" not in record or not record.get("test_name"):
|
||||
if "test_name" in filename_meta:
|
||||
record["test_name"] = filename_meta["test_name"]
|
||||
record["source_file"] = os.path.basename(full_path)
|
||||
yield record
|
||||
if isinstance(data, dict):
|
||||
records = [data]
|
||||
elif isinstance(data, list):
|
||||
records = [r for r in data if isinstance(r, dict)]
|
||||
else:
|
||||
records = []
|
||||
|
||||
if not records:
|
||||
LOGGER.warning("diffusion json '%s' has no valid records, skip", full_path)
|
||||
continue
|
||||
|
||||
for record in records:
|
||||
flat: dict[str, Any] = dict(record)
|
||||
result = flat.pop("result", None)
|
||||
if isinstance(result, dict):
|
||||
flat.update(result)
|
||||
if "date" not in flat or not flat.get("date"):
|
||||
flat["date"] = filename_meta.get("date") or datetime.now(
|
||||
timezone.utc,
|
||||
).strftime("%Y%m%d-%H%M%S")
|
||||
if "test_name" not in flat or not flat.get("test_name"):
|
||||
if "test_name" in filename_meta:
|
||||
flat["test_name"] = filename_meta["test_name"]
|
||||
flat["source_file"] = os.path.basename(full_path)
|
||||
yield flat
|
||||
|
||||
|
||||
def _collect_omni_records(input_dir: str) -> list[dict[str, Any]]:
|
||||
|
||||
Reference in new issue
Block a user