Repository: DataDog/dd-agent

Issue:
override proxies for localhost?
We received [a report](https://datadog.desk.com/agent/case/14226) that when the `http_proxy` env var was set, `urllib.getproxies()` was bypassing local localhost resolution and getting the wrong thing, something like `localhost.resolv.conf.search`.  The reporter had discovered a [similar issue](https://github.com/kennethreitz/requests/issues/879) that requests dealt with.

I'm wondering if it might be a good idea to disable proxies for localhost resolution across the board to avoid this:

``` python
import os
if 'no_proxy' not in os.environ:
    os.environ['no_proxy'] = '127.0.0.1,localhost'
```

Or even something smarter which always attempts to add `127.0.0.1,localhost` to the env `no_proxy`, even if it's already set to something else.



Discussion:
Thanks for the report.

Set the milestone for 5.2.0


Resolving patch:
diff --git a/dogstatsd.py b/dogstatsd.py
--- a/dogstatsd.py
+++ b/dogstatsd.py
@@ -11,7 +11,6 @@
 os.umask(022)
 
 # stdlib
-import httplib as http_client
 import logging
 import optparse
 import re
@@ -32,6 +31,7 @@
 from util import PidFile, get_hostname, plural, get_uuid, chunks
 
 # 3rd party
+import requests
 import simplejson as json
 
 log = logging.getLogger('dogstatsd')
@@ -87,15 +87,6 @@ def __init__(self, interval, metrics_aggregator, api_host, api_key=None, use_wat
         self.api_host = api_host
         self.event_chunk_size = event_chunk_size or EVENT_CHUNK_SIZE
 
-        self.http_conn_cls = http_client.HTTPSConnection
-
-        match = re.match('^(https?)://(.*)', api_host)
-
-        if match:
-            self.api_host = match.group(2)
-            if match.group(1) == 'http':
-                self.http_conn_cls = http_client.HTTPConnection
-
     def stop(self):
         log.info("Stopping reporter")
         self.finished.set()
@@ -163,38 +154,15 @@ def flush(self):
                 log.exception("Error flushing metrics")
 
     def submit(self, metrics):
-        # Copy and pasted from dogapi, because it's a bit of a pain to distribute python
-        # dependencies with the agent.
         body, headers = serialize_metrics(metrics)
-        method = 'POST'
-
         params = {}
         if self.api_key:
             params['api_key'] = self.api_key
-        url = '/api/v1/series?%s' % urlencode(params)
-
-        start_time = time()
-        status = None
-        conn = self.http_conn_cls(self.api_host)
-        try:
-            conn.request(method, url, body, headers)
-
-            #FIXME: add timeout handling code here
-
-            response = conn.getresponse()
-            status = response.status
-            response.close()
-        finally:
-            conn.close()
-        duration = round((time() - start_time) * 1000.0, 4)
-        log.debug("%s %s %s%s (%sms)" % (
-                        status, method, self.api_host, url, duration))
-        return duration
+        url = '%s/api/v1/series?%s' % (self.api_host, urlencode(params))
+        self.submit_http(url, body, headers)
 
     def submit_events(self, events):
         headers = {'Content-Type':'application/json'}
-        method = 'POST'
-
         events_len = len(events)
         event_chunk_size = self.event_chunk_size
 
@@ -210,23 +178,38 @@ def submit_events(self, events):
             params = {}
             if self.api_key:
                 params['api_key'] = self.api_key
-            url = '/intake?%s' % urlencode(params)
+            url = '%s/intake?%s' % (self.api_host, urlencode(params))
+
+            self.submit_http(url, payload, headers)            
+
+    def submit_http(self, url, data, headers):
+        no_proxy = {
+        # See https://github.com/kennethreitz/requests/issues/879
+        # and https://github.com/DataDog/dd-agent/issues/1112
+            'no': 'pass',
+        }
+        log.debug("Posting payload to %s" % url)
+        try:
+            start_time = time()
+            r = requests.post(url, data=data, timeout=5,
+                headers=headers, proxies=no_proxy)
+
+            r.raise_for_status()
 
-            status = None
-            conn = self.http_conn_cls(self.api_host)
+            if r.status_code >= 200 and r.status_code < 205:
+                log.debug("Payload accepted")
+
+            status = r.status_code
+            duration = round((time() - start_time) * 1000.0, 4)
+            log.debug("%s POST %s (%sms)" % (
+                            status, url, duration))
+        except Exception:
+            log.exception("Unable to post payload.")
             try:
-                start_time = time()
-                conn.request(method, url, json.dumps(payload), headers)
-
-                response = conn.getresponse()
-                status = response.status
-                response.close()
-                duration = round((time() - start_time) * 1000.0, 4)
-                log.debug("%s %s %s%s (%sms)" % (
-                                status, method, self.api_host, url, duration))
-
-            finally:
-                conn.close()
+                log.error("Received status code: {0}".format(r.status_code))
+            except Exception:
+                pass
+
 
 class Server(object):
     """
diff --git a/emitter.py b/emitter.py
--- a/emitter.py
+++ b/emitter.py
@@ -18,6 +18,13 @@
 control_chars = ''.join(map(unichr, range(0,32) + range(127,160)))
 control_char_re = re.compile('[%s]' % re.escape(control_chars))
 
+NO_PROXY = {
+# See https://github.com/kennethreitz/requests/issues/879
+# and https://github.com/DataDog/dd-agent/issues/1112
+    'no': 'pass',
+}
+
+
 def remove_control_chars(s):
     return control_char_re.sub('', s)
 
@@ -45,8 +52,8 @@ def http_emitter(message, log, agentConfig):
     url = "{0}/intake?api_key={1}".format(url, apiKey)
 
     try:
-        r = requests.post(url, data=zipped, timeout=10,
-            headers=post_headers(agentConfig, zipped))
+        r = requests.post(url, data=zipped, timeout=5,
+            headers=post_headers(agentConfig, zipped), proxies=NO_PROXY)
 
         r.raise_for_status()
 


Test patch: