transit_server.py: rewrite stats

This commit is contained in:
Brian Warner 2017-09-13 17:24:37 -07:00
parent ea9e24913c
commit 26efac7da9

View File

@ -1,5 +1,5 @@
from __future__ import print_function, unicode_literals from __future__ import print_function, unicode_literals
import re, time, collections import os, re, time, json
from twisted.python import log from twisted.python import log
from twisted.internet import protocol from twisted.internet import protocol
from twisted.application import service from twisted.application import service
@ -230,7 +230,7 @@ class Transit(protocol.ServerFactory):
self._stats_file = stats_file self._stats_file = stats_file
self._pending_requests = {} # token -> set((side, TransitConnection)) self._pending_requests = {} # token -> set((side, TransitConnection))
self._active_connections = set() # TransitConnection self._active_connections = set() # TransitConnection
self._counts = collections.defaultdict(int) self._counts = {"lonely": 0, "happy": 0, "errory": 0}
self._count_bytes = 0 self._count_bytes = 0
def connection_got_token(self, token, new_side, new_tc): def connection_got_token(self, token, new_side, new_tc):
@ -265,21 +265,25 @@ class Transit(protocol.ServerFactory):
def recordUsage(self, started, result, total_bytes, def recordUsage(self, started, result, total_bytes,
total_time, waiting_time): total_time, waiting_time):
self._counts[result] += 1
self._count_bytes += total_bytes
if self._log_requests: if self._log_requests:
log.msg(format="Transit.recordUsage {bytes}B", bytes=total_bytes) log.msg(format="Transit.recordUsage {bytes}B", bytes=total_bytes)
if self._blur_usage: if self._blur_usage:
started = self._blur_usage * (started // self._blur_usage) started = self._blur_usage * (started // self._blur_usage)
total_bytes = blur_size(total_bytes) total_bytes = blur_size(total_bytes)
if self._usage_logfile if self._usage_logfile:
self._db.execute("INSERT INTO `transit_usage`" data = {"started": started,
" (`started`, `total_time`, `waiting_time`," "total_time": total_time,
" `total_bytes`, `result`)" "waiting_time": waiting_time,
" VALUES (?,?,?, ?,?)", "total_bytes": total_bytes,
(started, total_time, waiting_time, "mood": result,
total_bytes, result)) }
self._db.commit() self._usage_logfile.write(json.dumps(data))
self._counts[result] += 1 self._usage_logfile.write("\n")
self._count_bytes += total_bytes self._usage_logfile.flush()
if self._stats_file:
self._update_stats(total_bytes, result)
def transitFinished(self, tc, token, side, description): def transitFinished(self, tc, token, side, description):
if token in self._pending_requests: if token in self._pending_requests:
@ -297,16 +301,17 @@ class Transit(protocol.ServerFactory):
log.msg("transitFailed %r" % p) log.msg("transitFailed %r" % p)
pass pass
def get_stats(self): def _update_stats(self, total_bytes, mood):
stats = {} try:
def q(query, values=()): with open(self._stats_file, "rb") as f:
row = self._db.execute(query, values).fetchone() stats = json.load(f)
return list(row.values())[0] except (EnvironmentError, ValueError):
stats = {}
# current status: expected to be zero most of the time # current status: expected to be zero most of the time
c = stats["active"] = {} stats["active"] = {"connected": len(self._active_connections) / 2,
c["connected"] = len(self._active_connections) / 2 "waiting": len(self._pending_requests),
c["waiting"] = len(self._pending_requests) }
# usage since last reboot # usage since last reboot
rb = stats["since_reboot"] = {} rb = stats["since_reboot"] = {}
@ -317,15 +322,20 @@ class Transit(protocol.ServerFactory):
rbm[result] = count rbm[result] = count
# historical usage (all-time) # historical usage (all-time)
u = stats["all_time"] = {} if "all_time" not in stats:
u["total"] = q("SELECT COUNT() FROM `transit_usage`") stats["all_time"] = {}
u["bytes"] = q("SELECT SUM(`total_bytes`) FROM `transit_usage`") or 0 u = stats["all_time"]
um = u["moods"] = {} u["total"] = u.get("total", 0) + 1
um["happy"] = q("SELECT COUNT() FROM `transit_usage`" u["bytes"] = u.get("bytes", 0) + total_bytes
" WHERE `result`='happy'") if "moods" not in u:
um["lonely"] = q("SELECT COUNT() FROM `transit_usage`" u["moods"] = {}
" WHERE `result`='lonely'") um = u["moods"]
um["errory"] = q("SELECT COUNT() FROM `transit_usage`" for m in "happy", "lonely", "errory":
" WHERE `result`='errory'") if m not in um:
um[m] = 0
return stats um[mood] += 1
tmpfile = self._stats_file + ".tmp"
with open(tmpfile, "wb") as f:
f.write(json.dumps(stats))
f.write("\n")
os.rename(tmpfile, self._stats_file)