rrd_rest_api 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/rrd_repo.rb +97 -0
- data/server.rb +36 -3
- metadata +3 -3
- data/lib/rrd_query.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0bcb45d62b3521655a92b06314bc6a9ea551f1f9
|
4
|
+
data.tar.gz: bdc45d4f92e258f117386fd8e89e730dc40b1c3b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 026c76a12ed4114c96b73c64a674a3d038db949746f0522e8a24111afc712d55fa76fa30c97614f4ccf116a33043478f87231b96a57ae5d4bb23a1e0a5860b6a
|
7
|
+
data.tar.gz: e557e453ee8466052c333b60f7c33d3ffefea5e50586ccf86e550b5a8d5059897f629392ad3df8b54743397916234ffef69c52d0de57f0379e33b454b64864a5
|
data/lib/rrd_repo.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'rrd'
|
2
|
+
|
3
|
+
class RRDRepo
|
4
|
+
attr_reader :filename
|
5
|
+
|
6
|
+
def self.create(filename, datasources, start = Time.now)
|
7
|
+
one_day = 60 * 60 * 24
|
8
|
+
|
9
|
+
rrd = RRD::Base.new(filename)
|
10
|
+
rrd.create(:start => start, :step => 60) do
|
11
|
+
datasources.each do |name|
|
12
|
+
datasource name, :type => :gauge, :heartbeat => 120, :min => 0, :max => :unlimited
|
13
|
+
end
|
14
|
+
archive :average, :every => 60, :during => one_day
|
15
|
+
archive :average, :every => 300, :during => one_day
|
16
|
+
end
|
17
|
+
RRDRepo.new(filename)
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(filename)
|
21
|
+
@filename = filename
|
22
|
+
end
|
23
|
+
|
24
|
+
def latest_value(datasource)
|
25
|
+
_rrd.info["ds[#{datasource}].last_ds"].to_f
|
26
|
+
end
|
27
|
+
|
28
|
+
def info
|
29
|
+
info = _rrd.info
|
30
|
+
archives = unflatten_archives(info)
|
31
|
+
{
|
32
|
+
:step => info["step"],
|
33
|
+
:archives => archives.map do |archive|
|
34
|
+
{
|
35
|
+
:consolidation_function => archive["cf"],
|
36
|
+
:resolution_sec => info["step"] * archive["pdp_per_row"],
|
37
|
+
:duration_sec => info["step"] * archive["pdp_per_row"] * archive["rows"]
|
38
|
+
}
|
39
|
+
end
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def read(resolution, start_ts, end_ts, function = :average)
|
44
|
+
start_time = (start_ts.to_i / resolution) * resolution
|
45
|
+
end_time = (end_ts.to_i / resolution) * resolution
|
46
|
+
data = _rrd.fetch(
|
47
|
+
function,
|
48
|
+
:resolution => resolution,
|
49
|
+
:start => start_time,
|
50
|
+
:end => end_time
|
51
|
+
)
|
52
|
+
header, values = data.first, data[1..-1]
|
53
|
+
nan_filtered = values.reject { |v| v[1..-1].any?(&:nan?) }
|
54
|
+
nan_filtered.map { |v| Hash[header.zip(v)] }
|
55
|
+
end
|
56
|
+
|
57
|
+
def write(time, values = [])
|
58
|
+
_rrd.update(time, *values)
|
59
|
+
end
|
60
|
+
|
61
|
+
def _rrd
|
62
|
+
raise("Unable to open RRD, because it doesn't exist: #{@filename}") unless File.exist?(@filename)
|
63
|
+
@rrd ||= RRD::Base.new(@filename)
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
# Takes a flat hash output from an rrd "info" call and unflattens
|
69
|
+
# it by each archive.
|
70
|
+
#
|
71
|
+
# Input:
|
72
|
+
# {
|
73
|
+
# "rra[0].pdp_per_row"=>1,
|
74
|
+
# "rra[0].xff"=>0.5,
|
75
|
+
# "rra[1].pdp_per_row"=>168,
|
76
|
+
# "rra[1].xff"=>0.5,
|
77
|
+
# ...
|
78
|
+
# }
|
79
|
+
#
|
80
|
+
# Output:
|
81
|
+
# [
|
82
|
+
# {
|
83
|
+
# "pdp_per_row"=>1,
|
84
|
+
# "xff" => 0.5,
|
85
|
+
# },
|
86
|
+
# {
|
87
|
+
# "pdp_per_row" => 168,
|
88
|
+
# "xff" => 0.5
|
89
|
+
# }
|
90
|
+
# ]
|
91
|
+
def unflatten_archives(info)
|
92
|
+
info.select { |key, value| key.index("rra") == 0 }
|
93
|
+
.group_by { |elem| elem[0].split('.')[0] }
|
94
|
+
.sort_by { |rra, _| rra }
|
95
|
+
.map { |rra, values| Hash[values.map { |key, val| [key.split('.')[1], val] }] }
|
96
|
+
end
|
97
|
+
end
|
data/server.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
+
require 'json'
|
1
2
|
require 'sinatra'
|
2
3
|
require 'yaml'
|
3
|
-
require File.expand_path(File.dirname(__FILE__) + "/lib/
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + "/lib/rrd_repo")
|
4
5
|
|
5
6
|
configure :production do
|
6
7
|
set :port, 5678
|
@@ -16,8 +17,40 @@ get '/data/:file/latest/sum' do |file|
|
|
16
17
|
end
|
17
18
|
|
18
19
|
filename = _allowed_rrds[file]
|
19
|
-
|
20
|
-
|
20
|
+
rrd_repo = RRDRepo.new(filename)
|
21
|
+
rrd_repo.latest_value("sum").to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
get '/data/:file/read/' do |file|
|
25
|
+
unless _allowed_rrds.has_key?(file)
|
26
|
+
return 404
|
27
|
+
end
|
28
|
+
|
29
|
+
if params[:resolution].nil?
|
30
|
+
status 400
|
31
|
+
body "You must provide a 'resolution' query param in seconds"
|
32
|
+
return
|
33
|
+
end
|
34
|
+
|
35
|
+
if params[:duration].nil?
|
36
|
+
status 400
|
37
|
+
body "You must provide a 'duration' query param in seconds"
|
38
|
+
return
|
39
|
+
end
|
40
|
+
|
41
|
+
filename = _allowed_rrds[file]
|
42
|
+
rrd_repo = RRDRepo.new(filename)
|
43
|
+
info = rrd_repo.info
|
44
|
+
response.headers["X-RRD"] = "step=#{info[:step]}"
|
45
|
+
info[:archives].each_with_index do |archive, i|
|
46
|
+
response.headers["X-RRD-Archive#{i}"] = "cf=#{archive[:consolidation_function]}; resolution=#{archive[:resolution_sec]}; duration=#{archive[:duration_sec]}"
|
47
|
+
end
|
48
|
+
|
49
|
+
res = params[:resolution].to_i
|
50
|
+
dur = params[:duration].to_i
|
51
|
+
stop = Time.now
|
52
|
+
start = stop - dur
|
53
|
+
JSON.dump(rrd_repo.read(res, start, stop))
|
21
54
|
end
|
22
55
|
|
23
56
|
def _allowed_rrds
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rrd_rest_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- TempoIQ Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sinatra
|
@@ -47,7 +47,7 @@ extensions: []
|
|
47
47
|
extra_rdoc_files: []
|
48
48
|
files:
|
49
49
|
- config.ru
|
50
|
-
- lib/
|
50
|
+
- lib/rrd_repo.rb
|
51
51
|
- public/.gitemptydir
|
52
52
|
- server.rb
|
53
53
|
- tmp/.gitemptydir
|
data/lib/rrd_query.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'rrd'
|
2
|
-
|
3
|
-
class RRDQuery
|
4
|
-
attr_reader :filename
|
5
|
-
|
6
|
-
def initialize(filename)
|
7
|
-
@filename = filename
|
8
|
-
end
|
9
|
-
|
10
|
-
def latest_value(datasource)
|
11
|
-
_rrd.info["ds[#{datasource}].last_ds"].to_f
|
12
|
-
end
|
13
|
-
|
14
|
-
def _rrd
|
15
|
-
raise("Unable to open RRD, because it doesn't exist: #{@filename}") unless File.exist?(@filename)
|
16
|
-
@rrd ||= RRD::Base.new(@filename)
|
17
|
-
end
|
18
|
-
end
|