Skip to content

Display UI to view app host logs in extension#17465

Open
JamesNK wants to merge 1 commit into
mainfrom
jnewman/apphost-logs-ui
Open

Display UI to view app host logs in extension#17465
JamesNK wants to merge 1 commit into
mainfrom
jnewman/apphost-logs-ui

Conversation

@JamesNK
Copy link
Copy Markdown
Member

@JamesNK JamesNK commented May 25, 2026

Summary

aspire ps now includes the app host log file path in JSON output. This PR adds UI in the extension to surface it.

extensions-log-path.mp4

I also removed the PID tree items. They don't seem like high value information. Instead, they're now accessible by right clicking the apphost and choosing "View source". This gives a complete JSON breakdown of all the apphost information.

Changes

  • AppHost logs tree item: When logFilePath is present in the aspire ps output, an "AppHost logs" item appears under the app host in the tree view. Clicking it opens the log file in VS Code.
  • Context menu on log file item: Right-click offers "Open AppHost logs file" and "Copy Path".
  • View source: New "View source" context menu on appHost/workspaceResources items opens a readonly JSON document showing the raw aspire ps data for that app host instance.
  • Removed PID tree items: AppHost PID and CLI PID are no longer shown as child tree items (the PID is still visible in the appHost item description).

Fixes #17460

Copilot AI review requested due to automatic review settings May 25, 2026 07:26
@JamesNK JamesNK requested a review from adamint as a code owner May 25, 2026 07:26
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 25, 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 -- 17465

Or

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

Copy link
Copy Markdown
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 updates the Aspire VS Code extension’s running AppHosts tree to surface the AppHost log file path (when provided by aspire ps JSON output) and adds a “View source” action to inspect the raw aspire ps data for an AppHost instance.

Changes:

  • Add an “AppHost logs” tree item (when logFilePath is present) that opens the log file, plus context menu actions to open/copy the path.
  • Add a “View source” context menu action for AppHost/workspace items that opens a virtual JSON document containing the raw aspire ps data.
  • Remove PID child tree items (AppHost PID / CLI PID) from the tree.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
extension/src/views/AspireAppHostTreeProvider.ts Removes PID child nodes; adds LogFileItem, new commands, and a TextDocumentContentProvider-backed “View source” virtual document.
extension/src/views/AppHostDataRepository.ts Extends AppHostDisplayInfo to include optional logFilePath.
extension/src/loc/strings.ts Adds localized label for the log-file tree item.
extension/src/extension.ts Registers new commands for viewing AppHost source and opening/copying the log file path; removes PID copy command registration.
extension/package.nls.json Updates localized command titles (replaces Copy ID with View source; adds log-file related commands).
extension/package.json Adds command contributions and context menu wiring for “View source” and log file actions; removes PID menu wiring.

Comment thread extension/src/views/AspireAppHostTreeProvider.ts Outdated
Comment thread extension/src/views/AspireAppHostTreeProvider.ts
Comment thread extension/src/views/AspireAppHostTreeProvider.ts
Comment thread extension/src/views/AspireAppHostTreeProvider.ts
- Add logFilePath to AppHostDisplayInfo from aspire ps JSON output
- Show 'AppHost logs' tree item when log path is available
- Click opens the log file in VS Code editor
- Add 'Copy Path' context menu on log file item
- Add 'View source' context menu on appHost to show raw JSON
- Remove PID tree items (PID still shown in appHost description)

Fixes #17460
@JamesNK JamesNK force-pushed the jnewman/apphost-logs-ui branch from 529c038 to db230ae Compare May 25, 2026 14:05
@github-actions
Copy link
Copy Markdown
Contributor

Re-running the failed jobs in the CI workflow for this pull request because 1 job was identified as retry-safe transient failures in the CI run attempt.
GitHub was asked to rerun all failed jobs for that attempt, and the rerun is being tracked in the rerun attempt.
The job links below point to the failed attempt jobs that matched the retry-safe transient failure rules.

@github-actions
Copy link
Copy Markdown
Contributor

CLI E2E Tests unknown — 95 passed, 0 failed, 6 unknown (commit db230ae)

