Repository: DataDog/dd-trace-py

Issue:
Profile exporter crashes when DD_VERSION is used
The profile exporter is crashing due to `DD_VERSION` not being encoded before generating the export request. Looking at the code the same applies probably to `DD_ENV` as well.

Lines missing `.decode("utf-8")`: https://github.com/DataDog/dd-trace-py/blob/6a14a9ba75a6866d968ddf0eb84b8fee5bd3f49c/ddtrace/profiling/exporter/http.py#L144-L150

**Sentry traceback**
![image](https://user-images.githubusercontent.com/74944/80689205-43e17800-8acd-11ea-9068-87b76e106660.png)

### Which version of dd-trace-py are you using?

0.37.0

### Which version of the libraries are you using?

N/A

### How can we reproduce your problem?

```
DD_VERSION=foobar pyddprofile ...
```


Discussion:

Resolving patch:
diff --git a/ddtrace/profiling/exporter/http.py b/ddtrace/profiling/exporter/http.py
--- a/ddtrace/profiling/exporter/http.py
+++ b/ddtrace/profiling/exporter/http.py
@@ -143,11 +143,11 @@ def _get_tags(service):
 
         version = os.environ.get("DD_VERSION")
         if version:
-            tags["version"] = version
+            tags["version"] = version.encode("utf-8")
 
         env = os.environ.get("DD_ENV")
         if env:
-            tags["env"] = env
+            tags["env"] = env.encode("utf-8")
 
         user_tags = parse_tags_str(os.environ.get("DD_TAGS", {}))
         user_tags.update(parse_tags_str(os.environ.get("DD_PROFILING_TAGS", {})))


Test patch:
diff --git a/tests/profiling/exporter/test_http.py b/tests/profiling/exporter/test_http.py
--- a/tests/profiling/exporter/test_http.py
+++ b/tests/profiling/exporter/test_http.py
@@ -218,8 +218,15 @@ def test_default_from_env(monkeypatch):
     assert exp.service_name == "myservice"
 
 
+def _check_tags_types(tags):
+    for k, v in tags.items():
+        assert isinstance(k, str)
+        assert isinstance(v, bytes)
+
+
 def test_get_tags():
     tags = http.PprofHTTPExporter()._get_tags("foobar")
+    _check_tags_types(tags)
     assert len(tags) == 7
     assert tags["service"] == b"foobar"
     assert len(tags["host"])
@@ -233,6 +240,7 @@ def test_get_tags():
 def test_get_malformed(monkeypatch):
     monkeypatch.setenv("DD_TAGS", "mytagfoobar")
     tags = http.PprofHTTPExporter()._get_tags("foobar")
+    _check_tags_types(tags)
     assert len(tags) == 7
     assert tags["service"] == b"foobar"
     assert len(tags["host"])
@@ -243,6 +251,7 @@ def test_get_malformed(monkeypatch):
 
     monkeypatch.setenv("DD_TAGS", "mytagfoobar,")
     tags = http.PprofHTTPExporter()._get_tags("foobar")
+    _check_tags_types(tags)
     assert len(tags) == 7
     assert tags["service"] == b"foobar"
     assert len(tags["host"])
@@ -253,6 +262,7 @@ def test_get_malformed(monkeypatch):
 
     monkeypatch.setenv("DD_TAGS", ",")
     tags = http.PprofHTTPExporter()._get_tags("foobar")
+    _check_tags_types(tags)
     assert len(tags) == 7
     assert tags["service"] == b"foobar"
     assert len(tags["host"])
@@ -263,6 +273,7 @@ def test_get_malformed(monkeypatch):
 
     monkeypatch.setenv("DD_TAGS", "foo:bar,")
     tags = http.PprofHTTPExporter()._get_tags("foobar")
+    _check_tags_types(tags)
     assert len(tags) == 8
     assert tags["service"] == b"foobar"
     assert len(tags["host"])
@@ -276,6 +287,7 @@ def test_get_malformed(monkeypatch):
 def test_get_tags_override(monkeypatch):
     monkeypatch.setenv("DD_TAGS", "mytag:foobar")
     tags = http.PprofHTTPExporter()._get_tags("foobar")
+    _check_tags_types(tags)
     assert len(tags) == 8
     assert tags["service"] == b"foobar"
     assert len(tags["host"])
@@ -288,6 +300,7 @@ def test_get_tags_override(monkeypatch):
 
     monkeypatch.setenv("DD_TAGS", "mytag:foobar,author:jd")
     tags = http.PprofHTTPExporter()._get_tags("foobar")
+    _check_tags_types(tags)
     assert len(tags) == 9
     assert tags["service"] == b"foobar"
     assert len(tags["host"])
@@ -301,6 +314,7 @@ def test_get_tags_override(monkeypatch):
 
     monkeypatch.setenv("DD_TAGS", "")
     tags = http.PprofHTTPExporter()._get_tags("foobar")
+    _check_tags_types(tags)
     assert len(tags) == 7
     assert tags["service"] == b"foobar"
     assert len(tags["host"])
@@ -312,6 +326,7 @@ def test_get_tags_override(monkeypatch):
 
     monkeypatch.setenv("DD_TAGS", "foobar:baz,service:mycustomservice")
     tags = http.PprofHTTPExporter()._get_tags("foobar")
+    _check_tags_types(tags)
     assert len(tags) == 8
     assert tags["service"] == b"mycustomservice"
     assert len(tags["host"])
@@ -324,6 +339,7 @@ def test_get_tags_override(monkeypatch):
 
     monkeypatch.setenv("DD_TAGS", "foobar:baz,service:🤣")
     tags = http.PprofHTTPExporter()._get_tags("foobar")
+    _check_tags_types(tags)
     assert len(tags) == 8
     assert tags["service"] == u"🤣".encode("utf-8")
     assert len(tags["host"])
@@ -336,6 +352,7 @@ def test_get_tags_override(monkeypatch):
 
     monkeypatch.setenv("DD_VERSION", "123")
     tags = http.PprofHTTPExporter()._get_tags("foobar")
+    _check_tags_types(tags)
     assert len(tags) == 9
     assert tags["service"] == u"🤣".encode("utf-8")
     assert len(tags["host"])
@@ -344,11 +361,12 @@ def test_get_tags_override(monkeypatch):
     assert tags["runtime"] == b"CPython"
     assert tags["foobar"] == b"baz"
     assert tags["profiler_version"] == ddtrace.__version__.encode("utf-8")
-    assert tags["version"] == "123"
+    assert tags["version"] == b"123"
     assert "env" not in tags
 
     monkeypatch.setenv("DD_ENV", "prod")
     tags = http.PprofHTTPExporter()._get_tags("foobar")
+    _check_tags_types(tags)
     assert len(tags) == 10
     assert tags["service"] == u"🤣".encode("utf-8")
     assert len(tags["host"])
@@ -357,19 +375,21 @@ def test_get_tags_override(monkeypatch):
     assert tags["runtime"] == b"CPython"
     assert tags["foobar"] == b"baz"
     assert tags["profiler_version"] == ddtrace.__version__.encode("utf-8")
-    assert tags["version"] == "123"
-    assert tags["env"] == "prod"
+    assert tags["version"] == b"123"
+    assert tags["env"] == b"prod"
 
 
 def test_get_tags_legacy(monkeypatch):
     monkeypatch.setenv("DD_PROFILING_TAGS", "mytag:baz")
     tags = http.PprofHTTPExporter()._get_tags("foobar")
+    _check_tags_types(tags)
     assert tags["mytag"] == b"baz"
 
     # precedence
     monkeypatch.setenv("DD_TAGS", "mytag:val1,ddtag:hi")
     monkeypatch.setenv("DD_PROFILING_TAGS", "mytag:val2,ddptag:lo")
     tags = http.PprofHTTPExporter()._get_tags("foobar")
+    _check_tags_types(tags)
     assert tags["mytag"] == b"val2"
     assert tags["ddtag"] == b"hi"
     assert tags["ddptag"] == b"lo"