astro-collectd 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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
@@ -0,0 +1,9 @@
1
+ require 'collectd/interface'
2
+ require 'collectd/server'
3
+ begin
4
+ require 'collectd/em_server'
5
+ rescue LoadError
6
+ # EM is optional
7
+ end
8
+
9
+
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
+