예제 #1
0
def test_aggregator_single_span():
    class Proc(TraceProcessor):
        def process_trace(self, trace):
            return trace

    mock_proc1 = mock.Mock(wraps=Proc())
    mock_proc2 = mock.Mock(wraps=Proc())
    writer = DummyWriter()
    aggr = SpanAggregator(
        partial_flush_enabled=False,
        partial_flush_min_spans=0,
        trace_processors=[
            mock_proc1,
            mock_proc2,
        ],
        writer=writer,
    )

    span = Span(None, "span", on_finish=[aggr.on_span_finish])
    aggr.on_span_start(span)
    span.finish()

    mock_proc1.process_trace.assert_called_with([span])
    mock_proc2.process_trace.assert_called_with([span])
    assert writer.pop() == [span]
예제 #2
0
def test_aggregator_bad_processor():
    class Proc(TraceProcessor):
        def process_trace(self, trace):
            return trace

    class BadProc(TraceProcessor):
        def process_trace(self, trace):
            raise ValueError

    mock_good_before = mock.Mock(wraps=Proc())
    mock_bad = mock.Mock(wraps=BadProc())
    mock_good_after = mock.Mock(wraps=Proc())
    writer = DummyWriter()
    aggr = SpanAggregator(
        partial_flush_enabled=False,
        partial_flush_min_spans=0,
        trace_processors=[
            mock_good_before,
            mock_bad,
            mock_good_after,
        ],
        writer=writer,
    )

    span = Span(None, "span", on_finish=[aggr.on_span_finish])
    aggr.on_span_start(span)
    span.finish()

    mock_good_before.process_trace.assert_called_with([span])
    mock_bad.process_trace.assert_called_with([span])
    mock_good_after.process_trace.assert_called_with([span])
    assert writer.pop() == [span]
예제 #3
0
def test_aggregator_partial_flush_0_spans():
    writer = DummyWriter()
    aggr = SpanAggregator(partial_flush_enabled=True, partial_flush_min_spans=0, trace_processors=[], writer=writer)

    # Normal usage
    parent = Span(None, "parent", on_finish=[aggr.on_span_finish])
    aggr.on_span_start(parent)
    child = Span(None, "child", on_finish=[aggr.on_span_finish])
    child.trace_id = parent.trace_id
    child.parent_id = parent.span_id
    aggr.on_span_start(child)

    assert writer.pop() == []
    child.finish()
    assert writer.pop() == [child]
    parent.finish()
    assert writer.pop() == [parent]

    # Parent closes before child
    parent = Span(None, "parent", on_finish=[aggr.on_span_finish])
    aggr.on_span_start(parent)
    child = Span(None, "child", on_finish=[aggr.on_span_finish])
    child.trace_id = parent.trace_id
    child.parent_id = parent.span_id
    aggr.on_span_start(child)

    assert writer.pop() == []
    parent.finish()
    assert writer.pop() == [parent]
    child.finish()
    assert writer.pop() == [child]
예제 #4
0
    def test_tracer_is_properly_configured(self):
        # the tracer must be properly configured
        assert self.tracer.tags == {"env": "production", "debug": "false"}
        assert self.tracer.enabled is False
        assert self.tracer.writer.agent_url == "http://dd-agent.service.consul:8126"

        writer = DummyWriter()
        self.tracer.configure(enabled=True, writer=writer)
        with self.tracer.trace("keep"):
            pass
        spans = writer.pop()
        assert len(spans) == 1

        with self.tracer.trace("drop"):
            pass
        spans = writer.pop()
        assert len(spans) == 0
예제 #5
0
def test_trace_top_level_span_processor_different_service_name():
    """Parent span and child span have the different service names"""

    tracer = Tracer()
    tracer.configure(writer=DummyWriter())

    with tracer.trace("parent", service="top_level_test_service") as parent:
        with tracer.trace("child", service="top_level_test_service2") as child:
            pass

    assert parent.get_metric("_dd.top_level") == 1
    assert child.get_metric("_dd.top_level") == 1
예제 #6
0
def test_trace_top_level_span_processor_same_service_name():
    """Parent span and child span have the same service name"""

    tracer = Tracer()
    tracer.configure(writer=DummyWriter())

    with tracer.trace("parent", service="top_level_test") as parent:
        with tracer.trace("child") as child:
            pass

    assert parent.get_metric("_dd.top_level") == 1
    assert "_dd.top_level" not in child.metrics
예제 #7
0
def test_trace_top_level_span_processor_orphan_span():
    """Trace chuck does not contain parent span"""

    tracer = Tracer()
    tracer.configure(writer=DummyWriter())

    with tracer.trace("parent") as parent:
        pass

    with tracer.start_span("orphan span", child_of=parent) as orphan_span:
        pass

    # top_level in orphan_span should be explicitly set to zero/false
    assert orphan_span.get_metric("_dd.top_level") == 0
