-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added v14 support of crash reports
- Loading branch information
Showing
142 changed files
with
1,154 additions
and
598 deletions.
There are no files selected for viewing
18 changes: 18 additions & 0 deletions
18
...R.Site.NexusMods.Server.CrashReport.v13/BUTR.Site.NexusMods.Server.CrashReport.v13.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="BUTR.CrashReport.Models" Version="13.0.0.82" /> | ||
<PackageReference Include="BUTR.CrashReport.Bannerlord.Parser" Version="13.0.0.82" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\BUTR.Site.NexusMods.Server.Persistence\BUTR.Site.NexusMods.Server.Persistence.csproj" /> | ||
<ProjectReference Include="..\BUTR.Site.NexusMods.Server.ValueObjects.Vogen\BUTR.Site.NexusMods.Server.ValueObjects.Vogen.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
110 changes: 110 additions & 0 deletions
110
src/BUTR.Site.NexusMods.Server.CrashReport.v13/CrashReportV13.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Linq; | ||
using System.Text.Json; | ||
using BUTR.CrashReport.Models; | ||
using BUTR.Site.NexusMods.Server.Extensions; | ||
using BUTR.Site.NexusMods.Server.Models; | ||
using BUTR.Site.NexusMods.Server.Models.Database; | ||
using BUTR.Site.NexusMods.Server.Repositories; | ||
|
||
namespace BUTR.Site.NexusMods.Server.CrashReport.v13; | ||
|
||
public static class CrashReportV13 | ||
{ | ||
private static ExceptionTypeId FromException(ExceptionModel exception) | ||
{ | ||
var exc = exception; | ||
while (exc.InnerException is not null) | ||
exc = exc.InnerException; | ||
|
||
return ExceptionTypeId.From(exc.Type); | ||
} | ||
|
||
private static string GetException(ExceptionModel? exception, bool inner = false) => exception is null ? string.Empty : $""" | ||
{(inner ? "Inner " : string.Empty)}Exception information | ||
Type: {exception.Type} | ||
Message: {exception.Message} | ||
CallStack: | ||
{exception.CallStack} | ||
{GetException(exception.InnerException, true)} | ||
"""; | ||
|
||
public static bool TryFromJson( | ||
IUnitOfWrite unitOfWrite, | ||
TenantId tenant, | ||
CrashReportFileId fileId, | ||
CrashReportUrl url, | ||
DateTime date, | ||
byte version, | ||
string content, | ||
[NotNullWhen(true)] out CrashReportEntity? crashReportEntity, | ||
[NotNullWhen(true)] out CrashReportToMetadataEntity? crashReportToMetadataEntity, | ||
[NotNullWhen(true)] out IList<CrashReportToModuleMetadataEntity>? crashReportToModuleMetadataEntities) | ||
{ | ||
if (version != 13) | ||
{ | ||
crashReportEntity = null!; | ||
crashReportToMetadataEntity = null!; | ||
crashReportToModuleMetadataEntities = null!; | ||
return false; | ||
} | ||
|
||
var report = JsonSerializer.Deserialize<CrashReportModel>(content); | ||
if (report is null) | ||
{ | ||
crashReportEntity = null!; | ||
crashReportToMetadataEntity = null!; | ||
crashReportToModuleMetadataEntities = null!; | ||
return false; | ||
} | ||
|
||
var butrLoaderVersion = report.Metadata.AdditionalMetadata.FirstOrDefault(x => x.Key == "BUTRLoaderVersion")?.Value; | ||
var blseVersion = report.Metadata.AdditionalMetadata.FirstOrDefault(x => x.Key == "BLSEVersion")?.Value; | ||
var launcherExVersion = report.Metadata.AdditionalMetadata.FirstOrDefault(x => x.Key == "LauncherExVersion")?.Value; | ||
|
||
var crashReportId = CrashReportId.From(report.Id); | ||
crashReportEntity = new CrashReportEntity | ||
{ | ||
TenantId = tenant, | ||
CrashReportId = crashReportId, | ||
Url = url, | ||
Version = CrashReportVersion.From(report.Version), | ||
GameVersion = GameVersion.From(report.Metadata.GameVersion), | ||
ExceptionTypeId = FromException(report.Exception), | ||
ExceptionType = unitOfWrite.UpsertEntityFactory.GetOrCreateExceptionType(FromException(report.Exception)), | ||
Exception = GetException(report.Exception), | ||
CreatedAt = fileId.Value.Length == 8 ? DateTimeOffset.UnixEpoch.ToUniversalTime() : date.ToUniversalTime(), | ||
}; | ||
crashReportToMetadataEntity = new CrashReportToMetadataEntity | ||
{ | ||
TenantId = tenant, | ||
CrashReportId = crashReportId, | ||
LauncherType = string.IsNullOrEmpty(report.Metadata.LauncherType) ? null : report.Metadata.LauncherType, | ||
LauncherVersion = string.IsNullOrEmpty(report.Metadata.LauncherVersion) ? null : report.Metadata.LauncherVersion, | ||
Runtime = string.IsNullOrEmpty(report.Metadata.Runtime) ? null : report.Metadata.Runtime, | ||
BUTRLoaderVersion = butrLoaderVersion, | ||
BLSEVersion = blseVersion, | ||
LauncherExVersion = launcherExVersion, | ||
OperatingSystemType = null, | ||
OperatingSystemVersion = null, | ||
}; | ||
crashReportToModuleMetadataEntities = report.Modules.DistinctBy(x => new { x.Id }).Select(x => new CrashReportToModuleMetadataEntity | ||
{ | ||
TenantId = tenant, | ||
CrashReportId = crashReportId, | ||
ModuleId = ModuleId.From(x.Id), | ||
Module = unitOfWrite.UpsertEntityFactory.GetOrCreateModule(ModuleId.From(x.Id)), | ||
Version = ModuleVersion.From(x.Version), | ||
NexusModsModId = NexusModsModId.TryParseUrl(x.Url, out var modId1) ? modId1 : null, | ||
NexusModsMod = NexusModsModId.TryParseUrl(x.Url, out var modId2) ? unitOfWrite.UpsertEntityFactory.GetOrCreateNexusModsMod(modId2) : null, | ||
InvolvedPosition = (byte) (report.InvolvedModules.IndexOf(y => y.ModuleOrLoaderPluginId == x.Id) + 1), | ||
IsInvolved = report.InvolvedModules.Any(y => y.ModuleOrLoaderPluginId == x.Id), | ||
}).ToArray(); | ||
|
||
return true; | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
...R.Site.NexusMods.Server.CrashReport.v14/BUTR.Site.NexusMods.Server.CrashReport.v14.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="BUTR.CrashReport.Models" Version="14.0.0.84" /> | ||
<PackageReference Include="BUTR.CrashReport.Bannerlord.Parser" Version="14.0.0.84" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\BUTR.Site.NexusMods.Server.Persistence\BUTR.Site.NexusMods.Server.Persistence.csproj" /> | ||
<ProjectReference Include="..\BUTR.Site.NexusMods.Server.ValueObjects.Vogen\BUTR.Site.NexusMods.Server.ValueObjects.Vogen.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
147 changes: 147 additions & 0 deletions
147
src/BUTR.Site.NexusMods.Server.CrashReport.v14/CrashReportV14.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Linq; | ||
using System.Text.Json; | ||
using BUTR.CrashReport.Bannerlord.Parser; | ||
using BUTR.CrashReport.Models; | ||
using BUTR.Site.NexusMods.Server.Extensions; | ||
using BUTR.Site.NexusMods.Server.Models; | ||
using BUTR.Site.NexusMods.Server.Models.Database; | ||
using BUTR.Site.NexusMods.Server.Repositories; | ||
|
||
namespace BUTR.Site.NexusMods.Server.CrashReport.v14; | ||
|
||
public static class CrashReportV14 | ||
{ | ||
private static ExceptionTypeId FromException(ExceptionModel exception) | ||
{ | ||
var exc = exception; | ||
while (exc.InnerException is not null) | ||
exc = exc.InnerException; | ||
|
||
return ExceptionTypeId.From(exc.Type); | ||
} | ||
|
||
private static string GetException(ExceptionModel? exception, bool inner = false) => exception is null ? string.Empty : $""" | ||
{(inner ? "Inner " : string.Empty)}Exception information | ||
Type: {exception.Type} | ||
Message: {exception.Message} | ||
CallStack: | ||
{exception.CallStack} | ||
{GetException(exception.InnerException, true)} | ||
"""; | ||
|
||
public static bool TryFromHtml( | ||
IUnitOfWrite unitOfWrite, | ||
TenantId tenant, | ||
CrashReportFileId fileId, | ||
CrashReportUrl url, | ||
DateTime date, | ||
byte version, | ||
string content, | ||
[NotNullWhen(true)] out CrashReportEntity? crashReportEntity, | ||
[NotNullWhen(true)] out CrashReportToMetadataEntity? crashReportToMetadataEntity, | ||
[NotNullWhen(true)] out IList<CrashReportToModuleMetadataEntity>? crashReportToModuleMetadataEntities) | ||
{ | ||
var report = CrashReportParser.ParseLegacyHtml(version, content); | ||
if (report is null) | ||
{ | ||
crashReportEntity = null!; | ||
crashReportToMetadataEntity = null!; | ||
crashReportToModuleMetadataEntities = null!; | ||
return false; | ||
} | ||
return TryFromModel(unitOfWrite, tenant, fileId, url, date, report, out crashReportEntity, out crashReportToMetadataEntity, out crashReportToModuleMetadataEntities); | ||
} | ||
|
||
public static bool TryFromJson( | ||
IUnitOfWrite unitOfWrite, | ||
TenantId tenant, | ||
CrashReportFileId fileId, | ||
CrashReportUrl url, | ||
DateTime date, | ||
byte version, | ||
string content, | ||
[NotNullWhen(true)] out CrashReportEntity? crashReportEntity, | ||
[NotNullWhen(true)] out CrashReportToMetadataEntity? crashReportToMetadataEntity, | ||
[NotNullWhen(true)] out IList<CrashReportToModuleMetadataEntity>? crashReportToModuleMetadataEntities) | ||
{ | ||
if (version != 14) | ||
{ | ||
crashReportEntity = null!; | ||
crashReportToMetadataEntity = null!; | ||
crashReportToModuleMetadataEntities = null!; | ||
return false; | ||
} | ||
|
||
var report = JsonSerializer.Deserialize<CrashReportModel>(content); | ||
if (report is null) | ||
{ | ||
crashReportEntity = null!; | ||
crashReportToMetadataEntity = null!; | ||
crashReportToModuleMetadataEntities = null!; | ||
return false; | ||
} | ||
|
||
return TryFromModel(unitOfWrite, tenant, fileId, url, date, report, out crashReportEntity, out crashReportToMetadataEntity, out crashReportToModuleMetadataEntities); | ||
} | ||
public static bool TryFromModel( | ||
IUnitOfWrite unitOfWrite, | ||
TenantId tenant, | ||
CrashReportFileId fileId, | ||
CrashReportUrl url, | ||
DateTime date, | ||
CrashReportModel report, | ||
[NotNullWhen(true)] out CrashReportEntity? crashReportEntity, | ||
[NotNullWhen(true)] out CrashReportToMetadataEntity? crashReportToMetadataEntity, | ||
[NotNullWhen(true)] out IList<CrashReportToModuleMetadataEntity>? crashReportToModuleMetadataEntities) | ||
{ | ||
var butrLoaderVersion = report.Metadata.AdditionalMetadata.FirstOrDefault(x => x.Key == "BUTRLoaderVersion")?.Value; | ||
var blseVersion = report.Metadata.AdditionalMetadata.FirstOrDefault(x => x.Key == "BLSEVersion")?.Value; | ||
var launcherExVersion = report.Metadata.AdditionalMetadata.FirstOrDefault(x => x.Key == "LauncherExVersion")?.Value; | ||
|
||
var crashReportId = CrashReportId.From(report.Id); | ||
crashReportEntity = new CrashReportEntity | ||
{ | ||
TenantId = tenant, | ||
CrashReportId = crashReportId, | ||
Url = url, | ||
Version = CrashReportVersion.From(report.Version), | ||
GameVersion = GameVersion.From(report.Metadata.GameVersion), | ||
ExceptionTypeId = FromException(report.Exception), | ||
ExceptionType = unitOfWrite.UpsertEntityFactory.GetOrCreateExceptionType(FromException(report.Exception)), | ||
Exception = GetException(report.Exception), | ||
CreatedAt = fileId.Value.Length == 8 ? DateTimeOffset.UnixEpoch.ToUniversalTime() : date.ToUniversalTime(), | ||
}; | ||
crashReportToMetadataEntity = new CrashReportToMetadataEntity | ||
{ | ||
TenantId = tenant, | ||
CrashReportId = crashReportId, | ||
LauncherType = string.IsNullOrEmpty(report.Metadata.LauncherType) ? null : report.Metadata.LauncherType, | ||
LauncherVersion = string.IsNullOrEmpty(report.Metadata.LauncherVersion) ? null : report.Metadata.LauncherVersion, | ||
Runtime = string.IsNullOrEmpty(report.Metadata.Runtime) ? null : report.Metadata.Runtime, | ||
BUTRLoaderVersion = butrLoaderVersion, | ||
BLSEVersion = blseVersion, | ||
LauncherExVersion = launcherExVersion, | ||
OperatingSystemType = report.Metadata.OperatingSystemType.ToString(), | ||
OperatingSystemVersion = report.Metadata.OperatingSystemVersion, | ||
}; | ||
crashReportToModuleMetadataEntities = report.Modules.DistinctBy(x => new { x.Id }).Select(x => new CrashReportToModuleMetadataEntity | ||
{ | ||
TenantId = tenant, | ||
CrashReportId = crashReportId, | ||
ModuleId = ModuleId.From(x.Id), | ||
Module = unitOfWrite.UpsertEntityFactory.GetOrCreateModule(ModuleId.From(x.Id)), | ||
Version = ModuleVersion.From(x.Version), | ||
NexusModsModId = NexusModsModId.TryParseUrl(x.Url, out var modId1) ? modId1 : null, | ||
NexusModsMod = NexusModsModId.TryParseUrl(x.Url, out var modId2) ? unitOfWrite.UpsertEntityFactory.GetOrCreateNexusModsMod(modId2) : null, | ||
InvolvedPosition = (byte) (report.InvolvedModules.IndexOf(y => y.ModuleOrLoaderPluginId == x.Id) + 1), | ||
IsInvolved = report.InvolvedModules.Any(y => y.ModuleOrLoaderPluginId == x.Id), | ||
}).ToArray(); | ||
|
||
return true; | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
src/BUTR.Site.NexusMods.Server.Persistence/BUTR.Site.NexusMods.Server.Persistence.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<Nullable>enable</Nullable> | ||
<LangVersion>latest</LangVersion> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<FrameworkReference Include="Microsoft.AspNetCore.App" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\BUTR.Site.NexusMods.Server.ValueObjects.Vogen\BUTR.Site.NexusMods.Server.ValueObjects.Vogen.csproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Bannerlord.ModuleManager" Version="5.0.226" /> | ||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.4" /> | ||
</ItemGroup> | ||
|
||
</Project> |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
33 changes: 33 additions & 0 deletions
33
src/BUTR.Site.NexusMods.Server.Persistence/Extensions/IAsyncEnumerableExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
using JetBrains.Annotations; | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.Runtime.CompilerServices; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace BUTR.Site.NexusMods.Server.Extensions; | ||
|
||
/// <summary> | ||
/// Provides extension methods for <see cref="IAsyncEnumerable{T}"/> objects. | ||
/// </summary> | ||
public static class IAsyncEnumerableExtensions | ||
{ | ||
public static int IndexOf<T>(this IEnumerable<T> source, Predicate<T> predicate) | ||
{ | ||
ArgumentNullException.ThrowIfNull(source); | ||
ArgumentNullException.ThrowIfNull(predicate); | ||
|
||
var index = 0; | ||
foreach (var item in source) | ||
{ | ||
if (predicate(item)) | ||
return index; | ||
|
||
index += 1; | ||
} | ||
|
||
return -1; | ||
} | ||
} |
Oops, something went wrong.