Skip to content

Commit

Permalink
Merge pull request #34 from KosyanMedia/tornado
Browse files Browse the repository at this point in the history
Allow to send requests with Tornado's AsyncHTTPClient
  • Loading branch information
brianr committed Nov 17, 2014
2 parents b29944e + ea946a0 commit 4f27a48
Showing 1 changed file with 51 additions and 1 deletion.
52 changes: 51 additions & 1 deletion rollbar/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,17 @@
except ImportError:
BottleRequest = None

try:
from tornado.gen import coroutine as tornado_coroutine
from tornado.httpclient import AsyncHTTPClient as TornadoAsyncHTTPClient
except ImportError:
def tornado_coroutine(func):
def wrap(*args, **kwargs):
return func(*args, **kwargs)
return wrap

TornadoAsyncHTTPClient = None


def get_request():
"""
Expand Down Expand Up @@ -154,7 +165,7 @@ def _get_pylons_request():
'root': None, # root path to your code
'branch': None, # git branch name
'code_version': None,
'handler': 'thread', # 'blocking', 'thread' or 'agent'
'handler': 'thread', # 'blocking', 'thread', 'agent' or 'tornado'
'endpoint': DEFAULT_ENDPOINT,
'timeout': DEFAULT_TIMEOUT,
'agent.log_file': 'log.rollbar',
Expand Down Expand Up @@ -268,13 +279,19 @@ def send_payload(payload):
- 'blocking': calls _send_payload() (which makes an HTTP request) immediately, blocks on it
- 'thread': starts a single-use thread that will call _send_payload(). returns immediately.
- 'agent': writes to a log file to be processed by rollbar-agent
- 'tornado': calls _send_payload_tornado() (which makes an async HTTP request using tornado's AsyncHTTPClient)
"""
handler = SETTINGS.get('handler')
if handler == 'blocking':
_send_payload(payload)
elif handler == 'agent':
payload = ErrorIgnoringJSONEncoder().encode(payload)
agent_log.error(payload)
elif handler == 'tornado':
if TornadoAsyncHTTPClient is None:
log.error('Unable to find tornado')
return
_send_payload_tornado(payload)
else:
# default to 'thread'
thread = threading.Thread(target=_send_payload, args=(payload,))
Expand Down Expand Up @@ -987,6 +1004,7 @@ def _post_api(path, payload, access_token=None):
payload = ErrorIgnoringJSONEncoder().encode(payload)

url = urlparse.urljoin(SETTINGS['endpoint'], path)

resp = requests.post(url, data=payload, headers=headers, timeout=SETTINGS.get('timeout', DEFAULT_TIMEOUT))
return _parse_response(path, SETTINGS['access_token'], payload, resp)

Expand All @@ -999,6 +1017,38 @@ def _get_api(path, access_token=None, endpoint=None, **params):
return _parse_response(path, access_token, params, resp, endpoint=endpoint)


def _send_payload_tornado(payload):
try:
_post_api_tornado('item/', payload, access_token=payload.get('access_token'))
except Exception as e:
log.exception('Exception while posting item %r', e)


@tornado_coroutine
def _post_api_tornado(path, payload, access_token=None):
headers = {'Content-Type': 'application/json'}

if access_token is not None:
headers['X-Rollbar-Access-Token'] = access_token

# Serialize this ourselves so we can handle error cases more gracefully
payload = ErrorIgnoringJSONEncoder().encode(payload)

url = urlparse.urljoin(SETTINGS['endpoint'], path)

resp = yield TornadoAsyncHTTPClient().fetch(
url, body=payload, method='POST', connect_timeout=SETTINGS.get('timeout', DEFAULT_TIMEOUT),
request_timeout=SETTINGS.get('timeout', DEFAULT_TIMEOUT)
)

r = requests.Response()
r._content = resp.body
r.status_code = resp.code
r.headers.update(resp.headers)

_parse_response(path, SETTINGS['access_token'], payload, r)


def _parse_response(path, access_token, params, resp, endpoint=None):
if resp.status_code == 429:
log.warning("Rollbar: over rate limit, data was dropped. Payload was: %r", params)
Expand Down

0 comments on commit 4f27a48

Please sign in to comment.