newrelic_rpm 2.8.0 → 2.8.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of newrelic_rpm might be problematic. Click here for more details.

data/Rakefile CHANGED
@@ -22,8 +22,10 @@ spec = Gem::Specification.new do |s|
22
22
  s.email = EMAIL
23
23
  s.homepage = HOMEPAGE
24
24
  s.require_path = 'lib'
25
- s.files = %w(install.rb LICENSE README newrelic.yml Rakefile) + Dir.glob("{lib,recipes,test,ui}/**/*")
26
-
25
+ s.files = %w(install.rb LICENSE README newrelic.yml Rakefile) + Dir.glob("{lib,bin,recipes,test,ui}/**/*")
26
+ s.bindir = "bin" # Use these for applications.
27
+ s.executables = ["newrelic_cmd"]
28
+ s.default_executable = "newrelic_cmd"
27
29
  end
28
30
 
29
31
  Rake::GemPackageTask.new(spec) do |pkg|
data/bin/newrelic_cmd ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ # executes one of the commands in the new_relic/commands directory
3
+ # pass the name of the command as an argument
4
+ require File.dirname(__FILE__) + '/../lib/new_relic/commands/new_relic_commands'
@@ -149,8 +149,6 @@ module NewRelic::Agent
149
149
  attr_reader :error_collector
150
150
  attr_reader :worker_loop
151
151
  attr_reader :license_key
152
- attr_reader :remote_host
153
- attr_reader :remote_port
154
152
  attr_reader :record_sql
155
153
  attr_reader :identifier
156
154
 
@@ -415,7 +413,6 @@ module NewRelic::Agent
415
413
 
416
414
  @error_collector.ignore(ignore_errors)
417
415
 
418
-
419
416
  @capture_params = config.fetch('capture_params', false)
420
417
 
421
418
  sampler_config = config.fetch('transaction_tracer', {})
@@ -430,17 +427,6 @@ module NewRelic::Agent
430
427
  log.info "Transaction tracing is enabled in agent config" if @use_transaction_sampler
431
428
  log.warn "Agent is configured to send raw SQL to RPM service" if @record_sql == :raw
432
429
 
433
- @use_ssl = config.fetch('ssl', false)
434
- default_port = @use_ssl ? 443 : 80
435
-
436
- @remote_host = config.fetch('host', 'collector.newrelic.com')
437
- @remote_port = config.fetch('port', default_port)
438
-
439
- @proxy_host = config.fetch('proxy_host', nil)
440
- @proxy_port = config.fetch('proxy_port', nil)
441
- @proxy_user = config.fetch('proxy_user', nil)
442
- @proxy_pass = config.fetch('proxy_pass', nil)
443
-
444
430
  @prod_mode_enabled = force_enable || config['enabled']
445
431
 
446
432
  # Initialize transaction sampler
@@ -518,7 +504,7 @@ module NewRelic::Agent
518
504
  config.settings
519
505
  @report_period = invoke_remote :get_data_report_period, @agent_id
520
506
 
521
- log! "Connected to NewRelic Service at #{@remote_host}:#{@remote_port}."
507
+ log! "Connected to NewRelic Service at #{config.server}"
522
508
  log.debug "Agent ID = #{@agent_id}."
523
509
 
524
510
  # Ask the server for permission to send transaction samples. determined by subscription license.
@@ -539,7 +525,7 @@ module NewRelic::Agent
539
525
  return false
540
526
 
541
527
  rescue Timeout::Error, StandardError => e
542
- log.info "Unable to establish connection with New Relic RPM Service at #{@remote_host}:#{@remote_port}"
528
+ log.info "Unable to establish connection with New Relic RPM Service at #{config.server}"
543
529
  unless e.instance_of? IgnoreSilentlyException
544
530
  log.error e.message
545
531
  log.debug e.backtrace.join("\n")
@@ -674,14 +660,7 @@ module NewRelic::Agent
674
660
  # to go for higher compression instead, we could use Zlib::BEST_COMPRESSION and
675
661
  # pay a little more CPU.
676
662
  post_data = Zlib::Deflate.deflate(Marshal.dump(args), Zlib::BEST_SPEED)
677
-
678
- # Proxy returns regular HTTP if @proxy_host is nil (the default)
679
- http = Net::HTTP::Proxy(@proxy_host, @proxy_port, @proxy_user, @proxy_pass).new(@remote_host, @remote_port.to_i)
680
- if @use_ssl
681
- http.use_ssl = true
682
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
683
- end
684
-
663
+ http = config.http_connection
685
664
  http.read_timeout = @request_timeout
686
665
 
687
666
  # params = {:method => method, :license_key => license_key, :protocol_version => PROTOCOL_VERSION }
@@ -740,9 +719,9 @@ module NewRelic::Agent
740
719
  end
