Skip to content

Add aspire export command for telemetry and resource data#14969

Merged
JamesNK merged 11 commits intorelease/13.2from
feature/aspire-export-command
Mar 6, 2026
Merged

Add aspire export command for telemetry and resource data#14969
JamesNK merged 11 commits intorelease/13.2from
feature/aspire-export-command

Conversation

@JamesNK
Copy link
Member

@JamesNK JamesNK commented Mar 5, 2026

Fixes #14820

Description

Add a new aspire export CLI command that exports telemetry and resource data from a running Aspire AppHost to a zip file.

The command connects to a running AppHost via the backchannel, fetches resource snapshots, console logs, structured logs, and traces from the Dashboard API, and organizes them into a zip archive. Data is grouped per resource using resolved resource names (handling replicas correctly):

resources/{resourceName}.json       — Resource snapshot details (indented JSON)
consolelogs/{resourceName}.txt      — Console log output per resource
structuredlogs/{resourceName}.json  — OTLP structured logs per resource (indented JSON)
traces/{resourceName}.json          — OTLP trace spans per resource (indented JSON)

For replica resources, each replica gets its own files using its resolved name (e.g., apiservice-abc, apiservice-def).

Key changes

  • ExportCommand (src/Aspire.Cli/Commands/ExportCommand.cs) — New CLI command with --output, --apphost, and optional resource argument. Groups structured logs and traces per resource by resolved name via TelemetryCommandHelpers.ResolveResourceName.
  • ExportArchive (src/Shared/Export/ExportArchive.cs) — Shared utility for writing telemetry data to zip archives (reusable by Dashboard and CLI). Uses Utf8JsonWriter with indented output and UnsafeRelaxedJsonEscaping for AOT-compatible serialization that preserves non-ASCII characters.
  • Consolidated OtlpJsonSerializerContext (src/Shared/Otlp/Serialization/OtlpJsonSerializerContext.cs) — Single shared source-generated JSON serializer context with #if CLI / #else guards for project-specific types, replacing separate CLI and Dashboard serializer contexts.
  • Shared OTLP types — Moved OtlpTelemetryDataJson, metrics JSON types, OtlpCommonJson extensions, and LogEntrySerializer to shared code for cross-project reuse.
  • Localization — Added ExportCommandStrings.resx with xlf files for all 13 supported languages.
  • Tests — 5 unit tests covering:
    • Zip output with expected per-resource data and content verification
    • --output path handling with nested directory creation
    • --apphost option behavior when AppHost is not running
    • Automatic connection selection with single in-scope connection
    • Replica resources correctly grouped into separate per-resource files

Files changed (54 files, +3068 / -826)

Area Files Summary
CLI command ExportCommand.cs, RootCommand.cs, Program.cs New export command, registration, DI wiring
CLI telemetry helpers TelemetryCommandHelpers.cs, TelemetryLogsCommand.cs, TelemetrySpansCommand.cs, TelemetryTracesCommand.cs Minor refactors to share telemetry resolution logic
CLI MCP tools 3 List*Tool.cs files Updated namespace references for moved types
CLI serialization OtlpCliJsonSerializerContext.cs Reduced to re-export of shared context
Localization ExportCommandStrings.resx, .Designer.cs, 13 .xlf files New resource strings for export command
Dashboard TelemetryExportService.cs, TelemetryApiService.cs, LogEntrySerializer.cs, etc. Refactored to use shared ExportArchive and serializer context
Shared code ExportArchive.cs, LogEntrySerializer.cs, OtlpJsonSerializerContext.cs, OtlpCommonJson.cs, OtlpMetricsJson.cs New and moved shared types
Tests ExportCommandTests.cs + 6 other test files 5 new export tests, updated references in existing tests

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
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
    • No
  • Does the change require an update in our Aspire docs?

@github-actions
Copy link
Contributor

github-actions bot commented Mar 5, 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/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 14969

Or

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

@github-actions
Copy link
Contributor

github-actions bot commented Mar 5, 2026

🎬 CLI E2E Test Recordings

The following terminal recordings are available for commit c6fd421:

Test Recording
AddPackageInteractiveWhileAppHostRunningDetached ▶️ View Recording
AddPackageWhileAppHostRunningDetached ▶️ View Recording
AgentCommands_AllHelpOutputs_AreCorrect ▶️ View Recording
AgentInitCommand_DefaultSelection_InstallsSkillOnly ▶️ View Recording
AgentInitCommand_MigratesDeprecatedConfig ▶️ View Recording
AspireUpdateRemovesAppHostPackageVersionFromDirectoryPackagesProps ▶️ View Recording
Banner_DisplayedOnFirstRun ▶️ View Recording
Banner_DisplayedWithExplicitFlag ▶️ View Recording
CreateAndDeployToDockerCompose ▶️ View Recording
CreateAndDeployToDockerComposeInteractive ▶️ View Recording
CreateAndPublishToKubernetes ▶️ View Recording
CreateAndRunAspireStarterProject ▶️ View Recording
CreateAndRunAspireStarterProjectWithBundle ▶️ View Recording
CreateAndRunJsReactProject ▶️ View Recording
CreateAndRunPythonReactProject ▶️ View Recording
CreateAndRunTypeScriptStarterProject ▶️ View Recording
CreateEmptyAppHostProject ▶️ View Recording
CreateStartAndStopAspireProject ▶️ View Recording
CreateStartWaitAndStopAspireProject ▶️ View Recording
CreateTypeScriptAppHostWithViteApp ▶️ View Recording
DescribeCommandResolvesReplicaNames ▶️ View Recording
DescribeCommandShowsRunningResources ▶️ View Recording
DetachFormatJsonProducesValidJson ▶️ View Recording
DoctorCommand_DetectsDeprecatedAgentConfig ▶️ View Recording
DoctorCommand_WithSslCertDir_ShowsTrusted ▶️ View Recording
DoctorCommand_WithoutSslCertDir_ShowsPartiallyTrusted ▶️ View Recording
LogsCommandShowsResourceLogs ▶️ View Recording
PsCommandListsRunningAppHost ▶️ View Recording
PsFormatJsonOutputsOnlyJsonToStdout ▶️ View Recording
SecretCrudOnDotNetAppHost ▶️ View Recording
SecretCrudOnTypeScriptAppHost ▶️ View Recording
StagingChannel_ConfigureAndVerifySettings_ThenSwitchChannels ▶️ View Recording
StopAllAppHostsFromAppHostDirectory ▶️ View Recording
StopAllAppHostsFromUnrelatedDirectory ▶️ View Recording
StopNonInteractiveMultipleAppHostsShowsError ❌ Upload failed
StopNonInteractiveSingleAppHost ❌ Upload failed
StopWithNoRunningAppHostExitsSuccessfully ❌ Upload failed
TypeScriptAppHostWithProjectReferenceIntegration ▶️ View Recording

📹 Recordings uploaded automatically from CI run #22752687294

@JamesNK JamesNK marked this pull request as ready for review March 5, 2026 11:37
Copilot AI review requested due to automatic review settings March 5, 2026 11:37
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

Adds a new aspire export CLI command to collect resource snapshots, console logs, and OTLP telemetry (logs/traces) from a running AppHost/Dashboard API and package the results into a zip archive. This also refactors OTLP JSON types/serializer context and log serialization into shared code so both the CLI and Dashboard can reuse the same export/serialization pipeline.

Changes:

  • Introduces aspire export command, DI wiring, localization resources, and unit tests for zip output and replica grouping.
  • Adds shared ExportArchive zip writer and consolidates OTLP JSON source-gen serialization context + shared telemetry/resource DTOs.
  • Refactors Dashboard telemetry export and telemetry API serialization to use the shared archive + serializer context.

Reviewed changes

Copilot reviewed 55 out of 56 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/Aspire.Dashboard.Tests/Model/TelemetryImportServiceTests.cs Updates test imports to use shared OTLP serialization namespace.
tests/Aspire.Dashboard.Tests/Model/TelemetryExportServiceTests.cs Updates test imports/serialization to shared OTLP serializer context.
tests/Aspire.Dashboard.Tests/Integration/TelemetryApiTests.cs Switches JSON parsing to shared TelemetryApiResponse type info.
tests/Aspire.Dashboard.Tests/Integration/OtlpHttpJsonTests.cs Updates OTLP serialization imports to shared namespace.
tests/Aspire.Cli.Tests/Utils/CliTestHelper.cs Registers ExportCommand in test DI.
tests/Aspire.Cli.Tests/Mcp/ListTracesToolTests.cs Updates MCP tool tests to shared OTLP types/context (ResourceInfo, OtlpTelemetryDataJson).
tests/Aspire.Cli.Tests/Mcp/ListStructuredLogsToolTests.cs Updates MCP tool tests to shared OTLP types/context.
tests/Aspire.Cli.Tests/Commands/TelemetryTracesCommandTests.cs Updates telemetry command tests to shared OTLP types/context.
tests/Aspire.Cli.Tests/Commands/TelemetryTestHelper.cs Updates helper to serialize ResourceInfo[] via shared context.
tests/Aspire.Cli.Tests/Commands/TelemetrySpansCommandTests.cs Updates telemetry command tests to shared OTLP types/context.
tests/Aspire.Cli.Tests/Commands/TelemetryLogsCommandTests.cs Updates telemetry command tests to shared OTLP types/context.
tests/Aspire.Cli.Tests/Commands/TelemetryCommandTests.cs Renames/updates resource conversion test to ResourceInfo.
tests/Aspire.Cli.Tests/Commands/ExportCommandTests.cs Adds new unit tests covering aspire export zip output, output path handling, apphost option, auto-connection selection, and replica grouping.
src/Shared/Otlp/Serialization/TelemetryApiResponse.cs Adds shared telemetry API response wrapper DTO for OTLP payloads.
src/Shared/Otlp/Serialization/ResourceInfo.cs Adds shared telemetry resource DTO (ResourceInfo) for Dashboard API interop.
src/Shared/Otlp/Serialization/OtlpMetricsJson.cs Moves OTLP metrics JSON model types into shared code.
src/Shared/Otlp/Serialization/OtlpJsonSerializerContext.cs Consolidates source-gen JSON context into shared namespace with #if CLI guards.
src/Shared/Otlp/Serialization/OtlpCommonJson.cs Moves OtlpTelemetryDataJson into shared OTLP common types.
src/Shared/Export/ExportArchive.cs Adds shared zip archive writer for exporting resources/telemetry (CLI + Dashboard reuse).
src/Shared/ConsoleLogs/LogEntrySerializer.cs Moves/renames namespace to shared console log serializer.
src/Aspire.Dashboard/Otlp/Model/Serialization/OtlpMetricsJson.cs Removes Dashboard-local OTLP metrics JSON types (now shared).
src/Aspire.Dashboard/Otlp/Model/Serialization/OtlpCommonJson.cs Removes Dashboard-local OtlpTelemetryDataJson (now shared).
src/Aspire.Dashboard/Otlp/Http/OtlpJsonConverters.cs Updates imports to shared OTLP serialization types.
src/Aspire.Dashboard/Model/TelemetryExportService.cs Refactors Dashboard export flow to populate ExportArchive instead of writing ZipArchive directly.
src/Aspire.Dashboard/Model/Assistant/AIHelpers.cs Updates imports to shared OTLP serialization namespace.
src/Aspire.Dashboard/DashboardEndpointsBuilder.cs Updates telemetry API endpoints to serialize responses using shared TelemetryApiResponse type info.
src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs Updates console log serializer namespace usage to shared.
src/Aspire.Dashboard/Aspire.Dashboard.csproj Links new shared export + OTLP serialization files into Dashboard build.
src/Aspire.Dashboard/Api/TelemetryApiService.cs Switches telemetry API service to shared TelemetryApiResponse and removes old local DTO definitions.
src/Aspire.Cli/Resources/xlf/ExportCommandStrings.cs.xlf Adds localization entries for export command (cs).
src/Aspire.Cli/Resources/xlf/ExportCommandStrings.de.xlf Adds localization entries for export command (de).
src/Aspire.Cli/Resources/xlf/ExportCommandStrings.es.xlf Adds localization entries for export command (es).
src/Aspire.Cli/Resources/xlf/ExportCommandStrings.fr.xlf Adds localization entries for export command (fr).
src/Aspire.Cli/Resources/xlf/ExportCommandStrings.it.xlf Adds localization entries for export command (it).
src/Aspire.Cli/Resources/xlf/ExportCommandStrings.ja.xlf Adds localization entries for export command (ja).
src/Aspire.Cli/Resources/xlf/ExportCommandStrings.ko.xlf Adds localization entries for export command (ko).
src/Aspire.Cli/Resources/xlf/ExportCommandStrings.pl.xlf Adds localization entries for export command (pl).
src/Aspire.Cli/Resources/xlf/ExportCommandStrings.pt-BR.xlf Adds localization entries for export command (pt-BR).
src/Aspire.Cli/Resources/xlf/ExportCommandStrings.ru.xlf Adds localization entries for export command (ru).
src/Aspire.Cli/Resources/xlf/ExportCommandStrings.tr.xlf Adds localization entries for export command (tr).
src/Aspire.Cli/Resources/xlf/ExportCommandStrings.zh-Hans.xlf Adds localization entries for export command (zh-Hans).
src/Aspire.Cli/Resources/xlf/ExportCommandStrings.zh-Hant.xlf Adds localization entries for export command (zh-Hant).
src/Aspire.Cli/Resources/ExportCommandStrings.resx Adds CLI resource strings for export command.
src/Aspire.Cli/Resources/ExportCommandStrings.Designer.cs Adds generated strongly-typed resource wrapper for export command strings.
src/Aspire.Cli/Program.cs Registers ExportCommand in CLI host DI.
src/Aspire.Cli/Otlp/OtlpCliJsonSerializerContext.cs Removes CLI-specific serializer context (replaced by shared context).
src/Aspire.Cli/Mcp/Tools/ListTracesTool.cs Updates MCP traces tool to shared OtlpJsonSerializerContext and DTOs.
src/Aspire.Cli/Mcp/Tools/ListTraceStructuredLogsTool.cs Updates MCP structured logs tool to shared OtlpJsonSerializerContext and DTOs.
src/Aspire.Cli/Mcp/Tools/ListStructuredLogsTool.cs Updates MCP structured logs tool to shared OtlpJsonSerializerContext and DTOs.
src/Aspire.Cli/Commands/TelemetryTracesCommand.cs Updates deserialization to shared OtlpJsonSerializerContext.
src/Aspire.Cli/Commands/TelemetrySpansCommand.cs Updates deserialization to shared OtlpJsonSerializerContext.
src/Aspire.Cli/Commands/TelemetryLogsCommand.cs Updates deserialization to shared OtlpJsonSerializerContext.
src/Aspire.Cli/Commands/TelemetryCommandHelpers.cs Updates telemetry resource DTO usage to shared ResourceInfo and shared serializer context.
src/Aspire.Cli/Commands/RootCommand.cs Adds export as a root subcommand.
src/Aspire.Cli/Commands/ExportCommand.cs Adds new aspire export command implementation (resource + telemetry export to zip).
src/Aspire.Cli/Aspire.Cli.csproj Links shared export/OTLP serialization files + adds resx integration for export strings.
Files not reviewed (1)
  • src/Aspire.Cli/Resources/ExportCommandStrings.Designer.cs: Language not supported

@davidfowl
Copy link
Contributor

davidfowl commented Mar 6, 2026

PR Testing Report - aspire export E2E Validation

CLI Version: 13.2.0-pr.14969.g500867c4 (commit 500867c4)
Environment: Linux x86_64, Node.js 22.22.1

Full E2E Lifecycle Test

Created a TypeScript starter project (aspire-ts-starter with Express API + React frontend) and ran the complete lifecycle:

Step Command Result
1 aspire new aspire-ts-starter Pass - Project created
2 aspire start Pass - AppHost started in background
3 aspire wait app / aspire wait frontend Pass - Both resources healthy
4 aspire describe Pass - 4 resources listed (app, frontend, 2 installers)
5 curl /api/weatherforecast x5 + frontend x3 Pass - All HTTP 200, generated telemetry
6 aspire export (full) Pass - Zip with 8 files: 4 resources json + 4 consolelogs txt
7 aspire export app (resource filter) Pass - Zip filtered to only app resource + logs
8 aspire export nonexistent Pass - Error: Resource not found (exit code 1)
9 aspire export --output nested/dir/out.zip Pass - Nested directories auto-created
10 aspire export (no running AppHost) Pass - Friendly message, no crash
11 aspire export --help Pass - Shows resource arg, --output, --apphost options
12 aspire stop Pass - AppHost stopped cleanly
13 aspire logs / aspire --version / aspire --help Pass - No regressions in existing commands

