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