Make "abnormal thread terminations" into "ClientLogoutsDueToNoReceives" and add this to the StatsManager
This reflects the actual use of this stat - it hasn't recorded general exceptions for some time. Make the sim extra stats collector draw the data from the stats manager rather than maintaing this data itself.TeleportWork
parent
7eee9eb312
commit
8efe4bfc2e
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenMetaverse.StructuredData;
|
using OpenMetaverse.StructuredData;
|
||||||
|
@ -39,8 +40,6 @@ namespace OpenSim.Framework.Monitoring
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SimExtraStatsCollector : BaseStatsCollector
|
public class SimExtraStatsCollector : BaseStatsCollector
|
||||||
{
|
{
|
||||||
private long abnormalClientThreadTerminations;
|
|
||||||
|
|
||||||
// private long assetsInCache;
|
// private long assetsInCache;
|
||||||
// private long texturesInCache;
|
// private long texturesInCache;
|
||||||
// private long assetCacheMemoryUsage;
|
// private long assetCacheMemoryUsage;
|
||||||
|
@ -73,11 +72,6 @@ namespace OpenSim.Framework.Monitoring
|
||||||
private volatile float activeScripts;
|
private volatile float activeScripts;
|
||||||
private volatile float scriptLinesPerSecond;
|
private volatile float scriptLinesPerSecond;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Number of times that a client thread terminated because of an exception
|
|
||||||
/// </summary>
|
|
||||||
public long AbnormalClientThreadTerminations { get { return abnormalClientThreadTerminations; } }
|
|
||||||
|
|
||||||
// /// <summary>
|
// /// <summary>
|
||||||
// /// These statistics are being collected by push rather than pull. Pull would be simpler, but I had the
|
// /// These statistics are being collected by push rather than pull. Pull would be simpler, but I had the
|
||||||
// /// notion of providing some flow statistics (which pull wouldn't give us). Though admittedly these
|
// /// notion of providing some flow statistics (which pull wouldn't give us). Though admittedly these
|
||||||
|
@ -166,11 +160,6 @@ namespace OpenSim.Framework.Monitoring
|
||||||
private IDictionary<UUID, PacketQueueStatsCollector> packetQueueStatsCollectors
|
private IDictionary<UUID, PacketQueueStatsCollector> packetQueueStatsCollectors
|
||||||
= new Dictionary<UUID, PacketQueueStatsCollector>();
|
= new Dictionary<UUID, PacketQueueStatsCollector>();
|
||||||
|
|
||||||
public void AddAbnormalClientThreadTermination()
|
|
||||||
{
|
|
||||||
abnormalClientThreadTerminations++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// public void AddAsset(AssetBase asset)
|
// public void AddAsset(AssetBase asset)
|
||||||
// {
|
// {
|
||||||
// assetsInCache++;
|
// assetsInCache++;
|
||||||
|
@ -324,10 +313,12 @@ Asset service request failures: {3}" + Environment.NewLine,
|
||||||
sb.Append(Environment.NewLine);
|
sb.Append(Environment.NewLine);
|
||||||
sb.Append("CONNECTION STATISTICS");
|
sb.Append("CONNECTION STATISTICS");
|
||||||
sb.Append(Environment.NewLine);
|
sb.Append(Environment.NewLine);
|
||||||
sb.Append(
|
|
||||||
string.Format(
|
List<Stat> stats = StatsManager.GetStatsFromEachContainer("clientstack", "ClientLogoutsDueToNoReceives");
|
||||||
"Abnormal client thread terminations: {0}" + Environment.NewLine,
|
|
||||||
abnormalClientThreadTerminations));
|
sb.AppendFormat(
|
||||||
|
"Client logouts due to no data receive timeout: {0}\n\n",
|
||||||
|
stats != null ? stats.Sum(s => s.Value).ToString() : "unknown");
|
||||||
|
|
||||||
// sb.Append(Environment.NewLine);
|
// sb.Append(Environment.NewLine);
|
||||||
// sb.Append("INVENTORY STATISTICS");
|
// sb.Append("INVENTORY STATISTICS");
|
||||||
|
@ -338,7 +329,7 @@ Asset service request failures: {3}" + Environment.NewLine,
|
||||||
// InventoryServiceRetrievalFailures));
|
// InventoryServiceRetrievalFailures));
|
||||||
|
|
||||||
sb.Append(Environment.NewLine);
|
sb.Append(Environment.NewLine);
|
||||||
sb.Append("FRAME STATISTICS");
|
sb.Append("SAMPLE FRAME STATISTICS");
|
||||||
sb.Append(Environment.NewLine);
|
sb.Append(Environment.NewLine);
|
||||||
sb.Append("Dilatn SimFPS PhyFPS AgntUp RootAg ChldAg Prims AtvPrm AtvScr ScrLPS");
|
sb.Append("Dilatn SimFPS PhyFPS AgntUp RootAg ChldAg Prims AtvPrm AtvScr ScrLPS");
|
||||||
sb.Append(Environment.NewLine);
|
sb.Append(Environment.NewLine);
|
||||||
|
|
|
@ -271,7 +271,7 @@ namespace OpenSim.Framework.Monitoring
|
||||||
// Stat name is not unique across category/container/shortname key.
|
// Stat name is not unique across category/container/shortname key.
|
||||||
// XXX: For now just return false. This is to avoid problems in regression tests where all tests
|
// XXX: For now just return false. This is to avoid problems in regression tests where all tests
|
||||||
// in a class are run in the same instance of the VM.
|
// in a class are run in the same instance of the VM.
|
||||||
if (TryGetStat(stat, out category, out container))
|
if (TryGetStatParents(stat, out category, out container))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// We take a copy-on-write approach here of replacing dictionaries when keys are added or removed.
|
// We take a copy-on-write approach here of replacing dictionaries when keys are added or removed.
|
||||||
|
@ -307,7 +307,7 @@ namespace OpenSim.Framework.Monitoring
|
||||||
|
|
||||||
lock (RegisteredStats)
|
lock (RegisteredStats)
|
||||||
{
|
{
|
||||||
if (!TryGetStat(stat, out category, out container))
|
if (!TryGetStatParents(stat, out category, out container))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
newContainer = new SortedDictionary<string, Stat>(container);
|
newContainer = new SortedDictionary<string, Stat>(container);
|
||||||
|
@ -323,12 +323,67 @@ namespace OpenSim.Framework.Monitoring
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool TryGetStats(string category, out SortedDictionary<string, SortedDictionary<string, Stat>> stats)
|
public static bool TryGetStat(string category, string container, string statShortName, out Stat stat)
|
||||||
{
|
{
|
||||||
return RegisteredStats.TryGetValue(category, out stats);
|
stat = null;
|
||||||
|
SortedDictionary<string, SortedDictionary<string, Stat>> categoryStats;
|
||||||
|
|
||||||
|
lock (RegisteredStats)
|
||||||
|
{
|
||||||
|
if (!TryGetStatsForCategory(category, out categoryStats))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SortedDictionary<string, Stat> containerStats;
|
||||||
|
|
||||||
|
if (!categoryStats.TryGetValue(container, out containerStats))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return containerStats.TryGetValue(statShortName, out stat);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool TryGetStat(
|
public static bool TryGetStatsForCategory(
|
||||||
|
string category, out SortedDictionary<string, SortedDictionary<string, Stat>> stats)
|
||||||
|
{
|
||||||
|
lock (RegisteredStats)
|
||||||
|
return RegisteredStats.TryGetValue(category, out stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the same stat for each container in a given category.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// The stats if there were any to fetch. Otherwise null.
|
||||||
|
/// </returns>
|
||||||
|
/// <param name='category'></param>
|
||||||
|
/// <param name='statShortName'></param>
|
||||||
|
public static List<Stat> GetStatsFromEachContainer(string category, string statShortName)
|
||||||
|
{
|
||||||
|
SortedDictionary<string, SortedDictionary<string, Stat>> categoryStats;
|
||||||
|
|
||||||
|
lock (RegisteredStats)
|
||||||
|
{
|
||||||
|
if (!RegisteredStats.TryGetValue(category, out categoryStats))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
List<Stat> stats = null;
|
||||||
|
|
||||||
|
foreach (SortedDictionary<string, Stat> containerStats in categoryStats.Values)
|
||||||
|
{
|
||||||
|
if (containerStats.ContainsKey(statShortName))
|
||||||
|
{
|
||||||
|
if (stats == null)
|
||||||
|
stats = new List<Stat>();
|
||||||
|
|
||||||
|
stats.Add(containerStats[statShortName]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryGetStatParents(
|
||||||
Stat stat,
|
Stat stat,
|
||||||
out SortedDictionary<string, SortedDictionary<string, Stat>> category,
|
out SortedDictionary<string, SortedDictionary<string, Stat>> category,
|
||||||
out SortedDictionary<string, Stat> container)
|
out SortedDictionary<string, Stat> container)
|
||||||
|
|
|
@ -67,11 +67,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
m_udpServer.AddScene(scene);
|
m_udpServer.AddScene(scene);
|
||||||
|
|
||||||
|
StatsManager.RegisterStat(
|
||||||
|
new Stat(
|
||||||
|
"ClientLogoutsDueToNoReceives",
|
||||||
|
"Number of times a client has been logged out because no packets were received before the timeout.",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"clientstack",
|
||||||
|
scene.Name,
|
||||||
|
StatType.Pull,
|
||||||
|
MeasuresOfInterest.None,
|
||||||
|
stat => stat.Value = m_udpServer.ClientLogoutsDueToNoReceives,
|
||||||
|
StatVerbosity.Debug));
|
||||||
|
|
||||||
StatsManager.RegisterStat(
|
StatsManager.RegisterStat(
|
||||||
new Stat(
|
new Stat(
|
||||||
"IncomingUDPReceivesCount",
|
"IncomingUDPReceivesCount",
|
||||||
"Number of UDP receives performed",
|
"Number of UDP receives performed",
|
||||||
"Number of UDP receives performed",
|
"",
|
||||||
"",
|
"",
|
||||||
"clientstack",
|
"clientstack",
|
||||||
scene.Name,
|
scene.Name,
|
||||||
|
@ -84,7 +97,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
new Stat(
|
new Stat(
|
||||||
"IncomingPacketsProcessedCount",
|
"IncomingPacketsProcessedCount",
|
||||||
"Number of inbound LL protocol packets processed",
|
"Number of inbound LL protocol packets processed",
|
||||||
"Number of inbound LL protocol packets processed",
|
"",
|
||||||
"",
|
"",
|
||||||
"clientstack",
|
"clientstack",
|
||||||
scene.Name,
|
scene.Name,
|
||||||
|
@ -97,7 +110,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
new Stat(
|
new Stat(
|
||||||
"OutgoingUDPSendsCount",
|
"OutgoingUDPSendsCount",
|
||||||
"Number of UDP sends performed",
|
"Number of UDP sends performed",
|
||||||
"Number of UDP sends performed",
|
"",
|
||||||
"",
|
"",
|
||||||
"clientstack",
|
"clientstack",
|
||||||
scene.Name,
|
scene.Name,
|
||||||
|
@ -149,6 +162,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary>
|
/// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary>
|
||||||
public const int MTU = 1400;
|
public const int MTU = 1400;
|
||||||
|
|
||||||
|
/// <summary>Number of forced client logouts due to no receipt of packets before timeout.</summary>
|
||||||
|
public int ClientLogoutsDueToNoReceives { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default packet debug level given to new clients
|
/// Default packet debug level given to new clients
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1037,7 +1053,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
timeoutTicks = m_pausedAckTimeout;
|
timeoutTicks = m_pausedAckTimeout;
|
||||||
|
|
||||||
if (client.IsActive &&
|
if (client.IsActive &&
|
||||||
(Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > timeoutTicks)
|
(Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > -1)
|
||||||
{
|
{
|
||||||
// We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even
|
// We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even
|
||||||
// though it's set later on by LLClientView.Close()
|
// though it's set later on by LLClientView.Close()
|
||||||
|
@ -1778,7 +1794,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
"[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}",
|
"[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}",
|
||||||
client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName);
|
client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName);
|
||||||
|
|
||||||
StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
|
ClientLogoutsDueToNoReceives++;
|
||||||
|
|
||||||
if (!client.SceneAgent.IsChildAgent)
|
if (!client.SceneAgent.IsChildAgent)
|
||||||
client.Kick("Simulator logged you out due to connection timeout");
|
client.Kick("Simulator logged you out due to connection timeout");
|
||||||
|
|
Loading…
Reference in New Issue