feat: 完善健康检查界面
This commit is contained in:
parent
383eaaf14e
commit
9612e48bbb
|
@ -1 +1,30 @@
|
||||||
@page "/Admin/Healths"
|
@page "/Admin/Healths"
|
||||||
|
@using Bootstrap.Security.Blazor.HealthChecks
|
||||||
|
|
||||||
|
<Card IsShadow="true">
|
||||||
|
<CardHeader>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<span class="flex-fill">健康检查结果</span>
|
||||||
|
<span class="mx-3">@Duration</span>
|
||||||
|
<Tag Color="GetTagColor()" Icon="@GetTagIcon()">@GetTagText()</Tag>
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
<CardBody>
|
||||||
|
<Table TItem="HealthsCheckReportItem" OnQueryAsync="OnQueryAsync" ShowSkeleton="true" IsBordered="true" IsStriped="true" ShowExtendButtons="true">
|
||||||
|
<TableColumns>
|
||||||
|
<TableColumn @bind-Field="@context.Name" Lookup="@GetNameLookup()" Text="检查项"></TableColumn>
|
||||||
|
<TableColumn @bind-Field="@context.Description" Text="描述"></TableColumn>
|
||||||
|
<TableColumn @bind-Field="@context.Duration" Text="时长"></TableColumn>
|
||||||
|
<TableColumn @bind-Field="@context.Exception" Text="异常"></TableColumn>
|
||||||
|
<TableColumn @bind-Field="@context.Status" Text="检查结果">
|
||||||
|
<Template Context="v">
|
||||||
|
<Tag Icon="@GetTagIcon(v.Value)" Color="@GetTagColor(v.Value)">@GetTagText(v.Value)</Tag>
|
||||||
|
</Template>
|
||||||
|
</TableColumn>
|
||||||
|
</TableColumns>
|
||||||
|
<RowButtonTemplate>
|
||||||
|
<TableCellButton Color="Color.Primary" Icon="fa fa-info-circle" Text="明细" OnClick="@(() => OnRowButtonClick(context))" />
|
||||||
|
</RowButtonTemplate>
|
||||||
|
</Table>
|
||||||
|
</CardBody>
|
||||||
|
</Card>
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
using BootstrapAdmin.Web.Services;
|
using Bootstrap.Security.Blazor.HealthChecks;
|
||||||
|
using BootstrapAdmin.Web.Components;
|
||||||
|
using BootstrapAdmin.Web.Services;
|
||||||
|
using BootstrapAdmin.Web.Utils;
|
||||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||||
using System;
|
using System;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
@ -16,32 +19,74 @@ public partial class Healths
|
||||||
[NotNull]
|
[NotNull]
|
||||||
private NavigationManager? NavigationManager { get; set; }
|
private NavigationManager? NavigationManager { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
private TimeSpan Duration { get; set; }
|
||||||
/// OnInitializedAsync
|
|
||||||
/// </summary>
|
private HealthStatus Status { get; set; }
|
||||||
/// <returns></returns>
|
|
||||||
protected override async Task OnInitializedAsync()
|
[Inject]
|
||||||
|
[NotNull]
|
||||||
|
private DialogService? DialogService { get; set; }
|
||||||
|
|
||||||
|
[NotNull]
|
||||||
|
private HttpClient? Client { get; set; }
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
await base.OnInitializedAsync();
|
base.OnInitialized();
|
||||||
|
|
||||||
var client = HttpClientFactory.CreateClient();
|
Client = HttpClientFactory.CreateClient();
|
||||||
client.BaseAddress = new Uri(NavigationManager.BaseUri);
|
Client.BaseAddress = new Uri(NavigationManager.BaseUri);
|
||||||
var payload = await client.GetStringAsync("/Healths");
|
|
||||||
|
|
||||||
var serializeOption = new JsonSerializerOptions
|
|
||||||
{
|
|
||||||
PropertyNamingPolicy = null,
|
|
||||||
PropertyNameCaseInsensitive = true
|
|
||||||
};
|
|
||||||
serializeOption.Converters.Add(new StringToTimeSpanConverter());
|
|
||||||
|
|
||||||
var report = JsonSerializer.Deserialize<dynamic>(payload, serializeOption);
|
|
||||||
if (report != null)
|
|
||||||
{
|
|
||||||
foreach (var entry in report.Keys)
|
|
||||||
{
|
|
||||||
var item = report.Entries[entry];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<QueryData<HealthsCheckReportItem>> OnQueryAsync(QueryPageOptions options)
|
||||||
|
{
|
||||||
|
var payload = await Client.GetStringAsync("/Healths");
|
||||||
|
var report = HealthsCheckHelper.Parse(payload);
|
||||||
|
|
||||||
|
var ret = new QueryData<HealthsCheckReportItem>()
|
||||||
|
{
|
||||||
|
IsSorted = true,
|
||||||
|
IsFiltered = true,
|
||||||
|
IsSearch = true
|
||||||
|
};
|
||||||
|
|
||||||
|
ret.Items = report.Items;
|
||||||
|
Duration = report.Duration;
|
||||||
|
Status = report.Status;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<SelectedItem> GetNameLookup() => LookupHelper.GetCheckItems();
|
||||||
|
|
||||||
|
private string? GetTagText(HealthStatus? status = null) => (status ?? Status) switch
|
||||||
|
{
|
||||||
|
HealthStatus.Healthy => "健康",
|
||||||
|
HealthStatus.Degraded => "亚健康",
|
||||||
|
_ => "不健康"
|
||||||
|
};
|
||||||
|
|
||||||
|
private Color GetTagColor(HealthStatus? status = null) => (status ?? Status) switch
|
||||||
|
{
|
||||||
|
HealthStatus.Healthy => Color.Success,
|
||||||
|
HealthStatus.Degraded => Color.Warning,
|
||||||
|
_ => Color.Danger
|
||||||
|
};
|
||||||
|
|
||||||
|
private string? GetTagIcon(HealthStatus? status = null) => (status ?? Status) switch
|
||||||
|
{
|
||||||
|
HealthStatus.Healthy => "fa fa-check-circle",
|
||||||
|
HealthStatus.Degraded => "fa fa-exclamation-circle",
|
||||||
|
_ => "fa fa-times-circle"
|
||||||
|
};
|
||||||
|
|
||||||
|
private Task OnRowButtonClick(HealthsCheckReportItem item) => DialogService.Show(new DialogOption()
|
||||||
|
{
|
||||||
|
Title = $"{LookupHelper.GetCheckItems().FirstOrDefault(i => i.Value == item.Name)?.Text} - 详细数据",
|
||||||
|
IsScrolling = true,
|
||||||
|
Component = BootstrapDynamicComponent.CreateComponent<HealthCheckDetails>(new Dictionary<string, object?>
|
||||||
|
{
|
||||||
|
{ nameof(HealthCheckDetails.Data), item.Data }
|
||||||
|
})
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,4 +15,16 @@ static class LookupHelper
|
||||||
new SelectedItem("App", "应用程序"),
|
new SelectedItem("App", "应用程序"),
|
||||||
new SelectedItem("DB", "数据库")
|
new SelectedItem("DB", "数据库")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static List<SelectedItem> GetCheckItems() => new()
|
||||||
|
{
|
||||||
|
new("db", "数据库"),
|
||||||
|
new("environment", "环境变量"),
|
||||||
|
new("dotnet-runtime", "运行时"),
|
||||||
|
new("file", "文件系统"),
|
||||||
|
new("gc", "回收器"),
|
||||||
|
new("app-mem", "程序内存"),
|
||||||
|
new("sys-mem", "系统内存"),
|
||||||
|
new("Gitee", "Gitee")
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,14 +45,6 @@
|
||||||
height: calc(100vh - var(--bb-layout-header-height) - var(--bb-tab-header-height) - var(--bb-footer-height));
|
height: calc(100vh - var(--bb-layout-header-height) - var(--bb-tab-header-height) - var(--bb-footer-height));
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-scroll {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-scroll:hover {
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs-body-content .error-stack {
|
.tabs-body-content .error-stack {
|
||||||
height: calc(100vh - var(--bb-layout-header-height) - var(--bb-tab-header-height) - var(--bb-footer-height));
|
height: calc(100vh - var(--bb-layout-header-height) - var(--bb-tab-header-height) - var(--bb-footer-height));
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
Loading…
Reference in New Issue