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_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_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_encode_traces_msgpack_v03(self): # test encoding for MsgPack format encoder = MsgpackEncoderV03(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"]
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 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)
def test_encoding_invalid_data(data): encoder = MsgpackEncoderV03(1 << 20, 1 << 20) span = Span(tracer=None, name="test") for key, value in data.items(): setattr(span, key, value) trace = [span] with pytest.raises(TypeError): encoder.put(trace) assert encoder.encode() is None
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_dd_origin_tagging_spans_via_encoder(benchmark, trace_size): """Propagate dd_origin tags to all spans in [1, 50, 200, 1000] span trace via Encoder""" trace_encoder = MsgpackEncoderV03(4 << 20, 4 << 20) tracer = DummyTracer() with tracer.trace("pytest-test") as root: root.context.dd_origin = CI_APP_TEST_ORIGIN for _ in range(trace_size - 1): with tracer.trace("") as span: span.set_tag("tag", "value") pass trace = tracer.writer.pop() def _(trace): trace_encoder.put(trace) trace_encoder.encode() benchmark(_, trace) # Ensure encoded trace contains dd_origin tag in all spans trace_encoder.put(trace) (decoded_trace, ) = trace_encoder._decode(trace_encoder.encode()) 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())