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:

  • 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
# 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_dispatcher
  @gems = Set.new
  @plugins = Set.new
  @config = Hash.new
end

Instance Attribute Details

#dispatcher_instance_idObject

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



71
72
73
74
75
76
77
78
# File 'lib/new_relic/local_environment.rb', line 71

def dispatcher_instance_id
  if @dispatcher_instance_id.nil?
    if @discovered_dispatcher.nil?
      @dispatcher_instance_id = File.basename($0).split(".").first
    end
  end
  @dispatcher_instance_id
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.



46
47
48
49
50
51
# File 'lib/new_relic/local_environment.rb', line 46

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



55
56
57
58
59
# File 'lib/new_relic/local_environment.rb', line 55

def append_gem_list
  @gems += yield
rescue => e
  Agent.logger.error e
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



63
64
65
66
67
# File 'lib/new_relic/local_environment.rb', line 63

def append_plugin_list
  @plugins += yield
rescue => e
  Agent.logger.error e
end

#discovered_dispatcherObject

mongrel, thin, webrick, or possibly nil



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

def discovered_dispatcher
  discover_dispatcher unless @discovered_dispatcher
  @discovered_dispatcher
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



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

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



159
160
161
162
163
164
165
166
167
168
169
# File 'lib/new_relic/local_environment.rb', line 159

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



128
129
130
131
# File 'lib/new_relic/local_environment.rb', line 128

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



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/new_relic/local_environment.rb', line 100

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



181
182
183
184
185
186
187
188
189
# File 'lib/new_relic/local_environment.rb', line 181

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



172
173
174
175
176
177
# File 'lib/new_relic/local_environment.rb', line 172

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.



193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/new_relic/local_environment.rb', line 193

def gather_environment_info
  append_environment_value 'Framework', Agent.config[:framework].to_s
  append_environment_value 'Dispatcher', Agent.config[:dispatcher].to_s if Agent.config[: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



94
95
96
97
# File 'lib/new_relic/local_environment.rb', line 94

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



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

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



148
149
150
151
152
153
154
155
# File 'lib/new_relic/local_environment.rb', line 148

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



82
83
84
85
86
87
88
89
90
91
# File 'lib/new_relic/local_environment.rb', line 82

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



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

def gather_system_info
  gather_architecture_info
  gather_cpu_info
end

#mongrelObject

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



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

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



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

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



377
378
379
380
381
382
# File 'lib/new_relic/local_environment.rb', line 377

def to_s
  s = "LocalEnvironment["
  s << ";dispatcher=#{@discovered_dispatcher}" if @discovered_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)


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

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