fill in hw info from logs (still needs installation id extractor)

This commit is contained in:
13xforever 2022-06-29 23:22:38 +05:00
parent af32deb58e
commit 7dc07f282f
10 changed files with 205 additions and 18 deletions

View File

@ -1,5 +1,7 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Linq;
using CompatApiClient;
using Microsoft.EntityFrameworkCore;
@ -20,6 +22,7 @@ internal class HardwareDb : DbContext
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.UseCollation("NOCASE");
modelBuilder.Entity<HwInfo>().HasKey(m => new { m.HwId, m.CpuModel, m.GpuModel, m.OsType, });
modelBuilder.Entity<HwInfo>().HasIndex(m => m.Timestamp).HasDatabaseName("hardware_timestamp");
@ -43,6 +46,7 @@ internal enum CpuFeatures
Fma4 = 0b_00000000_00000000_00000000_00100000,
Tsx = 0b_00000000_00000000_00000000_01000000,
TsxFa = 0b_00000000_00000000_00000000_10000000,
Xop = 0b_00000000_00000000_00000001_00000000,
}
internal enum OsType : byte

View File

@ -11,13 +11,15 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace CompatBot.Migrations.HardwareDbMigrations
{
[DbContext(typeof(HardwareDb))]
[Migration("20220629140504_InitialCreate")]
[Migration("20220629172134_InitialCreate")]
partial class InitialCreate
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "6.0.6");
modelBuilder
.UseCollation("NOCASE")
.HasAnnotation("ProductVersion", "6.0.6");
modelBuilder.Entity("CompatBot.Database.HwInfo", b =>
{

View File

@ -15,7 +15,9 @@ namespace CompatBot.Migrations.HardwareDbMigrations
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "6.0.6");
modelBuilder
.UseCollation("NOCASE")
.HasAnnotation("ProductVersion", "6.0.6");
modelBuilder.Entity("CompatBot.Database.HwInfo", b =>
{

View File

@ -0,0 +1,130 @@
using System;
using System.Collections.Specialized;
using System.Globalization;
using System.Text;
using CompatBot.Utils;
namespace CompatBot.Database.Providers;
internal static class HwInfoProvider
{
private static readonly Encoding Utf8 = new UTF8Encoding(false);
public static void AddOrUpdateSystem(NameValueCollection items)
{
if (items["cpu_model"] is not string cpuString
|| (items["gpu_name"] ?? items["gpu_info"]) is not string gpuString
|| !int.TryParse(items["thread_count"], out var threadCount)
|| !decimal.TryParse(items["memory_amount"], out var ramGB)
|| items["cpu_extensions"] is not string cpuExtensions)
return;
var cpuStringParts = cpuString.Split(' ', 2);
var gpuStringParts = gpuString.Split(' ', 2);
if (cpuStringParts.Length != 2 || gpuStringParts.Length != 2)
return;
if (cpuStringParts[0].ToLower() is not ("intel" or "amd" or "apple"))
{
Config.Log.Warn($"Unknown CPU maker {cpuStringParts[0]}, plz fix");
return;
}
if (gpuStringParts[0].ToLower() is not ("nvidia" or "amd" or "intel" or "apple"))
{
Config.Log.Warn($"Unknown GPU maker {gpuStringParts[0]}, plz fix");
return;
}
var ts = DateTime.UtcNow;
if (items["log_start_timestamp"] is string logTs
&& DateTime.TryParse(logTs, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out var logTsVal))
ts = logTsVal.ToUniversalTime();
var osType = GetOsType(items["os_type"]);
var info = new HwInfo
{
Timestamp = ts.Ticks,
HwId = GetHwId(items),
CpuMaker = cpuStringParts[0],
CpuModel = cpuStringParts[1],
ThreadCount = threadCount,
CpuFeatures = GetFeatures(cpuExtensions),
RamInMb = (int)(ramGB * 1024),
GpuMaker = gpuStringParts[0],
GpuModel = gpuStringParts[1],
OsType = osType,
OsName = GetName(osType, items),
OsVersion = items["os_version"],
};
}
private static byte[] GetHwId(NameValueCollection items)
{
var id = items["hw_id"] ?? items["compat_database_path"] ?? "anonymous";
return Utf8.GetBytes(id).GetSaltedHash();
}
private static CpuFeatures GetFeatures(string extensions)
{
var result = CpuFeatures.None;
foreach (var ext in extensions.Split('|', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries))
{
if (ext.StartsWith("AVX"))
{
result |= CpuFeatures.Avx;
if (ext.EndsWith('x'))
result |= CpuFeatures.Xop;
if (ext.Contains("512"))
{
result |= CpuFeatures.Avx512;
if (ext.Contains('+'))
result |= CpuFeatures.Avx512IL;
}
else if (ext.Contains('+'))
result |= CpuFeatures.Avx2;
}
else if (ext.StartsWith("FMA"))
{
if (ext.Contains('3'))
result |= CpuFeatures.Fma3;
if (ext.Contains('4'))
result |= CpuFeatures.Fma4;
}
else if (ext.StartsWith("TSX"))
{
if (ext.Contains("disabled"))
continue;
result |= CpuFeatures.Tsx;
if (ext.Contains("TSX-FA"))
result |= CpuFeatures.TsxFa;
}
}
return result;
}
private static OsType GetOsType(string? osType)
=> osType switch
{
"Windows" => OsType.Windows,
"Linux" => OsType.Linux,
"MacOS" => OsType.MacOs,
"" => OsType.Unknown,
null => OsType.Unknown,
_ => OsType.Bsd,
};
private static string? GetName(OsType osType, NameValueCollection items)
=> osType switch
{
OsType.Windows => items["os_windows_version"],
OsType.Linux => items["os_linux_version"],
OsType.MacOs => items["os_mac_version"],
OsType.Bsd => items["os_linux_version"],
_ => null
};
}

View File

@ -32,6 +32,7 @@ namespace CompatBot.EventHandlers.LogParsing
["RPCS3 v"] = new(@"(^|.+\d:\d\d:\d\d\.\d{6})\s*(?<build_and_specs>RPCS3 [^\xC2\xB7]+?)\r?(\n·|$)", DefaultSingleLineOptions),
["0:00:00.0"] = new(@"(?<first_unicode_dot>·).+\r?$", DefaultOptions),
["Operating system:"] = LogParserResult.OsInfoInLog,
["Current Time:"] = new(@"Current Time: (?<log_start_timestamp>.+)\r?$", DefaultOptions),
["Physical device intialized"] = new(@"Physical device intialized\. GPU=(?<vulkan_gpu>.+), driver=(?<vulkan_driver_version_raw>-?\d+)\r?$", DefaultOptions),
["Found vulkan-compatible GPU:"] = new(@"Found vulkan-compatible GPU: (?<vulkan_found_device>'(?<vulkan_compatible_device_name>.+)' running.+)\r?$", DefaultOptions),
["Finished reading database from file:"] = new(@"Finished reading database from file: (?<compat_database_path>.*compat_database.dat).*\r?$", DefaultOptions),

View File

@ -24,13 +24,7 @@ namespace CompatBot.Utils.Extensions
}
}
public static string? ToSaltedSha256(this DiscordUser user)
{
var data = BitConverter.GetBytes(user.Id);
using var sha256 = System.Security.Cryptography.SHA256.Create();
sha256.TransformBlock(Config.CryptoSalt, 0, Config.CryptoSalt.Length, null, 0);
sha256.TransformFinalBlock(data, 0, data.Length);
return sha256.Hash?.ToHexString();
}
public static string ToSaltedSha256(this DiscordUser user)
=> BitConverter.GetBytes(user.Id).GetSaltedHash().ToHexString();
}
}

