Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add details column to trace view, remove status badge and put counter badge on resource name #1788

Merged
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
4 changes: 2 additions & 2 deletions src/Aspire.Dashboard/Components/Pages/Resources.razor
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@
<ChildContent>
<PropertyColumn Title="@Loc[nameof(Dashboard.Resources.Resources.ResourcesTypeColumnHeader)]" Property="@(c => c.ResourceType)" Sortable="true" />
<TemplateColumn Title="@ControlsStringsLoc[nameof(ControlsStrings.NameColumnHeader)]" Sortable="true" SortBy="@_nameSort">
<ResourceNameDisplay Resource="context" FilterText="@_filter" FormatName="GetResourceName" />
<ResourceNameDisplay Resource="context" FilterText="@_filter" FormatName="GetResourceName" UnviewedErrorCounts="@_applicationUnviewedErrorCounts" />
</TemplateColumn>
<TemplateColumn Title="@Loc[nameof(Dashboard.Resources.Resources.ResourcesStateColumnHeader)]" Sortable="true" SortBy="@_stateSort">
<StateColumnDisplay UnviewedErrorCounts="@_applicationUnviewedErrorCounts" Resource="@context" />
<StateColumnDisplay Resource="@context"/>
</TemplateColumn>
<PropertyColumn Property="@(c => c.CreationTimeStamp)" Title="@Loc[nameof(Dashboard.Resources.Resources.ResourcesStartTimeColumnHeader)]" Sortable="true" Tooltip="true" />
<TemplateColumn Title="@Loc[nameof(Dashboard.Resources.Resources.ResourcesSourceColumnHeader)]">
Expand Down
2 changes: 1 addition & 1 deletion src/Aspire.Dashboard/Components/Pages/Resources.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,5 +182,5 @@ public void Dispose()
}

private string? GetRowClass(ResourceViewModel resource)
=> resource == SelectedResource ? "selected-row" : null;
=> resource == SelectedResource ? "selected-row resource-row" : "resource-row";
}
8 changes: 3 additions & 5 deletions src/Aspire.Dashboard/Components/Pages/Resources.razor.css
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
::deep .resource-state-container {
display: flex;
align-items: center;
}

::deep .resource-state-badge {
padding: 0 3px;
cursor: pointer;
Expand All @@ -18,3 +13,6 @@
margin-left: 3px;
}

::deep .resource-row > fluent-data-grid-cell {
overflow: visible;
}
2 changes: 1 addition & 1 deletion src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
</a>
}
</TemplateColumn>
<TemplateColumn Title="@Loc[nameof(Dashboard.Resources.StructuredLogs.StructuredLogsDetailsColumnHeader)]">
<TemplateColumn Title="@ControlsStringsLoc[nameof(ControlsStrings.DetailsColumnHeader)]">
<FluentButton Appearance="Appearance.Lightweight" OnClick="() => OnShowProperties(context)">@ControlsStringsLoc[nameof(ControlsStrings.ViewAction)]</FluentButton>
</TemplateColumn>
</ChildContent>
Expand Down
10 changes: 7 additions & 3 deletions src/Aspire.Dashboard/Components/Pages/TraceDetail.razor
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
@page "/Trace/{traceId}"
@page "/Trace/{traceId}/Span/{spanId}"

@using Aspire.Dashboard.Model
@using Aspire.Dashboard.Model.Otlp
@using Aspire.Dashboard.Otlp.Model
@using System.Globalization
@using Aspire.Dashboard.Resources
@inject IStringLocalizer<Dashboard.Resources.TraceDetail> Loc
@inject IStringLocalizer<ControlsStrings> ControlStringsLoc
@inject IDashboardClient DashboardClient

<PageTitle><ApplicationName ResourceName="@nameof(Dashboard.Resources.TraceDetail.TraceDetailPageTitle)" Loc="@Loc" /></PageTitle>

