Esempio n. 1
0
def test_status():
    p = profiler.Profiler()
    assert repr(p.status) == "<ServiceStatus.STOPPED: 'stopped'>"
    p.start()
    assert repr(p.status) == "<ServiceStatus.RUNNING: 'running'>"
    p.stop(flush=False)
    assert repr(p.status) == "<ServiceStatus.STOPPED: 'stopped'>"
Esempio n. 2
0
def test_status():
    p = profiler.Profiler()
    assert repr(p.status) == "STOPPED"
    p.start()
    assert repr(p.status) == "RUNNING"
    p.stop()
    assert repr(p.status) == "STOPPED"
Esempio n. 3
0
def test_default_tracer_and_url():
    try:
        ddtrace.tracer.configure(hostname="foobar")
        prof = profiler.Profiler(url="https://foobaz:123")
        _check_url(prof, "https://foobaz:123")
    finally:
        ddtrace.tracer.configure(hostname="localhost")
Esempio n. 4
0
def test_env_api_key(name_var, monkeypatch):
    monkeypatch.setenv(name_var, "foobar")
    prof = profiler.Profiler()
    _check_url(prof,
               "https://intake.profile.datadoghq.com/v1/input",
               "foobar",
               endpoint_path="/v1/input")
Esempio n. 5
0
def test_accuracy(monkeypatch):
    # Set this to 100 so we don't sleep too often and mess with the precision.
    monkeypatch.setenv("DD_PROFILING_MAX_TIME_USAGE_PCT", "100")
    p = profiler.Profiler(exporters=[])
    p.start()
    spend_16()
    p.stop()
    recorder = list(p.recorders)[0]
    # First index is the stack position, second is the function name
    time_spent_ns = collections.defaultdict(lambda: collections.defaultdict(lambda: 0))
    cpu_spent_ns = collections.defaultdict(lambda: collections.defaultdict(lambda: 0))
    for event in recorder.events[stack.StackSampleEvent]:
        for idx, frame in enumerate(reversed(event.frames)):
            time_spent_ns[idx][frame[2]] += event.wall_time_ns
            cpu_spent_ns[idx][frame[2]] += event.cpu_time_ns

    assert almost_equal(total_time(time_spent_ns, "spend_3"), 9e9)
    assert almost_equal(total_time(time_spent_ns, "spend_1"), 2e9)
    assert almost_equal(total_time(time_spent_ns, "spend_4"), 4e9)
    assert almost_equal(total_time(time_spent_ns, "spend_16"), 16e9)
    assert almost_equal(total_time(time_spent_ns, "spend_7"), 7e9)

    try:
        from time import monotonic_ns  # noqa
    except ImportError:
        # If we don't have access to high resolution clocks, we can't really test accurately things as it's spread in
        # various Python implementation of monotonic, etc.
        pass
    else:
        assert almost_equal(total_time(time_spent_ns, "spend_cpu_2"), 2e9)
        assert almost_equal(total_time(time_spent_ns, "spend_cpu_3"), 3e9)
        assert almost_equal(total_time(time_spent_ns, "spend_cpu_2"), 2e9, CPU_TOLERANCE)
        assert almost_equal(total_time(time_spent_ns, "spend_cpu_3"), 3e9, CPU_TOLERANCE)
Esempio n. 6
0
def test_env_agentless(monkeypatch):
    monkeypatch.setenv("DD_PROFILING_AGENTLESS", "true")
    monkeypatch.setenv("DD_API_KEY", "foobar")
    prof = profiler.Profiler()
    _check_url(prof,
               "https://intake.profile.datadoghq.com",
               "foobar",
               endpoint_path="/v1/input")
Esempio n. 7
0
def test_env_endpoint_url_no_agent(monkeypatch):
    monkeypatch.setenv("DD_SITE", "datadoghq.eu")
    monkeypatch.setenv("DD_API_KEY", "123")
    prof = profiler.Profiler()
    _check_url(prof,
               "https://intake.profile.datadoghq.eu/v1/input",
               "123",
               endpoint_path="/v1/input")
Esempio n. 8
0
def test_env_no_api_key():
    prof = profiler.Profiler()
    for exporter in prof.exporters:
        if isinstance(exporter, http.PprofHTTPExporter):
            assert exporter.api_key is None
            assert exporter.endpoint == "http://localhost:8126/profiling/v1/input"
            break
    else:
        pytest.fail("Unable to find HTTP exporter")
