Repository: DataDog/datadogpy

Issue:
Threadstatsd set metric
There appears to be a disconnect between dogstatd and threadstatsd.

the `set` method is not supported. What is the equivalent in the thread version?

https://github.com/DataDog/datadogpy/blob/master/datadog/dogstatsd/base.py#L227


Discussion:
jirikuncar: /azp run DataDog.datadogpy.integration
azure-pipelines[bot]: <samp>
Azure Pipelines successfully started running 1 pipeline(s).<br>

</samp>

Patch:
diff --git a/datadog/threadstats/base.py b/datadog/threadstats/base.py
index ec89c3e..87421a0 100644
--- a/datadog/threadstats/base.py
+++ b/datadog/threadstats/base.py
@@ -7,20 +7,21 @@ performance. It collects metrics in the application thread with very little over
 and allows flushing metrics in process, in a thread or in a greenlet, depending
 on your application's needs.
 """
+import atexit
+import logging
+import os
 # stdlib
 from contextlib import contextmanager
 from functools import wraps
 from time import time
-import atexit
-import logging
-import os
 
 # datadog
 from datadog.api.exceptions import ApiNotInitialized
 from datadog.threadstats.constants import MetricType
 from datadog.threadstats.events import EventsAggregator
-from datadog.threadstats.metrics import MetricsAggregator, Counter, Gauge, Histogram, Timing,\
-    Distribution
+from datadog.threadstats.metrics import (
+    MetricsAggregator, Counter, Gauge, Histogram, Timing, Distribution, Set
+)
 from datadog.threadstats.reporters import HttpReporter
 
 # Loggers
@@ -177,6 +178,18 @@ class ThreadStats(object):
             self._metric_aggregator.add_point(metric_name, tags, timestamp or time(), value, Gauge,
                                               sample_rate=sample_rate, host=host)
 
+    def set(self, metric_name, value, timestamp=None, tags=None, sample_rate=1, host=None):
+        """
+        Add ``value`` to the current set. The length of the set is
+        flushed as a gauge to Datadog. Optionally, specify a set of
+        tags to associate with the metric.
+
+        >>> stats.set('example_metric.set', "value_1", tags=['environement:dev'])
+        """
+        if not self._disabled:
+            self._metric_aggregator.add_point(metric_name, tags, timestamp or time(), value, Set,
+                                              sample_rate=sample_rate, host=host)
+
     def increment(self, metric_name, value=1, timestamp=None, tags=None, sample_rate=1, host=None):
         """
         Increment the counter by the given ``value``. Optionally, specify a list of
@@ -285,13 +298,16 @@ class ThreadStats(object):
             finally:
                 stats.histogram('user.query.time', time.time() - start)
         """
+
         def wrapper(func):
             @wraps(func)
             def wrapped(*args, **kwargs):
                 with self.timer(metric_name, sample_rate, tags, host):
                     result = func(*args, **kwargs)
                     return result
+
             return wrapped
+
         return wrapper
 
     def flush(self, timestamp=None):
diff --git a/datadog/threadstats/metrics.py b/datadog/threadstats/metrics.py
index 00ff71e..fe3a0b7 100644
--- a/datadog/threadstats/metrics.py
+++ b/datadog/threadstats/metrics.py
@@ -28,6 +28,25 @@ class Metric(object):
         raise NotImplementedError()
 
 
+class Set(Metric):
+    """ A set metric. """
+
+    stats_tag = 'g'
+
+    def __init__(self, name, tags, host):
+        self.name = name
+        self.tags = tags
+        self.host = host
+        self.set = set()
+
+    def add_point(self, value):
+        self.set.add(value)
+
+    def flush(self, timestamp, interval):
+        return [(timestamp, len(self.set), self.name, self.tags,
+                self.host, MetricType.Gauge, interval)]
+
+
 class Gauge(Metric):
     """ A gauge metric. """
 


Test patch:
diff --git a/tests/unit/threadstats/test_threadstats.py b/tests/unit/threadstats/test_threadstats.py
index 918a3b2..40c74a4 100644
--- a/tests/unit/threadstats/test_threadstats.py
+++ b/tests/unit/threadstats/test_threadstats.py
@@ -25,10 +25,6 @@ logger = logging.getLogger('dd.datadogpy')
 logger.setLevel(logging.ERROR)
 
 
-def assert_equal(a, b):
-    assert a == b
-
-
 class MemoryReporter(object):
     """
     A reporting class that reports to memory for testing.
