instrumental_agent 0.4.0 → 0.5.0

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/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --format Fuubar
data/Guardfile CHANGED
@@ -1,4 +1,4 @@
1
- guard 'rspec', :version => 2 do
1
+ guard 'rspec', :version => 2, :cli => '--format Fuubar' do
2
2
  watch(%r{^spec/.+_spec\.rb$})
3
3
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
4
4
  watch(%r{spec/(spec_helper|test_server).rb}) { "spec/" }
@@ -1,225 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'rubygems'
4
- $: << File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
5
- require 'instrumental_agent'
6
-
7
-
8
- class SystemInspector
9
- TYPES = [:gauges, :incrementors]
10
- attr_accessor *TYPES
11
-
12
- def initialize
13
- @gauges = {}
14
- @incrementors = {}
15
- @platform =
16
- case RUBY_PLATFORM
17
- when /linux/
18
- Linux
19
- when /darwin/
20
- OSX
21
- else
22
- raise "unsupported OS"
23
- end
24
- end
25
-
26
- def load_all
27
- load @platform.load_cpu
28
- load @platform.load_memory
29
- load @platform.load_disks
30
- end
31
-
32
- def load(stats)
33
- @gauges.merge!(stats[:gauges] || {})
34
- end
35
-
36
- module OSX
37
- def self.load_cpu
38
- { :gauges => top }
39
- end
40
-
41
- def self.top
42
- lines = []
43
- processes = date = load = cpu = nil
44
- IO.popen('top -l 1 -n 0') do |top|
45
- processes = top.gets.split(': ')[1]
46
- date = top.gets
47
- load = top.gets.split(': ')[1]
48
- cpu = top.gets.split(': ')[1]
49
- end
50
-
51
- user, system, idle = cpu.split(", ").map { |v| v.to_f }
52
- load1, load5, load15 = load.split(", ").map { |v| v.to_f }
53
- total, running, stuck, sleeping, threads = processes.split(", ").map { |v| v.to_i }
54
-
55
- {
56
- 'cpu.user' => user,
57
- 'cpu.system' => system,
58
- 'cpu.idle' => idle,
59
- 'load.1min' => load1,
60
- 'load.5min' => load5,
61
- 'load.15min' => load15,
62
- 'processes.total' => total,
63
- 'processes.running' => running,
64
- 'processes.stuck' => stuck,
65
- 'processes.sleeping' => sleeping,
66
- 'threads' => threads,
67
- }
68
- end
69
-
70
- def self.load_memory
71
- # TODO: swap
72
- { :gauges => vm_stat }
73
- end
74
-
75
- def self.vm_stat
76
- header, *rows = `vm_stat`.split("\n")
77
- page_size = header.match(/page size of (\d+) bytes/)[1].to_i
78
- sections = ["free", "active", "inactive", "wired", "speculative", "wired down"]
79
- output = {}
80
- total = 0.0
81
- rows.each do |row|
82
- if match = row.match(/Pages (.*):\s+(\d+)\./)
83
- section, value = match[1, 2]
84
- if sections.include?(section)
85
- value = value.to_f * page_size / 1024 / 1024
86
- output["memory.#{section.gsub(' ', '_')}_mb"] = value
87
- total += value
88
- end
89
- end
90
- end
91
- output["memory.free_percent"] = output["memory.free_mb"] / total * 100 # TODO: verify
92
- output
93
- end
94
-
95
- def self.load_disks
96
- { :gauges => df }
97
- end
98
-
99
- def self.df
100
- output = {}
101
- `df -k`.split("\n").grep(%r{^/dev/}).each do |line|
102
- device, total, used, available, capacity, mount = line.split(/\s+/)
103
- names = [File.basename(device)]
104
- names << 'root' if mount == '/'
105
- names.each do |name|
106
- output["disk.#{name}.total_mb"] = total.to_f / 1024
107
- output["disk.#{name}.used_mb"] = used.to_f / 1024
108
- output["disk.#{name}.available_mb"] = available.to_f / 1024
109
- output["disk.#{name}.available_percent"] = available.to_f / total.to_f * 100
110
- end
111
- end
112
- output
113
- end
114
-
115
- def self.netstat(interface = 'en1')
116
- # mostly functional network io stats
117
- headers, *lines = `netstat -ibI #{interface}`.split("\n").map { |l| l.split(/\s+/) } # FIXME: vulnerability?
118
- headers = headers.map { |h| h.downcase }
119
- lines.each do |line|
120
- if !line[3].include?(':')
121
- return Hash[headers.zip(line)]
122
- end
123
- end
124
- end
125
- end
126
-
127
- module Linux
128
- def self.load_cpu
129
- output = { :gauges => {} }
130
- output[:gauges].merge!(cpu)
131
- output[:gauges].merge!(loadavg)
132
- output
133
- end
134
-
135
- def self.cpu
136
- cpu, user, nice, system, idle, iowait = `cat /proc/stat | grep cpu[^0-9]`.chomp.split(/\s+/)
137
- total = user.to_i + system.to_i + idle.to_i + iowait.to_i
138
- {
139
- 'cpu.user' => (user.to_f / total) * 100,
140
- 'cpu.system' => (system.to_f / total) * 100,
141
- 'cpu.idle' => (idle.to_f / total) * 100,
142
- 'cpu.iowait' => (iowait.to_f / total) * 100,
143
- }
144
- end
145
-
146
- def self.loadavg
147
- min_1, min_5, min_15 = `cat /proc/loadavg`.split(/\s+/)
148
- {
149
- 'load.1min' => min_1.to_f,
150
- 'load.5min' => min_5.to_f,
151
- 'load.15min' => min_15.to_f,
152
- }
153
- end
154
-
155
- def self.load_memory
156
- output = { :gauges => {} }
157
- output[:gauges].merge!(memory)
158
- output[:gauges].merge!(swap)
159
- output
160
- end
161
-
162
- def self.memory
163
- _, total, used, free, shared, buffers, cached = `free -k -o | grep Mem`.chomp.split(/\s+/)
164
- {
165
- 'memory.used_mb' => used.to_f / 1024,
166
- 'memory.free_mb' => free.to_f / 1024,
167
- 'memory.buffers_mb' => buffers.to_f / 1024,
168
- 'memory.cached_mb' => cached.to_f / 1024,
169
- 'memory.free_percent' => (free.to_f / total.to_f) * 100,
170
- }
171
- end
172
-
173
- def self.swap
174
- _, total, used, free = `free -k -o | grep Swap`.chomp.split(/\s+/)
175
- {
176
- 'swap.used_mb' => used.to_f / 1024,
177
- 'swap.free_mb' => free.to_f / 1024,
178
- 'swap.free_percent' => (free.to_f / total.to_f) * 100,
179
- }
180
- end
181
-
182
- def self.load_disks
183
- { :gauges => disks }
184
- end
185
-
186
- def self.disks
187
- output = {}
188
- `df -Pk`.split("\n").grep(%r{^/dev/}).each do |line|
189
- device, total, used, available, capacity, mount = line.split(/\s+/)
190
- names = [File.basename(device)]
191
- names << 'root' if mount == '/'
192
- names.each do |name|
193
- output["disk.#{name}.total_mb"] = total.to_f / 1024
194
- output["disk.#{name}.used_mb"] = used.to_f / 1024
195
- output["disk.#{name}.available_mb"] = available.to_f / 1024
196
- output["disk.#{name}.available_percent"] = available.to_f / total.to_f * 100
197
- end
198
- end
199
- output
200
- end
201
- end
202
- end
203
-
204
- # TODO: utilization
205
-
206
- token, collector = *ARGV
207
- unless token
208
- puts "Usage: #{$0} <token> [collector]"
209
- exit 1
210
- end
211
- I = Instrumental::Agent.new(token, :collector => collector)
212
-
213
- host = `hostname`.chomp
214
-
215
- puts "Collecting stats under the hostname: #{host}"
216
-
217
- loop do
218
- inspector = SystemInspector.new
219
- inspector.load_all
220
- inspector.gauges.each do |stat, value|
221
- I.gauge("#{host}.#{stat}", value)
222
- end
223
- # I.increment("#{host}.#{stat}", delta)
224
- sleep 10
225
- end
3
+ puts '***********************************'
4
+ puts '*** Moved to instrumental_tools ***'
5
+ puts '***********************************'
6
+ puts "\ngem install instrumental_tools\n"
7
+ exit 1
@@ -20,4 +20,5 @@ Gem::Specification.new do |s|
20
20
  s.add_development_dependency(%q<guard-rspec>, [">= 0"])
