!B (Sandbox) (CE-21795) Importing models with multisubmaterials via fbx switches...
[CRYENGINE.git] / Code / Tools / Statoscope / Statoscope / Program.cs
blob8f39b4bbf2e609c16da34b77b0254e92a5ebce66
1 // Copyright 2001-2019 Crytek GmbH / Crytek Group. All rights reserved.
3 using System;
4 using System.Collections.Generic;
5 using System.Globalization;
6 using System.IO;
7 using System.ServiceModel;
8 using System.Windows.Forms;
9 using System.Xml;
10 using Microsoft.Win32;
12 namespace Statoscope
14 static class Program
16 public static bool IsRunningOnWindows()
18 PlatformID pid = Environment.OSVersion.Platform;
19 switch (pid)
21 case PlatformID.Win32NT:
22 case PlatformID.Win32S:
23 case PlatformID.Win32Windows:
24 case PlatformID.WinCE:
25 return true;
26 default:
27 return false;
31 /// <summary>
32 /// The main entry point for the application.
33 /// </summary>
34 [STAThread]
35 static void Main(string[] args)
37 Application.CurrentCulture = new CultureInfo("en-US");
38 Application.EnableVisualStyles();
39 Application.SetCompatibleTextRenderingDefault(false);
40 bool success = false;
42 InstallProtocolHandler();
44 try
46 if (args.Length == 1 && !args[0].StartsWith("/"))
48 if (WCF.CheckForExistingToolProcess(args[0]))
49 Environment.Exit(0);
51 success = true;
52 RunForm(args[0]);
54 else if (args.Length > 0)
56 string logfilename = string.Empty;
57 string uploadSettings = string.Empty;
58 string platform = string.Empty;
59 string buildid = string.Empty;
60 string metricManifest = string.Empty;
61 string buildInfo = string.Empty;
62 bool uploadSummary = true;
63 string[] groups = null;
65 for (int idx = 0; idx < args.Length; idx++)
67 if (args[idx].StartsWith("/dumplog"))
69 logfilename = args[idx + 1];
72 if (args[idx].StartsWith("/statgroups"))
74 groups = args[idx + 1].Split(',');
77 if (args[idx].StartsWith("/autoupload"))
79 uploadSettings = args[idx + 1];
82 if (args[idx].StartsWith("/metrics"))
84 metricManifest = args[idx + 1];
87 if (args[idx].StartsWith("/nosummary"))
89 uploadSummary = false;
92 if (args[idx].StartsWith("/buildinfo"))
94 buildInfo = args[idx + 1];
98 if (logfilename != string.Empty)
99 success = WriteXMLForLog(logfilename, groups);
101 if (uploadSettings != string.Empty && success)
103 if (buildInfo != string.Empty)
105 StreamReader stream = new StreamReader(buildInfo);
106 while (!stream.EndOfStream)
108 string line = stream.ReadLine();
109 if (line.StartsWith("BuildName="))
111 buildid = line.Substring(line.IndexOf('=') + 1);
112 string[] tokens = buildid.Split('(')[0].Split('_');
113 platform = tokens[tokens.Length - 2];
116 stream.Close();
118 buildid += " - Auto-testing Statistics - ";
119 platform += " - Auto-testing Statistics - ";
121 success = UploadConfluenceData(uploadSettings, logfilename, groups, platform, buildid, metricManifest, uploadSummary);
124 else
126 //If launching graphical front end, assume success here.
127 success = true;
128 RunForm("");
131 catch (System.Exception ex)
133 // Use this as a last ditch attempt to catch failures without the crash dialog being displayed
134 Console.WriteLine("Unhandled exception thrown! {0}: {1}", ex.Message, ex.StackTrace);
137 Environment.Exit(success ? 0 : 1);
140 static void RunForm(string logFilename)
142 StatoscopeForm ssForm = new StatoscopeForm(logFilename);
143 WCF.CreateServiceHost(ssForm);
144 Application.Run(ssForm);
147 static bool WriteXMLForLog(string logFilename, string[] groups)
149 FileLogProcessor logProcessor = new FileLogProcessor(logFilename);
150 LogData logData = logProcessor.ProcessLog();
152 XmlWriterSettings settings = new XmlWriterSettings();
153 settings.Indent = true;
154 settings.IndentChars = (" ");
156 char[] delims = { '.' };
157 string[] fileNameElements = logFilename.Split(delims);
158 if (fileNameElements.Length < 2)
160 Console.WriteLine("Input file name not parseable {0} : Canceling XML Write", logFilename);
161 return false;
164 string outputFile = fileNameElements[0] + ".xml";
165 Console.WriteLine("Writing XML output: {0}", outputFile);
167 using (XmlWriter writer = XmlWriter.Create(outputFile, settings))
169 writer.WriteStartElement("testsuites");
170 CultureInfo decimalCulture = new CultureInfo("en-US");
172 UserMarkerLocation currentStartMarker = null;
173 writer.WriteStartElement("testsuite");
174 writer.WriteAttributeString("name", "BasicPerformance");
176 foreach (FrameRecord fr in logData.FrameRecords)
177 foreach (UserMarkerLocation markerLocation in fr.UserMarkers)
179 if (markerLocation.m_name.Split(' ')[0].EndsWith("_start"))
181 if (currentStartMarker != null)
183 //Warn about unmatched start marker
184 Console.WriteLine("Warning: Performance Marker End Not Found For {0} at frame index: {1} : Skipping", currentStartMarker.m_name, currentStartMarker.m_fr.Index);
186 currentStartMarker = markerLocation;
187 continue;
190 if (markerLocation.m_name.EndsWith("_end"))
192 if (currentStartMarker == null)
194 //Warn and skip if we didn't have a start marker we were looking for
195 Console.WriteLine("Warning: Performance Marker End Found With No Matching Start For {0} at frame index: {1} : Skipping", currentStartMarker != null ? currentStartMarker.m_name : "invalid start marker", currentStartMarker != null ? currentStartMarker.m_fr.Index : 0);
196 continue;
199 string markerNameStart = currentStartMarker.m_name.Replace("_start", "").Split(' ')[0];
200 string markerExportName = currentStartMarker.m_name.Replace("_start", "");
201 string markerNameEnd = markerLocation.m_name.Replace("_end", "");
203 if (markerNameStart != markerNameEnd)
205 Console.WriteLine("Warning: Performance Marker End: {0} Does not Match Start Marker {1}: Skipping", markerNameStart, markerNameEnd);
206 currentStartMarker = null;
207 continue;
210 int startIdx = currentStartMarker.m_fr.Index;
211 int endIdx = markerLocation.m_fr.Index;
212 currentStartMarker = null;
214 writer.WriteStartElement("phase");
215 writer.WriteAttributeString("name", markerExportName);
216 writer.WriteAttributeString("duration", (logData.FrameRecords[endIdx].FrameTimeInS - logData.FrameRecords[startIdx].FrameTimeInS).ToString(decimalCulture));
218 float minFrameTime, maxFrameTime, avgFrameTime;
219 logData.GetFrameTimeData(startIdx, endIdx, out minFrameTime, out maxFrameTime, out avgFrameTime);
221 writer.WriteStartElement("metrics");
222 writer.WriteAttributeString("name", "frameTimes");
224 writer.WriteStartElement("metric");
225 writer.WriteAttributeString("name", "min");
226 writer.WriteAttributeString("value", minFrameTime.ToString(decimalCulture));
227 writer.WriteEndElement();
229 writer.WriteStartElement("metric");
230 writer.WriteAttributeString("name", "max");
231 writer.WriteAttributeString("value", maxFrameTime.ToString(decimalCulture));
232 writer.WriteEndElement();
234 writer.WriteStartElement("metric");
235 writer.WriteAttributeString("name", "avg");
236 writer.WriteAttributeString("value", avgFrameTime.ToString(decimalCulture));
237 writer.WriteEndElement();
239 writer.WriteEndElement();
241 writer.WriteEndElement();
244 //End testsuite block
245 writer.WriteEndElement();
247 if (groups != null)
249 currentStartMarker = null;
250 writer.WriteStartElement("testsuite");
251 writer.WriteAttributeString("name", "GroupStatistics");
253 foreach (FrameRecord fr in logData.FrameRecords)
254 foreach (UserMarkerLocation markerLocation in fr.UserMarkers)
256 if (markerLocation.m_name.Split(' ')[0].EndsWith("_start"))
258 if (currentStartMarker != null)
260 //Warn about unmatched start marker
261 Console.WriteLine("Warning: Performance Marker End Not Found For {0} at frame index: {1} : Skipping", currentStartMarker.m_name, currentStartMarker.m_fr.Index);
263 currentStartMarker = markerLocation;
264 continue;
267 if (markerLocation.m_name.EndsWith("_end"))
269 if (currentStartMarker == null)
271 //Warn and skip if we didn't have a start marker we were looking for
272 Console.WriteLine("Warning: Performance Marker End Found With No Matching Start For {0} at frame index: {1} : Skipping", currentStartMarker != null ? currentStartMarker.m_name : "invalid start marker", currentStartMarker != null ? currentStartMarker.m_fr.Index : 0);
273 continue;
276 string markerNameStart = currentStartMarker.m_name.Replace("_start", "").Split(' ')[0];
277 string markerExportName = currentStartMarker.m_name.Replace("_start", "");
278 string markerNameEnd = markerLocation.m_name.Replace("_end", "");
280 if (markerNameStart != markerNameEnd)
282 Console.WriteLine("Warning: Performance Marker End: {0} Does not Match Start Marker {1}: Skipping", markerNameStart, markerNameEnd);
283 currentStartMarker = null;
284 continue;
287 int startIdx = currentStartMarker.m_fr.Index;
288 int endIdx = markerLocation.m_fr.Index;
289 currentStartMarker = null;
291 writer.WriteStartElement("phase");
292 writer.WriteAttributeString("name", markerExportName);
293 writer.WriteAttributeString("duration", (logData.FrameRecords[endIdx].FrameTimeInS - logData.FrameRecords[startIdx].FrameTimeInS).ToString(decimalCulture));
295 GroupsStats stats = new GroupsStats();
296 logData.GetFrameGroupData(startIdx, endIdx, groups, stats);
297 foreach (string group in stats.m_groupStats.Keys)
299 GroupItemStats groupsStats = stats.GetGroupItemsStats(group);
300 foreach (string item in groupsStats.m_groupItemStats.Keys)
302 Stats itemStats = groupsStats.GetItemStats(item);
303 writer.WriteStartElement("metrics");
304 writer.WriteAttributeString("name", item);
306 writer.WriteStartElement("metric");
307 writer.WriteAttributeString("name", "min");
308 writer.WriteAttributeString("value", itemStats.m_min.ToString(decimalCulture));
309 writer.WriteEndElement();
311 writer.WriteStartElement("metric");
312 writer.WriteAttributeString("name", "max");
313 writer.WriteAttributeString("value", itemStats.m_max.ToString(decimalCulture));
314 writer.WriteEndElement();
316 writer.WriteStartElement("metric");
317 writer.WriteAttributeString("name", "avg");
318 writer.WriteAttributeString("value", itemStats.m_avg.ToString(decimalCulture));
319 writer.WriteEndElement();
321 writer.WriteEndElement();
325 writer.WriteEndElement();
328 //End testsuite block
329 writer.WriteEndElement();
332 //End testsuites block
333 writer.WriteEndElement();
334 writer.Flush();
336 return true;
340 static bool UploadConfluenceData(string settingsfile, string logfile, string[] groups, string platform, string buildid, string metrics, bool uploadSummary)
342 string username = string.Empty;
343 string password = string.Empty;
344 string space = string.Empty;
345 string parent = string.Empty;
346 string pagepostfix = string.Empty;
350 StreamReader stream = new StreamReader(settingsfile);
351 XmlDocument xmlDoc = new XmlDocument();
352 String xmlstring = stream.ReadToEnd();
353 stream.Close();
354 xmlDoc.LoadXml(xmlstring);
355 XmlNode settings = xmlDoc.SelectSingleNode("/settings");
357 stream = new StreamReader(metrics);
358 xmlDoc = new XmlDocument();
359 xmlstring = stream.ReadToEnd();
360 stream.Close();
361 xmlDoc.LoadXml(xmlstring);
362 XmlNodeList metricNodes = xmlDoc.SelectNodes("//metrics");
364 foreach (XmlAttribute attrib in settings.Attributes)
366 if (attrib.Name == "username")
368 username = attrib.Value;
371 if (attrib.Name == "password")
373 password = attrib.Value;
376 if (attrib.Name == "space")
378 space = attrib.Value;
381 if (attrib.Name == "parent")
383 parent = attrib.Value;
386 if (attrib.Name == "pageuniqueid")
388 pagepostfix = attrib.Value;
392 FileLogProcessor logProcessor = new FileLogProcessor(logfile);
393 LogData logData = logProcessor.ProcessLog();
395 if (platform == string.Empty)
397 platform = logData.BuildInfo.PlatformString + " - Auto-testing Statistics - ";
400 if (buildid == string.Empty)
402 buildid = logData.BuildInfo.BuildNumberString + " - Auto-testing Statistics - ";
405 platform += pagepostfix;
406 buildid += pagepostfix;
408 ConfluenceService confluence = new ConfluenceService(logData);
409 if (confluence.TryLogin(true, username, password))
411 UploadStatsPages(confluence, logData, groups, space, parent, platform, buildid, metricNodes, uploadSummary, logfile);
414 catch (System.Exception ex)
416 Console.WriteLine("Error: " + ex.Message + System.Environment.NewLine + "Stack: " + ex.StackTrace + System.Environment.NewLine);
417 System.Environment.Exit(2);
419 return true;
422 static void UploadStatsPages(ConfluenceService confluence, LogData logData, string[] groups, string spaceName, string rootPageName, string platformPageName, string buildPageName, XmlNodeList metrics, bool uploadSummary, string logfile)
426 List<ConfluenceSOAP.RemoteSpaceSummary> spaces = confluence.GetSpaces();
428 bool spaceExists = false;
429 bool rootPageExists = false;
430 bool platformPageExists = false;
431 bool buildPageExists = false;
433 foreach (ConfluenceSOAP.RemoteSpaceSummary space in spaces)
435 if (space.key == spaceName)
437 spaceExists = true;
438 break;
442 if (!spaceExists)
444 confluence.CreateSpace(spaceName);
447 List<ConfluenceSOAP.RemotePageSummary> pages = confluence.GetPages(spaceName);
449 foreach (ConfluenceSOAP.RemotePageSummary page in pages)
451 if (page.title == rootPageName)
453 rootPageExists = true;
456 if (page.title == platformPageName)
458 platformPageExists = true;
461 if (page.title == buildPageName)
463 buildPageExists = true;
467 if (!rootPageExists)
469 confluence.CreatePage(rootPageName, spaceName);
472 if (!platformPageExists)
474 confluence.CreatePage(platformPageName, rootPageName, spaceName);
477 if (!buildPageExists)
479 confluence.CreatePage(buildPageName, platformPageName, spaceName);
482 string timeDateString = DateTime.Now.ToString("dd/MM/yy hh:mm:ss \\(\\U\\T\\Cz\\)");
484 ConfluenceService.PageContentMetaData pageContentMD = new ConfluenceService.PageContentMetaData(timeDateString, logData.Name, logData.BuildInfo.PlatformString, logData.BuildInfo.BuildNumberString, "", confluence.m_username, "automated build system", false);
485 ConfluenceService.PageMetaData pageMetaData = new ConfluenceService.PageMetaData(spaceName, buildPageName, platformPageName, pageContentMD);
486 confluence.UploadStatsDataPage(pageMetaData, logData, groups, metrics, uploadSummary);
488 foreach (FrameRecordRange frr in logData.LevelRanges)
490 LogData levelLogData = new LogData(logData, frr);
491 pageContentMD.m_levelName = levelLogData.Name;
492 ConfluenceService.PageMetaData levelPageMD = new ConfluenceService.PageMetaData(spaceName, levelLogData.Name + " - " + buildPageName, buildPageName, pageContentMD);
493 confluence.UploadStatsDataPage(levelPageMD, levelLogData, groups, metrics, true);
496 catch (Exception ex)
498 Console.WriteLine("Something went wrong! :(\n\n" + ex.ToString() + Environment.NewLine + "Stack trace: " + ex.StackTrace);
499 System.Environment.Exit(3);
503 static void InstallProtocolHandler()
507 RegistryKey statoscopeKey = Registry.ClassesRoot.CreateSubKey("statoscope");
508 if (statoscopeKey != null)
510 statoscopeKey.SetValue("", "URL:Statoscope Protocol");
511 statoscopeKey.SetValue("URL Protocol", "");
513 RegistryKey iconKey = statoscopeKey.CreateSubKey("DefaultIcon");
514 if (iconKey != null)
516 iconKey.SetValue("", Application.ExecutablePath + ",1");
517 iconKey.Close();
520 RegistryKey shellKey = statoscopeKey.CreateSubKey("shell");
521 if (shellKey != null)
523 RegistryKey openKey = shellKey.CreateSubKey("open");
524 if (openKey != null)
526 RegistryKey commandKey = openKey.CreateSubKey("command");
527 if (commandKey != null)
529 commandKey.SetValue("", string.Format("\"{0}\" \"%1\"", Application.ExecutablePath));
530 commandKey.Close();
532 openKey.Close();
534 shellKey.Close();
537 statoscopeKey.Close();
540 catch (Exception ex)
542 Console.WriteLine("Exception while trying to install statoscope:// protocol handler to the registry: " + ex.ToString());