mirror of
https://github.com/open-telemetry/opentelemetry-python-contrib.git
synced 2025-07-31 06:03:21 +08:00
220 lines
7.7 KiB
Python
220 lines
7.7 KiB
Python
import time
|
|
|
|
import pytest
|
|
|
|
import mock
|
|
|
|
from ddtrace.span import Span
|
|
from ddtrace.api import API
|
|
from ddtrace.internal.writer import AgentWriter, Q, Empty
|
|
from ..base import BaseTestCase
|
|
|
|
|
|
class RemoveAllFilter:
|
|
def __init__(self):
|
|
self.filtered_traces = 0
|
|
|
|
def process_trace(self, trace):
|
|
self.filtered_traces += 1
|
|
return None
|
|
|
|
|
|
class KeepAllFilter:
|
|
def __init__(self):
|
|
self.filtered_traces = 0
|
|
|
|
def process_trace(self, trace):
|
|
self.filtered_traces += 1
|
|
return trace
|
|
|
|
|
|
class AddTagFilter:
|
|
def __init__(self, tag_name):
|
|
self.tag_name = tag_name
|
|
self.filtered_traces = 0
|
|
|
|
def process_trace(self, trace):
|
|
self.filtered_traces += 1
|
|
for span in trace:
|
|
span.set_tag(self.tag_name, "A value")
|
|
return trace
|
|
|
|
|
|
class DummyAPI(API):
|
|
def __init__(self):
|
|
# Call API.__init__ to setup required properties
|
|
super(DummyAPI, self).__init__(hostname="localhost", port=8126)
|
|
|
|
self.traces = []
|
|
|
|
def send_traces(self, traces):
|
|
responses = []
|
|
for trace in traces:
|
|
self.traces.append(trace)
|
|
response = mock.Mock()
|
|
response.status = 200
|
|
responses.append(response)
|
|
return responses
|
|
|
|
|
|
class FailingAPI(object):
|
|
@staticmethod
|
|
def send_traces(traces):
|
|
return [Exception("oops")]
|
|
|
|
|
|
class AgentWriterTests(BaseTestCase):
|
|
N_TRACES = 11
|
|
|
|
def create_worker(self, filters=None, api_class=DummyAPI, enable_stats=False):
|
|
with self.override_global_config(dict(health_metrics_enabled=enable_stats)):
|
|
self.dogstatsd = mock.Mock()
|
|
worker = AgentWriter(dogstatsd=self.dogstatsd, filters=filters)
|
|
worker._STATS_EVERY_INTERVAL = 1
|
|
self.api = api_class()
|
|
worker.api = self.api
|
|
for i in range(self.N_TRACES):
|
|
worker.write(
|
|
[Span(tracer=None, name="name", trace_id=i, span_id=j, parent_id=j - 1 or None) for j in range(7)]
|
|
)
|
|
worker.stop()
|
|
worker.join()
|
|
return worker
|
|
|
|
def test_send_stats(self):
|
|
dogstatsd = mock.Mock()
|
|
worker = AgentWriter(dogstatsd=dogstatsd)
|
|
assert worker._send_stats is False
|
|
with self.override_global_config(dict(health_metrics_enabled=True)):
|
|
assert worker._send_stats is True
|
|
|
|
worker = AgentWriter(dogstatsd=None)
|
|
assert worker._send_stats is False
|
|
with self.override_global_config(dict(health_metrics_enabled=True)):
|
|
assert worker._send_stats is False
|
|
|
|
def test_filters_keep_all(self):
|
|
filtr = KeepAllFilter()
|
|
self.create_worker([filtr])
|
|
self.assertEqual(len(self.api.traces), self.N_TRACES)
|
|
self.assertEqual(filtr.filtered_traces, self.N_TRACES)
|
|
|
|
def test_filters_remove_all(self):
|
|
filtr = RemoveAllFilter()
|
|
self.create_worker([filtr])
|
|
self.assertEqual(len(self.api.traces), 0)
|
|
self.assertEqual(filtr.filtered_traces, self.N_TRACES)
|
|
|
|
def test_filters_add_tag(self):
|
|
tag_name = "Tag"
|
|
filtr = AddTagFilter(tag_name)
|
|
self.create_worker([filtr])
|
|
self.assertEqual(len(self.api.traces), self.N_TRACES)
|
|
self.assertEqual(filtr.filtered_traces, self.N_TRACES)
|
|
for trace in self.api.traces:
|
|
for span in trace:
|
|
self.assertIsNotNone(span.get_tag(tag_name))
|
|
|
|
def test_filters_short_circuit(self):
|
|
filtr = KeepAllFilter()
|
|
filters = [RemoveAllFilter(), filtr]
|
|
self.create_worker(filters)
|
|
self.assertEqual(len(self.api.traces), 0)
|
|
self.assertEqual(filtr.filtered_traces, 0)
|
|
|
|
def test_no_dogstats(self):
|
|
worker = self.create_worker()
|
|
assert worker._send_stats is False
|
|
assert [] == self.dogstatsd.gauge.mock_calls
|
|
|
|
def test_dogstatsd(self):
|
|
self.create_worker(enable_stats=True)
|
|
assert [
|
|
mock.call("datadog.tracer.heartbeat", 1),
|
|
mock.call("datadog.tracer.queue.max_length", 1000),
|
|
] == self.dogstatsd.gauge.mock_calls
|
|
|
|
assert [
|
|
mock.call("datadog.tracer.flushes"),
|
|
mock.call("datadog.tracer.flush.traces.total", 11, tags=None),
|
|
mock.call("datadog.tracer.flush.spans.total", 77, tags=None),
|
|
mock.call("datadog.tracer.flush.traces_filtered.total", 0, tags=None),
|
|
mock.call("datadog.tracer.api.requests.total", 11, tags=None),
|
|
mock.call("datadog.tracer.api.errors.total", 0, tags=None),
|
|
mock.call("datadog.tracer.api.responses.total", 11, tags=["status:200"]),
|
|
mock.call("datadog.tracer.queue.dropped.traces", 0),
|
|
mock.call("datadog.tracer.queue.enqueued.traces", 11),
|
|
mock.call("datadog.tracer.queue.enqueued.spans", 77),
|
|
mock.call("datadog.tracer.shutdown"),
|
|
] == self.dogstatsd.increment.mock_calls
|
|
|
|
histogram_calls = [
|
|
mock.call("datadog.tracer.flush.traces", 11, tags=None),
|
|
mock.call("datadog.tracer.flush.spans", 77, tags=None),
|
|
mock.call("datadog.tracer.flush.traces_filtered", 0, tags=None),
|
|
mock.call("datadog.tracer.api.requests", 11, tags=None),
|
|
mock.call("datadog.tracer.api.errors", 0, tags=None),
|
|
mock.call("datadog.tracer.api.responses", 11, tags=["status:200"]),
|
|
]
|
|
if hasattr(time, "thread_time"):
|
|
histogram_calls.append(mock.call("datadog.tracer.writer.cpu_time", mock.ANY))
|
|
|
|
assert histogram_calls == self.dogstatsd.histogram.mock_calls
|
|
|
|
def test_dogstatsd_failing_api(self):
|
|
self.create_worker(api_class=FailingAPI, enable_stats=True)
|
|
assert [
|
|
mock.call("datadog.tracer.heartbeat", 1),
|
|
mock.call("datadog.tracer.queue.max_length", 1000),
|
|
] == self.dogstatsd.gauge.mock_calls
|
|
|
|
assert [
|
|
mock.call("datadog.tracer.flushes"),
|
|
mock.call("datadog.tracer.flush.traces.total", 11, tags=None),
|
|
mock.call("datadog.tracer.flush.spans.total", 77, tags=None),
|
|
mock.call("datadog.tracer.flush.traces_filtered.total", 0, tags=None),
|
|
mock.call("datadog.tracer.api.requests.total", 1, tags=None),
|
|
mock.call("datadog.tracer.api.errors.total", 1, tags=None),
|
|
mock.call("datadog.tracer.queue.dropped.traces", 0),
|
|
mock.call("datadog.tracer.queue.enqueued.traces", 11),
|
|
mock.call("datadog.tracer.queue.enqueued.spans", 77),
|
|
mock.call("datadog.tracer.shutdown"),
|
|
] == self.dogstatsd.increment.mock_calls
|
|
|
|
histogram_calls = [
|
|
mock.call("datadog.tracer.flush.traces", 11, tags=None),
|
|
mock.call("datadog.tracer.flush.spans", 77, tags=None),
|
|
mock.call("datadog.tracer.flush.traces_filtered", 0, tags=None),
|
|
mock.call("datadog.tracer.api.requests", 1, tags=None),
|
|
mock.call("datadog.tracer.api.errors", 1, tags=None),
|
|
]
|
|
if hasattr(time, "thread_time"):
|
|
histogram_calls.append(mock.call("datadog.tracer.writer.cpu_time", mock.ANY))
|
|
|
|
assert histogram_calls == self.dogstatsd.histogram.mock_calls
|
|
|
|
|
|
def test_queue_full():
|
|
q = Q(maxsize=3)
|
|
q.put([1])
|
|
q.put(2)
|
|
q.put([3])
|
|
q.put([4, 4])
|
|
assert list(q.queue) == [[1], 2, [4, 4]] or list(q.queue) == [[1], [4, 4], [3]] or list(q.queue) == [[4, 4], 2, [3]]
|
|
assert q.dropped == 1
|
|
assert q.accepted == 4
|
|
assert q.accepted_lengths == 5
|
|
dropped, accepted, accepted_lengths = q.reset_stats()
|
|
assert dropped == 1
|
|
assert accepted == 4
|
|
assert accepted_lengths == 5
|
|
|
|
|
|
def test_queue_get():
|
|
q = Q(maxsize=3)
|
|
q.put(1)
|
|
q.put(2)
|
|
assert list(q.get()) == [1, 2]
|
|
with pytest.raises(Empty):
|
|
q.get(block=False)
|