Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

switch metrics to float64 #68

Merged
merged 1 commit into from
Mar 16, 2016
Merged

Conversation

teepark
Copy link
Contributor

@teepark teepark commented May 14, 2015

I was having trouble with go-statsd-client and realized the issue was server-side: timers are being parsed as uint64s, but decimal points are allowed. evidence

@markrechler
Copy link
Contributor

Thanks @teepark. Looks good. The Uint64Slice code can be removed. Since we are moving closer to the official statsd specs do you want to take a stab at supporting floats for all metric types?
https://github.com/b/statsd_spec

@ploxiln
Copy link
Contributor

ploxiln commented Nov 6, 2015

worth mentioning that @jsocol's pystatsd recently started sending floats for all timings (so I had to temporarily back down to pystatsd-3.1)

@ploxiln
Copy link
Contributor

ploxiln commented Jan 18, 2016

I agree that supporting floats is a good idea, but I don't think those "official statsd specs" support the idea:

The protocol allows for both integer and floating point values. Most implementations store values internally as a IEEE 754 double precision float, but many implementations and graphing systems only support integer values. For compatibility all values should be integers in the range (-2^53^, 2^53^)

@markrechler
Copy link
Contributor

@teepark This looks good. Can you rebase/squash off of master when you get a chance?

@ploxiln Agreed on the official docs indicating it's not fully supported/encouraged. Given that we only output to graphite at the moment which supports floats, this feels like an OK change.

@markrechler markrechler changed the title timers don't necessarily have to be ints, so support floats switch metrics to float64 Feb 24, 2016
@teepark
Copy link
Contributor Author

teepark commented Feb 24, 2016

@markrechler all rebased and squashed!

@@ -289,12 +289,12 @@ func processGauges(buffer *bytes.Buffer, now int64) int64 {

switch {
case hasChanged:
fmt.Fprintf(buffer, "%s %d %d\n", bucket, currentValue, now)
fmt.Fprintf(buffer, "%s %.0f %d\n", bucket, currentValue, now)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, with this PR, statsdaemon will still send integer values to graphite, even though statsdaemon will accept floats?

The most specific thing I can find in the official graphite documentation is that the Whisper backend stores doubles and can handle anything python's float() can parse: http://graphite.readthedocs.org/en/0.9.12/whisper.html#data-points

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. On re-read was wondering how the test values did not change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ugh, the documentation never even touched on that: http://graphite.readthedocs.org/en/0.9.12/feeding-carbon.html#the-plaintext-protocol

had to dig for a bit, but it looks like carbon parses it that way as well:
https://github.com/tmm1/graphite/blob/master/carbon/lib/carbon/protocols.py#L66

My goal was to accept floats from the statsd client, leaving the statsdaemon->graphite connection untouched. I'll change it to pass floats back to graphite, but one question: for float values that represent integers (as closely as they can), do we want to truncate to the integer in the protocol (it's a pretty verbose integer now for the most common case http://play.golang.org/p/AA1ku5wkDF)? And if so, what should that test look like?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd vote for not truncating and accepting the increased verbosity. Feels like it will be cleaner not having to have a truncate case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually looks like it's a moot point -- we can format them all with strconv.FormatFloat(n, 'f', -1, 64) which includes the minimum number of decimal places to represent it exactly (and appears to omit the decimal point entirely for integers).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strconv.FormatFloat() looks great - I was a bit worried initially about avoiding exponent notations that would be printed and parsed differently by go and python, and FormatFloat() seems to do exactly what we want

+ timers
+ guages
+ counters

Also pass values back to graphite as formatted floats.
@@ -289,12 +289,12 @@ func processGauges(buffer *bytes.Buffer, now int64) int64 {

switch {
case hasChanged:
fmt.Fprintf(buffer, "%s %d %d\n", bucket, currentValue, now)
fmt.Fprintf(buffer, "%s %s %d\n", bucket, strconv.FormatFloat(currentValue, 'f', -1, 64), now)
lastGaugeValue[bucket] = currentValue
gauges[bucket] = math.MaxUint64
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes look good. This is more of a nitpick for consistency, would you mind changing this to MaxFloat64? @ploxiln also had a good suggestion in #71 for refactoring gauges + lastGaugeValue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants