def test_encoder_buffer_item_size_limit():
    max_item_size = 1 << 10
    encoder = MsgpackEncoder(max_item_size << 1, max_item_size)

    span = Span(tracer=None, name="test")
    trace = [span]
    encoder.put(trace)
    trace_size = encoder.size - 1  # This includes the global msgpack array size prefix

    with pytest.raises(BufferItemTooLarge):
        encoder.put([span] * (int(max_item_size / trace_size) + 1))
def test_msgpack_span_property_variations(span):
    refencoder = RefMsgpackEncoder()
    encoder = MsgpackEncoder(1 << 10, 1 << 10)

    # Finish the span to ensure a duration exists.
    span.finish()

    trace = [span]
    encoder.put(trace)
    assert decode(refencoder.encode_traces([trace
                                            ])) == decode(encoder.encode())
def test_custom_msgpack_encode_trace_size(name, service, resource, meta,
                                          metrics, error, span_type):
    encoder = MsgpackEncoder(1 << 20, 1 << 20)
    span = Span(tracer=None, name=name, service=service, resource=resource)
    span.meta = meta
    span.metrics = metrics
    span.error = error
    span.span_type = span_type
    trace = [span, span, span]

    encoder.put(trace)
    assert encoder.size == len(encoder.encode())
def test_span_types(span, tags):
    refencoder = RefMsgpackEncoder()
    encoder = MsgpackEncoder(1 << 10, 1 << 10)

    span.set_tags(tags)

    # Finish the span to ensure a duration exists.
    span.finish()

    trace = [span]
    encoder.put(trace)
    assert decode(refencoder.encode_traces([trace
                                            ])) == decode(encoder.encode())
def test_encoder_propagates_dd_origin():
    tracer = DummyTracer()
    encoder = MsgpackEncoder(1 << 20, 1 << 20)
    with tracer.trace("Root") as root:
        root.context.dd_origin = CI_APP_TEST_ORIGIN
        for _ in range(999):
            with tracer.trace("child"):
                pass
    # Ensure encoded trace contains dd_origin tag in all spans
    trace = tracer.writer.pop()
    encoder.put(trace)
    decoded_trace = decode(encoder.encode())[0]
    for span in decoded_trace:
        assert span[b"meta"][b"_dd.origin"] == b"ciapp-test"
def test_custom_msgpack_encode():
    encoder = MsgpackEncoder(1 << 20, 1 << 20)
    refencoder = RefMsgpackEncoder()

    trace = gen_trace(nspans=50)

    # Note that we assert on the decoded versions because the encoded
    # can vary due to non-deterministic map key/value positioning
    encoder.put(trace)
    assert decode(refencoder.encode_traces([trace
                                            ])) == decode(encoder.encode())

    ref_encoded = refencoder.encode_traces([trace, trace])
    encoder.put(trace)
    encoder.put(trace)
    encoded = encoder.encode()
    assert decode(encoded) == decode(ref_encoded)

    # Empty trace (not that this should be done in practice)
    encoder.put([])
    assert decode(refencoder.encode_traces([[]])) == decode(encoder.encode())

    s = Span(None, None)
    # Need to .finish() to have a duration since the old implementation will not encode
    # duration_ns, the new one will encode as None
    s.finish()
    encoder.put([s])
    assert decode(refencoder.encode_traces([[s]])) == decode(encoder.encode())
def test_encoder_buffer_size_limit():
    buffer_size = 1 << 10
    encoder = MsgpackEncoder(buffer_size, buffer_size)

    trace = [Span(tracer=None, name="test")]
    encoder.put(trace)
    trace_size = encoder.size - 1  # This includes the global msgpack array size prefix

    for _ in range(1, int(buffer_size / trace_size)):
        encoder.put(trace)

    with pytest.raises(BufferFull):
        encoder.put(trace)

    with pytest.raises(BufferFull):
        encoder.put(trace)
Example #8
0
class DummyWriter(AgentWriter):
    """DummyWriter is a small fake writer used for tests. not thread-safe."""
    def __init__(self, *args, **kwargs):
        # original call
        if len(args) == 0 and "agent_url" not in kwargs:
            kwargs["agent_url"] = "http://localhost:8126"

        super(DummyWriter, self).__init__(*args, **kwargs)
        self.spans = []
        self.traces = []
        self.json_encoder = JSONEncoder()
        self.msgpack_encoder = Encoder(4 << 20, 4 << 20)

    def write(self, spans=None):
        if spans:
            # the traces encoding expect a list of traces so we
            # put spans in a list like we do in the real execution path
            # with both encoders
            traces = [spans]
            self.json_encoder.encode_traces(traces)
            self.msgpack_encoder.put(spans)
            self.msgpack_encoder.encode()
            self.spans += spans
            self.traces += traces

    def pop(self):
        # type: () -> List[Span]
        s = self.spans
        self.spans = []
        return s

    def pop_traces(self):
        # type: () -> List[List[Span]]
        traces = self.traces
        self.traces = []
        return traces
    def test_encode_traces_msgpack(self):
        # test encoding for MsgPack format
        encoder = MsgpackEncoder(2 << 10, 2 << 10)
        encoder.put([
            Span(name="client.testing", tracer=None),
            Span(name="client.testing", tracer=None),
        ])
        encoder.put([
            Span(name="client.testing", tracer=None),
            Span(name="client.testing", tracer=None),
        ])

        spans = encoder.encode()
        items = encoder._decode(spans)

        # test the encoded output that should be a string
        # and the output must be flatten
        assert isinstance(spans, msgpack_type)
        assert len(items) == 2
        assert len(items[0]) == 2
        assert len(items[1]) == 2
        for i in range(2):
            for j in range(2):
                assert b"client.testing" == items[i][j][b"name"]