741
720
 
742
721
  def graceful_disconnect
743
- if @connected && !(remote_host == "localhost" && @identifier == '3000')
722
+ if @connected && !(config.server.host == "localhost" && @identifier == '3000')
744
723
  begin
745
- log.debug "Sending graceful shutdown message to #{remote_host}:#{remote_port}"
724
+ log.debug "Sending graceful shutdown message to #{config.server}"
746
725
 
747
726
  @request_timeout = 5
748
727
 
@@ -0,0 +1,147 @@
1
+ # This is a class for executing commands related to deployment
2
+ # events. It runs without loading the rails environment
3
+
4
+ $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__),"..",".."))
5
+ require 'yaml'
6
+ require 'net/http'
7
+ require 'rexml/document'
8
+
9
+ # We need to use the Config object but we don't want to load
10
+ # the rails/merb environment. The defined? clause is so that
11
+ # it won't load it twice, something it does when run inside a test
12
+ require 'new_relic/config' unless defined? NewRelic::Config
13
+
14
+ module NewRelic
15
+ module Commands
16
+ # Capture a failure to execute the command.
17
+ # Ask it for a return status to exit the vm with,
18
+ # if appropriate.
19
+ class CommandFailure < StandardError
20
+ attr_reader :exit_code
21
+ def initialize message, return_status=nil
22
+ super message
23
+ @exit_code = return_status || 0
24
+ end
25
+ end
26
+
27
+ class Deployments
28
+
29
+ attr_reader :config
30
+ def self.command; "deployments"; end
31
+
32
+ # Initialize the deployment uploader with command line args.
33
+ # Use -h to see options.
34
+ # When command_line_args is a hash, we are invoking directly and
35
+ # it's treated as an options with optional sttring values for
36
+ # :user, :description, :appname, :revision, :environment,
37
+ # and :changes.
38
+ #
39
+ # Will throw CommandFailed exception if there's any error.
40
+ #
41
+ def initialize command_line_args
42
+ @config = NewRelic::Config.instance
43
+ @user = ENV['USER']
44
+ if Hash === command_line_args
45
+ # command line args is an options hash
46
+ command_line_args.each do | key, value |
47
+ if %w[user environment description appname revision changelog].include? key.to_s
48
+ instance_variable_set "@#{key}", value.to_s if value
49
+ else
50
+ raise "Unrecognized option #{key}=#{value}"
51
+ end
52
+ end
53
+ else
54
+ # parse command line args. Throw an exception on a bad arg.
55
+ @description = options.parse(command_line_args).join " "
56
+ end
57
+ config.env = @environment if @environment
58
+ @appname ||= config.app_name || config.env || 'development'
59
+ end
60
+
61
+ # Run the Deployment upload in RPM via Active Resource.
62
+ # Will possibly print errors and exit the VM
63
+ def run
64
+ begin
65
+ @description = nil if @description && @description.strip.empty?
66
+ create_params = {}
67
+ {
68
+ :application_id => @appname,
69
+ :host => Socket.gethostname,
70
+ :description => @description,
71
+ :user => @user,
72
+ :revision => @revision,
73
+ :changelog => @changelog
74
+ }.each do |k, v|
75
+ create_params["deployment[#{k}]"] = v unless v.nil? || v == ''
76
+ end
77
+ http = config.http_connection(config.api_server)
78
+
79
+ uri = "/deployments.xml"
80
+
81
+ raise "license_key was not set in newrelic.yml for #{config.env}" if config['license_key'].nil?
82
+ request = Net::HTTP::Post.new(uri, {'x-license-key' => config['license_key']})
83
+ request.content_type = "application/octet-stream"
84
+
85
+ request.set_form_data(create_params)
86
+
87
+ response = http.request(request)
88
+
89
+ if response.is_a? Net::HTTPSuccess
90
+ info "Recorded deployment to NewRelic RPM (#{@description || Time.now })"
91
+ else
92
+ err_string = [ "Unexpected response from server: #{response.code}: #{response.message}" ]
93
+ begin
94
+ doc = REXML::Document.new(response.body)
95
+ doc.elements.each('errors/error') do |error|
96
+ err_string << "Error: #{error.text}"
97
+ end
98
+ rescue
99
+ end
100
+ raise CommandFailure.new(err_string.join("\n"), -1)
101
+ end
102
+ rescue SystemCallError, SocketError => e
103
+ # These include Errno connection errors
104
+ err_string = "Transient error attempting to connect to #{config.api_server} (#{e})"
105
+ raise CommandFailure.new(err_string, -1)
106
+ rescue CommandFailure
107
+ raise
108
+ rescue Exception => e
109
+ err "Unexpected error attempting to connect to #{config.api_server}"
110
+ info e.backtrace.join("\n")
111
+ raise CommandFailure.new(e.to_s, -1)
112
+ end
113
+ end
114
+
115
+ private
116
+
117
+ def options
118
+ OptionParser.new "Usage: #{self.class.command} [OPTIONS] [description] ", 40 do |o|
119
+ o.separator "OPTIONS:"
120
+ o.on("-a", "--appname=DIR", String,
121
+ "Set the application name.",
122
+ "Default is app_name setting in newrelic.yml") { |@appname| }
123
+ o.on("-e", "--environment=name", String,
124
+ "Override the (RAILS|MERB|RUBY)_ENV setting",
125
+ "currently: #{config.env}") { | @environment| }
126
+ o.on("-u", "--user=USER", String,
127
+ "Specify the user deploying.",
128
+ "Default: #{@user}") { |@user| }
129
+ o.on("-r", "--revision=REV", String,
130
+ "Specify the revision being deployed") { |@revision | }
131
+ o.on("-c", "--changes",
132
+ "Read in a change log from the standard input") { @changelog = STDIN.read }
133
+ o.on("-?", "Print this help") { raise CommandFailure.new(o.help, 0) }
134
+ o.separator ""
135
+ o.separator 'description = "short text"'
136
+ end
137
+ end
138
+
139
+ def info message
140
+ STDOUT.puts message
141
+ end
142
+ def err message
143
+ STDERR.puts message
144
+ end
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,30 @@
1
+ require 'optparse'
2
+
3
+ # Run the command given by the first argument. Right
4
+ # now all we have is deployments. We hope to have other
5
+ # kinds of events here later.
6
+
7
+ libdir = File.expand_path(File.join(File.dirname(__FILE__), '..','..'))
8
+ command_list = Dir[File.join(libdir,'new_relic','commands','*.rb')].map{|command| command =~ /.*\/(.*)\.rb/ && $1}
9
+ command_list.delete 'new_relic_commands'
10
+ extra = []
11
+ options = ARGV.options do |opts|
12
+ script_name = File.basename($0)
13
+ opts.banner = "Usage: #{__FILE__} #{ command_list.join(" | ")} [options]"
14
+ opts.separator "use -h to see detailed command options"
15
+ opts
16
+ end
17
+ extra = options.order!
18
+ command = extra.shift
19
+ if !command_list.include?(command)
20
+ STDERR.puts options
21
+ else
22
+ require File.join(libdir, 'new_relic','commands', command + ".rb")
23
+ command_class = NewRelic::Commands.const_get(command.capitalize)
24
+ begin
25
+ command_class.new(extra).run
26
+ rescue NewRelic::Commands::CommandFailure => failure
27
+ STDERR.puts failure.message
28
+ exit failure.exit_code
29
+ end
30
+ end
@@ -1,21 +1,28 @@
1
1
  require 'yaml'