Esempio n. 9
0
def test_url():
    prof = profiler.Profiler(url="https://foobar:123")
    for exporter in prof._profiler._scheduler.exporters:
        if isinstance(exporter, http.PprofHTTPExporter):
            assert exporter.api_key is None
            assert exporter.endpoint == "https://foobar:123"
            break
    else:
        pytest.fail("Unable to find HTTP exporter")
Esempio n. 10
0
def test_default_from_env(service_name_var, monkeypatch):
    monkeypatch.setenv("DD_API_KEY", "foobar")
    monkeypatch.setenv(service_name_var, "foobar")
    prof = profiler.Profiler()
    for exp in prof._profiler._scheduler.exporters:
        if isinstance(exp, http.PprofHTTPExporter):
            assert exp.service == "foobar"
            break
    else:
        pytest.fail("Unable to find HTTP exporter")
Esempio n. 11
0
def test_env_api_key(name_var, monkeypatch):
    monkeypatch.setenv(name_var, "foobar")
    prof = profiler.Profiler()
    for exporter in prof.exporters:
        if isinstance(exporter, http.PprofHTTPExporter):
            assert exporter.api_key == "foobar"
            assert exporter.endpoint == "https://intake.profile.datadoghq.com/v1/input"
            break
    else:
        pytest.fail("Unable to find HTTP exporter")
Esempio n. 12
0
def test_multiple_stop():
    """Check that the profiler can be stopped twice.

    This is useful since the atexit.unregister call might not exist on Python 2,
    therefore the profiler can be stopped twice (once per the user, once at exit).
    """
    p = profiler.Profiler()
    p.start()
    p.stop()
    p.stop()
Esempio n. 13
0
def test_service_api(monkeypatch):
    monkeypatch.setenv("DD_API_KEY", "foobar")
    prof = profiler.Profiler(service="foobar")
    assert prof.service == "foobar"
    for exp in prof._profiler._scheduler.exporters:
        if isinstance(exp, http.PprofHTTPExporter):
            assert exp.service == "foobar"
            break
    else:
        pytest.fail("Unable to find HTTP exporter")
Esempio n. 14
0
def test_tracer_api(monkeypatch):
    monkeypatch.setenv("DD_API_KEY", "foobar")
    prof = profiler.Profiler(tracer=ddtrace.tracer)
    assert prof.tracer == ddtrace.tracer
    for col in prof._profiler._collectors:
        if isinstance(col, stack.StackCollector):
            assert col.tracer == ddtrace.tracer
            break
    else:
        pytest.fail("Unable to find stack collector")
Esempio n. 15
0
def test_env_api(monkeypatch):
    monkeypatch.setenv("DD_API_KEY", "foobar")
    prof = profiler.Profiler(env="staging")
    assert prof.env == "staging"
    for exporter in prof.exporters:
        if isinstance(exporter, http.PprofHTTPExporter):
            assert exporter.env == "staging"
            break
    else:
        pytest.fail("Unable to find HTTP exporter")
Esempio n. 16
0
def start_profiler():
    if hasattr(bootstrap, "profiler"):
        # Stop the previous profiler (stop thread if ever needed, but also unpatch classes)
        # Python 2 does not have unregister so we can't use it all the time
        if six.PY3:
            atexit.unregister(bootstrap.profiler.stop)
        bootstrap.profiler.stop()
    # Export the profiler so we can introspect it if needed
    bootstrap.profiler = profiler.Profiler()
    bootstrap.profiler.start()
    atexit.register(bootstrap.profiler.stop)
Esempio n. 17
0
def test_env_endpoint_url(monkeypatch):
    monkeypatch.setenv("DD_AGENT_HOST", "foobar")
    monkeypatch.setenv("DD_TRACE_AGENT_PORT", "123")
    prof = profiler.Profiler()
    for exporter in prof.exporters:
        if isinstance(exporter, http.PprofHTTPExporter):
            assert exporter.api_key is None
            assert exporter.endpoint == "http://foobar:123/profiling/v1/input"
            break
    else:
        pytest.fail("Unable to find HTTP exporter")
