private async Task <HealthReportEntry> RunCheckAsync(IServiceScope scope, HealthCheckRegistration registration, CancellationToken cancellationToken)
        {
            await Task.Yield();

            cancellationToken.ThrowIfCancellationRequested();

            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);

                HealthReportEntry entry;
                try
                {
                    var result = await healthCheck.CheckHealthAsync(context, cancellationToken);

                    var duration = stopwatch.GetElapsedTime();

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

                    Log.HealthCheckEnd(_logger, registration, entry, duration);
                    Log.HealthCheckData(_logger, registration, entry);
                }

                // Allow cancellation to propagate.
                catch (Exception ex) when(ex as OperationCanceledException == null)
                {
                    var duration = stopwatch.GetElapsedTime();

                    entry = new HealthReportEntry(
                        status: HealthStatus.Unhealthy,
                        description: ex.Message,
                        duration: duration,
                        exception: ex,
                        data: null);

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

                return(entry);
            }
        }
Esempio n. 2
0
        private async Task <HealthReportEntry> RunCheckAsync(IServiceScope scope, HealthCheckRegistration registration, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            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);

                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);

                    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: 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();

                    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);
            }
        }
Esempio n. 3
0
 public static void HealthCheckData(ILogger logger, HealthCheckRegistration registration, HealthReportEntry entry)
 {
     if (entry.Data.Count > 0 && logger.IsEnabled(LogLevel.Debug))
     {
         logger.Log(
             LogLevel.Debug,
             EventIds.HealthCheckData,
             new HealthCheckDataLogValue(registration.Name, entry.Data),
             null,
             (state, ex) => state.ToString());
     }
 }
Esempio n. 4
0
            public static void HealthCheckEnd(ILogger logger, HealthCheckRegistration registration, HealthReportEntry entry, TimeSpan duration)
            {
                switch (entry.Status)
                {
                case HealthStatus.Healthy:
                    _healthCheckEndHealthy(logger, registration.Name, duration.TotalMilliseconds, entry.Status, entry.Description, null);
                    break;

                case HealthStatus.Degraded:
                    _healthCheckEndDegraded(logger, registration.Name, duration.TotalMilliseconds, entry.Status, entry.Description, null);
                    break;

                case HealthStatus.Unhealthy:
                    _healthCheckEndUnhealthy(logger, registration.Name, duration.TotalMilliseconds, entry.Status, entry.Description, null);
                    break;
                }
            }
Esempio n. 5
0
        public override async Task <HealthReport> CheckHealthAsync(
            Func <HealthCheckRegistration, bool> predicate,
            CancellationToken cancellationToken = default)
        {
            var registrations = _options.Value.Registrations;

            using (var scope = _scopeFactory.CreateScope())
            {
                var context = new HealthCheckContext();
                var entries = new Dictionary <string, HealthReportEntry>(StringComparer.OrdinalIgnoreCase);

                var totalTime = ValueStopwatch.StartNew();
                Log.HealthCheckProcessingBegin(_logger);

                foreach (var registration in registrations)
                {
                    if (predicate != null && !predicate(registration))
                    {
                        continue;
                    }

                    cancellationToken.ThrowIfCancellationRequested();

                    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();
                        context.Registration = registration;

                        Log.HealthCheckBegin(_logger, registration);

                        HealthReportEntry entry;
                        try
                        {
                            var result = await healthCheck.CheckHealthAsync(context, cancellationToken);

                            entry = new HealthReportEntry(
                                result.Result ? HealthStatus.Healthy : registration.FailureStatus,
                                result.Description,
                                result.Exception,
                                result.Data);

                            Log.HealthCheckEnd(_logger, registration, entry, stopwatch.GetElapsedTime());
                            Log.HealthCheckData(_logger, registration, entry);
                        }

                        // Allow cancellation to propagate.
                        catch (Exception ex) when(ex as OperationCanceledException == null)
                        {
                            entry = new HealthReportEntry(HealthStatus.Failed, ex.Message, ex, data: null);
                            Log.HealthCheckError(_logger, registration, ex, stopwatch.GetElapsedTime());
                        }

                        entries[registration.Name] = entry;
                    }
                }

                var report = new HealthReport(entries);
                Log.HealthCheckProcessingEnd(_logger, report.Status, totalTime.GetElapsedTime());
                return(report);
            }
        }
Esempio n. 6
0
 public static void HealthCheckEnd(ILogger logger, HealthCheckRegistration registration, HealthReportEntry entry, TimeSpan duration)
 {
     _healthCheckEnd(logger, registration.Name, duration.TotalMilliseconds, entry.Status, entry.Description, null);
 }