21
21
  s.add_development_dependency(%q<growl_notify>, [">= 0"])
22
22
  s.add_development_dependency(%q<rb-fsevent>, [">= 0"])
23
+ s.add_development_dependency(%q<fuubar>, [">= 0"])
23
24
  end
@@ -101,24 +101,35 @@ module Instrumental
101
101
  @socket && !@socket.closed?
102
102
  end
103
103
 
104
+ def logger=(logger)
105
+ @logger = logger
106
+ end
107
+
104
108
  def logger
105
- self.class.logger
109
+ @logger ||= self.class.logger
106
110
  end
107
111
 
108
112
  private
109
113
 
110
114
  def valid?(metric, value, time)
111
- if metric !~ /^([\d\w\-_]+\.)*[\d\w\-_]+$/i
112
- increment 'agent.invalid_metric'
113
- logger.warn "Invalid metric #{metric}"
114
- return false
115
- end
116
- if value.to_s !~ /^\d+(\.\d+)?$/
117
- increment 'agent.invalid_value'
118
- logger.warn "Invalid value #{value.inspect} for #{metric}"
119
- return false
120
- end
121
- true
115
+ valid_metric = metric =~ /^([\d\w\-_]+\.)*[\d\w\-_]+$/i
116
+ valid_value = value.to_s =~ /^-?\d+(\.\d+)?$/
117
+
118
+ return true if valid_metric && valid_value
119
+
120
+ report_invalid_metric(metric) unless valid_metric
121
+ report_invalid_value(metric, value) unless valid_value
122
+ false
123
+ end
124
+
125
+ def report_invalid_metric(metric)
126
+ increment "agent.invalid_metric"
127
+ logger.warn "Invalid metric #{metric}"
128
+ end
129
+
130
+ def report_invalid_value(metric, value)
131
+ increment "agent.invalid_value"
132
+ logger.warn "Invalid value #{value.inspect} for #{metric}"
122
133
  end
