Write UDP statistics to the log, not just the console (e.g., "show queues")

bullet-2.82
Oren Hurvitz 2014-06-29 16:40:11 +03:00
parent 0d70033a5d
commit 5d53412766
2 changed files with 59 additions and 63 deletions

View File

@ -30,6 +30,8 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using log4net;
using OpenSim.Framework;
using OpenMetaverse.StructuredData;
@ -41,6 +43,8 @@ namespace OpenSim.Framework.Monitoring
/// </summary>
public static class StatsManager
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// Subcommand used to list other stats.
public const string AllSubCommand = "all";
@ -98,6 +102,7 @@ namespace OpenSim.Framework.Monitoring
public static void HandleShowStatsCommand(string module, string[] cmd)
{
ICommandConsole con = MainConsole.Instance;
StringBuilder report = new StringBuilder();
if (cmd.Length > 2)
{
@ -111,7 +116,8 @@ namespace OpenSim.Framework.Monitoring
if (categoryName == AllSubCommand)
{
OutputAllStatsToConsole(con);
foreach (string report2 in GetAllStatsReports())
report.AppendLine(report2);
}
else if (categoryName == ListSubCommand)
{
@ -130,7 +136,8 @@ namespace OpenSim.Framework.Monitoring
{
if (String.IsNullOrEmpty(containerName))
{
OutputCategoryStatsToConsole(con, category);
foreach (string report2 in GetCategoryStatsReports(category))
report.AppendLine(report2);
}
else
{
@ -139,14 +146,15 @@ namespace OpenSim.Framework.Monitoring
{
if (String.IsNullOrEmpty(statName))
{
OutputContainerStatsToConsole(con, container);
foreach (string report2 in GetContainerStatsReports(container))
report.AppendLine(report2);
}
else
{
Stat stat;
if (container.TryGetValue(statName, out stat))
{
OutputStatToConsole(con, stat);
report.AppendLine(stat.ToConsoleString());
}
else
{
@ -168,10 +176,18 @@ namespace OpenSim.Framework.Monitoring
{
// Legacy
if (SimExtraStats != null)
con.Output(SimExtraStats.Report());
{
report.Append(SimExtraStats.Report());
}
else
OutputAllStatsToConsole(con);
{
foreach (string report2 in GetAllStatsReports())
report.AppendLine(report2);
}
}
if (report.Length > 0)
m_log.Debug(string.Join(" ", cmd) + "\n" + report.ToString());
}
public static List<string> GetAllStatsReports()
@ -184,12 +200,6 @@ namespace OpenSim.Framework.Monitoring
return reports;
}
private static void OutputAllStatsToConsole(ICommandConsole con)
{
foreach (string report in GetAllStatsReports())
con.Output(report);
}
private static List<string> GetCategoryStatsReports(
SortedDictionary<string, SortedDictionary<string, Stat>> category)
{
@ -201,13 +211,6 @@ namespace OpenSim.Framework.Monitoring
return reports;
}
private static void OutputCategoryStatsToConsole(
ICommandConsole con, SortedDictionary<string, SortedDictionary<string, Stat>> category)
{
foreach (string report in GetCategoryStatsReports(category))
con.Output(report);
}
private static List<string> GetContainerStatsReports(SortedDictionary<string, Stat> container)
{
List<string> reports = new List<string>();
@ -218,18 +221,6 @@ namespace OpenSim.Framework.Monitoring
return reports;
}
private static void OutputContainerStatsToConsole(
ICommandConsole con, SortedDictionary<string, Stat> container)
{
foreach (string report in GetContainerStatsReports(container))
con.Output(report);
}
private static void OutputStatToConsole(ICommandConsole con, Stat stat)
{
con.Output(stat.ToConsoleString());
}
// Creates an OSDMap of the format:
// { categoryName: {
// containerName: {

View File

@ -87,8 +87,8 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
"show pqueues [full]",
"Show priority queue data for each client",
"Without the 'full' option, only root agents are shown."
+ " With the 'full' option child agents are also shown.",
(mod, cmd) => MainConsole.Instance.Output(GetPQueuesReport(cmd)));
+ " With the 'full' option child agents are also shown.",
(mod, cmd) => m_log.Debug(string.Join(" ", cmd) + "\n" + GetPQueuesReport(cmd)));
scene.AddCommand(
"Comms", this, "show queues",
@ -103,27 +103,27 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
+ "Pkts Resent - Number of packets resent to the client.\n"
+ "Bytes Unacked - Number of bytes transferred to the client that are awaiting acknowledgement.\n"
+ "Q Pkts * - Number of packets of various types (land, wind, etc.) to be sent to the client that are waiting for available bandwidth.\n",
(mod, cmd) => MainConsole.Instance.Output(GetQueuesReport(cmd)));
(mod, cmd) => m_log.Debug(string.Join(" ", cmd) + "\n" + GetQueuesReport(cmd)));
scene.AddCommand(
"Comms", this, "show image queues",
"show image queues <first-name> <last-name>",
"Show the image queues (textures downloaded via UDP) for a particular client.",
(mod, cmd) => MainConsole.Instance.Output(GetImageQueuesReport(cmd)));
(mod, cmd) => m_log.Debug(string.Join(" ", cmd) + "\n" + GetImageQueuesReport(cmd)));
scene.AddCommand(
"Comms", this, "clear image queues",
"clear image queues <first-name> <last-name>",
"Clear the image queues (textures downloaded via UDP) for a particular client.",
(mod, cmd) => MainConsole.Instance.Output(HandleImageQueuesClear(cmd)));
(mod, cmd) => m_log.Debug(string.Join(" ", cmd) + "\n" + HandleImageQueuesClear(cmd)));
scene.AddCommand(
"Comms", this, "show throttles",
"show throttles [full]",
"Show throttle settings for each client and for the server overall",
"Without the 'full' option, only root agents are shown."
+ " With the 'full' option child agents are also shown.",
(mod, cmd) => MainConsole.Instance.Output(GetThrottlesReport(cmd)));
+ " With the 'full' option child agents are also shown.",
(mod, cmd) => m_log.Debug(string.Join(" ", cmd) + "\n" + GetThrottlesReport(cmd)));
scene.AddCommand(
"Comms", this, "emergency-monitoring",
@ -138,7 +138,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
"Show client request stats",
"Without the 'first_name last_name' option, all clients are shown."
+ " With the 'first_name last_name' option only a specific client is shown.",
(mod, cmd) => MainConsole.Instance.Output(HandleClientStatsReport(cmd)));
(mod, cmd) => m_log.Debug(string.Join(" ", cmd) + "\n" + HandleClientStatsReport(cmd)));
}
@ -279,7 +279,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
return;
string name = client.Name;
if (pname != "" && name != pname)
if (pname != "" && name.ToLower() != pname.ToLower())
return;
string regionName = scene.RegionInfo.RegionName;
@ -440,7 +440,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
return;
string name = client.Name;
if (pname != "" && name != pname)
if (pname != "" && name.ToLower() != pname.ToLower())
return;
string regionName = scene.RegionInfo.RegionName;
@ -535,7 +535,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
return;
string name = client.Name;
if (pname != "" && name != pname)
if (pname != "" && name.ToLower() != pname.ToLower())
return;
string regionName = scene.RegionInfo.RegionName;
@ -604,12 +604,12 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
/// <returns></returns>
protected string HandleClientStatsReport(string[] showParams)
{
// NOTE: This writes to m_log on purpose. We want to store this information
// in case we need to analyze it later.
//
StringBuilder report = new StringBuilder();
if (showParams.Length <= 4)
{
m_log.InfoFormat("[INFO]: {0,-12} {1,-20} {2,-6} {3,-11} {4,-11} {5,-16}", "Region", "Name", "Root", "Time", "Reqs/min", "AgentUpdates");
report.AppendFormat("{0,-30} {1,-30} {2,-6} {3,-11} {4,-11} {5,-16}\n", "Region", "Name", "Root", "Time", "Reqs/min", "AgentUpdates");
foreach (Scene scene in m_scenes.Values)
{
scene.ForEachClient(
@ -629,7 +629,10 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
else
childAgentStatus = "Off!";
m_log.InfoFormat("[INFO]: {0,-12} {1,-20} {2,-6} {3,-11} {4,-11} {5,-16}",
int agentUpdates = 0;
cinfo.SyncRequests.TryGetValue("AgentUpdate", out agentUpdates);
report.AppendFormat("{0,-30} {1,-30} {2,-6} {3,-11} {4,-11} {5,-16}\n",
scene.RegionInfo.RegionName, llClient.Name,
childAgentStatus,
(DateTime.Now - cinfo.StartedTime).Minutes,
@ -637,11 +640,12 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
string.Format(
"{0} ({1:0.00}%)",
llClient.TotalAgentUpdates,
(float)cinfo.SyncRequests["AgentUpdate"] / llClient.TotalAgentUpdates * 100));
((float)agentUpdates) / llClient.TotalAgentUpdates * 100));
}
});
}
return string.Empty;
return report.ToString();
}
string fname = "", lname = "";
@ -660,7 +664,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
{
LLClientView llClient = client as LLClientView;
if (llClient.Name == fname + " " + lname)
if (llClient.Name.ToLower() == (fname + " " + lname).ToLower())
{
ClientInfo cinfo = llClient.GetClientInfo();
@ -669,41 +673,42 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
aCircuit = new AgentCircuitData();
if (!llClient.SceneAgent.IsChildAgent)
m_log.InfoFormat("[INFO]: {0} # {1} # {2}", llClient.Name, Util.GetViewerName(aCircuit), aCircuit.Id0);
report.AppendFormat("{0} # {1} # {2}\n", llClient.Name, Util.GetViewerName(aCircuit), aCircuit.Id0);
int avg_reqs = cinfo.AsyncRequests.Values.Sum() + cinfo.GenericRequests.Values.Sum() + cinfo.SyncRequests.Values.Sum();
avg_reqs = avg_reqs / ((DateTime.Now - cinfo.StartedTime).Minutes + 1);
m_log.InfoFormat("[INFO]:");
m_log.InfoFormat("[INFO]: {0} # {1} # Time: {2}min # Avg Reqs/min: {3}", scene.RegionInfo.RegionName,
report.AppendLine();
report.AppendFormat("{0} # {1} # Time: {2}min # Avg Reqs/min: {3}\n", scene.RegionInfo.RegionName,
(llClient.SceneAgent.IsChildAgent ? "Child" : "Root"), (DateTime.Now - cinfo.StartedTime).Minutes, avg_reqs);
Dictionary<string, int> sortedDict = (from entry in cinfo.AsyncRequests orderby entry.Value descending select entry)
.ToDictionary(pair => pair.Key, pair => pair.Value);
PrintRequests("TOP ASYNC", sortedDict, cinfo.AsyncRequests.Values.Sum());
PrintRequests(report, "TOP ASYNC", sortedDict, cinfo.AsyncRequests.Values.Sum());
sortedDict = (from entry in cinfo.SyncRequests orderby entry.Value descending select entry)
.ToDictionary(pair => pair.Key, pair => pair.Value);
PrintRequests("TOP SYNC", sortedDict, cinfo.SyncRequests.Values.Sum());
PrintRequests(report, "TOP SYNC", sortedDict, cinfo.SyncRequests.Values.Sum());
sortedDict = (from entry in cinfo.GenericRequests orderby entry.Value descending select entry)
.ToDictionary(pair => pair.Key, pair => pair.Value);
PrintRequests("TOP GENERIC", sortedDict, cinfo.GenericRequests.Values.Sum());
PrintRequests(report, "TOP GENERIC", sortedDict, cinfo.GenericRequests.Values.Sum());
}
}
});
}
return string.Empty;
return report.ToString();
}
private void PrintRequests(string type, Dictionary<string, int> sortedDict, int sum)
private void PrintRequests(StringBuilder report, string type, Dictionary<string, int> sortedDict, int sum)
{
m_log.InfoFormat("[INFO]:");
m_log.InfoFormat("[INFO]: {0,25}", type);
report.AppendLine();
report.AppendFormat("{0,25}\n", type);
foreach (KeyValuePair<string, int> kvp in sortedDict.Take(12))
m_log.InfoFormat("[INFO]: {0,25} {1,-6}", kvp.Key, kvp.Value);
m_log.InfoFormat("[INFO]: {0,25}", "...");
m_log.InfoFormat("[INFO]: {0,25} {1,-6}", "Total", sum);
report.AppendFormat("{0,25} {1,-6}\n", kvp.Key, kvp.Value);
report.AppendFormat("{0,25}\n", "...");
report.AppendFormat("{0,25} {1,-6}\n", "Total", sum);
}
}
}