instrumental_tools 0.6.0 → 1.0.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,114 @@
1
+ class SystemInspector
2
+ module OSX
3
+ def self.load_cpu
4
+ output = { :gauges => {} }
5
+ if SystemInspector.command_present?('top', 'CPU')
6
+ output[:gauges].merge!(top)
7
+ end
8
+ output
9
+ end
10
+
11
+ def self.top
12
+ lines = []
13
+ processes = date = load = cpu = nil
14
+
15
+ IO.popen('top -l 1 -n 0') do |top|
16
+ processes = top.gets.split(': ')[1]
17
+ date = top.gets
18
+ load = top.gets.split(': ')[1]
19
+ cpu = top.gets.split(': ')[1]
20
+ end
21
+
22
+ user, system, idle = cpu.split(", ").map { |v| v.to_f }
23
+ load1, load5, load15 = load.split(", ").map { |v| v.to_f }
24
+ total, running, stuck, sleeping, threads = processes.split(", ").map { |v| v.to_i }
25
+
26
+ {
27
+ 'cpu.user' => user,
28
+ 'cpu.system' => system,
29
+ 'cpu.idle' => idle,
30
+ 'load.1min' => load1,
31
+ 'load.5min' => load5,
32
+ 'load.15min' => load15,
33
+ 'processes.total' => total,
34
+ 'processes.running' => running,
35
+ 'processes.stuck' => stuck,
36
+ 'processes.sleeping' => sleeping,
37
+ 'threads' => threads,
38
+ }
39
+ end
40
+
41
+ def self.load_memory
42
+ # TODO: swap
43
+ output = { :gauges => {} }
44
+ if SystemInspector.command_present?('vm_stat', 'memory')
45
+ output[:gauges].merge!(vm_stat)
46
+ end
47
+ output
48
+ end
49
+
50
+ def self.vm_stat
51
+ header, *rows = `vm_stat`.lines.map(&:chomp)
52
+ page_size = header.match(/page size of (\d+) bytes/)[1].to_i
53
+ sections = ["free", "active", "inactive", "wired", "speculative", "wired down"]
54
+ output = {}
55
+ total = 0.0
56
+
57
+ rows.each do |row|
58
+ if match = row.match(/Pages (.*):\s+(\d+)\./)
59
+ section, value = match[1, 2]
60
+ if sections.include?(section)
61
+ value = value.to_f * page_size / 1024 / 1024
62
+ output["memory.#{section.gsub(' ', '_')}_mb"] = value
63
+ total += value
64
+ end
65
+ end
66
+ end
67
+ output["memory.free_percent"] = output["memory.free_mb"] / total * 100 # TODO: verify
68
+ output
69
+ end
70
+
71
+ def self.load_disks
72
+ output = { :gauges => {} }
73
+ if SystemInspector.command_present?('df', 'disk')
74
+ output[:gauges].merge!(df)
75
+ end
76
+ output
77
+ end
78
+
79
+ def self.df
80
+ output = {}
81
+ `df -k`.lines.grep(%r{^/dev/}).each do |line|
82
+
83
+ device, total, used, available, capacity, mount = line.chomp.split
84
+
85
+ names = [File.basename(device)]
86
+ names << 'root' if mount == '/'
87
+
88
+ names.each do |name|
89
+ output["disk.#{name}.total_mb"] = total.to_f / 1024
90
+ output["disk.#{name}.used_mb"] = used.to_f / 1024
91
+ output["disk.#{name}.available_mb"] = available.to_f / 1024
92
+ output["disk.#{name}.available_percent"] = available.to_f / total.to_f * 100
93
+ end
94
+
95
+ end
96
+ output
97
+ end
98
+
99
+ def self.netstat(interface = 'en1')
100
+ # mostly functional network io stats
101
+ headers, *lines = `netstat -ibI #{interface}`.lines.map { |l| l.split } # FIXME: vulnerability?
102
+ headers = headers.map { |h| h.downcase }
103
+ lines.each do |line|
104
+ if !line[3].include?(':')
105
+ return Hash[headers.zip(line)]
106
+ end
107
+ end
108
+ end
109
+
110
+ def self.load_filesystem
111
+ {}
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,67 @@
1
+ class SystemInspector
2
+ TYPES = [:gauges, :incrementors]
3
+ attr_accessor *TYPES
4
+
5
+ def self.memory
6
+ @memory ||= Memory.new
7
+ end
8
+
9
+ def initialize
10
+ @gauges = {}
11
+ @incrementors = {}
12
+ @platform =
13
+ case RUBY_PLATFORM
14
+ when /linux/
15
+ require "instrumental_tools/system_inspector/linux"
16
+ SystemInspector::Linux
17
+ when /darwin/
18
+ require "instrumental_tools/system_inspector/osx"
19
+ SystemInspector::OSX
20
+ else
21
+ raise "unsupported OS"
22
+ end
23
+ end
24
+
25
+ def self.command_missing(command, section)
26
+ puts "Command #{command} not found. Metrics for #{section} will not be collected."
27
+ end
28
+
29
+ def self.command_present?(command, section)
30
+ `which #{command}`.length > 0 || command_missing(command, section)
31
+ end
32
+
33
+ def load_all
34
+ self.class.memory.cycle
35
+
36
+ load @platform.load_cpu
37
+ load @platform.load_memory
38
+ load @platform.load_disks
39
+ load @platform.load_filesystem
40
+ end
41
+
42
+ def load(stats)
43
+ @gauges.merge!(stats[:gauges] || {})
44
+ end
45
+
46
+ class Memory
47
+ attr_reader :past_values, :current_values
48
+
49
+ def initialize
50
+ @past_values = {}
51
+ @current_values = {}
52
+ end
53
+
54
+ def store(attribute, value)
55
+ @current_values[attribute] = value
56
+ end
57
+
58
+ def retrieve(attribute)
59
+ @past_values[attribute]
60
+ end
61
+
62
+ def cycle
63
+ @past_values = @current_values
64
+ @current_values = {}
65
+ end
66
+ end
67
+ end
@@ -1,5 +1,5 @@
1
1
  module Instrumental
