Skip to content

Commit

Permalink
[api] static APIClient class
Browse files Browse the repository at this point in the history
Following @degemer's feedback:
* Make `APIClient` class 100% static
* Rewrite the `resolve_http_client` logic in the `HTTPClient` class
  • Loading branch information
yannmh committed May 26, 2016
1 parent 49cf300 commit 844e0b8
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 52 deletions.
30 changes: 19 additions & 11 deletions datadog/api/api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from datadog.api import _api_version, _max_timeouts, _backoff_period
from datadog.api.exceptions import ClientError, ApiError, HttpBackoff, \
HttpTimeout, ApiNotInitialized
from datadog.api.http_client import get_http_client
from datadog.api.http_client import resolve_http_client
from datadog.util.compat import json, is_p3k


Expand All @@ -25,13 +25,21 @@ class APIClient(object):
_timeout_counter = 0
_api_version = _api_version

def __init__(self):
# Plugged HTTP client
_http_client = None

@classmethod
def _get_http_client(cls):
"""
Instantiate the client. Plug a HTTP client.
Getter for the embedded HTTP client.
"""
self._http_client = get_http_client()
if not cls._http_client:
cls._http_client = resolve_http_client()

def submit(self, method, path, body=None, attach_host_name=False, response_formatter=None,
return cls._http_client

@classmethod
def submit(cls, method, path, body=None, attach_host_name=False, response_formatter=None,
error_formatter=None, **params):
"""
Make an HTTP API request
Expand Down Expand Up @@ -61,8 +69,8 @@ def submit(self, method, path, body=None, attach_host_name=False, response_forma
"""
try:
# Check if it's ok to submit
if not self._should_submit():
_, backoff_time_left = self._backoff_status()
if not cls._should_submit():
_, backoff_time_left = cls._backoff_status()
raise HttpBackoff(backoff_time_left)

# Import API, User and HTTP settings
Expand Down Expand Up @@ -103,14 +111,14 @@ def submit(self, method, path, body=None, attach_host_name=False, response_forma
# Construct the URL
url = "{api_host}/api/{api_version}/{path}".format(
api_host=_api_host,
api_version=self._api_version,
api_version=cls._api_version,
path=path.lstrip("/"),
)

# Process requesting
start_time = time.time()

result = self._http_client.request(
result = cls._get_http_client().request(
method=method, url=url,
headers=headers, params=params, data=body,
timeout=_timeout, max_retries=_max_retries,
Expand All @@ -120,7 +128,7 @@ def submit(self, method, path, body=None, attach_host_name=False, response_forma
# Request succeeded: log it and reset the timeout counter
duration = round((time.time() - start_time) * 1000., 4)
log.info("%s %s %s (%sms)" % (result.status_code, method, url, duration))
self._timeout_counter = 0
cls._timeout_counter = 0

# Format response content
content = result.content
Expand All @@ -144,7 +152,7 @@ def submit(self, method, path, body=None, attach_host_name=False, response_forma
return response_formatter(response_obj)

except HttpTimeout:
self._timeout_counter += 1
cls._timeout_counter += 1
raise
except ClientError as e:
if _mute:
Expand Down
45 changes: 22 additions & 23 deletions datadog/api/http_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,20 @@
import logging
import urllib

# 3p
try:
import requests
except ImportError:
requests = None

try:
from google.appengine.api import urlfetch, urlfetch_errors
except ImportError:
urlfetch, urlfetch_errors = None, None

# datadog
from datadog.api.exceptions import ClientError, HTTPError, HttpTimeout

requests = None
urlfetch = None
urlfetch_errors = None

log = logging.getLogger('dd.datadogpy')

Expand Down Expand Up @@ -138,28 +146,19 @@ def raise_on_status(cls, result):
raise HTTPError(status_code)


HTTP_CLIENTS = [RequestClient, URLFetchClient]


def get_http_client():
def resolve_http_client():
"""
Return the appropriate HTTP client based the defined priority and user environment.
Resolve an appropriate HTTP client based the defined priority and user environment.
"""
global requests
global urlfetch
global urlfetch_errors

try:
import requests
if requests:
log.debug(u"Use `requests` based HTTP client.")
return RequestClient
except ImportError:
pass

try:
from google.appengine.api import urlfetch, urlfetch_errors
if urlfetch and urlfetch_errors:
log.debug(u"Use `urlfetch` based HTTP client.")
return URLFetchClient
except ImportError:
raise ImportError(
u"Datadog API client was unable to resolve a HTTP client. "
u" Please install `requests` library."
)

raise ImportError(
u"Datadog API client was unable to resolve a HTTP client. "
u" Please install `requests` library."
)
36 changes: 18 additions & 18 deletions datadog/api/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ def create(cls, attach_host_name=False, method='POST', id=None, params=None, **b
if params is None:
params = {}
if method == 'GET':
return APIClient().submit('GET', cls._class_url, **body)
return APIClient.submit('GET', cls._class_url, **body)
if id is None:
return APIClient().submit('POST', cls._class_url, body,
attach_host_name=attach_host_name, **params)
return APIClient.submit('POST', cls._class_url, body,
attach_host_name=attach_host_name, **params)
else:
return APIClient().submit('POST', cls._class_url + "/" + str(id), body,
attach_host_name=attach_host_name, **params)
return APIClient.submit('POST', cls._class_url + "/" + str(id), body,
attach_host_name=attach_host_name, **params)


class SendableAPIResource(object):
Expand All @@ -70,11 +70,11 @@ def send(cls, attach_host_name=False, id=None, **body):
:returns: JSON response from HTTP API request
"""
if id is None:
return APIClient().submit('POST', cls._class_url, body,
attach_host_name=attach_host_name)
return APIClient.submit('POST', cls._class_url, body,
attach_host_name=attach_host_name)
else:
return APIClient().submit('POST', cls._class_url + "/" + str(id), body,
attach_host_name=attach_host_name)
return APIClient.submit('POST', cls._class_url + "/" + str(id), body,
attach_host_name=attach_host_name)


class UpdatableAPIResource(object):
Expand All @@ -96,7 +96,7 @@ def update(cls, id, params=None, **body):
"""
if params is None:
params = {}
return APIClient().submit('PUT', cls._class_url + "/" + str(id), body, **params)
return APIClient.submit('PUT', cls._class_url + "/" + str(id), body, **params)


class DeletableAPIResource(object):
Expand All @@ -113,7 +113,7 @@ def delete(cls, id, **params):
:returns: JSON response from HTTP API request
"""
return APIClient().submit('DELETE', cls._class_url + "/" + str(id), **params)
return APIClient.submit('DELETE', cls._class_url + "/" + str(id), **params)


class GetableAPIResource(object):
Expand All @@ -133,7 +133,7 @@ def get(cls, id, **params):
:returns: JSON response from HTTP API request
"""
return APIClient().submit('GET', cls._class_url + "/" + str(id), **params)
return APIClient.submit('GET', cls._class_url + "/" + str(id), **params)


class ListableAPIResource(object):
Expand All @@ -150,7 +150,7 @@ def get_all(cls, **params):
:returns: JSON response from HTTP API request
"""
return APIClient().submit('GET', cls._class_url, **params)
return APIClient.submit('GET', cls._class_url, **params)


class SearchableAPIResource(object):
Expand All @@ -167,7 +167,7 @@ def _search(cls, **params):
:returns: JSON response from HTTP API request
"""
return APIClient().submit('GET', cls._class_url, **params)
return APIClient.submit('GET', cls._class_url, **params)


class ActionAPIResource(object):
Expand All @@ -194,9 +194,9 @@ def _trigger_class_action(cls, method, name, id=None, **params):
:returns: JSON response from HTTP API request
"""
if id is None:
return APIClient().submit(method, cls._class_url + "/" + name, params)
return APIClient.submit(method, cls._class_url + "/" + name, params)
else:
return APIClient().submit(method, cls._class_url + "/" + str(id) + "/" + name, params)
return APIClient.submit(method, cls._class_url + "/" + str(id) + "/" + name, params)

@classmethod
def _trigger_action(cls, method, name, id=None, **params):
Expand All @@ -218,6 +218,6 @@ def _trigger_action(cls, method, name, id=None, **params):
:returns: JSON response from HTTP API request
"""
if id is None:
return APIClient().submit(method, name, params)
return APIClient.submit(method, name, params)
else:
return APIClient().submit(method, name + "/" + str(id), params)
return APIClient.submit(method, name + "/" + str(id), params)

0 comments on commit 844e0b8

Please sign in to comment.