Beispiel #1
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);
        }
        public DefaultHealthCheckPolicyProvider(HealthCheckPolicy defaultPolicy)
        {
            if (defaultPolicy == null)
            {
                throw new ArgumentNullException(nameof(defaultPolicy));
            }

            DefaultPolicy = defaultPolicy;
            _policies     = CreatePolicies(defaultPolicy);
        }
Beispiel #3
0
        public async Task <HealthCheckResponse> CheckHealthAsync(HealthCheckPolicy policy)
        {
            var taskResults = new Task <HealthCheckResult> [policy.CheckSettings.Count];

            for (int i = 0; i < policy.CheckSettings.Count; i++)
            {
                var settings = policy.CheckSettings[i].Value;
                taskResults[i] = Task.Run(() => CheckHealthAsync(policy, settings));
            }

            var results = await Task.WhenAll(taskResults);

            return(new HealthCheckResponse(results));
        }
        private Dictionary <string, HealthCheckPolicy> CreatePolicies(HealthCheckPolicy policy)
        {
            var policies = policy.CheckSettings
                           .SelectMany(s => s.Value.Tags, (s, t) => new { Tag = t, Settings = s })
                           .GroupBy(item => item.Tag)
                           .ToDictionary(
                group => group.Key,
                group => group.Aggregate(new HealthCheckSettingsCollection(), (settings, item) =>
            {
                settings.Add(item.Settings);
                return(settings);
            },
                                         settings => new HealthCheckPolicy(settings)));

            return(policies);
        }
Beispiel #5
0
        public DefaultHealthCheckService(ISystemClock clock, IHealthCheckPolicyProvider policyProvider, ICheckFactory checkFactory)
        {
            if (checkFactory == null)
            {
                throw new ArgumentNullException(nameof(checkFactory));
            }

            if (clock == null)
            {
                throw new ArgumentNullException(nameof(clock));
            }

            if (policyProvider == null)
            {
                throw new ArgumentNullException(nameof(policyProvider));
            }

            _checkFactory  = checkFactory;
            _clock         = clock;
            _defaultPolicy = policyProvider.DefaultPolicy;
            _resultCache   = CreateCache();
        }
        public async Task Invoke(HttpContext context)
        {
            PathString subpath;

            if (!context.Request.Path.StartsWithSegments(_options.Path, out subpath))
            {
                await _next(context);

                return;
            }

            var policyName = subpath.ToUriComponent().Trim('/');

            if (policyName.Length == 0)
            {
                policyName = Constants.DefaultPolicy;
            }

            if (_options.AuthorizationPolicy != null)
            {
                var principal = await SecurityHelper.GetUserPrincipal(context, _options.AuthorizationPolicy);

                if (!await _authorizationService.AuthorizeAsync(principal, context, _options.AuthorizationPolicy))
                {
                    _logger.AuthorizationFailed();
                    await _next(context);

                    return;
                }
            }

            HealthCheckPolicy policy = _policyProvider.GetPolicy(policyName);

            if (policy == null)
            {
                _logger.InvalidPolicy(policyName);
                await _next(context);

                return;
            }

            var response            = context.Response;
            var healthCheckResponse = await _healthService.CheckHealthAsync(policy);

            if (healthCheckResponse.HasErrors)
            {
                _logger.HealthCheckFailed(healthCheckResponse.Errors);
                if (healthCheckResponse.HasCriticalErrors)
                {
                    response.StatusCode = StatusCodes.Status503ServiceUnavailable;
                    response.WriteRetryAfterHeader(healthCheckResponse.RetryAfter);
                }
            }
            else
            {
                _logger.HealthCheckSucceeded();
                response.StatusCode = StatusCodes.Status200OK;
            }

            if (_options.SendResults && !HttpMethods.IsHead(context.Request.Method))
            {
                response.ContentType = ApplicationJson;
                using (var writer = new HttpResponseStreamWriter(response.Body, Encoding.UTF8, 1024, _bytePool, _charPool))
                {
                    using (var jsonWriter = new JsonTextWriter(writer))
                    {
                        jsonWriter.ArrayPool   = _jsonCharPool;
                        jsonWriter.CloseOutput = false;

                        _jsonSerializer.Serialize(jsonWriter, healthCheckResponse.Results);
                    }
                }
            }
        }
Beispiel #7
0
        public CanaryMiddleware(
            RequestDelegate next,
            IOptions <CanaryOptions> options,
            ILoggerFactory loggerFactory,
            IHealthCheckService healthService,
            IHealthCheckPolicyProvider policyProvider,
            IServerSwitch serverSwitch,
            IAuthorizationService authorizationService)
        {
            if (next == null)
            {
                throw new ArgumentNullException(nameof(next));
            }

            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            if (loggerFactory == null)
            {
                throw new ArgumentNullException(nameof(loggerFactory));
            }

            if (healthService == null)
            {
                throw new ArgumentNullException(nameof(healthService));
            }

            if (policyProvider == null)
            {
                throw new ArgumentNullException(nameof(policyProvider));
            }

            if (authorizationService == null)
            {
                throw new ArgumentNullException(nameof(authorizationService));
            }

            if (authorizationService == null)
            {
                throw new ArgumentNullException(nameof(authorizationService));
            }

            _next                 = next;
            _options              = options.Value;
            _logger               = loggerFactory.CreateLogger <CanaryMiddleware>();
            _healthService        = healthService;
            _serverSwitch         = serverSwitch;
            _authorizationService = authorizationService;

            if (_options.EnableHealthCheck)
            {
                var defaultPolicy = policyProvider.GetPolicy(_options.PolicyName);
                if (defaultPolicy == null)
                {
                    throw new ArgumentException($"{nameof(_options.PolicyName)} '{_options.PolicyName}' is not a valid policy.", nameof(_options));
                }

                _defaultPolicy = defaultPolicy;
            }
        }