From d03efc240439aaafbc6994e99f152737fb6dd2aa Mon Sep 17 00:00:00 2001 From: Varorbc Date: Tue, 30 Sep 2025 13:34:18 +0800 Subject: [PATCH 1/2] Update Aspire --- src/ProjectTemplates/GeneratedContent.targets | 6 +++--- .../.template.config/template.json | 4 ++-- .../{Program.cs => AppHost.cs} | 0 .../ChatWithCustomData-CSharp.AppHost.csproj.in | 1 - .../Properties/launchSettings.json | 8 ++++---- .../Extensions.cs | 16 ++++++++++++---- .../Services/Ingestion/DataIngestor.cs | 6 +++--- .../src/ChatWithCustomData/README.Aspire.md | 4 ++-- .../aichatweb/README.md | 4 ++-- .../aichatweb.AppHost/{Program.cs => AppHost.cs} | 0 .../Properties/launchSettings.json | 8 ++++---- .../aichatweb.AppHost/aichatweb.AppHost.csproj | 9 ++++----- .../aichatweb.ServiceDefaults/Extensions.cs | 16 ++++++++++++---- .../Services/Ingestion/DataIngestor.cs | 6 +++--- .../aichatweb/aichatweb.Web/aichatweb.Web.csproj | 6 +++--- .../aichatweb/Services/Ingestion/DataIngestor.cs | 6 +++--- .../aichatweb/README.md | 4 ++-- .../aichatweb.AppHost/{Program.cs => AppHost.cs} | 0 .../Properties/launchSettings.json | 8 ++++---- .../aichatweb.AppHost/aichatweb.AppHost.csproj | 5 ++--- .../aichatweb.ServiceDefaults/Extensions.cs | 16 ++++++++++++---- .../Services/Ingestion/DataIngestor.cs | 6 +++--- .../aichatweb/aichatweb.Web/aichatweb.Web.csproj | 4 ++-- .../aichatweb/README.md | 4 ++-- .../aichatweb.AppHost/{Program.cs => AppHost.cs} | 0 .../Properties/launchSettings.json | 8 ++++---- .../aichatweb.AppHost/aichatweb.AppHost.csproj | 7 +++---- .../aichatweb.ServiceDefaults/Extensions.cs | 16 ++++++++++++---- .../Services/Ingestion/DataIngestor.cs | 6 +++--- .../aichatweb/aichatweb.Web/aichatweb.Web.csproj | 2 +- .../aichatweb/Services/Ingestion/DataIngestor.cs | 6 +++--- 31 files changed, 110 insertions(+), 82 deletions(-) rename src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.AppHost/{Program.cs => AppHost.cs} (100%) rename test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.AppHost/{Program.cs => AppHost.cs} (100%) rename test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.AppHost/{Program.cs => AppHost.cs} (100%) rename test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.AppHost/{Program.cs => AppHost.cs} (100%) diff --git a/src/ProjectTemplates/GeneratedContent.targets b/src/ProjectTemplates/GeneratedContent.targets index 31093493821..b4cd8f3c7af 100644 --- a/src/ProjectTemplates/GeneratedContent.targets +++ b/src/ProjectTemplates/GeneratedContent.targets @@ -33,9 +33,9 @@ Specifies external packages that get referenced in generated template content. --> - 9.4.0 - 9.4.0-preview.1.25378.8 - 2.3.0-beta.1 + 9.5.0 + 9.5.0-preview.1.25474.7 + 2.3.0-beta.2 1.0.0-beta.9 1.14.0 11.6.1 diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/.template.config/template.json b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/.template.config/template.json index d95f7c41c13..865795822c2 100644 --- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/.template.config/template.json +++ b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/.template.config/template.json @@ -1,7 +1,7 @@ { "$schema": "http://json.schemastore.org/template", "author": "Microsoft", - "classifications": [ "Common", "AI", "Web", "Blazor", ".NET Aspire" ], + "classifications": [ "Common", "AI", "Web", "Blazor", "Aspire" ], "identity": "Microsoft.Extensions.AI.Templates.WebChat.CSharp", "name": "AI Chat Web App", "description": "A project template for creating an AI chat application, which uses retrieval-augmented generation (RAG) to chat with your own data.", @@ -177,7 +177,7 @@ "displayName": "Use Aspire orchestration", "datatype": "bool", "defaultValue": "false", - "description": "Create the project as a distributed application using .NET Aspire." + "description": "Create the project as a distributed application using Aspire." }, "IsAspire": { "type": "computed", diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.AppHost/Program.cs b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.AppHost/AppHost.cs similarity index 100% rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.AppHost/Program.cs rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.AppHost/AppHost.cs diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.AppHost/ChatWithCustomData-CSharp.AppHost.csproj.in b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.AppHost/ChatWithCustomData-CSharp.AppHost.csproj.in index 3bbd301af75..8f5b8baabc0 100644 --- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.AppHost/ChatWithCustomData-CSharp.AppHost.csproj.in +++ b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.AppHost/ChatWithCustomData-CSharp.AppHost.csproj.in @@ -7,7 +7,6 @@ net9.0 enable enable - true b2f4f5e9-1083-472c-8c3b-f055ac67ba54 diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.AppHost/Properties/launchSettings.json b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.AppHost/Properties/launchSettings.json index cff9159f816..ff3cb400c10 100644 --- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.AppHost/Properties/launchSettings.json +++ b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.AppHost/Properties/launchSettings.json @@ -9,8 +9,8 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development", "DOTNET_ENVIRONMENT": "Development", - "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21000", - "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22000" + "ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21000", + "ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22000" } }, "http": { @@ -21,8 +21,8 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development", "DOTNET_ENVIRONMENT": "Development", - "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19000", - "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20000" + "ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19000", + "ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20000" } } } diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.ServiceDefaults/Extensions.cs b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.ServiceDefaults/Extensions.cs index 108f1ed2a08..d274752091c 100644 --- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.ServiceDefaults/Extensions.cs +++ b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.ServiceDefaults/Extensions.cs @@ -10,11 +10,14 @@ namespace Microsoft.Extensions.Hosting; -// Adds common .NET Aspire services: service discovery, resilience, health checks, and OpenTelemetry. +// Adds common Aspire services: service discovery, resilience, health checks, and OpenTelemetry. // This project should be referenced by each service project in your solution. // To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults public static class Extensions { + private const string HealthEndpointPath = "/health"; + private const string AlivenessEndpointPath = "/alive"; + public static TBuilder AddServiceDefaults(this TBuilder builder) where TBuilder : IHostApplicationBuilder { builder.ConfigureOpenTelemetry(); @@ -77,7 +80,12 @@ public static TBuilder ConfigureOpenTelemetry(this TBuilder builder) w .WithTracing(tracing => { tracing.AddSource(builder.Environment.ApplicationName) - .AddAspNetCoreInstrumentation() + .AddAspNetCoreInstrumentation(tracing => + // Exclude health check requests from tracing + tracing.Filter = context => + !context.Request.Path.StartsWithSegments(HealthEndpointPath) + && !context.Request.Path.StartsWithSegments(AlivenessEndpointPath) + ) // Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package) //.AddGrpcClientInstrumentation() .AddHttpClientInstrumentation() @@ -124,10 +132,10 @@ public static WebApplication MapDefaultEndpoints(this WebApplication app) if (app.Environment.IsDevelopment()) { // All health checks must pass for app to be considered ready to accept traffic after starting - app.MapHealthChecks("/health"); + app.MapHealthChecks(HealthEndpointPath); // Only health checks tagged with the "live" tag must pass for app to be considered alive - app.MapHealthChecks("/alive", new HealthCheckOptions + app.MapHealthChecks(AlivenessEndpointPath, new HealthCheckOptions { Predicate = r => r.Tags.Contains("live") }); diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Services/Ingestion/DataIngestor.cs b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Services/Ingestion/DataIngestor.cs index 7eeb41c99fb..175cc505670 100644 --- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Services/Ingestion/DataIngestor.cs +++ b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Services/Ingestion/DataIngestor.cs @@ -31,7 +31,7 @@ public async Task IngestDataAsync(IIngestionSource source) var deletedDocuments = await source.GetDeletedDocumentsAsync(documentsForSource); foreach (var deletedDocument in deletedDocuments) { - logger.LogInformation("Removing ingested data for {documentId}", deletedDocument.DocumentId); + logger.LogInformation("Removing ingested data for {DocumentId}", deletedDocument.DocumentId); await DeleteChunksForDocumentAsync(deletedDocument); await documentsCollection.DeleteAsync(deletedDocument.Key); } @@ -39,7 +39,7 @@ public async Task IngestDataAsync(IIngestionSource source) var modifiedDocuments = await source.GetNewOrModifiedDocumentsAsync(documentsForSource); foreach (var modifiedDocument in modifiedDocuments) { - logger.LogInformation("Processing {documentId}", modifiedDocument.DocumentId); + logger.LogInformation("Processing {DocumentId}", modifiedDocument.DocumentId); await DeleteChunksForDocumentAsync(modifiedDocument); await documentsCollection.UpsertAsync(modifiedDocument); @@ -54,7 +54,7 @@ async Task DeleteChunksForDocumentAsync(IngestedDocument document) { var documentId = document.DocumentId; var chunksToDelete = await chunksCollection.GetAsync(record => record.DocumentId == documentId, int.MaxValue).ToListAsync(); - if (chunksToDelete.Any()) + if (chunksToDelete.Count != 0) { await chunksCollection.DeleteAsync(chunksToDelete.Select(r => r.Key)); } diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/README.Aspire.md b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/README.Aspire.md index 0b1934bfff7..0b4c8adcfbf 100644 --- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/README.Aspire.md +++ b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/README.Aspire.md @@ -143,9 +143,9 @@ Note: Qdrant and Docker are excellent open source products, but are not maintain ## Trust the localhost certificate -Several .NET Aspire templates include ASP.NET Core projects that are configured to use HTTPS by default. If this is the first time you're running the project, an exception might occur when loading the Aspire dashboard. This error can be resolved by trusting the self-signed development certificate with the .NET CLI. +Several Aspire templates include ASP.NET Core projects that are configured to use HTTPS by default. If this is the first time you're running the project, an exception might occur when loading the Aspire dashboard. This error can be resolved by trusting the self-signed development certificate with the .NET CLI. -See [Troubleshoot untrusted localhost certificate in .NET Aspire](https://learn.microsoft.com/dotnet/aspire/troubleshooting/untrusted-localhost-certificate) for more information. +See [Troubleshoot untrusted localhost certificate in Aspire](https://learn.microsoft.com/dotnet/aspire/troubleshooting/untrusted-localhost-certificate) for more information. # Updating JavaScript dependencies diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/README.md b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/README.md index d1459703de1..24f63d7aaa0 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/README.md +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/README.md @@ -47,9 +47,9 @@ Make sure to replace placeholder values with real configuration values. ## Trust the localhost certificate -Several .NET Aspire templates include ASP.NET Core projects that are configured to use HTTPS by default. If this is the first time you're running the project, an exception might occur when loading the Aspire dashboard. This error can be resolved by trusting the self-signed development certificate with the .NET CLI. +Several Aspire templates include ASP.NET Core projects that are configured to use HTTPS by default. If this is the first time you're running the project, an exception might occur when loading the Aspire dashboard. This error can be resolved by trusting the self-signed development certificate with the .NET CLI. -See [Troubleshoot untrusted localhost certificate in .NET Aspire](https://learn.microsoft.com/dotnet/aspire/troubleshooting/untrusted-localhost-certificate) for more information. +See [Troubleshoot untrusted localhost certificate in Aspire](https://learn.microsoft.com/dotnet/aspire/troubleshooting/untrusted-localhost-certificate) for more information. # Updating JavaScript dependencies diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.AppHost/Program.cs b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.AppHost/AppHost.cs similarity index 100% rename from test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.AppHost/Program.cs rename to test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.AppHost/AppHost.cs diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.AppHost/Properties/launchSettings.json b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.AppHost/Properties/launchSettings.json index 4444e808585..681e3bf0d26 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.AppHost/Properties/launchSettings.json +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.AppHost/Properties/launchSettings.json @@ -9,8 +9,8 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development", "DOTNET_ENVIRONMENT": "Development", - "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:9999", - "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:9999" + "ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:9999", + "ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:9999" } }, "http": { @@ -21,8 +21,8 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development", "DOTNET_ENVIRONMENT": "Development", - "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:9999", - "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:9999" + "ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:9999", + "ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:9999" } } } diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.AppHost/aichatweb.AppHost.csproj b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.AppHost/aichatweb.AppHost.csproj index 54bcd4bc3a0..2ba82b12b27 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.AppHost/aichatweb.AppHost.csproj +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.AppHost/aichatweb.AppHost.csproj @@ -1,20 +1,19 @@  - + Exe net9.0 enable enable - true secret - - - + + + diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.ServiceDefaults/Extensions.cs b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.ServiceDefaults/Extensions.cs index f56908872e0..b44d60b604b 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.ServiceDefaults/Extensions.cs +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.ServiceDefaults/Extensions.cs @@ -10,11 +10,14 @@ namespace Microsoft.Extensions.Hosting; -// Adds common .NET Aspire services: service discovery, resilience, health checks, and OpenTelemetry. +// Adds common Aspire services: service discovery, resilience, health checks, and OpenTelemetry. // This project should be referenced by each service project in your solution. // To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults public static class Extensions { + private const string HealthEndpointPath = "/health"; + private const string AlivenessEndpointPath = "/alive"; + public static TBuilder AddServiceDefaults(this TBuilder builder) where TBuilder : IHostApplicationBuilder { builder.ConfigureOpenTelemetry(); @@ -64,7 +67,12 @@ public static TBuilder ConfigureOpenTelemetry(this TBuilder builder) w .WithTracing(tracing => { tracing.AddSource(builder.Environment.ApplicationName) - .AddAspNetCoreInstrumentation() + .AddAspNetCoreInstrumentation(tracing => + // Exclude health check requests from tracing + tracing.Filter = context => + !context.Request.Path.StartsWithSegments(HealthEndpointPath) + && !context.Request.Path.StartsWithSegments(AlivenessEndpointPath) + ) // Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package) //.AddGrpcClientInstrumentation() .AddHttpClientInstrumentation() @@ -111,10 +119,10 @@ public static WebApplication MapDefaultEndpoints(this WebApplication app) if (app.Environment.IsDevelopment()) { // All health checks must pass for app to be considered ready to accept traffic after starting - app.MapHealthChecks("/health"); + app.MapHealthChecks(HealthEndpointPath); // Only health checks tagged with the "live" tag must pass for app to be considered alive - app.MapHealthChecks("/alive", new HealthCheckOptions + app.MapHealthChecks(AlivenessEndpointPath, new HealthCheckOptions { Predicate = r => r.Tags.Contains("live") }); diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.Web/Services/Ingestion/DataIngestor.cs b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.Web/Services/Ingestion/DataIngestor.cs index 59732141849..2fe43370071 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.Web/Services/Ingestion/DataIngestor.cs +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.Web/Services/Ingestion/DataIngestor.cs @@ -26,7 +26,7 @@ public async Task IngestDataAsync(IIngestionSource source) var deletedDocuments = await source.GetDeletedDocumentsAsync(documentsForSource); foreach (var deletedDocument in deletedDocuments) { - logger.LogInformation("Removing ingested data for {documentId}", deletedDocument.DocumentId); + logger.LogInformation("Removing ingested data for {DocumentId}", deletedDocument.DocumentId); await DeleteChunksForDocumentAsync(deletedDocument); await documentsCollection.DeleteAsync(deletedDocument.Key); } @@ -34,7 +34,7 @@ public async Task IngestDataAsync(IIngestionSource source) var modifiedDocuments = await source.GetNewOrModifiedDocumentsAsync(documentsForSource); foreach (var modifiedDocument in modifiedDocuments) { - logger.LogInformation("Processing {documentId}", modifiedDocument.DocumentId); + logger.LogInformation("Processing {DocumentId}", modifiedDocument.DocumentId); await DeleteChunksForDocumentAsync(modifiedDocument); await documentsCollection.UpsertAsync(modifiedDocument); @@ -49,7 +49,7 @@ async Task DeleteChunksForDocumentAsync(IngestedDocument document) { var documentId = document.DocumentId; var chunksToDelete = await chunksCollection.GetAsync(record => record.DocumentId == documentId, int.MaxValue).ToListAsync(); - if (chunksToDelete.Any()) + if (chunksToDelete.Count != 0) { await chunksCollection.DeleteAsync(chunksToDelete.Select(r => r.Key)); } diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.Web/aichatweb.Web.csproj b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.Web/aichatweb.Web.csproj index a4c6ec68b94..56e1e1ec23a 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.Web/aichatweb.Web.csproj +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/aichatweb.Web/aichatweb.Web.csproj @@ -8,14 +8,14 @@ - - + + - + diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Basic.verified/aichatweb/Services/Ingestion/DataIngestor.cs b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Basic.verified/aichatweb/Services/Ingestion/DataIngestor.cs index 65b520980c1..89fe287ebed 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Basic.verified/aichatweb/Services/Ingestion/DataIngestor.cs +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Basic.verified/aichatweb/Services/Ingestion/DataIngestor.cs @@ -26,7 +26,7 @@ public async Task IngestDataAsync(IIngestionSource source) var deletedDocuments = await source.GetDeletedDocumentsAsync(documentsForSource); foreach (var deletedDocument in deletedDocuments) { - logger.LogInformation("Removing ingested data for {documentId}", deletedDocument.DocumentId); + logger.LogInformation("Removing ingested data for {DocumentId}", deletedDocument.DocumentId); await DeleteChunksForDocumentAsync(deletedDocument); await documentsCollection.DeleteAsync(deletedDocument.Key); } @@ -34,7 +34,7 @@ public async Task IngestDataAsync(IIngestionSource source) var modifiedDocuments = await source.GetNewOrModifiedDocumentsAsync(documentsForSource); foreach (var modifiedDocument in modifiedDocuments) { - logger.LogInformation("Processing {documentId}", modifiedDocument.DocumentId); + logger.LogInformation("Processing {DocumentId}", modifiedDocument.DocumentId); await DeleteChunksForDocumentAsync(modifiedDocument); await documentsCollection.UpsertAsync(modifiedDocument); @@ -49,7 +49,7 @@ async Task DeleteChunksForDocumentAsync(IngestedDocument document) { var documentId = document.DocumentId; var chunksToDelete = await chunksCollection.GetAsync(record => record.DocumentId == documentId, int.MaxValue).ToListAsync(); - if (chunksToDelete.Any()) + if (chunksToDelete.Count != 0) { await chunksCollection.DeleteAsync(chunksToDelete.Select(r => r.Key)); } diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/README.md b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/README.md index c05c18281ef..94c542fda7f 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/README.md +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/README.md @@ -43,9 +43,9 @@ Learn more about [prototyping with AI models using GitHub Models](https://docs.g ## Trust the localhost certificate -Several .NET Aspire templates include ASP.NET Core projects that are configured to use HTTPS by default. If this is the first time you're running the project, an exception might occur when loading the Aspire dashboard. This error can be resolved by trusting the self-signed development certificate with the .NET CLI. +Several Aspire templates include ASP.NET Core projects that are configured to use HTTPS by default. If this is the first time you're running the project, an exception might occur when loading the Aspire dashboard. This error can be resolved by trusting the self-signed development certificate with the .NET CLI. -See [Troubleshoot untrusted localhost certificate in .NET Aspire](https://learn.microsoft.com/dotnet/aspire/troubleshooting/untrusted-localhost-certificate) for more information. +See [Troubleshoot untrusted localhost certificate in Aspire](https://learn.microsoft.com/dotnet/aspire/troubleshooting/untrusted-localhost-certificate) for more information. # Updating JavaScript dependencies diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.AppHost/Program.cs b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.AppHost/AppHost.cs similarity index 100% rename from test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.AppHost/Program.cs rename to test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.AppHost/AppHost.cs diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.AppHost/Properties/launchSettings.json b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.AppHost/Properties/launchSettings.json index 4444e808585..681e3bf0d26 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.AppHost/Properties/launchSettings.json +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.AppHost/Properties/launchSettings.json @@ -9,8 +9,8 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development", "DOTNET_ENVIRONMENT": "Development", - "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:9999", - "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:9999" + "ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:9999", + "ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:9999" } }, "http": { @@ -21,8 +21,8 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development", "DOTNET_ENVIRONMENT": "Development", - "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:9999", - "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:9999" + "ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:9999", + "ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:9999" } } } diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.AppHost/aichatweb.AppHost.csproj b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.AppHost/aichatweb.AppHost.csproj index ffef1abf363..a7c93eb2928 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.AppHost/aichatweb.AppHost.csproj +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.AppHost/aichatweb.AppHost.csproj @@ -1,18 +1,17 @@  - + Exe net9.0 enable enable - true secret - + diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.ServiceDefaults/Extensions.cs b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.ServiceDefaults/Extensions.cs index f56908872e0..b44d60b604b 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.ServiceDefaults/Extensions.cs +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.ServiceDefaults/Extensions.cs @@ -10,11 +10,14 @@ namespace Microsoft.Extensions.Hosting; -// Adds common .NET Aspire services: service discovery, resilience, health checks, and OpenTelemetry. +// Adds common Aspire services: service discovery, resilience, health checks, and OpenTelemetry. // This project should be referenced by each service project in your solution. // To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults public static class Extensions { + private const string HealthEndpointPath = "/health"; + private const string AlivenessEndpointPath = "/alive"; + public static TBuilder AddServiceDefaults(this TBuilder builder) where TBuilder : IHostApplicationBuilder { builder.ConfigureOpenTelemetry(); @@ -64,7 +67,12 @@ public static TBuilder ConfigureOpenTelemetry(this TBuilder builder) w .WithTracing(tracing => { tracing.AddSource(builder.Environment.ApplicationName) - .AddAspNetCoreInstrumentation() + .AddAspNetCoreInstrumentation(tracing => + // Exclude health check requests from tracing + tracing.Filter = context => + !context.Request.Path.StartsWithSegments(HealthEndpointPath) + && !context.Request.Path.StartsWithSegments(AlivenessEndpointPath) + ) // Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package) //.AddGrpcClientInstrumentation() .AddHttpClientInstrumentation() @@ -111,10 +119,10 @@ public static WebApplication MapDefaultEndpoints(this WebApplication app) if (app.Environment.IsDevelopment()) { // All health checks must pass for app to be considered ready to accept traffic after starting - app.MapHealthChecks("/health"); + app.MapHealthChecks(HealthEndpointPath); // Only health checks tagged with the "live" tag must pass for app to be considered alive - app.MapHealthChecks("/alive", new HealthCheckOptions + app.MapHealthChecks(AlivenessEndpointPath, new HealthCheckOptions { Predicate = r => r.Tags.Contains("live") }); diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.Web/Services/Ingestion/DataIngestor.cs b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.Web/Services/Ingestion/DataIngestor.cs index 59732141849..2fe43370071 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.Web/Services/Ingestion/DataIngestor.cs +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.Web/Services/Ingestion/DataIngestor.cs @@ -26,7 +26,7 @@ public async Task IngestDataAsync(IIngestionSource source) var deletedDocuments = await source.GetDeletedDocumentsAsync(documentsForSource); foreach (var deletedDocument in deletedDocuments) { - logger.LogInformation("Removing ingested data for {documentId}", deletedDocument.DocumentId); + logger.LogInformation("Removing ingested data for {DocumentId}", deletedDocument.DocumentId); await DeleteChunksForDocumentAsync(deletedDocument); await documentsCollection.DeleteAsync(deletedDocument.Key); } @@ -34,7 +34,7 @@ public async Task IngestDataAsync(IIngestionSource source) var modifiedDocuments = await source.GetNewOrModifiedDocumentsAsync(documentsForSource); foreach (var modifiedDocument in modifiedDocuments) { - logger.LogInformation("Processing {documentId}", modifiedDocument.DocumentId); + logger.LogInformation("Processing {DocumentId}", modifiedDocument.DocumentId); await DeleteChunksForDocumentAsync(modifiedDocument); await documentsCollection.UpsertAsync(modifiedDocument); @@ -49,7 +49,7 @@ async Task DeleteChunksForDocumentAsync(IngestedDocument document) { var documentId = document.DocumentId; var chunksToDelete = await chunksCollection.GetAsync(record => record.DocumentId == documentId, int.MaxValue).ToListAsync(); - if (chunksToDelete.Any()) + if (chunksToDelete.Count != 0) { await chunksCollection.DeleteAsync(chunksToDelete.Select(r => r.Key)); } diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.Web/aichatweb.Web.csproj b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.Web/aichatweb.Web.csproj index 7fe3b1022ee..ed4f3c914c8 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.Web/aichatweb.Web.csproj +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.BasicAspire.verified/aichatweb/aichatweb.Web/aichatweb.Web.csproj @@ -8,8 +8,8 @@ - - + + diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/README.md b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/README.md index 70e543ffeae..0ef2c04a907 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/README.md +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/README.md @@ -46,9 +46,9 @@ Note: Qdrant and Docker are excellent open source products, but are not maintain ## Trust the localhost certificate -Several .NET Aspire templates include ASP.NET Core projects that are configured to use HTTPS by default. If this is the first time you're running the project, an exception might occur when loading the Aspire dashboard. This error can be resolved by trusting the self-signed development certificate with the .NET CLI. +Several Aspire templates include ASP.NET Core projects that are configured to use HTTPS by default. If this is the first time you're running the project, an exception might occur when loading the Aspire dashboard. This error can be resolved by trusting the self-signed development certificate with the .NET CLI. -See [Troubleshoot untrusted localhost certificate in .NET Aspire](https://learn.microsoft.com/dotnet/aspire/troubleshooting/untrusted-localhost-certificate) for more information. +See [Troubleshoot untrusted localhost certificate in Aspire](https://learn.microsoft.com/dotnet/aspire/troubleshooting/untrusted-localhost-certificate) for more information. # Updating JavaScript dependencies diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.AppHost/Program.cs b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.AppHost/AppHost.cs similarity index 100% rename from test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.AppHost/Program.cs rename to test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.AppHost/AppHost.cs diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.AppHost/Properties/launchSettings.json b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.AppHost/Properties/launchSettings.json index 4444e808585..681e3bf0d26 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.AppHost/Properties/launchSettings.json +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.AppHost/Properties/launchSettings.json @@ -9,8 +9,8 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development", "DOTNET_ENVIRONMENT": "Development", - "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:9999", - "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:9999" + "ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:9999", + "ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:9999" } }, "http": { @@ -21,8 +21,8 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development", "DOTNET_ENVIRONMENT": "Development", - "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:9999", - "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:9999" + "ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:9999", + "ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:9999" } } } diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.AppHost/aichatweb.AppHost.csproj b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.AppHost/aichatweb.AppHost.csproj index 7637a36ca6f..c78ef8c5d91 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.AppHost/aichatweb.AppHost.csproj +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.AppHost/aichatweb.AppHost.csproj @@ -1,19 +1,18 @@  - + Exe net9.0 enable enable - true secret - - + + diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.ServiceDefaults/Extensions.cs b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.ServiceDefaults/Extensions.cs index 81cc28b27d2..00a461ccec3 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.ServiceDefaults/Extensions.cs +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.ServiceDefaults/Extensions.cs @@ -10,11 +10,14 @@ namespace Microsoft.Extensions.Hosting; -// Adds common .NET Aspire services: service discovery, resilience, health checks, and OpenTelemetry. +// Adds common Aspire services: service discovery, resilience, health checks, and OpenTelemetry. // This project should be referenced by each service project in your solution. // To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults public static class Extensions { + private const string HealthEndpointPath = "/health"; + private const string AlivenessEndpointPath = "/alive"; + public static TBuilder AddServiceDefaults(this TBuilder builder) where TBuilder : IHostApplicationBuilder { builder.ConfigureOpenTelemetry(); @@ -72,7 +75,12 @@ public static TBuilder ConfigureOpenTelemetry(this TBuilder builder) w .WithTracing(tracing => { tracing.AddSource(builder.Environment.ApplicationName) - .AddAspNetCoreInstrumentation() + .AddAspNetCoreInstrumentation(tracing => + // Exclude health check requests from tracing + tracing.Filter = context => + !context.Request.Path.StartsWithSegments(HealthEndpointPath) + && !context.Request.Path.StartsWithSegments(AlivenessEndpointPath) + ) // Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package) //.AddGrpcClientInstrumentation() .AddHttpClientInstrumentation() @@ -119,10 +127,10 @@ public static WebApplication MapDefaultEndpoints(this WebApplication app) if (app.Environment.IsDevelopment()) { // All health checks must pass for app to be considered ready to accept traffic after starting - app.MapHealthChecks("/health"); + app.MapHealthChecks(HealthEndpointPath); // Only health checks tagged with the "live" tag must pass for app to be considered alive - app.MapHealthChecks("/alive", new HealthCheckOptions + app.MapHealthChecks(AlivenessEndpointPath, new HealthCheckOptions { Predicate = r => r.Tags.Contains("live") }); diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.Web/Services/Ingestion/DataIngestor.cs b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.Web/Services/Ingestion/DataIngestor.cs index d0f7a6bc3a8..894b85c10de 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.Web/Services/Ingestion/DataIngestor.cs +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.Web/Services/Ingestion/DataIngestor.cs @@ -26,7 +26,7 @@ public async Task IngestDataAsync(IIngestionSource source) var deletedDocuments = await source.GetDeletedDocumentsAsync(documentsForSource); foreach (var deletedDocument in deletedDocuments) { - logger.LogInformation("Removing ingested data for {documentId}", deletedDocument.DocumentId); + logger.LogInformation("Removing ingested data for {DocumentId}", deletedDocument.DocumentId); await DeleteChunksForDocumentAsync(deletedDocument); await documentsCollection.DeleteAsync(deletedDocument.Key); } @@ -34,7 +34,7 @@ public async Task IngestDataAsync(IIngestionSource source) var modifiedDocuments = await source.GetNewOrModifiedDocumentsAsync(documentsForSource); foreach (var modifiedDocument in modifiedDocuments) { - logger.LogInformation("Processing {documentId}", modifiedDocument.DocumentId); + logger.LogInformation("Processing {DocumentId}", modifiedDocument.DocumentId); await DeleteChunksForDocumentAsync(modifiedDocument); await documentsCollection.UpsertAsync(modifiedDocument); @@ -49,7 +49,7 @@ async Task DeleteChunksForDocumentAsync(IngestedDocument document) { var documentId = document.DocumentId; var chunksToDelete = await chunksCollection.GetAsync(record => record.DocumentId == documentId, int.MaxValue).ToListAsync(); - if (chunksToDelete.Any()) + if (chunksToDelete.Count != 0) { await chunksCollection.DeleteAsync(chunksToDelete.Select(r => r.Key)); } diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.Web/aichatweb.Web.csproj b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.Web/aichatweb.Web.csproj index 85dc735b4c4..03fba5231ac 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.Web/aichatweb.Web.csproj +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.Ollama_Qdrant.verified/aichatweb/aichatweb.Web/aichatweb.Web.csproj @@ -14,7 +14,7 @@ - + diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.OpenAI_AzureAISearch.verified/aichatweb/Services/Ingestion/DataIngestor.cs b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.OpenAI_AzureAISearch.verified/aichatweb/Services/Ingestion/DataIngestor.cs index 65b520980c1..89fe287ebed 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.OpenAI_AzureAISearch.verified/aichatweb/Services/Ingestion/DataIngestor.cs +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.OpenAI_AzureAISearch.verified/aichatweb/Services/Ingestion/DataIngestor.cs @@ -26,7 +26,7 @@ public async Task IngestDataAsync(IIngestionSource source) var deletedDocuments = await source.GetDeletedDocumentsAsync(documentsForSource); foreach (var deletedDocument in deletedDocuments) { - logger.LogInformation("Removing ingested data for {documentId}", deletedDocument.DocumentId); + logger.LogInformation("Removing ingested data for {DocumentId}", deletedDocument.DocumentId); await DeleteChunksForDocumentAsync(deletedDocument); await documentsCollection.DeleteAsync(deletedDocument.Key); } @@ -34,7 +34,7 @@ public async Task IngestDataAsync(IIngestionSource source) var modifiedDocuments = await source.GetNewOrModifiedDocumentsAsync(documentsForSource); foreach (var modifiedDocument in modifiedDocuments) { - logger.LogInformation("Processing {documentId}", modifiedDocument.DocumentId); + logger.LogInformation("Processing {DocumentId}", modifiedDocument.DocumentId); await DeleteChunksForDocumentAsync(modifiedDocument); await documentsCollection.UpsertAsync(modifiedDocument); @@ -49,7 +49,7 @@ async Task DeleteChunksForDocumentAsync(IngestedDocument document) { var documentId = document.DocumentId; var chunksToDelete = await chunksCollection.GetAsync(record => record.DocumentId == documentId, int.MaxValue).ToListAsync(); - if (chunksToDelete.Any()) + if (chunksToDelete.Count != 0) { await chunksCollection.DeleteAsync(chunksToDelete.Select(r => r.Key)); } From ce273c058f8d260194e8ab64bbef9d5c672547e4 Mon Sep 17 00:00:00 2001 From: Mackinnon Buck Date: Tue, 30 Sep 2025 14:10:10 -0700 Subject: [PATCH 2/2] Update Aspire template README --- .../src/ChatWithCustomData/README.Aspire.md | 32 +------------------ .../aichatweb/README.md | 13 +------- 2 files changed, 2 insertions(+), 43 deletions(-) diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/README.Aspire.md b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/README.Aspire.md index 0b4c8adcfbf..14aa513acae 100644 --- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/README.Aspire.md +++ b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/README.Aspire.md @@ -84,38 +84,8 @@ Note: Ollama and Docker are excellent open source products, but are not maintain #### ---#if (IsAzureOpenAI || UseAzureAISearch) ## Using Azure Provisioning -The project is set up to automatically provision Azure resources, but local configuration is configured. For detailed instructions, see the [Local Provisioning documentation](https://learn.microsoft.com/dotnet/aspire/azure/local-provisioning#configuration). +The project is set up to automatically provision Azure resources. When running the app for the first time, you will be prompted to provide Azure configuration values. For detailed instructions, see the [Local Provisioning documentation](https://learn.microsoft.com/dotnet/aspire/azure/local-provisioning#configuration). -#### ---#if (hostIdentifier == "vs") -Configure local provisioning for this project using .NET User Secrets: - -1. In Visual Studio, right-click on the ChatWithCustomData-CSharp.AppHost project in the Solution Explorer and select "Manage User Secrets". -2. This opens a `secrets.json` file where you can store your API keys without them being tracked in source control. Add the following configuration: - - ```json - { - "Azure": { - "SubscriptionId": "", - "AllowResourceGroupCreation": true, - "ResourceGroup": "", - "Location": "" - } - } - ``` - -#### ---#else -From the command line, configure local provisioning for this project using .NET User Secrets by running the following commands: - -```sh -cd ChatWithCustomData-CSharp.AppHost -dotnet user-secrets set Azure:SubscriptionId "" -dotnet user-secrets set Azure:AllowResourceGroupCreation "true" -dotnet user-secrets set Azure:ResourceGroup "" -dotnet user-secrets set Azure:Location "" -``` -#### ---#endif - -Make sure to replace placeholder values with real configuration values. #### ---#endif #### ---#if (UseQdrant) diff --git a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/README.md b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/README.md index 24f63d7aaa0..a2f61924c32 100644 --- a/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/README.md +++ b/test/ProjectTemplates/Microsoft.Extensions.AI.Templates.IntegrationTests/Snapshots/aichatweb.AzureOpenAI_Qdrant_Aspire.verified/aichatweb/README.md @@ -17,19 +17,8 @@ This incompatibility can be addressed by upgrading to Docker Desktop 4.41.1. See ## Using Azure Provisioning -The project is set up to automatically provision Azure resources, but local configuration is configured. For detailed instructions, see the [Local Provisioning documentation](https://learn.microsoft.com/dotnet/aspire/azure/local-provisioning#configuration). +The project is set up to automatically provision Azure resources. When running the app for the first time, you will be prompted to provide Azure configuration values. For detailed instructions, see the [Local Provisioning documentation](https://learn.microsoft.com/dotnet/aspire/azure/local-provisioning#configuration). -From the command line, configure local provisioning for this project using .NET User Secrets by running the following commands: - -```sh -cd aichatweb.AppHost -dotnet user-secrets set Azure:SubscriptionId "" -dotnet user-secrets set Azure:AllowResourceGroupCreation "true" -dotnet user-secrets set Azure:ResourceGroup "" -dotnet user-secrets set Azure:Location "" -``` - -Make sure to replace placeholder values with real configuration values. # Running the application