newrelic_zfs 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9fdd5091dd94e9ea8d6b2b9ac4a6f856b6a8f8b9
4
+ data.tar.gz: 4be49358deb4349c9ce20f31cecda0bf79d1e6bf
5
+ SHA512:
6
+ metadata.gz: 4726fd516e06b68227dbcce1af4cd46c9afa61a3a6dd3f910dd5aadc5673291d587ac221d011481792230ddd7a53b5642236f2acb19b8c573b3eb01d70925b00
7
+ data.tar.gz: cd7ba440866b75b6fb57ac14a0188b6eb8b94826b9c385baa5f2be0da4b5f9d7cbf3edaea4bdb0ba79825a7c101ed7127e68779d0916ddf7aa5b9778fdc604d5
data/bin/newrelic_zfs ADDED
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+
6
+ require 'newrelic_plugin'
7
+ require 'trollop'
8
+
9
+ require 'newrelic_zfs'
10
+ require 'newrelic_zfs/config'
11
+
12
+ module ZfsAgent
13
+
14
+ class Agent < NewRelic::Plugin::Agent::Base
15
+
16
+ agent_guid 'com.tomreay.newrelic-zfs'
17
+ agent_version '1.0.0'
18
+ agent_config_options :instance_name, :print_metrics
19
+ agent_human_labels("ZFS Agent") { instance_name }
20
+
21
+ def poll_cycle
22
+ collector = ZFSTools::Collector.new
23
+ stats = collector.collect_stats
24
+ health_total = 0
25
+ stats.each do |stat|
26
+ if stat.name == 'UnhealthyCount'
27
+ health_total = health_total + stat.value
28
+ end
29
+
30
+ stat_name = 'ZPools/' + stat.name + '/' + stat.pool_name
31
+ if print_metrics
32
+ puts 'Reporting metric named ' + stat_name + ' with value ' + stat.value.to_s + ' and unit ' + stat.unit
33
+ end
34
+ report_metric stat_name, stat.unit, stat.value
35
+ end
36
+
37
+ stat_name = 'ZPools/UnhealthyCount'
38
+ if print_metrics
39
+ puts 'Reporting metric named ' + stat_name + ' with value ' + health_total.to_s + ' and unit Value'
40
+ end
41
+ report_metric stat_name, 'Value', health_total
42
+ end
43
+ end
44
+
45
+
46
+ opts = Trollop::options do
47
+ opt :config_file, "Config file", :type => :string
48
+ end
49
+
50
+ config_file_path = ZfsConfig::get_config_location(ARGV[0])
51
+ if config_file_path.nil?
52
+ exit
53
+ end
54
+
55
+ NewRelic::Plugin::Config::config_file = config_file_path
56
+ NewRelic::Plugin::Setup.install_agent :zfs, ZfsAgent
57
+ NewRelic::Plugin::Run.setup_and_run
58
+
59
+ puts 'Newrelic ZFS Agent started'
60
+ end
@@ -0,0 +1,116 @@
1
+ module ZFSTools
2
+ class Stat
3
+ attr_reader :pool_name
4
+ attr_reader :name
5
+ attr_reader :unit
6
+ attr_reader :value
7
+
8
+ def initialize(pool_name, name, unit, value)
9
+ @pool_name = pool_name
10
+ @name = name
11
+ @unit = unit
12
+ @value = value
13
+ end
14
+ end
15
+
16
+ class Pool
17
+ BLACK_LIST = ['Altroot']
18
+
19
+ attr_accessor :name
20
+ attr_reader :values
21
+
22
+ def initialize()
23
+ @values = {}
24
+ end
25
+
26
+ def add_value(heading, value)
27
+ if !BLACK_LIST.include?(heading)
28
+ @values.merge!({ heading => value })
29
+ end
30
+ end
31
+ end
32
+
33
+ class Converter
34
+ UNITS = { 'B' => 'bytes', 'K' => 'kilobytes', 'M' => 'megabytes', 'G' => 'gigabytes', 'T' => 'terabytes', 'P' => 'petabytes'}
35
+ HEADINGS = { 'Health' => 'UnhealthyCount' }
36
+
37
+ def convert(heading, value)
38
+ values = _split(value)
39
+ return [ _convert(heading, HEADINGS), _convert_d(values[1], UNITS, 'Value'), values[0] ]
40
+ end
41
+
42
+ def _split(value)
43
+ match = /\d+\.?\d*/.match(value)
44
+ #If numeric value
45
+ if match
46
+ numeric_part = match[0]
47
+ unit = value.slice(numeric_part.length, value.length)
48
+ return [numeric_part, unit]
49
+ elsif value == 'ONLINE'
50
+ return [0, '']
51
+ else
52
+ return [1, '']
53
+ end
54
+ end
55
+
56
+ def _convert_d(value, hash, default)
57
+ converted = _convert(value, hash)
58
+
59
+ if converted.nil?
60
+ converted = default
61
+ end
62
+
63
+ return converted
64
+ end
65
+
66
+ def _convert(value, hash)
67
+ converted = hash[value]
68
+
69
+ #If the converted value is null, use the original unit
70
+ if converted.nil?
71
+ converted = value
72
+ end
73
+
74
+ return converted
75
+ end
76
+ end
77
+
78
+ class Collector
79
+ CONVERTER = Converter.new
80
+
81
+ def collect_stats()
82
+ first = true
83
+ headings = {}
84
+ pools = []
85
+
86
+ `zpool list`.each_line do |line|
87
+ #File.open('/Users/tomreay/Documents/workspaceWebApps/newrelic-zfs/list.txt').each_line do |line|
88
+ pool = Pool.new
89
+ line.split(' ').each_with_index do |token, index|
90
+ if first
91
+ headings.merge!({ index => token.capitalize})
92
+ else
93
+ if headings[index] == 'Name'
94
+ pool.name = token
95
+ else
96
+ pool.add_value(headings[index], token)
97
+ end
98
+ end
99
+ end
100
+ first = false
101
+ pools << pool
102
+ end
103
+
104
+ stats = []
105
+ pools.each do |pool|
106
+ pool.values.each do |heading, value|
107
+ converted = CONVERTER.convert(heading, value)
108
+ stat = Stat.new(pool.name, converted[0], converted[1], converted[2])
109
+ stats << stat
110
+ end
111
+ end
112
+
113
+ return stats
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,70 @@
1
+ module ZfsConfig
2
+ def self.get_config_location(config_file_location)
3
+ if config_file_location.nil?
4
+ print "No config file argument given, if you have already generated a config file please rerun using:\n" +
5
+ "\n" +
6
+ "newrelic_zfs full/path/to/file \n"+
7
+ "\n" +
8
+ 'Or, create a config file now? [y/n]: '
9
+ if user_says_yes?
10
+ print 'Where should the file be created? '
11
+ file_path = get_user_input
12
+ create_config(File.join(file_path, 'config.yml'))
13
+
14
+ config_file_location = get_file_path(file_path)
15
+ end
16
+ elsif !File.exist?(config_file_location)
17
+ print 'The specified config file does not exist, do you want to create it now? [y/n]: '
18
+ if user_says_yes?
19
+ create_config(config_file_location)
20
+ else
21
+ config_file_location = nil
22
+ end
23
+ end
24
+
25
+ return config_file_location
26
+ end
27
+
28
+ def self.create_config(config_file_name)
29
+ puts "Writing file #{config_file_name}"
30
+ print 'Please enter your API key: '
31
+ api_key = get_user_input
32
+ raise 'API Key must be non-empty' unless !api_key.nil? && !api_key.empty?
33
+
34
+ print 'Please enter a name for this server: '
35
+ server_name = get_user_input
36
+ raise 'Server name must be non-empty' unless !server_name.nil? && !server_name.empty?
37
+
38
+ File.open(config_file_name, 'w') do |f|
39
+ f.write ERB.new(
40
+ "newrelic: \n" +
41
+ " license_key: '<%= api_key %>' \n" +
42
+ "agents:\n" +
43
+ " zfs:\n" +
44
+ " instance_name: '<%= server_name %>'\n" +
45
+ " print_metrics: false").result(binding)
46
+ end
47
+ puts 'Config file written, starting newrelic_zfs agent'
48
+ end
49
+
50
+ def self.get_file_path(file_path)
51
+ if File.directory?(file_path)
52
+ file_path = File.join(file_path, 'config.yml')
53
+ end
54
+
55
+ if File.extname(file_path).empty?
56
+ file_path = file_path + '.yml'
57
+ end
58
+
59
+ return file_path
60
+ end
61
+
62
+ def self.user_says_yes?()
63
+ return get_user_input == 'y'
64
+ end
65
+
66
+ def self.get_user_input()
67
+ return $stdin.gets.chomp
68
+ end
69
+ end
70
+
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: newrelic_zfs
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Tom Reay
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-01-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: newrelic_plugin
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: trollop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ description: Newrelic plugin to monitor ZFS pools
56
+ email: dev@tomreay.co.uk
57
+ executables:
58
+ - newrelic_zfs
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - bin/newrelic_zfs
63
+ - lib/newrelic_zfs.rb
64
+ - lib/newrelic_zfs/config.rb
65
+ homepage: http://rubygems.org/gems/newrelic-zfs
66
+ licenses:
67
+ - MIT
68
+ metadata: {}
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 2.2.1
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: Newrelic ZFS
89
+ test_files: []