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_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_THREAD_END_HASH, RubyRunGlobals::RUBYRUN_VIEW_HASH, RubyRunGlobals::RUBYRUN_WORKING_DIR
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.
-
#deserialize_scan_history ⇒ Object
Use Marshal to de-serialize the include and exclude hashes.
-
#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_exclude_hash_file ⇒ Object
return the target file name that stores the serialized EXCLUDE_HASH.
-
#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(logname) ⇒ 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.
-
#scan_super(path) ⇒ Object
Line up all the method names in a file by line # Line up all the line numbers that contain the keyworkd super Collate the two arrays to determine which method has super in it Put these method names in EXCLUDE_HASH and skip instrumentation.
-
#serialize_scan_history(dir_signature) ⇒ Object
Use Marshal to serialize scan results (the include and exclude hashes).
-
#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_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
129 130 131 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 129 def config_prop_exists?(prop) $rubyrun_config.has_key?(prop) && !$rubyrun_config[prop].nil? ? true : false end |
#deserialize_scan_history ⇒ Object
Use Marshal to de-serialize the include and exclude hashes
223 224 225 226 227 228 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 223 def deserialize_scan_history f = get_include_hash_file $rubyrun_include_hash = File.exists?(f) ? File.open(f) {|f| Marshal.load(f)} : {} f = get_exclude_hash_file $rubyrun_exclude_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)
204 205 206 207 208 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 204 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
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 136 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.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.
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 180 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
211 212 213 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 211 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.
282 283 284 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 282 def get_dir_hash_file @rubyrun_signature_folder + '/' + RUBYRUN_DIR_HASH_FILE + '_' + Digest::MD5.hexdigest(Dir.getwd) end |
#get_exclude_hash_file ⇒ Object
return the target file name that stores the serialized EXCLUDE_HASH
275 276 277 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 275 def get_exclude_hash_file @rubyrun_signature_folder + '/' + RUBYRUN_EXCLUDE_HASH_FILE end |
#get_include_hash_file ⇒ Object
Return the target file name that stores the serialized INCLUDE_HASH
270 271 272 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 270 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.
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 158 def identify_candidates $rubyrun_config['APP_PATHS'].each {|element| element = Dir.getwd if element == '.' (element) } unless $rubyrun_file_date_hash.empty? dir_signature = generate_hash($rubyrun_file_date_hash) exclude_array = [] if directory_changed?(dir_signature) $rubyrun_file_date_hash.each {|f, date| scan_module_class(f) scan_super(f).each {|name| exclude_array << name} } $rubyrun_exclude_hash['*'] = exclude_array.uniq if exclude_array.length > 0 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
and an EXCLUDE_HASH
33 34 35 36 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 33 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
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 91 def load_config_props(config_file) begin $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)
67 68 69 70 71 72 73 74 75 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 67 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(logname) ⇒ Object
Initialize rubyrun logger and create its own log format
78 79 80 81 82 83 84 85 86 87 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 78 def ready_logfile(logname) $rubyrun_logger = Logger.new(@rubyrun_log_folder + '/' + logname + '_' + $$.to_s + '.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 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
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 45 def ready_rubyrun_env begin raise RuntimeError, "environment variable #{RUBYRUN_WORKING_DIR} not set", caller \ unless env_var_exists?(RUBYRUN_WORKING_DIR) rubyrun_working_dir = ENV[RUBYRUN_WORKING_DIR] raise RuntimeError, "Missing #{RUBYRUN_OPTS_FILE} in #{rubyrun_working_dir}", caller \ 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 logname = File.basename($0, ".*") ready_logfile(logname) 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 + '/' + logname + '_' + $$.to_s + '_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
231 232 233 234 235 236 237 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 231 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 |
#scan_super(path) ⇒ Object
Line up all the method names in a file by line # Line up all the line numbers that contain the keyworkd super Collate the two arrays to determine which method has super in it Put these method names in EXCLUDE_HASH and skip instrumentation
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 243 def scan_super(path) $rubyrun_logger.info "Method(s) to be excluded from instrumentation in #{path}:" method_name_array, method_lineno_array, super_array, exclude_array = [],[],[],[] open(path) {|f| f.readlines.each_with_index {|code, lineno| code.scan(/^\s*def\s+(.*)\(+.*\)+/m) (method_name_array << $1; method_lineno_array << lineno) if $1 code.scan(/^\s*(super)/m) super_array << lineno if $1 } } method_name_array.reverse! method_lineno_array.reverse! super_array.each {|lineno| method_lineno_array.each_with_index {|linenum, i| unless lineno < linenum $rubyrun_logger.info "\t #{method_name_array[i]}" m = method_name_array[i].split('.') exclude_array << (m.length > 1 ? m[1] : m[0]) break end } } exclude_array end |
#serialize_scan_history(dir_signature) ⇒ Object
Use Marshal to serialize scan results (the include and exclude hashes)
216 217 218 219 220 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 216 def serialize_scan_history(dir_signature) File.open(get_include_hash_file, 'w') {|f| Marshal.dump($rubyrun_include_hash, f)} File.open(get_exclude_hash_file, 'w') {|f| Marshal.dump($rubyrun_exclude_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
116 117 118 119 120 121 122 123 124 125 |
# File 'lib/rubyrun/rubyrun_initializer__.rb', line 116 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 |