Class: RequestLogAnalyzer::Tracker::Duration

Inherits:
Base
  • Object
show all
Defined in:
lib/request_log_analyzer/tracker/duration.rb

Overview

Analyze the duration of a specific attribute

Options

  • :amount The amount of lines in the report

  • :category Proc that handles request categorization for given fileformat (REQUEST_CATEGORIZER)

  • :duration The field containing the duration in the request hash.

  • :if Proc that has to return !nil for a request to be passed to the tracker.

  • :line_type The line type that contains the duration field (determined by the category proc).

  • :title Title do be displayed above the report

  • :unless Handle request if this proc is false for the handled request.

The items in the update request hash are set during the creation of the Duration tracker.

Example output:

Request duration - top 20 by cumulative time   |    Hits |      Sum. |      Avg.
---------------------------------------------------------------------------------
EmployeeController#show.html [GET]             |    4742 |  4922.56s |     1.04s
EmployeeController#update.html [POST]          |    4647 |  2731.23s |     0.59s
EmployeeController#index.html [GET]            |    5802 |  1477.32s |     0.25s
.............

Instance Attribute Summary collapse

Attributes inherited from Base

#options

Instance Method Summary collapse

Methods inherited from Base

#finalize, #initialize, #setup_should_update_checks!, #should_update?

Constructor Details

This class inherits a constructor from RequestLogAnalyzer::Tracker::Base

Instance Attribute Details

#categoriesObject (readonly)

Returns the value of attribute categories.



25
26
27
# File 'lib/request_log_analyzer/tracker/duration.rb', line 25

def categories
  @categories
end

Instance Method Details

#average_duration(cat) ⇒ Object

Get the average duration of a specific category. cat The category



93
94
95
# File 'lib/request_log_analyzer/tracker/duration.rb', line 93

def average_duration(cat)
  categories[cat][:cumulative] / categories[cat][:hits]  
end

#cumulative_duration(cat) ⇒ Object

Get the total duration of a specific category. cat The category



75
76
77
# File 'lib/request_log_analyzer/tracker/duration.rb', line 75

def cumulative_duration(cat)
  categories[cat][:cumulative]
end

#hits(cat) ⇒ Object

Get the number of hits of a specific category. cat The category



69
70
71
# File 'lib/request_log_analyzer/tracker/duration.rb', line 69

def hits(cat)
  categories[cat][:hits]
end

#max_duration(cat) ⇒ Object

Get the maximum duration of a specific category. cat The category



87
88
89
# File 'lib/request_log_analyzer/tracker/duration.rb', line 87

def max_duration(cat)
  categories[cat][:max]
end

#min_duration(cat) ⇒ Object

Get the minimal duration of a specific category. cat The category



81
82
83
# File 'lib/request_log_analyzer/tracker/duration.rb', line 81

def min_duration(cat)
  categories[cat][:min]
end

#overall_average_durationObject

Get the average duration of a all categories.



98
99
100
# File 'lib/request_log_analyzer/tracker/duration.rb', line 98

def overall_average_duration
  overall_cumulative_duration / overall_hits
end

#overall_cumulative_durationObject

Get the cumlative duration of a all categories.



103
104
105
# File 'lib/request_log_analyzer/tracker/duration.rb', line 103

def overall_cumulative_duration
  categories.inject(0.0) { |sum, (name, cat)| sum + cat[:cumulative] }  
end

#overall_hitsObject

Get the total hits of a all categories.



108
109
110
# File 'lib/request_log_analyzer/tracker/duration.rb', line 108

def overall_hits
  categories.inject(0) { |sum, (name, cat)| sum + cat[:hits] }
end

#prepareObject

Check if duration and catagory option have been received,



28
29
30
31
32
33
34
35
# File 'lib/request_log_analyzer/tracker/duration.rb', line 28

def prepare
  raise "No duration field set up for category tracker #{self.inspect}" unless options[:duration]
  raise "No categorizer set up for duration tracker #{self.inspect}" unless options[:category]

  @categorizer  = options[:category].respond_to?(:call) ? options[:category] : lambda { |request| request[options[:category]] }
  @durationizer = options[:duration].respond_to?(:call) ? options[:duration] : lambda { |request| request[options[:duration]] }
  @categories = {}
end

#report(output) ⇒ Object

Generate a request duration report to the given output object By default colulative and average duration are generated. Any options for the report should have been set during initialize. output The output object



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/request_log_analyzer/tracker/duration.rb', line 166

