Class: MetricScriptExecutor
- Inherits:
-
Object
- Object
- MetricScriptExecutor
- Defined in:
- lib/instrumental_tools/metric_script_executor.rb
Instance Attribute Summary collapse
-
#directory ⇒ Object
readonly
Returns the value of attribute directory.
-
#last_ran_at ⇒ Object
readonly
Returns the value of attribute last_ran_at.
-
#previous ⇒ Object
readonly
Returns the value of attribute previous.
Instance Method Summary collapse
- #can_execute_file?(path) ⇒ Boolean
- #can_execute_in_directory?(directory) ⇒ Boolean
- #execute_custom_script(full_path) ⇒ Object
- #file_is_owner_only?(file_stat) ⇒ Boolean
-
#initialize(directory) ⇒ MetricScriptExecutor
constructor
A new instance of MetricScriptExecutor.
- #powershell_script?(path) ⇒ Boolean
- #print_executable_in_directory_warning(directory) ⇒ Object
- #print_executable_warning(path) ⇒ Object
- #run ⇒ Object
- #windows? ⇒ Boolean
Constructor Details
#initialize(directory) ⇒ MetricScriptExecutor
Returns a new instance of MetricScriptExecutor.
7 8 9 10 |
# File 'lib/instrumental_tools/metric_script_executor.rb', line 7 def initialize(directory) @directory = directory @previous = {} end |
Instance Attribute Details
#directory ⇒ Object (readonly)
Returns the value of attribute directory.
5 6 7 |
# File 'lib/instrumental_tools/metric_script_executor.rb', line 5 def directory @directory end |
#last_ran_at ⇒ Object (readonly)
Returns the value of attribute last_ran_at.
5 6 7 |
# File 'lib/instrumental_tools/metric_script_executor.rb', line 5 def last_ran_at @last_ran_at end |
#previous ⇒ Object (readonly)
Returns the value of attribute previous.
5 6 7 |
# File 'lib/instrumental_tools/metric_script_executor.rb', line 5 def previous @previous end |
Instance Method Details
#can_execute_file?(path) ⇒ Boolean
12 13 14 15 |
# File 'lib/instrumental_tools/metric_script_executor.rb', line 12 def can_execute_file?(path) stat = File::Stat.new(path) powershell_script?(path) || (stat.executable? && file_is_owner_only?(stat)) end |
#can_execute_in_directory?(directory) ⇒ Boolean
17 18 19 20 |
# File 'lib/instrumental_tools/metric_script_executor.rb', line 17 def can_execute_in_directory?(directory) stat = File::Stat.new(directory) stat.directory? && file_is_owner_only?(stat) end |
#execute_custom_script(full_path) ⇒ Object
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/instrumental_tools/metric_script_executor.rb', line 57 def execute_custom_script(full_path) stdin_r, stdin_w = IO.pipe stdout_r, stdout_w = IO.pipe stderr_r, stderr_w = IO.pipe previous_status, previous_time, previous_output = previous[full_path] stdin_w.write(previous_output || "") stdin_w.close cmd = [full_path, (previous_time || 0).to_i, (previous_status && previous_status.to_i)].compact.map(&:to_s) if powershell_script?(full_path) && !File.executable?(full_path) native_path = if File::ALT_SEPARATOR full_path.split(File::SEPARATOR).join(File::ALT_SEPARATOR) else full_path end cmd[0] = native_path cmd.unshift "-File" cmd.unshift "powershell" end pid = Process.spawn(*cmd, :chdir => File.dirname(full_path), :in => stdin_r, :out => stdout_w, :err => stderr_w) exit_status = nil exec_time = Benchmark.realtime do pid, exit_status = Process.wait2(pid) end if exec_time > 1.0 puts "[SLOW SCRIPT] Time to execute process #{full_path} took #{exec_time} seconds" end [stdin_r, stdout_w, stderr_w].each(&:close) output = stdout_r.read.to_s.chomp stderr = stderr_r.read.to_s.chomp unless stderr.empty? puts "[STDERR] #{full_path} (PID:#{pid}) [#{Time.now.to_s}]:: #{stderr}" end [stdout_r, stderr_r].each(&:close) [full_path, [exit_status, Time.now, output]] end |
#file_is_owner_only?(file_stat) ⇒ Boolean
30 31 32 33 34 35 36 37 |
# File 'lib/instrumental_tools/metric_script_executor.rb', line 30 def file_is_owner_only?(file_stat) owned_by_executor = file_stat.owned? unless windows? owned_by_executor && ((file_stat.mode & 0xFFF) ^ 0O700) == 0 else owned_by_executor end end |
#powershell_script?(path) ⇒ Boolean
22 23 24 |
# File 'lib/instrumental_tools/metric_script_executor.rb', line 22 def powershell_script?(path) windows? && File.extname(path).to_s.downcase == ".ps1" end |
#print_executable_in_directory_warning(directory) ⇒ Object
49 50 51 52 53 54 55 |
# File 'lib/instrumental_tools/metric_script_executor.rb', line 49 def print_executable_in_directory_warning(directory) if windows? puts "Directory #{directory} has gone away, not scanning for metric scripts." else puts "Directory #{directory} has gone away or does not have the correct permissions (0700), not scanning for metric scripts." end end |
#print_executable_warning(path) ⇒ Object
39 40 41 42 43 44 45 46 47 |
# File 'lib/instrumental_tools/metric_script_executor.rb', line 39 def print_executable_warning(path) if windows? puts "[INFO] Cannot execute #{path}, must exist and be executable" else uid = Process.uid user = Etc.getpwuid(uid).name puts "[INFO] Cannot execute #{path}, must exist, be executable and only readable/writable by #{user}/#{uid}" end end |
#run ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/instrumental_tools/metric_script_executor.rb', line 109 def run process_to_output = {} if can_execute_in_directory?(directory) current = Dir[File.join(directory, "*")].map do |path| full_path = File.(path) if can_execute_file?(path) execute_custom_script(full_path) else if !File.directory?(full_path) print_executable_warning(full_path) end [full_path, []] end end process_to_output = Hash[current] @previous = process_to_output else print_executable_in_directory_warning(directory) end process_to_output.flat_map do |path, (status, time, output)| if status && status.success? prefix = File.basename(path).split(".")[0..-2].join(".").gsub(/[^\d\w\-\_\.]/i, "_") output.lines # each line .map { |line| line.chomp.split } # split by whitespace .select { |data| (2..3).include?(data.size) } # and only valid name value time? pairs .map { |(name, value, specific_time)| [[prefix, name].join("."), value.to_f, (specific_time || time).to_i] } # with value coerced to a float end end.compact end |
#windows? ⇒ Boolean
26 27 28 |
# File 'lib/instrumental_tools/metric_script_executor.rb', line 26 def windows? RUBY_PLATFORM =~ /(win32|mswin|mingw)/ end |