// TARGET:msedge.exe -inPrivate --force-renderer-accessibility "https://silver.urih.com/" -> Use this for edge! // START_IN: using LoginPI.Engine.ScriptBase; using System; using System.Linq; using System.IO; using System.Diagnostics; using System.Text.RegularExpressions; using System.Collections.Generic; using System.Text; using System.Globalization; using LoginPI.Engine.ScriptBase.Components; /// /* chrome.exe -incognito --force-renderer-accessibility "https://silver.urih.com/" -> Use this for chrome! msedge.exe -inPrivate --force-renderer-accessibility "https://silver.urih.com/" -> Use this for edge! */ /// public class Silverbench : ScriptBase { // Variables for PowerShell script string timeOffset = "0:00"; // Time offset in hours:minutes (e.g., "-7:00" for PST, "+7:00" or "7:00" for UTC+7). The Login Enterprise API only accepts Zulu ISO 8601 timestamps, so this can be used to adjust the timestamps to the correct time zone. string configurationAccessToken = ""; // Your configuration access token here. To create one log into the Login Enterprise web interface -> External notifications -> Public API -> New system access token -> provide a name for the token -> select Configuration from the Access-level drop-down -> Save -> in the new popup copy out the token and put here in this configurationAccessToken variable. Ensure to store the token elsewhere securely. string baseUrl = "https://"; // Your base Login Enterprise URL here including the ending slash. For example: https://myLoginEnterprise.myDomain.com/ string environmentId = ""; // Your environment key/ID here. To get an environment ID to put here: log into the Login Enterprise web interface -> Environments -> Open the Environment to use -> at the end of the address bar of the browser find the environment unique ID, for example: 3221ce29-06ba-46a2-8c8b-da99dea341c4. Or create a new Environment in the Environments page -> Add environment -> fill out needed information in this page (but only Name is needed) -> Save -> the unique Environment ID will be at the end of the address bar string apiEndpoint = "/publicApi/v7-preview/platform-metrics"; // API Endpoint for Platform Metrics string tempScriptFile; // Initializing the path we'll write the powershell script to string payloadFilePath; // Initializing the path we'll write the payload to string tempResultsDir; List BenchmarkDataList = new List(); // Initializing a list of Lists string computerName; // Initializing a string to store computername for platform metrics attribution string processName; // Initializing a string to store the browser for platform metrics atttribution int standardTimeout = 30; string silverBenchScore; // Initializing a string to store the SilverBench Score double doubleSilverBenchScore; // Initializing a string to store the SilverBench Score, as type `double` int waitForSilverbenchToComplete = 120; // Specify how long to wait for SilverBench to complete bool chrome; bool edge; void Execute() { computerName = GetEnvironmentVariable("COMPUTERNAME"); string temp = GetEnvironmentVariable("TEMP"); string tempLoginPI = Path.Combine(temp, "LoginPI"); tempResultsDir = Path.Combine(tempLoginPI, "Results"); if (!DirectoryExists(tempResultsDir)) { Directory.CreateDirectory(tempResultsDir); } else { Log("Directory already existed..."); } payloadFilePath = Path.Combine(tempResultsDir, "payload.json"); tempScriptFile = Path.Combine(tempResultsDir, "sendPlatformMetrics.ps1"); // check for command line here, switches for chrome/edge if (CommandLine.Contains("chrome")) { processName = "chrome"; Log("Script set to run Octane via Chrome..."); } else if (CommandLine.Contains("msedge")) { processName = "msedge"; Log("Script set to run Octane via Edge..."); } START(mainWindowTitle: "SilverBench*", processName: processName); Wait(2); MainWindow.Maximize(); // verify we reched octane page by finding the top-left logo MainWindow.FindControl(className : "Text", title : "SilverBench", timeout: standardTimeout); MainWindow.Focus(); MainWindow.Type("{DOWN}".Repeat(10)); var startSilverBenchTestBtn = MainWindow.FindControl(className : "Button*", title : "Benchmark", timeout: standardTimeout); Wait(2, showOnScreen: true, onScreenText: "Starting SilverBench Test"); string silverBenchTimestamp = GetTimeNow(); // Start SilverBench test startSilverBenchTestBtn.Click(); // wait for test to complete Wait(waitForSilverbenchToComplete); if (processName == "msedge") { var silverBenchScoreContainer = MainWindow.FindControl(className: "Document*", title: "SilverBench*", timeout: standardTimeout); var silverBenchScoreContainerChildren = silverBenchScoreContainer.GetAllChildControls(); var silverBenchScoreRaw = silverBenchScoreContainerChildren[18]; var silverBenchScoreText = silverBenchScoreRaw.GetTitle(); silverBenchScore = string.Concat(silverBenchScoreText.Where(char.IsDigit)); } else if (processName == "chrome") { var silverBenchScoreContainer = MainWindow.FindControl(className: "Document*", title: "Chrome Legacy Window", timeout: standardTimeout); var silverBenchScoreContainerChildren = silverBenchScoreContainer.GetAllChildControls(); var silverBenchScoreRaw = silverBenchScoreContainerChildren[21]; var silverBenchScoreText = silverBenchScoreRaw.GetTitle(); Log(silverBenchScoreText); silverBenchScore = string.Concat(silverBenchScoreText.Where(char.IsDigit)); Log(silverBenchScore); } string metricGroup = "SilverBench"; try { double doubleSilverBenchScore = double.Parse(silverBenchScore); BuildBenchmarkData(metricGroup: metricGroup, metricName: "SilverBench Score", metricValue: doubleSilverBenchScore, metricUnits: "Score", metricTimestamp: silverBenchTimestamp); } catch (Exception e) { CreateEvent($"Could not return SilverBench score because {e}"); } MainWindow.Close(); if (silverBenchScore != null) { BuildPayloadFile(); Wait(.5); BuildPowerShellScript(); Wait(.5); UploadPlatformMetricsPowerShellRunner(); Wait(.5); DoCleanup(); } STOP(); } void BuildBenchmarkData(string metricGroup, string metricName, double metricValue, string metricUnits, string metricTimestamp) { var BenchmarkData = new BenchmarkData { Group = metricGroup, Name = metricName, Instance = computerName, ComponentType = processName, Value = metricValue, Units = metricUnits, TimeStamp = metricTimestamp }; BenchmarkDataList.Add(BenchmarkData); } void DoCleanup() { // Clean up the temporary files if (FileExists(tempScriptFile)) { RemoveFile(tempScriptFile); } if (FileExists(payloadFilePath)) { RemoveFile(payloadFilePath); } if (DirectoryExists(tempResultsDir)) { RemoveFolder(tempResultsDir); } } void UploadPlatformMetricsPowerShellRunner() // Run the PowerShell script to upload platform metrics { Log("Starting method: UploadPlatformMetricsPowerShellRunner"); try { ProcessStartInfo psi = new ProcessStartInfo { FileName = "powershell.exe", Arguments = $"-NoProfile -ExecutionPolicy Bypass -File \"{tempScriptFile}\"", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; using (Process process = new Process()) { process.StartInfo = psi; // Event handlers to capture asynchronous output process.OutputDataReceived += (sender, e) => { if (!string.IsNullOrEmpty(e.Data)) { Log(e.Data); } }; process.ErrorDataReceived += (sender, e) => { if (!string.IsNullOrEmpty(e.Data)) { Log("Error: " + e.Data); } }; process.Start(); process.BeginOutputReadLine(); process.BeginErrorReadLine(); process.WaitForExit(); } } catch (Exception ex) { Log("Exception: " + ex.Message); } } void BuildPowerShellScript() { string scriptContent = $@" [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {{ $true }} $configurationAccessToken = '{configurationAccessToken}' $fullUrl = '{baseUrl}{apiEndpoint}' $payloadFile = '{payloadFilePath.Replace("\\", "\\\\")}' ### Read payload from file ### $payload = Get-Content -Path $payloadFile -Raw ### Debug: Output JSON Payload ### Write-Host 'JSON Payload:' Write-Host $payload ### Create HttpWebRequest ### $request = [System.Net.HttpWebRequest]::Create($fullUrl) $request.Method = 'POST' $request.ContentType = 'application/json' $request.Accept = 'application/json' $request.Headers.Add('Authorization', 'Bearer ' + $configurationAccessToken) # Write JSON Payload to Request Body $byteArray = [System.Text.Encoding]::UTF8.GetBytes($payload) $request.ContentLength = $byteArray.Length $requestStream = $request.GetRequestStream() $requestStream.Write($byteArray, 0, $byteArray.Length) $requestStream.Close() ### Send Request and Handle Response ### try {{ Write-Host ""$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] - Sending POST request to $fullUrl..."" $response = $request.GetResponse() $responseStream = $response.GetResponseStream() $reader = New-Object IO.StreamReader($responseStream) $responseContent = $reader.ReadToEnd() $reader.Close() Write-Host ""$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [SUCCESS] - Response received:"" Write-Host $responseContent }} catch [System.Net.WebException] {{ Write-Host ""$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [ERROR] - Error: $($_.Exception.Message)"" if ($_.Exception.Response) {{ $errorStream = $_.Exception.Response.GetResponseStream() $reader = New-Object IO.StreamReader($errorStream) $errorContent = $reader.ReadToEnd() $reader.Close() Write-Host '[ERROR] - Full HTTP Response:' Write-Host $errorContent }} }} "; // Write the PowerShell script to the specified location File.WriteAllText(tempScriptFile, scriptContent); } void BuildPayloadFile() { // Manually build the JSON payload StringBuilder payloadBuilder = new StringBuilder(); payloadBuilder.Append("["); for (int i = 0; i < BenchmarkDataList.Count; i++) { var data = BenchmarkDataList[i]; payloadBuilder.Append("{"); payloadBuilder.AppendFormat("\"metricId\":\"{0}\",", EscapeString(data.Name)); payloadBuilder.AppendFormat("\"environmentKey\":\"{0}\",", EscapeString(environmentId)); payloadBuilder.AppendFormat("\"timestamp\":\"{0}\",", EscapeString(data.TimeStamp)); payloadBuilder.AppendFormat("\"group\":\"{0}\",", EscapeString(data.Group)); payloadBuilder.AppendFormat("\"instance\":\"{0}\",", EscapeString(data.Instance)); payloadBuilder.AppendFormat("\"displayName\":\"{0}\",", EscapeString(data.Name)); payloadBuilder.AppendFormat("\"unit\":\"{0}\",", EscapeString(data.Units)); payloadBuilder.AppendFormat("\"componentType\":\"{0}\",", EscapeString(data.ComponentType)); payloadBuilder.AppendFormat("\"value\":{0}", data.Value); payloadBuilder.Append("}"); if (i < BenchmarkDataList.Count - 1) { payloadBuilder.Append(","); } } payloadBuilder.Append("]"); string payload = payloadBuilder.ToString(); // Write payload to the determined path File.WriteAllText(payloadFilePath, payload); } string GetTimeNow() { if (!TryParseTimeOffset(timeOffset, out TimeSpan offset)) { throw new Exception($"Invalid time offset format: {timeOffset}"); } // Adjust the time to UTC by subtracting the offset DateTime timeNow = DateTime.Now; DateTime utcTimeNow = timeNow - offset; string TimeNow = utcTimeNow.ToString("yyyy-MM-ddTHH:mm:ssZ"); return TimeNow; } // Helper method to escape strings for JSON private string EscapeString(string s) { if (string.IsNullOrEmpty(s)) return ""; return s.Replace("\\", "\\\\").Replace("\"", "\\\""); } private bool TryParseTimeOffset(string timeOffsetStr, out TimeSpan offset) // Handle time offset parsing { offset = TimeSpan.Zero; if (string.IsNullOrWhiteSpace(timeOffsetStr)) return false; // Remove whitespace timeOffsetStr = timeOffsetStr.Trim(); // Handle '+' or '-' sign bool isNegative = false; if (timeOffsetStr.StartsWith("+")) { timeOffsetStr = timeOffsetStr.Substring(1); } else if (timeOffsetStr.StartsWith("-")) { isNegative = true; timeOffsetStr = timeOffsetStr.Substring(1); } // Try parsing the time offset if (TimeSpan.TryParse(timeOffsetStr, out TimeSpan parsedOffset)) { offset = isNegative ? parsedOffset.Negate() : parsedOffset; return true; } else { return false; } } // Class to store benchmark data class BenchmarkData { public string MetricId { get; set; } public string ComponentType { get; set; } public string Group { get; set; } public string Name { get; set; } // Corresponds to 'instance' in the API public string Instance { get; set; } public string Units { get; set; } public double Value { get; set; } // Corresponds to 'value' in the API public string TimeStamp { get; set; } // Original timestamp //public string IsoTimeStamp { get; set; } // Adjusted to UTC and formatted in ISO 8601 } }