import logging from dataclasses import dataclass, field logger = logging.getLogger(__name__) def _avg(vals: list[int]) -> int: return round(sum(vals) / len(vals)) if vals else 0 def _p95(vals: list[int]) -> int: if not vals: return 0 return sorted(vals)[int(len(vals) * 0.95)] @dataclass class FanTimings: token_ms: list[int] = field(default_factory=list) profile_ms: list[int] = field(default_factory=list) top_artists_ms: list[int] = field(default_factory=list) top_tracks_ms: list[int] = field(default_factory=list) recently_played_ms: list[int] = field(default_factory=list) playlists_ms: list[int] = field(default_factory=list) saved_albums_ms: list[int] = field(default_factory=list) saved_tracks_ms: list[int] = field(default_factory=list) followed_artists_ms: list[int] = field(default_factory=list) def log_summary( self, processed: int, errors: int, *, dsp_client: str | None = None ) -> None: extra: dict[str, object] = {"processed": processed, "errors": errors} if dsp_client is not None: extra["dsp_client"] = dsp_client logger.info( "Batch timing: %d ok, %d err | " "token avg=%dms p95=%dms (n=%d) | " "profile avg=%dms p95=%dms (n=%d) | " "top_artists avg=%dms p95=%dms (n=%d) | " "top_tracks avg=%dms p95=%dms (n=%d) | " "recently_played avg=%dms p95=%dms (n=%d) | " "playlists avg=%dms p95=%dms (n=%d) | " "saved_albums avg=%dms p95=%dms (n=%d) | " "saved_tracks avg=%dms p95=%dms (n=%d) | " "followed_artists avg=%dms p95=%dms (n=%d)", processed, errors, _avg(self.token_ms), _p95(self.token_ms), len(self.token_ms), _avg(self.profile_ms), _p95(self.profile_ms), len(self.profile_ms), _avg(self.top_artists_ms), _p95(self.top_artists_ms), len(self.top_artists_ms), _avg(self.top_tracks_ms), _p95(self.top_tracks_ms), len(self.top_tracks_ms), _avg(self.recently_played_ms), _p95(self.recently_played_ms), len(self.recently_played_ms), _avg(self.playlists_ms), _p95(self.playlists_ms), len(self.playlists_ms), _avg(self.saved_albums_ms), _p95(self.saved_albums_ms), len(self.saved_albums_ms), _avg(self.saved_tracks_ms), _p95(self.saved_tracks_ms), len(self.saved_tracks_ms), _avg(self.followed_artists_ms), _p95(self.followed_artists_ms), len(self.followed_artists_ms), extra=extra, )