2
2
  #require 'new_relic/version'
3
3
  require 'singleton'
4
- require 'new_relic/agent'
5
4
  require 'erb'
5
+ require 'net/https'
6
6
 
7
7
  # Configuration supports the behavior of the agent which is dependent
8
8
  # on what environment is being monitored: rails, merb, ruby, etc
9
9
  # It is an abstract factory with concrete implementations under
10
10
  # the config folder.
11
11
  module NewRelic
12
+
12
13
  class Config
13
14
 
15
+ # Structs holding info for the remote server and proxy server
16
+ class Server < Struct.new :host, :port
17
+ def to_s; "#{host}:#{port}"; end
18
+ end
19
+
20
+ ProxyServer = Struct.new :host, :port, :user, :password
21
+
14
22
  def self.instance
15
23
  @instance ||= new_instance
16
24
  end
17
25
 
18
- attr_reader :settings
19
26
 
20
27
 
21
28
  @settings = nil
@@ -40,9 +47,26 @@ module NewRelic
40
47
  def [](key)
41
48
  fetch(key)
42
49
  end
50
+ ####################################
51
+ def env=(env_name)
52
+ @env = env_name
53
+ @settings = @yaml[env_name]
54
+ end
55
+
56
+ def settings
57
+ @settings ||= (@yaml && @yaml[env]) || {}
58
+ end
59
+
60
+ def []=(key, value)
61
+ settings[key] = value
62
+ end
63
+
64
+ def set_config(key,value)
65
+ self[key]=value
66
+ end
43
67
 
44
68
  def fetch(key, default=nil)
45
- @settings[key].nil? ? default : @settings[key]
69
+ settings[key].nil? ? default : settings[key]
46
70
  end
47
71
 
48
72
  ###################################
@@ -65,10 +89,44 @@ module NewRelic
65
89
  fetch('app_name', nil)
66
90
  end
67
91
 
