Skip to content

Commit

Permalink
test importlibs instead of pkg_resources
Browse files Browse the repository at this point in the history
  • Loading branch information
mabdinur committed May 27, 2022
1 parent 5875b21 commit 23566fc
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 5 deletions.
32 changes: 32 additions & 0 deletions ddtrace/internal/packages.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import typing


Distribution = typing.NamedTuple("Distribution", [("name", str), ("version", str)])

_DISTRIBUTIONS = None


def get_distributions():
# type: () -> typing.List[Distribution]
global _DISTRIBUTIONS
if _DISTRIBUTIONS is not None:
return _DISTRIBUTIONS

try:
import importlib.metadata as importlib_metadata
except ImportError:
import importlib_metadata

pkgs = []
pkg_names = set()
for dist in importlib_metadata.distributions():
metadata = dist.metadata
name = metadata["version"]
version = metadata["version"]
if name and version and name not in pkg_names:
pkgs.append(Distribution(name, version))
# Avoids adding duplicates
pkg_names.add(name)

_DISTRIBUTIONS = pkgs
return _DISTRIBUTIONS
10 changes: 7 additions & 3 deletions ddtrace/internal/telemetry/writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from ...internal import atexit
from ...internal import forksafe
from ...internal.packages import get_distributions
from ...settings import _config as config
from ..agent import get_connection
from ..agent import get_trace_url
Expand All @@ -28,6 +29,11 @@ def _get_interval_or_default():
return float(os.getenv("DD_INSTRUMENTATION_TELEMETRY_INTERVAL_SECONDS", default=60))


def get_distributions_as_dict():
# type: () -> List[Dict[str, str]]
return [{"name": dist.name, "version": dist.version} for dist in get_distributions()]


class TelemetryWriter(PeriodicService):
"""
Periodic service which sends Telemetry request payloads to the agent.
Expand Down Expand Up @@ -185,10 +191,8 @@ def app_started_event(self):
return
# pkg_resources import is inlined for performance reasons
# This import is an expensive operation
import pkg_resources

payload = {
"dependencies": [{"name": pkg.project_name, "version": pkg.version} for pkg in pkg_resources.working_set],
"dependencies": get_distributions_as_dict(),
"integrations": self._flush_integrations_queue(),
"configurations": [],
}
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ def get_exts_for(name):
"attrs>=19.2.0",
"six>=1.12.0",
"typing_extensions; python_version<'3.8'",
"importlib_metadata; python_version<'3.8'",
]
+ bytecode,
extras_require={
Expand Down
11 changes: 11 additions & 0 deletions tests/internal/test_packages.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from ddtrace.internal.packages import Distribution
from ddtrace.internal.packages import get_distributions


def test_get_distributions():
import pkg_resources

pkg_resources_ws = [Distribution(pkg.project_name, pkg.version) for pkg in pkg_resources.working_set]
importlib_pkg = get_distributions()

assert pkg_resources_ws.sort(key=lambda x: x[0]) == importlib_pkg.sort(key=lambda x: x[0])
13 changes: 11 additions & 2 deletions tests/tracer/telemetry/test_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

import httpretty
import mock
import pkg_resources
import pytest

from ddtrace.internal.telemetry.data import get_application
from ddtrace.internal.telemetry.data import get_host_info
from ddtrace.internal.telemetry.writer import TelemetryWriter
from ddtrace.internal.telemetry.writer import get_distributions_as_dict
from ddtrace.internal.telemetry.writer import get_runtime_id
from ddtrace.settings import _config as config

Expand Down Expand Up @@ -51,6 +51,15 @@ def telemetry_writer_disabled():
yield telemetry_writer


def test_get_distributions_as_dict():
import pkg_resources

pkg_resources_ws = [{"name": pkg.project_name, "version": pkg.version} for pkg in pkg_resources.working_set]
importlib_pkg = get_distributions_as_dict()

assert pkg_resources_ws.sort(key=lambda x: x["name"]) == importlib_pkg.sort(key=lambda x: x["name"])


def test_add_event(mock_time, mock_send_request, telemetry_writer):
"""asserts that add_event queues a telemetry request with valid headers and payload"""
payload = {"test": "123"}
Expand Down Expand Up @@ -98,7 +107,7 @@ def test_app_started_event(mock_time, mock_send_request, telemetry_writer):
assert headers["DD-Telemetry-Request-Type"] == "app-started"
# validate request body
payload = {
"dependencies": [{"name": pkg.project_name, "version": pkg.version} for pkg in pkg_resources.working_set],
"dependencies": get_distributions_as_dict(),
"integrations": [
{
"name": "integration-t",
Expand Down

0 comments on commit 23566fc

Please sign in to comment.