Skip to content

Commit

Permalink
added View Health Check popup.
Browse files Browse the repository at this point in the history
  • Loading branch information
VeritasSoftware committed Oct 2, 2023
1 parent b3ebdc9 commit de72667
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 27 deletions.
Binary file added Docs/LiveHealthChecks-UI-ViewHealthCheck.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 7 additions & 1 deletion Docs/README_LiveHealthChecks.UI.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,10 @@ received from the Server.

Also, you can search this data in the Search popup (click on Search button on Dashboard).

![**Search**](/Docs/LiveHealthChecks-UI-Search.jpg)
![**Search**](/Docs/LiveHealthChecks-UI-Search.jpg)

You can click on a row in the table and a **View Health Check** popup comes up.

This has all the details of the Health Check, including the Health Report JSON.

![**View Health Check**](/Docs/LiveHealthChecks-UI-ViewHealthCheck.jpg)
24 changes: 14 additions & 10 deletions LiveHealthChecks.UI/Components/ApiWidget.razor
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,9 @@

public Dictionary<string, double[]> HealthChecks = new Dictionary<string, double[]>();

public List<HealthReport> HealthChecksTemp = new List<HealthReport>();
public List<HealthCheck> HealthChecksTemp = new List<HealthCheck>();

public List<HealthReport> LastHealthChecks = new List<HealthReport>();
public List<HealthCheck> LastHealthChecks = new List<HealthCheck>();

ChartOptions ChartOptions = new ChartOptions();