92
+ def use_ssl?
93
+ @use_ssl ||= fetch('ssl', false)
94
+ end
95
+
96
+ def server
97
+ @remote_server ||=
98
+ NewRelic::Config::Server.new fetch('host', 'collector.newrelic.com'), fetch('port', use_ssl? ? 443 : 80).to_i
99
+ end
100
+
101
+ def api_server
102
+ @api_server ||=
103
+ NewRelic::Config::Server.new fetch('api_host', 'rpm.newrelic.com'), fetch('api_port', fetch('port', use_ssl? ? 443 : 80)).to_i
104
+ end
105
+
106
+ def proxy_server
107
+ @proxy_server ||=
108
+ NewRelic::Config::ProxyServer.new fetch('proxy_host', nil), fetch('proxy_port', nil),
109
+ fetch('proxy_user', nil), fetch('proxy_pass', nil)
110
+ end
111
+
112
+ # Return the Net::HTTP with proxy configuration given the NewRelic::Config::Server object.
113
+ # Default is the collector but for api calls you need to pass api_server
114
+ def http_connection(host = server)
115
+ # Proxy returns regular HTTP if @proxy_host is nil (the default)
116
+ http = Net::HTTP::Proxy(proxy_server.host, proxy_server.port,
117
+ proxy_server.user, proxy_server.password).new(host.host, host.port)
118
+ if use_ssl?
119
+ http.use_ssl = true
120
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
121
+ end
122
+ http
123
+ end
124
+
68
125
  def to_s
69
126
  puts self.inspect
70
127
  "Config[#{self.app}]"
71
128
  end
129
+
72
130
  def log
73
131
  # If we try to get a log before one has been set up, return a stdout log
74
132
  unless @log
@@ -103,7 +161,7 @@ module NewRelic
103
161
  end
104
162
 
105
163
  def local_env
106
- @env ||= NewRelic::LocalEnvironment.new
164
+ @local_env ||= NewRelic::LocalEnvironment.new
107
165
  end
108
166
 
109
167
  # send the given message to STDERR so that it shows
@@ -145,6 +203,7 @@ module NewRelic
145
203
  end
146
204
 
147
205
  def log_file_name(identifier="")
206
+ identifier ||= ""
148
207
  "newrelic_agent.#{identifier.gsub(/[^-\w.]/, '_')}.log"
149
208
  end
150
209
 
@@ -179,12 +238,13 @@ module NewRelic
179
238
  yml_file = File.expand_path(File.join(__FILE__,"..","..","..","newrelic.yml"))
180
239
  yaml = ::ERB.new(File.read(yml_file)).result(binding)
181
240
  log! "Cannot find newrelic.yml file at #{config_file}."
241
+ log! "Be sure to run this from the app root dir."
182
242
  log! "Using #{yml_file} file."
183
243
  log! "Signup at rpm.newrelic.com to get a newrelic.yml file configured for a free Lite account."
184
244
  else
185
245
  yaml = ERB.new(File.read(config_file)).result(binding)
186
246
  end
187
- @settings = YAML.load(yaml)[env] || {}
247
+ @yaml = YAML.load(yaml)
188
248
  rescue ScriptError, StandardError => e
189
249
  puts e
190
250
  puts e.backtrace.join("\n")
@@ -3,7 +3,7 @@ class NewRelic::Config::Merb < NewRelic::Config
3
3
  def app; :merb; end
4
4
 
5
5
  def env
6
- ::Merb.env
6
+ @env ||= ::Merb.env
7
7
  end
8
8
  def root
9
9
  ::Merb.root
@@ -3,7 +3,7 @@ class NewRelic::Config::Rails < NewRelic::Config
3
3
  def app; :rails; end
4
4
 
5
5
  def env
6
- RAILS_ENV
6
+ @env ||= RAILS_ENV
7
7
  end
8
8
  def root
9
9
  RAILS_ROOT
@@ -1,9 +1,22 @@
1
1
  class NewRelic::Config::Ruby < NewRelic::Config
2
2
  def app; :ruby; end
3
3
  def env
4
- ENV['RUBY_ENV'] || 'development'
4
+ @env ||= ENV['RUBY_ENV'] || ENV['RAILS_ENV'] || 'development'
5
5
  end
6
6
  def root
7
7
  Dir['.']
8
8
  end
9
+ # Check a sequence of file locations for newrelic.yml
10
+ def config_file
11
+ files = []
12
+ files << File.join(root,"config","newrelic.yml")
13
+ files << File.join(root,"newrelic.yml")
14
+ files << File.join(ENV["HOME"], ".newrelic", "newrelic.yml")
15
+ files << File.join(ENV["HOME"], "newrelic.yml")
16
+ files.each do | file |
17
+ return File.expand_path(file) if File.exists? file
18
+ end
19
+ return File.expand_path(files.first)
20
+ end
21
+
9
22
  end
