anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
os_stats.cpp (9510B)
1 /* OperServ core functions 2 * 3 * (C) 2003-2022 Anope Team 4 * Contact us at team@anope.org 5 * 6 * Please read COPYING and README for further details. 7 * 8 * Based on the original code of Epona by Lara. 9 * Based on the original code of Services by Andy Church. 10 */ 11 12 #include "module.h" 13 #include "modules/os_session.h" 14 15 struct Stats : Serializable 16 { 17 static Stats *me; 18 19 Stats() : Serializable("Stats") 20 { 21 me = this; 22 } 23 24 void Serialize(Serialize::Data &data) const anope_override 25 { 26 data["maxusercnt"] << MaxUserCount; 27 data["maxusertime"] << MaxUserTime; 28 } 29 30 static Serializable* Unserialize(Serializable *obj, Serialize::Data &data) 31 { 32 data["maxusercnt"] >> MaxUserCount; 33 data["maxusertime"] >> MaxUserTime; 34 return me; 35 } 36 }; 37 38 Stats *Stats::me; 39 40 /** 41 * Count servers connected to server s 42 * @param s The server to start counting from 43 * @return Amount of servers connected to server s 44 **/ 45 static int stats_count_servers(Server *s) 46 { 47 if (!s) 48 return 0; 49 50 int count = 1; 51 52 if (!s->GetLinks().empty()) 53 for (unsigned i = 0, j = s->GetLinks().size(); i < j; ++i) 54 count += stats_count_servers(s->GetLinks()[i]); 55 56 return count; 57 } 58 59 class CommandOSStats : public Command 60 { 61 ServiceReference<XLineManager> akills, snlines, sqlines; 62 private: 63 void DoStatsAkill(CommandSource &source) 64 { 65 int timeout; 66 if (akills) 67 { 68 /* AKILLs */ 69 source.Reply(_("Current number of AKILLs: \002%d\002"), akills->GetCount()); 70 timeout = Config->GetModule("operserv")->Get<time_t>("autokillexpiry", "30d") + 59; 71 if (timeout >= 172800) 72 source.Reply(_("Default AKILL expiry time: \002%d days\002"), timeout / 86400); 73 else if (timeout >= 86400) 74 source.Reply(_("Default AKILL expiry time: \0021 day\002")); 75 else if (timeout >= 7200) 76 source.Reply(_("Default AKILL expiry time: \002%d hours\002"), timeout / 3600); 77 else if (timeout >= 3600) 78 source.Reply(_("Default AKILL expiry time: \0021 hour\002")); 79 else if (timeout >= 120) 80 source.Reply(_("Default AKILL expiry time: \002%d minutes\002"), timeout / 60); 81 else if (timeout >= 60) 82 source.Reply(_("Default AKILL expiry time: \0021 minute\002")); 83 else 84 source.Reply(_("Default AKILL expiry time: \002No expiration\002")); 85 } 86 if (snlines) 87 { 88 /* SNLINEs */ 89 source.Reply(_("Current number of SNLINEs: \002%d\002"), snlines->GetCount()); 90 timeout = Config->GetModule("operserv")->Get<time_t>("snlineexpiry", "30d") + 59; 91 if (timeout >= 172800) 92 source.Reply(_("Default SNLINE expiry time: \002%d days\002"), timeout / 86400); 93 else if (timeout >= 86400) 94 source.Reply(_("Default SNLINE expiry time: \0021 day\002")); 95 else if (timeout >= 7200) 96 source.Reply(_("Default SNLINE expiry time: \002%d hours\002"), timeout / 3600); 97 else if (timeout >= 3600) 98 source.Reply(_("Default SNLINE expiry time: \0021 hour\002")); 99 else if (timeout >= 120) 100 source.Reply(_("Default SNLINE expiry time: \002%d minutes\002"), timeout / 60); 101 else if (timeout >= 60) 102 source.Reply(_("Default SNLINE expiry time: \0021 minute\002")); 103 else 104 source.Reply(_("Default SNLINE expiry time: \002No expiration\002")); 105 } 106 if (sqlines) 107 { 108 /* SQLINEs */ 109 source.Reply(_("Current number of SQLINEs: \002%d\002"), sqlines->GetCount()); 110 timeout = Config->GetModule("operserv")->Get<time_t>("sglineexpiry", "30d") + 59; 111 if (timeout >= 172800) 112 source.Reply(_("Default SQLINE expiry time: \002%d days\002"), timeout / 86400); 113 else if (timeout >= 86400) 114 source.Reply(_("Default SQLINE expiry time: \0021 day\002")); 115 else if (timeout >= 7200) 116 source.Reply(_("Default SQLINE expiry time: \002%d hours\002"), timeout / 3600); 117 else if (timeout >= 3600) 118 source.Reply(_("Default SQLINE expiry time: \0021 hour\002")); 119 else if (timeout >= 120) 120 source.Reply(_("Default SQLINE expiry time: \002%d minutes\002"), timeout / 60); 121 else if (timeout >= 60) 122 source.Reply(_("Default SQLINE expiry time: \0021 minute\002")); 123 else 124 source.Reply(_("Default SQLINE expiry time: \002No expiration\002")); 125 } 126 } 127 128 void DoStatsReset(CommandSource &source) 129 { 130 MaxUserCount = UserListByNick.size(); 131 source.Reply(_("Statistics reset.")); 132 return; 133 } 134 135 void DoStatsUptime(CommandSource &source) 136 { 137 time_t uptime = Anope::CurTime - Anope::StartTime; 138 source.Reply(_("Current users: \002%d\002 (\002%d\002 ops)"), UserListByNick.size(), OperCount); 139 source.Reply(_("Maximum users: \002%d\002 (%s)"), MaxUserCount, Anope::strftime(MaxUserTime, source.GetAccount()).c_str()); 140 source.Reply(_("Services up %s."), Anope::Duration(uptime, source.GetAccount()).c_str()); 141 142 return; 143 } 144 145 void DoStatsUplink(CommandSource &source) 146 { 147 Anope::string buf; 148 for (std::set<Anope::string>::iterator it = Servers::Capab.begin(); it != Servers::Capab.end(); ++it) 149 buf += " " + *it; 150 if (!buf.empty()) 151 buf.erase(buf.begin()); 152 153 source.Reply(_("Uplink server: %s"), Me->GetLinks().front()->GetName().c_str()); 154 source.Reply(_("Uplink capab: %s"), buf.c_str()); 155 source.Reply(_("Servers found: %d"), stats_count_servers(Me->GetLinks().front())); 156 return; 157 } 158 159 template<typename T> void GetHashStats(const T& map, size_t& entries, size_t& buckets, size_t& max_chain) 160 { 161 entries = map.size(), buckets = map.bucket_count(), max_chain = 0; 162 for (size_t i = 0; i < buckets; ++i) 163 if (map.bucket_size(i) > max_chain) 164 max_chain = map.bucket_size(i); 165 } 166 167 void DoStatsHash(CommandSource &source) 168 { 169 size_t entries, buckets, max_chain; 170 171 GetHashStats(UserListByNick, entries, buckets, max_chain); 172 source.Reply(_("Users (nick): %lu entries, %lu buckets, longest chain is %d"), entries, buckets, max_chain); 173 174 if (!UserListByUID.empty()) 175 { 176 GetHashStats(UserListByUID, entries, buckets, max_chain); 177 source.Reply(_("Users (uid): %lu entries, %lu buckets, longest chain is %d"), entries, buckets, max_chain); 178 } 179 180 GetHashStats(ChannelList, entries, buckets, max_chain); 181 source.Reply(_("Channels: %lu entries, %lu buckets, longest chain is %d"), entries, buckets, max_chain); 182 183 GetHashStats(*RegisteredChannelList, entries, buckets, max_chain); 184 source.Reply(_("Registered channels: %lu entries, %lu buckets, longest chain is %d"), entries, buckets, max_chain); 185 186 GetHashStats(*NickAliasList, entries, buckets, max_chain); 187 source.Reply(_("Registered nicknames: %lu entries, %lu buckets, longest chain is %d"), entries, buckets, max_chain); 188 189 GetHashStats(*NickCoreList, entries, buckets, max_chain); 190 source.Reply(_("Registered nick groups: %lu entries, %lu buckets, longest chain is %d"), entries, buckets, max_chain); 191 192 if (session_service) 193 { 194 GetHashStats(session_service->GetSessions(), entries, buckets, max_chain); 195 source.Reply(_("Sessions: %lu entries, %lu buckets, longest chain is %d"), entries, buckets, max_chain); 196 } 197 } 198 199 public: 200 CommandOSStats(Module *creator) : Command(creator, "operserv/stats", 0, 1), 201 akills("XLineManager", "xlinemanager/sgline"), snlines("XLineManager", "xlinemanager/snline"), sqlines("XLineManager", "xlinemanager/sqline") 202 { 203 this->SetDesc(_("Show status of Services and network")); 204 this->SetSyntax("[AKILL | HASH | UPLINK | UPTIME | ALL | RESET]"); 205 } 206 207 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 208 { 209 Anope::string extra = !params.empty() ? params[0] : ""; 210 211 Log(LOG_ADMIN, source, this) << extra; 212 213 if (extra.equals_ci("RESET")) 214 return this->DoStatsReset(source); 215 216 if (extra.equals_ci("ALL") || extra.equals_ci("AKILL")) 217 this->DoStatsAkill(source); 218 219 if (extra.equals_ci("ALL") || extra.equals_ci("HASH")) 220 this->DoStatsHash(source); 221 222 if (extra.equals_ci("ALL") || extra.equals_ci("UPLINK")) 223 this->DoStatsUplink(source); 224 225 if (extra.empty() || extra.equals_ci("ALL") || extra.equals_ci("UPTIME")) 226 this->DoStatsUptime(source); 227 228 if (!extra.empty() && !extra.equals_ci("ALL") && !extra.equals_ci("AKILL") && !extra.equals_ci("HASH") && !extra.equals_ci("UPLINK") && !extra.equals_ci("UPTIME")) 229 source.Reply(_("Unknown STATS option: \002%s\002"), extra.c_str()); 230 } 231 232 bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override 233 { 234 this->SendSyntax(source); 235 source.Reply(" "); 236 source.Reply(_("Without any option, shows the current number of users online,\n" 237 "and the highest number of users online since Services was\n" 238 "started, and the length of time Services has been running.\n" 239 " \n" 240 "With the \002AKILL\002 option, displays the current size of the\n" 241 "AKILL list and the current default expiry time.\n" 242 " \n" 243 "The \002RESET\002 option currently resets the maximum user count\n" 244 "to the number of users currently present on the network.\n" 245 " \n" 246 "The \002UPLINK\002 option displays information about the current\n" 247 "server Anope uses as an uplink to the network.\n" 248 " \n" 249 "The \002HASH\002 option displays information about the hash maps.\n" 250 " \n" 251 "The \002ALL\002 option displays all of the above statistics.")); 252 return true; 253 } 254 }; 255 256 class OSStats : public Module 257 { 258 CommandOSStats commandosstats; 259 Serialize::Type stats_type; 260 Stats stats_saver; 261 262 public: 263 OSStats(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), 264 commandosstats(this), stats_type("Stats", Stats::Unserialize) 265 { 266 267 } 268 269 void OnUserConnect(User *u, bool &exempt) anope_override 270 { 271 if (UserListByNick.size() == MaxUserCount && Anope::CurTime == MaxUserTime) 272 stats_saver.QueueUpdate(); 273 } 274 }; 275 276 MODULE_INIT(OSStats)