diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props index 6daf4e67a673..faa6bae454a1 100644 --- a/dotnet/Directory.Packages.props +++ b/dotnet/Directory.Packages.props @@ -12,7 +12,7 @@ - + @@ -49,8 +49,10 @@ - - + + @@ -94,12 +96,14 @@ - + - + diff --git a/dotnet/samples/Demos/AgentFrameworkWithAspire/ChatWithAgent.AppHost/ChatWithAgent.AppHost.csproj b/dotnet/samples/Demos/AgentFrameworkWithAspire/ChatWithAgent.AppHost/ChatWithAgent.AppHost.csproj index ed2d670a7ef8..6f27fe618eba 100644 --- a/dotnet/samples/Demos/AgentFrameworkWithAspire/ChatWithAgent.AppHost/ChatWithAgent.AppHost.csproj +++ b/dotnet/samples/Demos/AgentFrameworkWithAspire/ChatWithAgent.AppHost/ChatWithAgent.AppHost.csproj @@ -1,6 +1,6 @@  - + Exe diff --git a/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.AppHost/ProcessFramework.Aspire.AppHost.csproj b/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.AppHost/ProcessFramework.Aspire.AppHost.csproj index 4c8cfe4b3363..9310b9a042eb 100644 --- a/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.AppHost/ProcessFramework.Aspire.AppHost.csproj +++ b/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.AppHost/ProcessFramework.Aspire.AppHost.csproj @@ -1,6 +1,6 @@  - + Exe diff --git a/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.AppHost/Program.cs b/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.AppHost/Program.cs index d286b93ccf92..e5fc1b3f7a5f 100644 --- a/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.AppHost/Program.cs +++ b/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.AppHost/Program.cs @@ -12,6 +12,12 @@ var processOrchestrator = builder.AddProject("processorchestrator") .WithReference(translateAgent) - .WithReference(summaryAgent); + .WithReference(summaryAgent) + .WithHttpCommand("/api/processdoc", "Trigger Process", + commandOptions: new() + { + Method = HttpMethod.Get + } + ); builder.Build().Run(); diff --git a/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.ProcessOrchestrator/Program.cs b/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.ProcessOrchestrator/Program.cs index de3d58905e35..d59b135b9bac 100644 --- a/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.ProcessOrchestrator/Program.cs +++ b/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.ProcessOrchestrator/Program.cs @@ -1,46 +1,14 @@ // Copyright (c) Microsoft. All rights reserved. using Microsoft.SemanticKernel; -using OpenTelemetry; -using OpenTelemetry.Exporter; -using OpenTelemetry.Logs; -using OpenTelemetry.Metrics; -using OpenTelemetry.Trace; using ProcessFramework.Aspire.ProcessOrchestrator; using ProcessFramework.Aspire.ProcessOrchestrator.Models; using ProcessFramework.Aspire.ProcessOrchestrator.Steps; var builder = WebApplication.CreateBuilder(args); -string otelExporterEndpoint = builder.GetConfiguration("OTEL_EXPORTER_OTLP_ENDPOINT"); -string otelExporterHeaders = builder.GetConfiguration("OTEL_EXPORTER_OTLP_HEADERS"); - AppContext.SetSwitch("Microsoft.SemanticKernel.Experimental.GenAI.EnableOTelDiagnosticsSensitive", true); -var loggerFactory = LoggerFactory.Create(builder => -{ - // Add OpenTelemetry as a logging provider - builder.AddOpenTelemetry(options => - { - options.AddOtlpExporter(exporter => { exporter.Endpoint = new Uri(otelExporterEndpoint); exporter.Headers = otelExporterHeaders; exporter.Protocol = OtlpExportProtocol.Grpc; }); - // Format log messages. This defaults to false. - options.IncludeFormattedMessage = true; - }); - - builder.AddTraceSource("Microsoft.SemanticKernel"); - builder.SetMinimumLevel(LogLevel.Information); -}); - -using var traceProvider = Sdk.CreateTracerProviderBuilder() - .AddSource("Microsoft.SemanticKernel*") - .AddOtlpExporter(exporter => { exporter.Endpoint = new Uri(otelExporterEndpoint); exporter.Headers = otelExporterHeaders; exporter.Protocol = OtlpExportProtocol.Grpc; }) - .Build(); - -using var meterProvider = Sdk.CreateMeterProviderBuilder() - .AddMeter("Microsoft.SemanticKernel*") - .AddOtlpExporter(exporter => { exporter.Endpoint = new Uri(otelExporterEndpoint); exporter.Headers = otelExporterHeaders; exporter.Protocol = OtlpExportProtocol.Grpc; }) - .Build(); - builder.AddServiceDefaults(); builder.Services.AddHttpClient(client => { client.BaseAddress = new("https+http://translatoragent"); }); builder.Services.AddHttpClient(client => { client.BaseAddress = new("https+http://summaryagent"); }); diff --git a/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.ServiceDefaults/Extensions.cs b/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.ServiceDefaults/CommonExtensions.cs similarity index 60% rename from dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.ServiceDefaults/Extensions.cs rename to dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.ServiceDefaults/CommonExtensions.cs index b95812023687..3a9b4d9241af 100644 --- a/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.ServiceDefaults/Extensions.cs +++ b/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.ServiceDefaults/CommonExtensions.cs @@ -12,30 +12,21 @@ namespace Microsoft.Extensions.Hosting; /// -/// Adds common .NET 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 +/// Provides extension methods for adding common .NET Aspire services, including service discovery, +/// resilience, health checks, and OpenTelemetry. /// -public static class ServiceExtensions +public static class CommonExtensions { - /// - /// Gets a configuration setting from the WebApplicationBuilder. - /// - /// The WebApplicationBuilder instance. - /// The name of the configuration setting. - /// The value of the configuration setting. - /// Thrown when the configuration setting is missing. - public static string GetConfiguration(this WebApplicationBuilder builder, string settingName) - { - return builder.Configuration[settingName] ?? throw new InvalidOperationException($"Missing configuration setting: {settingName}"); - } + private const string HealthEndpointPath = "/health"; + private const string AlivenessEndpointPath = "/alive"; /// - /// Adds default services to the application builder. + /// Adds default services to the application, including OpenTelemetry, health checks, + /// service discovery, and HTTP client defaults with resilience and service discovery enabled. /// - /// The type of the application builder. - /// The application builder instance. - /// The application builder instance with default services added. + /// The type of the host application builder. + /// The host application builder instance. + /// The updated host application builder. public static TBuilder AddServiceDefaults(this TBuilder builder) where TBuilder : IHostApplicationBuilder { builder.ConfigureOpenTelemetry(); @@ -63,13 +54,14 @@ public static TBuilder AddServiceDefaults(this TBuilder builder) where } /// - /// Configures OpenTelemetry for the application builder. + /// Configures OpenTelemetry for the application, including logging, metrics, and tracing. /// - /// The type of the application builder. - /// The application builder instance. - /// The application builder instance with OpenTelemetry configured. + /// The type of the host application builder. + /// The host application builder instance. + /// The updated host application builder. public static TBuilder ConfigureOpenTelemetry(this TBuilder builder) where TBuilder : IHostApplicationBuilder { + builder.Logging.AddTraceSource("Microsoft.SemanticKernel"); builder.Logging.AddOpenTelemetry(logging => { logging.IncludeFormattedMessage = true; @@ -81,15 +73,22 @@ public static TBuilder ConfigureOpenTelemetry(this TBuilder builder) w { metrics.AddAspNetCoreInstrumentation() .AddHttpClientInstrumentation() - .AddRuntimeInstrumentation(); + .AddRuntimeInstrumentation() + .AddMeter("Microsoft.SemanticKernel*"); }) .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(); + .AddHttpClientInstrumentation() + .AddSource("Microsoft.SemanticKernel*"); }); builder.AddOpenTelemetryExporters(); @@ -97,12 +96,6 @@ public static TBuilder ConfigureOpenTelemetry(this TBuilder builder) w return builder; } - /// - /// Adds OpenTelemetry exporters to the application builder. - /// - /// The type of the application builder. - /// The application builder instance. - /// The application builder instance with OpenTelemetry exporters added. private static TBuilder AddOpenTelemetryExporters(this TBuilder builder) where TBuilder : IHostApplicationBuilder { var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]); @@ -123,11 +116,11 @@ private static TBuilder AddOpenTelemetryExporters(this TBuilder builde } /// - /// Adds default health checks to the application builder. + /// Adds default health checks to the application, including a liveness check to ensure the app is responsive. /// - /// The type of the application builder. - /// The application builder instance. - /// The application builder instance with default health checks added. + /// The type of the host application builder. + /// The host application builder instance. + /// The updated host application builder. public static TBuilder AddDefaultHealthChecks(this TBuilder builder) where TBuilder : IHostApplicationBuilder { builder.Services.AddHealthChecks() @@ -138,10 +131,11 @@ public static TBuilder AddDefaultHealthChecks(this TBuilder builder) w } /// - /// Maps default endpoints for the application. + /// Maps default health check endpoints for the application. + /// Adds "/health" and "/alive" endpoints in development environments. /// - /// The WebApplication instance. - /// The WebApplication instance with default endpoints mapped. + /// The web application instance. + /// The updated web application instance. public static WebApplication MapDefaultEndpoints(this WebApplication app) { // Adding health checks endpoints to applications in non-development environments has security implications. @@ -149,10 +143,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/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.SummaryAgent/Program.cs b/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.SummaryAgent/Program.cs index 0fb9020d5202..2a31b2b9b796 100644 --- a/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.SummaryAgent/Program.cs +++ b/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.SummaryAgent/Program.cs @@ -1,57 +1,17 @@ // Copyright (c) Microsoft. All rights reserved. -using Azure.AI.OpenAI; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents; using Microsoft.SemanticKernel.ChatCompletion; -using OpenTelemetry; -using OpenTelemetry.Exporter; -using OpenTelemetry.Logs; -using OpenTelemetry.Metrics; -using OpenTelemetry.Trace; using ProcessFramework.Aspire.Shared; var builder = WebApplication.CreateBuilder(args); -string otelExporterEndpoint = builder.GetConfiguration("OTEL_EXPORTER_OTLP_ENDPOINT"); -string otelExporterHeaders = builder.GetConfiguration("OTEL_EXPORTER_OTLP_HEADERS"); - AppContext.SetSwitch("Microsoft.SemanticKernel.Experimental.GenAI.EnableOTelDiagnosticsSensitive", true); -var loggerFactory = LoggerFactory.Create(builder => -{ - // Add OpenTelemetry as a logging provider - builder.AddOpenTelemetry(options => - { - options.AddOtlpExporter(exporter => { exporter.Endpoint = new Uri(otelExporterEndpoint); exporter.Headers = otelExporterHeaders; exporter.Protocol = OtlpExportProtocol.Grpc; }); - // Format log messages. This defaults to false. - options.IncludeFormattedMessage = true; - }); - - builder.AddTraceSource("Microsoft.SemanticKernel"); - builder.SetMinimumLevel(LogLevel.Information); -}); - -using var traceProvider = Sdk.CreateTracerProviderBuilder() - .AddSource("Microsoft.SemanticKernel*") - .AddOtlpExporter(exporter => { exporter.Endpoint = new Uri(otelExporterEndpoint); exporter.Headers = otelExporterHeaders; exporter.Protocol = OtlpExportProtocol.Grpc; }) - .Build(); - -using var meterProvider = Sdk.CreateMeterProviderBuilder() - .AddMeter("Microsoft.SemanticKernel*") - .AddOtlpExporter(exporter => { exporter.Endpoint = new Uri(otelExporterEndpoint); exporter.Headers = otelExporterHeaders; exporter.Protocol = OtlpExportProtocol.Grpc; }) - .Build(); - builder.AddServiceDefaults(); builder.AddAzureOpenAIClient("openAiConnectionName"); -builder.Services.AddSingleton(builder => -{ - var kernelBuilder = Kernel.CreateBuilder(); - - kernelBuilder.AddAzureOpenAIChatCompletion("gpt-4o", builder.GetService()); - - return kernelBuilder.Build(); -}); +builder.Services.AddKernel().AddAzureOpenAIChatCompletion("gpt-4o"); var app = builder.Build(); diff --git a/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.TranslatorAgent/Program.cs b/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.TranslatorAgent/Program.cs index ac6080e44f18..1dbc6a991df9 100644 --- a/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.TranslatorAgent/Program.cs +++ b/dotnet/samples/Demos/ProcessFrameworkWithAspire/ProcessFramework.Aspire/ProcessFramework.Aspire.TranslatorAgent/Program.cs @@ -1,57 +1,17 @@ // Copyright (c) Microsoft. All rights reserved. -using Azure.AI.OpenAI; using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Agents; using Microsoft.SemanticKernel.ChatCompletion; -using OpenTelemetry; -using OpenTelemetry.Exporter; -using OpenTelemetry.Logs; -using OpenTelemetry.Metrics; -using OpenTelemetry.Trace; using ProcessFramework.Aspire.Shared; var builder = WebApplication.CreateBuilder(args); -string otelExporterEndpoint = builder.GetConfiguration("OTEL_EXPORTER_OTLP_ENDPOINT"); -string otelExporterHeaders = builder.GetConfiguration("OTEL_EXPORTER_OTLP_HEADERS"); - AppContext.SetSwitch("Microsoft.SemanticKernel.Experimental.GenAI.EnableOTelDiagnosticsSensitive", true); -var loggerFactory = LoggerFactory.Create(builder => -{ - // Add OpenTelemetry as a logging provider - builder.AddOpenTelemetry(options => - { - options.AddOtlpExporter(exporter => { exporter.Endpoint = new Uri(otelExporterEndpoint); exporter.Headers = otelExporterHeaders; exporter.Protocol = OtlpExportProtocol.Grpc; }); - // Format log messages. This defaults to false. - options.IncludeFormattedMessage = true; - }); - - builder.AddTraceSource("Microsoft.SemanticKernel"); - builder.SetMinimumLevel(LogLevel.Information); -}); - -using var traceProvider = Sdk.CreateTracerProviderBuilder() - .AddSource("Microsoft.SemanticKernel*") - .AddOtlpExporter(exporter => { exporter.Endpoint = new Uri(otelExporterEndpoint); exporter.Headers = otelExporterHeaders; exporter.Protocol = OtlpExportProtocol.Grpc; }) - .Build(); - -using var meterProvider = Sdk.CreateMeterProviderBuilder() - .AddMeter("Microsoft.SemanticKernel*") - .AddOtlpExporter(exporter => { exporter.Endpoint = new Uri(otelExporterEndpoint); exporter.Headers = otelExporterHeaders; exporter.Protocol = OtlpExportProtocol.Grpc; }) - .Build(); - builder.AddServiceDefaults(); builder.AddAzureOpenAIClient("openAiConnectionName"); -builder.Services.AddSingleton(builder => -{ - var kernelBuilder = Kernel.CreateBuilder(); - - kernelBuilder.AddAzureOpenAIChatCompletion("gpt-4o", builder.GetService()); - - return kernelBuilder.Build(); -}); +builder.Services.AddKernel().AddAzureOpenAIChatCompletion("gpt-4o"); var app = builder.Build();