@@ -0,0 +1,71 @@
1
+ # When installed as a plugin this is loaded automatically.
2
+ #
3
+ # When installed as a gem, you need to add
4
+ # require 'new_relic/recipes'
5
+ # to your deploy.rb
6
+ #
7
+ # Defined deploy:notify_rpm which will send information about the deploy to RPM.
8
+ # The task will run on app servers except where no_release is true.
9
+ # If it fails, it will not affect the task execution or do a rollback.
10
+ #
11
+ make_notify_task = lambda do
12
+
13
+ namespace :newrelic do
14
+
15
+ # on all deployments, notify RPM
16
+ desc "Record a deployment in New Relic RPM (rpm.newrelic.com)"
17
+ task :notice_deployment, :roles => :app, :except => {:no_release => true } do
18
+ rails_env = fetch(:rails_env, "production")
19
+ begin
20
+ require File.join(File.dirname(__FILE__), 'commands', 'deployments.rb')
21
+ # Try getting the changelog from the server. Then fall back to local changelog
22
+ # if it doesn't work. Problem is that I don't know what directory the .git is
23
+ # in when using git. I could possibly use the remote cache but i don't know
24
+ # if that's always there.
25
+ =begin
26
+ run "cd #{current_release}; #{log_command}" do | io, stream_id, output |
27
+ changelog = output
28
+ end
29
+ =end
30
+ # allow overrides to be defined for revision, description, changelog and appname
31
+ rev = fetch(:newrelic_revision) if exists?(:newrelic_revision)
32
+ description = fetch(:newrelic_desc) if exists?(:newrelic_desc)
33
+ changelog = fetch(:newrelic_changelog) if exists?(:newrelic_changelog)
34
+ appname = fetch(:newrelic_appname) if exists?(:newrelic_appname)
35
+ if !changelog
36
+ logger.debug "Getting log of changes for New Relic Deployment details"
37
+ from_revision = source.next_revision(current_revision)
38
+ log_command = "#{source.log(from_revision)}"
39
+ changelog = `#{log_command}`
40
+ end
41
+ new_revision = rev || source.query_revision(source.head()) { |cmd| `#{cmd}` }
42
+ deploy_options = { :environment => rails_env,
43
+ :revision => new_revision,
44
+ :changelog => changelog,
45
+ :description => description,
46
+ :appname => appname }
47
+ logger.debug "Uploading deployment to New Relic"
48
+ deployment = NewRelic::Commands::Deployments.new deploy_options
49
+ deployment.run
50
+ logger.info "Uploaded deployment information to New Relic"
51
+ rescue ScriptError => e
52
+ logger.info "error creating New Relic deployment (#{e})\n#{e.backtrace.join("\n")}"
53
+ rescue NewRelic::Commands::CommandFailure => e
54
+ logger.info "unable to notify New Relic of the deployment (#{e})... skipping"
55
+ rescue CommandError
56
+ logger.info "unable to notify New Relic of the deployment... skipping"
57
+ end
58
+ # WIP: For rollbacks, let's update the deployment we created with an indication of the failure:
59
+ # on_rollback do
60
+ # run(...)
61
+ # end
62
+ end
63
+ end
64
+ end
65
+
66
+ instance = Capistrano::Configuration.instance
67
+ if instance
68
+ instance.load &make_notify_task
69
+ else
70
+ make_notify_task.call
71
+ end
@@ -1,4 +1,4 @@
1
- #require 'new_relic/stats'
1
+ require 'new_relic/stats'
2
2
 
3
3
  # This agent is loaded by the plug when the plug-in is disabled
4
4
  # It recreates just enough of the API to not break any clients that
@@ -28,7 +28,7 @@ module NewRelic
28
28
  module Agent
29
29
 
30
30
  class << self
31
- @@dummy_stats = MethodTraceStats.new
31
+ @@dummy_stats = NewRelic::MethodTraceStats.new
32
32
  def agent
33
33
  NewRelic::Agent::Agent.instance
34
34
  end
@@ -3,14 +3,22 @@ module NewRelic
3
3
  module VERSION #:nodoc:
4
4
  MAJOR = 2
5
5
  MINOR = 8
6
- TINY = 0
6
+ TINY = 1
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  def self.changes
9
- puts "NewRelic RPM Plugin Version: #{NewRelic::VERSION}"
9
+ puts "NewRelic RPM Plugin Version: #{NewRelic::VERSION::STRING}"
10
10
  puts CHANGELOG
11
11
  end
12
12
 
13
13
  CHANGELOG = <<EOF
