Conversation
|
The regression test added to librato_metrics_reporter_test.rb will only pass on Ruby 1.9. It's only a temporary measure which will be replaced by a better test once complete. |
|
@eric Have any opinions on the isolated LibratoMetrics tests? They're only separate for the time being. Some are really messy but I think that's a code smell coming from the reporter doing too much. |
lib/metriks/histogram.rb
Outdated
There was a problem hiding this comment.
I realized this code doesn't even need a hash. Would either of these be better than using a hash here?
report_snapshot = snapshot
block.call 'count', count
block.call 'min', min
block.call 'max', maxor
report_snapshot = snapshot
block['count', count]
block['min', min]
block['max', max]There was a problem hiding this comment.
Great idea. I like this a lot better than the unnecessary hash.
There was a problem hiding this comment.
This would also make it easier for Metrics to be composed of other Metrics. The parent would call #each on its children passing block instead of merging all responses into a single hash.
On that note, is there a reason why things like Histogram and Meter keep their own counts instead of delegating to an internal Counter?
There was a problem hiding this comment.
We're not doing anything special with block. Would this be cleaner?
yield 'count', count
yield 'min', min
yield 'max', max|
I think this is a great improvement. Should we make sure we include more of the snapshot in the list, too? |
|
Thanks for the feedback! Glad you approve of the direction. I wasn't sure how you'd take to all the mocking but I love testing against an abstraction instead of a concrete object. For example, I like that the What do you mean by including more of the snapshot in the list? |
There was a problem hiding this comment.
What do you think of this compromise, @eric? :only and :except have two higher level tests using string matchers for clarity and a third expectation test. The later defines the protocol for the matchers and asserts the report is sending the right messages. If the implementation changes from sending #=== to sending another message, the expectation test will fail. That's by design because it means that change may break clients coded against the original protocol.
There was a problem hiding this comment.
Is there anything that is better by doing this vs just passing in strings directly?
There was a problem hiding this comment.
The difference is writing an expectation to use #=== means it can't be changed to something like this without failing the mock test:
if matcher.is_a? Regexp
matcher =~ gauge[:name]
else
matcher == gauge[:name]
endThere was a problem hiding this comment.
I don't think it's useful to test the internal mechanics of how the reporter decides when to send stuff.
There was a problem hiding this comment.
I agree. That TODO is a placeholder to remind me that I hate that test.
|
@eric OK most of the big stuff is done. I'd like to get better full-blown integration tests and then combine them all. There's still duplication and interface inconsistencies that could be addressed at some point. |
|
The more I've thought about this, the more I've realized that it could be helpful to use some sort of "adapter" classes that could take a reporter and yield, for instance, a flat namespace of metric names to values. Another example adapter could report rate by storing and recording the difference in |
|
Omg, started doing exactly the same refactoring as you are doing here without checking open PRs first and notice yours now, when I wanted to open mine. Bummer. Let me know if I can help in any way with this 👍 |
There was a problem hiding this comment.
raise NotImplementedError maybe?
|
@lmarburger This looks pretty great! Left few suggestions in comments. |
|
I've been re-thinking the idea of having the reporters in this gem at all. Here's an example of the Librato Metrics reporter that has been extracted: |
|
I'm not convinced there's a lot of common logic that is worth encapsulating into a reporter base class or helper class so far. It's hard to standardize a lot of this, because the correct way to translate the metrics to be sent seems to be fairly different from one destination to the next. |
|
Actual sate yells for refactoring and having base reporter class. I've just implemented custom reporter and 90% of it is copypasted from librato metrics. The only difference are hash keys in It's true and I agree that many different reporters/destinations will format data differently but I don't think it'll hurt them if the base class will provide some convenience methods which they can use if they want, if not - the base won't add any burden. In most cases though (graphite, librato, riemann) it'll be quite the same and the only difference will be at the end of the process which is actually sending metrics. Regarding extracting reporters from this gem. Seems like a premature optimization and over kill for me 🙊 Those are only one-class implementations and we have only couple of them right now, the most demanded I'd say. Additonaly, I almost always use 3 of reporters at the time. The main one (graphite, librato, custom one) and proctitle on production and logger for development. I'd personally love to see this refactor finished and merged to master. I also offer my help in finishing it up 😸 |
|
The problem with having all of the reporters in this gem is that if a reporter has a dependency (like the library generally used to submit metrics to that service), it means that everyone who uses metriks will be pulling in that dependency, even if they don't use that reporter. Over time, that becomes a huge pain (especially if a given reporter needs a gem that has a compiled dependency). |
|
So far, I've found with the reporters that I have written, that many of them actually need the metric type to be able to know how to act on it. Having a simple |
There's a simple pattern used in many gems to overcome this: begin
require 'librato'
resuce LoadError
raise "You need to include `librato` gem in your gemfile if you want to use `Metriks::Reporter::Librato`"
end |
|
I agree that that can solve the problem, but it feels like a pretty dirty solution to me. You now have to manually start explaining versioning dependencies and checking for them, etc. Yuck. |
Feeling things out for now. @eric, do you have any thoughts on adding
#reportto meters? It's spiked onCounterandMeterso far.