Skip to content

Commit

Permalink
Add custom actuator
Browse files Browse the repository at this point in the history
  • Loading branch information
TimHess committed Nov 6, 2024
1 parent 8969b48 commit 4040b60
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 9 deletions.
6 changes: 6 additions & 0 deletions Management/src/ActuatorWeb/ActuatorWeb.http
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Steeltoe.Management.Endpoint.Configuration;

namespace Steeltoe.Samples.ActuatorWeb.CustomActuators.LocalTime;

internal sealed class ConfigureLocalTimeEndpointOptions(IConfiguration configuration)
: ConfigureEndpointOptions<LocalTimeEndpointOptions>(configuration, "Management:Endpoints:LocalTime", "local-time")
{
public override void Configure(LocalTimeEndpointOptions options)
{
base.Configure(options);

options.Format ??= "O";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using Steeltoe.Management.Endpoint;

namespace Steeltoe.Samples.ActuatorWeb.CustomActuators.LocalTime;

public static class EndpointServiceCollectionExtensions
{
/// <summary>
/// Adds the local time actuator to the service container and configures the ASP.NET middleware pipeline.
/// </summary>
/// <param name="services">
/// The <see cref="IServiceCollection" /> to add services to.
/// </param>
/// <returns>
/// The incoming <paramref name="services" /> so that additional calls can be chained.
/// </returns>
public static IServiceCollection AddLocalTimeActuator(this IServiceCollection services)
{
return services.AddLocalTimeActuator(true);
}

/// <summary>
/// Adds the local time actuator to the service container.
/// </summary>
/// <param name="services">
/// The <see cref="IServiceCollection" /> to add services to.
/// </param>
/// <param name="configureMiddleware">
/// When <c>false</c>, 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.
/// </param>
/// <returns>
/// The incoming <paramref name="services" /> so that additional calls can be chained.
/// </returns>
public static IServiceCollection AddLocalTimeActuator(this IServiceCollection services, bool configureMiddleware)
{
ArgumentNullException.ThrowIfNull(services);

services.AddCoreActuatorServices<LocalTimeEndpointOptions, ConfigureLocalTimeEndpointOptions, LocalTimeEndpointMiddleware, ILocalTimeEndpointHandler,
LocalTimeEndpointHandler, object?, string>(configureMiddleware);

return services;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using Steeltoe.Management.Endpoint;

namespace Steeltoe.Samples.ActuatorWeb.CustomActuators.LocalTime;

public interface ILocalTimeEndpointHandler : IEndpointHandler<object?, string>;
Original file line number Diff line number Diff line change
@@ -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<LocalTimeEndpointOptions> _optionsMonitor;

public EndpointOptions Options => _optionsMonitor.CurrentValue;

public LocalTimeEndpointHandler(IOptionsMonitor<LocalTimeEndpointOptions> optionsMonitor)
{
ArgumentNullException.ThrowIfNull(optionsMonitor);

_optionsMonitor = optionsMonitor;
}

public Task<string> InvokeAsync(object? argument, CancellationToken cancellationToken)
{
string localTime = GetLocalTime();
return Task.FromResult(localTime);
}

private string GetLocalTime()
{
return DateTime.Now.ToString(_optionsMonitor.CurrentValue.Format, CultureInfo.InvariantCulture);
}
}
Original file line number Diff line number Diff line change
@@ -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<ManagementOptions> managementOptionsMonitor, ILoggerFactory loggerFactory)
: EndpointMiddleware<object?, string>(endpointHandler, managementOptionsMonitor, loggerFactory)
{
protected override async Task<string> InvokeEndpointHandlerAsync(HttpContext context, CancellationToken cancellationToken)
{
return await EndpointHandler.InvokeAsync(null, cancellationToken);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Steeltoe.Management.Configuration;

namespace Steeltoe.Samples.ActuatorWeb.CustomActuators.LocalTime;

public sealed class LocalTimeEndpointOptions : EndpointOptions
{
/// <summary>
/// Gets or sets the date/time format to use in the response. Defaults to "O".
/// </summary>
/// <remarks>
/// See <see href="https://learn.microsoft.com/dotnet/standard/base-types/standard-date-and-time-format-strings" /> and
/// <see href="https://learn.microsoft.com/dotnet/standard/base-types/custom-date-and-time-format-strings" /> for possible values.
/// </remarks>
public string? Format { get; set; }
}
5 changes: 5 additions & 0 deletions Management/src/ActuatorWeb/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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<bool>("UseSpringBootAdmin"))
{
Expand Down
22 changes: 13 additions & 9 deletions Management/src/ActuatorWeb/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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 <http://localhost:9090>.

Expand All @@ -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)
Expand Down
4 changes: 4 additions & 0 deletions Management/src/ActuatorWeb/appsettings.Development.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
"*"
]
}
},
// Steeltoe: Configure local time actuator.
"LocalTime": {
"Format": "dd-MM-yyyy HH:mm:ss,fff"
}
}
},
Expand Down

0 comments on commit 4040b60

Please sign in to comment.