import os import platform import threading import time from threading import Thread import psutil from core.buddy_service import BuddyService from core.chat_blob import ChatBlob from core.command_alias_service import CommandAliasService from core.command_param_types import Const from core.db import DB from core.decorators import instance, command from core.lookup.pork_service import PorkService from core.message_hub_service import MessageHubService from core.text import Text from core.igncore import IgnCore from core.util import Util from modules.core.accounting.services.access_service import AccessService # noinspection DuplicatedCode @instance() class StatController: threads = {} letters = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "others", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] pork_uri = "https://people.anarchy-online.com/people/lookup/orgs.html?l=%s" single_org_uri = "https://people.anarchy-online.com/org/stats/d/5/name/%d/basicstats.xml?data_type=json" def inject(self, registry): self.bot: IgnCore = registry.get_instance("bot") self.db: DB = registry.get_instance("db") self.text: Text = registry.get_instance("text") self.util: Util = registry.get_instance("util") self.pork: PorkService = registry.get_instance("pork_service") self.org_pork: PorkService = registry.get_instance("org_pork_service") self.command_alias_service: CommandAliasService = registry.get_instance("command_alias_service") self.buddy_service: BuddyService = registry.get_instance("buddy_service") self.access_service: AccessService = registry.get_instance("access_service") self.relay_hub_service: MessageHubService = registry.get_instance("message_hub_service") # noinspection LongLine @command(command="debug", params=[Const("verbose", is_optional=True)], access_level="admin", description="Display debugging statistics about igncom") def debug_output(self, _, verbose): def adjust_size(size): factor = 1024 for i in [" B", " KB", " MB", " GB", " TB"]: if size > factor: size /= factor else: return f"{size:.3f}{i}" threads = "" for thread in threading.enumerate(): thread: Thread threads += f" - {thread.name} [Deamon: {'YES' if thread.daemon else 'NO'}] [Alive: {'YES' if thread.is_alive() else 'NO'}]\n" uname = platform.uname() virtual_mem = psutil.virtual_memory() blob = f"
::: Summary :::
\n" \ f" - Tracked orgs: {self.db.query_single('SELECT count(*) as count from orgs').count}\n" \ f"- Tracked characters: {self.db.query_single('SELECT count(*) as count from account a where member>1').count}\n" \ f"- Registered alts: {self.db.query_single('SELECT count(*) as count from account where char_id != main').count}\n" \ f"- Registered mains: {self.db.query_single('SELECT count(*) as count from (SELECT main from account where char_id != main group by main) a').count}\n" \ f"- Banned players: {self.db.query_single('SELECT count(*) as count from account where disabled=1').count}\n" \ f"- Online players: {self.db.query_single('SELECT count(*) as count from online where char_id not in (SELECT char_id from org_bots)').count}\n" \ f"- Online bots: {self.db.query_single('SELECT count(*) as count from online where char_id in (SELECT char_id from org_bots)').count}\n" \ f"- Registered bots: {self.db.query_single('SELECT count(*) as count from org_bots').count}\n" \ f" - Active discord accounts: {self.db.query_single('SELECT count(*) as count from account where discord_joined=1').count}\n" \ f""" - Inactive discord accounts: {self.db.query_single("SELECT count(*) as count from account where discord_joined=0 and discord_id != 0 and member>1").count}\n""" \ f" - Commands issued: {self.db.query_single('SELECT count(*) as count from command_usage').count} [since last reset]\n" \ f"- Most used command: {self.db.query_single('SELECT COUNT(*) AS count, command from command_usage GROUP BY command ORDER BY count desc;').command} [since last reset]\n" \ f" - Cached players: {self.db.query_single('SELECT count(*) as count from player').count}\n" \ f" - Cached orgs: {self.db.query_single('SELECT count(*) as count from all_orgs').count}\n" \ f"\n" \ f"
::: Bot :::
\n" \ f" - Memory usage: {adjust_size(psutil.Process(os.getpid()).memory_info().rss)}\n" \ f" - Thread count: {len(threading.enumerate())}\n" \ f" - Slaves: {len(self.bot.conns)}\n" \ f" - Runtime: {self.util.time_to_readable(int(time.time()) - self.bot.start_time, max_levels=None)}\n" \ f"\n" \ f"
::: System :::
\n" \ f" - System: {uname.system}\n" \ f" - Release: {uname.release}\n" \ f" - Version: {uname.version}\n" \ f" - Processor: {uname.processor} ({psutil.cpu_count(logical=False)}C / {psutil.cpu_count()}T)\n" \ f" - CPU Usage: {psutil.cpu_percent()}%\n" \ f" - Memory (Total): {adjust_size(virtual_mem.total)}\n" \ f" - Memory (Avail): {adjust_size(virtual_mem.available)}\n" \ f" - Memory (Used): {adjust_size(virtual_mem.used)}\n" \ f" - Database: {self.db.get_type()} using {self.db.pool_size} connections\n" \ f"\n" if verbose: blob += f"
::: Threads :::
\n" \ f"{threads}\n" \ f"\n" return ChatBlob(f"{self.bot.get_char_name()}'s debugging stats", blob)