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.
Files changed (84) 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 +2 -2
  7. data/lib/cli/progressbar.rb +10 -10
  8. data/lib/cli/tools.rb +3 -3
  9. data/lib/request_log_analyzer.rb +4 -4
  10. data/lib/request_log_analyzer/aggregator.rb +10 -10
  11. data/lib/request_log_analyzer/aggregator/database_inserter.rb +9 -9
  12. data/lib/request_log_analyzer/aggregator/echo.rb +14 -9
  13. data/lib/request_log_analyzer/aggregator/summarizer.rb +26 -26
  14. data/lib/request_log_analyzer/controller.rb +153 -69
  15. data/lib/request_log_analyzer/database.rb +13 -13
  16. data/lib/request_log_analyzer/database/base.rb +17 -17
  17. data/lib/request_log_analyzer/database/connection.rb +3 -3
  18. data/lib/request_log_analyzer/database/request.rb +2 -2
  19. data/lib/request_log_analyzer/database/source.rb +1 -1
  20. data/lib/request_log_analyzer/file_format.rb +15 -15
  21. data/lib/request_log_analyzer/file_format/amazon_s3.rb +16 -16
  22. data/lib/request_log_analyzer/file_format/apache.rb +20 -19
  23. data/lib/request_log_analyzer/file_format/merb.rb +12 -12
  24. data/lib/request_log_analyzer/file_format/rack.rb +4 -4
  25. data/lib/request_log_analyzer/file_format/rails.rb +146 -70
  26. data/lib/request_log_analyzer/file_format/rails_development.rb +4 -49
  27. data/lib/request_log_analyzer/filter.rb +6 -6
  28. data/lib/request_log_analyzer/filter/anonymize.rb +6 -6
  29. data/lib/request_log_analyzer/filter/field.rb +9 -9
  30. data/lib/request_log_analyzer/filter/timespan.rb +12 -10
  31. data/lib/request_log_analyzer/line_definition.rb +15 -14
  32. data/lib/request_log_analyzer/log_processor.rb +22 -22
  33. data/lib/request_log_analyzer/mailer.rb +15 -9
  34. data/lib/request_log_analyzer/output.rb +53 -12
  35. data/lib/request_log_analyzer/output/fixed_width.rb +40 -41
  36. data/lib/request_log_analyzer/output/html.rb +20 -20
  37. data/lib/request_log_analyzer/request.rb +35 -36
  38. data/lib/request_log_analyzer/source.rb +7 -7
  39. data/lib/request_log_analyzer/source/database_loader.rb +7 -7
  40. data/lib/request_log_analyzer/source/log_parser.rb +48 -43
  41. data/lib/request_log_analyzer/tracker.rb +128 -14
  42. data/lib/request_log_analyzer/tracker/duration.rb +39 -132
  43. data/lib/request_log_analyzer/tracker/frequency.rb +31 -32
  44. data/lib/request_log_analyzer/tracker/hourly_spread.rb +20 -19
  45. data/lib/request_log_analyzer/tracker/timespan.rb +17 -17
  46. data/lib/request_log_analyzer/tracker/traffic.rb +36 -116
  47. data/request-log-analyzer.gemspec +19 -15
  48. data/spec/fixtures/rails_22.log +1 -1
  49. data/spec/integration/command_line_usage_spec.rb +1 -1
  50. data/spec/lib/helpers.rb +7 -7
  51. data/spec/lib/macros.rb +3 -3
  52. data/spec/lib/matchers.rb +41 -27
  53. data/spec/lib/mocks.rb +15 -14
  54. data/spec/lib/testing_format.rb +9 -9
  55. data/spec/spec_helper.rb +6 -6
  56. data/spec/unit/aggregator/database_inserter_spec.rb +13 -13
  57. data/spec/unit/aggregator/summarizer_spec.rb +4 -4
  58. data/spec/unit/controller/controller_spec.rb +2 -2
  59. data/spec/unit/controller/log_processor_spec.rb +1 -1
  60. data/spec/unit/database/base_class_spec.rb +19 -19
  61. data/spec/unit/database/connection_spec.rb +3 -3
  62. data/spec/unit/database/database_spec.rb +25 -25
  63. data/spec/unit/file_format/amazon_s3_format_spec.rb +5 -5
  64. data/spec/unit/file_format/apache_format_spec.rb +13 -13
  65. data/spec/unit/file_format/file_format_api_spec.rb +13 -13
  66. data/spec/unit/file_format/line_definition_spec.rb +24 -17
  67. data/spec/unit/file_format/merb_format_spec.rb +41 -45
  68. data/spec/unit/file_format/rails_format_spec.rb +157 -117
  69. data/spec/unit/filter/anonymize_filter_spec.rb +2 -2
  70. data/spec/unit/filter/field_filter_spec.rb +13 -13
  71. data/spec/unit/filter/filter_spec.rb +1 -1
  72. data/spec/unit/filter/timespan_filter_spec.rb +15 -15
  73. data/spec/unit/mailer_spec.rb +30 -0
  74. data/spec/unit/{source/request_spec.rb → request_spec.rb} +30 -30
  75. data/spec/unit/source/log_parser_spec.rb +27 -27
  76. data/spec/unit/tracker/duration_tracker_spec.rb +115 -78
  77. data/spec/unit/tracker/frequency_tracker_spec.rb +74 -63
  78. data/spec/unit/tracker/hourly_spread_spec.rb +28 -20
  79. data/spec/unit/tracker/timespan_tracker_spec.rb +25 -13
  80. data/spec/unit/tracker/tracker_api_spec.rb +13 -13
  81. data/spec/unit/tracker/traffic_tracker_spec.rb +81 -79
  82. data/tasks/github-gem.rake +125 -75
  83. data/tasks/request_log_analyzer.rake +2 -2
  84. metadata +8 -6
