-
Notifications
You must be signed in to change notification settings - Fork 31
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this resulted in being a bit over-engineered in an attempt to fit in this decorator pattern which is not natural to Go imho. The fact that a type cast is required and that the new methods added on the sampler say nothing about their use (for stats) is a good indication that this isn't the way to do it.
I'd prefer it if we didn't go with this solution. The intention here is to only report occasionally, right?
Instead, let's:
- Add a method
(*maxEPSSampler).report
which reports to statsd when called. - Inside
(*maxEPSSampler).Start
create a new routine which calls that method on an interval:
go func() {
for range s.reportTicker.C {
s.report()
}
}()
- Call
reportTicker.Stop
in(*maxEPSSampler).Stop
In my opinion this is the way to go. This way, instrumentation is separated out into its own method as you've intended, while still not decoupled from its source. At this stage, we don't need a reusable component. Even so, if we were to create one we should do it differently.
If we need a reusable component later, we could create an interface:
type Reporter interface {
Report(client statsd.Client)
}
We could then simply add this method to the sampler (or any other component) to enable it as a candidate for interval reporting. A separate struct could use these reporters to call them on an interval. This way the implementation and intention is clear, with not much modification required.
Edit: the for loop for the ticker in my example needs to be extended a bit, more along the lines of the example in https://golang.org/pkg/time/#NewTicker to exit cleanly. |
3f9a97c
to
c49fce6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Alex. LGTM. Left a couple more nits but don't feel strongly about them so I'll leave it up to you.
event/sampler_max_eps.go
Outdated
func NewMaxEPSSampler(maxEPS float64) Sampler { | ||
return newMaxEPSSampler(maxEPS, newSamplerBackendRateCounter()) | ||
// NewMaxEPSSampler creates a new instance of a MaxEPSSampler with the provided maximum amount of events per second. | ||
func NewMaxEPSSampler(maxEPS float64, reportFrequency time.Duration) *MaxEPSSampler { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can remove the reportFrequency
from the arguments list, since it's not likely to be needed there, right? Then, for testing, you can keep it in the unexported constructor. It could be just a const.
event/sampler_max_eps.go
Outdated
@@ -47,19 +75,51 @@ func (s *maxEPSSampler) Sample(event *model.APMEvent) (sampled bool, rate float6 | |||
return true, 1 | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the risk of becoming annoying here: can we remove all the whitespace?
c49fce6
to
185d8fa
Compare
8ac92b4
to
57be144
Compare
185d8fa
to
e4a3cda
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
27566d7
to
8c7017d
Compare
8c7017d
to
2796ea1
Compare
This PR adds periodic max eps sampling reporting. This reporting is 2-fold:
MaxEPS
setting if the maximum event rate was reached.Sample output: