request-log-analyzer 1.1.1 → 1.1.2
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/bin/request-log-analyzer +0 -11
- data/lib/request_log_analyzer/aggregator/summarizer.rb +7 -3
- data/lib/request_log_analyzer/controller.rb +15 -3
- data/lib/request_log_analyzer/file_format.rb +44 -16
- data/lib/request_log_analyzer/file_format/merb.rb +5 -5
- data/lib/request_log_analyzer/file_format/rails.rb +35 -21
- data/lib/request_log_analyzer/file_format/rails_development.rb +27 -20
- data/lib/request_log_analyzer/filter/{anonimize.rb → anonymize.rb} +3 -5
- data/lib/request_log_analyzer/filter/field.rb +1 -5
- data/lib/request_log_analyzer/filter/timespan.rb +0 -2
- data/lib/request_log_analyzer/line_definition.rb +12 -88
- data/lib/request_log_analyzer/log_processor.rb +5 -25
- data/lib/request_log_analyzer/request.rb +56 -4
- data/lib/request_log_analyzer/source/log_parser.rb +3 -4
- data/lib/request_log_analyzer/tracker/{category.rb → frequency.rb} +2 -2
- data/spec/controller_spec.rb +38 -19
- data/spec/file_format_spec.rb +2 -2
- data/spec/file_formats/spec_format.rb +12 -5
- data/spec/filter_spec.rb +3 -3
- data/spec/line_definition_spec.rb +18 -85
- data/spec/log_parser_spec.rb +2 -3
- data/spec/log_processor_spec.rb +0 -38
- data/spec/merb_format_spec.rb +1 -1
- data/spec/rails_format_spec.rb +6 -5
- data/spec/spec_helper.rb +16 -0
- metadata +4 -4
data/bin/request-log-analyzer
CHANGED
@@ -27,14 +27,6 @@ begin
|
|
27
27
|
strip.switch(:keep_junk_lines, :j)
|
28
28
|
end
|
29
29
|
|
30
|
-
command_line.command(:anonymize) do |anonymize|
|
31
|
-
anonymize.minimum_parameters = 1
|
32
|
-
anonymize.option(:format, :alias => :f, :default => 'rails')
|
33
|
-
anonymize.option(:output, :alias => :o)
|
34
|
-
anonymize.switch(:discard_teaser_lines, :t)
|
35
|
-
anonymize.switch(:keep_junk_lines, :j)
|
36
|
-
end
|
37
|
-
|
38
30
|
command_line.option(:format, :alias => :f, :default => 'rails')
|
39
31
|
command_line.option(:file, :alias => :e)
|
40
32
|
command_line.switch(:assume_correct_order)
|
@@ -111,9 +103,6 @@ when :install
|
|
111
103
|
when :strip
|
112
104
|
require File.dirname(__FILE__) + '/../lib/request_log_analyzer/log_processor'
|
113
105
|
RequestLogAnalyzer::LogProcessor.build(:strip, arguments).run!
|
114
|
-
when :anonymize
|
115
|
-
require File.dirname(__FILE__) + '/../lib/request_log_analyzer/log_processor'
|
116
|
-
RequestLogAnalyzer::LogProcessor.build(:anonymize, arguments).run!
|
117
106
|
else
|
118
107
|
puts "Request-log-analyzer, by Willem van Bergen and Bart ten Brinke - version #{RequestLogAnalyzer::VERSION}"
|
119
108
|
puts "Website: http://github.com/wvanbergen/request-log-analyzer"
|
@@ -12,15 +12,19 @@ module RequestLogAnalyzer::Aggregator
|
|
12
12
|
@trackers = []
|
13
13
|
end
|
14
14
|
|
15
|
+
def reset!
|
16
|
+
@trackers = []
|
17
|
+
end
|
18
|
+
|
15
19
|
def method_missing(tracker_method, *args)
|
16
20
|
track(tracker_method, args.first)
|
17
21
|
end
|
18
22
|
|
19
|
-
def
|
23
|
+
def frequency(category_field, options = {})
|
20
24
|
if category_field.kind_of?(Symbol)
|
21
|
-
track(:
|
25
|
+
track(:frequency, options.merge(:category => category_field))
|
22
26
|
elsif category_field.kind_of?(Hash)
|
23
|
-
track(:
|
27
|
+
track(:frequency, category_field.merge(options))
|
24
28
|
end
|
25
29
|
end
|
26
30
|
|
@@ -131,7 +131,7 @@ module RequestLogAnalyzer
|
|
131
131
|
def handle_progress(message, value = nil)
|
132
132
|
case message
|
133
133
|
when :started
|
134
|
-
@progress_bar = CommandLine::ProgressBar.new(File.basename(value), File.size(value))
|
134
|
+
@progress_bar = CommandLine::ProgressBar.new(File.basename(value), File.size(value), STDOUT)
|
135
135
|
when :finished
|
136
136
|
@progress_bar.finish
|
137
137
|
@progress_bar = nil
|
@@ -160,6 +160,18 @@ module RequestLogAnalyzer
|
|
160
160
|
@filters << filter.new(file_format, @options.merge(filter_options))
|
161
161
|
end
|
162
162
|
|
163
|
+
def filter_request(request)
|
164
|
+
@filters.each do |filter|
|
165
|
+
request = filter.filter(request)
|
166
|
+
return nil if request.nil?
|
167
|
+
end
|
168
|
+
return request
|
169
|
+
end
|
170
|
+
|
171
|
+
def aggregate_request(request)
|
172
|
+
@aggregators.each { |agg| agg.aggregate(request) }
|
173
|
+
end
|
174
|
+
|
163
175
|
# Runs RequestLogAnalyzer
|
164
176
|
# 1. Call prepare on every aggregator
|
165
177
|
# 2. Generate requests from source object
|
@@ -175,8 +187,8 @@ module RequestLogAnalyzer
|
|
175
187
|
|
176
188
|
begin
|
177
189
|
@source.each_request do |request|
|
178
|
-
|
179
|
-
|
190
|
+
request = filter_request(request)
|
191
|
+
aggregate_request(request) unless request.nil?
|
180
192
|
end
|
181
193
|
rescue Interrupt => e
|
182
194
|
handle_progress(:interrupted)
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module RequestLogAnalyzer::FileFormat
|
2
2
|
|
3
|
-
|
4
3
|
def self.const_missing(const)
|
5
4
|
RequestLogAnalyzer::load_default_class_file(self, const)
|
6
5
|
end
|
@@ -24,14 +23,24 @@ module RequestLogAnalyzer::FileFormat
|
|
24
23
|
elsif file_format.kind_of?(String) && File.exist?(file_format)
|
25
24
|
# load a format from a ruby file
|
26
25
|
require file_format
|
27
|
-
|
26
|
+
const = RequestLogAnalyzer::to_camelcase(File.basename(file_format, '.rb'))
|
27
|
+
if RequestLogAnalyzer::FileFormat.const_defined?(const)
|
28
|
+
klass = RequestLogAnalyzer::FileFormat.const_get(const)
|
29
|
+
elsif Object.const_defined?(const)
|
30
|
+
klass = Object.const_get(const)
|
31
|
+
else
|
32
|
+
raise "Cannot load class #{const} from #{file_format}!"
|
33
|
+
end
|
28
34
|
|
29
35
|
else
|
30
36
|
# load a provided file format
|
31
37
|
klass = RequestLogAnalyzer::FileFormat.const_get(RequestLogAnalyzer::to_camelcase(file_format))
|
32
38
|
end
|
33
39
|
|
34
|
-
|
40
|
+
# check the returned klass to see if it can be used
|
41
|
+
raise "Could not load a file format from #{file_format.inspect}" if klass.nil?
|
42
|
+
raise "Invalid FileFormat class" unless klass.kind_of?(Class) && klass.ancestors.include?(RequestLogAnalyzer::FileFormat::Base)
|
43
|
+
|
35
44
|
@current_file_format = klass.new # return an instance of the class
|
36
45
|
end
|
37
46
|
|
@@ -56,13 +65,29 @@ module RequestLogAnalyzer::FileFormat
|
|
56
65
|
|
57
66
|
# Registers the line definer instance for a subclass.
|
58
67
|
def self.inherited(subclass)
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
68
|
+
if subclass.superclass == RequestLogAnalyzer::FileFormat::Base
|
69
|
+
|
70
|
+
# Create aline and report definer for this class
|
71
|
+
subclass.class_eval do
|
72
|
+
instance_variable_set(:@line_definer, RequestLogAnalyzer::LineDefinition::Definer.new)
|
73
|
+
instance_variable_set(:@report_definer, RequestLogAnalyzer::Aggregator::Summarizer::Definer.new)
|
74
|
+
class << self; attr_accessor :line_definer, :report_definer; end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Create a custom Request class for this file format
|
78
|
+
subclass.const_set('Request', Class.new(RequestLogAnalyzer::Request)) unless subclass.const_defined?('Request')
|
79
|
+
else
|
80
|
+
|
81
|
+
# Copy the line and report definer from the parent class.
|
82
|
+
subclass.class_eval do
|
83
|
+
instance_variable_set(:@line_definer, superclass.line_definer)
|
84
|
+
instance_variable_set(:@report_definer, superclass.report_definer)
|
85
|
+
class << self; attr_accessor :line_definer, :report_definer; end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Create a custom Request class based on the superclass's Request class
|
89
|
+
subclass.const_set('Request', Class.new(subclass.superclass::Request)) unless subclass.const_defined?('Request')
|
90
|
+
end
|
66
91
|
end
|
67
92
|
|
68
93
|
# Specifies a single line defintions.
|
@@ -77,16 +102,19 @@ module RequestLogAnalyzer::FileFormat
|
|
77
102
|
# Specifies multiple line definitions at once using a block
|
78
103
|
def self.format_definition(&block)
|
79
104
|
if block_given?
|
80
|
-
yield
|
105
|
+
yield self.line_definer
|
81
106
|
else
|
82
|
-
return
|
107
|
+
return self.line_definer
|
83
108
|
end
|
84
109
|
end
|
85
110
|
|
86
111
|
# Specifies the summary report using a block.
|
87
|
-
def self.report(&block)
|
88
|
-
|
89
|
-
|
112
|
+
def self.report(mode = :append, &block)
|
113
|
+
if mode == :overwrite
|
114
|
+
self.report_definer.reset!
|
115
|
+
end
|
116
|
+
|
117
|
+
yield(self.report_definer)
|
90
118
|
end
|
91
119
|
|
92
120
|
# Returns all line definitions
|
@@ -96,7 +124,7 @@ module RequestLogAnalyzer::FileFormat
|
|
96
124
|
|
97
125
|
# Returns all the defined trackers for the summary report.
|
98
126
|
def report_trackers
|
99
|
-
self.class.
|
127
|
+
self.class.report_definer.trackers# => rescue []
|
100
128
|
end
|
101
129
|
|
102
130
|
# Checks whether the line definitions form a valid language.
|
@@ -7,7 +7,7 @@ module RequestLogAnalyzer::FileFormat
|
|
7
7
|
line.header = true
|
8
8
|
line.teaser = /Started/
|
9
9
|
line.regexp = /Started request handling\:\ (.+)/
|
10
|
-
line.captures << { :name => :timestamp, :type => :timestamp
|
10
|
+
line.captures << { :name => :timestamp, :type => :timestamp }
|
11
11
|
end
|
12
12
|
|
13
13
|
# ~ Params: {"action"=>"create", "controller"=>"session"}
|
@@ -23,10 +23,10 @@ module RequestLogAnalyzer::FileFormat
|
|
23
23
|
line.footer = true
|
24
24
|
line.teaser = /\{:dispatch_time/
|
25
25
|
line.regexp = /\{\:dispatch_time=>(\d+\.\d+(?:e-?\d+)?), (?:\:after_filters_time=>(\d+\.\d+(?:e-?\d+)?), )?(?:\:before_filters_time=>(\d+\.\d+(?:e-?\d+)?), )?\:action_time=>(\d+\.\d+(?:e-?\d+)?)\}/
|
26
|
-
line.captures << { :name => :dispatch_time, :type => :
|
27
|
-
<< { :name => :after_filters_time, :type => :
|
28
|
-
<< { :name => :before_filters_time, :type => :
|
29
|
-
<< { :name => :action_time, :type => :
|
26
|
+
line.captures << { :name => :dispatch_time, :type => :duration } \
|
27
|
+
<< { :name => :after_filters_time, :type => :duration } \
|
28
|
+
<< { :name => :before_filters_time, :type => :duration } \
|
29
|
+
<< { :name => :action_time, :type => :duration }
|
30
30
|
end
|
31
31
|
|
32
32
|
|
@@ -9,9 +9,9 @@ module RequestLogAnalyzer::FileFormat
|
|
9
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
10
|
line.captures << { :name => :controller, :type => :string } \
|
11
11
|
<< { :name => :action, :type => :string } \
|
12
|
-
<< { :name => :format, :type => :
|
13
|
-
<< { :name => :ip, :type => :string
|
14
|
-
<< { :name => :timestamp, :type => :timestamp
|
12
|
+
<< { :name => :format, :type => :format } \
|
13
|
+
<< { :name => :ip, :type => :string } \
|
14
|
+
<< { :name => :timestamp, :type => :timestamp } \
|
15
15
|
<< { :name => :method, :type => :string }
|
16
16
|
end
|
17
17
|
|
@@ -28,7 +28,7 @@ module RequestLogAnalyzer::FileFormat
|
|
28
28
|
<< { :name => :message, :type => :string } \
|
29
29
|
<< { :name => :line, :type => :integer } \
|
30
30
|
<< { :name => :file, :type => :string } \
|
31
|
-
<< { :name => :stack_trace, :type => :string
|
31
|
+
<< { :name => :stack_trace, :type => :string }
|
32
32
|
end
|
33
33
|
|
34
34
|
|
@@ -49,42 +49,56 @@ module RequestLogAnalyzer::FileFormat
|
|
49
49
|
line.teaser = /Completed in /
|
50
50
|
line.regexp = Regexp.new("(?:#{RAILS_21_COMPLETED}|#{RAILS_22_COMPLETED})")
|
51
51
|
|
52
|
-
line.captures << { :name => :duration, :type => :
|
53
|
-
<< { :name => :view, :type => :
|
54
|
-
<< { :name => :db, :type => :
|
52
|
+
line.captures << { :name => :duration, :type => :duration, :unit => :sec } \
|
53
|
+
<< { :name => :view, :type => :duration, :unit => :sec } \
|
54
|
+
<< { :name => :db, :type => :duration, :unit => :sec } \
|
55
55
|
<< { :name => :status, :type => :integer } \
|
56
|
-
<< { :name => :url, :type => :string
|
56
|
+
<< { :name => :url, :type => :string } # Old variant
|
57
57
|
|
58
|
-
line.captures << { :name => :duration, :type => :
|
59
|
-
<< { :name => :view, :type => :
|
60
|
-
<< { :name => :db, :type => :
|
61
|
-
<< { :name => :status, :type => :integer} \
|
62
|
-
<< { :name => :url, :type => :string
|
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
63
|
end
|
64
64
|
|
65
65
|
|
66
66
|
|
67
67
|
REQUEST_CATEGORIZER = Proc.new do |request|
|
68
|
-
format
|
69
|
-
"#{request[:controller]}##{request[:action]}.#{format} [#{request[:method]}]"
|
68
|
+
"#{request[:controller]}##{request[:action]}.#{request[:format]} [#{request[:method]}]"
|
70
69
|
end
|
71
70
|
|
72
71
|
report do |analyze|
|
73
72
|
analyze.timespan :line_type => :processing
|
74
|
-
analyze.
|
75
|
-
analyze.
|
76
|
-
analyze.
|
77
|
-
analyze.
|
73
|
+
analyze.frequency :category => REQUEST_CATEGORIZER, :title => 'Top 20 hits', :amount => 20, :line_type => :processing
|
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'
|
78
77
|
|
79
78
|
analyze.duration :duration, :category => REQUEST_CATEGORIZER, :title => "Request duration", :line_type => :completed
|
80
79
|
analyze.duration :view, :category => REQUEST_CATEGORIZER, :title => "Database time", :line_type => :completed
|
81
80
|
analyze.duration :db, :category => REQUEST_CATEGORIZER, :title => "View rendering time", :line_type => :completed
|
82
81
|
|
83
|
-
analyze.
|
82
|
+
analyze.frequency :category => REQUEST_CATEGORIZER, :title => 'Process blockers (> 1 sec duration)',
|
84
83
|
:if => lambda { |request| request[:duration] && request[:duration] > 1.0 }, :amount => 20
|
85
84
|
|
86
85
|
analyze.hourly_spread :line_type => :processing
|
87
|
-
analyze.
|
86
|
+
analyze.frequency :error, :title => 'Failed requests', :line_type => :failed, :amount => 20
|
87
|
+
end
|
88
|
+
|
89
|
+
# Define a custom Request class for the Rails file format to speed up timestamp handling
|
90
|
+
# and to ensure that a format is always set.
|
91
|
+
class Request < RequestLogAnalyzer::Request
|
92
|
+
|
93
|
+
# Do not use DateTime.parse
|
94
|
+
def convert_timestamp(value, definition)
|
95
|
+
value.gsub(/[^0-9]/, '')[0...14].to_i unless value.nil?
|
96
|
+
end
|
97
|
+
|
98
|
+
# Set 'html' as default format for a request
|
99
|
+
def convert_format(value, definition)
|
100
|
+
value || 'html'
|
101
|
+
end
|
88
102
|
end
|
89
103
|
|
90
104
|
end
|
@@ -10,8 +10,8 @@ module RequestLogAnalyzer::FileFormat
|
|
10
10
|
line.captures << { :name => :controller, :type => :string } \
|
11
11
|
<< { :name => :action, :type => :string } \
|
12
12
|
<< { :name => :format, :type => :string } \
|
13
|
-
<< { :name => :ip, :type => :string
|
14
|
-
<< { :name => :timestamp, :type => :timestamp
|
13
|
+
<< { :name => :ip, :type => :string } \
|
14
|
+
<< { :name => :timestamp, :type => :timestamp } \
|
15
15
|
<< { :name => :method, :type => :string }
|
16
16
|
end
|
17
17
|
|
@@ -25,14 +25,14 @@ module RequestLogAnalyzer::FileFormat
|
|
25
25
|
line.teaser = /Rendered /
|
26
26
|
line.regexp = /Rendered (\w+(?:\/\w+)+) \((\d+\.\d+)ms\)/
|
27
27
|
line.captures << { :name => :render_file, :type => :string } \
|
28
|
-
<< { :name => :render_duration, :type => :msec }
|
28
|
+
<< { :name => :render_duration, :type => :duration, :unit => :msec }
|
29
29
|
end
|
30
30
|
|
31
31
|
# [4;36;1mUser Load (0.4ms)[0m [0;1mSELECT * FROM `users` WHERE (`users`.`id` = 18205844) [0m
|
32
32
|
line_definition :query_executed do |line|
|
33
33
|
line.regexp = /\s+(?:\e\[4;36;1m)?((?:\w+::)*\w+) Load \((\d+\.\d+)ms\)(?:\e\[0m)?\s+(?:\e\[0;1m)?(.+) (?:\e\[0m)?/
|
34
34
|
line.captures << { :name => :query_class, :type => :string } \
|
35
|
-
<< { :name => :query_duration, :type => :msec } \
|
35
|
+
<< { :name => :query_duration, :type => :duration, :unit => :msec } \
|
36
36
|
<< { :name => :query_sql, :type => :string }
|
37
37
|
end
|
38
38
|
|
@@ -40,7 +40,7 @@ module RequestLogAnalyzer::FileFormat
|
|
40
40
|
line_definition :query_cached do |line|
|
41
41
|
line.teaser = /\s+(?:\e\[4;35;1m)?CACHE \((\d+\.\d+)ms\)(?:\e\[0m)?\s+(?:\e\[0m)?(.+) (?:\e\[0m)?/
|
42
42
|
line.regexp = /\s+(?:\e\[4;35;1m)?CACHE \((\d+\.\d+)ms\)(?:\e\[0m)?\s+(?:\e\[0m)?(.+) (?:\e\[0m)?/
|
43
|
-
line.captures << { :name => :cached_duration, :type => :msec } \
|
43
|
+
line.captures << { :name => :cached_duration, :type => :duration, :unit => :msec } \
|
44
44
|
<< { :name => :cached_sql, :type => :string }
|
45
45
|
end
|
46
46
|
|
@@ -52,7 +52,7 @@ module RequestLogAnalyzer::FileFormat
|
|
52
52
|
<< { :name => :message, :type => :string } \
|
53
53
|
<< { :name => :line, :type => :integer } \
|
54
54
|
<< { :name => :file, :type => :string } \
|
55
|
-
<< { :name => :stack_trace, :type => :string
|
55
|
+
<< { :name => :stack_trace, :type => :string }
|
56
56
|
end
|
57
57
|
|
58
58
|
|
@@ -73,17 +73,17 @@ module RequestLogAnalyzer::FileFormat
|
|
73
73
|
line.teaser = /Completed in /
|
74
74
|
line.regexp = Regexp.new("(?:#{RAILS_21_COMPLETED}|#{RAILS_22_COMPLETED})")
|
75
75
|
|
76
|
-
line.captures << { :name => :duration, :type => :
|
77
|
-
<< { :name => :view, :type => :
|
78
|
-
<< { :name => :db, :type => :
|
76
|
+
line.captures << { :name => :duration, :type => :duration } \
|
77
|
+
<< { :name => :view, :type => :duration } \
|
78
|
+
<< { :name => :db, :type => :duration } \
|
79
79
|
<< { :name => :status, :type => :integer } \
|
80
|
-
<< { :name => :url, :type => :string
|
80
|
+
<< { :name => :url, :type => :string } # Old variant
|
81
81
|
|
82
|
-
line.captures << { :name => :duration, :type => :
|
83
|
-
<< { :name => :view, :type => :
|
84
|
-
<< { :name => :db, :type => :
|
82
|
+
line.captures << { :name => :duration, :type => :duration, :unit => :msec } \
|
83
|
+
<< { :name => :view, :type => :duration, :unit => :msec } \
|
84
|
+
<< { :name => :db, :type => :duration, :unit => :msec } \
|
85
85
|
<< { :name => :status, :type => :integer} \
|
86
|
-
<< { :name => :url, :type => :string
|
86
|
+
<< { :name => :url, :type => :string } # 2.2 variant
|
87
87
|
end
|
88
88
|
|
89
89
|
REQUEST_CATEGORIZER = Proc.new do |request|
|
@@ -93,20 +93,27 @@ module RequestLogAnalyzer::FileFormat
|
|
93
93
|
|
94
94
|
report do |analyze|
|
95
95
|
analyze.timespan :line_type => :processing
|
96
|
-
analyze.
|
97
|
-
analyze.
|
98
|
-
analyze.
|
99
|
-
analyze.
|
96
|
+
analyze.frequency :category => REQUEST_CATEGORIZER, :title => 'Top 20 hits', :amount => 20, :line_type => :processing
|
97
|
+
analyze.frequency :method, :title => 'HTTP methods'
|
98
|
+
analyze.frequency :status, :title => 'HTTP statuses returned'
|
99
|
+
analyze.frequency :category => lambda { |request| request =~ :cache_hit ? 'Cache hit' : 'No hit' }, :title => 'Rails action cache hits'
|
100
100
|
|
101
101
|
analyze.duration :duration, :category => REQUEST_CATEGORIZER, :title => "Request duration", :line_type => :completed
|
102
102
|
analyze.duration :view, :category => REQUEST_CATEGORIZER, :title => "Database time", :line_type => :completed
|
103
103
|
analyze.duration :db, :category => REQUEST_CATEGORIZER, :title => "View rendering time", :line_type => :completed
|
104
104
|
|
105
|
-
analyze.
|
105
|
+
analyze.frequency :category => REQUEST_CATEGORIZER, :title => 'Process blockers (> 1 sec duration)',
|
106
106
|
:if => lambda { |request| request[:duration] && request[:duration] > 1.0 }, :amount => 20
|
107
107
|
|
108
108
|
analyze.hourly_spread :line_type => :processing
|
109
|
-
analyze.
|
109
|
+
analyze.frequency :error, :title => 'Failed requests', :line_type => :failed, :amount => 20
|
110
110
|
end
|
111
|
+
|
112
|
+
class Request < RequestLogAnalyzer::Request
|
113
|
+
|
114
|
+
def convert_timestamp(value, definition)
|
115
|
+
value.gsub(/[^0-9]/)[0...14].to_i unless value.nil?
|
116
|
+
end
|
117
|
+
end
|
111
118
|
end
|
112
119
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module RequestLogAnalyzer::Filter
|
2
2
|
|
3
|
-
# Filter to
|
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
|
-
class
|
8
|
+
class Anonymize < Base
|
9
9
|
|
10
10
|
def prepare
|
11
11
|
end
|
@@ -22,9 +22,7 @@ module RequestLogAnalyzer::Filter
|
|
22
22
|
value * ((75 + rand(50)) / 100.0)
|
23
23
|
end
|
24
24
|
|
25
|
-
def filter(request)
|
26
|
-
return nil unless request
|
27
|
-
|
25
|
+
def filter(request)
|
28
26
|
request.attributes.each do |key, value|
|
29
27
|
if key == :ip
|
30
28
|
request.attributes[key] = generate_random_ip
|
@@ -27,13 +27,9 @@ module RequestLogAnalyzer::Filter
|
|
27
27
|
# Returns nil otherwise.
|
28
28
|
# <tt>request</tt> Request Object
|
29
29
|
def filter(request)
|
30
|
-
|
31
|
-
|
32
|
-
found_field = request.every(@field).any? { |value| @value === value }
|
33
|
-
|
30
|
+
found_field = request.every(@field).any? { |value| @value === value.to_s }
|
34
31
|
return nil if !found_field && @mode == :select
|
35
32
|
return nil if found_field && @mode == :reject
|
36
|
-
|
37
33
|
return request
|
38
34
|
end
|
39
35
|
end
|