aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Monitoring/StatsManager.cs
diff options
context:
space:
mode:
authorMelanie Thielker2014-06-21 00:39:55 +0200
committerMelanie Thielker2014-06-21 00:39:55 +0200
commit159fcbf150b7da0e229b29aa7b94793484543d12 (patch)
treeb8c0ff3b4c758a3fba8315b556c923ef4c02a185 /OpenSim/Framework/Monitoring/StatsManager.cs
parentMerge commit '68c8633ba18f0a11cfc0ed04d1d0c7c59e6cec76' (diff)
parentMerge branch 'master' into careminster (diff)
downloadopensim-SC-159fcbf150b7da0e229b29aa7b94793484543d12.zip
opensim-SC-159fcbf150b7da0e229b29aa7b94793484543d12.tar.gz
opensim-SC-159fcbf150b7da0e229b29aa7b94793484543d12.tar.bz2
opensim-SC-159fcbf150b7da0e229b29aa7b94793484543d12.tar.xz
Merge branch 'master' of ssh://3dhosting.de/var/git/careminster
Conflicts: OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
Diffstat (limited to 'OpenSim/Framework/Monitoring/StatsManager.cs')
-rw-r--r--OpenSim/Framework/Monitoring/StatsManager.cs334
1 files changed, 269 insertions, 65 deletions
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs
index 24db6d4..05ee4c5 100644
--- a/OpenSim/Framework/Monitoring/StatsManager.cs
+++ b/OpenSim/Framework/Monitoring/StatsManager.cs
@@ -26,15 +26,20 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections;
29using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Linq;
30using System.Text; 32using System.Text;
31 33
34using OpenSim.Framework;
35using OpenMetaverse.StructuredData;
36
32namespace OpenSim.Framework.Monitoring 37namespace OpenSim.Framework.Monitoring
33{ 38{
34 /// <summary> 39 /// <summary>
35 /// Singleton used to provide access to statistics reporters 40 /// Static class used to register/deregister/fetch statistics
36 /// </summary> 41 /// </summary>
37 public class StatsManager 42 public static class StatsManager
38 { 43 {
39 // Subcommand used to list other stats. 44 // Subcommand used to list other stats.
40 public const string AllSubCommand = "all"; 45 public const string AllSubCommand = "all";
@@ -54,13 +59,13 @@ namespace OpenSim.Framework.Monitoring
54 public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>> RegisteredStats 59 public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>> RegisteredStats
55 = new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>>(); 60 = new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>>();
56 61
57 private static AssetStatsCollector assetStats; 62// private static AssetStatsCollector assetStats;
58 private static UserStatsCollector userStats; 63// private static UserStatsCollector userStats;
59 private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector(); 64// private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
60 65
61 public static AssetStatsCollector AssetStats { get { return assetStats; } } 66// public static AssetStatsCollector AssetStats { get { return assetStats; } }
62 public static UserStatsCollector UserStats { get { return userStats; } } 67// public static UserStatsCollector UserStats { get { return userStats; } }
63 public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } 68 public static SimExtraStatsCollector SimExtraStats { get; set; }
64 69
65 public static void RegisterConsoleCommands(ICommandConsole console) 70 public static void RegisterConsoleCommands(ICommandConsole console)
66 { 71 {
@@ -68,14 +73,18 @@ namespace OpenSim.Framework.Monitoring
68 "General", 73 "General",
69 false, 74 false,
70 "show stats", 75 "show stats",
71 "show stats [list|all|<category>]", 76 "show stats [list|all|(<category>[.<container>])+",
72 "Show statistical information for this server", 77 "Show statistical information for this server",
73 "If no final argument is specified then legacy statistics information is currently shown.\n" 78 "If no final argument is specified then legacy statistics information is currently shown.\n"
74 + "If list is specified then statistic categories are shown.\n" 79 + "'list' argument will show statistic categories.\n"
75 + "If all is specified then all registered statistics are shown.\n" 80 + "'all' will show all statistics.\n"
76 + "If a category name is specified then only statistics from that category are shown.\n" 81 + "A <category> name will show statistics from that category.\n"
82 + "A <category>.<container> name will show statistics from that category in that container.\n"
83 + "More than one name can be given separated by spaces.\n"
77 + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS", 84 + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS",
78 HandleShowStatsCommand); 85 HandleShowStatsCommand);
86
87 StatsLogger.RegisterConsoleCommands(console);
79 } 88 }
80 89
81 public static void HandleShowStatsCommand(string module, string[] cmd) 90 public static void HandleShowStatsCommand(string module, string[] cmd)
@@ -84,43 +93,47 @@ namespace OpenSim.Framework.Monitoring
84 93
85 if (cmd.Length > 2) 94 if (cmd.Length > 2)
86 { 95 {
87 var categoryName = cmd[2]; 96 foreach (string name in cmd.Skip(2))
88 var containerName = cmd.Length > 3 ? cmd[3] : String.Empty;
89
90 if (categoryName == AllSubCommand)
91 { 97 {
92 foreach (var category in RegisteredStats.Values) 98 string[] components = name.Split('.');
99
100 string categoryName = components[0];
101 string containerName = components.Length > 1 ? components[1] : null;
102
103 if (categoryName == AllSubCommand)
93 { 104 {
94 OutputCategoryStatsToConsole(con, category); 105 OutputAllStatsToConsole(con);
95 } 106 }
96 } 107 else if (categoryName == ListSubCommand)
97 else if (categoryName == ListSubCommand)
98 {
99 con.Output("Statistic categories available are:");
100 foreach (string category in RegisteredStats.Keys)
101 con.OutputFormat(" {0}", category);
102 }
103 else
104 {
105 SortedDictionary<string, SortedDictionary<string, Stat>> category;
106 if (!RegisteredStats.TryGetValue(categoryName, out category))
107 { 108 {
108 con.OutputFormat("No such category as {0}", categoryName); 109 con.Output("Statistic categories available are:");
110 foreach (string category in RegisteredStats.Keys)
111 con.OutputFormat(" {0}", category);
109 } 112 }
110 else 113 else
111 { 114 {
112 if (String.IsNullOrEmpty(containerName)) 115 SortedDictionary<string, SortedDictionary<string, Stat>> category;
113 OutputCategoryStatsToConsole(con, category); 116 if (!RegisteredStats.TryGetValue(categoryName, out category))
117 {
118 con.OutputFormat("No such category as {0}", categoryName);
119 }
114 else 120 else
115 { 121 {
116 SortedDictionary<string, Stat> container; 122 if (String.IsNullOrEmpty(containerName))
117 if (category.TryGetValue(containerName, out container))
118 { 123 {
119 OutputContainerStatsToConsole(con, container); 124 OutputCategoryStatsToConsole(con, category);
120 } 125 }
121 else 126 else
122 { 127 {
123 con.OutputFormat("No such container {0} in category {1}", containerName, categoryName); 128 SortedDictionary<string, Stat> container;
129 if (category.TryGetValue(containerName, out container))
130 {
131 OutputContainerStatsToConsole(con, container);
132 }
133 else
134 {
135 con.OutputFormat("No such container {0} in category {1}", containerName, categoryName);
136 }
124 } 137 }
125 } 138 }
126 } 139 }
@@ -129,51 +142,187 @@ namespace OpenSim.Framework.Monitoring
129 else 142 else
130 { 143 {
131 // Legacy 144 // Legacy
132 con.Output(SimExtraStats.Report()); 145 if (SimExtraStats != null)
146 con.Output(SimExtraStats.Report());
147 else
148 OutputAllStatsToConsole(con);
133 } 149 }
134 } 150 }
135 151
152 public static List<string> GetAllStatsReports()
153 {
154 List<string> reports = new List<string>();
155
156 foreach (var category in RegisteredStats.Values)
157 reports.AddRange(GetCategoryStatsReports(category));
158
159 return reports;
160 }
161
162 private static void OutputAllStatsToConsole(ICommandConsole con)
163 {
164 foreach (string report in GetAllStatsReports())
165 con.Output(report);
166 }
167
168 private static List<string> GetCategoryStatsReports(
169 SortedDictionary<string, SortedDictionary<string, Stat>> category)
170 {
171 List<string> reports = new List<string>();
172
173 foreach (var container in category.Values)
174 reports.AddRange(GetContainerStatsReports(container));
175
176 return reports;
177 }
178
136 private static void OutputCategoryStatsToConsole( 179 private static void OutputCategoryStatsToConsole(
137 ICommandConsole con, SortedDictionary<string, SortedDictionary<string, Stat>> category) 180 ICommandConsole con, SortedDictionary<string, SortedDictionary<string, Stat>> category)
138 { 181 {
139 foreach (var container in category.Values) 182 foreach (string report in GetCategoryStatsReports(category))
140 { 183 con.Output(report);
141 OutputContainerStatsToConsole(con, container);
142 }
143 } 184 }
144 185
145 private static void OutputContainerStatsToConsole( ICommandConsole con, SortedDictionary<string, Stat> container) 186 private static List<string> GetContainerStatsReports(SortedDictionary<string, Stat> container)
146 { 187 {
188 List<string> reports = new List<string>();
189
147 foreach (Stat stat in container.Values) 190 foreach (Stat stat in container.Values)
148 { 191 reports.Add(stat.ToConsoleString());
149 con.Output(stat.ToConsoleString()); 192
150 } 193 return reports;
151 } 194 }
152 195
153 /// <summary> 196 private static void OutputContainerStatsToConsole(
154 /// Start collecting statistics related to assets. 197 ICommandConsole con, SortedDictionary<string, Stat> container)
155 /// Should only be called once. 198 {
156 /// </summary> 199 foreach (string report in GetContainerStatsReports(container))
157 public static AssetStatsCollector StartCollectingAssetStats() 200 con.Output(report);
201 }
202
203 // Creates an OSDMap of the format:
204 // { categoryName: {
205 // containerName: {
206 // statName: {
207 // "Name": name,
208 // "ShortName": shortName,
209 // ...
210 // },
211 // statName: {
212 // "Name": name,
213 // "ShortName": shortName,
214 // ...
215 // },
216 // ...
217 // },
218 // containerName: {
219 // ...
220 // },
221 // ...
222 // },
223 // categoryName: {
224 // ...
225 // },
226 // ...
227 // }
228 // The passed in parameters will filter the categories, containers and stats returned. If any of the
229 // parameters are either EmptyOrNull or the AllSubCommand value, all of that type will be returned.
230 // Case matters.
231 public static OSDMap GetStatsAsOSDMap(string pCategoryName, string pContainerName, string pStatName)
158 { 232 {
159 assetStats = new AssetStatsCollector(); 233 OSDMap map = new OSDMap();
234
235 foreach (string catName in RegisteredStats.Keys)
236 {
237 // Do this category if null spec, "all" subcommand or category name matches passed parameter.
238 // Skip category if none of the above.
239 if (!(String.IsNullOrEmpty(pCategoryName) || pCategoryName == AllSubCommand || pCategoryName == catName))
240 continue;
160 241
161 return assetStats; 242 OSDMap contMap = new OSDMap();
243 foreach (string contName in RegisteredStats[catName].Keys)
244 {
245 if (!(string.IsNullOrEmpty(pContainerName) || pContainerName == AllSubCommand || pContainerName == contName))
246 continue;
247
248 OSDMap statMap = new OSDMap();
249
250 SortedDictionary<string, Stat> theStats = RegisteredStats[catName][contName];
251 foreach (string statName in theStats.Keys)
252 {
253 if (!(String.IsNullOrEmpty(pStatName) || pStatName == AllSubCommand || pStatName == statName))
254 continue;
255
256 statMap.Add(statName, theStats[statName].ToOSDMap());
257 }
258
259 contMap.Add(contName, statMap);
260 }
261 map.Add(catName, contMap);
262 }
263
264 return map;
162 } 265 }
163 266
164 /// <summary> 267 public static Hashtable HandleStatsRequest(Hashtable request)
165 /// Start collecting statistics related to users.
166 /// Should only be called once.
167 /// </summary>
168 public static UserStatsCollector StartCollectingUserStats()
169 { 268 {
170 userStats = new UserStatsCollector(); 269 Hashtable responsedata = new Hashtable();
270// string regpath = request["uri"].ToString();
271 int response_code = 200;
272 string contenttype = "text/json";
273
274 string pCategoryName = StatsManager.AllSubCommand;
275 string pContainerName = StatsManager.AllSubCommand;
276 string pStatName = StatsManager.AllSubCommand;
277
278 if (request.ContainsKey("cat")) pCategoryName = request["cat"].ToString();
279 if (request.ContainsKey("cont")) pContainerName = request["cat"].ToString();
280 if (request.ContainsKey("stat")) pStatName = request["cat"].ToString();
281
282 string strOut = StatsManager.GetStatsAsOSDMap(pCategoryName, pContainerName, pStatName).ToString();
283
284 // If requestor wants it as a callback function, build response as a function rather than just the JSON string.
285 if (request.ContainsKey("callback"))
286 {
287 strOut = request["callback"].ToString() + "(" + strOut + ");";
288 }
171 289
172 return userStats; 290 // m_log.DebugFormat("{0} StatFetch: uri={1}, cat={2}, cont={3}, stat={4}, resp={5}",
291 // LogHeader, regpath, pCategoryName, pContainerName, pStatName, strOut);
292
293 responsedata["int_response_code"] = response_code;
294 responsedata["content_type"] = contenttype;
295 responsedata["keepalive"] = false;
296 responsedata["str_response_string"] = strOut;
297 responsedata["access_control_allow_origin"] = "*";
298
299 return responsedata;
173 } 300 }
174 301
302// /// <summary>
303// /// Start collecting statistics related to assets.
304// /// Should only be called once.
305// /// </summary>
306// public static AssetStatsCollector StartCollectingAssetStats()
307// {
308// assetStats = new AssetStatsCollector();
309//
310// return assetStats;
311// }
312//
313// /// <summary>
314// /// Start collecting statistics related to users.
315// /// Should only be called once.
316// /// </summary>
317// public static UserStatsCollector StartCollectingUserStats()
318// {
319// userStats = new UserStatsCollector();
320//
321// return userStats;
322// }
323
175 /// <summary> 324 /// <summary>
176 /// Registers a statistic. 325 /// Register a statistic.
177 /// </summary> 326 /// </summary>
178 /// <param name='stat'></param> 327 /// <param name='stat'></param>
179 /// <returns></returns> 328 /// <returns></returns>
@@ -187,7 +336,7 @@ namespace OpenSim.Framework.Monitoring
187 // Stat name is not unique across category/container/shortname key. 336 // Stat name is not unique across category/container/shortname key.
188 // XXX: For now just return false. This is to avoid problems in regression tests where all tests 337 // XXX: For now just return false. This is to avoid problems in regression tests where all tests
189 // in a class are run in the same instance of the VM. 338 // in a class are run in the same instance of the VM.
190 if (TryGetStat(stat, out category, out container)) 339 if (TryGetStatParents(stat, out category, out container))
191 return false; 340 return false;
192 341
193 // We take a copy-on-write approach here of replacing dictionaries when keys are added or removed. 342 // We take a copy-on-write approach here of replacing dictionaries when keys are added or removed.
@@ -223,7 +372,7 @@ namespace OpenSim.Framework.Monitoring
223 372
224 lock (RegisteredStats) 373 lock (RegisteredStats)
225 { 374 {
226 if (!TryGetStat(stat, out category, out container)) 375 if (!TryGetStatParents(stat, out category, out container))
227 return false; 376 return false;
228 377
229 newContainer = new SortedDictionary<string, Stat>(container); 378 newContainer = new SortedDictionary<string, Stat>(container);
@@ -239,12 +388,67 @@ namespace OpenSim.Framework.Monitoring
239 } 388 }
240 } 389 }
241 390
242 public static bool TryGetStats(string category, out SortedDictionary<string, SortedDictionary<string, Stat>> stats) 391 public static bool TryGetStat(string category, string container, string statShortName, out Stat stat)
243 { 392 {
244 return RegisteredStats.TryGetValue(category, out stats); 393 stat = null;
394 SortedDictionary<string, SortedDictionary<string, Stat>> categoryStats;
395
396 lock (RegisteredStats)
397 {
398 if (!TryGetStatsForCategory(category, out categoryStats))
399 return false;
400
401 SortedDictionary<string, Stat> containerStats;
402
403 if (!categoryStats.TryGetValue(container, out containerStats))
404 return false;
405
406 return containerStats.TryGetValue(statShortName, out stat);
407 }
408 }
409
410 public static bool TryGetStatsForCategory(
411 string category, out SortedDictionary<string, SortedDictionary<string, Stat>> stats)
412 {
413 lock (RegisteredStats)
414 return RegisteredStats.TryGetValue(category, out stats);
415 }
416
417 /// <summary>
418 /// Get the same stat for each container in a given category.
419 /// </summary>
420 /// <returns>
421 /// The stats if there were any to fetch. Otherwise null.
422 /// </returns>
423 /// <param name='category'></param>
424 /// <param name='statShortName'></param>
425 public static List<Stat> GetStatsFromEachContainer(string category, string statShortName)
426 {
427 SortedDictionary<string, SortedDictionary<string, Stat>> categoryStats;
428
429 lock (RegisteredStats)
430 {
431 if (!RegisteredStats.TryGetValue(category, out categoryStats))
432 return null;
433
434 List<Stat> stats = null;
435
436 foreach (SortedDictionary<string, Stat> containerStats in categoryStats.Values)
437 {
438 if (containerStats.ContainsKey(statShortName))
439 {
440 if (stats == null)
441 stats = new List<Stat>();
442
443 stats.Add(containerStats[statShortName]);
444 }
445 }
446
447 return stats;
448 }
245 } 449 }
246 450
247 public static bool TryGetStat( 451 public static bool TryGetStatParents(
248 Stat stat, 452 Stat stat,
249 out SortedDictionary<string, SortedDictionary<string, Stat>> category, 453 out SortedDictionary<string, SortedDictionary<string, Stat>> category,
250 out SortedDictionary<string, Stat> container) 454 out SortedDictionary<string, Stat> container)