def report(output)

  options[:title]  ||= 'Request duration'
  options[:report] ||= [:cumulative, :average]
  options[:top]    ||= 20
  
  options[:report].each do |report|
    case report
    when :average
      report_table(output, options[:top], :title => "#{options[:title]} - top #{options[:top]} by average time", :sort => :average) { |cat| cat[:cumulative] / cat[:hits] }  
    when :cumulative
      report_table(output, options[:top], :title => "#{options[:title]} - top #{options[:top]} by cumulative time", :sort => :cumulative) { |cat| cat[:cumulative] }
    when :hits
      report_table(output, options[:top], :title => "#{options[:title]} - top #{options[:top]} by hits", :sort => :hits) { |cat| cat[:hits] }
    else
      raise "Unknown duration report specified: #{report}!"
    end
  end
end

#report_table(output, amount = 10, options = {}, &block) ⇒ Object

Block function to build a result table using a provided sorting function. output The output object. amount The number of rows in the report table (default 10).

Options

* </tt>:title</tt> The title of the table
* </tt>:sort</tt> The key to sort on (:hits, :cumulative, :average, :min or :max)


143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/request_log_analyzer/tracker/duration.rb', line 143

def report_table(output, amount = 10, options = {}, &block)

  output.title(options[:title])

  top_categories = @categories.sort { |a, b| yield(b[1]) <=> yield(a[1]) }.slice(0...amount)
  output.table({:title => 'Category', :width => :rest}, 
        {:title => 'Hits',       :align => :right, :highlight => (options[:sort] == :hits), :min_width => 4}, 
        {:title => 'Cumulative', :align => :right, :highlight => (options[:sort] == :cumulative), :min_width => 10}, 
        {:title => 'Average',    :align => :right, :highlight => (options[:sort] == :average), :min_width => 8},
        {:title => 'Min',        :align => :right, :highlight => (options[:sort] == :min)}, 
        {:title => 'Max',        :align => :right, :highlight => (options[:sort] == :max)}) do |rows|
  
    top_categories.each do |(cat, info)|
      rows << [cat, info[:hits], "%0.02fs" % info[:cumulative], "%0.02fs" % (info[:cumulative] / info[:hits]),
                "%0.02fs" % info[:min], "%0.02fs" % info[:max]]
    end        
  end
end

#sorted_by(by = nil) ⇒ Object

Return categories sorted by a given key. by The key.



129
130
131
132
133
134
135
# File 'lib/request_log_analyzer/tracker/duration.rb', line 129

def sorted_by(by = nil) 
  if block_given?
    categories.sort { |a, b| yield(b[1]) <=> yield(a[1]) } 
  else
    categories.sort { |a, b| b[1][by] <=> a[1][by] } 
  end
end

#sorted_by_averageObject

Return categories sorted by cumulative duration.



123
124
125
# File 'lib/request_log_analyzer/tracker/duration.rb', line 123

def sorted_by_average
  sorted_by { |cat| cat[:cumulative] / cat[:hits] }
end

#sorted_by_cumulativeObject

Return categories sorted by cumulative duration.



118
119
120
# File 'lib/request_log_analyzer/tracker/duration.rb', line 118

def sorted_by_cumulative
  sorted_by(:cumulative)
end

#sorted_by_hitsObject

Return categories sorted by hits.



113
114
115
# File 'lib/request_log_analyzer/tracker/duration.rb', line 113

def sorted_by_hits
  sorted_by(:hits)
end

#titleObject

Returns the title of this tracker for reports



187
188
189
# File 'lib/request_log_analyzer/tracker/duration.rb', line 187

def title
  options[:title]  || 'Request duration'
end

#to_yaml_objectObject

Returns all the categories and the tracked duration as a hash than can be exported to YAML



192
193
194
195
# File 'lib/request_log_analyzer/tracker/duration.rb', line 192

def to_yaml_object
  return nil if @categories.empty?      
  @categories
end

#update(request) ⇒ Object

Get the duration information fron the request and store it in the different categories. request The request.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/request_log_analyzer/tracker/duration.rb', line 39

def update(request)
  if options[:multiple]
    categories = request.every(options[:category])
    durations  = request.every(options[:duration])
    
    if categories.length == durations.length
      categories.each_with_index do |category, index|
        @categories[category] ||= {:hits => 0, :cumulative => 0.0}
        @categories[category][:hits] += 1
        @categories[category][:cumulative] += durations[index]
      end
    else
      raise "Capture mismatch for multiple values in a request"
    end
  else
    category = @categorizer.call(request)
    duration = @durationizer.call(request)
  
    if duration.kind_of?(Numeric) && !category.nil?
      @categories[category] ||= {:hits => 0, :cumulative => 0.0, :min => duration, :max => duration }
      @categories[category][:hits] += 1
      @categories[category][:cumulative] += duration
      @categories[category][:min] = duration if duration < @categories[category][:min]
      @categories[category][:max] = duration if duration > @categories[category][:max]
    end
  end
end