Merge branch 'master' of github.com:getsentry/raven-python
This commit is contained in:
commit
69940fc47c
|
@ -4,6 +4,8 @@ python:
|
|||
- "2.7"
|
||||
- "3.2"
|
||||
- "3.3"
|
||||
- "3.4"
|
||||
- "pypy"
|
||||
env:
|
||||
matrix:
|
||||
- DJANGO=Django==1.4.10
|
||||
|
@ -46,6 +48,8 @@ matrix:
|
|||
env: DJANGO=Django==1.4.10
|
||||
- python: "3.3"
|
||||
env: DJANGO=Django==1.4.10
|
||||
- python: "3.4"
|
||||
env: DJANGO=Django==1.4.10
|
||||
- python: "2.6"
|
||||
env: DJANGO="-e git+git://github.com/django/django.git#egg=Django"
|
||||
- python: "2.6"
|
||||
|
|
6
CHANGES
6
CHANGES
|
@ -1,3 +1,9 @@
|
|||
Version 5.0.0
|
||||
-------------
|
||||
|
||||
* Sentry client protocol is now version 5.
|
||||
* Various improvements to threaded transport.
|
||||
|
||||
Version 4.2.0
|
||||
-------------
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ Add the following lines to your project's `.ini` file to setup `SentryHandler`:
|
|||
|
||||
[handler_sentry]
|
||||
class = raven.handlers.logging.SentryHandler
|
||||
args = ('SENTRY_DSN')
|
||||
args = ('SENTRY_DSN',)
|
||||
level = NOTSET
|
||||
formatter = generic
|
||||
|
||||
|
|
|
@ -115,17 +115,19 @@ class Client(object):
|
|||
>>> print "Exception caught; reference is %s" % ident
|
||||
"""
|
||||
logger = logging.getLogger('raven')
|
||||
protocol_version = '4'
|
||||
protocol_version = '5'
|
||||
|
||||
_registry = TransportRegistry(transports=default_transports)
|
||||
|
||||
def __init__(self, dsn=None, **options):
|
||||
def __init__(self, dsn=None, raise_send_errors=False, **options):
|
||||
global Raven
|
||||
|
||||
o = options
|
||||
|
||||
self.configure_logging()
|
||||
|
||||
self.raise_send_errors = raise_send_errors
|
||||
|
||||
# configure loggers first
|
||||
cls = self.__class__
|
||||
self.state = ClientState()
|
||||
|
@ -296,7 +298,7 @@ class Client(object):
|
|||
if k not in data:
|
||||
data[k] = v
|
||||
|
||||
if stack and 'sentry.interfaces.Stacktrace' not in data:
|
||||
if stack and 'stacktrace' not in data:
|
||||
if stack is True:
|
||||
frames = iter_stack_frames()
|
||||
|
||||
|
@ -309,12 +311,12 @@ class Client(object):
|
|||
capture_locals=self.capture_locals,
|
||||
)
|
||||
data.update({
|
||||
'sentry.interfaces.Stacktrace': stack_info,
|
||||
'stacktrace': stack_info,
|
||||
})
|
||||
|
||||
if 'sentry.interfaces.Stacktrace' in data:
|
||||
if 'stacktrace' in data:
|
||||
if self.include_paths:
|
||||
for frame in data['sentry.interfaces.Stacktrace']['frames']:
|
||||
for frame in data['stacktrace']['frames']:
|
||||
if frame.get('in_app') is not None:
|
||||
continue
|
||||
|
||||
|
@ -332,10 +334,12 @@ class Client(object):
|
|||
)
|
||||
|
||||
if not culprit:
|
||||
if 'sentry.interfaces.Stacktrace' in data:
|
||||
culprit = get_culprit(data['sentry.interfaces.Stacktrace']['frames'])
|
||||
elif data.get('sentry.interfaces.Exception', {}).get('stacktrace'):
|
||||
culprit = get_culprit(data['sentry.interfaces.Exception']['stacktrace']['frames'])
|
||||
if 'stacktrace' in data:
|
||||
culprit = get_culprit(data['stacktrace']['frames'])
|
||||
elif 'exception' in data:
|
||||
stacktrace = data['exception']['values'][0].get('stacktrace')
|
||||
if stacktrace:
|
||||
culprit = get_culprit(stacktrace['frames'])
|
||||
|
||||
if not data.get('level'):
|
||||
data['level'] = kwargs.get('level') or logging.ERROR
|
||||
|
@ -407,7 +411,7 @@ class Client(object):
|
|||
>>> client.user_context({'email': 'foo@example.com'})
|
||||
"""
|
||||
return self.context.merge({
|
||||
'sentry.interfaces.User': data,
|
||||
'user': data,
|
||||
})
|
||||
|
||||
def http_context(self, data, **kwargs):
|
||||
|
@ -417,7 +421,7 @@ class Client(object):
|
|||
>>> client.http_context({'url': 'http://example.com'})
|
||||
"""
|
||||
return self.context.merge({
|
||||
'sentry.interfaces.Http': data,
|
||||
'request': data,
|
||||
})
|
||||
|
||||
def extra_context(self, data, **kwargs):
|
||||
|
@ -448,7 +452,7 @@ class Client(object):
|
|||
To use structured data (interfaces) with capture:
|
||||
|
||||
>>> capture('raven.events.Message', message='foo', data={
|
||||
>>> 'sentry.interfaces.Http': {
|
||||
>>> 'request': {
|
||||
>>> 'url': '...',
|
||||
>>> 'data': {},
|
||||
>>> 'query_string': '...',
|
||||
|
@ -546,9 +550,12 @@ class Client(object):
|
|||
self.state.set_fail(retry_after=retry_after)
|
||||
|
||||
def send_remote(self, url, data, headers=None):
|
||||
# If the client is configured to raise errors on sending,
|
||||
# the implication is that the backoff and retry strategies
|
||||
# will be handled by the calling application
|
||||
if headers is None:
|
||||
headers = {}
|
||||
if not self.state.should_try():
|
||||
if not self.raise_send_errors and not self.state.should_try():
|
||||
message = self._get_log_message(data)
|
||||
self.error_logger.error(message)
|
||||
return
|
||||
|
@ -569,6 +576,8 @@ class Client(object):
|
|||
transport.send(data, headers)
|
||||
self._successful_send()
|
||||
except Exception as e:
|
||||
if self.raise_send_errors:
|
||||
raise
|
||||
failed_send(e)
|
||||
|
||||
def send(self, auth_header=None, **data):
|
||||
|
|
|
@ -62,4 +62,9 @@ PROCESSORS = (
|
|||
# Default Project ID
|
||||
PROJECT = 1
|
||||
|
||||
CA_BUNDLE = os.path.join(ROOT, 'data', 'cacert.pem')
|
||||
try:
|
||||
# Try for certifi first since they likely keep their bundle more up to date
|
||||
import certifi
|
||||
CA_BUNDLE = certifi.where()
|
||||
except ImportError:
|
||||
CA_BUNDLE = os.path.join(ROOT, 'data', 'cacert.pem')
|
||||
|
|
|
@ -26,4 +26,4 @@ class AsyncClient(Client):
|
|||
super(AsyncClient, self).send(**kwargs)
|
||||
|
||||
def send(self, **kwargs):
|
||||
self.worker.queue(self.send_sync, kwargs)
|
||||
self.worker.queue(self.send_sync, **kwargs)
|
||||
|
|
|
@ -26,7 +26,7 @@ def get_data_from_request(request):
|
|||
formdata = {}
|
||||
|
||||
data = {
|
||||
'sentry.interfaces.Http': {
|
||||
'request': {
|
||||
'url': '%s://%s%s' % (urlparts.scheme, urlparts.netloc, urlparts.path),
|
||||
'query_string': urlparts.query,
|
||||
'method': request.method,
|
||||
|
|
|
@ -58,7 +58,7 @@ class DjangoClient(Client):
|
|||
result = {}
|
||||
|
||||
if hasattr(request, 'user') and isinstance(request.user, BaseUser):
|
||||
result['sentry.interfaces.User'] = self.get_user_info(request.user)
|
||||
result['user'] = self.get_user_info(request.user)
|
||||
|
||||
try:
|
||||
uri = request.build_absolute_uri()
|
||||
|
@ -90,7 +90,7 @@ class DjangoClient(Client):
|
|||
environ = request.META
|
||||
|
||||
result.update({
|
||||
'sentry.interfaces.Http': {
|
||||
'request': {
|
||||
'method': request.method,
|
||||
'url': uri,
|
||||
'query_string': request.META.get('QUERY_STRING'),
|
||||
|
@ -106,10 +106,11 @@ class DjangoClient(Client):
|
|||
def build_msg(self, *args, **kwargs):
|
||||
data = super(DjangoClient, self).build_msg(*args, **kwargs)
|
||||
|
||||
stacks = (
|
||||
data.get('sentry.interfaces.Stacktrace'),
|
||||
data.get('sentry.interfaces.Exception', {}).get('stacktrace'),
|
||||
)
|
||||
stacks = [
|
||||
data.get('stacktrace'),
|
||||
]
|
||||
if 'exception' in data:
|
||||
stacks.append(data['exception']['values'][0]['stacktrace'])
|
||||
|
||||
for stacktrace in filter(bool, stacks):
|
||||
for frame in stacktrace['frames']:
|
||||
|
@ -181,6 +182,8 @@ class DjangoClient(Client):
|
|||
try:
|
||||
return self.send_integrated(kwargs)
|
||||
except Exception as e:
|
||||
if self.raise_send_errors:
|
||||
raise
|
||||
self.error_logger.error(
|
||||
'Unable to record event: %s\nEvent was: %r', e,
|
||||
kwargs['message'], exc_info=True)
|
||||
|
|
|
@ -142,7 +142,7 @@ def get_client(client=None):
|
|||
class_name = str(class_name)
|
||||
|
||||
try:
|
||||
instance = getattr(__import__(module, {}, {}, class_name), class_name)(**options)
|
||||
Client = getattr(__import__(module, {}, {}, class_name), class_name)
|
||||
except ImportError:
|
||||
logger.exception('Failed to import client: %s', client)
|
||||
if not _client[1]:
|
||||
|
@ -150,6 +150,7 @@ def get_client(client=None):
|
|||
client = 'raven.contrib.django.DjangoClient'
|
||||
_client = (client, get_client(client))
|
||||
else:
|
||||
instance = Client(**options)
|
||||
if not tmp_client:
|
||||
_client = (client, instance)
|
||||
return instance
|
||||
|
|
|
@ -41,7 +41,7 @@ def get_data_from_template(source):
|
|||
context_line = source_lines[lineno]
|
||||
|
||||
return {
|
||||
'sentry.interfaces.Template': {
|
||||
'template': {
|
||||
'filename': origin.loadname,
|
||||
'abs_path': origin.name,
|
||||
'pre_context': pre_context,
|
||||
|
|
|
@ -207,11 +207,17 @@ class Sentry(object):
|
|||
def captureException(self, *args, **kwargs):
|
||||
assert self.client, 'captureException called before application configured'
|
||||
result = self.client.captureException(*args, **kwargs)
|
||||
self.last_event_id = self.client.get_ident(result)
|
||||
if result:
|
||||
self.last_event_id = self.client.get_ident(result)
|
||||
else:
|
||||
self.last_event_id = None
|
||||
return result
|
||||
|
||||
def captureMessage(self, *args, **kwargs):
|
||||
assert self.client, 'captureMessage called before application configured'
|
||||
result = self.client.captureMessage(*args, **kwargs)
|
||||
self.last_event_id = self.client.get_ident(result)
|
||||
if result:
|
||||
self.last_event_id = self.client.get_ident(result)
|
||||
else:
|
||||
self.last_event_id = None
|
||||
return result
|
||||
|
|
|
@ -183,7 +183,7 @@ class SentryMixin(object):
|
|||
:param return: A dictionary.
|
||||
"""
|
||||
return {
|
||||
'sentry.interfaces.Http': {
|
||||
'request': {
|
||||
'url': self.request.full_url(),
|
||||
'method': self.request.method,
|
||||
'data': self.request.body,
|
||||
|
@ -202,7 +202,7 @@ class SentryMixin(object):
|
|||
Truth calue testing
|
||||
"""
|
||||
return {
|
||||
'sentry.interfaces.User': {
|
||||
'user': {
|
||||
'is_authenticated': True if self.get_current_user() else False
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ from raven.utils.wsgi import get_headers, get_environ
|
|||
def get_data_from_request():
|
||||
"""Returns request data extracted from web.ctx."""
|
||||
return {
|
||||
'sentry.interfaces.Http': {
|
||||
'request': {
|
||||
'url': '%s://%s%s' % (web.ctx['protocol'], web.ctx['host'], web.ctx['path']),
|
||||
'query_string': web.ctx.query,
|
||||
'method': web.ctx.method,
|
||||
|
|
|
@ -86,9 +86,8 @@ class ZopeSentryHandler(SentryHandler):
|
|||
http['headers']['User-Agent'] = \
|
||||
http['headers']['HTTP_USER_AGENT']
|
||||
if 'QUERY_STRING' in http['headers']:
|
||||
http['query_string'] = http['headers'
|
||||
]['QUERY_STRING']
|
||||
setattr(record, 'sentry.interfaces.Http', http)
|
||||
http['query_string'] = http['headers']['QUERY_STRING']
|
||||
setattr(record, 'request', http)
|
||||
user = request.get('AUTHENTICATED_USER', None)
|
||||
if user is not None:
|
||||
user_dict = dict(id=user.getId(),
|
||||
|
@ -96,7 +95,7 @@ class ZopeSentryHandler(SentryHandler):
|
|||
email=user.getProperty('email') or '')
|
||||
else:
|
||||
user_dict = {'is_authenticated': False}
|
||||
setattr(record, 'sentry.interfaces.User', user_dict)
|
||||
setattr(record, 'user', user_dict)
|
||||
except (AttributeError, KeyError):
|
||||
logger.warning('Could not extract data from request', exc_info=True)
|
||||
return super(ZopeSentryHandler, self).emit(record)
|
||||
|
|
|
@ -41,9 +41,10 @@ class Exception(BaseEvent):
|
|||
- module '__builtin__' (i.e. __builtin__.TypeError)
|
||||
- frames: a list of serialized frames (see _get_traceback_frames)
|
||||
"""
|
||||
name = 'exception'
|
||||
|
||||
def to_string(self, data):
|
||||
exc = data['sentry.interfaces.Exception']
|
||||
exc = data[self.name]['values'][0]
|
||||
if exc['value']:
|
||||
return '%s: %s' % (exc['type'], exc['value'])
|
||||
return exc['type']
|
||||
|
@ -71,11 +72,13 @@ class Exception(BaseEvent):
|
|||
|
||||
return {
|
||||
'level': kwargs.get('level', logging.ERROR),
|
||||
'sentry.interfaces.Exception': {
|
||||
'value': to_unicode(exc_value),
|
||||
'type': str(exc_type),
|
||||
'module': to_unicode(exc_module),
|
||||
'stacktrace': stack_info,
|
||||
self.name: {
|
||||
'values': [{
|
||||
'value': to_unicode(exc_value),
|
||||
'type': str(exc_type),
|
||||
'module': to_unicode(exc_module),
|
||||
'stacktrace': stack_info,
|
||||
}],
|
||||
},
|
||||
}
|
||||
finally:
|
||||
|
@ -92,10 +95,12 @@ class Message(BaseEvent):
|
|||
- message: 'My message from %s about %s'
|
||||
- params: ('foo', 'bar')
|
||||
"""
|
||||
name = 'sentry.interfaces.Message'
|
||||
|
||||
def capture(self, message, params=(), formatted=None, **kwargs):
|
||||
message = to_unicode(message)
|
||||
data = {
|
||||
'sentry.interfaces.Message': {
|
||||
self.name: {
|
||||
'message': message,
|
||||
'params': self.transform(params),
|
||||
},
|
||||
|
@ -112,13 +117,15 @@ class Query(BaseEvent):
|
|||
- query: 'SELECT * FROM table'
|
||||
- engine: 'postgesql_psycopg2'
|
||||
"""
|
||||
name = 'sentry.interfaces.Query'
|
||||
|
||||
def to_string(self, data):
|
||||
sql = data['sentry.interfaces.Query']
|
||||
sql = data[self.name]
|
||||
return sql['query']
|
||||
|
||||
def capture(self, query, engine, **kwargs):
|
||||
return {
|
||||
'sentry.interfaces.Query': {
|
||||
self.name: {
|
||||
'query': to_unicode(query),
|
||||
'engine': str(engine),
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ class SentryHandler(logbook.Handler):
|
|||
if len(args) == 1:
|
||||
arg = args[0]
|
||||
if isinstance(arg, six.string_types):
|
||||
self.client = kwargs.pop('client_cls', Client)(dsn=arg)
|
||||
self.client = kwargs.pop('client_cls', Client)(dsn=arg, **kwargs)
|
||||
elif isinstance(arg, Client):
|
||||
self.client = arg
|
||||
else:
|
||||
|
@ -48,6 +48,8 @@ class SentryHandler(logbook.Handler):
|
|||
|
||||
return self._emit(record)
|
||||
except Exception:
|
||||
if self.client.raise_send_errors:
|
||||
raise
|
||||
print("Top level Sentry exception caught - failed creating log record", file=sys.stderr)
|
||||
print(to_string(record.msg), file=sys.stderr)
|
||||
print(to_string(traceback.format_exc()))
|
||||
|
|
|
@ -32,7 +32,7 @@ class SentryHandler(logging.Handler, object):
|
|||
if len(args) == 1:
|
||||
arg = args[0]
|
||||
if isinstance(arg, six.string_types):
|
||||
self.client = client(dsn=arg)
|
||||
self.client = client(dsn=arg, **kwargs)
|
||||
elif isinstance(arg, Client):
|
||||
self.client = arg
|
||||
else:
|
||||
|
@ -67,6 +67,8 @@ class SentryHandler(logging.Handler, object):
|
|||
|
||||
return self._emit(record)
|
||||
except Exception:
|
||||
if self.client.raise_send_errors:
|
||||
raise
|
||||
print("Top level Sentry exception caught - failed creating log record", file=sys.stderr)
|
||||
print(to_string(record.msg), file=sys.stderr)
|
||||
print(to_string(traceback.format_exc()), file=sys.stderr)
|
||||
|
@ -159,7 +161,7 @@ class SentryHandler(logging.Handler, object):
|
|||
handler_kwargs = {'exc_info': record.exc_info}
|
||||
|
||||
# HACK: discover a culprit when we normally couldn't
|
||||
elif not (data.get('sentry.interfaces.Stacktrace') or data.get('culprit')) and (record.name or record.funcName):
|
||||
elif not (data.get('stacktrace') or data.get('culprit')) and (record.name or record.funcName):
|
||||
culprit = label_from_frame({'module': record.name, 'function': record.funcName})
|
||||
if culprit:
|
||||
data['culprit'] = culprit
|
||||
|
|
|
@ -25,15 +25,15 @@ class Processor(object):
|
|||
if resp:
|
||||
data = resp
|
||||
|
||||
if 'sentry.interfaces.Stacktrace' in data:
|
||||
self.filter_stacktrace(data['sentry.interfaces.Stacktrace'])
|
||||
if 'stacktrace' in data:
|
||||
self.filter_stacktrace(data['stacktrace'])
|
||||
|
||||
if 'sentry.interfaces.Exception' in data:
|
||||
if 'stacktrace' in data['sentry.interfaces.Exception']:
|
||||
self.filter_stacktrace(data['sentry.interfaces.Exception']['stacktrace'])
|
||||
if 'exception' in data:
|
||||
if 'stacktrace' in data['exception']:
|
||||
self.filter_stacktrace(data['exception']['stacktrace'])
|
||||
|
||||
if 'sentry.interfaces.Http' in data:
|
||||
self.filter_http(data['sentry.interfaces.Http'])
|
||||
if 'request' in data:
|
||||
self.filter_http(data['request'])
|
||||
|
||||
return data
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ def send_test_message(client, options):
|
|||
data = options.get('data', {
|
||||
'culprit': 'raven.scripts.runner',
|
||||
'logger': 'raven.test',
|
||||
'sentry.interfaces.Http': {
|
||||
'request': {
|
||||
'method': 'GET',
|
||||
'url': 'http://example.com',
|
||||
}
|
||||
|
|
|
@ -9,10 +9,11 @@ from __future__ import absolute_import
|
|||
|
||||
import atexit
|
||||
import logging
|
||||
import time
|
||||
import threading
|
||||
import os
|
||||
|
||||
from time import sleep, time
|
||||
|
||||
from raven.transport.base import AsyncTransport
|
||||
from raven.transport.http import HTTPTransport
|
||||
from raven.utils.compat import Queue
|
||||
|
@ -35,16 +36,67 @@ class AsyncWorker(object):
|
|||
self.start()
|
||||
|
||||
def main_thread_terminated(self):
|
||||
size = self._queue.qsize()
|
||||
if size:
|
||||
self._lock.acquire()
|
||||
try:
|
||||
if not self._thread:
|
||||
# thread not started or already stopped - nothing to do
|
||||
return
|
||||
|
||||
# wake the processing thread up
|
||||
self._queue.put_nowait(self._terminator)
|
||||
|
||||
timeout = self.options['shutdown_timeout']
|
||||
print("Sentry is attempting to send %s pending error messages" % size)
|
||||
print("Waiting up to %s seconds" % timeout)
|
||||
if os.name == 'nt':
|
||||
print("Press Ctrl-Break to quit")
|
||||
else:
|
||||
print("Press Ctrl-C to quit")
|
||||
self.stop(timeout=timeout)
|
||||
|
||||
# wait briefly, initially
|
||||
initial_timeout = 0.1
|
||||
if timeout < initial_timeout:
|
||||
initial_timeout = timeout
|
||||
|
||||
if not self._timed_queue_join(initial_timeout):
|
||||
# if that didn't work, wait a bit longer
|
||||
# NB that size is an approximation, because other threads may
|
||||
# add or remove items
|
||||
size = self._queue.qsize()
|
||||
|
||||
print("Sentry is attempting to send %i pending error messages"
|
||||
% size)
|
||||
print("Waiting up to %s seconds" % timeout)
|
||||
|
||||
if os.name == 'nt':
|
||||
print("Press Ctrl-Break to quit")
|
||||
else:
|
||||
print("Press Ctrl-C to quit")
|
||||
|
||||
self._timed_queue_join(timeout - initial_timeout)
|
||||
|
||||
self._thread = None
|
||||
|
||||
finally:
|
||||
self._lock.release()
|
||||
|
||||
def _timed_queue_join(self, timeout):
|
||||
"""
|
||||
implementation of Queue.join which takes a 'timeout' argument
|
||||
|
||||
returns true on success, false on timeout
|
||||
"""
|
||||
deadline = time() + timeout
|
||||
queue = self._queue
|
||||
|
||||
queue.all_tasks_done.acquire()
|
||||
try:
|
||||
while queue.unfinished_tasks:
|
||||
delay = deadline - time()
|
||||
if delay <= 0:
|
||||
# timed out
|
||||
return False
|
||||
|
||||
queue.all_tasks_done.wait(timeout=delay)
|
||||
|
||||
return True
|
||||
|
||||
finally:
|
||||
queue.all_tasks_done.release()
|
||||
|
||||
def start(self):
|
||||
"""
|
||||
|
@ -77,17 +129,20 @@ class AsyncWorker(object):
|
|||
self._queue.put_nowait((callback, args, kwargs))
|
||||
|
||||
def _target(self):
|
||||
while 1:
|
||||
while True:
|
||||
record = self._queue.get()
|
||||
if record is self._terminator:
|
||||
break
|
||||
callback, args, kwargs = record
|
||||
try:
|
||||
callback(*args, **kwargs)
|
||||
except Exception:
|
||||
logger.error('Failed processing job', exc_info=True)
|
||||
if record is self._terminator:
|
||||
break
|
||||
callback, args, kwargs = record
|
||||
try:
|
||||
callback(*args, **kwargs)
|
||||
except Exception:
|
||||
logger.error('Failed processing job', exc_info=True)
|
||||
finally:
|
||||
self._queue.task_done()
|
||||
|
||||
time.sleep(0)
|
||||
sleep(0)
|
||||
|
||||
|
||||
class ThreadedHTTPTransport(AsyncTransport, HTTPTransport):
|
||||
|
|
|
@ -19,19 +19,22 @@ except:
|
|||
|
||||
class TornadoHTTPTransport(HTTPTransport):
|
||||
|
||||
scheme = ['tornado+http']
|
||||
scheme = ['tornado+http', 'tornado+https']
|
||||
|
||||
def __init__(self, parsed_url):
|
||||
def __init__(self, parsed_url, **kwargs):
|
||||
if not has_tornado:
|
||||
raise ImportError('TornadoHTTPTransport requires tornado.')
|
||||
|
||||
super(TornadoHTTPTransport, self).__init__(parsed_url)
|
||||
super(TornadoHTTPTransport, self).__init__(parsed_url, **kwargs)
|
||||
|
||||
# remove the tornado+ from the protocol, as it is not a real protocol
|
||||
self._url = self._url.split('+', 1)[-1]
|
||||
|
||||
def send(self, data, headers):
|
||||
kwargs = dict(method='POST', headers=headers, body=data)
|
||||
kwargs["validate_cert"] = self.verify_ssl
|
||||
kwargs["connect_timeout"] = self.timeout
|
||||
kwargs["ca_certs"] = self.ca_certs
|
||||
|
||||
# only use async if ioloop is running, otherwise it will never send
|
||||
if ioloop.IOLoop.initialized():
|
||||
|
|
|
@ -6,6 +6,7 @@ raven.transport.udp
|
|||
:license: BSD, see LICENSE for more details.
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from raven.transport.base import Transport
|
||||
|
||||
|
@ -48,7 +49,7 @@ class BaseUDPTransport(Transport):
|
|||
|
||||
host, port = self._parsed_url.netloc.rsplit(':')
|
||||
addr_info = self._get_addr_info(host, int(port))
|
||||
self._send_data(auth_header + '\n\n' + data, addr_info)
|
||||
self._send_data(auth_header.encode('utf-8') + b'\n\n' + data, addr_info)
|
||||
|
||||
|
||||
class UDPTransport(BaseUDPTransport):
|
||||
|
|
|
@ -233,7 +233,7 @@ def get_stack_info(frames, transformer=transform, capture_locals=True,
|
|||
# This changes /foo/site-packages/baz/bar.py into baz/bar.py
|
||||
try:
|
||||
base_filename = sys.modules[module_name.split('.', 1)[0]].__file__
|
||||
filename = abs_path.split(base_filename.rsplit('/', 2)[0], 1)[-1][1:]
|
||||
filename = abs_path.split(base_filename.rsplit('/', 2)[0], 1)[-1].lstrip("/")
|
||||
except:
|
||||
filename = abs_path
|
||||
|
||||
|
|
2
setup.py
2
setup.py
|
@ -97,7 +97,7 @@ class PyTest(TestCommand):
|
|||
|
||||
setup(
|
||||
name='raven',
|
||||
version='4.2.1',
|
||||
version='5.0.0',
|
||||
author='David Cramer',
|
||||
author_email='dcramer@gmail.com',
|
||||
url='http://github.com/getsentry/raven-python',
|
||||
|
|
|
@ -187,7 +187,7 @@ class ClientTest(TestCase):
|
|||
'Content-Type': 'application/octet-stream',
|
||||
'X-Sentry-Auth': (
|
||||
'Sentry sentry_timestamp=1328055286.51, '
|
||||
'sentry_client=raven-python/%s, sentry_version=4, '
|
||||
'sentry_client=raven-python/%s, sentry_version=5, '
|
||||
'sentry_key=public, '
|
||||
'sentry_secret=secret' % (raven.VERSION,))
|
||||
},
|
||||
|
@ -216,6 +216,35 @@ class ClientTest(TestCase):
|
|||
},
|
||||
)
|
||||
|
||||
@mock.patch('raven.transport.http.HTTPTransport.send')
|
||||
@mock.patch('raven.base.ClientState.should_try')
|
||||
def test_raise_exception_on_send_error(self, should_try, _send_remote):
|
||||
should_try.return_value = True
|
||||
client = Client(
|
||||
servers=['sync+http://example.com'],
|
||||
public_key='public',
|
||||
secret_key='secret',
|
||||
project=1,
|
||||
)
|
||||
|
||||
# Test for the default behaviour in which a send error is handled by the client
|
||||
_send_remote.side_effect = Exception()
|
||||
client.capture('Message', data={}, date=None, time_spent=10,
|
||||
extra={}, stack=None, tags=None, message='Test message')
|
||||
assert client.state.status == client.state.ERROR
|
||||
|
||||
# Test for the case in which a send error is raised to the calling frame.
|
||||
client = Client(
|
||||
servers=['sync+http://example.com'],
|
||||
public_key='public',
|
||||
secret_key='secret',
|
||||
project=1,
|
||||
raise_send_errors=True,
|
||||
)
|
||||
with self.assertRaises(Exception):
|
||||
client.capture('Message', data={}, date=None, time_spent=10,
|
||||
extra={}, stack=None, tags=None, message='Test message')
|
||||
|
||||
def test_encode_decode(self):
|
||||
data = {'foo': 'bar'}
|
||||
encoded = self.client.encode(data)
|
||||
|
@ -291,12 +320,12 @@ class ClientTest(TestCase):
|
|||
self.assertEquals(len(self.client.events), 1)
|
||||
event = self.client.events.pop(0)
|
||||
self.assertEquals(event['message'], 'ValueError: foo')
|
||||
self.assertTrue('sentry.interfaces.Exception' in event)
|
||||
exc = event['sentry.interfaces.Exception']
|
||||
self.assertTrue('exception' in event)
|
||||
exc = event['exception']['values'][0]
|
||||
self.assertEquals(exc['type'], 'ValueError')
|
||||
self.assertEquals(exc['value'], 'foo')
|
||||
self.assertEquals(exc['module'], ValueError.__module__) # this differs in some Python versions
|
||||
assert 'sentry.interfaces.Stacktrace' not in event
|
||||
assert 'stacktrace' not in event
|
||||
stacktrace = exc['stacktrace']
|
||||
self.assertEquals(len(stacktrace['frames']), 1)
|
||||
frame = stacktrace['frames'][0]
|
||||
|
@ -329,7 +358,7 @@ class ClientTest(TestCase):
|
|||
self.assertEquals(len(self.client.events), 1)
|
||||
event = self.client.events.pop(0)
|
||||
self.assertEquals(event['message'], 'DecoratorTestException')
|
||||
exc = event['sentry.interfaces.Exception']
|
||||
exc = event['exception']['values'][0]
|
||||
self.assertEquals(exc['type'], 'DecoratorTestException')
|
||||
self.assertEquals(exc['module'], self.DecoratorTestException.__module__)
|
||||
stacktrace = exc['stacktrace']
|
||||
|
@ -357,7 +386,7 @@ class ClientTest(TestCase):
|
|||
self.assertEquals(len(self.client.events), 1)
|
||||
event = self.client.events.pop(0)
|
||||
self.assertEquals(event['message'], 'test')
|
||||
self.assertFalse('sentry.interfaces.Stacktrace' in event)
|
||||
assert 'stacktrace' not in event
|
||||
self.assertTrue('timestamp' in event)
|
||||
|
||||
def test_context(self):
|
||||
|
@ -386,9 +415,9 @@ class ClientTest(TestCase):
|
|||
self.assertEquals(len(self.client.events), 1)
|
||||
event = self.client.events.pop(0)
|
||||
self.assertEquals(event['message'], 'test')
|
||||
self.assertTrue('sentry.interfaces.Stacktrace' in event)
|
||||
self.assertEquals(len(frames), len(event['sentry.interfaces.Stacktrace']['frames']))
|
||||
for frame, frame_i in zip(frames, event['sentry.interfaces.Stacktrace']['frames']):
|
||||
assert 'stacktrace' in event
|
||||
self.assertEquals(len(frames), len(event['stacktrace']['frames']))
|
||||
for frame, frame_i in zip(frames, event['stacktrace']['frames']):
|
||||
self.assertEquals(frame[0].f_code.co_filename, frame_i['abs_path'])
|
||||
self.assertEquals(frame[0].f_code.co_name, frame_i['function'])
|
||||
|
||||
|
@ -398,7 +427,7 @@ class ClientTest(TestCase):
|
|||
self.assertEquals(len(self.client.events), 1)
|
||||
event = self.client.events.pop(0)
|
||||
self.assertEquals(event['message'], 'test')
|
||||
self.assertTrue('sentry.interfaces.Stacktrace' in event)
|
||||
self.assertTrue('stacktrace' in event)
|
||||
self.assertTrue('timestamp' in event)
|
||||
|
||||
def test_site(self):
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import logging
|
||||
|
||||
from exam import fixture
|
||||
|
||||
from webtest import TestApp
|
||||
|
@ -66,14 +64,10 @@ class BottleTest(BaseTest):
|
|||
|
||||
self.assertEquals(len(self.raven.events), 1)
|
||||
event = self.raven.events.pop(0)
|
||||
self.assertTrue('sentry.interfaces.Exception' in event)
|
||||
assert 'exception' in event
|
||||
|
||||
exc = event['sentry.interfaces.Exception']
|
||||
exc = event['exception']['values'][0]
|
||||
self.assertEquals(exc['type'], 'ValueError')
|
||||
self.assertEquals(exc['value'], 'hello world')
|
||||
self.assertEquals(event['level'], logging.ERROR)
|
||||
self.assertEquals(event['message'], 'ValueError: hello world')
|
||||
self.assertEquals(event['culprit'], 'tests.contrib.bottle.tests in an_error')
|
||||
|
||||
def test_captureException_captures_http(self):
|
||||
response = self.client.get('/capture/?foo=bar')
|
||||
|
@ -83,8 +77,8 @@ class BottleTest(BaseTest):
|
|||
event = self.raven.events.pop(0)
|
||||
|
||||
assert event['message'] == 'ValueError: Boom'
|
||||
assert 'sentry.interfaces.Http' in event
|
||||
assert 'sentry.interfaces.Exception' in event
|
||||
assert 'request' in event
|
||||
assert 'exception' in event
|
||||
|
||||
def test_captureMessage_captures_http(self):
|
||||
response = self.client.get('/message/?foo=bar')
|
||||
|
@ -93,5 +87,5 @@ class BottleTest(BaseTest):
|
|||
|
||||
event = self.raven.events.pop(0)
|
||||
|
||||
self.assertTrue('sentry.interfaces.Message' in event)
|
||||
self.assertTrue('sentry.interfaces.Http' in event)
|
||||
assert 'sentry.interfaces.Message' in event
|
||||
assert 'request' in event
|
||||
|
|
|
@ -147,8 +147,8 @@ class DjangoClientTest(TestCase):
|
|||
|
||||
self.assertEquals(len(self.raven.events), 1)
|
||||
event = self.raven.events.pop(0)
|
||||
self.assertTrue('sentry.interfaces.Exception' in event)
|
||||
exc = event['sentry.interfaces.Exception']
|
||||
assert 'exception' in event
|
||||
exc = event['exception']['values'][0]
|
||||
self.assertEquals(exc['type'], 'ValueError')
|
||||
self.assertEquals(exc['value'], "invalid literal for int() with base 10: 'hello'")
|
||||
self.assertEquals(event['level'], logging.ERROR)
|
||||
|
@ -160,8 +160,8 @@ class DjangoClientTest(TestCase):
|
|||
|
||||
self.assertEquals(len(self.raven.events), 1)
|
||||
event = self.raven.events.pop(0)
|
||||
self.assertTrue('sentry.interfaces.Exception' in event)
|
||||
exc = event['sentry.interfaces.Exception']
|
||||
assert 'exception' in event
|
||||
exc = event['exception']['values'][0]
|
||||
self.assertEquals(exc['type'], 'Exception')
|
||||
self.assertEquals(exc['value'], 'view exception')
|
||||
self.assertEquals(event['level'], logging.ERROR)
|
||||
|
@ -178,7 +178,7 @@ class DjangoClientTest(TestCase):
|
|||
|
||||
assert len(self.raven.events) == 1
|
||||
event = self.raven.events.pop(0)
|
||||
assert 'sentry.interfaces.User' not in event
|
||||
assert 'user' not in event
|
||||
|
||||
assert self.client.login(username='admin', password='admin')
|
||||
|
||||
|
@ -186,8 +186,8 @@ class DjangoClientTest(TestCase):
|
|||
|
||||
self.assertEquals(len(self.raven.events), 1)
|
||||
event = self.raven.events.pop(0)
|
||||
assert 'sentry.interfaces.User' in event
|
||||
user_info = event['sentry.interfaces.User']
|
||||
assert 'user' in event
|
||||
user_info = event['user']
|
||||
assert user_info == {
|
||||
'is_authenticated': True,
|
||||
'username': user.username,
|
||||
|
@ -226,8 +226,8 @@ class DjangoClientTest(TestCase):
|
|||
self.assertEquals(len(self.raven.events), 1)
|
||||
event = self.raven.events.pop(0)
|
||||
|
||||
self.assertTrue('sentry.interfaces.Exception' in event)
|
||||
exc = event['sentry.interfaces.Exception']
|
||||
assert 'exception' in event
|
||||
exc = event['exception']['values'][0]
|
||||
self.assertEquals(exc['type'], 'ImportError')
|
||||
self.assertEquals(exc['value'], 'request')
|
||||
self.assertEquals(event['level'], logging.ERROR)
|
||||
|
@ -243,8 +243,8 @@ class DjangoClientTest(TestCase):
|
|||
self.assertEquals(len(self.raven.events), 1)
|
||||
event = self.raven.events.pop(0)
|
||||
|
||||
self.assertTrue('sentry.interfaces.Exception' in event)
|
||||
exc = event['sentry.interfaces.Exception']
|
||||
assert 'exception' in event
|
||||
exc = event['exception']['values'][0]
|
||||
self.assertEquals(exc['type'], 'ImportError')
|
||||
self.assertEquals(exc['value'], 'response')
|
||||
self.assertEquals(event['level'], logging.ERROR)
|
||||
|
@ -261,8 +261,8 @@ class DjangoClientTest(TestCase):
|
|||
assert len(self.raven.events) == 2
|
||||
event = self.raven.events.pop(0)
|
||||
|
||||
self.assertTrue('sentry.interfaces.Exception' in event)
|
||||
exc = event['sentry.interfaces.Exception']
|
||||
assert 'exception' in event
|
||||
exc = event['exception']['values'][0]
|
||||
self.assertEquals(exc['type'], 'Exception')
|
||||
self.assertEquals(exc['value'], 'view exception')
|
||||
self.assertEquals(event['level'], logging.ERROR)
|
||||
|
@ -271,8 +271,8 @@ class DjangoClientTest(TestCase):
|
|||
|
||||
event = self.raven.events.pop(0)
|
||||
|
||||
self.assertTrue('sentry.interfaces.Exception' in event)
|
||||
exc = event['sentry.interfaces.Exception']
|
||||
assert 'exception' in event
|
||||
exc = event['exception']['values'][0]
|
||||
self.assertEquals(exc['type'], 'ValueError')
|
||||
self.assertEquals(exc['value'], 'handler500')
|
||||
self.assertEquals(event['level'], logging.ERROR)
|
||||
|
@ -286,8 +286,8 @@ class DjangoClientTest(TestCase):
|
|||
self.assertEquals(len(self.raven.events), 1)
|
||||
event = self.raven.events.pop(0)
|
||||
|
||||
self.assertTrue('sentry.interfaces.Exception' in event)
|
||||
exc = event['sentry.interfaces.Exception']
|
||||
assert 'exception' in event
|
||||
exc = event['exception']['values'][0]
|
||||
self.assertEquals(exc['type'], 'ImportError')
|
||||
self.assertEquals(exc['value'], 'view')
|
||||
self.assertEquals(event['level'], logging.ERROR)
|
||||
|
@ -368,8 +368,8 @@ class DjangoClientTest(TestCase):
|
|||
self.assertEquals(event['level'], logging.INFO)
|
||||
self.assertEquals(event['logger'], 'http404')
|
||||
|
||||
self.assertTrue('sentry.interfaces.Http' in event)
|
||||
http = event['sentry.interfaces.Http']
|
||||
assert 'request' in event
|
||||
http = event['request']
|
||||
self.assertEquals(http['url'], 'http://testserver/non-existent-page')
|
||||
self.assertEquals(http['method'], 'GET')
|
||||
self.assertEquals(http['query_string'], '')
|
||||
|
@ -434,8 +434,8 @@ class DjangoClientTest(TestCase):
|
|||
self.assertEquals(len(self.raven.events), 1)
|
||||
event = self.raven.events.pop(0)
|
||||
|
||||
self.assertTrue('sentry.interfaces.Http' in event)
|
||||
http = event['sentry.interfaces.Http']
|
||||
assert 'request' in event
|
||||
http = event['request']
|
||||
self.assertEquals(http['method'], 'POST')
|
||||
self.assertEquals(http['data'], '<unavailable>')
|
||||
|
||||
|
@ -449,8 +449,8 @@ class DjangoClientTest(TestCase):
|
|||
self.assertEquals(len(self.raven.events), 1)
|
||||
event = self.raven.events.pop(0)
|
||||
|
||||
self.assertTrue('sentry.interfaces.Http' in event)
|
||||
http = event['sentry.interfaces.Http']
|
||||
assert 'request' in event
|
||||
http = event['request']
|
||||
self.assertEquals(http['method'], 'POST')
|
||||
self.assertEquals(http['data'], {'foo': 'bar', 'ham': 'spam'})
|
||||
|
||||
|
@ -463,8 +463,8 @@ class DjangoClientTest(TestCase):
|
|||
self.assertEquals(len(self.raven.events), 1)
|
||||
event = self.raven.events.pop(0)
|
||||
|
||||
self.assertTrue('sentry.interfaces.Http' in event)
|
||||
http = event['sentry.interfaces.Http']
|
||||
assert 'request' in event
|
||||
http = event['request']
|
||||
self.assertEquals(http['method'], 'POST')
|
||||
self.assertEquals(http['data'], '<unavailable>')
|
||||
self.assertTrue('headers' in http)
|
||||
|
@ -483,7 +483,7 @@ class DjangoClientTest(TestCase):
|
|||
self.assertEquals(len(self.raven.events), 1)
|
||||
event = self.raven.events.pop(0)
|
||||
|
||||
frames = event['sentry.interfaces.Exception']['stacktrace']['frames']
|
||||
frames = event['exception']['values'][0]['stacktrace']['frames']
|
||||
for frame in frames:
|
||||
if frame['module'].startswith('django.'):
|
||||
assert frame.get('in_app') is False
|
||||
|
@ -527,8 +527,8 @@ class DjangoClientTest(TestCase):
|
|||
request.META['HTTP_HOST'] = 'example.com'
|
||||
result = self.raven.get_data_from_request(request)
|
||||
build_absolute_uri.assert_called_once_with()
|
||||
assert 'sentry.interfaces.Http' in result
|
||||
assert result['sentry.interfaces.Http']['url'] == 'http://example.com/'
|
||||
assert 'request' in result
|
||||
assert result['request']['url'] == 'http://example.com/'
|
||||
|
||||
|
||||
class DjangoTemplateTagTest(TestCase):
|
||||
|
@ -568,8 +568,8 @@ class DjangoLoggingTest(TestCase):
|
|||
|
||||
self.assertEquals(len(self.raven.events), 1)
|
||||
event = self.raven.events.pop(0)
|
||||
self.assertTrue('sentry.interfaces.Http' in event)
|
||||
http = event['sentry.interfaces.Http']
|
||||
assert 'request' in event
|
||||
http = event['request']
|
||||
self.assertEquals(http['method'], 'POST')
|
||||
|
||||
|
||||
|
|
|
@ -106,8 +106,8 @@ class FlaskTest(BaseTest):
|
|||
|
||||
event = self.raven.events.pop(0)
|
||||
|
||||
self.assertTrue('sentry.interfaces.Exception' in event)
|
||||
exc = event['sentry.interfaces.Exception']
|
||||
assert 'exception' in event
|
||||
exc = event['exception']['values'][0]
|
||||
self.assertEquals(exc['type'], 'ValueError')
|
||||
self.assertEquals(exc['value'], 'hello world')
|
||||
self.assertEquals(event['level'], logging.ERROR)
|
||||
|
@ -121,8 +121,8 @@ class FlaskTest(BaseTest):
|
|||
|
||||
event = self.raven.events.pop(0)
|
||||
|
||||
self.assertTrue('sentry.interfaces.Http' in event)
|
||||
http = event['sentry.interfaces.Http']
|
||||
assert 'request' in event
|
||||
http = event['request']
|
||||
self.assertEquals(http['url'], 'http://localhost/an-error/')
|
||||
self.assertEquals(http['query_string'], 'foo=bar')
|
||||
self.assertEquals(http['method'], 'GET')
|
||||
|
@ -148,8 +148,8 @@ class FlaskTest(BaseTest):
|
|||
|
||||
event = self.raven.events.pop(0)
|
||||
|
||||
self.assertTrue('sentry.interfaces.Http' in event)
|
||||
http = event['sentry.interfaces.Http']
|
||||
assert 'request' in event
|
||||
http = event['request']
|
||||
self.assertEquals(http['url'], 'http://localhost/an-error/')
|
||||
self.assertEquals(http['query_string'], 'biz=baz')
|
||||
self.assertEquals(http['method'], 'POST')
|
||||
|
@ -177,8 +177,8 @@ class FlaskTest(BaseTest):
|
|||
self.assertEquals(event['event_id'], response.headers['X-Sentry-ID'])
|
||||
|
||||
assert event['message'] == 'ValueError: Boom'
|
||||
assert 'sentry.interfaces.Http' in event
|
||||
assert 'sentry.interfaces.Exception' in event
|
||||
assert 'request' in event
|
||||
assert 'exception' in event
|
||||
|
||||
def test_captureMessage_captures_http(self):
|
||||
response = self.client.get('/message/?foo=bar')
|
||||
|
@ -188,8 +188,8 @@ class FlaskTest(BaseTest):
|
|||
event = self.raven.events.pop(0)
|
||||
self.assertEquals(event['event_id'], response.headers['X-Sentry-ID'])
|
||||
|
||||
self.assertTrue('sentry.interfaces.Message' in event)
|
||||
self.assertTrue('sentry.interfaces.Http' in event)
|
||||
assert 'sentry.interfaces.Message' in event
|
||||
assert 'request' in event
|
||||
|
||||
@patch('flask.wrappers.RequestBase._load_form_data')
|
||||
def test_get_data_handles_disconnected_client(self, lfd):
|
||||
|
@ -199,8 +199,8 @@ class FlaskTest(BaseTest):
|
|||
|
||||
event = self.raven.events.pop(0)
|
||||
|
||||
self.assertTrue('sentry.interfaces.Http' in event)
|
||||
http = event['sentry.interfaces.Http']
|
||||
assert 'request' in event
|
||||
http = event['request']
|
||||
self.assertEqual({}, http.get('data'))
|
||||
|
||||
def test_error_handler_with_ignored_exception(self):
|
||||
|
@ -249,5 +249,5 @@ class FlaskLoginTest(BaseTest):
|
|||
self.client.get('/an-error-logged-in/')
|
||||
event = self.raven.events.pop(0)
|
||||
assert event['message'] == 'ValueError: hello world'
|
||||
assert 'sentry.interfaces.Http' in event
|
||||
assert 'sentry.interfaces.User' in event
|
||||
assert 'request' in event
|
||||
assert 'user' in event
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
tests
|
||||
|
||||
Test the tornado Async Client
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import unittest
|
||||
from mock import patch
|
||||
from tornado import web, gen, testing
|
||||
from raven.contrib.tornado import SentryMixin, AsyncSentryClient
|
||||
|
@ -88,17 +82,17 @@ class TornadoAsyncClientTestCase(testing.AsyncHTTPTestCase):
|
|||
self.assertEqual(send.call_count, 1)
|
||||
args, kwargs = send.call_args
|
||||
|
||||
self.assertTrue(('sentry.interfaces.User' in kwargs))
|
||||
self.assertTrue(('sentry.interfaces.Http' in kwargs))
|
||||
self.assertTrue(('sentry.interfaces.Exception' in kwargs))
|
||||
assert 'user' in kwargs
|
||||
assert 'request' in kwargs
|
||||
assert 'exception' in kwargs
|
||||
|
||||
http_data = kwargs['sentry.interfaces.Http']
|
||||
http_data = kwargs['request']
|
||||
self.assertEqual(http_data['cookies'], None)
|
||||
self.assertEqual(http_data['url'], response.effective_url)
|
||||
self.assertEqual(http_data['query_string'], 'qs=qs')
|
||||
self.assertEqual(http_data['method'], 'GET')
|
||||
|
||||
user_data = kwargs['sentry.interfaces.User']
|
||||
user_data = kwargs['user']
|
||||
self.assertEqual(user_data['is_authenticated'], False)
|
||||
|
||||
@patch('raven.contrib.tornado.AsyncSentryClient.send')
|
||||
|
@ -108,18 +102,18 @@ class TornadoAsyncClientTestCase(testing.AsyncHTTPTestCase):
|
|||
self.assertEqual(send.call_count, 1)
|
||||
args, kwargs = send.call_args
|
||||
|
||||
self.assertTrue(('sentry.interfaces.User' in kwargs))
|
||||
self.assertTrue(('sentry.interfaces.Http' in kwargs))
|
||||
self.assertTrue(('sentry.interfaces.Exception' in kwargs))
|
||||
self.assertTrue(('extra' in kwargs))
|
||||
assert 'user' in kwargs
|
||||
assert 'request' in kwargs
|
||||
assert 'exception' in kwargs
|
||||
assert 'extra' in kwargs
|
||||
|
||||
http_data = kwargs['sentry.interfaces.Http']
|
||||
http_data = kwargs['request']
|
||||
self.assertEqual(http_data['cookies'], None)
|
||||
self.assertEqual(http_data['url'], response.effective_url)
|
||||
self.assertEqual(http_data['query_string'], 'qs=qs')
|
||||
self.assertEqual(http_data['method'], 'GET')
|
||||
|
||||
user_data = kwargs['sentry.interfaces.User']
|
||||
user_data = kwargs['user']
|
||||
self.assertEqual(user_data['is_authenticated'], False)
|
||||
|
||||
assert 'extra_data' in kwargs['extra']
|
||||
|
@ -136,18 +130,18 @@ class TornadoAsyncClientTestCase(testing.AsyncHTTPTestCase):
|
|||
self.assertEqual(send.call_count, 1)
|
||||
args, kwargs = send.call_args
|
||||
|
||||
self.assertTrue(('sentry.interfaces.User' in kwargs))
|
||||
self.assertTrue(('sentry.interfaces.Http' in kwargs))
|
||||
self.assertTrue(('sentry.interfaces.Exception' in kwargs))
|
||||
self.assertTrue(('extra' in kwargs))
|
||||
assert 'user' in kwargs
|
||||
assert 'request' in kwargs
|
||||
assert 'exception' in kwargs
|
||||
assert 'extra' in kwargs
|
||||
|
||||
http_data = kwargs['sentry.interfaces.Http']
|
||||
http_data = kwargs['request']
|
||||
self.assertEqual(http_data['cookies'], None)
|
||||
self.assertEqual(http_data['url'], response.effective_url)
|
||||
self.assertEqual(http_data['query_string'], 'qs=qs')
|
||||
self.assertEqual(http_data['method'], 'GET')
|
||||
|
||||
user_data = kwargs['sentry.interfaces.User']
|
||||
user_data = kwargs['user']
|
||||
self.assertEqual(user_data['is_authenticated'], False)
|
||||
|
||||
assert 'extra_data' in kwargs['extra']
|
||||
|
@ -166,17 +160,17 @@ class TornadoAsyncClientTestCase(testing.AsyncHTTPTestCase):
|
|||
self.assertEqual(send.call_count, 1)
|
||||
args, kwargs = send.call_args
|
||||
|
||||
self.assertTrue(('sentry.interfaces.User' in kwargs))
|
||||
self.assertTrue(('sentry.interfaces.Http' in kwargs))
|
||||
self.assertTrue(('sentry.interfaces.Message' in kwargs))
|
||||
assert 'user' in kwargs
|
||||
assert 'request' in kwargs
|
||||
assert 'sentry.interfaces.Message' in kwargs
|
||||
|
||||
http_data = kwargs['sentry.interfaces.Http']
|
||||
http_data = kwargs['request']
|
||||
self.assertEqual(http_data['cookies'], None)
|
||||
self.assertEqual(http_data['url'], response.effective_url)
|
||||
self.assertEqual(http_data['query_string'], 'qs=qs')
|
||||
self.assertEqual(http_data['method'], 'GET')
|
||||
|
||||
user_data = kwargs['sentry.interfaces.User']
|
||||
user_data = kwargs['user']
|
||||
self.assertEqual(user_data['is_authenticated'], True)
|
||||
|
||||
@patch('raven.contrib.tornado.AsyncSentryClient.send')
|
||||
|
@ -186,17 +180,17 @@ class TornadoAsyncClientTestCase(testing.AsyncHTTPTestCase):
|
|||
self.assertEqual(send.call_count, 1)
|
||||
args, kwargs = send.call_args
|
||||
|
||||
self.assertTrue(('sentry.interfaces.User' in kwargs))
|
||||
self.assertTrue(('sentry.interfaces.Http' in kwargs))
|
||||
self.assertTrue(('sentry.interfaces.Exception' in kwargs))
|
||||
assert 'user' in kwargs
|
||||
assert 'request' in kwargs
|
||||
assert 'exception' in kwargs
|
||||
|
||||
http_data = kwargs['sentry.interfaces.Http']
|
||||
http_data = kwargs['request']
|
||||
self.assertEqual(http_data['cookies'], None)
|
||||
self.assertEqual(http_data['url'], response.effective_url)
|
||||
self.assertEqual(http_data['query_string'], 'qs=qs')
|
||||
self.assertEqual(http_data['method'], 'GET')
|
||||
|
||||
user_data = kwargs['sentry.interfaces.User']
|
||||
user_data = kwargs['user']
|
||||
self.assertEqual(user_data['is_authenticated'], False)
|
||||
|
||||
@patch('raven.contrib.tornado.AsyncSentryClient.send')
|
||||
|
@ -206,19 +200,15 @@ class TornadoAsyncClientTestCase(testing.AsyncHTTPTestCase):
|
|||
self.assertEqual(send.call_count, 1)
|
||||
args, kwargs = send.call_args
|
||||
|
||||
self.assertTrue(('sentry.interfaces.User' in kwargs))
|
||||
self.assertTrue(('sentry.interfaces.Http' in kwargs))
|
||||
self.assertTrue(('sentry.interfaces.Exception' in kwargs))
|
||||
assert 'user' in kwargs
|
||||
assert 'request' in kwargs
|
||||
assert 'exception' in kwargs
|
||||
|
||||
http_data = kwargs['sentry.interfaces.Http']
|
||||
http_data = kwargs['request']
|
||||
self.assertEqual(http_data['cookies'], None)
|
||||
self.assertEqual(http_data['url'], response.effective_url)
|
||||
self.assertEqual(http_data['query_string'], 'qs=qs')
|
||||
self.assertEqual(http_data['method'], 'GET')
|
||||
|
||||
user_data = kwargs['sentry.interfaces.User']
|
||||
user_data = kwargs['user']
|
||||
self.assertEqual(user_data['is_authenticated'], False)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -52,8 +52,8 @@ class WebPyTest(TestCase):
|
|||
self.assertEquals(len(self.store.events), 1)
|
||||
|
||||
event = self.store.events.pop()
|
||||
self.assertTrue('sentry.interfaces.Exception' in event)
|
||||
exc = event['sentry.interfaces.Exception']
|
||||
assert 'exception' in event
|
||||
exc = event['exception']['values'][0]
|
||||
self.assertEquals(exc['type'], 'ValueError')
|
||||
self.assertEquals(exc['value'], 'That\'s what she said')
|
||||
self.assertEquals(event['message'], 'ValueError: That\'s what she said')
|
||||
|
@ -66,8 +66,8 @@ class WebPyTest(TestCase):
|
|||
|
||||
event = self.store.events.pop()
|
||||
|
||||
self.assertTrue('sentry.interfaces.Http' in event)
|
||||
http = event['sentry.interfaces.Http']
|
||||
assert 'request' in event
|
||||
http = event['request']
|
||||
self.assertEquals(http['url'], 'http://localhost/test')
|
||||
self.assertEquals(http['query_string'], '?biz=baz')
|
||||
self.assertEquals(http['method'], 'POST')
|
||||
|
|
|
@ -47,9 +47,9 @@ class ZeroRPCTest(TestCase):
|
|||
except zerorpc.exceptions.RemoteError as ex:
|
||||
self.assertEqual(ex.name, 'IndexError')
|
||||
self.assertEqual(len(self._sentry.events), 1)
|
||||
exc = self._sentry.events[0]['sentry.interfaces.Exception']
|
||||
exc = self._sentry.events[0]['exception']
|
||||
self.assertEqual(exc['type'], 'IndexError')
|
||||
frames = self._sentry.events[0]['sentry.interfaces.Exception']['stacktrace']['frames']
|
||||
frames = exc['stacktrace']['frames']
|
||||
self.assertEqual(frames[0]['function'], 'choice')
|
||||
self.assertEqual(frames[0]['module'], 'random')
|
||||
else:
|
||||
|
@ -68,9 +68,9 @@ class ZeroRPCTest(TestCase):
|
|||
for attempt in xrange(0, 10):
|
||||
gevent.sleep(0.1)
|
||||
if len(self._sentry.events):
|
||||
exc = self._sentry.events[0]['sentry.interfaces.Exception']
|
||||
exc = self._sentry.events[0]['exception']
|
||||
self.assertEqual(exc['type'], 'IndexError')
|
||||
frames = self._sentry.events[0]['sentry.interfaces.Exception']['stacktrace']['frames']
|
||||
frames = exc['stacktrace']['frames']
|
||||
self.assertEqual(frames[0]['function'], 'choice')
|
||||
self.assertEqual(frames[0]['module'], 'random')
|
||||
return
|
||||
|
|
|
@ -37,7 +37,7 @@ class LogbookHandlerTest(TestCase):
|
|||
self.assertEquals(event['logger'], __name__)
|
||||
self.assertEquals(event['level'], 'error')
|
||||
self.assertEquals(event['message'], 'This is a test error')
|
||||
self.assertFalse('sentry.interfaces.Exception' in event)
|
||||
self.assertFalse('exception' in event)
|
||||
self.assertTrue('sentry.interfaces.Message' in event)
|
||||
msg = event['sentry.interfaces.Message']
|
||||
self.assertEquals(msg['message'], 'This is a test error')
|
||||
|
@ -49,7 +49,7 @@ class LogbookHandlerTest(TestCase):
|
|||
self.assertEquals(event['logger'], __name__)
|
||||
self.assertEquals(event['level'], 'warning')
|
||||
self.assertEquals(event['message'], 'This is a test warning')
|
||||
self.assertFalse('sentry.interfaces.Exception' in event)
|
||||
self.assertFalse('exception' in event)
|
||||
self.assertTrue('sentry.interfaces.Message' in event)
|
||||
msg = event['sentry.interfaces.Message']
|
||||
self.assertEquals(msg['message'], 'This is a test warning')
|
||||
|
@ -65,7 +65,7 @@ class LogbookHandlerTest(TestCase):
|
|||
else:
|
||||
expected = "u'http://example.com'"
|
||||
self.assertEquals(event['extra']['url'], expected)
|
||||
self.assertFalse('sentry.interfaces.Exception' in event)
|
||||
self.assertFalse('exception' in event)
|
||||
self.assertTrue('sentry.interfaces.Message' in event)
|
||||
msg = event['sentry.interfaces.Message']
|
||||
self.assertEquals(msg['message'], 'This is a test info with a url')
|
||||
|
@ -80,8 +80,8 @@ class LogbookHandlerTest(TestCase):
|
|||
event = client.events.pop(0)
|
||||
|
||||
self.assertEquals(event['message'], 'This is a test info with an exception')
|
||||
self.assertTrue('sentry.interfaces.Exception' in event)
|
||||
exc = event['sentry.interfaces.Exception']
|
||||
assert 'exception' in event
|
||||
exc = event['exception']['values'][0]
|
||||
self.assertEquals(exc['type'], 'ValueError')
|
||||
self.assertEquals(exc['value'], 'This is a test ValueError')
|
||||
self.assertTrue('sentry.interfaces.Message' in event)
|
||||
|
@ -94,7 +94,7 @@ class LogbookHandlerTest(TestCase):
|
|||
self.assertEquals(len(client.events), 1)
|
||||
event = client.events.pop(0)
|
||||
self.assertEquals(event['message'], 'This is a test of args')
|
||||
self.assertFalse('sentry.interfaces.Exception' in event)
|
||||
assert 'exception' not in event
|
||||
self.assertTrue('sentry.interfaces.Message' in event)
|
||||
msg = event['sentry.interfaces.Message']
|
||||
self.assertEquals(msg['message'], 'This is a test of {0}')
|
||||
|
|
|
@ -2,11 +2,13 @@ from __future__ import unicode_literals
|
|||
|
||||
import logging
|
||||
import sys
|
||||
from raven.utils.testutils import TestCase
|
||||
from raven.utils import six
|
||||
import mock
|
||||
|
||||
from raven.base import Client
|
||||
from raven.handlers.logging import SentryHandler
|
||||
from raven.utils import six
|
||||
from raven.utils.stacks import iter_stack_frames
|
||||
from raven.utils.testutils import TestCase
|
||||
|
||||
|
||||
class TempStoreClient(Client):
|
||||
|
@ -42,7 +44,7 @@ class LoggingIntegrationTest(TestCase):
|
|||
self.assertEqual(event['logger'], 'root')
|
||||
self.assertEqual(event['level'], logging.INFO)
|
||||
self.assertEqual(event['message'], 'This is a test error')
|
||||
self.assertFalse('sentry.interfaces.Exception' in event)
|
||||
assert 'exception' not in event
|
||||
self.assertTrue('sentry.interfaces.Message' in event)
|
||||
msg = event['sentry.interfaces.Message']
|
||||
self.assertEqual(msg['message'], 'This is a test error')
|
||||
|
@ -61,6 +63,37 @@ class LoggingIntegrationTest(TestCase):
|
|||
record = self.make_record("Test", name=test[0])
|
||||
self.assertEqual(self.handler.can_record(record), test[1])
|
||||
|
||||
@mock.patch('raven.transport.http.HTTPTransport.send')
|
||||
@mock.patch('raven.base.ClientState.should_try')
|
||||
def test_exception_on_emit(self, should_try, _send_remote):
|
||||
should_try.return_value = True
|
||||
# Test for the default behaviour in which an exception is handled by the client or handler
|
||||
client = Client(
|
||||
servers=['sync+http://example.com'],
|
||||
public_key='public',
|
||||
secret_key='secret',
|
||||
project=1,
|
||||
)
|
||||
handler = SentryHandler(client)
|
||||
_send_remote.side_effect = Exception()
|
||||
record = self.make_record('This is a test error')
|
||||
handler.emit(record)
|
||||
self.assertEquals(handler.client.state.status, handler.client.state.ERROR)
|
||||
|
||||
# Test for the case in which a send error is raised to the calling frame.
|
||||
client = Client(
|
||||
servers=['sync+http://example.com'],
|
||||
public_key='public',
|
||||
secret_key='secret',
|
||||
project=1,
|
||||
raise_send_errors=True,
|
||||
)
|
||||
handler = SentryHandler(client)
|
||||
_send_remote.side_effect = Exception()
|
||||
with self.assertRaises(Exception):
|
||||
record = self.make_record('This is a test error')
|
||||
handler.emit(record)
|
||||
|
||||
def test_logger_extra_data(self):
|
||||
record = self.make_record('This is a test error', extra={'data': {
|
||||
'url': 'http://example.com',
|
||||
|
@ -89,8 +122,8 @@ class LoggingIntegrationTest(TestCase):
|
|||
event = self.client.events.pop(0)
|
||||
|
||||
self.assertEqual(event['message'], 'This is a test info with an exception')
|
||||
self.assertTrue('sentry.interfaces.Exception' in event)
|
||||
exc = event['sentry.interfaces.Exception']
|
||||
assert 'exception' in event
|
||||
exc = event['exception']['values'][0]
|
||||
self.assertEqual(exc['type'], 'ValueError')
|
||||
self.assertEqual(exc['value'], 'This is a test ValueError')
|
||||
self.assertTrue('sentry.interfaces.Message' in event)
|
||||
|
@ -116,12 +149,12 @@ class LoggingIntegrationTest(TestCase):
|
|||
|
||||
self.assertEqual(len(self.client.events), 1)
|
||||
event = self.client.events.pop(0)
|
||||
self.assertTrue('sentry.interfaces.Stacktrace' in event)
|
||||
frames = event['sentry.interfaces.Stacktrace']['frames']
|
||||
self.assertTrue('stacktrace' in event)
|
||||
frames = event['stacktrace']['frames']
|
||||
self.assertNotEquals(len(frames), 1)
|
||||
frame = frames[0]
|
||||
self.assertEqual(frame['module'], 'raven.handlers.logging')
|
||||
self.assertFalse('sentry.interfaces.Exception' in event)
|
||||
assert 'exception' not in event
|
||||
self.assertTrue('sentry.interfaces.Message' in event)
|
||||
self.assertEqual(event['culprit'], 'root in make_record')
|
||||
self.assertEqual(event['message'], 'This is a test of stacks')
|
||||
|
@ -141,12 +174,12 @@ class LoggingIntegrationTest(TestCase):
|
|||
|
||||
self.assertEqual(len(self.client.events), 1)
|
||||
event = self.client.events.pop(0)
|
||||
assert 'sentry.interfaces.Stacktrace' in event
|
||||
assert 'stacktrace' in event
|
||||
assert 'culprit' in event
|
||||
assert event['culprit'] == 'root in make_record'
|
||||
self.assertTrue('message' in event, event)
|
||||
self.assertEqual(event['message'], 'This is a test of stacks')
|
||||
self.assertFalse('sentry.interfaces.Exception' in event)
|
||||
assert 'exception' not in event
|
||||
self.assertTrue('sentry.interfaces.Message' in event)
|
||||
msg = event['sentry.interfaces.Message']
|
||||
self.assertEqual(msg['message'], 'This is a test of stacks')
|
||||
|
|
|
@ -65,15 +65,15 @@ class MiddlewareTestCase(TestCase):
|
|||
self.assertEquals(len(self.client.events), 1)
|
||||
event = self.client.events.pop(0)
|
||||
|
||||
self.assertTrue('sentry.interfaces.Exception' in event)
|
||||
exc = event['sentry.interfaces.Exception']
|
||||
assert 'exception' in event
|
||||
exc = event['exception']['values'][0]
|
||||
self.assertEquals(exc['type'], 'ValueError')
|
||||
self.assertEquals(exc['value'], 'hello world')
|
||||
self.assertEquals(event['level'], logging.ERROR)
|
||||
self.assertEquals(event['message'], 'ValueError: hello world')
|
||||
|
||||
self.assertTrue('sentry.interfaces.Http' in event)
|
||||
http = event['sentry.interfaces.Http']
|
||||
assert 'request' in event
|
||||
http = event['request']
|
||||
self.assertEquals(http['url'], 'http://localhost/an-error')
|
||||
self.assertEquals(http['query_string'], 'foo=bar')
|
||||
self.assertEquals(http['method'], 'GET')
|
||||
|
|
|
@ -37,7 +37,7 @@ class SantizePasswordsProcessorTest(TestCase):
|
|||
|
||||
def test_stacktrace(self):
|
||||
data = {
|
||||
'sentry.interfaces.Stacktrace': {
|
||||
'stacktrace': {
|
||||
'frames': [{'vars': VARS}],
|
||||
}
|
||||
}
|
||||
|
@ -45,8 +45,8 @@ class SantizePasswordsProcessorTest(TestCase):
|
|||
proc = SanitizePasswordsProcessor(Mock())
|
||||
result = proc.process(data)
|
||||
|
||||
self.assertTrue('sentry.interfaces.Stacktrace' in result)
|
||||
stack = result['sentry.interfaces.Stacktrace']
|
||||
self.assertTrue('stacktrace' in result)
|
||||
stack = result['stacktrace']
|
||||
self.assertTrue('frames' in stack)
|
||||
self.assertEquals(len(stack['frames']), 1)
|
||||
frame = stack['frames'][0]
|
||||
|
@ -55,7 +55,7 @@ class SantizePasswordsProcessorTest(TestCase):
|
|||
|
||||
def test_http(self):
|
||||
data = {
|
||||
'sentry.interfaces.Http': {
|
||||
'request': {
|
||||
'data': VARS,
|
||||
'env': VARS,
|
||||
'headers': VARS,
|
||||
|
@ -66,26 +66,25 @@ class SantizePasswordsProcessorTest(TestCase):
|
|||
proc = SanitizePasswordsProcessor(Mock())
|
||||
result = proc.process(data)
|
||||
|
||||
self.assertTrue('sentry.interfaces.Http' in result)
|
||||
http = result['sentry.interfaces.Http']
|
||||
self.assertTrue('request' in result)
|
||||
http = result['request']
|
||||
for n in ('data', 'env', 'headers', 'cookies'):
|
||||
self.assertTrue(n in http)
|
||||
self._check_vars_sanitized(http[n], proc)
|
||||
|
||||
def test_querystring_as_string(self):
|
||||
data = {
|
||||
'sentry.interfaces.Http': {
|
||||
'query_string':
|
||||
'foo=bar&password=hello&the_secret=hello'
|
||||
'&a_password_here=hello&api_key=secret_key',
|
||||
'request': {
|
||||
'query_string': 'foo=bar&password=hello&the_secret=hello'
|
||||
'&a_password_here=hello&api_key=secret_key',
|
||||
}
|
||||
}
|
||||
|
||||
proc = SanitizePasswordsProcessor(Mock())
|
||||
result = proc.process(data)
|
||||
|
||||
self.assertTrue('sentry.interfaces.Http' in result)
|
||||
http = result['sentry.interfaces.Http']
|
||||
self.assertTrue('request' in result)
|
||||
http = result['request']
|
||||
self.assertEquals(
|
||||
http['query_string'],
|
||||
'foo=bar&password=%(m)s&the_secret=%(m)s'
|
||||
|
@ -93,7 +92,7 @@ class SantizePasswordsProcessorTest(TestCase):
|
|||
|
||||
def test_querystring_as_string_with_partials(self):
|
||||
data = {
|
||||
'sentry.interfaces.Http': {
|
||||
'request': {
|
||||
'query_string': 'foo=bar&password&baz=bar',
|
||||
}
|
||||
}
|
||||
|
@ -101,8 +100,8 @@ class SantizePasswordsProcessorTest(TestCase):
|
|||
proc = SanitizePasswordsProcessor(Mock())
|
||||
result = proc.process(data)
|
||||
|
||||
self.assertTrue('sentry.interfaces.Http' in result)
|
||||
http = result['sentry.interfaces.Http']
|
||||
self.assertTrue('request' in result)
|
||||
http = result['request']
|
||||
self.assertEquals(http['query_string'], 'foo=bar&password&baz=bar' % dict(m=proc.MASK))
|
||||
|
||||
def test_sanitize_credit_card(self):
|
||||
|
@ -120,7 +119,7 @@ class SantizePasswordsProcessorTest(TestCase):
|
|||
class RemovePostDataProcessorTest(TestCase):
|
||||
def test_does_remove_data(self):
|
||||
data = {
|
||||
'sentry.interfaces.Http': {
|
||||
'request': {
|
||||
'data': 'foo',
|
||||
}
|
||||
}
|
||||
|
@ -128,22 +127,22 @@ class RemovePostDataProcessorTest(TestCase):
|
|||
proc = RemovePostDataProcessor(Mock())
|
||||
result = proc.process(data)
|
||||
|
||||
self.assertTrue('sentry.interfaces.Http' in result)
|
||||
http = result['sentry.interfaces.Http']
|
||||
self.assertTrue('request' in result)
|
||||
http = result['request']
|
||||
self.assertFalse('data' in http)
|
||||
|
||||
|
||||
class RemoveStackLocalsProcessorTest(TestCase):
|
||||
def test_does_remove_data(self):
|
||||
data = {
|
||||
'sentry.interfaces.Stacktrace': {
|
||||
'frames': [{'vars': VARS,}],
|
||||
'stacktrace': {
|
||||
'frames': [{'vars': VARS}],
|
||||
}
|
||||
}
|
||||
proc = RemoveStackLocalsProcessor(Mock())
|
||||
result = proc.process(data)
|
||||
|
||||
self.assertTrue('sentry.interfaces.Stacktrace' in result)
|
||||
stack = result['sentry.interfaces.Stacktrace']
|
||||
assert 'stacktrace' in result
|
||||
stack = result['stacktrace']
|
||||
for frame in stack['frames']:
|
||||
self.assertFalse('vars' in frame)
|
||||
|
|
|
@ -4,25 +4,27 @@ from raven.utils.testutils import TestCase
|
|||
|
||||
from raven.base import Client
|
||||
from raven.transport.threaded import ThreadedHTTPTransport
|
||||
from raven.utils.urlparse import urlparse
|
||||
|
||||
|
||||
class DummyThreadedScheme(ThreadedHTTPTransport):
|
||||
|
||||
scheme = ['threaded+mock']
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ThreadedHTTPTransport, self).__init__(*args, **kwargs)
|
||||
self.events = []
|
||||
self.send_delay = 0
|
||||
|
||||
def send_sync(self, data, headers):
|
||||
self.events.append((data, headers))
|
||||
def send_sync(self, data, headers, success_cb, failure_cb):
|
||||
# delay sending the message, to allow us to test that the shutdown
|
||||
# hook waits correctly
|
||||
time.sleep(self.send_delay)
|
||||
|
||||
self.events.append((data, headers, success_cb, failure_cb))
|
||||
|
||||
|
||||
class ThreadedTransportTest(TestCase):
|
||||
def setUp(self):
|
||||
self.client = Client(
|
||||
dsn="threaded+http://some_username:some_password@localhost:8143/1",
|
||||
)
|
||||
self.url = "threaded+http://some_username:some_password@localhost:8143/1"
|
||||
self.client = Client(dsn=self.url)
|
||||
|
||||
@mock.patch('raven.transport.http.HTTPTransport.send')
|
||||
def test_does_send(self, send):
|
||||
|
@ -33,3 +35,18 @@ class ThreadedTransportTest(TestCase):
|
|||
# TODO: This test could be more precise by ensuring it's sending the same params that are sent
|
||||
# to the ThreadedHTTPTransport.send() method
|
||||
self.assertEqual(send.call_count, 1)
|
||||
|
||||
def test_shutdown_waits_for_send(self):
|
||||
url = urlparse(self.url)
|
||||
transport = DummyThreadedScheme(url)
|
||||
transport.send_delay = 0.5
|
||||
|
||||
data = self.client.build_msg('raven.events.Message', message='foo')
|
||||
transport.async_send(data, None, None, None)
|
||||
|
||||
time.sleep(0.1)
|
||||
|
||||
# this should wait for the message to get sent
|
||||
transport.get_worker().main_thread_terminated()
|
||||
|
||||
self.assertEqual(len(transport.events), 1)
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
import mock
|
||||
|
||||
from raven.base import Client
|
||||
from raven.utils.testutils import TestCase
|
||||
|
||||
|
||||
class TornadoTransportTests(TestCase):
|
||||
@mock.patch("raven.transport.tornado.HTTPClient")
|
||||
def test_send(self, fake_client):
|
||||
url = "https://user:pass@host:1234/1"
|
||||
timeout = 1
|
||||
verify_ssl = 1
|
||||
ca_certs = "/some/path/somefile"
|
||||
|
||||
fake = fake_client.return_value
|
||||
raven_client = Client(
|
||||
dsn="tornado+{0}?timeout={1}&verify_ssl={2}&ca_certs={3}".
|
||||
format(url, timeout, verify_ssl, ca_certs))
|
||||
|
||||
raven_client.captureMessage(message="test")
|
||||
|
||||
# make sure an instance of HTTPClient was created, since we are not in
|
||||
# an IOLoop
|
||||
fake_client.assert_called_once_with()
|
||||
fake_fetch = fake.fetch
|
||||
|
||||
# make sure we called fetch() which does the sending
|
||||
self.assertEqual(fake_fetch.call_count, 1)
|
||||
# only verify the special kwargs that we should be passing through,
|
||||
# no need to verify the urls and whatnot
|
||||
args, kwargs = fake_fetch.call_args
|
||||
self.assertEqual(kwargs["connect_timeout"], timeout)
|
||||
self.assertEqual(kwargs["validate_cert"], bool(verify_ssl))
|
||||
self.assertEqual(kwargs["ca_certs"], ca_certs)
|
Loading…
Reference in New Issue