public void set_default_parameters_when_is_created() { var watch = new Stopwatch(); watch.Start(); var highResolution = Stopwatch.IsHighResolution; watch.Stop(); var i = watch.ElapsedMilliseconds; var options = new BeatPulseOptions(); options.Path .Should().Be(BeatPulseKeys.BEATPULSE_DEFAULT_PATH); options.Timeout .Should().Be(-1); options.DetailedOutput .Should().BeFalse(); options.CacheOutput .Should().BeFalse(); options.CacheDuration .Should().Be(0); options.DetailedErrors .Should().BeFalse(); options.CacheMode .Should().Be(CacheMode.Header); }
public async Task <IEnumerable <LivenessResult> > IsHealthy(string path, BeatPulseOptions options, HttpContext httpContext) { _logger.LogInformation($"BeatPulse is checking health on all registered liveness on [BeatPulsePath]/{path}."); using (_logger.BeginScope($"BeatPulse is checking health status on all registered liveness from [BeatPulsePath]/{path} path.")) { var livenessResults = new List <LivenessResult>(); foreach (var registration in _beatPulseContext.GetAllLiveness(path)) { var liveness = _beatPulseContext .CreateLivenessFromRegistration(registration); var executionContext = LivenessExecutionContext .FromRegistration(registration, showDetailedErrors: options.DetailedErrors); var livenessResult = await RunLiveness(liveness, executionContext, options); await RunTrackers(livenessResult); livenessResults.Add(livenessResult); if (!livenessResult.IsHealthy && !options.DetailedOutput) { //if is unhealthy and not detailed options is true return inmediatly _logger.LogWarning($"Liveness {executionContext.Name} is not healthy. Breaking liveness execution because detailed output is false."); return(livenessResults); } } return(livenessResults); } }
private static bool MatchesBeatPulseRequestPath(this HttpContext context, BeatPulseOptions options) { var routeValues = new RouteValueDictionary(); var templateMatcher = GetTemplateMatcher(options); return(templateMatcher.TryMatch(context.Request.Path, routeValues)); }
public void evaluate_the_beatpulse_path() { var options = new BeatPulseOptions(); var httpContext = new DefaultHttpContext(); httpContext.Request.Method = "GET"; httpContext.Request.Path = "/hc"; httpContext.GetBeatPulseRequestPath(options) .Should().BeEquivalentTo(string.Empty); httpContext.Request.Path = "/hc/sqlserver"; httpContext.GetBeatPulseRequestPath(options) .Should().BeEquivalentTo("sqlserver"); options.ConfigurePath("health"); httpContext.Request.Path = "/health"; httpContext.GetBeatPulseRequestPath(options) .Should().BeEquivalentTo(string.Empty); httpContext.Request.Path = "/health/sqlserver"; httpContext.GetBeatPulseRequestPath(options) .Should().BeEquivalentTo("sqlserver"); }
public static string GetBeatPulseRequestPath(this HttpContext context, BeatPulseOptions options) { var routeValues = new RouteValueDictionary(); var templateMatcher = GetTemplateMatcher(options); templateMatcher.TryMatch(context.Request.Path, routeValues); return(routeValues[BeatPulseKeys.BEATPULSE_PATH_SEGMENT_NAME].ToString()); }
private static TemplateMatcher GetTemplateMatcher(BeatPulseOptions options) { var templateMatcher = new TemplateMatcher(TemplateParser.Parse($"{options.Path}/{{{BeatPulseKeys.BEATPULSE_PATH_SEGMENT_NAME}}}"), new RouteValueDictionary() { { BeatPulseKeys.BEATPULSE_PATH_SEGMENT_NAME, string.Empty } }); return(templateMatcher); }
public void change_default_detailed_errors() { var options = new BeatPulseOptions(); options.DetailedErrors .Should().BeFalse(); options.ConfigureDetailedOutput(detailedOutput: true, includeExceptionMessages: true); options.DetailedErrors .Should().BeTrue(); }
public void change_default_beatpulse_path() { var options = new BeatPulseOptions(); options.Path .Should().Be(BeatPulseKeys.BEATPULSE_DEFAULT_PATH); options.ConfigurePath("health"); options.Path .Should().Be("health"); }
public void change_default_timeout() { var options = new BeatPulseOptions(); options.Timeout .Should().Be(-1); options.ConfigureTimeout(1000); options.Timeout .Should().Be(1000); }
public static IApplicationBuilder UseBeatPulse(this IApplicationBuilder app, Action <BeatPulseOptions> setup) { var options = new BeatPulseOptions(); setup?.Invoke(options); app.MapWhen(context => context.IsBeatPulseRequest(options), appBuilder => { appBuilder.UseMiddleware <BeatPulseMiddleware>(options); }); return(app); }
public static IWebHostBuilder UseBeatPulse(this IWebHostBuilder hostBuilder, Action <BeatPulseOptions> setup = null) { var options = new BeatPulseOptions(); setup?.Invoke(options); hostBuilder.ConfigureServices(defaultServices => { defaultServices.AddSingleton <IStartupFilter>(new BeatPulseFilter(options)); }); return(hostBuilder); }
async Task <LivenessResult> RunLiveness(IBeatPulseLiveness liveness, BeatPulseOptions options, HttpContext httpContext) { _logger.LogInformation($"Executing liveness {liveness.Name}."); var livenessResult = new LivenessResult(liveness.Name, liveness.Path); livenessResult.StartCounter(); try { using (var cancellationTokenSource = new CancellationTokenSource()) { var livenessTask = liveness.IsHealthy(httpContext, _environment.IsDevelopment(), cancellationTokenSource.Token); if (await Task.WhenAny(livenessTask, Task.Delay(options.Timeout, cancellationTokenSource.Token)) == livenessTask) { // The liveness is executed successfully and get the results var(message, healthy) = await livenessTask; livenessResult.StopCounter(message, healthy); _logger.LogInformation($"The liveness {liveness.Name} is executed."); } else { // The liveness is timeout ( from configured options) _logger.LogWarning($"The liveness {liveness.Name} is timeout"); cancellationTokenSource.Cancel(); livenessResult.StopCounter(BeatPulseKeys.BEATPULSE_TIMEOUT_MESSAGE, false); } } } catch (Exception ex) { // The uri executed is now well formed, dns not found // or any unexpected errror _logger.LogError(ex, $"The liveness {liveness.Name} is unhealthy."); var message = _environment.IsDevelopment() ? ex.Message : string.Format(BeatPulseKeys.BEATPULSE_HEALTHCHECK_DEFAULT_ERROR_MESSAGE, liveness.Name); livenessResult.StopCounter(message, false); } return(livenessResult); }
public void change_default_cachemode() { var options = new BeatPulseOptions(); options.CacheOutput .Should().BeFalse(); options.ConfigureOutputCache(10, CacheMode.HeaderAndServerMemory); options.CacheOutput .Should().BeTrue(); options.CacheMode .Should().Be(CacheMode.HeaderAndServerMemory); options.CacheDuration .Should().Be(10); }
public async Task <IEnumerable <LivenessResult> > IsHealthy(string path, BeatPulseOptions options, HttpContext httpContext) { _logger.LogInformation($"BeatPulse is checking health on [BeatPulsePath]/{path}"); if (String.IsNullOrEmpty(path)) { var livenessResults = new List <LivenessResult>(); foreach (var liveness in _beatPulseContext.AllLiveness) { var healthCheckResult = await RunLiveness(liveness, options, httpContext); await RunTrackers(healthCheckResult); livenessResults.Add(healthCheckResult); if (!healthCheckResult.IsHealthy && !options.DetailedOutput) { //if is unhealthy and not detailed options is true return inmediatly _logger.LogWarning($"Liveness {liveness.Name} is not healthy"); return(livenessResults); } } return(livenessResults); } else { var liveness = _beatPulseContext.FindLiveness(path); if (liveness != null) { var livenessResult = await RunLiveness(liveness, options, httpContext); return(new[] { livenessResult }); } } return(Enumerable.Empty <LivenessResult>()); }
public void evaluate_if_some_request_is_beatpulse_request_when_port_is_configured() { var options = new BeatPulseOptions() .ConfigurePath("hc") .ConfigurePort(5000); var httpContext = new DefaultHttpContext(); httpContext.Request.Method = "GET"; httpContext.Request.Path = "/hc"; httpContext.Connection.LocalPort = 5000; httpContext.IsBeatPulseRequest(options) .Should().BeTrue(); httpContext.Connection.LocalPort = 6000; httpContext.IsBeatPulseRequest(options) .Should().BeFalse(); }
public void return_true_if_request_is_beaptulse_request() { var options = new BeatPulseOptions(); var httpContext = new DefaultHttpContext(); httpContext.Request.Method = "GET"; httpContext.Request.Path = "/hc"; httpContext.IsBeatPulseRequest(options) .Should().BeTrue(); options.ConfigurePath("health"); httpContext.Request.Method = "GET"; httpContext.Request.Path = "/health"; httpContext.IsBeatPulseRequest(options) .Should().BeTrue(); }
public void deepclone_create_clone() { var options = new BeatPulseOptions(); options.ConfigureDetailedOutput(includeExceptionMessages: true); options.DetailedErrors .Should().BeTrue(); var clone = options.DeepClone(); object.ReferenceEquals(options, clone) .Should().BeFalse(); clone.ConfigureDetailedOutput(includeExceptionMessages: false); options.DetailedErrors .Should().BeTrue(); clone.DetailedErrors .Should().BeFalse(); }
public static bool IsBeatPulseRequest(this HttpContext context, BeatPulseOptions options) { return(context.Request.Method == HttpMethods.Get && context.MatchesBeatPulseRequestPath(options) && context.MatchesBeatPulsePort(options)); }
public BeatPulseFilter(BeatPulseOptions options) { this._options = options; }
private static bool MatchesBeatPulsePort(this HttpContext context, BeatPulseOptions options) { return(options.Port.HasValue ? context.Connection.LocalPort == options.Port : true); }
async Task <LivenessResult> RunLiveness(IBeatPulseLiveness liveness, LivenessExecutionContext executionContext, BeatPulseOptions options) { _logger.LogInformation($"Executing liveness {executionContext.Name}."); var clock = Clock.StartNew(); try { using (var cancellationTokenSource = new CancellationTokenSource()) { var livenessTask = liveness.IsHealthy(executionContext, cancellationTokenSource.Token); if (await Task.WhenAny(livenessTask, Task.Delay(options.Timeout, cancellationTokenSource.Token)) == livenessTask) { _logger.LogInformation($"The liveness {executionContext.Name} is executed."); return((await livenessTask) .SetEnforced(name: executionContext.Name, path: executionContext.Path, duration: clock.Elapsed(), detailedErrors: options.DetailedErrors)); } else { _logger.LogWarning($"The liveness {executionContext.Name} return timeout, execution is cancelled."); cancellationTokenSource.Cancel(); return(LivenessResult.TimedOut() .SetEnforced(name: executionContext.Name, path: executionContext.Path, duration: clock.Elapsed(), detailedErrors: options.DetailedErrors)); } } } catch (Exception ex) { // The uri executed is now well formed, dns not found // or any other unexpected exceptions from liveness executions. _logger.LogError(ex, $"The liveness {executionContext.Name} is unhealthy."); return(LivenessResult.UnHealthy(ex) .SetEnforced(name: executionContext.Name, path: executionContext.Path, duration: clock.Elapsed(), detailedErrors: options.DetailedErrors)); } }