finished diagnose system
This commit is contained in:
@@ -1,5 +1,12 @@
|
|||||||
|
using System.IO.Compression;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging.Console;
|
||||||
using MoonCore.Attributes;
|
using MoonCore.Attributes;
|
||||||
|
using MoonCore.Exceptions;
|
||||||
|
using MoonCore.Helpers;
|
||||||
|
using Moonlight.ApiServer.Helpers;
|
||||||
|
using Moonlight.ApiServer.Interfaces;
|
||||||
|
using Moonlight.ApiServer.Models.Diagnose;
|
||||||
using Moonlight.ApiServer.Services;
|
using Moonlight.ApiServer.Services;
|
||||||
using Moonlight.Shared.Http.Responses.Admin.Sys;
|
using Moonlight.Shared.Http.Responses.Admin.Sys;
|
||||||
|
|
||||||
@@ -10,10 +17,14 @@ namespace Moonlight.ApiServer.Http.Controllers.Admin.Sys;
|
|||||||
public class SystemController : Controller
|
public class SystemController : Controller
|
||||||
{
|
{
|
||||||
private readonly ApplicationService ApplicationService;
|
private readonly ApplicationService ApplicationService;
|
||||||
|
private readonly IEnumerable<IDiagnoseProvider> DiagnoseProviders;
|
||||||
|
private readonly DiagnoseService DiagnoseService;
|
||||||
|
|
||||||
public SystemController(ApplicationService applicationService)
|
public SystemController(ApplicationService applicationService, IEnumerable<IDiagnoseProvider> diagnoseProviders, DiagnoseService diagnoseService)
|
||||||
{
|
{
|
||||||
ApplicationService = applicationService;
|
ApplicationService = applicationService;
|
||||||
|
DiagnoseProviders = diagnoseProviders;
|
||||||
|
DiagnoseService = diagnoseService;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
@@ -35,4 +46,15 @@ public class SystemController : Controller
|
|||||||
{
|
{
|
||||||
await ApplicationService.Shutdown();
|
await ApplicationService.Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("diagnose")]
|
||||||
|
[RequirePermission("admin.system.diagnose")]
|
||||||
|
public async Task<IActionResult> Diagnose()
|
||||||
|
{
|
||||||
|
var stream = new MemoryStream();
|
||||||
|
|
||||||
|
await DiagnoseService.GenerateDiagnose(stream);
|
||||||
|
|
||||||
|
return File(stream, "application/zip", "diagnose.zip");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -6,11 +6,15 @@ namespace Moonlight.ApiServer.Implementations.Diagnose;
|
|||||||
|
|
||||||
public class CoreDiagnoseProvider : IDiagnoseProvider
|
public class CoreDiagnoseProvider : IDiagnoseProvider
|
||||||
{
|
{
|
||||||
public async Task<DiagnoseEntry> GetFiles()
|
public DiagnoseEntry[] GetFiles()
|
||||||
{
|
{
|
||||||
return new DiagnoseFile()
|
return
|
||||||
|
[
|
||||||
|
new DiagnoseFile()
|
||||||
{
|
{
|
||||||
|
Name = "test.txt",
|
||||||
GetContent = () => Encoding.UTF8.GetBytes("hello world")
|
GetContent = () => Encoding.UTF8.GetBytes("hello world")
|
||||||
};
|
}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace Moonlight.ApiServer.Implementations.Diagnose;
|
|
||||||
|
|
||||||
public class TestProvider
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
using Moonlight.ApiServer.Configuration;
|
using Moonlight.ApiServer.Configuration;
|
||||||
using Moonlight.ApiServer.Database;
|
using Moonlight.ApiServer.Database;
|
||||||
|
using Moonlight.ApiServer.Implementations.Diagnose;
|
||||||
|
using Moonlight.ApiServer.Interfaces;
|
||||||
using Moonlight.ApiServer.Interfaces.Startup;
|
using Moonlight.ApiServer.Interfaces.Startup;
|
||||||
|
|
||||||
namespace Moonlight.ApiServer.Implementations.Startup;
|
namespace Moonlight.ApiServer.Implementations.Startup;
|
||||||
@@ -50,6 +52,12 @@ public class CoreStartup : IPluginStartup
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Diagnose
|
||||||
|
|
||||||
|
builder.Services.AddSingleton<IDiagnoseProvider, CoreDiagnoseProvider>();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ namespace Moonlight.ApiServer.Interfaces;
|
|||||||
|
|
||||||
public interface IDiagnoseProvider
|
public interface IDiagnoseProvider
|
||||||
{
|
{
|
||||||
public Task<DiagnoseEntry> GetFiles();
|
public DiagnoseEntry[] GetFiles();
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@ namespace Moonlight.ApiServer.Models.Diagnose;
|
|||||||
|
|
||||||
public abstract class DiagnoseEntry
|
public abstract class DiagnoseEntry
|
||||||
{
|
{
|
||||||
public string Name { get; set; } = "";
|
public required string Name { get; set; } = "";
|
||||||
|
|
||||||
public abstract bool IsDirectory { get; }
|
public abstract bool IsDirectory { get; }
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,119 @@
|
|||||||
|
using MoonCore.Helpers;
|
||||||
|
using Moonlight.ApiServer.Interfaces;
|
||||||
|
using Moonlight.ApiServer.Models.Diagnose;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using MoonCore.Attributes;
|
||||||
|
|
||||||
namespace Moonlight.ApiServer.Services;
|
namespace Moonlight.ApiServer.Services;
|
||||||
|
|
||||||
|
[Scoped]
|
||||||
public class DiagnoseService
|
public class DiagnoseService
|
||||||
{
|
{
|
||||||
|
|
||||||
|
private readonly IEnumerable<IDiagnoseProvider> DiagnoseProviders;
|
||||||
|
|
||||||
|
public DiagnoseService(IEnumerable<IDiagnoseProvider> diagnoseProviders)
|
||||||
|
{
|
||||||
|
DiagnoseProviders = diagnoseProviders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task GenerateDiagnose(Stream outputStream)
|
||||||
|
{
|
||||||
|
var tasks = DiagnoseProviders
|
||||||
|
.SelectMany(x => x.GetFiles())
|
||||||
|
.Select(async x => await ProcessDiagnoseEntry(null, x));
|
||||||
|
|
||||||
|
|
||||||
|
var fileEntries = (await Task.WhenAll(tasks))
|
||||||
|
.SelectMany(x => x)
|
||||||
|
.ToDictionary();
|
||||||
|
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
using (var zip = new ZipArchive(outputStream, ZipArchiveMode.Create, leaveOpen: true))
|
||||||
|
{
|
||||||
|
foreach (var kv in fileEntries)
|
||||||
|
{
|
||||||
|
string entryName = kv.Key.Replace('\\', '/');
|
||||||
|
byte[] data = kv.Value;
|
||||||
|
|
||||||
|
// Optionally pick CompressionLevel.Optimal or NoCompression
|
||||||
|
var entry = zip.CreateEntry(entryName, CompressionLevel.Fastest);
|
||||||
|
|
||||||
|
using (var entryStream = entry.Open())
|
||||||
|
using (var ms = new MemoryStream(data))
|
||||||
|
{
|
||||||
|
await ms.CopyToAsync(entryStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outputStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new Exception($"An unknown error occured while building the Diagnose: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<Dictionary<string, byte[]>> ProcessDiagnoseEntry(string? path, DiagnoseEntry entry)
|
||||||
|
{
|
||||||
|
var fileEntries = new Dictionary<string, byte[]>();
|
||||||
|
|
||||||
|
switch (entry)
|
||||||
|
{
|
||||||
|
case DiagnoseDirectory diagnoseDirectory:
|
||||||
|
{
|
||||||
|
var files = await ProcessDiagnoseDirectory(path, diagnoseDirectory);
|
||||||
|
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
fileEntries.Add(file.Key, file.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DiagnoseFile diagnoseFile:
|
||||||
|
{
|
||||||
|
var file = await ProcessDiagnoseFile(path, diagnoseFile);
|
||||||
|
|
||||||
|
fileEntries.Add(file.Key, file.Value);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileEntries;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<Dictionary<string, byte[]>> ProcessDiagnoseDirectory(string? path, DiagnoseDirectory directory)
|
||||||
|
{
|
||||||
|
var result = new Dictionary<string, byte[]>();
|
||||||
|
|
||||||
|
var directoryPath = path != null ? string.Join("/", path, directory.Name) : directory.Name;
|
||||||
|
|
||||||
|
foreach (var entry in directory.Children)
|
||||||
|
{
|
||||||
|
var files = await ProcessDiagnoseEntry(directoryPath, entry);
|
||||||
|
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
result.Add(file.Key, file.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<KeyValuePair<string, byte[]>> ProcessDiagnoseFile(string? path, DiagnoseFile file)
|
||||||
|
{
|
||||||
|
|
||||||
|
var filePath = path != null ? string.Join("/", path, file.Name) : file.Name;
|
||||||
|
|
||||||
|
var bytes = file.GetContent();
|
||||||
|
|
||||||
|
return new KeyValuePair<string, byte[]>(filePath, bytes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user