feat(gui): câbler l'envoi de la télémétrie d'usage en fin de run
Le module usage_telemetry est maintenant réellement branché : la GUI V6 envoie les statistiques au portail après chaque run (les stats web restaient vides sans cela). - processing_runner : RunSummary porte une liste DocResult (ordinal, page_count via page_count_for, status, duration_ms, extension) — peuplée dans la boucle. Aucun nom/chemin de fichier. - usage_telemetry : report_run_summary(summary, base_url, license_ref, machine_id, session, ...) construit le payload depuis le RunSummary et l'envoie (non bloquant). N'envoie RIEN sans license_ref. Spool JSONL si échec réseau. - tab_usage : _finish() déclenche l'envoi en thread daemon (jamais bloquant pour l'UI ni le run). - app : fournit le reporter à UsageTab avec le contexte licence (base_url du LicenseClient, license_ref via local_status, machine_id, app_version). Tests : RunSummary.documents peuplé (0 chemin) ; report_run_summary (payload correct, réseau KO → spool sans crash, pas d'envoi sans licence) ; _finish appelle le reporter. 252 tests unit OK (0 régression), self-test OK. V5/moteur/app_aivanov intacts, 0 dépendance. Aucun build/push sans GO Dom. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -163,3 +163,29 @@ def test_no_double_run(tmp_path):
|
||||
release.set()
|
||||
worker.join(timeout=2)
|
||||
assert runner.is_running is False
|
||||
|
||||
|
||||
# -- détails par document (télémétrie) -------------------------------------
|
||||
|
||||
def test_run_records_per_document_details(tmp_path):
|
||||
_touch(tmp_path / "a.pdf")
|
||||
_touch(tmp_path / "b.pdf")
|
||||
|
||||
def fake(doc, out):
|
||||
if doc.name == "b.pdf":
|
||||
raise RuntimeError("boom")
|
||||
return {}
|
||||
|
||||
runner = ProcessingRunner(process_fn=fake, extensions=_EXTS)
|
||||
summary = runner.run(tmp_path)
|
||||
|
||||
assert len(summary.documents) == 2
|
||||
statuses = {doc.ordinal: doc.status for doc in summary.documents}
|
||||
assert statuses == {0: "success", 1: "failed"}
|
||||
for doc in summary.documents:
|
||||
assert doc.extension == "pdf"
|
||||
assert isinstance(doc.duration_ms, int)
|
||||
# RGPD : aucun nom/chemin de fichier dans les détails
|
||||
assert not hasattr(doc, "path")
|
||||
assert not hasattr(doc, "filename")
|
||||
assert not hasattr(doc, "name")
|
||||
|
||||
Reference in New Issue
Block a user