github.com/hellofresh/janus@v0.0.0-20230925145208-ce8de8183c67/pkg/plugin/cb/stats_collector.go (about) 1 package cb 2 3 import ( 4 "errors" 5 6 metricCollector "github.com/afex/hystrix-go/hystrix/metric_collector" 7 "github.com/hellofresh/stats-go/bucket" 8 "github.com/hellofresh/stats-go/client" 9 "github.com/hellofresh/stats-go/timer" 10 log "github.com/sirupsen/logrus" 11 ) 12 13 // StatsCollector fulfills the metricCollector interface allowing users to ship circuit 14 // stats to a metric backend. To use users must call InitializeStatsCollector before 15 // circuits are started. 16 type StatsCollector struct { 17 client client.Client 18 section string 19 name string 20 circuitOpenPrefix string 21 attemptsPrefix string 22 errorsPrefix string 23 successesPrefix string 24 failuresPrefix string 25 rejectsPrefix string 26 shortCircuitsPrefix string 27 timeoutsPrefix string 28 fallbackSuccessesPrefix string 29 fallbackFailuresPrefix string 30 canceledPrefix string 31 deadlinePrefix string 32 totalDurationPrefix string 33 runDurationPrefix string 34 } 35 36 // NewCollectorRegistry returns a function to be registerd with metricCollector.Registry.Register(NewCollectorRegistry). 37 func NewCollectorRegistry(client client.Client) func(string) metricCollector.MetricCollector { 38 return func(name string) metricCollector.MetricCollector { 39 c, err := NewStatsCollector(name, client) 40 if err != nil { 41 log.WithError(err).Error("could not initialize the stats collector") 42 } 43 44 return c 45 } 46 } 47 48 // NewStatsCollector creates a collector for a specific circuit. The 49 // prefix given to this circuit will be {config.Prefix}.{circuit_name}.{metric}. 50 // Circuits with "/" in their names will have them replaced with ".". 51 func NewStatsCollector(name string, client client.Client) (*StatsCollector, error) { 52 if client == nil { 53 return nil, errors.New("metrics client must be initialized before circuits are created") 54 } 55 56 return &StatsCollector{ 57 client: client, 58 name: name, 59 circuitOpenPrefix: "circuitOpen", 60 attemptsPrefix: "attempts", 61 errorsPrefix: "errors", 62 successesPrefix: "successes", 63 failuresPrefix: "failures", 64 rejectsPrefix: "rejects", 65 shortCircuitsPrefix: "shortCircuits", 66 timeoutsPrefix: "timeouts", 67 fallbackSuccessesPrefix: "fallbackSuccesses", 68 fallbackFailuresPrefix: "fallbackFailures", 69 canceledPrefix: "contextCanceled", 70 deadlinePrefix: "contextDeadlineExceeded", 71 totalDurationPrefix: "totalDuration", 72 runDurationPrefix: "runDuration", 73 }, nil 74 } 75 76 // Update metrics 77 func (g *StatsCollector) Update(r metricCollector.MetricResult) { 78 if r.Successes > 0 { 79 g.client.TrackState(g.section, bucket.MetricOperation{g.name, g.circuitOpenPrefix}, 0) 80 } else if r.ShortCircuits > 0 { 81 g.client.TrackState(g.section, bucket.MetricOperation{g.name, g.circuitOpenPrefix}, 1) 82 } 83 84 g.incrementCounterMetric(g.attemptsPrefix, r.Attempts) 85 g.incrementCounterMetric(g.errorsPrefix, r.Errors) 86 g.incrementCounterMetric(g.successesPrefix, r.Successes) 87 g.incrementCounterMetric(g.failuresPrefix, r.Failures) 88 g.incrementCounterMetric(g.rejectsPrefix, r.Rejects) 89 g.incrementCounterMetric(g.shortCircuitsPrefix, r.ShortCircuits) 90 g.incrementCounterMetric(g.timeoutsPrefix, r.Timeouts) 91 g.incrementCounterMetric(g.fallbackSuccessesPrefix, r.FallbackSuccesses) 92 g.incrementCounterMetric(g.fallbackFailuresPrefix, r.FallbackFailures) 93 g.incrementCounterMetric(g.canceledPrefix, r.ContextCanceled) 94 g.incrementCounterMetric(g.deadlinePrefix, r.ContextDeadlineExceeded) 95 96 g.client.TrackOperation( 97 g.section, 98 bucket.MetricOperation{g.name, g.totalDurationPrefix}, 99 timer.NewDuration(r.TotalDuration), 100 r.Successes > 0, 101 ) 102 103 g.client.TrackOperation( 104 g.section, 105 bucket.MetricOperation{g.name, g.runDurationPrefix}, 106 timer.NewDuration(r.RunDuration), 107 r.Successes > 0, 108 ) 109 } 110 111 // Reset is a noop operation in this collector. 112 func (g *StatsCollector) Reset() {} 113 114 func (g *StatsCollector) incrementCounterMetric(prefix string, i float64) { 115 if i == 0 { 116 return 117 } 118 g.client.TrackMetricN(g.section, bucket.MetricOperation{g.name, prefix}, int(i)) 119 }