Class: IWonder::Metric
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- IWonder::Metric
- Defined in:
- app/models/i_wonder/metric.rb
Constant Summary collapse
- BACK_DATE_ITERATIONS =
30
- QUOTE_REMOVER =
this should strip out quoted text first. This way variables can still be used in where statements
/(\".*?\")/m
- DANGEROUS_WORDS =
/(save|update|create|destroy|delete)/
Instance Attribute Summary collapse
-
#back_date_snapshots ⇒ Object
Returns the value of attribute back_date_snapshots.
Class Method Summary collapse
Instance Method Summary collapse
- #adjust_snapshot_settings ⇒ Object
- #avoid_dangerous_words ⇒ Object
- #back_date_if_chosen ⇒ Object
- #custom_type? ⇒ Boolean
- #event_counter_type? ⇒ Boolean
-
#locked? ⇒ Boolean
TODO: some safegaurds need to be added for editing metrics that are already running.
- #model_counter_is_valid ⇒ Object
- #model_counter_type? ⇒ Boolean
- #remove_existing_snapshots ⇒ Object
- #set_collection_method ⇒ Object
-
#take_snapshot ⇒ Object
TODO: some code to avoid overlap in snapshots needs to be added.
-
#value_from(start_time, end_time) ⇒ Object
returns a hash with all the key values between the two times.
Instance Attribute Details
#back_date_snapshots ⇒ Object
Returns the value of attribute back_date_snapshots.
6 7 8 |
# File 'app/models/i_wonder/metric.rb', line 6 def back_date_snapshots @back_date_snapshots end |
Class Method Details
.take_snapshots ⇒ Object
165 166 167 |
# File 'app/models/i_wonder/metric.rb', line 165 def take_snapshots needs_to_be_measured.find_each(&:take_snapshot) end |
Instance Method Details
#adjust_snapshot_settings ⇒ Object
52 53 54 55 56 57 58 59 60 |
# File 'app/models/i_wonder/metric.rb', line 52 def adjust_snapshot_settings self.frequency ||= -1 if self.takes_snapshots_changed? and not self.takes_snapshots? self.frequency = -1 end self.takes_snapshots = !!(self.frequency.nil? or self.frequency > 0) true # this preventing it from thinking the validation failed end |
#avoid_dangerous_words ⇒ Object
71 72 73 74 75 |
# File 'app/models/i_wonder/metric.rb', line 71 def avoid_dangerous_words if collection_method.present? and collection_method.gsub(QUOTE_REMOVER, "") =~ DANGEROUS_WORDS errors.add(:collection_method, "Doesn't like the word \"#{$1}\"") end end |
#back_date_if_chosen ⇒ Object
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'app/models/i_wonder/metric.rb', line 218 def back_date_if_chosen if @back_date_snapshots and @back_date_snapshots.to_s =~ /1|true|on/i and takes_snapshots? and self.earliest_measurement.nil? self.reload # this keeps bad variables and change states from sneaking in start_time = Time.zone.now - BACK_DATE_ITERATIONS * frequency end_time = start_time + frequency start_time += 1.second self.snapshots.create(:data => run_collection_method_from(start_time, end_time), :start_time => start_time, :end_time => end_time) self.update_attribute(:earliest_measurement, start_time) # not that the first snapshot is taken, running the :take_snapshot command will fill in the rest take_snapshot end end |
#custom_type? ⇒ Boolean
114 115 116 |
# File 'app/models/i_wonder/metric.rb', line 114 def custom_type? self.collection_type == "custom" end |
#event_counter_type? ⇒ Boolean
108 109 110 |
# File 'app/models/i_wonder/metric.rb', line 108 def event_counter_type? self.collection_type == "event_counter" or self.collection_type.nil? end |
#locked? ⇒ Boolean
TODO: some safegaurds need to be added for editing metrics that are already running.
119 120 121 |
# File 'app/models/i_wonder/metric.rb', line 119 def locked? snapshots.count > 0 end |
#model_counter_is_valid ⇒ Object
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 |
# File 'app/models/i_wonder/metric.rb', line 78 def model_counter_is_valid if model_counter_type? begin self.model_counter_class.constantize if self.model_counter_scopes.present? if self.model_counter_scopes =~ /\s/ errors.add(:model_counter_scopes, "can't contain spaces") elsif self.model_counter_scopes =~ DANGEROUS_WORDS errors.add(:model_counter_scopes, "can't contain dangerous words (save|update|create|destroy|delete)") else self.model_counter_scopes.split(".").each{|sc| unless self.model_counter_class.constantize.respond_to?(sc) errors.add(:model_counter_scopes, "doesn't respond to '#{sc}'") end } end end if self.model_counter_method == "Creation Rate" and !self.model_counter_class.constantize.new.respond_to?("created_at") errors.add(:base, "Can't calculate creation rate on models without a :created_at column") end rescue Exception => e errors.add(:model_counter_class, "is not a valid class") end end end |
#model_counter_type? ⇒ Boolean
111 112 113 |
# File 'app/models/i_wonder/metric.rb', line 111 def model_counter_type? self.collection_type == "model_counter" end |
#remove_existing_snapshots ⇒ Object
63 64 65 66 67 68 |
# File 'app/models/i_wonder/metric.rb', line 63 def remove_existing_snapshots if collection_method_changed? or frequency_changed? self.earliest_measurement = nil self.snapshots.each(&:mark_for_destruction) end end |
#set_collection_method ⇒ Object
41 42 43 44 45 46 47 48 49 |
# File 'app/models/i_wonder/metric.rb', line 41 def set_collection_method if event_counter_type? set_event_collection_method elsif model_counter_type? set_model_collection_method elsif custom_type? # It should have saved directly end end |
#take_snapshot ⇒ Object
TODO: some code to avoid overlap in snapshots needs to be added
204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'app/models/i_wonder/metric.rb', line 204 def take_snapshot start_time, end_time = timeframe_for_next_snapshot while end_time <= Time.zone.now do self.snapshots.create(:data => run_collection_method_from(start_time, end_time), :start_time => start_time, :end_time => end_time) if self.earliest_measurement.nil? or self.earliest_measurement > start_time self.update_attribute(:earliest_measurement, start_time) end start_time, end_time = timeframe_for_next_snapshot end end |
#value_from(start_time, end_time) ⇒ Object
returns a hash with all the key values between the two times. If it has been collecting integers, the key will be the name of the metric
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'app/models/i_wonder/metric.rb', line 172 def value_from(start_time, end_time) if takes_snapshots? data = self.snapshots.where("start_time < ? AND end_time > ?", end_time, start_time).collect(&:data) else data = [run_collection_method_from(start_time, end_time)] end # at this point we have an array of hashs or integers array_of_hashes = data.collect{|d| d.is_a?(Hash) ? d.stringify_keys! : {self.name => d} } # At this point we have an array of hashes where the key is the series name. Now we have to merge them into a single hash # TODO: if it is a custom metric, follow the combination_rule final_hash = {} array_of_hashes.each{|hash| hash.each{|key, value| final_hash[key] = (final_hash[key] || 0.0) + value.to_f } } if combination_rule == "average" # we have to now divide by the number of snapshots we added together final_hash.each{|key, value| final_hash[key] = final_hash[key] / array_of_hashes.length.to_f } end return final_hash end |