Class: Hitimes::TimedValueMetric

Inherits:
Metric
  • Object
show all
Defined in:
lib/hitimes/timed_value_metric.rb

Overview

A TimedValueMetric holds the metrics on how long it takes to do a batch of something. something. For measuring how long a method takes to operate on N items.

tm = TimedValueMetric.new( 'my-batch-method' )

42.times do 
  tm.start
  number_of_items_processed = do_something
  tm.stop( number_of_items_processed )
end

puts "#{ tm.name } operated at a rate of #{ tm.rate } calls per second"

TimedValueMetric combines the usefulness of a ValueMetric and a TimedMetric. The stats are available for both the time it took to do the operation and the sizes of the batches that were run.

A TimedValueMetric keeps track of both the time it took to do an operation and the size of the batch that was operated on. These metrics are kept separately as timed_stats and value_stats accessors.

Instance Attribute Summary collapse

Attributes inherited from Metric

#additional_data, #name, #sampling_delta

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Metric

#sampling_start_time, #sampling_stop_time, #utc_microseconds

Constructor Details

#initialize(name, additional_data = {}) ⇒ TimedValueMetric

:call-seq:

TimedValueMetric.new( 'name') -> TimedValueMetric
TimedValueMetric.new( 'name', 'other' => 'data') -> TimedValueMetric

Create a new TimedValueMetric giving it a name and additional data. additional_data may be anything that follows the to_hash protocol



58
59
60
61
62
63
# File 'lib/hitimes/timed_value_metric.rb', line 58

def initialize( name, additional_data = {} )
  super( name, additional_data )
  @timed_stats      = Stats.new
  @value_stats      = Stats.new
  @current_interval = Interval.new
end

Instance Attribute Details

#timed_statsObject (readonly)

holds all the Timed statistics



31
32
33
# File 'lib/hitimes/timed_value_metric.rb', line 31

def timed_stats
  @timed_stats
end

#value_statsObject (readonly)

holds all the Value statistics



34
35
36
# File 'lib/hitimes/timed_value_metric.rb', line 34

def value_stats
  @value_stats
end

Class Method Details

.now(name, additional_data = {}) ⇒ Object

:call-seq:

TimedValueMetric.now( 'name' ) -> TimedValueMetric

Return a TimedValueMetric that has been started



43
44
45
46
47
# File 'lib/hitimes/timed_value_metric.rb', line 43

def now( name, additional_data = {} )
  t = TimedValueMetric.new( name, additional_data )
  t.start
  return t
end

Instance Method Details

#durationObject

:call-seq:

timed_value_metric.duration -> Float

The duration of measured time from the metric.



172
173
174
# File 'lib/hitimes/timed_value_metric.rb', line 172

def duration
  @timed_stats.sum
end

#measure(value, &block) ⇒ Object

:call-seq:

timed_value_metric.measure( value ) {  ... } -> Object

Measure the execution of a block and add those stats to the running stats. The return value is the return value of the block. A value must be passed into measure to update the value_stats portion of the TimedValueMetric.



129
130
131
132
133
134
135
136
137
138
# File 'lib/hitimes/timed_value_metric.rb', line 129

def measure( value, &block )
  return_value = nil
  begin
    start
    return_value = yield
  ensure
    stop( value )
  end
  return return_value
end

#rateObject

:call-seq:

timed_value_metric.rate -> Float

Rate in the context of the TimedValueMetric is different than the TimedMetric. In the TimedValueMetric, each measurement of time is associated with a quantity of things done during that unit of time. So the rate for a TimedValueMetric is the (sum of all quantities sampled) / ( sum of all durations measured )

For example, say you were measuring, using a TimedValueMetric batch jobs that had individual units of work.

tvm = TimedValueMetric.new( 'some-batch' )
tvm.start
# process a batch of 12 units
duration1 = tvm.stop( 12 )

tvm.start
# process a larger batch of 42 units
duration2 = tvm.stop( 42 )

At this point the rate of units per second is calculated as ( 12 + 42 ) / ( duration1 + duration2 )

some_batch_rate = tvm.rate # returns ( 34 / ( duration1+duration2 ) )


212
213
214
# File 'lib/hitimes/timed_value_metric.rb', line 212

def rate
  @value_stats.sum / @timed_stats.sum
end

#running?Boolean

:call-seq:

timed_value_metric.running? -> true or false

return whether or not the metric is currently timing something.

Returns:

  • (Boolean)


71
72
73
# File 'lib/hitimes/timed_value_metric.rb', line 71

def running?
  @current_interval.running?
end

#split(value) ⇒ Object

:call-seq:

timed_value_metric.split( value ) -> Float

Split the current metric. Essentially, mark a split time. This means stop the current interval, with the givein value and create a new interval, but make sure that the new interval lines up exactly, timewise, behind the previous interval.

If the metric is running, then split returns the duration of the previous interval, i.e. the split-time. If the metric is not running, nothing happens, no stats are updated, and false is returned.



154
155
156
157
158
159
160
161
162
163
164
# File 'lib/hitimes/timed_value_metric.rb', line 154

def split( value )
  if @current_interval.running? then 
    next_interval = @current_interval.split
    d = @current_interval.duration
    @timed_stats.update( d )
    @value_stats.update( value )
    @current_interval = next_interval 
    return d
  end 
  return false
end

#startObject

:call-seq:

timed_value_metric.start -> nil

Start the current timer, if the current timer is already started, then this is a noop.



82
83
84
85
86
87
88
89
# File 'lib/hitimes/timed_value_metric.rb', line 82

def start
  if not @current_interval.running? then
    @current_interval.start
    @sampling_start_time ||= self.utc_microseconds() 
    @sampling_start_interval ||= Interval.now
  end
  nil
end

#stop(value) ⇒ Object

:call-seq:

timed_value_metric.stop( count ) -> Float or nil

Stop the current metric. The count parameter must be a value to update to the value portion of the TimedValueMetric. Generally this is probably the number of things that were operated upon since start was invoked.

This updates both the value_stats and timed_stats stats and removes the current interval. If the metric is stopped then the duration of the last Interval is returned. If the metric was already stopped before this call, then false is returned and no stats are updated.



106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/hitimes/timed_value_metric.rb', line 106

def stop( value )
  if @current_interval.running? then
    d = @current_interval.stop
    @timed_stats.update( d )
    @current_interval = Interval.new
    @value_stats.update( value )

    # update the lenght of time we have been sampling
    @sampling_delta = @sampling_start_interval.duration_so_far

    return d
  end
  return false
end

#to_hashObject

:call-seq:

metric.to_hash -> Hash

Convert the metric to a hash



222
223
224
225
226
227
228
229
# File 'lib/hitimes/timed_value_metric.rb', line 222

def to_hash
  h = super
  h['timed_stats'] = @timed_stats.to_hash
  h['value_stats'] = @value_stats.to_hash( Stats::STATS - %w[ rate ] )
  h['rate'] = self.rate
  h['unit_count'] = self.unit_count
  return h
end

#unit_countObject

:call-seq:

timed_value_metric.unit_count -> Float

The sum of all values passed to stop or skip or measure



182
183
184
# File 'lib/hitimes/timed_value_metric.rb', line 182

def unit_count
  @value_stats.sum
end