/// <summary>
        /// Checks to see if the breaker should trip, and trips if it should.
        /// </summary>
        /// <returns><code>true</code> if breaker is tripped</returns>
        private bool CheckAndSetTripped()
        {
            var stopwatch = Stopwatch.StartNew();
            var state     = "Unknown";

            try
            {
                if (_state == State.Tripped)
                {
                    state = "AlreadyTripped";
                    return(true);
                }

                if (!Monitor.TryEnter(_stateChangeLock))
                {
                    state = "MissedLock";
                    return(_state == State.Tripped);
                }

                try
                {
                    var snapshot = _metrics.GetSnapshot();

                    // If we haven't met the minimum number of operations needed to trip, don't trip.
                    if (snapshot.Total < Properties.MinimumOperations.Value)
                    {
                        state = "CriteriaNotMet";
                        return(false);
                    }

                    // If we're within the error threshold, don't trip.
                    if (snapshot.ErrorPercentage < Properties.ThresholdPercentage.Value)
                    {
                        state = "CriteriaNotMet";
                        return(false);
                    }

                    _state = State.Tripped;
                    _lastTrippedTimestamp = _clock.GetMillisecondTimestamp();
                    state = "JustTripped";

                    _stats.Event(StatsPrefix, State.Tripped.ToString(), null);
                    Log.ErrorFormat("Tripped Breaker={0} Operations={1} ErrorPercentage={2} Wait={3}",
                                    _key,
                                    snapshot.Total,
                                    snapshot.ErrorPercentage,
                                    Properties.TrippedDurationMillis.Value);

                    return(true);
                }
                finally
                {
                    Monitor.Exit(_stateChangeLock);
                }
            }
            finally
            {
                _stats.Elapsed(StatsPrefix + " CheckAndSetTripped", state, stopwatch.Elapsed);
            }
        }
Example #2
0
        /// <summary>
        /// Checks to see if the breaker should trip, and trips if it should.
        /// </summary>
        /// <returns><code>true</code> if breaker is tripped</returns>
        private bool CheckAndSetTripped()
        {
            if (_state == State.Tripped)
            {
                return(true);
            }

            if (!Monitor.TryEnter(_stateChangeLock))
            {
                return(_state == State.Tripped);
            }

            try
            {
                var snapshot = _metrics.GetSnapshot();

                // If we haven't met the minimum number of operations needed to trip, don't trip.
                if (snapshot.Total < _config.GetMinimumOperations(_key))
                {
                    return(false);
                }

                // If we're within the error threshold, don't trip.
                if (snapshot.ErrorPercentage < _config.GetThresholdPercentage(_key))
                {
                    return(false);
                }

                _state = State.Tripped;
                _lastTrippedTimestamp = _clock.GetMillisecondTimestamp();

                _metricEvents.BreakerTripped(Name);
                _log.Error($"Tripped Breaker={_key} Operations={snapshot.Total} ErrorPercentage={snapshot.ErrorPercentage} Wait={_config.GetTrippedDurationMillis(_key)}");

                return(true);
            }
            finally
            {
                Monitor.Exit(_stateChangeLock);
            }
        }
        internal FailurePercentageCircuitBreaker(GroupKey key, IClock clock, ICommandMetrics metrics, IStats stats, IMetricEvents metricEvents, FailurePercentageCircuitBreakerProperties properties, IConfigurableValue<long> gaugeIntervalMillisOverride = null)
        {
            _key = key;
            _clock = clock;
            _metrics = metrics;

            if (stats == null)
            {
                throw new ArgumentNullException("stats");
            }

            if (metricEvents == null)
            {
                throw new ArgumentNullException("metricEvents");
            }

            _stats = stats;
            _metricEvents = metricEvents;

            Properties = properties;
            _state = State.Fixed; // Start off assuming everything's fixed.
            _lastTrippedTimestamp = 0; // 0 is fine since it'll be far less than the first compared value.

            // Old gauge, will be phased out in v3.0 when IStats are removed.
            _statsTimer = new GaugeTimer((source, args) =>
            {
                var snapshot = _metrics.GetSnapshot();
                _stats.Gauge(StatsPrefix + " total", snapshot.Total >= properties.MinimumOperations.Value ? "Above" : "Below", snapshot.Total);
                _stats.Gauge(StatsPrefix + " error", snapshot.ErrorPercentage >= properties.ThresholdPercentage.Value ? "Above" : "Below", snapshot.ErrorPercentage);
            }, gaugeIntervalMillisOverride);

            _metricsTimer = new GaugeTimer((source, args) =>
            {
                _metricEvents.BreakerConfigGauge(
                    Name,
                    Properties.MinimumOperations.Value,
                    Properties.ThresholdPercentage.Value,
                    Properties.TrippedDurationMillis.Value);
            }, ConfigGaugeIntervalMillis);
        }
        internal FailurePercentageCircuitBreaker(GroupKey key, IClock clock, ICommandMetrics metrics, IStats stats, FailurePercentageCircuitBreakerProperties properties, IConfigurableValue <long> gaugeIntervalMillisOverride = null)
        {
            _key     = key;
            _clock   = clock;
            _metrics = metrics;

            if (stats == null)
            {
                throw new ArgumentNullException("stats");
            }

            _stats = stats;

            Properties            = properties;
            _state                = State.Fixed; // Start off assuming everything's fixed.
            _lastTrippedTimestamp = 0;           // 0 is fine since it'll be far less than the first compared value.

            _timer = new GaugeTimer((source, args) =>
            {
                var snapshot = _metrics.GetSnapshot();
                _stats.Gauge(StatsPrefix + " total", snapshot.Total >= properties.MinimumOperations.Value ? "Above" : "Below", snapshot.Total);
                _stats.Gauge(StatsPrefix + " error", snapshot.ErrorPercentage >= properties.ThresholdPercentage.Value ? "Above" : "Below", snapshot.ErrorPercentage);
            }, gaugeIntervalMillisOverride);
        }