2
2
  module Tools
3
- VERSION = "0.6.0"
3
+ VERSION = "1.0.0.pre.1"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: instrumental_tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 1.0.0.pre.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elijah Miller
@@ -11,22 +11,8 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2014-12-14 00:00:00.000000000 Z
14
+ date: 2015-03-10 00:00:00.000000000 Z
15
15
  dependencies:
16
- - !ruby/object:Gem::Dependency
17
- name: json
18
- requirement: !ruby/object:Gem::Requirement
19
- requirements:
20
- - - ">="
21
- - !ruby/object:Gem::Version
22
- version: '0'
23
- type: :runtime
24
- prerelease: false
25
- version_requirements: !ruby/object:Gem::Requirement
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- version: '0'
30
16
  - !ruby/object:Gem::Dependency
31
17
  name: instrumental_agent
32
18
  requirement: !ruby/object:Gem::Requirement
@@ -80,13 +66,26 @@ extra_rdoc_files: []
80
66
  files:
81
67
  - ".gitignore"
82
68
  - CHANGELOG.md
69
+ - CUSTOM_METRICS.md
83
70
  - Gemfile
84
71
  - LICENSE
85
72
  - README.md
86
73
  - Rakefile
87
74
  - bin/instrument_server
75
+ - examples/README.md
76
+ - examples/docker/README.md
77
+ - examples/docker/docker.rb
78
+ - examples/mongo/README.md
79
+ - examples/mongo/mongo_3.rb
80
+ - examples/mysql/README.md
81
+ - examples/mysql/mysql_status.rb
88
82
  - instrumental_tools.gemspec
89
83
  - lib/instrumental_tools/capistrano.rb
84
+ - lib/instrumental_tools/metric_script_executor.rb
85
+ - lib/instrumental_tools/server_controller.rb
86
+ - lib/instrumental_tools/system_inspector.rb
87
+ - lib/instrumental_tools/system_inspector/linux.rb
88
+ - lib/instrumental_tools/system_inspector/osx.rb
90
89
  - lib/instrumental_tools/version.rb
91
90
  homepage: http://github.com/expectedbehavior/instrumental_tools
92
91
  licenses: []
@@ -99,12 +98,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
99
98
  requirements:
100
99
  - - ">="
101
100
  - !ruby/object:Gem::Version
102
- version: '0'
101
+ version: '1.9'
103
102
  required_rubygems_version: !ruby/object:Gem::Requirement
104
103
  requirements:
105
- - - ">="
104
+ - - ">"
106
105
  - !ruby/object:Gem::Version
107
- version: '0'
106
+ version: 1.3.1
108
107
  requirements: []
109
108
  rubyforge_project:
110
109
  rubygems_version: 2.2.2