instrumental_tools 0.6.0 → 1.0.0.pre.1

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,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