Skip to content

Commit

Permalink
Provide more information in health check (#635)
Browse files Browse the repository at this point in the history
* Provide more information in health check

* Code styling
  • Loading branch information
tomkerkhove authored Jul 25, 2019
1 parent fca5900 commit 0e1af05
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 44 deletions.
17 changes: 14 additions & 3 deletions src/Promitor.Scraper.Host/Controllers/v1/HealthController.cs
Original file line number Diff line number Diff line change
@@ -1,23 +1,34 @@
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Swashbuckle.AspNetCore.Annotations;

namespace Promitor.Scraper.Host.Controllers.v1
{
[Route("api/v1/health")]
public class HealthController : Controller
{
private readonly HealthCheckService _healthCheckService;

public HealthController(HealthCheckService healthCheckService)
{
_healthCheckService = healthCheckService;
}

/// <summary>
/// Get Health
/// </summary>
/// <remarks>Provides an indication about the health of the scraper</remarks>
[HttpGet]
[SwaggerOperation(OperationId = "Health_Get")]
[SwaggerResponse((int)HttpStatusCode.OK, Description = "Scraper is healthy")]
[SwaggerResponse((int)HttpStatusCode.OK, Description = "Scraper is healthy", Type = typeof(HealthReport))]
[SwaggerResponse((int)HttpStatusCode.ServiceUnavailable, Description = "Scraper is not healthy")]
public IActionResult Get()
public async Task<IActionResult> Get()
{
return Ok();
var report = await _healthCheckService.CheckHealthAsync();

return report.Status == HealthStatus.Healthy ? Ok(report) : StatusCode((int)HttpStatusCode.ServiceUnavailable, report);
}
}
}
19 changes: 13 additions & 6 deletions src/Promitor.Scraper.Host/Docs/Open-Api.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging;
using Promitor.Core.Scraping.Configuration.Providers;
using Promitor.Core.Scraping.Configuration.Providers.Interfaces;
using Promitor.Core.Configuration.FeatureFlags;
using Promitor.Core.Configuration.Model.FeatureFlags;
using Promitor.Core.Configuration.Model.Metrics;
using Promitor.Core.Configuration.Model.Prometheus;
using Promitor.Core.Configuration.Model.Server;
using Promitor.Core.Configuration.Model.Telemetry;
using Promitor.Core.Configuration.Model.Telemetry.Sinks;
using Promitor.Core.Scraping.Configuration.Providers;
using Promitor.Core.Scraping.Configuration.Providers.Interfaces;
using Promitor.Core.Scraping.Factories;
using Promitor.Core.Telemetry;
using Promitor.Core.Telemetry.Interfaces;
Expand All @@ -34,14 +35,13 @@ public static class IServiceCollectionExtensions
/// Defines to use the cron scheduler
/// </summary>
/// <param name="services">Collections of services in application</param>
public static void ScheduleMetricScraping(this IServiceCollection services)
public static IServiceCollection ScheduleMetricScraping(this IServiceCollection services)
{
var spToCreateJobsWith = services.BuildServiceProvider();
var metricsProvider = spToCreateJobsWith.GetService<IMetricsDeclarationProvider>();
var metrics = metricsProvider.Get(applyDefaults: true);
var metrics = metricsProvider.Get(true);

foreach (var metric in metrics.Metrics)
{
services.AddScheduler(builder =>
{
builder.AddJob(serviceProvider => new MetricScrapingJob(metric,
Expand All @@ -52,26 +52,59 @@ public static void ScheduleMetricScraping(this IServiceCollection services)
serviceProvider.GetService<IExceptionTracker>()));
builder.UnobservedTaskExceptionHandler = (sender, exceptionEventArgs) => UnobservedJobHandlerHandler(sender, exceptionEventArgs, services);
});
}

return services;
}

/// <summary>
/// Defines the dependencies that Promitor requires
/// </summary>
/// <param name="services">Collections of services in application</param>
public static IServiceCollection DefineDependencies(this IServiceCollection services)
{
services.AddTransient<IExceptionTracker, ApplicationInsightsTelemetry>();
services.AddTransient<ILogger, RuntimeLogger>();
services.AddTransient<IMetricsDeclarationProvider, MetricsDeclarationProvider>();
services.AddTransient<IRuntimeMetricsCollector, RuntimeMetricsCollector>();
services.AddTransient<FeatureToggleClient>();
services.AddTransient<MetricScraperFactory>();
services.AddTransient<RuntimeValidator>();
services.AddTransient<ValidationLogger>();

return services;
}

/// <summary>
/// Use health checks
/// </summary>
/// <param name="services">Collections of services in application</param>
public static IServiceCollection UseHealthChecks(this IServiceCollection services)
{
services.AddHealthChecks()
.AddCheck("self", () => HealthCheckResult.Healthy());

return services;
}

/// <summary>
/// Expose services as Web API
/// </summary>
public static void UseWebApi(this IServiceCollection services)
public static IServiceCollection UseWebApi(this IServiceCollection services)
{
services.AddMvc()
.AddJsonOptions(jsonOptions =>
{
jsonOptions.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
jsonOptions.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
});

return services;
}

/// <summary>
/// Inject configuration
/// </summary>
public static void InjectConfiguration(this IServiceCollection services, IConfiguration configuration)
public static IServiceCollection ConfigureYamlConfiguration(this IServiceCollection services, IConfiguration configuration)
{
services.Configure<FeatureFlagsConfiguration>(configuration.GetSection("featureFlags"));
services.Configure<MetricsConfiguration>(configuration.GetSection("metricsConfiguration"));
Expand All @@ -81,21 +114,8 @@ public static void InjectConfiguration(this IServiceCollection services, IConfig
services.Configure<ServerConfiguration>(configuration.GetSection("server"));
services.Configure<PrometheusConfiguration>(configuration.GetSection("prometheus"));
services.Configure<ScrapeEndpointConfiguration>(configuration.GetSection("prometheus:scrapeEndpoint"));
}

/// <summary>
/// Inject dependencies
/// </summary>
public static void InjectDependencies(this IServiceCollection services)
{
services.AddTransient<IExceptionTracker, ApplicationInsightsTelemetry>();
services.AddTransient<ILogger, RuntimeLogger>();
services.AddTransient<IMetricsDeclarationProvider, MetricsDeclarationProvider>();
services.AddTransient<IRuntimeMetricsCollector, RuntimeMetricsCollector>();
services.AddTransient<FeatureToggleClient>();
services.AddTransient<MetricScraperFactory>();
services.AddTransient<RuntimeValidator>();
services.AddTransient<ValidationLogger>();
return services;
}

/// <summary>
Expand All @@ -104,7 +124,7 @@ public static void InjectDependencies(this IServiceCollection services)
/// <param name="services">Collections of services in application</param>
/// <param name="prometheusScrapeEndpointPath">Endpoint where the prometheus scraping is exposed</param>
/// <param name="apiVersion">Version of the API</param>
public static void UseOpenApiSpecifications(this IServiceCollection services, string prometheusScrapeEndpointPath, int apiVersion)
public static IServiceCollection UseOpenApiSpecifications(this IServiceCollection services, string prometheusScrapeEndpointPath, int apiVersion)
{
var openApiInformation = new Info
{
Expand Down Expand Up @@ -136,6 +156,8 @@ public static void UseOpenApiSpecifications(this IServiceCollection services, st
swaggerGenerationOptions.IncludeXmlComments(xmlDocumentationPath);
}
});

return services;
}

private static string GetXmlDocumentationPath(IServiceCollection services)
Expand All @@ -162,4 +184,4 @@ private static void UnobservedJobHandlerHandler(object sender, UnobservedTaskExc
e.SetObserved();
}
}
}
}
20 changes: 9 additions & 11 deletions src/Promitor.Scraper.Host/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ namespace Promitor.Scraper.Host
{
public class Startup
{
private readonly IConfiguration _configuration;
private readonly string _prometheusBaseUriPath;

public Startup(IConfiguration configuration)
{
_configuration = configuration;
Expand All @@ -18,16 +21,11 @@ public Startup(IConfiguration configuration)
_prometheusBaseUriPath = scrapeEndpointConfiguration.BaseUriPath;
}

private readonly IConfiguration _configuration;
private readonly string _prometheusBaseUriPath;

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

ValidateRuntimeConfiguration(app);

Expand All @@ -39,12 +37,12 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env)
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.InjectConfiguration(_configuration);
services.InjectDependencies();

services.UseWebApi();
services.UseOpenApiSpecifications(_prometheusBaseUriPath, apiVersion: 1);
services.ScheduleMetricScraping();
services.DefineDependencies()
.ConfigureYamlConfiguration(_configuration)
.UseWebApi()
.UseOpenApiSpecifications(_prometheusBaseUriPath, 1)
.UseHealthChecks()
.ScheduleMetricScraping();
}

private void ValidateRuntimeConfiguration(IApplicationBuilder app)
Expand Down

0 comments on commit 0e1af05

Please sign in to comment.