diff --git a/blockstack_client/config.py b/blockstack_client/config.py index 62271f12a..bc4d7e88d 100644 --- a/blockstack_client/config.py +++ b/blockstack_client/config.py @@ -33,6 +33,7 @@ import urllib2 import copy import time import shutil +import requests from binascii import hexlify from ConfigParser import SafeConfigParser @@ -41,11 +42,92 @@ import virtualchain from .backend.utxo import * from .constants import * + +class NetworkLogFormatter( logging.Formatter ): + """ + Log formatter for network endpoints, such as Blockstack Portal + """ + level_names = { + logging.DEBUG: 'DEBUG', + logging.INFO: 'INFO', + logging.WARN: 'WARN', + logging.ERROR: 'ERROR', + logging.FATAL: 'FATAL' + } + + def format(self, record): + data = { + 'time': int(time.time()), + 'level': NetworkLogFormatter.level_names.get(record.levelno, 'TRACE'), + 'category': os.path.basename(record.pathname), + 'message': record.msg, + } + return data + + + +class NetworkLogHandler( logging.Handler ): + """ + Log handler for network endpoints, such as Blockstack Portal + """ + def config(self, url, authorization): + self.authorization = authorization + self.url = url + + def emit(self, record): + log_entry = self.format(record) + headers = { + 'Authorization': self.authorization + } + + try: + requests.post(self.url, json=log_entry, headers=headers, timeout=1.0) + except: + pass + + +def get_network_log_handler(api_password=None, name=None, scheme="http", host="localhost", port=LOG_NETWORK_PORT): + """ + Get a log handler to sending messages over the network. + """ + + level = logging.CRITICAL + if DEBUG: + logging.disable(logging.NOTSET) + level = logging.DEBUG + + if name is None: + name = "" + level = logging.CRITICAL + + if api_password is None: + api_password = get_secret("BLOCKSTACK_API_PASSWORD") + if api_password is None: + return None + + url = "{}://{}:{}".format(scheme, host, port) + authorization = 'bearer {}'.format(api_password) + network = NetworkLogHandler() + network.config(url, authorization) + network.setLevel( level ) + formatter = NetworkLogFormatter() + network.setFormatter(formatter) + network.propagate = False + + return network + + def get_logger(name="blockstack-client", debug=DEBUG): logger = virtualchain.get_logger(name) logger.setLevel(logging.DEBUG if debug else logging.INFO) + + network_logger = get_network_log_handler(name=name) + if network_logger: + logger.addHandler(network_logger) + return logger + log = get_logger('blockstack-client') # NOTE: duplicated from blockstack-core and streamlined. diff --git a/blockstack_client/constants.py b/blockstack_client/constants.py index f744c2dc5..624c2885e 100644 --- a/blockstack_client/constants.py +++ b/blockstack_client/constants.py @@ -66,6 +66,8 @@ DEFAULT_BLOCKSTACKD_SERVER = 'node.blockstack.org' DEFAULT_API_PORT = 6270 # API endpoint port +LOG_NETWORK_PORT = 8333 # port to send log messages on (e.g. to Portal) + # initialize to default settings BLOCKSTACKD_SERVER = DEFAULT_BLOCKSTACKD_SERVER BLOCKSTACKD_PORT = DEFAULT_BLOCKSTACKD_PORT