@@ -1,5 +1,5 @@
1
1
  module RequestLogAnalyzer::FileFormat
2
-
2
+
3
3
  # The Merb file format parses the request header with the timestamp, the params line
4
4
  # with the most important request information and the durations line which contains
5
5
  # the different request durations that can be used for analysis.
@@ -11,14 +11,14 @@ module RequestLogAnalyzer::FileFormat
11
11
  line.teaser = /Started request handling\:/
12
12
  line.regexp = /Started request handling\:\ (.+)/
13
13
  line.captures << { :name => :timestamp, :type => :timestamp }
14
- end
15
-
14
+ end
15
+
16
16
  # ~ Params: {"action"=>"create", "controller"=>"session"}
17
17
  # ~ Params: {"_method"=>"delete", "authenticity_token"=>"[FILTERED]", "action"=>"d}
18
18
  line_definition :params do |line|
19
19
  line.teaser = /Params\:\ /
20
20
  line.regexp = /Params\:\ (\{.+\})/
21
- line.captures << { :name => :params, :type => :eval, :provides => {
21
+ line.captures << { :name => :params, :type => :eval, :provides => {
22
22
  :namespace => :string, :controller => :string, :action => :string, :format => :string, :method => :string } }
23
23
  end
24
24
 
@@ -31,32 +31,32 @@ module RequestLogAnalyzer::FileFormat
31
31
  :dispatch_time => :duration, :after_filters_time => :duration,
32
32
  :before_filters_time => :duration, :action_time => :duration } }
33
33
  end
34
-
35
- REQUEST_CATEGORIZER = Proc.new do |request|
34
+
35
+ REQUEST_CATEGORIZER = Proc.new do |request|
36
36
  category = "#{request[:controller]}##{request[:action]}"
37
37
  category = "#{request[:namespace]}::#{category}" if request[:namespace]
38
38
  category = "#{category}.#{request[:format]}" if request[:format]
39
39
  category
40
40
  end
41
-
41
+
42
42
  report do |analyze|
43
-
43
+
44
44
  analyze.timespan
45
45
  analyze.hourly_spread
46
46
 
47
- analyze.frequency :category => REQUEST_CATEGORIZER, :amount => 20, :title => "Top 20 by hits"
47
+ analyze.frequency :category => REQUEST_CATEGORIZER, :title => "Top 20 by hits"
48
48
  analyze.duration :dispatch_time, :category => REQUEST_CATEGORIZER, :title => 'Request dispatch duration'
49
-
49
+
50
50
  # analyze.duration :action_time, :category => REQUEST_CATEGORIZER, :title => 'Request action duration'
51
51
  # analyze.duration :after_filters_time, :category => REQUEST_CATEGORIZER, :title => 'Request after_filter duration'
52
52
  # analyze.duration :before_filters_time, :category => REQUEST_CATEGORIZER, :title => 'Request before_filter duration'
