auxesis-RubyRRDtool 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|