summaryrefslogtreecommitdiffstats
path: root/deluge/plugins/Stats/deluge_stats/core.py
diff options
context:
space:
mode:
Diffstat (limited to 'deluge/plugins/Stats/deluge_stats/core.py')
-rw-r--r--deluge/plugins/Stats/deluge_stats/core.py218
1 files changed, 218 insertions, 0 deletions
diff --git a/deluge/plugins/Stats/deluge_stats/core.py b/deluge/plugins/Stats/deluge_stats/core.py
new file mode 100644
index 0000000..1be51e6
--- /dev/null
+++ b/deluge/plugins/Stats/deluge_stats/core.py
@@ -0,0 +1,218 @@
+#
+# Copyright (C) 2009 Ian Martin <ianmartin@cantab.net>
+# Copyright (C) 2008 Damien Churchill <damoxc@gmail.com>
+# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
+# Copyright (C) 2007 Marcos Mobley <markybob@gmail.com>
+#
+# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
+# the additional special exception to link portions of this program with the OpenSSL library.
+# See LICENSE for more details.
+#
+
+import logging
+import time
+
+from twisted.internet.task import LoopingCall
+
+from deluge import component, configmanager
+from deluge.core.rpcserver import export
+from deluge.plugins.pluginbase import CorePluginBase
+
+DEFAULT_PREFS = {
+ 'test': 'NiNiNi',
+ 'update_interval': 1, # 2 seconds.
+ 'length': 150, # 2 seconds * 150 --> 5 minutes.
+}
+
+DEFAULT_TOTALS = {
+ 'total_upload': 0,
+ 'total_download': 0,
+ 'total_payload_upload': 0,
+ 'total_payload_download': 0,
+ 'stats': {},
+}
+
+log = logging.getLogger(__name__)
+
+
+def get_key(config, key):
+ try:
+ return config[key]
+ except KeyError:
+ return None
+
+
+def mean(items):
+ try:
+ return sum(items) // len(items)
+ except Exception:
+ return 0
+
+
+class Core(CorePluginBase):
+ totals = {} # class var to catch only updating this once per session in enable.
+
+ def enable(self):
+ log.debug('Stats plugin enabled')
+ self.core = component.get('Core')
+ self.stats = {}
+ self.count = {}
+ self.intervals = [1, 5, 30, 300]
+
+ self.last_update = {}
+ t = time.time()
+ for i in self.intervals:
+ self.stats[i] = {}
+ self.last_update[i] = t
+ self.count[i] = 0
+
+ self.config = configmanager.ConfigManager('stats.conf', DEFAULT_PREFS)
+ self.saved_stats = configmanager.ConfigManager('stats.totals', DEFAULT_TOTALS)
+ if self.totals == {}:
+ self.totals.update(self.saved_stats.config)
+
+ self.length = self.config['length']
+
+ # self.stats = get_key(self.saved_stats, 'stats') or {}
+
+ # keys needed from core.get_session_status
+ self.stat_keys = [
+ 'upload_rate',
+ 'download_rate',
+ 'dht.dht_nodes',
+ 'dht.dht_node_cache',
+ 'dht.dht_torrents',
+ 'peer.num_peers_connected',
+ 'peer.num_peers_half_open',
+ ]
+ # collected statistics and functions to get them
+ self.stat_getters = {
+ 'upload_rate': lambda s: s['upload_rate'],
+ 'download_rate': lambda s: s['download_rate'],
+ 'dht_nodes': lambda s: s['dht.dht_nodes'],
+ 'dht_cache_nodes': lambda s: s['dht.dht_node_cache'],
+ 'dht_torrents': lambda s: s['dht.dht_torrents'],
+ 'num_peers': lambda s: s['peer.num_peers_connected'],
+ 'num_connections': lambda s: s['peer.num_peers_connected']
+ + s['peer.num_peers_half_open'],
+ }
+
+ # initialize stats object
+ for key in self.stat_getters.keys():
+ for i in self.intervals:
+ if key not in self.stats[i]:
+ self.stats[i][key] = []
+
+ self.update_stats()
+
+ self.update_timer = LoopingCall(self.update_stats)
+ self.update_timer.start(self.config['update_interval'])
+
+ self.save_timer = LoopingCall(self.save_stats)
+ self.save_timer.start(60)
+
+ def disable(self):
+ self.update_timer.stop() if self.update_timer.running else None
+ self.save_timer.stop() if self.save_timer.running else None
+ self.save_stats()
+
+ def update_stats(self):
+ # Get all possible stats!
+ stats = {}
+ raw_stats = self.core.get_session_status(self.stat_keys)
+ for name, fn in self.stat_getters.items():
+ stats[name] = fn(raw_stats)
+
+ # status = self.core.session.status()
+ # for stat in dir(status):
+ # if not stat.startswith('_') and stat not in stats:
+ # stats[stat] = getattr(status, stat, None)
+
+ update_time = time.time()
+ self.last_update[1] = update_time
+
+ # extract the ones we are interested in
+ # adding them to the 1s array
+ for stat, stat_list in self.stats[1].items():
+ if stat in stats:
+ stat_list.insert(0, int(stats[stat]))
+ else:
+ stat_list.insert(0, 0)
+ if len(stat_list) > self.length:
+ stat_list.pop()
+
+ def update_interval(interval, base, multiplier):
+ self.count[interval] = self.count[interval] + 1
+ if self.count[interval] >= interval:
+ self.last_update[interval] = update_time
+ self.count[interval] = 0
+ current_stats = self.stats[interval]
+ for stat, stat_list in self.stats[base].items():
+ try:
+ avg = mean(stat_list[0:multiplier])
+ except ValueError:
+ avg = 0
+ current_stats[stat].insert(0, avg)
+ if len(current_stats[stat]) > self.length:
+ current_stats[stat].pop()
+
+ update_interval(5, 1, 5)
+ update_interval(30, 5, 6)
+ update_interval(300, 30, 10)
+
+ def save_stats(self):
+ self.saved_stats['stats'] = self.stats
+ self.saved_stats.config.update(self.get_totals())
+ self.saved_stats.save()
+
+ # export:
+ @export
+ def get_stats(self, keys, interval):
+ if interval not in self.intervals:
+ return None
+
+ stats_dict = {}
+ for key in keys:
+ if key in self.stats[interval]:
+ stats_dict[key] = self.stats[interval][key]
+
+ stats_dict['_last_update'] = self.last_update[interval]
+ stats_dict['_length'] = self.config['length']
+ stats_dict['_update_interval'] = interval
+ return stats_dict
+
+ @export
+ def get_totals(self):
+ result = {}
+ session_totals = self.get_session_totals()
+ for key in session_totals:
+ result[key] = self.totals[key] + session_totals[key]
+ return result
+
+ @export
+ def get_session_totals(self):
+ return self.core.get_session_status(
+ [
+ 'total_upload',
+ 'total_download',
+ 'total_payload_upload',
+ 'total_payload_download',
+ ]
+ )
+
+ @export
+ def set_config(self, config):
+ """Sets the config dictionary."""
+ for key in config:
+ self.config[key] = config[key]
+ self.config.save()
+
+ @export
+ def get_config(self):
+ """Returns the config dictionary."""
+ return self.config.config
+
+ @export
+ def get_intervals(self):
+ """Returns the available resolutions."""
+ return self.intervals