-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
161 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require "linr/encoder/line" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
module Linr | ||
module Encoder | ||
# Encodes data entry into the InfluxDB line format. | ||
# @see https://influxdb.com/docs/v0.9/write_protocols/write_syntax.html | ||
# @example Encode a data series | ||
# Line.new.dump(Data.new(measurement: "series", fields: { a: 0.5 })) | ||
class Line | ||
# Encodes data into the line syntax | ||
# @param data [Data] | ||
# @return [String] | ||
def dump(data) | ||
[ | ||
dump_measurement(data.measurement), | ||
dump_tags(data.tags), | ||
dump_fields(data.fields), | ||
dump_timestamp(data.timestamp) | ||
].compact.join | ||
end | ||
|
||
private | ||
|
||
def dump_measurement(measurement) | ||
escape_key(measurement) | ||
end | ||
|
||
def dump_tags(tags) | ||
dump_collection(tags, ",") do |key, value| | ||
"#{escape_key(key)}=#{escape_value(value)}" | ||
end | ||
end | ||
|
||
def dump_fields(fields) | ||
dump_collection(fields) do |key, value| | ||
"#{escape_key(key)}=#{encode_field_value(value)}" | ||
end | ||
end | ||
|
||
def dump_timestamp(timestamp) | ||
" #{timestamp}" if timestamp | ||
end | ||
|
||
def dump_collection(data, prefix = " ", &block) | ||
return unless data && !data.empty? | ||
prefix + data.map(&block).join(",") | ||
end | ||
|
||
def encode_field_value(value) | ||
case value | ||
when Numeric | ||
encode_numberic(value) | ||
when TrueClass, FalseClass | ||
value.to_s | ||
else | ||
escape_qoute(escape_value(value)) | ||
end | ||
end | ||
|
||
def encode_numberic(value) | ||
"#{value}i" if value.is_a?(Fixnum) | ||
value | ||
end | ||
|
||
def escape_value(input) | ||
input.to_s | ||
.gsub(/\s/, '\ ') | ||
.gsub(",", '\,') | ||
.gsub('"', '\"') | ||
end | ||
|
||
def escape_qoute(input) | ||
%("#{input}") | ||
end | ||
|
||
def escape_key(input) | ||
input.to_s | ||
.gsub(/\s/, '\ ') | ||
.gsub(",", '\,') | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
require "spec_helper" | ||
|
||
describe ::Linr::Encoder::Line do | ||
subject { ::Linr::Encoder::Line.new } | ||
let(:data) { ::Linr::Data.new(source) } | ||
let(:output) { subject.dump(data) } | ||
|
||
describe "whitespace" do | ||
let(:source) do | ||
{ | ||
measurement: "A test measurement", | ||
fields: { "some long field" => 5 }, | ||
tags: { "some tag" => "with whitespace" }, | ||
timestamp: 123_456_789 | ||
} | ||
end | ||
|
||
it "escapes" do | ||
expected = 'A\ test\ measurement' | ||
expected << ',some\ tag=with\ whitespace' | ||
expected << ' some\ long\ field=5' | ||
expected << " 123456789" | ||
output.must_equal expected | ||
end | ||
end | ||
|
||
describe "commas" do | ||
let(:source) do | ||
{ | ||
measurement: "A,test,measurement", | ||
fields: { "some,long,field" => 5 }, | ||
tags: { "some,tag" => "with,comma" }, | ||
timestamp: 123_456_789 | ||
} | ||
end | ||
|
||
it "escapes" do | ||
expected = 'A\,test\,measurement' | ||
expected << ',some\,tag=with\,comma' | ||
expected << ' some\,long\,field=5' | ||
expected << " 123456789" | ||
output.must_equal expected | ||
end | ||
end | ||
|
||
describe "minimum data" do | ||
let(:source) do | ||
{ | ||
measurement: "series", | ||
fields: { "field" => 0.51 } | ||
} | ||
end | ||
|
||
it "dumps" do | ||
output.must_equal "series field=0.51" | ||
end | ||
end | ||
|
||
describe "complex data types" do | ||
let(:source) do | ||
{ | ||
measurement: "series", | ||
fields: { A: true, B: false, C: 'A"B' } | ||
} | ||
end | ||
|
||
it "dumps" do | ||
output.must_equal 'series A=true,B=false,C="A\"B"' | ||
end | ||
end | ||
end |