14
+
15
+ 2009-01-27 version 2.8.1
16
+ * Convert the deployment information upload script to an executable
17
+ and put in the bin directory. When installed as a gem this command
18
+ is symlinked to /usr/bin. Usage: newrelic_cmd deployments --help
19
+ * Fix issue invoking api when host is not set in newrelic.yml
20
+ * Fix deployments api so it will work from a gem
21
+ * Fix thin incompatibility in developer mode
14
22
  2008-12-18 version 2.8.0
15
23
  * add beta of api in new_relic_api.rb
16
24
  * instrumented dynamic finders in ActiveRecord
data/lib/new_relic_api.rb CHANGED
@@ -105,7 +105,9 @@ module NewRelicApi
105
105
  end
106
106
 
107
107
  def site_url
108
- "http#{'s' if (NewRelicApi.ssl || NewRelic::Config.instance['ssl'])}://#{NewRelicApi.host || NewRelic::Config.instance['host']}:#{NewRelicApi.port || NewRelic::Config.instance['port']}"
108
+ host = NewRelicApi.host || NewRelic::Config.instance.api_server.host
109
+ port = NewRelicApi.port || NewRelic::Config.instance.api_server.port
110
+ "#{port == 443 ? 'https' : 'http'}://#{host}:#{port}"
109
111
  end
110
112
 
111
113
  def reset!
@@ -245,31 +247,4 @@ module NewRelicApi
245
247
  end
246
248
 
247
249
  end
248
- if (__FILE__ == $0) || ($0 =~ /script\/runner$/)
249
- # Run the command given by the first argument. Right
250
- # now all we have is deployments. We hope to have other
251
- # kinds of events here later
252
- command = "(no command given)"
253
- extra = [command]
254
- ARGV.options do |opts|
255
- script_name = File.basename($0)
256
- opts.banner = "Usage: #{__FILE__} command [options]"
257
-
258
- opts.separator ""
259
-
260
- opts.on("-e", "--environment=name", String,
261
- "Specifies the environment for the runner to operate under (test/development/production).",
262
- "Default: development")
263
-
264
- extra = opts.order!
265
- end
266
- command = extra.shift
267
- begin
268
- require "new_relic/api/#{command}"
269
- command_class = NewRelic::API.const_get(command.camelize)
270
- rescue
271
- STDERR.puts "Unknown command: #{command}"
272
- exit 1
273
- end
274
- command_class.new(extra).run
275
- end
250
+
data/recipes/newrelic.rb CHANGED
@@ -1,46 +1,6 @@
1
- # To be included in Capistrano deploy.rb files
2
- #
3
- # Defined deploy:notify_rpm which will send information about the deploy to RPM.
4
- # The task will run on app servers except where no_release is true.
5
- # If it fails, it will not affect the task execution or do a rollback.
6
- #
1
+ # The capistrano recipes in plugins are automatically
2
+ # loaded from here. From gems, they are available from
3
+ # the lib directory. We have to make them available from
4
+ # both locations
7
5
 
8
- make_notify_task = lambda do
9
-
10
- namespace :newrelic do
11
-
12
- # on all deployments, notify RPM
13
- desc "Record a deployment in New Relic RPM (rpm.newrelic.com)"
14
- task :notice_deployment, :roles => :app, :except => {:no_release => true } do
15
- rails_env = fetch(:rails_env, "production")
16
- from_revision = source.next_revision(current_revision)
17
- log_command = source.log(from_revision)
18
- # I don't believe this will work if rpm is installed as a gem, or
19
- # if they put the plugin elsewhere. Need to revisit.
20
- script = [ "vendor/plugins/newrelic_rpm/lib/new_relic_api.rb" ] <<
21
- "deployments" <<
22
- "-u" << ENV['USER'] <<
23
- "-r" << current_revision <<
24
- "-c"
25
- script = script.map { | arg | "'#{arg}'" }.join(" ")
26
- begin
27
- run "cd #{current_release}; #{log_command} | script/runner -e #{rails_env} #{script}" do | io, stream_id, output |
28
- logger.trace(output)
29
- end
30
- rescue CommandError
31
- logger.info "unable to notify New Relic of the deployment... skipping"
32
- end
33
- # For rollbacks, let's update the deployment we created with an indication of the failure:
34
- #on_rollback do
35
- # run(command.gsub(/Subject:.*\\n/, "Subject: #{ENV['USER']} deployed a ROLLBACK\\n"))
36
- #end
37
- end
38
- end
39
- end
40
-
41
- instance = Capistrano::Configuration.instance
42
- if instance
43
- instance.load make_notify_task
44
- else
45
- make_notify_task.call
46
- end
6
+ require File.join(File.dirname(__FILE__),'..','lib','new_relic','recipes')
@@ -9,6 +9,8 @@ test:
9
9
  enabled: false
10
10
  developer: true
