astro-collectd 0.0.4
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/lib/collectd/em_server.rb +20 -0
- data/lib/collectd/interface.rb +147 -0
- data/lib/collectd/pkt.rb +107 -0
- data/lib/collectd/server.rb +25 -0
- data/lib/collectd.rb +9 -0
- metadata +57 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
|
3
|
+
module Collectd
|
4
|
+
class EmServer < Values
|
5
|
+
|
6
|
+
def initialize(interval, host, port)
|
7
|
+
super(interval)
|
8
|
+
@sock = UDPSocket.new(host.index(':') ? Socket::AF_INET6 : Socket::AF_INET)
|
9
|
+
@sock.connect(host, port)
|
10
|
+
|
11
|
+
EM.add_periodic_timer(interval) do
|
12
|
+
Thread.critical = true
|
13
|
+
pkt = make_pkt
|
14
|
+
Thread.critical = false
|
15
|
+
@sock.send(pkt, 0)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'collectd/pkt'
|
2
|
+
|
3
|
+
|
4
|
+
module Collectd
|
5
|
+
class << self
|
6
|
+
|
7
|
+
def hostname
|
8
|
+
@@hostname ||= `hostname -f`.strip
|
9
|
+
@@hostname
|
10
|
+
end
|
11
|
+
def hostname=(h)
|
12
|
+
@@hostname = h
|
13
|
+
end
|
14
|
+
|
15
|
+
@@servers = []
|
16
|
+
|
17
|
+
def add_server(interval, addr='ff18::efc0:4a42', port=25826)
|
18
|
+
@@servers << Server.new(interval, addr, port)
|
19
|
+
end
|
20
|
+
|
21
|
+
def each_server(&block)
|
22
|
+
@@servers.each(&block)
|
23
|
+
end
|
24
|
+
|
25
|
+
def method_missing(plugin, plugin_instance)
|
26
|
+
Plugin.new(plugin, plugin_instance)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Interface helper
|
33
|
+
class Plugin
|
34
|
+
def initialize(plugin, plugin_instance)
|
35
|
+
@plugin, @plugin_instance = plugin, plugin_instance
|
36
|
+
end
|
37
|
+
def method_missing(type, type_instance)
|
38
|
+
Type.new(@plugin, @plugin_instance, type, type_instance)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# Interface helper
|
44
|
+
class Type
|
45
|
+
def initialize(plugin, plugin_instance, type, type_instance)
|
46
|
+
@plugin, @plugin_instance = plugin, plugin_instance
|
47
|
+
@type, @type_instance = type, type_instance
|
48
|
+
end
|
49
|
+
def gauge=(values)
|
50
|
+
values = [values] unless values.kind_of? Array
|
51
|
+
Collectd.each_server do |server|
|
52
|
+
server.set_gauge(plugin_type, values)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
def counter=(values)
|
56
|
+
values = [values] unless values.kind_of? Array
|
57
|
+
Collectd.each_server do |server|
|
58
|
+
server.set_counter(plugin_type, values)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
def count!(*values)
|
62
|
+
Collectd.each_server do |server|
|
63
|
+
server.inc_counter(plugin_type, values)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
def plugin_type
|
67
|
+
[@plugin, @plugin_instance, @type, @type_instance]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
##
|
72
|
+
# Value-holder, baseclass for servers
|
73
|
+
class Values
|
74
|
+
attr_reader :interval
|
75
|
+
def initialize(interval)
|
76
|
+
@interval = interval
|
77
|
+
@counters = {}
|
78
|
+
@gauges = {}
|
79
|
+
end
|
80
|
+
def set_counter(plugin_type, values)
|
81
|
+
@counters[plugin_type] = values
|
82
|
+
end
|
83
|
+
def inc_counter(plugin_type, values)
|
84
|
+
old_values = @counters[plugin_type] || []
|
85
|
+
values.map! { |value|
|
86
|
+
value + (old_values.shift || 0)
|
87
|
+
}
|
88
|
+
@counters[plugin_type] = values
|
89
|
+
end
|
90
|
+
def set_gauge(plugin_type, values)
|
91
|
+
# Use count & sums for average
|
92
|
+
if @gauges.has_key?(plugin_type)
|
93
|
+
old_values = @gauges[plugin_type]
|
94
|
+
count = old_values.shift
|
95
|
+
values.map! { |value| value + (old_values.shift || value) }
|
96
|
+
@gauges[plugin_type] = [count + 1] + values
|
97
|
+
else
|
98
|
+
@gauges[plugin_type] = [1] + values
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def make_pkt
|
103
|
+
plugin_type_values = {}
|
104
|
+
@counters.each do |plugin_types,values|
|
105
|
+
plugin, plugin_instance, type, type_instance = plugin_types
|
106
|
+
plugin_type_values[plugin] ||= {}
|
107
|
+
plugin_type_values[plugin][plugin_instance] ||= {}
|
108
|
+
plugin_type_values[plugin][plugin_instance][type] ||= {}
|
109
|
+
plugin_type_values[plugin][plugin_instance][type][type_instance] =
|
110
|
+
Packet::Values.new(values.map { |value| Packet::Values::Counter.new(value) })
|
111
|
+
end
|
112
|
+
@gauges.each do |plugin_types,values|
|
113
|
+
plugin, plugin_instance, type, type_instance = plugin_types
|
114
|
+
plugin_type_values[plugin] ||= {}
|
115
|
+
plugin_type_values[plugin][plugin_instance] ||= {}
|
116
|
+
plugin_type_values[plugin][plugin_instance][type] ||= {}
|
117
|
+
count = values.shift
|
118
|
+
values.map! { |value| value.to_f / count }
|
119
|
+
plugin_type_values[plugin][plugin_instance][type][type_instance] =
|
120
|
+
Packet::Values.new(values.map { |value| Packet::Values::Gauge.new(value) })
|
121
|
+
end
|
122
|
+
pkt = [Packet::Host.new(Collectd.hostname),
|
123
|
+
Packet::Time.new(Time.now.to_i),
|
124
|
+
Packet::Interval.new(10)]
|
125
|
+
plugin_type_values.each do |plugin,plugin_instances|
|
126
|
+
pkt << Packet::Plugin.new(plugin)
|
127
|
+
plugin_instances.each do |plugin_instance,types|
|
128
|
+
pkt << Packet::PluginInstance.new(plugin_instance)
|
129
|
+
types.each do |type,type_instances|
|
130
|
+
pkt << Packet::Type.new(type)
|
131
|
+
type_instances.each do |type_instance,values|
|
132
|
+
pkt << Packet::TypeInstance.new(type_instance)
|
133
|
+
pkt << values
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Reset only gauges. Counters are persistent for incrementing.
|
140
|
+
@gauges = {}
|
141
|
+
|
142
|
+
# And return serialized packet of parts
|
143
|
+
pkt.to_s
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
data/lib/collectd/pkt.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
module Collectd
|
2
|
+
module Packet
|
3
|
+
|
4
|
+
class Part
|
5
|
+
def to_s(content)
|
6
|
+
[type, content.length + 4].pack("nn") + content
|
7
|
+
end
|
8
|
+
|
9
|
+
##
|
10
|
+
# Makes subclasses more declarative
|
11
|
+
def self.type(number)
|
12
|
+
define_method(:type) { number }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class String < Part
|
17
|
+
def initialize(s)
|
18
|
+
@s = s
|
19
|
+
end
|
20
|
+
def to_s
|
21
|
+
super "#{@s}\000"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Number < Part
|
26
|
+
def initialize(n)
|
27
|
+
@n = n
|
28
|
+
end
|
29
|
+
def to_s
|
30
|
+
super [@n >> 32, @n & 0xffffffff].pack("NN")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Host < String
|
35
|
+
type 0
|
36
|
+
end
|
37
|
+
|
38
|
+
class Time < Number
|
39
|
+
type 1
|
40
|
+
end
|
41
|
+
|
42
|
+
class Plugin < String
|
43
|
+
type 2
|
44
|
+
end
|
45
|
+
|
46
|
+
class PluginInstance < String
|
47
|
+
type 3
|
48
|
+
end
|
49
|
+
|
50
|
+
class Type < String
|
51
|
+
type 4
|
52
|
+
end
|
53
|
+
|
54
|
+
class TypeInstance < String
|
55
|
+
type 5
|
56
|
+
end
|
57
|
+
|
58
|
+
class Values < Part
|
59
|
+
type 6
|
60
|
+
def initialize(v)
|
61
|
+
@v = v
|
62
|
+
end
|
63
|
+
def to_s
|
64
|
+
types, values = [], []
|
65
|
+
@v.each { |v1|
|
66
|
+
types << [v1.type].pack("C")
|
67
|
+
values << v1.to_s
|
68
|
+
}
|
69
|
+
super [@v.length].pack("n") + types.join + values.join
|
70
|
+
end
|
71
|
+
|
72
|
+
class Counter < Part
|
73
|
+
type 0
|
74
|
+
def initialize(c)
|
75
|
+
@c = c
|
76
|
+
end
|
77
|
+
def to_s
|
78
|
+
[@c >> 32, @c & 0xffffffff].pack("NN")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class Gauge < Part
|
83
|
+
type 1
|
84
|
+
def initialize(f)
|
85
|
+
@f = f
|
86
|
+
end
|
87
|
+
def to_s
|
88
|
+
[@f].pack("d")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class Interval < Number
|
94
|
+
type 7
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
class Message < String
|
99
|
+
type 0x100
|
100
|
+
end
|
101
|
+
|
102
|
+
class Severity < Number
|
103
|
+
type 0x101
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'thread'
|
3
|
+
|
4
|
+
module Collectd
|
5
|
+
class Server < Values
|
6
|
+
|
7
|
+
def initialize(interval, host, port)
|
8
|
+
super(interval)
|
9
|
+
@sock = UDPSocket.new(Socket::AF_INET6)
|
10
|
+
@sock.connect(host, port)
|
11
|
+
|
12
|
+
Thread.new do
|
13
|
+
loop do
|
14
|
+
sleep interval
|
15
|
+
|
16
|
+
Thread.critical = true
|
17
|
+
pkt = make_pkt
|
18
|
+
Thread.critical = false
|
19
|
+
@sock.send(pkt, 0)
|
20
|
+
end
|
21
|
+
end.abort_on_exception = true
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
data/lib/collectd.rb
ADDED
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: astro-collectd
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stephan Maka
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-04-25 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: stephan@spaceboyz.net
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- lib/collectd/interface.rb
|
26
|
+
- lib/collectd/pkt.rb
|
27
|
+
- lib/collectd/server.rb
|
28
|
+
- lib/collectd/em_server.rb
|
29
|
+
- lib/collectd.rb
|
30
|
+
has_rdoc: false
|
31
|
+
homepage: http://github.com/astro/ruby-collectd
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options: []
|
34
|
+
|
35
|
+
require_paths:
|
36
|
+
- lib
|
37
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: "0"
|
42
|
+
version:
|
43
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: "0"
|
48
|
+
version:
|
49
|
+
requirements: []
|
50
|
+
|
51
|
+
rubyforge_project:
|
52
|
+
rubygems_version: 1.2.0
|
53
|
+
signing_key:
|
54
|
+
specification_version: 2
|
55
|
+
summary: Send collectd statistics from Ruby
|
56
|
+
test_files: []
|
57
|
+
|