@@ -127,21 +123,21 @@ class TestUnitThreadStats(unittest.TestCase):
             """docstring"""
             return (a, b, c, d)
 
-        assert_equal(func.__name__, 'func')
-        assert_equal(func.__doc__, 'docstring')
+        assert func.__name__ == 'func'
+        assert func.__doc__ == 'docstring'
 
         result = func(1, 2, d=3)
         # Assert it handles args and kwargs correctly.
-        assert_equal(result, (1, 2, 1, 3))
+        assert result == (1, 2, 1, 3)
         time.sleep(1)  # Argh. I hate this.
         dog.flush()
         metrics = self.sort_metrics(reporter.metrics)
-        assert_equal(len(metrics), 8)
+        assert len(metrics) == 8
         (_, _, _, _, avg, count, max_, min_) = metrics
-        assert_equal(avg['metric'], 'timed.test.avg')
-        assert_equal(count['metric'], 'timed.test.count')
-        assert_equal(max_['metric'], 'timed.test.max')
-        assert_equal(min_['metric'], 'timed.test.min')
+        assert avg['metric'] == 'timed.test.avg'
+        assert count['metric'] == 'timed.test.count'
+        assert max_['metric'] == 'timed.test.max'
+        assert min_['metric'] == 'timed.test.min'
 
     def test_event(self):
         dog = ThreadStats()
@@ -159,10 +155,10 @@ class TestUnitThreadStats(unittest.TestCase):
         # Flush and test
         dog.flush()
         event1, event2 = reporter.events
-        assert_equal(event1['title'], event1_title)
-        assert_equal(event1['text'], event1_text)
-        assert_equal(event2['title'], event2_title)
-        assert_equal(event2['text'], event2_text)
+        assert event1['title'] == event1_title
+        assert event1['text'] == event1_text
+        assert event2['title'] == event2_title
+        assert event2['text'] == event2_text
 
         # Test more parameters
         reporter.events = []
@@ -175,11 +171,11 @@ class TestUnitThreadStats(unittest.TestCase):
         # Flush and test
         dog.flush()
         event, = reporter.events
-        assert_equal(event['title'], event1_title)
-        assert_equal(event['text'], event1_text)
-        assert_equal(event['priority'], event1_priority)
-        assert_equal(event['date_happened'], event1_date_happened)
-        assert_equal(event['tags'], [event1_tag])
+        assert event['title'] == event1_title
+        assert event['text'] == event1_text
+        assert event['priority'] == event1_priority
+        assert event['date_happened'] == event1_date_happened
+        assert event['tags'] == [event1_tag]
 
     def test_event_constant_tags(self):
         constant_tag = 'type:constant'
@@ -198,13 +194,13 @@ class TestUnitThreadStats(unittest.TestCase):
         # Flush and test
         dog.flush()
         event1, event2 = reporter.events
-        assert_equal(event1['title'], event1_title)
-        assert_equal(event1['text'], event1_text)
-        assert_equal(event1['tags'], [constant_tag])
-        assert_equal(event2['title'], event2_title)
-        assert_equal(event2['text'], event2_text)
-        assert_equal(event2['text'], event2_text)
-        assert_equal(event2['tags'], [constant_tag])
+        assert event1['title'] == event1_title
+        assert event1['text'] == event1_text
+        assert event1['tags'] == [constant_tag]
+        assert event2['title'] == event2_title
+        assert event2['text'] == event2_text
+        assert event2['text'] == event2_text
+        assert event2['tags'] == [constant_tag]
 
         # Test more parameters
         reporter.events = []
