Spaces:
Sleeping
Sleeping
| """Aggregate, privacy-preserving usage logging. | |
| Logs the RESULT of each identification (predicted raaga + confidence + tonic + whether a | |
| prediction was made) to a private Hugging Face Dataset. It NEVER logs the audio, an IP, or any | |
| user identifier — just anonymous per-identification result metadata, so we can see how much the | |
| app is used and what it's recognising in the wild (the passive real-world signal). | |
| Robustness: | |
| - Disabled unless HF_TOKEN is set (a write token, as a Space secret). Without it the app runs | |
| exactly as before, just without logging. | |
| - Every call is wrapped so a logging failure can NEVER break recognition. | |
| - Uses huggingface_hub.CommitScheduler: appends locally, flushes to the dataset every few minutes | |
| (one commit per identification would be far too many). | |
| """ | |
| from __future__ import annotations | |
| import json | |
| import os | |
| from pathlib import Path | |
| DATASET = "twelveswaras/usage-logs" | |
| LOG_DIR = Path("usage_logs") | |
| LOG_FILE = LOG_DIR / "identifications.jsonl" | |
| _scheduler = None | |
| _tried = False | |
| def _scheduler_or_none(): | |
| global _scheduler, _tried | |
| if _scheduler is not None or _tried: | |
| return _scheduler | |
| _tried = True | |
| if not os.environ.get("HF_TOKEN"): | |
| return None # logging off; app still works | |
| try: | |
| from huggingface_hub import CommitScheduler | |
| LOG_DIR.mkdir(exist_ok=True) | |
| _scheduler = CommitScheduler(repo_id=DATASET, repo_type="dataset", private=True, | |
| folder_path=str(LOG_DIR), path_in_repo="data", every=5) | |
| except Exception: # noqa: BLE001 (bad token / no access -> stay disabled) | |
| _scheduler = None | |
| return _scheduler | |
| def record(*, top1=None, confidence=None, top3=None, tonic_hz=None, | |
| heard_seconds=None, no_prediction=False, elapsed_s=None) -> None: | |
| """Append one identification's RESULT metadata. No audio, no PII. Never raises.""" | |
| try: | |
| sch = _scheduler_or_none() | |
| if sch is None: | |
| return | |
| from datetime import datetime, timezone | |
| row = { | |
| "ts": datetime.now(timezone.utc).isoformat(timespec="seconds"), | |
| "top1": top1, | |
| "confidence": round(float(confidence), 3) if confidence is not None else None, | |
| "top3": top3, | |
| "tonic_hz": round(float(tonic_hz)) if tonic_hz else None, | |
| "heard_s": round(float(heard_seconds), 1) if heard_seconds is not None else None, | |
| "no_prediction": bool(no_prediction), | |
| "elapsed_s": round(float(elapsed_s), 2) if elapsed_s is not None else None, | |
| } | |
| with sch.lock: | |
| with open(LOG_FILE, "a", encoding="utf-8") as fh: | |
| fh.write(json.dumps(row, ensure_ascii=False) + "\n") | |
| except Exception: # noqa: BLE001 (logging must never break recognition) | |
| pass | |