request-log-analyzer 1.9.10 → 1.10.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/.gitignore +3 -1
- data/Gemfile +2 -0
- data/lib/request_log_analyzer.rb +1 -1
- data/lib/request_log_analyzer/file_format.rb +3 -1
- data/lib/request_log_analyzer/file_format/apache.rb +19 -28
- data/lib/request_log_analyzer/file_format/haproxy.rb +138 -0
- data/lib/request_log_analyzer/file_format/rails3.rb +1 -1
- data/lib/request_log_analyzer/file_format/w3c.rb +56 -0
- data/lib/request_log_analyzer/request.rb +7 -0
- data/request-log-analyzer.gemspec +4 -4
- data/spec/spec_helper.rb +3 -2
- data/spec/unit/file_format/apache_format_spec.rb +17 -0
- data/spec/unit/file_format/haproxy_format_spec.rb +84 -0
- data/spec/unit/file_format/postgresql_format_spec.rb +10 -19
- data/spec/unit/file_format/rails3_format_spec.rb +8 -2
- data/spec/unit/file_format/w3c_format_spec.rb +46 -0
- metadata +10 -3
data/.gitignore
CHANGED
data/Gemfile
ADDED
data/lib/request_log_analyzer.rb
CHANGED
@@ -13,7 +13,7 @@ module RequestLogAnalyzer
|
|
13
13
|
|
14
14
|
# The current version of request-log-analyzer.
|
15
15
|
# Do not change the value by hand; it will be updated automatically by the gem release script.
|
16
|
-
VERSION = "1.
|
16
|
+
VERSION = "1.10.0"
|
17
17
|
|
18
18
|
|
19
19
|
autoload :Controller, 'request_log_analyzer/controller'
|
@@ -13,6 +13,8 @@ module RequestLogAnalyzer::FileFormat
|
|
13
13
|
autoload :DelayedJob21, 'request_log_analyzer/file_format/delayed_job21'
|
14
14
|
autoload :Apache, 'request_log_analyzer/file_format/apache'
|
15
15
|
autoload :AmazonS3, 'request_log_analyzer/file_format/amazon_s3'
|
16
|
+
autoload :W3c, 'request_log_analyzer/file_format/w3c'
|
17
|
+
autoload :Haproxy, 'request_log_analyzer/file_format/haproxy'
|
16
18
|
|
17
19
|
# Loads a FileFormat::Base subclass instance.
|
18
20
|
# You can provide:
|
@@ -293,4 +295,4 @@ module RequestLogAnalyzer::FileFormat
|
|
293
295
|
return nil
|
294
296
|
end
|
295
297
|
end
|
296
|
-
end
|
298
|
+
end
|
@@ -30,20 +30,23 @@ module RequestLogAnalyzer::FileFormat
|
|
30
30
|
|
31
31
|
# A hash that defines how the log format directives should be parsed.
|
32
32
|
LOG_DIRECTIVES = {
|
33
|
-
'%' => { :regexp => '%', :captures => [] },
|
34
|
-
'h' => { :regexp => '([A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)+)', :captures => [{:name => :remote_host, :type => :string}] },
|
35
|
-
'a' => { :regexp => "(#{ip_address})", :captures => [{:name => :remote_ip, :type => :string}] },
|
36
|
-
'b' => { :regexp => '(\d+|-)', :captures => [{:name => :bytes_sent, :type => :traffic}] },
|
37
|
-
'c' => { :regexp => '(\+|\-|\X)', :captures => [{:name => :connection_status, :type => :integer}] },
|
38
|
-
'D' => { :regexp => '(\d+|-)', :captures => [{:name => :duration, :type => :duration, :unit => :musec}] },
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
'
|
43
|
-
'
|
44
|
-
'
|
45
|
-
'
|
46
|
-
|
33
|
+
'%' => { nil => { :regexp => '%', :captures => [] } },
|
34
|
+
'h' => { nil => { :regexp => '([A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)+)', :captures => [{:name => :remote_host, :type => :string}] } },
|
35
|
+
'a' => { nil => { :regexp => "(#{ip_address})", :captures => [{:name => :remote_ip, :type => :string}] } },
|
36
|
+
'b' => { nil => { :regexp => '(\d+|-)', :captures => [{:name => :bytes_sent, :type => :traffic}] } },
|
37
|
+
'c' => { nil => { :regexp => '(\+|\-|\X)', :captures => [{:name => :connection_status, :type => :integer}] } },
|
38
|
+
'D' => { nil => { :regexp => '(\d+|-)', :captures => [ {:name => :duration, :type => :duration, :unit => :musec }] },
|
39
|
+
'micro' => { :regexp => '(\d+|-)', :captures => [ {:name => :duration, :type => :duration, :unit => :musec }] },
|
40
|
+
'milli' => { :regexp => '(\d+|-)', :captures => [ {:name => :duration, :type => :duration, :unit => :msec }] }
|
41
|
+
},
|
42
|
+
'l' => { nil => { :regexp => '([\w-]+)', :captures => [{:name => :remote_logname, :type => :nillable_string}] } },
|
43
|
+
'T' => { nil => { :regexp => '((?:\d+(?:\.\d+))|-)', :captures => [{:name => :duration, :type => :duration, :unit => :sec}] } },
|
44
|
+
't' => { nil => { :regexp => "\\[(#{APACHE_TIMESTAMP})?\\]", :captures => [{:name => :timestamp, :type => :timestamp}] } },
|
45
|
+
's' => { nil => { :regexp => '(\d{3})', :captures => [{:name => :http_status, :type => :integer}] } },
|
46
|
+
'u' => { nil => { :regexp => '(\w+|-)', :captures => [{:name => :user, :type => :nillable_string}] } },
|
47
|
+
'U' => { nil => { :regexp => '(\/\S*)', :captures => [{:name => :path, :type => :string}] } },
|
48
|
+
'r' => { nil => { :regexp => '([A-Z]+) (\S+) HTTP\/(\d+(?:\.\d+)*)', :captures => [{:name => :http_method, :type => :string},
|
49
|
+
{:name => :path, :type => :path}, {:name => :http_version, :type => :string}]} },
|
47
50
|
'i' => { 'Referer' => { :regexp => '(\S+)', :captures => [{:name => :referer, :type => :nillable_string}] },
|
48
51
|
'User-agent' => { :regexp => '(.*)', :captures => [{:name => :user_agent, :type => :user_agent}] }
|
49
52
|
}
|
@@ -72,14 +75,13 @@ module RequestLogAnalyzer::FileFormat
|
|
72
75
|
|
73
76
|
if variable
|
74
77
|
# Check if we recognize the log directive
|
75
|
-
directive = LOG_DIRECTIVES[variable]
|
76
|
-
directive = directive[arg] if directive && arg
|
78
|
+
directive = LOG_DIRECTIVES[variable][arg] rescue nil
|
77
79
|
|
78
80
|
if directive
|
79
81
|
line_regexp << directive[:regexp] # Parse the value of the directive
|
80
82
|
captures += directive[:captures] # Add the directive's information to the captures
|
81
83
|
else
|
82
|
-
puts "%#{
|
84
|
+
puts "Apache log directive %#{arg}#{variable} is not yet supported by RLA, the field will be ignored."
|
83
85
|
line_regexp << '.*' # Just accept any input for this literal
|
84
86
|
end
|
85
87
|
end
|
@@ -126,22 +128,11 @@ module RequestLogAnalyzer::FileFormat
|
|
126
128
|
"#{value[7,4]}#{MONTHS[value[3,3]]}#{value[0,2]}#{value[12,2]}#{value[15,2]}#{value[18,2]}".to_i
|
127
129
|
end
|
128
130
|
|
129
|
-
# This function can be overridden to rewrite the path for better categorization in the
|
130
|
-
# reports.
|
131
|
-
def convert_path(value, definition)
|
132
|
-
value
|
133
|
-
end
|
134
|
-
|
135
131
|
# This function can be overridden to simplify the user agent string for better
|
136
132
|
# categorization in the reports
|
137
133
|
def convert_user_agent(value, definition)
|
138
134
|
value # TODO
|
139
135
|
end
|
140
|
-
|
141
|
-
# Make sure that the string '-' is parsed as a nil value.
|
142
|
-
def convert_nillable_string(value, definition)
|
143
|
-
value == '-' ? nil : value
|
144
|
-
end
|
145
136
|
end
|
146
137
|
end
|
147
138
|
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module RequestLogAnalyzer::FileFormat
|
2
|
+
|
3
|
+
class Haproxy < RequestLogAnalyzer::FileFormat::Base
|
4
|
+
|
5
|
+
extend CommonRegularExpressions
|
6
|
+
|
7
|
+
# Define line types
|
8
|
+
line_definition :haproxy do |line|
|
9
|
+
line.header = true
|
10
|
+
line.footer = true
|
11
|
+
|
12
|
+
line.regexp = %r{
|
13
|
+
(#{ip_address}):\d+\s # client_ip ':' client_port
|
14
|
+
\[(#{timestamp('%d/%b/%Y:%H:%M:%S')})\.\d{3}\]\s # '[' accept_date ']'
|
15
|
+
(\S+)\s # frontend_name
|
16
|
+
(\S+)\/(\S+)\s # backend_name '/' server_name
|
17
|
+
(\d+|-1)\/(\d+|-1)\/(\d+|-1)\/(\d+|-1)\/\+?(\d+)\s # Tq '/' Tw '/' Tc '/' Tr '/' Tt
|
18
|
+
(\d+)\s # status_code
|
19
|
+
\+?(\d+)\s # bytes_read
|
20
|
+
(\S+)\s # captured_request_cookie
|
21
|
+
(\S+)\s # captured_response_cookie
|
22
|
+
(\w|-)(\w|-)(\w|-)(\w|-)\s # termination_state
|
23
|
+
(\d+)\/(\d+)\/(\d+)\/(\d+)\/\+?(\d+)\s # actconn '/' feconn '/' beconn '/' srv_conn '/' retries
|
24
|
+
(\d+)\/(\d+)\s # srv_queue '/' backend_queue
|
25
|
+
(\S*)\s? # captured_request_headers
|
26
|
+
(\S*)\s? # captured_response_headers
|
27
|
+
"([^"]*)" # '"' http_request '"'
|
28
|
+
}x
|
29
|
+
|
30
|
+
line.capture(:client_ip).as(:string)
|
31
|
+
line.capture(:accept_date).as(:timestamp)
|
32
|
+
line.capture(:frontend_name).as(:string)
|
33
|
+
line.capture(:backend_name).as(:string)
|
34
|
+
line.capture(:server_name).as(:string)
|
35
|
+
line.capture(:tq).as(:nillable_duration, :unit => :msec)
|
36
|
+
line.capture(:tw).as(:nillable_duration, :unit => :msec)
|
37
|
+
line.capture(:tc).as(:nillable_duration, :unit => :msec)
|
38
|
+
line.capture(:tr).as(:nillable_duration, :unit => :msec)
|
39
|
+
line.capture(:tt).as(:duration, :unit => :msec)
|
40
|
+
line.capture(:status_code).as(:integer)
|
41
|
+
line.capture(:bytes_read).as(:traffic, :unit => :byte)
|
42
|
+
line.capture(:captured_request_cookie).as(:nillable_string)
|
43
|
+
line.capture(:captured_response_cookie).as(:nillable_string)
|
44
|
+
line.capture(:termination_event_code).as(:nillable_string)
|
45
|
+
line.capture(:terminated_session_state).as(:nillable_string)
|
46
|
+
line.capture(:clientside_persistence_cookie).as(:nillable_string)
|
47
|
+
line.capture(:serverside_persistence_cookie).as(:nillable_string)
|
48
|
+
line.capture(:actconn).as(:integer)
|
49
|
+
line.capture(:feconn).as(:integer)
|
50
|
+
line.capture(:beconn).as(:integer)
|
51
|
+
line.capture(:srv_conn).as(:integer)
|
52
|
+
line.capture(:retries).as(:integer)
|
53
|
+
line.capture(:srv_queue).as(:integer)
|
54
|
+
line.capture(:backend_queue).as(:integer)
|
55
|
+
line.capture(:captured_request_headers).as(:nillable_string)
|
56
|
+
line.capture(:captured_response_headers).as(:nillable_string)
|
57
|
+
line.capture(:http_request).as(:nillable_string)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Define the summary report
|
61
|
+
report do |analyze|
|
62
|
+
analyze.hourly_spread :field => :accept_date
|
63
|
+
|
64
|
+
analyze.frequency :client_ip,
|
65
|
+
:title => "Hits per IP"
|
66
|
+
|
67
|
+
analyze.frequency :frontend_name,
|
68
|
+
:title => "Hits per frontend service"
|
69
|
+
|
70
|
+
analyze.frequency :backend_name,
|
71
|
+
:title => "Hits per backend service"
|
72
|
+
|
73
|
+
analyze.frequency :server_name,
|
74
|
+
:title => "Hits per backend server"
|
75
|
+
|
76
|
+
analyze.frequency :status_code,
|
77
|
+
:title => "HTTP response code frequency"
|
78
|
+
|
79
|
+
analyze.frequency :http_request,
|
80
|
+
:title => "Most popular requests"
|
81
|
+
|
82
|
+
analyze.frequency :http_request,
|
83
|
+
:title => "Most frequent HTTP 40x errors",
|
84
|
+
:category => lambda { |r| "#{r[:http_request]}"},
|
85
|
+
:if => lambda { |r| r[:status_code] >= 400 and r[:status_code] <= 417 }
|
86
|
+
|
87
|
+
analyze.frequency :http_request,
|
88
|
+
:title => "Most frequent HTTP 50x errors",
|
89
|
+
:category => lambda { |r| "#{r[:http_request]}"},
|
90
|
+
:if => lambda { |r| r[:status_code] >= 500 and r[:status_code] <= 505 }
|
91
|
+
|
92
|
+
analyze.traffic :bytes_read,
|
93
|
+
:title => "Traffic per frontend service",
|
94
|
+
:category => lambda { |r| "#{r[:frontend_name]}"}
|
95
|
+
|
96
|
+
analyze.traffic :bytes_read,
|
97
|
+
:title => "Traffic per backend service",
|
98
|
+
:category => lambda { |r| "#{r[:backend_name]}"}
|
99
|
+
|
100
|
+
analyze.traffic :bytes_read,
|
101
|
+
:title => "Traffic per backend server",
|
102
|
+
:category => lambda { |r| "#{r[:server_name]}"}
|
103
|
+
|
104
|
+
analyze.duration :tr,
|
105
|
+
:title => "Time waiting for backend response",
|
106
|
+
:category => lambda { |r| "#{r[:http_request]}"}
|
107
|
+
|
108
|
+
analyze.duration :tt,
|
109
|
+
:title => "Total time spent on request",
|
110
|
+
:category => lambda { |r| "#{r[:http_request]}"}
|
111
|
+
end
|
112
|
+
|
113
|
+
# Define a custom Request class for the HAProxy file format to speed up
|
114
|
+
# timestamp handling. Shamelessly copied from apache.rb
|
115
|
+
class Request < RequestLogAnalyzer::Request
|
116
|
+
|
117
|
+
MONTHS = {'Jan' => '01', 'Feb' => '02', 'Mar' => '03', 'Apr' => '04', 'May' => '05', 'Jun' => '06',
|
118
|
+
'Jul' => '07', 'Aug' => '08', 'Sep' => '09', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12' }
|
119
|
+
|
120
|
+
# Do not use DateTime.parse, but parse the timestamp ourselves to return
|
121
|
+
# a integer to speed up parsing.
|
122
|
+
def convert_timestamp(value, definition)
|
123
|
+
"#{value[7,4]}#{MONTHS[value[3,3]]}#{value[0,2]}#{value[12,2]}#{value[15,2]}#{value[18,2]}".to_i
|
124
|
+
end
|
125
|
+
|
126
|
+
# Make sure that the strings '-' or '{}' or '' are parsed as a nil value.
|
127
|
+
def convert_nillable_string(value, definition)
|
128
|
+
value =~ /-|\{\}|^$/ ? nil : value
|
129
|
+
end
|
130
|
+
|
131
|
+
# Make sure that -1 is parsed as a nil value.
|
132
|
+
def convert_nillable_duration(value, definition)
|
133
|
+
value == '-1' ? nil : convert_duration(value, definition)
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -36,7 +36,7 @@ module RequestLogAnalyzer::FileFormat
|
|
36
36
|
line_definition :completed do |line|
|
37
37
|
line.footer = true
|
38
38
|
line.teaser = /Completed /
|
39
|
-
line.regexp = /Completed (\d+)? .*in (\d+(?:\.\d+)?)ms(?:[^\(]*\(Views: (\d+(?:\.\d+)?)ms .* ActiveRecord: (\d+(?:\.\d+)?)ms
|
39
|
+
line.regexp = /Completed (\d+)? .*in (\d+(?:\.\d+)?)ms(?:[^\(]*\(Views: (\d+(?:\.\d+)?)ms .* ActiveRecord: (\d+(?:\.\d+)?)ms.*\))?/
|
40
40
|
|
41
41
|
line.capture(:status).as(:integer)
|
42
42
|
line.capture(:duration).as(:duration, :unit => :msec)
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module RequestLogAnalyzer::FileFormat
|
2
|
+
|
3
|
+
# FileFormat for W3C access logs.
|
4
|
+
class W3c < Base
|
5
|
+
|
6
|
+
extend CommonRegularExpressions
|
7
|
+
|
8
|
+
line_definition :access do |line|
|
9
|
+
line.header = true
|
10
|
+
line.footer = true
|
11
|
+
line.regexp = /^(#{timestamp('%Y-%m-%d %H:%M:%S')}) (#{ip_address}) (.*) (#{ip_address}) (\d+) (\w+) ([\w|\/|.]+) \- (\d+) (\d+) (\d+) (\d+) (.*) (\S+)/
|
12
|
+
|
13
|
+
line.capture(:timestamp).as(:timestamp)
|
14
|
+
line.capture(:remote_ip)
|
15
|
+
line.capture(:username).as(:nillable_string)
|
16
|
+
line.capture(:local_ip)
|
17
|
+
line.capture(:port).as(:integer)
|
18
|
+
line.capture(:method)
|
19
|
+
line.capture(:path).as(:path)
|
20
|
+
line.capture(:http_status).as(:integer)
|
21
|
+
line.capture(:bytes_sent).as(:traffic, :unit => :byte)
|
22
|
+
line.capture(:bytes_received).as(:traffic, :unit => :byte)
|
23
|
+
line.capture(:duration).as(:duration, :unit => :msec)
|
24
|
+
line.capture(:user_agent)
|
25
|
+
line.capture(:referer)
|
26
|
+
end
|
27
|
+
|
28
|
+
report do |analyze|
|
29
|
+
analyze.timespan
|
30
|
+
analyze.hourly_spread
|
31
|
+
|
32
|
+
analyze.frequency :category => :http_method, :title => "HTTP methods"
|
33
|
+
analyze.frequency :category => :http_status, :title => "HTTP statuses"
|
34
|
+
|
35
|
+
analyze.frequency :category => :path, :title => "Most popular URIs"
|
36
|
+
|
37
|
+
analyze.frequency :category => :user_agent, :title => "User agents"
|
38
|
+
analyze.frequency :category => :referer, :title => "Referers"
|
39
|
+
|
40
|
+
analyze.duration :duration => :duration, :category => :path, :title => 'Request duration'
|
41
|
+
analyze.traffic :traffic => :bytes_sent, :category => :path, :title => 'Traffic out'
|
42
|
+
analyze.traffic :traffic => :bytes_received, :category => :path, :title => 'Traffic in'
|
43
|
+
end
|
44
|
+
|
45
|
+
class Request < RequestLogAnalyzer::Request
|
46
|
+
# Do not use DateTime.parse, but parse the timestamp ourselves to return a integer
|
47
|
+
# to speed up parsing.
|
48
|
+
def convert_timestamp(value, definition)
|
49
|
+
"#{value[0,4]}#{value[5,2]}#{value[8,2]}#{value[11,2]}#{value[14,2]}#{value[17,2]}".to_i
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -27,6 +27,13 @@ module RequestLogAnalyzer
|
|
27
27
|
def convert_integer(value, capture_definition); value.to_i; end
|
28
28
|
def convert_sym(value, capture_definition); value.to_sym; end
|
29
29
|
def convert_symbol(value, capture_definition); value.to_sym; end
|
30
|
+
def convert_nillable_string(value, definition); value == '-' ? nil : value ; end
|
31
|
+
|
32
|
+
# This function can be overridden to rewrite the path for better categorization in the
|
33
|
+
# reports.
|
34
|
+
def convert_path(value, definition)
|
35
|
+
value
|
36
|
+
end
|
30
37
|
|
31
38
|
# Converts :eval field, which should evaluate to a hash.
|
32
39
|
def convert_eval(value, capture_definition)
|
@@ -2,8 +2,8 @@ Gem::Specification.new do |s|
|
|
2
2
|
s.name = "request-log-analyzer"
|
3
3
|
|
4
4
|
# Do not set the version and date field manually, this is done by the release script
|
5
|
-
s.version = "1.
|
6
|
-
s.date = "2011-
|
5
|
+
s.version = "1.10.0"
|
6
|
+
s.date = "2011-02-26"
|
7
7
|
|
8
8
|
s.rubyforge_project = 'r-l-a'
|
9
9
|
|
@@ -39,6 +39,6 @@ Gem::Specification.new do |s|
|
|
39
39
|
|
40
40
|
# The files and test_files directives are set automatically by the release script.
|
41
41
|
# Do not change them by hand, but make sure to add the files to the git repository.
|
42
|
-
s.files = %w(.gitignore DESIGN.rdoc LICENSE README.rdoc Rakefile bin/request-log-analyzer lib/cli/command_line_arguments.rb lib/cli/database_console.rb lib/cli/database_console_init.rb lib/cli/progressbar.rb lib/cli/tools.rb lib/mixins/gets_memory_protection.rb lib/request_log_analyzer.rb lib/request_log_analyzer/aggregator.rb lib/request_log_analyzer/aggregator/database_inserter.rb lib/request_log_analyzer/aggregator/echo.rb lib/request_log_analyzer/aggregator/summarizer.rb lib/request_log_analyzer/controller.rb lib/request_log_analyzer/database.rb lib/request_log_analyzer/database/base.rb lib/request_log_analyzer/database/connection.rb lib/request_log_analyzer/database/request.rb lib/request_log_analyzer/database/source.rb lib/request_log_analyzer/database/warning.rb lib/request_log_analyzer/file_format.rb lib/request_log_analyzer/file_format/amazon_s3.rb lib/request_log_analyzer/file_format/apache.rb lib/request_log_analyzer/file_format/delayed_job.rb lib/request_log_analyzer/file_format/delayed_job2.rb lib/request_log_analyzer/file_format/delayed_job21.rb lib/request_log_analyzer/file_format/merb.rb lib/request_log_analyzer/file_format/mysql.rb lib/request_log_analyzer/file_format/oink.rb lib/request_log_analyzer/file_format/postgresql.rb lib/request_log_analyzer/file_format/rack.rb lib/request_log_analyzer/file_format/rails.rb lib/request_log_analyzer/file_format/rails3.rb lib/request_log_analyzer/file_format/rails_development.rb lib/request_log_analyzer/filter.rb lib/request_log_analyzer/filter/anonymize.rb lib/request_log_analyzer/filter/field.rb lib/request_log_analyzer/filter/timespan.rb lib/request_log_analyzer/line_definition.rb lib/request_log_analyzer/log_processor.rb lib/request_log_analyzer/mailer.rb lib/request_log_analyzer/output.rb lib/request_log_analyzer/output/fancy_html.rb lib/request_log_analyzer/output/fixed_width.rb lib/request_log_analyzer/output/html.rb lib/request_log_analyzer/request.rb lib/request_log_analyzer/source.rb lib/request_log_analyzer/source/database_loader.rb lib/request_log_analyzer/source/log_parser.rb lib/request_log_analyzer/tracker.rb lib/request_log_analyzer/tracker/duration.rb lib/request_log_analyzer/tracker/frequency.rb lib/request_log_analyzer/tracker/hourly_spread.rb lib/request_log_analyzer/tracker/numeric_value.rb lib/request_log_analyzer/tracker/timespan.rb lib/request_log_analyzer/tracker/traffic.rb request-log-analyzer.gemspec spec/database.yml spec/fixtures/apache_combined.log spec/fixtures/apache_common.log spec/fixtures/decompression.log spec/fixtures/decompression.log.bz2 spec/fixtures/decompression.log.gz spec/fixtures/decompression.log.zip spec/fixtures/decompression.tar.gz spec/fixtures/decompression.tgz spec/fixtures/header_and_footer.log spec/fixtures/merb.log spec/fixtures/merb_prefixed.log spec/fixtures/multiple_files_1.log spec/fixtures/multiple_files_2.log spec/fixtures/mysql_slow_query.log spec/fixtures/oink_22.log spec/fixtures/oink_22_failure.log spec/fixtures/postgresql.log spec/fixtures/rails.db spec/fixtures/rails_1x.log spec/fixtures/rails_22.log spec/fixtures/rails_22_cached.log spec/fixtures/rails_unordered.log spec/fixtures/sinatra.log spec/fixtures/syslog_1x.log spec/fixtures/test_file_format.log spec/fixtures/test_language_combined.log spec/fixtures/test_order.log spec/integration/command_line_usage_spec.rb spec/integration/mailer_spec.rb spec/integration/munin_plugins_rails_spec.rb spec/integration/scout_spec.rb spec/lib/helpers.rb spec/lib/macros.rb spec/lib/matchers.rb spec/lib/mocks.rb spec/lib/testing_format.rb spec/spec_helper.rb spec/unit/aggregator/database_inserter_spec.rb spec/unit/aggregator/summarizer_spec.rb spec/unit/controller/controller_spec.rb spec/unit/controller/log_processor_spec.rb spec/unit/database/base_class_spec.rb spec/unit/database/connection_spec.rb spec/unit/database/database_spec.rb spec/unit/file_format/amazon_s3_format_spec.rb spec/unit/file_format/apache_format_spec.rb spec/unit/file_format/common_regular_expressions_spec.rb spec/unit/file_format/delayed_job21_format_spec.rb spec/unit/file_format/delayed_job2_format_spec.rb spec/unit/file_format/delayed_job_format_spec.rb spec/unit/file_format/file_format_api_spec.rb spec/unit/file_format/format_autodetection_spec.rb spec/unit/file_format/line_definition_spec.rb spec/unit/file_format/merb_format_spec.rb spec/unit/file_format/mysql_format_spec.rb spec/unit/file_format/oink_format_spec.rb spec/unit/file_format/postgresql_format_spec.rb spec/unit/file_format/rack_format_spec.rb spec/unit/file_format/rails3_format_spec.rb spec/unit/file_format/rails_format_spec.rb spec/unit/filter/anonymize_filter_spec.rb spec/unit/filter/field_filter_spec.rb spec/unit/filter/filter_spec.rb spec/unit/filter/timespan_filter_spec.rb spec/unit/mailer_spec.rb spec/unit/request_spec.rb spec/unit/source/log_parser_spec.rb spec/unit/tracker/duration_tracker_spec.rb spec/unit/tracker/frequency_tracker_spec.rb spec/unit/tracker/hourly_spread_spec.rb spec/unit/tracker/numeric_value_tracker_spec.rb spec/unit/tracker/timespan_tracker_spec.rb spec/unit/tracker/tracker_api_spec.rb spec/unit/tracker/traffic_tracker_spec.rb tasks/github-gem.rake tasks/request_log_analyzer.rake)
|
43
|
-
s.test_files = %w(spec/integration/command_line_usage_spec.rb spec/integration/mailer_spec.rb spec/integration/munin_plugins_rails_spec.rb spec/integration/scout_spec.rb spec/unit/aggregator/database_inserter_spec.rb spec/unit/aggregator/summarizer_spec.rb spec/unit/controller/controller_spec.rb spec/unit/controller/log_processor_spec.rb spec/unit/database/base_class_spec.rb spec/unit/database/connection_spec.rb spec/unit/database/database_spec.rb spec/unit/file_format/amazon_s3_format_spec.rb spec/unit/file_format/apache_format_spec.rb spec/unit/file_format/common_regular_expressions_spec.rb spec/unit/file_format/delayed_job21_format_spec.rb spec/unit/file_format/delayed_job2_format_spec.rb spec/unit/file_format/delayed_job_format_spec.rb spec/unit/file_format/file_format_api_spec.rb spec/unit/file_format/format_autodetection_spec.rb spec/unit/file_format/line_definition_spec.rb spec/unit/file_format/merb_format_spec.rb spec/unit/file_format/mysql_format_spec.rb spec/unit/file_format/oink_format_spec.rb spec/unit/file_format/postgresql_format_spec.rb spec/unit/file_format/rack_format_spec.rb spec/unit/file_format/rails3_format_spec.rb spec/unit/file_format/rails_format_spec.rb spec/unit/filter/anonymize_filter_spec.rb spec/unit/filter/field_filter_spec.rb spec/unit/filter/filter_spec.rb spec/unit/filter/timespan_filter_spec.rb spec/unit/mailer_spec.rb spec/unit/request_spec.rb spec/unit/source/log_parser_spec.rb spec/unit/tracker/duration_tracker_spec.rb spec/unit/tracker/frequency_tracker_spec.rb spec/unit/tracker/hourly_spread_spec.rb spec/unit/tracker/numeric_value_tracker_spec.rb spec/unit/tracker/timespan_tracker_spec.rb spec/unit/tracker/tracker_api_spec.rb spec/unit/tracker/traffic_tracker_spec.rb)
|
42
|
+
s.files = %w(.gitignore DESIGN.rdoc Gemfile LICENSE README.rdoc Rakefile bin/request-log-analyzer lib/cli/command_line_arguments.rb lib/cli/database_console.rb lib/cli/database_console_init.rb lib/cli/progressbar.rb lib/cli/tools.rb lib/mixins/gets_memory_protection.rb lib/request_log_analyzer.rb lib/request_log_analyzer/aggregator.rb lib/request_log_analyzer/aggregator/database_inserter.rb lib/request_log_analyzer/aggregator/echo.rb lib/request_log_analyzer/aggregator/summarizer.rb lib/request_log_analyzer/controller.rb lib/request_log_analyzer/database.rb lib/request_log_analyzer/database/base.rb lib/request_log_analyzer/database/connection.rb lib/request_log_analyzer/database/request.rb lib/request_log_analyzer/database/source.rb lib/request_log_analyzer/database/warning.rb lib/request_log_analyzer/file_format.rb lib/request_log_analyzer/file_format/amazon_s3.rb lib/request_log_analyzer/file_format/apache.rb lib/request_log_analyzer/file_format/delayed_job.rb lib/request_log_analyzer/file_format/delayed_job2.rb lib/request_log_analyzer/file_format/delayed_job21.rb lib/request_log_analyzer/file_format/haproxy.rb lib/request_log_analyzer/file_format/merb.rb lib/request_log_analyzer/file_format/mysql.rb lib/request_log_analyzer/file_format/oink.rb lib/request_log_analyzer/file_format/postgresql.rb lib/request_log_analyzer/file_format/rack.rb lib/request_log_analyzer/file_format/rails.rb lib/request_log_analyzer/file_format/rails3.rb lib/request_log_analyzer/file_format/rails_development.rb lib/request_log_analyzer/file_format/w3c.rb lib/request_log_analyzer/filter.rb lib/request_log_analyzer/filter/anonymize.rb lib/request_log_analyzer/filter/field.rb lib/request_log_analyzer/filter/timespan.rb lib/request_log_analyzer/line_definition.rb lib/request_log_analyzer/log_processor.rb lib/request_log_analyzer/mailer.rb lib/request_log_analyzer/output.rb lib/request_log_analyzer/output/fancy_html.rb lib/request_log_analyzer/output/fixed_width.rb lib/request_log_analyzer/output/html.rb lib/request_log_analyzer/request.rb lib/request_log_analyzer/source.rb lib/request_log_analyzer/source/database_loader.rb lib/request_log_analyzer/source/log_parser.rb lib/request_log_analyzer/tracker.rb lib/request_log_analyzer/tracker/duration.rb lib/request_log_analyzer/tracker/frequency.rb lib/request_log_analyzer/tracker/hourly_spread.rb lib/request_log_analyzer/tracker/numeric_value.rb lib/request_log_analyzer/tracker/timespan.rb lib/request_log_analyzer/tracker/traffic.rb request-log-analyzer.gemspec spec/database.yml spec/fixtures/apache_combined.log spec/fixtures/apache_common.log spec/fixtures/decompression.log spec/fixtures/decompression.log.bz2 spec/fixtures/decompression.log.gz spec/fixtures/decompression.log.zip spec/fixtures/decompression.tar.gz spec/fixtures/decompression.tgz spec/fixtures/header_and_footer.log spec/fixtures/merb.log spec/fixtures/merb_prefixed.log spec/fixtures/multiple_files_1.log spec/fixtures/multiple_files_2.log spec/fixtures/mysql_slow_query.log spec/fixtures/oink_22.log spec/fixtures/oink_22_failure.log spec/fixtures/postgresql.log spec/fixtures/rails.db spec/fixtures/rails_1x.log spec/fixtures/rails_22.log spec/fixtures/rails_22_cached.log spec/fixtures/rails_unordered.log spec/fixtures/sinatra.log spec/fixtures/syslog_1x.log spec/fixtures/test_file_format.log spec/fixtures/test_language_combined.log spec/fixtures/test_order.log spec/integration/command_line_usage_spec.rb spec/integration/mailer_spec.rb spec/integration/munin_plugins_rails_spec.rb spec/integration/scout_spec.rb spec/lib/helpers.rb spec/lib/macros.rb spec/lib/matchers.rb spec/lib/mocks.rb spec/lib/testing_format.rb spec/spec_helper.rb spec/unit/aggregator/database_inserter_spec.rb spec/unit/aggregator/summarizer_spec.rb spec/unit/controller/controller_spec.rb spec/unit/controller/log_processor_spec.rb spec/unit/database/base_class_spec.rb spec/unit/database/connection_spec.rb spec/unit/database/database_spec.rb spec/unit/file_format/amazon_s3_format_spec.rb spec/unit/file_format/apache_format_spec.rb spec/unit/file_format/common_regular_expressions_spec.rb spec/unit/file_format/delayed_job21_format_spec.rb spec/unit/file_format/delayed_job2_format_spec.rb spec/unit/file_format/delayed_job_format_spec.rb spec/unit/file_format/file_format_api_spec.rb spec/unit/file_format/format_autodetection_spec.rb spec/unit/file_format/haproxy_format_spec.rb spec/unit/file_format/line_definition_spec.rb spec/unit/file_format/merb_format_spec.rb spec/unit/file_format/mysql_format_spec.rb spec/unit/file_format/oink_format_spec.rb spec/unit/file_format/postgresql_format_spec.rb spec/unit/file_format/rack_format_spec.rb spec/unit/file_format/rails3_format_spec.rb spec/unit/file_format/rails_format_spec.rb spec/unit/file_format/w3c_format_spec.rb spec/unit/filter/anonymize_filter_spec.rb spec/unit/filter/field_filter_spec.rb spec/unit/filter/filter_spec.rb spec/unit/filter/timespan_filter_spec.rb spec/unit/mailer_spec.rb spec/unit/request_spec.rb spec/unit/source/log_parser_spec.rb spec/unit/tracker/duration_tracker_spec.rb spec/unit/tracker/frequency_tracker_spec.rb spec/unit/tracker/hourly_spread_spec.rb spec/unit/tracker/numeric_value_tracker_spec.rb spec/unit/tracker/timespan_tracker_spec.rb spec/unit/tracker/tracker_api_spec.rb spec/unit/tracker/traffic_tracker_spec.rb tasks/github-gem.rake tasks/request_log_analyzer.rake)
|
43
|
+
s.test_files = %w(spec/integration/command_line_usage_spec.rb spec/integration/mailer_spec.rb spec/integration/munin_plugins_rails_spec.rb spec/integration/scout_spec.rb spec/unit/aggregator/database_inserter_spec.rb spec/unit/aggregator/summarizer_spec.rb spec/unit/controller/controller_spec.rb spec/unit/controller/log_processor_spec.rb spec/unit/database/base_class_spec.rb spec/unit/database/connection_spec.rb spec/unit/database/database_spec.rb spec/unit/file_format/amazon_s3_format_spec.rb spec/unit/file_format/apache_format_spec.rb spec/unit/file_format/common_regular_expressions_spec.rb spec/unit/file_format/delayed_job21_format_spec.rb spec/unit/file_format/delayed_job2_format_spec.rb spec/unit/file_format/delayed_job_format_spec.rb spec/unit/file_format/file_format_api_spec.rb spec/unit/file_format/format_autodetection_spec.rb spec/unit/file_format/haproxy_format_spec.rb spec/unit/file_format/line_definition_spec.rb spec/unit/file_format/merb_format_spec.rb spec/unit/file_format/mysql_format_spec.rb spec/unit/file_format/oink_format_spec.rb spec/unit/file_format/postgresql_format_spec.rb spec/unit/file_format/rack_format_spec.rb spec/unit/file_format/rails3_format_spec.rb spec/unit/file_format/rails_format_spec.rb spec/unit/file_format/w3c_format_spec.rb spec/unit/filter/anonymize_filter_spec.rb spec/unit/filter/field_filter_spec.rb spec/unit/filter/filter_spec.rb spec/unit/filter/timespan_filter_spec.rb spec/unit/mailer_spec.rb spec/unit/request_spec.rb spec/unit/source/log_parser_spec.rb spec/unit/tracker/duration_tracker_spec.rb spec/unit/tracker/frequency_tracker_spec.rb spec/unit/tracker/hourly_spread_spec.rb spec/unit/tracker/numeric_value_tracker_spec.rb spec/unit/tracker/timespan_tracker_spec.rb spec/unit/tracker/tracker_api_spec.rb spec/unit/tracker/traffic_tracker_spec.rb)
|
44
44
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -28,6 +28,23 @@ describe RequestLogAnalyzer::FileFormat::Apache do
|
|
28
28
|
@line_definition.captures?(:duration).should be_true
|
29
29
|
end
|
30
30
|
end
|
31
|
+
|
32
|
+
describe '.access_line_definition' do
|
33
|
+
it "should parse values in microseconds when no argument is given to %D" do
|
34
|
+
format = RequestLogAnalyzer::FileFormat::Apache.create('%D')
|
35
|
+
format.should parse_line('12345').and_capture(:duration => 0.012345)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should parse values in microseconds when micro is given as argument to %D" do
|
39
|
+
format = RequestLogAnalyzer::FileFormat::Apache.create('%{micro}D')
|
40
|
+
format.should parse_line('12345').and_capture(:duration => 0.012345)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should parse values in microseconds when micro is given as argument to %D" do
|
44
|
+
format = RequestLogAnalyzer::FileFormat::Apache.create('%{milli}D')
|
45
|
+
format.should parse_line('12345').and_capture(:duration => 12.345)
|
46
|
+
end
|
47
|
+
end
|
31
48
|
|
32
49
|
describe '.create' do
|
33
50
|
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RequestLogAnalyzer::FileFormat::Haproxy do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@file_format = RequestLogAnalyzer::FileFormat.load(:haproxy)
|
7
|
+
@log_parser = RequestLogAnalyzer::Source::LogParser.new(@file_format)
|
8
|
+
@sample1 = 'Feb 6 12:14:14 localhost haproxy[14389]: 10.0.1.2:33317 [06/Feb/2009:12:14:14.655] http-in static/srv1 10/0/30/69/109 200 2750 - - ---- 1/1/1/1/0 0/0 {1wt.eu} {} "GET /index.html HTTP/1.1"'
|
9
|
+
@sample2 = 'haproxy[18113]: 127.0.0.1:34549 [15/Oct/2003:15:19:06.103] px-http px-http/<NOSRV> -1/-1/-1/-1/+50001 408 +2750 - - cR-- 2/2/2/0/+2 0/0 ""'
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should be a valid file format" do
|
13
|
+
@file_format.should be_valid
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should parse access lines and capture all of its fields" do
|
17
|
+
@file_format.should have_line_definition(:haproxy).capturing(:client_ip, :accept_date, :frontend_name, :backend_name, :server_name, :tq, :tw, :tc, :tr, :tt, :status_code, :bytes_read, :captured_request_cookie, :captured_response_cookie, :termination_event_code, :terminated_session_state, :clientside_persistence_cookie, :serverside_persistence_cookie, :actconn, :feconn, :beconn, :srv_conn, :retries, :srv_queue, :backend_queue, :captured_request_headers, :captured_response_headers, :http_request)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should match the sample line" do
|
21
|
+
@file_format.parse_line(@sample1).should include(:line_definition, :captures)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should not match a nonsense line" do
|
25
|
+
@file_format.parse_line('dsadasdas dsaadsads dsaadsads').should be_nil
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should parse and convert the sample fields correctly" do
|
29
|
+
@log_parser.parse_io(StringIO.new(@sample1)) do |request|
|
30
|
+
request[:client_ip].should == '10.0.1.2'
|
31
|
+
request[:accept_date].should == 20090206121414
|
32
|
+
request[:frontend_name].should == 'http-in'
|
33
|
+
request[:backend_name].should == 'static'
|
34
|
+
request[:server_name].should == 'srv1'
|
35
|
+
request[:tq].should == 0.010
|
36
|
+
request[:tw].should == 0.000
|
37
|
+
request[:tc].should == 0.030
|
38
|
+
request[:tr].should == 0.069
|
39
|
+
request[:tt].should == 0.109
|
40
|
+
request[:status_code].should == 200
|
41
|
+
request[:bytes_read].should == 2750
|
42
|
+
request[:captured_request_cookie].should == nil
|
43
|
+
request[:captured_response_cookie].should == nil
|
44
|
+
request[:termination_event_code].should == nil
|
45
|
+
request[:terminated_session_state].should == nil
|
46
|
+
request[:clientside_persistence_cookie].should == nil
|
47
|
+
request[:serverside_persistence_cookie].should == nil
|
48
|
+
request[:actconn].should == 1
|
49
|
+
request[:feconn].should == 1
|
50
|
+
request[:beconn].should == 1
|
51
|
+
request[:srv_conn].should == 1
|
52
|
+
request[:retries].should == 0
|
53
|
+
request[:srv_queue].should == 0
|
54
|
+
request[:backend_queue].should == 0
|
55
|
+
request[:captured_request_headers].should == '{1wt.eu}'
|
56
|
+
request[:captured_response_headers].should == nil
|
57
|
+
request[:http_request].should == 'GET /index.html HTTP/1.1'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should parse and convert edge case sample fields correctly" do
|
62
|
+
@log_parser.parse_io(StringIO.new(@sample2)) do |request|
|
63
|
+
request[:accept_date].should == 20031015151906
|
64
|
+
request[:server_name].should == '<NOSRV>'
|
65
|
+
request[:tq].should == nil
|
66
|
+
request[:tw].should == nil
|
67
|
+
request[:tc].should == nil
|
68
|
+
request[:tr].should == nil
|
69
|
+
request[:tt].should == 50.001
|
70
|
+
request[:bytes_read].should == 2750
|
71
|
+
request[:captured_request_cookie].should == nil
|
72
|
+
request[:captured_response_cookie].should == nil
|
73
|
+
request[:termination_event_code].should == 'c'
|
74
|
+
request[:terminated_session_state].should == 'R'
|
75
|
+
request[:clientside_persistence_cookie].should == nil
|
76
|
+
request[:serverside_persistence_cookie].should == nil
|
77
|
+
request[:retries].should == 2
|
78
|
+
request[:captured_request_headers].should == nil
|
79
|
+
request[:captured_response_headers].should == nil
|
80
|
+
request[:http_request].should == nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -2,36 +2,29 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe RequestLogAnalyzer::FileFormat::Postgresql do
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
subject { RequestLogAnalyzer::FileFormat.load(:Postgresql) }
|
6
|
+
let(:log_parser) { RequestLogAnalyzer::Source::LogParser.new(subject) }
|
7
|
+
|
8
|
+
it { should be_valid }
|
8
9
|
|
9
10
|
describe '#parse_line' do
|
10
|
-
before(:each) do
|
11
|
-
@file_format = RequestLogAnalyzer::FileFormat.load(:Postgresql)
|
12
|
-
end
|
13
|
-
|
14
11
|
it "should parse a :query line correctly" do
|
15
12
|
line = '2010-10-10 13:52:07 GMT [38747]: [33-1] LOG: 00000: duration: 0.710 ms statement: SELECT * FROM "delayed_jobs"'
|
16
|
-
|
13
|
+
subject.should parse_line(line).as(:query).and_capture(:timestamp => 20101010135207, :query_fragment => 'SELECT * FROM "delayed_jobs"')
|
17
14
|
end
|
18
15
|
|
19
16
|
it "should parse a :query_fragment line correctly" do
|
20
17
|
line = ' ("failed_at", "locked_by", "created_at", "handler", "updated_at", "priority", "run_at", "attempts", "locked_at",'
|
21
|
-
|
18
|
+
subject.should parse_line(line).as(:query_fragment).and_capture(:query_fragment => '("failed_at", "locked_by", "created_at", "handler", "updated_at", "priority", "run_at", "attempts", "locked_at",')
|
22
19
|
end
|
23
20
|
|
24
21
|
it "should parse a :query line correctly" do
|
25
22
|
line = '2010-10-10 13:52:07 GMT [38747]: [33-1] LOG: 00000: duration: 0.710 ms statement: SELECT * FROM "delayed_jobs"'
|
26
|
-
|
27
|
-
end
|
23
|
+
subject.should parse_line(line).as(:query).and_capture(:query_time => 0.710)
|
24
|
+
end
|
28
25
|
end
|
29
26
|
|
30
27
|
describe '#parse_io' do
|
31
|
-
before(:each) do
|
32
|
-
@log_parser = RequestLogAnalyzer::Source::LogParser.new(RequestLogAnalyzer::FileFormat.load(:postgresql))
|
33
|
-
end
|
34
|
-
|
35
28
|
it "should parse a multiline query entry correctly" do
|
36
29
|
fixture = <<-EOS
|
37
30
|
2010-10-10 15:00:02 GMT [38747]: [1669-1] LOG: 00000: duration: 0.195 ms statement: INSERT INTO "delayed_jobs" ("failed_at", "locked_by", "created_at", "handler", "updated_at", "priority", "run_at", "attempts", "locked_at", "last_error") VALUES(NULL, NULL, '2010-10-10 15:00:02.159884', E'--- !ruby/object:RuntheChooChootrain {}
|
@@ -40,13 +33,11 @@ describe RequestLogAnalyzer::FileFormat::Postgresql do
|
|
40
33
|
EOS
|
41
34
|
|
42
35
|
request_counter.should_receive(:hit!).exactly(1).times
|
43
|
-
|
44
|
-
|
36
|
+
log_parser.should_not_receive(:warn)
|
37
|
+
log_parser.parse_io(StringIO.new(fixture)) do |request|
|
45
38
|
request_counter.hit! if request.kind_of?(RequestLogAnalyzer::FileFormat::Postgresql::Request) && request.completed?
|
46
39
|
request[:query].should == 'INSERT INTO delayed_jobs (failed_at, locked_by, created_at, handler, updated_at, priority, run_at, attempts, locked_at, last_error) VALUES(NULL, NULL, :string, E:string, :string, :int, :string, :int, NULL, NULL) RETURNING id'
|
47
40
|
end
|
48
41
|
end
|
49
|
-
|
50
42
|
end
|
51
43
|
end
|
52
|
-
|
@@ -44,9 +44,9 @@ describe RequestLogAnalyzer::FileFormat::Rails do
|
|
44
44
|
end
|
45
45
|
|
46
46
|
it "should parse :completed lines correctly" do
|
47
|
-
line = 'Completed 200 OK in 170ms (Views: 78.
|
47
|
+
line = 'Completed 200 OK in 170ms (Views: 78.0ms | ActiveRecord: 48.2ms)'
|
48
48
|
@file_format.should parse_line(line).as(:completed).and_capture(
|
49
|
-
:duration => 0.170, :status => 200)
|
49
|
+
:duration => 0.170, :view => 0.078, :db => 0.0482, :status => 200)
|
50
50
|
end
|
51
51
|
|
52
52
|
it "should parse :completed lines correctly when ActiveRecord is not mentioned" do
|
@@ -54,6 +54,12 @@ describe RequestLogAnalyzer::FileFormat::Rails do
|
|
54
54
|
@file_format.should parse_line(line).as(:completed).and_capture(:duration => 0.364, :status => 200)
|
55
55
|
end
|
56
56
|
|
57
|
+
it "should parse :completed lines correctly when other durations are specified" do
|
58
|
+
line = 'Completed 200 OK in 384ms (Views: 222.0ms | ActiveRecord: 121.0ms | Sphinx: 0.0ms)'
|
59
|
+
@file_format.should parse_line(line).as(:completed).and_capture(:duration => 0.384, :view => 0.222,
|
60
|
+
:db => 0.121, :status => 200)
|
61
|
+
end
|
62
|
+
|
57
63
|
|
58
64
|
it "should pase :failure lines correctly" do
|
59
65
|
line = "ActionView::Template::Error (undefined local variable or method `field' for #<Class>) on line #3 of /Users/willem/Code/warehouse/app/views/queries/execute.csv.erb:"
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RequestLogAnalyzer::FileFormat::W3c do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@file_format = RequestLogAnalyzer::FileFormat.load(:w3c)
|
7
|
+
@log_parser = RequestLogAnalyzer::Source::LogParser.new(@file_format)
|
8
|
+
# date time c-ip cs-username s-ip s-port cs-method cs-uri-stem cs-uri-query sc-status sc-bytes cs-bytes time-taken cs(User-Agent) cs(Referrer)
|
9
|
+
@sample = '2002-05-24 20:18:01 172.224.24.114 - 206.73.118.24 80 GET /Default.htm - 200 7930 248 31 Mozilla/4.0+(compatible;+MSIE+5.01;+Windows+2000+Server) http://64.224.24.114/'
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should be a valid file format" do
|
13
|
+
@file_format.should be_valid
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should parse access lines and capture all of its fields" do
|
17
|
+
@file_format.should have_line_definition(:access).capturing(:timestamp, :remote_ip, :username, :local_ip, :port, :method, :path, :http_status, :bytes_sent, :bytes_received, :duration, :user_agent, :referer)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should match the sample line" do
|
21
|
+
@file_format.parse_line(@sample).should include(:line_definition, :captures)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should not match a nonsense line" do
|
25
|
+
@file_format.parse_line('#Software: Microsoft Internet Information Services 6.0').should be_nil
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should parse and convert the sample fields correctly" do
|
29
|
+
@log_parser.parse_io(StringIO.new(@sample)) do |request|
|
30
|
+
request[:timestamp].should == 20020524201801
|
31
|
+
request[:remote_ip].should == "172.224.24.114"
|
32
|
+
request[:username].should == nil
|
33
|
+
request[:local_ip].should == "206.73.118.24"
|
34
|
+
request[:port].should == 80
|
35
|
+
request[:method].should == 'GET'
|
36
|
+
request[:path].should == '/Default.htm'
|
37
|
+
request[:http_status].should == 200
|
38
|
+
request[:bytes_sent].should == 7930
|
39
|
+
request[:bytes_received].should == 248
|
40
|
+
request[:duration].should == 0.031
|
41
|
+
request[:user_agent].should == 'Mozilla/4.0+(compatible;+MSIE+5.01;+Windows+2000+Server)'
|
42
|
+
request[:referer].should == 'http://64.224.24.114/'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 1
|
7
|
-
- 9
|
8
7
|
- 10
|
9
|
-
|
8
|
+
- 0
|
9
|
+
version: 1.10.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Willem van Bergen
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-02-26 00:00:00 -05:00
|
19
19
|
default_executable: request-log-analyzer
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -84,6 +84,7 @@ extra_rdoc_files:
|
|
84
84
|
files:
|
85
85
|
- .gitignore
|
86
86
|
- DESIGN.rdoc
|
87
|
+
- Gemfile
|
87
88
|
- LICENSE
|
88
89
|
- README.rdoc
|
89
90
|
- Rakefile
|
@@ -112,6 +113,7 @@ files:
|
|
112
113
|
- lib/request_log_analyzer/file_format/delayed_job.rb
|
113
114
|
- lib/request_log_analyzer/file_format/delayed_job2.rb
|
114
115
|
- lib/request_log_analyzer/file_format/delayed_job21.rb
|
116
|
+
- lib/request_log_analyzer/file_format/haproxy.rb
|
115
117
|
- lib/request_log_analyzer/file_format/merb.rb
|
116
118
|
- lib/request_log_analyzer/file_format/mysql.rb
|
117
119
|
- lib/request_log_analyzer/file_format/oink.rb
|
@@ -120,6 +122,7 @@ files:
|
|
120
122
|
- lib/request_log_analyzer/file_format/rails.rb
|
121
123
|
- lib/request_log_analyzer/file_format/rails3.rb
|
122
124
|
- lib/request_log_analyzer/file_format/rails_development.rb
|
125
|
+
- lib/request_log_analyzer/file_format/w3c.rb
|
123
126
|
- lib/request_log_analyzer/filter.rb
|
124
127
|
- lib/request_log_analyzer/filter/anonymize.rb
|
125
128
|
- lib/request_log_analyzer/filter/field.rb
|
@@ -196,6 +199,7 @@ files:
|
|
196
199
|
- spec/unit/file_format/delayed_job_format_spec.rb
|
197
200
|
- spec/unit/file_format/file_format_api_spec.rb
|
198
201
|
- spec/unit/file_format/format_autodetection_spec.rb
|
202
|
+
- spec/unit/file_format/haproxy_format_spec.rb
|
199
203
|
- spec/unit/file_format/line_definition_spec.rb
|
200
204
|
- spec/unit/file_format/merb_format_spec.rb
|
201
205
|
- spec/unit/file_format/mysql_format_spec.rb
|
@@ -204,6 +208,7 @@ files:
|
|
204
208
|
- spec/unit/file_format/rack_format_spec.rb
|
205
209
|
- spec/unit/file_format/rails3_format_spec.rb
|
206
210
|
- spec/unit/file_format/rails_format_spec.rb
|
211
|
+
- spec/unit/file_format/w3c_format_spec.rb
|
207
212
|
- spec/unit/filter/anonymize_filter_spec.rb
|
208
213
|
- spec/unit/filter/field_filter_spec.rb
|
209
214
|
- spec/unit/filter/filter_spec.rb
|
@@ -277,6 +282,7 @@ test_files:
|
|
277
282
|
- spec/unit/file_format/delayed_job_format_spec.rb
|
278
283
|
- spec/unit/file_format/file_format_api_spec.rb
|
279
284
|
- spec/unit/file_format/format_autodetection_spec.rb
|
285
|
+
- spec/unit/file_format/haproxy_format_spec.rb
|
280
286
|
- spec/unit/file_format/line_definition_spec.rb
|
281
287
|
- spec/unit/file_format/merb_format_spec.rb
|
282
288
|
- spec/unit/file_format/mysql_format_spec.rb
|
@@ -285,6 +291,7 @@ test_files:
|
|
285
291
|
- spec/unit/file_format/rack_format_spec.rb
|
286
292
|
- spec/unit/file_format/rails3_format_spec.rb
|
287
293
|
- spec/unit/file_format/rails_format_spec.rb
|
294
|
+
- spec/unit/file_format/w3c_format_spec.rb
|
288
295
|
- spec/unit/filter/anonymize_filter_spec.rb
|
289
296
|
- spec/unit/filter/field_filter_spec.rb
|
290
297
|
- spec/unit/filter/filter_spec.rb
|