Export Content Verification

Extracted and inspected zip contents:

  • resources/app.json - Well-formed indented JSON with resource name, type, state, health status, endpoints, environment variables, relationships, and commands
  • consolelogs/app.txt - Timestamped console output including wait-for-dependency messages and Express startup
  • consolelogs/frontend.txt - Timestamped Vite dev server startup logs
  • resources/app-installer.json / resources/frontend-installer.json - Installer lifecycle captured correctly

No structuredlogs/ or traces/ directories were present in the zip. This is expected for a Node.js Express app without an OTLP SDK configured. The command handled this gracefully (no errors).

Result: All scenarios passed

JamesNK added 11 commits March 6, 2026 14:53
Adds a new 'aspire export' CLI command that saves telemetry and resource
data to a zip file. The command connects to a running AppHost via the
backchannel, fetches resource snapshots, console logs, structured logs,
and traces from the Dashboard API, and writes them into an organized zip
archive.

Changes:
- Add ExportCommand with --output, --apphost, and resource argument
- Add TelemetryArchiveWriter shared utility for zip archive writing
- Move OTLP metrics/telemetry JSON types to shared code for CLI reuse
- Add ExportCommandStrings resource files with localization support
- Add ExportCommandTests with 4 unit tests covering zip output,
  --output path, --apphost option, and connection auto-selection
- Register ExportCommand in CLI test DI container
- Move TelemetryApiResponse and ResourceInfo to src/Shared/Otlp/Serialization
- Remove duplicate type definitions from Dashboard (TelemetryApiService.cs) and CLI (OtlpCliJsonSerializerContext.cs)
- Delete redundant Dashboard partial OtlpJsonSerializerContext.cs, consolidate into shared file with #if !CLI for Dashboard-specific types
- Add [JsonPropertyName] attributes for consistency with other shared OTLP types
- Update all references in source and test files
…d code, use TimeProvider, broaden error handling
@JamesNK JamesNK force-pushed the feature/aspire-export-command branch from ad59466 to c6fd421 Compare March 6, 2026 06:54
@JamesNK JamesNK merged commit c6dc1b5 into release/13.2 Mar 6, 2026
385 checks passed
@JamesNK JamesNK deleted the feature/aspire-export-command branch March 6, 2026 07:16
@dotnet-policy-service dotnet-policy-service bot added this to the 13.2 milestone Mar 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants