Class: NewRelic::LocalEnvironment

Inherits:
Object
  • Object
show all
Defined in:
lib/new_relic/local_environment.rb

Overview

An instance of LocalEnvironment is responsible for determining three things:

  • Framework - :rails, :rails3, :merb, :ruby, :external, :test

  • Dispatcher - A supported dispatcher, or nil (:mongrel, :thin, :passenger, :webrick, etc)

  • Dispatcher Instance ID, which distinguishes agents on a single host from each other

If the environment can’t be determined, it will be set to nil and dispatcher_instance_id will have nil.

NewRelic::LocalEnvironment should be accessed through NewRelic::Control#env (via the NewRelic::Control singleton).

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeLocalEnvironment

Returns a new instance of LocalEnvironment.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/new_relic/local_environment.rb', line 29

def initialize
  # Extend self with any any submodules of LocalEnvironment.  These can override
  # the discover methods to discover new framworks and dispatchers.
  NewRelic::LocalEnvironment.constants.each do | const |
    mod = NewRelic::LocalEnvironment.const_get const
    self.extend mod if mod.instance_of? Module
  end

  discover_framework
  discover_dispatcher
  @dispatcher = nil if @dispatcher == :none
  @gems = Set.new
  @plugins = Set.new
  @config = Hash.new
end

Instance Attribute Details

#dispatcherObject Also known as: environment

mongrel, thin, webrick, or possibly nil



19
20
21
# File 'lib/new_relic/local_environment.rb', line 19

def dispatcher
  @dispatcher
end

#dispatcher_instance_idObject

An instance id pulled from either @dispatcher_instance_id or by splitting out the first part of the running file



77
78
79
80
81
82
83
84
# File 'lib/new_relic/local_environment.rb', line 77

def dispatcher_instance_id
  if @dispatcher_instance_id.nil?
    if @dispatcher.nil?
      @dispatcher_instance_id = File.basename($0).split(".").first
    end
  end
  @dispatcher_instance_id
end

#frameworkObject

rails, rails3, merb, external, ruby, test, etc



23
24
25
# File 'lib/new_relic/local_environment.rb', line 23

def framework
  @framework
end

#processorsObject (readonly)

The number of cpus, if detected, or nil - many platforms do not support this :(



26
27
28
# File 'lib/new_relic/local_environment.rb', line 26

def processors
  @processors
end

Instance Method Details

#append_environment_value(name, value = nil) ⇒ Object

Add the given key/value pair to the app environment settings. Must pass either a value or a block. Block is called to get the value and any raised errors are silently ignored.



49
50
51
52
53
54
55
# File 'lib/new_relic/local_environment.rb', line 49

def append_environment_value(name, value = nil)
  value = yield if block_given?
  @config[name] = value if value
rescue Exception
  # puts "#{e}\n  #{e.backtrace.join("\n  ")}"
  raise if @framework == :test
end

#append_gem_listObject

yields to the block and appends the returned value to the list of gems - this catches errors that might be raised in the block



59
60
61
62
63
64
# File 'lib/new_relic/local_environment.rb', line 59

def append_gem_list
  @gems += yield
rescue Exception => e
  # puts "#{e}\n  #{e.backtrace.join("\n  ")}"
  raise if @framework == :test
end

#append_plugin_listObject

yields to the block and appends the returned value to the list of plugins - this catches errors that might be raised in the block



68
69
70
71
72
73
# File 'lib/new_relic/local_environment.rb', line 68

def append_plugin_list
  @plugins += yield
rescue Exception
  # puts "#{e}\n  #{e.backtrace.join("\n  ")}"
  raise if @framework == :test
end

#find_class_in_object_space(klass) ⇒ Object

Runs through all the objects in ObjectSpace to find the first one that match the provided class



216
217
218
219
220
221
# File 'lib/new_relic/local_environment.rb', line 216

def find_class_in_object_space(klass)
  ObjectSpace.each_object(klass) do |x|
    return x
  end
  return nil
end

#gather_ar_adapter_infoObject

The name of the AR database adapter for the current environment and the current schema version



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/new_relic/local_environment.rb', line 148

def gather_ar_adapter_info
  
  append_environment_value 'Database adapter' do
    if defined?(ActiveRecord) && defined?(ActiveRecord::Base) &&
        ActiveRecord::Base.respond_to?(:configurations)
      config = ActiveRecord::Base.configurations[NewRelic::Control.instance.env]
      if config
        config['adapter']
      end
    end
  end
  append_environment_value 'Database schema version' do
    ActiveRecord::Migrator.current_version
  end
end

#gather_architecture_infoObject

Grabs the architecture string from either ‘uname -p` or the env variable PROCESSOR_ARCHITECTURE



117
118
119
120
# File 'lib/new_relic/local_environment.rb', line 117

def gather_architecture_info
  append_environment_value('Arch') { `uname -p` } ||
    append_environment_value('Arch') { ENV['PROCESSOR_ARCHITECTURE'] }
end

#gather_cpu_infoObject

See what the number of cpus is, works only on some linux variants



106
107
108
109
110
111
112
113
# File 'lib/new_relic/local_environment.rb', line 106

def gather_cpu_info
  return unless File.readable? '/proc/cpuinfo'
  @processors = append_environment_value('Processors') do
    processors = File.readlines('/proc/cpuinfo').select { |line| line =~ /^processor\s*:/ }.size
    raise "Cannot determine the number of processors in /proc/cpuinfo" unless processors > 0
    processors
  end
end

#gather_db_infoObject

sensing for which adapter is defined, then appends the relevant config information



174
175
176
177
178
179
180
181
182
# File 'lib/new_relic/local_environment.rb', line 174

def gather_db_info
  # room here for more database adapters, when.
  if defined? ::ActiveRecord
    gather_ar_adapter_info
  end
  if defined? ::DataMapper
    gather_dm_adapter_info
  end
end

#gather_dm_adapter_infoObject

Datamapper version



165
166
167
168
169
170
# File 'lib/new_relic/local_environment.rb', line 165

def gather_dm_adapter_info
  append_environment_value 'DataMapper version' do
    require 'dm-core/version'
    DataMapper::VERSION
  end
end

#gather_environment_infoObject

Collect base statistics about the environment and record them for comparison and change detection.



186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/new_relic/local_environment.rb', line 186

def gather_environment_info
  append_environment_value 'Framework', @framework.to_s
  append_environment_value 'Dispatcher', @dispatcher.to_s if @dispatcher
  append_environment_value 'Dispatcher instance id', @dispatcher_instance_id if @dispatcher_instance_id
  append_environment_value('Environment') { NewRelic::Control.instance.env }

  # miscellaneous other helpful debugging information
  gather_ruby_info
  gather_system_info
  gather_revision_info
  gather_db_info
end

#gather_jruby_infoObject

like gather_ruby_info but for the special case of JRuby



100
101
102
103
# File 'lib/new_relic/local_environment.rb', line 100

def gather_jruby_info
  append_environment_value('JRuby version') { JRUBY_VERSION }
  append_environment_value('Java VM version') { ENV_JAVA['java.vm.version']}
end

#gather_os_infoObject

gathers OS info from either ‘uname -v`, `uname -s`, or the OS env variable



124
125
126
127
128
# File 'lib/new_relic/local_environment.rb', line 124

def gather_os_info
  append_environment_value('OS version') { `uname -v` }
  append_environment_value('OS') { `uname -s` } ||
    append_environment_value('OS') { ENV['OS'] }
end

#gather_revision_infoObject

Looks for a capistrano file indicating the current revision



137
138
139
140
141
142
143
144
# File 'lib/new_relic/local_environment.rb', line 137

def gather_revision_info
  rev_file = File.join(NewRelic::Control.instance.root, "REVISION")
  if File.readable?(rev_file) && File.size(rev_file) < 64
    append_environment_value('Revision') do
      File.open(rev_file) { | file | file.readline.strip }
    end
  end
end

#gather_ruby_infoObject

Interrogates some common ruby constants for useful information about what kind of ruby environment the agent is running in



88
89
90
91
92
93
94
95
96
97
# File 'lib/new_relic/local_environment.rb', line 88

def gather_ruby_info
  append_environment_value('Ruby version'){ RUBY_VERSION }
  append_environment_value('Ruby description'){ RUBY_DESCRIPTION } if defined? ::RUBY_DESCRIPTION
  append_environment_value('Ruby platform') { RUBY_PLATFORM }
  append_environment_value('Ruby patchlevel') { RUBY_PATCHLEVEL }
  # room here for other ruby implementations, when.
  if defined? ::JRUBY_VERSION
    gather_jruby_info
  end
end

#gather_system_infoObject

Gathers the architecture and cpu info



131
132
133
134
# File 'lib/new_relic/local_environment.rb', line 131

def gather_system_info
  gather_architecture_info
  gather_cpu_info
end

#mongrelObject

Sets the @mongrel instance variable if we can find a Mongrel::HttpServer



224
225
226
227
228
229
230
# File 'lib/new_relic/local_environment.rb', line 224

def mongrel
  return @mongrel if @mongrel
  if defined?(::Mongrel) && defined?(::Mongrel::HttpServer) && working_jruby?
    @mongrel = find_class_in_object_space(::Mongrel::HttpServer)
  end
  @mongrel
end

#snapshotObject

Take a snapshot of the environment information for this application Returns an associative array



201
202
203
204
205
206
# File 'lib/new_relic/local_environment.rb', line 201

def snapshot
  i = @config.to_a
  i << [ 'Plugin List', @plugins.to_a] if not @plugins.empty?
  i << [ 'Gems', @gems.to_a] if not @gems.empty?
  i
end

#to_sObject

outputs a human-readable description



405
406
407
408
409
410
411
# File 'lib/new_relic/local_environment.rb', line 405

def to_s
  s = "LocalEnvironment["
  s << @framework.to_s
  s << ";dispatcher=#{@dispatcher}" if @dispatcher
  s << ";instance=#{@dispatcher_instance_id}" if @dispatcher_instance_id
  s << "]"
end

#working_jruby?Boolean

it’s a working jruby if it has the runtime method, and object space is enabled

Returns:

  • (Boolean)


210
211
212
# File 'lib/new_relic/local_environment.rb', line 210

def working_jruby?
  !(defined?(::JRuby) && JRuby.respond_to?(:runtime) && !JRuby.runtime.is_object_space_enabled)
end