Expand Down Expand Up @@ -183,10 +183,12 @@
{
try
{
dynamic jsonReport = JsonSerializer.Deserialize<JsonObject>(report);
var deserializedHealthReport = JsonSerializer.Deserialize<HealthReport>(report);

// dynamic jsonReport = JsonSerializer.Deserialize<JsonObject>(report);
////Generate random Status
//var td = int.Parse(jsonReport["TotalDuration"].ToString().Replace(":", "").Replace(".", ""));
//var td = int.Parse(deserializedHealthReport.TotalDuration?.ToString().Replace(":", "").Replace(".", ""));
//Random = new Random(td);
Expand All @@ -195,24 +197,26 @@
//var random = new Random(seed);
//var num = random.Next(1, 100);
//jsonReport["Status"] = num % 2 == 0 ? 2 : 1;
////jsonReport["Status"] = num % 2 == 0 ? 2 : 1;
//deserializedHealthReport.Status = num % 2 == 0 ? Status.Healthy : Status.Unhealthy;
List<HealthReport> healthChecksTemp;
List<HealthCheck> healthChecksTemp;

if (await Repository.ContainKeyAsync(model.ReceiveMethod))
{
healthChecksTemp = await Repository.GetHealthChecksDataAsync(model.ReceiveMethod);
}
else
{
healthChecksTemp = new List<HealthReport>() { };
healthChecksTemp = new List<HealthCheck>() { };
}

var healthy = healthChecksTemp.Count(x => x.Status == HealthStatus.Healthy);
var unHealthy = healthChecksTemp.Count(x => x.Status == HealthStatus.Unhealthy);
double healthStatus;

if ((int)jsonReport["Status"] == 2)
if (deserializedHealthReport.Status == Status.Healthy)
{
healthy = healthy + 1;
healthStatus = HealthStatus.Healthy;
Expand All @@ -225,10 +229,10 @@
LastHealthCheck = "red";
}

healthChecksTemp.Add(new HealthReport {
healthChecksTemp.Add(new HealthCheck {
Api = model.ApiName,
ReceiveMethod = model.ReceiveMethod,
Report = report,
Report = deserializedHealthReport,
ReceiveTimeStamp = DateTime.UtcNow,
Status = healthStatus
});
Expand Down
40 changes: 31 additions & 9 deletions LiveHealthChecks.UI/Components/SearchWidget.razor
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
@using MudBlazor.Services
@using LiveHealthChecks.UI.Models
@using LiveHealthChecks.UI.Repository
@inject IDialogService DialogService
@inject IMyHealthChecksRepository Repository

@if(DashboardSettings != null && HealthChecks != null)
{
<MudTable T="HealthReport" Items="@HealthChecks" Dense="@dense" Hover="@hover" Bordered="@bordered" Striped="@striped" Filter="FilterFunc" @bind-SelectedItem="selectedItem1">
<MudTable T="HealthCheck" Items="@HealthChecks" Dense="@dense" Hover="@hover" Bordered="@bordered" Striped="@striped" Filter="FilterFunc" @bind-SelectedItem="selectedItem1" OnRowClick="HealthCheckSelected">
<ToolBarContent>
<MudText Typo="Typo.h6">Health Reports</MudText>
<MudSpacer />
Expand Down Expand Up @@ -74,16 +75,16 @@
}
}

private List<HealthReport>? HealthChecksView { get; set; } = new List<HealthReport>();
private List<HealthCheck>? HealthChecksView { get; set; } = new List<HealthCheck>();

private List<HealthReport>? HealthChecks { get; set; } = new List<HealthReport>();
private List<HealthCheck>? HealthChecks { get; set; } = new List<HealthCheck>();

private bool dense = false;
private bool hover = true;
private bool striped = false;
private bool bordered = false;
private HealthReport? selectedItem1 = null;
private HashSet<HealthReport> selectedItems = new HashSet<HealthReport>();
private HealthCheck? selectedItem1 = null;
private HashSet<HealthCheck> selectedItems = new HashSet<HealthCheck>();

protected override async Task OnInitializedAsync()
{
Expand All @@ -101,7 +102,7 @@
{
if (DashboardSettings != null)
{
HealthChecks = new List<HealthReport>();
HealthChecks = new List<HealthCheck>();

foreach(var api in DashboardSettings.Apis)
{
Expand All @@ -110,10 +111,31 @@
}
}

private bool FilterFunc(HealthReport element)
private void HealthCheckSelected(TableRowClickEventArgs<HealthCheck> e)
{
Func<HealthReport, bool> healthStatus = element => SelectedHealthStatus == "-1" ? true : element.Status == double.Parse(SelectedHealthStatus);
Func<HealthReport, int, bool> receiveTimestamp = (element, hours) => element.ReceiveTimeStamp >= DateTime.UtcNow.AddHours(hours);
OpenDialog(e.Item);
}

private void OpenDialog(HealthCheck healthReport)
{
var options = new DialogOptions
{
CloseOnEscapeKey = true,
MaxWidth = MaxWidth.ExtraSmall,
FullWidth = true,
Position = DialogPosition.Center,
CloseButton = true,
};
var parameters = new DialogParameters<ViewDialog>();
parameters.Add(x => x.HealthCheck, healthReport);

DialogService.Show<ViewDialog>("View Health Check", parameters, options);
}

private bool FilterFunc(HealthCheck element)
{
Func<HealthCheck, bool> healthStatus = element => SelectedHealthStatus == "-1" ? true : element.Status == double.Parse(SelectedHealthStatus);
Func<HealthCheck, int, bool> receiveTimestamp = (element, hours) => element.ReceiveTimeStamp >= DateTime.UtcNow.AddHours(hours);

switch(SelectedPeriod)
{
Expand Down
85 changes: 85 additions & 0 deletions LiveHealthChecks.UI/Components/View.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
@using System.Text.Json
@using MudBlazor
@using LiveHealthChecks.UI.Models

@if (HealthCheck != null)
{
<div style="min-width: 300px; min-height:300px;">
<div class="row">
<div class="col-10">
<b>Received Time</b>
</div>
<div class="col-2">
<b>Status</b>
</div>
</div>
<div class="row">
<div class="col-10">
@($"{HealthCheck?.ReceiveTimeStamp?.ToLocalTime().ToLongDateString()} - {HealthCheck?.ReceiveTimeStamp?.ToLocalTime().ToLongTimeString()}")
</div>
<div class="col-2">
@if(HealthCheck?.Status == HealthStatus.Healthy)
{
<MudIcon Icon="@Icons.Material.Filled.Square" Style="font-size: 1.5rem; background-color: green; color: green;" />
}
else
{
<MudIcon Icon="@Icons.Material.Filled.Square" Style="font-size: 1.5rem; background-color: red; color: red;" />
}
</div>
</div>
<div class="row">
<div class="col-10">
<b>Api</b>
</div>
<div class="col-2">
<br/>
</div>
</div>
<div class="row">
<div class="col-10">
@HealthCheck?.Api
</div>
<div class="col-2">
<br/>
</div>
</div>
<div class="row">
<div class="col-12">
<b>Health Report</b>
</div>
</div>
<div class="row">
<div class="col-12">
@if(@HealthCheck?.Report != null)
{
<pre>@JsonPrettify(HealthCheck?.Report)</pre>
}
</div>
</div>
</div>
}

@code {
[Parameter]
public HealthCheck? HealthCheck { get; set; }

private string JsonPrettify(HealthReport healthReport)
{
if (healthReport == null)
{
return string.Empty;
}

var transformedHealthReport = new TransformedHealthReport
{
Status = healthReport.Status.ToString(),
Results = healthReport.Entries?.ToDictionary(x => x.Key, y => y.Value.ToString())
};

var transformedJson = JsonSerializer.Serialize<TransformedHealthReport>(transformedHealthReport,
new JsonSerializerOptions { WriteIndented = true });

return transformedJson;
}
}
22 changes: 22 additions & 0 deletions LiveHealthChecks.UI/Components/ViewDialog.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
@using MudBlazor
@using LiveHealthChecks.UI.Models

<MudDialog>
<DialogContent>
@if (HealthCheck != null)
{
<div style="min-width: 300px; min-height:300px;">
<View
HealthCheck="HealthCheck"
></View>
</div>
}
</DialogContent>
<DialogActions>
</DialogActions>
</MudDialog>

@code {
[CascadingParameter] MudDialogInstance MudDialog { get; set; }
[Parameter] public HealthCheck? HealthCheck { get; set; }
}
24 changes: 22 additions & 2 deletions LiveHealthChecks.UI/Models/Models.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
namespace LiveHealthChecks.UI.Models
{
public class HealthReport
public class HealthCheck
{
public string Api { get; set; } = string.Empty;
public string ReceiveMethod { get; set; } = string.Empty;
public DateTime? ReceiveTimeStamp { get; set; } = null;
public string Report { get; set; } = string.Empty;
public HealthReport? Report { get; set; }
public double Status { get; set; }
}

Expand All @@ -15,4 +15,24 @@ public struct HealthStatus

public const double Healthy = 2.00;
}

public class HealthReport
{
public Status Status { get; set; }
public string? TotalDuration { get; set; }
public Dictionary<string, Status>? Entries { get; set; }
}

public enum Status
{
Unhealthy,
Degraded,
Healthy
}

public class TransformedHealthReport
{
public string? Status { get; set; }
public Dictionary<string, string>? Results { get; set; }
}
}
10 changes: 5 additions & 5 deletions LiveHealthChecks.UI/Repository/MyHealthChecksRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ namespace LiveHealthChecks.UI.Repository
public interface IMyHealthChecksRepository
{
ValueTask<bool> ContainKeyAsync(string key, CancellationToken cancellationToken = default);
ValueTask<List<HealthReport>> GetHealthChecksDataAsync(string receiveMethod, CancellationToken cancellationToken = default);
ValueTask SetHealthChecksDataAsync(string receiveMethod, List<HealthReport> data, CancellationToken cancellationToken = default);
ValueTask<List<HealthCheck>> GetHealthChecksDataAsync(string receiveMethod, CancellationToken cancellationToken = default);
ValueTask SetHealthChecksDataAsync(string receiveMethod, List<HealthCheck> data, CancellationToken cancellationToken = default);
}


Expand All @@ -25,12 +25,12 @@ public async ValueTask<bool> ContainKeyAsync(string key, CancellationToken cance
return await _localStorageService.ContainKeyAsync(key, cancellationToken);
}

public async ValueTask<List<HealthReport>> GetHealthChecksDataAsync(string receiveMethod, CancellationToken cancellationToken = default)
public async ValueTask<List<HealthCheck>> GetHealthChecksDataAsync(string receiveMethod, CancellationToken cancellationToken = default)
{
return await _localStorageService.GetItemAsync<List<HealthReport>>(receiveMethod, cancellationToken);
return await _localStorageService.GetItemAsync<List<HealthCheck>>(receiveMethod, cancellationToken);
}

public async ValueTask SetHealthChecksDataAsync(string receiveMethod, List<HealthReport> data, CancellationToken cancellationToken = default)
public async ValueTask SetHealthChecksDataAsync(string receiveMethod, List<HealthCheck> data, CancellationToken cancellationToken = default)
{
await _localStorageService.SetItemAsync(receiveMethod, data, cancellationToken);
}
Expand Down

0 comments on commit de72667

Please sign in to comment.