astro-collectd 0.0.7 → 0.0.8
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/README.rst +83 -0
- data/Rakefile +32 -0
- data/VERSION.yml +4 -0
- data/examples/em_sender.rb +17 -0
- data/examples/sender.rb +13 -0
- data/lib/collectd/proc_stats.rb +13 -16
- data/spec/interface_spec.rb +145 -0
- metadata +21 -13
data/README.rst
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
collectd Data Model
|
2
|
+
-------------------
|
3
|
+
|
4
|
+
Collectd groups data by **six categories:**
|
5
|
+
|
6
|
+
* *hostname* is grabbed from `hostname -f`
|
7
|
+
* *plugin* is the application's name
|
8
|
+
* *plugin-instance* is passed from the programs' side with the
|
9
|
+
programs instance identifier, useful if you're running the same
|
10
|
+
script twice (PIDs are quite too random)
|
11
|
+
* *type* is the kind of data you are measuring and must be defined in
|
12
|
+
types.db_ for collectd to understand
|
13
|
+
* *type-instance* provides further distinction and have no relation to
|
14
|
+
other type-instances. Multiple type-instances are only rendered into
|
15
|
+
one graph by collection3 if defined with module GenericStacked.
|
16
|
+
* *values* are one or more field names and types belonging
|
17
|
+
together. The exact amount of fields and their corresponding names
|
18
|
+
(useful to collection3) are specified in collectd's types.db_.
|
19
|
+
|
20
|
+
A value can be either of **two types:**
|
21
|
+
|
22
|
+
* *COUNTER* is for increasing counters where you want to plot the
|
23
|
+
delta. Network interface traffic counters are a good example.
|
24
|
+
* *GAUGE* is values that go up and down to be plotted as-is, like a
|
25
|
+
temperature graph.
|
26
|
+
|
27
|
+
|
28
|
+
Usage
|
29
|
+
-----
|
30
|
+
|
31
|
+
::
|
32
|
+
|
33
|
+
gem 'astro-collectd'
|
34
|
+
require 'collectd'
|
35
|
+
|
36
|
+
First of all, specify a server to send data to:
|
37
|
+
|
38
|
+
::
|
39
|
+
|
40
|
+
Collectd.add_server(interval, addr='ff18::efc0:4a42', port=25826)
|
41
|
+
|
42
|
+
Each server definition you add will receive all the data you push to
|
43
|
+
later. An interval of 10 is quite reasonable. Because of UDP and some
|
44
|
+
buffering in collectd, an interval of 1 seconds shouldn't hurt either.
|
45
|
+
|
46
|
+
All the identifiers from above can be given free form with some
|
47
|
+
method_missing stuff. Like this:
|
48
|
+
|
49
|
+
::
|
50
|
+
|
51
|
+
# Set gauge absolutely
|
52
|
+
Collectd.plugin(:plugin_instance).type(:type_instance).gauge = 23
|
53
|
+
|
54
|
+
# Increase counter relatively (collectd caches counters)
|
55
|
+
Collectd.plugin(:plugin_instance).type(:type_instance).count! 5
|
56
|
+
|
57
|
+
# Set counter absolutely
|
58
|
+
Collectd.plugin(:plugin_instance).type(:type_instance).counter = 42
|
59
|
+
|
60
|
+
For convenience, define yourself a global *shortcut*, like:
|
61
|
+
|
62
|
+
::
|
63
|
+
|
64
|
+
Stats = Collectd.my_zombie(RAILS_ENV)
|
65
|
+
|
66
|
+
To automatically collect *memory and CPU statistics* of your Ruby
|
67
|
+
process, do:
|
68
|
+
|
69
|
+
::
|
70
|
+
|
71
|
+
Stats.with_full_proc_stats
|
72
|
+
|
73
|
+
You can also have the library *poll* for your data, if you feel
|
74
|
+
comfortable with that, eg:
|
75
|
+
|
76
|
+
::
|
77
|
+
|
78
|
+
Stats.counter(:seconds_elapsed).polled_counter do
|
79
|
+
Time.now.to_i
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
.. _types.db: http://collectd.org/documentation/manpages/types.db.5.shtml
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
rescue LoadError
|
4
|
+
raise "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
5
|
+
end
|
6
|
+
|
7
|
+
Jeweler::Tasks.new do |s|
|
8
|
+
s.name = "collectd"
|
9
|
+
s.summary = "Send collectd statistics from Ruby"
|
10
|
+
s.email = "astro@spaceboyz.net"
|
11
|
+
s.homepage = "http://github.com/astro/ruby-collectd"
|
12
|
+
s.authors = ["Stephan Maka"]
|
13
|
+
s.files = FileList["[A-Z]*", "{lib,spec,examples}/**/*"]
|
14
|
+
#s.add_dependency 'eventmachine'
|
15
|
+
end
|
16
|
+
|
17
|
+
begin
|
18
|
+
require 'spec/rake/spectask'
|
19
|
+
desc "Run all Spec"
|
20
|
+
Spec::Rake::SpecTask.new('spec') do |spec|
|
21
|
+
spec.spec_files = FileList['spec/*.rb']
|
22
|
+
spec.verbose = true
|
23
|
+
spec.warning = true
|
24
|
+
spec.rcov = true
|
25
|
+
spec.rcov_opts = []
|
26
|
+
spec.rcov_opts = ['--exclude', 'spec']
|
27
|
+
end
|
28
|
+
rescue LoadError
|
29
|
+
task :spec do
|
30
|
+
abort "Rspec is not available. In order to run rspec, you must: sudo gem install rspec"
|
31
|
+
end
|
32
|
+
end
|
data/VERSION.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'collectd'
|
3
|
+
|
4
|
+
EM.run do
|
5
|
+
Collectd::use_eventmachine = true
|
6
|
+
Collectd::add_server 1
|
7
|
+
|
8
|
+
c = 0
|
9
|
+
EM.add_periodic_timer(0.01) do
|
10
|
+
Collectd.ruby_collectd(:test).ping(:fun).gauge = 42 + Math.sin(Time.now.to_f / 600) * 23.5
|
11
|
+
Collectd.ruby_collectd(:test).cpu(:time).counter = c
|
12
|
+
|
13
|
+
c += 1
|
14
|
+
print '.'
|
15
|
+
STDOUT.flush
|
16
|
+
end
|
17
|
+
end
|
data/examples/sender.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'collectd'
|
2
|
+
|
3
|
+
Collectd::add_server 1
|
4
|
+
|
5
|
+
c = 0
|
6
|
+
loop do
|
7
|
+
Collectd.ruby_collectd(:test).ping(:fun).gauge = 42 + Math.sin(Time.now.to_f / 600) * 23.5
|
8
|
+
Collectd.ruby_collectd(:test).cpu(:time).counter = c
|
9
|
+
c += 1
|
10
|
+
sleep 0.01
|
11
|
+
print '.'
|
12
|
+
STDOUT.flush
|
13
|
+
end
|
data/lib/collectd/proc_stats.rb
CHANGED
@@ -2,42 +2,39 @@ module Collectd
|
|
2
2
|
##
|
3
3
|
# Included by Interface
|
4
4
|
module ProcStats
|
5
|
-
def
|
6
|
-
|
7
|
-
|
5
|
+
def process_status(field)
|
6
|
+
fields = {}
|
7
|
+
begin
|
8
8
|
IO.readlines("/proc/#{$$}/status").each { |line|
|
9
9
|
line.strip!
|
10
10
|
if line =~ /^(.+?):\s+(.+)$/
|
11
11
|
fields[$1] = $2
|
12
12
|
end
|
13
13
|
}
|
14
|
+
rescue Errno::ENOENT
|
15
|
+
nil
|
16
|
+
else
|
14
17
|
fields[field]
|
15
18
|
end
|
19
|
+
end
|
16
20
|
|
21
|
+
def with_polled_memory
|
17
22
|
memory('VmRSS').polled_gauge do
|
18
|
-
process_status('VmRSS').to_i * 1024
|
23
|
+
v = process_status('VmRSS') ? v.to_i * 1024 : nil
|
19
24
|
end
|
20
25
|
memory('VmSize').polled_gauge do
|
21
|
-
process_status('VmSize').to_i * 1024
|
26
|
+
v = process_status('VmSize') ? v.to_i * 1024 : nil
|
22
27
|
end
|
23
28
|
|
24
29
|
self
|
25
30
|
end
|
26
31
|
|
27
32
|
def with_polled_cpu
|
28
|
-
def schedstats
|
29
|
-
if IO.readlines("/proc/#{$$}/schedstat").to_s =~ /^(\d+) (\d+) (\d+)/
|
30
|
-
[$1.to_i, $2.to_i, $3.to_i]
|
31
|
-
else
|
32
|
-
[]
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
33
|
cpu('user').polled_counter do
|
37
|
-
|
34
|
+
(Process::times.utime * 100).to_i
|
38
35
|
end
|
39
|
-
cpu('
|
40
|
-
|
36
|
+
cpu('sys').polled_counter do
|
37
|
+
(Process::times.stime * 100).to_i
|
41
38
|
end
|
42
39
|
end
|
43
40
|
|
@@ -0,0 +1,145 @@
|
|
1
|
+
$: << File.dirname(__FILE__) + '/../lib'
|
2
|
+
require 'collectd'
|
3
|
+
|
4
|
+
describe Collectd do
|
5
|
+
before(:each) do
|
6
|
+
Collectd.reset!
|
7
|
+
@server = mock('Server')
|
8
|
+
Collectd << @server
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should set_counter' do
|
12
|
+
@server.should_receive(:set_counter).
|
13
|
+
with([:plugin1, :plugin_instance1,
|
14
|
+
:type1, :type_instance1], [23])
|
15
|
+
Collectd.plugin1(:plugin_instance1).type1(:type_instance1).counter = 23
|
16
|
+
end
|
17
|
+
it 'should inc_counter' do
|
18
|
+
@server.should_receive(:inc_counter).
|
19
|
+
with([:plugin1, :plugin_instance1,
|
20
|
+
:type1, :type_instance1], [23, 42])
|
21
|
+
Collectd.plugin1(:plugin_instance1).type1(:type_instance1).count! 23, 42
|
22
|
+
end
|
23
|
+
it 'should set_gauge' do
|
24
|
+
@server.should_receive(:set_gauge).
|
25
|
+
with([:plugin1, :plugin_instance1,
|
26
|
+
:type1, :type_instance1], [23, 42, 5])
|
27
|
+
Collectd.plugin1(:plugin_instance1).type1(:type_instance1).gauge = [23, 42, 5]
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should poll a pollable' do
|
31
|
+
pollable = mock('Pollable')
|
32
|
+
Collectd.add_pollable { |*a|
|
33
|
+
pollable.call *a
|
34
|
+
}
|
35
|
+
pollable.should_receive(:call).with(@server).and_return(nil)
|
36
|
+
Collectd.run_pollables_for @server
|
37
|
+
end
|
38
|
+
it 'should poll a polled_count' do
|
39
|
+
Collectd.plugin1(:plugin_instance1).type1(:type_instance1).polled_count do
|
40
|
+
[23, 42, 5, 7]
|
41
|
+
end
|
42
|
+
@server.should_receive(:inc_counter).
|
43
|
+
with([:plugin1, :plugin_instance1,
|
44
|
+
:type1, :type_instance1], [23, 42, 5, 7])
|
45
|
+
Collectd.run_pollables_for @server
|
46
|
+
end
|
47
|
+
it 'should poll a polled_counter' do
|
48
|
+
Collectd.plugin1(:plugin_instance1).type1(:type_instance1).polled_counter do
|
49
|
+
[23, 42, 5, 7]
|
50
|
+
end
|
51
|
+
@server.should_receive(:set_counter).
|
52
|
+
with([:plugin1, :plugin_instance1,
|
53
|
+
:type1, :type_instance1], [23, 42, 5, 7])
|
54
|
+
Collectd.run_pollables_for @server
|
55
|
+
end
|
56
|
+
it 'should poll a polled_gauge' do
|
57
|
+
Collectd.plugin1(:plugin_instance1).type1(:type_instance1).polled_gauge do
|
58
|
+
[23, 42, 5, 7]
|
59
|
+
end
|
60
|
+
@server.should_receive(:set_gauge).
|
61
|
+
with([:plugin1, :plugin_instance1,
|
62
|
+
:type1, :type_instance1], [23, 42, 5, 7])
|
63
|
+
Collectd.run_pollables_for @server
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class StubServer < Collectd::Values
|
68
|
+
attr_reader :counters
|
69
|
+
attr_reader :gauges
|
70
|
+
def initialize
|
71
|
+
super(1000)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe Collectd::ProcStats do
|
76
|
+
before(:each) do
|
77
|
+
Collectd.reset!
|
78
|
+
@server = StubServer.new
|
79
|
+
Collectd << @server
|
80
|
+
Collectd.plugin1(:plugin_instance1).with_full_proc_stats
|
81
|
+
Collectd.run_pollables_for @server
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'when polling memory' do
|
85
|
+
it 'should report VmRSS' do
|
86
|
+
g = @server.gauges[[:plugin1, :plugin_instance1, :memory, "VmRSS"]]
|
87
|
+
g[0].should be_kind_of(Fixnum)
|
88
|
+
end
|
89
|
+
it 'should report VmSize' do
|
90
|
+
g = @server.gauges[[:plugin1, :plugin_instance1, :memory, "VmSize"]]
|
91
|
+
g[0].should be_kind_of(Fixnum)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
context 'when polling cpu' do
|
95
|
+
it 'should report user time' do
|
96
|
+
c = @server.counters[[:plugin1, :plugin_instance1, :cpu, "user"]]
|
97
|
+
c[0].should be_kind_of(Fixnum)
|
98
|
+
end
|
99
|
+
it 'should report system time' do
|
100
|
+
c = @server.counters[[:plugin1, :plugin_instance1, :cpu, "sys"]]
|
101
|
+
c[0].should be_kind_of(Fixnum)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe Collectd::EmPlugin do
|
107
|
+
before(:each) do
|
108
|
+
Collectd.reset!
|
109
|
+
@server = StubServer.new
|
110
|
+
Collectd << @server
|
111
|
+
@df = EM::DefaultDeferrable.new
|
112
|
+
Collectd.plugin1(:plugin_instance1).track_deferrable('df', @df)
|
113
|
+
end
|
114
|
+
|
115
|
+
context 'when succeeding' do
|
116
|
+
it 'should callback' do
|
117
|
+
@df.succeed
|
118
|
+
end
|
119
|
+
it 'should report latency' do
|
120
|
+
@df.succeed
|
121
|
+
g = @server.gauges[[:plugin1, :plugin_instance1, :latency, 'df success']]
|
122
|
+
g[0].should be_kind_of(Numeric)
|
123
|
+
end
|
124
|
+
it 'should increase a counter' do
|
125
|
+
@df.succeed
|
126
|
+
c = @server.counters[[:plugin1, :plugin_instance1, :counter, 'df success']]
|
127
|
+
c[0].should be_kind_of(Numeric)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
context 'when failing' do
|
131
|
+
it 'should callback' do
|
132
|
+
@df.fail
|
133
|
+
end
|
134
|
+
it 'should report latency' do
|
135
|
+
@df.fail
|
136
|
+
g = @server.gauges[[:plugin1, :plugin_instance1, :latency, 'df error']]
|
137
|
+
g[0].should be_kind_of(Numeric)
|
138
|
+
end
|
139
|
+
it 'should increase a counter' do
|
140
|
+
@df.fail
|
141
|
+
c = @server.counters[[:plugin1, :plugin_instance1, :counter, 'df error']]
|
142
|
+
c[0].should be_kind_of(Numeric)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: astro-collectd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephan Maka
|
@@ -9,31 +9,37 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-05-
|
12
|
+
date: 2009-05-29 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
16
16
|
description:
|
17
|
-
email:
|
17
|
+
email: astro@spaceboyz.net
|
18
18
|
executables: []
|
19
19
|
|
20
20
|
extensions: []
|
21
21
|
|
22
|
-
extra_rdoc_files:
|
23
|
-
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.rst
|
24
24
|
files:
|
25
|
-
-
|
25
|
+
- README.rst
|
26
|
+
- Rakefile
|
27
|
+
- VERSION.yml
|
28
|
+
- examples/em_sender.rb
|
29
|
+
- examples/sender.rb
|
30
|
+
- lib/collectd.rb
|
26
31
|
- lib/collectd/em_server.rb
|
32
|
+
- lib/collectd/em_support.rb
|
27
33
|
- lib/collectd/interface.rb
|
34
|
+
- lib/collectd/pkt.rb
|
28
35
|
- lib/collectd/proc_stats.rb
|
29
36
|
- lib/collectd/server.rb
|
30
|
-
-
|
31
|
-
- lib/collectd.rb
|
37
|
+
- spec/interface_spec.rb
|
32
38
|
has_rdoc: false
|
33
39
|
homepage: http://github.com/astro/ruby-collectd
|
34
40
|
post_install_message:
|
35
|
-
rdoc_options:
|
36
|
-
|
41
|
+
rdoc_options:
|
42
|
+
- --charset=UTF-8
|
37
43
|
require_paths:
|
38
44
|
- lib
|
39
45
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -53,7 +59,9 @@ requirements: []
|
|
53
59
|
rubyforge_project:
|
54
60
|
rubygems_version: 1.2.0
|
55
61
|
signing_key:
|
56
|
-
specification_version:
|
62
|
+
specification_version: 3
|
57
63
|
summary: Send collectd statistics from Ruby
|
58
|
-
test_files:
|
59
|
-
|
64
|
+
test_files:
|
65
|
+
- spec/interface_spec.rb
|
66
|
+
- examples/sender.rb
|
67
|
+
- examples/em_sender.rb
|