View File

@ -0,0 +1,15 @@
using System;
namespace CompatBot.Utils;
public static class Hashing
{
public static byte[] GetSaltedHash(this byte[] data)
{
using var sha256 = System.Security.Cryptography.SHA256.Create();
if (data.Length > 0)
sha256.TransformBlock(data, 0, data.Length, null, 0);
sha256.TransformFinalBlock(Config.CryptoSalt, 0, Config.CryptoSalt.Length);
return sha256.Hash ?? Guid.Empty.ToByteArray();
}
}

View File

@ -4,6 +4,7 @@ using System.Collections.Specialized;
using System.Linq;
using System.Text;
using CompatApiClient.Utils;
using CompatBot.Database.Providers;
using DSharpPlus.Entities;
namespace CompatBot.Utils.ResultFormatters
@ -49,7 +50,7 @@ namespace CompatBot.Utils.ResultFormatters
};
}
else if (cpuModel.Equals("VirtualApple", StringComparison.OrdinalIgnoreCase))
cpuModel = "Apple Mx";
cpuModel = items["gpu_name"] is string appleGpu && appleGpu.StartsWith("Apple M", StringComparison.OrdinalIgnoreCase) ? appleGpu : "Apple Mx";
items["cpu_model"] = cpuModel;
items["thread_count"] = cpuInfo.Groups["thread_count"].Value;
items["memory_amount"] = cpuInfo.Groups["memory_amount"].Value;
@ -72,13 +73,15 @@ namespace CompatBot.Utils.ResultFormatters
{
items["os_type"] = osInfo.Groups["posix_name"].Value;
items["os_version"] = osInfo.Groups["posix_release"].Value;
items["os_linux_version"] = GetLinuxVersion(items["os_version"], osInfo.Groups["posix_version"].Value);
items["os_linux_version"] = GetLinuxVersion(items["os_type"], items["os_version"], osInfo.Groups["posix_version"].Value);
break;
}
case "macos":
{
items["os_type"] = "MacOS";
items["os_version"] = osInfo.Groups["macos_version"].Value;
if (Version.TryParse(items["os_version"], out var macVer) && GetMacOsVersion(macVer) is string macOsVer)
items["os_mac_version"] = macOsVer;
break;
}
}
@ -99,7 +102,7 @@ namespace CompatBot.Utils.ResultFormatters
{
items["os_type"] = items["posix_name"];
items["os_version"] = items["posix_release"];
items["os_linux_version"] = GetLinuxVersion(items["os_version"], osInfo.Groups["posix_version"].Value);
items["os_linux_version"] = GetLinuxVersion(items["posix_name"], items["os_version"], osInfo.Groups["posix_version"].Value);
break;
}
}
@ -118,6 +121,8 @@ namespace CompatBot.Utils.ResultFormatters
systemInfo += "Windows " + winVer;
else if (items["os_linux_version"] is string linVer)
systemInfo += linVer;
else if (items["os_mac_version"] is string macVer)
systemInfo += $"{macVer} {items["os_version"]}";
else
{
systemInfo += items["os_type"];
@ -140,6 +145,7 @@ namespace CompatBot.Utils.ResultFormatters
systemInfo += $"{Environment.NewLine}GPU{(multiple ? "s" : "")}:{(multiple ? Environment.NewLine : " ")}{availableGpus}";
}
builder.AddField("Build Info", systemInfo.Trim(EmbedPager.MaxFieldLength));
HwInfoProvider.AddOrUpdateSystem(items);
}
private const int ColumnWidth = 30;

