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.
- data/lib/collectd/em_server.rb +21 -0
- data/lib/collectd/em_support.rb +21 -0
- data/lib/collectd/interface.rb +207 -0
- data/lib/collectd/pkt.rb +107 -0
- data/lib/collectd/proc_stats.rb +49 -0
- data/lib/collectd/server.rb +26 -0
- data/lib/collectd.rb +10 -0
- metadata +10 -4
@@ -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
|
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,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
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.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-
|
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:
|