asyncio support

This commit is contained in:
Andrew Svetlov 2014-05-19 01:57:21 +03:00
parent 300451cf27
commit 8a9536aeed
3 changed files with 83 additions and 0 deletions

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.asyncio import * # NOQA

View File

@ -0,0 +1,72 @@
"""
raven.transport.asyncio
~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: (c) 2010-2014 by the Sentry Team, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""
from __future__ import absolute_import
import logging
from raven.transport.base import AsyncTransport
from raven.transport.http import HTTPTransport
from raven.transport.udp import BaseUDPTransport
try:
import asyncio
import aiohttp
has_asyncio = True
except:
has_asyncio = False
class AsyncioHttpTransport(AsyncTransport, HTTPTransport):
scheme = ['asyncio+http', 'asyncio+https']
def __init__(self, parsed_url, *, loop=None):
if not has_asyncio:
raise ImportError('AIOHttpTransport requires asyncio and aiohttp.')
if loop is None:
loop = asyncio.get_event_loop()
self._loop = loop
super().__init__(parsed_url)
self.logger = logging.getLogger('sentry.errors')
# remove the aiohttp+ from the protocol, as it is not a real protocol
self._url = self._url.split('+', 1)[-1]
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,
loop=self._loop)
resp.close()
success_cb()
except Exception as exc:
failure_cb(exc)
asyncio.async(f(), loop=self._loop)
class AsyncioUDPTransport(BaseUDPTransport):
scheme = ['asyncio+udp']
def __init__(self, parsed_url, *, loop=None):
super().__init__(parsed_url)
if not has_asyncio:
raise ImportError('AsyncioUDPTransport requires asyncio.')
if loop is None:
loop = asyncio.get_event_loop()
self._loop = loop
self._transport, _ = loop.run_until_complete(
loop.create_datagram_endpoint(asyncio.DatagramProtocol))
def _send_data(self, data, addr):
self._transport.send_to(data, addr)

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.asyncio import AsyncioHttpTransport
class TransportRegistry(object):
def __init__(self, transports=None):
@ -78,3 +82,6 @@ default_transports = [
UDPTransport,
EventletHTTPTransport,
]
if sys.version_info() >= (3.3):
default_transports += [AsyncioHttpTransport,]