From 7be334e2e201a146d9c6b945c71a7f7478d2ebee Mon Sep 17 00:00:00 2001 From: Alistair Matthews Date: Wed, 8 Jan 2025 13:20:59 +0000 Subject: [PATCH 1/2] Orleans integration article rewrite (#2355) * Initial changes. * Orleans article restructuring. * Complete Orleans integration rewrite. * Orleans integration article revision completed. * Removed unnecessary spaces. * Fixed namespace typos. * Fixes for feedback from @IEvangelist and @ReubenBond. --- docs/frameworks/orleans.md | 134 +++++++++++++----- .../Orleans/OrleansAppHost/Program.cs | 6 +- 2 files changed, 104 insertions(+), 36 deletions(-) diff --git a/docs/frameworks/orleans.md b/docs/frameworks/orleans.md index 25e23e773d..ba340c753d 100644 --- a/docs/frameworks/orleans.md +++ b/docs/frameworks/orleans.md @@ -1,27 +1,22 @@ --- -title: Use Orleans with .NET Aspire -description: Learn how to use Orleans with .NET Aspire +title: .NET Aspire Orleans integration +description: Learn how to use the .NET Aspire Orleans hosting integration, which can configure and orchestrate Orleans from a .NET Aspire app host project. ms.date: 11/05/2024 -ms.topic: overview +uid: frameworks/orleans --- -# Use Orleans with .NET Aspire +# .NET Aspire Orleans integration -Orleans has built-in support for .NET Aspire. .NET Aspire's application model lets you describe the services, databases, and other resources/infrastructure in your app and how they relate. Orleans provides a straightforward way to build distributed applications which are elastically scalable and fault-tolerant. .NET Aspire is used to configure and orchestrate Orleans and its dependencies, such as, by providing Orleans with database cluster membership and storage. +[Orleans](https://github.com/dotnet/orleans) has built-in support for .NET Aspire. .NET Aspire's application model lets you describe the services, databases, and other resources and infrastructure in your app and how they relate to each other. Orleans provides a straightforward way to build distributed applications that are elastically scalable and fault-tolerant. You can use .NET Aspire to configure and orchestrate Orleans and its dependencies, such as by providing Orleans with cluster membership and storage. -Orleans is represented as a resource in .NET Aspire. The Orleans resource includes configuration which your service needs to operate, such as cluster membership providers and storage providers. +Orleans is represented as a resource in .NET Aspire. Unlike other integrations, the Orleans integration doesn't create a container and doesn't require a separate client integration package. Instead you complete the Orleans configuration in the .NET Aspire app host project. -[!INCLUDE [aspire-prereqs](../includes/aspire-prereqs.md)] +> [!NOTE] +> This integration requires Orleans version 8.1.0 or later. -In addition to the prerequisites for .NET Aspire, you need: +## Hosting integration -- Orleans version 8.1.0 or later - -For more information, see [.NET Aspire setup and tooling](../fundamentals/setup-tooling.md). - -## Get started - -To get started, you need to add the Orleans hosting package to your app host project by installing the [📦 Aspire.Hosting.Orleans](https://www.nuget.org/packages/Aspire.Hosting.Orleans) NuGet package. +The Orleans hosting integration models an Orleans service as the type. To access this type and APIs, add the [📦 Aspire.Hosting.Orleans](https://www.nuget.org/packages/Aspire.Hosting.Orleans) NuGet package in the [app host](xref:dotnet/aspire/app-host) project. ### [.NET CLI](#tab/dotnet-cli) @@ -40,13 +35,19 @@ dotnet add package Aspire.Hosting.Orleans For more information, see [dotnet add package](/dotnet/core/tools/dotnet-add-package) or [Manage package dependencies in .NET applications](/dotnet/core/tools/dependencies). -The Orleans resource is added to the .NET Aspire distributed application builder using the `AddOrleans(string name)` method, which returns an Orleans resource builder. The name provided to the Orleans resource is for diagnostic purposes. For most applications, a value of `"default"` suffices. +### Add an Orleans resource + +In your app host project, call to add and return an Orleans service resource builder. The name provided to the Orleans resource is for diagnostic purposes. For most applications, a value of `"default"` suffices. :::code language="csharp" source="snippets/Orleans/OrleansAppHost/Program.cs" range="12"::: -The Orleans resource builder offers methods to configure your Orleans resource. +### Use Azure storage for clustering tables and grain storage -To configure Orleans with clustering and grain storage, install the [📦 Aspire.Hosting.Azure.Storage](https://www.nuget.org/packages/Aspire.Hosting.Azure.Storage) NuGet package in the app host project: +In an Orleans app, the fundamental building block is a **grain**. Grains can have durable states. You must store the durable state for a grain somewhere. In a .NET Aspire application, **Azure Blob Storage** is one possible location. + +Orleans hosts register themselves in a database and use that database to find each other and form a cluster. They store which servers are members of which silos in a database table. You can use either relational or NoSQL databases to store this information. In a .NET Aspire application, a popular choice to store this table is **Azure Table Storage**. + +To configure Orleans with clustering and grain storage in Azure, install the [📦 Aspire.Hosting.Azure.Storage](https://www.nuget.org/packages/Aspire.Hosting.Azure.Storage) NuGet package in the app host project: ### [.NET CLI](#tab/dotnet-cli) @@ -63,41 +64,107 @@ dotnet add package Aspire.Hosting.Azure.Storage --- -In the following example, the Orleans resource is configured with clustering and grain storage using the `WithClustering` and `WithGrainStorage` methods respectively: +In your app host project, after you call , configure the Orleans resource with clustering and grain storage using the and methods respectively: :::code language="csharp" source="snippets/Orleans/OrleansAppHost/Program.cs" range="3-14" highlight="4-5,11-12"::: -The preceding code tells Orleans that any service referencing it also needs to reference the `clusteringTable` resource. +The preceding code tells Orleans that any service referencing it must also reference the `clusteringTable` resource. + +### Add an Orleans server project in the app host -To participate in an Orleans cluster, reference the Orleans resource from your service project, either using `WithReference(orleans)` to participate as an Orleans server, or `WithReference(orleans.AsClient())` to participate as a client. When you reference the Orleans resource from your service, those resources are also referenced: +Now you can add a new project, enrolled in .NET Aspire orchestration, to your solution as an Orleans server. It will take part in the Orleans cluster as a silo with constituent grains. Reference the Orleans resource from your server project using `WithReference(orleans)`. When you reference the Orleans resource from your service, those resources are also referenced: :::code language="csharp" source="snippets/Orleans/OrleansAppHost/Program.cs" range="16-22"::: -Putting that all together, here's an example of a .NET Aspire app host project which includes: +### Add an Orleans client project in the app host + +Orleans clients communicate with grains hosted on Orleans servers. In a .NET Aspire app, for example, you might have a front-end Web site that calls grains in an Orleans cluster. Reference the Orleans resource from your Orleans client using `WithReference(orleans.AsClient())`. + +:::code language="csharp" source="snippets/Orleans/OrleansAppHost/Program.cs" range="24-29"::: + +## Create the Orleans server project + +Now that the app host project is completed, you can implement the Orleans server project. Let's start by adding the necessary NuGet packages: + +### [.NET CLI](#tab/dotnet-cli) + +In the folder for the Orleans server project, run these commands: + +```dotnetcli +dotnet add package Aspire.Azure.Data.Tables +dotnet add package Aspire.Azure.Storage.Blobs +dotnet add package Microsoft.Orleans.Persistence.AzureStorage +dotnet add package Microsoft.Orleans.Clustering.AzureStorage +``` + +### [PackageReference](#tab/package-reference) + +In the configuration file for the Orleans server project, add these package references: + +```xml + + + + -- An Orleans resource with clustering and storage. -- An Orleans server project, **OrleansServer**. -- An Orleans client project, **OrleansClient**. +``` -:::code language="csharp" source="snippets/Orleans/OrleansAppHost/Program.cs" ::: +--- -To consume the .NET Aspire Orleans resource from an Orleans server project, there are a few steps: +Next, in the _:::no-loc text="Program.cs":::_ file of your Orleans server project, add the Azure Storage blob and tables clients and then call . -1. Add the relevant .NET Aspire integrations. In this example, you're using and . -1. Add the Orleans provider packages for those .NET Aspire integrations. In this example, you're using `Microsoft.Orleans.Persistence.AzureStorage` and `Microsoft.Orleans.Clustering.AzureStorage`. -1. Add Orleans to the host application builder. +:::code language="csharp" source="snippets/Orleans/OrleansServer/Program.cs" range="4-9" ::: -In the _:::no-loc text="Program.cs":::_ file of your Orleans server project, you must configure the .NET Aspire integrations you're using and add Orleans to the host builder. The names provided must match the names used in the .NET Aspire app host project: "clustering" for the clustering provider, and "grain-state" for the grain state storage provider: +The following code is a complete example of an Orleans server project, including a grain named `CounterGrain`: :::code language="csharp" source="snippets/Orleans/OrleansServer/Program.cs" ::: -You do similarly in the _OrleansClient_ project, adding the .NET Aspire resources which your project needs to join the Orleans cluster as a client, and configuring the host builder to add an Orleans client: +## Create an Orleans client project + +In the Orleans client project, add the same NuGet packages: + +### [.NET CLI](#tab/dotnet-cli) + +```dotnetcli +dotnet add package Aspire.Azure.Data.Tables +dotnet add package Aspire.Azure.Storage.Blobs +dotnet add package Microsoft.Orleans.Persistence.AzureStorage +dotnet add package Microsoft.Orleans.Clustering.AzureStorage +``` + +### [PackageReference](#tab/package-reference) + +```xml + + + + + +``` + +--- + +Next, in the _:::no-loc text="Program.cs":::_ file of your Orleans client project, add the Azure table storage client and then call . + +:::code language="csharp" source="snippets/Orleans/OrleansClient/Program.cs" range="6-7" ::: + +The following code is a complete example of an Orleans client project. It calls the `CounterGrain` grain defined in the Orleans server example above: :::code language="csharp" source="snippets/Orleans/OrleansClient/Program.cs" ::: ## Enabling OpenTelemetry -By convention, .NET Aspire solutions include a project for defining default configuration and behavior for your service. This project is called the _service default_ project and templates create it with a name ending in _ServiceDefaults_. To configure Orleans for OpenTelemetry in .NET Aspire, you need to apply configuration to your service defaults project following the [Orleans observability](/dotnet/orleans/host/monitoring/) guide. In short, you need to modify the `ConfigureOpenTelemetry` method to add the Orleans _meters_ and _tracing_ instruments. The following code snippet shows the modified _Extensions.cs_ file from a service defaults project that includes metrics and traces from Orleans. +By convention, .NET Aspire solutions include a project for defining default configuration and behavior for your service. This project is called the _service defaults_ project and templates create it with a name ending in _ServiceDefaults_. To configure Orleans for OpenTelemetry in .NET Aspire, apply configuration to your service defaults project following the [Orleans observability](/dotnet/orleans/host/monitoring/) guide. + +Modify the `ConfigureOpenTelemetry` method to add the Orleans _meters_ and _tracing_ instruments. The following code snippet shows the modified _Extensions.cs_ file from a service defaults project that includes metrics and traces from Orleans. :::code language="csharp" source="snippets/Orleans/OrleansServiceDefaults/Extensions.cs" range="40-68" highlight="15,19-20"::: @@ -124,4 +191,5 @@ Streaming providers aren't supported as of Orleans version 8.1.0. ## Next steps > [!div class="nextstepaction"] +> [Microsoft Orleans documentation](/dotnet/orleans/) > [Explore the Orleans voting sample app](/samples/dotnet/aspire-samples/orleans-voting-sample-app-on-aspire/) diff --git a/docs/frameworks/snippets/Orleans/OrleansAppHost/Program.cs b/docs/frameworks/snippets/Orleans/OrleansAppHost/Program.cs index 640ae32b4f..8376091572 100644 --- a/docs/frameworks/snippets/Orleans/OrleansAppHost/Program.cs +++ b/docs/frameworks/snippets/Orleans/OrleansAppHost/Program.cs @@ -13,9 +13,9 @@ .WithClustering(clusteringTable) .WithGrainStorage("Default", grainStorage); -// Add our server project and reference your 'orleans' resource from it. -// it can join the Orleans cluster as a service. -// This implicitly add references to the required resources. +// Add your server project and reference your 'orleans' resource from it. +// It can join the Orleans cluster as a silo. +// This implicitly adds references to the required resources. // In this case, that is the 'clusteringTable' resource declared earlier. builder.AddProject("silo") .WithReference(orleans) From 2f33d718449840ae77534a1b18afee8b78bc46f7 Mon Sep 17 00:00:00 2001 From: David Pine Date: Wed, 8 Jan 2025 09:28:12 -0600 Subject: [PATCH 2/2] Rewrite of the Azure Cosmos DB articles (#2324) * Initial rewrite of the Azure Cosmos DB. * Fix MD issue * Fix links * Fix more links * Add clarifying message about add database call * Remove CORS config --- ...-cosmos-db-entity-framework-integration.md | 131 +++++----- docs/database/azure-cosmos-db-integration.md | 164 ++++++------ docs/database/includes/cosmos-app-host.md | 233 ++++++++++++++++++ .../AppHost/Program.ConfigureCosmosInfra.cs | 24 ++ 4 files changed, 386 insertions(+), 166 deletions(-) create mode 100644 docs/database/includes/cosmos-app-host.md create mode 100644 docs/snippets/azure/AppHost/Program.ConfigureCosmosInfra.cs diff --git a/docs/database/azure-cosmos-db-entity-framework-integration.md b/docs/database/azure-cosmos-db-entity-framework-integration.md index cb249d33cc..75c392b512 100644 --- a/docs/database/azure-cosmos-db-entity-framework-integration.md +++ b/docs/database/azure-cosmos-db-entity-framework-integration.md @@ -1,15 +1,27 @@ --- -title: .NET Aspire Microsoft Entity Framework Core Cosmos DB integration -description: This article describes the .NET Aspire Microsoft Entity Framework Core Cosmos DB integration features and capabilities. -ms.topic: how-to -ms.date: 08/12/2024 +title: .NET Aspire Cosmos DB Entity Framework Core integration +description: Learn how to install and configure the .NET Aspire Cosmos DB Entity Framework Core integration to connect to existing Cosmos DB instances or create new instances from .NET with the Azure Cosmos DB emulator. +ms.date: 12/18/2024 +uid: dotnet/aspire/azure-cosmos-db-entity-framework-integration --- -# .NET Aspire Microsoft Entity Framework Core Cosmos DB integration +# .NET Aspire Cosmos DB Entity Framework Core integration -In this article, you learn how to use the .NET Aspire Microsoft Entity Framework Core Cosmos DB integration. The `Aspire.Microsoft.EntityFrameworkCore.Cosmos` library is used to register a as a singleton in the DI container for connecting to Azure Cosmos DB. It also enables corresponding health checks, logging and telemetry. +[!INCLUDE [includes-hosting-and-client](../includes/includes-hosting-and-client.md)] -## Get started +[Azure Cosmos DB](https://azure.microsoft.com/services/cosmos-db/) is a fully managed NoSQL database service for modern app development. The .NET Aspire Cosmos DB Entity Framework Core integration enables you to connect to existing Cosmos DB instances or create new instances from .NET with the Azure Cosmos DB emulator. + +## Hosting integration + +[!INCLUDE [cosmos-app-host](includes/cosmos-app-host.md)] + +### Hosting integration health checks + +The Azure Cosmos DB hosting integration automatically adds a health check for the Cosmos DB resource. The health check verifies that the Cosmos DB is running and that a connection can be established to it. + +The hosting integration relies on the [📦 AspNetCore.HealthChecks.CosmosDb](https://www.nuget.org/packages/AspNetCore.HealthChecks.CosmosDb) NuGet package. + +## Client integration To get started with the .NET Aspire Microsoft Entity Framework Core Cosmos DB integration, install the [📦 Aspire.Microsoft.EntityFrameworkCore.Cosmos](https://www.nuget.org/packages/Aspire.Microsoft.EntityFrameworkCore.Cosmos) NuGet package in the client-consuming project, i.e., the project for the application that uses the Microsoft Entity Framework Core Cosmos DB client. @@ -28,16 +40,17 @@ dotnet add package Aspire.Microsoft.EntityFrameworkCore.Cosmos --- -For more information, see [dotnet add package](/dotnet/core/tools/dotnet-add-package) or [Manage package dependencies in .NET applications](/dotnet/core/tools/dependencies). - -## Example usage +### Add Cosmos DB context -In the _:::no-loc text="Program.cs":::_ file of your client-consuming project, call the extension to register a for use via the dependency injection container. +In the :::no-loc text="Program.cs"::: file of your client-consuming project, call the extension method to register a for use via the dependency injection container. The method takes a connection name parameter. ```csharp builder.AddCosmosDbContext("cosmosdb"); ``` +> [!TIP] +> The `connectionName` parameter must match the name used when adding the Cosmos DB resource in the app host project. In other words, when you call `AddAzureCosmosDB` and provide a name of `cosmosdb` that same name should be used when calling `AddCosmosDbContext`. For more information, see [Add Azure Cosmos DB resource](#add-azure-cosmos-db-resource). + You can then retrieve the instance using dependency injection. For example, to retrieve the client from a service: ```csharp @@ -49,49 +62,11 @@ public class ExampleService(MyDbContext context) For more information on using Entity Framework Core with Azure Cosmos DB, see the [Examples for Azure Cosmos DB for NoSQL SDK for .NET](/ef/core/providers/cosmos/?tabs=dotnet-core-cli). -## App host usage - -To add Azure Cosmos DB hosting support to your , install the [📦 Aspire.Hosting.Azure.CosmosDB](https://www.nuget.org/packages/Aspire.Hosting.Azure.CosmosDB) NuGet package in the [app host](xref:dotnet/aspire/app-host) project. - -### [.NET CLI](#tab/dotnet-cli) - -```dotnetcli -dotnet add package Aspire.Hosting.Azure.CosmosDB -``` - -### [PackageReference](#tab/package-reference) - -```xml - -``` - ---- - -In your app host project, register the .NET Aspire Microsoft Entity Framework Core Cosmos DB integration and consume the service using the following methods: - -```csharp -var builder = DistributedApplication.CreateBuilder(args); - -var cosmos = builder.AddAzureCosmosDB("cosmos"); -var cosmosdb = cosmos.AddDatabase("cosmosdb"); - -var exampleProject = builder.AddProject() - .WithReference(cosmosdb); -``` - -> [!TIP] -> To use the Azure Cosmos DB emulator, chain a call to the method. -> -> ```csharp -> cosmosdb.RunAsEmulator(); -> ``` - -## Configuration +### Configuration The .NET Aspire Microsoft Entity Framework Core Cosmos DB integration provides multiple options to configure the Azure Cosmos DB connection based on the requirements and conventions of your project. -### Use a connection string +#### Use a connection string When using a connection string from the `ConnectionStrings` configuration section, you can provide the name of the connection string when calling `builder.AddCosmosDbContext`: @@ -111,9 +86,9 @@ And then the connection string will be retrieved from the `ConnectionStrings` co For more information, see the [ConnectionString documentation](/azure/cosmos-db/nosql/how-to-dotnet-get-started#connect-with-a-connection-string). -### Use configuration providers +#### Use configuration providers -The .NET Aspire Microsoft Entity Framework Core Cosmos DB integration supports . It loads the from _:::no-loc text="appsettings.json":::_ or other configuration files using `Aspire:Microsoft:EntityFrameworkCore:Cosmos` key. Example _:::no-loc text="appsettings.json":::_ that configures some of the options: +The .NET Aspire Microsoft Entity Framework Core Cosmos DB integration supports . It loads the from configuration files such as _:::no-loc text="appsettings.json":::_. Example _:::no-loc text="appsettings.json"::: that configures some of the options: ```json { @@ -129,7 +104,9 @@ The .NET Aspire Microsoft Entity Framework Core Cosmos DB integration supports < } ``` -### Use inline delegates +For the complete Cosmos DB client integration JSON schema, see [Aspire.Microsoft.EntityFrameworkCore.Cosmos/ConfigurationSchema.json](https://github.com/dotnet/aspire/blob/v9.0.0/src/Components/Aspire.Microsoft.EntityFrameworkCore.Cosmos/ConfigurationSchema.json). + +#### Use inline delegates You can also pass the `Action configureSettings` delegate to set up some or all the options inline, for example to disable tracing from code: @@ -139,44 +116,46 @@ builder.AddCosmosDbContext( settings => settings.DisableTracing = true); ``` -[!INCLUDE [integration-health-checks](../includes/integration-health-checks.md)] +### Client integration health checks + +By default, .NET Aspire integrations enable health checks for all services. For more information, see [.NET Aspire integrations overview](../fundamentals/integrations-overview.md). The .NET Aspire Microsoft Entity Framework Core Cosmos DB integration currently doesn't implement health checks, though this may change in future releases. [!INCLUDE [integration-observability-and-telemetry](../includes/integration-observability-and-telemetry.md)] -### Logging +#### Logging The .NET Aspire Microsoft Entity Framework Core Cosmos DB integration uses the following log categories: -- Azure-Cosmos-Operation-Request-Diagnostics -- Microsoft.EntityFrameworkCore.ChangeTracking -- Microsoft.EntityFrameworkCore.Database.Command -- Microsoft.EntityFrameworkCore.Infrastructure -- Microsoft.EntityFrameworkCore.Query +- `Azure-Cosmos-Operation-Request-Diagnostics` +- `Microsoft.EntityFrameworkCore.ChangeTracking` +- `Microsoft.EntityFrameworkCore.Database.Command` +- `Microsoft.EntityFrameworkCore.Infrastructure` +- `Microsoft.EntityFrameworkCore.Query` -### Tracing +#### Tracing The .NET Aspire Microsoft Entity Framework Core Cosmos DB integration will emit the following tracing activities using OpenTelemetry: -- Azure.Cosmos.Operation -- OpenTelemetry.Instrumentation.EntityFrameworkCore +- `Azure.Cosmos.Operation` +- `OpenTelemetry.Instrumentation.EntityFrameworkCore` -### Metrics +#### Metrics The .NET Aspire Microsoft Entity Framework Core Cosmos DB integration currently supports the following metrics: -- Microsoft.EntityFrameworkCore" - - ec_Microsoft_EntityFrameworkCore_active_db_contexts - - ec_Microsoft_EntityFrameworkCore_total_queries - - ec_Microsoft_EntityFrameworkCore_queries_per_second - - ec_Microsoft_EntityFrameworkCore_total_save_changes - - ec_Microsoft_EntityFrameworkCore_save_changes_per_second - - ec_Microsoft_EntityFrameworkCore_compiled_query_cache_hit_rate - - ec_Microsoft_Entity_total_execution_strategy_operation_failures - - ec_Microsoft_E_execution_strategy_operation_failures_per_second - - ec_Microsoft_EntityFramew_total_optimistic_concurrency_failures - - ec_Microsoft_EntityF_optimistic_concurrency_failures_per_second +- `Microsoft.EntityFrameworkCore` + - `ec_Microsoft_EntityFrameworkCore_active_db_contexts` + - `ec_Microsoft_EntityFrameworkCore_total_queries` + - `ec_Microsoft_EntityFrameworkCore_queries_per_second` + - `ec_Microsoft_EntityFrameworkCore_total_save_changes` + - `ec_Microsoft_EntityFrameworkCore_save_changes_per_second` + - `ec_Microsoft_EntityFrameworkCore_compiled_query_cache_hit_rate` + - `ec_Microsoft_Entity_total_execution_strategy_operation_failures` + - `ec_Microsoft_E_execution_strategy_operation_failures_per_second` + - `ec_Microsoft_EntityFramew_total_optimistic_concurrency_failures` + - `ec_Microsoft_EntityF_optimistic_concurrency_failures_per_second` ## See also diff --git a/docs/database/azure-cosmos-db-integration.md b/docs/database/azure-cosmos-db-integration.md index 1a4542a8f8..028cd25567 100644 --- a/docs/database/azure-cosmos-db-integration.md +++ b/docs/database/azure-cosmos-db-integration.md @@ -1,17 +1,29 @@ --- title: .NET Aspire Azure Cosmos DB integration -description: This article describes the .NET Aspire Azure Cosmos DB integration features and capabilities. -ms.topic: how-to -ms.date: 08/12/2024 +description: Learn how to install and configure the .NET Aspire Azure Cosmos DB integration to connect to existing Cosmos DB instances or create new instances from .NET with the Azure Cosmos DB emulator. +ms.date: 12/18/2024 +uid: dotnet/aspire/azure-cosmos-db-integration --- # .NET Aspire Azure Cosmos DB integration -In this article, you learn how to use the .NET Aspire Azure Cosmos DB integration. The `Aspire.Microsoft.Azure.Cosmos` library is used to register a as a singleton in the DI container for connecting to Azure Cosmos DB. It also enables corresponding health checks, logging and telemetry. +[!INCLUDE [includes-hosting-and-client](../includes/includes-hosting-and-client.md)] -## Get started +[Azure Cosmos DB](https://azure.microsoft.com/services/cosmos-db/) is a fully managed NoSQL database service for modern app development. The .NET Aspire Azure Cosmos DB integration enables you to connect to existing Cosmos DB instances or create new instances from .NET with the Azure Cosmos DB emulator. -To get started with the .NET Aspire Azure Cosmos DB integration, install the [📦 Aspire.Microsoft.Azure.Cosmos](https://www.nuget.org/packages/Aspire.Microsoft.Azure.Cosmos) NuGet package in the client-consuming project, i.e., the project for the application that uses the Azure Cosmos DB client. +## Hosting integration + +[!INCLUDE [cosmos-app-host](includes/cosmos-app-host.md)] + +### Hosting integration health checks + +The Azure Cosmos DB hosting integration automatically adds a health check for the Cosmos DB resource. The health check verifies that the Cosmos DB is running and that a connection can be established to it. + +The hosting integration relies on the [📦 AspNetCore.HealthChecks.CosmosDb](https://www.nuget.org/packages/AspNetCore.HealthChecks.CosmosDb) NuGet package. + +## Client integration + +To get started with the .NET Aspire Azure Cosmos DB client integration, install the [📦 Aspire.Microsoft.Azure.Cosmos](https://www.nuget.org/packages/Aspire.Microsoft.Azure.Cosmos) NuGet package in the client-consuming project, that is, the project for the application that uses the Cosmos DB client. The Cosmos DB client integration registers a instance that you can use to interact with Cosmos DB. ### [.NET CLI](#tab/dotnet-cli) @@ -28,17 +40,18 @@ dotnet add package Aspire.Microsoft.Azure.Cosmos --- -For more information, see [dotnet add package](/dotnet/core/tools/dotnet-add-package) or [Manage package dependencies in .NET applications](/dotnet/core/tools/dependencies). +### Add Cosmos DB client -## Example usage - -In the _:::no-loc text="Program.cs":::_ file of your client-consuming project, call the extension to register a for use via the dependency injection container. +In the :::no-loc text="Program.cs"::: file of your client-consuming project, call the extension method on any to register a for use via the dependency injection container. The method takes a connection name parameter. ```csharp -builder.AddAzureCosmosClient("cosmosConnectionName"); +builder.AddAzureCosmosClient(connectionName: "cosmos-db"); ``` -You can then retrieve the `CosmosClient` instance using dependency injection. For example, to retrieve the client from a service: +> [!TIP] +> The `connectionName` parameter must match the name used when adding the Cosmos DB resource in the app host project. In other words, when you call `AddAzureCosmosDB` and provide a name of `cosmos-db` that same name should be used when calling `AddAzureCosmosClient`. For more information, see [Add Azure Cosmos DB resource](#add-azure-cosmos-db-resource). + +You can then retrieve the instance using dependency injection. For example, to retrieve the connection from an example service: ```csharp public class ExampleService(CosmosClient client) @@ -47,99 +60,60 @@ public class ExampleService(CosmosClient client) } ``` -For more information on using the , see the [Examples for Azure Cosmos DB for NoSQL SDK for .NET](/azure/cosmos-db/nosql/samples-dotnet). - -## App host usage - -To add Azure Cosmos DB hosting support to your , install the [📦 Aspire.Hosting.Azure.CosmosDB](https://www.nuget.org/packages/Aspire.Hosting.Azure.CosmosDB) NuGet package in the [app host](xref:dotnet/aspire/app-host) project. This is helpful if you want Aspire to provision a new Azure Cosmos DB account for you, or if you want to use the Azure Cosmos DB emulator. If you want to use an Azure Cosmos DB account that is already provisioned, there's no need to add it to the app host project. +For more information on dependency injection, see [.NET dependency injection](/dotnet/core/extensions/dependency-injection). -### [.NET CLI](#tab/dotnet-cli) - -```dotnetcli -dotnet add package Aspire.Hosting.Azure.CosmosDB -``` +### Add keyed Cosmos DB client -### [PackageReference](#tab/package-reference) +There might be situations where you want to register multiple `CosmosClient` instances with different connection names. To register keyed Cosmos DB clients, call the method: -```xml - +```csharp +builder.AddKeyedAzureCosmosClient(name: "mainDb"); +builder.AddKeyedAzureCosmosClient(name: "loggingDb"); ``` ---- +> [!IMPORTANT] +> When using keyed services, it's expected that your Cosmos DB resource configured two named databases, one for the `mainDb` and one for the `loggingDb`. -In your app host project, register the .NET Aspire Azure Cosmos DB integration and consume the service using the following methods: +Then you can retrieve the `CosmosClient` instances using dependency injection. For example, to retrieve the connection from an example service: ```csharp -var builder = DistributedApplication.CreateBuilder(args); - -var cosmos = builder.AddAzureCosmosDB("myNewCosmosAccountName"); -var cosmosdb = cosmos.AddDatabase("myCosmosDatabaseName"); - -var exampleProject = builder.AddProject() - .WithReference(cosmosdb); +public class ExampleService( + [FromKeyedServices("mainDb")] CosmosClient mainDbClient, + [FromKeyedServices("loggingDb")] CosmosClient loggingDbClient) +{ + // Use clients... +} ``` -> [!TIP] -> To use the Azure Cosmos DB emulator, chain a call to the method. -> -> ```csharp -> cosmosdb.RunAsEmulator(); -> ``` -> -> Starting the Cosmos DB emulator may take some time. Use to delay your .NET project's code execution until the emulator is running and ready to serve requests. -> -> ```csharp -> var exampleProject = builder.AddProject() -> .WithReference(cosmosdb) -> .WaitFor(cosmosdb); -> ``` +For more information on keyed services, see [.NET dependency injection: Keyed services](/dotnet/core/extensions/dependency-injection#keyed-services). -## Configuration +### Configuration -The .NET Aspire Azure Cosmos DB library provides multiple options to configure the `CosmosClient` connection based on the requirements and conventions of your project. +The .NET Aspire Azure Cosmos DB integration provides multiple options to configure the connection based on the requirements and conventions of your project. -### Use a connection string +#### Use a connection string -When using a connection string from the `ConnectionStrings` configuration section, you can provide the name of the connection string when calling `builder.AddAzureCosmosClient`: +When using a connection string from the `ConnectionStrings` configuration section, you can provide the name of the connection string when calling the method: ```csharp -builder.AddAzureCosmosClient("cosmosConnectionName"); +builder.AddAzureCosmosClient("cosmos-db"); ``` -And then the connection string will be retrieved from the `ConnectionStrings` configuration section: +Then the connection string is retrieved from the `ConnectionStrings` configuration section: ```json { "ConnectionStrings": { - "cosmosConnectionName": "https://{account_name}.documents.azure.com:443/" + "cosmos-db": "AccountEndpoint=https://{account_name}.documents.azure.com:443/;AccountKey={account_key};" } } ``` -The recommended connection approach is to use an account endpoint, which works with the property to establish a connection. If no credential is configured, the is used: +For more information on how to format this connection string, see the ConnectionString documentation. -```json -{ - "ConnectionStrings": { - "cosmosConnectionName": "https://{account_name}.documents.azure.com:443/" - } -} -``` +#### Use configuration providers -Alternatively, an Azure Cosmos DB connection string can be used: - -```json -{ - "ConnectionStrings": { - "cosmosConnectionName": "AccountEndpoint=https://{account_name}.documents.azure.com:443/;AccountKey={account_key};" - } -} -``` - -### Use configuration providers - -The .NET Aspire Azure Cosmos DB integration supports . It loads the from _:::no-loc text="appsettings.json":::_ or other configuration files using `Aspire:Microsoft:Azure:Cosmos` key. Example _:::no-loc text="appsettings.json":::_ that configures some of the options: +The .NET Aspire Azure Cosmos DB integration supports . It loads the from configuration by using the `Aspire:Microsoft:Azure:Cosmos` key. The following snippet is an example of a :::no-loc text="appsettings.json"::: file that configures some of the options: ```json { @@ -155,13 +129,15 @@ The .NET Aspire Azure Cosmos DB integration supports ` delegate to set up some or all the options inline, for example to disable tracing from code: +#### Use inline delegates + +Also you can pass the `Action configureSettings` delegate to set up some or all the options inline, for example to disable tracing from code: ```csharp builder.AddAzureCosmosClient( - "cosmosConnectionName", + "cosmos-db", static settings => settings.DisableTracing = true); ``` @@ -174,17 +150,22 @@ builder.AddAzureCosmosClient( clientOptions => clientOptions.ApplicationName = "myapp"); ``` -[!INCLUDE [integration-health-checks](../includes/integration-health-checks.md)] +### Client integration health checks + +By default, .NET Aspire integrations enable health checks for all services. For more information, see [.NET Aspire integrations overview](../fundamentals/integrations-overview.md). -The .NET Aspire Azure Cosmos DB integration currently doesn't implement health checks, though this may change in future releases. +The .NET Aspire Azure Cosmos DB integration: + +- Adds the health check when is `false`, which attempts to connect to the Cosmos DB. +- Integrates with the `/health` HTTP endpoint, which specifies all registered health checks must pass for app to be considered ready to accept traffic. [!INCLUDE [integration-observability-and-telemetry](../includes/integration-observability-and-telemetry.md)] -### Logging +#### Logging The .NET Aspire Azure Cosmos DB integration uses the following log categories: -- Azure-Cosmos-Operation-Request-Diagnostics +- `Azure-Cosmos-Operation-Request-Diagnostics` In addition to getting Azure Cosmos DB request diagnostics for failed requests, you can configure latency thresholds to determine which successful Azure Cosmos DB request diagnostics will be logged. The default values are 100 ms for point operations and 500 ms for non point operations. @@ -204,24 +185,27 @@ builder.AddAzureCosmosClient( }); ``` -### Tracing +#### Tracing The .NET Aspire Azure Cosmos DB integration will emit the following tracing activities using OpenTelemetry: -- Azure.Cosmos.Operation +- `Azure.Cosmos.Operation` -Azure Cosmos DB tracing is currently in preview, so you must set the experimental switch to ensure traces are emitted. [Learn more about tracing in Azure Cosmos DB.](/azure/cosmos-db/nosql/sdk-observability#trace-attributes) +Azure Cosmos DB tracing is currently in preview, so you must set the experimental switch to ensure traces are emitted. ```csharp AppContext.SetSwitch("Azure.Experimental.EnableActivitySource", true); ``` -### Metrics +For more information, see [Azure Cosmos DB SDK observability: Trace attributes](/azure/cosmos-db/nosql/sdk-observability?tabs=dotnet#trace-attributes). + +#### Metrics The .NET Aspire Azure Cosmos DB integration currently doesn't support metrics by default due to limitations with the Azure SDK. ## See also -- [Azure Cosmos DB docs](/azure/cosmos-db/introduction) -- [.NET Aspire integrations](../fundamentals/integrations-overview.md) +- [Azure Cosmos DB](https://azure.microsoft.com/services/cosmos-db) +- [.NET Aspire integrations overview](../fundamentals/integrations-overview.md) +- [.NET Aspire Azure integrations overview](../azure/integrations-overview.md) - [.NET Aspire GitHub repo](https://github.com/dotnet/aspire) diff --git a/docs/database/includes/cosmos-app-host.md b/docs/database/includes/cosmos-app-host.md new file mode 100644 index 0000000000..23563b49f1 --- /dev/null +++ b/docs/database/includes/cosmos-app-host.md @@ -0,0 +1,233 @@ +--- +ms.topic: include +--- + +The .NET Aspire [Azure Cosmos DB](https://azure.microsoft.com/services/cosmos-db/) hosting integration models the various Cosmos DB resources as the following types: + +- : Represents an Azure Cosmos DB resource. +- : Represents an Azure Cosmos DB emulator resource. + +To access these types and APIs for expressing them, add the [📦 Aspire.Hosting.Azure.CosmosDB](https://www.nuget.org/packages/Aspire.Hosting.Azure.CosmosDB) NuGet package in the [app host](xref:dotnet/aspire/app-host) project. + +### [.NET CLI](#tab/dotnet-cli) + +```dotnetcli +dotnet add package Aspire.Hosting.Azure.CosmosDB +``` + +### [PackageReference](#tab/package-reference) + +```xml + +``` + +--- + +For more information, see [dotnet add package](/dotnet/core/tools/dotnet-add-package) or [Manage package dependencies in .NET applications](/dotnet/core/tools/dependencies). + +### Add Azure Cosmos DB resource + +In your app host project, call to add and return an Azure Cosmos DB resource builder. + +```csharp +var builder = DistributedApplication.CreateBuilder(args); + +var cosmos = builder.AddAzureCosmosDB("cosmos-db"); + +// After adding all resources, run the app... +``` + +When you add an to the app host, it exposes other useful APIs to add databases and containers. In other words, you must add an `AzureCosmosDBResource` before adding any of the other Cosmos DB resources. + +> [!IMPORTANT] +> When you call , it implicitly calls —which adds support for generating Azure resources dynamically during app startup. The app must configure the appropriate subscription and location. For more information, see [Local provisioning: Configuration](../../azure/local-provisioning.md#configuration). + +#### Generated provisioning Bicep + +If you're new to [Bicep](/azure/azure-resource-manager/bicep/overview), it's a domain-specific language for defining Azure resources. With .NET Aspire, you don't need to write Bicep by-hand, instead the provisioning APIs generate Bicep for you. When you publish your app, the generated Bicep is output alongside the manifest file. When you add an Azure Cosmos DB resource, the following Bicep is generated: + + +
+
+Toggle Azure Cosmos DB Bicep. +

+ +:::code language="bicep" source="../../snippets/azure/AppHost/cosmos.module.bicep"::: + +

+
+ + +The preceding Bicep is a module that provisions an Azure Cosmos DB account with the following defaults: + +- `kind`: The kind of Cosmos DB account. The default is `GlobalDocumentDB`. +- `consistencyPolicy`: The consistency policy of the Cosmos DB account. The default is `Session`. +- `locations`: The locations for the Cosmos DB account. The default is the resource group's location. + +In addition to the Cosmos DB account, it also provisions an Azure Key Vault resource. This is used to store the Cosmos DB account's connection string securely. The generated Bicep is a starting point and can be customized to meet your specific requirements. + +#### Customize provisioning infrastructure + +All .NET Aspire Azure resources are subclasses of the type. This type enables the customization of the generated Bicep by providing a fluent API to configure the Azure resources—using the API. For example, you can configure the `kind`, `consistencyPolicy`, `locations`, and more. The following example demonstrates how to customize the Azure Cosmos DB resource: + +:::code language="csharp" source="../../snippets/azure/AppHost/Program.ConfigureCosmosInfra.cs" id="configure"::: + +The preceding code: + +- Chains a call to the API: + - The `infra` parameter is an instance of the type. + - The provisionable resources are retrieved by calling the method. + - The single is retrieved. + - The is assigned to a . + - A tag is added to the Cosmos DB account with a key of `ExampleKey` and a value of `Example value`. + +There are many more configuration options available to customize the Azure Cosmos DB resource. For more information, see . For more information, see [Azure.Provisioning customization](../../azure/integrations-overview.md#azureprovisioning-customization). + +### Connect to an existing Azure Cosmos DB account + +You might have an existing Azure Cosmos DB account that you want to connect to. Instead of representing a new Azure Cosmos DB resource, you can add a connection string to the app host. To add a connection to an existing Azure Cosmos DB account, call the method: + +```csharp +var builder = DistributedApplication.CreateBuilder(args); + +var cosmos = builder.AddConnectionString("cosmos-db"); + +builder.AddProject("web") + .WithReference(cosmos); + +// After adding all resources, run the app... +``` + +[!INCLUDE [connection-strings-alert](../../includes/connection-strings-alert.md)] + +The connection string is configured in the app host's configuration, typically under [User Secrets](/aspnet/core/security/app-secrets), under the `ConnectionStrings` section. The app host injects this connection string as an environment variable into all dependent resources, for example: + +```json +{ + "ConnectionStrings": { + "cosmos-db": "AccountEndpoint=https://{account_name}.documents.azure.com:443/;AccountKey={account_key};" + } +} +``` + +The dependent resource can access the injected connection string by calling the method, and passing the connection name as the parameter, in this case `"cosmos-db"`. The `GetConnectionString` API is shorthand for `IConfiguration.GetSection("ConnectionStrings")[name]`. + +### Add Azure Cosmos DB database resource + +To add an Azure Cosmos DB database resource, chain a call on an `IResourceBuilder` to the API: + +```csharp +var builder = DistributedApplication.CreateBuilder(args); + +var cosmos = builder.AddAzureCosmosDB("cosmos-db") + .AddDatabase("db"); + +// After adding all resources, run the app... +``` + +When you call `AddDatabase`, it configures your Cosmos DB resources to have a database named `db`. The database is created in the Cosmos DB account that's represented by the `AzureCosmosDBResource` that you added earlier. The database is a logical container for collections and users. For more information, see [Databases, containers, and items in Azure Cosmos DB](/azure/cosmos-db/resource-model). + +> [!NOTE] +> When using the `AddDatabase` API to add a database to an Azure Cosmos DB resource, if you're running the emulator, the database isn't actually created in the emulator. This API is intended to include a database in the [Bicep generated](#generated-provisioning-bicep) by the provisioning infrastructure. + +### Add Azure Cosmos DB emulator resource + +To add an Azure Cosmos DB emulator resource, chain a call on an `IResourceBuilder` to the API: + +```csharp +var builder = DistributedApplication.CreateBuilder(args); + +var cosmos = builder.AddAzureCosmosDB("cosmos-db") + .RunAsEmulator(); + +// After adding all resources, run the app... +``` + +When you call `RunAsEmulator`, it configures your Cosmos DB resources to run locally using an emulator. The emulator in this case is the [Azure Cosmos DB Emulator](/azure/cosmos-db/local-emulator). The Azure Cosmos DB Emulator provides a free local environment for testing your Azure Cosmos DB apps and it's a perfect companion to the .NET Aspire Azure hosting integration. The emulator isn't installed, instead, it's accessible to .NET Aspire as a container. When you add a container to the app host, as shown in the preceding example with the `mcr.microsoft.com/cosmosdb/emulator` image, it creates and starts the container when the app host starts. For more information, see [Container resource lifecycle](../../fundamentals/app-host-overview.md#container-resource-lifecycle). + +#### Configure Cosmos DB emulator container + +There are various configurations available to container resources, for example, you can configure the container's ports, environment variables, it's [lifetime](../../fundamentals/app-host-overview.md#container-resource-lifetime), and more. + +##### Configure Cosmos DB emulator container gateway port + +By default, the Cosmos DB emulator container when configured by .NET Aspire, exposes the following endpoints: + +| Endpoint | Container port | Host port | +|----------|----------------|-----------| +| `https` | 8081 | dynamic | + +The port that it's listening on is dynamic by default. When the container starts, the port is mapped to a random port on the host machine. To configure the endpoint port, chain calls on the container resource builder provided by the `RunAsEmulator` method as shown in the following example: + +```csharp +var builder = DistributedApplication.CreateBuilder(args); + +var cosmos = builder.AddAzureCosmosDB("cosmos-db").RunAsEmulator( + emulator => + { + emulator.WithGatewayPort(7777); + }); + +// After adding all resources, run the app... +``` + +The preceding code configures the Cosmos DB emulator container's existing `https` endpoint to listen on port `8081`. The Cosmos DB emulator container's port is mapped to the host port as shown in the following table: + +| Endpoint name | Port mapping (`container:host`) | +|--------------:|---------------------------------| +| `https` | `8081:7777` | + +##### Configure Cosmos DB emulator container with persistent lifetime + +To configure the Cosmos DB emulator container with a persistent lifetime, call the method on the Cosmos DB emulator container resource and pass : + +```csharp +var builder = DistributedApplication.CreateBuilder(args); + +var cosmos = builder.AddAzureCosmosDB("cosmos-db").RunAsEmulator( + emulator => + { + emulator.WithLifetime(ContainerLifetime.Persistent); + }); + +// After adding all resources, run the app... +``` + +For more information, see [Container resource lifetime](../../fundamentals/app-host-overview.md#container-resource-lifetime). + +##### Configure Cosmos DB emulator container with data volume + +To add a data volume to the Azure Cosmos DB emulator resource, call the method on the Azure Cosmos DB emulator resource: + +```csharp +var builder = DistributedApplication.CreateBuilder(args); + +var cosmos = builder.AddAzureCosmosDB("cosmos-db").RunAsEmulator( + emulator => + { + emulator.WithDataVolume(); + }); + +// After adding all resources, run the app... +``` + +The data volume is used to persist the Cosmos DB emulator data outside the lifecycle of its container. The data volume is mounted at the `/tmp/cosmos/appdata` path in the Cosmos DB emulator container and when a `name` parameter isn't provided, the name is generated. The emulator has its `AZURE_COSMOS_EMULATOR_ENABLE_DATA_PERSISTENCE` environment variable set to `true`. For more information on data volumes and details on why they're preferred over bind mounts, see [Docker docs: Volumes](https://docs.docker.com/engine/storage/volumes). + +#### Configure Cosmos DB emulator container partition count + +To configure the partition count of the Cosmos DB emulator container, call the method: + +```csharp +var builder = DistributedApplication.CreateBuilder(args); + +var cosmos = builder.AddAzureCosmosDB("cosmos-db").RunAsEmulator( + emulator => + { + emulator.WithPartitionCount(100); // Defaults to 25 + }); + +// After adding all resources, run the app... +``` + +The preceding code configures the Cosmos DB emulator container to have a partition count of `100`. This is a shorthand for setting the `AZURE_COSMOS_EMULATOR_PARTITION_COUNT` environment variable. diff --git a/docs/snippets/azure/AppHost/Program.ConfigureCosmosInfra.cs b/docs/snippets/azure/AppHost/Program.ConfigureCosmosInfra.cs new file mode 100644 index 0000000000..6d021dc491 --- /dev/null +++ b/docs/snippets/azure/AppHost/Program.ConfigureCosmosInfra.cs @@ -0,0 +1,24 @@ +using Azure.Provisioning.CosmosDB; + +internal static partial class Program +{ + public static void ConfigureCosmosInfra(IDistributedApplicationBuilder builder) + { + // + builder.AddAzureCosmosDB("cosmos-db") + .ConfigureInfrastructure(infra => + { + var cosmosDbAccount = infra.GetProvisionableResources() + .OfType() + .Single(); + + cosmosDbAccount.Kind = CosmosDBAccountKind.MongoDB; + cosmosDbAccount.ConsistencyPolicy = new() + { + DefaultConsistencyLevel = DefaultConsistencyLevel.Strong, + }; + cosmosDbAccount.Tags.Add("ExampleKey", "Example value"); + }); + // + } +}