request-log-analyzer 1.3.7 → 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.
- data/LICENSE +3 -3
- data/README.rdoc +1 -1
- data/bin/request-log-analyzer +17 -14
- data/lib/cli/command_line_arguments.rb +51 -51
- data/lib/cli/database_console.rb +3 -3
- data/lib/cli/database_console_init.rb +2 -2
- data/lib/cli/progressbar.rb +10 -10
- data/lib/cli/tools.rb +3 -3
- data/lib/request_log_analyzer.rb +4 -4
- data/lib/request_log_analyzer/aggregator.rb +10 -10
- data/lib/request_log_analyzer/aggregator/database_inserter.rb +9 -9
- data/lib/request_log_analyzer/aggregator/echo.rb +14 -9
- data/lib/request_log_analyzer/aggregator/summarizer.rb +26 -26
- data/lib/request_log_analyzer/controller.rb +153 -69
- data/lib/request_log_analyzer/database.rb +13 -13
- data/lib/request_log_analyzer/database/base.rb +17 -17
- data/lib/request_log_analyzer/database/connection.rb +3 -3
- data/lib/request_log_analyzer/database/request.rb +2 -2
- data/lib/request_log_analyzer/database/source.rb +1 -1
- data/lib/request_log_analyzer/file_format.rb +15 -15
- data/lib/request_log_analyzer/file_format/amazon_s3.rb +16 -16
- data/lib/request_log_analyzer/file_format/apache.rb +20 -19
- data/lib/request_log_analyzer/file_format/merb.rb +12 -12
- data/lib/request_log_analyzer/file_format/rack.rb +4 -4
- data/lib/request_log_analyzer/file_format/rails.rb +146 -70
- data/lib/request_log_analyzer/file_format/rails_development.rb +4 -49
- data/lib/request_log_analyzer/filter.rb +6 -6
- data/lib/request_log_analyzer/filter/anonymize.rb +6 -6
- data/lib/request_log_analyzer/filter/field.rb +9 -9
- data/lib/request_log_analyzer/filter/timespan.rb +12 -10
- data/lib/request_log_analyzer/line_definition.rb +15 -14
- data/lib/request_log_analyzer/log_processor.rb +22 -22
- data/lib/request_log_analyzer/mailer.rb +15 -9
- data/lib/request_log_analyzer/output.rb +53 -12
- data/lib/request_log_analyzer/output/fixed_width.rb +40 -41
- data/lib/request_log_analyzer/output/html.rb +20 -20
- data/lib/request_log_analyzer/request.rb +35 -36
- data/lib/request_log_analyzer/source.rb +7 -7
- data/lib/request_log_analyzer/source/database_loader.rb +7 -7
- data/lib/request_log_analyzer/source/log_parser.rb +48 -43
- data/lib/request_log_analyzer/tracker.rb +128 -14
- data/lib/request_log_analyzer/tracker/duration.rb +39 -132
- data/lib/request_log_analyzer/tracker/frequency.rb +31 -32
- data/lib/request_log_analyzer/tracker/hourly_spread.rb +20 -19
- data/lib/request_log_analyzer/tracker/timespan.rb +17 -17
- data/lib/request_log_analyzer/tracker/traffic.rb +36 -116
- data/request-log-analyzer.gemspec +19 -15
- data/spec/fixtures/rails_22.log +1 -1
- data/spec/integration/command_line_usage_spec.rb +1 -1
- data/spec/lib/helpers.rb +7 -7
- data/spec/lib/macros.rb +3 -3
- data/spec/lib/matchers.rb +41 -27
- data/spec/lib/mocks.rb +15 -14
- data/spec/lib/testing_format.rb +9 -9
- data/spec/spec_helper.rb +6 -6
- data/spec/unit/aggregator/database_inserter_spec.rb +13 -13
- data/spec/unit/aggregator/summarizer_spec.rb +4 -4
- data/spec/unit/controller/controller_spec.rb +2 -2
- data/spec/unit/controller/log_processor_spec.rb +1 -1
- data/spec/unit/database/base_class_spec.rb +19 -19
- data/spec/unit/database/connection_spec.rb +3 -3
- data/spec/unit/database/database_spec.rb +25 -25
- data/spec/unit/file_format/amazon_s3_format_spec.rb +5 -5
- data/spec/unit/file_format/apache_format_spec.rb +13 -13
- data/spec/unit/file_format/file_format_api_spec.rb +13 -13
- data/spec/unit/file_format/line_definition_spec.rb +24 -17
- data/spec/unit/file_format/merb_format_spec.rb +41 -45
- data/spec/unit/file_format/rails_format_spec.rb +157 -117
- data/spec/unit/filter/anonymize_filter_spec.rb +2 -2
- data/spec/unit/filter/field_filter_spec.rb +13 -13
- data/spec/unit/filter/filter_spec.rb +1 -1
- data/spec/unit/filter/timespan_filter_spec.rb +15 -15
- data/spec/unit/mailer_spec.rb +30 -0
- data/spec/unit/{source/request_spec.rb → request_spec.rb} +30 -30
- data/spec/unit/source/log_parser_spec.rb +27 -27
- data/spec/unit/tracker/duration_tracker_spec.rb +115 -78
- data/spec/unit/tracker/frequency_tracker_spec.rb +74 -63
- data/spec/unit/tracker/hourly_spread_spec.rb +28 -20
- data/spec/unit/tracker/timespan_tracker_spec.rb +25 -13
- data/spec/unit/tracker/tracker_api_spec.rb +13 -13
- data/spec/unit/tracker/traffic_tracker_spec.rb +81 -79
- data/tasks/github-gem.rake +125 -75
- data/tasks/request_log_analyzer.rake +2 -2
- metadata +8 -6
@@ -3,139 +3,58 @@ module RequestLogAnalyzer::Tracker
|
|
3
3
|
# Analyze the average and total traffic of requests
|
4
4
|
#
|
5
5
|
# === Options
|
6
|
-
# * <tt>:amount</tt> The amount of lines in the report
|
7
6
|
# * <tt>:category</tt> Proc that handles request categorization for given fileformat (REQUEST_CATEGORIZER)
|
8
7
|
# * <tt>:traffic</tt> The field containing the duration in the request hash.
|
9
8
|
# * <tt>:if</tt> Proc that has to return !nil for a request to be passed to the tracker.
|
10
9
|
# * <tt>:line_type</tt> The line type that contains the duration field (determined by the category proc).
|
11
|
-
# * <tt>:title</tt> Title do be displayed above the report
|
10
|
+
# * <tt>:title</tt> Title do be displayed above the report
|
12
11
|
# * <tt>:unless</tt> Handle request if this proc is false for the handled request.
|
13
12
|
class Traffic < Base
|
14
|
-
|
13
|
+
|
15
14
|
attr_reader :categories
|
16
15
|
|
16
|
+
include RequestLogAnalyzer::Tracker::StatisticsTracking
|
17
|
+
|
17
18
|
# Check if duration and catagory option have been received,
|
18
19
|
def prepare
|
19
20
|
raise "No traffic field set up for category tracker #{self.inspect}" unless options[:traffic]
|
20
|
-
raise "No categorizer set up for duration tracker #{self.inspect}"
|
21
|
+
raise "No categorizer set up for duration tracker #{self.inspect}" unless options[:category]
|
21
22
|
|
22
|
-
@categorizer = options[:category]
|
23
|
-
@trafficizer = options[:traffic]
|
24
|
-
@categories
|
23
|
+
@categorizer = create_lambda(options[:category])
|
24
|
+
@trafficizer = create_lambda(options[:traffic])
|
25
|
+
@categories = {}
|
25
26
|
end
|
26
27
|
|
27
|
-
|
28
|
+
|
29
|
+
# Get the duration information from the request and store it in the different categories.
|
28
30
|
# <tt>request</tt> The request.
|
29
31
|
def update(request)
|
30
32
|
category = @categorizer.call(request)
|
31
33
|
traffic = @trafficizer.call(request)
|
32
|
-
|
33
|
-
if traffic.kind_of?(Numeric) && !category.nil?
|
34
|
-
@categories[category] ||= {:hits => 0, :cumulative => 0, :min => traffic, :max => traffic }
|
35
|
-
@categories[category][:hits] += 1
|
36
|
-
@categories[category][:cumulative] += traffic
|
37
|
-
@categories[category][:min] = traffic if traffic < @categories[category][:min]
|
38
|
-
@categories[category][:max] = traffic if traffic > @categories[category][:max]
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
# Get the number of hits of a specific category.
|
43
|
-
# <tt>cat</tt> The category
|
44
|
-
def hits(cat)
|
45
|
-
categories[cat][:hits]
|
46
|
-
end
|
47
|
-
|
48
|
-
# Get the total duration of a specific category.
|
49
|
-
# <tt>cat</tt> The category
|
50
|
-
def cumulative_traffic(cat)
|
51
|
-
categories[cat][:cumulative]
|
52
|
-
end
|
53
|
-
|
54
|
-
# Get the minimal duration of a specific category.
|
55
|
-
# <tt>cat</tt> The category
|
56
|
-
def min_traffic(cat)
|
57
|
-
categories[cat][:min]
|
58
|
-
end
|
59
|
-
|
60
|
-
# Get the maximum duration of a specific category.
|
61
|
-
# <tt>cat</tt> The category
|
62
|
-
def max_traffic(cat)
|
63
|
-
categories[cat][:max]
|
64
|
-
end
|
65
|
-
|
66
|
-
# Get the average duration of a specific category.
|
67
|
-
# <tt>cat</tt> The category
|
68
|
-
def average_traffic(cat)
|
69
|
-
categories[cat][:cumulative].to_f / categories[cat][:hits]
|
70
|
-
end
|
71
|
-
|
72
|
-
# Get the average duration of a all categories.
|
73
|
-
def overall_average_traffic
|
74
|
-
overall_cumulative_duration.to_f / overall_hits
|
75
|
-
end
|
76
|
-
|
77
|
-
# Get the cumlative duration of a all categories.
|
78
|
-
def overall_cumulative_traffic
|
79
|
-
categories.inject(0) { |sum, (name, cat)| sum + cat[:cumulative] }
|
80
|
-
end
|
81
|
-
|
82
|
-
# Get the total hits of a all categories.
|
83
|
-
def overall_hits
|
84
|
-
categories.inject(0) { |sum, (name, cat)| sum + cat[:hits] }
|
34
|
+
update_statistics(category, traffic) if traffic.kind_of?(Numeric) && !category.nil?
|
85
35
|
end
|
86
36
|
|
87
|
-
# Return categories sorted by hits.
|
88
|
-
def sorted_by_hits
|
89
|
-
sorted_by(:hits)
|
90
|
-
end
|
91
|
-
|
92
|
-
# Return categories sorted by cumulative duration.
|
93
|
-
def sorted_by_cumulative
|
94
|
-
sorted_by(:cumulative)
|
95
|
-
end
|
96
|
-
|
97
|
-
# Return categories sorted by cumulative duration.
|
98
|
-
def sorted_by_average
|
99
|
-
sorted_by { |cat| cat[:cumulative].to_f / cat[:hits] }
|
100
|
-
end
|
101
|
-
|
102
|
-
# Return categories sorted by a given key.
|
103
|
-
# <tt>by</tt> The key.
|
104
|
-
def sorted_by(by = nil)
|
105
|
-
if block_given?
|
106
|
-
categories.sort { |a, b| yield(b[1]) <=> yield(a[1]) }
|
107
|
-
else
|
108
|
-
categories.sort { |a, b| b[1][by] <=> a[1][by] }
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
37
|
# Block function to build a result table using a provided sorting function.
|
113
38
|
# <tt>output</tt> The output object.
|
114
39
|
# <tt>amount</tt> The number of rows in the report table (default 10).
|
115
40
|
# === Options
|
116
41
|
# * </tt>:title</tt> The title of the table
|
117
42
|
# * </tt>:sort</tt> The key to sort on (:hits, :cumulative, :average, :min or :max)
|
118
|
-
def report_table(output,
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
{:title => 'Cumulative', :align => :right, :highlight => (options[:sort] == :cumulative), :min_width => 10},
|
126
|
-
{:title => 'Average', :align => :right, :highlight => (options[:sort] == :average), :min_width => 8},
|
127
|
-
{:title => 'Min', :align => :right, :highlight => (options[:sort] == :min)},
|
128
|
-
{:title => 'Max', :align => :right, :highlight => (options[:sort] == :max)}) do |rows|
|
129
|
-
|
130
|
-
top_categories.each do |(cat, info)|
|
131
|
-
rows << [cat, info[:hits], format_traffic(info[:cumulative]), format_traffic((info[:cumulative] / info[:hits]).round),
|
132
|
-
format_traffic(info[:min]), format_traffic(info[:max])]
|
43
|
+
def report_table(output, sort, options = {}, &block)
|
44
|
+
output.puts
|
45
|
+
|
46
|
+
top_categories = output.slice_results(sorted_by(sort))
|
47
|
+
output.with_style(:top_line => true) do
|
48
|
+
output.table(*statistics_header(:title => options[:title],:highlight => sort)) do |rows|
|
49
|
+
top_categories.each { |(cat, info)| rows.push(statistics_row(cat)) }
|
133
50
|
end
|
134
51
|
end
|
52
|
+
output.puts
|
135
53
|
end
|
136
|
-
|
54
|
+
|
137
55
|
# Formats the traffic number using x B/kB/MB/GB etc notation
|
138
|
-
def
|
56
|
+
def display_value(bytes)
|
57
|
+
return "-" if bytes.nil?
|
139
58
|
return "0 B" if bytes.zero?
|
140
59
|
case Math.log10(bytes).floor
|
141
60
|
when 1...4 then '%d B' % bytes
|
@@ -152,31 +71,32 @@ module RequestLogAnalyzer::Tracker
|
|
152
71
|
# <tt>output</tt> The output object
|
153
72
|
def report(output)
|
154
73
|
|
155
|
-
options[:
|
156
|
-
|
157
|
-
|
158
|
-
options[:report].each do |report|
|
74
|
+
sortings = output.options[:sort] || [:sum, :mean]
|
75
|
+
|
76
|
+
sortings.each do |report|
|
159
77
|
case report
|
160
|
-
when :
|
161
|
-
report_table(output,
|
162
|
-
when :
|
163
|
-
report_table(output,
|
78
|
+
when :mean
|
79
|
+
report_table(output, :mean, :title => "#{title} - sorted by mean")
|
80
|
+
when :stddev
|
81
|
+
report_table(output, :stddev, :title => "#{title} - sorted by standard deviation")
|
82
|
+
when :sum
|
83
|
+
report_table(output, :sum, :title => "#{title} - sorted by sum")
|
164
84
|
when :hits
|
165
|
-
report_table(output,
|
85
|
+
report_table(output, :hits, :title => "#{title} - sorted by hits")
|
166
86
|
else
|
167
87
|
raise "Unknown duration report specified: #{report}!"
|
168
88
|
end
|
169
89
|
end
|
170
|
-
|
90
|
+
|
171
91
|
output.puts
|
172
|
-
output.puts "#{output.colorize(title, :white, :bold)} - observed total: " + output.colorize(
|
92
|
+
output.puts "#{output.colorize(title, :white, :bold)} - observed total: " + output.colorize(display_value(sum_overall), :brown, :bold)
|
173
93
|
end
|
174
|
-
|
94
|
+
|
175
95
|
# Returns the title of this tracker for reports
|
176
96
|
def title
|
177
97
|
options[:title] || 'Request traffic'
|
178
98
|
end
|
179
|
-
|
99
|
+
|
180
100
|
# Returns all the categories and the tracked duration as a hash than can be exported to YAML
|
181
101
|
def to_yaml_object
|
182
102
|
return nil if @categories.empty?
|
@@ -1,36 +1,40 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "request-log-analyzer"
|
3
|
-
s.version = "1.3.7"
|
4
|
-
s.date = "2009-09-22"
|
5
3
|
|
4
|
+
# Do not set the version and date field manually, this is done by the release script
|
5
|
+
s.version = "1.4.0"
|
6
|
+
s.date = "2009-09-30"
|
7
|
+
|
6
8
|
s.rubyforge_project = 'r-l-a'
|
7
|
-
|
9
|
+
|
8
10
|
s.bindir = 'bin'
|
9
11
|
s.executables = ['request-log-analyzer']
|
10
12
|
s.default_executable = 'request-log-analyzer'
|
11
|
-
|
12
|
-
s.summary = "A command line tool to analyze request logs for Apache, Rails, Merb and other application servers"
|
13
|
+
|
14
|
+
s.summary = "A command line tool to analyze request logs for Apache, Rails, Merb and other web application servers"
|
13
15
|
s.description = <<-eos
|
14
16
|
Request log analyzer's purpose is to find ot how your web application is being used and to focus your optimization efforts.
|
15
|
-
This tool will parse all requests in the application's log file and aggregate the information. Once it is finished parsing
|
16
|
-
the log file(s), it will show the requests that take op most server time using various metrics. It can also insert all
|
17
|
-
parsed request information into a database so you can roll your own analysis. It supports Rails- and Merb-based applications
|
18
|
-
and Apache access log files out of the box, but file formats of other applications can easily be supported by supplying an
|
17
|
+
This tool will parse all requests in the application's log file and aggregate the information. Once it is finished parsing
|
18
|
+
the log file(s), it will show the requests that take op most server time using various metrics. It can also insert all
|
19
|
+
parsed request information into a database so you can roll your own analysis. It supports Rails- and Merb-based applications
|
20
|
+
and Apache access log files out of the box, but file formats of other applications can easily be supported by supplying an
|
19
21
|
easy to write log file format definition.
|
20
22
|
eos
|
21
|
-
|
23
|
+
|
22
24
|
s.rdoc_options << '--title' << s.name << '--main' << 'README.rdoc' << '--line-numbers' << '--inline-source'
|
23
25
|
s.extra_rdoc_files = ['README.rdoc']
|
24
|
-
|
26
|
+
|
25
27
|
s.requirements << "To use the database inserter, ActiveRecord and an appropriate database adapter are required."
|
26
|
-
|
28
|
+
|
27
29
|
s.add_development_dependency('rspec', '>= 1.2.4')
|
28
30
|
s.add_development_dependency('git', '>= 1.1.0')
|
29
|
-
|
31
|
+
|
30
32
|
s.authors = ['Willem van Bergen', 'Bart ten Brinke']
|
31
33
|
s.email = ['willem@railsdoctors.com', 'bart@railsdoctors.com']
|
32
34
|
s.homepage = 'http://railsdoctors.com'
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
+
# The files and test_files directives are set automatically by the release script.
|
37
|
+
# Do not change them by hand, but make sure to add the files to the git repository.
|
38
|
+
s.files = %w(spec/unit/filter/anonymize_filter_spec.rb spec/fixtures/rails_22_cached.log lib/request_log_analyzer/line_definition.rb lib/request_log_analyzer/output/html.rb lib/request_log_analyzer/controller.rb spec/lib/macros.rb lib/request_log_analyzer/file_format/rails_development.rb spec/fixtures/apache_combined.log spec/fixtures/apache_common.log spec/fixtures/merb_prefixed.log lib/request_log_analyzer/file_format/amazon_s3.rb tasks/request_log_analyzer.rake spec/unit/file_format/file_format_api_spec.rb spec/unit/file_format/apache_format_spec.rb spec/integration/command_line_usage_spec.rb lib/request_log_analyzer/database.rb spec/fixtures/decompression.log.bz2 spec/fixtures/rails_unordered.log lib/request_log_analyzer/log_processor.rb lib/request_log_analyzer/tracker.rb lib/request_log_analyzer/filter.rb bin/request-log-analyzer request-log-analyzer.gemspec DESIGN.rdoc spec/unit/filter/timespan_filter_spec.rb spec/unit/aggregator/database_inserter_spec.rb spec/lib/matchers.rb lib/request_log_analyzer/filter/field.rb lib/request_log_analyzer/tracker/frequency.rb spec/fixtures/decompression.log.gz spec/fixtures/decompression.log spec/lib/testing_format.rb spec/fixtures/test_order.log spec/fixtures/rails.db lib/request_log_analyzer/output/fixed_width.rb lib/request_log_analyzer/filter/anonymize.rb lib/request_log_analyzer/tracker/timespan.rb lib/request_log_analyzer/database/base.rb lib/request_log_analyzer/aggregator.rb spec/unit/request_spec.rb lib/cli/progressbar.rb lib/request_log_analyzer/mailer.rb README.rdoc lib/request_log_analyzer/database/warning.rb spec/fixtures/merb.log lib/request_log_analyzer/tracker/hourly_spread.rb .gitignore spec/unit/tracker/tracker_api_spec.rb spec/unit/tracker/duration_tracker_spec.rb spec/unit/file_format/amazon_s3_format_spec.rb lib/request_log_analyzer/aggregator/echo.rb spec/unit/mailer_spec.rb spec/unit/controller/log_processor_spec.rb spec/spec_helper.rb lib/request_log_analyzer.rb spec/database.yml Rakefile lib/request_log_analyzer/database/connection.rb spec/unit/filter/filter_spec.rb spec/fixtures/test_language_combined.log lib/request_log_analyzer/aggregator/database_inserter.rb lib/request_log_analyzer/aggregator/summarizer.rb lib/request_log_analyzer/file_format/rack.rb lib/request_log_analyzer/database/source.rb lib/request_log_analyzer/file_format/rails.rb spec/fixtures/decompression.tar.gz spec/unit/tracker/traffic_tracker_spec.rb spec/unit/filter/field_filter_spec.rb spec/unit/database/base_class_spec.rb lib/request_log_analyzer/filter/timespan.rb lib/request_log_analyzer/source/log_parser.rb spec/fixtures/decompression.tgz spec/unit/tracker/timespan_tracker_spec.rb spec/unit/tracker/hourly_spread_spec.rb spec/fixtures/header_and_footer.log lib/cli/tools.rb lib/request_log_analyzer/file_format/merb.rb spec/fixtures/multiple_files_1.log spec/unit/file_format/merb_format_spec.rb spec/unit/file_format/line_definition_spec.rb lib/request_log_analyzer/source.rb lib/request_log_analyzer/request.rb lib/cli/database_console.rb spec/unit/database/connection_spec.rb spec/unit/controller/controller_spec.rb spec/lib/mocks.rb spec/lib/helpers.rb spec/fixtures/rails_1x.log lib/cli/database_console_init.rb lib/request_log_analyzer/output.rb lib/request_log_analyzer/file_format/apache.rb spec/fixtures/decompression.log.zip spec/unit/source/log_parser_spec.rb spec/fixtures/test_file_format.log tasks/github-gem.rake spec/unit/database/database_spec.rb lib/request_log_analyzer/tracker/duration.rb lib/request_log_analyzer/tracker/traffic.rb lib/request_log_analyzer/file_format.rb spec/unit/aggregator/summarizer_spec.rb spec/fixtures/syslog_1x.log spec/fixtures/rails_22.log lib/request_log_analyzer/database/request.rb spec/fixtures/multiple_files_2.log LICENSE lib/request_log_analyzer/source/database_loader.rb spec/unit/tracker/frequency_tracker_spec.rb spec/unit/file_format/rails_format_spec.rb lib/cli/command_line_arguments.rb)
|
39
|
+
s.test_files = %w(spec/unit/filter/anonymize_filter_spec.rb spec/unit/file_format/file_format_api_spec.rb spec/unit/file_format/apache_format_spec.rb spec/integration/command_line_usage_spec.rb spec/unit/filter/timespan_filter_spec.rb spec/unit/aggregator/database_inserter_spec.rb spec/unit/request_spec.rb spec/unit/tracker/tracker_api_spec.rb spec/unit/tracker/duration_tracker_spec.rb spec/unit/file_format/amazon_s3_format_spec.rb spec/unit/mailer_spec.rb spec/unit/controller/log_processor_spec.rb spec/unit/filter/filter_spec.rb spec/unit/tracker/traffic_tracker_spec.rb spec/unit/filter/field_filter_spec.rb spec/unit/database/base_class_spec.rb spec/unit/tracker/timespan_tracker_spec.rb spec/unit/tracker/hourly_spread_spec.rb spec/unit/file_format/merb_format_spec.rb spec/unit/file_format/line_definition_spec.rb spec/unit/database/connection_spec.rb spec/unit/controller/controller_spec.rb spec/unit/source/log_parser_spec.rb spec/unit/database/database_spec.rb spec/unit/aggregator/summarizer_spec.rb spec/unit/tracker/frequency_tracker_spec.rb spec/unit/file_format/rails_format_spec.rb)
|
36
40
|
end
|
data/spec/fixtures/rails_22.log
CHANGED
@@ -9,4 +9,4 @@ Rendered shared/_analytics (0.2ms)
|
|
9
9
|
Rendered layouts/_actions (0.6ms)
|
10
10
|
Rendered layouts/_menu (2.2ms)
|
11
11
|
Rendered layouts/_tabbar (0.5ms)
|
12
|
-
Completed in 614ms (View: 120, DB: 31) | 200 OK [http://www.example.
|
12
|
+
Completed in 614ms (View: 120, DB: 31) | 200 OK [http://www.example.com/demo]
|
@@ -76,7 +76,7 @@ describe RequestLogAnalyzer, 'running from command line' do
|
|
76
76
|
File.exist?(temp_output_file(:dump)).should be_true
|
77
77
|
YAML::load(File.read(temp_output_file(:dump))).should have_at_least(1).item
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
it "should parse 4 requests from the standard input" do
|
81
81
|
output = run("- < #{log_fixture(:rails_1x)}")
|
82
82
|
output.any? { |line| /^Parsed requests\:\s*4\s/ =~ line }.should be_true
|
data/spec/lib/helpers.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
module RequestLogAnalyzer::Spec::Helpers
|
2
|
-
|
2
|
+
|
3
3
|
# Create or return a new TestingFormat
|
4
4
|
def testing_format
|
5
5
|
@testing_format ||= TestingFormat.create
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
# Load a log file from the fixture folder
|
9
9
|
def log_fixture(name, extention = "log")
|
10
10
|
File.dirname(__FILE__) + "/../fixtures/#{name}.#{extention}"
|
@@ -15,7 +15,7 @@ module RequestLogAnalyzer::Spec::Helpers
|
|
15
15
|
if fields.kind_of?(Array)
|
16
16
|
format.request(*fields)
|
17
17
|
else
|
18
|
-
format.request(fields)
|
18
|
+
format.request(fields)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -24,7 +24,7 @@ module RequestLogAnalyzer::Spec::Helpers
|
|
24
24
|
def run(arguments)
|
25
25
|
binary = "#{File.dirname(__FILE__)}/../../bin/request-log-analyzer"
|
26
26
|
arguments = arguments.join(' ') if arguments.kind_of?(Array)
|
27
|
-
|
27
|
+
|
28
28
|
output = []
|
29
29
|
IO.popen("#{binary} #{arguments}") do |pipe|
|
30
30
|
output = pipe.readlines
|
@@ -32,16 +32,16 @@ module RequestLogAnalyzer::Spec::Helpers
|
|
32
32
|
$?.exitstatus.should == 0
|
33
33
|
output
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
# Cleanup all temporary files generated by specs
|
37
37
|
def cleanup_temp_files!
|
38
38
|
Dir["#{File.dirname(__FILE__)}/../../tmp/spec.*tmp"].each do |file|
|
39
39
|
File.unlink(file)
|
40
40
|
end
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
# Return a filename that can be used as temporary file in specs
|
44
44
|
def temp_output_file(file_type)
|
45
|
-
"#{File.dirname(__FILE__)}/../../tmp/spec.#{file_type}.tmp"
|
45
|
+
"#{File.dirname(__FILE__)}/../../tmp/spec.#{file_type}.tmp"
|
46
46
|
end
|
47
47
|
end
|
data/spec/lib/macros.rb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
module RequestLogAnalyzer::Spec::Macros
|
2
|
-
|
2
|
+
|
3
3
|
def test_databases
|
4
4
|
require 'yaml'
|
5
5
|
hash = YAML.load(File.read("#{File.dirname(__FILE__)}/../database.yml"))
|
6
6
|
hash.inject({}) { |res, (name, h)| res[name] = h.map { |(k,v)| "#{k}=#{v}" }.join(';'); res }
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
# Create or return a new TestingFormat
|
10
10
|
def testing_format
|
11
11
|
@testing_format ||= TestingFormat.create
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def default_orm_class_names
|
15
15
|
['Warning', 'Request', 'Source']
|
16
16
|
end
|
data/spec/lib/matchers.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
module RequestLogAnalyzer::Spec::Matchers
|
2
|
-
|
2
|
+
|
3
3
|
class HasLineDefinition
|
4
|
-
|
4
|
+
|
5
5
|
def initialize(line_type)
|
6
6
|
@line_type = line_type.to_sym
|
7
7
|
@captures = []
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
def capturing(*captures)
|
11
11
|
@captures += captures
|
12
12
|
return self
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
def matches?(file_format)
|
16
16
|
file_format = file_format.create if file_format.kind_of?(Class)
|
17
17
|
if ld = file_format.line_definitions[@line_type]
|
@@ -21,43 +21,57 @@ module RequestLogAnalyzer::Spec::Matchers
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
24
|
-
|
25
|
-
class
|
24
|
+
|
25
|
+
class ParseLine
|
26
|
+
|
26
27
|
def initialize(line)
|
27
|
-
@line
|
28
|
-
@captures
|
28
|
+
@line = line
|
29
|
+
@captures = {}
|
30
|
+
@line_type = nil
|
29
31
|
end
|
30
|
-
|
32
|
+
|
31
33
|
def failure_message
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
@failure_message
|
35
|
+
end
|
36
|
+
|
37
|
+
def as(line_type)
|
38
|
+
@line_type = line_type
|
39
|
+
return self
|
37
40
|
end
|
38
41
|
|
39
|
-
def
|
42
|
+
def and_capture(captures)
|
40
43
|
@captures = captures
|
41
44
|
return self
|
42
45
|
end
|
43
|
-
|
44
|
-
def
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
|
47
|
+
def fail(message)
|
48
|
+
@failure_message = message
|
49
|
+
return false
|
50
|
+
end
|
51
|
+
|
52
|
+
def matches?(file_format)
|
53
|
+
if @line_hash = file_format.parse_line(@line)
|
54
|
+
if @line_type.nil? || @line_hash[:line_definition].name == @line_type
|
55
|
+
@request = file_format.request(@line_hash)
|
56
|
+
@captures.each do |key, value|
|
57
|
+
return fail("Expected line #{@line.inspect}\n to capture #{key.inspect} as #{value.inspect} but was #{@request[key].inspect}.") if @request[key] != value
|
58
|
+
end
|
59
|
+
return true
|
60
|
+
else
|
61
|
+
return fail("The line should match the #{@line_type.inspect} line definition, but matched #{@line_hash[:line_definition].name.inspect} instead.")
|
62
|
+
end
|
49
63
|
else
|
50
|
-
return
|
64
|
+
return fail("The line did not match any line definition.")
|
51
65
|
end
|
52
66
|
end
|
53
67
|
end
|
54
|
-
|
68
|
+
|
55
69
|
def have_line_definition(line_type)
|
56
70
|
return HasLineDefinition.new(line_type)
|
57
71
|
end
|
58
|
-
|
59
|
-
def
|
60
|
-
|
72
|
+
|
73
|
+
def parse_line(line)
|
74
|
+
ParseLine.new(line)
|
61
75
|
end
|
62
|
-
|
76
|
+
|
63
77
|
end
|