[CHANGE] Service extended and events
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
</MudTooltip>
|
||||
}
|
||||
</MudAppBar>
|
||||
<div style="margin: 20px">
|
||||
<div style="display: flex; flex-direction: column; flex: 1; padding: 20px; min-height: 0;">
|
||||
@Body
|
||||
</div>
|
||||
</CascadingValue>
|
@@ -7,7 +7,7 @@
|
||||
|
||||
<CascadingValue Value="this">
|
||||
<MudLayout>
|
||||
<MudMainContent>
|
||||
<MudMainContent Style="display: flex; flex-direction: column; height: 100vh;">
|
||||
@Body
|
||||
</MudMainContent>
|
||||
</MudLayout>
|
||||
|
@@ -1,26 +1,90 @@
|
||||
@page "/Services"
|
||||
@using Manager.App.Services.System
|
||||
|
||||
@implements IDisposable
|
||||
|
||||
@inject BackgroundServiceManager ServiceManager
|
||||
|
||||
<title>Services</title>
|
||||
|
||||
<MudDataGrid T="ExtendedBackgroundService" MultiSelection Items="@_backgroundServices">
|
||||
<MudDataGrid T="ExtendedBackgroundService" Items="@_backgroundServices" Filterable QuickFilter="@QuickFilter">
|
||||
<ToolBarContent>
|
||||
<MudText Typo="Typo.h6">Services</MudText>
|
||||
<MudSpacer />
|
||||
<MudSpacer/>
|
||||
<MudTextField T="string" @bind-Value="@_searchText" Immediate
|
||||
Placeholder="Search" Adornment="Adornment.Start"
|
||||
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium"/>
|
||||
</ToolBarContent>
|
||||
<Columns>
|
||||
<PropertyColumn Property="x => x.Name" Title="Service"/>
|
||||
<PropertyColumn Property="x => x.Description" Title="Description"/>
|
||||
<PropertyColumn Property="x => x.State" Title="Status"/>
|
||||
<PropertyColumn Property="x => x.ExecuteInterval" Title="Execute interval"/>
|
||||
<TemplateColumn></TemplateColumn>
|
||||
<TemplateColumn>
|
||||
<CellTemplate>
|
||||
<MudStack Row Spacing="2">
|
||||
<MudButton Disabled="@(context.Item?.State == ServiceState.Paused)"
|
||||
OnClick="@(() => { context.Item?.Pause(); })" Variant="Variant.Outlined">Pause
|
||||
</MudButton>
|
||||
<MudButton Disabled="@(context.Item?.State == ServiceState.Running)"
|
||||
OnClick="@(() => { context.Item?.Resume(); })" Variant="Variant.Outlined">Resume
|
||||
</MudButton>
|
||||
</MudStack>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
</Columns>
|
||||
<PagerContent>
|
||||
<MudDataGridPager T="ExtendedBackgroundService" />
|
||||
<MudDataGridPager T="ExtendedBackgroundService"/>
|
||||
</PagerContent>
|
||||
</MudDataGrid>
|
||||
</MudDataGrid>
|
||||
|
||||
<MudPaper Elevation="0" Class="mt-3" Style="flex: 1; display: flex; flex-direction: column; min-height: 0;">
|
||||
<MudStack Class="ml-2 mb-2" Spacing="1">
|
||||
<MudText Typo="Typo.h5">Service events</MudText>
|
||||
<MudText Typo="Typo.caption">@($"{_serviceEvents.Count}/{VisibleEventCapacity} events")</MudText>
|
||||
</MudStack>
|
||||
<div class="console-container">
|
||||
@foreach (var serviceEvent in _serviceEvents)
|
||||
{
|
||||
<div class="log-line">
|
||||
<span>@serviceEvent.Date</span>
|
||||
<span>|</span>
|
||||
<span class="@GetLogClass(serviceEvent)">@serviceEvent.Severity</span>
|
||||
<span>|</span>
|
||||
<span style="color: #4d69f1">@serviceEvent.Source</span>
|
||||
<span>-</span>
|
||||
<span style="color: #d4d4d4">@serviceEvent.Message</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</MudPaper>
|
||||
|
||||
<style>
|
||||
.console-container {
|
||||
background-color: #1e1e1e;
|
||||
color: #9c9898;
|
||||
padding: 10px;
|
||||
border-radius: 8px;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.log-line {
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.log-info {
|
||||
color: #9cdcfe;
|
||||
}
|
||||
|
||||
.log-warning {
|
||||
color: #dcdcaa;
|
||||
}
|
||||
|
||||
.log-error {
|
||||
color: #f44747;
|
||||
}
|
||||
</style>
|
@@ -1,16 +1,67 @@
|
||||
using DotBased.Logging;
|
||||
using Manager.App.Extensions;
|
||||
using Manager.App.Services;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using MudBlazor;
|
||||
|
||||
namespace Manager.App.Components.Pages;
|
||||
|
||||
public partial class Services : ComponentBase
|
||||
{
|
||||
private const int VisibleEventCapacity = 500;
|
||||
private string _searchText = "";
|
||||
private List<ExtendedBackgroundService> _backgroundServices = [];
|
||||
|
||||
private List<ServiceEvent> _serviceEvents = [];
|
||||
private CancellationTokenSource _cts = new();
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
_backgroundServices = ServiceManager.GetServices();
|
||||
_ = Task.Run(() => ReadEventStreamsAsync(_cts.Token));
|
||||
}
|
||||
|
||||
private Func<ExtendedBackgroundService, bool> QuickFilter
|
||||
=> x => string.IsNullOrWhiteSpace(_searchText) || $"{x.Name} {x.Description} {x.State} {x.ExecuteInterval}".Contains(_searchText);
|
||||
|
||||
private async Task ReadEventStreamsAsync(CancellationToken token)
|
||||
{
|
||||
if (_backgroundServices.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var totalToGet = VisibleEventCapacity / _backgroundServices.Count;
|
||||
_serviceEvents.AddRange(_backgroundServices.SelectMany(x => x.ProgressEvents.Items.TakeLast(totalToGet)));
|
||||
|
||||
var asyncEnumerators = _backgroundServices.Select(x => x.ProgressEvents.GetStreamAsync());
|
||||
await foreach (var serviceEvent in AsyncEnumerableExtensions.Merge(asyncEnumerators, token))
|
||||
{
|
||||
if (!_serviceEvents.Contains(serviceEvent))
|
||||
{
|
||||
_serviceEvents.Add(serviceEvent);
|
||||
}
|
||||
|
||||
if (_serviceEvents.Count > VisibleEventCapacity)
|
||||
{
|
||||
_serviceEvents.RemoveAt(0);
|
||||
}
|
||||
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetLogClass(ServiceEvent serviceEvent) =>
|
||||
serviceEvent.Severity switch
|
||||
{
|
||||
LogSeverity.Info => "log-info",
|
||||
LogSeverity.Warning => "log-warning",
|
||||
LogSeverity.Error => "log-error",
|
||||
_ => "log-info"
|
||||
};
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user