コード例 #1
0
        /// <inheritdoc/>
        public async Task <HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
        {
            return(await _memoryCache.GetOrCreateAsync(_cacheKey, async result =>
            {
                result.AbsoluteExpiration = DateTimeOffset.UtcNow.AddMilliseconds(_cacheExpirationMs);

                return await _healthCheck.CheckHealthAsync(context, cancellationToken);
            }));
        }
コード例 #2
0
        private async Task <HealthCheckResult> CheckHealthAsync(HealthCheckPolicy policy, IHealthCheckSettings settings)
        {
            var checkCache = _resultCache[settings.Name];

            var utcNow = _clock.UtcNow;
            HealthCheckResult result = null;

            if (!checkCache.ShouldCheck(utcNow))
            {
                result = checkCache.Result;
            }
            else
            {
                using (CancellationTokenSource cts = new CancellationTokenSource(settings.Timeout))
                {
                    IHealthCheck check         = checkCache.Check;
                    var          healthContext = new HealthCheckContext(settings);
                    healthContext.CancellationToken = cts.Token;
                    try
                    {
                        await check.CheckHealthAsync(healthContext);

                        result = new HealthCheckResult
                        {
                            Name       = settings.Name,
                            Elapsed    = healthContext.ElapsedMilliseconds,
                            Message    = healthContext.Message,
                            Status     = healthContext.HasSucceeded ? HealthStatus.Healthy : healthContext.HasWarned ? HealthStatus.Warning : HealthStatus.Unhealthy,
                            Issued     = utcNow.ToUnixTimeSeconds(),
                            NextTry    = utcNow.AddSeconds(settings.Frequency),
                            Critical   = settings.Critical,
                            Properties = healthContext.Properties?.ToDictionary(kvp => kvp.Key, kvp => JToken.FromObject(kvp.Value))
                        };

                        checkCache.Result = result;
                    }
                    catch (Exception e)
                    {
                        result = new HealthCheckResult
                        {
                            Name      = settings.Name,
                            Elapsed   = healthContext.ElapsedMilliseconds,
                            Message   = "An error occured. See logs for more details.",
                            Status    = HealthStatus.Unhealthy,
                            Issued    = utcNow.ToUnixTimeSeconds(),
                            NextTry   = utcNow.AddSeconds(settings.Frequency),
                            Critical  = settings.Critical,
                            Exception = e
                        };
                        checkCache.Result = result;
                    }
                }
            }

            return(result);
        }
コード例 #3
0
        private async Task <(string Name, HealthCheckResult Result)> MakeHealthCheckAsync(string name, IHealthCheck check, CancellationToken ct)
        {
            try
            {
                var result = await check.CheckHealthAsync(ct);

                return(name, result);
            }
            catch
            {
                return(name, new HealthCheckResult(false));
            }
        }
コード例 #4
0
        public async Task <HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
        {
            if (_lastChecked >= ExpirationWindow)
            {
                return(_lastResult);
            }

            try
            {
                await _semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
            }
            catch (OperationCanceledException oce) when(cancellationToken.IsCancellationRequested)
            {
                _logger.LogInformation(oce, $"Cancellation was requested for {nameof(CheckHealthAsync)}");
                return(_lastResult);
            }

            try
            {
                if (_lastChecked >= ExpirationWindow)
                {
                    return(_lastResult);
                }

                using (IServiceScope scope = _provider.CreateScope())
                {
                    try
                    {
                        IHealthCheck check = _healthCheck.Invoke(scope.ServiceProvider);
                        _lastResult = await check.CheckHealthAsync(context, cancellationToken).ConfigureAwait(false);

                        _lastChecked = Clock.UtcNow;
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, Resources.FailedHealthCheckMessage);
                        _lastResult  = HealthCheckResult.Unhealthy(Resources.FailedHealthCheckMessage);
                        _lastChecked = Clock.UtcNow;
                    }
                }

                return(_lastResult);
            }
            finally
            {
                _semaphore.Release();
            }
        }