View all recordings
Status Test Recording
AddPackageInteractiveWhileAppHostRunningDetached ▶️ View recording
AddPackageWhileAppHostRunningDetached ▶️ View recording
AgentCommands_AllHelpOutputs_AreCorrect ▶️ View recording
AgentInitCommand_DefaultSelection_InstallsDefaultSkills ▶️ View recording
AgentInitCommand_MigratesDeprecatedConfig ▶️ View recording
AgentMcpListStructuredLogsFromStarterAppCore ▶️ View recording
AllPublishMethodsBuildDockerImages ▶️ View recording
AspireAddPackageVersionToDirectoryPackagesProps ▶️ View recording
AspireInitSingleFileAppHostRunsViaDotnetRunAppHost ▶️ View recording
AspireInitWithExistingAppHostDirRecreatesMissingNuGetConfigAndPreservesFiles ▶️ View recording
AspireInitWithSolutionFileGeneratesAppHostThatBuildsAgainstChannelHive ▶️ View recording
AspireStartUpdatesStaleTypeScriptAppHostPath ▶️ View recording
AspireUpdateRemovesAppHostPackageVersionFromDirectoryPackagesProps ▶️ View recording
AspireUpdateRemovesOrphanAppHostPackageVersionWhenSdkAlreadyCurrent ▶️ View recording
Banner_DisplayedOnFirstRun ▶️ View recording
Banner_DisplayedWithExplicitFlag ▶️ View recording
Banner_NotDisplayedWithNoLogoFlag ▶️ View recording
CertificatesClean_RemovesCertificates ▶️ View recording
CertificatesTrust_WithNoCert_CreatesAndTrustsCertificate ▶️ View recording
CertificatesTrust_WithUntrustedCert_TrustsCertificate ▶️ View recording
ConfigSetGet_CreatesNestedJsonFormat ▶️ View recording
CreateAndRunAspireStarterProject ▶️ View recording
CreateAndRunAspireStarterProjectWithBundle ▶️ View recording
CreateAndRunEmptyAppHostProject ▶️ View recording
CreateAndRunJavaEmptyAppHostProject ▶️ View recording
CreateAndRunJsReactProject ▶️ View recording
CreateAndRunPythonReactProject ▶️ View recording
CreateAndRunTypeScriptEmptyAppHostProject ▶️ View recording
CreateAndRunTypeScriptStarterProject ▶️ View recording
CreateJavaAppHostWithViteApp ▶️ View recording
CreateTypeScriptAppHostWithViteApp_UsesConfiguredToolchain ▶️ View recording
DashboardRunWithAgentMcpCore ▶️ View recording
DashboardRunWithOtelTracesReturnsNoTracesCore ▶️ View recording
DeployK8sBasicApiService ▶️ View recording
DeployK8sWithExternalHelmChart ▶️ View recording
DeployK8sWithGarnet ▶️ View recording
DeployK8sWithMongoDB ▶️ View recording
DeployK8sWithMySql ▶️ View recording
DeployK8sWithPostgres ▶️ View recording
DeployK8sWithRabbitMQ ▶️ View recording
DeployK8sWithRedis ▶️ View recording
DeployK8sWithSqlServer ▶️ View recording
DeployK8sWithValkey ▶️ View recording
DeployTypeScriptAppToKubernetes ▶️ View recording
DescribeCommandResolvesReplicaNames ▶️ View recording
DescribeCommandShowsRunningResources ▶️ View recording
DetachFormatJsonProducesValidJson ▶️ View recording
DetachFormatJsonProducesValidJsonWhenRestartingExistingInstance ▶️ View recording
DoListStepsShowsPipelineSteps ▶️ View recording
DocsCommand_RendersInteractiveMarkdownFromLocalSource ▶️ View recording
DoctorCommand_DetectsDeprecatedAgentConfig ▶️ View recording
DoctorCommand_TypeScriptAppHostReportsMissingConfiguredToolchain ▶️ View recording
DoctorCommand_WithSslCertDir_ShowsTrusted ▶️ View recording
DoctorCommand_WithoutSslCertDir_ShowsPartiallyTrusted ▶️ View recording
GeneratedAspireDevScript_StartsWatchMode_WithConfiguredToolchain ▶️ View recording
GlobalMigration_HandlesCommentsAndTrailingCommas ▶️ View recording
GlobalMigration_HandlesMalformedLegacyJson ▶️ View recording
GlobalMigration_PreservesAllValueTypes ▶️ View recording
GlobalMigration_SkipsWhenNewConfigExists ▶️ View recording
GlobalSettings_MigratedFromLegacyFormat ▶️ View recording
InitTypeScriptAppHost_AugmentsExistingViteRepoAtRoot ▶️ View recording
InteractiveCSharpInitCreatesExpectedFiles ▶️ View recording
InvalidAppHostPathWithComments_IsHealedOnRun ▶️ View recording
JavaScriptHostingApisRunFromTypeScriptAppHost ▶️ View recording
LatestCliCanStartStableChannelAppHost ▶️ View recording
LatestCliCanStartStableChannelTypeScriptAppHost ▶️ View recording
LegacySettingsMigration_AdjustsRelativeAppHostPath ▶️ View recording
LogLevelTrace_ProducesTraceEntriesInCliLogFile ▶️ View recording
LogsCommandShowsResourceLogs ▶️ View recording
OtelLogsReturnsStructuredLogsFromStarterApp ▶️ View recording
OtelLogsReturnsStructuredLogsFromStarterAppIsolated ▶️ View recording
PsCommandListsRunningAppHost ▶️ View recording
PsFormatJsonOutputsOnlyJsonToStdout ▶️ View recording
PublishJavaScriptPatternsGeneratesExpectedDockerComposeArtifacts ▶️ View recording
PublishWithConfigureEnvFileUpdatesEnvOutput ▶️ View recording
PublishWithDockerComposeServiceCallbackSucceeds ▶️ View recording
PublishWithoutOutputPathUsesAppHostDirectoryDefault ▶️ View recording
ResourceCommand_FailedExecution_DisplaysAppHostLogPathAndLogContainsEntries ▶️ View recording
ResourceCommand_FailsWhenInteractionServiceIsRequired ▶️ View recording
ResourceCommand_SetAndDeleteParameterUpdatesDescribeOutput ▶️ View recording
RestoreGeneratesSdkFiles ▶️ View recording
RestoreGeneratesSdkFiles_WithConfiguredToolchain ▶️ View recording
RestoreRefreshesGeneratedSdkAfterAddingIntegration ▶️ View recording
RestoreSupportsConfigOnlyHelperPackageAndCrossPackageTypes ▶️ View recording
RunFromParentDirectory_UsesExistingConfigNearAppHost ▶️ View recording
RunPublishFailureScenarioAsync ▶️ View recording
RunReportsSyntaxErrorsForDotNetAppHost ▶️ View recording
RunReportsSyntaxErrorsForTypeScriptAppHost ▶️ View recording
SecretCrudOnDotNetAppHost ▶️ View recording
SecretCrudOnTypeScriptAppHost ▶️ View recording
StagingChannel_ConfigureAndVerifySettings_ThenSwitchChannels ▶️ View recording
StartAndWaitForTypeScriptSqlServerAppHostWithNativeAssets ▶️ View recording
StartReportsSyntaxErrorsForDotNetAppHost ▶️ View recording
StartReportsSyntaxErrorsForTypeScriptAppHost ▶️ View recording
StopAllAppHostsFromAppHostDirectory ▶️ View recording
StopJavaPolyglotAppHostUsingApphostDirectory ▶️ View recording
StopNonInteractiveSingleAppHost ▶️ View recording
StopTypeScriptPolyglotAppHostUsingApphostDirectory ▶️ View recording
StopWithNoRunningAppHostExitsSuccessfully ▶️ View recording
UnAwaitedChainsCompileWithAutoResolvePromises ▶️ View recording
UpdateProjectChannelToStable_TypeScript_PicksUpStablePackages ▶️ View recording