11
11
  monitor_daemons: false
12
+ api_host: 127.0.0.1
13
+ api_port: 443
12
14
  message: '<%= generated_for_user %>'
13
15
  license_key: '<%= license_key %>'
14
16
  transaction_tracer:
@@ -1,9 +1,12 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__),'/../test_helper'))
2
- require 'new_relic_api'
1
+ #require File.expand_path(File.join(File.dirname(__FILE__),'/../test_helper'))
2
+ require File.expand_path(File.join(File.dirname(__FILE__),'../../lib/new_relic/commands/deployments'))
3
+ require 'rubygems'
4
+ require 'mocha'
5
+
3
6
  class NewRelic::DeploymentsTests < Test::Unit::TestCase
4
7
 
5
8
  def setup
6
- NewRelic::API::Deployments.class_eval do
9
+ NewRelic::Commands::Deployments.class_eval do
7
10
  attr_accessor :messages, :exit_status, :errors, :revision
8
11
  def err(message); @errors = @errors ? @errors + message : message; end
9
12
  def info(message); @messages = @messages ? @messages + message : message; end
@@ -17,21 +20,45 @@ class NewRelic::DeploymentsTests < Test::Unit::TestCase
17
20
  puts @deployment.exit_status
18
21
  end
19
22
  def test_help
20
- @deployment = NewRelic::API::Deployments.new "-?"
21
- assert_equal 0, @deployment.exit_status
22
- assert_match /^Usage/, @deployment.messages
23
- assert_nil @deployment.revision
23
+ begin
24
+ NewRelic::Commands::Deployments.new "-?"
25
+ fail "should have thrown"
26
+ rescue NewRelic::Commands::CommandFailure => c
27
+ assert_match /^Usage/, c.message
28
+ end
29
+ end
30
+ def test_interactive
31
+ mock_the_connection
32
+ @deployment = NewRelic::Commands::Deployments.new :appname => 'APP', :revision => 3838, :user => 'Bill', :description => "Some lengthy description"
33
+ assert_nil @deployment.exit_status
34
+ assert_nil @deployment.errors
35
+ assert_equal '3838', @deployment.revision
36
+ @deployment.run
24
37
  @deployment = nil
25
38
  end
26
- def test_run
27
- @deployment = NewRelic::API::Deployments.new(%w[-a APP -r 3838 --user=Bill] << "Some lengthy description")
39
+
40
+ def test_command_line_run
41
+ mock_the_connection
42
+ # @mock_response.expects(:body).returns("<xml>deployment</xml>")
43
+ @deployment = NewRelic::Commands::Deployments.new(%w[-a APP -r 3838 --user=Bill] << "Some lengthy description")
28
44
  assert_nil @deployment.exit_status
29
45
  assert_nil @deployment.errors
30
46
  assert_equal '3838', @deployment.revision
31
47
  @deployment.run
32
- assert_equal 1, @deployment.exit_status
33
- assert_match /Unable to upload/, @deployment.errors
48
+
49
+ # This should pass because it's a bogus deployment
50
+ #assert_equal 1, @deployment.exit_status
51
+ #assert_match /Unable to upload/, @deployment.errors
52
+
34
53
  @deployment = nil
35
54
  end
55
+ private
56
+ def mock_the_connection
57
+ mock_connection = mock()
58
+ @mock_response = mock()
59
+ @mock_response.expects(:is_a?).with(Net::HTTPSuccess).returns(true)
60
+ mock_connection.expects(:request).returns(@mock_response)
61
+ NewRelic::Config.instance.stubs(:http_connection).returns(mock_connection)
62
+ end
36
63
 
37
64
  end
@@ -150,7 +150,7 @@ class NewrelicController < ActionController::Base
150
150
  :last_modified => last_modified,
151
151
  :type => 'text/plain'
152
152
  else
153
- response.headers['Last-Modified'] = last_modified
153
+ response.headers['Last-Modified'] = last_modified.to_formatted_s(:rfc822)
154
154
  expires_in 24.hours
155
155
  send_file file, :content_type => mime_type_from_extension(file), :disposition => 'inline' #, :filename => File.basename(file)
156
156
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: newrelic_rpm
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.8.0
4
+ version: 2.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bill Kayser
@@ -9,14 +9,14 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-01-13 00:00:00 -08:00
13
- default_executable:
12
+ date: 2009-01-29 00:00:00 -08:00
13
+ default_executable: newrelic_cmd
14
14
  dependencies: []
15
15
 
16
16
  description: New Relic Ruby Performance Monitoring Agent
17
17
  email: bkayser@newrelic.com
18
- executables: []
19
-
18
+ executables:
19
+ - newrelic_cmd
20
20
  extensions: []
21
21
 
22
22
  extra_rdoc_files:
@@ -61,8 +61,9 @@ files:
61
61
  - lib/new_relic/agent/transaction_sampler.rb
62
62
  - lib/new_relic/agent/worker_loop.rb
63
63
  - lib/new_relic/agent.rb
64
- - lib/new_relic/api
65
- - lib/new_relic/api/deployments.rb
64
+ - lib/new_relic/commands
65
+ - lib/new_relic/commands/deployments.rb
66
+ - lib/new_relic/commands/new_relic_commands.rb
66
67
  - lib/new_relic/config
67
68
  - lib/new_relic/config/merb.rb
68
69
  - lib/new_relic/config/rails.rb
@@ -74,6 +75,7 @@ files:
74
75
  - lib/new_relic/metric_spec.rb
75
76
  - lib/new_relic/metrics.rb
76
77
  - lib/new_relic/noticed_error.rb
78
+ - lib/new_relic/recipes.rb
77
79
  - lib/new_relic/shim_agent.rb
78
80
  - lib/new_relic/stats.rb
79
81
  - lib/new_relic/transaction_analysis.rb
@@ -85,6 +87,7 @@ files:
85
87
  - lib/tasks/agent_tests.rake
86
88
  - lib/tasks/all.rb
87
89
  - lib/tasks/install.rake
90
+ - bin/newrelic_cmd
88
91
  - recipes/newrelic.rb
89
92
  - test/config
90
93
  - test/config/newrelic.yml
@@ -172,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
172
175
  requirements: []
173
176
 
174
177
  rubyforge_project: newrelic
175
- rubygems_version: 1.3.1
178
+ rubygems_version: 1.3.0
176
179
  signing_key:
177
180
  specification_version: 2
178
181
  summary: New Relic Ruby Performance Monitoring Agent
@@ -1,92 +0,0 @@
1
- # This is a class for executing commands related to deployment
2
- # events
3
-
4
- require 'optparse'
5
-
6
- module NewRelic::API
7
-
8
- class Deployments
9
-
10
- def self.command; "deployments"; end
11
-
12
- # Initialize the deployment uploader with command line args.
13
- # Use -h to see options. Will possibly exit the VM
14
- def initialize command_line_args
15
- @application_id = NewRelic::Config.instance.app_name || RAILS_ENV
16
- @user = ENV['USER']
17
- @description = options.parse(command_line_args).join " "
18
- end
19
-
20
- # Run the Deployment upload in RPM via Active Resource.
21
- # Will possibly print errors and exit the VM
22
- def run
23
- begin
24
- @description = nil if @description.blank?
25
- create_params = {
26
- :application_id => @application_id,
27
- :host => Socket.gethostname,
28
- :description => @description,
29
- :user => @user,
30
- :revision => @revision,
31
- :changelog => @changelog
32
- }
33
- d = NewRelicApi::Deployment.create(create_params)
34
- rescue Exception => e
35
- err "Attempting to connect to #{NewRelicApi::BaseResource.site_url}\nUnable to upload deployment (#{e.message})"
36
- info e.backtrace.join("\n")
37
- just_exit 1
38
- end
39
- if d.nil?
40
- err "No value returned from create!"
41
- just_exit 1
42
- elsif d.valid?
43
- puts "Recorded deployment to NewRelic RPM (#{d.description})"
44
- else
45
- err "Could not record deployment to NewRelic RPM:"
46
- err d.errors.full_messages.join("\n")
47
- just_exit 1
48
- end
49
- end
50
-
51
- private
52
-
53
- def options
54
- OptionParser.new "Usage: #{self.class.command} [OPTIONS] [description] ", 40 do |o|
55
- o.separator "OPTIONS:"
56
- o.on("-a", "--appname=DIR", String,
57
- "Specify an application name.",
58
- "Default: #{@application_id}") { |@application_id| }
59
- o.on("-u", "--user=USER", String,
60
- "Specify the user deploying.",
61
- "Default: #{ENV['USER']}") { |@user| }
62
- o.on("-r", "--revision=REV", String,
63
- "Specify the revision being deployed") { |@revision | }
64
- o.on("-c", "--changes",
65
- "Read in a change log from the standard input") { @changelog = STDIN.read }
66
- o.on("-?", "Print this help") { info o.help; just_exit }
67
- o.separator ""
68
- o.separator 'description = "short text"'
69
- end
70
- end
71
-
72
- def help(message)
73
- if message
74
- err message
75
- info options.help
76
- just_exit 1
77
- else
78
- info options
79
- just_exit 0
80
- end
81
- end
82
- def info message
83
- STDOUT.puts message
84
- end
85
- def err message
86
- STDERR.puts message
87
- end
88
- def just_exit status=0
89
- exit status
90
- end
91
- end
92
- end