From 539bb9ac45f4d4f92b27effea2dc874bca841f15 Mon Sep 17 00:00:00 2001 From: David Pine Date: Mon, 12 May 2025 15:27:43 -0500 Subject: [PATCH 1/5] Fixes #3372. Adds new eventing APIs. --- docs/app-host/eventing.md | 13 +++++++------ .../AspireApp.AppHost/AspireApp.AppHost.csproj | 4 ++-- .../AspireApp/AspireApp.AppHost/Console.txt | 12 ++++++++---- .../snippets/AspireApp/AspireApp.AppHost/Program.cs | 13 ++++++++++++- .../AspireApp.ResourceAppHost.csproj | 4 ++-- .../AspireApp/AspireApp.ResourceAppHost/Console.txt | 10 ++++++---- .../AspireApp/AspireApp.ResourceAppHost/Program.cs | 10 ++++++++++ .../AspireApp.AppHost/AspireApp.AppHost.csproj | 2 +- 8 files changed, 48 insertions(+), 20 deletions(-) diff --git a/docs/app-host/eventing.md b/docs/app-host/eventing.md index 9b0f4ed026..43a43ed808 100644 --- a/docs/app-host/eventing.md +++ b/docs/app-host/eventing.md @@ -26,20 +26,21 @@ All of the preceding events are analogous to the [app host life cycles](xref:dot To subscribe to the built-in app host events, use the eventing API. After you have a distributed application builder instance, walk up to the property and call the API. Consider the following sample app host _Program.cs_ file: -:::code source="snippets/AspireApp/AspireApp.AppHost/Program.cs" highlight="17-25,27-35,37-45"::: +:::code source="snippets/AspireApp/AspireApp.AppHost/Program.cs"::: The preceding code is based on the starter template with the addition of the calls to the `Subscribe` API. The `Subscribe` API returns a instance that you can use to unsubscribe from the event. It's common to discard the returned subscriptions, as you don't usually need to unsubscribe from events as the entire app is torn down when the app host is shut down. When the app host is run, by the time the .NET Aspire dashboard is displayed, you should see the following log output in the console: -:::code language="Plaintext" source="snippets/AspireApp/AspireApp.AppHost/Console.txt" highlight="2,10,16"::: +:::code language="Plaintext" source="snippets/AspireApp/AspireApp.AppHost/Console.txt" highlight="2,10-14,20"::: -The log output confirms that event handlers are executed in the order of the app host life cycle events. The subscription order doesn't affect execution order. The `BeforeStartEvent` is triggered first, followed by `AfterEndpointsAllocatedEvent`, and finally `AfterResourcesCreatedEvent`. +The log output confirms that event handlers are executed in the order of the app host life cycle events. The subscription order doesn't affect execution order. The `BeforeStartEvent` is triggered first, followed by `AfterEndpointsAllocatedEvent`, then each resource has its `ResourceEndpointsAllocatedEvent` event fired, and finally `AfterResourcesCreatedEvent`. ## Resource eventing In addition to the app host events, you can also subscribe to resource events. Resource events are raised specific to an individual resource. Resource events are defined as implementations of the interface. The following resource events are available in the listed order: +1. `InitializeResourceEvent`: Raised by orchestrators to signal to resources that they should initialize themselves. 1. : Raised when a connection string becomes available for a resource. 1. : Raised before the orchestrator starts a new resource. 1. : Raised when a resource initially transitions to a ready state. @@ -48,13 +49,13 @@ In addition to the app host events, you can also subscribe to resource events. R To subscribe to resource events, use the eventing API. After you have a distributed application builder instance, walk up to the property and call the API. Consider the following sample app host _Program.cs_ file: -:::code source="snippets/AspireApp/AspireApp.ResourceAppHost/Program.cs" highlight="8-17,19-28,30-39"::: +:::code source="snippets/AspireApp/AspireApp.ResourceAppHost/Program.cs"::: -The preceding code subscribes to the `ResourceReadyEvent`, `ConnectionStringAvailableEvent`, and `BeforeResourceStartedEvent` events on the `cache` resource. When is called, it returns an where `T` is a . The resource builder exposes the resource as the property. The resource in question is then passed to the `Subscribe` API to subscribe to the events on the resource. +The preceding code subscribes to the `InitializeResourceEvent`, `ResourceReadyEvent`, `ConnectionStringAvailableEvent`, and `BeforeResourceStartedEvent` events on the `cache` resource. When is called, it returns an where `T` is a . The resource builder exposes the resource as the property. The resource in question is then passed to the `Subscribe` API to subscribe to the events on the resource. When the app host is run, by the time the .NET Aspire dashboard is displayed, you should see the following log output in the console: -:::code language="Plaintext" source="snippets/AspireApp/AspireApp.ResourceAppHost/Console.txt" highlight="8,10,12"::: +:::code language="Plaintext" source="snippets/AspireApp/AspireApp.ResourceAppHost/Console.txt" highlight="8,10,12,18"::: > [!NOTE] > Some events are blocking. For example, when the `BeforeResourceStartEvent` is published, the startup of the resource will be blocked until all subscriptions for that event on a given resource have completed executing. Whether an event is blocking or not depends on how it is published (see the following section). diff --git a/docs/app-host/snippets/AspireApp/AspireApp.AppHost/AspireApp.AppHost.csproj b/docs/app-host/snippets/AspireApp/AspireApp.AppHost/AspireApp.AppHost.csproj index d4552282ef..44f2cf540b 100644 --- a/docs/app-host/snippets/AspireApp/AspireApp.AppHost/AspireApp.AppHost.csproj +++ b/docs/app-host/snippets/AspireApp/AspireApp.AppHost/AspireApp.AppHost.csproj @@ -16,8 +16,8 @@ - - + + diff --git a/docs/app-host/snippets/AspireApp/AspireApp.AppHost/Console.txt b/docs/app-host/snippets/AspireApp/AspireApp.AppHost/Console.txt index fe73c4232e..a3eadd2048 100644 --- a/docs/app-host/snippets/AspireApp/AspireApp.AppHost/Console.txt +++ b/docs/app-host/snippets/AspireApp/AspireApp.AppHost/Console.txt @@ -1,18 +1,22 @@ info: Program[0] 1. BeforeStartEvent info: Aspire.Hosting.DistributedApplication[0] - Aspire version: 9.0.0 + Aspire version: 9.3.0-preview.1.25262.2+6d54dc081cd2e7ea435e33f7c0e62ff6946ae66d info: Aspire.Hosting.DistributedApplication[0] Distributed application starting. info: Aspire.Hosting.DistributedApplication[0] - Application host directory is: ..\AspireApp\AspireApp.AppHost + Application host directory is: ../AspireApp/AspireApp.AppHost info: Program[0] 2. AfterEndpointsAllocatedEvent + 3. 'aspire-dashboard' ResourceEndpointsAllocatedEvent + 3. 'cache' ResourceEndpointsAllocatedEvent + 3. 'apiservice' ResourceEndpointsAllocatedEvent + 3. 'webfrontend' ResourceEndpointsAllocatedEvent info: Aspire.Hosting.DistributedApplication[0] Now listening on: https://localhost:17178 info: Aspire.Hosting.DistributedApplication[0] Login to the dashboard at https://localhost:17178/login?t= info: Program[0] - 3. AfterResourcesCreatedEvent + 4. AfterResourcesCreatedEvent info: Aspire.Hosting.DistributedApplication[0] - Distributed application started. Press Ctrl+C to shut down. \ No newline at end of file + Distributed application started. Press Ctrl+C to shut down. diff --git a/docs/app-host/snippets/AspireApp/AspireApp.AppHost/Program.cs b/docs/app-host/snippets/AspireApp/AspireApp.AppHost/Program.cs index 14af8aa466..125ee9ba4b 100644 --- a/docs/app-host/snippets/AspireApp/AspireApp.AppHost/Program.cs +++ b/docs/app-host/snippets/AspireApp/AspireApp.AppHost/Program.cs @@ -14,6 +14,17 @@ .WithReference(apiService) .WaitFor(apiService); +builder.Eventing.Subscribe( + (@event, cancellationToken) => + { + // The event doesn't expose an IServiceProvider, just write to the console. + Console.WriteLine($""" + 3. '{@event.Resource.Name}' ResourceEndpointsAllocatedEvent + """); + + return Task.CompletedTask; + }); + builder.Eventing.Subscribe( static (@event, cancellationToken) => { @@ -39,7 +50,7 @@ { var logger = @event.Services.GetRequiredService>(); - logger.LogInformation("3. AfterResourcesCreatedEvent"); + logger.LogInformation("4. AfterResourcesCreatedEvent"); return Task.CompletedTask; }); diff --git a/docs/app-host/snippets/AspireApp/AspireApp.ResourceAppHost/AspireApp.ResourceAppHost.csproj b/docs/app-host/snippets/AspireApp/AspireApp.ResourceAppHost/AspireApp.ResourceAppHost.csproj index d4552282ef..44f2cf540b 100644 --- a/docs/app-host/snippets/AspireApp/AspireApp.ResourceAppHost/AspireApp.ResourceAppHost.csproj +++ b/docs/app-host/snippets/AspireApp/AspireApp.ResourceAppHost/AspireApp.ResourceAppHost.csproj @@ -16,8 +16,8 @@ - - + + diff --git a/docs/app-host/snippets/AspireApp/AspireApp.ResourceAppHost/Console.txt b/docs/app-host/snippets/AspireApp/AspireApp.ResourceAppHost/Console.txt index c8ca1f88cb..2ffe31f260 100644 --- a/docs/app-host/snippets/AspireApp/AspireApp.ResourceAppHost/Console.txt +++ b/docs/app-host/snippets/AspireApp/AspireApp.ResourceAppHost/Console.txt @@ -1,18 +1,20 @@ info: Aspire.Hosting.DistributedApplication[0] - Aspire version: 9.0.0 + Aspire version: 9.3.0 info: Aspire.Hosting.DistributedApplication[0] Distributed application starting. info: Aspire.Hosting.DistributedApplication[0] - Application host directory is: ..\AspireApp\AspireApp.AppHost + Application host directory is: ../AspireApp/AspireApp.AppHost +info: Program[0] + 0. InitializeResourceEvent info: Program[0] 1. ConnectionStringAvailableEvent info: Program[0] 2. BeforeResourceStartedEvent -info: Program[0] - 3. ResourceReadyEvent info: Aspire.Hosting.DistributedApplication[0] Now listening on: https://localhost:17222 info: Aspire.Hosting.DistributedApplication[0] Login to the dashboard at https://localhost:17222/login?t= +info: Program[0] + 3. ResourceReadyEvent info: Aspire.Hosting.DistributedApplication[0] Distributed application started. Press Ctrl+C to shut down. \ No newline at end of file diff --git a/docs/app-host/snippets/AspireApp/AspireApp.ResourceAppHost/Program.cs b/docs/app-host/snippets/AspireApp/AspireApp.ResourceAppHost/Program.cs index b2134aa607..51e49aa667 100644 --- a/docs/app-host/snippets/AspireApp/AspireApp.ResourceAppHost/Program.cs +++ b/docs/app-host/snippets/AspireApp/AspireApp.ResourceAppHost/Program.cs @@ -16,6 +16,16 @@ return Task.CompletedTask; }); +builder.Eventing.Subscribe(cache.Resource, + static (@event, cancellationToken) => + { + var logger = @event.Services.GetRequiredService>(); + + logger.LogInformation("0. InitializeResourceEvent"); + + return Task.CompletedTask; + }); + builder.Eventing.Subscribe( cache.Resource, static (@event, cancellationToken) => diff --git a/docs/authentication/snippets/AspireApp/AspireApp.AppHost/AspireApp.AppHost.csproj b/docs/authentication/snippets/AspireApp/AspireApp.AppHost/AspireApp.AppHost.csproj index ecf2b62c33..5c7c5a1168 100644 --- a/docs/authentication/snippets/AspireApp/AspireApp.AppHost/AspireApp.AppHost.csproj +++ b/docs/authentication/snippets/AspireApp/AspireApp.AppHost/AspireApp.AppHost.csproj @@ -17,7 +17,7 @@ - From 2833de581944b8992e3071da82f3b6a89f794b50 Mon Sep 17 00:00:00 2001 From: David Pine Date: Mon, 12 May 2025 15:34:07 -0500 Subject: [PATCH 2/5] Minor edit for constistency --- docs/app-host/eventing.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/app-host/eventing.md b/docs/app-host/eventing.md index 43a43ed808..58d12b5598 100644 --- a/docs/app-host/eventing.md +++ b/docs/app-host/eventing.md @@ -32,7 +32,7 @@ The preceding code is based on the starter template with the addition of the cal When the app host is run, by the time the .NET Aspire dashboard is displayed, you should see the following log output in the console: -:::code language="Plaintext" source="snippets/AspireApp/AspireApp.AppHost/Console.txt" highlight="2,10-14,20"::: +:::code language="Output" source="snippets/AspireApp/AspireApp.AppHost/Console.txt" highlight="2,10-14,20"::: The log output confirms that event handlers are executed in the order of the app host life cycle events. The subscription order doesn't affect execution order. The `BeforeStartEvent` is triggered first, followed by `AfterEndpointsAllocatedEvent`, then each resource has its `ResourceEndpointsAllocatedEvent` event fired, and finally `AfterResourcesCreatedEvent`. @@ -55,7 +55,7 @@ The preceding code subscribes to the `InitializeResourceEvent`, `ResourceReadyEv When the app host is run, by the time the .NET Aspire dashboard is displayed, you should see the following log output in the console: -:::code language="Plaintext" source="snippets/AspireApp/AspireApp.ResourceAppHost/Console.txt" highlight="8,10,12,18"::: +:::code language="Output" source="snippets/AspireApp/AspireApp.ResourceAppHost/Console.txt" highlight="8,10,12,18"::: > [!NOTE] > Some events are blocking. For example, when the `BeforeResourceStartEvent` is published, the startup of the resource will be blocked until all subscriptions for that event on a given resource have completed executing. Whether an event is blocking or not depends on how it is published (see the following section). @@ -114,7 +114,7 @@ info: Aspire.Hosting.DistributedApplication[0] info: Aspire.Hosting.DistributedApplication[0] Distributed application starting. info: Aspire.Hosting.DistributedApplication[0] - Application host directory is: ..\AspireApp\AspireApp.AppHost + Application host directory is: ../AspireApp/AspireApp.AppHost info: LifecycleLogger[0] AfterEndpointsAllocatedAsync info: Aspire.Hosting.DistributedApplication[0] From 6d2ee171e575bb85766368bad32edb7efd8c15de Mon Sep 17 00:00:00 2001 From: David Pine Date: Mon, 12 May 2025 15:38:39 -0500 Subject: [PATCH 3/5] Fix output --- docs/app-host/eventing.md | 25 +++---------------- .../AspireApp.ResourceAppHost/Console.txt | 8 +++--- .../AspireApp.ResourceAppHost/Program.cs | 8 +++--- .../AspireApp/AspireApp.AppHost/Console.txt | 18 +++++++++++++ .../AspireApp/AspireApp.AppHost/Program.cs | 6 ++--- 5 files changed, 32 insertions(+), 33 deletions(-) create mode 100644 docs/fundamentals/snippets/lifecycles/AspireApp/AspireApp.AppHost/Console.txt diff --git a/docs/app-host/eventing.md b/docs/app-host/eventing.md index 58d12b5598..1c5387c8b3 100644 --- a/docs/app-host/eventing.md +++ b/docs/app-host/eventing.md @@ -106,28 +106,9 @@ The preceding code: When this app host is run, the life cycle hook is executed for each event. The following output is generated: -```Output -info: LifecycleLogger[0] - BeforeStartAsync -info: Aspire.Hosting.DistributedApplication[0] - Aspire version: 9.0.0 -info: Aspire.Hosting.DistributedApplication[0] - Distributed application starting. -info: Aspire.Hosting.DistributedApplication[0] - Application host directory is: ../AspireApp/AspireApp.AppHost -info: LifecycleLogger[0] - AfterEndpointsAllocatedAsync -info: Aspire.Hosting.DistributedApplication[0] - Now listening on: https://localhost:17043 -info: Aspire.Hosting.DistributedApplication[0] - Login to the dashboard at https://localhost:17043/login?t=d80f598bc8a64c7ee97328a1cbd55d72 -info: LifecycleLogger[0] - AfterResourcesCreatedAsync -info: Aspire.Hosting.DistributedApplication[0] - Distributed application started. Press Ctrl+C to shut down. -``` - -The preferred way to hook into the app host life cycle is to use the eventing API. For more information, see [Eventing in .NET Aspire](#eventing-in-net-aspire). +:::code lang="Output" source="../fundamentals/snippets/lifecycles/AspireApp/AspireApp.AppHost/Console.txt" highlight="2,10,16"::: + +The preferred way to hook into the app host life cycle is to use the eventing API. For more information, see [App host eventing](#app-host-eventing). ## See also diff --git a/docs/app-host/snippets/AspireApp/AspireApp.ResourceAppHost/Console.txt b/docs/app-host/snippets/AspireApp/AspireApp.ResourceAppHost/Console.txt index 2ffe31f260..cdfecf5a0b 100644 --- a/docs/app-host/snippets/AspireApp/AspireApp.ResourceAppHost/Console.txt +++ b/docs/app-host/snippets/AspireApp/AspireApp.ResourceAppHost/Console.txt @@ -5,16 +5,16 @@ info: Aspire.Hosting.DistributedApplication[0] info: Aspire.Hosting.DistributedApplication[0] Application host directory is: ../AspireApp/AspireApp.AppHost info: Program[0] - 0. InitializeResourceEvent + 1. InitializeResourceEvent info: Program[0] - 1. ConnectionStringAvailableEvent + 2. ConnectionStringAvailableEvent info: Program[0] - 2. BeforeResourceStartedEvent + 3. BeforeResourceStartedEvent info: Aspire.Hosting.DistributedApplication[0] Now listening on: https://localhost:17222 info: Aspire.Hosting.DistributedApplication[0] Login to the dashboard at https://localhost:17222/login?t= info: Program[0] - 3. ResourceReadyEvent + 4. ResourceReadyEvent info: Aspire.Hosting.DistributedApplication[0] Distributed application started. Press Ctrl+C to shut down. \ No newline at end of file diff --git a/docs/app-host/snippets/AspireApp/AspireApp.ResourceAppHost/Program.cs b/docs/app-host/snippets/AspireApp/AspireApp.ResourceAppHost/Program.cs index 51e49aa667..0350aa75b3 100644 --- a/docs/app-host/snippets/AspireApp/AspireApp.ResourceAppHost/Program.cs +++ b/docs/app-host/snippets/AspireApp/AspireApp.ResourceAppHost/Program.cs @@ -11,7 +11,7 @@ { var logger = @event.Services.GetRequiredService>(); - logger.LogInformation("3. ResourceReadyEvent"); + logger.LogInformation("4. ResourceReadyEvent"); return Task.CompletedTask; }); @@ -21,7 +21,7 @@ { var logger = @event.Services.GetRequiredService>(); - logger.LogInformation("0. InitializeResourceEvent"); + logger.LogInformation("1. InitializeResourceEvent"); return Task.CompletedTask; }); @@ -32,7 +32,7 @@ { var logger = @event.Services.GetRequiredService>(); - logger.LogInformation("2. BeforeResourceStartedEvent"); + logger.LogInformation("3. BeforeResourceStartedEvent"); return Task.CompletedTask; }); @@ -43,7 +43,7 @@ { var logger = @event.Services.GetRequiredService>(); - logger.LogInformation("1. ConnectionStringAvailableEvent"); + logger.LogInformation("2. ConnectionStringAvailableEvent"); return Task.CompletedTask; }); diff --git a/docs/fundamentals/snippets/lifecycles/AspireApp/AspireApp.AppHost/Console.txt b/docs/fundamentals/snippets/lifecycles/AspireApp/AspireApp.AppHost/Console.txt new file mode 100644 index 0000000000..8e36e37c71 --- /dev/null +++ b/docs/fundamentals/snippets/lifecycles/AspireApp/AspireApp.AppHost/Console.txt @@ -0,0 +1,18 @@ +info: LifecycleLogger[0] + 1. BeforeStartAsync +info: Aspire.Hosting.DistributedApplication[0] + Aspire version: 9.3.0 +info: Aspire.Hosting.DistributedApplication[0] + Distributed application starting. +info: Aspire.Hosting.DistributedApplication[0] + Application host directory is: ../AspireApp/AspireApp.AppHost +info: LifecycleLogger[0] + 2. AfterEndpointsAllocatedAsync +info: Aspire.Hosting.DistributedApplication[0] + Now listening on: https://localhost:17043 +info: Aspire.Hosting.DistributedApplication[0] + Login to the dashboard at https://localhost:17043/login?t= +info: LifecycleLogger[0] + 3. AfterResourcesCreatedAsync +info: Aspire.Hosting.DistributedApplication[0] + Distributed application started. Press Ctrl+C to shut down. \ No newline at end of file diff --git a/docs/fundamentals/snippets/lifecycles/AspireApp/AspireApp.AppHost/Program.cs b/docs/fundamentals/snippets/lifecycles/AspireApp/AspireApp.AppHost/Program.cs index 7e9c4fb3e8..5c8b5e3d7e 100644 --- a/docs/fundamentals/snippets/lifecycles/AspireApp/AspireApp.AppHost/Program.cs +++ b/docs/fundamentals/snippets/lifecycles/AspireApp/AspireApp.AppHost/Program.cs @@ -13,21 +13,21 @@ internal sealed class LifecycleLogger(ILogger logger) public Task BeforeStartAsync( DistributedApplicationModel appModel, CancellationToken cancellationToken = default) { - logger.LogInformation("BeforeStartAsync"); + logger.LogInformation("1. BeforeStartAsync"); return Task.CompletedTask; } public Task AfterEndpointsAllocatedAsync( DistributedApplicationModel appModel, CancellationToken cancellationToken = default) { - logger.LogInformation("AfterEndpointsAllocatedAsync"); + logger.LogInformation("2. AfterEndpointsAllocatedAsync"); return Task.CompletedTask; } public Task AfterResourcesCreatedAsync( DistributedApplicationModel appModel, CancellationToken cancellationToken = default) { - logger.LogInformation("AfterResourcesCreatedAsync"); + logger.LogInformation("3. AfterResourcesCreatedAsync"); return Task.CompletedTask; } } From b238079a87eba0a164b3ba5dce1037b12d2ae692 Mon Sep 17 00:00:00 2001 From: David Pine Date: Mon, 12 May 2025 15:50:55 -0500 Subject: [PATCH 4/5] Fix build --- docs/app-host/eventing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/app-host/eventing.md b/docs/app-host/eventing.md index 1c5387c8b3..5a16c48b49 100644 --- a/docs/app-host/eventing.md +++ b/docs/app-host/eventing.md @@ -106,7 +106,7 @@ The preceding code: When this app host is run, the life cycle hook is executed for each event. The following output is generated: -:::code lang="Output" source="../fundamentals/snippets/lifecycles/AspireApp/AspireApp.AppHost/Console.txt" highlight="2,10,16"::: +:::code language="Output" source="../fundamentals/snippets/lifecycles/AspireApp/AspireApp.AppHost/Console.txt" highlight="2,10,16"::: The preferred way to hook into the app host life cycle is to use the eventing API. For more information, see [App host eventing](#app-host-eventing). From f9dd014bf73bca2ffab78eb4084705a2ce6c9f34 Mon Sep 17 00:00:00 2001 From: David Pine Date: Tue, 13 May 2025 07:58:26 -0500 Subject: [PATCH 5/5] Try to fix highlighting --- docs/app-host/eventing.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/app-host/eventing.md b/docs/app-host/eventing.md index 5a16c48b49..827c6cc352 100644 --- a/docs/app-host/eventing.md +++ b/docs/app-host/eventing.md @@ -32,7 +32,7 @@ The preceding code is based on the starter template with the addition of the cal When the app host is run, by the time the .NET Aspire dashboard is displayed, you should see the following log output in the console: -:::code language="Output" source="snippets/AspireApp/AspireApp.AppHost/Console.txt" highlight="2,10-14,20"::: +:::code language="Plaintext" source="snippets/AspireApp/AspireApp.AppHost/Console.txt" highlight="2,10-14,20"::: The log output confirms that event handlers are executed in the order of the app host life cycle events. The subscription order doesn't affect execution order. The `BeforeStartEvent` is triggered first, followed by `AfterEndpointsAllocatedEvent`, then each resource has its `ResourceEndpointsAllocatedEvent` event fired, and finally `AfterResourcesCreatedEvent`. @@ -55,7 +55,7 @@ The preceding code subscribes to the `InitializeResourceEvent`, `ResourceReadyEv When the app host is run, by the time the .NET Aspire dashboard is displayed, you should see the following log output in the console: -:::code language="Output" source="snippets/AspireApp/AspireApp.ResourceAppHost/Console.txt" highlight="8,10,12,18"::: +:::code language="Plaintext" source="snippets/AspireApp/AspireApp.ResourceAppHost/Console.txt" highlight="8,10,12,18"::: > [!NOTE] > Some events are blocking. For example, when the `BeforeResourceStartEvent` is published, the startup of the resource will be blocked until all subscriptions for that event on a given resource have completed executing. Whether an event is blocking or not depends on how it is published (see the following section). @@ -106,7 +106,7 @@ The preceding code: When this app host is run, the life cycle hook is executed for each event. The following output is generated: -:::code language="Output" source="../fundamentals/snippets/lifecycles/AspireApp/AspireApp.AppHost/Console.txt" highlight="2,10,16"::: +:::code language="Plaintext" source="../fundamentals/snippets/lifecycles/AspireApp/AspireApp.AppHost/Console.txt" highlight="2,10,16"::: The preferred way to hook into the app host life cycle is to use the eventing API. For more information, see [App host eventing](#app-host-eventing).