newrelic_ia 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,4 @@
1
+ == 0.1.0 2009-06-15
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/Manifest ADDED
@@ -0,0 +1,21 @@
1
+ bin/newrelic_ia
2
+ CHANGELOG
3
+ lib/new_relic/ia/cli.rb
4
+ lib/new_relic/ia/disk_sampler.rb
5
+ lib/new_relic/ia/iostat_reader/linux.rb
6
+ lib/new_relic/ia/iostat_reader/osx.rb
7
+ lib/new_relic/ia/iostat_reader.rb
8
+ lib/new_relic/ia/metric_names.rb
9
+ lib/new_relic/ia/newrelic.yml
10
+ lib/newrelic_ia.rb
11
+ Manifest
12
+ Rakefile
13
+ README.rdoc
14
+ spec/cli_spec.rb
15
+ spec/disk_sampler_spec.rb
16
+ spec/iostat-linux.out
17
+ spec/iostat-osx.out
18
+ spec/iostat_reader_spec.rb
19
+ spec/spec.opts
20
+ spec/spec_helper.rb
21
+ tasks/rspec.rake
data/README.rdoc ADDED
@@ -0,0 +1,70 @@
1
+ = New Relic Infrastructure Agent
2
+
3
+ Bare bones Gem for collecting disk, cpu and IO statistics and
4
+ sending them to the New Relic RPM application.
5
+
6
+ This is a work in progress. We hope to add more statistics
7
+ to the agent as well as more useful views on the RPM site
8
+ for viewing these metrics.
9
+
10
+ == DESCRIPTION:
11
+
12
+ Use this gem to collect statistics from a given host by running
13
+ newrelic_ia -a as a daemon. This will contribute System/* metrics
14
+ to your RPM console which can be viewed with custom dashboards.
15
+
16
+ == SYNOPSIS:
17
+
18
+ newrelic_ia [ options ] aspect, aspect..
19
+
20
+ aspect: one or more of 'iostat' or 'disk' (more to come)
21
+
22
+ -a, --all use all available aspects
23
+ -v, --verbose debug output
24
+ -q, --quiet quiet output
25
+ -e, --environment=ENV use ENV section in newrelic.yml
26
+ --install create a default newrelic.yml
27
+ -h, --help Show this help message.
28
+
29
+ == REQUIREMENTS:
30
+
31
+ * New Relic Agent version 2.9.2 or later
32
+ * Gold Subscription for creating and viewing custom dashboards
33
+
34
+ == INSTALL:
35
+
36
+ sudo gem sources -a http://gems.github.com
37
+ sudo gem install newrelic-ia
38
+
39
+ Once installed, run from the home directory of your Rails
40
+ application, or create a separate working directory and run
41
+
42
+ newrelic_ia --install
43
+
44
+ to create a template newrelic.yml file you can use. Edit this file
45
+ and substitute your license key and app_name value.
46
+
47
+ == LICENSE:
48
+
49
+ (The MIT License)
50
+
51
+ Copyright (c) 2009 FIXME full name
52
+
53
+ Permission is hereby granted, free of charge, to any person obtaining
54
+ a copy of this software and associated documentation files (the
55
+ 'Software'), to deal in the Software without restriction, including
56
+ without limitation the rights to use, copy, modify, merge, publish,
57
+ distribute, sublicense, and/or sell copies of the Software, and to
58
+ permit persons to whom the Software is furnished to do so, subject to
59
+ the following conditions:
60
+
61
+ The above copyright notice and this permission notice shall be
62
+ included in all copies or substantial portions of the Software.
63
+
64
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
65
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
66
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
67
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
68
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
69
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
70
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,43 @@
1
+ require 'rubygems'
2
+ require 'echoe'
3
+ %w[rake rake/clean fileutils rubigen].each { |f| require f }
4
+ require File.dirname(__FILE__) + '/lib/newrelic_ia'
5
+
6
+ GEM_NAME = "newrelic_ia"
7
+ GEM_VERSION = NewRelic::IA::VERSION
8
+ AUTHOR = "Bill Kayser"
9
+ EMAIL = "bkayser@newrelic.com"
10
+ HOMEPAGE = "http://www.newrelic.com"
11
+ SUMMARY = "New Relic Gem for gathering system metrics"
12
+ DESCRIPTION = <<EOF
13
+ The New Relic Infrastructure Agent (IA) collects system metrics and transmits
14
+ them to the RPM server where they can be viewed with custom dashboards.
15
+ EOF
16
+
17
+ # Generate all the Rake tasks
18
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
19
+ Echoe.new('newrelic_ia', NewRelic::IA::VERSION) do |p|
20
+ p.author = AUTHOR
21
+ p.email = EMAIL
22
+ p.summary = SUMMARY
23
+ p.description = DESCRIPTION
24
+ p.url = HOMEPAGE
25
+ p.project = 'newrelic'
26
+ p.need_tar_gz = false
27
+ p.need_gem = true
28
+ p.runtime_dependencies = [
29
+ ['newrelic_rpm','>= 2.9.2'],
30
+ ]
31
+ p.development_dependencies = [
32
+ #['newgem', ">= #{::Newgem::VERSION}"]
33
+ ]
34
+ p.bin_files = 'bin/newrelic_ia'
35
+ p.test_pattern = "spec/*.rb"
36
+ p.install_message = File.read('PostInstall.txt')
37
+ p.ignore_pattern = %w[PostInstall.txt newrelic.yml]
38
+ p.clean_pattern |= %w[**/.DS_Store tmp *.log]
39
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
40
+ end
41
+
42
+ Dir['tasks/**/*.rake'].each { |t| load t }
43
+
data/bin/newrelic_ia ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Created on 2009-6-15.
4
+ # Copyright (c) 2009. All rights reserved.
5
+
6
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/newrelic_ia")
7
+
8
+ require "new_relic/ia/cli"
9
+
10
+ status = NewRelic::IA::CLI.execute(STDOUT, ARGV)
11
+ exit status if status
12
+ # if execute returned nil, we are running forever:
13
+ sleep
14
+
@@ -0,0 +1,104 @@
1
+ require 'optparse'
2
+ require 'logger'
3
+
4
+ class NewRelic::IA::CLI
5
+
6
+ LOGFILE = "newrelic_ia.log"
7
+ @log = Logger.new(STDOUT)
8
+
9
+ class << self
10
+ attr_accessor :log
11
+ def level= l
12
+ @log.level = l
13
+ end
14
+
15
+ # Run the command line args. Return nil if running
16
+ # or an exit status if not.
17
+ def execute(stdout, arguments=[])
18
+ @aspects = []
19
+ @log = Logger.new LOGFILE
20
+ @log_level = Logger::INFO
21
+ parser = OptionParser.new do |opts|
22
+ opts.banner = <<-BANNER.gsub(/^ */,'')
23
+
24
+ Monitor different aspects of your environment with New Relic RPM.
25
+
26
+ Usage: #{File.basename($0)} [ options ] aspect, aspect..
27
+
28
+ aspect: one or more of 'iostat' or 'disk' (more to come)
29
+ BANNER
30
+ opts.separator ""
31
+ opts.on("-a", "--all",
32
+ "use all available aspects") { @aspects = %w[iostat disk] }
33
+ opts.on("-v", "--verbose",
34
+ "debug output") { @log_level = Logger::DEBUG }
35
+ opts.on("-q", "--quiet",
36
+ "quiet output") { @log_level = Logger::ERROR }
37
+ opts.on("-e", "--environment=ENV",
38
+ "use ENV section in newrelic.yml") { |e| @env = e }
39
+ opts.on("--install",
40
+ "create a default newrelic.yml") { |e| return self.install(stdout) }
41
+
42
+ opts.on("-h", "--help",
43
+ "Show this help message.") { stdout.puts "#{opts}\n"; return 0 }
44
+ begin
45
+ args = opts.parse! arguments
46
+ unless args.empty?
47
+ @aspects = args
48
+ end
49
+ rescue => e
50
+ stdout.puts e
51
+ stdout.puts opts
52
+ return 1
53
+ end
54
+ end
55
+ @aspects.delete_if do |aspect|
56
+ unless self.instance_methods(false).include? aspect
57
+ stdout.puts "Unknown aspect: #{aspect}"
58
+ true
59
+ end
60
+ end
61
+ if @aspects.empty?
62
+ stdout.puts "No aspects specified."
63
+ stdout.puts parser
64
+ return 1
65
+ end
66
+
67
+ @log.level = @log_level
68
+ gem 'newrelic_rpm'
69
+ require 'newrelic_rpm'
70
+ NewRelic::Agent.manual_start :log => @log, :env => @env, :enabled => true
71
+ cli = new
72
+ @aspects.each do | aspect |
73
+ cli.send aspect
74
+ end
75
+ return nil
76
+ end
77
+ end
78
+ # Aspect definitions
79
+ def iostat # :nodoc:
80
+ self.class.log.info "Starting iostat monitor..."
81
+ require 'new_relic/ia/iostat_reader'
82
+ reader = NewRelic::IA::IostatReader.new
83
+ Thread.new { reader.run }
84
+ end
85
+
86
+ def disk
87
+ self.class.log.info "Starting disk sampler..."
88
+ require 'new_relic/ia/disk_sampler'
89
+ NewRelic::Agent.instance.stats_engine.add_harvest_sampler NewRelic::IA::DiskSampler.new
90
+ end
91
+
92
+ private
93
+ def self.install(stdio)
94
+ if File.exists? "newrelic.yml"
95
+ stdio.puts "A newrelic.yml file already exists. Please remove it before installing another."
96
+ 1 # error
97
+ else
98
+ FileUtils.copy File.join(File.dirname(__FILE__), "newrelic.yml"), "."
99
+ stdio.puts "A newrelic.yml template was copied to #{File.expand_path('.')}."
100
+ stdio.puts "Please add a license key to the file before starting."
101
+ 0 # normal
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/ruby
2
+ require 'new_relic/agent'
3
+ require 'new_relic/ia/metric_names'
4
+
5
+ # This is some demo code which shows how you might install your
6
+ # own sampler. This one theoretically monitors cpu.
7
+
8
+ class NewRelic::IA::DiskSampler < NewRelic::Agent::Sampler
9
+ include NewRelic::IA::MetricNames
10
+ case RUBY_PLATFORM
11
+ when /darwin/
12
+ # Do some special stuff...
13
+ when /linux/
14
+ # Do some special stuff...
15
+ else
16
+ NewRelic::IA::CLI.log.warn "unsupported platform #{RUBY_PLATFORM}"
17
+ end
18
+
19
+ def initialize
20
+ super 'disk_sampler'
21
+ @disk_stats = {}
22
+ end
23
+
24
+ def disk_stats(filesystem)
25
+ name = File.basename(filesystem)
26
+ @disk_stats[name] ||= stats_engine.get_stats(DISK.gsub('_name_', name), false)
27
+ end
28
+
29
+ # This gets called every 10 seconds, or once a minute depending
30
+ # on how you add the sampler to the stats engine.
31
+ # It only looks at fs partitions beginning with '/'
32
+ def poll
33
+ stats = `df -k`
34
+ stats.each_line do | line |
35
+ if line =~ /^(\/[^\s]+)\s.*\s(\d+)%/
36
+ name = $1; alloc = $2
37
+ disk_stats(name).record_data_point alloc.to_i
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+
44
+
45
+
@@ -0,0 +1,47 @@
1
+ require 'new_relic/ia/metric_names'
2
+
3
+ # The iostat reader simply opens a pipe on the iostat command, listening every 15
4
+ # seconds and taking a sample for RPM. It runs on the thread of the caller
5
+ # of the #run method.
6
+ #
7
+ # There are implementations of the command reader for different platforms. The
8
+ # implementations are in modules which are included into the Monitor class.
9
+ #
10
+ class NewRelic::IA::IostatReader
11
+ include NewRelic::IA::MetricNames
12
+ attr_reader :io_stats, :system_cpu, :user_cpu
13
+ def initialize
14
+ stats_engine = NewRelic::Agent.instance.stats_engine
15
+ @io_stats = stats_engine.get_stats(DISK_IO, false) # Usage in MB
16
+ @system_cpu = stats_engine.get_stats(SYSTEM_CPU, false) # percentage utilization
17
+ @user_cpu = stats_engine.get_stats(USER_CPU, false) # percentage utilization
18
+
19
+ # Open the iostat reporting every 15 seconds cumulative
20
+ # values for disk transfers and cpu utilization
21
+ @pipe = IO.popen(cmd)
22
+ end
23
+
24
+ def self.log
25
+ NewRelic::IA::CLI.log
26
+ end
27
+
28
+ def log
29
+ self.class.log
30
+ end
31
+
32
+ case RUBY_PLATFORM
33
+ when /darwin/
34
+ require 'new_relic/ia/iostat_reader/osx'
35
+ include OSX
36
+ when /linux/
37
+ require 'new_relic/ia/iostat_reader/linux'
38
+ include Linux
39
+ else
40
+ raise "unrecognized platform: #{RUBY_PLATFORM}"
41
+ end
42
+
43
+ def run
44
+ init
45
+ read_next while true
46
+ end
47
+ end
@@ -0,0 +1,40 @@
1
+
2
+ module NewRelic::IA::IostatReader::Linux
3
+ def cmd; "iostat -dck 15" ; end
4
+ def init
5
+ # read to "Device:"
6
+ line = @pipe.gets until line =~ /^Device:/
7
+
8
+ # read to first blank line
9
+ @disk_count = 0
10
+ line = @pipe.gets
11
+ until line =~ /^\s*$/
12
+ @disk_count += 1
13
+ line = @pipe.gets
14
+ end
15
+ end
16
+ def read_next
17
+ # read up to the next header
18
+ begin
19
+ line = @pipe.gets.chomp
20
+ end until line =~ /avg-cpu/
21
+ line = @pipe.gets
22
+ # Get the CPU stats
23
+ values = line.strip.split /\s+/
24
+ user, nice, system = values.map { |v| v.to_f }
25
+ log.debug "CPU #{user}% (user), #{system}% (system)"
26
+ user_cpu.record_data_point user
27
+ system_cpu.record_data_point system
28
+ # skip two lines
29
+ @pipe.gets
30
+ @pipe.gets
31
+ # Iterate over each disk's stats
32
+ @disk_count.times do | disk_number |
33
+ line = @pipe.gets.chomp.strip
34
+ values = line.split /\s+/
35
+ usage = values[4].to_f + values[5].to_f
36
+ log.debug "Disk #{values[0]}: #{usage}kb (processed '#{values.inspect}'"
37
+ io_stats.record_data_point(usage * 1024)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,35 @@
1
+ module NewRelic::IA::IostatReader::OSX
2
+ def cmd; "iostat -dCI 15" ; end
3
+ BYTES_PER_MB = 1048576
4
+ def init
5
+ # get the first header
6
+ header = @pipe.gets
7
+ @disk_count = header.split("\s").size - 1
8
+ @pipe.gets # skip the second header
9
+ @pipe.gets # skip the first line, uptime summary
10
+ @running_total = 0
11
+ end
12
+
13
+ def read_next
14
+ # The running total of MB transferred
15
+ line = @pipe.gets.chomp while line.nil? || line =~ /cpu|id/ # skip if it's a header line
16
+ values = line.split("\s")
17
+ current_total = 0.0
18
+ # Iterate over each disk's stats
19
+ @disk_count.times do | disk_number |
20
+ values.shift
21
+ values.shift
22
+ v = values.shift.to_f
23
+ current_total += v
24
+ end
25
+ data_point = current_total - @running_total
26
+ log.debug "Disk usage: #{data_point} mb (#{@running_total})"
27
+ io_stats.record_data_point(data_point * BYTES_PER_MB)
28
+ @running_total = current_total
29
+ # Get the CPU stats
30
+ user, system, idle = values.map { |v| v.to_f }
31
+ log.debug "CPU #{user}% (user), #{system}% (system)"
32
+ user_cpu.record_data_point(user)
33
+ system_cpu.record_data_point(system)
34
+ end
35
+ end
@@ -0,0 +1,8 @@
1
+ module NewRelic::IA::MetricNames
2
+
3
+ DISK = "System/Filesystem/_name_/percent"
4
+ DISK_IO = "System/Resource/DiskIO/b"
5
+ SYSTEM_CPU = "System/CPU/System/percent"
6
+ USER_CPU = "System/CPU/User/percent"
7
+
8
+ end
@@ -0,0 +1,26 @@
1
+ #
2
+ # This is a configuration file for the RPM Agent, tailored
3
+ # for use as a system monitor.
4
+ #
5
+ common: &default_settings
6
+ license_key: 'your licene key here'
7
+ agent_enabled: true
8
+ disable_samplers: true
9
+ app_name: System Monitor
10
+ ssl: false
11
+ capture_params: false
12
+ transaction_tracer:
13
+ enabled: false
14
+
15
+ # NOTE if your application has other named environments, you should
16
+ # provide newrelic conifguration settings for these enviromnents here.
17
+ production:
18
+ <<: *default_settings
19
+ enabled: true
20
+
21
+ development:
22
+ <<: *default_settings
23
+ # turn off communication to RPM service in development mode.
24
+ # NOTE: for initial evaluation purposes, you may want to temporarily turn
25
+ # the agent on in development mode.
26
+ enabled: false
@@ -0,0 +1,15 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'rubygems'
5
+ gem 'newrelic_rpm'
6
+ # You can select different newrelic.yml sections by setting the
7
+ # RUBY_ENV environment variable, similar to RAILS_ENV (which is also checked).
8
+ # Default is 'monitor'
9
+ # ENV['RUBY_ENV'] = 'production'
10
+
11
+ module NewRelic
12
+ module IA
13
+ VERSION = '0.1.0'
14
+ end
15
+ end
@@ -0,0 +1,41 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{newrelic_ia}
5
+ s.version = "0.1.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Bill Kayser"]
9
+ s.date = %q{2009-06-24}
10
+ s.default_executable = %q{newrelic_ia}
11
+ s.description = %q{The New Relic Infrastructure Agent (IA) collects system metrics and transmits them to the RPM server where they can be viewed with custom dashboards.}
12
+ s.email = %q{bkayser@newrelic.com}
13
+ s.executables = ["newrelic_ia"]
14
+ s.extra_rdoc_files = ["bin/newrelic_ia", "CHANGELOG", "lib/new_relic/ia/cli.rb", "lib/new_relic/ia/disk_sampler.rb", "lib/new_relic/ia/iostat_reader/linux.rb", "lib/new_relic/ia/iostat_reader/osx.rb", "lib/new_relic/ia/iostat_reader.rb", "lib/new_relic/ia/metric_names.rb", "lib/new_relic/ia/newrelic.yml", "lib/newrelic_ia.rb", "README.rdoc", "tasks/rspec.rake"]
15
+ s.files = ["bin/newrelic_ia", "CHANGELOG", "lib/new_relic/ia/cli.rb", "lib/new_relic/ia/disk_sampler.rb", "lib/new_relic/ia/iostat_reader/linux.rb", "lib/new_relic/ia/iostat_reader/osx.rb", "lib/new_relic/ia/iostat_reader.rb", "lib/new_relic/ia/metric_names.rb", "lib/new_relic/ia/newrelic.yml", "lib/newrelic_ia.rb", "Manifest", "Rakefile", "README.rdoc", "spec/cli_spec.rb", "spec/disk_sampler_spec.rb", "spec/iostat-linux.out", "spec/iostat-osx.out", "spec/iostat_reader_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/rspec.rake", "newrelic_ia.gemspec"]
16
+ s.has_rdoc = true
17
+ s.homepage = %q{http://www.newrelic.com}
18
+ s.post_install_message = %q{
19
+ For more information refer to http://support.newrelic.com or
20
+ say 'newrelic' at #newrelic on freenode IRC.
21
+ }
22
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Newrelic_ia", "--main", "README.rdoc"]
23
+ s.require_paths = ["lib"]
24
+ s.rubyforge_project = %q{newrelic}
25
+ s.rubygems_version = %q{1.3.1}
26
+ s.summary = %q{New Relic Gem for gathering system metrics}
27
+ s.test_files = ["spec/cli_spec.rb", "spec/disk_sampler_spec.rb", "spec/iostat_reader_spec.rb", "spec/spec_helper.rb"]
28
+
29
+ if s.respond_to? :specification_version then
30
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
31
+ s.specification_version = 2
32
+
33
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
34
+ s.add_runtime_dependency(%q<newrelic_rpm>, [">= 2.9.2"])
35
+ else
36
+ s.add_dependency(%q<newrelic_rpm>, [">= 2.9.2"])
37
+ end
38
+ else
39
+ s.add_dependency(%q<newrelic_rpm>, [">= 2.9.2"])
40
+ end
41
+ end
data/spec/cli_spec.rb ADDED
@@ -0,0 +1,35 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'new_relic/ia/cli'
3
+ require 'new_relic/ia/iostat_reader'
4
+ require 'new_relic/ia/disk_sampler'
5
+ describe NewRelic::IA::CLI, "execute" do
6
+ before(:each) do
7
+ @stdout_io = StringIO.new
8
+ end
9
+ it "should print help" do
10
+ NewRelic::IA::CLI.execute(@stdout_io, [ "-h"])
11
+ @stdout_io.rewind
12
+ @stdout = @stdout_io.read
13
+ @stdout.should =~ /Usage:/
14
+ end
15
+ it "should not accept a bad aspect" do
16
+ stat = NewRelic::IA::CLI.execute(@stdout_io, [ "foo"])
17
+ stat.should == 1
18
+ end
19
+ it "should start iostat" do
20
+ NewRelic::IA::IostatReader.any_instance.expects(:run).once
21
+ stat = NewRelic::IA::CLI.execute(@stdout_io, [ "iostat"])
22
+ stat.should == nil
23
+ Thread.pass
24
+ end
25
+ it "should start disk" do
26
+ NewRelic::Agent::StatsEngine.any_instance.expects(:add_harvest_sampler)
27
+ stat = NewRelic::IA::CLI.execute(@stdout_io, [ "disk"])
28
+ stat.should == nil
29
+ end
30
+ it "should override the env" do
31
+ stat = NewRelic::IA::CLI.execute(@stdout_io, [ "disk", "-e", "production"])
32
+ stat.should == nil
33
+ NewRelic::Control.instance.env.should == "production"
34
+ end
35
+ end
@@ -0,0 +1,21 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+ require 'new_relic/ia/disk_sampler'
3
+ # http://rspec.info/
4
+ describe NewRelic::IA::DiskSampler do
5
+
6
+ before do
7
+ @sampler = NewRelic::IA::DiskSampler.new
8
+ # @statsengine = stub(:get_stats => @stats)
9
+ @statsengine = NewRelic::Agent::StatsEngine.new
10
+ @sampler.stats_engine = @statsengine
11
+ end
12
+
13
+ it "should poll on demand" do
14
+ 2.times { @sampler.poll }
15
+ @statsengine.metrics.each do |m|
16
+ stats = @statsengine.lookup_stat m
17
+ stats.call_count.should == 2
18
+ m.should match(/System\/Filesystem\/.*percent/)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,96 @@
1
+ avg-cpu: %user %nice %system %iowait %steal %idle
2
+ 7.30 0.00 1.50 0.33 2.17 88.70
3
+
4
+ Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
5
+ sda1 2.34 6.37 17.13 28109808 75636708
6
+ sda2 1.27 11.39 11.42 50284100 50407144
7
+ sdb1 7.11 28.80 28.22 127150441 124602856
8
+
9
+ avg-cpu: %user %nice %system %iowait %steal %idle
10
+ 18.00 0.00 0.88 0.12 2.12 79.12
11
+
12
+ Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
13
+ sda1 2.50 0.00 36.00 0 20
14
+ sda2 0.00 0.00 0.00 10 0
15
+ sdb1 29.50 0.00 846.00 0 30
16
+
17
+ avg-cpu: %user %nice %system %iowait %steal %idle
18
+ 1.5 0.00 0.13 0.00 0.25 88.49
19
+
20
+ Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
21
+ sda1 0.00 0.00 0.00 0 0
22
+ sda2 0.00 0.00 0.00 1 0
23
+ sdb1 0.00 0.00 0.00 3 4
24
+
25
+ avg-cpu: %user %nice %system %iowait %steal %idle
26
+ 13.5 0.00 0.50 0.00 0.75 87.66
27
+
28
+ Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
29
+ sda1 3.50 0.00 40.00 3000 0
30
+ sda2 0.00 0.00 0.00 0 0
31
+ sdb1 1.50 0.00 18.00 0 5000
32
+
33
+ avg-cpu: %user %nice %system %iowait %steal %idle
34
+ 9.76 0.00 0.50 0.00 0.88 88.86
35
+
36
+ Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
37
+ sda1 0.00 0.00 0.00 0 0
38
+ sda2 0.00 0.00 0.00 0 0
39
+ sdb1 0.00 0.00 0.00 0 0
40
+
41
+ avg-cpu: %user %nice %system %iowait %steal %idle
42
+ 4.01 0.00 0.25 0.00 0.25 95.49
43
+
44
+ Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
45
+ sda1 0.00 0.00 0.00 0 0
46
+ sda2 0.00 0.00 0.00 0 0
47
+ sdb1 0.00 0.00 0.00 0 0
48
+
49
+ avg-cpu: %user %nice %system %iowait %steal %idle
50
+ 18.98 0.00 0.87 0.00 1.37 78.78
51
+
52
+ Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
53
+ sda1 14.50 0.00 78.00 0 156
54
+ sda2 0.00 0.00 0.00 0 0
55
+ sdb1 1.00 0.00 16.00 0 32
56
+
57
+ avg-cpu: %user %nice %system %iowait %steal %idle
58
+ 8.99 0.00 0.62 4.37 1.00 85.02
59
+
60
+ Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
61
+ sda1 0.00 0.00 0.00 0 0
62
+ sda2 0.00 0.00 0.00 0 0
63
+ sdb1 48.50 194.00 0.00 388 0
64
+
65
+ avg-cpu: %user %nice %system %iowait %steal %idle
66
+ 9.12 0.00 0.38 0.00 2.00 88.50
67
+
68
+ Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
69
+ sda1 8.00 0.00 68.00 0 136
70
+ sda2 0.00 0.00 0.00 0 0
71
+ sdb1 4.50 0.00 36.00 0 72
72
+
73
+ avg-cpu: %user %nice %system %iowait %steal %idle
74
+ 11.26 0.00 0.88 0.00 0.88 86.98
75
+
76
+ Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
77
+ sda1 0.00 0.00 0.00 0 0
78
+ sda2 0.00 0.00 0.00 0 0
79
+ sdb1 0.00 0.00 0.00 0 0
80
+
81
+ avg-cpu: %user %nice %system %iowait %steal %idle
82
+ 5.99 0.00 0.25 0.00 0.25 93.51
83
+
84
+ Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
85
+ sda1 0.00 0.00 0.00 0 0
86
+ sda2 0.00 0.00 0.00 0 0
87
+ sdb1 0.00 0.00 0.00 0 0
88
+
89
+ avg-cpu: %user %nice %system %iowait %steal %idle
90
+ 11.15 0.00 1.80 0.60 0.96 85.49
91
+
92
+ Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
93
+ sda1 5.74 0.00 53.59 0 112
94
+ sda2 0.96 15.31 0.00 32 0
95
+ sdb1 0.96 0.00 15.31 0 32
96
+
@@ -0,0 +1,9 @@
1
+ disk0 disk1 cpu
2
+ KB/t xfrs MB KB/t xfrs MB us sy id
3
+ 15.34 321122 4810.56 40.00 30376 1186.55 10 5 85
4
+ 0.00 0 0.05 0.00 0 0.00 4 1 92
5
+ 4.00 1 0.11 0.00 0 0.00 5 2 92
6
+ 4.00 1 0.40 0.00 0 1.00 6 3 94
7
+ 4.00 1 1.00 0.00 0 0.00 5 3 92
8
+ 4.00 1 0.00 0.00 0 0.00 4 3 93
9
+ 4.00 1 0.00 0.00 0 0.00 4 3 93
@@ -0,0 +1,70 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+ require 'new_relic/ia/iostat_reader'
3
+ require 'new_relic/ia/iostat_reader/linux'
4
+ require 'new_relic/ia/iostat_reader/osx'
5
+ require 'new_relic/ia/metric_names'
6
+
7
+ # Change the refresh time to 2 to speed up tests.
8
+ NewRelic::IA::IostatReader::OSX.class_eval do
9
+ def cmd; "iostat -dCI 2" ; end
10
+ end
11
+
12
+ describe NewRelic::IA::IostatReader do
13
+
14
+ include NewRelic::IA::MetricNames
15
+ METRICS = [NewRelic::IA::MetricNames::SYSTEM_CPU, NewRelic::IA::MetricNames::USER_CPU, NewRelic::IA::MetricNames::DISK_IO].sort
16
+ before do
17
+ @statsengine = NewRelic::Agent::StatsEngine.new
18
+ NewRelic::Agent.instance.stubs(:stats_engine).returns(@statsengine)
19
+ @reader = NewRelic::IA::IostatReader.new
20
+ end
21
+
22
+ def canned_data_loader(filename)
23
+ @reader.instance_eval do
24
+ @pipe = File.open(File.join(File.dirname(__FILE__),filename))
25
+ end
26
+ @reader.init
27
+ @reader.read_next
28
+ @reader.read_next
29
+ @reader.read_next
30
+ metrics = [NewRelic::IA::MetricNames::SYSTEM_CPU, NewRelic::IA::MetricNames::USER_CPU, NewRelic::IA::MetricNames::DISK_IO].sort
31
+ @statsengine.metrics.sort.should == metrics
32
+ stats = metrics.map { | m | [m, @statsengine.lookup_stat(m) ] }
33
+ Hash[*stats.flatten]
34
+ end
35
+
36
+ it "should read repeatedly" do
37
+ @reader.init
38
+ @reader.read_next
39
+ @reader.read_next
40
+ @statsengine.metrics.sort.should == METRICS
41
+ @statsengine.metrics.each do |m|
42
+ stats = @statsengine.lookup_stat m
43
+ stats.call_count.should == 2
44
+ end
45
+ end
46
+
47
+ it "should process linux stats" do
48
+ # NewRelic::IA::CLI.log.level=Logger::DEBUG
49
+ @reader.extend NewRelic::IA::IostatReader::Linux
50
+ stats = canned_data_loader("iostat-linux.out")
51
+
52
+ stats[NewRelic::IA::MetricNames::DISK_IO].total_call_time.should == 8261632.0
53
+ stats[NewRelic::IA::MetricNames::DISK_IO].call_count.should == 9
54
+ stats[NewRelic::IA::MetricNames::SYSTEM_CPU].call_count.should == 3
55
+ stats[NewRelic::IA::MetricNames::SYSTEM_CPU].total_call_time.should == 1.51
56
+ stats[NewRelic::IA::MetricNames::USER_CPU].call_count.should == 3
57
+ stats[NewRelic::IA::MetricNames::USER_CPU].total_call_time.should == 33.0
58
+ end
59
+
60
+ it "should process osx stats" do
61
+ # NewRelic::IA::CLI.log.level=Logger::DEBUG
62
+ @reader.extend NewRelic::IA::IostatReader::OSX
63
+ stats = canned_data_loader("iostat-osx.out")
64
+ stats.values.each { |s| s.call_count.should == 3 }
65
+ stats[NewRelic::IA::MetricNames::SYSTEM_CPU].total_call_time.should == 6.0
66
+ stats[NewRelic::IA::MetricNames::USER_CPU].total_call_time.should == 15.0
67
+ stats[NewRelic::IA::MetricNames::DISK_IO].total_call_time.round.should == 1468006.0
68
+ end
69
+
70
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,52 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
5
+ gem 'rspec'
6
+ require 'spec'
7
+ end
8
+
9
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
10
+ require 'newrelic_ia'
11
+ require 'newrelic_rpm'
12
+ require 'new_relic/ia/cli'
13
+ module NewRelic; TEST = true; end unless defined? NewRelic::TEST
14
+ NewRelic::IA::CLI.level = Logger::ERROR
15
+
16
+ Spec::Runner.configure do |config|
17
+ # == Fixtures
18
+ #
19
+ # You can declare fixtures for each example_group like this:
20
+ # describe "...." do
21
+ # fixtures :table_a, :table_b
22
+ #
23
+ # Alternatively, if you prefer to declare them only once, you can
24
+ # do so right here. Just uncomment the next line and replace the fixture
25
+ # names with your fixtures.
26
+ #
27
+ # config.global_fixtures = :table_a, :table_b
28
+ #
29
+ # If you declare global fixtures, be aware that they will be declared
30
+ # for all of your examples, even those that don't use them.
31
+ #
32
+ # You can also declare which fixtures to use (for example fixtures for test/fixtures):
33
+ #
34
+ # config.fixture_path = RAILS_ROOT + '/spec/fixtures/'
35
+ #
36
+ #config.fixture_path = RAILS_ROOT + '/test/fixtures/'
37
+
38
+ # == Mock Framework
39
+ #
40
+ # RSpec uses it's own mocking framework by default. If you prefer to
41
+ # use mocha, flexmock or RR, uncomment the appropriate line:
42
+ #
43
+ # config.mock_with :mocha
44
+ # config.mock_with :flexmock
45
+ # config.mock_with :rr
46
+ #
47
+ config.mock_with :mocha
48
+
49
+ # == Notes
50
+ #
51
+ # For more information take a look at Spec::Example::Configuration and Spec::Runner
52
+ end
data/tasks/rspec.rake ADDED
@@ -0,0 +1,21 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
5
+ require 'spec'
6
+ end
7
+ begin
8
+ require 'spec/rake/spectask'
9
+ rescue LoadError
10
+ puts <<-EOS
11
+ To use rspec for testing you must install rspec gem:
12
+ gem install rspec
13
+ EOS
14
+ exit(0)
15
+ end
16
+
17
+ desc "Run the specs under spec/models"
18
+ Spec::Rake::SpecTask.new do |t|
19
+ t.spec_opts = ['--options', "spec/spec.opts"]
20
+ t.spec_files = FileList['spec/**/*_spec.rb']
21
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: newrelic_ia
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Bill Kayser
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-06-24 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: newrelic_rpm
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.9.2
24
+ version:
25
+ description: The New Relic Infrastructure Agent (IA) collects system metrics and transmits them to the RPM server where they can be viewed with custom dashboards.
26
+ email: bkayser@newrelic.com
27
+ executables:
28
+ - newrelic_ia
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - bin/newrelic_ia
33
+ - CHANGELOG
34
+ - lib/new_relic/ia/cli.rb
35
+ - lib/new_relic/ia/disk_sampler.rb
36
+ - lib/new_relic/ia/iostat_reader/linux.rb
37
+ - lib/new_relic/ia/iostat_reader/osx.rb
38
+ - lib/new_relic/ia/iostat_reader.rb
39
+ - lib/new_relic/ia/metric_names.rb
40
+ - lib/new_relic/ia/newrelic.yml
41
+ - lib/newrelic_ia.rb
42
+ - README.rdoc
43
+ - tasks/rspec.rake
44
+ files:
45
+ - bin/newrelic_ia
46
+ - CHANGELOG
47
+ - lib/new_relic/ia/cli.rb
48
+ - lib/new_relic/ia/disk_sampler.rb
49
+ - lib/new_relic/ia/iostat_reader/linux.rb
50
+ - lib/new_relic/ia/iostat_reader/osx.rb
51
+ - lib/new_relic/ia/iostat_reader.rb
52
+ - lib/new_relic/ia/metric_names.rb
53
+ - lib/new_relic/ia/newrelic.yml
54
+ - lib/newrelic_ia.rb
55
+ - Manifest
56
+ - Rakefile
57
+ - README.rdoc
58
+ - spec/cli_spec.rb
59
+ - spec/disk_sampler_spec.rb
60
+ - spec/iostat-linux.out
61
+ - spec/iostat-osx.out
62
+ - spec/iostat_reader_spec.rb
63
+ - spec/spec.opts
64
+ - spec/spec_helper.rb
65
+ - tasks/rspec.rake
66
+ - newrelic_ia.gemspec
67
+ has_rdoc: true
68
+ homepage: http://www.newrelic.com
69
+ post_install_message: |
70
+
71
+ For more information refer to http://support.newrelic.com or
72
+ say 'newrelic' at #newrelic on freenode IRC.
73
+
74
+ rdoc_options:
75
+ - --line-numbers
76
+ - --inline-source
77
+ - --title
78
+ - Newrelic_ia
79
+ - --main
80
+ - README.rdoc
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: "0"
88
+ version:
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: "1.2"
94
+ version:
95
+ requirements: []
96
+
97
+ rubyforge_project: newrelic
98
+ rubygems_version: 1.3.1
99
+ signing_key:
100
+ specification_version: 2
101
+ summary: New Relic Gem for gathering system metrics
102
+ test_files:
103
+ - spec/cli_spec.rb
104
+ - spec/disk_sampler_spec.rb
105
+ - spec/iostat_reader_spec.rb
106
+ - spec/spec_helper.rb