Skip to content

Instantly share code, notes, and snippets.

@pyhedgehog
Last active February 20, 2017 15:06
Show Gist options
  • Save pyhedgehog/99dae38d1cca86d6fb3ed0d6a4c3cab2 to your computer and use it in GitHub Desktop.
Save pyhedgehog/99dae38d1cca86d6fb3ed0d6a4c3cab2 to your computer and use it in GitHub Desktop.
# curl --data-urlencode source@- https://hook.io/marak/gateway-python <hooklog.py
import os
import sys
import logging
import json
import pkg_resources
import traceback
import random
# This is fake for flake8 and local run
try:
globals()['Hook']
except:
Hook = {'env': os.environ, 'req': {'params': {'hook':'gateway-python'}}}
debug_output = 'gateway' in Hook['req']['params']['hook']
prod_mode = Hook['resource'].get('mode','Development') == 'Production'
if debug_output:
sys.stderr = sys.stdout
class FullHookIOJSONFormatter(logging.Formatter):
def format(self, record):
record.message = record.getMessage()
if record.exc_info and not record.exc_text:
record.exc_text = self.formatException(record.exc_info)
record = record.__dict__.copy()
record['exc_info'] = None
try:
json.dumps(record['args'])
except Exception:
del record['args']
record['msg'] = record['message']
res = {'type': 'log', 'payload': {'entry': record}}
return json.dumps(res)
class SimpleHookIOJSONFormatter(logging.Formatter):
def format(self, record):
msg = logging.Formatter.format(self, record)
res = {'type': 'log', 'payload': {'entry': msg}}
return json.dumps(res)
class HookIOExceptHook:
def __init__(self, display=1, verbose=1):
self.display = display
self.verbose = verbose
def __call__(self, etype, evalue, etb):
self.handle((etype, evalue, etb))
def handle(self, info=None):
info = info or sys.exc_info()
code = info[0].__name__
if getattr(info[0], '__module__ ', None):
code = info[0].__module__ + '.' + code
payload = {'code': code}
if hasattr(info[1], 'args'):
payload['args'] = repr(info[1].args)
if self.verbose:
payload['error'] = ''.join(traceback.format_exception(*info))
else:
payload['error'] = str(info[1])
res = {'type': 'error', 'payload': payload}
if isinstance(info[1], ImportError) and info[1].message.startswith('No module named '):
payload['code'] = 'MODULE_NOT_FOUND'
payload['module'] = info[1].message.replace('No module named ', '')
if isinstance(info[1], (pkg_resources.VersionConflict, pkg_resources.DistributionNotFound)):
req = None
try:
if hasattr(info[1], 'req'):
req = info[1].req
# This is check for compatibility with old version of setuptools
if req is None:
for arg in info[1].args:
if isinstance(arg, pkg_resources.Requirement):
req = arg
except:
# unable to parse exception to requirement - it's ok
pass
if req is not None:
payload['code'] = 'MODULE_NOT_FOUND'
payload['module'] = str(req)
error = '%s(%s): %s' % (payload['code'], code, str(info[1]))
if self.verbose:
payload['error'] += error
else:
payload['error'] = error
sys.stderr.write(json.dumps(res)+'\n')
sys.stderr.flush()
sys.stderr.write(json.dumps({'type': 'statusCode', 'payload': {'value': 500}})+'\n')
sys.stderr.flush()
if self.display:
sys.stdout.write(payload['error'].rstrip('\n')+'\n')
sys.stdout.flush()
sys.stderr.write(json.dumps({'type': 'end'})+'\n')
sys.stderr.flush()
sys.exit(1)
def hookioLoggingConfig(level=None, format=None, datefmt=None):
logging._acquireLock()
try:
if len(logging.root.handlers) > 0:
return
hdlr = logging.StreamHandler(sys.stderr)
if format is None:
fmt = FullHookIOJSONFormatter()
else:
fmt = SimpleHookIOJSONFormatter(format, datefmt)
hdlr.setFormatter(fmt)
logging.root.addHandler(hdlr)
if level is not None:
logging.root.setLevel(level)
finally:
logging._releaseLock()
level = [logging.DEBUG, logging.INFO][prod_mode]
hookioLoggingConfig(level)
# hookioLoggingConfig(level, logging.BASIC_FORMAT)
sys.excepthook = HookIOExceptHook(debug_output, not prod_mode)
log = logging.getLogger('hooklog')
log.info('log = %s', log)
log.debug('debug')
log.info('info')
branch = str(Hook.get('params', {}).get('branch') or random.randint(0, 3))
print('branch='+branch)
sys.stdout.flush()
if branch == '1':
print('pkg = %r' % (pkg_resources.require("pip>=9999.0"),)) # Will raise unhandled VersionConflict
elif branch == '2':
print('pkg = %r' % (pkg_resources.require("inexistant-package"),)) # Will raise unhandled DistributionNotFound
elif branch == '3':
import inexistant_module # Will raise unhandled ImportError
sys.stdout.flush()
log.warn('warn')
log.error('error')
try:
1/0
except Exception:
log.exception('exception')
log.fatal('fatal')
head = {'type': 'writeHead', 'payload': {'code': 200, 'headers': {'content-type': 'text/plain'}}}
sys.stderr.write(json.dumps(head)+'\n')
sys.stderr.flush()
print('OK')
sys.stdout.flush()
sys.stderr.write(json.dumps({'type': 'end'})+'\n')
sys.stderr.flush()
@pyhedgehog
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment