diff --git a/lbry/lbry/blob_exchange/downloader.py b/lbry/lbry/blob_exchange/downloader.py index 98d626fa0..84e8414bc 100644 --- a/lbry/lbry/blob_exchange/downloader.py +++ b/lbry/lbry/blob_exchange/downloader.py @@ -26,6 +26,7 @@ class BlobDownloader: self.ignored: typing.Dict['KademliaPeer', int] = {} self.scores: typing.Dict['KademliaPeer', int] = {} self.failures: typing.Dict['KademliaPeer', int] = {} + self.connection_failures: typing.List['KademliaPeer'] = [] self.connections: typing.Dict['KademliaPeer', asyncio.Transport] = {} self.is_running = asyncio.Event(loop=self.loop) @@ -47,6 +48,8 @@ class BlobDownloader: connection_manager=self.blob_manager.connection_manager ) + if not bytes_received and not transport and peer not in self.connection_failures: + self.connection_failures.append(peer) if not transport and peer not in self.ignored: self.ignored[peer] = self.loop.time() log.debug("drop peer %s:%i", peer.address, peer.tcp_port) @@ -113,6 +116,7 @@ class BlobDownloader: blob.close() def close(self): + self.connection_failures.clear() self.scores.clear() self.ignored.clear() self.is_running.clear() diff --git a/lbry/lbry/extras/daemon/analytics.py b/lbry/lbry/extras/daemon/analytics.py index 18bfac0f0..45b40cbdb 100644 --- a/lbry/lbry/extras/daemon/analytics.py +++ b/lbry/lbry/extras/daemon/analytics.py @@ -44,7 +44,8 @@ def _event_properties(installation_id: str, session_id: str, def _download_properties(conf: Config, external_ip: str, resolve_duration: float, total_duration: typing.Optional[float], download_id: str, name: str, - outpoint: str, active_peer_count: int, tried_peers_count: int, + outpoint: str, active_peer_count: typing.Optional[int], + tried_peers_count: typing.Optional[int], connection_failures_count: typing.Optional[int], added_fixed_peers: bool, fixed_peer_delay: float, sd_hash: str, sd_download_duration: typing.Optional[float] = None, head_blob_hash: typing.Optional[str] = None, @@ -74,7 +75,9 @@ def _download_properties(conf: Config, external_ip: str, resolve_duration: float "head_blob_hash": head_blob_hash, "head_blob_length": head_blob_length, - "head_blob_duration": None if not head_blob_download_duration else round(head_blob_download_duration, 4) + "head_blob_duration": None if not head_blob_download_duration else round(head_blob_download_duration, 4), + + "connection_failures_count": connection_failures_count } @@ -99,7 +102,6 @@ def _make_context(platform): class AnalyticsManager: - def __init__(self, conf: Config, installation_id: str, session_id: str): self.conf = conf self.cookies = {} @@ -110,7 +112,7 @@ class AnalyticsManager: self.context = _make_context(system_info.get_platform()) self.installation_id = installation_id self.session_id = session_id - self.task: asyncio.Task = None + self.task: typing.Optional[asyncio.Task] = None self.external_ip: typing.Optional[str] = None @property @@ -172,8 +174,11 @@ class AnalyticsManager: async def send_time_to_first_bytes(self, resolve_duration: typing.Optional[float], total_duration: typing.Optional[float], download_id: str, - name: str, outpoint: str, found_peers_count: int, - tried_peers_count: int, added_fixed_peers: bool, + name: str, outpoint: typing.Optional[str], + found_peers_count: typing.Optional[int], + tried_peers_count: typing.Optional[int], + connection_failures_count: typing.Optional[int], + added_fixed_peers: bool, fixed_peers_delay: float, sd_hash: str, sd_download_duration: typing.Optional[float] = None, head_blob_hash: typing.Optional[str] = None, @@ -182,8 +187,8 @@ class AnalyticsManager: error: typing.Optional[str] = None): await self.track(self._event(TIME_TO_FIRST_BYTES, _download_properties( self.conf, self.external_ip, resolve_duration, total_duration, download_id, name, outpoint, - found_peers_count, tried_peers_count, added_fixed_peers, fixed_peers_delay, sd_hash, - sd_download_duration, head_blob_hash, head_blob_length, head_blob_duration, error + found_peers_count, tried_peers_count, connection_failures_count, added_fixed_peers, fixed_peers_delay, + sd_hash, sd_download_duration, head_blob_hash, head_blob_length, head_blob_duration, error ))) async def send_download_finished(self, download_id, name, sd_hash): diff --git a/lbry/lbry/stream/downloader.py b/lbry/lbry/stream/downloader.py index df79b6a4f..17363b37e 100644 --- a/lbry/lbry/stream/downloader.py +++ b/lbry/lbry/stream/downloader.py @@ -18,7 +18,7 @@ log = logging.getLogger(__name__) class StreamDownloader: - def __init__(self, loop: asyncio.BaseEventLoop, config: 'Config', blob_manager: 'BlobManager', sd_hash: str, + def __init__(self, loop: asyncio.AbstractEventLoop, config: 'Config', blob_manager: 'BlobManager', sd_hash: str, descriptor: typing.Optional[StreamDescriptor] = None): self.loop = loop self.config = config diff --git a/lbry/lbry/stream/stream_manager.py b/lbry/lbry/stream/stream_manager.py index 2e458bfe9..2d8490707 100644 --- a/lbry/lbry/stream/stream_manager.py +++ b/lbry/lbry/stream/stream_manager.py @@ -454,6 +454,7 @@ class StreamManager: uri, outpoint, None if not stream else len(stream.downloader.blob_downloader.active_connections), None if not stream else len(stream.downloader.blob_downloader.scores), + None if not stream else len(stream.downloader.blob_downloader.connection_failures), False if not stream else stream.downloader.added_fixed_peers, self.config.fixed_peer_delay if not stream else stream.downloader.fixed_peers_delay, None if not stream else stream.sd_hash,