diff --git a/README.md b/README.md index 1bc9d42..6424033 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,10 @@ public Startup(IConfiguration configuration) _options = new StartupOptions(); + // Middleware + _options + .AddMiddleware(); + // Add Swagger _options .AddOpenApi("v1") @@ -29,7 +33,8 @@ public Startup(IConfiguration configuration) // Add Monitoring _options - .AddMonitoring(Configuration["ServiceName"], Configuration["ServiceVersion"]) + .AddMonitoring() + .WithMeter(Observability.Meter.Name) .WithApplicationInsights(Configuration["AzureApplicationInsightsConnectionString"]) .WithPrometheus(); } @@ -82,12 +87,16 @@ We use Open Telemetry to provide monitoring for your application. The library pr Every project should have a `Observability.cs` class, which is responsible for defining the Meters. ```csharp +using System.Diagnostics; using System.Diagnostics.Metrics; using System.Reflection; using OpenTelemetry.Metrics; public class Observability { + // Define a default ActivitySource + public static readonly ActivitySource DefaultActivities = new ActivitySource("ServiceName"); + // Define a default Meter with name and version public static readonly Meter Meter = new("ServiceName", Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "0.0.0"); @@ -102,7 +111,8 @@ Make sure to register the Meter at Startup. ```csharp var options = new StartupOptions(); options - .AddMonitoring(Configuration["ServiceName"], Configuration["ServiceVersion"]) + .AddMonitoring() + .WithActivitySource(Observability.DefaultActivities.Name) .WithMeter(Observability.Meter.Name) // ... ``` @@ -114,3 +124,44 @@ Observability.Pings.Add(1); Observability.PingDelay.Record(new Random().Next(50, 100)); ``` + +Use Activities in your Code to create sections of code that can be traced. + +```csharp +using (var fistActivity = Observability.DefaultActivities.StartActivity("First section")) +{ + fistActivity.AddTag("date", DateTime.UtcNow.ToString()); + fistActivity.AddTag("section", "first"); + Thread.Sleep(100); // Do work + fistActivity.Stop(); +}; + +using (var secondActivity = Observability.DefaultActivities.StartActivity("Second section")) +{ + secondActivity.AddTag("date", DateTime.UtcNow.ToString()); + secondActivity.AddTag("section", "second"); + Thread.Sleep(200); // Do work + secondActivity.Stop(); +}; +``` + +## Health Checks + +The library automatically includes a health check endpoint at `/healthz`, which checks the basic health of the service. + +You can add additional health checks to the default setup. + +- Inline Health Checks +- Custom Health Checks, that implement the IHealthCheck interface +- [Database Health Checks](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-6.0#database-probe) +- [Entity Framework Core DbContext probes](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-6.0#entity-framework-core-dbcontext-probe) + +```csharp +_options.ConfigureHealthChecks(builder => { + builder + .AddCheck("MyHealthCheck", () => HealthCheckResult.Healthy("Everything is fine.") + .AddCheck("MyOtherHealthCheck", MyHealthChecker) // Implement IHealthCheck + .AddSqlServer("") + .AddDbContextCheck(); +}); +``` diff --git a/src/Wemogy.AspNet/Monitoring/MonitoringExtensions.cs b/src/Wemogy.AspNet/Monitoring/MonitoringExtensions.cs index f31651a..2f2acec 100644 --- a/src/Wemogy.AspNet/Monitoring/MonitoringExtensions.cs +++ b/src/Wemogy.AspNet/Monitoring/MonitoringExtensions.cs @@ -47,6 +47,11 @@ public static IServiceCollection AddDefaultMonitoring( builder.AddAspNetCoreInstrumentation(); builder.AddEntityFrameworkCoreInstrumentation(); + foreach (var activitySourceName in environment.ActivitySourceNames) + { + builder.AddSource(activitySourceName); + } + if (environment.UseOtlpExporter) { builder.AddOtlpExporter(options => diff --git a/src/Wemogy.AspNet/Startup/StartupExtensions.cs b/src/Wemogy.AspNet/Startup/StartupExtensions.cs index 51ce0ee..c4b7bb7 100644 --- a/src/Wemogy.AspNet/Startup/StartupExtensions.cs +++ b/src/Wemogy.AspNet/Startup/StartupExtensions.cs @@ -56,6 +56,10 @@ public static void AddDefaultSetup(this IServiceCollection serviceCollection, St serviceCollection.AddDefaultControllers(options.DaprEnvironment != null, options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes); + // Health checks + var healthChecksBuilder = serviceCollection.AddHealthChecks(); + options.ConfigureHealthCheckBuilder?.Invoke(healthChecksBuilder); + serviceCollection.AddDefaultRouting(); } @@ -120,9 +124,9 @@ public static void UseDefaultSetup(this IApplicationBuilder applicationBuilder, { applicationBuilder.UseEndpoints(endpoints => { - // Register endpoints for Dapr PubSub subscription information - endpoints.MapSubscribeHandler(); + endpoints.MapSubscribeHandler(); // Register endpoints for Dapr PubSub endpoints.MapControllers(); + endpoints.MapHealthChecks("/healthz"); }); } else diff --git a/src/Wemogy.AspNet/Startup/StartupOptions.cs b/src/Wemogy.AspNet/Startup/StartupOptions.cs index 309679c..c9e6f6b 100644 --- a/src/Wemogy.AspNet/Startup/StartupOptions.cs +++ b/src/Wemogy.AspNet/Startup/StartupOptions.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Reflection; +using Microsoft.Extensions.DependencyInjection; using Wemogy.AspNet.Dapr; using Wemogy.AspNet.Monitoring; using Wemogy.AspNet.Swagger; @@ -15,6 +16,7 @@ public class StartupOptions internal MonitoringEnvironment? MonitoringEnvironment { get; private set; } internal DaprEnvironment? DaprEnvironment { get; private set; } internal HashSet Middlewares { get; private set; } + internal Action? ConfigureHealthCheckBuilder { get; private set; } /// /// Sets the property for all contollers. @@ -68,4 +70,10 @@ public StartupOptions AddMiddleware() Middlewares.Add(typeof(TMiddleware)); return this; } + + public StartupOptions ConfigureHealthChecks(Action configure) + { + ConfigureHealthCheckBuilder = configure; + return this; + } } diff --git a/src/Wemogy.AspNet/Wemogy.AspNet.csproj b/src/Wemogy.AspNet/Wemogy.AspNet.csproj index cbac5e0..c0e9fa9 100644 --- a/src/Wemogy.AspNet/Wemogy.AspNet.csproj +++ b/src/Wemogy.AspNet/Wemogy.AspNet.csproj @@ -42,7 +42,7 @@ - +