View File

@ -364,13 +364,16 @@ namespace CompatBot.Utils.ResultFormatters
GetVulkanDriverVersionRaw(items["gpu_info"], items["vulkan_driver_version_raw"]);
}
if (items["driver_version_info"] != null)
{
items["gpu_name"] = items["gpu_info"];
items["gpu_info"] += $" ({items["driver_version_info"]})";
}
if (multiItems["vulkan_compatible_device_name"] is UniqueList<string> vulkanDevices && vulkanDevices.Any())
if (multiItems["vulkan_compatible_device_name"] is { Count: > 0 } vulkanDevices)
{
var devices = vulkanDevices
.Distinct()
.Select(n => new {name = n.StripMarks(), driverVersion = GetVulkanDriverVersion(n, multiItems["vulkan_found_device"])})
.Select(n => new { name = n.StripMarks(), driverVersion = GetVulkanDriverVersion(n, multiItems["vulkan_found_device"]) })
.Reverse()
.ToList();
if (string.IsNullOrEmpty(items["gpu_info"]) && devices.Count > 0)
@ -378,6 +381,7 @@ namespace CompatBot.Utils.ResultFormatters
var discreteGpu = devices.FirstOrDefault(d => IsNvidia(d.name))
?? devices.FirstOrDefault(d => IsAmd(d.name))
?? devices.First();
items["gpu_name"] = discreteGpu.name;
items["discrete_gpu_info"] = $"{discreteGpu.name} ({discreteGpu.driverVersion})";
items["driver_version_info"] = discreteGpu.driverVersion;
}
@ -775,7 +779,7 @@ namespace CompatBot.Utils.ResultFormatters
_ => null,
};
private static string? GetLinuxVersion(string? release, string version)
private static string? GetLinuxVersion(string? osType, string? release, string version)
{
if (string.IsNullOrEmpty(release))
return null;
@ -801,9 +805,38 @@ namespace CompatBot.Utils.ResultFormatters
return "Fedora " + ver;
}
return "Linux " + kernelVersion;
return $"{osType} {kernelVersion}";
}
private static string? GetMacOsVersion(Version macVer)
=> macVer.Major switch
{
10 => macVer.Minor switch
{
0 => "Mac OS X Cheetah",
1 => "Mac OS X Puma",
2 => "Mac OS X Jaguar",
3 => "Mac OS X Panther",
4 => "Mac OS X Tiger",
5 => "Mac OS X Leopard",
6 => "Mac OS X Snow Leopard",
7 => "OS X Lion",
8 => "OS X Mountain Lion",
9 => "OS X Mavericks",
10 => "OS X Yosemite",
11 => "OS X El Capitan",
12 => "macOS Sierra",
13 => "macOS High Sierra",
14 => "macOS Mojave",
15 => "macOS Catalina",
_ => null,
},
11 => "macOS Big Sur",
12 => "macOS Monterey",
13 => "macOS Ventura",
_ => null,
};
private static bool IsAmd(string gpuInfo)
{
return gpuInfo.Contains("Radeon", StringComparison.InvariantCultureIgnoreCase) ||