PowerShell/test/perf/dotnet-tools/Reporting/Reporter.cs

154 lines
6.4 KiB
C#

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using RuntimeEnvironment = Microsoft.DotNet.PlatformAbstractions.RuntimeEnvironment;
namespace Reporting
{
public class Reporter
{
private Run run;
private Os os;
private Build build;
private List<Test> tests = new List<Test>();
protected IEnvironment environment;
private Reporter() { }
public void AddTest(Test test)
{
if (tests.Any(t => t.Name.Equals(test.Name)))
throw new Exception($"Duplicate test name, {test.Name}");
tests.Add(test);
}
/// <summary>
/// Get a Reporter. Relies on environment variables.
/// </summary>
/// <param name="environment">Optional environment variable provider</param>
/// <returns>A Reporter instance or null if the environment is incorrect.</returns>
public static Reporter CreateReporter(IEnvironment environment = null)
{
var ret = new Reporter();
ret.environment = environment == null ? new EnvironmentProvider() : environment;
if (ret.InLab)
{
ret.Init();
}
return ret;
}
private void Init()
{
run = new Run
{
CorrelationId = environment.GetEnvironmentVariable("HELIX_CORRELATION_ID"),
PerfRepoHash = environment.GetEnvironmentVariable("PERFLAB_PERFHASH"),
Name = environment.GetEnvironmentVariable("PERFLAB_RUNNAME"),
Queue = environment.GetEnvironmentVariable("PERFLAB_QUEUE"),
};
Boolean.TryParse(environment.GetEnvironmentVariable("PERFLAB_HIDDEN"), out bool hidden);
run.Hidden = hidden;
var configs = environment.GetEnvironmentVariable("PERFLAB_CONFIGS");
if (!String.IsNullOrEmpty(configs)) // configs should be optional.
{
foreach (var kvp in configs.Split(';'))
{
var split = kvp.Split('=');
run.Configurations.Add(split[0], split[1]);
}
}
os = new Os()
{
Name = $"{RuntimeEnvironment.OperatingSystem} {RuntimeEnvironment.OperatingSystemVersion}",
Architecture = RuntimeInformation.OSArchitecture.ToString(),
Locale = CultureInfo.CurrentUICulture.ToString()
};
build = new Build
{
Repo = environment.GetEnvironmentVariable("PERFLAB_REPO"),
Branch = environment.GetEnvironmentVariable("PERFLAB_BRANCH"),
Architecture = environment.GetEnvironmentVariable("PERFLAB_BUILDARCH"),
Locale = environment.GetEnvironmentVariable("PERFLAB_LOCALE"),
GitHash = environment.GetEnvironmentVariable("PERFLAB_HASH"),
BuildName = environment.GetEnvironmentVariable("PERFLAB_BUILDNUM"),
TimeStamp = DateTime.Parse(environment.GetEnvironmentVariable("PERFLAB_BUILDTIMESTAMP")),
};
build.AdditionalData["productVersion"] = environment.GetEnvironmentVariable("DOTNET_VERSION");
}
public string GetJson()
{
if (!InLab)
{
return null;
}
var jsonobj = new
{
build,
os,
run,
tests
};
var settings = new JsonSerializerSettings();
var resolver = new DefaultContractResolver();
resolver.NamingStrategy = new CamelCaseNamingStrategy() { ProcessDictionaryKeys = false };
settings.ContractResolver = resolver;
return JsonConvert.SerializeObject(jsonobj, Formatting.Indented, settings);
}
public string WriteResultTable()
{
StringBuilder ret = new StringBuilder();
foreach (var test in tests)
{
var defaultCounter = test.Counters.Single(c => c.DefaultCounter);
var topCounters = test.Counters.Where(c => c.TopCounter && !c.DefaultCounter);
var restCounters = test.Counters.Where(c => !(c.TopCounter || c.DefaultCounter));
var counterWidth = Math.Max(test.Counters.Max(c => c.Name.Length) + 1, 15);
var resultWidth = Math.Max(test.Counters.Max(c => c.Results.Max().ToString("F3").Length + c.MetricName.Length) + 2, 15);
ret.AppendLine(test.Name);
ret.AppendLine($"{LeftJustify("Metric", counterWidth)}|{LeftJustify("Average",resultWidth)}|{LeftJustify("Min", resultWidth)}|{LeftJustify("Max",resultWidth)}");
ret.AppendLine($"{new String('-', counterWidth)}|{new String('-', resultWidth)}|{new String('-', resultWidth)}|{new String('-', resultWidth)}");
ret.AppendLine(Print(defaultCounter, counterWidth, resultWidth));
foreach(var counter in topCounters)
{
ret.AppendLine(Print(counter, counterWidth, resultWidth));
}
foreach (var counter in restCounters)
{
ret.AppendLine(Print(counter, counterWidth, resultWidth));
}
}
return ret.ToString();
}
private string Print(Counter counter, int counterWidth, int resultWidth)
{
string average = $"{counter.Results.Average():F3} {counter.MetricName}";
string max = $"{counter.Results.Max():F3} {counter.MetricName}";
string min = $"{counter.Results.Min():F3} {counter.MetricName}";
return $"{LeftJustify(counter.Name, counterWidth)}|{LeftJustify(average, resultWidth)}|{LeftJustify(min, resultWidth)}|{LeftJustify(max, resultWidth)}";
}
private string LeftJustify(string str, int width)
{
return String.Format("{0,-" + width + "}", str);
}
public bool InLab => environment.GetEnvironmentVariable("PERFLAB_INLAB")?.Equals("1") ?? false;
}
}