diff --git a/benchmarks/rate_limiter/scenario.py b/benchmarks/rate_limiter/scenario.py index 5c1f80f2537..5210647ef89 100644 --- a/benchmarks/rate_limiter/scenario.py +++ b/benchmarks/rate_limiter/scenario.py @@ -9,7 +9,8 @@ class RateLimiter(bm.Scenario): num_windows: int def run(self): - from ddtrace.internal.compat import time_ns + from time import time_ns + from ddtrace.internal.rate_limiter import RateLimiter rate_limiter = RateLimiter(rate_limit=self.rate_limit, time_window=self.time_window) diff --git a/ddtrace/_trace/span.py b/ddtrace/_trace/span.py index ae642b97a19..eb2649c541d 100644 --- a/ddtrace/_trace/span.py +++ b/ddtrace/_trace/span.py @@ -1,6 +1,7 @@ import math import pprint import sys +from time import time_ns import traceback from types import TracebackType from typing import Any @@ -46,7 +47,6 @@ from ddtrace.internal.compat import StringIO from ddtrace.internal.compat import ensure_text from ddtrace.internal.compat import is_integer -from ddtrace.internal.compat import time_ns from ddtrace.internal.constants import MAX_UINT_64BITS as _MAX_UINT_64BITS from ddtrace.internal.constants import SPAN_API_DATADOG from ddtrace.internal.logger import get_logger diff --git a/ddtrace/contrib/internal/botocore/services/kinesis.py b/ddtrace/contrib/internal/botocore/services/kinesis.py index 2d60252bdc2..7a2926db569 100644 --- a/ddtrace/contrib/internal/botocore/services/kinesis.py +++ b/ddtrace/contrib/internal/botocore/services/kinesis.py @@ -1,5 +1,6 @@ from datetime import datetime import json +from time import time_ns from typing import Any from typing import Dict from typing import List @@ -12,7 +13,6 @@ from ddtrace.contrib.trace_utils import ext_service from ddtrace.ext import SpanTypes from ddtrace.internal import core -from ddtrace.internal.compat import time_ns from ddtrace.internal.logger import get_logger from ddtrace.internal.schema import schematize_cloud_messaging_operation from ddtrace.internal.schema import schematize_service_name diff --git a/ddtrace/contrib/internal/kafka/patch.py b/ddtrace/contrib/internal/kafka/patch.py index 74a65e4c84c..3bc593726ae 100644 --- a/ddtrace/contrib/internal/kafka/patch.py +++ b/ddtrace/contrib/internal/kafka/patch.py @@ -1,5 +1,6 @@ import os import sys +from time import time_ns import confluent_kafka @@ -12,7 +13,6 @@ from ddtrace.ext import SpanTypes from ddtrace.ext import kafka as kafkax from ddtrace.internal import core -from ddtrace.internal.compat import time_ns from ddtrace.internal.constants import COMPONENT from ddtrace.internal.constants import MESSAGING_SYSTEM from ddtrace.internal.logger import get_logger diff --git a/ddtrace/debugging/_debugger.py b/ddtrace/debugging/_debugger.py index 0a1163aa27e..98a26979934 100644 --- a/ddtrace/debugging/_debugger.py +++ b/ddtrace/debugging/_debugger.py @@ -6,6 +6,7 @@ from pathlib import Path import sys import threading +from time import monotonic_ns from types import FunctionType from types import ModuleType from types import TracebackType @@ -55,7 +56,6 @@ from ddtrace.debugging._uploader import LogsIntakeUploaderV1 from ddtrace.debugging._uploader import UploaderProduct from ddtrace.internal import atexit -from ddtrace.internal import compat from ddtrace.internal.logger import get_logger from ddtrace.internal.metrics import Metrics from ddtrace.internal.module import ModuleHookType @@ -229,11 +229,11 @@ def _open_contexts(self) -> None: contexts.append(self._collector.attach(signal)) # Save state on the wrapping context - self.set("start_time", compat.monotonic_ns()) + self.set("start_time", monotonic_ns()) self.set("contexts", contexts) def _close_contexts(self, retval=None, exc_info=(None, None, None)) -> None: - end_time = compat.monotonic_ns() + end_time = monotonic_ns() contexts = self.get("contexts") while contexts: # Open probe signal contexts are ordered, with those that have diff --git a/ddtrace/internal/compat.py b/ddtrace/internal/compat.py index 457618dc393..7f00043f049 100644 --- a/ddtrace/internal/compat.py +++ b/ddtrace/internal/compat.py @@ -122,41 +122,6 @@ def is_integer(obj): return isinstance(obj, int) and not isinstance(obj, bool) -try: - from time import time_ns -except ImportError: - from time import time as _time - - def time_ns(): - # type: () -> int - return int(_time() * 10e5) * 1000 - - -try: - from time import monotonic -except ImportError: - from ddtrace.vendor.monotonic import monotonic - - -try: - from time import monotonic_ns -except ImportError: - - def monotonic_ns(): - # type: () -> int - return int(monotonic() * 1e9) - - -try: - from time import process_time_ns -except ImportError: - from time import clock as _process_time # type: ignore[attr-defined] - - def process_time_ns(): - # type: () -> int - return int(_process_time() * 1e9) - - main_thread = threading.main_thread() diff --git a/ddtrace/internal/opentelemetry/span.py b/ddtrace/internal/opentelemetry/span.py index bd2b0dfe83b..15f497a358e 100644 --- a/ddtrace/internal/opentelemetry/span.py +++ b/ddtrace/internal/opentelemetry/span.py @@ -1,3 +1,4 @@ +from time import time_ns import traceback from typing import TYPE_CHECKING @@ -15,7 +16,6 @@ from ddtrace.constants import ERROR_STACK from ddtrace.constants import ERROR_TYPE from ddtrace.constants import SPAN_KIND -from ddtrace.internal.compat import time_ns from ddtrace.internal.logger import get_logger from ddtrace.internal.utils.formats import flatten_key_value from ddtrace.internal.utils.formats import is_sequence diff --git a/ddtrace/internal/rate_limiter.py b/ddtrace/internal/rate_limiter.py index 63312911ecc..c0fa1400e24 100644 --- a/ddtrace/internal/rate_limiter.py +++ b/ddtrace/internal/rate_limiter.py @@ -4,6 +4,7 @@ from dataclasses import field import random import threading +import time from typing import Any # noqa:F401 from typing import Callable # noqa:F401 from typing import Optional # noqa:F401 @@ -11,7 +12,6 @@ from ddtrace.internal.utils.deprecations import DDTraceDeprecationWarning from ddtrace.vendor.debtcollector import deprecate -from ..internal import compat from ..internal.constants import DEFAULT_SAMPLING_RATE_LIMIT @@ -50,7 +50,7 @@ def __init__(self, rate_limit: int, time_window: float = 1e9): self.tokens = rate_limit # type: float self.max_tokens = rate_limit - self.last_update_ns = compat.monotonic_ns() + self.last_update_ns = time.monotonic_ns() self.current_window_ns = 0 # type: float self.tokens_allowed = 0 @@ -82,7 +82,7 @@ def is_allowed(self, timestamp_ns: Optional[int] = None) -> bool: # rate limits are tested and mocked in pytest so we need to compute the timestamp here # (or move the unit tests to rust) - timestamp_ns = timestamp_ns or compat.monotonic_ns() + timestamp_ns = timestamp_ns or time.monotonic_ns() allowed = self._is_allowed(timestamp_ns) # Update counts used to determine effective rate self._update_rate_counts(allowed, timestamp_ns) @@ -218,7 +218,7 @@ class BudgetRateLimiterWithJitter: call_once: bool = False budget: float = field(init=False) max_budget: float = field(init=False) - last_time: float = field(init=False, default_factory=compat.monotonic) + last_time: float = field(init=False, default_factory=time.monotonic) _lock: threading.Lock = field(init=False, default_factory=threading.Lock) def __post_init__(self): @@ -234,7 +234,7 @@ def limit(self, f: Optional[Callable[..., Any]] = None, *args: Any, **kwargs: An """Make rate-limited calls to a function with the given arguments.""" should_call = False with self._lock: - now = compat.monotonic() + now = time.monotonic() self.budget += self.limit_rate * (now - self.last_time) * (0.5 + random.random()) # jitter should_call = self.budget >= 1.0 if self.budget > self.max_budget: diff --git a/ddtrace/internal/utils/time.py b/ddtrace/internal/utils/time.py index b31f3c3e4f1..43ffde5a1e2 100644 --- a/ddtrace/internal/utils/time.py +++ b/ddtrace/internal/utils/time.py @@ -1,9 +1,9 @@ from datetime import datetime +import time from types import TracebackType from typing import Optional from typing import Type # noqa:F401 -from ddtrace.internal import compat from ddtrace.internal.logger import get_logger @@ -46,7 +46,7 @@ def __init__(self) -> None: def start(self): # type: () -> StopWatch """Starts the watch.""" - self._started_at = compat.monotonic() + self._started_at = time.monotonic() return self def elapsed(self) -> float: @@ -59,7 +59,7 @@ def elapsed(self) -> float: if self._started_at is None: raise RuntimeError("Can not get the elapsed time of a stopwatch" " if it has not been started/stopped") if self._stopped_at is None: - now = compat.monotonic() + now = time.monotonic() else: now = self._stopped_at return now - self._started_at @@ -81,7 +81,7 @@ def stop(self): """Stops the watch.""" if self._started_at is None: raise RuntimeError("Can not stop a stopwatch that has not been" " started") - self._stopped_at = compat.monotonic() + self._stopped_at = time.monotonic() return self @@ -89,7 +89,7 @@ class HourGlass(object): """An implementation of an hourglass.""" def __init__(self, duration: float) -> None: - t = compat.monotonic() + t = time.monotonic() self._duration = duration self._started_at = t - duration @@ -99,7 +99,7 @@ def __init__(self, duration: float) -> None: def turn(self) -> None: """Turn the hourglass.""" - t = compat.monotonic() + t = time.monotonic() top_0 = self._end_at - self._started_at bottom = self._duration - top_0 + min(t - self._started_at, top_0) @@ -119,7 +119,7 @@ def _trickled(self): def _trickling(self): # type: () -> bool - if compat.monotonic() < self._end_at: + if time.monotonic() < self._end_at: return True # No longer trickling, so we change state diff --git a/ddtrace/profiling/collector/_lock.py b/ddtrace/profiling/collector/_lock.py index 74a94e380e2..9d9c13a3b07 100644 --- a/ddtrace/profiling/collector/_lock.py +++ b/ddtrace/profiling/collector/_lock.py @@ -4,13 +4,13 @@ import abc import os.path import sys +from time import monotonic_ns import types import typing import wrapt from ddtrace._trace.tracer import Tracer -from ddtrace.internal import compat from ddtrace.internal.datadog.profiling import ddup from ddtrace.internal.logger import get_logger from ddtrace.profiling import _threading @@ -117,12 +117,12 @@ def _acquire(self, inner_func, *args, **kwargs): if not self._self_capture_sampler.capture(): return inner_func(*args, **kwargs) - start = compat.monotonic_ns() + start = monotonic_ns() try: return inner_func(*args, **kwargs) finally: try: - end = self._self_acquired_at = compat.monotonic_ns() + end = self._self_acquired_at = monotonic_ns() thread_id, thread_name = _current_thread() task_id, task_name, task_frame = _task.get_task(thread_id) self._maybe_update_self_name() @@ -185,7 +185,7 @@ def _release(self, inner_func, *args, **kwargs): try: if hasattr(self, "_self_acquired_at"): try: - end = compat.monotonic_ns() + end = monotonic_ns() thread_id, thread_name = _current_thread() task_id, task_name, task_frame = _task.get_task(thread_id) lock_name = ( diff --git a/ddtrace/profiling/collector/memalloc.py b/ddtrace/profiling/collector/memalloc.py index 2605fe9ff85..48a6d7e2ee6 100644 --- a/ddtrace/profiling/collector/memalloc.py +++ b/ddtrace/profiling/collector/memalloc.py @@ -3,6 +3,7 @@ from math import ceil import os import threading +from time import monotonic_ns import typing # noqa:F401 @@ -11,7 +12,6 @@ except ImportError: _memalloc = None # type: ignore[assignment] -from ddtrace.internal import compat from ddtrace.internal.datadog.profiling import ddup from ddtrace.profiling import _threading from ddtrace.profiling import collector @@ -186,7 +186,7 @@ def collect(self): if thread_id in thread_id_ignore_set: continue handle = ddup.SampleHandle() - handle.push_monotonic_ns(compat.monotonic_ns()) + handle.push_monotonic_ns(monotonic_ns()) handle.push_alloc(int((ceil(size) * alloc_count) / count), count) # Roundup to help float precision handle.push_threadinfo( thread_id, _threading.get_thread_native_id(thread_id), _threading.get_thread_name(thread_id) diff --git a/ddtrace/profiling/collector/stack.pyx b/ddtrace/profiling/collector/stack.pyx index b936c709853..a39a127dced 100644 --- a/ddtrace/profiling/collector/stack.pyx +++ b/ddtrace/profiling/collector/stack.pyx @@ -5,12 +5,12 @@ from itertools import chain import logging import sys import typing +import time from ddtrace.internal._unpatched import _threading as ddtrace_threading from ddtrace._trace import context from ddtrace._trace import span as ddspan from ddtrace._trace.tracer import Tracer -from ddtrace.internal import compat from ddtrace.internal._threads import periodic_threads from ddtrace.internal.datadog.profiling import ddup from ddtrace.internal.datadog.profiling import stack_v2 @@ -131,10 +131,10 @@ ELSE: cdef stdint.int64_t _last_process_time def __init__(self): - self._last_process_time = compat.process_time_ns() + self._last_process_time = time.process_time_ns() def __call__(self, pthread_ids): - current_process_time = compat.process_time_ns() + current_process_time = time.process_time_ns() cpu_time = current_process_time - self._last_process_time self._last_process_time = current_process_time # Spread the consumed CPU time on all threads. @@ -520,7 +520,7 @@ class StackCollector(collector.PeriodicCollector): def _init(self): # type: (...) -> None self._thread_time = _ThreadTime() - self._last_wall_time = compat.monotonic_ns() + self._last_wall_time = time.monotonic_ns() if self.tracer is not None: self._thread_span_links = _ThreadSpanLinks() self.tracer.context_provider._on_activate(self._thread_span_links.link_span) @@ -563,7 +563,7 @@ class StackCollector(collector.PeriodicCollector): def collect(self): # Compute wall time - now = compat.monotonic_ns() + now = time.monotonic_ns() wall_time = now - self._last_wall_time self._last_wall_time = now all_events = [] @@ -581,7 +581,7 @@ class StackCollector(collector.PeriodicCollector): now_ns=now, ) - used_wall_time_ns = compat.monotonic_ns() - now + used_wall_time_ns = time.monotonic_ns() - now self.interval = self._compute_new_interval(used_wall_time_ns) if self._stack_collector_v2_enabled: diff --git a/ddtrace/profiling/event.py b/ddtrace/profiling/event.py index d92d2d75e35..90c76e6a22f 100644 --- a/ddtrace/profiling/event.py +++ b/ddtrace/profiling/event.py @@ -1,4 +1,5 @@ from collections import namedtuple +import time import typing from ddtrace._trace import span as ddspan # noqa:F401 diff --git a/ddtrace/profiling/scheduler.py b/ddtrace/profiling/scheduler.py index 7d9690c29fd..1e7d604e49c 100644 --- a/ddtrace/profiling/scheduler.py +++ b/ddtrace/profiling/scheduler.py @@ -1,5 +1,6 @@ # -*- encoding: utf-8 -*- import logging +import time from typing import Any # noqa F401 from typing import Callable from typing import Dict # noqa F401 @@ -7,7 +8,6 @@ from typing import Optional from typing import Sequence # noqa F401 -from ddtrace.internal import compat from ddtrace.internal import periodic from ddtrace.internal.datadog.profiling import ddup from ddtrace.profiling import _traceback @@ -45,7 +45,7 @@ def _start_service(self): """Start the scheduler.""" LOG.debug("Starting scheduler") super(Scheduler, self)._start_service() - self._last_export = compat.time_ns() + self._last_export = time.time_ns() LOG.debug("Scheduler started") def flush(self): @@ -58,7 +58,7 @@ def flush(self): # These are only used by the Python uploader, but set them here to keep logs/etc # consistent for now start = self._last_export - self._last_export = compat.time_ns() + self._last_export = time.time_ns() return if self.before_flush is not None: @@ -70,7 +70,7 @@ def flush(self): if self.recorder: events = self.recorder.reset() start = self._last_export - self._last_export = compat.time_ns() + self._last_export = time.time_ns() if self.exporters: for exp in self.exporters: try: @@ -85,11 +85,11 @@ def flush(self): def periodic(self): # type: (...) -> None - start_time = compat.monotonic() + start_time = time.monotonic() try: self.flush() finally: - self.interval = max(0, self._configured_interval - (compat.monotonic() - start_time)) + self.interval = max(0, self._configured_interval - (time.monotonic() - start_time)) class ServerlessScheduler(Scheduler): @@ -114,7 +114,7 @@ def __init__(self, *args, **kwargs): def periodic(self): # type: (...) -> None # Check both the number of intervals and time frame to be sure we don't flush, e.g., empty profiles - if self._profiled_intervals >= self.FLUSH_AFTER_INTERVALS and (compat.time_ns() - self._last_export) >= ( + if self._profiled_intervals >= self.FLUSH_AFTER_INTERVALS and (time.time_ns() - self._last_export) >= ( self.FORCED_INTERVAL * self.FLUSH_AFTER_INTERVALS ): try: diff --git a/tests/debugging/mocking.py b/tests/debugging/mocking.py index dee76125ba3..4446bce559c 100644 --- a/tests/debugging/mocking.py +++ b/tests/debugging/mocking.py @@ -2,6 +2,7 @@ from collections import Counter from contextlib import contextmanager import json +from time import monotonic from time import sleep from typing import Any from typing import Generator @@ -16,7 +17,6 @@ from ddtrace.debugging._probe.remoteconfig import _filter_by_env_and_version from ddtrace.debugging._signal.collector import SignalCollector from ddtrace.debugging._uploader import LogsIntakeUploaderV1 -from ddtrace.internal.compat import monotonic from tests.debugging.probe.test_status import DummyProbeStatusLogger diff --git a/tests/integration/test_sampling.py b/tests/integration/test_sampling.py index 09de91d6ef5..110f8b67645 100644 --- a/tests/integration/test_sampling.py +++ b/tests/integration/test_sampling.py @@ -330,7 +330,7 @@ def test_rate_limiter_on_long_running_spans(tracer): """ tracer.configure(sampler=DatadogSampler(rate_limit=5)) - with mock.patch("ddtrace.internal.rate_limiter.compat.monotonic_ns", return_value=1617333414): + with mock.patch("ddtrace.internal.rate_limiter.time.monotonic_ns", return_value=1617333414): span_m30 = tracer.trace(name="march 30") span_m30.start = 1622347257 # Mar 30 2021 span_m30.finish(1617333414) # April 2 2021 diff --git a/tests/profiling/exporter/test_http.py b/tests/profiling/exporter/test_http.py index d38c02dafd1..f28362e20dc 100644 --- a/tests/profiling/exporter/test_http.py +++ b/tests/profiling/exporter/test_http.py @@ -11,7 +11,6 @@ import pytest import ddtrace -from ddtrace.internal import compat from ddtrace.internal.processor.endpoint_call_counter import EndpointCallCounterProcessor from ddtrace.internal.utils.formats import parse_tags_str from ddtrace.profiling import exporter @@ -200,7 +199,7 @@ def test_export(endpoint_test_server): exp = http.PprofHTTPExporter( endpoint=_ENDPOINT, api_key=_API_KEY, endpoint_call_counter_span_processor=_get_span_processor() ) - exp.export(test_pprof.TEST_EVENTS, 0, compat.time_ns()) + exp.export(test_pprof.TEST_EVENTS, 0, time.time_ns()) def test_export_server_down(): @@ -265,7 +264,7 @@ def test_export_tracer_base_path(endpoint_test_server): endpoint_path="v1/input", endpoint_call_counter_span_processor=_get_span_processor(), ) - exp.export(test_pprof.TEST_EVENTS, 0, compat.time_ns()) + exp.export(test_pprof.TEST_EVENTS, 0, time.time_ns()) def test_export_tracer_base_path_agent_less(endpoint_test_server): @@ -277,7 +276,7 @@ def test_export_tracer_base_path_agent_less(endpoint_test_server): endpoint_path="/profiling/v1/input", endpoint_call_counter_span_processor=_get_span_processor(), ) - exp.export(test_pprof.TEST_EVENTS, 0, compat.time_ns()) + exp.export(test_pprof.TEST_EVENTS, 0, time.time_ns()) def test_get_tags(): diff --git a/tests/profiling/test_accuracy.py b/tests/profiling/test_accuracy.py index e23317db8b1..b5f3a3017d9 100644 --- a/tests/profiling/test_accuracy.py +++ b/tests/profiling/test_accuracy.py @@ -4,8 +4,6 @@ import pytest -from ddtrace.internal import compat - TESTING_GEVENT = os.getenv("DD_PROFILE_TEST_GEVENT", False) @@ -37,16 +35,16 @@ def spend_16(): def spend_cpu_2(): - now = compat.monotonic_ns() + now = time.monotonic_ns() # Active wait for 2 seconds - while compat.monotonic_ns() - now < 2e9: + while time.monotonic_ns() - now < 2e9: pass def spend_cpu_3(): # Active wait for 3 seconds - now = compat.monotonic_ns() - while compat.monotonic_ns() - now < 3e9: + now = time.monotonic_ns() + while time.monotonic_ns() - now < 3e9: pass diff --git a/tests/profiling/test_scheduler.py b/tests/profiling/test_scheduler.py index 483ec643527..42d8ccc29fe 100644 --- a/tests/profiling/test_scheduler.py +++ b/tests/profiling/test_scheduler.py @@ -1,9 +1,9 @@ # -*- encoding: utf-8 -*- import logging +import time import mock -from ddtrace.internal import compat from ddtrace.profiling import event from ddtrace.profiling import exporter from ddtrace.profiling import recorder @@ -64,11 +64,11 @@ def test_serverless_periodic(mock_periodic): r = recorder.Recorder() s = scheduler.ServerlessScheduler(r, [exporter.NullExporter()]) # Fake start() - s._last_export = compat.time_ns() + s._last_export = time.time_ns() s.periodic() assert s._profiled_intervals == 1 mock_periodic.assert_not_called() - s._last_export = compat.time_ns() - 65 + s._last_export = time.time_ns() - 65 s._profiled_intervals = 65 s.periodic() assert s._profiled_intervals == 0 diff --git a/tests/submod/stuff.py b/tests/submod/stuff.py index d2fa07e0ec5..375520bf76b 100644 --- a/tests/submod/stuff.py +++ b/tests/submod/stuff.py @@ -125,7 +125,7 @@ def __init__(self): foo = property(operator.attrgetter("_foo")) -from ddtrace.internal.compat import monotonic_ns # noqa:E402 +from time import monotonic_ns # noqa:E402 def durationstuff(ns): diff --git a/tests/tracer/test_rate_limiter.py b/tests/tracer/test_rate_limiter.py index d66f980cbc3..df9e1458525 100644 --- a/tests/tracer/test_rate_limiter.py +++ b/tests/tracer/test_rate_limiter.py @@ -1,9 +1,10 @@ from __future__ import division +import time + import mock import pytest -from ddtrace.internal import compat from ddtrace.internal.rate_limiter import BudgetRateLimiterWithJitter from ddtrace.internal.rate_limiter import RateLimiter from ddtrace.internal.rate_limiter import RateLimitExceeded @@ -20,7 +21,7 @@ def test_rate_limiter_init(time_window): assert limiter.rate_limit == 100 assert limiter.tokens == 100 assert limiter.max_tokens == 100 - assert limiter.last_update_ns <= compat.monotonic_ns() + assert limiter.last_update_ns <= time.monotonic_ns() @pytest.mark.parametrize("time_window", [1e3, 1e6, 1e9]) @@ -30,10 +31,10 @@ def test_rate_limiter_rate_limit_0(time_window): assert limiter.tokens == 0 assert limiter.max_tokens == 0 - now_ns = compat.monotonic_ns() + now_ns = time.monotonic_ns() for i in nanoseconds(10000, time_window): # Make sure the time is different for every check - with mock.patch("ddtrace.internal.rate_limiter.compat.monotonic_ns", return_value=now_ns + i): + with mock.patch("ddtrace.internal.rate_limiter.time.monotonic_ns", return_value=now_ns + i): assert limiter.is_allowed() is False @@ -44,10 +45,10 @@ def test_rate_limiter_rate_limit_negative(time_window): assert limiter.tokens == -1 assert limiter.max_tokens == -1 - now_ns = compat.monotonic_ns() + now_ns = time.monotonic_ns() for i in nanoseconds(10000, time_window): # Make sure the time is different for every check - with mock.patch("ddtrace.internal.rate_limiter.compat.monotonic_ns", return_value=now_ns + i): + with mock.patch("ddtrace.internal.rate_limiter.time.monotonic_ns", return_value=now_ns + i): assert limiter.is_allowed() is True @@ -66,12 +67,12 @@ def check_limit(): assert limiter.is_allowed() is False # Start time - now = compat.monotonic_ns() + now = time.monotonic_ns() # Check the limit for 5 time frames for i in nanoseconds(5, time_window): # Keep the same timeframe - with mock.patch("ddtrace.internal.rate_limiter.compat.monotonic_ns", return_value=now + i): + with mock.patch("ddtrace.internal.rate_limiter.time.monotonic_ns", return_value=now + i): check_limit() @@ -80,14 +81,14 @@ def test_rate_limiter_is_allowed_large_gap(time_window): limiter = RateLimiter(rate_limit=100, time_window=time_window) # Start time - now_ns = compat.monotonic_ns() + now_ns = time.monotonic_ns() # Keep the same timeframe - with mock.patch("ddtrace.internal.rate_limiter.compat.monotonic_ns", return_value=now_ns): + with mock.patch("ddtrace.internal.rate_limiter.time.monotonic_ns", return_value=now_ns): for _ in range(100): assert limiter.is_allowed() is True # Large gap before next call to `is_allowed()` - with mock.patch("ddtrace.internal.rate_limiter.compat.monotonic_ns", return_value=now_ns + (time_window * 100)): + with mock.patch("ddtrace.internal.rate_limiter.time.monotonic_ns", return_value=now_ns + (time_window * 100)): for _ in range(100): assert limiter.is_allowed() is True @@ -97,13 +98,13 @@ def test_rate_limiter_is_allowed_small_gaps(time_window): limiter = RateLimiter(rate_limit=100, time_window=time_window) # Start time - now_ns = compat.monotonic_ns() + now_ns = time.monotonic_ns() gap = 1e9 / 100 # Keep incrementing by a gap to keep us at our rate limit for i in nanoseconds(10000, time_window): # Keep the same timeframe time_ns = now_ns + (gap * i) - with mock.patch("ddtrace.internal.rate_limiter.compat.monotonic_ns", return_value=time_ns): + with mock.patch("ddtrace.internal.rate_limiter.time.monotonic_ns", return_value=time_ns): assert limiter.is_allowed() is True @@ -112,8 +113,8 @@ def test_rate_liimter_effective_rate_rates(time_window): limiter = RateLimiter(rate_limit=100, time_window=time_window) # Static rate limit window - starting_window_ns = compat.monotonic_ns() - with mock.patch("ddtrace.internal.rate_limiter.compat.monotonic_ns", return_value=starting_window_ns): + starting_window_ns = time.monotonic_ns() + with mock.patch("ddtrace.internal.rate_limiter.time.monotonic_ns", return_value=starting_window_ns): for _ in range(100): assert limiter.is_allowed() is True assert limiter.effective_rate == 1.0 @@ -127,7 +128,7 @@ def test_rate_liimter_effective_rate_rates(time_window): prev_rate = 0.5 window_ns = starting_window_ns + time_window - with mock.patch("ddtrace.internal.rate_limiter.compat.monotonic_ns", return_value=window_ns): + with mock.patch("ddtrace.internal.rate_limiter.time.monotonic_ns", return_value=window_ns): for _ in range(100): assert limiter.is_allowed() is True assert limiter.effective_rate == 0.75 @@ -144,7 +145,7 @@ def test_rate_liimter_effective_rate_rates(time_window): def test_rate_limiter_effective_rate_starting_rate(time_window): limiter = RateLimiter(rate_limit=1, time_window=time_window) - now_ns = compat.monotonic_ns() + now_ns = time.monotonic_ns() # Default values assert limiter.current_window_ns == 0 @@ -156,7 +157,7 @@ def test_rate_limiter_effective_rate_starting_rate(time_window): assert limiter.prev_window_rate is None # Calling `.is_allowed()` updates the values - with mock.patch("ddtrace.internal.rate_limiter.compat.monotonic_ns", return_value=now_ns): + with mock.patch("ddtrace.internal.rate_limiter.time.monotonic_ns", return_value=now_ns): assert limiter.is_allowed() is True assert limiter.effective_rate == 1.0 assert limiter.current_window_ns == now_ns @@ -164,7 +165,7 @@ def test_rate_limiter_effective_rate_starting_rate(time_window): # Gap of 0.85 seconds, same window time_ns = now_ns + (0.85 * time_window) - with mock.patch("ddtrace.internal.rate_limiter.compat.monotonic_ns", return_value=time_ns): + with mock.patch("ddtrace.internal.rate_limiter.time.monotonic_ns", return_value=time_ns): assert limiter.is_allowed() is False # DEV: We have rate_limit=1 set assert limiter.effective_rate == 0.5 @@ -173,7 +174,7 @@ def test_rate_limiter_effective_rate_starting_rate(time_window): # Gap of 1.0 seconds, new window time_ns = now_ns + time_window - with mock.patch("ddtrace.internal.rate_limiter.compat.monotonic_ns", return_value=time_ns): + with mock.patch("ddtrace.internal.rate_limiter.time.monotonic_ns", return_value=time_ns): assert limiter.is_allowed() is True assert limiter.effective_rate == 0.75 assert limiter.current_window_ns == (now_ns + time_window) @@ -181,7 +182,7 @@ def test_rate_limiter_effective_rate_starting_rate(time_window): # Gap of 1.85 seconds, same window time_ns = now_ns + (1.85 * time_window) - with mock.patch("ddtrace.internal.rate_limiter.compat.monotonic_ns", return_value=time_ns): + with mock.patch("ddtrace.internal.rate_limiter.time.monotonic_ns", return_value=time_ns): assert limiter.is_allowed() is False assert limiter.effective_rate == 0.5 assert limiter.current_window_ns == (now_ns + time_window) # Same as old window @@ -189,7 +190,7 @@ def test_rate_limiter_effective_rate_starting_rate(time_window): # Large gap of 100 seconds, new window time_ns = now_ns + (100.0 * time_window) - with mock.patch("ddtrace.internal.rate_limiter.compat.monotonic_ns", return_value=time_ns): + with mock.patch("ddtrace.internal.rate_limiter.time.monotonic_ns", return_value=time_ns): assert limiter.is_allowed() is True assert limiter.effective_rate == 0.75 assert limiter.current_window_ns == (now_ns + (100.0 * time_window))