123
134
 
124
135
  def report_exception(e)
@@ -1,3 +1,3 @@
1
1
  module Instrumental
2
- VERSION = "0.4.0"
2
+ VERSION = "0.5.0"
3
3
  end
data/spec/agent_spec.rb CHANGED
@@ -180,4 +180,39 @@ describe Instrumental::Agent, "enabled" do
180
180
  end
181
181
  @agent.increment("test").should be_nil
182
182
  end
183
+
184
+ it "should track invalid metrics" do
185
+ @agent.logger.should_receive(:warn).with(/%%/)
186
+ @agent.increment(' %% .!#@$%^&*', 1, 1)
187
+ wait
188
+ @server.commands.join("\n").should include("increment agent.invalid_metric")
189
+ end
190
+
191
+ it "should allow reasonable metric names" do
192
+ @agent.increment('a')
193
+ @agent.increment('a.b')
194
+ @agent.increment('hello.world')
195
+ @agent.increment('ThisIsATest.Of.The.Emergency.Broadcast.System.12345')
196
+ wait
197
+ @server.commands.join("\n").should_not include("increment agent.invalid_metric")
198
+ end
199
+
200
+ it "should track invalid values" do
201
+ @agent.logger.should_receive(:warn).with(/hello.*testington/)
202
+ @agent.increment('testington', 'hello')
203
+ wait
204
+ @server.commands.join("\n").should include("increment agent.invalid_value")
205
+ end
206
+
207
+ it "should allow reasonable values" do
208
+ @agent.increment('a', -333.333)
209
+ @agent.increment('a', -2.2)
210
+ @agent.increment('a', -1)
211
+ @agent.increment('a', 0)
212
+ @agent.increment('a', 1)
213
+ @agent.increment('a', 2.2)
214
+ @agent.increment('a', 333.333)
215
+ wait
216
+ @server.commands.join("\n").should_not include("increment agent.invalid_value")
217
+ end
183
218
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: instrumental_agent
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
5
- prerelease:
4
+ prerelease: false
6
5
  segments:
7
6
  - 0
8
- - 4
7
+ - 5
9
8
  - 0
10
- version: 0.4.0
9
+ segments_generated: true
10
+ version: 0.5.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Elijah Miller
@@ -17,94 +17,101 @@ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
19
 
20
- date: 2011-12-01 00:00:00 -05:00
20
+ date: 2011-12-09 00:00:00 -05:00
21
21
  default_executable:
22
22
  dependencies:
23
23
  - !ruby/object:Gem::Dependency
24
- name: rake
25
- prerelease: false
26
- requirement: &id001 !ruby/object:Gem::Requirement
27
- none: false
24
+ version_requirements: &id001 !ruby/object:Gem::Requirement
28
25
  requirements:
29
26
  - - ">="
30
27
  - !ruby/object:Gem::Version
31
- hash: 3
32
28
  segments:
33
29
  - 0
30
+ segments_generated: true
34
31
  version: "0"
32
+ requirement: *id001
33
+ name: rake
34
+ prerelease: false
35
35
  type: :development
36
- version_requirements: *id001
37
36
  - !ruby/object:Gem::Dependency
38
- name: rspec
39
- prerelease: false
40
- requirement: &id002 !ruby/object:Gem::Requirement
41
- none: false
37
+ version_requirements: &id002 !ruby/object:Gem::Requirement
42
38
  requirements:
