auxesis-RubyRRDtool 0.6.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.
- data/Manifest.txt +9 -0
- data/README +67 -0
- data/Rakefile +38 -0
- data/examples/function_test.rb +134 -0
- data/examples/minmax.rb +60 -0
- data/extconf.rb +30 -0
- data/rrd_info.h +47 -0
- data/rrdtool_main.c +260 -0
- data/test/test_rrdtool.rb +172 -0
- metadata +72 -0
data/Manifest.txt
ADDED
data/README
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# README -- ruby librrd bindings
|
2
|
+
|
3
|
+
Authors: David Bacher <drbacher at alum.mit.edu>
|
4
|
+
Mark Probert <probertm at acm.org>
|
5
|
+
based on work by Miles Egan <miles at caddr.com>
|
6
|
+
|
7
|
+
|
8
|
+
== Introduction
|
9
|
+
|
10
|
+
rubyrrdtool provides ruby bindings for RRD functions (via librrd), with
|
11
|
+
functionality comparable to the native perl bindings. See examples/minmax.rb
|
12
|
+
or the unit tests in the test directory for scripts that exercise the
|
13
|
+
rrdtool functions.
|
14
|
+
|
15
|
+
|
16
|
+
== Installation
|
17
|
+
|
18
|
+
rubyrrdtool requires RRDtool version 1.2 or later. Some RRD functions such
|
19
|
+
as rrddump are only available with the latest RRDtool.
|
20
|
+
|
21
|
+
Installation is standard. If you've installed the gem, you should be ready
|
22
|
+
to go. Otherwise, simply run:
|
23
|
+
|
24
|
+
ruby extconf.rb
|
25
|
+
make
|
26
|
+
make install
|
27
|
+
|
28
|
+
I hope this works for you. Please let me know if you have any problems or
|
29
|
+
suggestions.
|
30
|
+
|
31
|
+
Thanks to Tobi for rrdtool!
|
32
|
+
|
33
|
+
== Building gem
|
34
|
+
|
35
|
+
gem build RubyRRDtool.gemspec
|
36
|
+
|
37
|
+
== To do
|
38
|
+
|
39
|
+
* Documentation
|
40
|
+
* Build an interface that feels more ruby-like around this simple functional
|
41
|
+
translation
|
42
|
+
|
43
|
+
|
44
|
+
== License
|
45
|
+
|
46
|
+
(the MIT license)
|
47
|
+
|
48
|
+
Copyright (c) 2006
|
49
|
+
|
50
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
51
|
+
a copy of this software and associated documentation files (the
|
52
|
+
"Software"), to deal in the Software without restriction, including
|
53
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
54
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
55
|
+
permit persons to whom the Software is furnished to do so, subject to
|
56
|
+
the following conditions:
|
57
|
+
|
58
|
+
The above copyright notice and this permission notice shall be
|
59
|
+
included in all copies or substantial portions of the Software.
|
60
|
+
|
61
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
62
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
63
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
64
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
65
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
66
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
67
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'hoe'
|
6
|
+
|
7
|
+
RUBY_RRDTOOL_VERSION = '0.6.0'
|
8
|
+
|
9
|
+
Hoe.new("RubyRRDtool", RUBY_RRDTOOL_VERSION) do |p|
|
10
|
+
p.rubyforge_name = "rubyrrdtool"
|
11
|
+
p.summary = "Ruby language binding for RRD tool version 1.2+"
|
12
|
+
p.description = p.paragraphs_of('README', 2..3).join("\n\n")
|
13
|
+
|
14
|
+
p.url = "http://rubyforge.org/projects/rubyrrdtool/"
|
15
|
+
|
16
|
+
p.author = [ "David Bacher", "Mark Probert" ]
|
17
|
+
p.email = "drbacher @nospam@ alum dot mit dot edu"
|
18
|
+
|
19
|
+
p.spec_extras = { 'extensions' => 'extconf.rb' }
|
20
|
+
|
21
|
+
p.changes =<<EOC
|
22
|
+
* applied patches (thanks to Hrvoje Marjanovic, Akihiro Sagawa and Thorsten von Eicken)
|
23
|
+
* changed version, graph, xport methods to be class methods
|
24
|
+
* removed dump method from pre two-arg-dump rrdtool versions
|
25
|
+
* fixed compiler warnings in debug output
|
26
|
+
* hoe-ified Rakefile
|
27
|
+
EOC
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "Build RRD driver"
|
31
|
+
task :build do
|
32
|
+
puts `[ -e Makefile ] || ruby extconf.rb; make`
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "Rebuild RRD driver"
|
36
|
+
task :rebuild do
|
37
|
+
puts `ruby extconf.rb; make clean all`
|
38
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# $Id: function_test.rb,v 1.2 2006/10/18 21:43:38 dbach Exp $
|
3
|
+
# Driver does not carry cash.
|
4
|
+
|
5
|
+
# insert the lib directory at the front of the path to pick up
|
6
|
+
# the latest build -- useful for testing during development
|
7
|
+
$:.unshift '../lib'
|
8
|
+
|
9
|
+
require 'RRDtool'
|
10
|
+
|
11
|
+
name = "test"
|
12
|
+
rrdname = "#{name}.rrd"
|
13
|
+
start = Time.now.to_i
|
14
|
+
|
15
|
+
rrd = RRDtool.new(rrdname)
|
16
|
+
puts "created new RRD database -> #{rrd.rrdname}"
|
17
|
+
|
18
|
+
|
19
|
+
# ---------------------------------------------
|
20
|
+
# Version
|
21
|
+
# ---------------------------------------------
|
22
|
+
puts "RRD Version "
|
23
|
+
n = RRDtool.version
|
24
|
+
puts "version() returned #{(n.nil?) ? "nil" : n}"
|
25
|
+
puts
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
# ---------------------------------------------
|
31
|
+
# Create
|
32
|
+
# ---------------------------------------------
|
33
|
+
puts "creating #{rrdname}"
|
34
|
+
n = rrd.create(
|
35
|
+
300, start-1,
|
36
|
+
["DS:a:GAUGE:600:U:U",
|
37
|
+
"DS:b:GAUGE:600:U:U",
|
38
|
+
"RRA:AVERAGE:0.5:1:300"])
|
39
|
+
puts "create() returned #{(n.nil?) ? "nil" : n}"
|
40
|
+
puts
|
41
|
+
|
42
|
+
|
43
|
+
# ---------------------------------------------
|
44
|
+
# Update
|
45
|
+
# ---------------------------------------------
|
46
|
+
puts "updating #{rrdname}"
|
47
|
+
val = start.to_i
|
48
|
+
while (val < (start.to_i+300*300)) do
|
49
|
+
rrd.update("a:b", ["#{val}:#{rand()}:#{Math.sin(val / 3000) * 50 + 50}"])
|
50
|
+
val += 300
|
51
|
+
end
|
52
|
+
puts
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
# ---------------------------------------------
|
58
|
+
# Dump
|
59
|
+
# ---------------------------------------------
|
60
|
+
puts "dumping #{rrdname}"
|
61
|
+
n = rrd.dump
|
62
|
+
puts "dump() returned #{(n.nil?) ? "nil" : n}"
|
63
|
+
puts
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
# ---------------------------------------------
|
68
|
+
# Fetch
|
69
|
+
# ---------------------------------------------
|
70
|
+
puts "fetching data from #{rrdname}"
|
71
|
+
arr = rrd.fetch(["AVERAGE"])
|
72
|
+
data = arr[3]
|
73
|
+
puts "got #{data.length} data points"
|
74
|
+
puts
|
75
|
+
|
76
|
+
|
77
|
+
|
78
|
+
# ---------------------------------------------
|
79
|
+
# Info
|
80
|
+
# ---------------------------------------------
|
81
|
+
puts "RRD info "
|
82
|
+
h = rrd.info
|
83
|
+
puts "info() returned #{h.size} items"
|
84
|
+
h.each do |k, v|
|
85
|
+
puts " #{k} --> #{v}"
|
86
|
+
end
|
87
|
+
puts
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
# ---------------------------------------------
|
92
|
+
# Graph
|
93
|
+
# ---------------------------------------------
|
94
|
+
puts "generating graph #{name}.png"
|
95
|
+
rrd.graph(
|
96
|
+
["#{name}.png",
|
97
|
+
"--title", " RubyRRD Demo",
|
98
|
+
"--start", "#{start} + 1 h",
|
99
|
+
"--end", "#{start} + 1000 min",
|
100
|
+
"--interlace",
|
101
|
+
"--imgformat", "PNG",
|
102
|
+
"--width=450",
|
103
|
+
"DEF:a=#{rrd.rrdname}:a:AVERAGE",
|
104
|
+
"DEF:b=#{rrd.rrdname}:b:AVERAGE",
|
105
|
+
"CDEF:line=TIME,2400,%,300,LT,a,UNKN,IF",
|
106
|
+
"AREA:b#00b6e4:beta",
|
107
|
+
"AREA:line#0022e9:alpha",
|
108
|
+
"LINE3:line#ff0000"])
|
109
|
+
puts
|
110
|
+
|
111
|
+
|
112
|
+
exit # <<<<============== STOP ==================
|
113
|
+
|
114
|
+
# ---------------------------------------------
|
115
|
+
# First
|
116
|
+
# ---------------------------------------------
|
117
|
+
puts "first value for #{rrdname}"
|
118
|
+
n = rrd.first(nil)
|
119
|
+
puts "first() returned #{(n.nil?) ? "nil" : n}"
|
120
|
+
n = rrd.first(0)
|
121
|
+
puts "first(0) returned #{(n.nil?) ? "nil" : n}"
|
122
|
+
puts
|
123
|
+
|
124
|
+
# ---------------------------------------------
|
125
|
+
# Last
|
126
|
+
# ---------------------------------------------
|
127
|
+
puts "last value for #{rrdname}"
|
128
|
+
n = rrd.last
|
129
|
+
puts "last() returned #{(n.nil?) ? "nil" : n}"
|
130
|
+
puts
|
131
|
+
|
132
|
+
|
133
|
+
print "This script has created #{name}.png in the current directory\n";
|
134
|
+
print "This demonstrates the use of the TIME and % RPN operators\n";
|
data/examples/minmax.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "RRDtool"
|
4
|
+
|
5
|
+
name = "minmax"
|
6
|
+
rrdname = "#{name}.rrd"
|
7
|
+
start = Time.now.to_i
|
8
|
+
|
9
|
+
rrd = RRDtool.new(rrdname)
|
10
|
+
puts "created new RRD database -> #{rrd.rrdname}"
|
11
|
+
|
12
|
+
puts "vers -> #{RRDtool.version}"
|
13
|
+
|
14
|
+
# ---------------------------------------------
|
15
|
+
# Create
|
16
|
+
# ---------------------------------------------
|
17
|
+
puts " .. creating #{rrdname}"
|
18
|
+
n = rrd.create(
|
19
|
+
300, start-1,
|
20
|
+
["DS:ds_0:GAUGE:600:U:U",
|
21
|
+
"RRA:AVERAGE:0.5:1:300",
|
22
|
+
"RRA:MIN:0.5:12:300",
|
23
|
+
"RRA:MAX:0.5:12:300"])
|
24
|
+
|
25
|
+
# ---------------------------------------------
|
26
|
+
# Update
|
27
|
+
# ---------------------------------------------
|
28
|
+
puts " .. updating #{rrdname}"
|
29
|
+
val = start.to_i
|
30
|
+
while (val < (start.to_i+300*300)) do
|
31
|
+
rrd.update("ds_0", ["#{val}:#{Math.sin(val / 3000) * 50 + 50}"])
|
32
|
+
val += 300
|
33
|
+
# sleep(1)
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
# ---------------------------------------------
|
39
|
+
# Graph
|
40
|
+
# ---------------------------------------------
|
41
|
+
puts "generating graph #{name}.png"
|
42
|
+
RRDtool.graph(
|
43
|
+
["#{name}.png",
|
44
|
+
"DEF:a=#{rrdname}:ds_0:AVERAGE",
|
45
|
+
"DEF:b=#{rrdname}:ds_0:MIN",
|
46
|
+
"DEF:c=#{rrdname}:ds_0:MAX",
|
47
|
+
"--title", " #{name} Demo",
|
48
|
+
"--start", "now",
|
49
|
+
"--end", "start+1d",
|
50
|
+
"--lower-limit=0",
|
51
|
+
"--interlace",
|
52
|
+
"--imgformat", "PNG",
|
53
|
+
"--width=450",
|
54
|
+
"AREA:a#00b6e4:real",
|
55
|
+
"LINE1:b#0022e9:min",
|
56
|
+
"LINE1:c#000000:max"])
|
57
|
+
|
58
|
+
|
59
|
+
puts "This script has created #{rrdname}.png in the current directory"
|
60
|
+
puts "This demonstrates the use of the TIME and % RPN operators"
|
data/extconf.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# $Id: extconf.rb,v 1.4 2008/03/11 22:47:06 dbach Exp $
|
2
|
+
|
3
|
+
require 'mkmf'
|
4
|
+
|
5
|
+
# If there are build errors, be sure to say where your rrdtool lives:
|
6
|
+
#
|
7
|
+
# ruby ./extconf.rb --with-rrd-dir=/usr/local/rrdtool-1.2.12
|
8
|
+
|
9
|
+
libpaths=%w(/lib /usr/lib /usr/local/lib /sw/lib /opt/local/lib)
|
10
|
+
%w(art_lgpl_2 freetype png z).sort.reverse.each do |lib|
|
11
|
+
find_library(lib, nil, *libpaths)
|
12
|
+
end
|
13
|
+
|
14
|
+
dir_config("rrd")
|
15
|
+
# rrd_first is only defined rrdtool >= 1.2.x
|
16
|
+
have_library("rrd", "rrd_first")
|
17
|
+
|
18
|
+
# rrd_dump_r has 2nd arg in rrdtool >= 1.2.14
|
19
|
+
if try_link(<<EOF)
|
20
|
+
#include <rrd.h>
|
21
|
+
main()
|
22
|
+
{
|
23
|
+
rrd_dump_r("/dev/null", NULL);
|
24
|
+
}
|
25
|
+
EOF
|
26
|
+
$CFLAGS += " -DHAVE_RRD_DUMP_R_2"
|
27
|
+
end
|
28
|
+
|
29
|
+
create_makefile("RRDtool")
|
30
|
+
|
data/rrd_info.h
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
/* -*- C -*-
|
2
|
+
* file: rrd_info.h
|
3
|
+
* date: $Date: 2008/03/11 22:47:06 $
|
4
|
+
* init: 2005-07-26
|
5
|
+
* vers: $Version$
|
6
|
+
* auth: $Author: dbach $
|
7
|
+
* -----
|
8
|
+
*
|
9
|
+
* Support file to add rrd_info() to rrd.h
|
10
|
+
*
|
11
|
+
*/
|
12
|
+
#ifndef __RRD_INFO_H
|
13
|
+
#define __RRD_INFO_H
|
14
|
+
|
15
|
+
#if defined(__cplusplus) || defined(c_plusplus)
|
16
|
+
extern "C" {
|
17
|
+
#endif
|
18
|
+
|
19
|
+
/* rrd info interface
|
20
|
+
enum info_type { RD_I_VAL=0,
|
21
|
+
RD_I_CNT,
|
22
|
+
RD_I_STR,
|
23
|
+
RD_I_INT };
|
24
|
+
*/
|
25
|
+
|
26
|
+
typedef union infoval {
|
27
|
+
unsigned long u_cnt;
|
28
|
+
rrd_value_t u_val;
|
29
|
+
char *u_str;
|
30
|
+
int u_int;
|
31
|
+
} infoval;
|
32
|
+
|
33
|
+
typedef struct info_t {
|
34
|
+
char *key;
|
35
|
+
rrd_info_type_t type;
|
36
|
+
union infoval value;
|
37
|
+
struct info_t *next;
|
38
|
+
} info_t;
|
39
|
+
|
40
|
+
//info_t *rrd_info(int, char **);
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
#if defined(__cplusplus) || defined(c_plusplus)
|
45
|
+
}
|
46
|
+
#endif
|
47
|
+
#endif /* __RRD_INFO_H */
|
data/rrdtool_main.c
ADDED
@@ -0,0 +1,260 @@
|
|
1
|
+
/* $Id: rrdtool_main.c,v 1.1 2008/03/11 22:47:06 dbach Exp $
|
2
|
+
* Substantial penalty for early withdrawal.
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include <unistd.h>
|
6
|
+
#include <math.h> /* for isnan */
|
7
|
+
#include <ruby.h>
|
8
|
+
#include <rrd.h>
|
9
|
+
#include "rrd_info.h"
|
10
|
+
|
11
|
+
typedef struct string_arr_t {
|
12
|
+
int len;
|
13
|
+
char **strings;
|
14
|
+
} string_arr;
|
15
|
+
|
16
|
+
VALUE mRRD;
|
17
|
+
VALUE rb_eRRDError;
|
18
|
+
|
19
|
+
typedef int (*RRDFUNC)(int argc, char ** argv);
|
20
|
+
#define RRD_CHECK_ERROR \
|
21
|
+
if (rrd_test_error()) \
|
22
|
+
rb_raise(rb_eRRDError, rrd_get_error()); \
|
23
|
+
rrd_clear_error();
|
24
|
+
|
25
|
+
string_arr string_arr_new(VALUE rb_strings)
|
26
|
+
{
|
27
|
+
string_arr a;
|
28
|
+
char buf[64];
|
29
|
+
int i;
|
30
|
+
|
31
|
+
Check_Type(rb_strings, T_ARRAY);
|
32
|
+
a.len = RARRAY_LEN(rb_strings) + 1;
|
33
|
+
|
34
|
+
a.strings = malloc(a.len * sizeof(char *));
|
35
|
+
a.strings[0] = "dummy"; /* first element is a dummy element */
|
36
|
+
|
37
|
+
for (i = 0; i < a.len - 1; i++) {
|
38
|
+
VALUE v = rb_ary_entry(rb_strings, i);
|
39
|
+
switch (TYPE(v)) {
|
40
|
+
case T_STRING:
|
41
|
+
a.strings[i + 1] = strdup(STR2CSTR(v));
|
42
|
+
break;
|
43
|
+
case T_FIXNUM:
|
44
|
+
snprintf(buf, 63, "%d", FIX2INT(v));
|
45
|
+
a.strings[i + 1] = strdup(buf);
|
46
|
+
break;
|
47
|
+
default:
|
48
|
+
rb_raise(rb_eTypeError, "invalid argument - %s, expected T_STRING or T_FIXNUM on index %d", rb_class2name(CLASS_OF(v)), i);
|
49
|
+
break;
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
return a;
|
54
|
+
}
|
55
|
+
|
56
|
+
void string_arr_delete(string_arr a)
|
57
|
+
{
|
58
|
+
int i;
|
59
|
+
|
60
|
+
/* skip dummy first entry */
|
61
|
+
for (i = 1; i < a.len; i++) {
|
62
|
+
free(a.strings[i]);
|
63
|
+
}
|
64
|
+
|
65
|
+
free(a.strings);
|
66
|
+
}
|
67
|
+
|
68
|
+
void reset_rrd_state()
|
69
|
+
{
|
70
|
+
optind = 0;
|
71
|
+
opterr = 0;
|
72
|
+
rrd_clear_error();
|
73
|
+
}
|
74
|
+
|
75
|
+
VALUE rrd_call(RRDFUNC func, VALUE args)
|
76
|
+
{
|
77
|
+
string_arr a;
|
78
|
+
|
79
|
+
a = string_arr_new(args);
|
80
|
+
reset_rrd_state();
|
81
|
+
func(a.len, a.strings);
|
82
|
+
string_arr_delete(a);
|
83
|
+
|
84
|
+
RRD_CHECK_ERROR
|
85
|
+
|
86
|
+
return Qnil;
|
87
|
+
}
|
88
|
+
|
89
|
+
VALUE rb_rrd_create(VALUE self, VALUE args)
|
90
|
+
{
|
91
|
+
return rrd_call(rrd_create, args);
|
92
|
+
}
|
93
|
+
|
94
|
+
VALUE rb_rrd_dump(VALUE self, VALUE args)
|
95
|
+
{
|
96
|
+
return rrd_call(rrd_dump, args);
|
97
|
+
}
|
98
|
+
|
99
|
+
VALUE rb_rrd_fetch(VALUE self, VALUE args)
|
100
|
+
{
|
101
|
+
string_arr a;
|
102
|
+
unsigned long i, j, k, step, ds_cnt;
|
103
|
+
rrd_value_t *raw_data;
|
104
|
+
char **raw_names;
|
105
|
+
VALUE data, names, result;
|
106
|
+
time_t start, end;
|
107
|
+
|
108
|
+
a = string_arr_new(args);
|
109
|
+
reset_rrd_state();
|
110
|
+
rrd_fetch(a.len, a.strings, &start, &end, &step, &ds_cnt, &raw_names, &raw_data);
|
111
|
+
string_arr_delete(a);
|
112
|
+
|
113
|
+
RRD_CHECK_ERROR
|
114
|
+
|
115
|
+
names = rb_ary_new();
|
116
|
+
for (i = 0; i < ds_cnt; i++) {
|
117
|
+
rb_ary_push(names, rb_str_new2(raw_names[i]));
|
118
|
+
free(raw_names[i]);
|
119
|
+
}
|
120
|
+
free(raw_names);
|
121
|
+
|
122
|
+
k = 0;
|
123
|
+
data = rb_ary_new();
|
124
|
+
for (i = start; i < end; i += step) {
|
125
|
+
VALUE line = rb_ary_new2(ds_cnt);
|
126
|
+
for (j = 0; j < ds_cnt; j++) {
|
127
|
+
rb_ary_store(line, j, rb_float_new(raw_data[k]));
|
128
|
+
k++;
|
129
|
+
}
|
130
|
+
rb_ary_push(data, line);
|
131
|
+
}
|
132
|
+
free(raw_data);
|
133
|
+
|
134
|
+
result = rb_ary_new2(4);
|
135
|
+
rb_ary_store(result, 0, INT2NUM(start));
|
136
|
+
rb_ary_store(result, 1, INT2NUM(end));
|
137
|
+
rb_ary_store(result, 2, names);
|
138
|
+
rb_ary_store(result, 3, data);
|
139
|
+
return result;
|
140
|
+
}
|
141
|
+
|
142
|
+
VALUE rb_rrd_graph(VALUE self, VALUE args)
|
143
|
+
{
|
144
|
+
string_arr a;
|
145
|
+
char **calcpr, **p;
|
146
|
+
VALUE result, print_results;
|
147
|
+
int xsize, ysize;
|
148
|
+
double ymin, ymax;
|
149
|
+
|
150
|
+
a = string_arr_new(args);
|
151
|
+
reset_rrd_state();
|
152
|
+
rrd_graph(a.len, a.strings, &calcpr, &xsize, &ysize, NULL, &ymin, &ymax);
|
153
|
+
string_arr_delete(a);
|
154
|
+
|
155
|
+
RRD_CHECK_ERROR
|
156
|
+
|
157
|
+
result = rb_ary_new2(3);
|
158
|
+
print_results = rb_ary_new();
|
159
|
+
p = calcpr;
|
160
|
+
for (p = calcpr; p && *p; p++) {
|
161
|
+
rb_ary_push(print_results, rb_str_new2(*p));
|
162
|
+
free(*p);
|
163
|
+
}
|
164
|
+
free(calcpr);
|
165
|
+
rb_ary_store(result, 0, print_results);
|
166
|
+
rb_ary_store(result, 1, INT2FIX(xsize));
|
167
|
+
rb_ary_store(result, 2, INT2FIX(ysize));
|
168
|
+
return result;
|
169
|
+
}
|
170
|
+
|
171
|
+
VALUE rb_rrd_info(VALUE self, VALUE args)
|
172
|
+
{
|
173
|
+
string_arr a;
|
174
|
+
info_t *p, *data;
|
175
|
+
VALUE result;
|
176
|
+
|
177
|
+
a = string_arr_new(args);
|
178
|
+
data = rrd_info(a.len, a.strings);
|
179
|
+
string_arr_delete(a);
|
180
|
+
|
181
|
+
RRD_CHECK_ERROR
|
182
|
+
|
183
|
+
result = rb_hash_new();
|
184
|
+
while (data) {
|
185
|
+
VALUE key = rb_str_new2(data->key);
|
186
|
+
switch (data->type) {
|
187
|
+
case RD_I_VAL:
|
188
|
+
if (isnan(data->value.u_val)) {
|
189
|
+
rb_hash_aset(result, key, Qnil);
|
190
|
+
}
|
191
|
+
else {
|
192
|
+
rb_hash_aset(result, key, rb_float_new(data->value.u_val));
|
193
|
+
}
|
194
|
+
break;
|
195
|
+
case RD_I_CNT:
|
196
|
+
rb_hash_aset(result, key, INT2FIX(data->value.u_cnt));
|
197
|
+
break;
|
198
|
+
case RD_I_STR:
|
199
|
+
rb_hash_aset(result, key, rb_str_new2(data->value.u_str));
|
200
|
+
free(data->value.u_str);
|
201
|
+
break;
|
202
|
+
}
|
203
|
+
p = data;
|
204
|
+
data = data->next;
|
205
|
+
free(p);
|
206
|
+
}
|
207
|
+
return result;
|
208
|
+
}
|
209
|
+
|
210
|
+
VALUE rb_rrd_last(VALUE self, VALUE args)
|
211
|
+
{
|
212
|
+
string_arr a;
|
213
|
+
time_t last;
|
214
|
+
|
215
|
+
a = string_arr_new(args);
|
216
|
+
reset_rrd_state();
|
217
|
+
last = rrd_last(a.len, a.strings);
|
218
|
+
string_arr_delete(a);
|
219
|
+
|
220
|
+
RRD_CHECK_ERROR
|
221
|
+
|
222
|
+
return rb_funcall(rb_cTime, rb_intern("at"), 1, INT2FIX(last));
|
223
|
+
}
|
224
|
+
|
225
|
+
VALUE rb_rrd_resize(VALUE self, VALUE args)
|
226
|
+
{
|
227
|
+
return rrd_call(rrd_resize, args);
|
228
|
+
}
|
229
|
+
|
230
|
+
VALUE rb_rrd_restore(VALUE self, VALUE args)
|
231
|
+
{
|
232
|
+
return rrd_call(rrd_restore, args);
|
233
|
+
}
|
234
|
+
|
235
|
+
VALUE rb_rrd_tune(VALUE self, VALUE args)
|
236
|
+
{
|
237
|
+
return rrd_call(rrd_tune, args);
|
238
|
+
}
|
239
|
+
|
240
|
+
VALUE rb_rrd_update(VALUE self, VALUE args)
|
241
|
+
{
|
242
|
+
return rrd_call(rrd_update, args);
|
243
|
+
}
|
244
|
+
|
245
|
+
void Init_RRD()
|
246
|
+
{
|
247
|
+
mRRD = rb_define_module("RRD");
|
248
|
+
rb_eRRDError = rb_define_class("RRDError", rb_eStandardError);
|
249
|
+
|
250
|
+
rb_define_module_function(mRRD, "create", rb_rrd_create, -2);
|
251
|
+
rb_define_module_function(mRRD, "dump", rb_rrd_dump, -2);
|
252
|
+
rb_define_module_function(mRRD, "fetch", rb_rrd_fetch, -2);
|
253
|
+
rb_define_module_function(mRRD, "graph", rb_rrd_graph, -2);
|
254
|
+
rb_define_module_function(mRRD, "last", rb_rrd_last, -2);
|
255
|
+
rb_define_module_function(mRRD, "resize", rb_rrd_resize, -2);
|
256
|
+
rb_define_module_function(mRRD, "restore", rb_rrd_restore, -2);
|
257
|
+
rb_define_module_function(mRRD, "tune", rb_rrd_tune, -2);
|
258
|
+
rb_define_module_function(mRRD, "update", rb_rrd_update, -2);
|
259
|
+
rb_define_module_function(mRRD, "info", rb_rrd_info, -2);
|
260
|
+
}
|
@@ -0,0 +1,172 @@
|
|
1
|
+
# Code Generated by ZenTest v. 3.2.0
|
2
|
+
# classname: asrt / meth = ratio%
|
3
|
+
|
4
|
+
$:.unshift '..'
|
5
|
+
|
6
|
+
require 'test/unit' unless defined? $ZENTEST and $ZENTEST
|
7
|
+
require 'RRDtool'
|
8
|
+
|
9
|
+
class TestRRDtool < Test::Unit::TestCase
|
10
|
+
def setup
|
11
|
+
@f = 'test.rrd'
|
12
|
+
@g = (File.basename @f, '.rrd') + '.png'
|
13
|
+
File.delete @f if File.exists? @f
|
14
|
+
File.delete @g if File.exists? @g
|
15
|
+
@r = RRDtool.new @f
|
16
|
+
end
|
17
|
+
|
18
|
+
def teardown
|
19
|
+
File.delete @f if File.exists? @f
|
20
|
+
# note: leave the graph file around to check it by hand
|
21
|
+
@r = nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def create_file
|
25
|
+
@start = Time.now.to_i - 1
|
26
|
+
@step = 300
|
27
|
+
@r.create @step, @start, [ "DS:a:GAUGE:#{2*@step}:0:1",
|
28
|
+
"DS:b:GAUGE:#{2*@step}:-10:10",
|
29
|
+
"RRA:AVERAGE:0.5:1:300",
|
30
|
+
"RRA:LAST:0.5:1:10" ]
|
31
|
+
end
|
32
|
+
|
33
|
+
def create_data
|
34
|
+
scale = 10
|
35
|
+
ts = Time.now.to_i + 1
|
36
|
+
while (ts < (@start.to_i + @step*300)) do
|
37
|
+
@r.update "a:b", ["#{ts}:#{rand()}:#{Math.sin(ts / @step / 10)}"]
|
38
|
+
ts += @step
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_create
|
43
|
+
create_file
|
44
|
+
assert File.readable?(@f)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_dump
|
48
|
+
# RRDtool.dump is not defined for older versions of RRDtool
|
49
|
+
dump_file = "#{@f}.out"
|
50
|
+
create_file
|
51
|
+
create_data
|
52
|
+
if RRDtool.version < 1.2015 then
|
53
|
+
assert_raise NoMethodError do
|
54
|
+
@r.dump dump_file
|
55
|
+
end
|
56
|
+
else
|
57
|
+
@r.dump dump_file
|
58
|
+
assert File.readable? dump_file
|
59
|
+
end
|
60
|
+
# cleanup
|
61
|
+
File.delete dump_file if File.exists? dump_file
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_fetch
|
65
|
+
assert_raise RRDtoolError do
|
66
|
+
@r.fetch ["AVERAGE"]
|
67
|
+
end
|
68
|
+
create_file
|
69
|
+
create_data
|
70
|
+
fary = @r.fetch ["AVERAGE"]
|
71
|
+
assert_not_nil fary
|
72
|
+
assert !fary.empty?
|
73
|
+
#assert_equals expected_data_points, fary[3]
|
74
|
+
# LATER: test rrd.fetch ["AVERAGE", "LAST"]
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_first
|
78
|
+
# first and last should raise an exception without an RRD file
|
79
|
+
assert_raise RRDtoolError do
|
80
|
+
@r.first 0
|
81
|
+
end
|
82
|
+
create_file
|
83
|
+
(0..1).each do |i|
|
84
|
+
f = @r.first i
|
85
|
+
assert_not_nil f
|
86
|
+
assert f > 0
|
87
|
+
end
|
88
|
+
assert_raise RRDtoolError do
|
89
|
+
f2 = @r.first 2
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_graph
|
94
|
+
create_file
|
95
|
+
create_data
|
96
|
+
RRDtool.graph(
|
97
|
+
[@g, "--title", " RubyRRD Demo",
|
98
|
+
"--start", "#{@start} + 1 h",
|
99
|
+
"--end", "#{@start} + 1000 min",
|
100
|
+
"--interlace",
|
101
|
+
"--imgformat", "PNG",
|
102
|
+
"--width=450",
|
103
|
+
"DEF:a=#{@f}:a:AVERAGE",
|
104
|
+
"DEF:b=#{@f}:b:AVERAGE",
|
105
|
+
"CDEF:line=TIME,2400,%,300,LT,a,UNKN,IF",
|
106
|
+
"AREA:b#00b6e4:beta",
|
107
|
+
"AREA:line#0022e9:alpha",
|
108
|
+
"LINE3:line#ff0000"])
|
109
|
+
assert File.exists?(@g)
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_info
|
113
|
+
create_file
|
114
|
+
info = @r.info
|
115
|
+
assert_not_nil info
|
116
|
+
assert_equal info['filename'], @f
|
117
|
+
assert_equal info['step'], @step
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_last
|
121
|
+
# first and last should raise an exception without an RRD file
|
122
|
+
assert_raise RRDtoolError do
|
123
|
+
@r.last
|
124
|
+
end
|
125
|
+
create_file
|
126
|
+
l = @r.last
|
127
|
+
assert l > 0
|
128
|
+
assert_equal @start, l
|
129
|
+
create_data
|
130
|
+
l = @r.last
|
131
|
+
assert l > @start
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_resize
|
135
|
+
raise NotImplementedError, 'Need to write test_resize'
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_restore
|
139
|
+
raise NotImplementedError, 'Need to write test_restore'
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_rrdname
|
143
|
+
r = RRDtool.new 'foo'
|
144
|
+
assert_equal r.rrdname, 'foo'
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_tune
|
148
|
+
raise NotImplementedError, 'Need to write test_tune'
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_update
|
152
|
+
create_file
|
153
|
+
# first, test the simple update case (now)
|
154
|
+
@r.update "a:b", ["N:0:0"]
|
155
|
+
assert_in_delta Time.now.to_i, @r.last, 1
|
156
|
+
# next, create a bunch of data entries
|
157
|
+
create_data
|
158
|
+
l = @r.last
|
159
|
+
@r.update "a:b", ["#{l+1}:0:0", "#{l+2}:1:1"]
|
160
|
+
assert_equal @r.last, l+2
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_version
|
164
|
+
v = RRDtool.version
|
165
|
+
assert_instance_of Float, v
|
166
|
+
assert_not_nil v
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_xport
|
170
|
+
raise NotImplementedError, 'Need to write test_xport'
|
171
|
+
end
|
172
|
+
end
|
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: auxesis-RubyRRDtool
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.6.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- David Bacher
|
8
|
+
- Mark Probert
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain:
|
12
|
+
date: 2010-01-09 00:00:00 +11:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: hoe
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.1.1
|
24
|
+
version:
|
25
|
+
description: rubyrrdtool provides ruby bindings for RRD functions (via librrd), with functionality comparable to the native perl bindings. See examples/minmax.rb or the unit tests in the test directory for scripts that exercise the rrdtool functions.
|
26
|
+
email: drbacher @nospam@ alum dot mit dot edu
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions:
|
30
|
+
- extconf.rb
|
31
|
+
extra_rdoc_files: []
|
32
|
+
|
33
|
+
files:
|
34
|
+
- README
|
35
|
+
- Manifest.txt
|
36
|
+
- Rakefile
|
37
|
+
- extconf.rb
|
38
|
+
- rrd_info.h
|
39
|
+
- rrdtool_main.c
|
40
|
+
- test/test_rrdtool.rb
|
41
|
+
- examples/function_test.rb
|
42
|
+
- examples/minmax.rb
|
43
|
+
has_rdoc: true
|
44
|
+
homepage: http://rubyforge.org/projects/rubyrrdtool/
|
45
|
+
licenses: []
|
46
|
+
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
|
50
|
+
require_paths:
|
51
|
+
- test
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">"
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 0.0.0
|
57
|
+
version:
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: "0"
|
63
|
+
version:
|
64
|
+
requirements: []
|
65
|
+
|
66
|
+
rubyforge_project: rubyrrdtool
|
67
|
+
rubygems_version: 1.3.5
|
68
|
+
signing_key:
|
69
|
+
specification_version: 1
|
70
|
+
summary: Ruby language binding for RRD tool version 1.2+
|
71
|
+
test_files: []
|
72
|
+
|