Prevents event.sprintf from converting floats to sci notation

This allows sprintf to correctly print floats up to 15 decimal
places, which should be enough for most. Without this, very big
or very small floats will be converted to scientific notation.

closes #1670
This commit is contained in:
Joao Duarte 2014-09-04 15:03:38 +01:00
parent 6096d3013d
commit 277a890451
3 changed files with 100 additions and 4 deletions

View file

@ -48,6 +48,11 @@ class LogStash::Event
TIMESTAMP_FAILURE_TAG = "_timestampparsefailure"
TIMESTAMP_FAILURE_FIELD = "_@timestamp"
# Floats outside of these upper and lower bounds are forcibly converted
# to scientific notation by Float#to_s
MIN_FLOAT_BEFORE_SCI_NOT = 0.0001
MAX_FLOAT_BEFORE_SCI_NOT = 1000000000000000.0
public
def initialize(data = {})
@logger = Cabin::Channel.get(LogStash)
@ -192,7 +197,12 @@ class LogStash::Event
# is an array (or hash?) should be. Join by comma? Something else?
public
def sprintf(format)
format = format.to_s
if format.is_a?(Float) and
(format < MIN_FLOAT_BEFORE_SCI_NOT or format >= MAX_FLOAT_BEFORE_SCI_NOT) then
format = ("%.15f" % format).sub(/0*$/,"")
else
format = format.to_s
end
if format.index("%").nil?
return format
end

View file

@ -95,11 +95,11 @@ class LogStash::Outputs::Statsd < LogStash::Outputs::Base
end
@count.each do |metric, val|
@client.count(build_stat(event.sprintf(metric), sender),
event.sprintf(val).to_f, @sample_rate)
event.sprintf(val), @sample_rate)
end
@timing.each do |metric, val|
@client.timing(build_stat(event.sprintf(metric), sender),
event.sprintf(val).to_f, @sample_rate)
event.sprintf(val), @sample_rate)
end
@set.each do |metric, val|
@client.set(build_stat(event.sprintf(metric), sender),
@ -107,7 +107,7 @@ class LogStash::Outputs::Statsd < LogStash::Outputs::Base
end
@gauge.each do |metric, val|
@client.gauge(build_stat(event.sprintf(metric), sender),
event.sprintf(val).to_f, @sample_rate)
event.sprintf(val), @sample_rate)
end
end # def receive

86
spec/outputs/statsd.rb Normal file
View file

@ -0,0 +1,86 @@
require "test_utils"
require "logstash/outputs/statsd"
require "mocha/api"
require "socket"
describe LogStash::Outputs::Statsd do
extend LogStash::RSpec
port = 4399
udp_server = UDPSocket.new
udp_server.bind("127.0.0.1", port)
describe "send metric to statsd" do
config <<-CONFIG
input {
generator {
message => "valid"
count => 1
}
}
output {
statsd {
host => "localhost"
sender => "spec"
port => #{port}
count => [ "test.valid", "0.1" ]
}
}
CONFIG
agent do
metric, *data = udp_server.recvfrom(100)
insist { metric } == "logstash.spec.test.valid:0.1|c"
end
end
describe "output a very small float" do
config <<-CONFIG
input {
generator {
message => "valid"
count => 1
}
}
output {
statsd {
host => "localhost"
sender => "spec"
port => #{port}
count => [ "test.valid", 0.000001 ]
}
}
CONFIG
agent do
metric, *data = udp_server.recvfrom(100)
insist { metric } == "logstash.spec.test.valid:0.000001|c"
end
end
describe "output a very big float" do
config <<-CONFIG
input {
generator {
message => "valid"
count => 1
}
}
output {
statsd {
host => "localhost"
sender => "spec"
port => #{port}
count => [ "test.valid", 9999999999999.01 ]
}
}
CONFIG
agent do
metric, *data = udp_server.recvfrom(100)
insist { metric } == "logstash.spec.test.valid:9999999999999.01|c"
end
end
end