43
39
  - - ~>
44
40
  - !ruby/object:Gem::Version
45
- hash: 3
46
41
  segments:
47
42
  - 2
48
43
  - 0
44
+ segments_generated: true
49
45
  version: "2.0"
46
+ requirement: *id002
47
+ name: rspec
48
+ prerelease: false
50
49
  type: :development
51
- version_requirements: *id002
52
50
  - !ruby/object:Gem::Dependency
53
- name: guard
54
- prerelease: false
55
- requirement: &id003 !ruby/object:Gem::Requirement
56
- none: false
51
+ version_requirements: &id003 !ruby/object:Gem::Requirement
57
52
  requirements:
58
53
  - - ">="
59
54
  - !ruby/object:Gem::Version
60
- hash: 3
61
55
  segments:
62
56
  - 0
57
+ segments_generated: true
63
58
  version: "0"
59
+ requirement: *id003
60
+ name: guard
61
+ prerelease: false
64
62
  type: :development
65
- version_requirements: *id003
66
63
  - !ruby/object:Gem::Dependency
67
- name: guard-rspec
68
- prerelease: false
69
- requirement: &id004 !ruby/object:Gem::Requirement
70
- none: false
64
+ version_requirements: &id004 !ruby/object:Gem::Requirement
71
65
  requirements:
72
66
  - - ">="
73
67
  - !ruby/object:Gem::Version
74
- hash: 3
75
68
  segments:
76
69
  - 0
70
+ segments_generated: true
77
71
  version: "0"
72
+ requirement: *id004
73
+ name: guard-rspec
74
+ prerelease: false
78
75
  type: :development
79
- version_requirements: *id004
80
76
  - !ruby/object:Gem::Dependency
81
- name: growl_notify
82
- prerelease: false
83
- requirement: &id005 !ruby/object:Gem::Requirement
84
- none: false
77
+ version_requirements: &id005 !ruby/object:Gem::Requirement
85
78
  requirements:
86
79
  - - ">="
87
80
  - !ruby/object:Gem::Version
88
- hash: 3
89
81
  segments:
90
82
  - 0
83
+ segments_generated: true
91
84
  version: "0"
85
+ requirement: *id005
86
+ name: growl_notify
87
+ prerelease: false
92
88
  type: :development
93
- version_requirements: *id005
94
89
  - !ruby/object:Gem::Dependency
90
+ version_requirements: &id006 !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ segments:
95
+ - 0
96
+ segments_generated: true
97
+ version: "0"
98
+ requirement: *id006
95
99
  name: rb-fsevent
96
100
  prerelease: false
97
- requirement: &id006 !ruby/object:Gem::Requirement
98
- none: false
101
+ type: :development
102
+ - !ruby/object:Gem::Dependency
103
+ version_requirements: &id007 !ruby/object:Gem::Requirement
99
104
  requirements:
100
105
  - - ">="
101
106
  - !ruby/object:Gem::Version
102
- hash: 3
103
107
  segments:
104
108
  - 0
109
+ segments_generated: true
105
110
  version: "0"
111
+ requirement: *id007
112
+ name: fuubar
113
+ prerelease: false
106
114
  type: :development
107
- version_requirements: *id006
108
115
  description: Keep track of anything.
109
116
  email:
110
117
  - support@instrumentalapp.com
@@ -116,6 +123,7 @@ extra_rdoc_files: []
116
123
 
117
124
  files:
118
125
  - .gitignore
126
+ - .rspec
119
127
  - Gemfile
120
128
  - Guardfile
121
129
  - README.rdoc
@@ -142,27 +150,25 @@ rdoc_options: []
142
150
  require_paths:
143
151
  - lib
144
152
  required_ruby_version: !ruby/object:Gem::Requirement
145
- none: false
146
153
  requirements:
147
154
  - - ">="
148
155
  - !ruby/object:Gem::Version
149
- hash: 3
150
156
  segments:
151
157
  - 0
158
+ segments_generated: true
152
159
  version: "0"
153
160
  required_rubygems_version: !ruby/object:Gem::Requirement
154
- none: false
155
161
  requirements:
156
162
  - - ">="
157
163
  - !ruby/object:Gem::Version
158
- hash: 3
159
164
  segments:
160
165
  - 0
166
+ segments_generated: true
161
167
  version: "0"
162
168
  requirements: []
163
169
 
164
170
  rubyforge_project:
165
- rubygems_version: 1.6.1
171
+ rubygems_version: 1.3.6
166
172
  signing_key:
167
173
  specification_version: 3
168
174
  summary: Agent for reporting data to instrumentalapp.com