internal void Increment(CounterMetric metric)
        {
            // Notes:
            // - If we have long periods with no stats, we won't reset until we get one.
            // - This is a "pretty close" implementation.
            //   - Accuracy on Gets isn't 100% and is subject to racing.
            //   - We may write metrics into "old" buckets immediately before resetting at the interval.

            if (_clock.GetMillisecondTimestamp() - _lastResetAtTime > _config.GetWindowMillis(_key))
            {
                Reset();
            }

            // See note in Reset() about potential for losing current window counts here.

            _counters[(int)metric].Increment();
        }
Ejemplo n.º 2
0
        public CircuitBreakerFactory(IMetricEvents metricEvents, IFailurePercentageCircuitBreakerConfig breakerConfig, IMjolnirLogFactory logFactory)
        {
            _metricEvents  = metricEvents ?? throw new ArgumentNullException(nameof(metricEvents));
            _breakerConfig = breakerConfig ?? throw new ArgumentNullException(nameof(breakerConfig));
            _logFactory    = logFactory ?? throw new ArgumentNullException(nameof(logFactory));

            _log = logFactory.CreateLog <FailurePercentageCircuitBreaker>();
            if (_log == null)
            {
                throw new InvalidOperationException($"{nameof(IMjolnirLogFactory)} implementation returned null from {nameof(IMjolnirLogFactory.CreateLog)} for type {typeof(CircuitBreakerFactory)}, please make sure the implementation returns a non-null log for all calls to {nameof(IMjolnirLogFactory.CreateLog)}");
            }

            _timer = new GaugeTimer(state =>
            {
                try
                {
                    var keys = _circuitBreakers.Keys;
                    foreach (var key in keys)
                    {
                        if (_circuitBreakers.TryGetValue(key, out Lazy <FailurePercentageCircuitBreaker> lazy) && lazy.IsValueCreated)
                        {
                            var breaker = lazy.Value;
                            _metricEvents.BreakerGauge(
                                breaker.Name,
                                _breakerConfig.GetMinimumOperations(key),
                                _breakerConfig.GetWindowMillis(key),
                                _breakerConfig.GetThresholdPercentage(key),
                                _breakerConfig.GetTrippedDurationMillis(key),
                                _breakerConfig.GetForceTripped(key),
                                _breakerConfig.GetForceFixed(key),
                                breaker.IsTripped(),
                                breaker.Metrics.SuccessCount,
                                breaker.Metrics.FailureCount);
                        }
                    }
                }
                catch (Exception e)
                {
                    _log.Error($"Error sending {nameof(IMetricEvents.BreakerGauge)} metric event", e);
                }
            });
        }