Repository: DataDog/datadogpy

Issue:
DD_ENV (SERVICE, VERSION) are not used in ThreadStats
https://github.com/DataDog/datadogpy/pull/548 added support for taking unified tags from env vars, but it doesn't works when using ThreadStats in the following way:

```
>>> from datadog import initialize, ThreadStats
>>> initialize(api_key='my_api_key')
>>> stats = ThreadStats()
>>> stats.start()
```

Comments:

Patch:
diff --git a/datadog/threadstats/base.py b/datadog/threadstats/base.py
index 5fc8a4e..84041bb 100644
--- a/datadog/threadstats/base.py
+++ b/datadog/threadstats/base.py
@@ -31,6 +31,12 @@ from datadog.threadstats.reporters import HttpReporter
 # Loggers
 log = logging.getLogger('datadog.threadstats')
 
+DD_ENV_TAGS_MAPPING = {
+    'DD_ENV': 'env',
+    'DD_SERVICE': 'service',
+    'DD_VERSION': 'version',
+}
+
 
 class ThreadStats(object):
 
@@ -48,11 +54,27 @@ class ThreadStats(object):
         :type compress_payload: bool
 
         :envvar DATADOG_TAGS: Tags to attach to every metric reported by ThreadStats client
-        :type DATADOG_TAGS: list of strings
+        :type DATADOG_TAGS: comma-delimited string
+
+        :envvar DD_ENV: the env of the service running the ThreadStats client.
+        If set, it is appended to the constant (global) tags of the client.
+        :type DD_ENV: string
+
+        :envvar DD_SERVICE: the name of the service running the ThreadStats client.
+        If set, it is appended to the constant (global) tags of the client.
+        :type DD_SERVICE: string
+
+        :envvar DD_VERSION: the version of the service running the ThreadStats client.
+        If set, it is appended to the constant (global) tags of the client.
+        :type DD_VERSION: string
         """
         # Parameters
         self.namespace = namespace
         env_tags = [tag for tag in os.environ.get('DATADOG_TAGS', '').split(',') if tag]
+        for var, tag_name in DD_ENV_TAGS_MAPPING.items():
+            value = os.environ.get(var, '')
+            if value:
+                env_tags.append('{name}:{value}'.format(name=tag_name, value=value))
         if constant_tags is None:
             constant_tags = []
         self.constant_tags = constant_tags + env_tags


Test patch:
diff --git a/tests/unit/threadstats/test_threadstats.py b/tests/unit/threadstats/test_threadstats.py
index bc1b9c1..998633b 100644
--- a/tests/unit/threadstats/test_threadstats.py
+++ b/tests/unit/threadstats/test_threadstats.py
@@ -18,7 +18,7 @@ from mock import patch
 # datadog
 from datadog import ThreadStats, lambda_metric, datadog_lambda_wrapper
 from datadog.threadstats.aws_lambda import _get_lambda_stats
-from tests.util.contextmanagers import preserve_environment_variable
+from tests.util.contextmanagers import preserve_environment_variable, EnvVars
 
 # Silence the logger.
 logger = logging.getLogger('dd.datadogpy')
@@ -772,6 +772,31 @@ class TestUnitThreadStats(unittest.TestCase):
         assert event['tags'] == [event1_tag] + constant_tags + test_tags
         dog.start(flush_interval=1, roll_up_interval=1)
 
+    def test_tags_from_environment_env_service_version(self):
+        test_tags = set(['env:staging', 'service:food', 'version:1.2.3'])
+        with EnvVars(
+            env_vars={
+                "DD_ENV": "staging",
+                "DD_VERSION": "1.2.3",
+                "DD_SERVICE": "food",
+            }
+        ):
+            dog = ThreadStats()
+        dog.start(roll_up_interval=10, flush_in_thread=False)
+        reporter = dog.reporter = MemoryReporter()
+
+        # Add two events
+        event1_title = "Event 1 title"
+        event1_text = "Event 1 text"
+        dog.event(event1_title, event1_text)
+
+        # Flush and test
+        dog.flush()
+        [event1] = reporter.events
+        assert event1['title'] == event1_title
+        assert event1['text'] == event1_text
+        assert set(event1['tags']) == test_tags
+
     def test_metric_type(self):
         """
         Checks the submitted metric's metric type.