Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,7 @@ private async Task RequeueManifest()

var registration = TrainDiscovery
.DiscoverTrains()
.FirstOrDefault(r =>
r.ServiceType.FullName == manifest.Name
|| r.ImplementationType.FullName == manifest.Name
);
.FirstOrDefault(r => r.ServiceType.FullName == manifest.Name);

if (registration is null)
{
Expand Down
35 changes: 31 additions & 4 deletions src/Trax.Dashboard/Components/Pages/Data/DeadLettersPage.razor
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@page "/trax/data/dead-letters"
@using System.Linq.Dynamic.Core
@inherits PollingComponentBase
@inject IDataContextProviderFactory DataContextFactory
@inject NavigationManager Navigation
Expand All @@ -8,9 +9,9 @@
Train executions that exceeded their maximum retry count and require manual intervention. Resolve by retrying or acknowledging.
</RadzenText>

<TraxDataGrid Data="@_items"
<TraxDataGrid @ref="_grid"
TItem="DeadLetter"
IsLoading="@IsLoading">
ServerLoadData="@LoadPageAsync">
<Columns>
<RadzenDataGridColumn TItem="DeadLetter"
Title=""
Expand Down Expand Up @@ -70,11 +71,37 @@
</TraxDataGrid>

@code {
private List<DeadLetter> _items = [];
private TraxDataGrid<DeadLetter>? _grid;

protected override async Task LoadDataAsync(CancellationToken cancellationToken)
{
if (_grid is not null)
await _grid.ReloadAsync();
}

private async Task<ServerDataResult<DeadLetter>> LoadPageAsync(
LoadDataArgs args,
CancellationToken cancellationToken)
{
using var context = await DataContextFactory.CreateDbContextAsync(cancellationToken);
_items = await context.DeadLetters.AsNoTracking().ToListAsync(cancellationToken);
IQueryable<DeadLetter> query = context.DeadLetters.AsNoTracking();

if (!string.IsNullOrEmpty(args.Filter))
query = query.Where(args.Filter);

if (!string.IsNullOrEmpty(args.OrderBy))
query = query.OrderBy(args.OrderBy);
else
query = query.OrderByDescending(d => d.Id);

var count = await query.CountAsync(cancellationToken);

if (args.Skip.HasValue)
query = query.Skip(args.Skip.Value);
if (args.Top.HasValue)
query = query.Take(args.Top.Value);

var items = await query.ToListAsync(cancellationToken);
return new ServerDataResult<DeadLetter>(items, count);
}
}
35 changes: 31 additions & 4 deletions src/Trax.Dashboard/Components/Pages/Data/LogsPage.razor
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@page "/trax/data/logs"
@using System.Linq.Dynamic.Core
@inherits PollingComponentBase
@inject IDataContextProviderFactory DataContextFactory

Expand All @@ -7,9 +8,9 @@
Log entries captured during train execution, including messages, exceptions, and diagnostic information.
</RadzenText>

<TraxDataGrid Data="@_items"
<TraxDataGrid @ref="_grid"
TItem="Log"
IsLoading="@IsLoading">
ServerLoadData="@LoadPageAsync">
<Columns>
<RadzenDataGridColumn TItem="Log"
Property="Id"
Expand Down Expand Up @@ -40,11 +41,37 @@
</TraxDataGrid>

@code {
private List<Log> _items = [];
private TraxDataGrid<Log>? _grid;

protected override async Task LoadDataAsync(CancellationToken cancellationToken)
{
if (_grid is not null)
await _grid.ReloadAsync();
}

private async Task<ServerDataResult<Log>> LoadPageAsync(
LoadDataArgs args,
CancellationToken cancellationToken)
{
using var context = await DataContextFactory.CreateDbContextAsync(cancellationToken);
_items = await context.Logs.AsNoTracking().ToListAsync(cancellationToken);
IQueryable<Log> query = context.Logs.AsNoTracking();

if (!string.IsNullOrEmpty(args.Filter))
query = query.Where(args.Filter);

if (!string.IsNullOrEmpty(args.OrderBy))
query = query.OrderBy(args.OrderBy);
else
query = query.OrderByDescending(l => l.Id);

var count = await query.CountAsync(cancellationToken);

if (args.Skip.HasValue)
query = query.Skip(args.Skip.Value);
if (args.Top.HasValue)
query = query.Take(args.Top.Value);

var items = await query.ToListAsync(cancellationToken);
return new ServerDataResult<Log>(items, count);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ protected override async Task LoadDataAsync(CancellationToken cancellationToken)
.Metadatas.AsNoTracking()
.Where(m => m.ManifestId == ManifestId)
.OrderByDescending(m => m.StartTime)
.Take(500)
.ToListAsync(cancellationToken);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,6 @@

_items = await context.ManifestGroups
.AsNoTracking()
.Include(g => g.Manifests)
.ThenInclude(m => m.Metadatas)
.Select(g => new GroupSummary
{
Id = g.Id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,7 @@ private async Task RequeueTrain()
{
var registration = TrainDiscovery
.DiscoverTrains()
.FirstOrDefault(r =>
r.ServiceType.FullName == _metadata.Name
|| r.ImplementationType.FullName == _metadata.Name
);
.FirstOrDefault(r => r.ServiceType.FullName == _metadata.Name);

if (registration is null)
{
Expand Down
204 changes: 106 additions & 98 deletions src/Trax.Dashboard/Components/Pages/Index.razor
Original file line number Diff line number Diff line change
Expand Up @@ -95,67 +95,102 @@
</RadzenRow>
}

@* ── Executions Chart (with time range toggle) ── *@
@if (DashboardSettings.ShowExecutionsChart)
@* ── Executions Chart + Avg Execution Duration ── *@
@if (DashboardSettings.ShowExecutionsChart || DashboardSettings.ShowAvgDuration)
{
<RadzenRow Gap="1rem" class="rz-mb-4">
<RadzenColumn Size="12">
<RadzenCard>
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.SpaceBetween" AlignItems="AlignItems.Center" class="rz-mb-2">
<RadzenText TextStyle="TextStyle.H6">Executions</RadzenText>
<RadzenSelectBar Value="@_selectedTimeRange" TValue="string" Size="ButtonSize.Small" Change="@OnTimeRangeChanged">
<Items>
<RadzenSelectBarItem Text="Last Hour" Value="@TimeRange1H" />
<RadzenSelectBarItem Text="Last 24h" Value="@TimeRange24H" />
</Items>
</RadzenSelectBar>
</RadzenStack>
@if (_executionsOverTime.Any(e => e.Completed > 0 || e.Failed > 0 || e.Cancelled > 0))
{
<RadzenChart Style="height: 300px;">
<RadzenColumnSeries Data="@_executionsOverTime"
CategoryProperty="Label"
ValueProperty="Completed"
Title="Completed"
Fill="#2E7D32">
<RadzenSeriesDataLabels Visible="false" />
</RadzenColumnSeries>
<RadzenColumnSeries Data="@_executionsOverTime"
CategoryProperty="Label"
ValueProperty="Failed"
Title="Failed"
Fill="#C62828">
<RadzenSeriesDataLabels Visible="false" />
</RadzenColumnSeries>
<RadzenColumnSeries Data="@_executionsOverTime"
CategoryProperty="Label"
ValueProperty="Cancelled"
Title="Cancelled"
Fill="#F9A825">
<RadzenSeriesDataLabels Visible="false" />
</RadzenColumnSeries>
<RadzenColumnOptions Margin="2" />
<RadzenCategoryAxis>
<RadzenGridLines Visible="true" />
</RadzenCategoryAxis>
<RadzenValueAxis>
<RadzenGridLines Visible="true" />
</RadzenValueAxis>
<RadzenLegend Position="LegendPosition.Bottom" />
</RadzenChart>
}
else
{
<RadzenStack AlignItems="AlignItems.Center" JustifyContent="JustifyContent.Center" Style="height: 300px;">
<RadzenText TextStyle="TextStyle.Body2" Style="color: var(--rz-text-disabled-color);">No executions in this time range</RadzenText>
@if (DashboardSettings.ShowExecutionsChart)
{
<RadzenColumn Size="12" SizeLG="6">
<RadzenCard>
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.SpaceBetween" AlignItems="AlignItems.Center" class="rz-mb-2">
<RadzenText TextStyle="TextStyle.H6">Executions</RadzenText>
<RadzenSelectBar @bind-Value="_selectedTimeRange" TValue="string" Size="ButtonSize.Small">
<Items>
<RadzenSelectBarItem Text="Last Hour" Value="@TimeRange1H" />
<RadzenSelectBarItem Text="Last 24h" Value="@TimeRange24H" />
</Items>
</RadzenSelectBar>
</RadzenStack>
}
</RadzenCard>
</RadzenColumn>
@if (ExecutionsOverTime.Any(e => e.Completed > 0 || e.Failed > 0 || e.Cancelled > 0))
{
<RadzenChart Style="height: 300px;">
<RadzenColumnSeries Data="@ExecutionsOverTime"
CategoryProperty="Label"
ValueProperty="Completed"
Title="Completed"
Fill="#2E7D32">
<RadzenSeriesDataLabels Visible="false" />
</RadzenColumnSeries>
<RadzenColumnSeries Data="@ExecutionsOverTime"
CategoryProperty="Label"
ValueProperty="Failed"
Title="Failed"
Fill="#C62828">
<RadzenSeriesDataLabels Visible="false" />
</RadzenColumnSeries>
<RadzenColumnSeries Data="@ExecutionsOverTime"
CategoryProperty="Label"
ValueProperty="Cancelled"
Title="Cancelled"
Fill="#F9A825">
<RadzenSeriesDataLabels Visible="false" />
</RadzenColumnSeries>
<RadzenColumnOptions Margin="2" />
<RadzenCategoryAxis Formatter="@FormatCategoryLabel">
<RadzenGridLines Visible="true" />
</RadzenCategoryAxis>
<RadzenValueAxis>
<RadzenGridLines Visible="true" />
</RadzenValueAxis>
<RadzenLegend Position="LegendPosition.Bottom" />
</RadzenChart>
}
else
{
<RadzenStack AlignItems="AlignItems.Center" JustifyContent="JustifyContent.Center" Style="height: 300px;">
<RadzenText TextStyle="TextStyle.Body2" Style="color: var(--rz-text-disabled-color);">No executions in this time range</RadzenText>
</RadzenStack>
}
</RadzenCard>
</RadzenColumn>
}
@if (DashboardSettings.ShowAvgDuration)
{
<RadzenColumn Size="12" SizeLG="6">
<RadzenCard>
<RadzenText TextStyle="TextStyle.H6" class="rz-mb-2">Avg Execution Duration (7d)</RadzenText>
@if (_avgDurations.Count > 0)
{
<RadzenChart Style="height: 300px;">
<RadzenBarSeries Data="@_avgDurations"
CategoryProperty="Name"
ValueProperty="AvgMs"
Title="Avg (ms)"
Fill="#2E7D32">
<RadzenSeriesDataLabels Visible="false" />
</RadzenBarSeries>
<RadzenCategoryAxis>
<RadzenGridLines Visible="true" />
</RadzenCategoryAxis>
<RadzenValueAxis>
<RadzenGridLines Visible="true" />
</RadzenValueAxis>
</RadzenChart>
}
else
{
<RadzenStack AlignItems="AlignItems.Center" JustifyContent="JustifyContent.Center" Style="height: 300px;">
<RadzenText TextStyle="TextStyle.Body2" Style="color: var(--rz-text-disabled-color);">No completed trains in the last 7 days</RadzenText>
</RadzenStack>
}
</RadzenCard>
</RadzenColumn>
}
</RadzenRow>
}

@* ── Failures (Top Failures chart + Recent Failures table) ── *@
@* ── Failures + Throughput ── *@
@if (DashboardSettings.ShowFailures)
{
<RadzenRow Gap="1rem" class="rz-mb-4">
Expand Down Expand Up @@ -190,56 +225,29 @@
</RadzenColumn>
<RadzenColumn Size="12" SizeLG="6">
<RadzenCard>
<RadzenText TextStyle="TextStyle.H6" class="rz-mb-2">Recent Failures</RadzenText>
@if (_recentFailures.Count > 0)
{
<RadzenDataGrid Data="@_recentFailures"
TItem="Metadata"
AllowColumnResize="true"
RowClick="@OnRecentFailureRowClick"
Style="cursor: pointer;"
class="rz-datatable-striped">
<Columns>
<RadzenDataGridColumn TItem="Metadata" Property="Name" Title="Train" Width="180px">
<Template Context="m">@ShortName(m.Name)</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn TItem="Metadata" Property="FailureReason" Title="Reason" />
<RadzenDataGridColumn TItem="Metadata" Property="StartTime" Title="Time" Width="150px" FormatString="{0:MM-dd HH:mm:ss}" />
</Columns>
</RadzenDataGrid>
}
else
{
<RadzenText TextStyle="TextStyle.Body2" Style="color: var(--rz-text-disabled-color); text-align: center; padding: 2rem;">No recent failures</RadzenText>
}
</RadzenCard>
</RadzenColumn>
</RadzenRow>
}

@* ── Avg Execution Duration ── *@
@if (DashboardSettings.ShowAvgDuration)
{
<RadzenRow Gap="1rem" class="rz-mb-4">
<RadzenColumn Size="12">
<RadzenCard>
<RadzenText TextStyle="TextStyle.H6" class="rz-mb-2">Avg Execution Duration (7d)</RadzenText>
@if (_avgDurations.Count > 0)
<RadzenText TextStyle="TextStyle.H6" class="rz-mb-2">Throughput (7d)</RadzenText>
@if (_throughputSeries.Count > 0)
{
<RadzenChart Style="height: 300px;">
<RadzenBarSeries Data="@_avgDurations"
CategoryProperty="Name"
ValueProperty="AvgMs"
Title="Avg (ms)"
Fill="#2E7D32">
<RadzenSeriesDataLabels Visible="false" />
</RadzenBarSeries>
<RadzenCategoryAxis>
@foreach (var series in _throughputSeries)
{
<RadzenLineSeries Data="@series.Points"
CategoryProperty="Label"
ValueProperty="Count"
Title="@series.Name"
Stroke="@series.Color"
StrokeWidth="2"
Smooth="true">
<RadzenSeriesDataLabels Visible="false" />
</RadzenLineSeries>
}
<RadzenCategoryAxis Formatter="@FormatCategoryLabel">
<RadzenGridLines Visible="true" />
</RadzenCategoryAxis>
<RadzenValueAxis>
<RadzenGridLines Visible="true" />
</RadzenValueAxis>
<RadzenLegend Position="LegendPosition.Bottom" />
</RadzenChart>
}
else
Expand Down
Loading