wvanbergen-request-log-analyzer 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/DESIGN +14 -0
- data/HACKING +7 -0
- data/README.textile +9 -98
- data/Rakefile +2 -2
- data/bin/request-log-analyzer +1 -1
- data/lib/cli/bashcolorizer.rb +60 -0
- data/lib/cli/command_line_arguments.rb +301 -0
- data/lib/cli/progressbar.rb +236 -0
- data/lib/request_log_analyzer/aggregator/base.rb +51 -0
- data/lib/request_log_analyzer/aggregator/database.rb +97 -0
- data/lib/request_log_analyzer/aggregator/echo.rb +25 -0
- data/lib/request_log_analyzer/aggregator/summarizer.rb +116 -0
- data/lib/request_log_analyzer/controller.rb +206 -0
- data/lib/request_log_analyzer/file_format/merb.rb +33 -0
- data/lib/request_log_analyzer/file_format/rails.rb +119 -0
- data/lib/request_log_analyzer/file_format.rb +77 -0
- data/lib/request_log_analyzer/filter/base.rb +29 -0
- data/lib/request_log_analyzer/filter/field.rb +36 -0
- data/lib/request_log_analyzer/filter/timespan.rb +32 -0
- data/lib/request_log_analyzer/line_definition.rb +159 -0
- data/lib/request_log_analyzer/log_parser.rb +183 -0
- data/lib/request_log_analyzer/log_processor.rb +121 -0
- data/lib/request_log_analyzer/request.rb +115 -0
- data/lib/request_log_analyzer/source/base.rb +42 -0
- data/lib/request_log_analyzer/source/log_file.rb +180 -0
- data/lib/request_log_analyzer/tracker/base.rb +54 -0
- data/lib/request_log_analyzer/tracker/category.rb +71 -0
- data/lib/request_log_analyzer/tracker/duration.rb +81 -0
- data/lib/request_log_analyzer/tracker/hourly_spread.rb +80 -0
- data/lib/request_log_analyzer/tracker/timespan.rb +54 -0
- data/spec/file_format_spec.rb +78 -0
- data/spec/file_formats/spec_format.rb +26 -0
- data/spec/filter_spec.rb +137 -0
- data/spec/log_processor_spec.rb +57 -0
- data/tasks/rspec.rake +6 -0
- metadata +53 -55
- data/TODO +0 -58
- data/bin/request-log-database +0 -81
- data/lib/base/log_parser.rb +0 -78
- data/lib/base/record_inserter.rb +0 -139
- data/lib/command_line/arguments.rb +0 -129
- data/lib/command_line/flag.rb +0 -51
- data/lib/merb_analyzer/log_parser.rb +0 -26
- data/lib/rails_analyzer/log_parser.rb +0 -35
- data/lib/rails_analyzer/record_inserter.rb +0 -39
- data/tasks/test.rake +0 -8
- data/test/log_fragments/fragment_1.log +0 -59
- data/test/log_fragments/fragment_2.log +0 -5
- data/test/log_fragments/fragment_3.log +0 -12
- data/test/log_fragments/fragment_4.log +0 -10
- data/test/log_fragments/fragment_5.log +0 -24
- data/test/log_fragments/merb_1.log +0 -84
- data/test/merb_log_parser_test.rb +0 -39
- data/test/rails_log_parser_test.rb +0 -94
- data/test/record_inserter_test.rb +0 -45
data/lib/base/record_inserter.rb
DELETED
@@ -1,139 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'sqlite3'
|
3
|
-
|
4
|
-
module Base
|
5
|
-
|
6
|
-
# Set of functions that can be used to easily log requests into a SQLite3 Database.
|
7
|
-
class RecordInserter
|
8
|
-
|
9
|
-
attr_reader :database
|
10
|
-
attr_reader :current_request
|
11
|
-
attr_reader :warning_count
|
12
|
-
|
13
|
-
# Initializer
|
14
|
-
# <tt>db_file</tt> The file which will be used for the SQLite3 Database storage.
|
15
|
-
def initialize(db_file, options = {})
|
16
|
-
@database = SQLite3::Database.new(db_file)
|
17
|
-
@insert_statements = nil
|
18
|
-
@warning_count = 0
|
19
|
-
create_tables_if_needed!
|
20
|
-
|
21
|
-
self.initialize_hook(options) if self.respond_to?(:initialize_hook)
|
22
|
-
end
|
23
|
-
|
24
|
-
# Calculate the database durations of the requests currenty in the database.
|
25
|
-
# Used if a logfile does contain any database durations.
|
26
|
-
def calculate_db_durations!
|
27
|
-
@database.execute('UPDATE "completed_queries" SET "database" = "duration" - "rendering" WHERE "database" IS NULL OR "database" = 0.0')
|
28
|
-
end
|
29
|
-
|
30
|
-
# Insert a batch of loglines into the database.
|
31
|
-
# Function prepares insert statements, yeilds and then closes and commits.
|
32
|
-
def insert_batch(&block)
|
33
|
-
@database.transaction
|
34
|
-
prepare_statements!
|
35
|
-
block.call(self)
|
36
|
-
close_prepared_statements!
|
37
|
-
@database.commit
|
38
|
-
rescue Exception => e
|
39
|
-
puts e.message
|
40
|
-
@database.rollback
|
41
|
-
end
|
42
|
-
|
43
|
-
def insert_warning(line, warning)
|
44
|
-
@database.execute("INSERT INTO parse_warnings (line, warning) VALUES (:line, :warning)", :line => line, :warning => warning)
|
45
|
-
@warning_count += 1
|
46
|
-
end
|
47
|
-
|
48
|
-
# Insert a request into the database.
|
49
|
-
# def insert(request, close_statements = false)
|
50
|
-
# raise 'No insert defined for this log file type'
|
51
|
-
# end
|
52
|
-
|
53
|
-
# Insert a batch of files into the database.
|
54
|
-
# <tt>db_file</tt> The filename of the database file to use.
|
55
|
-
# Returns the created database.
|
56
|
-
def self.insert_batch_into(db_file, options = {}, &block)
|
57
|
-
db = self.new(db_file)
|
58
|
-
db.insert_batch(&block)
|
59
|
-
return db
|
60
|
-
end
|
61
|
-
|
62
|
-
def count(type)
|
63
|
-
@database.get_first_value("SELECT COUNT(*) FROM \"#{type}_requests\"").to_i
|
64
|
-
end
|
65
|
-
|
66
|
-
protected
|
67
|
-
|
68
|
-
# Prepare insert statements.
|
69
|
-
def prepare_statements!
|
70
|
-
@insert_statements = {
|
71
|
-
:started => @database.prepare("
|
72
|
-
INSERT INTO started_requests ( line, timestamp, ip, method, controller, action)
|
73
|
-
VALUES (:line, :timestamp, :ip, :method, :controller, :action)"),
|
74
|
-
|
75
|
-
:failed => @database.prepare("
|
76
|
-
INSERT INTO failed_requests ( line, exception_string, stack_trace, error)
|
77
|
-
VALUES (:line, :exception_string, :stack_trace, :error)"),
|
78
|
-
|
79
|
-
:completed => @database.prepare("
|
80
|
-
INSERT INTO completed_requests ( line, url, status, duration, rendering_time, database_time)
|
81
|
-
VALUES (:line, :url, :status, :duration, :rendering, :db)")
|
82
|
-
}
|
83
|
-
end
|
84
|
-
|
85
|
-
# Close all prepared statments
|
86
|
-
def close_prepared_statements!
|
87
|
-
@insert_statements.each { |key, stmt| stmt.close }
|
88
|
-
end
|
89
|
-
|
90
|
-
# Create the needed database tables if they don't exist.
|
91
|
-
def create_tables_if_needed!
|
92
|
-
|
93
|
-
@database.execute("
|
94
|
-
CREATE TABLE IF NOT EXISTS started_requests (
|
95
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
96
|
-
line INTEGER NOT NULL,
|
97
|
-
timestamp DATETIME NOT NULL,
|
98
|
-
controller VARCHAR(255) NOT NULL,
|
99
|
-
action VARCHAR(255) NOT NULL,
|
100
|
-
method VARCHAR(6) NOT NULL,
|
101
|
-
ip VARCHAR(6) NOT NULL
|
102
|
-
)
|
103
|
-
");
|
104
|
-
|
105
|
-
@database.execute("
|
106
|
-
CREATE TABLE IF NOT EXISTS failed_requests (
|
107
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
108
|
-
line INTEGER NOT NULL,
|
109
|
-
started_request_id INTEGER,
|
110
|
-
error VARCHAR(255),
|
111
|
-
exception_string VARCHAR(255),
|
112
|
-
stack_trace TEXT
|
113
|
-
)
|
114
|
-
");
|
115
|
-
|
116
|
-
@database.execute("
|
117
|
-
CREATE TABLE IF NOT EXISTS completed_requests (
|
118
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
119
|
-
line INTEGER NOT NULL,
|
120
|
-
started_request_id INTEGER,
|
121
|
-
url VARCHAR(255) NOT NULL,
|
122
|
-
hashed_url VARCHAR(255),
|
123
|
-
status INTEGER NOT NULL,
|
124
|
-
duration FLOAT,
|
125
|
-
rendering_time FLOAT,
|
126
|
-
database_time FLOAT
|
127
|
-
)
|
128
|
-
");
|
129
|
-
|
130
|
-
@database.execute("CREATE TABLE IF NOT EXISTS parse_warnings (
|
131
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
132
|
-
line INTEGER NOT NULL,
|
133
|
-
warning VARCHAR(255) NOT NULL
|
134
|
-
)
|
135
|
-
");
|
136
|
-
end
|
137
|
-
|
138
|
-
end
|
139
|
-
end
|
@@ -1,129 +0,0 @@
|
|
1
|
-
require "#{File.dirname(__FILE__)}/flag"
|
2
|
-
require "#{File.dirname(__FILE__)}/exceptions"
|
3
|
-
|
4
|
-
# Module used to parse commandline arguments
|
5
|
-
module CommandLine
|
6
|
-
|
7
|
-
# Parse argument lists and return an argument object containing all set flags and switches.
|
8
|
-
class Arguments
|
9
|
-
|
10
|
-
FLAG_REGEXP = /^--?[A-z0-9]/
|
11
|
-
|
12
|
-
attr_reader :flag_definitions
|
13
|
-
|
14
|
-
attr_reader :flags
|
15
|
-
attr_reader :files
|
16
|
-
attr_reader :command
|
17
|
-
|
18
|
-
attr_accessor :required_files
|
19
|
-
|
20
|
-
# Initializer.
|
21
|
-
# <tt>arguments</tt> The arguments which are going to be parsed (defaults to $*).
|
22
|
-
def initialize(arguments = $*, &block)
|
23
|
-
@arguments = arguments
|
24
|
-
@flag_definitions = {}
|
25
|
-
@begins_with_command = false
|
26
|
-
end
|
27
|
-
|
28
|
-
# Parse a list of arguments. Intatiates a Argument object with the given arguments and yeilds
|
29
|
-
# it so that flags and switches can be set by the application.
|
30
|
-
# <tt>arguments</tt> The arguments which are going to be parsed (defaults to $*).
|
31
|
-
# Returns the arguments object.parse!
|
32
|
-
def self.parse(arguments = $*, &block)
|
33
|
-
cla = Arguments.new(arguments)
|
34
|
-
yield(cla)
|
35
|
-
return cla.parse!
|
36
|
-
end
|
37
|
-
|
38
|
-
# Handle argument switches for the application
|
39
|
-
# <tt>switch</tt> A switch symbol like :fast
|
40
|
-
# <tt>switch_alias</tt> An short alias for the same switch (:f).
|
41
|
-
def switch(switch, switch_alias = nil)
|
42
|
-
return self.flag(switch, :alias => switch_alias, :expects => nil)
|
43
|
-
end
|
44
|
-
|
45
|
-
# Handle argument flags for the application
|
46
|
-
# <tt>flag</tt> A flag symbol like :fast
|
47
|
-
# Options
|
48
|
-
# * <tt>:expects</tt> Expects a value after the flag
|
49
|
-
def flag(flag, options)
|
50
|
-
options[:expects] = String unless options.has_key?(:expects)
|
51
|
-
argument = Flag.new(flag, options)
|
52
|
-
@flag_definitions[argument.to_argument] = argument
|
53
|
-
@flag_definitions[argument.to_alias] = argument if argument.has_alias?
|
54
|
-
return argument
|
55
|
-
end
|
56
|
-
|
57
|
-
# If called argument list must begin with a command.
|
58
|
-
# <tt>begins_w_command</tt> Defaults to true.
|
59
|
-
def begins_with_command!(begins_w_command=true)
|
60
|
-
@begins_with_command = begins_w_command
|
61
|
-
end
|
62
|
-
|
63
|
-
# Unknown flags will be silently ignored.
|
64
|
-
# <tt>ignore</tt> Defaults to true.
|
65
|
-
def ignore_unknown_flags!(ignore = true)
|
66
|
-
@ignore_unknown_flags = ignore
|
67
|
-
end
|
68
|
-
|
69
|
-
def [](name)
|
70
|
-
return flags[name.to_s.gsub(/_/, '-').to_sym]
|
71
|
-
end
|
72
|
-
|
73
|
-
# Parse the flags and switches set by the application.
|
74
|
-
# Returns an arguments object containing the flags and switches found in the commandline.
|
75
|
-
def parse!
|
76
|
-
@flags = {}
|
77
|
-
@files = []
|
78
|
-
|
79
|
-
i = 0
|
80
|
-
while @arguments.length > i do
|
81
|
-
arg = @arguments[i]
|
82
|
-
if FLAG_REGEXP =~ arg
|
83
|
-
if @flag_definitions.has_key?(arg)
|
84
|
-
flag = @flag_definitions[arg]
|
85
|
-
if flag.expects_argument?
|
86
|
-
|
87
|
-
if @arguments.length > (i + 1) && @arguments[i + 1]
|
88
|
-
@flags[flag.name] = @arguments[i + 1]
|
89
|
-
i += 1
|
90
|
-
else
|
91
|
-
raise CommandLine::FlagExpectsArgument.new(arg)
|
92
|
-
end
|
93
|
-
|
94
|
-
else
|
95
|
-
@flags[flag.name] = true
|
96
|
-
end
|
97
|
-
else
|
98
|
-
raise CommandLine::UnknownFlag.new(arg) unless @ignore_unknown_flags
|
99
|
-
end
|
100
|
-
else
|
101
|
-
if @begins_with_command && @command.nil?
|
102
|
-
@command = arg
|
103
|
-
else
|
104
|
-
@files << arg
|
105
|
-
end
|
106
|
-
end
|
107
|
-
i += 1
|
108
|
-
end
|
109
|
-
|
110
|
-
check_parsed_arguments!
|
111
|
-
|
112
|
-
return self
|
113
|
-
end
|
114
|
-
|
115
|
-
# Check if the parsed arguments meet their requirements.
|
116
|
-
# Raises CommandLineexception on error.
|
117
|
-
def check_parsed_arguments!
|
118
|
-
if @begins_with_command && @command.nil?
|
119
|
-
raise CommandLine::CommandMissing.new
|
120
|
-
end
|
121
|
-
|
122
|
-
if @required_files && @files.length < @required_files
|
123
|
-
raise CommandLine::FileMissing.new("You need at least #{@required_files} files")
|
124
|
-
end
|
125
|
-
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
end
|
data/lib/command_line/flag.rb
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
module CommandLine
|
2
|
-
|
3
|
-
# Argument flag handling.
|
4
|
-
class Flag
|
5
|
-
|
6
|
-
attr_reader :name
|
7
|
-
attr_reader :alias
|
8
|
-
attr_reader :argument
|
9
|
-
|
10
|
-
# Initialize new Flag
|
11
|
-
# <tt>name</tt> The name of the flag
|
12
|
-
# <tt>definition</tt> The definition of the flag.
|
13
|
-
def initialize(name, definition)
|
14
|
-
@name = name.to_s.gsub(/_/, '-').to_sym
|
15
|
-
@alias = definition[:alias].to_sym if definition[:alias]
|
16
|
-
@required = definition.has_key?(:required) && definition[:required] == true
|
17
|
-
@argument = definition[:expects] if definition[:expects]
|
18
|
-
end
|
19
|
-
|
20
|
-
# Argument representation of the flag (--fast)
|
21
|
-
def to_argument
|
22
|
-
"--#{@name}"
|
23
|
-
end
|
24
|
-
|
25
|
-
# Argument alias representation of the flag (-f)
|
26
|
-
def to_alias
|
27
|
-
"-#{@alias}"
|
28
|
-
end
|
29
|
-
|
30
|
-
# Check if flag has an alias
|
31
|
-
def has_alias?
|
32
|
-
!@alias.nil?
|
33
|
-
end
|
34
|
-
|
35
|
-
# Check if flag is optional
|
36
|
-
def optional?
|
37
|
-
!@required
|
38
|
-
end
|
39
|
-
|
40
|
-
# Check if flag is required
|
41
|
-
def required?
|
42
|
-
@required
|
43
|
-
end
|
44
|
-
|
45
|
-
# Check if flag expects an argument (Are you talking to me?)
|
46
|
-
def expects_argument?
|
47
|
-
!@argument.nil?
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
module MerbAnalyzer
|
2
|
-
|
3
|
-
class LogParser < Base::LogParser
|
4
|
-
LOG_LINES = {
|
5
|
-
# ~ Started request handling: Fri Aug 29 11:10:23 +0200 2008
|
6
|
-
:started => {
|
7
|
-
:teaser => /Started/,
|
8
|
-
:regexp => /Started request handling\:\ (.+)/,
|
9
|
-
:params => [{:timestamp => :timestamp}]
|
10
|
-
},
|
11
|
-
# ~ Params: {"action"=>"create", "controller"=>"session"}
|
12
|
-
# ~ Params: {"_method"=>"delete", "authenticity_token"=>"[FILTERED]", "action"=>"d}
|
13
|
-
:params => {
|
14
|
-
:teaser => /Params/,
|
15
|
-
:regexp => /Params\:\ \{(.+)\}/,
|
16
|
-
:params => [{:raw_hash => :string}]
|
17
|
-
},
|
18
|
-
# ~ {:dispatch_time=>0.006117, :after_filters_time=>6.1e-05, :before_filters_time=>0.000712, :action_time=>0.005833}
|
19
|
-
:completed => {
|
20
|
-
:teaser => /\{:dispatch_time/,
|
21
|
-
:regexp => /\{\:dispatch_time=>(.+), (?:\:after_filters_time=>(.+), )?(?:\:before_filters_time=>(.+), )?\:action_time=>(.+)\}/,
|
22
|
-
:params => [ {:dispatch_time => :sec}, {:after_filters_time => :sec}, {:before_filters_time => :sec}, {:action_time => :sec} ]
|
23
|
-
}
|
24
|
-
}
|
25
|
-
end
|
26
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
module RailsAnalyzer
|
2
|
-
|
3
|
-
class LogParser < Base::LogParser
|
4
|
-
|
5
|
-
# Completed in 0.21665 (4 reqs/sec) | Rendering: 0.00926 (4%) | DB: 0.00000 (0%) | 200 OK [http://demo.nu/employees]
|
6
|
-
RAILS_21_COMPLETED = /Completed in (\d+\.\d{5}) \(\d+ reqs\/sec\) (?:\| Rendering: (\d+\.\d{5}) \(\d+\%\) )?(?:\| DB: (\d+\.\d{5}) \(\d+\%\) )?\| (\d\d\d).+\[(http.+)\]/
|
7
|
-
|
8
|
-
# Completed in 614ms (View: 120, DB: 31) | 200 OK [http://floorplanner.local/demo]
|
9
|
-
RAILS_22_COMPLETED = /Completed in (\d+)ms \((?:View: (\d+), )?DB: (\d+)\) \| (\d\d\d).+\[(http.+)\]/
|
10
|
-
|
11
|
-
|
12
|
-
LOG_LINES = {
|
13
|
-
# Processing EmployeeController#index (for 123.123.123.123 at 2008-07-13 06:00:00) [GET]
|
14
|
-
:started => {
|
15
|
-
:teaser => /Processing/,
|
16
|
-
:regexp => /Processing ((?:\w+::)?\w+)#(\w+)(?: to (\w+))? \(for (\d+\.\d+\.\d+\.\d+) at (\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d)\) \[([A-Z]+)\]/,
|
17
|
-
:params => [{:controller => :string}, {:action => :string}, {:format => :string}, {:ip => :string}, {:timestamp => :timestamp}, {:method => :string}]
|
18
|
-
},
|
19
|
-
# RuntimeError (Cannot destroy employee): /app/models/employee.rb:198:in `before_destroy'
|
20
|
-
:failed => {
|
21
|
-
:teaser => /Error/,
|
22
|
-
:regexp => /(\w+)(?:Error|Invalid) \((.*)\)\:(.*)/,
|
23
|
-
:params => [{:error => :string}, {:exception_string => :string}, {:stack_trace => :string}]
|
24
|
-
},
|
25
|
-
|
26
|
-
:completed => {
|
27
|
-
:teaser => /Completed in /,
|
28
|
-
:regexp => Regexp.new("(?:#{RAILS_21_COMPLETED}|#{RAILS_22_COMPLETED})"),
|
29
|
-
:params => [{:duration => :sec}, {:rendering => :sec}, {:db => :sec}, {:status => :int}, {:url => :string}, # 2.1 variant
|
30
|
-
{:duration => :msec}, {:rendering => :msec}, {:db => :msec}, {:status => :int}, {:url => :string}] # 2.2 variant
|
31
|
-
|
32
|
-
}
|
33
|
-
}
|
34
|
-
end
|
35
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'sqlite3'
|
3
|
-
|
4
|
-
module RailsAnalyzer
|
5
|
-
|
6
|
-
# Set of functions that can be used to easily log requests into a SQLite3 Database.
|
7
|
-
class RecordInserter < Base::RecordInserter
|
8
|
-
|
9
|
-
# Insert a request into the database.
|
10
|
-
# <tt>request</tt> The request to insert.
|
11
|
-
# <tt>close_statements</tt> Close prepared statements (default false)
|
12
|
-
def insert(request, close_statements = false)
|
13
|
-
unless @insert_statements
|
14
|
-
prepare_statements!
|
15
|
-
close_statements = true
|
16
|
-
end
|
17
|
-
|
18
|
-
if request[:type] && @insert_statements.has_key?(request[:type])
|
19
|
-
if request[:type] == :started
|
20
|
-
insert_warning(request[:line], "Unclosed request encountered on line #{request[:line]} (request started on line #{@current_request})") unless @current_request.nil?
|
21
|
-
@current_request = request[:line]
|
22
|
-
elsif [:failed, :completed].include?(request[:type])
|
23
|
-
@current_request = nil
|
24
|
-
end
|
25
|
-
|
26
|
-
begin
|
27
|
-
@insert_statements[request.delete(:type)].execute(request)
|
28
|
-
rescue SQLite3::Exception => e
|
29
|
-
insert_warning(request[:line], "Could not save log line to database: " + e.message.to_s)
|
30
|
-
end
|
31
|
-
else
|
32
|
-
insert_warning(request[:line], "Ignored unknown statement type")
|
33
|
-
end
|
34
|
-
|
35
|
-
close_prepared_statements! if close_statements
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
end
|
data/tasks/test.rake
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
Processing DashboardController#index (for 130.89.162.199 at 2008-08-14 21:16:25) [GET]
|
2
|
-
Session ID: BAh7CToMcmVmZXJlciIbL3ByaXNjaWxsYS9wZW9wbGUvMjM1MCIKZmxhc2hJ
|
3
|
-
QzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNoSGFzaHsABjoKQHVz
|
4
|
-
ZWR7ADoNbGFuZ3VhZ2VvOhNMb2NhbGU6Ok9iamVjdBI6CUB3aW4wOg1AY291
|
5
|
-
bnRyeSIHTkw6CkBoYXNoaf3L2Js6DkBvcmlnX3N0ciIKbmwtTkw6DUBpc28z
|
6
|
-
MDY2MDoNQGNoYXJzZXQiClVURi04Og5AbGFuZ3VhZ2UiB25sOg5AbW9kaWZp
|
7
|
-
ZXIwOgtAcG9zaXgiCm5sX05MOg1AZ2VuZXJhbCIKbmxfTkw6DUB2YXJpYW50
|
8
|
-
MDoOQGZhbGxiYWNrMDoMQHNjcmlwdDA6DnBlcnNvbl9pZGkCMgc=--7918aed37151c13360cd370c37b541f136146fbd
|
9
|
-
Parameters: {"action"=>"index", "controller"=>"dashboard"}
|
10
|
-
Set language to: nl_NL
|
11
|
-
Rendering template within layouts/priscilla
|
12
|
-
Rendering dashboard/index
|
13
|
-
Completed in 0.22699 (4 reqs/sec) | Rendering: 0.02667 (11%) | DB: 0.03057 (13%) | 200 OK [https://www.example.com/]
|
14
|
-
|
15
|
-
|
16
|
-
Processing PeopleController#index (for 130.89.162.199 at 2008-08-14 21:16:30) [GET]
|
17
|
-
Session ID: BAh7CSIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNo
|
18
|
-
SGFzaHsABjoKQHVzZWR7ADoMcmVmZXJlciIQL3ByaXNjaWxsYS86DnBlcnNv
|
19
|
-
bl9pZGkCMgc6DWxhbmd1YWdlbzoTTG9jYWxlOjpPYmplY3QSOg1AY291bnRy
|
20
|
-
eSIHTkw6CUB3aW4wOg5Ab3JpZ19zdHIiCm5sLU5MOgpAaGFzaGn9y9ibOg5A
|
21
|
-
bGFuZ3VhZ2UiB25sOg1AY2hhcnNldCIKVVRGLTg6DUBpc28zMDY2MDoOQG1v
|
22
|
-
ZGlmaWVyMDoLQHBvc2l4IgpubF9OTDoNQHZhcmlhbnQwOg1AZ2VuZXJhbCIK
|
23
|
-
bmxfTkw6DEBzY3JpcHQwOg5AZmFsbGJhY2sw--48cbe3788ef27f6005f8e999610a42af6e90ffb3
|
24
|
-
Parameters: {"commit"=>"Zoek", "action"=>"index", "q"=>"gaby", "controller"=>"people"}
|
25
|
-
Set language to: nl_NL
|
26
|
-
Redirected to https://www.example.com/people/2545
|
27
|
-
Completed in 0.04759 (21 reqs/sec) | DB: 0.03719 (78%) | 302 Found [https://www.example.com/people?q=gaby&commit=Zoek]
|
28
|
-
|
29
|
-
|
30
|
-
Processing PeopleController#show (for 130.89.162.199 at 2008-08-14 21:16:30) [GET]
|
31
|
-
Session ID: BAh7CToMcmVmZXJlciIpL3ByaXNjaWxsYS9wZW9wbGU/cT1nYWJ5JmNvbW1p
|
32
|
-
dD1ab2VrIgpmbGFzaElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxh
|
33
|
-
c2hIYXNoewAGOgpAdXNlZHsAOg1sYW5ndWFnZW86E0xvY2FsZTo6T2JqZWN0
|
34
|
-
EjoJQHdpbjA6DUBjb3VudHJ5IgdOTDoKQGhhc2hp/cvYmzoOQG9yaWdfc3Ry
|
35
|
-
IgpubC1OTDoNQGlzbzMwNjYwOg1AY2hhcnNldCIKVVRGLTg6DkBsYW5ndWFn
|
36
|
-
ZSIHbmw6DkBtb2RpZmllcjA6C0Bwb3NpeCIKbmxfTkw6DUBnZW5lcmFsIgpu
|
37
|
-
bF9OTDoNQHZhcmlhbnQwOg5AZmFsbGJhY2swOgxAc2NyaXB0MDoOcGVyc29u
|
38
|
-
X2lkaQIyBw==--3ad1948559448522a49d289a2a89dc7ccbe8847a
|
39
|
-
Parameters: {"action"=>"show", "id"=>"2545", "controller"=>"people"}
|
40
|
-
Set language to: nl_NL
|
41
|
-
Rendering template within layouts/priscilla
|
42
|
-
Rendering people/show
|
43
|
-
person: Gaby Somers, study_year: 2008/2009
|
44
|
-
Completed in 0.29077 (3 reqs/sec) | Rendering: 0.24187 (83%) | DB: 0.04030 (13%) | 200 OK [https://www.example.com/people/2545]
|
45
|
-
|
46
|
-
|
47
|
-
Processing PeopleController#picture (for 130.89.162.199 at 2008-08-14 21:16:35) [GET]
|
48
|
-
Session ID: BAh7CSIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNo
|
49
|
-
SGFzaHsABjoKQHVzZWR7ADoMcmVmZXJlciIbL3ByaXNjaWxsYS9wZW9wbGUv
|
50
|
-
MjU0NToOcGVyc29uX2lkaQIyBzoNbGFuZ3VhZ2VvOhNMb2NhbGU6Ok9iamVj
|
51
|
-
dBI6DUBjb3VudHJ5IgdOTDoJQHdpbjA6DkBvcmlnX3N0ciIKbmwtTkw6CkBo
|
52
|
-
YXNoaf3L2Js6DkBsYW5ndWFnZSIHbmw6DUBjaGFyc2V0IgpVVEYtODoNQGlz
|
53
|
-
bzMwNjYwOg5AbW9kaWZpZXIwOgtAcG9zaXgiCm5sX05MOg1AdmFyaWFudDA6
|
54
|
-
DUBnZW5lcmFsIgpubF9OTDoMQHNjcmlwdDA6DkBmYWxsYmFjazA=--797a33f280a482647111397d138d0918f2658167
|
55
|
-
Parameters: {"action"=>"picture", "id"=>"2545", "controller"=>"people"}
|
56
|
-
Set language to: nl_NL
|
57
|
-
Rendering template within layouts/priscilla
|
58
|
-
Rendering people/picture
|
59
|
-
Completed in 0.05383 (18 reqs/sec) | Rendering: 0.04622 (85%) | DB: 0.00206 (3%) | 200 OK [https://www.example.com/people/2545/picture]
|
@@ -1,5 +0,0 @@
|
|
1
|
-
Jul 13 06:25:58 10.1.1.32 app_p [1957]: Processing EmployeeController#index (for 10.1.1.33 at 2008-07-13 06:25:58) [GET]
|
2
|
-
Jul 13 06:25:58 10.1.1.32 app_p [1957]: Session ID: bd1810833653be11c38ad1e5675635bd
|
3
|
-
Jul 13 06:25:58 10.1.1.32 app_p [1957]: Parameters: {"format"=>"xml", "action"=>"index}
|
4
|
-
Jul 13 06:25:58 10.1.1.32 app_p [1957]: Rendering employees
|
5
|
-
Jul 13 06:25:58 10.1.1.32 app_p [1957]: Completed in 0.21665 (4 reqs/sec) | Rendering: 0.00926 (4%) | DB: 0.00000 (0%) | 200 OK [http://example.com/employee.xml]
|
@@ -1,12 +0,0 @@
|
|
1
|
-
Processing PageController#demo (for 127.0.0.1 at 2008-12-10 16:28:09) [GET]
|
2
|
-
Parameters: {"action"=>"demo", "controller"=>"page"}
|
3
|
-
Logging in from session data...
|
4
|
-
Logged in as willem@depillem.com
|
5
|
-
Using locale: en-US, http-accept: ["en-US"], session: , det browser: en-US, det domain:
|
6
|
-
Rendering template within layouts/demo
|
7
|
-
Rendering page/demo
|
8
|
-
Rendered shared/_analytics (0.2ms)
|
9
|
-
Rendered layouts/_actions (0.6ms)
|
10
|
-
Rendered layouts/_menu (2.2ms)
|
11
|
-
Rendered layouts/_tabbar (0.5ms)
|
12
|
-
Completed in 614ms (View: 120, DB: 31) | 200 OK [http://floorplanner.local/demo]
|
@@ -1,10 +0,0 @@
|
|
1
|
-
Processing CachedController#cached (for 1.1.1.1 at 2008-12-24 07:36:53) [GET]
|
2
|
-
Parameters: {"action"=>"cached", "controller"=>"cached"}
|
3
|
-
Logging in from session data...
|
4
|
-
Logging in using cookie...
|
5
|
-
Using locale: zh-Hans, http-accept: ["zh-CN", "zh-HK", "zh-TW", "en-US"], session: , det browser: zh-Hans, det domain: , user pref locale:
|
6
|
-
Referer: http://www.example.com/referer
|
7
|
-
Cached fragment hit: views/zh-Hans-www-cached-cached-all-CN--- (0.0ms)
|
8
|
-
Filter chain halted as [#<ActionController::Caching::Actions::ActionCacheFilter:0x2a999ad620 @check=nil, @options={:store_options=>{}, :layout=>nil, :cache_path=>#<Proc:0x0000002a999b8890@/app/controllers/cached_controller.rb:8>}>] rendered_or_redirected.
|
9
|
-
Filter chain halted as [#<ActionController::Filters::AroundFilter:0x2a999ad120 @identifier=nil, @kind=:filter, @options={:only=>#<Set: {"cached"}>, :if=>:not_logged_in?, :unless=>nil}, @method=#<ActionController::Caching::Actions::ActionCacheFilter:0x2a999ad620 @check=nil, @options={:store_options=>{}, :layout=>nil, :cache_path=>#<Proc:0x0000002a999b8890@/app/controllers/cached_controller.rb:8>}>>] did_not_yield.
|
10
|
-
Completed in 3ms (View: 0, DB: 0) | 200 OK [http://www.example.com/cached/cached/]
|
@@ -1,24 +0,0 @@
|
|
1
|
-
Processing AccountController#dashboard (for 1.1.1.1 at 2008-12-24 07:36:49) [GET]
|
2
|
-
Parameters: {"action"=>"dashboard", "controller"=>"account", "first_use"=>"true"}
|
3
|
-
Logging in from session data...
|
4
|
-
|
5
|
-
|
6
|
-
Processing ProjectsController#new (for 1.1.1.1 at 2008-12-24 07:36:49) [GET]
|
7
|
-
Parameters: {"action"=>"new", "controller"=>"projects"}
|
8
|
-
Rendering template within layouts/default
|
9
|
-
Rendering account/dashboard
|
10
|
-
Logging in from session data...
|
11
|
-
Logging in using cookie...
|
12
|
-
Using locale: en-US, http-accept: [], session: , det browser: , det domain: , user pref locale:
|
13
|
-
Rendered shared/_maintenance (0.6ms)
|
14
|
-
Rendering template within layouts/templates/general_default/index.html.erb
|
15
|
-
Rendered projects/_recent_designs (4.3ms)
|
16
|
-
Rendered projects/_project (13.6ms)
|
17
|
-
Rendered projects/_projects (18.7ms)
|
18
|
-
Rendered layouts/_menu (1.4ms)
|
19
|
-
Completed in 36ms (View: 30, DB: 3) | 200 OK [http://www.example.com/projects/new]
|
20
|
-
Rendered layouts/_actions (0.3ms)
|
21
|
-
Rendered layouts/_menu (1.6ms)
|
22
|
-
Rendered layouts/_tabbar (1.9ms)
|
23
|
-
Rendered layouts/_footer (3.2ms)
|
24
|
-
Completed in 50ms (View: 41, DB: 4) | 200 OK [http://www.example.com/dashboard?first_use=true]
|
@@ -1,84 +0,0 @@
|
|
1
|
-
~ Loaded DEVELOPMENT Environment...
|
2
|
-
~ Connecting to database...
|
3
|
-
~ loading gem 'merb_datamapper' ...
|
4
|
-
~ loading gem 'gettext' ...
|
5
|
-
~ loading gem 'merb_helpers' ...
|
6
|
-
~ loading gem 'merb-assets' ...
|
7
|
-
~ loading gem 'merb-action-args' ...
|
8
|
-
~ loading gem 'merb-mailer' ...
|
9
|
-
~ loading gem 'merb_param_protection' ...
|
10
|
-
~ loading gem 'merb_has_flash' ...
|
11
|
-
~ loading gem 'merb_forgery_protection' ...
|
12
|
-
~ loading gem 'dm-validations' ...
|
13
|
-
~ loading gem 'dm-timestamps' ...
|
14
|
-
~ loading gem 'dm-migrations' ...
|
15
|
-
~ loading gem 'dm-aggregates' ...
|
16
|
-
~ loading gem 'dm-adjust' ...
|
17
|
-
~ loading gem 'dm-serializer' ...
|
18
|
-
~ loading gem 'dm-constraints' ...
|
19
|
-
~ loading gem 'dm-timeline' ...
|
20
|
-
~ loading gem 'dm-searchable' ...
|
21
|
-
~ loading gem 'dm-audited' ...
|
22
|
-
~ loading gem 'lib/extensions' ...
|
23
|
-
~ loading gem 'lib/authenticated_system/authenticated_dependencies' ...
|
24
|
-
~ Compiling routes...
|
25
|
-
~ Using 'share-nothing' cookie sessions (4kb limit per client)
|
26
|
-
~ Using Mongrel adapter
|
27
|
-
~ Started request handling: Fri Aug 29 11:10:23 +0200 2008
|
28
|
-
~ Params: {"_method"=>"delete", "authenticity_token"=>"[FILTERED]", "action"=>"destroy", "method"=>"delete", "controller"=>"session"}
|
29
|
-
~ Cookie deleted: auth_token => nil
|
30
|
-
~ Redirecting to: / (302)
|
31
|
-
~ {:dispatch_time=>0.243424, :after_filters_time=>6.9e-05, :before_filters_time=>0.213213, :action_time=>0.241652}
|
32
|
-
~
|
33
|
-
|
34
|
-
~ Started request handling: Fri Aug 29 11:10:23 +0200 2008
|
35
|
-
~ Params: {"action"=>"index", "controller"=>"dashboard"}
|
36
|
-
~ Redirecting to: /login (302)
|
37
|
-
~ {:dispatch_time=>0.002649, :after_filters_time=>7.4e-05, :action_time=>0.001951}
|
38
|
-
~
|
39
|
-
|
40
|
-
~ Started request handling: Fri Aug 29 11:10:23 +0200 2008
|
41
|
-
~ Params: {"action"=>"create", "controller"=>"session"}
|
42
|
-
~ {:dispatch_time=>0.006117, :after_filters_time=>6.1e-05, :before_filters_time=>0.000712, :action_time=>0.005833}
|
43
|
-
~
|
44
|
-
|
45
|
-
~ Started request handling: Fri Aug 29 11:10:27 +0200 2008
|
46
|
-
~ Params: {"authenticity_token"=>"[FILTERED]", "action"=>"create", "controller"=>"session", "login"=>"username", "password"=>"[FILTERED]", "remember_me"=>"0"}
|
47
|
-
~ Redirecting to: / (302)
|
48
|
-
~ {:dispatch_time=>0.006652, :after_filters_time=>0.000143, :before_filters_time=>0.000861, :action_time=>0.006171}
|
49
|
-
~
|
50
|
-
|
51
|
-
~ Started request handling: Fri Aug 29 11:10:27 +0200 2008
|
52
|
-
~ Params: {"action"=>"index", "controller"=>"dashboard"}
|
53
|
-
~ Redirecting to: /dashboard (302)
|
54
|
-
~ {:dispatch_time=>0.008241, :after_filters_time=>0.000126, :before_filters_time=>0.002632, :action_time=>0.007711}
|
55
|
-
~
|
56
|
-
|
57
|
-
~ Started request handling: Fri Aug 29 11:10:27 +0200 2008
|
58
|
-
~ Params: {"action"=>"index", "namespace"=>"dashboard", "controller"=>"dashboard"}
|
59
|
-
~ {:dispatch_time=>0.009458, :after_filters_time=>0.000103, :before_filters_time=>0.00266, :action_time=>0.008742}
|
60
|
-
~
|
61
|
-
|
62
|
-
~ Started request handling: Fri Aug 29 11:10:29 +0200 2008
|
63
|
-
~ Params: {"format"=>nil, "action"=>"index", "namespace"=>"dashboard", "controller"=>"employees"}
|
64
|
-
~ {:dispatch_time=>0.102725, :after_filters_time=>0.000115, :before_filters_time=>0.00411, :action_time=>0.101836}
|
65
|
-
~
|
66
|
-
|
67
|
-
~ Started request handling: Fri Aug 29 11:10:30 +0200 2008
|
68
|
-
~ Params: {"format"=>nil, "action"=>"index", "namespace"=>"dashboard", "controller"=>"organisations"}
|
69
|
-
~ {:dispatch_time=>0.042575, :after_filters_time=>8.9e-05, :before_filters_time=>0.004267, :action_time=>0.041762}
|
70
|
-
~
|
71
|
-
|
72
|
-
~ Started request handling: Fri Aug 29 11:10:31 +0200 2008
|
73
|
-
~ Params: {"action"=>"index", "namespace"=>"dashboard", "controller"=>"dashboard"}
|
74
|
-
~ {:dispatch_time=>0.010311, :after_filters_time=>8.0e-05, :before_filters_time=>0.003195, :action_time=>0.009567}
|
75
|
-
~
|
76
|
-
|
77
|
-
~ Started request handling: Fri Aug 29 11:10:33 +0200 2008
|
78
|
-
~ Params: {"format"=>nil, "action"=>"index", "namespace"=>"dashboard", "controller"=>"employees"}
|
79
|
-
~ {:dispatch_time=>0.012913, :after_filters_time=>7.1e-05, :before_filters_time=>0.004422, :action_time=>0.012141}
|
80
|
-
~
|
81
|
-
|
82
|
-
~ Started request handling: Fri Aug 29 11:10:35 +0200 2008
|
83
|
-
~ Params: {"action"=>"new", "namespace"=>"dashboard", "controller"=>"employees"}
|
84
|
-
~ {:dispatch_time=>0.013051, :after_filters_time=>7.8e-05, :before_filters_time=>0.003576, :action_time=>0.011773}
|
@@ -1,39 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
|
3
|
-
require "#{File.dirname(__FILE__)}/../lib/base/log_parser"
|
4
|
-
require "#{File.dirname(__FILE__)}/../lib/merb_analyzer/log_parser"
|
5
|
-
|
6
|
-
class MerbLogParserTest < Test::Unit::TestCase
|
7
|
-
|
8
|
-
def fragment_file(number)
|
9
|
-
"#{File.dirname(__FILE__)}/log_fragments/merb_#{number}.log"
|
10
|
-
end
|
11
|
-
|
12
|
-
def test_parse_started_merb_fragment
|
13
|
-
requests = []
|
14
|
-
parser = MerbAnalyzer::LogParser.new(fragment_file(1)).each(:started) do |request|
|
15
|
-
requests << request
|
16
|
-
end
|
17
|
-
assert_equal requests[0][:timestamp], "Fri Aug 29 11:10:23 +0200 2008"
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_parse_completed_merb_fragment
|
21
|
-
requests = []
|
22
|
-
parser = MerbAnalyzer::LogParser.new(fragment_file(1)).each(:completed) do |request|
|
23
|
-
requests << request
|
24
|
-
end
|
25
|
-
|
26
|
-
assert_equal requests[0][:action_time], 0.241652
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_parse_params_merb_fragment
|
30
|
-
requests = []
|
31
|
-
parser = MerbAnalyzer::LogParser.new(fragment_file(1)).each(:params) do |request|
|
32
|
-
requests << request
|
33
|
-
end
|
34
|
-
|
35
|
-
assert_match '"controller"=>"session"', requests[0][:raw_hash]
|
36
|
-
assert_match '"action"=>"destroy"', requests[0][:raw_hash]
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|