"""Small request-local timings; no board payloads or external tracing dependency.""" from contextlib import contextmanager import json import os from threading import Lock from time import perf_counter from uuid import uuid4 class MoveTrace: def __init__(self, game_id, turn): self.id = uuid4().hex self.game_id = game_id self.turn = turn self.started = perf_counter() self._lock = Lock() self._fields = {} def set(self, **fields): with self._lock: self._fields.update(fields) @contextmanager def stage(self, name): started = perf_counter() try: yield finally: self.set(**{name + '_ms': round((perf_counter() - started) * 1000, 3)}) def snapshot(self): with self._lock: return {'trace_id': self.id, **self._fields} def log(self, logger): fields = self.snapshot() # Every timeout/slow request, plus deterministic sampling of normal moves. try: sample = max(0, int(os.getenv('MOVE_TRACE_SAMPLE_EVERY', '100'))) slow_ms = max(0, float(os.getenv('MOVE_TRACE_SLOW_MS', '300'))) except ValueError: sample, slow_ms = 100, 300 slow_stage = any(value >= slow_ms for key, value in fields.items() if key.endswith('_ms') and isinstance(value, (int, float))) if not (fields.get('timed_out') or fields.get('metrics_publish_failed') or slow_stage or (sample and int(self.id[:8], 16) % sample == 0)): return logger.info('move_trace %s', json.dumps({ 'game_id': self.game_id, 'turn': self.turn, **fields, }, separators=(',', ':')))