forked from LBRYCommunity/lbry-sdk
Merge branch 'download_analytics_v2'
This commit is contained in:
commit
bcf52c3f24
5 changed files with 52 additions and 14 deletions
|
@ -18,6 +18,7 @@ HEARTBEAT = 'Heartbeat'
|
||||||
CLAIM_ACTION = 'Claim Action' # publish/create/update/abandon
|
CLAIM_ACTION = 'Claim Action' # publish/create/update/abandon
|
||||||
NEW_CHANNEL = 'New Channel'
|
NEW_CHANNEL = 'New Channel'
|
||||||
CREDITS_SENT = 'Credits Sent'
|
CREDITS_SENT = 'Credits Sent'
|
||||||
|
NEW_DOWNLOAD_STAT = 'Download'
|
||||||
|
|
||||||
BLOB_BYTES_UPLOADED = 'Blob Bytes Uploaded'
|
BLOB_BYTES_UPLOADED = 'Blob Bytes Uploaded'
|
||||||
|
|
||||||
|
@ -41,6 +42,32 @@ class Manager:
|
||||||
return cls(api)
|
return cls(api)
|
||||||
|
|
||||||
# Things We Track
|
# Things We Track
|
||||||
|
def send_new_download_start(self, download_id, name, claim_dict):
|
||||||
|
self._send_new_download_stats("start", download_id, name, claim_dict)
|
||||||
|
|
||||||
|
def send_new_download_success(self, download_id, name, claim_dict):
|
||||||
|
self._send_new_download_stats("success", download_id, name, claim_dict)
|
||||||
|
|
||||||
|
def send_new_download_fail(self, download_id, name, claim_dict, e):
|
||||||
|
self._send_new_download_stats("failure", download_id, name, claim_dict, {
|
||||||
|
'name': type(e).__name__ if hasattr(type(e), "__name__") else str(type(e)),
|
||||||
|
'message': e.message,
|
||||||
|
})
|
||||||
|
|
||||||
|
def _send_new_download_stats(self, action, download_id, name, claim_dict, e=None):
|
||||||
|
self.analytics_api.track({
|
||||||
|
'userId': 'lbry', # required, see https://segment.com/docs/sources/server/http/#track
|
||||||
|
'event': NEW_DOWNLOAD_STAT,
|
||||||
|
'properties': self._event_properties({
|
||||||
|
'download_id': download_id,
|
||||||
|
'name': name,
|
||||||
|
'sd_hash': None if not claim_dict else claim_dict.source_hash,
|
||||||
|
'action': action,
|
||||||
|
'error': e,
|
||||||
|
}),
|
||||||
|
'context': self.context,
|
||||||
|
'timestamp': utils.isonow(),
|
||||||
|
})
|
||||||
|
|
||||||
def send_server_startup(self):
|
def send_server_startup(self):
|
||||||
self.analytics_api.track(self._event(SERVER_STARTUP))
|
self.analytics_api.track(self._event(SERVER_STARTUP))
|
||||||
|
@ -185,26 +212,18 @@ class Manager:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _make_context(platform, wallet):
|
def _make_context(platform, wallet):
|
||||||
|
# see https://segment.com/docs/spec/common/#context
|
||||||
|
# they say they'll ignore fields outside the spec, but evidently they don't
|
||||||
context = {
|
context = {
|
||||||
'app': {
|
'app': {
|
||||||
'name': 'lbrynet',
|
|
||||||
'version': platform['lbrynet_version'],
|
'version': platform['lbrynet_version'],
|
||||||
'python_version': platform['python_version'],
|
|
||||||
'build': platform['build'],
|
'build': platform['build'],
|
||||||
'wallet': {
|
|
||||||
'name': wallet,
|
|
||||||
'version': platform['lbrynet_version']
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
# TODO: expand os info to give linux/osx specific info
|
# TODO: expand os info to give linux/osx specific info
|
||||||
'os': {
|
'os': {
|
||||||
'name': platform['os_system'],
|
'name': platform['os_system'],
|
||||||
'version': platform['os_release']
|
'version': platform['os_release']
|
||||||
},
|
},
|
||||||
'library': {
|
|
||||||
'name': 'lbrynet-analytics',
|
|
||||||
'version': '1.0.0'
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
if 'desktop' in platform and 'distro' in platform:
|
if 'desktop' in platform and 'distro' in platform:
|
||||||
context['os']['desktop'] = platform['desktop']
|
context['os']['desktop'] = platform['desktop']
|
||||||
|
|
|
@ -49,6 +49,20 @@ class InsufficientFundsError(RPCError):
|
||||||
code = -310
|
code = -310
|
||||||
|
|
||||||
|
|
||||||
|
class CurrencyConversionError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class FileOpenError(ValueError):
|
||||||
|
# this extends ValueError because it is replacing a ValueError in EncryptedFileDownloader
|
||||||
|
# and I don't know where it might get caught upstream
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ResolveError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ConnectionClosedBeforeResponseError(Exception):
|
class ConnectionClosedBeforeResponseError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ from lbrynet.core.StreamDescriptor import download_sd_blob
|
||||||
from lbrynet.core.Error import InsufficientFundsError, UnknownNameError
|
from lbrynet.core.Error import InsufficientFundsError, UnknownNameError
|
||||||
from lbrynet.core.Error import DownloadDataTimeout, DownloadSDTimeout
|
from lbrynet.core.Error import DownloadDataTimeout, DownloadSDTimeout
|
||||||
from lbrynet.core.Error import NullFundsError, NegativeFundsError
|
from lbrynet.core.Error import NullFundsError, NegativeFundsError
|
||||||
|
from lbrynet.core.Error import ResolveError
|
||||||
from lbrynet.dht.error import TimeoutError
|
from lbrynet.dht.error import TimeoutError
|
||||||
from lbrynet.core.Peer import Peer
|
from lbrynet.core.Peer import Peer
|
||||||
from lbrynet.core.SinglePeerDownloader import SinglePeerDownloader
|
from lbrynet.core.SinglePeerDownloader import SinglePeerDownloader
|
||||||
|
@ -339,12 +340,14 @@ class Daemon(AuthJSONRPCServer):
|
||||||
def _download_finished(download_id, name, claim_dict):
|
def _download_finished(download_id, name, claim_dict):
|
||||||
report = yield self._get_stream_analytics_report(claim_dict)
|
report = yield self._get_stream_analytics_report(claim_dict)
|
||||||
self.analytics_manager.send_download_finished(download_id, name, report, claim_dict)
|
self.analytics_manager.send_download_finished(download_id, name, report, claim_dict)
|
||||||
|
self.analytics_manager.send_new_download_success(download_id, name, claim_dict)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def _download_failed(error, download_id, name, claim_dict):
|
def _download_failed(error, download_id, name, claim_dict):
|
||||||
report = yield self._get_stream_analytics_report(claim_dict)
|
report = yield self._get_stream_analytics_report(claim_dict)
|
||||||
self.analytics_manager.send_download_errored(error, download_id, name, claim_dict,
|
self.analytics_manager.send_download_errored(error, download_id, name, claim_dict,
|
||||||
report)
|
report)
|
||||||
|
self.analytics_manager.send_new_download_fail(download_id, name, claim_dict, error)
|
||||||
|
|
||||||
if sd_hash in self.streams:
|
if sd_hash in self.streams:
|
||||||
downloader = self.streams[sd_hash]
|
downloader = self.streams[sd_hash]
|
||||||
|
@ -353,6 +356,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
else:
|
else:
|
||||||
download_id = utils.random_string()
|
download_id = utils.random_string()
|
||||||
self.analytics_manager.send_download_started(download_id, name, claim_dict)
|
self.analytics_manager.send_download_started(download_id, name, claim_dict)
|
||||||
|
self.analytics_manager.send_new_download_start(download_id, name, claim_dict)
|
||||||
self.streams[sd_hash] = GetStream(
|
self.streams[sd_hash] = GetStream(
|
||||||
self.sd_identifier, self.wallet_manager, self.exchange_rate_manager, self.blob_manager,
|
self.sd_identifier, self.wallet_manager, self.exchange_rate_manager, self.blob_manager,
|
||||||
self.dht_node.peer_finder, self.rate_limiter, self.payment_rate_manager, self.storage,
|
self.dht_node.peer_finder, self.rate_limiter, self.payment_rate_manager, self.storage,
|
||||||
|
@ -1851,7 +1855,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
resolved = resolved if 'value' in resolved else resolved.get('claim')
|
resolved = resolved if 'value' in resolved else resolved.get('claim')
|
||||||
|
|
||||||
if not resolved:
|
if not resolved:
|
||||||
raise Exception(
|
raise ResolveError(
|
||||||
"Failed to resolve stream at lbry://{}".format(uri.replace("lbry://", ""))
|
"Failed to resolve stream at lbry://{}".format(uri.replace("lbry://", ""))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import treq
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
from twisted.internet.task import LoopingCall
|
from twisted.internet.task import LoopingCall
|
||||||
|
|
||||||
from lbrynet.core.Error import InvalidExchangeRateResponse
|
from lbrynet.core.Error import InvalidExchangeRateResponse, CurrencyConversionError
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ class ExchangeRateManager:
|
||||||
market.rate.currency_pair[0] == from_currency):
|
market.rate.currency_pair[0] == from_currency):
|
||||||
return self.convert_currency(
|
return self.convert_currency(
|
||||||
market.rate.currency_pair[1], to_currency, amount * market.rate.spot)
|
market.rate.currency_pair[1], to_currency, amount * market.rate.spot)
|
||||||
raise Exception(
|
raise CurrencyConversionError(
|
||||||
'Unable to convert {} from {} to {}'.format(amount, from_currency, to_currency))
|
'Unable to convert {} from {} to {}'.format(amount, from_currency, to_currency))
|
||||||
|
|
||||||
def fee_dict(self):
|
def fee_dict(self):
|
||||||
|
|
|
@ -6,6 +6,7 @@ from binascii import hexlify, unhexlify
|
||||||
from lbrynet.core.StreamDescriptor import save_sd_info
|
from lbrynet.core.StreamDescriptor import save_sd_info
|
||||||
from lbrynet.cryptstream.client.CryptStreamDownloader import CryptStreamDownloader
|
from lbrynet.cryptstream.client.CryptStreamDownloader import CryptStreamDownloader
|
||||||
from lbrynet.core.client.StreamProgressManager import FullStreamProgressManager
|
from lbrynet.core.client.StreamProgressManager import FullStreamProgressManager
|
||||||
|
from lbrynet.core.Error import FileOpenError
|
||||||
from lbrynet.lbry_file.client.EncryptedFileMetadataHandler import EncryptedFileMetadataHandler
|
from lbrynet.lbry_file.client.EncryptedFileMetadataHandler import EncryptedFileMetadataHandler
|
||||||
from twisted.internet import defer, threads
|
from twisted.internet import defer, threads
|
||||||
|
|
||||||
|
@ -153,7 +154,7 @@ class EncryptedFileSaver(EncryptedFileDownloader):
|
||||||
self.file_written_to = file_written_to
|
self.file_written_to = file_written_to
|
||||||
except IOError:
|
except IOError:
|
||||||
log.error(traceback.format_exc())
|
log.error(traceback.format_exc())
|
||||||
raise ValueError(
|
raise FileOpenError(
|
||||||
"Failed to open %s. Make sure you have permission to save files to that"
|
"Failed to open %s. Make sure you have permission to save files to that"
|
||||||
" location." % file_written_to
|
" location." % file_written_to
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue