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_method_name
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
180 181 182 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 180 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
135 136 137 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 135 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
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 78 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
69 70 71 72 73 74 75 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 69 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
274 275 276 277 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 274 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)
256 257 258 259 260 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 256 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
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 187 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.
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 232 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
263 264 265 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 263 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.
296 297 298 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 296 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
289 290 291 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 289 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.
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 211 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
35 36 37 38 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 35 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
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 141 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)
96 97 98 99 100 101 102 103 104 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 96 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
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 107 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
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 47 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
280 281 282 283 284 285 286 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 280 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)
268 269 270 271 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 268 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
167 168 169 170 171 172 173 174 175 176 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 167 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 |