Merge pull request #461 from asvetlov/master
Add asyncio aiohttp transport for raven-python
This commit is contained in:
commit
133fcdb748
|
@ -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
|
||||
----------------
|
||||
|
|
|
@ -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
|
||||
--------
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
|
@ -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]
|
||||
|
|
9
setup.py
9
setup.py
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue