class TestRateByService(TestCase): """ Check we get feedback from the agent and we're able to process it. """ def setUp(self): """ Create a tracer without workers, while spying the ``send()`` method """ # create a new API object to test the transport using synchronous calls self.tracer = get_dummy_tracer() self.api_json = API('localhost', 8126, encoder=JSONEncoder()) self.api_msgpack = API('localhost', 8126, encoder=MsgpackEncoder()) def test_send_single_trace(self): # register a single trace with a span and send them to the trace agent self.tracer.trace('client.testing').finish() trace = self.tracer.writer.pop() traces = [trace] # [TODO:christian] when CI has an agent that is able to process the v0.4 # endpoint, add a check to: # - make sure the output is a valid JSON # - make sure the priority sampler (if enabled) is updated # test JSON encoder response = self.api_json.send_traces(traces) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_traces(traces) ok_(response) eq_(response.status, 200)
class TestRateByService(TestCase): """ Check we get feedback from the agent and we're able to process it. """ def setUp(self): """ Create a tracer without workers, while spying the ``send()`` method """ # create a new API object to test the transport using synchronous calls self.tracer = get_dummy_tracer() self.api_json = API('localhost', 8126, encoder=JSONEncoder()) self.api_msgpack = API('localhost', 8126, encoder=MsgpackEncoder()) def test_send_single_trace(self): # register a single trace with a span and send them to the trace agent self.tracer.trace('client.testing').finish() trace = self.tracer.writer.pop() traces = [trace] # [TODO:christian] when CI has an agent that is able to process the v0.4 # endpoint, add a check to: # - make sure the output is a valid JSON # - make sure the priority sampler (if enabled) is updated # test JSON encoder response = self.api_json.send_traces(traces) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_traces(traces) ok_(response) eq_(response.status, 200)
class TestRateByService(TestCase): """ Check we get feedback from the agent and we're able to process it. """ def setUp(self): """ Create a tracer without workers, while spying the ``send()`` method """ # create a new API object to test the transport using synchronous calls self.tracer = get_dummy_tracer() self.api_json = API("localhost", 8126, encoder=JSONEncoder(), priority_sampling=True) self.api_msgpack = API("localhost", 8126, encoder=MsgpackEncoder(), priority_sampling=True) @pytest.mark.skipif(AGENT_VERSION == "testagent", reason="Test agent doesn't yet support rate sampling.") def test_send_single_trace(self): # register a single trace with a span and send them to the trace agent self.tracer.trace("client.testing").finish() trace = self.tracer.writer.pop() traces = [trace] # [TODO:christian] when CI has an agent that is able to process the v0.4 # endpoint, add a check to: # - make sure the output is a valid JSON # - make sure the priority sampler (if enabled) is updated # test JSON encoder responses = self.api_json.send_traces(traces) assert len(responses) == 1 assert responses[0].status == 200 resp = responses[0].get_json() assert isinstance(resp["rate_by_service"]["service:,env:"], numeric_types) # test Msgpack encoder responses = self.api_msgpack.send_traces(traces) assert len(responses) == 1 assert responses[0].status == 200 resp = responses[0].get_json() assert isinstance(resp["rate_by_service"]["service:,env:"], numeric_types)
def test_downgrade_api(self): # make a call to a not existing endpoint, downgrades # the current API to a stable one tracer = get_dummy_tracer() tracer.trace('client.testing').finish() trace = tracer.writer.pop() # the encoder is right but we're targeting an API # endpoint that is not available api = API('localhost', 8126) api._traces = '/v0.0/traces' assert isinstance(api._encoder, MsgpackEncoder) # after the call, we downgrade to a working endpoint response = api.send_traces([trace]) assert response assert response.status == 200 assert isinstance(api._encoder, JSONEncoder)
def test_downgrade_api(self): # make a call to a not existing endpoint, downgrades # the current API to a stable one tracer = get_dummy_tracer() tracer.trace('client.testing').finish() trace = tracer.writer.pop() # the encoder is right but we're targeting an API # endpoint that is not available api = API('localhost', 8126) api._traces = '/v0.0/traces' ok_(isinstance(api._encoder, MsgpackEncoder)) # after the call, we downgrade to a working endpoint response = api.send_traces([trace]) ok_(response) eq_(response.status, 200) ok_(isinstance(api._encoder, JSONEncoder))
class TestAPITransport(TestCase): """ Ensures that traces are properly sent to a local agent. These are part of integration tests so real calls are triggered and you have to execute a real trace-agent to let them pass. """ @mock.patch('ddtrace.internal.runtime.container.get_container_info') def setUp(self, get_container_info): """ Create a tracer without workers, while spying the ``send()`` method """ # Mock the container id we use for making requests get_container_info.return_value = CGroupInfo( container_id='test-container-id') # create a new API object to test the transport using synchronous calls self.tracer = get_dummy_tracer() self.api_json = API('localhost', 8126, encoder=JSONEncoder()) self.api_msgpack = API('localhost', 8126, encoder=MsgpackEncoder()) @mock.patch('ddtrace.api.httplib.HTTPConnection') def test_send_presampler_headers(self, mocked_http): # register a single trace with a span and send them to the trace agent self.tracer.trace('client.testing').finish() trace = self.tracer.writer.pop() traces = [trace] # make a call and retrieve the `conn` Mock object self.api_msgpack.send_traces(traces) request_call = mocked_http.return_value.request assert request_call.call_count == 1 # retrieve the headers from the mocked request call expected_headers = { 'Datadog-Container-Id': 'test-container-id', # mocked in setUp() 'Datadog-Meta-Lang': 'python', 'Datadog-Meta-Lang-Interpreter': PYTHON_INTERPRETER, 'Datadog-Meta-Lang-Version': PYTHON_VERSION, 'Datadog-Meta-Tracer-Version': ddtrace.__version__, 'X-Datadog-Trace-Count': '1', 'Content-Type': 'application/msgpack', } params, _ = request_call.call_args_list[0] headers = params[3] assert len(expected_headers) == len(headers) for k, v in expected_headers.items(): assert v == headers[k] @mock.patch('ddtrace.api.httplib.HTTPConnection') def test_send_presampler_headers_not_in_services(self, mocked_http): # register some services and send them to the trace agent services = [{ 'client.service': { 'app': 'django', 'app_type': 'web', }, }] # make a call and retrieve the `conn` Mock object self.api_msgpack.send_services(services) request_call = mocked_http.return_value.request assert request_call.call_count == 0 def _send_traces_and_check(self, traces, nresponses=1): # test JSON encoder responses = self.api_json.send_traces(traces) assert len(responses) == nresponses for response in responses: assert response.status == 200 # test Msgpack encoder responses = self.api_msgpack.send_traces(traces) assert len(responses) == nresponses for response in responses: assert response.status == 200 def test_send_single_trace(self): # register a single trace with a span and send them to the trace agent self.tracer.trace('client.testing').finish() trace = self.tracer.writer.pop() traces = [trace] self._send_traces_and_check(traces) def test_send_many_traces(self): # register a single trace with a span and send them to the trace agent self.tracer.trace('client.testing').finish() trace = self.tracer.writer.pop() # 30k is a right number to have both json and msgpack send 2 payload :) traces = [trace] * 30000 self._send_traces_and_check(traces, 2) def test_send_single_with_wrong_errors(self): # if the error field is set to True, it must be cast as int so # that the agent decoder handles that properly without providing # a decoding error span = self.tracer.trace('client.testing') span.error = True span.finish() trace = self.tracer.writer.pop() traces = [trace] self._send_traces_and_check(traces) def test_send_multiple_traces(self): # register some traces and send them to the trace agent self.tracer.trace('client.testing').finish() trace_1 = self.tracer.writer.pop() self.tracer.trace('client.testing').finish() trace_2 = self.tracer.writer.pop() traces = [trace_1, trace_2] self._send_traces_and_check(traces) def test_send_single_trace_multiple_spans(self): # register some traces and send them to the trace agent with self.tracer.trace('client.testing'): self.tracer.trace('client.testing').finish() trace = self.tracer.writer.pop() traces = [trace] self._send_traces_and_check(traces) def test_send_multiple_traces_multiple_spans(self): # register some traces and send them to the trace agent with self.tracer.trace('client.testing'): self.tracer.trace('client.testing').finish() trace_1 = self.tracer.writer.pop() with self.tracer.trace('client.testing'): self.tracer.trace('client.testing').finish() trace_2 = self.tracer.writer.pop() traces = [trace_1, trace_2] self._send_traces_and_check(traces) def test_send_single_service(self): # register some services and send them to the trace agent services = [{ 'client.service': { 'app': 'django', 'app_type': 'web', }, }] # test JSON encoder response = self.api_json.send_services(services) assert response is None # test Msgpack encoder response = self.api_msgpack.send_services(services) assert response is None def test_send_service_called_multiple_times(self): # register some services and send them to the trace agent services = [{ 'backend': { 'app': 'django', 'app_type': 'web', }, 'database': { 'app': 'postgres', 'app_type': 'db', }, }] # test JSON encoder response = self.api_json.send_services(services) assert response is None # test Msgpack encoder response = self.api_msgpack.send_services(services) assert response is None
class TestAPITransport(TestCase): """ Ensures that traces are properly sent to a local agent. These are part of integration tests so real calls are triggered and you have to execute a real trace-agent to let them pass. """ def setUp(self): """ Create a tracer without workers, while spying the ``send()`` method """ # create a new API object to test the transport using synchronous calls self.tracer = get_dummy_tracer() self.api_json = API('localhost', 7777, encoder=JSONEncoder()) self.api_msgpack = API('localhost', 7777, encoder=MsgpackEncoder()) def test_send_single_trace(self): # register a single trace with a span and send them to the trace agent self.tracer.trace('client.testing').finish() trace = self.tracer.writer.pop() traces = [trace] # test JSON encoder response = self.api_json.send_traces(traces) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_traces(traces) ok_(response) eq_(response.status, 200) def test_send_multiple_traces(self): # register some traces and send them to the trace agent self.tracer.trace('client.testing').finish() trace_1 = self.tracer.writer.pop() self.tracer.trace('client.testing').finish() trace_2 = self.tracer.writer.pop() traces = [trace_1, trace_2] # test JSON encoder response = self.api_json.send_traces(traces) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_traces(traces) ok_(response) eq_(response.status, 200) def test_send_single_trace_multiple_spans(self): # register some traces and send them to the trace agent with self.tracer.trace('client.testing'): self.tracer.trace('client.testing').finish() trace = self.tracer.writer.pop() traces = [trace] # test JSON encoder response = self.api_json.send_traces(traces) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_traces(traces) ok_(response) eq_(response.status, 200) def test_send_multiple_traces_multiple_spans(self): # register some traces and send them to the trace agent with self.tracer.trace('client.testing'): self.tracer.trace('client.testing').finish() trace_1 = self.tracer.writer.pop() with self.tracer.trace('client.testing'): self.tracer.trace('client.testing').finish() trace_2 = self.tracer.writer.pop() traces = [trace_1, trace_2] # test JSON encoder response = self.api_json.send_traces(traces) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_traces(traces) ok_(response) eq_(response.status, 200) def test_send_single_service(self): # register some services and send them to the trace agent services = [{ 'client.service': { 'app': 'django', 'app_type': 'web', }, }] # test JSON encoder response = self.api_json.send_services(services) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_services(services) ok_(response) eq_(response.status, 200) def test_send_service_called_multiple_times(self): # register some services and send them to the trace agent services = [{ 'backend': { 'app': 'django', 'app_type': 'web', }, 'database': { 'app': 'postgres', 'app_type': 'db', }, }] # test JSON encoder response = self.api_json.send_services(services) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_services(services) ok_(response) eq_(response.status, 200)
class TestAPITransport(TestCase): """ Ensures that traces are properly sent to a local agent. These are part of integration tests so real calls are triggered and you have to execute a real trace-agent to let them pass. """ def setUp(self): """ Create a tracer without workers, while spying the ``send()`` method """ # create a new API object to test the transport using synchronous calls self.tracer = get_dummy_tracer() self.api_json = API('localhost', 8126, encoder=JSONEncoder()) self.api_msgpack = API('localhost', 8126, encoder=MsgpackEncoder()) @mock.patch('ddtrace.api.httplib.HTTPConnection') def test_send_presampler_headers(self, mocked_http): # register a single trace with a span and send them to the trace agent self.tracer.trace('client.testing').finish() trace = self.tracer.writer.pop() traces = [trace] # make a call and retrieve the `conn` Mock object response = self.api_msgpack.send_traces(traces) request_call = mocked_http.return_value.request eq_(request_call.call_count, 1) # retrieve the headers from the mocked request call expected_headers = { 'Datadog-Meta-Lang': 'python', 'Datadog-Meta-Lang-Interpreter': PYTHON_INTERPRETER, 'Datadog-Meta-Lang-Version': PYTHON_VERSION, 'Datadog-Meta-Tracer-Version': ddtrace.__version__, 'X-Datadog-Trace-Count': '1', 'Content-Type': 'application/msgpack' } params, _ = request_call.call_args_list[0] headers = params[3] eq_(len(expected_headers), len(headers)) for k, v in expected_headers.items(): eq_(v, headers[k]) @mock.patch('ddtrace.api.httplib.HTTPConnection') def test_send_presampler_headers_not_in_services(self, mocked_http): # register some services and send them to the trace agent services = [{ 'client.service': { 'app': 'django', 'app_type': 'web', }, }] # make a call and retrieve the `conn` Mock object response = self.api_msgpack.send_services(services) request_call = mocked_http.return_value.request eq_(request_call.call_count, 1) # retrieve the headers from the mocked request call expected_headers = { 'Datadog-Meta-Lang': 'python', 'Datadog-Meta-Lang-Interpreter': PYTHON_INTERPRETER, 'Datadog-Meta-Lang-Version': PYTHON_VERSION, 'Datadog-Meta-Tracer-Version': ddtrace.__version__, 'Content-Type': 'application/msgpack' } params, _ = request_call.call_args_list[0] headers = params[3] eq_(len(expected_headers), len(headers)) for k, v in expected_headers.items(): eq_(v, headers[k]) # retrieve the headers from the mocked request call params, _ = request_call.call_args_list[0] headers = params[3] ok_('X-Datadog-Trace-Count' not in headers.keys()) def test_send_single_trace(self): # register a single trace with a span and send them to the trace agent self.tracer.trace('client.testing').finish() trace = self.tracer.writer.pop() traces = [trace] # test JSON encoder response = self.api_json.send_traces(traces) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_traces(traces) ok_(response) eq_(response.status, 200) def test_send_single_with_wrong_errors(self): # if the error field is set to True, it must be cast as int so # that the agent decoder handles that properly without providing # a decoding error span = self.tracer.trace('client.testing') span.error = True span.finish() trace = self.tracer.writer.pop() traces = [trace] # test JSON encoder response = self.api_json.send_traces(traces) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_traces(traces) ok_(response) eq_(response.status, 200) def test_send_multiple_traces(self): # register some traces and send them to the trace agent self.tracer.trace('client.testing').finish() trace_1 = self.tracer.writer.pop() self.tracer.trace('client.testing').finish() trace_2 = self.tracer.writer.pop() traces = [trace_1, trace_2] # test JSON encoder response = self.api_json.send_traces(traces) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_traces(traces) ok_(response) eq_(response.status, 200) def test_send_single_trace_multiple_spans(self): # register some traces and send them to the trace agent with self.tracer.trace('client.testing'): self.tracer.trace('client.testing').finish() trace = self.tracer.writer.pop() traces = [trace] # test JSON encoder response = self.api_json.send_traces(traces) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_traces(traces) ok_(response) eq_(response.status, 200) def test_send_multiple_traces_multiple_spans(self): # register some traces and send them to the trace agent with self.tracer.trace('client.testing'): self.tracer.trace('client.testing').finish() trace_1 = self.tracer.writer.pop() with self.tracer.trace('client.testing'): self.tracer.trace('client.testing').finish() trace_2 = self.tracer.writer.pop() traces = [trace_1, trace_2] # test JSON encoder response = self.api_json.send_traces(traces) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_traces(traces) ok_(response) eq_(response.status, 200) def test_send_single_service(self): # register some services and send them to the trace agent services = [{ 'client.service': { 'app': 'django', 'app_type': 'web', }, }] # test JSON encoder response = self.api_json.send_services(services) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_services(services) ok_(response) eq_(response.status, 200) def test_send_service_called_multiple_times(self): # register some services and send them to the trace agent services = [{ 'backend': { 'app': 'django', 'app_type': 'web', }, 'database': { 'app': 'postgres', 'app_type': 'db', }, }] # test JSON encoder response = self.api_json.send_services(services) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_services(services) ok_(response) eq_(response.status, 200)
class TestAPITransport(TestCase): """ Ensures that traces are properly sent to a local agent. These are part of integration tests so real calls are triggered and you have to execute a real trace-agent to let them pass. """ def setUp(self): """ Create a tracer without workers, while spying the ``send()`` method """ # create a new API object to test the transport using synchronous calls self.tracer = get_dummy_tracer() self.api_json = API('localhost', 8126, encoder=JSONEncoder()) self.api_msgpack = API('localhost', 8126, encoder=MsgpackEncoder()) @mock.patch('ddtrace.api.httplib.HTTPConnection') def test_send_presampler_headers(self, mocked_http): # register a single trace with a span and send them to the trace agent self.tracer.trace('client.testing').finish() trace = self.tracer.writer.pop() traces = [trace] # make a call and retrieve the `conn` Mock object response = self.api_msgpack.send_traces(traces) request_call = mocked_http.return_value.request eq_(request_call.call_count, 1) # retrieve the headers from the mocked request call expected_headers = { 'Datadog-Meta-Lang': 'python', 'Datadog-Meta-Lang-Interpreter': PYTHON_INTERPRETER, 'Datadog-Meta-Lang-Version': PYTHON_VERSION, 'Datadog-Meta-Tracer-Version': ddtrace.__version__, 'X-Datadog-Trace-Count': '1', 'Content-Type': 'application/msgpack' } params, _ = request_call.call_args_list[0] headers = params[3] eq_(len(expected_headers), len(headers)) for k, v in expected_headers.items(): eq_(v, headers[k]) @mock.patch('ddtrace.api.httplib.HTTPConnection') def test_send_presampler_headers_not_in_services(self, mocked_http): # register some services and send them to the trace agent services = [{ 'client.service': { 'app': 'django', 'app_type': 'web', }, }] # make a call and retrieve the `conn` Mock object response = self.api_msgpack.send_services(services) request_call = mocked_http.return_value.request eq_(request_call.call_count, 1) # retrieve the headers from the mocked request call expected_headers = { 'Datadog-Meta-Lang': 'python', 'Datadog-Meta-Lang-Interpreter': PYTHON_INTERPRETER, 'Datadog-Meta-Lang-Version': PYTHON_VERSION, 'Datadog-Meta-Tracer-Version': ddtrace.__version__, 'Content-Type': 'application/msgpack' } params, _ = request_call.call_args_list[0] headers = params[3] eq_(len(expected_headers), len(headers)) for k, v in expected_headers.items(): eq_(v, headers[k]) # retrieve the headers from the mocked request call params, _ = request_call.call_args_list[0] headers = params[3] ok_('X-Datadog-Trace-Count' not in headers.keys()) def test_send_single_trace(self): # register a single trace with a span and send them to the trace agent self.tracer.trace('client.testing').finish() trace = self.tracer.writer.pop() traces = [trace] # test JSON encoder response = self.api_json.send_traces(traces) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_traces(traces) ok_(response) eq_(response.status, 200) def test_send_single_with_wrong_errors(self): # if the error field is set to True, it must be cast as int so # that the agent decoder handles that properly without providing # a decoding error span = self.tracer.trace('client.testing') span.error = True span.finish() trace = self.tracer.writer.pop() traces = [trace] # test JSON encoder response = self.api_json.send_traces(traces) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_traces(traces) ok_(response) eq_(response.status, 200) def test_send_multiple_traces(self): # register some traces and send them to the trace agent self.tracer.trace('client.testing').finish() trace_1 = self.tracer.writer.pop() self.tracer.trace('client.testing').finish() trace_2 = self.tracer.writer.pop() traces = [trace_1, trace_2] # test JSON encoder response = self.api_json.send_traces(traces) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_traces(traces) ok_(response) eq_(response.status, 200) def test_send_single_trace_multiple_spans(self): # register some traces and send them to the trace agent with self.tracer.trace('client.testing'): self.tracer.trace('client.testing').finish() trace = self.tracer.writer.pop() traces = [trace] # test JSON encoder response = self.api_json.send_traces(traces) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_traces(traces) ok_(response) eq_(response.status, 200) def test_send_multiple_traces_multiple_spans(self): # register some traces and send them to the trace agent with self.tracer.trace('client.testing'): self.tracer.trace('client.testing').finish() trace_1 = self.tracer.writer.pop() with self.tracer.trace('client.testing'): self.tracer.trace('client.testing').finish() trace_2 = self.tracer.writer.pop() traces = [trace_1, trace_2] # test JSON encoder response = self.api_json.send_traces(traces) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_traces(traces) ok_(response) eq_(response.status, 200) def test_send_single_service(self): # register some services and send them to the trace agent services = [{ 'client.service': { 'app': 'django', 'app_type': 'web', }, }] # test JSON encoder response = self.api_json.send_services(services) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_services(services) ok_(response) eq_(response.status, 200) def test_send_service_called_multiple_times(self): # register some services and send them to the trace agent services = [{ 'backend': { 'app': 'django', 'app_type': 'web', }, 'database': { 'app': 'postgres', 'app_type': 'db', }, }] # test JSON encoder response = self.api_json.send_services(services) ok_(response) eq_(response.status, 200) # test Msgpack encoder response = self.api_msgpack.send_services(services) ok_(response) eq_(response.status, 200)
class TestAPITransport(TestCase): """ Ensures that traces are properly sent to a local agent. These are part of integration tests so real calls are triggered and you have to execute a real trace-agent to let them pass. """ @mock.patch("ddtrace.internal.runtime.container.get_container_info") def setUp(self, get_container_info): """ Create a tracer without workers, while spying the ``send()`` method """ # Mock the container id we use for making requests get_container_info.return_value = CGroupInfo( container_id="test-container-id") # create a new API object to test the transport using synchronous calls self.tracer = get_dummy_tracer() self.api_json = API("localhost", 8126, encoder=JSONEncoder()) self.api_msgpack = API("localhost", 8126, encoder=MsgpackEncoder()) @mock.patch("ddtrace.api.httplib.HTTPConnection") def test_send_presampler_headers(self, mocked_http): # register a single trace with a span and send them to the trace agent self.tracer.trace("client.testing").finish() trace = self.tracer.writer.pop() traces = [trace] # make a call and retrieve the `conn` Mock object self.api_msgpack.send_traces(traces) request_call = mocked_http.return_value.request assert request_call.call_count == 1 # retrieve the headers from the mocked request call expected_headers = { "Datadog-Container-Id": "test-container-id", # mocked in setUp() "Datadog-Meta-Lang": "python", "Datadog-Meta-Lang-Interpreter": PYTHON_INTERPRETER, "Datadog-Meta-Lang-Version": PYTHON_VERSION, "Datadog-Meta-Tracer-Version": ddtrace.__version__, "X-Datadog-Trace-Count": "1", "Content-Type": "application/msgpack", } params, _ = request_call.call_args_list[0] headers = params[3] assert expected_headers == headers def _send_traces_and_check(self, traces, nresponses=1): # test JSON encoder responses = self.api_json.send_traces(traces) assert len(responses) == nresponses for response in responses: assert isinstance(response, Exception) or response.status == 200 # test Msgpack encoder responses = self.api_msgpack.send_traces(traces) assert len(responses) == nresponses for response in responses: assert isinstance(response, Exception) or response.status == 200 def test_send_single_trace(self): # register a single trace with a span and send them to the trace agent self.tracer.trace("client.testing").finish() trace = self.tracer.writer.pop() traces = [trace] self._send_traces_and_check(traces) def test_send_many_traces(self): # register a single trace with a span and send them to the trace agent self.tracer.trace("client.testing").finish() trace = self.tracer.writer.pop() # 20k is a right number to have both json and msgpack send 2 payload :) traces = [trace] * 20000 self._send_traces_and_check(traces, 2) def test_send_single_trace_max_payload(self): payload = Payload() # compute number of spans to create to surpass max payload trace = [Span(self.tracer, "child.span")] trace_size = len(payload.encoder.encode_trace(trace)) num_spans = int(math.floor(payload.max_payload_size / trace_size)) # setup logging capture log = logging.getLogger("ddtrace.api") log_handler = MockedLogHandler(level="WARNING") log.addHandler(log_handler) with self.tracer.trace("client.testing"): for n in range(num_spans): self.tracer.trace("child.span").finish() trace = self.tracer.writer.pop() self._send_traces_and_check([trace], 1) logged_warnings = log_handler.messages["warning"] assert len(logged_warnings) == 1 assert "Trace is larger than the max payload size, dropping it" in logged_warnings[ 0] def test_send_multiple_trace_max_payload(self): payload = Payload() # compute number of spans to create to surpass max payload trace = [Span(self.tracer, "child.span")] trace_size = len(payload.encoder.encode_trace(trace)) num_spans = int( math.floor((payload.max_payload_size - trace_size) / trace_size)) # setup logging capture log = logging.getLogger("ddtrace.api") log_handler = MockedLogHandler(level="WARNING") log.addHandler(log_handler) self.tracer.trace("client.testing").finish() traces = [self.tracer.writer.pop()] # create a trace larger than max payload size with self.tracer.trace("client.testing"): for n in range(num_spans): self.tracer.trace("child.span").finish() traces.append(self.tracer.writer.pop()) self._send_traces_and_check(traces, 2) logged_warnings = log_handler.messages["warning"] assert len(logged_warnings) == 1 assert "Trace is too big to fit in a payload, dropping it" in logged_warnings[ 0] def test_send_single_with_wrong_errors(self): # if the error field is set to True, it must be cast as int so # that the agent decoder handles that properly without providing # a decoding error span = self.tracer.trace("client.testing") span.error = True span.finish() trace = self.tracer.writer.pop() traces = [trace] self._send_traces_and_check(traces) def test_send_multiple_traces(self): # register some traces and send them to the trace agent self.tracer.trace("client.testing").finish() trace_1 = self.tracer.writer.pop() self.tracer.trace("client.testing").finish() trace_2 = self.tracer.writer.pop() traces = [trace_1, trace_2] self._send_traces_and_check(traces) def test_send_single_trace_multiple_spans(self): # register some traces and send them to the trace agent with self.tracer.trace("client.testing"): self.tracer.trace("client.testing").finish() trace = self.tracer.writer.pop() traces = [trace] self._send_traces_and_check(traces) def test_send_multiple_traces_multiple_spans(self): # register some traces and send them to the trace agent with self.tracer.trace("client.testing"): self.tracer.trace("client.testing").finish() trace_1 = self.tracer.writer.pop() with self.tracer.trace("client.testing"): self.tracer.trace("client.testing").finish() trace_2 = self.tracer.writer.pop() traces = [trace_1, trace_2] self._send_traces_and_check(traces)