forked from LBRYCommunity/lbry-sdk
improve error analytics
- move analytics creation earlier in the startup process - add several events to track startup, startup failure, other errors - abstract platform detection into separate file - add "build" type to platform so we can differentiate devs vs live users
This commit is contained in:
parent
6b72b4de11
commit
7ecc8103d8
11 changed files with 167 additions and 83 deletions
|
@ -56,11 +56,10 @@ class Api(object):
|
||||||
def track(self, event):
|
def track(self, event):
|
||||||
"""Send a single tracking event"""
|
"""Send a single tracking event"""
|
||||||
log.debug('Sending track event: %s', event)
|
log.debug('Sending track event: %s', event)
|
||||||
import base64
|
|
||||||
return self.session.post(self.url + '/track', json=event, auth=self.auth)
|
return self.session.post(self.url + '/track', json=event, auth=self.auth)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls, session=None):
|
def new_instance(cls, session=None):
|
||||||
"""Initialize an instance using values from the configuration"""
|
"""Initialize an instance using values from the configuration"""
|
||||||
if not session:
|
if not session:
|
||||||
session = sessions.FuturesSession()
|
session = sessions.FuturesSession()
|
||||||
|
|
|
@ -22,6 +22,20 @@ class Events(object):
|
||||||
self.lbry_id = lbry_id
|
self.lbry_id = lbry_id
|
||||||
self.session_id = session_id
|
self.session_id = session_id
|
||||||
|
|
||||||
|
def update_context(self, context):
|
||||||
|
self.context = context
|
||||||
|
|
||||||
|
def server_startup(self):
|
||||||
|
return self._event('Server Startup')
|
||||||
|
|
||||||
|
def server_startup_success(self):
|
||||||
|
return self._event('Server Startup Success')
|
||||||
|
|
||||||
|
def server_startup_error(self, message):
|
||||||
|
return self._event('Server Startup Error', {
|
||||||
|
'message': message,
|
||||||
|
})
|
||||||
|
|
||||||
def heartbeat(self):
|
def heartbeat(self):
|
||||||
return self._event('Heartbeat')
|
return self._event('Heartbeat')
|
||||||
|
|
||||||
|
@ -32,6 +46,13 @@ class Events(object):
|
||||||
}
|
}
|
||||||
return self._event('Download Started', properties)
|
return self._event('Download Started', properties)
|
||||||
|
|
||||||
|
def error(self, message, sd_hash=None):
|
||||||
|
properties = {
|
||||||
|
'message': message,
|
||||||
|
'stream_info': sd_hash
|
||||||
|
}
|
||||||
|
return self._event('Error', properties)
|
||||||
|
|
||||||
def metric_observed(self, metric_name, value):
|
def metric_observed(self, metric_name, value):
|
||||||
properties = {
|
properties = {
|
||||||
'value': value,
|
'value': value,
|
||||||
|
@ -57,15 +78,14 @@ class Events(object):
|
||||||
return properties
|
return properties
|
||||||
|
|
||||||
|
|
||||||
def make_context(platform, wallet, is_dev=False):
|
def make_context(platform, wallet):
|
||||||
# TODO: distinguish between developer and release instances
|
|
||||||
return {
|
return {
|
||||||
'is_dev': is_dev,
|
|
||||||
'app': {
|
'app': {
|
||||||
'name': 'lbrynet',
|
'name': 'lbrynet',
|
||||||
'version': platform['lbrynet_version'],
|
'version': platform['lbrynet_version'],
|
||||||
'ui_version': platform['ui_version'],
|
'ui_version': platform['ui_version'],
|
||||||
'python_version': platform['python_version'],
|
'python_version': platform['python_version'],
|
||||||
|
'build': platform['build'],
|
||||||
'wallet': {
|
'wallet': {
|
||||||
'name': wallet,
|
'name': wallet,
|
||||||
# TODO: add in version info for lbrycrdd
|
# TODO: add in version info for lbrycrdd
|
||||||
|
|
|
@ -3,7 +3,13 @@ from lbrynet.core import looping_call_manager
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
from twisted.internet import task
|
from twisted.internet import task
|
||||||
|
|
||||||
|
from lbrynet.core.Platform import get_platform
|
||||||
|
from lbrynet.conf import settings
|
||||||
|
|
||||||
import constants
|
import constants
|
||||||
|
from api import Api
|
||||||
|
from events import Events, make_context
|
||||||
|
from track import Track
|
||||||
|
|
||||||
|
|
||||||
class Manager(object):
|
class Manager(object):
|
||||||
|
@ -12,28 +18,63 @@ class Manager(object):
|
||||||
self.events_generator = events_generator
|
self.events_generator = events_generator
|
||||||
self.track = track
|
self.track = track
|
||||||
self.looping_call_manager = self.setup_looping_calls()
|
self.looping_call_manager = self.setup_looping_calls()
|
||||||
|
self.is_started = False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def new_instance(cls, api=None, events=None):
|
||||||
|
if api is None:
|
||||||
|
api = Api.new_instance()
|
||||||
|
if events is None:
|
||||||
|
events = Events(
|
||||||
|
make_context(get_platform(), settings.wallet),
|
||||||
|
'not loaded', 'not loaded'
|
||||||
|
)
|
||||||
|
return cls(api, events, Track())
|
||||||
|
|
||||||
|
def update_events_generator(self, events_generator):
|
||||||
|
self.events_generator = events_generator
|
||||||
|
|
||||||
|
def _get_looping_calls(self):
|
||||||
|
return [
|
||||||
|
('send_heartbeat', self._send_heartbeat, 60),
|
||||||
|
('update_tracked_metrics', self._update_tracked_metrics, 300),
|
||||||
|
]
|
||||||
|
|
||||||
def setup_looping_calls(self):
|
def setup_looping_calls(self):
|
||||||
call_manager = looping_call_manager.LoopingCallManager()
|
call_manager = looping_call_manager.LoopingCallManager()
|
||||||
looping_calls = [
|
for name, fn, _ in self._get_looping_calls():
|
||||||
('send_heartbeat', self._send_heartbeat),
|
|
||||||
('update_tracked_metrics', self._update_tracked_metrics),
|
|
||||||
]
|
|
||||||
for name, fn in looping_calls:
|
|
||||||
call_manager.register_looping_call(name, task.LoopingCall(fn))
|
call_manager.register_looping_call(name, task.LoopingCall(fn))
|
||||||
return call_manager
|
return call_manager
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
self.looping_call_manager.start('send_heartbeat', 60)
|
if not self.is_started:
|
||||||
self.looping_call_manager.start('update_tracked_metrics', 300)
|
for name, _, interval in self._get_looping_calls():
|
||||||
|
self.looping_call_manager.start(name, interval)
|
||||||
|
self.is_started = True
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
self.looping_call_manager.shutdown()
|
self.looping_call_manager.shutdown()
|
||||||
|
|
||||||
|
def send_server_startup(self):
|
||||||
|
event = self.events_generator.server_startup()
|
||||||
|
self.analytics_api.track(event)
|
||||||
|
|
||||||
|
def send_server_startup_success(self):
|
||||||
|
event = self.events_generator.server_startup_success()
|
||||||
|
self.analytics_api.track(event)
|
||||||
|
|
||||||
|
def send_server_startup_error(self, message):
|
||||||
|
event = self.events_generator.server_startup_error(message)
|
||||||
|
self.analytics_api.track(event)
|
||||||
|
|
||||||
def send_download_started(self, name, stream_info=None):
|
def send_download_started(self, name, stream_info=None):
|
||||||
event = self.events_generator.download_started(name, stream_info)
|
event = self.events_generator.download_started(name, stream_info)
|
||||||
self.analytics_api.track(event)
|
self.analytics_api.track(event)
|
||||||
|
|
||||||
|
def send_error(self, message, sd_hash=None):
|
||||||
|
event = self.events_generator.error(message, sd_hash)
|
||||||
|
self.analytics_api.track(event)
|
||||||
|
|
||||||
def register_repeating_metric(self, event_name, value_generator, frequency=300):
|
def register_repeating_metric(self, event_name, value_generator, frequency=300):
|
||||||
lcall = task.LoopingCall(self._send_repeating_metric, event_name, value_generator)
|
lcall = task.LoopingCall(self._send_repeating_metric, event_name, value_generator)
|
||||||
self.looping_call_manager.register_looping_call(event_name, lcall)
|
self.looping_call_manager.register_looping_call(event_name, lcall)
|
||||||
|
|
2
lbrynet/build_type.py
Normal file
2
lbrynet/build_type.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# dont touch this. Travis changes this during build/deployment
|
||||||
|
BUILD = "dev"
|
29
lbrynet/core/Platform.py
Normal file
29
lbrynet/core/Platform.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import platform
|
||||||
|
import simplejson as json
|
||||||
|
|
||||||
|
from urllib2 import urlopen
|
||||||
|
|
||||||
|
from lbrynet import __version__ as lbrynet_version
|
||||||
|
from lbrynet import build_type
|
||||||
|
from lbryum.version import LBRYUM_VERSION as lbryum_version
|
||||||
|
|
||||||
|
|
||||||
|
def get_platform():
|
||||||
|
p = {
|
||||||
|
"processor": platform.processor(),
|
||||||
|
"python_version": platform.python_version(),
|
||||||
|
"platform": platform.platform(),
|
||||||
|
"os_release": platform.release(),
|
||||||
|
"os_system": platform.system(),
|
||||||
|
"lbrynet_version": lbrynet_version,
|
||||||
|
"lbryum_version": lbryum_version,
|
||||||
|
"ui_version": "not loaded yet",
|
||||||
|
"build": build_type.BUILD, # travis sets this during build step
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
p['ip'] = json.load(urlopen('http://jsonip.com'))['ip']
|
||||||
|
except:
|
||||||
|
p['ip'] = "Could not determine IP"
|
||||||
|
|
||||||
|
return p
|
|
@ -2,7 +2,6 @@ import binascii
|
||||||
import logging.handlers
|
import logging.handlers
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import os
|
import os
|
||||||
import platform
|
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@ -21,7 +20,6 @@ from twisted.internet.task import LoopingCall
|
||||||
from txjsonrpc import jsonrpclib
|
from txjsonrpc import jsonrpclib
|
||||||
from jsonschema import ValidationError
|
from jsonschema import ValidationError
|
||||||
|
|
||||||
from lbrynet import __version__ as lbrynet_version
|
|
||||||
# TODO: importing this when internet is disabled raises a socket.gaierror
|
# TODO: importing this when internet is disabled raises a socket.gaierror
|
||||||
from lbryum.version import LBRYUM_VERSION as lbryum_version
|
from lbryum.version import LBRYUM_VERSION as lbryum_version
|
||||||
|
|
||||||
|
@ -30,27 +28,15 @@ from lbrynet import conf
|
||||||
from lbrynet.conf import settings as lbrynet_settings
|
from lbrynet.conf import settings as lbrynet_settings
|
||||||
from lbrynet.conf import LBRYCRD_WALLET, LBRYUM_WALLET, PTC_WALLET
|
from lbrynet.conf import LBRYCRD_WALLET, LBRYUM_WALLET, PTC_WALLET
|
||||||
from lbrynet import analytics
|
from lbrynet import analytics
|
||||||
from lbrynet import reflector
|
|
||||||
from lbrynet.metadata.Metadata import Metadata, verify_name_characters
|
|
||||||
from lbrynet.metadata.Fee import FeeValidator
|
from lbrynet.metadata.Fee import FeeValidator
|
||||||
from lbrynet.core import log_support
|
from lbrynet.core import Platform
|
||||||
from lbrynet.core import utils
|
|
||||||
from lbrynet.core.utils import generate_id
|
|
||||||
from lbrynet.core.StreamDescriptor import StreamDescriptorIdentifier, download_sd_blob, BlobStreamDescriptorReader
|
|
||||||
from lbrynet.core.Session import Session
|
|
||||||
from lbrynet.core.looping_call_manager import LoopingCallManager
|
from lbrynet.core.looping_call_manager import LoopingCallManager
|
||||||
from lbrynet.core.server.BlobRequestHandler import BlobRequestHandlerFactory
|
from lbrynet.core.server.BlobRequestHandler import BlobRequestHandlerFactory
|
||||||
from lbrynet.core.server.ServerProtocol import ServerProtocolFactory
|
from lbrynet.core.server.ServerProtocol import ServerProtocolFactory
|
||||||
from lbrynet.core.Error import InsufficientFundsError, InvalidNameError
|
from lbrynet.core.Error import InsufficientFundsError, InvalidNameError
|
||||||
from lbrynet.core.PTCWallet import PTCWallet
|
|
||||||
from lbrynet.core.Wallet import LBRYcrdWallet, LBRYumWallet
|
|
||||||
from lbrynet.lbrynet_console.Settings import Settings
|
|
||||||
from lbrynet.lbryfilemanager.EncryptedFileManager import EncryptedFileManager
|
|
||||||
from lbrynet.lbryfile.StreamDescriptor import EncryptedFileStreamType
|
from lbrynet.lbryfile.StreamDescriptor import EncryptedFileStreamType
|
||||||
from lbrynet.lbryfile.client.EncryptedFileDownloader import EncryptedFileSaverFactory, EncryptedFileOpenerFactory
|
from lbrynet.lbryfile.client.EncryptedFileDownloader import EncryptedFileSaverFactory, EncryptedFileOpenerFactory
|
||||||
from lbrynet.lbryfile.client.EncryptedFileOptions import add_lbry_file_to_sd_identifier
|
from lbrynet.lbryfile.client.EncryptedFileOptions import add_lbry_file_to_sd_identifier
|
||||||
from lbrynet.lbryfile.EncryptedFileMetadataManager import DBEncryptedFileMetadataManager
|
|
||||||
from lbrynet.lbryfile.EncryptedFileMetadataManager import TempEncryptedFileMetadataManager
|
|
||||||
from lbrynet.lbrynet_daemon.UIManager import UIManager
|
from lbrynet.lbrynet_daemon.UIManager import UIManager
|
||||||
from lbrynet.lbrynet_daemon.Downloader import GetStream
|
from lbrynet.lbrynet_daemon.Downloader import GetStream
|
||||||
from lbrynet.lbrynet_daemon.Publisher import Publisher
|
from lbrynet.lbrynet_daemon.Publisher import Publisher
|
||||||
|
@ -222,7 +208,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
LBRYnet daemon, a jsonrpc interface to lbry functions
|
LBRYnet daemon, a jsonrpc interface to lbry functions
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, root):
|
def __init__(self, root, analytics_manager):
|
||||||
AuthJSONRPCServer.__init__(self, lbrynet_settings.use_auth_http)
|
AuthJSONRPCServer.__init__(self, lbrynet_settings.use_auth_http)
|
||||||
reactor.addSystemEventTrigger('before', 'shutdown', self._shutdown)
|
reactor.addSystemEventTrigger('before', 'shutdown', self._shutdown)
|
||||||
|
|
||||||
|
@ -274,7 +260,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
self.git_lbrynet_version = None
|
self.git_lbrynet_version = None
|
||||||
self.git_lbryum_version = None
|
self.git_lbryum_version = None
|
||||||
self.ui_version = None
|
self.ui_version = None
|
||||||
self.ip = None
|
self.platform = None
|
||||||
self.first_run = None
|
self.first_run = None
|
||||||
self.log_file = lbrynet_settings.get_log_filename()
|
self.log_file = lbrynet_settings.get_log_filename()
|
||||||
self.current_db_revision = 1
|
self.current_db_revision = 1
|
||||||
|
@ -314,6 +300,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
self.blob_request_payment_rate_manager = None
|
self.blob_request_payment_rate_manager = None
|
||||||
self.lbry_file_metadata_manager = None
|
self.lbry_file_metadata_manager = None
|
||||||
self.lbry_file_manager = None
|
self.lbry_file_manager = None
|
||||||
|
self.analytics_manager = analytics_manager
|
||||||
|
|
||||||
@AuthJSONRPCServer.subhandler
|
@AuthJSONRPCServer.subhandler
|
||||||
def _exclude_lbrycrd_only_commands_from_lbryum_session(self, request):
|
def _exclude_lbrycrd_only_commands_from_lbryum_session(self, request):
|
||||||
|
@ -412,24 +399,10 @@ class Daemon(AuthJSONRPCServer):
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def _get_platform(self):
|
def _get_platform(self):
|
||||||
r = {
|
if self.platform is None:
|
||||||
"processor": platform.processor(),
|
self.platform = Platform.get_platform()
|
||||||
"python_version": platform.python_version(),
|
self.platform["ui_version"] = self.lbry_ui_manager.loaded_git_version
|
||||||
"platform": platform.platform(),
|
return self.platform
|
||||||
"os_release": platform.release(),
|
|
||||||
"os_system": platform.system(),
|
|
||||||
"lbrynet_version": lbrynet_version,
|
|
||||||
"lbryum_version": lbryum_version,
|
|
||||||
"ui_version": self.lbry_ui_manager.loaded_git_version,
|
|
||||||
}
|
|
||||||
if not self.ip:
|
|
||||||
try:
|
|
||||||
r['ip'] = json.load(urlopen('http://jsonip.com'))['ip']
|
|
||||||
self.ip = r['ip']
|
|
||||||
except:
|
|
||||||
r['ip'] = "Could not determine"
|
|
||||||
|
|
||||||
return r
|
|
||||||
|
|
||||||
def _initial_setup(self):
|
def _initial_setup(self):
|
||||||
def _log_platform():
|
def _log_platform():
|
||||||
|
@ -557,6 +530,11 @@ class Daemon(AuthJSONRPCServer):
|
||||||
return defer.succeed(True)
|
return defer.succeed(True)
|
||||||
return defer.succeed(True)
|
return defer.succeed(True)
|
||||||
|
|
||||||
|
def _stop_file_manager(self):
|
||||||
|
if self.lbry_file_manager:
|
||||||
|
self.lbry_file_manager.stop()
|
||||||
|
return defer.succeed(True)
|
||||||
|
|
||||||
def _stop_server(self):
|
def _stop_server(self):
|
||||||
try:
|
try:
|
||||||
if self.lbry_server_port is not None:
|
if self.lbry_server_port is not None:
|
||||||
|
@ -654,11 +632,12 @@ class Daemon(AuthJSONRPCServer):
|
||||||
except Exception:
|
except Exception:
|
||||||
log.warn('Failed to upload log', exc_info=True)
|
log.warn('Failed to upload log', exc_info=True)
|
||||||
d = defer.succeed(None)
|
d = defer.succeed(None)
|
||||||
|
|
||||||
d.addCallback(lambda _: self._stop_server())
|
d.addCallback(lambda _: self._stop_server())
|
||||||
d.addErrback(log_support.failure, log, 'Failure while shutting down: %s')
|
d.addErrback(log_support.failure, log, 'Failure while shutting down: %s')
|
||||||
d.addCallback(lambda _: self._stop_reflector())
|
d.addCallback(lambda _: self._stop_reflector())
|
||||||
d.addErrback(log_support.failure, log, 'Failure while shutting down: %s')
|
d.addErrback(log_support.failure, log, 'Failure while shutting down: %s')
|
||||||
d.addCallback(lambda _: self.lbry_file_manager.stop())
|
d.addCallback(lambda _: self._stop_file_manager())
|
||||||
d.addErrback(log_support.failure, log, 'Failure while shutting down: %s')
|
d.addErrback(log_support.failure, log, 'Failure while shutting down: %s')
|
||||||
if self.session is not None:
|
if self.session is not None:
|
||||||
d.addCallback(lambda _: self.session.shut_down())
|
d.addCallback(lambda _: self.session.shut_down())
|
||||||
|
@ -784,12 +763,17 @@ class Daemon(AuthJSONRPCServer):
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def _get_analytics(self):
|
def _get_analytics(self):
|
||||||
analytics_api = analytics.Api.load()
|
|
||||||
context = analytics.make_context(self._get_platform(), self.wallet_type)
|
context = analytics.make_context(self._get_platform(), self.wallet_type)
|
||||||
events_generator = analytics.Events(
|
events_generator = analytics.Events(
|
||||||
context, base58.b58encode(self.lbryid), self._session_id)
|
context, base58.b58encode(self.lbryid), self._session_id)
|
||||||
self.analytics_manager = analytics.Manager(
|
if self.analytics_manager is None:
|
||||||
analytics_api, events_generator, analytics.Track())
|
self.analytics_manager = analytics.Manager.new_instance(
|
||||||
|
events=events_generator
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.analytics_manager.update_events_generator(events_generator)
|
||||||
|
|
||||||
|
if not self.analytics_manager.is_started:
|
||||||
self.analytics_manager.start()
|
self.analytics_manager.start()
|
||||||
self.analytics_manager.register_repeating_metric(
|
self.analytics_manager.register_repeating_metric(
|
||||||
analytics.BLOB_BYTES_AVAILABLE,
|
analytics.BLOB_BYTES_AVAILABLE,
|
||||||
|
@ -868,11 +852,14 @@ class Daemon(AuthJSONRPCServer):
|
||||||
|
|
||||||
def eb():
|
def eb():
|
||||||
if not r.called:
|
if not r.called:
|
||||||
|
self.analytics_manager.send_error("sd blob download timed out", sd_hash)
|
||||||
r.errback(Exception("sd timeout"))
|
r.errback(Exception("sd timeout"))
|
||||||
|
|
||||||
r = defer.Deferred(None)
|
r = defer.Deferred(None)
|
||||||
reactor.callLater(timeout, eb)
|
reactor.callLater(timeout, eb)
|
||||||
d = download_sd_blob(self.session, sd_hash, self.session.payment_rate_manager)
|
d = download_sd_blob(self.session, sd_hash, self.session.payment_rate_manager)
|
||||||
|
d.addErrback(lambda err: self.analytics_manager.send_error(
|
||||||
|
"error downloading sd blob: " + err, sd_hash))
|
||||||
d.addCallback(BlobStreamDescriptorReader)
|
d.addCallback(BlobStreamDescriptorReader)
|
||||||
d.addCallback(lambda blob: blob.get_info())
|
d.addCallback(lambda blob: blob.get_info())
|
||||||
d.addCallback(cb)
|
d.addCallback(cb)
|
||||||
|
@ -1047,12 +1034,6 @@ class Daemon(AuthJSONRPCServer):
|
||||||
)
|
)
|
||||||
return run_reflector_factory(factory)
|
return run_reflector_factory(factory)
|
||||||
|
|
||||||
def _log_to_slack(self, msg):
|
|
||||||
URL = "https://hooks.slack.com/services/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"
|
|
||||||
msg = platform.platform() + ": " + base58.b58encode(self.lbryid)[:20] + ", " + msg
|
|
||||||
requests.post(URL, json.dumps({"text": msg}))
|
|
||||||
return defer.succeed(None)
|
|
||||||
|
|
||||||
def _run_scripts(self):
|
def _run_scripts(self):
|
||||||
if len([k for k in self.startup_scripts if 'run_once' in k.keys()]):
|
if len([k for k in self.startup_scripts if 'run_once' in k.keys()]):
|
||||||
log.info("Removing one time startup scripts")
|
log.info("Removing one time startup scripts")
|
||||||
|
@ -2128,8 +2109,6 @@ class Daemon(AuthJSONRPCServer):
|
||||||
exclude_previous = True
|
exclude_previous = True
|
||||||
|
|
||||||
d = self._upload_log(log_type=log_type, exclude_previous=exclude_previous, force=force)
|
d = self._upload_log(log_type=log_type, exclude_previous=exclude_previous, force=force)
|
||||||
if 'message' in p.keys():
|
|
||||||
d.addCallback(lambda _: self._log_to_slack(p['message']))
|
|
||||||
d.addCallback(lambda _: self._render_response(True, OK_CODE))
|
d.addCallback(lambda _: self._render_response(True, OK_CODE))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ from twisted.internet import defer, reactor, error
|
||||||
from twisted.cred import portal
|
from twisted.cred import portal
|
||||||
from jsonrpc.proxy import JSONRPCProxy
|
from jsonrpc.proxy import JSONRPCProxy
|
||||||
|
|
||||||
|
from lbrynet import analytics
|
||||||
from lbrynet.lbrynet_daemon.auth.auth import PasswordChecker, HttpPasswordRealm
|
from lbrynet.lbrynet_daemon.auth.auth import PasswordChecker, HttpPasswordRealm
|
||||||
from lbrynet.lbrynet_daemon.auth.util import initialize_api_key_file
|
from lbrynet.lbrynet_daemon.auth.util import initialize_api_key_file
|
||||||
from lbrynet import conf
|
from lbrynet import conf
|
||||||
|
@ -98,7 +99,9 @@ def start():
|
||||||
print "To quit press ctrl-c or call 'stop' via the API"
|
print "To quit press ctrl-c or call 'stop' via the API"
|
||||||
|
|
||||||
if test_internet_connection():
|
if test_internet_connection():
|
||||||
start_server_and_listen(args.launchui, args.useauth)
|
analytics_manager = analytics.Manager.new_instance()
|
||||||
|
analytics_manager.send_server_startup()
|
||||||
|
start_server_and_listen(args.launchui, args.useauth, analytics_manager)
|
||||||
reactor.run()
|
reactor.run()
|
||||||
|
|
||||||
if not args.logtoconsole and not args.quiet:
|
if not args.logtoconsole and not args.quiet:
|
||||||
|
@ -121,29 +124,32 @@ def update_settings_from_args(args):
|
||||||
settings.update(to_pass)
|
settings.update(to_pass)
|
||||||
|
|
||||||
|
|
||||||
def log_and_kill(failure):
|
def log_and_kill(failure, analytics_manager):
|
||||||
|
analytics_manager.send_server_startup_error(failure.getErrorMessage() + " " + str(failure))
|
||||||
log_support.failure(failure, log, 'Failed to startup: %s')
|
log_support.failure(failure, log, 'Failed to startup: %s')
|
||||||
reactor.callFromThread(reactor.stop)
|
reactor.callFromThread(reactor.stop)
|
||||||
|
|
||||||
|
|
||||||
def start_server_and_listen(launchui, use_auth):
|
def start_server_and_listen(launchui, use_auth, analytics_manager):
|
||||||
"""The primary entry point for launching the daemon.
|
"""The primary entry point for launching the daemon.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
launchui: set to true to open a browser window
|
launchui: set to true to open a browser window
|
||||||
use_auth: set to true to enable http authentication
|
use_auth: set to true to enable http authentication
|
||||||
|
analytics_manager: to send analytics
|
||||||
kwargs: passed along to `DaemonServer().start()`
|
kwargs: passed along to `DaemonServer().start()`
|
||||||
"""
|
"""
|
||||||
lbry = DaemonServer()
|
daemon_server = DaemonServer(analytics_manager)
|
||||||
d = lbry.start()
|
d = daemon_server.start()
|
||||||
d.addCallback(lambda _: listen(lbry, use_auth))
|
d.addCallback(lambda _: listen(daemon_server, use_auth))
|
||||||
if launchui:
|
if launchui:
|
||||||
d.addCallback(lambda _: webbrowser.open(settings.UI_ADDRESS))
|
d.addCallback(lambda _: webbrowser.open(settings.UI_ADDRESS))
|
||||||
d.addErrback(log_and_kill)
|
d.addCallback(lambda _: analytics_manager.send_server_startup_success())
|
||||||
|
d.addErrback(log_and_kill, analytics_manager)
|
||||||
|
|
||||||
|
|
||||||
def listen(lbry, use_auth):
|
def listen(daemon_server, use_auth):
|
||||||
site_base = get_site_base(use_auth, lbry.root)
|
site_base = get_site_base(use_auth, daemon_server.root)
|
||||||
lbrynet_server = server.Site(site_base)
|
lbrynet_server = server.Site(site_base)
|
||||||
lbrynet_server.requestFactory = DaemonRequest
|
lbrynet_server.requestFactory = DaemonRequest
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -3,7 +3,6 @@ import os
|
||||||
|
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
|
|
||||||
from lbrynet.conf import settings
|
|
||||||
from lbrynet.lbrynet_daemon.Daemon import Daemon
|
from lbrynet.lbrynet_daemon.Daemon import Daemon
|
||||||
from lbrynet.lbrynet_daemon.Resources import LBRYindex, HostedEncryptedFile, EncryptedFileUpload
|
from lbrynet.lbrynet_daemon.Resources import LBRYindex, HostedEncryptedFile, EncryptedFileUpload
|
||||||
from lbrynet.conf import settings
|
from lbrynet.conf import settings
|
||||||
|
@ -13,10 +12,14 @@ log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class DaemonServer(object):
|
class DaemonServer(object):
|
||||||
|
def __init__(self, analytics_manager=None):
|
||||||
|
self.root = None
|
||||||
|
self.analytics_manager = analytics_manager
|
||||||
|
|
||||||
def _setup_server(self):
|
def _setup_server(self):
|
||||||
ui_path = os.path.join(settings.ensure_data_dir(), "lbry-ui", "active")
|
ui_path = os.path.join(settings.ensure_data_dir(), "lbry-ui", "active")
|
||||||
self.root = LBRYindex(ui_path)
|
self.root = LBRYindex(ui_path)
|
||||||
self._api = Daemon(self.root)
|
self._api = Daemon(self.root, self.analytics_manager)
|
||||||
self.root.putChild("view", HostedEncryptedFile(self._api))
|
self.root.putChild("view", HostedEncryptedFile(self._api))
|
||||||
self.root.putChild("upload", EncryptedFileUpload(self._api))
|
self.root.putChild("upload", EncryptedFileUpload(self._api))
|
||||||
self.root.putChild(settings.API_ADDRESS, self._api)
|
self.root.putChild(settings.API_ADDRESS, self._api)
|
||||||
|
|
|
@ -8,6 +8,7 @@ from txjsonrpc import jsonrpclib
|
||||||
|
|
||||||
from lbrynet.core.Error import InvalidAuthenticationToken, InvalidHeaderError, SubhandlerError
|
from lbrynet.core.Error import InvalidAuthenticationToken, InvalidHeaderError, SubhandlerError
|
||||||
from lbrynet.conf import settings
|
from lbrynet.conf import settings
|
||||||
|
from lbrynet.core import log_support
|
||||||
from lbrynet.lbrynet_daemon.auth.util import APIKey, get_auth_message
|
from lbrynet.lbrynet_daemon.auth.util import APIKey, get_auth_message
|
||||||
from lbrynet.lbrynet_daemon.auth.client import LBRY_SECRET
|
from lbrynet.lbrynet_daemon.auth.client import LBRY_SECRET
|
||||||
|
|
||||||
|
@ -262,10 +263,7 @@ class AuthJSONRPCServer(AuthorizedBase):
|
||||||
self._render_message(request, encoded_message)
|
self._render_message(request, encoded_message)
|
||||||
|
|
||||||
def _errback_render(self, failure, id):
|
def _errback_render(self, failure, id):
|
||||||
log.error("Request failed:")
|
log_support.failure(failure, log, "Request failed. Id: %s, Failure: %s", id)
|
||||||
log.error(failure)
|
|
||||||
log.error(failure.value)
|
|
||||||
log.error(id)
|
|
||||||
if isinstance(failure.value, jsonrpclib.Fault):
|
if isinstance(failure.value, jsonrpclib.Fault):
|
||||||
return failure.value
|
return failure.value
|
||||||
return server.failure
|
return server.failure
|
||||||
|
|
|
@ -22,6 +22,7 @@ if not os.path.isfile(lbrycrdd_path_conf):
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
from lbrynet.lbrynet_daemon import DaemonControl
|
from lbrynet.lbrynet_daemon import DaemonControl
|
||||||
|
from lbrynet import analytics
|
||||||
from lbrynet.conf import settings
|
from lbrynet.conf import settings
|
||||||
from lbrynet.core import utils
|
from lbrynet.core import utils
|
||||||
|
|
||||||
|
@ -62,7 +63,10 @@ class LBRYDaemonApp(AppKit.NSApplication):
|
||||||
notify("LBRY needs an internet connection to start, try again when one is available")
|
notify("LBRY needs an internet connection to start, try again when one is available")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
DaemonControl.start_server_and_listen(launchui=True, use_auth=False)
|
DaemonControl.start_server_and_listen(
|
||||||
|
launchui=True, use_auth=False,
|
||||||
|
analytics_manager=analytics.Manager.new_instance()
|
||||||
|
)
|
||||||
|
|
||||||
def openui_(self, sender):
|
def openui_(self, sender):
|
||||||
webbrowser.open(settings.UI_ADDRESS)
|
webbrowser.open(settings.UI_ADDRESS)
|
||||||
|
|
|
@ -15,7 +15,7 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import win32gui
|
import win32gui
|
||||||
|
|
||||||
from lbrynet import conf
|
from lbrynet import conf, analytics
|
||||||
from lbrynet.core import log_support
|
from lbrynet.core import log_support
|
||||||
from lbrynet.core import utils
|
from lbrynet.core import utils
|
||||||
from lbrynet.lbrynet_daemon import DaemonControl
|
from lbrynet.lbrynet_daemon import DaemonControl
|
||||||
|
@ -267,7 +267,10 @@ def main(lbry_name=None):
|
||||||
systray_thread.daemon = True
|
systray_thread.daemon = True
|
||||||
systray_thread.start()
|
systray_thread.start()
|
||||||
|
|
||||||
DaemonControl.start_server_and_listen(launchui=True, use_auth=False)
|
DaemonControl.start_server_and_listen(
|
||||||
|
launchui=True, use_auth=False,
|
||||||
|
analytics_manager=analytics.Manager.new_instance()
|
||||||
|
)
|
||||||
reactor.run()
|
reactor.run()
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue