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
  # 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 => 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
  # 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



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

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



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

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



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

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



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

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



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

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



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

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.



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

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



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

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



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

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



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

def gather_system_info
  gather_architecture_info
  gather_cpu_info
end

#mongrelObject

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



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

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



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

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



419
420
421
422
423
424
425
# File 'lib/new_relic/local_environment.rb', line 419

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)


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

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