53
53
  end
54
54
 
55
55
  class Request < RequestLogAnalyzer::Request
56
-
56
+
57
57
  MONTHS = {'Jan' => '01', 'Feb' => '02', 'Mar' => '03', 'Apr' => '04', 'May' => '05', 'Jun' => '06',
58
58
  'Jul' => '07', 'Aug' => '08', 'Sep' => '09', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12' }
59
-
59
+
60
60
  # Speed up timestamp conversion
61
61
  def convert_timestamp(value, definition)
62
62
  "#{value[26,4]}#{MONTHS[value[4,3]]}#{value[8,2]}#{value[11,2]}#{value[14,2]}#{value[17,2]}".to_i
@@ -1,11 +1,11 @@
1
1
  module RequestLogAnalyzer::FileFormat
2
-
2
+
3
3
  class Rack < Apache
4
-
4
+
5
5
  def self.create(*args)
6
6
  super(:rack, *args)
7
7
  end
8
-
8
+
9
9
  end
10
-
10
+
11
11
  end
@@ -1,98 +1,174 @@
1
1
  module RequestLogAnalyzer::FileFormat
2
-
2
+
3
+ # Default FileFormat class for Rails logs.
4
+ #
5
+ # Instances will be created dynamically based on the lines you want it to parse. You can
6
+ # specify what lines should be included in the parser by providing a list to the create
7
+ # method as first argument.
3
8
  class Rails < Base
4
-
5
- # Processing EmployeeController#index (for 123.123.123.123 at 2008-07-13 06:00:00) [GET]
6
- line_definition :processing do |line|
7
- line.header = true # this line is the first log line for a request
8
- line.teaser = /Processing /
9
- line.regexp = /Processing ((?:\w+::)?\w+)#(\w+)(?: to (\w+))? \(for (\d+\.\d+\.\d+\.\d+) at (\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d)\) \[([A-Z]+)\]/
10
- line.captures << { :name => :controller, :type => :string } \
11
- << { :name => :action, :type => :string } \
12
- << { :name => :format, :type => :string, :default => 'html' } \
13
- << { :name => :ip, :type => :string } \
14
- << { :name => :timestamp, :type => :timestamp } \
15
- << { :name => :method, :type => :string }
16
- end
17
9
 
18
- # Filter chain halted as [#<ActionController::Caching::Actions::ActionCacheFilter:0x2a999ad620 @check=nil, @options={:store_options=>{}, :layout=>nil, :cache_path=>#<Proc:0x0000002a999b8890@/app/controllers/cached_controller.rb:8>}>] rendered_or_redirected.
19
- line_definition :cache_hit do |line|
20
- line.regexp = /Filter chain halted as \[\#<ActionController::Caching::Actions::ActionCacheFilter/
21
- end
22
-
23
- # RuntimeError (Cannot destroy employee): /app/models/employee.rb:198:in `before_destroy'
24
- line_definition :failed do |line|
25
- line.footer = true
26
- line.regexp = /((?:[A-Z]\w+\:\:)*[A-Z]\w+) \((.*)\)(?: on line #(\d+) of .+)?\:(.*)/
27
- line.captures << { :name => :error, :type => :string } \
28
- << { :name => :message, :type => :string } \
29
- << { :name => :line, :type => :integer } \
30
- << { :name => :file, :type => :string } \
31
- << { :name => :stack_trace, :type => :string }
10
+ # Creates a Rails FileFormat instance.
11
+ #
12
+ # The lines that will be parsed can be defined by the argument to this function,
13
+ # which should be an array of line names, or a list of line names as comma separated
14
+ # string. The resulting report depends on the lines that will be parsed. You can
15
+ # also provide s string that describes a common set of lines, like "production",
16
+ # "development" or "production".
17
+ def self.create(lines = 'production')
18
+ definitions_hash = line_definer.line_definitions.clone
19
+
20
+ lines = lines.to_s.split(',') if lines.kind_of?(String)
21
+ lines = [lines.to_s] if lines.kind_of?(Symbol)
22
+
23
+ lines.each do |line|
24
+ line = line.to_sym
25
+ if LINE_COLLECTIONS.has_key?(line)
26
+ LINE_COLLECTIONS[line].each { |l| definitions_hash[l] = LINE_DEFINITIONS[l] }
27
+ elsif LINE_DEFINITIONS.has_key?(line)
28
+ definitions_hash[line] = LINE_DEFINITIONS[line]
29
+ else
30
+ raise "Unrecognized Rails log line name: #{line.inspect}!"
31
+ end
32
+ end
33
+
34
+ return self.new(definitions_hash, report_trackers(definitions_hash))
32
35
  end
36
+
37
+ # Creates trackers based on the specified line definitions.
38
+ #
39
+ # The more lines that will be parsed, the more information will appear in the report.
40
+ def self.report_trackers(lines)
41
+ analyze = RequestLogAnalyzer::Aggregator::Summarizer::Definer.new
42
+
43
+ analyze.timespan
44
+ analyze.hourly_spread
45
+
46
+ analyze.frequency :category => REQUEST_CATEGORIZER, :title => 'Most requested'
47
+ analyze.frequency :method, :title => 'HTTP methods'
48
+ analyze.frequency :status, :title => 'HTTP statuses returned'
49
+
50
+ if lines.has_key?(:cache_hit)
51
+ analyze.frequency(:category => lambda { |request| request =~ :cache_hit ? 'Cache hit' : 'No hit' },
52
+ :title => 'Rails action cache hits')
53
+ end
54
+
55
+ analyze.duration :duration, :category => REQUEST_CATEGORIZER, :title => "Request duration", :line_type => :completed
56
+ analyze.duration :view, :category => REQUEST_CATEGORIZER, :title => "View rendering time", :line_type => :completed
57
+ analyze.duration :db, :category => REQUEST_CATEGORIZER, :title => "Database time", :line_type => :completed
58
+
59
+ analyze.frequency :category => REQUEST_CATEGORIZER, :title => 'Process blockers (> 1 sec duration)',
60
+ :if => lambda { |request| request[:duration] && request[:duration] > 1.0 }
61
+
62
+ if lines.has_key?(:failure)
63
+ analyze.frequency :error, :title => 'Failed requests', :line_type => :failure
64
+ end
33
65
 
66
+ if lines.has_key?(:rendered)
67
+ analyze.duration :render_duration, :category => :render_file, :multiple_per_request => true, :title => 'Partial rendering duration'
68
+ end
69
+
70
+ if lines.has_key?(:query_executed)
71
+ analyze.duration :query_duration, :category => :query_sql, :multiple_per_request => true, :title => 'Query duration'
72
+ end
73
+
74
+ return analyze.trackers + report_definer.trackers
75
+ end
34
76
 
35
77
  # Rails < 2.1 completed line example
36
78
  # Completed in 0.21665 (4 reqs/sec) | Rendering: 0.00926 (4%) | DB: 0.00000 (0%) | 200 OK [http://demo.nu/employees]
37
79
  RAILS_21_COMPLETED = /Completed in (\d+\.\d{5}) \(\d+ reqs\/sec\) (?:\| Rendering: (\d+\.\d{5}) \(\d+\%\) )?(?:\| DB: (\d+\.\d{5}) \(\d+\%\) )?\| (\d\d\d).+\[(http.+)\]/
38
80
 
39
81
  # Rails > 2.1 completed line example
40
- # Completed in 614ms (View: 120, DB: 31) | 200 OK [http://floorplanner.local/demo]
82
+ # Completed in 614ms (View: 120, DB: 31) | 200 OK [http://floorplanner.local/demo]
41
83
  RAILS_22_COMPLETED = /Completed in (\d+)ms \((?:View: (\d+), )?DB: (\d+)\) \| (\d\d\d).+\[(http.+)\]/
42
84
 
43
- # The completed line uses a kind of hack to ensure that both old style logs and new style logs
44
- # are both parsed by the same regular expression. The format in Rails 2.2 was slightly changed,
45
- # but the line contains exactly the same information.
46
- line_definition :completed do |line|
47
-
48
- line.footer = true
49
- line.teaser = /Completed in /
50
- line.regexp = Regexp.new("(?:#{RAILS_21_COMPLETED}|#{RAILS_22_COMPLETED})")
51
-
52
- line.captures << { :name => :duration, :type => :duration, :unit => :sec } \
53
- << { :name => :view, :type => :duration, :unit => :sec } \
54
- << { :name => :db, :type => :duration, :unit => :sec } \
55
- << { :name => :status, :type => :integer } \
56
- << { :name => :url, :type => :string } # Old variant
57
-
58
- line.captures << { :name => :duration, :type => :duration, :unit => :msec } \
59
- << { :name => :view, :type => :duration, :unit => :msec } \
60
- << { :name => :db, :type => :duration, :unit => :msec } \
61
- << { :name => :status, :type => :integer } \
62
- << { :name => :url, :type => :string } # 2.2 variant
63
- end
85
+ # A hash of definitions for all common lines in Rails logs.
86
+ LINE_DEFINITIONS = {
87
+ :processing => RequestLogAnalyzer::LineDefinition.new(:processing, :header => true,
88
+ :teaser => /Processing /,
89
+ :regexp => /Processing ((?:\w+::)?\w+)#(\w+)(?: to (\w+))? \(for (\d+\.\d+\.\d+\.\d+) at (\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d)\) \[([A-Z]+)\]/,
90
+ :captures => [{ :name => :controller, :type => :string },
91
+ { :name => :action, :type => :string },
92
+ { :name => :format, :type => :string, :default => 'html' },
93
+ { :name => :ip, :type => :string },
94
+ { :name => :timestamp, :type => :timestamp },
95
+ { :name => :method, :type => :string }]),
96
+
97
+ :completed => RequestLogAnalyzer::LineDefinition.new(:completed, :footer => true,
98
+ :teaser => /Completed in /,
99
+ :regexp => Regexp.union(RAILS_21_COMPLETED, RAILS_22_COMPLETED),
100
+ :captures => [{ :name => :duration, :type => :duration, :unit => :sec }, # First old variant capture
101
+ { :name => :view, :type => :duration, :unit => :sec },
102
+ { :name => :db, :type => :duration, :unit => :sec },
103
+ { :name => :status, :type => :integer },
104
+ { :name => :url, :type => :string }, # Last old variant capture
105
+ { :name => :duration, :type => :duration, :unit => :msec }, # First new variant capture
106
+ { :name => :view, :type => :duration, :unit => :msec },
107
+ { :name => :db, :type => :duration, :unit => :msec },
108
+ { :name => :status, :type => :integer },
109
+ { :name => :url, :type => :string }]), # Last new variant capture
64
110
 
111
+ :failure => RequestLogAnalyzer::LineDefinition.new(:failure, :footer => true,
112
+ :teaser => /((?:[A-Z]\w*[a-z]\w+\:\:)*[A-Z]\w*[a-z]\w+) \((.*)\)(?: on line #(\d+) of (.+))?\:/,
113
+ :regexp => /((?:[A-Z]\w*[a-z]\w+\:\:)*[A-Z]\w*[a-z]\w+) \((.*)\)(?: on line #(\d+) of (.+))?\:\s*$/,
114
+ :captures => [{ :name => :error, :type => :string },
115
+ { :name => :message, :type => :string },
116
+ { :name => :line, :type => :integer },
117
+ { :name => :file, :type => :string }]),
118
+
119
+ :cache_hit => RequestLogAnalyzer::LineDefinition.new(:cache_hit,
120
+ :regexp => /Filter chain halted as \[\#<ActionController::Caching::Actions::ActionCacheFilter/),
121
+
122
+ :parameters => RequestLogAnalyzer::LineDefinition.new(:parameters,
123
+ :teaser => / Parameters:/,
124
+ :regexp => / Parameters:\s+(\{.*\})/,
125
+ :captures => [{ :name => :params, :type => :eval }]),
126
+
127
+ :rendered => RequestLogAnalyzer::LineDefinition.new(:rendered,
128
+ :teaser => /Rendered /,
129
+ :regexp => /Rendered (\w+(?:\/\w+)+) \((\d+\.\d+)ms\)/,
130
+ :captures => [{ :name => :render_file, :type => :string },
131
+ { :name => :render_duration, :type => :duration, :unit => :msec }]),
132
+
133
+ :query_executed => RequestLogAnalyzer::LineDefinition.new(:query_executed,
134
+ :regexp => /\s+(?:\e\[4;36;1m)?((?:\w+::)*\w+) Load \((\d+\.\d+)ms\)(?:\e\[0m)?\s+(?:\e\[0;1m)?([^\e]+) ?(?:\e\[0m)?/,
135
+ :captures => [{ :name => :query_class, :type => :string },
136
+ { :name => :query_duration, :type => :duration, :unit => :msec },
137
+ { :name => :query_sql, :type => :sql }]),
138
+
139
+ :query_cached => RequestLogAnalyzer::LineDefinition.new(:query_cached,
140
+ :regexp => /\s+(?:\e\[4;35;1m)?CACHE \((\d+\.\d+)ms\)(?:\e\[0m)?\s+(?:\e\[0m)?([^\e]+) ?(?:\e\[0m)?/,
141
+ :captures => [{ :name => :cached_duration, :type => :duration, :unit => :msec },
142
+ { :name => :cached_sql, :type => :sql }])
143
+ }
144
+
145
+ # Definitions of common combinations of lines that can be parsed
146
+ LINE_COLLECTIONS = {
147
+ :minimal => [:processing, :completed],
148
+ :production => [:processing, :completed, :failure, :cache_hit],
149
+ :development => [:processing, :completed, :failure, :rendered, :query_executed, :query_cached],
150
+ :all => LINE_DEFINITIONS.keys
151
+ }
152
+
153
+
154
+ # Simple function to categorize Rails requests using controller/actions/format and method.
65
155
  REQUEST_CATEGORIZER = Proc.new do |request|
66
156
  "#{request[:controller]}##{request[:action]}.#{request[:format]} [#{request[:method]}]"
67
157
  end
68
158
 
69
- report do |analyze|
70
- analyze.timespan
71
- analyze.hourly_spread
72
-
73
- analyze.frequency :category => REQUEST_CATEGORIZER, :title => 'Top 20 hits', :amount => 20
74
- analyze.frequency :method, :title => 'HTTP methods'
75
- analyze.frequency :status, :title => 'HTTP statuses returned'
76
- analyze.frequency :category => lambda { |request| request =~ :cache_hit ? 'Cache hit' : 'No hit' }, :title => 'Rails action cache hits'
77
-
78
- analyze.duration :duration, :category => REQUEST_CATEGORIZER, :title => "Request duration", :line_type => :completed
79
- analyze.duration :view, :category => REQUEST_CATEGORIZER, :title => "View rendering time", :line_type => :completed
80
- analyze.duration :db, :category => REQUEST_CATEGORIZER, :title => "Database time", :line_type => :completed
81
-
82
- analyze.frequency :category => REQUEST_CATEGORIZER, :title => 'Process blockers (> 1 sec duration)',
83
- :if => lambda { |request| request[:duration] && request[:duration] > 1.0 }, :amount => 20
84
-
85
- analyze.frequency :error, :title => 'Failed requests', :line_type => :failed, :amount => 20
86
- end
87
-
88
159
  # Define a custom Request class for the Rails file format to speed up timestamp handling
89
160
  # and to ensure that a format is always set.
90
161
  class Request < RequestLogAnalyzer::Request
91
-
162
+
92
163
  # Do not use DateTime.parse
93
164
  def convert_timestamp(value, definition)
94
165
  value.gsub(/[^0-9]/, '')[0...14].to_i
95
166
  end
167
+
168
+ # Sanitizes SQL queries so that they can be grouped
169
+ def convert_sql(sql, definition)
170
+ sql.gsub(/\b\d+\b/, ':int').gsub(/`([^`]+)`/, '\1').gsub(/'[^']*'/, ':string').rstrip
171
+ end
96
172
  end
97
173
 
98
174
  end
@@ -1,57 +1,12 @@
1
1
  module RequestLogAnalyzer::FileFormat
2
-
2
+
3
3
  # The RailsDevelopment FileFormat is an extention to the default Rails file format. It includes
4
4
  # all lines of the normal Rails file format, but parses SQL queries and partial rendering lines
5
5
  # as well.
6
6
  class RailsDevelopment < Rails
7
-
8
- # Parameters: {"action"=>"demo", "controller"=>"page"}
9
- line_definition :parameters do |line|
10
- line.teaser = /Parameters/
11
- line.regexp = /\s+Parameters:\s+(\{.*\})/
12
- line.captures << { :name => :params, :type => :eval }
13
- end
14
-
15
- # Rendered layouts/_footer (2.9ms)
16
- line_definition :rendered do |line|
17
- line.regexp = /Rendered (\w+(?:\/\w+)+) \((\d+\.\d+)ms\)/
18
- line.captures << { :name => :render_file, :type => :string } \
19
- << { :name => :render_duration, :type => :duration, :unit => :msec }
20
- end
21
-
22
- # User Load (0.4ms) SELECT * FROM `users` WHERE (`users`.`id` = 18205844) 
23
- line_definition :query_executed do |line|
24
- line.regexp = /\s+(?:\e\[4;36;1m)?((?:\w+::)*\w+) Load \((\d+\.\d+)ms\)(?:\e\[0m)?\s+(?:\e\[0;1m)?([^\e]+) ?(?:\e\[0m)?/
25
- line.captures << { :name => :query_class, :type => :string } \
26
- << { :name => :query_duration, :type => :duration, :unit => :msec } \
27
- << { :name => :query_sql, :type => :sql }
28
- end
29
-
30
- # CACHE (0.0ms) SELECT * FROM `users` WHERE (`users`.`id` = 0) 
31
- line_definition :query_cached do |line|
32
- line.regexp = /\s+(?:\e\[4;35;1m)?CACHE \((\d+\.\d+)ms\)(?:\e\[0m)?\s+(?:\e\[0m)?([^\e]+) ?(?:\e\[0m)?/
33
- line.captures << { :name => :cached_duration, :type => :duration, :unit => :msec } \
34
- << { :name => :cached_sql, :type => :sql }
35
- end
36
-
37
- # Define the reporting for the additional parsed lines
38
- report(:append) do |analyze|
39
-
40
- analyze.duration :render_duration, :category => :render_file, :multiple_per_request => true,
41
- :amount => 20, :title => 'Partial rendering duration'
42
-
43
- analyze.duration :query_duration, :category => :query_sql, :multiple_per_request => true,
44
- :amount => 20, :title => 'Query duration'
45
-
46
- end
47
-
48
- # Add a converter method for the SQL fields the the Rails request class
49
- class Request < Rails::Request
50
-
51
- # Sanitizes SQL queries so that they can be grouped
52
- def convert_sql(sql, definition)
53
- sql.gsub(/\b\d+\b/, ':int').gsub(/`([^`]+)`/, '\1').gsub(/'[^']*'/, ':string').rstrip
54
- end
7
+ def self.create
8
+ puts 'DEPRECATED: use --rails-format development instead!'
9
+ super('development')
55
10
  end
56
11
  end
57
12
  end
@@ -1,17 +1,17 @@
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
10
  # All filters should interit from this base.
11
11
  class Base
12
-
12
+
13
13
  attr_reader :file_format, :options
14
-
14
+
15
15
  # Initializer
16
16
  # <tt>format</tt> The file format
17
17
  # <tt>options</tt> Are passed to the filters.
@@ -19,12 +19,12 @@ module RequestLogAnalyzer::Filter
19
19
  @file_format = format
20
20
  @options = options
21
21
  end
22
-
22
+
23
23
  # Return the request if the request should be kept.
24
24
  # Return nil otherwise.
25
25
  def filter(request)
26
26
  request
27
27
  end
28
28
  end
29
-
29
+
30
30
  end
@@ -1,12 +1,12 @@
1
1
  module RequestLogAnalyzer::Filter
2
-
2
+
3
3
  # Filter to anonymize parsed values
4
4
  # Options
5
5
  # * <tt>:mode</tt> :reject or :accept.
6
6
  # * <tt>:field</tt> Specific field to accept or reject.
7
7
  # * <tt>:value</tt> Value that the field should match to be accepted or rejected.
8
8
  class Anonymize < Base
9
-
9
+
10
10
  def generate_random_ip
11
11
  "#{rand(256)}.#{rand(256)}.#{rand(256)}.#{rand(256)}"
12
12
  end
@@ -14,7 +14,7 @@ module RequestLogAnalyzer::Filter
14
14
  def anonymize_url(value)
15
15
  return value.sub(/^https?\:\/\/[A-Za-z0-9\.-]+\//, "http://example.com/")
16
16
  end
17
-
17
+
18
18
  def fuzz(value)
19
19
  value * ((75 + rand(50)) / 100.0)
20
20
  end
@@ -31,9 +31,9 @@ module RequestLogAnalyzer::Filter
31
31
  request.attributes[key] = fuzz(value)
32
32
  end
33
33
  end
34
-
34
+
35
35
  return request
36
- end
36
+ end
37
37
  end
38
-
38
+
39
39
  end