1 // Copyright 2001-2019 Crytek GmbH / Crytek Group. All rights reserved.
4 using System
.Collections
.Generic
;
5 using System
.Globalization
;
7 using System
.ServiceModel
;
8 using System
.Windows
.Forms
;
10 using Microsoft
.Win32
;
16 public static bool IsRunningOnWindows()
18 PlatformID pid
= Environment
.OSVersion
.Platform
;
21 case PlatformID
.Win32NT
:
22 case PlatformID
.Win32S
:
23 case PlatformID
.Win32Windows
:
24 case PlatformID
.WinCE
:
32 /// The main entry point for the application.
35 static void Main(string[] args
)
37 Application
.CurrentCulture
= new CultureInfo("en-US");
38 Application
.EnableVisualStyles();
39 Application
.SetCompatibleTextRenderingDefault(false);
42 InstallProtocolHandler();
46 if (args
.Length
== 1 && !args
[0].StartsWith("/"))
48 if (WCF
.CheckForExistingToolProcess(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];
118 buildid
+= " - Auto-testing Statistics - ";
119 platform
+= " - Auto-testing Statistics - ";
121 success
= UploadConfluenceData(uploadSettings
, logfilename
, groups
, platform
, buildid
, metricManifest
, uploadSummary
);
126 //If launching graphical front end, assume success here.
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
);
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
;
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);
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;
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();
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
;
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);
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;
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();
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();
354 xmlDoc
.LoadXml(xmlstring
);
355 XmlNode settings
= xmlDoc
.SelectSingleNode("/settings");
357 stream
= new StreamReader(metrics
);
358 xmlDoc
= new XmlDocument();
359 xmlstring
= stream
.ReadToEnd();
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);
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
)
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;
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);
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");
516 iconKey
.SetValue("", Application
.ExecutablePath
+ ",1");
520 RegistryKey shellKey
= statoscopeKey
.CreateSubKey("shell");
521 if (shellKey
!= null)
523 RegistryKey openKey
= shellKey
.CreateSubKey("open");
526 RegistryKey commandKey
= openKey
.CreateSubKey("command");
527 if (commandKey
!= null)
529 commandKey
.SetValue("", string.Format("\"{0}\" \"%1\"", Application
.ExecutablePath
));
537 statoscopeKey
.Close();
542 Console
.WriteLine("Exception while trying to install statoscope:// protocol handler to the registry: " + ex
.ToString());