astro-collectd 0.0.6 → 0.0.7

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.
@@ -0,0 +1,21 @@
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
+ Collectd.run_pollables_for self
13
+ Thread.critical = true
14
+ pkt = make_pkt
15
+ Thread.critical = false
16
+ @sock.send(pkt, 0)
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module Collectd
2
+ # EventMachine support stuff. Included in Collectd::Plugin.
3
+ module EmPlugin
4
+ ##
5
+ # Attaches additional callback and errback to deferrable to track
6
+ # a common set of success/error rate/latency
7
+ def track_deferrable(name, deferrable)
8
+ attach_time = Time.now
9
+ deferrable.callback do |*a|
10
+ push_deferrable_values("#{name} success", attach_time)
11
+ end
12
+ deferrable.errback do |*a|
13
+ push_deferrable_values("#{name} error", attach_time)
14
+ end
15
+ end
16
+ def push_deferrable_values(name, attach_time)
17
+ latency(name).gauge = Time.now - attach_time
18
+ counter(name).count! 1
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,207 @@
1
+ require 'collectd/pkt'
2
+ require 'collectd/em_support'
3
+
4
+
5
+ module Collectd
6
+ class << self
7
+
8
+ def hostname
9
+ @@hostname ||= `hostname -f`.strip
10
+ @@hostname
11
+ end
12
+ def hostname=(h)
13
+ @@hostname = h
14
+ end
15
+
16
+ @@servers = []
17
+
18
+ def add_server(interval, addr='ff18::efc0:4a42', port=25826)
19
+ @@servers << Server.new(interval, addr, port)
20
+ end
21
+
22
+ def <<(server)
23
+ @@servers << server
24
+ end
25
+
26
+ def reset!
27
+ @@servers.each do |server|
28
+ server.close if server.respond_to?(:close)
29
+ end
30
+ @@servers = []
31
+ @@pollables = []
32
+ end
33
+
34
+ def each_server(&block)
35
+ @@servers.each(&block)
36
+ end
37
+
38
+ def add_pollable(&block)
39
+ @@pollables ||= []
40
+ @@pollables << block
41
+ end
42
+ def run_pollables_for(server)
43
+ @@pollables ||= []
44
+ @@pollables.each do |block|
45
+ block.call(server)
46
+ end
47
+ end
48
+
49
+ def method_missing(plugin, plugin_instance)
50
+ Plugin.new(plugin, plugin_instance)
51
+ end
52
+
53
+ end
54
+
55
+ ##
56
+ # Interface helper
57
+ class Plugin
58
+ include ProcStats
59
+ include EmPlugin
60
+ def initialize(plugin, plugin_instance)
61
+ @plugin, @plugin_instance = plugin, plugin_instance
62
+ end
63
+ def method_missing(type, type_instance)
64
+ Type.new(@plugin, @plugin_instance, type, type_instance)
65
+ end
66
+ end
67
+
68
+ ##
69
+ # Interface helper
70
+ class Type
71
+ def initialize(plugin, plugin_instance, type, type_instance)
72
+ @plugin, @plugin_instance = plugin, plugin_instance
73
+ @type, @type_instance = type, type_instance
74
+ end
75
+ ##
76
+ # GAUGE
77
+ def gauge=(values)
78
+ values = [values] unless values.kind_of? Array
79
+ Collectd.each_server do |server|
80
+ server.set_gauge(plugin_type, values)
81
+ end
82
+ end
83
+ ##
84
+ # COUNTER
85
+ def counter=(values)
86
+ values = [values] unless values.kind_of? Array
87
+ Collectd.each_server do |server|
88
+ server.set_counter(plugin_type, values)
89
+ end
90
+ end
91
+ def count!(*values)
92
+ Collectd.each_server do |server|
93
+ server.inc_counter(plugin_type, values)
94
+ end
95
+ end
96
+ def polled_gauge(&block)
97
+ Collectd.add_pollable do |server|
98
+ values = block.call
99
+ if values
100
+ values = [values] unless values.kind_of? Array
101
+ server.set_gauge(plugin_type, values)
102
+ end
103
+ end
104
+ end
105
+ def polled_count(&block)
106
+ Collectd.add_pollable do |server|
107
+ values = block.call
108
+ if values
109
+ values = [values] unless values.kind_of? Array
110
+ server.inc_counter(plugin_type, values)
111
+ end
112
+ end
113
+ end
114
+ def polled_counter(&block)
115
+ Collectd.add_pollable do |server|
116
+ values = block.call
117
+ if values
118
+ values = [values] unless values.kind_of? Array
119
+ server.set_counter(plugin_type, values)
120
+ end
121
+ end
122
+ end
123
+ private
124
+ ##
125
+ # [plugin, plugin_instance, type, type_instance]
126
+ def plugin_type
127
+ [@plugin, @plugin_instance, @type, @type_instance]
128
+ end
129
+ end
130
+
131
+ ##
132
+ # Value-holder, baseclass for servers
133
+ class Values
134
+ attr_reader :interval
135
+ def initialize(interval)
136
+ @interval = interval
137
+ @counters = {}
138
+ @gauges = {}
139
+ end
140
+ def set_counter(plugin_type, values)
141
+ @counters[plugin_type] = values
142
+ end
143
+ def inc_counter(plugin_type, values)
144
+ old_values = @counters[plugin_type] || []
145
+ values.map! { |value|
146
+ value + (old_values.shift || 0)
147
+ }
148
+ @counters[plugin_type] = values
149
+ end
150
+ def set_gauge(plugin_type, values)
151
+ # Use count & sums for average
152
+ if @gauges.has_key?(plugin_type)
153
+ old_values = @gauges[plugin_type]
154
+ count = old_values.shift
155
+ values.map! { |value| value + (old_values.shift || value) }
156
+ @gauges[plugin_type] = [count + 1] + values
157
+ else
158
+ @gauges[plugin_type] = [1] + values
159
+ end
160
+ end
161
+
162
+ def make_pkt
163
+ plugin_type_values = {}
164
+ @counters.each do |plugin_types,values|
165
+ plugin, plugin_instance, type, type_instance = plugin_types
166
+ plugin_type_values[plugin] ||= {}
167
+ plugin_type_values[plugin][plugin_instance] ||= {}
168
+ plugin_type_values[plugin][plugin_instance][type] ||= {}
169
+ plugin_type_values[plugin][plugin_instance][type][type_instance] =
170
+ Packet::Values.new(values.map { |value| Packet::Values::Counter.new(value) })
171
+ end
172
+ @gauges.each do |plugin_types,values|
173
+ plugin, plugin_instance, type, type_instance = plugin_types
174
+ plugin_type_values[plugin] ||= {}
175
+ plugin_type_values[plugin][plugin_instance] ||= {}
176
+ plugin_type_values[plugin][plugin_instance][type] ||= {}
177
+ count = values.shift
178
+ values.map! { |value| value.to_f / count }
179
+ plugin_type_values[plugin][plugin_instance][type][type_instance] =
180
+ Packet::Values.new(values.map { |value| Packet::Values::Gauge.new(value) })
181
+ end
182
+ pkt = [Packet::Host.new(Collectd.hostname),
183
+ Packet::Time.new(Time.now.to_i),
184
+ Packet::Interval.new(10)]
185
+ plugin_type_values.each do |plugin,plugin_instances|
186
+ pkt << Packet::Plugin.new(plugin)
187
+ plugin_instances.each do |plugin_instance,types|
188
+ pkt << Packet::PluginInstance.new(plugin_instance)
189
+ types.each do |type,type_instances|
190
+ pkt << Packet::Type.new(type)
191
+ type_instances.each do |type_instance,values|
192
+ pkt << Packet::TypeInstance.new(type_instance)
193
+ pkt << values
194
+ end
195
+ end
196
+ end
197
+ end
198
+
199
+ # Reset only gauges. Counters are persistent for incrementing.
200
+ @gauges = {}
201
+
202
+ # And return serialized packet of parts
203
+ pkt.to_s
204
+ end
205
+ end
206
+
207
+ 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,49 @@
1
+ module Collectd
2
+ ##
3
+ # Included by Interface
4
+ module ProcStats
5
+ def with_polled_memory
6
+ def process_status(field)
7
+ fields = {}
8
+ IO.readlines("/proc/#{$$}/status").each { |line|
9
+ line.strip!
10
+ if line =~ /^(.+?):\s+(.+)$/
11
+ fields[$1] = $2
12
+ end
13
+ }
14
+ fields[field]
15
+ end
16
+
17
+ memory('VmRSS').polled_gauge do
18
+ process_status('VmRSS').to_i * 1024
19
+ end
20
+ memory('VmSize').polled_gauge do
21
+ process_status('VmSize').to_i * 1024
22
+ end
23
+
24
+ self
25
+ end
26
+
27
+ 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
+ cpu('user').polled_counter do
37
+ schedstats[0]
38
+ end
39
+ cpu('wait').polled_counter do
40
+ schedstats[1]
41
+ end
42
+ end
43
+
44
+ def with_full_proc_stats
45
+ with_polled_memory
46
+ with_polled_cpu
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,26 @@
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
+ Collectd.run_pollables_for self
17
+ Thread.critical = true
18
+ pkt = make_pkt
19
+ Thread.critical = false
20
+ @sock.send(pkt, 0)
21
+ end
22
+ end.abort_on_exception = true
23
+ end
24
+
25
+ end
26
+ end
data/lib/collectd.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'collectd/proc_stats'
2
+ require 'collectd/interface'
3
+ require 'collectd/server'
4
+ begin
5
+ require 'collectd/em_server'
6
+ rescue LoadError
7
+ # EM is optional
8
+ end
9
+
10
+
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.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephan Maka
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-05-01 00:00:00 -07:00
12
+ date: 2009-05-27 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -21,8 +21,14 @@ extensions: []
21
21
 
22
22
  extra_rdoc_files: []
23
23
 
24
- files: []
25
-
24
+ files:
25
+ - lib/collectd/pkt.rb
26
+ - lib/collectd/em_server.rb
27
+ - lib/collectd/interface.rb
28
+ - lib/collectd/proc_stats.rb
29
+ - lib/collectd/server.rb
30
+ - lib/collectd/em_support.rb
31
+ - lib/collectd.rb
26
32
  has_rdoc: false
27
33
  homepage: http://github.com/astro/ruby-collectd
28
34
  post_install_message: