request-log-analyzer 1.3.4 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. data/LICENSE +3 -3
  2. data/README.rdoc +1 -1
  3. data/bin/request-log-analyzer +17 -14
  4. data/lib/cli/command_line_arguments.rb +51 -51
  5. data/lib/cli/database_console.rb +3 -3
  6. data/lib/cli/database_console_init.rb +4 -3
  7. data/lib/cli/progressbar.rb +10 -10
  8. data/lib/cli/tools.rb +3 -3
  9. data/lib/request_log_analyzer/aggregator/database_inserter.rb +19 -17
  10. data/lib/request_log_analyzer/aggregator/echo.rb +14 -9
  11. data/lib/request_log_analyzer/aggregator/summarizer.rb +26 -26
  12. data/lib/request_log_analyzer/aggregator.rb +11 -15
  13. data/lib/request_log_analyzer/controller.rb +162 -89
  14. data/lib/request_log_analyzer/database/base.rb +22 -21
  15. data/lib/request_log_analyzer/database/connection.rb +3 -3
  16. data/lib/request_log_analyzer/database/request.rb +22 -0
  17. data/lib/request_log_analyzer/database/source.rb +13 -0
  18. data/lib/request_log_analyzer/database/warning.rb +14 -0
  19. data/lib/request_log_analyzer/database.rb +28 -103
  20. data/lib/request_log_analyzer/file_format/amazon_s3.rb +20 -20
  21. data/lib/request_log_analyzer/file_format/apache.rb +37 -30
  22. data/lib/request_log_analyzer/file_format/merb.rb +30 -13
  23. data/lib/request_log_analyzer/file_format/rack.rb +11 -0
  24. data/lib/request_log_analyzer/file_format/rails.rb +143 -73
  25. data/lib/request_log_analyzer/file_format/rails_development.rb +4 -49
  26. data/lib/request_log_analyzer/file_format.rb +16 -28
  27. data/lib/request_log_analyzer/filter/anonymize.rb +8 -7
  28. data/lib/request_log_analyzer/filter/field.rb +9 -9
  29. data/lib/request_log_analyzer/filter/timespan.rb +12 -10
  30. data/lib/request_log_analyzer/filter.rb +12 -16
  31. data/lib/request_log_analyzer/line_definition.rb +15 -14
  32. data/lib/request_log_analyzer/log_processor.rb +27 -29
  33. data/lib/request_log_analyzer/mailer.rb +15 -9
  34. data/lib/request_log_analyzer/output/fixed_width.rb +48 -48
  35. data/lib/request_log_analyzer/output/html.rb +20 -20
  36. data/lib/request_log_analyzer/output.rb +53 -12
  37. data/lib/request_log_analyzer/request.rb +88 -69
  38. data/lib/request_log_analyzer/source/database_loader.rb +10 -14
  39. data/lib/request_log_analyzer/source/log_parser.rb +57 -50
  40. data/lib/request_log_analyzer/source.rb +10 -12
  41. data/lib/request_log_analyzer/tracker/duration.rb +41 -134
  42. data/lib/request_log_analyzer/tracker/frequency.rb +31 -32
  43. data/lib/request_log_analyzer/tracker/hourly_spread.rb +21 -21
  44. data/lib/request_log_analyzer/tracker/timespan.rb +17 -17
  45. data/lib/request_log_analyzer/tracker/traffic.rb +106 -0
  46. data/lib/request_log_analyzer/tracker.rb +139 -32
  47. data/lib/request_log_analyzer.rb +5 -5
  48. data/request-log-analyzer.gemspec +19 -15
  49. data/spec/database.yml +6 -0
  50. data/spec/fixtures/rails_22.log +1 -1
  51. data/spec/integration/command_line_usage_spec.rb +7 -1
  52. data/spec/lib/helpers.rb +7 -7
  53. data/spec/lib/macros.rb +3 -3
  54. data/spec/lib/matchers.rb +41 -27
  55. data/spec/lib/mocks.rb +19 -15
  56. data/spec/lib/testing_format.rb +9 -9
  57. data/spec/spec_helper.rb +6 -6
  58. data/spec/unit/aggregator/database_inserter_spec.rb +16 -16
  59. data/spec/unit/aggregator/summarizer_spec.rb +4 -4
  60. data/spec/unit/controller/controller_spec.rb +2 -2
  61. data/spec/unit/controller/log_processor_spec.rb +1 -1
  62. data/spec/unit/database/base_class_spec.rb +26 -33
  63. data/spec/unit/database/connection_spec.rb +3 -3
  64. data/spec/unit/database/database_spec.rb +33 -38
  65. data/spec/unit/file_format/amazon_s3_format_spec.rb +5 -5
  66. data/spec/unit/file_format/apache_format_spec.rb +48 -11
  67. data/spec/unit/file_format/file_format_api_spec.rb +13 -13
  68. data/spec/unit/file_format/line_definition_spec.rb +24 -17
  69. data/spec/unit/file_format/merb_format_spec.rb +41 -45
  70. data/spec/unit/file_format/rails_format_spec.rb +157 -117
  71. data/spec/unit/filter/anonymize_filter_spec.rb +2 -2
  72. data/spec/unit/filter/field_filter_spec.rb +13 -13
  73. data/spec/unit/filter/filter_spec.rb +1 -1
  74. data/spec/unit/filter/timespan_filter_spec.rb +15 -15
  75. data/spec/unit/mailer_spec.rb +30 -0
  76. data/spec/unit/{source/request_spec.rb → request_spec.rb} +30 -30
  77. data/spec/unit/source/log_parser_spec.rb +27 -27
  78. data/spec/unit/tracker/duration_tracker_spec.rb +115 -78
  79. data/spec/unit/tracker/frequency_tracker_spec.rb +74 -63
  80. data/spec/unit/tracker/hourly_spread_spec.rb +28 -20
  81. data/spec/unit/tracker/timespan_tracker_spec.rb +25 -13
  82. data/spec/unit/tracker/tracker_api_spec.rb +117 -42
  83. data/spec/unit/tracker/traffic_tracker_spec.rb +107 -0
  84. data/tasks/github-gem.rake +125 -75
  85. data/tasks/request_log_analyzer.rake +2 -2
  86. metadata +19 -10
@@ -1,34 +1,30 @@
1
1
  module RequestLogAnalyzer::Filter
2
-
2
+
3
3
  # Filter class loader using const_missing
4
4
  # This function will automatically load the class file based on the name of the class
5
5
  def self.const_missing(const)
6
6
  RequestLogAnalyzer::load_default_class_file(self, const)
7
7
  end
8
-
8
+
9
9
  # Base filter class used to filter input requests.
10
- # All filters should interit from this base.
10
+ # All filters should interit from this base.
11
11
  class Base
12
-
13
- include RequestLogAnalyzer::FileFormat::Awareness
14
-
15
- attr_reader :log_parser
16
- attr_reader :options
17
-
12
+
13
+ attr_reader :file_format, :options
14
+
18
15
  # Initializer
19
16
  # <tt>format</tt> The file format
20
17
  # <tt>options</tt> Are passed to the filters.
21
18
  def initialize(format, options = {})
22
- @options = options
23
- register_file_format(format)
19
+ @file_format = format
20
+ @options = options
24
21
  end
25
-
22
+
26
23
  # Return the request if the request should be kept.
27
24
  # Return nil otherwise.
28
25
  def filter(request)
29
- return nil unless request
30
- return request
31
- end
26
+ request
27
+ end
32
28
  end
33
-
29
+
34
30
  end
@@ -1,14 +1,14 @@
1
1
  module RequestLogAnalyzer
2
-
2
+
3
3
  # The line definition class is used to specify what lines should be parsed from the log file.
4
4
  # It contains functionality to match a line against the definition and parse the information
5
5
  # from this line. This is used by the LogParser class when parsing a log file..
6
6
  class LineDefinition
7
7
 
8
8
  class Definer
9
-
9
+
10
10
  attr_accessor :line_definitions
11
-
11
+
12
12
  def initialize
13
13
  @line_definitions = {}
14
14
  end
@@ -16,7 +16,7 @@ module RequestLogAnalyzer
16
16
  def initialize_copy(other)
17
17
  @line_definitions = other.line_definitions.dup
18
18
  end
19
-
19
+
20
20
  def method_missing(name, *args, &block)
21
21
  if block_given?
22
22
  @line_definitions[name] = RequestLogAnalyzer::LineDefinition.define(name, &block)
@@ -29,25 +29,26 @@ module RequestLogAnalyzer
29
29
  attr_reader :name
30
30
  attr_accessor :teaser, :regexp, :captures
31
31
  attr_accessor :header, :footer
32
-
32
+
33
33
  alias_method :header?, :header
34
34
  alias_method :footer?, :footer
35
-
35
+
36
36
  # Initializes the LineDefinition instance with a hash containing the different elements of
37
37
  # the definition.
38
38
  def initialize(name, definition = {})
39
39
  @name = name
40
40
  @captures = []
41
+ @teaser = nil
41
42
  definition.each { |key, value| self.send("#{key.to_s}=".to_sym, value) }
42
43
  end
43
-
44
+
44
45
  def self.define(name, &block)
45
46
  definition = self.new(name)
46
47
  yield(definition) if block_given?
47
48
  return definition
48
49
  end
49
-
50
- # Checks whether a given line matches this definition.
50
+
51
+ # Checks whether a given line matches this definition.
51
52
  # It will return false if a line does not match. If the line matches, a hash is returned
52
53
  # with all the fields parsed from that line as content.
53
54
  # If the line definition has a teaser-check, a :teaser_check_failed warning will be emitted
@@ -66,7 +67,7 @@ module RequestLogAnalyzer
66
67
  return false
67
68
  end
68
69
  end
69
-
70
+
70
71
  alias :=~ :matches
71
72
 
72
73
  # matches the line and converts the captured values using the request's
@@ -84,17 +85,17 @@ module RequestLogAnalyzer
84
85
  def convert_captured_values(values, request)
85
86
  value_hash = {}
86
87
  captures.each_with_index do |capture, index|
87
-
88
+
88
89
  # convert the value using the request convert_value function
89
90
  converted = request.convert_value(values[index], capture)
90
91
  value_hash[capture[:name]] ||= converted
91
-
92
+
92
93
  # Add items directly to the resulting hash from the converted value
93
94
  # if it is a hash and they are set in the :provides hash for this line definition
94
95
  if converted.kind_of?(Hash) && capture[:provides].kind_of?(Hash)
95
96
  capture[:provides].each do |name, type|
96
97
  value_hash[name] ||= request.convert_value(converted[name], { :type => type })
97
- end
98
+ end
98
99
  end
99
100
  end
100
101
  return value_hash
@@ -106,5 +107,5 @@ module RequestLogAnalyzer
106
107
  end
107
108
 
108
109
  end
109
-
110
+
110
111
  end
@@ -1,55 +1,53 @@
1
1
  module RequestLogAnalyzer
2
-
2
+
3
3
  # The Logprocessor class is used to perform simple processing actions over log files.
4
- # It will go over the log file/stream line by line, pass the line to a processor and
5
- # write the result back to the output file or stream. The processor can alter the
4
+ # It will go over the log file/stream line by line, pass the line to a processor and
5
+ # write the result back to the output file or stream. The processor can alter the
6
6
  # contents of the line, remain it intact or remove it altogether, based on the current
7
7
  # file format
8
8
  #
9
9
  # Currently, one processors is supported:
10
- # * :strip will remove all irrelevent lines (according to the file format) from the
10
+ # * :strip will remove all irrelevent lines (according to the file format) from the
11
11
  # sources. A compact, information packed log will remain/.
12
12
  #
13
13
  class LogProcessor