예제 #8
0
def test_trace_top_level_span_processor_partial_flushing():
    """Parent span and child span have the same service name"""
    tracer = Tracer()
    tracer.configure(
        partial_flush_enabled=True,
        partial_flush_min_spans=2,
        writer=DummyWriter(),
    )

    with tracer.trace("parent") as parent:
        with tracer.trace("1") as child1:
            pass
        with tracer.trace("2") as child2:
            pass
        with tracer.trace("3") as child3:
            pass

    # child spans 1 and 2 were partial flushed WITHOUT the parent span in the trace chunk
    assert child1.get_metric("_dd.top_level") == 0
    assert child2.get_metric("_dd.top_level") == 0

    # child span 3 was partial flushed WITH the parent span in the trace chunk
    assert "_dd.top_level" not in child3.metrics
    assert parent.get_metric("_dd.top_level") == 1
예제 #9
0
An integration test that uses a real Redis client
that we expect to be implicitly traced via `ddtrace-run`
"""

import redis

from ddtrace import Pin
from tests.contrib.config import REDIS_CONFIG
from tests.utils import DummyWriter

if __name__ == "__main__":
    r = redis.Redis(port=REDIS_CONFIG["port"])
    pin = Pin.get_from(r)
    assert pin

    pin.tracer.writer = DummyWriter()
    r.flushall()
    spans = pin.tracer.writer.pop()

    assert len(spans) == 1
    assert spans[0].service == "redis"
    assert spans[0].resource == "FLUSHALL"

    long_cmd = "mget %s" % " ".join(map(str, range(1000)))
    us = r.execute_command(long_cmd)

    spans = pin.tracer.writer.pop()
    assert len(spans) == 1
    span = spans[0]
    assert span.service == "redis"
    assert span.name == "redis.command"
예제 #10
0
An integration test that uses a real Redis client
that we expect to be implicitly traced via `ddtrace-run`
"""

import redis

from ddtrace import Pin
from tests.contrib.config import REDIS_CONFIG
from tests.utils import DummyWriter

if __name__ == "__main__":
    r = redis.Redis(port=REDIS_CONFIG["port"])
    pin = Pin.get_from(r)
    assert pin

    writer = DummyWriter()
    pin.tracer.configure(writer=writer)
    r.flushall()
    spans = writer.pop()

    assert len(spans) == 1
    assert spans[0].service == "redis"
    assert spans[0].resource == "FLUSHALL"

    long_cmd = "mget %s" % " ".join(map(str, range(1000)))
    us = r.execute_command(long_cmd)

    spans = writer.pop()
    assert len(spans) == 1
    span = spans[0]
    assert span.service == "redis"
예제 #11
0
def test_aggregator_partial_flush_2_spans():
    writer = DummyWriter()
    aggr = SpanAggregator(partial_flush_enabled=True,
                          partial_flush_min_spans=2,
                          trace_processors=[],
                          writer=writer)

    # Normal usage
    parent = Span("parent", on_finish=[aggr.on_span_finish])
    aggr.on_span_start(parent)
    child = Span("child", on_finish=[aggr.on_span_finish])
    child.trace_id = parent.trace_id
    child.parent_id = parent.span_id
    aggr.on_span_start(child)

    assert writer.pop() == []
    child.finish()
    assert writer.pop() == []
    parent.finish()
    assert writer.pop() == [parent, child]

    # Parent closes before child
    parent = Span("parent", on_finish=[aggr.on_span_finish])
    aggr.on_span_start(parent)
    child = Span("child", on_finish=[aggr.on_span_finish])
    child.trace_id = parent.trace_id
    child.parent_id = parent.span_id
    aggr.on_span_start(child)

    assert writer.pop() == []
    parent.finish()
    assert writer.pop() == []
    child.finish()
    assert writer.pop() == [parent, child]

    # Partial flush
    parent = Span("parent", on_finish=[aggr.on_span_finish])
    aggr.on_span_start(parent)
    child1 = Span("child1", on_finish=[aggr.on_span_finish])
    child1.trace_id = parent.trace_id
    child1.parent_id = parent.span_id
    aggr.on_span_start(child1)
    child2 = Span("child2", on_finish=[aggr.on_span_finish])
    child2.trace_id = parent.trace_id
    child2.parent_id = parent.span_id
    aggr.on_span_start(child2)

    assert writer.pop() == []
    child1.finish()
    assert writer.pop() == []
    child2.finish()
    assert writer.pop() == [child1, child2]
    assert child1.get_metric("_dd.py.partial_flush") == 2
    assert child2.get_metric("_dd.py.partial_flush") is None
    parent.finish()
    assert writer.pop() == [parent]
    assert parent.get_metric("_dd.py.partial_flush") is None