Example #1
0
        public static async Task <HealthCheckResult> HealthCheck(this HealthCheckRegistration registration, IServiceProvider provider)
        {
            var context = new HealthCheckContext {
                Registration = registration
            };
            var healthCheckResult = new HealthCheckResult();

            try
            {
                var res = await registration.Factory(provider).CheckHealthAsync(context).ConfigureAwait(false);

                healthCheckResult = new HealthCheckResult()
                {
                    Status      = res.Status.ToHealthStatus(),
                    Description = res.Description,
                    Details     = res.Data?.ToDictionary(i => i.Key, i => i.Value)
                };

                if (res.Exception != null && !string.IsNullOrEmpty(res.Exception.Message))
                {
                    healthCheckResult.Details.Add("error", res.Exception.Message);
                }
            }
#pragma warning disable CA1031 // Do not catch general exception types
            catch (Exception e)
            {
                // Catch all exceptions so that a status can always be returned
                healthCheckResult.Details.Add("exception", e.Message);
            }
#pragma warning restore CA1031 // Do not catch general exception types

            return(healthCheckResult);
        }
        public void AddServiceFabricHealthChecks_RegisterPublisherAndChecks()
        {
            string       checkName = "MockCheck";
            IHealthCheck check     = new MockCheck();

            IServiceProvider provider = new ServiceCollection()
                                        .AddSingleton(new Mock <IAccessor <IServicePartition> >().Object)
                                        .AddServiceFabricHealthChecks()
                                        .AddCheck(checkName, check)
                                        .Services
                                        .BuildServiceProvider();

            IHealthCheckPublisher[] publishers = provider
                                                 .GetRequiredService <IEnumerable <IHealthCheckPublisher> >()
                                                 .ToArray();

            Assert.IsTrue(
                publishers.Any(p => p is ServiceFabricHealthCheckPublisher),
                FormattableString.Invariant($"{nameof(ServiceFabricHealthCheckPublisher)} publisher should be registered"));

            IOptions <HealthCheckServiceOptions> options = provider.GetRequiredService <IOptions <HealthCheckServiceOptions> >();
            HealthCheckRegistration registration         = options.Value.Registrations.SingleOrDefault(r => string.Equals(checkName, r.Name, StringComparison.Ordinal));

            Assert.IsNotNull(registration, "HealthCheck should be registered");

            Assert.AreEqual(check, registration.Factory(provider));
        }
        public static async Task <HealthCheckResult> HealthCheck(this HealthCheckRegistration registration, IServiceProvider provider)
        {
            var context = new HealthCheckContext {
                Registration = registration
            };
            var healthCheckResult = new HealthCheckResult();

            try
            {
                var res = await registration.Factory(provider).CheckHealthAsync(context);

                healthCheckResult = new HealthCheckResult()
                {
                    Status      = res.Status.ToHealthStatus(),
                    Description = res.Description,
                    Details     = res.Data?.ToDictionary(i => i.Key, i => i.Value)
                };

                if (res.Exception != null && !string.IsNullOrEmpty(res.Exception.Message))
                {
                    healthCheckResult.Details.Add("error", res.Exception.Message);
                }
            }
            catch (Exception)
            {
            }

            return(healthCheckResult);
        }
Example #4
0
        private HttpHealthCheckParameters GetParameters(IServiceProvider provider, string checkName)
        {
            IOptions <HealthCheckServiceOptions> options = provider.GetRequiredService <IOptions <HealthCheckServiceOptions> >();
            HealthCheckRegistration registration         = options.Value.Registrations.SingleOrDefault(r => string.Equals(checkName, r.Name, StringComparison.Ordinal));

            Assert.IsNotNull(registration, "HealthCheck should be registered");

            IHealthCheck check = registration.Factory(provider);

            Assert.IsInstanceOfType(check, typeof(HttpEndpointHealthCheck));
            return(((HttpEndpointHealthCheck)check).Parameters);
        }
    private async Task <HealthReportEntry> RunCheckAsync(HealthCheckRegistration registration, CancellationToken cancellationToken)
    {
        cancellationToken.ThrowIfCancellationRequested();

        var scope = _scopeFactory.CreateAsyncScope();

        await using (scope.ConfigureAwait(false))
        {
            var healthCheck = registration.Factory(scope.ServiceProvider);

            // If the health check does things like make Database queries using EF or backend HTTP calls,
            // it may be valuable to know that logs it generates are part of a health check. So we start a scope.
            using (_logger.BeginScope(new HealthCheckLogScope(registration.Name)))
            {
                var stopwatch = ValueStopwatch.StartNew();
                var context   = new HealthCheckContext {
                    Registration = registration
                };

                Log.HealthCheckBegin(_logger, registration.Name);

                HealthReportEntry       entry;
                CancellationTokenSource?timeoutCancellationTokenSource = null;
                try
                {
                    HealthCheckResult result;

                    var checkCancellationToken = cancellationToken;
                    if (registration.Timeout > TimeSpan.Zero)
                    {
                        timeoutCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
                        timeoutCancellationTokenSource.CancelAfter(registration.Timeout);
                        checkCancellationToken = timeoutCancellationTokenSource.Token;
                    }

                    result = await healthCheck.CheckHealthAsync(context, checkCancellationToken).ConfigureAwait(false);

                    var duration = stopwatch.GetElapsedTime();

                    entry = new HealthReportEntry(
                        status: result.Status,
                        description: result.Description,
                        duration: duration,
                        exception: result.Exception,
                        data: result.Data,
                        tags: registration.Tags);

                    Log.HealthCheckEnd(_logger, registration, entry, duration);
                    Log.HealthCheckData(_logger, registration, entry);
                }
                catch (OperationCanceledException ex) when(!cancellationToken.IsCancellationRequested)
                {
                    var duration = stopwatch.GetElapsedTime();

                    entry = new HealthReportEntry(
                        status: registration.FailureStatus,
                        description: "A timeout occurred while running check.",
                        duration: duration,
                        exception: ex,
                        data: null,
                        tags: registration.Tags);

                    Log.HealthCheckError(_logger, registration, ex, duration);
                }

                // Allow cancellation to propagate if it's not a timeout.
                catch (Exception ex) when(ex as OperationCanceledException == null)
                {
                    var duration = stopwatch.GetElapsedTime();

                    entry = new HealthReportEntry(
                        status: registration.FailureStatus,
                        description: ex.Message,
                        duration: duration,
                        exception: ex,
                        data: null,
                        tags: registration.Tags);

                    Log.HealthCheckError(_logger, registration, ex, duration);
                }

                finally
                {
                    timeoutCancellationTokenSource?.Dispose();
                }

                return(entry);
            }
        }
    }
