using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; namespace NATS.Server.Monitoring; /// /// HTTP monitoring server providing /healthz, /varz, and other monitoring endpoints. /// Corresponds to Go server/monitor.go HTTP server setup. /// public sealed class MonitorServer : IAsyncDisposable { private readonly WebApplication _app; private readonly ILogger _logger; public MonitorServer(NatsServer server, NatsOptions options, ILoggerFactory loggerFactory) { _logger = loggerFactory.CreateLogger(); var builder = WebApplication.CreateSlimBuilder(); builder.WebHost.UseUrls($"http://{options.MonitorHost}:{options.MonitorPort}"); builder.Logging.ClearProviders(); _app = builder.Build(); var basePath = options.MonitorBasePath ?? ""; var varzHandler = new VarzHandler(server, options); _app.MapGet(basePath + "/", () => Results.Ok(new { endpoints = new[] { "/varz", "/connz", "/healthz", "/routez", "/gatewayz", "/leafz", "/subz", "/accountz", "/jsz", }, })); _app.MapGet(basePath + "/healthz", () => Results.Ok("ok")); _app.MapGet(basePath + "/varz", async () => Results.Ok(await varzHandler.HandleVarzAsync())); // Stubs for unimplemented endpoints _app.MapGet(basePath + "/routez", () => Results.Ok(new { })); _app.MapGet(basePath + "/gatewayz", () => Results.Ok(new { })); _app.MapGet(basePath + "/leafz", () => Results.Ok(new { })); _app.MapGet(basePath + "/subz", () => Results.Ok(new { })); _app.MapGet(basePath + "/subscriptionsz", () => Results.Ok(new { })); _app.MapGet(basePath + "/accountz", () => Results.Ok(new { })); _app.MapGet(basePath + "/accstatz", () => Results.Ok(new { })); _app.MapGet(basePath + "/jsz", () => Results.Ok(new { })); } public async Task StartAsync(CancellationToken ct) { await _app.StartAsync(ct); _logger.LogInformation("Monitoring listening on {Urls}", string.Join(", ", _app.Urls)); } public async ValueTask DisposeAsync() { await _app.DisposeAsync(); } }