Skip to content

Render publish summary hierarchy and timeline#15530

Open
sebastienros wants to merge 4 commits intomicrosoft:mainfrom
sebastienros:sebros/publish-steps-hierarchy
Open

Render publish summary hierarchy and timeline#15530
sebastienros wants to merge 4 commits intomicrosoft:mainfrom
sebastienros:sebros/publish-steps-hierarchy

Conversation

@sebastienros
Copy link
Contributor

@sebastienros sebastienros commented Mar 24, 2026

Description

Organizes the aspire do publish step summary hierarchically instead of sorting steps by duration alone.

It also adds a compact Unicode timeline ruler and per-step bars so the summary shows when each step starts and finishes while keeping the same number of step lines.

To support the display, the pipeline now includes display-parent and level metadata for publish steps, and the CLI uses that metadata when rendering the summary.

Examples:

image image

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No
  • Does the change require an update in our Aspire docs?

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 24, 2026 15:15
@github-actions
Copy link
Contributor

github-actions bot commented Mar 24, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 15530

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 15530"

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR enhances aspire do publish step summaries by rendering steps in a hierarchical (parent/child) order and adding a compact timeline ruler + per-step bars to visualize when each step starts/finishes. It does so by emitting hierarchy metadata from the hosting pipeline and consuming it in the CLI summary renderer.

Changes:

  • Add ParentStepId / HierarchyLevel metadata to publishing step activities and propagate it from pipeline execution.
  • Update CLI summary rendering to order steps hierarchically and display a timeline scale with per-step bars.
  • Add/extend unit tests for hierarchy metadata emission and timeline/tree rendering.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/Aspire.Hosting.Tests/Publishing/PipelineActivityReporterTests.cs Adds coverage ensuring hierarchy metadata is emitted on step create/complete activities.
tests/Aspire.Cli.Tests/Utils/ConsoleActivityLoggerTests.cs Adds assertions for hierarchical ordering and timeline ruler/bar output in summaries.
src/Aspire.Hosting/Pipelines/ReportingStep.cs Stores parent step id + hierarchy level on the reporting step instance.
src/Aspire.Hosting/Pipelines/PipelineActivityReporter.cs Emits hierarchy metadata in step activities via a shared activity-data builder.
src/Aspire.Hosting/Pipelines/DistributedApplicationPipeline.cs Computes display hierarchy from DAG dependencies and supplies parent/level metadata when creating reporting steps.
src/Aspire.Hosting/Backchannel/BackchannelDataTypes.cs Extends backchannel activity payload with ParentStepId and HierarchyLevel.
src/Aspire.Cli/Utils/ConsoleActivityLogger.cs Implements hierarchical ordering + timeline ruler/bars in the “Steps Summary” output.
src/Aspire.Cli/Commands/PipelineCommandBase.cs Captures hierarchy metadata from activities and populates duration records with offsets for timeline rendering.

sebastienros and others added 2 commits March 24, 2026 08:27
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Member

@adamint adamint left a comment

Choose a reason for hiding this comment

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

I like it, works well with multiple hierarchy levels too

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@JamesNK
Copy link
Member

JamesNK commented Mar 24, 2026

Nice.

I noticed the ticks at the top of the summary aren't consistently placed:
image

@JamesNK
Copy link
Member

JamesNK commented Mar 24, 2026

What happens with long step names when there isn't enough room:
image

@JamesNK
Copy link
Member

JamesNK commented Mar 24, 2026

How deeply can things be nested? If something is nested 10 levels deep, what is displayed? It seems like text would be completely out of view because of indenting.

var timelineLabelPrefix = $" {new string(' ', durationWidth)} {"Step timeline:".PadRight(nameWidth)} ";

_console.WriteLine();
_console.MarkupLine("Steps Summary:");
Copy link
Member

Choose a reason for hiding this comment

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

Move text to a resource file

{
var orderedRecords = OrderStepDurationsHierarchically(records);
var durationWidth = Math.Max(10, orderedRecords.Max(r => DurationFormatter.FormatDuration(r.Duration, CultureInfo.InvariantCulture, DecimalDurationDisplay.Fixed).Length));
var nameWidth = Math.Max("Step timeline:".Length, orderedRecords.Max(r => GetIndentedDisplayName(r).Length));
Copy link
Member

Choose a reason for hiding this comment

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

Move text to a resource file


private static string BuildTimelineLabels(TimeSpan totalTimeline, int width)
{
var startText = "0s";
Copy link
Member

Choose a reason for hiding this comment

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

Rather than hardcode "0s", what most timelines do (including the dashboard) is using the highest unit. That means if the highest time is still in ms, then the start should be "0ms"

For example:

ms:
Image

s:
Image


if (startIndex == endIndex)
{
chars[startIndex] = '●';
Copy link
Member

Choose a reason for hiding this comment

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

Is this for very small duration? What does it look like?

Maybe add some more comments to these methods.

Comment on lines +468 to +476
/// <summary>
/// Gets the identifier of the parent step used for hierarchical step summaries.
/// </summary>
public string? ParentStepId { get; init; }

/// <summary>
/// Gets the hierarchical level of the step used for display purposes.
/// </summary>
public int? HierarchyLevel { get; init; }
Copy link
Member

Choose a reason for hiding this comment

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

What happens if a new CLI is run against an old app host that doesn't return this data?

@JamesNK
Copy link
Member

JamesNK commented Mar 24, 2026

In the dashboard I found it useful to have a stress project that would generate extreme results that I could use to test the UI. I think you need something like that to test this timeline.

I added an internal aspire render command for testing rendering various things. I think you could add an option to render this timeline with static data for various scenarios: deeply nested steps, very long text, text containing markup, mixing in steps without parents, very long and very short durations, etc.

Use your imagination and try hard to break the UI with extreme situations. That's the only way to create something that consistently works for everyone.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants