prrd 0.2.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 +7 -0
- data/Gemfile +13 -0
- data/README.md +223 -0
- data/Rakefile +35 -0
- data/lib/prrd.rb +189 -0
- data/lib/prrd/database.rb +107 -0
- data/lib/prrd/database/archive.rb +39 -0
- data/lib/prrd/database/datasource.rb +40 -0
- data/lib/prrd/graph.rb +143 -0
- data/lib/prrd/graph/area.rb +50 -0
- data/lib/prrd/graph/colors.rb +28 -0
- data/lib/prrd/graph/comment.rb +29 -0
- data/lib/prrd/graph/definition.rb +47 -0
- data/lib/prrd/graph/hrule.rb +53 -0
- data/lib/prrd/graph/line.rb +53 -0
- data/lib/prrd/graph/print.rb +48 -0
- data/lib/prrd/graph/shift.rb +30 -0
- data/lib/prrd/graph/textalign.rb +32 -0
- data/lib/prrd/graph/vrule.rb +51 -0
- data/prrd.gemspec +23 -0
- data/showcase.rb +104 -0
- data/spec/prrd_spec.rb +15 -0
- metadata +65 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# File: database.rb
|
|
2
|
+
# Time-stamp: <2014-10-01 21:26:05 pierre>
|
|
3
|
+
# Copyright (C) 2014 Pierre Lecocq
|
|
4
|
+
# Description: Database class for PRRD
|
|
5
|
+
|
|
6
|
+
module PRRD
|
|
7
|
+
# PRRD Database class
|
|
8
|
+
class Database
|
|
9
|
+
# Accessors
|
|
10
|
+
attr_accessor :path
|
|
11
|
+
attr_accessor :start, :step
|
|
12
|
+
attr_accessor :datasources, :archives
|
|
13
|
+
|
|
14
|
+
# Constructor
|
|
15
|
+
def initialize(values = nil)
|
|
16
|
+
@datasources = []
|
|
17
|
+
@archives = []
|
|
18
|
+
@start = Time.now.to_i - 86_400
|
|
19
|
+
@step = 300
|
|
20
|
+
|
|
21
|
+
unless values.nil?
|
|
22
|
+
values.each do |k, v|
|
|
23
|
+
m = "#{k}=".to_sym
|
|
24
|
+
next unless respond_to? m
|
|
25
|
+
send m, v
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Does database file exist?
|
|
31
|
+
def exists?
|
|
32
|
+
File.exist? @path
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Check database existence
|
|
36
|
+
def check_file
|
|
37
|
+
fail 'Database path is missing' if @path.nil? || !exists?
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Add a datasource object
|
|
41
|
+
# @param datasource [PRRD::Database::Datasource]
|
|
42
|
+
def add_datasource(datasource)
|
|
43
|
+
@datasources << datasource
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Add datasource objects
|
|
47
|
+
# @param datasource [Array]
|
|
48
|
+
def add_datasources(datasources)
|
|
49
|
+
@datasources = datasources
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Add an archive object
|
|
53
|
+
# @param archive [PRRD::Database::Archive]
|
|
54
|
+
def add_archive(archive)
|
|
55
|
+
@archives << archive
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Add archive objects
|
|
59
|
+
# @param archives [Array]
|
|
60
|
+
def add_archives(archives)
|
|
61
|
+
@archives = archives
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Add an object
|
|
65
|
+
# @param object [Object]
|
|
66
|
+
def <<(object)
|
|
67
|
+
if object.is_a? PRRD::Database::Datasource
|
|
68
|
+
add_datasource object
|
|
69
|
+
elsif object.is_a? PRRD::Database::Archive
|
|
70
|
+
add_archive object
|
|
71
|
+
else
|
|
72
|
+
fail 'Can not add this kind of object in PRRD::Database'
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Create a database
|
|
77
|
+
# @return [String]
|
|
78
|
+
def create
|
|
79
|
+
File.write @path, ''
|
|
80
|
+
|
|
81
|
+
cmd = []
|
|
82
|
+
cmd << "#{PRRD.bin} create #{@path}"
|
|
83
|
+
cmd << "--start #{@start} --step #{@step}"
|
|
84
|
+
|
|
85
|
+
fail 'Datasources are missing' if @datasources.empty?
|
|
86
|
+
@datasources.map { |e| cmd << e.to_s }
|
|
87
|
+
|
|
88
|
+
fail 'Archives are missing' if @archives.empty?
|
|
89
|
+
@archives.map { |e| cmd << e.to_s }
|
|
90
|
+
|
|
91
|
+
# Execute
|
|
92
|
+
PRRD.execute cmd.join ' '
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Update a database
|
|
96
|
+
# @param timestamp [Integer]
|
|
97
|
+
# @param values [Array]
|
|
98
|
+
# @return [String]
|
|
99
|
+
def update(timestamp = nil, *values)
|
|
100
|
+
check_file
|
|
101
|
+
timestamp ||= Time.now.to_i
|
|
102
|
+
|
|
103
|
+
# Execute
|
|
104
|
+
PRRD.execute "#{PRRD.bin} update #{@path} #{timestamp}:#{values.join ':'}"
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# File: archive.rb
|
|
2
|
+
# Time-stamp: <2014-09-30 00:04:06 pierre>
|
|
3
|
+
# Copyright (C) 2014 Pierre Lecocq
|
|
4
|
+
# Description: Archive class for PRRD
|
|
5
|
+
|
|
6
|
+
module PRRD
|
|
7
|
+
class Database
|
|
8
|
+
# PRRD Database Archive class
|
|
9
|
+
class Archive < PRRD::Entity
|
|
10
|
+
# Constructor
|
|
11
|
+
def initialize(values = nil)
|
|
12
|
+
@keys = [
|
|
13
|
+
:cf,
|
|
14
|
+
:xff,
|
|
15
|
+
:steps,
|
|
16
|
+
:rows
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
super values
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Transform to a RRA formatted string
|
|
23
|
+
def to_s
|
|
24
|
+
fail 'Empty archive object' if @data.empty?
|
|
25
|
+
|
|
26
|
+
validate_presence :cf, :xff, :steps, :rows
|
|
27
|
+
|
|
28
|
+
chunks = ['RRA']
|
|
29
|
+
|
|
30
|
+
@keys.each do |k|
|
|
31
|
+
next unless @data.key?(k)
|
|
32
|
+
chunks << @data[k]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
chunks.join ':'
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# File: datasource.rb
|
|
2
|
+
# Time-stamp: <2014-09-30 00:04:37 pierre>
|
|
3
|
+
# Copyright (C) 2014 Pierre Lecocq
|
|
4
|
+
# Description: Datasource class for PRRD
|
|
5
|
+
|
|
6
|
+
module PRRD
|
|
7
|
+
class Database
|
|
8
|
+
# PRRD Database Datasource class
|
|
9
|
+
class Datasource < PRRD::Entity
|
|
10
|
+
# Constructor
|
|
11
|
+
def initialize(values = nil)
|
|
12
|
+
@keys = [
|
|
13
|
+
:name,
|
|
14
|
+
:type,
|
|
15
|
+
:heartbeat,
|
|
16
|
+
:min,
|
|
17
|
+
:max
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
super values
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Transform to a DS formatted string
|
|
24
|
+
def to_s
|
|
25
|
+
fail 'Empty datasource object' if @data.empty?
|
|
26
|
+
|
|
27
|
+
validate_presence :name, :type, :heartbeat, :min, :max
|
|
28
|
+
|
|
29
|
+
chunks = ['DS']
|
|
30
|
+
|
|
31
|
+
@keys.each do |k|
|
|
32
|
+
next unless @data.key?(k)
|
|
33
|
+
chunks << @data[k]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
chunks.join ':'
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
data/lib/prrd/graph.rb
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# File: graph.rb
|
|
2
|
+
# Time-stamp: <2014-10-01 21:26:29 pierre>
|
|
3
|
+
# Copyright (C) 2014 Pierre Lecocq
|
|
4
|
+
# Description: Graph class for PRRD
|
|
5
|
+
|
|
6
|
+
module PRRD
|
|
7
|
+
# PRRD Graph class
|
|
8
|
+
class Graph
|
|
9
|
+
# Accessors
|
|
10
|
+
attr_accessor :path, :database
|
|
11
|
+
|
|
12
|
+
attr_accessor :start, :end, :step
|
|
13
|
+
attr_accessor :title, :vertical_label
|
|
14
|
+
attr_accessor :width, :height, :only_graph, :full_size_mode
|
|
15
|
+
attr_accessor :lower_limit, :upper_limit, :rigid
|
|
16
|
+
attr_accessor :no_legend, :legend_position, :legend_direction
|
|
17
|
+
attr_accessor :base, :border, :zoom, :imgformat, :watermark
|
|
18
|
+
attr_accessor :entities
|
|
19
|
+
|
|
20
|
+
# Constructor
|
|
21
|
+
def initialize(values = nil)
|
|
22
|
+
@entities = {
|
|
23
|
+
colors: [],
|
|
24
|
+
definitions: [],
|
|
25
|
+
areas: [],
|
|
26
|
+
lines: [],
|
|
27
|
+
prints: [],
|
|
28
|
+
comments: [],
|
|
29
|
+
hrules: [],
|
|
30
|
+
vrules: [],
|
|
31
|
+
shift: [],
|
|
32
|
+
textalign: []
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
unless values.nil?
|
|
36
|
+
values.each do |k, v|
|
|
37
|
+
m = "#{k}=".to_sym
|
|
38
|
+
next unless respond_to? m
|
|
39
|
+
send m, v
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Check image existence
|
|
45
|
+
def check_file
|
|
46
|
+
fail 'Image path is missing' if @path.nil?
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Check database existence
|
|
50
|
+
def check_database
|
|
51
|
+
fail 'No database provided' if @database.nil?
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def method_missing(m, *args, &block)
|
|
55
|
+
entities = @entities.keys.map(&:to_s) + @entities.keys.map! { |e| e.to_s[0..-2] }
|
|
56
|
+
ms = m.to_s.gsub 'add_', ''
|
|
57
|
+
if entities.include? ms
|
|
58
|
+
if ms[-1] == 's'
|
|
59
|
+
@entities[ms.to_sym] = args[0]
|
|
60
|
+
else
|
|
61
|
+
@entities["#{ms}s".to_sym] << args[0]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
return true
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
super
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Add an object
|
|
71
|
+
# @param object [Object]
|
|
72
|
+
def <<(object)
|
|
73
|
+
if object.is_a? PRRD::Graph::Definition
|
|
74
|
+
@entities[:definitions] << object
|
|
75
|
+
elsif object.is_a? PRRD::Graph::Color
|
|
76
|
+
@entities[:colors] << object
|
|
77
|
+
elsif object.is_a? PRRD::Graph::Area
|
|
78
|
+
@entities[:areas] << object
|
|
79
|
+
elsif object.is_a? PRRD::Graph::Line
|
|
80
|
+
@entities[:lines] << object
|
|
81
|
+
elsif object.is_a? PRRD::Graph::Print
|
|
82
|
+
@entities[:prints] << object
|
|
83
|
+
elsif object.is_a? PRRD::Graph::Comment
|
|
84
|
+
@entities[:comments] << object
|
|
85
|
+
elsif object.is_a? PRRD::Graph::Hrule
|
|
86
|
+
@entities[:hrules] << object
|
|
87
|
+
elsif object.is_a? PRRD::Graph::Vrule
|
|
88
|
+
@entities[:vrules] << object
|
|
89
|
+
elsif object.is_a? PRRD::Graph::Shift
|
|
90
|
+
@entities[:shift] << object
|
|
91
|
+
elsif object.is_a? PRRD::Graph::Textalign
|
|
92
|
+
@entities[:textalign] << object
|
|
93
|
+
else
|
|
94
|
+
fail 'Can not add this kind of object in PRRD::Graph'
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Generate a graph
|
|
99
|
+
# @return [String]
|
|
100
|
+
def generate
|
|
101
|
+
check_file
|
|
102
|
+
check_database
|
|
103
|
+
|
|
104
|
+
fail 'Definitions are missing' if @entities[:definitions].empty?
|
|
105
|
+
|
|
106
|
+
cmd = []
|
|
107
|
+
|
|
108
|
+
cmd << "#{PRRD.bin} graph #{@path}"
|
|
109
|
+
|
|
110
|
+
cmd << "--start=#{@start}" unless @start.nil?
|
|
111
|
+
cmd << "--end=#{@end}" unless @end.nil?
|
|
112
|
+
cmd << "--step=#{@step}" unless @step.nil?
|
|
113
|
+
|
|
114
|
+
cmd << "--title=\"#{@title}\"" unless @title.nil?
|
|
115
|
+
cmd << "--vertical-label=\"#{@vertical_label}\"" unless @vertical_label.nil?
|
|
116
|
+
cmd << "--width=#{@width}" unless @width.nil?
|
|
117
|
+
cmd << "--height=#{@height}" unless @height.nil?
|
|
118
|
+
cmd << '--only-graph' unless @only_graph.nil?
|
|
119
|
+
cmd << '--full-size-mode' unless @full_size_mode.nil?
|
|
120
|
+
cmd << "--lower-limit=#{@lower_limit}" unless @lower_limit.nil?
|
|
121
|
+
cmd << "--upper-limit=#{@upper_limit}" unless @upper_limit.nil?
|
|
122
|
+
cmd << '--rigid' unless @rigid.nil?
|
|
123
|
+
cmd << "--no-legend" unless @no_legend.nil?
|
|
124
|
+
cmd << "--legend-position=\"#{@legend_position}\"" unless @legend_position.nil?
|
|
125
|
+
cmd << "--legend-direction=\"#{@legend_direction}\"" unless @legend_direction.nil?
|
|
126
|
+
cmd << "--base=#{@base}" unless @base.nil?
|
|
127
|
+
cmd << "--border=#{@border}" unless @border.nil?
|
|
128
|
+
cmd << "--zoom=#{@zoom}" unless @zoom.nil?
|
|
129
|
+
cmd << "--imgformat=\"#{@imgformat}\"" unless @imgformat.nil?
|
|
130
|
+
cmd << "--watermark=\"#{@watermark}\"" unless @watermark.nil?
|
|
131
|
+
|
|
132
|
+
@entities.each do |k, v|
|
|
133
|
+
next if v.empty?
|
|
134
|
+
v.each do |e|
|
|
135
|
+
cmd << e.to_s
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Exectute
|
|
140
|
+
PRRD.execute cmd.join ' '
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# File: area.rb
|
|
2
|
+
# Time-stamp: <2014-10-01 20:31:25 pierre>
|
|
3
|
+
# Copyright (C) 2014 Pierre Lecocq
|
|
4
|
+
# Description: Area class for PRRD
|
|
5
|
+
|
|
6
|
+
module PRRD
|
|
7
|
+
class Graph
|
|
8
|
+
# PRRD Graph Area class
|
|
9
|
+
class Area < PRRD::Entity
|
|
10
|
+
# Constructor
|
|
11
|
+
def initialize(values = nil)
|
|
12
|
+
@keys = [
|
|
13
|
+
:value,
|
|
14
|
+
:color,
|
|
15
|
+
:legend,
|
|
16
|
+
:stack
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
super values
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Transform to a AREA formatted string
|
|
23
|
+
def to_s
|
|
24
|
+
fail 'Empty area object' if @data.empty?
|
|
25
|
+
|
|
26
|
+
validate_presence :value
|
|
27
|
+
|
|
28
|
+
chunks = []
|
|
29
|
+
|
|
30
|
+
@keys.each do |k|
|
|
31
|
+
next unless @data.key?(k)
|
|
32
|
+
case k
|
|
33
|
+
when :value
|
|
34
|
+
chunks << "AREA:%s%s" % [@data[k], @data[:color]]
|
|
35
|
+
when :legend
|
|
36
|
+
chunks << "\"%s\"" % @data[k]
|
|
37
|
+
when :stack
|
|
38
|
+
chunks << "STACK"
|
|
39
|
+
when :color
|
|
40
|
+
# nope
|
|
41
|
+
else
|
|
42
|
+
chunks << @data[k]
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
chunks.join ':'
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# File: color.rb
|
|
2
|
+
# Time-stamp: <2014-10-01 20:31:49 pierre>
|
|
3
|
+
# Copyright (C) 2014 Pierre Lecocq
|
|
4
|
+
# Description: Color class for PRRD
|
|
5
|
+
|
|
6
|
+
module PRRD
|
|
7
|
+
class Graph
|
|
8
|
+
# PRRD Graph Color class
|
|
9
|
+
class Color < PRRD::Entity
|
|
10
|
+
# Constructor
|
|
11
|
+
def initialize(values = nil)
|
|
12
|
+
@keys = [
|
|
13
|
+
:colortag,
|
|
14
|
+
:color
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
super values
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Transform to a COLOR formatted string
|
|
21
|
+
def to_s
|
|
22
|
+
fail 'Empty color object' if @data.empty?
|
|
23
|
+
|
|
24
|
+
"--color %s%s " % [@data[:colortag], @data[:color]]
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# File: comment.rb
|
|
2
|
+
# Time-stamp: <2014-10-01 20:32:12 pierre>
|
|
3
|
+
# Copyright (C) 2014 Pierre Lecocq
|
|
4
|
+
# Description: Comment class for PRRD
|
|
5
|
+
|
|
6
|
+
module PRRD
|
|
7
|
+
class Graph
|
|
8
|
+
# PRRD Comment Line class
|
|
9
|
+
class Comment < PRRD::Entity
|
|
10
|
+
# Constructor
|
|
11
|
+
def initialize(values = nil)
|
|
12
|
+
@keys = [
|
|
13
|
+
:text
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
super values
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Transform to a COMMENT formatted string
|
|
20
|
+
def to_s
|
|
21
|
+
fail 'Empty comment object' if @data.empty?
|
|
22
|
+
|
|
23
|
+
validate_presence :text
|
|
24
|
+
|
|
25
|
+
"COMMENT:\"%s\"" % @data[:text]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# File: definition.rb
|
|
2
|
+
# Time-stamp: <2014-10-01 21:14:18 pierre>
|
|
3
|
+
# Copyright (C) 2014 Pierre Lecocq
|
|
4
|
+
# Description: Definition class for PRRD
|
|
5
|
+
|
|
6
|
+
module PRRD
|
|
7
|
+
class Graph
|
|
8
|
+
# PRRD Graph Definition class
|
|
9
|
+
class Definition < PRRD::Entity
|
|
10
|
+
# Constructor
|
|
11
|
+
def initialize(values = nil)
|
|
12
|
+
@keys = [
|
|
13
|
+
:vname,
|
|
14
|
+
:rrdfile,
|
|
15
|
+
:ds_name,
|
|
16
|
+
:cf,
|
|
17
|
+
:step,
|
|
18
|
+
:start,
|
|
19
|
+
:end
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
super values
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Transform to a DEF formatted string
|
|
26
|
+
def to_s
|
|
27
|
+
fail 'Empty definition object' if @data.empty?
|
|
28
|
+
|
|
29
|
+
chunks = []
|
|
30
|
+
|
|
31
|
+
@keys.each do |k|
|
|
32
|
+
next unless @data.key?(k)
|
|
33
|
+
case k
|
|
34
|
+
when :vname
|
|
35
|
+
chunks << "DEF:%s=%s" % [@data[k], @data[:rrdfile]]
|
|
36
|
+
when :rrdfile
|
|
37
|
+
# nope
|
|
38
|
+
else
|
|
39
|
+
chunks << @data[k]
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
chunks.join ':'
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|