diff --git a/synapse/metrics/metric.py b/synapse/metrics/metric.py
index 341043952a..d100841a7f 100644
--- a/synapse/metrics/metric.py
+++ b/synapse/metrics/metric.py
@@ -16,6 +16,8 @@
from itertools import chain
+import psutil
+
# TODO(paul): I can't believe Python doesn't have one of these
def map_concat(func, items):
@@ -153,3 +155,39 @@ class CacheMetric(object):
"""%s:total{name="%s"} %d""" % (self.name, self.cache_name, total),
"""%s:size{name="%s"} %d""" % (self.name, self.cache_name, size),
]
+
+
+class MemoryUsageMetric(object):
+ """Keeps track of the current memory usage, using psutil.
+
+ The class will keep the current min/max/sum/counts of rss over the last
+ WINDOW_SIZE_SEC, by polling UPDATE_HZ times per second
+ """
+
+ UPDATE_HZ = 2 # number of times to get memory per second
+ WINDOW_SIZE_SEC = 30 # the size of the window in seconds
+
+ def __init__(self, hs):
+ clock = hs.get_clock()
+ self.memory_snapshots = []
+ self.process = psutil.Process()
+
+ clock.looping_call(self._update_curr_values, 1000 / self.UPDATE_HZ)
+
+ def _update_curr_values(self):
+ max_size = self.UPDATE_HZ * self.WINDOW_SIZE_SEC
+ self.memory_snapshots.append(self.process.memory_info().rss)
+ self.memory_snapshots[:] = self.memory_snapshots[-max_size:]
+
+ def render(self):
+ max_rss = max(self.memory_snapshots)
+ min_rss = min(self.memory_snapshots)
+ sum_rss = sum(self.memory_snapshots)
+ len_rss = len(self.memory_snapshots)
+
+ return [
+ "process_psutil_rss:max %d" % max_rss,
+ "process_psutil_rss:min %d" % min_rss,
+ "process_psutil_rss:total %d" % sum_rss,
+ "process_psutil_rss:count %d" % len_rss,
+ ]
|