Skip to content

feat: added CSV export option to console logs download menu#18639

Open
IsxImattI wants to merge 9 commits into
microsoft:mainfrom
IsxImattI:feature/csv-export-console-logs
Open

feat: added CSV export option to console logs download menu#18639
IsxImattI wants to merge 9 commits into
microsoft:mainfrom
IsxImattI:feature/csv-export-console-logs

Conversation

@IsxImattI

Copy link
Copy Markdown

Description

Added a "Download as CSV" option to the console logs page alongside the existing "Download as text" option, both nested under a "Download" submenu.

Changes:

  • Added WriteLogEntriesToCsvStream to LogEntrySerializer with RFC 4180 escaping. CSV columns: Resource, Timestamp, Message

  • Split single download menu item into a submenu with "Download as text" and "Download as CSV" options

  • Added localized strings in ConsoleLogs.resx / ConsoleLogs.Designer.cs

  • XLF files auto-synced via XliffTasks (state="new", expected)

  • Added 7 unit tests for CSV serialization covering header, columns, escaping, pause skipping

Fixes #11121

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

@IsxImattI IsxImattI requested a review from JamesNK as a code owner July 4, 2026 13:36
Copilot AI review requested due to automatic review settings July 4, 2026 13:36
@IsxImattI IsxImattI requested a review from adamint as a code owner July 4, 2026 13:36
@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

🚀 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 -- 18639

Or

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 implements issue #11121 by adding a "Download as CSV" option to the dashboard console logs page, alongside the existing text download, both grouped under a "Download" submenu. The core addition is a new WriteLogEntriesToCsvStream serializer (Resource, Timestamp, Message columns with RFC 4180 escaping) that reuses the existing shared LogEntrySerializer and browser download infrastructure, so it fits cleanly into the established dashboard menu/download patterns.

Changes:

  • Added WriteLogEntriesToCsvStream (with RFC 4180 field escaping) to the shared LogEntrySerializer, stripping the inline timestamp into its own column.
  • Restructured the single download menu item into a parent "Download" item with nested "Download as text" / "Download as CSV" entries, and split the download handler in two with an extension-aware GetFileName.
  • Added localized strings (.resx, .Designer.cs, all .xlf cultures) and 7 unit tests covering header, columns, escaping, and pause-skipping.

Reviewed changes

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

Show a summary per file
File Description
src/Shared/ConsoleLogs/LogEntrySerializer.cs Adds the CSV serializer and RFC 4180 field-escaping helper.
src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs Converts download to a submenu and adds the CSV download handler / extension-parameterized filename.
src/Aspire.Dashboard/Resources/ConsoleLogs.resx Adds neutral DownloadLogsAsText / DownloadLogsAsCsv strings.
src/Aspire.Dashboard/Resources/ConsoleLogs.Designer.cs Adds designer accessors for the two new strings.
src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.*.xlf (13 files) Auto-synced XLF entries (state="new") for the new strings.
tests/Aspire.Dashboard.Tests/ConsoleLogsTests/LogEntrySerializerTests.cs New unit tests for CSV header, columns, escaping, and pause skipping.
Files not reviewed (1)
  • src/Aspire.Dashboard/Resources/ConsoleLogs.Designer.cs: Generated file

Comment thread src/Shared/ConsoleLogs/LogEntrySerializer.cs
Comment thread src/Shared/ConsoleLogs/LogEntrySerializer.cs Outdated
@IsxImattI

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

[
new()
{
OnClick = DownloadTextLogsAsync,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I’m going to carry the parent disabled condition onto these child download items too. Otherwise the submenu actions can still be invoked when no resource is selected and we are not subscribed to all logs, which gets into the filename path that assumes a selected resource.

}

private static readonly char[] s_csvSpecialChars = [',', '"', '\r', '\n'];
private static readonly char[] s_formulaInjectionChars = ['=', '+', '-', '@', '\t', '\r'];

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I’m going to include \n in this guard and add a regression test. A field that starts with LF before formula-looking content can still be opened by spreadsheet tools as formula content after line normalization.

Copilot AI review requested due to automatic review settings July 4, 2026 17:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

Files not reviewed (1)
  • src/Aspire.Dashboard/Resources/ConsoleLogs.Designer.cs: Generated file
  • Files reviewed: 17/18 changed files
  • Comments generated: 0 new
  • Review effort level: Medium

@davidfowl davidfowl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Performance review: 2 findings.

var stream = new MemoryStream();
lock (_updateLogsLock)
{
LogEntrySerializer.WriteLogEntriesToCsvStream(_logEntries.GetEntries(), stream);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This serializes the entire CSV while holding _updateLogsLock, which is also the lock used by StartLogEntryChannelReaderTask for live log ingestion. For a large configured log buffer, the export can block incoming log batches/UI updates for all timestamp stripping, CSV escaping, and stream writes. Consider snapshotting the entries under the lock and doing the CSV serialization after releasing it.

writer.Write(',');
writer.Write(EscapeCsvField(timestamp));
writer.Write(',');
writer.Write(EscapeCsvField(entry.GetStrippedLogContent() ?? string.Empty));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

GetStrippedLogContent() memoizes the stripped message on the LogEntry. A CSV download is a one-off export, but this call populates _strippedLogContent for every retained row and keeps another full message string alive until the entry is evicted or logs are cleared. Consider using a non-caching strip path for export so downloading CSV doesn't permanently increase the dashboard's log-buffer working set.

@IsxImattI IsxImattI force-pushed the feature/csv-export-console-logs branch from b4eabf6 to 6686271 Compare July 6, 2026 15:42
adamint added 2 commits July 6, 2026 11:32
…console-logs

# Conflicts:
#	src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs
…gs' into feature/csv-export-console-logs

# Conflicts:
#	src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs
#	src/Shared/ConsoleLogs/LogEntrySerializer.cs
#	tests/Aspire.Dashboard.Tests/ConsoleLogsTests/LogEntrySerializerTests.cs
: string.Join("_", PageViewModel.SelectedResource.Id!.InstanceId!.Split(Path.GetInvalidFileNameChars()));

return $"{fileNamePrefix}-{TimeProvider.GetLocalNow().ToString("yyyyMMddhhmmss", CultureInfo.InvariantCulture)}.txt";
return $"{fileNamePrefix}-{TimeProvider.GetLocalNow().ToString("yyyyMMddhhmmss", CultureInfo.InvariantCulture)}.{extension}";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

One small thing I found while testing this path: this uses hh, so the generated filenames are 12-hour timestamps without AM/PM. That can collide or be ambiguous between morning and evening exports. I'll switch it to HH while we're already touching this filename helper.

Use a 24-hour timestamp in console log export filenames so afternoon exports do not collide with morning exports.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 6, 2026 18:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

Files not reviewed (1)
  • src/Aspire.Dashboard/Resources/ConsoleLogs.Designer.cs: Generated file
  • Files reviewed: 20/21 changed files
  • Comments generated: 0 new
  • Review effort level: Medium

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Provide CSV export option in dashboard console logs

4 participants