diff --git a/dotnet/dotnet.sln b/dotnet/dotnet.sln index e76ebbf..c217dba 100644 --- a/dotnet/dotnet.sln +++ b/dotnet/dotnet.sln @@ -1,6 +1,6 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 +# 17 VisualStudioVersion = 17.5.002.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "net6.0", "net6.0", "{96F8E184-0AD2-4CC8-8B56-FC064C73E115}" @@ -15,7 +15,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "net8.0", "net8.0", "{82204A EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "consoleapp", "net8.0\consoleapp\consoleapp.csproj", "{73EC3307-ECBB-4F89-9307-FA59F73C454A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "razorpageapp", "net8.0\razorpageapp\razorpageapp.csproj", "{B7DCC524-D43F-4EE4-8C76-B29F5F595333}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "razorpageapp", "net8.0\razorpageapp\razorpageapp.csproj", "{B7DCC524-D43F-4EE4-8C76-B29F5F595333}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceDefaults", "net8.0\ServiceDefaults\ServiceDefaults.csproj", "{0C315506-9DFE-4099-B55C-60010E5B21DA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppHost", "net8.0\AppHost\AppHost.csproj", "{3FB90253-5CEC-480C-9DF6-5E45B09CDD12}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -39,6 +43,14 @@ Global {B7DCC524-D43F-4EE4-8C76-B29F5F595333}.Debug|Any CPU.Build.0 = Debug|Any CPU {B7DCC524-D43F-4EE4-8C76-B29F5F595333}.Release|Any CPU.ActiveCfg = Release|Any CPU {B7DCC524-D43F-4EE4-8C76-B29F5F595333}.Release|Any CPU.Build.0 = Release|Any CPU + {0C315506-9DFE-4099-B55C-60010E5B21DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C315506-9DFE-4099-B55C-60010E5B21DA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C315506-9DFE-4099-B55C-60010E5B21DA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C315506-9DFE-4099-B55C-60010E5B21DA}.Release|Any CPU.Build.0 = Release|Any CPU + {3FB90253-5CEC-480C-9DF6-5E45B09CDD12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3FB90253-5CEC-480C-9DF6-5E45B09CDD12}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3FB90253-5CEC-480C-9DF6-5E45B09CDD12}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3FB90253-5CEC-480C-9DF6-5E45B09CDD12}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -48,6 +60,8 @@ Global {1D2C0B5D-FCFD-4872-B38D-1661C8455F62} = {C6100442-FD97-4ABB-87CD-451375F8E9F2} {73EC3307-ECBB-4F89-9307-FA59F73C454A} = {82204ABB-A7FD-4904-BAFE-65834AFFFA3E} {B7DCC524-D43F-4EE4-8C76-B29F5F595333} = {82204ABB-A7FD-4904-BAFE-65834AFFFA3E} + {0C315506-9DFE-4099-B55C-60010E5B21DA} = {82204ABB-A7FD-4904-BAFE-65834AFFFA3E} + {3FB90253-5CEC-480C-9DF6-5E45B09CDD12} = {82204ABB-A7FD-4904-BAFE-65834AFFFA3E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8058C698-71A0-4FDF-AB5F-EDA80872CE2F} diff --git a/dotnet/net8.0/AppHost/AppHost.csproj b/dotnet/net8.0/AppHost/AppHost.csproj new file mode 100644 index 0000000..8588158 --- /dev/null +++ b/dotnet/net8.0/AppHost/AppHost.csproj @@ -0,0 +1,20 @@ + + + + Exe + net8.0 + enable + enable + true + 14c5edc2-3cb8-40c0-b3d1-e7a7dba832a8 + + + + + + + + + + + diff --git a/dotnet/net8.0/AppHost/Program.cs b/dotnet/net8.0/AppHost/Program.cs new file mode 100644 index 0000000..708cc7a --- /dev/null +++ b/dotnet/net8.0/AppHost/Program.cs @@ -0,0 +1,3 @@ +var builder = DistributedApplication.CreateBuilder(args); +builder.AddProject("razorpageapp"); +builder.Build().Run(); diff --git a/dotnet/net8.0/AppHost/Properties/launchSettings.json b/dotnet/net8.0/AppHost/Properties/launchSettings.json new file mode 100644 index 0000000..e666124 --- /dev/null +++ b/dotnet/net8.0/AppHost/Properties/launchSettings.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "https://localhost:17222;http://localhost:15104", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "DOTNET_ENVIRONMENT": "Development", + "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21172", + "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22261" + } + }, + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "http://localhost:15104", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "DOTNET_ENVIRONMENT": "Development", + "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19281", + "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20253" + } + } + } +} diff --git a/dotnet/net8.0/AppHost/appsettings.Development.json b/dotnet/net8.0/AppHost/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/dotnet/net8.0/AppHost/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/dotnet/net8.0/AppHost/appsettings.json b/dotnet/net8.0/AppHost/appsettings.json new file mode 100644 index 0000000..31c092a --- /dev/null +++ b/dotnet/net8.0/AppHost/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning", + "Aspire.Hosting.Dcp": "Warning" + } + } +} diff --git a/dotnet/net8.0/ServiceDefaults/Extensions.cs b/dotnet/net8.0/ServiceDefaults/Extensions.cs new file mode 100644 index 0000000..c404e89 --- /dev/null +++ b/dotnet/net8.0/ServiceDefaults/Extensions.cs @@ -0,0 +1,119 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Diagnostics.HealthChecks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.ServiceDiscovery; +using OpenTelemetry; +using OpenTelemetry.Metrics; +using OpenTelemetry.Trace; + +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 + public static class Extensions + { + public static IHostApplicationBuilder AddServiceDefaults(this IHostApplicationBuilder builder) + { + builder.ConfigureOpenTelemetry(); + + builder.AddDefaultHealthChecks(); + + builder.Services.AddServiceDiscovery(); + + builder.Services.ConfigureHttpClientDefaults(http => + { + // Turn on resilience by default + http.AddStandardResilienceHandler(); + + // Turn on service discovery by default + http.AddServiceDiscovery(); + }); + + // Uncomment the following to restrict the allowed schemes for service discovery. + // builder.Services.Configure(options => + // { + // options.AllowedSchemes = ["https"]; + // }); + + return builder; + } + + public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicationBuilder builder) + { + builder.Logging.AddOpenTelemetry(logging => + { + logging.IncludeFormattedMessage = true; + logging.IncludeScopes = true; + }); + + builder.Services.AddOpenTelemetry() + .WithMetrics(metrics => + { + metrics.AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + .AddRuntimeInstrumentation(); + }) + .WithTracing(tracing => + { + tracing.AddAspNetCoreInstrumentation() + // Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package) + //.AddGrpcClientInstrumentation() + .AddHttpClientInstrumentation(); + }); + + builder.AddOpenTelemetryExporters(); + + return builder; + } + + private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder) + { + var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]); + + if (useOtlpExporter) + { + builder.Services.AddOpenTelemetry().UseOtlpExporter(); + } + + // Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package) + //if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"])) + //{ + // builder.Services.AddOpenTelemetry() + // .UseAzureMonitor(); + //} + + return builder; + } + + public static IHostApplicationBuilder AddDefaultHealthChecks(this IHostApplicationBuilder builder) + { + builder.Services.AddHealthChecks() + // Add a default liveness check to ensure app is responsive + .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]); + + return builder; + } + + public static WebApplication MapDefaultEndpoints(this WebApplication app) + { + // Adding health checks endpoints to applications in non-development environments has security implications. + // See https://aka.ms/dotnet/aspire/healthchecks for details before enabling these endpoints in non-development environments. + if (app.Environment.IsDevelopment()) + { + // All health checks must pass for app to be considered ready to accept traffic after starting + app.MapHealthChecks("/health"); + + // Only health checks tagged with the "live" tag must pass for app to be considered alive + app.MapHealthChecks("/alive", new HealthCheckOptions + { + Predicate = r => r.Tags.Contains("live") + }); + } + + return app; + } + } +} diff --git a/dotnet/net8.0/ServiceDefaults/ServiceDefaults.csproj b/dotnet/net8.0/ServiceDefaults/ServiceDefaults.csproj new file mode 100644 index 0000000..84e9efc --- /dev/null +++ b/dotnet/net8.0/ServiceDefaults/ServiceDefaults.csproj @@ -0,0 +1,22 @@ + + + + net8.0 + enable + enable + true + + + + + + + + + + + + + + + diff --git a/dotnet/net8.0/razorpageapp/Program.cs b/dotnet/net8.0/razorpageapp/Program.cs index 1b8d3e8..5dfff43 100644 --- a/dotnet/net8.0/razorpageapp/Program.cs +++ b/dotnet/net8.0/razorpageapp/Program.cs @@ -4,8 +4,9 @@ builder. Services. AddRazorPages( ); builder.Services.AddApplicationInsightsTelemetry(); builder.Services.AddServiceProfiler(); +builder.AddServiceDefaults(); - var app = builder.Build(); +var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { @@ -30,4 +31,6 @@ return "This is a delayed response"; }); +app.MapDefaultEndpoints(); + app.Run(); diff --git a/dotnet/net8.0/razorpageapp/razorpageapp.csproj b/dotnet/net8.0/razorpageapp/razorpageapp.csproj index 23459fa..7aad760 100644 --- a/dotnet/net8.0/razorpageapp/razorpageapp.csproj +++ b/dotnet/net8.0/razorpageapp/razorpageapp.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -11,4 +11,8 @@ + + + +