Example #6
0
        private async Task <HealthReportEntry> RunCheckAsync(IServiceScope scope, HealthCheckRegistration registration, CacheableHealthChecksServiceOptions cacheOptionsValue, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            // If the health check does things like make Database queries using EF or backend HTTP calls,
            // it may be valuable to know that logs it generates are part of a health check. So we start a scope.
            using (logger.BeginScope(new HealthCheckLogScope(registration.Name)))
            {
                var cacheKey = $"{cacheOptionsValue.CachePrefix}{registration.Name}";

                if (memoryCache.TryGetValue(cacheKey, out HealthReportEntry entry))
                {
                    Log.HealthCheckFromCache(logger, registration, entry);
                    Log.HealthCheckData(logger, registration, entry);
                }
                else
                {
                    var cacheable       = registration.Tags.Any(a => a == cacheOptionsValue.Tag);
                    var optionsSnapshot = scope.ServiceProvider.GetService <IOptionsSnapshot <RegistrationOptions> >();

                    var healthCheck = registration.Factory(scope.ServiceProvider);

                    var stopwatch = ValueStopwatch.StartNew();
                    var context   = new HealthCheckContext {
                        Registration = registration
                    };

                    Log.HealthCheckBegin(logger, registration);

                    CancellationTokenSource timeoutCancellationTokenSource = null;
                    try
                    {
                        HealthCheckResult result;

                        var checkCancellationToken = cancellationToken;
                        if (registration.Timeout > TimeSpan.Zero)
                        {
                            timeoutCancellationTokenSource =
                                CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
                            timeoutCancellationTokenSource.CancelAfter(registration.Timeout);
                            checkCancellationToken = timeoutCancellationTokenSource.Token;
                        }

                        result = await healthCheck.CheckHealthAsync(context, checkCancellationToken)
                                 .ConfigureAwait(false);

                        var duration = stopwatch.GetElapsedTime();

                        if (cacheable)
                        {
                            entry = BuildAndCacheReportEntry(cacheKey, registration, cacheOptionsValue, optionsSnapshot, result, duration);
                        }
                        else
                        {
                            entry = new HealthReportEntry(
                                status: result.Status,
                                description: result.Description,
                                duration: duration,
                                exception: result.Exception,
                                data: result.Data,
                                tags: registration.Tags);
                        }

                        Log.HealthCheckEnd(logger, registration, entry, duration);
                        Log.HealthCheckData(logger, registration, entry);
                    }
                    catch (OperationCanceledException ex) when(!cancellationToken.IsCancellationRequested)
                    {
                        var duration = stopwatch.GetElapsedTime();

                        if (cacheable && cacheOptionsValue.CacheExceptions)
                        {
                            entry = BuildAndCacheExceptionReport(cacheKey, registration, cacheOptionsValue, optionsSnapshot, ex, duration);
                        }
                        else
                        {
                            entry = new HealthReportEntry(
                                status: HealthStatus.Unhealthy,
                                description: "A timeout occured while running check.",
                                duration: duration,
                                exception: ex,
                                data: null);
                        }

                        Log.HealthCheckError(logger, registration, ex, duration);
                    }

                    // Allow cancellation to propagate if it's not a timeout.
                    catch (Exception ex) when(ex as OperationCanceledException == null)
                    {
                        var duration = stopwatch.GetElapsedTime();

                        if (cacheable && cacheOptionsValue.CacheExceptions)
                        {
                            entry = BuildAndCacheExceptionReport(cacheKey, registration, cacheOptionsValue, optionsSnapshot, ex, duration);
                        }
                        else
                        {
                            entry = new HealthReportEntry(
                                status: HealthStatus.Unhealthy,
                                description: ex.Message,
                                duration: duration,
                                exception: ex,
                                data: null);
                        }

                        Log.HealthCheckError(logger, registration, ex, duration);
                    }
                    finally
                    {
                        timeoutCancellationTokenSource?.Dispose();
                    }
                }

                return(entry);
            }
        }