/ prometheus.py
prometheus.py
  1  #!/usr/bin/env python3
  2  
  3  
  4  # sum(shh_messages_total) by (chat)
  5  
  6  
  7  def openPrometheusURL(query, timestep):
  8      from time import time
  9      from urllib.request import urlopen
 10  
 11      # TODO: could escape it, but could also just avoid queries which need escaping
 12  
 13      cur_time = time()
 14      return urlopen(
 15          "http://master-01.do-ams3.metrics.hq.tinc:9090/api/v1/query_range?query=%s&end=%d&start=%d&step=%s"
 16          % (query, time(), time() - 3600 * 24 * 60, timestep)
 17      ).read()
 18  
 19  
 20  def parse_data(raw_json):
 21      from json import loads
 22  
 23      j = loads(raw_json)
 24      assert j["status"] == "success"
 25      assert j["data"]["resultType"] == "matrix"
 26      return j["data"]["result"][0]["values"]
 27  
 28  
 29  def getData(pj):
 30      from datetime import datetime
 31  
 32      return list(
 33          zip(
 34              *[
 35                  (datetime.fromtimestamp(z[0]), float(z[1]))
 36                  for z in sorted(pj, key=lambda _: _[0])
 37              ]
 38          )
 39      )
 40  
 41  
 42  def plotData(filename, ylabel, timespan, x, y):
 43      # TODO: factor out as common routine
 44      # allow this to run on a headless server
 45      import matplotlib
 46  
 47      matplotlib.use("Agg")
 48  
 49      import matplotlib.pyplot as plt
 50      import matplotlib.dates as mdates
 51  
 52      assert len(x) == len(y)
 53  
 54      # https://stackoverflow.com/questions/9627686/plotting-dates-on-the-x-axis-with-pythons-matplotlib#9627970
 55      plt.clf()
 56      plt.gca().xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d"))
 57      plt.gca().xaxis.set_major_locator(mdates.AutoDateLocator())
 58      plt.xlabel("Date")
 59  
 60      plt.ylabel(ylabel)
 61  
 62      plt.title("Status.im %s %s (Prometheus)" % (timespan, ylabel))
 63  
 64      plt.plot(x, y)
 65      plt.gcf().autofmt_xdate()
 66      plt.savefig(filename, dpi=150)
 67  
 68  
 69  def distinct_users():
 70      from collections import Counter
 71      from datetime import datetime
 72      from json import loads
 73  
 74      j = loads(
 75          openPrometheusURL(
 76              "sum(rate(shh_messages_total[1d])*3600)%20by%20(source)", "1d"
 77          )
 78      )
 79      assert j["status"] == "success"
 80      assert j["data"]["resultType"] == "matrix"
 81  
 82      distinct_user_count = Counter()
 83      for metric_values in j["data"]["result"]:
 84          source = metric_values["metric"].get("source", "")
 85          values = metric_values["values"]
 86          for epoch_time, hourly_rate in values:
 87              if float(hourly_rate) > 0:
 88                  distinct_user_count[datetime.fromtimestamp(epoch_time)] += 1
 89  
 90      # TODO: refactor, etc
 91      return list(zip(*sorted(distinct_user_count.items())))
 92  
 93  
 94  def main():
 95      from os.path import join
 96      from sys import argv
 97  
 98      getPath = lambda n: join(argv[1], n)
 99  
100      plotData(
101          getPath("whisper_distinct_users_daily.png"),
102          "Whisper Users (Public Channels)",
103          "Daily",
104          *distinct_users()
105      )
106  
107      plotData(
108          getPath("whisper_messages_hourly.png"),
109          "Whisper Messages (Public Channels)",
110          "Hourly",
111          *getData(
112              parse_data(
113                  openPrometheusURL("sum(rate(shh_messages_total[1h]))*3600", "1h")
114              )
115          )
116      )
117  
118      plotData(
119          getPath("whisper_messages_daily.png"),
120          "Whisper Messages (Public Channels)",
121          "Daily",
122          *getData(
123              parse_data(
124                  openPrometheusURL("sum(rate(shh_messages_total[1d]))*3600*24", "1d")
125              )
126          )
127      )
128  
129      plotData(
130          getPath("whisper_messages_weekly.png"),
131          "Whisper Messages (Public Channels)",
132          "Weekly",
133          *getData(
134              parse_data(
135                  openPrometheusURL("sum(rate(shh_messages_total[1w]))*3600*24*7", "1w")
136              )
137          )
138      )
139  
140  
141  main()