aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Monitoring/StatsManager.cs
diff options
context:
space:
mode:
authorDavid Walter Seikel2016-11-03 21:44:39 +1000
committerDavid Walter Seikel2016-11-03 21:44:39 +1000
commit134f86e8d5c414409631b25b8c6f0ee45fbd8631 (patch)
tree216b89d3fb89acfb81be1e440c25c41ab09fa96d /OpenSim/Framework/Monitoring/StatsManager.cs
parentMore changing to production grid. Double oops. (diff)
downloadopensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.zip
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.gz
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.bz2
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.xz
Initial update to OpenSim 0.8.2.1 source code.
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/Monitoring/StatsManager.cs403
1 files changed, 328 insertions, 75 deletions
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs
index 0762b01..3136ee8 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";
@@ -51,31 +56,43 @@ namespace OpenSim.Framework.Monitoring
51 /// <remarks> 56 /// <remarks>
52 /// Do not add or remove directly from this dictionary. 57 /// Do not add or remove directly from this dictionary.
53 /// </remarks> 58 /// </remarks>
54 public static Dictionary<string, Dictionary<string, Dictionary<string, Stat>>> RegisteredStats 59 public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>> RegisteredStats
55 = new Dictionary<string, Dictionary<string, Dictionary<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 {
67 console.Commands.AddCommand( 72 console.Commands.AddCommand(
68 "General", 73 "General",
69 false, 74 false,
70 "show stats", 75 "stats show",
71 "show stats [list|all|<category>]", 76 "stats show [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 console.Commands.AddCommand(
88 "General",
89 false,
90 "show stats",
91 "show stats [list|all|(<category>[.<container>])+",
92 "Alias for 'stats show' command",
93 HandleShowStatsCommand);
94
95 StatsLogger.RegisterConsoleCommands(console);
79 } 96 }
80 97
81 public static void HandleShowStatsCommand(string module, string[] cmd) 98 public static void HandleShowStatsCommand(string module, string[] cmd)
@@ -84,105 +101,286 @@ namespace OpenSim.Framework.Monitoring
84 101
85 if (cmd.Length > 2) 102 if (cmd.Length > 2)
86 { 103 {
87 var categoryName = cmd[2]; 104 foreach (string name in cmd.Skip(2))
88
89 if (categoryName == AllSubCommand)
90 { 105 {
91 foreach (var category in RegisteredStats.Values) 106 string[] components = name.Split('.');
107
108 string categoryName = components[0];
109 string containerName = components.Length > 1 ? components[1] : null;
110 string statName = components.Length > 2 ? components[2] : null;
111
112 if (categoryName == AllSubCommand)
92 { 113 {
93 OutputCategoryStatsToConsole(con, category); 114 OutputAllStatsToConsole(con);
94 } 115 }
95 } 116 else if (categoryName == ListSubCommand)
96 else if (categoryName == ListSubCommand)
97 {
98 con.Output("Statistic categories available are:");
99 foreach (string category in RegisteredStats.Keys)
100 con.OutputFormat(" {0}", category);
101 }
102 else
103 {
104 Dictionary<string, Dictionary<string, Stat>> category;
105 if (!RegisteredStats.TryGetValue(categoryName, out category))
106 { 117 {
107 con.OutputFormat("No such category as {0}", categoryName); 118 con.Output("Statistic categories available are:");
119 foreach (string category in RegisteredStats.Keys)
120 con.OutputFormat(" {0}", category);
108 } 121 }
109 else 122 else
110 { 123 {
111 OutputCategoryStatsToConsole(con, category); 124 SortedDictionary<string, SortedDictionary<string, Stat>> category;
125 if (!RegisteredStats.TryGetValue(categoryName, out category))
126 {
127 con.OutputFormat("No such category as {0}", categoryName);
128 }
129 else
130 {
131 if (String.IsNullOrEmpty(containerName))
132 {
133 OutputCategoryStatsToConsole(con, category);
134 }
135 else
136 {
137 SortedDictionary<string, Stat> container;
138 if (category.TryGetValue(containerName, out container))
139 {
140 if (String.IsNullOrEmpty(statName))
141 {
142 OutputContainerStatsToConsole(con, container);
143 }
144 else
145 {
146 Stat stat;
147 if (container.TryGetValue(statName, out stat))
148 {
149 OutputStatToConsole(con, stat);
150 }
151 else
152 {
153 con.OutputFormat(
154 "No such stat {0} in {1}.{2}", statName, categoryName, containerName);
155 }
156 }
157 }
158 else
159 {
160 con.OutputFormat("No such container {0} in category {1}", containerName, categoryName);
161 }
162 }
163 }
112 } 164 }
113 } 165 }
114 } 166 }
115 else 167 else
116 { 168 {
117 // Legacy 169 // Legacy
118 con.Output(SimExtraStats.Report()); 170 if (SimExtraStats != null)
171 con.Output(SimExtraStats.Report());
172 else
173 OutputAllStatsToConsole(con);
119 } 174 }
120 } 175 }
121 176
122 private static void OutputCategoryStatsToConsole( 177 public static List<string> GetAllStatsReports()
123 ICommandConsole con, Dictionary<string, Dictionary<string, Stat>> category) 178 {
179 List<string> reports = new List<string>();
180
181 foreach (var category in RegisteredStats.Values)
182 reports.AddRange(GetCategoryStatsReports(category));
183
184 return reports;
185 }
186
187 private static void OutputAllStatsToConsole(ICommandConsole con)
124 { 188 {
189 foreach (string report in GetAllStatsReports())
190 con.Output(report);
191 }
192
193 private static List<string> GetCategoryStatsReports(
194 SortedDictionary<string, SortedDictionary<string, Stat>> category)
195 {
196 List<string> reports = new List<string>();
197
125 foreach (var container in category.Values) 198 foreach (var container in category.Values)
199 reports.AddRange(GetContainerStatsReports(container));
200
201 return reports;
202 }
203
204 private static void OutputCategoryStatsToConsole(
205 ICommandConsole con, SortedDictionary<string, SortedDictionary<string, Stat>> category)
206 {
207 foreach (string report in GetCategoryStatsReports(category))
208 con.Output(report);
209 }
210
211 private static List<string> GetContainerStatsReports(SortedDictionary<string, Stat> container)
212 {
213 List<string> reports = new List<string>();
214
215 foreach (Stat stat in container.Values)
216 reports.Add(stat.ToConsoleString());
217
218 return reports;
219 }
220
221 private static void OutputContainerStatsToConsole(
222 ICommandConsole con, SortedDictionary<string, Stat> container)
223 {
224 foreach (string report in GetContainerStatsReports(container))
225 con.Output(report);
226 }
227
228 private static void OutputStatToConsole(ICommandConsole con, Stat stat)
229 {
230 con.Output(stat.ToConsoleString());
231 }
232
233 // Creates an OSDMap of the format:
234 // { categoryName: {
235 // containerName: {
236 // statName: {
237 // "Name": name,
238 // "ShortName": shortName,
239 // ...
240 // },
241 // statName: {
242 // "Name": name,
243 // "ShortName": shortName,
244 // ...
245 // },
246 // ...
247 // },
248 // containerName: {
249 // ...
250 // },
251 // ...
252 // },
253 // categoryName: {
254 // ...
255 // },
256 // ...
257 // }
258 // The passed in parameters will filter the categories, containers and stats returned. If any of the
259 // parameters are either EmptyOrNull or the AllSubCommand value, all of that type will be returned.
260 // Case matters.
261 public static OSDMap GetStatsAsOSDMap(string pCategoryName, string pContainerName, string pStatName)
262 {
263 OSDMap map = new OSDMap();
264
265 foreach (string catName in RegisteredStats.Keys)
126 { 266 {
127 foreach (Stat stat in container.Values) 267 // Do this category if null spec, "all" subcommand or category name matches passed parameter.
268 // Skip category if none of the above.
269 if (!(String.IsNullOrEmpty(pCategoryName) || pCategoryName == AllSubCommand || pCategoryName == catName))
270 continue;
271
272 OSDMap contMap = new OSDMap();
273 foreach (string contName in RegisteredStats[catName].Keys)
128 { 274 {
129 con.Output(stat.ToConsoleString()); 275 if (!(string.IsNullOrEmpty(pContainerName) || pContainerName == AllSubCommand || pContainerName == contName))
276 continue;
277
278 OSDMap statMap = new OSDMap();
279
280 SortedDictionary<string, Stat> theStats = RegisteredStats[catName][contName];
281 foreach (string statName in theStats.Keys)
282 {
283 if (!(String.IsNullOrEmpty(pStatName) || pStatName == AllSubCommand || pStatName == statName))
284 continue;
285
286 statMap.Add(statName, theStats[statName].ToOSDMap());
287 }
288
289 contMap.Add(contName, statMap);
130 } 290 }
291 map.Add(catName, contMap);
131 } 292 }
293
294 return map;
132 } 295 }
133 296
134 /// <summary> 297 public static Hashtable HandleStatsRequest(Hashtable request)
135 /// Start collecting statistics related to assets.
136 /// Should only be called once.
137 /// </summary>
138 public static AssetStatsCollector StartCollectingAssetStats()
139 { 298 {
140 assetStats = new AssetStatsCollector(); 299 Hashtable responsedata = new Hashtable();
300// string regpath = request["uri"].ToString();
301 int response_code = 200;
302 string contenttype = "text/json";
141 303
142 return assetStats; 304 string pCategoryName = StatsManager.AllSubCommand;
143 } 305 string pContainerName = StatsManager.AllSubCommand;
306 string pStatName = StatsManager.AllSubCommand;
144 307
145 /// <summary> 308 if (request.ContainsKey("cat")) pCategoryName = request["cat"].ToString();
146 /// Start collecting statistics related to users. 309 if (request.ContainsKey("cont")) pContainerName = request["cat"].ToString();
147 /// Should only be called once. 310 if (request.ContainsKey("stat")) pStatName = request["stat"].ToString();
148 /// </summary>
149 public static UserStatsCollector StartCollectingUserStats()
150 {
151 userStats = new UserStatsCollector();
152 311
153 return userStats; 312 string strOut = StatsManager.GetStatsAsOSDMap(pCategoryName, pContainerName, pStatName).ToString();
313
314 // If requestor wants it as a callback function, build response as a function rather than just the JSON string.
315 if (request.ContainsKey("callback"))
316 {
317 strOut = request["callback"].ToString() + "(" + strOut + ");";
318 }
319
320 // m_log.DebugFormat("{0} StatFetch: uri={1}, cat={2}, cont={3}, stat={4}, resp={5}",
321 // LogHeader, regpath, pCategoryName, pContainerName, pStatName, strOut);
322
323 responsedata["int_response_code"] = response_code;
324 responsedata["content_type"] = contenttype;
325 responsedata["keepalive"] = false;
326 responsedata["str_response_string"] = strOut;
327 responsedata["access_control_allow_origin"] = "*";
328
329 return responsedata;
154 } 330 }
155 331
332// /// <summary>
333// /// Start collecting statistics related to assets.
334// /// Should only be called once.
335// /// </summary>
336// public static AssetStatsCollector StartCollectingAssetStats()
337// {
338// assetStats = new AssetStatsCollector();
339//
340// return assetStats;
341// }
342//
343// /// <summary>
344// /// Start collecting statistics related to users.
345// /// Should only be called once.
346// /// </summary>
347// public static UserStatsCollector StartCollectingUserStats()
348// {
349// userStats = new UserStatsCollector();
350//
351// return userStats;
352// }
353
156 /// <summary> 354 /// <summary>
157 /// Registers a statistic. 355 /// Register a statistic.
158 /// </summary> 356 /// </summary>
159 /// <param name='stat'></param> 357 /// <param name='stat'></param>
160 /// <returns></returns> 358 /// <returns></returns>
161 public static bool RegisterStat(Stat stat) 359 public static bool RegisterStat(Stat stat)
162 { 360 {
163 Dictionary<string, Dictionary<string, Stat>> category = null, newCategory; 361 SortedDictionary<string, SortedDictionary<string, Stat>> category = null, newCategory;
164 Dictionary<string, Stat> container = null, newContainer; 362 SortedDictionary<string, Stat> container = null, newContainer;
165 363
166 lock (RegisteredStats) 364 lock (RegisteredStats)
167 { 365 {
168 // Stat name is not unique across category/container/shortname key. 366 // Stat name is not unique across category/container/shortname key.
169 // XXX: For now just return false. This is to avoid problems in regression tests where all tests 367 // XXX: For now just return false. This is to avoid problems in regression tests where all tests
170 // in a class are run in the same instance of the VM. 368 // in a class are run in the same instance of the VM.
171 if (TryGetStat(stat, out category, out container)) 369 if (TryGetStatParents(stat, out category, out container))
172 return false; 370 return false;
173 371
174 // We take a copy-on-write approach here of replacing dictionaries when keys are added or removed. 372 // We take a copy-on-write approach here of replacing dictionaries when keys are added or removed.
175 // This means that we don't need to lock or copy them on iteration, which will be a much more 373 // This means that we don't need to lock or copy them on iteration, which will be a much more
176 // common operation after startup. 374 // common operation after startup.
177 if (container != null) 375 if (container != null)
178 newContainer = new Dictionary<string, Stat>(container); 376 newContainer = new SortedDictionary<string, Stat>(container);
179 else 377 else
180 newContainer = new Dictionary<string, Stat>(); 378 newContainer = new SortedDictionary<string, Stat>();
181 379
182 if (category != null) 380 if (category != null)
183 newCategory = new Dictionary<string, Dictionary<string, Stat>>(category); 381 newCategory = new SortedDictionary<string, SortedDictionary<string, Stat>>(category);
184 else 382 else
185 newCategory = new Dictionary<string, Dictionary<string, Stat>>(); 383 newCategory = new SortedDictionary<string, SortedDictionary<string, Stat>>();
186 384
187 newContainer[stat.ShortName] = stat; 385 newContainer[stat.ShortName] = stat;
188 newCategory[stat.Container] = newContainer; 386 newCategory[stat.Container] = newContainer;
@@ -196,21 +394,21 @@ namespace OpenSim.Framework.Monitoring
196 /// Deregister a statistic 394 /// Deregister a statistic
197 /// </summary>> 395 /// </summary>>
198 /// <param name='stat'></param> 396 /// <param name='stat'></param>
199 /// <returns></returns 397 /// <returns></returns>
200 public static bool DeregisterStat(Stat stat) 398 public static bool DeregisterStat(Stat stat)
201 { 399 {
202 Dictionary<string, Dictionary<string, Stat>> category = null, newCategory; 400 SortedDictionary<string, SortedDictionary<string, Stat>> category = null, newCategory;
203 Dictionary<string, Stat> container = null, newContainer; 401 SortedDictionary<string, Stat> container = null, newContainer;
204 402
205 lock (RegisteredStats) 403 lock (RegisteredStats)
206 { 404 {
207 if (!TryGetStat(stat, out category, out container)) 405 if (!TryGetStatParents(stat, out category, out container))
208 return false; 406 return false;
209 407
210 newContainer = new Dictionary<string, Stat>(container); 408 newContainer = new SortedDictionary<string, Stat>(container);
211 newContainer.Remove(stat.ShortName); 409 newContainer.Remove(stat.ShortName);
212 410
213 newCategory = new Dictionary<string, Dictionary<string, Stat>>(category); 411 newCategory = new SortedDictionary<string, SortedDictionary<string, Stat>>(category);
214 newCategory.Remove(stat.Container); 412 newCategory.Remove(stat.Container);
215 413
216 newCategory[stat.Container] = newContainer; 414 newCategory[stat.Container] = newContainer;
@@ -220,15 +418,70 @@ namespace OpenSim.Framework.Monitoring
220 } 418 }
221 } 419 }
222 420
223 public static bool TryGetStats(string category, out Dictionary<string, Dictionary<string, Stat>> stats) 421 public static bool TryGetStat(string category, string container, string statShortName, out Stat stat)
224 { 422 {
225 return RegisteredStats.TryGetValue(category, out stats); 423 stat = null;
424 SortedDictionary<string, SortedDictionary<string, Stat>> categoryStats;
425
426 lock (RegisteredStats)
427 {
428 if (!TryGetStatsForCategory(category, out categoryStats))
429 return false;
430
431 SortedDictionary<string, Stat> containerStats;
432
433 if (!categoryStats.TryGetValue(container, out containerStats))
434 return false;
435
436 return containerStats.TryGetValue(statShortName, out stat);
437 }
438 }
439
440 public static bool TryGetStatsForCategory(
441 string category, out SortedDictionary<string, SortedDictionary<string, Stat>> stats)
442 {
443 lock (RegisteredStats)
444 return RegisteredStats.TryGetValue(category, out stats);
445 }
446
447 /// <summary>
448 /// Get the same stat for each container in a given category.
449 /// </summary>
450 /// <returns>
451 /// The stats if there were any to fetch. Otherwise null.
452 /// </returns>
453 /// <param name='category'></param>
454 /// <param name='statShortName'></param>
455 public static List<Stat> GetStatsFromEachContainer(string category, string statShortName)
456 {
457 SortedDictionary<string, SortedDictionary<string, Stat>> categoryStats;
458
459 lock (RegisteredStats)
460 {
461 if (!RegisteredStats.TryGetValue(category, out categoryStats))
462 return null;
463
464 List<Stat> stats = null;
465
466 foreach (SortedDictionary<string, Stat> containerStats in categoryStats.Values)
467 {
468 if (containerStats.ContainsKey(statShortName))
469 {
470 if (stats == null)
471 stats = new List<Stat>();
472
473 stats.Add(containerStats[statShortName]);
474 }
475 }
476
477 return stats;
478 }
226 } 479 }
227 480
228 public static bool TryGetStat( 481 public static bool TryGetStatParents(
229 Stat stat, 482 Stat stat,
230 out Dictionary<string, Dictionary<string, Stat>> category, 483 out SortedDictionary<string, SortedDictionary<string, Stat>> category,
231 out Dictionary<string, Stat> container) 484 out SortedDictionary<string, Stat> container)
232 { 485 {
233 category = null; 486 category = null;
234 container = null; 487 container = null;
@@ -252,9 +505,9 @@ namespace OpenSim.Framework.Monitoring
252 { 505 {
253 lock (RegisteredStats) 506 lock (RegisteredStats)
254 { 507 {
255 foreach (Dictionary<string, Dictionary<string, Stat>> category in RegisteredStats.Values) 508 foreach (SortedDictionary<string, SortedDictionary<string, Stat>> category in RegisteredStats.Values)
256 { 509 {
257 foreach (Dictionary<string, Stat> container in category.Values) 510 foreach (SortedDictionary<string, Stat> container in category.Values)
258 { 511 {
259 foreach (Stat stat in container.Values) 512 foreach (Stat stat in container.Values)
260 { 513 {