@@ -217,11 +213,11 @@ class TestUnitThreadStats(unittest.TestCase):
         # Flush and test
         dog.flush()
         event, = reporter.events
-        assert_equal(event['title'], event1_title)
-        assert_equal(event['text'], event1_text)
-        assert_equal(event['priority'], event1_priority)
-        assert_equal(event['date_happened'], event1_date_happened)
-        assert_equal(event['tags'], [event1_tag, constant_tag])
+        assert event['title'] == event1_title
+        assert event['text'] == event1_text
+        assert event['priority'] == event1_priority
+        assert event['date_happened'] == event1_date_happened
+        assert event['tags'] == [event1_tag, constant_tag]
 
     def test_histogram(self):
         dog = ThreadStats()
@@ -245,55 +241,55 @@ class TestUnitThreadStats(unittest.TestCase):
         # Flush and ensure they roll up properly.
         dog.flush(120.0)
         metrics = self.sort_metrics(reporter.metrics)
-        assert_equal(len(metrics), 24)
+        assert len(metrics) == 24
 
         # Test histograms elsewhere.
         (h1751, h1851, h1951, h1991, h1avg1, h1cnt1, h1max1, h1min1,
          _, _, _, _, h2avg1, h2cnt1, h2max1, h2min1,
          h1752, _, _, h1992, h1avg2, h1cnt2, h1max2, h1min2) = metrics
 
-        assert_equal(h1avg1['metric'], 'histogram.1.avg')
-        assert_equal(h1avg1['points'][0][0], 100.0)
-        assert_equal(h1avg1['points'][0][1], 35)
-        assert_equal(h1cnt1['metric'], 'histogram.1.count')
-        assert_equal(h1cnt1['points'][0][0], 100.0)
-        assert_equal(h1cnt1['points'][0][1], 0.4)
-        assert_equal(h1min1['metric'], 'histogram.1.min')
-        assert_equal(h1min1['points'][0][1], 20)
-        assert_equal(h1max1['metric'], 'histogram.1.max')
-        assert_equal(h1max1['points'][0][1], 50)
-        assert_equal(h1751['metric'], 'histogram.1.75percentile')
-        assert_equal(h1751['points'][0][1], 40)
-        assert_equal(h1991['metric'], 'histogram.1.99percentile')
-        assert_equal(h1991['points'][0][1], 50)
-
-        assert_equal(h1avg2['metric'], 'histogram.1.avg')
-        assert_equal(h1avg2['points'][0][0], 110.0)
-        assert_equal(h1avg2['points'][0][1], 40)
-        assert_equal(h1cnt2['metric'], 'histogram.1.count')
-        assert_equal(h1cnt2['points'][0][0], 110.0)
-        assert_equal(h1cnt2['points'][0][1], 0.3)
-        assert_equal(h1752['metric'], 'histogram.1.75percentile')
-        assert_equal(h1752['points'][0][0], 110.0)
-        assert_equal(h1752['points'][0][1], 40.0)
-        assert_equal(h1992['metric'], 'histogram.1.99percentile')
-        assert_equal(h1992['points'][0][0], 110.0)
-        assert_equal(h1992['points'][0][1], 50.0)
-
-        assert_equal(h2avg1['metric'], 'histogram.2.avg')
-        assert_equal(h2avg1['points'][0][0], 100.0)
-        assert_equal(h2avg1['points'][0][1], 40)
-        assert_equal(h2cnt1['metric'], 'histogram.2.count')
-        assert_equal(h2cnt1['points'][0][0], 100.0)
-        assert_equal(h2cnt1['points'][0][1], 0.1)
+        assert h1avg1['metric'] == 'histogram.1.avg'
+        assert h1avg1['points'][0][0] == 100.0
+        assert h1avg1['points'][0][1] == 35
+        assert h1cnt1['metric'] == 'histogram.1.count'
+        assert h1cnt1['points'][0][0] == 100.0
+        assert h1cnt1['points'][0][1] == 0.4
+        assert h1min1['metric'] == 'histogram.1.min'
+        assert h1min1['points'][0][1] == 20
+        assert h1max1['metric'] == 'histogram.1.max'
+        assert h1max1['points'][0][1] == 50
+        assert h1751['metric'] == 'histogram.1.75percentile'
+        assert h1751['points'][0][1] == 40
+        assert h1991['metric'] == 'histogram.1.99percentile'
+        assert h1991['points'][0][1] == 50
+
+        assert h1avg2['metric'] == 'histogram.1.avg'
+        assert h1avg2['points'][0][0] == 110.0
+        assert h1avg2['points'][0][1] == 40
+        assert h1cnt2['metric'] == 'histogram.1.count'
+        assert h1cnt2['points'][0][0] == 110.0
+        assert h1cnt2['points'][0][1] == 0.3
+        assert h1752['metric'] == 'histogram.1.75percentile'
+        assert h1752['points'][0][0] == 110.0
+        assert h1752['points'][0][1] == 40.0
+        assert h1992['metric'] == 'histogram.1.99percentile'
+        assert h1992['points'][0][0] == 110.0
+        assert h1992['points'][0][1] == 50.0
+
+        assert h2avg1['metric'] == 'histogram.2.avg'
+        assert h2avg1['points'][0][0] == 100.0
+        assert h2avg1['points'][0][1] == 40
+        assert h2cnt1['metric'] == 'histogram.2.count'
+        assert h2cnt1['points'][0][0] == 100.0
+        assert h2cnt1['points'][0][1] == 0.1
 
         # Flush again ensure they're gone.
         dog.reporter.metrics = []
         dog.flush(140.0)
-        assert_equal(len(dog.reporter.metrics), 8)
+        assert len(dog.reporter.metrics) == 8
         dog.reporter.metrics = []
         dog.flush(200.0)
-        assert_equal(len(dog.reporter.metrics), 0)
+        assert len(dog.reporter.metrics) == 0
 
     def test_histogram_percentiles(self):
         dog = ThreadStats()
@@ -312,10 +308,10 @@ class TestUnitThreadStats(unittest.TestCase):
         def assert_almost_equal(i, j, e=1):
             # Floating point math?
             assert abs(i - j) <= e, "%s %s %s" % (i, j, e)
-        assert_equal(len(metrics), 8)
+        assert len(metrics) == 8
         p75, p85, p95, p99, _, _, _, _ = self.sort_metrics(metrics)
-        assert_equal(p75['metric'], 'percentiles.75percentile')
-        assert_equal(p75['points'][0][0], 1000.0)
+        assert p75['metric'] == 'percentiles.75percentile'
+        assert p75['points'][0][0] == 1000.0
         assert_almost_equal(p75['points'][0][1], 75, 8)
         assert_almost_equal(p85['points'][0][1], 85, 8)
         assert_almost_equal(p95['points'][0][1], 95, 8)
@@ -335,23 +331,61 @@ class TestUnitThreadStats(unittest.TestCase):
 
         # Assert they've been properly flushed.
         metrics = self.sort_metrics(reporter.metrics)
-        assert_equal(len(metrics), 2)
+        assert len(metrics) == 2
 
         (first, second) = metrics
-        assert_equal(first['metric'], 'test.gauge.1')
-        assert_equal(first['points'][0][0], 100.0)
-        assert_equal(first['points'][0][1], 22)
-        assert_equal(second['metric'], 'test.gauge.2')
+        assert first['metric'] == 'test.gauge.1'
+        assert first['points'][0][0] == 100.0
+        assert first['points'][0][1] == 22
+        assert second['metric'] == 'test.gauge.2'
 
         # Flush again and make sure we're progressing.
         reporter.metrics = []
         dog.flush(130.0)
-        assert_equal(len(reporter.metrics), 1)
+        assert len(reporter.metrics) == 1
+
+        # Finally, make sure we've flushed all metrics.
+        reporter.metrics = []
+        dog.flush(150.0)
+        assert len(reporter.metrics) == 0
+
+    def test_set(self):
+        # Create some fake metrics.
+        dog = ThreadStats()
+        dog.start(roll_up_interval=10, flush_in_thread=False)
+        reporter = dog.reporter = MemoryReporter()
+
+        dog.set('test.set.1', "a string", 100.0)
+        dog.set('test.set.1', frozenset(), 105.0)
+        dog.set('test.set.2', 30, 115.0)
+        dog.set('test.set.3', 30, 125.0)
+        dog.flush(120.0)
+
+        # Assert they've been properly flushed.
+        metrics = self.sort_metrics(reporter.metrics)
+        assert len(metrics) == 2
+
+        (first, second) = metrics
+        assert first['metric'] == 'test.set.1'
+        assert first['points'][0][0] == 100.0
+        assert first['points'][0][1] == 2
+        assert second['metric'] == 'test.set.2'
+        assert second['points'][0][0] == 110.0
+        assert second['points'][0][1] == 1
+
+        # Flush again and make sure we're progressing.
+        reporter.metrics = []
+        dog.flush(130.0)
+        metrics = self.sort_metrics(reporter.metrics)
+        assert len(metrics) == 1
+        assert metrics[0]['metric'] == 'test.set.3'
+        assert metrics[0]['points'][0][0] == 120.0
+        assert metrics[0]['points'][0][1] == 1
 
         # Finally, make sure we've flushed all metrics.
         reporter.metrics = []
         dog.flush(150.0)
-        assert_equal(len(reporter.metrics), 0)
+        assert len(reporter.metrics) == 0
 
     def test_counter(self):
         # Create some fake metrics.
@@ -367,12 +401,12 @@ class TestUnitThreadStats(unittest.TestCase):
 
         # Assert they've been properly flushed.
         metrics = self.sort_metrics(reporter.metrics)
-        assert_equal(len(metrics), 2)
+        assert len(metrics) == 2
         (first, second) = metrics
-        assert_equal(first['metric'], 'test.counter.1')
-        assert_equal(first['points'][0][0], 1000.0)
-        assert_equal(first['points'][0][1], 0.3)
-        assert_equal(second['metric'], 'test.counter.2')
+        assert first['metric'] == 'test.counter.1'
+        assert first['points'][0][0] == 1000.0
+        assert first['points'][0][1] == 0.3
+        assert second['metric'] == 'test.counter.2'
 
         # Test decrement
         dog.increment('test.counter.1', value=10, timestamp=1000.0)
@@ -381,22 +415,22 @@ class TestUnitThreadStats(unittest.TestCase):
         dog.flush(1021.0)
 
         metrics = self.sort_metrics(reporter.metrics)
-        assert_equal(len(metrics), 1)
+        assert len(metrics) == 1
         first, = metrics
-        assert_equal(first['metric'], 'test.counter.1')
-        assert_equal(first['points'][0][0], 1000.0)
-        assert_equal(first['points'][0][1], 0.8)
-        assert_equal(second['metric'], 'test.counter.2')
+        assert first['metric'] == 'test.counter.1'
+        assert first['points'][0][0] == 1000.0
+        assert first['points'][0][1] == 0.8
+        assert second['metric'] == 'test.counter.2'
 
         # Flush again and make sure we're progressing.
         reporter.metrics = []
         dog.flush(1030.0)
-        assert_equal(len(reporter.metrics), 1)
+        assert len(reporter.metrics) == 1
 
         # Finally, make sure we've flushed all metrics.
         reporter.metrics = []
         dog.flush(1050.0)
-        assert_equal(len(reporter.metrics), 0)
+        assert len(reporter.metrics) == 0
 
     def test_distribution(self):
         # Create some fake metrics.