Expand Down Expand Up @@ -53,7 +51,7 @@
</div>
</DetailsTitleTemplate>
<Summary>
<FluentDataGrid Class="trace-view-grid" ResizableColumns="true" ItemsProvider="@GetData" TGridItem="SpanWaterfallViewModel" RowClass="@GetRowClass" GridTemplateColumns="2fr 6fr">
<FluentDataGrid Class="trace-view-grid" ResizableColumns="true" ItemsProvider="@GetData" TGridItem="SpanWaterfallViewModel" RowClass="@GetRowClass" GridTemplateColumns="4fr 12fr 85px">
<TemplateColumn Title="Name">
<div class="col-long-content" title="@context.GetTooltip()" @onclick="() => OnShowProperties(context)">
@{
Expand Down Expand Up @@ -126,6 +124,12 @@
</div>
</ChildContent>
</TemplateColumn>
<TemplateColumn Title="@ControlStringsLoc[nameof(ControlsStrings.DetailsColumnHeader)]">
<FluentButton
Style="margin-left: 7px;"
Title="@ControlStringsLoc[nameof(ControlsStrings.ViewAction)]"
Appearance="Appearance.Lightweight" OnClick="() => OnShowProperties(context)">@ControlStringsLoc[nameof(ControlsStrings.ViewAction)]</FluentButton>
</TemplateColumn>
</FluentDataGrid>
</Summary>
<Details>
Expand Down
2 changes: 1 addition & 1 deletion src/Aspire.Dashboard/Components/Pages/Traces.razor
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
</div>
</TemplateColumn>

<TemplateColumn Title="@Loc[nameof(Dashboard.Resources.Traces.TracesDetailsColumnHeader)]">
<TemplateColumn Title="@ControlsStringsLoc[nameof(ControlsStrings.DetailsColumnHeader)]">
<FluentAnchor Appearance="Appearance.Lightweight" Href="@($"/Trace/{context.TraceId}")">@ControlsStringsLoc[nameof(ControlsStrings.ViewAction)]</FluentAnchor>
</TemplateColumn>
</ChildContent>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
@using Aspire.Dashboard.Model
@namespace Aspire.Dashboard.Components

@using Aspire.Dashboard.Model
@using Aspire.Dashboard.Otlp.Model
@using Aspire.Dashboard.Resources
@inject IStringLocalizer<Columns> Loc

<FluentStack Orientation="Orientation.Horizontal" VerticalAlignment="VerticalAlignment.Center">
<span><FluentHighlighter HighlightedText="@FilterText" Text="@FormatName(Resource)" /></span>
</FluentStack>
@{
var unviewedErrorCount = GetUnviewedErrorCount(Resource);
}

@if (unviewedErrorCount > 0)
{
<FluentCounterBadge Class="error-counter-badge" Max="9" BackgroundColor="@Color.Error" Color="Color.Fill" Appearance="Appearance.Lightweight" Count="@unviewedErrorCount" HorizontalPosition="100">
<a href="@GetResourceErrorStructuredLogsUrl(Resource)" title="@FormatLogLinkTitle(unviewedErrorCount)"><FluentHighlighter HighlightedText="@FilterText" Text="@FormatName(Resource)" /></a>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can imagine that having the resource's name link to its logs would be good for all resources, not just those with errors.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@drewnoakes do you think links appearing for all resources would be noisy?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would probably be noisey. It's something to think about in the future. The PR is good as it is.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need to link to the logs from the resource name now that we're reinstated the "view logs" button?

</FluentCounterBadge>
}
else
{
<span title="@FormatName(Resource)"><FluentHighlighter HighlightedText="@FilterText" Text="@FormatName(Resource)"/></span>
}

@code {
[Parameter, EditorRequired]
Expand All @@ -15,4 +29,7 @@

[Parameter, EditorRequired]
public required string FilterText { get; set; }

[Parameter, EditorRequired]
public required Dictionary<OtlpApplication, int>? UnviewedErrorCounts { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Globalization;
using Aspire.Dashboard.Model;
using Aspire.Dashboard.Otlp.Storage;
using Aspire.Dashboard.Resources;
using Microsoft.AspNetCore.Components;

namespace Aspire.Dashboard.Components;

public partial class ResourceNameDisplay
{
[Inject]
public required TelemetryRepository TelemetryRepository { get; init; }

private int GetUnviewedErrorCount(ResourceViewModel resource)
{
if (UnviewedErrorCounts is null)
{
return 0;
}

var application = TelemetryRepository.GetApplication(resource.Uid);
return application is null ? 0 : UnviewedErrorCounts.GetValueOrDefault(application, 0);
}

private static string GetResourceErrorStructuredLogsUrl(ResourceViewModel resource)
{
return $"/StructuredLogs/{resource.Uid}?level=error";
}

private string FormatLogLinkTitle(int unviewedErrorCount)
{
return FormatName(Resource) + Environment.NewLine + string.Format(CultureInfo.CurrentCulture, Loc[nameof(Columns.UnreadLogErrors)], unviewedErrorCount);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,35 @@
@using Aspire.Dashboard.Resources
@inject IStringLocalizer<Columns> Loc

<div class="resource-state-container">
@if (Resource is { State: ResourceStates.ExitedState /* containers */ or ResourceStates.FinishedState /* executables */ })
@if (Resource is { State: ResourceStates.ExitedState /* containers */ or ResourceStates.FinishedState /* executables */ })
{
if (Resource.TryGetExitCode(out int exitCode) && exitCode is not 0)
{
if (Resource.TryGetExitCode(out int exitCode) && exitCode is not 0)
{
<!-- process completed unexpectedly, hence the non-zero code. this is almost certainly an error, so warn users -->
<FluentIcon Title="@string.Format(Loc[Columns.StateColumnResourceExitedUnexpectedly], Resource.ResourceType, exitCode)"
Icon="Icons.Filled.Size16.ErrorCircle"
Color="Color.Error"
Class="severity-icon" />
}
else
{
<!-- process completed, which may not have been unexpected -->
<FluentIcon Title="@string.Format(Loc[Columns.StateColumnResourceExited], Resource.ResourceType)"
Icon="Icons.Filled.Size16.Warning"
Color="Color.Warning"
Class="severity-icon" />
}
<!-- process completed unexpectedly, hence the non-zero code. this is almost certainly an error, so warn users -->
<FluentIcon Title="@string.Format(Loc[Columns.StateColumnResourceExitedUnexpectedly], Resource.ResourceType, exitCode)"
Icon="Icons.Filled.Size16.ErrorCircle"
Color="Color.Error"
Class="severity-icon"/>
}
else
{
<!-- process completed, which may not have been unexpected -->
<FluentIcon Title="@string.Format(Loc[Columns.StateColumnResourceExited], Resource.ResourceType)"
Icon="Icons.Filled.Size16.Warning"
Color="Color.Warning"
Class="severity-icon"/>
}
}
else
{
<FluentIcon Icon="Icons.Filled.Size16.CheckmarkCircle"
Color="Color.Success"
Class="severity-icon"/>
}

@Resource.State

@Resource.State
<UnreadLogErrorsBadge UnviewedErrorCounts="UnviewedErrorCounts" Resource="@Resource" />
</div>
@code {
[Parameter, EditorRequired]
public required ResourceViewModel Resource { get; set; }
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
@using Aspire.Dashboard.Model
@using Aspire.Dashboard.Resources
@inject IStringLocalizer<Columns> Loc

@if (Resource is { State: ResourceStates.ExitedState /* containers */ or ResourceStates.FinishedState /* executables */ })
{
if (Resource.TryGetExitCode(out int exitCode) && exitCode is not 0)
{
<!-- process completed unexpectedly, hence the non-zero code. this is almost certainly an error, so warn users -->
<FluentIcon Title="@string.Format(Loc[Columns.StateColumnResourceExitedUnexpectedly], Resource.ResourceType, exitCode)"
Icon="Icons.Filled.Size16.ErrorCircle"
Color="Color.Error"
Class="severity-icon"/>
}
else
{
<!-- process completed, which may not have been unexpected -->
<FluentIcon Title="@string.Format(Loc[Columns.StateColumnResourceExited], Resource.ResourceType)"
Icon="Icons.Filled.Size16.Warning"
Color="Color.Warning"
Class="severity-icon"/>
}
}
else
{
<FluentIcon Icon="Icons.Filled.Size16.CheckmarkCircle"
Color="Color.Success"
Class="severity-icon"/>
}

@Resource.State

@code {
[Parameter, EditorRequired]
public required ResourceViewModel Resource { get; set; }
}

This file was deleted.

This file was deleted.

15 changes: 3 additions & 12 deletions src/Aspire.Dashboard/Resources/Columns.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 2 additions & 6 deletions src/Aspire.Dashboard/Resources/Columns.resx
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,8 @@
<data name="SourceColumnSourceCopyContainerToClipboard" xml:space="preserve">
<value>Copy image name and tag to clipboard</value>
</data>
<data name="UnreadLogErrorsBadgeErrorLog" xml:space="preserve">
<value>{0} error log</value>
<comment>{0} is 1</comment>
</data>
<data name="UnreadLogErrorsBadgeErrorLogs" xml:space="preserve">
<value>{0} error logs</value>
<data name="UnreadLogErrors" xml:space="preserve">
<value>{0} errors</value>
<comment>{0} is a number</comment>
</data>
<data name="StateColumnResourceExitedUnexpectedly" xml:space="preserve">
Expand Down
Loading