14
-
15
- include RequestLogAnalyzer::FileFormat::Awareness
16
-
17
- attr_reader :mode, :options, :sources
14
+
15
+ attr_reader :mode, :options, :sources, :file_format
18
16
  attr_accessor :output_file
19
-
17
+
20
18
  # Builds a logprocessor instance from the arguments given on the command line
21
- # <tt>command</tt> The command hat was used to start the log processor. This will set the
19
+ # <tt>command</tt> The command hat was used to start the log processor. This will set the
22
20
  # processing mode. Currently, only :strip is supported.
23
21
  # <tt>arguments</tt> The parsed command line arguments (a CommandLine::Arguments instance)
24
22
  def self.build(command, arguments)
25
-
26
- options = {
27
- :discard_teaser_lines => arguments[:discard_teaser_lines],
28
- :keep_junk_lines => arguments[:keep_junk_lines],
23
+
24
+ options = {
25
+ :discard_teaser_lines => arguments[:discard_teaser_lines],
26
+ :keep_junk_lines => arguments[:keep_junk_lines],
29
27
  }
30
-
28
+
31
29
  log_processor = RequestLogAnalyzer::LogProcessor.new(arguments[:format].to_sym, command, options)
32
30
  log_processor.output_file = arguments[:output] if arguments[:output]
33
31
 
34
32
  arguments.parameters.each do |input|
35
33
  log_processor.sources << input
36
34
  end
37
-
35
+
38
36
  return log_processor
39
37
  end
40
-
38
+
41
39
  # Initializes a new LogProcessor instance.
42
40
  # <tt>format</tt> The file format to use (e.g. :rails).
43
41
  # <tt>mode</tt> The processing mode
44
42
  # <tt>options</tt> A hash with options to take into account
45
43
  def initialize(format, mode, options = {})
46
- @options = options
47
- @mode = mode
48
- @sources = []
44
+ @options = options
45
+ @mode = mode
46
+ @sources = []
47
+ @file_format = format
49
48
  $output_file = nil
50
- self.register_file_format(format)
51
49
  end
52
-
50
+
53
51
  # Processes input files by opening it and sending the filestream to <code>process_io</code>,
54
52
  # in which the actual processing is performed.
55
53
  # <tt>file</tt> The file to process
@@ -65,7 +63,7 @@ module RequestLogAnalyzer
65
63
  when :strip; io.each_line { |line| @output << strip_line(line) }
66
64
  end
67
65
  end
68
-
66
+
69
67
  # Returns the line itself if the string matches any of the line definitions. If no match is
70
68
  # found, an empty line is returned, which will strip the line from the output.
71
69
  # <tt>line</tt> The line to strip
@@ -74,25 +72,25 @@ module RequestLogAnalyzer
74
72
  end
75
73
 
76
74
  # Runs the log processing by setting up the output stream and iterating over all the
77
- # input sources. Input sources can either be filenames (String instances) or IO streams
75
+ # input sources. Input sources can either be filenames (String instances) or IO streams
78
76
  # (IO instances). The strings "-" and "STDIN" will be substituted for the $stdin variable.
79
77
  def run!
80
78
  if @output_file.nil?
81
- @output = $stdout
79
+ @output = $stdout
82
80
  else
83
- @output = File.new(@output_file, 'a')
81
+ @output = File.new(@output_file, 'a')
84
82
  end
85
-
83
+
86
84
  @sources.each do |source|
87
85
  if source.kind_of?(String) && File.exist?(source)
88
86
  process_file(source)
89
87
  elsif source.kind_of?(IO)
90
88
  process_io(source)
91
89
  elsif ['-', 'STDIN'].include?(source)
92
- process_io($stdin)
90
+ process_io($stdin)
93
91
  end
94
92
  end
95
-
93
+
96
94
  ensure
97
95
  @output.close if @output.kind_of?(File)
98
96
  end
@@ -1,21 +1,23 @@
1
1
  module RequestLogAnalyzer
2
2
 
3
3
  class Mailer
4
-
4
+
5
5
  attr_accessor :data, :to, :host
6
-
6
+
7
7
  # Initialize a mailer
8
8
  # <tt>to</tt> to address
9
9
  # <tt>host</tt> the mailer host
10
10
  # <tt>options</tt> Specific style options
11
+ # Options
12
+ # <tt>:debug</tt> Do not actually mail
11
13
  def initialize(to, host = 'localhost', options = {})
12
- require 'net/smtp'
14
+ require 'net/smtp'
13
15
  @to = to
14
16
  @host = host
15
17
  @options = options
16
18
  @data = []
17
19
  end
18
-
20
+
19
21
  def mail
20
22
  from = @options[:from] || 'contact@railsdoctors.com'
21
23
  from_alias = @options[:from_alias] || 'Request-log-analyzer reporter'
@@ -28,16 +30,20 @@ Subject: #{subject}
28
30
 
29
31
  #{@data.to_s}
30
32
  END_OF_MESSAGE
31
-
32
- Net::SMTP.start(@host) do |smtp|
33
- smtp.send_message msg, from, to
33
+
34
+ unless @options[:debug]
35
+ Net::SMTP.start(@host) do |smtp|
36
+ smtp.send_message msg, from, to
37
+ end
34
38
  end
39
+
40
+ return [msg, from, to]
35
41
  end
36
-
42
+
37
43
  def << string
38
44
  data << string
39
45
  end
40
-
46
+
41
47
  def puts string
42
48
  data << string
43
49
  end
@@ -1,23 +1,23 @@
1
1
  # coding: utf-8
2
2
  module RequestLogAnalyzer::Output
3
-
3
+
4
4
  # Fixed Width output class.
5
5
  # Outputs a fixed width ASCII or UF8 report.
6
6
  class FixedWidth < Base
7
-
7
+
8
8
  # Mixin module. Will disable any colorizing.
9
9
  module Monochrome
10
10
  def colorize(text, *options)
11
11
  text
12
12
  end
13
13
  end
14
-
14
+
15
15
  # Colorize module
16
16
  module Color
17
-
17
+
18
18
  STYLES = { :normal => 0, :bold => 1, :underscore => 4, :blink => 5, :inverse => 7, :concealed => 8 }
19
19
  COLORS = { :black => 0, :blue => 4, :green => 2, :cyan => 6, :red => 1, :purple => 5, :brown => 3, :white => 7 }
20
-
20
+
21
21
  # Colorize text
22
22
  # <tt>text</tt> The text to colorize
23
23
  # Options
@@ -25,18 +25,18 @@ module RequestLogAnalyzer::Output
25
25
  # * <tt>:color</tt> The foreground color to paint. Defined in Color::COLORS
26
26
  # * <tt>:on</tt> Alias for :background
27
27
  # * <tt>:style</tt> Font style, defined in Color::STYLES
28
- #
28
+ #
29
29
  # Returns ASCII colored string
30
30
  def colorize(text, *options)
31
-
31
+
32
32
  font_style = ''
33
33
  foreground_color = '0'
34
34
  background_color = ''
35
-
35
+
36
36
  options.each do |option|
37
37
  if option.kind_of?(Symbol)
38
38
  foreground_color = "3#{COLORS[option]}" if COLORS.include?(option)
39
- font_style = "#{STYLES[option]};" if STYLES.include?(option)
39
+ font_style = "#{STYLES[option]};" if STYLES.include?(option)
40
40
  elsif option.kind_of?(Hash)
41
41
  options.each do |key, value|
42
42
  case key
@@ -50,16 +50,16 @@ module RequestLogAnalyzer::Output
50
50
  end
51
51
  return "\e[#{background_color}#{font_style}#{foreground_color}m#{text}\e[0m"
52
52
  end
53
-
53
+
54
54
  end
55
-
55
+
56
56
  attr_reader :characters
57
-
57
+
58
58
  CHARACTERS = {
59
59
  :ascii => { :horizontal_line => '-', :vertical_line => '|', :block => '=' },
60
60
  :utf => { :horizontal_line => '━', :vertical_line => '┃', :block => '░' }
61
61
  }
62
-
62
+
63
63
  # Initialize a report
64
64
  # <tt>io</tt> iO Object (file, STDOUT, etc.)
65
65
  # <tt>options</tt>
@@ -71,25 +71,25 @@ module RequestLogAnalyzer::Output
71
71
  @options[:width] ||= 80
72
72
  @options[:characters] ||= :utf
73
73
  @characters = CHARACTERS[@options[:characters]]
74
-
74
+
75
75
  color_module = @options[:color] ? Color : Monochrome
76
- (class << self; self; end).send(:include, color_module)
76
+ (class << self; self; end).send(:include, color_module)
77
77
  end
78
-
78
+
79
79
  # Write a string to the output object.
80
80
  # <tt>str</tt> The string to write.
81
81
  def print(str)
82
82
  @io << str
83
83
  end
84
-
84
+
85
85
  alias :<< :print
86
-
86
+
87
87
  # Write a string to the output object with a newline at the end.
88
88
  # <tt>str</tt> The string to write.
89
89
  def puts(str = '')
90
90
  @io << str << "\n"
91
91
  end
92
-
92
+
93
93
  # Write the title of a report
94
94
  # <tt>title</tt> The title to write
95
95
  def title(title)
@@ -97,14 +97,14 @@ module RequestLogAnalyzer::Output
97
97
  puts colorize(title, :bold, :white)
98
98
  line(:green)
99
99
  end
100
-
100
+
101
101
  # Write a line
102
- def line(*font)
102
+ def line(*font)
103
103
  puts colorize(characters[:horizontal_line] * @options[:width], *font)
104
104
  end
105
105
 
106
106
  # Write a link
107
- # <tt>text</tt> The text in the link
107
+ # <tt>text</tt> The text in the link, or the URL itself if no text is given
108
108
  # <tt>url</tt> The url to link to.
109
109
  def link(text, url = nil)
110
110
  if url.nil?
@@ -113,30 +113,31 @@ module RequestLogAnalyzer::Output
113
113
  "#{text} (#{colorize(url, :blue, :bold)})"
114
114
  end
115
115
  end
116
-
117
- # Generate a header for a report
116
+
117
+ # Generate a header for a report
118
118
  def header
119
119
  if io.kind_of?(File)
120
- puts "Request-log-analyzer summary report"
121
- line
120
+ puts colorize("Request-log-analyzer summary report", :white, :bold)
121
+ line(:green)
122
122
  puts "Version #{RequestLogAnalyzer::VERSION} - written by Willem van Bergen and Bart ten Brinke"
123
- puts "Request-log-analyzer website: http://github.com/wvanbergen/request-log-analyzer"
123
+ puts "Website: #{link('http://github.com/wvanbergen/request-log-analyzer')}"
124
124
  end
125
125
  end
126
-
126
+
127
127
  # Generate a footer for a report
128
128
  def footer
129
129
  puts
130
130
  puts "Need an expert to analyze your application?"
131
- puts "Mail to contact@railsdoctors.com or visit us at http://railsdoctors.com"
132
- puts "Thanks for using request-log-analyzer!"
131
+ puts "Mail to #{link('contact@railsdoctors.com')} or visit us at #{link('http://railsdoctors.com')}."
132
+ line(:green)
133
+ puts "Thanks for using #{colorize('request-log-analyzer', :white, :bold)}!"
133
134
  end
134
-
135
+
135
136
  # Generate a report table and push it into the output object.
136
137
  # <tt>*colums<tt> Columns hash
137
138
  # <tt>&block</tt>: A block yeilding the rows.
138
139
  def table(*columns, &block)
139
-
140
+
140
141
  rows = Array.new
141
142
  yield(rows)
142
143
 
@@ -146,7 +147,7 @@ module RequestLogAnalyzer::Output
146
147
  result.each_with_index { |length, index| result[index] = ([length, lengths[index]].max rescue length) }
147
148
  end
148
149
  columns.each_with_index { |col, index| col[:actual_width] ||= max_cell_widths[index] }
149
-
150
+
150
151
  # determine actual column width
151
152
  column_widths = columns.map do |column|
152
153
  if column[:width] == :rest
@@ -161,29 +162,28 @@ module RequestLogAnalyzer::Output
161
162
  column[:actual_width]
162
163
  end
163
164
  end
164
-
165
+
165
166
  if column_widths.include?(nil)
166
167
  fill_column = columns[column_widths.index(nil)]
167
168
  width_left = options[:width] - ((columns.length - 1) * (style[:cell_separator] ? 3 : 1)) - column_widths.compact.inject(0) { |sum, col| sum + col}
168
- column_widths[column_widths.index(nil)] = case fill_column[:type]
169
- when :ratio; width_left # max out
170
- else; [width_left, fill_column[:actual_width]].min
171
- end
169
+ column_widths[column_widths.index(nil)] = width_left
172
170
  end
173
-
171
+
172
+ line(:green) if @style[:top_line]
173
+
174
174
  # Print table header
175
175
  if table_has_header?(columns)
176
176
  column_titles = []
177
177
  columns.each_with_index do |column, index|
178
- width = column_widths[index]
178
+ width = column_widths[index]
179
179
  alignment = (column[:align] == :right ? '' : '-')
180
180
  column_titles.push(colorize("%#{alignment}#{width}s" % column[:title].to_s[0...width], :bold))
181
181
  end
182
-
182
+
183
183
  puts column_titles.join(style[:cell_separator] ? " #{characters[:vertical_line]} " : ' ')
184
184
  line(:green)
185
185
  end
186
-
186
+
187
187
  # Print the rows
188
188
  rows.each do |row|
189
189
  row_values = []
@@ -194,12 +194,12 @@ module RequestLogAnalyzer::Output
194
194
  if width > 4
195
195
  if column[:treshold] && column[:treshold] < row[index].to_f
196
196
  bar = ''
197
- bar << characters[:block] * (width.to_f * column[:treshold]).round
198
- bar << colorize(characters[:block] * (width.to_f * (row[index].to_f - column[:treshold])).round, :red)
199
- row_values.push(bar)
197
+ bar << characters[:block] * (width.to_f * column[:treshold]).round
198
+ bar << colorize(characters[:block] * (width.to_f * (row[index].to_f - column[:treshold])).round, :red)
199
+ row_values.push(bar)
200
200
  else
201
201
  # Create a bar by combining block characters
202
- row_values.push(characters[:block] * (width.to_f * row[index].to_f).round)
202
+ row_values.push(characters[:block] * (width.to_f * row[index].to_f).round)
203
203
  end
204
204
  else
205
205
  # Too few characters for a ratio bar. Display nothing
@@ -212,9 +212,9 @@ module RequestLogAnalyzer::Output
212
212
  row_values.push(cell_value)
213
213
  end
214
214
  end
215
- puts row_values.join(style[:cell_separator] ? " #{characters[:vertical_line]} " : ' ')
215
+ puts row_values.join(style[:cell_separator] ? " #{characters[:vertical_line]} " : ' ')
216
216
  end
217
217
  end
218
-
218
+
219
219
  end
220
220
  end
@@ -1,12 +1,12 @@
1
1
  module RequestLogAnalyzer::Output
2
-
2
+
3
3
  # HTML Output class. Generated a HTML-formatted report, including CSS.
4
4
  class HTML < Base
5
-
5
+
6
6
  # def initialize(io, options = {})
7
7
  # super(io, options)
8
8
  # end
9
-
9
+
10
10
  # Print a string to the io object.
11
11
  def print(str)
12
12
  @io << str
@@ -26,10 +26,10 @@ module RequestLogAnalyzer::Output
26
26
 
27
27
  # Render a single line
28
28
  # <tt>*font</tt> The font.
29
- def line(*font)
29
+ def line(*font)
30
30
  @io.puts(tag(:hr))
31
31
  end
32
-
32
+
33
33
  # Write a link
34
34
  # <tt>text</tt> The text in the link
35
35
  # <tt>url</tt> The url to link to.
@@ -44,29 +44,29 @@ module RequestLogAnalyzer::Output
44
44
  def table(*columns, &block)
45
45
  rows = Array.new
46
46
  yield(rows)
47
-
47
+
48
48
  @io << tag(:table, {:id => 'mytable', :cellspacing => 0}) do |content|
49
49
  if table_has_header?(columns)
50
50
  content << tag(:tr) do
51
51
  columns.map { |col| tag(:th, col[:title]) }.join("\n")
52
52
  end
53
53
  end
54
-
54
+
55
55
  odd = false
56
56
  rows.each do |row|
57
57
  odd = !odd
58
58
  content << tag(:tr) do
59
59
  if odd
60
- row.map { |cell| tag(:td, cell, :class => 'alt') }.join("\n")
60
+ row.map { |cell| tag(:td, cell, :class => 'alt') }.join("\n")
61
61
  else
62
- row.map { |cell| tag(:td, cell) }.join("\n")
62
+ row.map { |cell| tag(:td, cell) }.join("\n")
63
63
  end
64
64
  end
65
65
  end
66
66
  end
67
-
67
+
68
68
  end
69
-
69
+
70
70
  # Genrate HTML header and associated stylesheet
71
71
  def header
72
72
  @io << "<html>"
@@ -85,13 +85,13 @@ module RequestLogAnalyzer::Output
85
85
  a {
86
86
  color: #c75f3e;
87
87
  }
88
-
88
+
89
89
  .color_bar {
90
90
  border: 1px solid;
91
91
  height:10px;
92
92
  background: #CAE8EA;
93
93
  }
94
-
94
+
95
95
  #mytable {
96
96
  width: 700px;
97
97
  padding: 0;
@@ -101,7 +101,7 @@ module RequestLogAnalyzer::Output
101
101
 
102
102
  caption {
103
103
  padding: 0 0 5px 0;
104
- width: 700px;
104
+ width: 700px;
105
105
  font: italic 11px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
106
106
  text-align: right;
107
107
  }
@@ -138,7 +138,7 @@ module RequestLogAnalyzer::Output
138
138
  @io << tag(:h1, 'Request-log-analyzer summary report')
139
139
  @io << tag(:p, "Version #{RequestLogAnalyzer::VERSION} - written by Willem van Bergen and Bart ten Brinke")
140
140
  end
141
-
141
+
142
142
  # Generate a footer for a report
143
143
  def footer
144
144
  @io << tag(:hr) << tag(:h2, 'Thanks for using request-log-analyzer')
@@ -146,9 +146,9 @@ module RequestLogAnalyzer::Output
146
146
  @io << tag(:p, 'If you need an expert who can analyze your application, mail to ' + link('contact@railsdoctors.com', 'mailto:contact@railsdoctors.com') + ' or visit us at ' + link('http://railsdoctors.com', 'http://railsdoctors.com') + '.')
147
147
  @io << "</body></html>\n"
148
148
  end
149
-
150
- protected
151
-
149
+
150
+ protected
151
+
152
152
  # HTML tag writer helper
153
153
  # <tt>tag</tt> The tag to generate
154
154
  # <tt>content</tt> The content inside the tag
@@ -158,7 +158,7 @@ module RequestLogAnalyzer::Output
158
158
  attributes = content.nil? ? '' : ' ' + content.map { |(key, value)| "#{key}=\"#{value}\"" }.join(' ')
159
159
  content_string = ''
160
160
  content = yield(content_string)
161
- content = content_string unless content_string.empty?
161
+ content = content_string unless content_string.empty?
162
162
  "<#{tag}#{attributes}>#{content}</#{tag}>"
163
163
  else
164
164
  attributes = attributes.nil? ? '' : ' ' + attributes.map { |(key, value)| "#{key}=\"#{value}\"" }.join(' ')
@@ -172,6 +172,6 @@ module RequestLogAnalyzer::Output
172
172
  end
173
173
  end
174
174
  end
175
- end
175
+ end
176
176
  end
177
177
  end