@@ -412,23 +446,23 @@ class TestUnitThreadStats(unittest.TestCase):
 
         # Assert they've been properly flushed.
         dists = self.sort_metrics(reporter.distributions)
-        assert_equal(len(dists), 2)
+        assert len(dists) == 2
 
         (first, second) = dists
-        assert_equal(first['metric'], 'test.dist.1')
-        assert_equal(first['points'][0][0], 100.0)
-        assert_equal(first['points'][0][1], [20, 22])
-        assert_equal(second['metric'], 'test.dist.2')
+        assert first['metric'] == 'test.dist.1'
+        assert first['points'][0][0] == 100.0
+        assert first['points'][0][1] == [20, 22]
+        assert second['metric'] == 'test.dist.2'
 
         # Flush again and make sure we're progressing.
         reporter.distributions = []
         dog.flush(130.0)
-        assert_equal(len(reporter.distributions), 1)
+        assert len(reporter.distributions) == 1
 
         # Finally, make sure we've flushed all metrics.
         reporter.distributions = []
         dog.flush(150.0)
-        assert_equal(len(reporter.distributions), 0)
+        assert len(reporter.distributions) == 0
 
     def test_default_host_and_device(self):
         dog = ThreadStats()
@@ -447,8 +481,8 @@ class TestUnitThreadStats(unittest.TestCase):
         dog.gauge('my.gauge', 1, 100.0, host='host')
         dog.flush(1000)
         metric = reporter.metrics[0]
-        assert_equal(metric['device'], 'dev')
-        assert_equal(metric['host'], 'host')
+        assert metric['device'] == 'dev'
+        assert metric['host'] == 'host'
 
     def test_tags(self):
         dog = ThreadStats()
@@ -467,24 +501,28 @@ class TestUnitThreadStats(unittest.TestCase):
         dog.flush(200.0)
 
         metrics = self.sort_metrics(reporter.metrics)
-        assert_equal(len(metrics), 6)
+        assert len(metrics) == 6
 
         [c1, c2, c3, g1, g2, g3] = metrics