📹 Recordings uploaded automatically from CI run #26404556775

Copy link
Copy Markdown
Member

@mitchdenny mitchdenny left a comment

Choose a reason for hiding this comment

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

Two issues from review:

  1. viewAppHostLogFile silently swallows both invalid arguments and file-open errors.
  2. registerTextDocumentContentProvider in the constructor can leak across test instances.

await vscode.window.showTextDocument(document, { preview: false });
} catch {
vscode.window.showWarningMessage(logFileOpenFailed(filePath));
}
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.

viewAppHostLogFile is a command system boundary — element can be anything when invoked from the command palette or another extension. Two problems with the current error handling:

  1. When given an invalid argument (e.g., an object, or a path-less click), the method silently returns with no user feedback. Consider showing a warning so misuse is visible rather than appearing to do nothing.
  2. The catch {} discards the underlying error. vscode.workspace.openTextDocument will surface useful detail (file not found, permission denied, etc.). Including error instanceof Error ? error.message : String(error) in logFileOpenFailed would let users diagnose the failure without checking the extension log.

this._dataSubscription = this._repository.onDidChangeData(() => {
this._onDidChangeTreeData.fire();
});
this._contentProviderRegistration = vscode.workspace.registerTextDocumentContentProvider('aspire-source', this);
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.

Registering the aspire-source TextDocumentContentProvider unconditionally in the constructor means each AspireAppHostTreeProvider instance creates a global registration for that scheme. In production there is only one instance, so this works, but in the unit tests many providers are constructed and not all paths call dispose(). VS Code keeps every leaked registration alive for the rest of the test run, and provideTextDocumentContent may then be dispatched to a stale provider whose _appHostSourceContents map does not contain the requested URI — returning "" and producing confusing test failures or flakiness if test ordering changes.

Two options:

  • Lazy-register on first call to viewAppHostSource (and dispose in dispose()), so providers that never open a source document do not register.
  • Accept the registration as a constructor parameter so tests can pass a shared no-op or a per-test fresh one.

@mitchdenny
Copy link
Copy Markdown
Member

Tested this out manually locally and it all works fine.

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.

Display UI to view app host logs in extension

3 participants