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.



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

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



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

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



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

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



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

def framework
  @framework
end

#processorsObject (readonly)

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



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

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.



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

def append_environment_value(name, value = nil)
  value = yield if block_given?
  @config[name] = value if value
rescue
  # 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



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

def append_gem_list
  @gems += yield
rescue => 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



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

def append_plugin_list
  @plugins += yield
rescue
  # 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



229
230
231
232
233
234
# File 'lib/new_relic/local_environment.rb', line 229

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



164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/new_relic/local_environment.rb', line 164

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
end

#gather_architecture_infoObject

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



133
134
135
136
# File 'lib/new_relic/local_environment.rb', line 133

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

#gather_cpu_info(proc_file = '/proc/cpuinfo') ⇒ Object

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



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/new_relic/local_environment.rb', line 105

def gather_cpu_info(proc_file='/proc/cpuinfo')
  return unless File.readable? proc_file
  @processors = append_environment_value('Processors') do
    cpuinfo = ''
    File.open(proc_file) do |f|
      loop do
        begin
          cpuinfo << f.read_nonblock(4096).strip
        rescue EOFError
          break
        rescue Errno::EWOULDBLOCK, Errno::EAGAIN
          cpuinfo = ''
          break # don't select file handle, just give up
        end
      end
    end
    processors = cpuinfo.split("\n").select {|line| line =~ /^processor\s*:/ }.size

    if processors == 0
      processors = 1 # assume there is at least one processor
      NewRelic::Agent.logger.warn("Cannot determine the number of processors in #{proc_file}")
    end
    processors
  end
end

#gather_db_infoObject

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



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

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



178
179
180
181
182
183
# File 'lib/new_relic/local_environment.rb', line 178

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.



199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/new_relic/local_environment.rb', line 199

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



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

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



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

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



153
154
155
156
157
158
159
160
# File 'lib/new_relic/local_environment.rb', line 153

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



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

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



147
148
149
150
# File 'lib/new_relic/local_environment.rb', line 147

def gather_system_info
  gather_architecture_info
  gather_cpu_info
end

#mongrelObject

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



237
238
239
240
241
242
243
# File 'lib/new_relic/local_environment.rb', line 237

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



214
215
216
217
218
219
# File 'lib/new_relic/local_environment.rb', line 214

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



425
426
427
428
429
430
431
# File 'lib/new_relic/local_environment.rb', line 425

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)


223
224
225
# File 'lib/new_relic/local_environment.rb', line 223

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