Esempio n. 18
0
def test_env_endpoint_url_no_agent(monkeypatch):
    monkeypatch.setenv("DD_SITE", "datadoghq.eu")
    monkeypatch.setenv("DD_API_KEY", "123")
    prof = profiler.Profiler()
    for exporter in prof.exporters:
        if isinstance(exporter, http.PprofHTTPExporter):
            assert exporter.api_key == "123"
            assert exporter.endpoint == "https://intake.profile.datadoghq.eu/v1/input"
            break
    else:
        pytest.fail("Unable to find HTTP exporter")
Esempio n. 19
0
def test_env_api():
    prof = profiler.Profiler(env="staging", version="123")
    assert prof.env == "staging"
    assert prof.version == "123"
    for exporter in prof.exporters:
        if isinstance(exporter, http.PprofHTTPExporter):
            assert exporter.env == "staging"
            assert exporter.version == "123"
            break
    else:
        pytest.fail("Unable to find HTTP exporter")
Esempio n. 20
0
def test_asyncio(tmp_path, monkeypatch) -> None:
    sleep_time = 0.2
    sleep_times = 5

    async def stuff() -> None:
        await asyncio.sleep(sleep_time)

    async def hello() -> None:
        t1 = _asyncio_compat.create_task(stuff(), name="sleep 1")
        t2 = _asyncio_compat.create_task(stuff(), name="sleep 2")
        for _ in range(sleep_times):
            await stuff()
        return (t1, t2)

    monkeypatch.setenv("DD_PROFILING_CAPTURE_PCT", "100")
    monkeypatch.setenv("DD_PROFILING_OUTPUT_PPROF", str(tmp_path / "pprof"))
    # start a complete profiler so asyncio policy is setup
    p = profiler.Profiler()
    p.start()
    t1, t2 = _asyncio_compat.run(hello())
    events = p._profiler._recorder.reset()
    p.stop()

    wall_time_ns = collections.defaultdict(lambda: 0)

    t1_name = _asyncio._task_get_name(t1)
    t2_name = _asyncio._task_get_name(t2)

    for event in events[stack_event.StackSampleEvent]:

        wall_time_ns[event.task_name] += event.wall_time_ns

        # This assertion does not work reliably on Python < 3.7
        if _asyncio_compat.PY37_AND_LATER:
            if event.task_name == "Task-1":
                assert event.thread_name == "MainThread"
                assert event.frames == [(__file__, 25, "hello")]
                assert event.nframes == 1
            elif event.task_name == t1_name:
                assert event.thread_name == "MainThread"
                assert event.frames == [(__file__, 19, "stuff")]
                assert event.nframes == 1
            elif event.task_name == t2_name:
                assert event.thread_name == "MainThread"
                assert event.frames == [(__file__, 19, "stuff")]
                assert event.nframes == 1

    if _asyncio_compat.PY38_AND_LATER:
        # We don't know the name of this task for Python < 3.8
        assert wall_time_ns["Task-1"] > 0

    assert wall_time_ns[t1_name] > 0
    assert wall_time_ns[t2_name] > 0
Esempio n. 21
0
def test_not_ignore_profiler_gevent_task(monkeypatch):
    monkeypatch.setenv("DD_PROFILING_API_TIMEOUT", "0.1")
    monkeypatch.setenv("DD_PROFILING_IGNORE_PROFILER", "0")
    p = profiler.Profiler()
    p.start()
    # This test is particularly useful with gevent enabled: create a test collector that run often and for long so we're
    # sure to catch it with the StackProfiler and that it's ignored.
    c = CollectorTest(p._profiler._recorder, interval=0.00001)
    c.start()
    events = p._profiler._recorder.events[stack.StackSampleEvent]
    time.sleep(3)
    c.stop()
    p.stop()
    assert c._worker.ident in {e.task_id for e in events}
Esempio n. 22
0
def test_env_default(monkeypatch):
    monkeypatch.setenv("DD_API_KEY", "foobar")
    monkeypatch.setenv("DD_ENV", "staging")
    monkeypatch.setenv("DD_VERSION", "123")
    prof = profiler.Profiler()
    assert prof.env == "staging"
    assert prof.version == "123"
    for exporter in prof.exporters:
        if isinstance(exporter, http.PprofHTTPExporter):
            assert exporter.env == "staging"
            assert exporter.version == "123"
            break
    else:
        pytest.fail("Unable to find HTTP exporter")
