From d1772d410235592b482e3b08b1863f6624d9fe6b Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 19 Feb 2023 15:52:21 +0100 Subject: Adding upstream version 2.0.3. Signed-off-by: Daniel Baumann --- deluge/plugins/Stats/deluge_stats/core.py | 223 ++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 deluge/plugins/Stats/deluge_stats/core.py (limited to 'deluge/plugins/Stats/deluge_stats/core.py') diff --git a/deluge/plugins/Stats/deluge_stats/core.py b/deluge/plugins/Stats/deluge_stats/core.py new file mode 100644 index 0000000..635c54d --- /dev/null +++ b/deluge/plugins/Stats/deluge_stats/core.py @@ -0,0 +1,223 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2009 Ian Martin +# Copyright (C) 2008 Damien Churchill +# Copyright (C) 2008 Martijn Voncken +# Copyright (C) 2007 Marcos Mobley +# +# 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. +# + +from __future__ import division, unicode_literals + +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 {} + self.stats_keys = ['peer.num_peers_half_open', 'dht.dht_node_cache'] + self.add_stats( + 'upload_rate', + 'download_rate', + 'dht_nodes', + 'dht_cache_nodes', + 'dht_torrents', + 'num_peers', + 'num_connections', + ) + + 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 add_stats(self, *stats): + for stat in stats: + if stat not in self.stats_keys: + self.stats_keys.append(stat) + for i in self.intervals: + if stat not in self.stats[i]: + self.stats[i][stat] = [] + + def update_stats(self): + # Get all possible stats! + stats = {} + for key in self.stats_keys: + # try all keys we have, very inefficient but saves having to + # work out where a key comes from... + try: + stats.update(self.core.get_session_status([key])) + except AttributeError: + pass + stats['num_connections'] = ( + stats['num_peers'] + stats['peer.num_peers_half_open'] + ) + stats['dht_cache_nodes'] = stats['dht.dht_node_cache'] + stats.update( + self.core.get_config_values( + ['max_download', 'max_upload', 'max_num_connections'] + ) + ) + # 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 -- cgit v1.2.3