Module: RubyRunInitializer__
- Includes:
- RubyRunGlobals, RubyRunUtils__
- Defined in:
- lib/rubyrun/rubyrun_initializer__.rb
Overview
—————————————————————#
#
(C) Copyright Rubysophic Inc. 2007-2008 #
All rights reserved. #
#
Use, duplication or disclosure of the code is not permitted #
unless licensed. #
#
Last Updated: 7/09/08 #
—————————————————————#
#
RubyRunInitializer__ sets up the environment for RubyRun. # The major task is to identify the application classes and # modules that are potential candidates for instrumentation. #
#
Also as at this release methods with super keyword is not # supported. These methods will need to be identified upfront. #
#
—————————————————————#
Constant Summary
Constants included from RubyRunGlobals
RubyRunGlobals::RUBYRUN_ACTIVERECORD, RubyRunGlobals::RUBYRUN_CMD_EXIT, RubyRunGlobals::RUBYRUN_CMD_HARD_KILL, RubyRunGlobals::RUBYRUN_CMD_OBJECT_MAP, RubyRunGlobals::RUBYRUN_CMD_SOFT_KILL, RubyRunGlobals::RUBYRUN_CMD_STATUS, RubyRunGlobals::RUBYRUN_DIR_HASH_FILE, RubyRunGlobals::RUBYRUN_DOC_DIR, RubyRunGlobals::RUBYRUN_ETC_DIR, RubyRunGlobals::RUBYRUN_EXCLUDE_HASH_FILE, RubyRunGlobals::RUBYRUN_FIREWALL_HASH, RubyRunGlobals::RUBYRUN_HIGHLIGHT_THRESHOLD, RubyRunGlobals::RUBYRUN_INCLUDE_HASH_FILE, RubyRunGlobals::RUBYRUN_INNER_DISPATCH_HASH, RubyRunGlobals::RUBYRUN_KILL_3_STRING, RubyRunGlobals::RUBYRUN_LOG, RubyRunGlobals::RUBYRUN_MONITOR_TIMER, RubyRunGlobals::RUBYRUN_OPTS_FILE, RubyRunGlobals::RUBYRUN_OUTER_DISPATCH_HASH, RubyRunGlobals::RUBYRUN_OUTPUT_PERF_SUMMARY, RubyRunGlobals::RUBYRUN_OUTPUT_TXN_LOG, RubyRunGlobals::RUBYRUN_PREFIX, RubyRunGlobals::RUBYRUN_PREFIX_LENGTH, RubyRunGlobals::RUBYRUN_PROP_DEFAULTS, RubyRunGlobals::RUBYRUN_REPORT, RubyRunGlobals::RUBYRUN_SIGNATURE, RubyRunGlobals::RUBYRUN_STARTUP_ID_TYPE_PORT, RubyRunGlobals::RUBYRUN_STARTUP_ID_TYPE_PROCESS, RubyRunGlobals::RUBYRUN_THREAD_END_HASH, RubyRunGlobals::RUBYRUN_VIEW_HASH, RubyRunGlobals::RUBYRUN_WORKING_DIR_NAME
Instance Method Summary collapse
-
#config_prop_exists?(prop) ⇒ Boolean
If the property is not defined or defined but with nil value, it is deemed to be non-existent.
-
#create_log_device ⇒ Object
Create new log device in case the log stream is closed.
-
#create_options_file(path) ⇒ Object
Create the options file.
-
#create_working_dir(path) ⇒ Object
Create the working directory, which will be ‘rubyrun’ under the current directory.
-
#deserialize_scan_history ⇒ Object
Use Marshal to de-serialize the include hash.
-
#directory_changed?(dir_signature) ⇒ Boolean
Compare the digest calculated from the current APP_PATHS directory contents to the last serialized one.
-
#discover_targets ⇒ Object
Set up global variables from the property file rubyrun_config.yml For APP_PATHS property, expand any subdirectories and look for .rb files recursively.
-
#expand_folder(folder) ⇒ Object
For each directory, expand into a list of filenames and its modifed time.
-
#generate_hash(hash) ⇒ Object
Calcualte the digest from the directory contents of APP_PATHS.
-
#get_dir_hash_file ⇒ Object
Return the target file name that stores the serialized directory contents digest This file has to be application dependent, and we use the current directory of the running process to represent the application directory.
-
#get_include_hash_file ⇒ Object
Return the target file name that stores the serialized INCLUDE_HASH.
-
#identify_candidates ⇒ Object
If the directory content has changed (new files, modified files, new APP_PATHS) a new scan will be required, otherwise the last scan results will simply be reused.
-
#init_rubyrun ⇒ Object
1.
-
#load_config_props(config_file) ⇒ Object
Property file is a yml file.
-
#make_folder(rubyrun_folders) ⇒ Object
Make sub-directories (folders).
-
#ready_logfile ⇒ Object
Initialize rubyrun logger and create its own log format.
-
#ready_rubyrun_env ⇒ Object
1.
-
#scan_module_class(path) ⇒ Object
Regular expression that detects the class or module names of a given file.
-
#serialize_scan_history(dir_signature) ⇒ Object
Use Marshal to serialize scan results (the include hash).
-
#validate_opts ⇒ Object
Validate the range of REPORT_TIMER and REPORT_SHIFT_AGE Use default values if out of acceptable range.
Methods included from RubyRunUtils__
#env_var_exists?, #fatal_exit, #get_caller_detail, #get_thread_id, #is_action?, #is_application_controller, #is_in?, #is_rails_controller?, #return_class_name, #return_method_name, #return_mid
Instance Method Details
#config_prop_exists?(prop) ⇒ Boolean
If the property is not defined or defined but with nil value, it is deemed to be non-existent
179 180 181 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 179 def config_prop_exists?(prop) $rubyrun_config.has_key?(prop) && !$rubyrun_config[prop].nil? ? true : false end |
#create_log_device ⇒ Object
Create new log device in case the log stream is closed. This happens only in Mongrel cluster scenario
134 135 136 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 134 def create_log_device Logger::LogDevice.new($rubyrun_log_folder + '/' + $rubyrun_file_basename + '_' + $rubyrun_startup_id + '.log', :shift_age => 10, :shift_size => 4096000) end |
#create_options_file(path) ⇒ Object
Create the options file
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 77 def (path) begin yml_source = __FILE__.gsub('\\','/').split('/')[0..-4].join('/') + '/' + RUBYRUN_ETC_DIR + RUBYRUN_OPTS_FILE opts_file = File.new(path + RUBYRUN_OPTS_FILE, "w") File.open(yml_source).each { |line| if line.include?('APP_PATHS: []') File.exists?("#{Dir.getwd+'/app/controllers'}") ? opts_file.puts("APP_PATHS: ['#{Dir.getwd+'/app/controllers'}']") : opts_file.puts("APP_PATHS: ['#{Dir.getwd}']") else opts_file.puts(line) end } opts_file.close rescue Exception => e raise RuntimeError, "Unable to create options file in #{path}" end end |
#create_working_dir(path) ⇒ Object
Create the working directory, which will be ‘rubyrun’ under the current directory
68 69 70 71 72 73 74 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 68 def create_working_dir(path) begin Dir.mkdir(path) rescue Exception => e raise RuntimeError, "Unable to create working directory #{path}" end end |
#deserialize_scan_history ⇒ Object
Use Marshal to de-serialize the include hash
273 274 275 276 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 273 def deserialize_scan_history f = get_include_hash_file $rubyrun_include_hash = File.exists?(f) ? File.open(f) {|f| Marshal.load(f)} : {} end |
#directory_changed?(dir_signature) ⇒ Boolean
Compare the digest calculated from the current APP_PATHS directory contents to the last serialized one. Return true(changed) or false (unchanged)
255 256 257 258 259 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 255 def directory_changed?(dir_signature) f = get_dir_hash_file dir_sig = File.exists?(f) ? File.open(f) {|f| Marshal.load(f)} : nil dir_signature != dir_sig end |
#discover_targets ⇒ Object
Set up global variables from the property file rubyrun_config.yml For APP_PATHS property, expand any subdirectories and look for .rb files recursively
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 186 def discover_targets identify_candidates $rubyrun_include_hash.merge!($rubyrun_config['INCLUDE_HASH']) ['DB_ADAPTER_HASH','OUTER_DISPATCH_HASH','INNER_DISPATCH_HASH'].each { |hash_key| $rubyrun_include_hash.merge!($rubyrun_config[hash_key]) { |k,o,n| o.concat(n) } if config_prop_exists?(hash_key) } [RUBYRUN_OUTER_DISPATCH_HASH,RUBYRUN_INNER_DISPATCH_HASH,RUBYRUN_THREAD_END_HASH,RUBYRUN_VIEW_HASH].each {|hash| $rubyrun_include_hash.merge!(hash) { |k,o,n| (o.empty? || n.empty?) ? [] : o.concat(n) } } $rubyrun_exclude_hash.merge!($rubyrun_config['EXCLUDE_HASH']) $rubyrun_outer_dispatch_hash = config_prop_exists?('OUTER_DISPATCH_HASH') ? RUBYRUN_OUTER_DISPATCH_HASH.merge($rubyrun_config['OUTER_DISPATCH_HASH']) : RUBYRUN_OUTER_DISPATCH_HASH $rubyrun_inner_dispatch_hash = config_prop_exists?('INNER_DISPATCH_HASH') ? RUBYRUN_INNER_DISPATCH_HASH.merge($rubyrun_config['INNER_DISPATCH_HASH']) : RUBYRUN_INNER_DISPATCH_HASH $rubyrun_logger.info "Final INCLUDE_HASH = #{$rubyrun_include_hash.inspect}" $rubyrun_logger.info "Final EXCLUDE_HASH = #{$rubyrun_exclude_hash.inspect}" end |
#expand_folder(folder) ⇒ Object
For each directory, expand into a list of filenames and its modifed time.
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 231 def (folder) ($rubyrun_logger.warn("WARN: APP_PATHS not found: #{folder}") ; return) unless File.exists?(folder) if File.file?(folder) return if File.extname(folder) != '.rb' path = File.(folder) $rubyrun_file_date_hash[path] = File.mtime(path).to_i else Dir.entries(folder).each {|entry| next if entry =~ /^\.+/ path = File.(entry, folder) case when File.directory?(path) (path) else next if File.extname(entry) != '.rb' $rubyrun_file_date_hash[path] = File.mtime(path).to_i end } end end |
#generate_hash(hash) ⇒ Object
Calcualte the digest from the directory contents of APP_PATHS
262 263 264 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 262 def generate_hash(hash) Digest::MD5.hexdigest(hash.to_s) end |
#get_dir_hash_file ⇒ Object
Return the target file name that stores the serialized directory contents digest This file has to be application dependent, and we use the current directory of the running process to represent the application directory.
295 296 297 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 295 def get_dir_hash_file $rubyrun_signature_folder + '/' + RUBYRUN_DIR_HASH_FILE + '_' + Digest::MD5.hexdigest(Dir.getwd) end |
#get_include_hash_file ⇒ Object
Return the target file name that stores the serialized INCLUDE_HASH
288 289 290 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 288 def get_include_hash_file $rubyrun_signature_folder + '/' + RUBYRUN_INCLUDE_HASH_FILE end |
#identify_candidates ⇒ Object
If the directory content has changed (new files, modified files, new APP_PATHS) a new scan will be required, otherwise the last scan results will simply be reused. When a new scan is finished, the results are serialized.
Digest technique is used to detect changes in directory content.
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 210 def identify_candidates $rubyrun_config['APP_PATHS'].each {|element| element = Dir.getwd if element == '.' print "=> [RubyRun] Preparing RubyRun for #{element}..." (element) puts "finished" } unless $rubyrun_file_date_hash.empty? dir_signature = generate_hash($rubyrun_file_date_hash) if directory_changed?(dir_signature) $rubyrun_file_date_hash.each {|f, date| scan_module_class(f) } serialize_scan_history(dir_signature) end end deserialize_scan_history $rubyrun_file_date_hash.clear if $rubyrun_file_date_hash end |
#init_rubyrun ⇒ Object
-
Get all directories, logs and properties set up correctly
-
Scan files in APP_PATHS to create an initial INCLUDE_HASH
34 35 36 37 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 34 def init_rubyrun ready_rubyrun_env discover_targets end |
#load_config_props(config_file) ⇒ Object
Property file is a yml file. Load the properties into $config hash
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 140 def load_config_props(config_file) begin $rubyrun_config_filename = config_file $rubyrun_config = YAML.load_file(config_file) $rubyrun_logger.info "Properties found in #{config_file}:" RUBYRUN_PROP_DEFAULTS.each {|prop, def_value| $rubyrun_config[prop] = def_value unless config_prop_exists?(prop) $rubyrun_logger.info "#{prop} = #{$rubyrun_config[prop].inspect}" } $rubyrun_logger.info "***** APP_PATHS is nil. Applications will not be instrumented. *****" \ if $rubyrun_config['APP_PATHS'].empty? rescue Exception => e fatal_exit(e) end $rubyrun_debug_args = $rubyrun_config['DEBUG_ARGS'] $rubyrun_debug_obj = $rubyrun_config['DEBUG_OBJ'] $rubyrun_dad = $rubyrun_config['DAD'] $rubyrun_report_timer = $rubyrun_config['REPORT_TIMER'] $rubyrun_report_shift_age = $rubyrun_config['REPORT_SHIFT_AGE'] $rubyrun_trace_hash = $rubyrun_config['TRACE_HASH'] $rubyrun_adapter_hash = $rubyrun_config['DB_ADAPTER_HASH'] validate_opts end |
#make_folder(rubyrun_folders) ⇒ Object
Make sub-directories (folders)
95 96 97 98 99 100 101 102 103 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 95 def make_folder(rubyrun_folders) rubyrun_folders.each {|rubyrun_folder| begin Dir.mkdir(rubyrun_folder) unless File.exist?(rubyrun_folder) rescue Exception => e fatal_exit(e) end } end |
#ready_logfile ⇒ Object
Initialize rubyrun logger and create its own log format
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/rubyrun/rubyrun_initializer__.rb', line 106 def ready_logfile $rubyrun_logger = Logger.new($rubyrun_log_folder + '/' + $rubyrun_file_basename + '_' + $rubyrun_startup_id + '.log', shift_age = 10, shift_size = 4096000) $rubyrun_logger.level = Logger::INFO class << $rubyrun_logger include RubyRunUtils__ def (severity, , progname, msg) "[#{.strftime("%Y-%m-%d %H:%M:%S")}.#{("%.3f" % .to_f).split('.')[1]}] #{get_thread_id} #{msg}\n" end def info(msg, &blk) begin super(msg, &blk) rescue (@logdev = create_log_device; super(msg, &blk)) end end def warn(msg, &blk) begin super(msg, &blk) rescue (@logdev = create_log_device; super(msg, &blk)) end end def fatal(msg, &blk) begin super(msg, &blk) rescue (@logdev = create_log_device; super(msg, &blk)) end end def error(msg, &blk) begin super(msg, &blk) rescue (@logdev = create_log_device; super(msg, &blk)) end end def debug(msg, &blk) begin super(msg, &blk) rescue (@logdev = create_log_device; super(msg, &blk)) end end end end |
#ready_rubyrun_env ⇒ Object
-
Extract the working directory from ENV VAR and recursively create all the
subdirectories if they dont exist
-
Create the log and trace folers
-
Initialize the loggers
-
Load the properties from either the current working directory or
rubyrun working directory
-
Spawn a separate thread to for monitoring and commands
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 46 def ready_rubyrun_env begin $rubyrun_working_dir = Dir.getwd + '/' + RUBYRUN_WORKING_DIR_NAME create_working_dir($rubyrun_working_dir) unless File.exists?($rubyrun_working_dir) ($rubyrun_working_dir) unless File.exists?($rubyrun_working_dir + RUBYRUN_OPTS_FILE) rescue Exception => e fatal_exit(e) end *rubyrun_folders = $rubyrun_working_dir + RUBYRUN_LOG, $rubyrun_working_dir + RUBYRUN_REPORT, $rubyrun_working_dir + RUBYRUN_SIGNATURE make_folder(rubyrun_folders) $rubyrun_log_folder, $rubyrun_report_folder, $rubyrun_signature_folder = *rubyrun_folders $rubyrun_startup_id = ARGV.join.slice(/.*-p([\d]+).*/,1) $rubyrun_startup_id ? $rubyrun_startup_id_type = RUBYRUN_STARTUP_ID_TYPE_PORT : ($rubyrun_startup_id = $$.to_s; $rubyrun_startup_id_type = RUBYRUN_STARTUP_ID_TYPE_PROCESS) $rubyrun_file_basename = File.basename($0, ".*") ready_logfile system_wide_opts = $rubyrun_working_dir + RUBYRUN_OPTS_FILE app_wide_opts = Dir.getwd + '/' + RUBYRUN_OPTS_FILE File.exists?(app_wide_opts) ? load_config_props(app_wide_opts) : load_config_props(system_wide_opts) $rubyrun_tracer = RubyRunHTMLWriter.new($rubyrun_report_folder + '/' + $rubyrun_file_basename + '_' + $rubyrun_startup_id + '_trace.html', METHOD_TRACE_HEADER, shift_age = 10, shift_size = 4096000) unless $rubyrun_trace_hash.empty? end |
#scan_module_class(path) ⇒ Object
Regular expression that detects the class or module names of a given file
279 280 281 282 283 284 285 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 279 def scan_module_class(path) $rubyrun_logger.info "Candidate modules/classes for instrumentation in #{path}:" open(path).grep(/^\s*(class|module)\s+([[:upper:]][A-Za-z0-9_:]*)/m) { $rubyrun_logger.info "\t #{$2}" $rubyrun_include_hash[$2] = [] } end |
#serialize_scan_history(dir_signature) ⇒ Object
Use Marshal to serialize scan results (the include hash)
267 268 269 270 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 267 def serialize_scan_history(dir_signature) File.open(get_include_hash_file, 'w') {|f| Marshal.dump($rubyrun_include_hash, f)} File.open(get_dir_hash_file, 'w') {|f| Marshal.dump(dir_signature, f)} end |
#validate_opts ⇒ Object
Validate the range of REPORT_TIMER and REPORT_SHIFT_AGE Use default values if out of acceptable range
166 167 168 169 170 171 172 173 174 175 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 166 def validate_opts if $rubyrun_report_timer > 3600 || $rubyrun_report_timer < 60 $rubyrun_report_timer = RUBYRUN_PROP_DEFAULTS['REPORT_TIMER'] $rubyrun_logger.warn "REPORT_TIMER value must be between 60 and 3600. #{$rubyrun_report_timer}is used." end if $rubyrun_report_shift_age > 120 || $rubyrun_report_shift_age < 1 $rubyrun_report_shift_age = RUBYRUN_PROP_DEFAULTS['REPORT_SHIFT_AGE'] $rubyrun_logger.warn "REPORT_SHIFT_AGE value must be between 1 and 120. #{$rubyrun_report_shift_age}is used." end end |