request-log-analyzer 1.9.10 → 1.10.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|