Esempio n. 23
0
def test_tags_api():
    prof = profiler.Profiler(env="staging", version="123", tags={"foo": "bar"})
    assert prof.env == "staging"
    assert prof.version == "123"
    assert prof.url is None
    assert prof.tags["foo"] == "bar"
    for exp in prof._profiler._scheduler.exporters:
        if isinstance(exp, http.PprofHTTPExporter):
            assert exp.env == "staging"
            assert exp.version == "123"
            assert exp.tags["foo"] == b"bar"
            break
    else:
        pytest.fail("Unable to find HTTP exporter")
Esempio n. 24
0
def test_ignore_profiler_gevent_task(monkeypatch, ignore):
    monkeypatch.setenv("DD_PROFILING_API_TIMEOUT", "0.1")
    monkeypatch.setenv("DD_PROFILING_IGNORE_PROFILER", str(ignore))
    p = profiler.Profiler()
    p.start()
    # This test is particularly useful with gevent enabled: create a test collector that run often and for long so we're
    # sure to catch it with the StackProfiler and that it's not ignored.
    c = CollectorTest(p._profiler._recorder, interval=0.00001)
    c.start()
    # Wait forever and stop when we finally find an event with our collector task id
    while True:
        events = p._profiler._recorder.reset()
        ids = {e.task_id for e in events[stack.StackSampleEvent]}
        if (c._worker.ident in ids) != ignore:
            break
        # Give some time for gevent to switch greenlets
        time.sleep(0.1)
    c.stop()
    p.stop(flush=False)
Esempio n. 25
0
def test_lock_acquire_events(tmp_path, monkeypatch):
    async def _lock():
        lock = threading.Lock()
        lock.acquire()

    def asyncio_run():
        lock = threading.Lock()
        lock.acquire()
        _asyncio_compat.run(_lock())

    monkeypatch.setenv("DD_PROFILING_CAPTURE_PCT", "100")
    monkeypatch.setenv("DD_PROFILING_OUTPUT_PPROF", str(tmp_path / "pprof"))
    # start a complete profiler so asyncio policy is setup
    p = profiler.Profiler()
    p.start()
    t = threading.Thread(target=asyncio_run, name="foobar")
    t.start()
    t.join()
    events = p._profiler._recorder.reset()
    p.stop()

    lock_found = 0
    for event in events[collector_threading.ThreadingLockAcquireEvent]:
        if event.lock_name == "test_threading_asyncio.py:18":
            assert event.task_name.startswith("Task-")
            lock_found += 1
        elif event.lock_name == "test_threading_asyncio.py:22":
            if TESTING_GEVENT:
                assert event.task_name == "foobar"
                assert event.thread_name == "MainThread"
            else:
                assert event.task_name is None
                assert event.thread_name == "foobar"
            lock_found += 1

    if lock_found != 2:
        pytest.fail("Lock events not found")
Esempio n. 26
0
def test_env_endpoint_url(monkeypatch):
    monkeypatch.setenv("DD_AGENT_HOST", "foobar")
    monkeypatch.setenv("DD_TRACE_AGENT_PORT", "123")
    t = ddtrace.Tracer()
    prof = profiler.Profiler(tracer=t)
    _check_url(prof, "http://foobar:123")
Esempio n. 27
0
def test_restart():
    p = profiler.Profiler()
    p.start()
    p.stop()
    p.start()
    p.stop()
Esempio n. 28
0
def test_env_endpoint_url_no_agent(monkeypatch):
    monkeypatch.setenv("DD_SITE", "datadoghq.eu")
    monkeypatch.setenv("DD_API_KEY", "123")
    prof = profiler.Profiler()
    _check_url(prof, "http://localhost:8126", "123")
Esempio n. 29
0
def test_restart():
    p = profiler.Profiler()
    p.start()
    p.stop(flush=False)
    p.start()
    p.stop(flush=False)
Esempio n. 30
0
def test_multiple_stop():
    """Check that the profiler can be stopped twice."""
    p = profiler.Profiler()
    p.start()
    p.stop(flush=False)
    p.stop(flush=False)