lbry-sdk/lbry/extras/daemon/loggly_handler.py

96 lines
3 KiB
Python
Raw Normal View History

2019-01-22 15:43:03 +01:00
import asyncio
import json
import logging.handlers
import traceback
2020-01-03 07:39:34 +01:00
2020-02-20 18:27:39 +01:00
import typing
2020-01-03 07:39:34 +01:00
from aiohttp.client_exceptions import ClientError
2019-10-04 15:40:41 +02:00
import aiohttp
2019-06-21 02:55:47 +02:00
from lbry import utils, __version__
2020-02-20 18:27:39 +01:00
if typing.TYPE_CHECKING:
from lbry.conf import Config
2019-01-22 15:43:03 +01:00
2019-01-21 21:55:50 +01:00
LOGGLY_TOKEN = 'BQEzZmMzLJHgAGxkBF00LGD0YGuyATVgAmqxAQEuAQZ2BQH4'
2019-01-22 15:43:03 +01:00
class JsonFormatter(logging.Formatter):
"""Format log records using json serialization"""
def __init__(self, **kwargs):
2020-01-03 07:39:34 +01:00
super().__init__()
2019-01-22 15:43:03 +01:00
self.attributes = kwargs
def format(self, record):
data = {
'loggerName': record.name,
'asciTime': self.formatTime(record),
'fileName': record.filename,
'functionName': record.funcName,
'levelNo': record.levelno,
'lineNo': record.lineno,
'levelName': record.levelname,
'message': record.getMessage(),
}
data.update(self.attributes)
if record.exc_info:
data['exc_info'] = self.formatException(record.exc_info)
return json.dumps(data)
class HTTPSLogglyHandler(logging.Handler):
2020-02-20 18:35:57 +01:00
def __init__(self, loggly_token: str, config: 'Config'):
2019-01-22 15:43:03 +01:00
super().__init__()
2020-02-20 18:35:57 +01:00
self.cookies = {}
2019-01-22 15:43:03 +01:00
self.url = "https://logs-01.loggly.com/inputs/{token}/tag/{tag}".format(
token=utils.deobfuscate(loggly_token), tag='lbrynet-' + __version__
)
2019-10-04 15:40:41 +02:00
self._loop = asyncio.get_event_loop()
self._session = aiohttp.ClientSession()
2020-02-20 18:35:57 +01:00
self._config = config
2020-02-18 22:57:52 +01:00
@property
def enabled(self):
2020-02-20 18:35:57 +01:00
return self._config.share_usage_data
2019-01-22 15:43:03 +01:00
2020-01-03 07:39:34 +01:00
@staticmethod
def get_full_message(record):
2019-01-22 15:43:03 +01:00
if record.exc_info:
return '\n'.join(traceback.format_exception(*record.exc_info))
else:
return record.getMessage()
2019-10-04 15:40:41 +02:00
async def _emit(self, record, retry=True):
data = self.format(record).encode()
try:
2019-10-04 15:40:41 +02:00
async with self._session.post(self.url, data=data,
cookies=self.cookies) as response:
self.cookies.update(response.cookies)
except ClientError:
2020-02-18 22:57:52 +01:00
if self._loop.is_running() and retry and self.enabled:
2019-10-04 15:40:41 +02:00
await self._session.close()
self._session = aiohttp.ClientSession()
return await self._emit(record, retry=False)
2019-01-22 15:43:03 +01:00
def emit(self, record):
2020-02-18 22:57:52 +01:00
if not self.enabled:
return
try:
asyncio.ensure_future(self._emit(record), loop=self._loop)
except RuntimeError: # TODO: use a second loop
print(f"\nfailed to send traceback to loggly, please file an issue with the following traceback:\n"
f"{self.format(record)}")
2019-01-22 15:43:03 +01:00
def close(self):
super().close()
try:
loop = asyncio.get_event_loop()
loop.run_until_complete(self._session.close())
except RuntimeError:
pass
2019-01-22 15:43:03 +01:00
2020-02-20 18:27:39 +01:00
def get_loggly_handler(config):
handler = HTTPSLogglyHandler(LOGGLY_TOKEN, config=config)
2019-01-22 15:43:03 +01:00
handler.setFormatter(JsonFormatter())
return handler