sara.mesquita commited on
Commit
1d13722
·
1 Parent(s): ee32f51

feat: add trace logging for Sharing is Caring badge

Browse files
Files changed (1) hide show
  1. core/tracer.py +85 -0
core/tracer.py ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ tracer.py — Logging de traces para o badge "Sharing is Caring" do hackathon.
3
+
4
+ Salva cada interação (analyze + confirm) em data/traces.jsonl.
5
+ Quando quiser publicar no HF Hub, chame push_to_hub().
6
+
7
+ Variáveis de ambiente:
8
+ HF_TOKEN — token HuggingFace (necessário só para push)
9
+ HF_DATASET_ID — ex: "build-small-hackathon/animal-visto-traces"
10
+ TRACE_ENABLED — "0" para desabilitar completamente (default: habilitado)
11
+ """
12
+ import json
13
+ import logging
14
+ import os
15
+ import threading
16
+ from datetime import datetime, timezone
17
+ from pathlib import Path
18
+
19
+ from core.database import DATA_DIR
20
+
21
+ log = logging.getLogger(__name__)
22
+
23
+ TRACES_PATH = DATA_DIR / "traces.jsonl"
24
+ ENABLED = os.environ.get("TRACE_ENABLED", "1") != "0"
25
+ HF_DATASET = os.environ.get("HF_DATASET_ID", "")
26
+
27
+ _lock = threading.Lock()
28
+
29
+
30
+ def log_trace(record: dict) -> None:
31
+ """Appenda um trace em data/traces.jsonl (thread-safe)."""
32
+ if not ENABLED:
33
+ return
34
+ record = {
35
+ "timestamp": datetime.now(timezone.utc).isoformat(),
36
+ **record,
37
+ }
38
+ # Remove campos sensíveis
39
+ record.pop("photo_path", None)
40
+ record.pop("temp_path", None)
41
+ coords = record.get("gps", {})
42
+ if coords:
43
+ # Arredonda para 2 casas (~1km de precisão) para preservar privacidade
44
+ record["gps"] = {
45
+ "lat": round(coords["lat"], 2) if coords.get("lat") else None,
46
+ "lng": round(coords["lng"], 2) if coords.get("lng") else None,
47
+ }
48
+
49
+ try:
50
+ DATA_DIR.mkdir(parents=True, exist_ok=True)
51
+ with _lock:
52
+ with open(TRACES_PATH, "a", encoding="utf-8") as f:
53
+ f.write(json.dumps(record, ensure_ascii=False) + "\n")
54
+ except Exception as e:
55
+ log.warning("Trace não salvo: %s", e)
56
+
57
+
58
+ def push_to_hub() -> None:
59
+ """
60
+ Publica traces.jsonl como dataset no HF Hub.
61
+ Só chamar quando estiver pronto para publicar.
62
+
63
+ Requer: HF_TOKEN e HF_DATASET_ID definidos.
64
+ """
65
+ if not HF_DATASET:
66
+ log.error("HF_DATASET_ID não definido — abortando push.")
67
+ return
68
+ if not TRACES_PATH.exists():
69
+ log.warning("Nenhum trace para publicar.")
70
+ return
71
+
72
+ try:
73
+ from huggingface_hub import HfApi
74
+ api = HfApi(token=os.environ.get("HF_TOKEN", ""))
75
+ api.create_repo(repo_id=HF_DATASET, repo_type="dataset", exist_ok=True)
76
+ api.upload_file(
77
+ path_or_fileobj=str(TRACES_PATH),
78
+ path_in_repo="traces.jsonl",
79
+ repo_id=HF_DATASET,
80
+ repo_type="dataset",
81
+ commit_message="chore: update traces",
82
+ )
83
+ log.info("Traces publicados em %s", HF_DATASET)
84
+ except Exception as e:
85
+ log.error("Erro ao publicar traces: %s", e)