def report_exception(exc, env=None, extra=None): if extra is None: extra = {} formatted = format_exception(exc, env, extra) if isinstance(exc, tuple): 'pick an exception from the tuple (type, value, traceback)' exc = exc[1] if not get_config('NOODLES_SEND_FULL_MAIL'): send_email(repr(exc), formatted, with_hostname=True, is_html=False) return subject = repr(exc) report = '' try: subject = repr(exc) report = _collect(exc) report = HTMLFormatter().format(report, maxdepth=4) except exceptions.MakoException: error = exceptions.text_error_template().render() formatted += '\nTemplate rendering error ' + error log.error(error) attachments = None if report: attachments = { 'report.html': report, } send_email(subject, formatted, with_hostname=True, attachments=attachments, is_html=False)
def run_callback(self, obj, args=None): try: assert hasattr(self, 'on%s' % obj) f = getattr(self, 'on%s' % obj) if args is not None: return f(args) else: return f() except WebSocketError as e: if is_ws_error_abnormal(e): log.warn('WebSocket fault: %s' % e.message) log.error(format_exception(e, None), extra=self.channel_history) report_exception(e, extra=self.channel_history) except Exception as e: self.onerror(e) if not self.ws.closed: try: self.ws.close() except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history) finally: if USE_ALCHEMY_MW: session_handler.close()
def onerror(self, e): """Send here Exception and traceback by Error channel """ f = Formatter() history = json.dumps(self.channel_history, indent=2, default=datahandler) data = (history, xml_escape(f.formatException(sys.exc_info())),) if EXCEPTION_FLAVOR == 'html': traceback = '<pre>%s\n\n%s</pre>' % data else: traceback = '%s\n%s' % data if DEBUG: err_message = {'channel': WS_CHANNELS['ERROR_CHID'], 'pkg': {'exception': repr(e), 'tb': traceback}} else: err_message = {'channel': WS_CHANNELS['ERROR_CHID'], 'pkg': {'exception': 'error 500', 'tb': 'an error occurred'}} log.error(format_exception(e, None), extra=self.channel_history) report_exception(e, extra=self.channel_history) if not self.ws.closed: try: self.ws.send(json.dumps(err_message, separators=(', ', ':'))) except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history)
def run_callback(self, obj, args=None): try: assert hasattr(self, 'on%s' % obj) f = getattr(self, 'on%s' % obj) if args is not None: return f(args) else: return f() except WebSocketError as e: if is_ws_error_abnormal(e): log.warn('WebSocket fault: %s' % e.message) log.error(format_exception(e, None), extra=self.channel_history) report_exception(e, extra=self.channel_history) except Exception as e: self.onerror(e) if not self.ws.closed: try: self.ws.close() except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history) finally: if USE_ALCHEMY_MW: session_handler.close()
def __call__(self): try: return self.callable() except Exception as e: log.error(format_exception(e, None)) report_exception(e) data = {'error': 0, 'message': e.message} return XResponse(data)
def safe_exec(self, fn): """ Must never fall """ try: fn() except Exception as e: log.error(e)
def channel_404(self, channel): try: return self.ws.send(json.dumps({'channel': channel, 'action': 'no-such-channel', 'note': 'Channel with ID=%s not ' 'found' % channel, })) except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history)
def noodlesapp(env, start_response): """ :rtype : noodles.http.Response :param env: :param start_response: :return: :rtype: :raise: """ # Get request object if get_config('ENCODE_SEMICOLON_IN_REQUEST') is True: env['QUERY_STRING'] = re.sub('[;]', '%3b', env['QUERY_STRING']) request = Request(env) if "HTTP_X_FORWARDED_FOR" in env: x_forwarded_for = env["HTTP_X_FORWARDED_FOR"].split(',')[:1] if x_forwarded_for: request.remote_addr = x_forwarded_for[0] #print("Try to handle url_path '%s'" % request.path) # Get callable object with routine method to handle request producer = dispatcher.get_callable(request) if not producer: # May be here an error,raise exception raise Exception('Can\'t find callable for this url path') # Callable function must return Response object try: response = middlewares.run_chain(producer, request) if not hasattr(response, 'is_noodles_response'): response = producer() # Capture traceback here and send it if debug mode except Exception as e: f = Formatter() if EXCEPTION_FLAVOR=='html': traceback = '<pre>%s\n\n%s</pre>' \ % (json.dumps(env, indent=2, default=datahandler), xml_escape(f.formatException(sys.exc_info()))) else: traceback = '%s\n%s' \ % (json.dumps(env, indent=2, default=datahandler), f.formatException(sys.exc_info())) extra = {'request': request} log.error(format_exception(e, None), extra=extra) report_exception(e, extra=extra) if DEBUG: response = Error500(e, traceback) else: response = Error500() finally: middlewares.end_chain(lambda x: x, request) return response(env, start_response)
def noodlesapp(env, start_response): """ :rtype : noodles.http.Response :param env: :param start_response: :return: :rtype: :raise: """ # Get request object if get_config('ENCODE_SEMICOLON_IN_REQUEST') is True: env['QUERY_STRING'] = re.sub('[;]', '%3b', env['QUERY_STRING']) request = Request(env) if "HTTP_X_FORWARDED_FOR" in env: x_forwarded_for = env["HTTP_X_FORWARDED_FOR"].split(',')[:1] if x_forwarded_for: request.remote_addr = x_forwarded_for[0] #print("Try to handle url_path '%s'" % request.path) # Get callable object with routine method to handle request producer = dispatcher.get_callable(request) if not producer: # May be here an error,raise exception raise Exception('Can\'t find callable for this url path') # Callable function must return Response object try: response = middlewares.run_chain(producer, request) if not hasattr(response, 'is_noodles_response'): response = producer() # Capture traceback here and send it if debug mode except Exception as e: f = Formatter() if EXCEPTION_FLAVOR=='html': traceback = '<pre>%s\n\n%s</pre>' \ % (json.dumps(env, indent=2, default=datahandler), xml_escape(f.formatException(sys.exc_info()))) else: traceback = '%s\n%s' \ % (json.dumps(env, indent=2, default=datahandler), f.formatException(sys.exc_info())) extra = {'request': request} log.error(format_exception(e, None), extra=extra) report_exception(e, extra=extra) if DEBUG: response = Error500(e, traceback) else: response = Error500() finally: middlewares.end_chain(lambda x: x, request) return response(env, start_response)
def channel_404(self, channel): try: return self.ws.send( json.dumps({ 'channel': channel, 'action': 'no-such-channel', 'note': 'Channel with ID=%s not ' 'found' % channel, })) except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history)
def worker(n): cli = bernhard.Client(**RIEMANN_ARGS) while True: try: target, metric = RIEMANN_QUEUE.get() target = target.partition('?')[0] target = target.replace('/', '.') event = {'service': target, 'metric': metric} event.update(RIEMANN_SOURCE) result = cli.send(event=event) log.debug("Sent %s result %s", target, result) except Exception as e: log.error(e)
def __init__(self, data): if type(data) == dict: self.data = data return # TODO: check lib: https://bitbucket.org/Jeffrey/gevent-websocket/ # issue/5/encoding-issue-when-sending-non-ascii self.raw_data = str(data.decode('utf-8')).encode(ENCODING) try: self.data = json.loads(self.raw_data) except ApiSocketError as e: self.data = self.raw_data extra = {'request': self.data} log.error(format_exception(e, None), extra=extra) report_exception(e, extra=extra)
def send_error_code(self, code, act, channel): if not self.ws.closed: try: self.ws.send(json.dumps({'pkg': {'action': act, 'data': {'channel': channel, 'result': code, }, }, })) self.ws.close() except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history)
def bad_request(self, message="Bad request"): if not self.ws.closed: try: self.ws.send( json.dumps({'pkg': {'action': 'open', 'data': {'result': 400, 'message': message, }, }, })) except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history)
def __init__(self, data): if type(data) == dict: self.data = data return # TODO: check lib: https://bitbucket.org/Jeffrey/gevent-websocket/ # issue/5/encoding-issue-when-sending-non-ascii self.raw_data = str(data.decode('utf-8')).encode(ENCODING) try: self.data = json.loads(self.raw_data) except ApiSocketError as e: self.data = self.raw_data extra = {'request': self.data} log.error(format_exception(e, None), extra=extra) report_exception(e, extra=extra)
def worker(n): cli = bernhard.Client(**RIEMANN_ARGS) while True: try: target, metric = RIEMANN_QUEUE.get() target = target.partition('?')[0] target = target.replace('/', '.') event = {'service': target, 'metric': metric} event.update(RIEMANN_SOURCE) result = cli.send(event=event) log.debug("Sent %s result %s", target, result) except Exception as e: log.error(e)
def close(self, data): if not data.get('channel'): raise Exception('No channel name, exit') handler = self.channel_handlers.get(data['channel']) if not handler: return self.channel_404(data['channel']) if self.check_permissions and not self.validate_close(data['channel']): return self.send_error_code(403, 'open', data['channel']) if not handler.closable and not self.ws.closed: try: self.ws.send( json.dumps({ 'pkg': { 'action': 'close', 'data': { 'channel': data['channel'], 'result': 501 }, }, })) except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history) return handler.onclose() del self.channel_handlers[data['channel']] if not self.ws.closed: try: self.ws.send( json.dumps({ 'pkg': { 'action': 'close', 'data': { 'channel': data['channel'], 'result': 200 }, }, })) except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history)
def _send_ws(self, data): if type(data) != dict: raise TypeError("data is %s not dict" % type(data)) package_to_send = {'channel': self.channel, 'pkg': data, 'session_params': self.session.params, } data = json.dumps(package_to_send, default=datahandler) try: self.ws.send(data) except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history) self.onclose()
def _send_ws(self, data): if type(data) != dict: raise TypeError("data is %s not dict" % type(data)) package_to_send = { 'channel': self.channel, 'pkg': data, 'session_params': self.session.params, } data = json.dumps(package_to_send, default=datahandler) try: self.ws.send(data) except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history) self.onclose()
def bad_request(self, message="Bad request"): if not self.ws.closed: try: self.ws.send( json.dumps({ 'pkg': { 'action': 'open', 'data': { 'result': 400, 'message': message, }, }, })) except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history)
def open(self, data): self.propagate_greenlet_data(data) if not data.get('token'): self.bad_request(message='No access token, exit') return if not data.get('channel'): self.bad_request(message='No channel name') return self.access_token = data.get('token') self.reopen = data.get('reopen', False) self.pre_open() handler = self.allowed_channels.get(data.get('channel')) if not handler: return self.channel_404(data['channel']) if self.check_permissions \ and not self.validate_open(data.get('channel')): return self.send_error_code(403, 'open', data.get('channel')) if not self.is_auth: return self.send_error_code(403, 'open', data.get('channel')) handler = self.register_channel(data.get('channel'), handler) self.run_callback('open') pkg = { 'action': 'open', 'data': { 'closable': handler.closable, 'result': 200 }, } package_to_send = { 'channel': data.get('channel'), 'pkg': pkg, 'session_params': self.session.params } raw_data = json.dumps(package_to_send, default=datahandler) self.after_open() try: self.ws.send(raw_data) except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history)
def send_error_code(self, code, act, channel): if not self.ws.closed: try: self.ws.send( json.dumps({ 'pkg': { 'action': act, 'data': { 'channel': channel, 'result': code, }, }, })) self.ws.close() except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history)
def close(self, data): if not data.get('channel'): raise Exception('No channel name, exit') handler = self.channel_handlers.get(data['channel']) if not handler: return self.channel_404(data['channel']) if self.check_permissions and not self.validate_close(data['channel']): return self.send_error_code(403, 'open', data['channel']) if not handler.closable and not self.ws.closed: try: self.ws.send( json.dumps({'pkg': {'action': 'close', 'data': {'channel': data['channel'], 'result': 501}, }, })) except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history) return handler.onclose() del self.channel_handlers[data['channel']] if not self.ws.closed: try: self.ws.send( json.dumps({'pkg': {'action': 'close', 'data': {'channel': data['channel'], 'result': 200}, }, })) except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history)
def open(self, data): self.propagate_greenlet_data(data) if not data.get('token'): self.bad_request(message='No access token, exit') return if not data.get('channel'): self.bad_request(message='No channel name') return self.access_token = data.get('token') self.reopen = data.get('reopen', False) self.pre_open() handler = self.allowed_channels.get(data.get('channel')) if not handler: return self.channel_404(data['channel']) if self.check_permissions \ and not self.validate_open(data.get('channel')): return self.send_error_code(403, 'open', data.get('channel')) if not self.is_auth: return self.send_error_code(403, 'open', data.get('channel')) handler = self.register_channel(data.get('channel'), handler) self.run_callback('open') pkg = {'action': 'open', 'data': {'closable': handler.closable, 'result': 200}, } package_to_send = {'channel': data.get('channel'), 'pkg': pkg, 'session_params': self.session.params} raw_data = json.dumps(package_to_send, default=datahandler) self.after_open() try: self.ws.send(raw_data) except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history)
def onerror(self, e): """Send here Exception and traceback by Error channel """ f = Formatter() history = json.dumps(self.channel_history, indent=2, default=datahandler) data = ( history, xml_escape(f.formatException(sys.exc_info())), ) if EXCEPTION_FLAVOR == 'html': traceback = '<pre>%s\n\n%s</pre>' % data else: traceback = '%s\n%s' % data if DEBUG: err_message = { 'channel': WS_CHANNELS['ERROR_CHID'], 'pkg': { 'exception': repr(e), 'tb': traceback } } else: err_message = { 'channel': WS_CHANNELS['ERROR_CHID'], 'pkg': { 'exception': 'error 500', 'tb': 'an error occurred' } } log.error(format_exception(e, None), extra=self.channel_history) report_exception(e, extra=self.channel_history) if not self.ws.closed: try: self.ws.send(json.dumps(err_message, separators=(', ', ':'))) except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history)
def basic_report_exception(exc, env=None, msg=''): formatted = format_exception(exc, env, msg) log.error(formatted) send_email(repr(exc), formatted, with_hostname=True, is_html=False)
def __call__(self, env, start_response): websocket = env.get('wsgi.websocket') if not websocket: self.bad_request() self.ws = websocket # Endless event loop while 1: try: data = self.ws.receive() self.clear_test_data() except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history) break except Exception: f = Formatter() traceback = f.formatException(sys.exc_info()) log.error('Servlet fault: \n%s' % traceback, extra=self.channel_history) break if data: jd = json.loads(data) if jd.get('pkg') \ and jd['pkg'].get('data') \ and isinstance(jd['pkg']['data'], dict)\ and jd['pkg']['data'].get('testData'): self.write_test_data(jd['pkg']['data']['testData']) del jd['pkg']['data']['testData'] self.channel_history['messages'].append(jd) if hasattr(self.session, 'sess') and self.session.sess: self.channel_history['session_id'] = self.session.sess.id self.channel_history['user_id'] = self.session.sess.user_id if not jd.get('channel') and jd.get('pkg'): act = jd['pkg'].get('action') assert not act.startswith('_'), "security violation" try: handler = getattr(self, act) except WebSocketError as e: if is_ws_error_abnormal(e): f = Formatter() traceback = f.formatException(sys.exc_info()) log.error('Global channel action error: \n%s' % traceback, extra=self.channel_history) break assert handler.__name__ == "action_wrapper", \ "%s is not allowed to be executed externally." % act handler(jd['pkg']['data']) continue if self.check_permissions \ and not self.validate_send(jd.get('channel')): jd['result'] = 403 if not self.ws.closed: try: self.ws.send(json.dumps(jd)) except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history) continue else: self.run_callback('message', ApiSocketMessage(data)) else: log.debug('Web Socket is disconnected') self.close_event.set() if self.close_event.is_set(): break self.run_callback('close')
def __call__(self, env, start_response): websocket = env.get('wsgi.websocket') if not websocket: self.bad_request() self.ws = websocket # Endless event loop while 1: try: data = self.ws.receive() self.clear_test_data() except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history) break except Exception: f = Formatter() traceback = f.formatException(sys.exc_info()) log.error('Servlet fault: \n%s' % traceback, extra=self.channel_history) break if data: jd = json.loads(data) if jd.get('pkg') \ and jd['pkg'].get('data') \ and isinstance(jd['pkg']['data'], dict)\ and jd['pkg']['data'].get('testData'): self.write_test_data(jd['pkg']['data']['testData']) del jd['pkg']['data']['testData'] self.channel_history['messages'].append(jd) if hasattr(self.session, 'sess') and self.session.sess: self.channel_history['session_id'] = self.session.sess.id self.channel_history['user_id'] = self.session.sess.user_id if not jd.get('channel') and jd.get('pkg'): act = jd['pkg'].get('action') assert not act.startswith('_'), "security violation" try: handler = getattr(self, act) except WebSocketError as e: if is_ws_error_abnormal(e): f = Formatter() traceback = f.formatException(sys.exc_info()) log.error('Global channel action error: \n%s' % traceback, extra=self.channel_history) break assert handler.__name__ == "action_wrapper", \ "%s is not allowed to be executed externally." % act handler(jd['pkg']['data']) continue if self.check_permissions \ and not self.validate_send(jd.get('channel')): jd['result'] = 403 if not self.ws.closed: try: self.ws.send(json.dumps(jd)) except WebSocketError as e: if is_ws_error_abnormal(e): log.error('WebSocket fault: %s' % e.message, extra=self.channel_history) continue else: self.run_callback('message', ApiSocketMessage(data)) else: log.debug('Web Socket is disconnected') self.close_event.set() if self.close_event.is_set(): break self.run_callback('close')