astro-collectd 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: