diff --git a/src/ServiceControl_Exporter/ServiceControl_Exporter/Config/Exporter.cs b/src/ServiceControl_Exporter/ServiceControl_Exporter/Config/Exporter.cs index d1a171c..ed5936b 100644 --- a/src/ServiceControl_Exporter/ServiceControl_Exporter/Config/Exporter.cs +++ b/src/ServiceControl_Exporter/ServiceControl_Exporter/Config/Exporter.cs @@ -2,6 +2,6 @@ public sealed class Exporter { - public string Host { get; set; } = "localhost"; - public int Port { get; set; } = 9002; + public string Host { get; set; } = "+"; + public ushort Port { get; set; } = 33334; } \ No newline at end of file diff --git a/src/ServiceControl_Exporter/ServiceControl_Exporter/Dockerfile b/src/ServiceControl_Exporter/ServiceControl_Exporter/Dockerfile index 45f47f3..9a018be 100644 --- a/src/ServiceControl_Exporter/ServiceControl_Exporter/Dockerfile +++ b/src/ServiceControl_Exporter/ServiceControl_Exporter/Dockerfile @@ -2,7 +2,7 @@ FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base WORKDIR /app -EXPOSE 9002 +EXPOSE 33334 FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build diff --git a/src/ServiceControl_Exporter/ServiceControl_Exporter/Program.cs b/src/ServiceControl_Exporter/ServiceControl_Exporter/Program.cs index 16247af..6cc19db 100644 --- a/src/ServiceControl_Exporter/ServiceControl_Exporter/Program.cs +++ b/src/ServiceControl_Exporter/ServiceControl_Exporter/Program.cs @@ -1,8 +1,4 @@ -namespace ServiceControl_Exporter; - -using System.Net; -using Commands; -using Config; +using System.Net; using Flurl.Http; using Mediator; using Microsoft.Extensions.Configuration; @@ -10,53 +6,72 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Prometheus; +using ServiceControl_Exporter; +using ServiceControl_Exporter.Commands; +using ServiceControl_Exporter.Config; + +var builder = Host.CreateApplicationBuilder(args); + +builder.Services.AddSingleton(provider => provider.GetRequiredService().Get()); +builder.Services.AddSingleton(); +builder.Services.AddHostedService(); +builder.Services.AddMediator(); +builder.Logging.AddConsole(); + +var appSettings = builder.Configuration.Get(); + +var registry = Metrics.DefaultRegistry; + +var serverOptions = new KestrelMetricServerOptions + { + Registry = registry, + Hostname = appSettings.Exporter.Host, + Port = appSettings.Exporter.Port + }; +builder.Services.AddSingleton(serverOptions); + +FlurlHttp.Clients.WithDefaults(settings => + { + settings.ConfigureInnerHandler(handler => + { + if (!string.IsNullOrWhiteSpace(appSettings.ProxyUrl)) + { + handler.Proxy = new WebProxy(new Uri(appSettings.ProxyUrl)); + handler.UseProxy = true; + } + }); + }); -internal class Program -{ - public static async Task Main(string[] args) - { - using var host = CreateHostBuilder(args).Build(); - - var mediator = host.Services.GetRequiredService(); - - var appSettings = host.Services.GetRequiredService(); - - FlurlHttp.Clients.WithDefaults(settings => - { - settings.ConfigureInnerHandler(handler => - { - if (!string.IsNullOrWhiteSpace(appSettings.ProxyUrl)) - { - handler.Proxy = new WebProxy(new Uri(appSettings.ProxyUrl)); - handler.UseProxy = true; - } - }); - }); - - Metrics.DefaultRegistry.AddBeforeCollectCallback(async cancel => - { - await mediator.Send(new UpdateEndpointStatsMetricsCommand(), cancel).ConfigureAwait(false); - await mediator.Send(new UpdateErrorMetricsCommand(), cancel).ConfigureAwait(false); - await mediator.Send(new UpdateCustomChecksMetricsCommand(), cancel).ConfigureAwait(false); - await mediator.Send(new UpdateHeartBeatStatsMetricsCommand(), cancel).ConfigureAwait(false); - await mediator.Send(new UpdateMonitoringMetricsCommand(), cancel).ConfigureAwait(false); - }); - - await host.RunAsync(); - } - - private static IHostBuilder CreateHostBuilder(string[] args) - { - return Host.CreateDefaultBuilder(args) - .UseWindowsService() - .UseSystemd() - .ConfigureServices(c => +var host = builder.Build(); + +var mediator = host.Services.GetRequiredService(); + +registry.AddBeforeCollectCallback(async cancel => + { + try + { + var logger = host.Services.GetRequiredService>(); + // If you see this in your container logs, the network route is working + if (logger.IsEnabled(LogLevel.Debug)) + logger.Log(LogLevel.Debug, "Kestrel handed execution to AddBeforeCollectCallback."); + + await mediator.Send(new UpdateEndpointStatsMetricsCommand(), cancel).ConfigureAwait(false); + await mediator.Send(new UpdateErrorMetricsCommand(), cancel).ConfigureAwait(false); + await mediator.Send(new UpdateCustomChecksMetricsCommand(), cancel).ConfigureAwait(false); + await mediator.Send(new UpdateHeartBeatStatsMetricsCommand(), cancel).ConfigureAwait(false); + await mediator.Send(new UpdateMonitoringMetricsCommand(), cancel).ConfigureAwait(false); + + if (logger.IsEnabled(LogLevel.Debug)) + logger.Log(LogLevel.Debug, "Callback completed successfully."); + } + catch (Exception ex) { - c.AddSingleton(provider => provider.GetRequiredService().Get()); - c.AddSingleton(); - c.AddHostedService(); - c.AddMediator(); - }) - .ConfigureLogging(c => c.AddConsole()); - } -} \ No newline at end of file + var logger = host.Services.GetRequiredService>(); + // Kestrel swallows pipeline faults; this forces it out to your container log stream + if (logger.IsEnabled(LogLevel.Error)) + logger.Log(LogLevel.Error, ex, "An error occurred while collecting metrics."); + throw; // Allow prometheus-net to handle the 503 response + } + }); + +host.Run(); \ No newline at end of file diff --git a/src/ServiceControl_Exporter/ServiceControl_Exporter/PrometheusExporter.cs b/src/ServiceControl_Exporter/ServiceControl_Exporter/PrometheusExporter.cs index 1e863d3..22376a8 100644 --- a/src/ServiceControl_Exporter/ServiceControl_Exporter/PrometheusExporter.cs +++ b/src/ServiceControl_Exporter/ServiceControl_Exporter/PrometheusExporter.cs @@ -1,22 +1,23 @@ namespace ServiceControl_Exporter; -using Config; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; using Prometheus; -internal class PrometheusExporter(AppSettings configuration) : IHostedService +internal class PrometheusExporter(KestrelMetricServerOptions options, ILogger logger) : IHostedService { - private readonly KestrelMetricServer _server = new KestrelMetricServer(configuration.Exporter.Host, - configuration.Exporter.Port); + private readonly KestrelMetricServer _server = new(options); public Task StartAsync(CancellationToken cancellationToken) { + logger.LogInformation("Starting Prometheus exporter for {0}:{1}", options.Hostname, options.Port); _server.Start(); return Task.CompletedTask; } public async Task StopAsync(CancellationToken cancellationToken) { + logger.LogInformation("Stopping Prometheus exporter for {0}:{1}", options.Hostname, options.Port); await _server.StopAsync(); } } \ No newline at end of file diff --git a/src/ServiceControl_Exporter/ServiceControl_Exporter/appsettings.json b/src/ServiceControl_Exporter/ServiceControl_Exporter/appsettings.json index aa977aa..a16a909 100644 --- a/src/ServiceControl_Exporter/ServiceControl_Exporter/appsettings.json +++ b/src/ServiceControl_Exporter/ServiceControl_Exporter/appsettings.json @@ -1,7 +1,7 @@ { "exporter": { "host": "+", - "port": 9002 + "port": 33334 }, "serviceControl": { "url": "http://localhost:33333/api",