From 4040b60148dc6a10c36711c4d20cac9e6325bcd7 Mon Sep 17 00:00:00 2001 From: Tim Hess Date: Wed, 6 Nov 2024 14:46:33 -0600 Subject: [PATCH] Add custom actuator https://github.com/SteeltoeOSS/Samples/issues/204#issuecomment-2449722705 --- Management/src/ActuatorWeb/ActuatorWeb.http | 6 +++ .../ConfigureLocalTimeEndpointOptions.cs | 14 ++++++ .../EndpointServiceCollectionExtensions.cs | 43 +++++++++++++++++++ .../LocalTime/ILocalTimeEndpointHandler.cs | 5 +++ .../LocalTime/LocalTimeEndpointHandler.cs | 30 +++++++++++++ .../LocalTime/LocalTimeEndpointMiddleware.cs | 15 +++++++ .../LocalTime/LocalTimeEndpointOptions.cs | 15 +++++++ Management/src/ActuatorWeb/Program.cs | 5 +++ Management/src/ActuatorWeb/README.md | 22 ++++++---- .../ActuatorWeb/appsettings.Development.json | 4 ++ 10 files changed, 150 insertions(+), 9 deletions(-) create mode 100644 Management/src/ActuatorWeb/CustomActuators/LocalTime/ConfigureLocalTimeEndpointOptions.cs create mode 100644 Management/src/ActuatorWeb/CustomActuators/LocalTime/EndpointServiceCollectionExtensions.cs create mode 100644 Management/src/ActuatorWeb/CustomActuators/LocalTime/ILocalTimeEndpointHandler.cs create mode 100644 Management/src/ActuatorWeb/CustomActuators/LocalTime/LocalTimeEndpointHandler.cs create mode 100644 Management/src/ActuatorWeb/CustomActuators/LocalTime/LocalTimeEndpointMiddleware.cs create mode 100644 Management/src/ActuatorWeb/CustomActuators/LocalTime/LocalTimeEndpointOptions.cs diff --git a/Management/src/ActuatorWeb/ActuatorWeb.http b/Management/src/ActuatorWeb/ActuatorWeb.http index 626e0ed5..a007c24f 100644 --- a/Management/src/ActuatorWeb/ActuatorWeb.http +++ b/Management/src/ActuatorWeb/ActuatorWeb.http @@ -89,3 +89,9 @@ Authorization: {{Authorization_Header_Value}} GET {{ManagementAddress}}/{{Actuator_Context}}/heapdump Accept: application/json Authorization: {{Authorization_Header_Value}} + +### CUSTOM Actuator + +GET {{ManagementAddress}}/{{Actuator_Context}}/local-time +Accept: application/json +Authorization: {{Authorization_Header_Value}} diff --git a/Management/src/ActuatorWeb/CustomActuators/LocalTime/ConfigureLocalTimeEndpointOptions.cs b/Management/src/ActuatorWeb/CustomActuators/LocalTime/ConfigureLocalTimeEndpointOptions.cs new file mode 100644 index 00000000..942a2419 --- /dev/null +++ b/Management/src/ActuatorWeb/CustomActuators/LocalTime/ConfigureLocalTimeEndpointOptions.cs @@ -0,0 +1,14 @@ +using Steeltoe.Management.Endpoint.Configuration; + +namespace Steeltoe.Samples.ActuatorWeb.CustomActuators.LocalTime; + +internal sealed class ConfigureLocalTimeEndpointOptions(IConfiguration configuration) + : ConfigureEndpointOptions(configuration, "Management:Endpoints:LocalTime", "local-time") +{ + public override void Configure(LocalTimeEndpointOptions options) + { + base.Configure(options); + + options.Format ??= "O"; + } +} diff --git a/Management/src/ActuatorWeb/CustomActuators/LocalTime/EndpointServiceCollectionExtensions.cs b/Management/src/ActuatorWeb/CustomActuators/LocalTime/EndpointServiceCollectionExtensions.cs new file mode 100644 index 00000000..8e45f623 --- /dev/null +++ b/Management/src/ActuatorWeb/CustomActuators/LocalTime/EndpointServiceCollectionExtensions.cs @@ -0,0 +1,43 @@ +using Steeltoe.Management.Endpoint; + +namespace Steeltoe.Samples.ActuatorWeb.CustomActuators.LocalTime; + +public static class EndpointServiceCollectionExtensions +{ + /// + /// Adds the local time actuator to the service container and configures the ASP.NET middleware pipeline. + /// + /// + /// The to add services to. + /// + /// + /// The incoming so that additional calls can be chained. + /// + public static IServiceCollection AddLocalTimeActuator(this IServiceCollection services) + { + return services.AddLocalTimeActuator(true); + } + + /// + /// Adds the local time actuator to the service container. + /// + /// + /// The to add services to. + /// + /// + /// When false, skips configuration of the ASP.NET middleware pipeline. While this provides full control over the pipeline order, it requires + /// manual addition of the appropriate middleware for actuators to work correctly. + /// + /// + /// The incoming so that additional calls can be chained. + /// + public static IServiceCollection AddLocalTimeActuator(this IServiceCollection services, bool configureMiddleware) + { + ArgumentNullException.ThrowIfNull(services); + + services.AddCoreActuatorServices(configureMiddleware); + + return services; + } +} diff --git a/Management/src/ActuatorWeb/CustomActuators/LocalTime/ILocalTimeEndpointHandler.cs b/Management/src/ActuatorWeb/CustomActuators/LocalTime/ILocalTimeEndpointHandler.cs new file mode 100644 index 00000000..638e7bb8 --- /dev/null +++ b/Management/src/ActuatorWeb/CustomActuators/LocalTime/ILocalTimeEndpointHandler.cs @@ -0,0 +1,5 @@ +using Steeltoe.Management.Endpoint; + +namespace Steeltoe.Samples.ActuatorWeb.CustomActuators.LocalTime; + +public interface ILocalTimeEndpointHandler : IEndpointHandler; diff --git a/Management/src/ActuatorWeb/CustomActuators/LocalTime/LocalTimeEndpointHandler.cs b/Management/src/ActuatorWeb/CustomActuators/LocalTime/LocalTimeEndpointHandler.cs new file mode 100644 index 00000000..3e8d38f8 --- /dev/null +++ b/Management/src/ActuatorWeb/CustomActuators/LocalTime/LocalTimeEndpointHandler.cs @@ -0,0 +1,30 @@ +using System.Globalization; +using Microsoft.Extensions.Options; +using Steeltoe.Management.Configuration; + +namespace Steeltoe.Samples.ActuatorWeb.CustomActuators.LocalTime; + +internal sealed class LocalTimeEndpointHandler : ILocalTimeEndpointHandler +{ + private readonly IOptionsMonitor _optionsMonitor; + + public EndpointOptions Options => _optionsMonitor.CurrentValue; + + public LocalTimeEndpointHandler(IOptionsMonitor optionsMonitor) + { + ArgumentNullException.ThrowIfNull(optionsMonitor); + + _optionsMonitor = optionsMonitor; + } + + public Task InvokeAsync(object? argument, CancellationToken cancellationToken) + { + string localTime = GetLocalTime(); + return Task.FromResult(localTime); + } + + private string GetLocalTime() + { + return DateTime.Now.ToString(_optionsMonitor.CurrentValue.Format, CultureInfo.InvariantCulture); + } +} diff --git a/Management/src/ActuatorWeb/CustomActuators/LocalTime/LocalTimeEndpointMiddleware.cs b/Management/src/ActuatorWeb/CustomActuators/LocalTime/LocalTimeEndpointMiddleware.cs new file mode 100644 index 00000000..d0e48c4a --- /dev/null +++ b/Management/src/ActuatorWeb/CustomActuators/LocalTime/LocalTimeEndpointMiddleware.cs @@ -0,0 +1,15 @@ +using Microsoft.Extensions.Options; +using Steeltoe.Management.Endpoint.Configuration; +using Steeltoe.Management.Endpoint.Middleware; + +namespace Steeltoe.Samples.ActuatorWeb.CustomActuators.LocalTime; + +internal sealed class LocalTimeEndpointMiddleware( + ILocalTimeEndpointHandler endpointHandler, IOptionsMonitor managementOptionsMonitor, ILoggerFactory loggerFactory) + : EndpointMiddleware(endpointHandler, managementOptionsMonitor, loggerFactory) +{ + protected override async Task InvokeEndpointHandlerAsync(HttpContext context, CancellationToken cancellationToken) + { + return await EndpointHandler.InvokeAsync(null, cancellationToken); + } +} diff --git a/Management/src/ActuatorWeb/CustomActuators/LocalTime/LocalTimeEndpointOptions.cs b/Management/src/ActuatorWeb/CustomActuators/LocalTime/LocalTimeEndpointOptions.cs new file mode 100644 index 00000000..f5c305e9 --- /dev/null +++ b/Management/src/ActuatorWeb/CustomActuators/LocalTime/LocalTimeEndpointOptions.cs @@ -0,0 +1,15 @@ +using Steeltoe.Management.Configuration; + +namespace Steeltoe.Samples.ActuatorWeb.CustomActuators.LocalTime; + +public sealed class LocalTimeEndpointOptions : EndpointOptions +{ + /// + /// Gets or sets the date/time format to use in the response. Defaults to "O". + /// + /// + /// See and + /// for possible values. + /// + public string? Format { get; set; } +} diff --git a/Management/src/ActuatorWeb/Program.cs b/Management/src/ActuatorWeb/Program.cs index 39cf4c94..945213ac 100644 --- a/Management/src/ActuatorWeb/Program.cs +++ b/Management/src/ActuatorWeb/Program.cs @@ -5,6 +5,7 @@ using Steeltoe.Management.Endpoint.SpringBootAdminClient; using Steeltoe.Management.Prometheus; using Steeltoe.Samples.ActuatorWeb; +using Steeltoe.Samples.ActuatorWeb.CustomActuators.LocalTime; using Steeltoe.Samples.ActuatorWeb.Pages; WebApplicationBuilder builder = WebApplication.CreateBuilder(args); @@ -28,6 +29,10 @@ builder.Services.AddAllActuators(); builder.Services.AddPrometheusActuator(); +// Steeltoe: Add custom actuator that displays the local server time. +// See appsettings.Development.json for how the response format can be configured. +builder.Services.AddLocalTimeActuator(); + // Steeltoe: Register with Spring Boot Admin. if (builder.Configuration.GetValue("UseSpringBootAdmin")) { diff --git a/Management/src/ActuatorWeb/README.md b/Management/src/ActuatorWeb/README.md index de4d35cc..808024d0 100644 --- a/Management/src/ActuatorWeb/README.md +++ b/Management/src/ActuatorWeb/README.md @@ -18,14 +18,13 @@ including [App Metrics for VMware Tanzu](https://docs.vmware.com/en/App-Metrics- ## General pre-requisites 1. Installed .NET 8 SDK -1. - -Optional: [VMware Tanzu Platform for Cloud Foundry](https://docs.vmware.com/en/VMware-Tanzu-Application-Service/index.html) -* [Cloud Foundry CLI](https://docs.cloudfoundry.org/cf-cli/install-go-cli.html) -* [Metrics Registrar](https://docs.vmware.com/en/VMware-Tanzu-Application-Service/6.0/tas-for-vms/metric-registrar-index.html) -* [App Metrics](https://docs.vmware.com/en/App-Metrics-for-VMware-Tanzu/2.2/app-metrics/GUID-index.html) -* [VMware MySQL for Tanzu Application Service](https://docs.vmware.com/en/VMware-SQL-with-MySQL-for-Tanzu-Application-Service/index.html) -or [VMware Tanzu Cloud Service Broker](https://docs.vmware.com/en/Cloud-Service-Broker-for-VMware-Tanzu/index.html) +1. Optional: + * [VMware Tanzu Platform for Cloud Foundry](https://docs.vmware.com/en/VMware-Tanzu-Application-Service/index.html) + * [Cloud Foundry CLI](https://docs.cloudfoundry.org/cf-cli/install-go-cli.html) + * [Metrics Registrar for VMware Tanzu Application Service](https://docs.vmware.com/en/VMware-Tanzu-Application-Service/6.0/tas-for-vms/metric-registrar-index.html) + * [App Metrics for VMware Tanzu](https://docs.vmware.com/en/App-Metrics-for-VMware-Tanzu/2.2/app-metrics/GUID-index.html) + * [VMware MySQL for Tanzu Application Service](https://docs.vmware.com/en/VMware-SQL-with-MySQL-for-Tanzu-Application-Service/index.html) + or [VMware Tanzu Cloud Service Broker](https://docs.vmware.com/en/Cloud-Service-Broker-for-VMware-Tanzu/index.html) ## Running locally @@ -87,7 +86,7 @@ As ActuatorWeb is a Razor Pages app, you can use a browser to [access the web UI is running. To request a weather forecast (and generate HTTP request traces) from ActuatorApi, click "Weather Forecast" in the site menu. -### Interacting with actuators +### Interacting with Management Endpoints Each app instance registers with Spring Boot Admin and can be viewed from the web interface at . @@ -101,6 +100,11 @@ time. You will need to either make an environment selection or define variables file in order for requests to work (review the .json file mentioned previously for variable examples). Please note that the "dhaka" environment is not expected to be available for use by those not on the Steeltoe team. +#### Custom Management Endpoints + +This sample includes a custom actuator that can be used to return the time on the server where the app is running. +Review the contents of [./CustomActuators](./CustomActuators/) to see how this integration is accomplished. + ### Reviewing HTTP Traces 1. Open the [Zipkin web UI on your machine](http://localhost:9411) diff --git a/Management/src/ActuatorWeb/appsettings.Development.json b/Management/src/ActuatorWeb/appsettings.Development.json index 4d52e373..73deb68e 100644 --- a/Management/src/ActuatorWeb/appsettings.Development.json +++ b/Management/src/ActuatorWeb/appsettings.Development.json @@ -17,6 +17,10 @@ "*" ] } + }, + // Steeltoe: Configure local time actuator. + "LocalTime": { + "Format": "dd-MM-yyyy HH:mm:ss,fff" } } },