def test_get_tags_override(monkeypatch): monkeypatch.setenv("DD_PROFILING_TAGS", "mytag:foobar") tags = http.PprofHTTPExporter()._get_tags("foobar") assert len(tags) == 8 assert tags["service"] == b"foobar" assert len(tags["host"]) assert len(tags["runtime-id"]) assert tags["language"] == b"python" assert tags["runtime"] == b"CPython" assert tags["mytag"] == b"foobar" assert tags["profiler_version"] == ddtrace.__version__.encode("utf-8") monkeypatch.setenv("DD_PROFILING_TAGS", "mytag:foobar,author:jd") tags = http.PprofHTTPExporter()._get_tags("foobar") assert len(tags) == 9 assert tags["service"] == b"foobar" assert len(tags["host"]) assert len(tags["runtime-id"]) assert tags["language"] == b"python" assert tags["runtime"] == b"CPython" assert tags["mytag"] == b"foobar" assert tags["author"] == b"jd" assert tags["profiler_version"] == ddtrace.__version__.encode("utf-8") monkeypatch.setenv("DD_PROFILING_TAGS", "") tags = http.PprofHTTPExporter()._get_tags("foobar") assert len(tags) == 7 assert tags["service"] == b"foobar" assert len(tags["host"]) assert len(tags["runtime-id"]) assert tags["language"] == b"python" assert tags["runtime"] == b"CPython" assert tags["profiler_version"] == ddtrace.__version__.encode("utf-8") monkeypatch.setenv("DD_PROFILING_TAGS", "foobar:baz,service:mycustomservice") tags = http.PprofHTTPExporter()._get_tags("foobar") assert len(tags) == 8 assert tags["service"] == b"mycustomservice" assert len(tags["host"]) assert len(tags["runtime-id"]) assert tags["language"] == b"python" assert tags["runtime"] == b"CPython" assert tags["foobar"] == b"baz" assert tags["profiler_version"] == ddtrace.__version__.encode("utf-8") monkeypatch.setenv("DD_PROFILING_TAGS", "foobar:baz,service:🤣") tags = http.PprofHTTPExporter()._get_tags("foobar") assert len(tags) == 8 assert tags["service"] == u"🤣".encode("utf-8") assert len(tags["host"]) assert len(tags["runtime-id"]) assert tags["language"] == b"python" assert tags["runtime"] == b"CPython" assert tags["foobar"] == b"baz" assert tags["profiler_version"] == ddtrace.__version__.encode("utf-8")
def test_get_tags_legacy(monkeypatch): monkeypatch.setenv("DD_PROFILING_TAGS", "mytag:baz") tags = http.PprofHTTPExporter(endpoint="")._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(endpoint="")._get_tags("foobar") _check_tags_types(tags) assert tags["mytag"] == b"val2" assert tags["ddtag"] == b"hi" assert tags["ddptag"] == b"lo"
def test_export_tracer_base_path(endpoint_test_server): # Base path is prepended to the endpoint path because # it does not start with a slash. exp = http.PprofHTTPExporter(_ENDPOINT + "/profiling/", _API_KEY, endpoint_path="v1/input") exp.export(test_pprof.TEST_EVENTS, 0, compat.time_ns())
def _build_default_exporters( tracer, # type: Optional[ddtrace.Tracer] url, # type: Optional[str] service, # type: Optional[str] env, # type: Optional[str] version, # type: Optional[str] ): # type: (...) -> List[exporter.Exporter] _OUTPUT_PPROF = os.environ.get("DD_PROFILING_OUTPUT_PPROF") if _OUTPUT_PPROF: return [ file.PprofFileExporter(_OUTPUT_PPROF), ] api_key = _get_api_key() if api_key is None: # Agent mode endpoint_path = "/profiling/v1/input" else: endpoint_path = "/v1/input" endpoint = _get_default_url(tracer, api_key) if url is None else url return [ http.PprofHTTPExporter( service=service, env=env, version=version, api_key=api_key, endpoint=endpoint, endpoint_path=endpoint_path, ), ]
def test_export_404_agent(endpoint_test_unknown_server): exp = http.PprofHTTPExporter(_UNKNOWN_ENDPOINT) with pytest.raises(exporter.ExportError) as t: exp.export(test_pprof.TEST_EVENTS, 0, 1) assert str(t.value) == ( "Datadog Agent is not accepting profiles. " "Agent-based profiling deployments require Datadog Agent >= 7.20")
def test_export_server_down(): exp = http.PprofHTTPExporter("http://localhost:2", _API_KEY) with pytest.raises(http.UploadFailed) as t: exp.export(test_pprof.TEST_EVENTS, 0, 1) e = t.exception assert isinstance(e, (IOError, OSError)) assert e.errno == errno.ECONNREFUSED
def _build_default_exporters(service, env, version): _OUTPUT_PPROF = os.environ.get("DD_PROFILING_OUTPUT_PPROF") if _OUTPUT_PPROF: return [ file.PprofFileExporter(_OUTPUT_PPROF), ] api_key = _get_api_key() if api_key: # Agentless mode endpoint = _get_endpoint() else: hostname = os.environ.get( "DD_AGENT_HOST", os.environ.get("DATADOG_TRACE_AGENT_HOSTNAME", "localhost")) port = int(os.environ.get("DD_TRACE_AGENT_PORT", 8126)) endpoint = os.environ.get("DD_TRACE_AGENT_URL", "http://%s:%d" % (hostname, port)) + "/profiling/v1/input" return [ http.PprofHTTPExporter(service=service, env=env, version=version, api_key=api_key, endpoint=endpoint), ]
def test_export_timeout(endpoint_test_timeout_server): exp = http.PprofHTTPExporter(_TIMEOUT_ENDPOINT, _API_KEY, timeout=1, max_retry_delay=2) with pytest.raises(http.UploadFailed) as t: exp.export(test_pprof.TEST_EVENTS, 0, 1) e = t.value.last_attempt.exception() assert isinstance(e, socket.timeout) assert str(t.value) == "timed out"
def test_export_server_down(): exp = http.PprofHTTPExporter("http://localhost:2", _API_KEY, max_retry_delay=2) with pytest.raises(http.UploadFailed) as t: exp.export(test_pprof.TEST_EVENTS, 0, 1) e = t.value.last_attempt.exception() assert isinstance(e, (IOError, OSError)) assert str(t.value).startswith("[Errno ")
def test_export_tracer_base_path_agent_less(endpoint_test_server): # Base path is ignored by the profiling HTTP exporter # because the endpoint path starts with a slash. exp = http.PprofHTTPExporter(_ENDPOINT + "/profiling/", _API_KEY, endpoint_path="/profiling/v1/input") exp.export(test_pprof.TEST_EVENTS, 0, compat.time_ns())
def test_export_server_down(): exp = http.PprofHTTPExporter("http://localhost:2", _API_KEY, max_retry_delay=10) with pytest.raises(http.UploadFailed) as t: exp.export(test_pprof.TEST_EVENTS, 0, 1) e = t.value.exception assert isinstance(e, error.URLError) assert isinstance(e.reason, (IOError, OSError)) assert e.reason.errno in (errno.ECONNREFUSED, errno.EADDRNOTAVAIL)
def test_wrong_api_key(endpoint_test_server): # This is mostly testing our test server, not the exporter exp = http.PprofHTTPExporter(_ENDPOINT, "this is not the right API key", max_retry_delay=2) with pytest.raises(exporter.ExportError) as t: exp.export(test_pprof.TEST_EVENTS, 0, 1) assert str(t.value) == "Server returned 400, check your API key"
def test_get_malformed(monkeypatch): monkeypatch.setenv("DD_TAGS", "mytagfoobar") tags = http.PprofHTTPExporter(endpoint="")._get_tags("foobar") _check_tags_types(tags) assert len(tags) == 7 assert tags["service"] == b"foobar" assert len(tags["host"]) assert len(tags["runtime-id"]) assert tags["language"] == b"python" assert tags["runtime"] == b"CPython" assert tags["profiler_version"] == ddtrace.__version__.encode("utf-8") monkeypatch.setenv("DD_TAGS", "mytagfoobar,") tags = http.PprofHTTPExporter(endpoint="")._get_tags("foobar") _check_tags_types(tags) assert len(tags) == 7 assert tags["service"] == b"foobar" assert len(tags["host"]) assert len(tags["runtime-id"]) assert tags["language"] == b"python" assert tags["runtime"] == b"CPython" assert tags["profiler_version"] == ddtrace.__version__.encode("utf-8") monkeypatch.setenv("DD_TAGS", ",") tags = http.PprofHTTPExporter(endpoint="")._get_tags("foobar") _check_tags_types(tags) assert len(tags) == 7 assert tags["service"] == b"foobar" assert len(tags["host"]) assert len(tags["runtime-id"]) assert tags["language"] == b"python" assert tags["runtime"] == b"CPython" assert tags["profiler_version"] == ddtrace.__version__.encode("utf-8") monkeypatch.setenv("DD_TAGS", "foo:bar,") tags = http.PprofHTTPExporter(endpoint="")._get_tags("foobar") _check_tags_types(tags) assert len(tags) == 8 assert tags["service"] == b"foobar" assert len(tags["host"]) assert len(tags["runtime-id"]) assert tags["language"] == b"python" assert tags["runtime"] == b"CPython" assert tags["foo"] == b"bar" assert tags["profiler_version"] == ddtrace.__version__.encode("utf-8")
def test_default_from_env(monkeypatch): monkeypatch.setenv("DD_PROFILING_API_KEY", "123") exp = http.PprofHTTPExporter() assert exp.api_key == "123" assert exp.endpoint == "https://intake.profile.datadoghq.com/v1/input" monkeypatch.setenv("DD_PROFILING_API_URL", "foobar") exp = http.PprofHTTPExporter() assert exp.endpoint == "foobar" monkeypatch.setenv("DD_SITE", "datadoghq.eu") exp = http.PprofHTTPExporter() assert exp.endpoint == "foobar" monkeypatch.delenv("DD_PROFILING_API_URL") exp = http.PprofHTTPExporter() assert exp.endpoint == "https://intake.profile.datadoghq.eu/v1/input" monkeypatch.setenv("DD_API_KEY", "456") exp = http.PprofHTTPExporter() assert exp.api_key == "123" monkeypatch.delenv("DD_PROFILING_API_KEY") exp = http.PprofHTTPExporter() assert exp.api_key == "456" monkeypatch.setenv("DD_SERVICE", "myservice") exp = http.PprofHTTPExporter() assert exp.service_name == "myservice"
def test_get_tags(): tags = http.PprofHTTPExporter()._get_tags("foobar") assert len(tags) == 7 assert tags["service"] == b"foobar" assert len(tags["host"]) assert len(tags["runtime-id"]) assert tags["language"] == b"python" assert tags["runtime"] == b"CPython" assert tags["profiler_version"] == ddtrace.__version__.encode("utf-8")
def test_wrong_api_key(endpoint_test_server): # This is mostly testing our test server, not the exporter exp = http.PprofHTTPExporter(_ENDPOINT, "this is not the right API key", max_retry_delay=10) with pytest.raises(http.UploadFailed) as t: exp.export(test_pprof.TEST_EVENTS, 0, 1) e = t.value.exception assert isinstance(e, error.HTTPError) assert e.code == 400 assert e.reason == "Wrong API Key"
def test_wrong_api_key(endpoint_test_server): # This is mostly testing our test server, not the exporter exp = http.PprofHTTPExporter(_ENDPOINT, "this is not the right API key") with pytest.raises(http.UploadFailed) as t: exp.export(test_pprof.TEST_EVENTS, 0, 1) e = t.exception assert isinstance(e, http.RequestFailed) assert e.response.status == 400 assert e.content == b"Wrong API Key\n"
def test_export_reset(endpoint_test_reset_server): exp = http.PprofHTTPExporter(_RESET_ENDPOINT, _API_KEY, timeout=1) with pytest.raises(http.UploadFailed) as t: exp.export(test_pprof.TEST_EVENTS, 0, 1) e = t.value.exception if six.PY3: assert isinstance(e, ConnectionResetError) else: assert isinstance(e, http_client.BadStatusLine)
def test_export_reset(endpoint_test_reset_server): exp = http.PprofHTTPExporter(_RESET_ENDPOINT, _API_KEY, timeout=1, max_retry_delay=2) with pytest.raises(http.UploadFailed) as t: exp.export(test_pprof.TEST_EVENTS, 0, 1) e = t.value.last_attempt.exception() if six.PY3: assert isinstance(e, ConnectionResetError) else: assert isinstance(e, http_client.BadStatusLine) assert str(e) == "No status line received - the server has closed the connection"
def test_export_404_agent(endpoint_test_unknown_server): exp = http.PprofHTTPExporter(_UNKNOWN_ENDPOINT) with pytest.raises(http.UploadFailed) as t: exp.export(test_pprof.TEST_EVENTS, 0, 1) e = t.value.exception assert isinstance(e, error.HTTPError) assert e.code == 404 assert str(t.value) == ( "Unable to upload profile: Datadog Agent is not accepting profiles. " "Agent-based profiling deployments require Datadog Agent >= 7.20")
def test_get_tags(): tags = http.PprofHTTPExporter(env="foobar")._get_tags("foobar") _check_tags_types(tags) assert len(tags) == 8 assert tags["service"] == b"foobar" assert len(tags["host"]) assert len(tags["runtime-id"]) assert tags["language"] == b"python" assert tags["env"] == b"foobar" assert tags["runtime"] == b"CPython" assert tags["profiler_version"] == ddtrace.__version__.encode("utf-8") assert "version" not in tags
def _build_default_exporters(): exporters = [] if "DD_PROFILING_API_KEY" in os.environ or "DD_API_KEY" in os.environ: exporters.append(http.PprofHTTPExporter()) _OUTPUT_PPROF = os.environ.get("DD_PROFILING_OUTPUT_PPROF") if _OUTPUT_PPROF: exporters.append(file.PprofFileExporter(_OUTPUT_PPROF)) if not exporters: LOG.warning("No exporters are configured, no profile will be output") return exporters
def test_export_404_agentless(endpoint_test_unknown_server): exp = http.PprofHTTPExporter(_UNKNOWN_ENDPOINT, api_key="123", timeout=1) with pytest.raises(http.UploadFailed) as t: exp.export(test_pprof.TEST_EVENTS, 0, 1) e = t.value.exception assert isinstance(e, error.HTTPError) assert e.code == 404 if six.PY2: assert str( t.value ) == "Unable to upload profile: HTTPError: HTTP Error 404: Argh\n" else: assert str( t.value ) == "Unable to upload profile: urllib.error.HTTPError: HTTP Error 404: Argh\n"
def _build_default_exporters(url, service, env, version): _OUTPUT_PPROF = os.environ.get("DD_PROFILING_OUTPUT_PPROF") if _OUTPUT_PPROF: return [ file.PprofFileExporter(_OUTPUT_PPROF), ] api_key = _get_api_key() endpoint = _get_default_url(api_key) if url is None else url return [ http.PprofHTTPExporter(service=service, env=env, version=version, api_key=api_key, endpoint=endpoint), ]
def _build_default_exporters(self): # type: (...) -> List[exporter.Exporter] _OUTPUT_PPROF = os.environ.get("DD_PROFILING_OUTPUT_PPROF") if _OUTPUT_PPROF: return [ file.PprofFileExporter(_OUTPUT_PPROF), ] if self.url is not None: endpoint = self.url elif self.agentless: LOG.warning( "Agentless uploading is currently for internal usage only and not officially supported. " "You should not enable it unless somebody at Datadog instructed you to do so." ) endpoint = self.ENDPOINT_TEMPLATE.format( os.environ.get("DD_SITE", "datadoghq.com")) else: if isinstance(self.tracer.writer, writer.AgentWriter): endpoint = self.tracer.writer.agent_url else: endpoint = agent.get_trace_url() if self.agentless: endpoint_path = "/v1/input" else: # Agent mode # path is relative because it is appended # to the agent base path. endpoint_path = "profiling/v1/input" return [ http.PprofHTTPExporter( service=self.service, env=self.env, tags=self.tags, version=self.version, api_key=self.api_key, endpoint=endpoint, endpoint_path=endpoint_path, ), ]
def test_export_no_endpoint(endpoint_test_server): exp = http.PprofHTTPExporter(endpoint="") with pytest.raises(http.InvalidEndpoint): exp.export(test_pprof.TEST_EVENTS, 0, 1)
def test_get_tags_override(monkeypatch): monkeypatch.setenv("DD_TAGS", "mytag:foobar") tags = http.PprofHTTPExporter(endpoint="")._get_tags("foobar") _check_tags_types(tags) assert len(tags) == 8 assert tags["service"] == b"foobar" assert len(tags["host"]) assert len(tags["runtime-id"]) assert tags["language"] == b"python" assert tags["runtime"] == b"CPython" assert tags["mytag"] == b"foobar" assert tags["profiler_version"] == ddtrace.__version__.encode("utf-8") assert "version" not in tags monkeypatch.setenv("DD_TAGS", "mytag:foobar,author:jd") tags = http.PprofHTTPExporter(endpoint="")._get_tags("foobar") _check_tags_types(tags) assert len(tags) == 9 assert tags["service"] == b"foobar" assert len(tags["host"]) assert len(tags["runtime-id"]) assert tags["language"] == b"python" assert tags["runtime"] == b"CPython" assert tags["mytag"] == b"foobar" assert tags["author"] == b"jd" assert tags["profiler_version"] == ddtrace.__version__.encode("utf-8") assert "version" not in tags monkeypatch.setenv("DD_TAGS", "") tags = http.PprofHTTPExporter(endpoint="")._get_tags("foobar") _check_tags_types(tags) assert len(tags) == 7 assert tags["service"] == b"foobar" assert len(tags["host"]) assert len(tags["runtime-id"]) assert tags["language"] == b"python" assert tags["runtime"] == b"CPython" assert tags["profiler_version"] == ddtrace.__version__.encode("utf-8") assert "version" not in tags monkeypatch.setenv("DD_TAGS", "foobar:baz,service:mycustomservice") tags = http.PprofHTTPExporter(endpoint="")._get_tags("foobar") _check_tags_types(tags) assert len(tags) == 8 assert tags["service"] == b"mycustomservice" assert len(tags["host"]) assert len(tags["runtime-id"]) assert tags["language"] == b"python" assert tags["runtime"] == b"CPython" assert tags["foobar"] == b"baz" assert tags["profiler_version"] == ddtrace.__version__.encode("utf-8") assert "version" not in tags monkeypatch.setenv("DD_TAGS", "foobar:baz,service:�不") tags = http.PprofHTTPExporter(endpoint="")._get_tags("foobar") _check_tags_types(tags) assert len(tags) == 8 assert tags["service"] == u"�不".encode("utf-8") assert len(tags["host"]) assert len(tags["runtime-id"]) assert tags["language"] == b"python" assert tags["runtime"] == b"CPython" assert tags["foobar"] == b"baz" assert tags["profiler_version"] == ddtrace.__version__.encode("utf-8") assert "version" not in tags tags = http.PprofHTTPExporter(endpoint="", version="123")._get_tags("foobar") _check_tags_types(tags) assert len(tags) == 9 assert tags["service"] == u"�不".encode("utf-8") assert len(tags["host"]) assert len(tags["runtime-id"]) assert tags["language"] == b"python" assert tags["runtime"] == b"CPython" assert tags["foobar"] == b"baz" assert tags["profiler_version"] == ddtrace.__version__.encode("utf-8") assert tags["version"] == b"123" assert "env" not in tags tags = http.PprofHTTPExporter(endpoint="", version="123", env="prod")._get_tags("foobar") _check_tags_types(tags) assert len(tags) == 10 assert tags["service"] == u"�不".encode("utf-8") assert len(tags["host"]) assert len(tags["runtime-id"]) assert tags["language"] == b"python" assert tags["runtime"] == b"CPython" assert tags["foobar"] == b"baz" assert tags["profiler_version"] == ddtrace.__version__.encode("utf-8") assert tags["version"] == b"123" assert tags["env"] == b"prod" tags = http.PprofHTTPExporter(endpoint="", version="123", env="prod", tags={ "mytag": "123" })._get_tags("foobar") _check_tags_types(tags) assert len(tags) == 11 assert tags["service"] == u"�不".encode("utf-8") assert len(tags["host"]) assert len(tags["runtime-id"]) assert tags["language"] == b"python" assert tags["runtime"] == b"CPython" assert tags["foobar"] == b"baz" assert tags["profiler_version"] == ddtrace.__version__.encode("utf-8") assert tags["version"] == b"123" assert tags["env"] == b"prod" assert tags["mytag"] == b"123"
def test_export_timeout(endpoint_test_timeout_server): exp = http.PprofHTTPExporter(_TIMEOUT_ENDPOINT, _API_KEY, timeout=1) with pytest.raises(http.UploadFailed) as t: exp.export(test_pprof.TEST_EVENTS, 0, 1) e = t.value.exception assert isinstance(e, socket.timeout)
def test_export_404_agentless(endpoint_test_unknown_server): exp = http.PprofHTTPExporter(_UNKNOWN_ENDPOINT, api_key="123", timeout=1) with pytest.raises(exporter.ExportError) as t: exp.export(test_pprof.TEST_EVENTS, 0, 1) assert str(t.value) == "HTTP Error 404"
def test_export(endpoint_test_server): exp = http.PprofHTTPExporter(_ENDPOINT, _API_KEY) exp.export(test_pprof.TEST_EVENTS, 0, compat.time_ns())