Skip to content

Always log dashboard startup summary across auth modes#17206

Merged
eerhardt merged 7 commits into
mainfrom
fix/dashboard-always-log-url
May 19, 2026
Merged

Always log dashboard startup summary across auth modes#17206
eerhardt merged 7 commits into
mainfrom
fix/dashboard-always-log-url

Conversation

@JamesNK
Copy link
Copy Markdown
Member

@JamesNK JamesNK commented May 18, 2026

Description

This PR ensures startup logs always include dashboard access details, regardless of frontend auth mode.

Previously, dashboard URL logging was gated on FrontendAuthMode.BrowserToken, so standalone/non-token scenarios could start successfully without printing a usable dashboard URL.

This change introduces a unified startup summary log and updates call sites/tests accordingly.

Fixes #16095

What changed

1) Replaced token-only URL logging with a unified summary helper

  • Replaced LoggingHelpers.WriteDashboardUrl(...) with:
    • LoggingHelpers.WriteDashboardSummary(ILogger logger, string? dashboardUrls, string? otlpGrpcUrls, string? otlpHttpUrls, string? token, bool isContainer = false)
  • New helper behavior:
    • Returns without logging if no valid dashboard URL is available
    • Always logs a dashboard summary block when a dashboard URL is available
    • Includes Login URL only when a token is present
    • Includes OTLP gRPC/HTTP entries when configured
    • Includes container networking guidance when isContainer == true
    • Keeps structured logging properties (DashboardUrl, LoginUrl, OtlpGrpcUrl, OtlpHttpUrl) for testability/querying

2) Dashboard startup logging now always emits summary

In DashboardWebApplication:

  • Removed BrowserToken-only guard around startup URL logging
  • Computes optional token based on auth mode:
    • BrowserToken mode => token included
    • Other modes => token omitted
  • Passes resolved frontend + OTLP addresses into WriteDashboardSummary(...)
  • Preserves existing container detection behavior (DOTNET_RUNNING_IN_CONTAINER)

3) AppHost dashboard event handler also uses summary logging

In DashboardEventHandlers:

  • Replaced conditional token-only WriteDashboardUrl(...) call with unconditional WriteDashboardSummary(...)
  • Continues to log Now listening on: ... for readiness/parsing compatibility, then logs summary

4) Reduced AI disabled log noise

In AIContextProvider:

  • Changed:
    • "AI is disabled in configuration."
    • from LogInformation to LogDebug

This keeps default/expected disabled state out of normal information-level startup output.

Test updates

  • Updated integration tests that previously matched the old login-only template to match the new startup summary format and LoginUrl property.
  • Added targeted LoggingHelpersTests covering:
    • token + OTLP endpoints present
    • no token (no login URL)
    • invalid/null dashboard URL (no log)
    • semicolon-delimited URL handling (first URL chosen)
    • no OTLP endpoints
    • container message inclusion
  • Updated startup integration expectations to include the new summary log line.

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
  • Did you add public API?
    • No
  • Does the change make any security assumptions or guarantees?
    • No

Previously the dashboard login URL was only logged when
FrontendAuthMode was BrowserToken. When running standalone without
browser-token auth, no URL was printed at all.

Now WriteDashboardUrl handles a null/empty token gracefully by
logging the base dashboard URL instead of the login link. The auth
mode guard in DashboardWebApplication is removed so a URL is always
printed at startup.

Fixes #16095
@JamesNK JamesNK requested a review from adamint as a code owner May 18, 2026 10:23
Copilot AI review requested due to automatic review settings May 18, 2026 10:23
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 18, 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 -- 17206

Or

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

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 ensures the Aspire dashboard startup logging always includes a usable dashboard URL, even when browser-token authentication is not active.

Changes:

  • LoggingHelpers.WriteDashboardUrl now accepts null/empty tokens and logs the base dashboard URL.
  • DashboardWebApplication now always calls the helper for the frontend endpoint.
  • Added unit coverage for token, no-token, invalid URL, and multi-URL scenarios.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/Shared/LoggingHelpers.cs Updates dashboard URL logging behavior for token and no-token modes.
src/Aspire.Dashboard/DashboardWebApplication.cs Removes the browser-token-only guard so startup logs always include the dashboard URL.
tests/Aspire.Dashboard.Tests/LoggingHelpersTests.cs Adds tests covering the updated logging helper behavior.

Comment thread src/Shared/LoggingHelpers.cs Outdated
@JamesNK JamesNK force-pushed the fix/dashboard-always-log-url branch from dfc4e7b to c882947 Compare May 18, 2026 14:21
@JamesNK JamesNK force-pushed the fix/dashboard-always-log-url branch from c882947 to 12bdff9 Compare May 18, 2026 14:23
@JamesNK JamesNK changed the title Always log dashboard URL at startup regardless of auth mode Always log dashboard startup summary across auth modes May 18, 2026
JamesNK added 3 commits May 19, 2026 07:25
- WriteDashboardSummary now logs OTLP endpoints even without a valid dashboard URL
- Moved WriteDashboardSummary call outside frontendEndpointInfo null check
- Simplified URL parsing (single URLs, no delimiter handling)
- Added tests for null/invalid dashboard URL scenarios
@JamesNK JamesNK force-pushed the fix/dashboard-always-log-url branch from 8dfdfb4 to 53faa6c Compare May 19, 2026 01:37
@JamesNK JamesNK requested a review from radical as a code owner May 19, 2026 01:38
@eerhardt eerhardt merged commit d3c69aa into main May 19, 2026
298 checks passed
@microsoft-github-policy-service microsoft-github-policy-service Bot added this to the 13.4 milestone May 19, 2026
@github-actions
Copy link
Copy Markdown
Contributor

CLI E2E Tests unknown — 90 passed, 0 failed, 1 unknown (commit c0f3c73)

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
AspireAddPackageVersionToDirectoryPackagesProps ▶️ View recording
AspireInitSingleFileAppHostRunsViaDotnetRunAppHost ▶️ View recording
AspireInitWithExistingAppHostDirRecreatesMissingNuGetConfigAndPreservesFiles ▶️ View recording
AspireInitWithSolutionFileGeneratesAppHostThatBuildsAgainstChannelHive ▶️ 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
DashboardRunWithOtelTracesReturnsNoTraces ▶️ 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
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
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
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
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
StopNonInteractiveSingleAppHost ▶️ View recording
StopWithNoRunningAppHostExitsSuccessfully ▶️ View recording
UnAwaitedChainsCompileWithAutoResolvePromises ▶️ View recording
UpdateProjectChannelToStable_TypeScript_PicksUpStablePackages ▶️ View recording

📹 Recordings uploaded automatically from CI run #26070889217

@aspire-repo-bot
Copy link
Copy Markdown
Contributor

✅ No documentation update needed.

docs_optional → bug_fix_restores_documented_behavior

No triggered signals (signal_count = 0). This PR fixes a bug where the Aspire dashboard startup URL was not logged when running with non-BrowserToken auth modes. The change makes LoggingHelpers.WriteDashboardSummary emit a consistent startup block for all auth modes (adding OTLP endpoint details and container guidance too), and demotes an "AI is disabled" message from LogInformation to LogDebug. No new public API, CLI options, configuration keys, or integration packages were introduced. The dashboard URL-at-startup feature was already documented behavior; this fix restores it to work consistently across all auth modes. All 8 changed files are implementation and test files with no user-visible surface changes beyond correcting the previously broken log output.

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.

Improve startup display and logging for the standalone dashboard container

4 participants