コード例 #5
0
ファイル: HealthController.cs プロジェクト: traegerp/dagger
        /// <summary>
        /// Health End Point
        /// </summary>
        /// <returns></returns>
        public async Task <IActionResult> HealthCheckPoint()
        {
            try
            {
                HealthCheckContext context = new HealthCheckContext();

                var result = await _healthCheck.CheckHealthAsync(context);

                return(Ok(Enum.GetName(typeof(HealthStatus), result.Status)));
            }
            catch (Exception error)
            {
                _logger.LogError(error, nameof(HealthCheckPoint));
                return(StatusCode(StatusCodes.Status500InternalServerError));
            }
        }
コード例 #6
0
        public async Task <HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
        {
            if (healthCheck == null)
            {
                var addresses = server.Features.Get <IServerAddressesFeature>().Addresses;
                if (!addresses.Any())
                {
                    return(HealthCheckResult.Unhealthy());
                }

                healthCheck = new UriHealthCheck(
                    new UriHealthCheckOptions().UseGet().AddUri(new Uri(addresses.First().Replace("[::]", "localhost"))), () => httpClientFactory.CreateClient());
            }

            return(await healthCheck.CheckHealthAsync(context, cancellationToken));
        }
コード例 #7
0
        public HealthCheckCachingTests()
        {
            var serviceProvider = Substitute.For <IServiceProvider>();
            var scopeFactory    = Substitute.For <IServiceScopeFactory>();

            serviceProvider.GetService(typeof(IServiceScopeFactory)).Returns(scopeFactory);

            _serviceScope = Substitute.For <IServiceScope>();
            scopeFactory.CreateScope().Returns(_serviceScope);

            _healthCheckFunc = Substitute.For <Func <IServiceProvider, IHealthCheck> >();
            _healthCheck     = Substitute.For <IHealthCheck>();
            _context         = new HealthCheckContext();

            _cahcedHealthCheck = new CachedHealthCheck(serviceProvider, _healthCheckFunc, NullLogger <CachedHealthCheck> .Instance);

            _healthCheckFunc.Invoke(Arg.Any <IServiceProvider>()).ReturnsForAnyArgs(_healthCheck);

            _healthCheck.CheckHealthAsync(Arg.Any <HealthCheckContext>()).Returns(HealthCheckResult.Healthy());
        }
コード例 #8
0
        public async Task <HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken)
        {
            if (_lastChecked >= ExpirationWindow)
            {
                return(_lastResult);
            }

            await _semaphore.WaitAsync(cancellationToken);

            try
            {
                if (_lastChecked >= ExpirationWindow)
                {
                    return(_lastResult);
                }

                using (IServiceScope scope = _provider.CreateScope())
                {
                    try
                    {
                        IHealthCheck check = _healthCheck.Invoke(scope.ServiceProvider);
                        _lastResult = await check.CheckHealthAsync(context, cancellationToken);

                        _lastChecked = Clock.UtcNow;
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, Resources.FailedHealthCheckMessage);
                        _lastResult  = HealthCheckResult.Unhealthy(Resources.FailedHealthCheckMessage);
                        _lastChecked = Clock.UtcNow;
                    }
                }

                return(_lastResult);
            }
            finally
            {
                _semaphore.Release();
            }
        }
コード例 #9
0
    public async Task <HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        // you could improve thread concurrency by separating the read/write logic but this would require additional thread safety checks.
        // will throw OperationCanceledException if the token is canceled while we're waiting.
        await _mutex.WaitAsync(cancellationToken);

        try
        {
            // previous check is cached & not yet expired; just return it
            if (_lastCheck > DateTime.MinValue && DateTime.Now - _lastCheck < _timeToLive)
            {
                return(_result);
            }
            // check has not been performed or is expired; run it now & cache the result
            _result = await _healthCheck.CheckHealthAsync(context, cancellationToken);

            _lastCheck = DateTime.Now;
            return(_result);
        }
        finally
        {
            _mutex.Release();
        }
    }