Merge pull request #461 from asvetlov/master

Add asyncio aiohttp transport for raven-python
This commit is contained in:
David Cramer 2014-06-26 11:35:44 -07:00
commit 133fcdb748
6 changed files with 108 additions and 3 deletions

View File

@ -9,6 +9,8 @@ This document describes configuration options available to Sentry.
.. toctree::
:maxdepth: 2
aiohttp
asyncio
bottle
celery
django
@ -62,7 +64,11 @@ It is composed of six important pieces:
* The project ID which the authenticated user is bound to.
.. note:: Protocol may also contain transporter type: gevent+http, gevent+https, twisted+http, tornado+http, eventlet+http, eventlet+https
.. note::
Protocol may also contain transporter type: gevent+http, gevent+https, twisted+http, tornado+http, eventlet+http, eventlet+https
For *Python 3.3+* also available: aiohttp+http and aiohttp+https
Client Arguments
----------------

View File

@ -25,6 +25,16 @@ For example, to increase the timeout and to disable SSL verification:
SENTRY_DSN = 'http://public:secret@example.com/1?timeout=5&verify_ssl=0'
aiohttp
-------
Should only be used within a :pep:`3156` compatible event loops
(*asyncio* itself and others).
::
SENTRY_DSN = 'aiohttp+http://public:secret@example.com/1'
Eventlet
--------

View File

@ -8,6 +8,7 @@ raven.transport
# TODO: deprecate this namespace and force non-default (sync + threaded) to
# manually import/register transports somehow
from __future__ import absolute_import
import sys
from raven.transport.base import * # NOQA
from raven.transport.eventlet import * # NOQA
@ -20,3 +21,6 @@ from raven.transport.twisted import * # NOQA
from raven.transport.threaded import * # NOQA
from raven.transport.tornado import * # NOQA
from raven.transport.udp import * # NOQA
if sys.version_info >= (3, 3):
from raven.transport.aiohttp import * # NOQA

View File

@ -0,0 +1,73 @@
"""
raven.transport.aiohttp
~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: (c) 2010-2014 by the Sentry Team, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""
# Skip flake8, python2 version doesn't recognize `yield from` statement
# flake8: noqa
from __future__ import absolute_import
from raven.exceptions import APIError, RateLimited
from raven.transport.base import AsyncTransport
from raven.transport.http import HTTPTransport
import socket
try:
import aiohttp
import asyncio
has_aiohttp = True
except:
has_aiohttp = False
class AioHttpTransport(AsyncTransport, HTTPTransport):
scheme = ['aiohttp+http', 'aiohttp+https']
def __init__(self, parsed_url, *, verify_ssl=True, resolve=True,
keepalive=True, family=socket.AF_INET, loop=None):
if not has_aiohttp:
raise ImportError('AioHttpTransport requires asyncio and aiohttp.')
if loop is None:
loop = asyncio.get_event_loop()
self._loop = loop
super().__init__(parsed_url)
if keepalive:
self._connector = aiohttp.TCPConnector(verify_ssl=verify_ssl,
resolve=resolve)
else:
self._connector = None
def async_send(self, data, headers, success_cb, failure_cb):
@asyncio.coroutine
def f():
try:
resp = yield from aiohttp.request('POST',
self._url, data=data,
headers=headers,
connector=self._connector,
loop=self._loop)
resp.close()
code = resp.status
if code != 200:
msg = resp.headers.get('x-sentry-error')
if code == 429:
try:
retry_after = int(resp.headers.get('retry-after'))
except (ValueError, TypeError):
retry_after = 0
failure_cb(RateLimited(msg, retry_after))
else:
failure_cb(APIError(msg, code))
else:
success_cb()
except Exception as exc:
failure_cb(exc)
asyncio.async(f(), loop=self._loop)

View File

@ -6,6 +6,7 @@ raven.transport.registry
:license: BSD, see LICENSE for more details.
"""
from __future__ import absolute_import
import sys
# TODO(dcramer): we really should need to import all of these by default
from raven.transport.eventlet import EventletHTTPTransport
@ -19,6 +20,9 @@ from raven.transport.tornado import TornadoHTTPTransport
from raven.transport.udp import UDPTransport
from raven.utils import urlparse
if sys.version_info >= (3, 3):
from raven.transport.aiohttp import AioHttpTransport
class TransportRegistry(object):
def __init__(self, transports=None):
@ -78,3 +82,6 @@ default_transports = [
UDPTransport,
EventletHTTPTransport,
]
if sys.version_info >= (3, 3):
default_transports += [AioHttpTransport]

View File

@ -54,6 +54,11 @@ if sys.version_info[0] == 3:
unittest2_requires = []
webpy_tests_requires = []
if sys.version_info >= (3, 3):
aiohttp_requires = ['aiohttp']
else:
aiohttp_requires = []
tests_require = [
'bottle',
@ -74,8 +79,8 @@ tests_require = [
'webob',
'webtest',
'anyjson',
] + (flask_requires + flask_tests_requires + unittest2_requires +
webpy_tests_requires)
] + (aiohttp_requires + flask_requires + flask_tests_requires +
unittest2_requires + webpy_tests_requires)
class PyTest(TestCommand):