-        (assert_equal(c['metric'], 'counter') for c in [c1, c2, c3])
-        assert_equal(c1['tags'], None)
-        assert_equal(c1['points'][0][1], 0.1)
-        assert_equal(c2['tags'], ['env:production', 'db'])
-        assert_equal(c2['points'][0][1], 0.1)
-        assert_equal(c3['tags'], ['env:staging'])
-        assert_equal(c3['points'][0][1], 0.1)
-
-        (assert_equal(c['metric'], 'gauge') for c in [g1, g2, g3])
-        assert_equal(g1['tags'], None)
-        assert_equal(g1['points'][0][1], 10)
-        assert_equal(g2['tags'], ['env:production', 'db'])
-        assert_equal(g2['points'][0][1], 15)
-        assert_equal(g3['tags'], ['env:staging'])
-        assert_equal(g3['points'][0][1], 20)
+        assert c1['metric'] == 'counter'
+        assert c2['metric'] == 'counter'
+        assert c3['metric'] == 'counter'
+        assert c1['tags'] is None
+        assert c1['points'][0][1] == 0.1
+        assert c2['tags'] == ['env:production', 'db']
+        assert c2['points'][0][1] == 0.1
+        assert c3['tags'] == ['env:staging']
+        assert c3['points'][0][1] == 0.1
+
+        assert g1['metric'] == 'gauge'
+        assert g2['metric'] == 'gauge'
+        assert g3['metric'] == 'gauge'
+        assert g1['tags'] is None
+        assert g1['points'][0][1] == 10
+        assert g2['tags'] == ['env:production', 'db']
+        assert g2['points'][0][1] == 15
+        assert g3['tags'] == ['env:staging']
+        assert g3['points'][0][1] == 20
 
     def test_constant_tags(self):
         """
@@ -579,27 +617,31 @@ class TestUnitThreadStats(unittest.TestCase):
         dog.flush(200.0)
 
         metrics = self.sort_metrics(reporter.metrics)
-        assert_equal(len(metrics), 6)
+        assert len(metrics) == 6
 
         [c1, c2, c3, g1, g2, g3] = metrics
-        (assert_equal(c['metric'], 'counter') for c in [c1, c2, c3])
-        assert_equal(c1['host'], None)
-        assert_equal(c1['tags'], None)
-        assert_equal(c1['points'][0][1], 0.2)
-        assert_equal(c2['host'], 'test')
-        assert_equal(c2['tags'], None)
-        assert_equal(c2['points'][0][1], 0.1)
-        assert_equal(c3['host'], 'test')
-        assert_equal(c3['tags'], ['tag'])
-        assert_equal(c3['points'][0][1], 0.2)
-
-        (assert_equal(g['metric'], 'gauge') for g in [g1, g2, g3])
-        assert_equal(g1['host'], None)
-        assert_equal(g1['points'][0][1], 10)
-        assert_equal(g2['host'], '')
-        assert_equal(g2['points'][0][1], 12)
-        assert_equal(g3['host'], 'test')
-        assert_equal(g3['points'][0][1], 15)
+        assert c1['metric'] == 'counter'
+        assert c2['metric'] == 'counter'
+        assert c3['metric'] == 'counter'
+        assert c1['host'] is None
+        assert c1['tags'] is None
+        assert c1['points'][0][1] == 0.2
+        assert c2['host'] == 'test'
+        assert c2['tags'] is None
+        assert c2['points'][0][1] == 0.1
+        assert c3['host'] == 'test'
+        assert c3['tags'] == ['tag']
+        assert c3['points'][0][1] == 0.2
+
+        assert g1['metric'] == 'gauge'
+        assert g2['metric'] == 'gauge'
+        assert g3['metric'] == 'gauge'
+        assert g1['host'] is None
+        assert g1['points'][0][1] == 10
+        assert g2['host'] == ''
+        assert g2['points'][0][1] == 12
+        assert g3['host'] == 'test'
+        assert g3['points'][0][1] == 15
 
         # Ensure histograms work as well.
         @dog.timed('timed', host='test')
@@ -658,13 +700,13 @@ class TestUnitThreadStats(unittest.TestCase):
         # Flush and test
         dog.flush()
         event1, event2 = reporter.events
-        assert_equal(event1['title'], event1_title)
-        assert_equal(event1['text'], event1_text)
-        assert_equal(event1['tags'], test_tags)
-        assert_equal(event2['title'], event2_title)
-        assert_equal(event2['text'], event2_text)
-        assert_equal(event2['text'], event2_text)
-        assert_equal(event2['tags'], test_tags)
+        assert event1['title'] == event1_title
+        assert event1['text'] == event1_text
+        assert event1['tags'] == test_tags
+        assert event2['title'] == event2_title
+        assert event2['text'] == event2_text
+        assert event2['text'] == event2_text
+        assert event2['tags'] == test_tags
 
         # Test more parameters
         reporter.events = []
@@ -677,11 +719,11 @@ class TestUnitThreadStats(unittest.TestCase):
         # Flush and test
         dog.flush()
         event, = reporter.events
-        assert_equal(event['title'], event1_title)
-        assert_equal(event['text'], event1_text)
-        assert_equal(event['priority'], event1_priority)
-        assert_equal(event['date_happened'], event1_date_happened)
-        assert_equal(event['tags'], [event1_tag] + test_tags)
+        assert event['title'] == event1_title
+        assert event['text'] == event1_text
+        assert event['priority'] == event1_priority
+        assert event['date_happened'] == event1_date_happened
+        assert event['tags'] == [event1_tag] + test_tags
         dog.start(flush_interval=1, roll_up_interval=1)
 
     def test_tags_from_environment_and_constant(self):
@@ -704,13 +746,13 @@ class TestUnitThreadStats(unittest.TestCase):
         # Flush and test
         dog.flush()
         event1, event2 = reporter.events
-        assert_equal(event1['title'], event1_title)
-        assert_equal(event1['text'], event1_text)
-        assert_equal(event1['tags'], constant_tags + test_tags)
-        assert_equal(event2['title'], event2_title)
-        assert_equal(event2['text'], event2_text)
-        assert_equal(event2['text'], event2_text)
-        assert_equal(event2['tags'], constant_tags + test_tags)
+        assert event1['title'] == event1_title
+        assert event1['text'] == event1_text
+        assert event1['tags'] == constant_tags + test_tags
+        assert event2['title'] == event2_title
+        assert event2['text'] == event2_text
+        assert event2['text'] == event2_text
+        assert event2['tags'] == constant_tags + test_tags
 
         # Test more parameters
         reporter.events = []
@@ -723,11 +765,11 @@ class TestUnitThreadStats(unittest.TestCase):
         # Flush and test
         dog.flush()
         event, = reporter.events
-        assert_equal(event['title'], event1_title)
-        assert_equal(event['text'], event1_text)
-        assert_equal(event['priority'], event1_priority)
-        assert_equal(event['date_happened'], event1_date_happened)
-        assert_equal(event['tags'], [event1_tag] + constant_tags + test_tags)
+        assert event['title'] == event1_title
+        assert event['text'] == event1_text
+        assert event['priority'] == event1_priority
+        assert event['date_happened'] == event1_date_happened
+        assert event['tags'] == [event1_tag] + constant_tags + test_tags
         dog.start(flush_interval=1, roll_up_interval=1)
 
     def test_metric_type(self):
@@ -748,16 +790,16 @@ class TestUnitThreadStats(unittest.TestCase):
         (first, second, p75, p85, p95, p99, avg, cnt, max_, min_) = self.sort_metrics(reporter.metrics)
 
         # Assert Metric type
-        assert_equal(first['type'], 'rate')
-        assert_equal(second['type'], 'gauge')
-        assert_equal(p75['type'], 'gauge')
-        assert_equal(p85['type'], 'gauge')
-        assert_equal(p95['type'], 'gauge')
-        assert_equal(p99['type'], 'gauge')
-        assert_equal(avg['type'], 'gauge')
-        assert_equal(cnt['type'], 'rate')
-        assert_equal(max_['type'], 'gauge')
-        assert_equal(min_['type'], 'gauge')
+        assert first['type'] == 'rate'
+        assert second['type'] == 'gauge'
+        assert p75['type'] == 'gauge'
+        assert p85['type'] == 'gauge'
+        assert p95['type'] == 'gauge'
+        assert p99['type'] == 'gauge'
+        assert avg['type'] == 'gauge'
+        assert cnt['type'] == 'rate'
+        assert max_['type'] == 'gauge'
+        assert min_['type'] == 'gauge'
 
     # Test lambda_wrapper (uses ThreadStats under the hood)
     def test_basic_lambda_decorator(self):
@@ -769,9 +811,9 @@ class TestUnitThreadStats(unittest.TestCase):
         _lambda_stats.reporter = self.reporter
         basic_wrapped_function()
 
-        assert_equal(_lambda_stats.reporter.dist_flush_counter, 1)
+        assert _lambda_stats.reporter.dist_flush_counter == 1
         dists = self.sort_metrics(_lambda_stats.reporter.distributions)
-        assert_equal(len(dists), 1)
+        assert len(dists) == 1
 
     def test_embedded_lambda_decorator(self):
         """
@@ -789,7 +831,7 @@ class TestUnitThreadStats(unittest.TestCase):
 
         _lambda_stats.reporter = self.reporter
         wrapped_function_2()
-        assert_equal(_lambda_stats.reporter.dist_flush_counter, 1)
+        assert _lambda_stats.reporter.dist_flush_counter == 1
 
         dists = self.sort_metrics(_lambda_stats.reporter.distributions)
-        assert_equal(len(dists), 2)
+        assert len(dists) == 2