Class: ActiveRecordProfiler::Collector
- Inherits:
-
Object
- Object
- ActiveRecordProfiler::Collector
- Defined in:
- lib/active-record-profiler/collector.rb
Constant Summary collapse
- DURATION =
0
- COUNT =
1
- LONGEST =
2
- LONGEST_SQL =
3
- LOCATION =
-1
- AVG_DURATION =
-2
- DATE_FORMAT =
'%Y-%m-%d'
- HOUR_FORMAT =
'-%H'
- DATETIME_FORMAT =
DATE_FORMAT + HOUR_FORMAT + '-%M'
- AGGREGATE_QUIET_PERIOD =
1.minutes
- CSV_DURATION =
0
- CSV_COUNT =
1
- CSV_AVG =
2
- CSV_LONGEST =
3
- CSV_LOCATION =
4
- CSV_LONGEST_SQL =
5
- NON_APP_CODE_DESCRIPTION =
'Non-application code'
Instance Attribute Summary collapse
-
#last_stats_flush ⇒ Object
Returns the value of attribute last_stats_flush.
-
#profile_data_directory ⇒ Object
Returns the value of attribute profile_data_directory.
-
#query_sites ⇒ Object
Returns the value of attribute query_sites.
Class Method Summary collapse
Instance Method Summary collapse
- #aggregate(options = {}) ⇒ Object
- #call_location_name(caller_array = nil) ⇒ Object
- #flush_query_sites_statistics ⇒ Object
-
#initialize ⇒ Collector
constructor
A new instance of Collector.
- #record_caller_info(location, seconds, sql) ⇒ Object
- #record_self_info(seconds, name) ⇒ Object
- #save_aggregated(date = nil) ⇒ Object
- #should_flush_stats? ⇒ Boolean
- #sorted_locations(sort_field = nil, max_locations = nil) ⇒ Object
Constructor Details
#initialize ⇒ Collector
Returns a new instance of Collector.
72 73 74 75 76 |
# File 'lib/active-record-profiler/collector.rb', line 72 def initialize @query_sites = {} @last_stats_flush = nil @profile_data_directory = self.class.profile_dir end |
Instance Attribute Details
#last_stats_flush ⇒ Object
Returns the value of attribute last_stats_flush.
54 55 56 |
# File 'lib/active-record-profiler/collector.rb', line 54 def last_stats_flush @last_stats_flush end |
#profile_data_directory ⇒ Object
Returns the value of attribute profile_data_directory.
56 57 58 |
# File 'lib/active-record-profiler/collector.rb', line 56 def profile_data_directory @profile_data_directory end |
#query_sites ⇒ Object
Returns the value of attribute query_sites.
55 56 57 |
# File 'lib/active-record-profiler/collector.rb', line 55 def query_sites @query_sites end |
Class Method Details
.clear_data ⇒ Object
66 67 68 69 70 |
# File 'lib/active-record-profiler/collector.rb', line 66 def self.clear_data dir = Dir.new(profile_dir) prof_files = dir.entries.select{ |filename| /.prof$/.match(filename) }.map{ |filename| File.join(dir.path, filename) } FileUtils.rm(prof_files) if prof_files.size > 0 end |
.instance ⇒ Object
58 59 60 |
# File 'lib/active-record-profiler/collector.rb', line 58 def self.instance Thread.current[:active_record_profiler_collector] ||= Collector.new end |
.profile_self? ⇒ Boolean
62 63 64 |
# File 'lib/active-record-profiler/collector.rb', line 62 def self.profile_self? self.profile_self end |
Instance Method Details
#aggregate(options = {}) ⇒ Object
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 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/active-record-profiler/collector.rb', line 117 def aggregate( = {}) prefix = [:prefix] compact = [:compact] raise "Cannot compact without a prefix!" if compact && prefix.nil? return self.query_sites unless File.exists?(self.profile_data_directory) dir = Dir.new(self.profile_data_directory) now = Time.now raw_files_processed = [] date_regexp = Regexp.new(prefix) if prefix dir.each do |filename| next unless /.prof$/.match(filename) next if date_regexp && ! date_regexp.match(filename) # Parse the datetime out of the filename and convert it to localtime begin file_time = DateTime.strptime(filename, DATETIME_FORMAT) file_time = Time.local(file_time.year, file_time.month, file_time.day, file_time.hour, file_time.min) rescue Exception => e if e.to_s != 'invalid date' raise e end end if (file_time.nil? || ((file_time + AGGREGATE_QUIET_PERIOD) < now)) begin update_from_file(File.join(dir.path, filename)) raw_files_processed << filename if file_time # any files that are already aggregated don't count rescue Exception => e RAILS_DEFAULT_LOGGER.warn "Unable to read file #{filename}: #{e.}" end else Rails.logger.info "Skipping file #{filename} because it is too new and may still be open for writing." end end if compact && raw_files_processed.size > 0 write_file(File.join(dir.path, "#{prefix}.prof")) raw_files_processed.each do |filename| FileUtils.rm(File.join(dir.path, filename)) end end return self.query_sites end |
#call_location_name(caller_array = nil) ⇒ Object
78 79 80 |
# File 'lib/active-record-profiler/collector.rb', line 78 def call_location_name(caller_array = nil) find_app_call_location(caller_array) || NON_APP_CODE_DESCRIPTION end |
#flush_query_sites_statistics ⇒ Object
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/active-record-profiler/collector.rb', line 97 def flush_query_sites_statistics pid = $$ thread_id = Thread.current.object_id flush_time = Time.now site_count = self.query_sites.keys.size Rails.logger.info("Flushing ActiveRecordProfiler statistics for PID #{pid} at #{flush_time} (#{site_count} sites).") if (site_count > 0) FileUtils.makedirs(self.profile_data_directory) filename = File.join(self.profile_data_directory, "#{flush_time.strftime(DATETIME_FORMAT)}.#{pid}-#{thread_id}.prof") write_file(filename) # Nuke each value to make sure it can be reclaimed by Ruby self.query_sites.keys.each{ |k| self.query_sites[k] = nil } end self.query_sites = {} self.last_stats_flush = flush_time end |
#record_caller_info(location, seconds, sql) ⇒ Object
82 83 84 85 86 |
# File 'lib/active-record-profiler/collector.rb', line 82 def record_caller_info(location, seconds, sql) return if sql_ignore_pattern.match(sql) update_counts(location, seconds, 1, sql) end |
#record_self_info(seconds, name) ⇒ Object
88 89 90 |
# File 'lib/active-record-profiler/collector.rb', line 88 def record_self_info(seconds, name) record_caller_info(trim_location(caller.first), seconds, name) end |
#save_aggregated(date = nil) ⇒ Object
165 166 167 |
# File 'lib/active-record-profiler/collector.rb', line 165 def save_aggregated(date = nil) aggregate(:date => date, :compact => true) end |
#should_flush_stats? ⇒ Boolean
92 93 94 95 |
# File 'lib/active-record-profiler/collector.rb', line 92 def should_flush_stats? self.last_stats_flush ||= Time.now return(Time.now > self.last_stats_flush + stats_flush_period) end |
#sorted_locations(sort_field = nil, max_locations = nil) ⇒ Object
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/active-record-profiler/collector.rb', line 169 def sorted_locations(sort_field = nil, max_locations = nil) sort_field ||= DURATION case sort_field when LOCATION sorted = self.query_sites.keys.sort when AVG_DURATION sorted = self.query_sites.keys.sort_by{ |k| (self.query_sites[k][DURATION] / self.query_sites[k][COUNT]) }.reverse when DURATION, COUNT, LONGEST sorted = self.query_sites.keys.sort{ |a,b| self.query_sites[b][sort_field] <=> self.query_sites[a][sort_field] } else raise "Invalid sort field: #{sort_field}" end if max_locations && max_locations > 0 sorted.first(max_locations) else sorted end end |