newrelic_ia 0.1.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/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