Spaces:
Sleeping
Sleeping
Download trackio/fragments.py from saba9/test-images: direct link, hf CLI and curl.
- Browser
- Download file 11.8 kB
-
https://huggingface.co/spaces/saba9/test-images/resolve/main/trackio/fragments.py
- Command line
-
hf download hf://spaces/saba9/test-images/trackio/fragments.py
-
curl -L -o fragments.py https://huggingface.co/spaces/saba9/test-images/resolve/main/trackio/fragments.py
11.8 kB
| """Append-only JSONL fragments used as a durable fallback for metric logging. | |
| Fragments are immutable JSONL files, one writer (process) per subdirectory, so | |
| concurrent training processes never contend on a shared file. They are written | |
| either to a Hugging Face Bucket inbox (when a Space is unreachable) or to a | |
| local inbox directory (when SQLite is unsafe, e.g. on network filesystems), and | |
| are later imported into the project SQLite database by the process that owns it | |
| (the Space or the dashboard server). Records carry the same ``log_id``/ | |
| ``alert_id`` UUIDs as the HTTP logging endpoints, and imports use | |
| ``INSERT OR IGNORE``, so importing a fragment is idempotent: fragments are | |
| deleted only after a successful import, and re-importing after a crash is | |
| harmless. | |
| """ | |
| import tempfile | |
| import threading | |
| import uuid | |
| from pathlib import Path | |
| from typing import Any | |
| import huggingface_hub | |
| import orjson | |
| from trackio import utils | |
| from trackio.typehints import AlertEntry, LogEntry, SystemLogEntry | |
| FRAGMENT_VERSION = 1 | |
| INBOX_DIR_NAME = "inbox" | |
| BUCKET_INBOX_PREFIX = "trackio/inbox" | |
| BUCKET_MEDIA_PREFIX = "trackio/media" | |
| METRIC_KIND = "metric" | |
| SYSTEM_METRIC_KIND = "system_metric" | |
| ALERT_KIND = "alert" | |
| KINDS = {METRIC_KIND, SYSTEM_METRIC_KIND, ALERT_KIND} | |
| def local_inbox_dir() -> Path: | |
| return utils.TRACKIO_DIR / INBOX_DIR_NAME | |
| def metric_record(entry: LogEntry | dict) -> dict: | |
| return { | |
| "v": FRAGMENT_VERSION, | |
| "kind": METRIC_KIND, | |
| "project": entry["project"], | |
| "run": entry["run"], | |
| "run_id": entry.get("run_id"), | |
| "metrics": utils.serialize_values(entry.get("metrics") or {}), | |
| "step": entry.get("step"), | |
| "timestamp": entry.get("timestamp"), | |
| "config": utils.serialize_values(entry.get("config")) | |
| if entry.get("config") | |
| else None, | |
| "log_id": entry.get("log_id"), | |
| } | |
| def system_metric_record(entry: SystemLogEntry | dict) -> dict: | |
| return { | |
| "v": FRAGMENT_VERSION, | |
| "kind": SYSTEM_METRIC_KIND, | |
| "project": entry["project"], | |
| "run": entry["run"], | |
| "run_id": entry.get("run_id"), | |
| "metrics": utils.serialize_values(entry.get("metrics") or {}), | |
| "timestamp": entry.get("timestamp"), | |
| "log_id": entry.get("log_id"), | |
| } | |
| def alert_record(entry: AlertEntry | dict) -> dict: | |
| return { | |
| "v": FRAGMENT_VERSION, | |
| "kind": ALERT_KIND, | |
| "project": entry["project"], | |
| "run": entry["run"], | |
| "run_id": entry.get("run_id"), | |
| "title": entry["title"], | |
| "text": entry.get("text"), | |
| "level": entry.get("level"), | |
| "step": entry.get("step"), | |
| "timestamp": entry.get("timestamp"), | |
| "alert_id": entry.get("alert_id"), | |
| } | |
| def bucket_media_path( | |
| project: str, | |
| run: str | None, | |
| step: int | None, | |
| relative_path: str | None, | |
| filename: str, | |
| ) -> str: | |
| parts = [BUCKET_MEDIA_PREFIX, utils.canonical_project_name(project)] | |
| if run: | |
| parts.append(run) | |
| if step is not None: | |
| parts.append(str(step)) | |
| else: | |
| parts.append("files") | |
| if relative_path: | |
| parts.append(str(relative_path)) | |
| parts.append(filename) | |
| return "/".join(parts) | |
| class FragmentWriter: | |
| """Writes immutable JSONL fragments for a single writer (process).""" | |
| def __init__(self, writer_id: str | None = None): | |
| self.writer_id = writer_id or uuid.uuid4().hex[:16] | |
| self._seq = 0 | |
| self._lock = threading.Lock() | |
| def _next_fragment_name(self) -> str: | |
| with self._lock: | |
| name = f"{self._seq:08d}.jsonl" | |
| self._seq += 1 | |
| return name | |
| def serialize_records(records: list[dict]) -> bytes: | |
| return b"".join(orjson.dumps(record) + b"\n" for record in records) | |
| def write_local( | |
| self, records: list[dict], inbox_dir: Path | None = None | |
| ) -> Path | None: | |
| if not records: | |
| return None | |
| inbox = inbox_dir or local_inbox_dir() | |
| writer_dir = inbox / self.writer_id | |
| fragment_path = writer_dir / self._next_fragment_name() | |
| data = self.serialize_records(records) | |
| for attempt in range(3): | |
| writer_dir.mkdir(parents=True, exist_ok=True) | |
| try: | |
| with tempfile.NamedTemporaryFile( | |
| mode="wb", dir=writer_dir, suffix=".tmp", delete=False | |
| ) as tmp: | |
| tmp.write(data) | |
| tmp_path = Path(tmp.name) | |
| tmp_path.replace(fragment_path) | |
| return fragment_path | |
| except FileNotFoundError: | |
| if attempt == 2 or writer_dir.exists(): | |
| raise | |
| def write_to_bucket(self, records: list[dict], bucket_id: str) -> str | None: | |
| if not records: | |
| return None | |
| remote_path = ( | |
| f"{BUCKET_INBOX_PREFIX}/{self.writer_id}/{self._next_fragment_name()}" | |
| ) | |
| huggingface_hub.batch_bucket_files( | |
| bucket_id, | |
| add=[(self.serialize_records(records), remote_path)], | |
| token=huggingface_hub.utils.get_token(), | |
| ) | |
| return remote_path | |
| def parse_fragment_bytes(data: bytes) -> list[dict]: | |
| records = [] | |
| for line in data.splitlines(): | |
| line = line.strip() | |
| if not line: | |
| continue | |
| try: | |
| record = orjson.loads(line) | |
| except orjson.JSONDecodeError: | |
| continue | |
| if isinstance(record, dict) and record.get("kind") in KINDS: | |
| records.append(record) | |
| return records | |
| def _group_by_run(records: list[dict]) -> dict[tuple, list[dict]]: | |
| grouped: dict[tuple, list[dict]] = {} | |
| for record in records: | |
| key = (record.get("project"), record.get("run"), record.get("run_id")) | |
| grouped.setdefault(key, []).append(record) | |
| return grouped | |
| def import_records(records: list[dict]) -> int: | |
| from trackio.sqlite_storage import SQLiteStorage # noqa: PLC0415 | |
| metric_records = [r for r in records if r.get("kind") == METRIC_KIND] | |
| system_records = [r for r in records if r.get("kind") == SYSTEM_METRIC_KIND] | |
| alert_records = [r for r in records if r.get("kind") == ALERT_KIND] | |
| imported = 0 | |
| for (project, run, run_id), group in _group_by_run(metric_records).items(): | |
| if not project or not run: | |
| continue | |
| config = next((r["config"] for r in group if r.get("config")), None) | |
| has_timestamps = all(r.get("timestamp") for r in group) | |
| SQLiteStorage.bulk_log( | |
| project=project, | |
| run=run, | |
| run_id=run_id, | |
| metrics_list=[r.get("metrics") or {} for r in group], | |
| steps=[r.get("step") for r in group], | |
| timestamps=[r["timestamp"] for r in group] if has_timestamps else None, | |
| config=config, | |
| log_ids=[r.get("log_id") for r in group], | |
| ) | |
| imported += len(group) | |
| for (project, run, run_id), group in _group_by_run(system_records).items(): | |
| if not project or not run: | |
| continue | |
| has_timestamps = all(r.get("timestamp") for r in group) | |
| SQLiteStorage.bulk_log_system( | |
| project=project, | |
| run=run, | |
| run_id=run_id, | |
| metrics_list=[r.get("metrics") or {} for r in group], | |
| timestamps=[r["timestamp"] for r in group] if has_timestamps else None, | |
| log_ids=[r.get("log_id") for r in group], | |
| ) | |
| imported += len(group) | |
| for (project, run, run_id), group in _group_by_run(alert_records).items(): | |
| if not project or not run: | |
| continue | |
| has_timestamps = all(r.get("timestamp") for r in group) | |
| SQLiteStorage.bulk_alert( | |
| project=project, | |
| run=run, | |
| run_id=run_id, | |
| titles=[r.get("title") or "" for r in group], | |
| texts=[r.get("text") for r in group], | |
| levels=[r.get("level") or "WARN" for r in group], | |
| steps=[r.get("step") for r in group], | |
| timestamps=[r["timestamp"] for r in group] if has_timestamps else None, | |
| alert_ids=[r.get("alert_id") for r in group], | |
| ) | |
| imported += len(group) | |
| return imported | |
| def import_inbox_dir(inbox_dir: Path | None = None) -> int: | |
| inbox = inbox_dir or local_inbox_dir() | |
| if not inbox.exists(): | |
| return 0 | |
| imported = 0 | |
| for fragment_path in sorted(inbox.rglob("*.jsonl")): | |
| try: | |
| data = fragment_path.read_bytes() | |
| except OSError: | |
| continue | |
| records = parse_fragment_bytes(data) | |
| if records: | |
| imported += import_records(records) | |
| try: | |
| fragment_path.unlink() | |
| except OSError: | |
| pass | |
| for writer_dir in inbox.glob("*"): | |
| if writer_dir.is_dir(): | |
| try: | |
| writer_dir.rmdir() | |
| except OSError: | |
| pass | |
| return imported | |
| def list_bucket_inbox_paths(bucket_id: str) -> list[str]: | |
| try: | |
| items = huggingface_hub.list_bucket_tree( | |
| bucket_id, | |
| prefix=BUCKET_INBOX_PREFIX, | |
| recursive=True, | |
| token=huggingface_hub.utils.get_token(), | |
| ) | |
| except Exception: | |
| return [] | |
| return sorted( | |
| item.path | |
| for item in items | |
| if getattr(item, "type", None) == "file" | |
| and getattr(item, "path", "").endswith(".jsonl") | |
| ) | |
| def import_inbox_from_bucket(bucket_id: str) -> int: | |
| paths = list_bucket_inbox_paths(bucket_id) | |
| if not paths: | |
| return 0 | |
| imported = 0 | |
| consumed: list[str] = [] | |
| with tempfile.TemporaryDirectory() as tmp_dir: | |
| for i, remote_path in enumerate(paths): | |
| local_path = Path(tmp_dir) / f"{i}.jsonl" | |
| try: | |
| huggingface_hub.download_bucket_files( | |
| bucket_id, | |
| files=[(remote_path, str(local_path))], | |
| token=huggingface_hub.utils.get_token(), | |
| ) | |
| records = parse_fragment_bytes(local_path.read_bytes()) | |
| except Exception: | |
| continue | |
| if records: | |
| imported += import_records(records) | |
| consumed.append(remote_path) | |
| if consumed: | |
| try: | |
| huggingface_hub.batch_bucket_files( | |
| bucket_id, | |
| delete=consumed, | |
| token=huggingface_hub.utils.get_token(), | |
| ) | |
| except Exception: | |
| pass | |
| return imported | |
| def _add_files_to_bucket(bucket_id: str, additions: list[tuple[str, str]]) -> None: | |
| if additions: | |
| huggingface_hub.batch_bucket_files( | |
| bucket_id, | |
| add=additions, | |
| token=huggingface_hub.utils.get_token(), | |
| ) | |
| def upload_media_files_to_bucket(bucket_id: str, uploads: list[dict[str, Any]]) -> None: | |
| _add_files_to_bucket( | |
| bucket_id, | |
| [ | |
| ( | |
| str(p), | |
| bucket_media_path( | |
| project=upload["project"], | |
| run=upload.get("run"), | |
| step=upload.get("step"), | |
| relative_path=upload.get("relative_path"), | |
| filename=p.name, | |
| ), | |
| ) | |
| for upload in uploads | |
| if (p := Path(upload["file_path"])).exists() | |
| ], | |
| ) | |
| def upload_artifact_blobs_to_bucket( | |
| bucket_id: str, uploads: list[dict[str, Any]] | |
| ) -> None: | |
| _add_files_to_bucket( | |
| bucket_id, | |
| [ | |
| (str(p), f"trackio/{p.relative_to(utils.TRACKIO_DIR).as_posix()}") | |
| for upload in uploads | |
| if (p := Path(upload["file_path"])).exists() | |
| ], | |
| ) | |