request-log-analyzer 1.0.2 → 1.6.3
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 +10 -0
- data/DESIGN.rdoc +41 -0
- data/LICENSE +4 -4
- data/README.rdoc +38 -0
- data/Rakefile +6 -3
- data/bin/request-log-analyzer +70 -72
- data/lib/cli/command_line_arguments.rb +53 -53
- data/lib/cli/database_console.rb +26 -0
- data/lib/cli/database_console_init.rb +43 -0
- data/lib/cli/progressbar.rb +166 -189
- data/lib/cli/tools.rb +49 -0
- data/lib/request_log_analyzer/aggregator/database_inserter.rb +83 -0
- data/lib/request_log_analyzer/aggregator/echo.rb +17 -12
- data/lib/request_log_analyzer/aggregator/summarizer.rb +101 -63
- data/lib/request_log_analyzer/{aggregator/base.rb → aggregator.rb} +17 -13
- data/lib/request_log_analyzer/controller.rb +251 -98
- data/lib/request_log_analyzer/database/base.rb +114 -0
- data/lib/request_log_analyzer/database/connection.rb +38 -0
- data/lib/request_log_analyzer/database/request.rb +22 -0
- data/lib/request_log_analyzer/database/source.rb +13 -0
- data/lib/request_log_analyzer/database/warning.rb +14 -0
- data/lib/request_log_analyzer/database.rb +102 -0
- data/lib/request_log_analyzer/file_format/amazon_s3.rb +74 -0
- data/lib/request_log_analyzer/file_format/apache.rb +147 -0
- data/lib/request_log_analyzer/file_format/delayed_job.rb +55 -0
- data/lib/request_log_analyzer/file_format/merb.rb +65 -29
- data/lib/request_log_analyzer/file_format/mysql.rb +101 -0
- data/lib/request_log_analyzer/file_format/postgresql.rb +68 -0
- data/lib/request_log_analyzer/file_format/rack.rb +9 -0
- data/lib/request_log_analyzer/file_format/rails.rb +164 -78
- data/lib/request_log_analyzer/file_format/rails3.rb +86 -0
- data/lib/request_log_analyzer/file_format/rails_development.rb +12 -0
- data/lib/request_log_analyzer/file_format.rb +252 -58
- data/lib/request_log_analyzer/filter/anonymize.rb +39 -0
- data/lib/request_log_analyzer/filter/field.rb +19 -13
- data/lib/request_log_analyzer/filter/timespan.rb +25 -12
- data/lib/request_log_analyzer/filter.rb +30 -0
- data/lib/request_log_analyzer/line_definition.rb +69 -96
- data/lib/request_log_analyzer/log_processor.rb +31 -53
- data/lib/request_log_analyzer/mailer.rb +65 -0
- data/lib/request_log_analyzer/output/fancy_html.rb +49 -0
- data/lib/request_log_analyzer/output/fixed_width.rb +220 -0
- data/lib/request_log_analyzer/output/html.rb +187 -0
- data/lib/request_log_analyzer/output.rb +117 -0
- data/lib/request_log_analyzer/request.rb +125 -40
- data/lib/request_log_analyzer/source/database_loader.rb +87 -0
- data/lib/request_log_analyzer/source/log_parser.rb +297 -0
- data/lib/request_log_analyzer/source.rb +72 -0
- data/lib/request_log_analyzer/tracker/duration.rb +28 -64
- data/lib/request_log_analyzer/tracker/frequency.rb +108 -0
- data/lib/request_log_analyzer/tracker/hourly_spread.rb +76 -49
- data/lib/request_log_analyzer/tracker/numeric_value.rb +223 -0
- data/lib/request_log_analyzer/tracker/timespan.rb +54 -27
- data/lib/request_log_analyzer/tracker/traffic.rb +40 -0
- data/lib/request_log_analyzer/tracker.rb +101 -0
- data/lib/request_log_analyzer.rb +43 -13
- data/request-log-analyzer.gemspec +41 -0
- data/spec/database.yml +23 -0
- data/spec/fixtures/apache_combined.log +5 -0
- data/spec/fixtures/apache_common.log +10 -0
- data/spec/fixtures/decompression.log +12 -0
- data/spec/fixtures/decompression.log.bz2 +0 -0
- data/spec/fixtures/decompression.log.gz +0 -0
- data/spec/fixtures/decompression.log.zip +0 -0
- data/spec/fixtures/decompression.tar.gz +0 -0
- data/spec/fixtures/decompression.tgz +0 -0
- data/spec/fixtures/header_and_footer.log +6 -0
- data/spec/fixtures/merb_prefixed.log +9 -0
- data/spec/fixtures/mysql_slow_query.log +110 -0
- data/spec/fixtures/postgresql.log +2980 -0
- data/spec/fixtures/rails.db +0 -0
- data/spec/fixtures/rails_22.log +1 -1
- data/spec/fixtures/sinatra.log +99 -0
- data/spec/integration/command_line_usage_spec.rb +84 -0
- data/spec/integration/mailer_spec.rb +179 -0
- data/spec/integration/munin_plugins_rails_spec.rb +58 -0
- data/spec/integration/scout_spec.rb +152 -0
- data/spec/lib/helpers.rb +72 -0
- data/spec/lib/macros.rb +18 -0
- data/spec/lib/matchers.rb +77 -0
- data/spec/lib/mocks.rb +77 -0
- data/spec/lib/testing_format.rb +46 -0
- data/spec/spec_helper.rb +16 -59
- data/spec/unit/aggregator/database_inserter_spec.rb +93 -0
- data/spec/unit/aggregator/summarizer_spec.rb +26 -0
- data/spec/unit/controller/controller_spec.rb +41 -0
- data/spec/unit/controller/log_processor_spec.rb +18 -0
- data/spec/unit/database/base_class_spec.rb +183 -0
- data/spec/unit/database/connection_spec.rb +34 -0
- data/spec/unit/database/database_spec.rb +133 -0
- data/spec/unit/file_format/amazon_s3_format_spec.rb +67 -0
- data/spec/unit/file_format/apache_format_spec.rb +203 -0
- data/spec/unit/file_format/common_regular_expressions_spec.rb +53 -0
- data/spec/unit/file_format/delayed_job_format_spec.rb +83 -0
- data/spec/unit/file_format/file_format_api_spec.rb +69 -0
- data/spec/unit/file_format/format_autodetection_spec.rb +40 -0
- data/spec/unit/file_format/line_definition_spec.rb +75 -0
- data/spec/unit/file_format/merb_format_spec.rb +52 -0
- data/spec/unit/file_format/mysql_format_spec.rb +154 -0
- data/spec/unit/file_format/postgresql_format_spec.rb +65 -0
- data/spec/unit/file_format/rack_format_spec.rb +50 -0
- data/spec/unit/file_format/rails3_format_spec.rb +120 -0
- data/spec/unit/file_format/rails_format_spec.rb +180 -0
- data/spec/unit/filter/anonymize_filter_spec.rb +21 -0
- data/spec/unit/filter/field_filter_spec.rb +66 -0
- data/spec/unit/filter/filter_spec.rb +17 -0
- data/spec/unit/filter/timespan_filter_spec.rb +58 -0
- data/spec/unit/mailer_spec.rb +42 -0
- data/spec/unit/request_spec.rb +111 -0
- data/spec/unit/source/log_parser_spec.rb +119 -0
- data/spec/unit/tracker/duration_tracker_spec.rb +49 -0
- data/spec/unit/tracker/frequency_tracker_spec.rb +88 -0
- data/spec/unit/tracker/hourly_spread_spec.rb +79 -0
- data/spec/unit/tracker/numeric_value_tracker_spec.rb +166 -0
- data/spec/unit/tracker/timespan_tracker_spec.rb +73 -0
- data/spec/unit/tracker/tracker_api_spec.rb +125 -0
- data/spec/unit/tracker/traffic_tracker_spec.rb +28 -0
- data/tasks/github-gem.rake +290 -139
- data/tasks/request_log_analyzer.rake +23 -7
- metadata +221 -94
- data/DESIGN +0 -14
- data/HACKING +0 -7
- data/README.textile +0 -36
- data/lib/cli/bashcolorizer.rb +0 -60
- data/lib/request_log_analyzer/aggregator/database.rb +0 -148
- data/lib/request_log_analyzer/filter/base.rb +0 -29
- data/lib/request_log_analyzer/log_parser.rb +0 -173
- data/lib/request_log_analyzer/source/base.rb +0 -42
- data/lib/request_log_analyzer/source/log_file.rb +0 -170
- data/lib/request_log_analyzer/tracker/base.rb +0 -54
- data/lib/request_log_analyzer/tracker/category.rb +0 -71
- data/spec/controller_spec.rb +0 -40
- data/spec/database_inserter_spec.rb +0 -101
- data/spec/file_format_spec.rb +0 -78
- data/spec/file_formats/spec_format.rb +0 -26
- data/spec/filter_spec.rb +0 -137
- data/spec/line_definition_spec.rb +0 -124
- data/spec/log_parser_spec.rb +0 -68
- data/spec/log_processor_spec.rb +0 -57
- data/spec/merb_format_spec.rb +0 -38
- data/spec/rails_format_spec.rb +0 -76
- data/spec/request_spec.rb +0 -72
- data/spec/summarizer_spec.rb +0 -9
- data/tasks/rspec.rake +0 -6
data/lib/cli/progressbar.rb
CHANGED
|
@@ -7,230 +7,207 @@
|
|
|
7
7
|
#
|
|
8
8
|
# You can redistribute it and/or modify it under the terms
|
|
9
9
|
# of Ruby's license.
|
|
10
|
-
#
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
11
|
+
module CommandLine
|
|
12
|
+
class ProgressBar
|
|
13
|
+
VERSION = "0.9"
|
|
14
|
+
|
|
15
|
+
def initialize (title, total, out = STDERR)
|
|
16
|
+
@title = title
|
|
17
|
+
@total = total
|
|
18
|
+
@out = out
|
|
19
|
+
@terminal_width = 80
|
|
20
|
+
@bar_mark = '='
|
|
21
|
+
@current = 0
|
|
22
|
+
@previous = 0
|
|
23
|
+
@finished_p = false
|
|
24
|
+
@start_time = Time.now
|
|
25
|
+
@previous_time = @start_time
|
|
26
|
+
@title_width = 24
|
|
27
|
+
@format = "%-#{@title_width}s %3d%% %s %s"
|
|
28
|
+
@format_arguments = [:title, :percentage, :bar, :stat]
|
|
29
|
+
clear
|
|
30
|
+
show
|
|
31
|
+
end
|
|
32
|
+
attr_reader :title
|
|
33
|
+
attr_reader :current
|
|
34
|
+
attr_reader :total
|
|
35
|
+
attr_accessor :start_time
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
def fmt_bar
|
|
39
|
+
bar_width = do_percentage * @terminal_width / 100
|
|
40
|
+
sprintf("[%s%s]",
|
|
41
|
+
@bar_mark * bar_width,
|
|
42
|
+
" " * (@terminal_width - bar_width))
|
|
43
|
+
end
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
def fmt_percentage
|
|
46
|
+
do_percentage
|
|
47
|
+
end
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
def fmt_stat
|
|
50
|
+
if @finished_p then elapsed else eta end
|
|
51
|
+
end
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
def fmt_stat_for_file_transfer
|
|
54
|
+
if @finished_p then
|
|
55
|
+
sprintf("%s %s %s", bytes, transfer_rate, elapsed)
|
|
56
|
+
else
|
|
57
|
+
sprintf("%s %s %s", bytes, transfer_rate, eta)
|
|
58
|
+
end
|
|
58
59
|
end
|
|
59
|
-
end
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
def fmt_title
|
|
62
|
+
@title[0,(@title_width - 1)] + ":"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def convert_bytes (bytes)
|
|
66
|
+
if bytes < 1024
|
|
67
|
+
sprintf("%6dB", bytes)
|
|
68
|
+
elsif bytes < 1024 * 1000 # 1000kb
|
|
69
|
+
sprintf("%5.1fKB", bytes.to_f / 1024)
|
|
70
|
+
elsif bytes < 1024 * 1024 * 1000 # 1000mb
|
|
71
|
+
sprintf("%5.1fMB", bytes.to_f / 1024 / 1024)
|
|
72
|
+
else
|
|
73
|
+
sprintf("%5.1fGB", bytes.to_f / 1024 / 1024 / 1024)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
64
76
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
sprintf("%
|
|
68
|
-
elsif bytes < 1024 * 1000 # 1000kb
|
|
69
|
-
sprintf("%5.1fKB", bytes.to_f / 1024)
|
|
70
|
-
elsif bytes < 1024 * 1024 * 1000 # 1000mb
|
|
71
|
-
sprintf("%5.1fMB", bytes.to_f / 1024 / 1024)
|
|
72
|
-
else
|
|
73
|
-
sprintf("%5.1fGB", bytes.to_f / 1024 / 1024 / 1024)
|
|
77
|
+
def transfer_rate
|
|
78
|
+
bytes_per_second = @current.to_f / (Time.now - @start_time)
|
|
79
|
+
sprintf("%s/s", convert_bytes(bytes_per_second))
|
|
74
80
|
end
|
|
75
|
-
end
|
|
76
81
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
end
|
|
82
|
+
def bytes
|
|
83
|
+
convert_bytes(@current)
|
|
84
|
+
end
|
|
81
85
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
86
|
+
def format_time (t)
|
|
87
|
+
t = t.to_i
|
|
88
|
+
sec = t % 60
|
|
89
|
+
min = (t / 60) % 60
|
|
90
|
+
hour = t / 3600
|
|
91
|
+
sprintf("%02d:%02d:%02d", hour, min, sec);
|
|
92
|
+
end
|
|
85
93
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
94
|
+
# ETA stands for Estimated Time of Arrival.
|
|
95
|
+
def eta
|
|
96
|
+
if @current == 0
|
|
97
|
+
"ETA: --:--:--"
|
|
98
|
+
else
|
|
99
|
+
elapsed = Time.now - @start_time
|
|
100
|
+
eta = elapsed * @total / @current - elapsed;
|
|
101
|
+
sprintf("ETA: %s", format_time(eta))
|
|
102
|
+
end
|
|
103
|
+
end
|
|
93
104
|
|
|
94
|
-
|
|
95
|
-
def eta
|
|
96
|
-
if @current == 0
|
|
97
|
-
"ETA: --:--:--"
|
|
98
|
-
else
|
|
105
|
+
def elapsed
|
|
99
106
|
elapsed = Time.now - @start_time
|
|
100
|
-
|
|
101
|
-
sprintf("ETA: %s", format_time(eta))
|
|
107
|
+
sprintf("Time: %s", format_time(elapsed))
|
|
102
108
|
end
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def elapsed
|
|
106
|
-
elapsed = Time.now - @start_time
|
|
107
|
-
sprintf("Time: %s", format_time(elapsed))
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def eol
|
|
111
|
-
if @finished_p then "\n" else "\r" end
|
|
112
|
-
end
|
|
113
109
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
100
|
|
117
|
-
else
|
|
118
|
-
@current * 100 / @total
|
|
110
|
+
def eol
|
|
111
|
+
if @finished_p then "\n" else "\r" end
|
|
119
112
|
end
|
|
120
|
-
end
|
|
121
113
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
begin
|
|
126
|
-
tiocgwinsz = 0x5413
|
|
127
|
-
data = [0, 0, 0, 0].pack("SSSS")
|
|
128
|
-
if @out.ioctl(tiocgwinsz, data) >= 0 then
|
|
129
|
-
rows, cols, xpixels, ypixels = data.unpack("SSSS")
|
|
130
|
-
if cols >= 0 then cols else default_width end
|
|
114
|
+
def do_percentage
|
|
115
|
+
if @total.zero?
|
|
116
|
+
100
|
|
131
117
|
else
|
|
132
|
-
|
|
118
|
+
@current * 100 / @total
|
|
133
119
|
end
|
|
134
|
-
rescue Exception
|
|
135
|
-
default_width
|
|
136
120
|
end
|
|
137
|
-
end
|
|
138
121
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
122
|
+
def show
|
|
123
|
+
arguments = @format_arguments.map {|method|
|
|
124
|
+
method = sprintf("fmt_%s", method)
|
|
125
|
+
send(method)
|
|
126
|
+
}
|
|
127
|
+
line = sprintf(@format, *arguments)
|
|
128
|
+
|
|
129
|
+
width = terminal_width(80)
|
|
130
|
+
if line.length == width - 1
|
|
131
|
+
@out.print(line + eol)
|
|
132
|
+
@out.flush
|
|
133
|
+
elsif line.length >= width
|
|
134
|
+
@terminal_width = [@terminal_width - (line.length - width + 1), 0].max
|
|
135
|
+
if @terminal_width == 0 then @out.print(line + eol) else show end
|
|
136
|
+
else # line.length < width - 1
|
|
137
|
+
@terminal_width += width - line.length + 1
|
|
138
|
+
show
|
|
139
|
+
end
|
|
140
|
+
@previous_time = Time.now
|
|
156
141
|
end
|
|
157
|
-
@previous_time = Time.now
|
|
158
|
-
end
|
|
159
142
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
143
|
+
def show_if_needed
|
|
144
|
+
if @total.zero?
|
|
145
|
+
cur_percentage = 100
|
|
146
|
+
prev_percentage = 0
|
|
147
|
+
else
|
|
148
|
+
cur_percentage = (@current * 100 / @total).to_i
|
|
149
|
+
prev_percentage = (@previous * 100 / @total).to_i
|
|
150
|
+
end
|
|
168
151
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
152
|
+
# Use "!=" instead of ">" to support negative changes
|
|
153
|
+
if cur_percentage != prev_percentage ||
|
|
154
|
+
Time.now - @previous_time >= 1 || @finished_p
|
|
155
|
+
show
|
|
156
|
+
end
|
|
173
157
|
end
|
|
174
|
-
end
|
|
175
158
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
159
|
+
public
|
|
160
|
+
def clear
|
|
161
|
+
@out.print "\r"
|
|
162
|
+
@out.print(" " * (terminal_width(80) - 1))
|
|
163
|
+
@out.print "\r"
|
|
164
|
+
end
|
|
182
165
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
166
|
+
def finish
|
|
167
|
+
@current = @total
|
|
168
|
+
@finished_p = true
|
|
169
|
+
show
|
|
170
|
+
end
|
|
188
171
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
172
|
+
def finished?
|
|
173
|
+
@finished_p
|
|
174
|
+
end
|
|
192
175
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
176
|
+
def file_transfer_mode
|
|
177
|
+
@format_arguments = [:title, :percentage, :bar, :stat_for_file_transfer]
|
|
178
|
+
end
|
|
196
179
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
180
|
+
def format= (format)
|
|
181
|
+
@format = format
|
|
182
|
+
end
|
|
200
183
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
184
|
+
def format_arguments= (arguments)
|
|
185
|
+
@format_arguments = arguments
|
|
186
|
+
end
|
|
204
187
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
188
|
+
def halt
|
|
189
|
+
@finished_p = true
|
|
190
|
+
show
|
|
191
|
+
end
|
|
209
192
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
193
|
+
def inc (step = 1)
|
|
194
|
+
@current += step
|
|
195
|
+
@current = @total if @current > @total
|
|
196
|
+
show_if_needed
|
|
197
|
+
@previous = @current
|
|
198
|
+
end
|
|
216
199
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
@current = count
|
|
222
|
-
show_if_needed
|
|
223
|
-
@previous = @current
|
|
224
|
-
end
|
|
200
|
+
def set (count)
|
|
201
|
+
count = 0 if count < 0
|
|
202
|
+
count = @total if count > @total
|
|
225
203
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
end
|
|
204
|
+
@current = count
|
|
205
|
+
show_if_needed
|
|
206
|
+
@previous = @current
|
|
207
|
+
end
|
|
230
208
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
209
|
+
def inspect
|
|
210
|
+
"#<ProgressBar:#{@current}/#{@total}>"
|
|
211
|
+
end
|
|
234
212
|
end
|
|
235
213
|
end
|
|
236
|
-
|
data/lib/cli/tools.rb
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Try to determine the terminal with.
|
|
2
|
+
# If it is not possible to to so, it returns the default_width.
|
|
3
|
+
# <tt>default_width</tt> Defaults to 81
|
|
4
|
+
def terminal_width(default_width = 81)
|
|
5
|
+
|
|
6
|
+
begin
|
|
7
|
+
tiocgwinsz = 0x5413
|
|
8
|
+
data = [0, 0, 0, 0].pack("SSSS")
|
|
9
|
+
if !RUBY_PLATFORM.include?('java') && @out.ioctl(tiocgwinsz, data) >= 0 # JRuby crashes on ioctl
|
|
10
|
+
rows, cols, xpixels, ypixels = data.unpack("SSSS")
|
|
11
|
+
raise unless cols > 0
|
|
12
|
+
cols
|
|
13
|
+
else
|
|
14
|
+
raise
|
|
15
|
+
end
|
|
16
|
+
rescue
|
|
17
|
+
begin
|
|
18
|
+
IO.popen('stty -a 2>&1') do |pipe|
|
|
19
|
+
column_line = pipe.detect { |line| /(\d+) columns/ =~ line }
|
|
20
|
+
raise unless column_line
|
|
21
|
+
$1.to_i
|
|
22
|
+
end
|
|
23
|
+
rescue
|
|
24
|
+
default_width
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Copies request-log-analyzer analyzer rake tasks into the /lib/tasks folder of a project, for easy access and
|
|
30
|
+
# environment integration.
|
|
31
|
+
# <tt>install_type</tt> Type of project to install into. Defaults to :rails.
|
|
32
|
+
# Raises if it cannot find the project folder or if the install_type is now known.
|
|
33
|
+
def install_rake_tasks(install_type = :rails)
|
|
34
|
+
if install_type.to_sym == :rails
|
|
35
|
+
require 'ftools'
|
|
36
|
+
if File.directory?('./lib/tasks/')
|
|
37
|
+
File.copy(File.dirname(__FILE__) + '/../../tasks/request_log_analyzer.rake', './lib/tasks/request_log_analyze.rake')
|
|
38
|
+
puts "Installed rake tasks."
|
|
39
|
+
puts "To use, run: rake rla:report"
|
|
40
|
+
else
|
|
41
|
+
puts "Cannot find /lib/tasks folder. Are you in your Rails directory?"
|
|
42
|
+
puts "Installation aborted."
|
|
43
|
+
end
|
|
44
|
+
else
|
|
45
|
+
raise "Cannot perform this install type! (#{install_type.to_s})"
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
|
|
2
|
+
module RequestLogAnalyzer::Aggregator
|
|
3
|
+
|
|
4
|
+
# The database aggregator will create an SQLite3 database with all parsed request information.
|
|
5
|
+
#
|
|
6
|
+
# The prepare method will create a database schema according to the file format definitions.
|
|
7
|
+
# It will also create ActiveRecord::Base subclasses to interact with the created tables.
|
|
8
|
+
# Then, the aggregate method will be called for every parsed request. The information of
|
|
9
|
+
# these requests is inserted into the tables using the ActiveRecord classes.
|
|
10
|
+
#
|
|
11
|
+
# A requests table will be created, in which a record is inserted for every parsed request.
|
|
12
|
+
# For every line type, a separate table will be created with a request_id field to point to
|
|
13
|
+
# the request record, and a field for every parsed value. Finally, a warnings table will be
|
|
14
|
+
# created to log all parse warnings.
|
|
15
|
+
class DatabaseInserter < Base
|
|
16
|
+
|
|
17
|
+
attr_reader :request_count, :sources, :database
|
|
18
|
+
|
|
19
|
+
# Establishes a connection to the database and creates the necessary database schema for the
|
|
20
|
+
# current file format
|
|
21
|
+
def prepare
|
|
22
|
+
@sources = {}
|
|
23
|
+
@database = RequestLogAnalyzer::Database.new(options[:database])
|
|
24
|
+
@database.file_format = source.file_format
|
|
25
|
+
|
|
26
|
+
database.drop_database_schema! if options[:reset_database]
|
|
27
|
+
database.create_database_schema!
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Aggregates a request into the database
|
|
31
|
+
# This will create a record in the requests table and create a record for every line that has been parsed,
|
|
32
|
+
# in which the captured values will be stored.
|
|
33
|
+
def aggregate(request)
|
|
34
|
+
@request_object = RequestLogAnalyzer::Database::Request.new(:first_lineno => request.first_lineno, :last_lineno => request.last_lineno)
|
|
35
|
+
request.lines.each do |line|
|
|
36
|
+
class_columns = database.get_class(line[:line_type]).column_names.reject { |column| ['id', 'source_id', 'request_id'].include?(column) }
|
|
37
|
+
attributes = Hash[*line.select { |(k, v)| class_columns.include?(k.to_s) }.flatten]
|
|
38
|
+
attributes[:source_id] = @sources[line[:source]].id if @sources[line[:source]]
|
|
39
|
+
@request_object.send("#{line[:line_type]}_lines").build(attributes)
|
|
40
|
+
end
|
|
41
|
+
@request_object.save!
|
|
42
|
+
rescue SQLite3::SQLException => e
|
|
43
|
+
raise Interrupt, e.message
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Finalizes the aggregator by closing the connection to the database
|
|
47
|
+
def finalize
|
|
48
|
+
@request_count = RequestLogAnalyzer::Database::Request.count
|
|
49
|
+
database.disconnect
|
|
50
|
+
database.remove_orm_classes!
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Records w warining in the warnings table.
|
|
54
|
+
def warning(type, message, lineno)
|
|
55
|
+
RequestLogAnalyzer::Database::Warning.create!(:warning_type => type.to_s, :message => message, :lineno => lineno)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Records source changes in the sources table
|
|
59
|
+
def source_change(change, filename)
|
|
60
|
+
if File.exist?(filename)
|
|
61
|
+
case change
|
|
62
|
+
when :started
|
|
63
|
+
@sources[filename] = RequestLogAnalyzer::Database::Source.create!(:filename => filename)
|
|
64
|
+
when :finished
|
|
65
|
+
@sources[filename].update_attributes!(:filesize => File.size(filename), :mtime => File.mtime(filename))
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Prints a short report of what has been inserted into the database
|
|
71
|
+
def report(output)
|
|
72
|
+
output.title('Request database created')
|
|
73
|
+
|
|
74
|
+
output << "A database file has been created with all parsed request information.\n"
|
|
75
|
+
output << "#{@request_count} requests have been added to the database.\n"
|
|
76
|
+
output << "\n"
|
|
77
|
+
output << "To open a Ruby console to inspect the database, run the following command.\n"
|
|
78
|
+
output << output.colorize(" $ request-log-analyzer console -d #{options[:database]}\n", :bold)
|
|
79
|
+
output << "\n"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -1,24 +1,29 @@
|
|
|
1
1
|
module RequestLogAnalyzer::Aggregator
|
|
2
2
|
|
|
3
|
+
# Echo Aggregator. Writes everything to the screen when it is passed to this aggregator
|
|
3
4
|
class Echo < Base
|
|
4
|
-
|
|
5
|
+
|
|
6
|
+
attr_accessor :warnings
|
|
7
|
+
|
|
5
8
|
def prepare
|
|
6
|
-
@warnings =
|
|
9
|
+
@warnings = []
|
|
7
10
|
end
|
|
8
|
-
|
|
11
|
+
|
|
12
|
+
# Display every parsed line immediately to the terminal
|
|
9
13
|
def aggregate(request)
|
|
10
|
-
puts "\nRequest: " + request.
|
|
14
|
+
puts "\nRequest: \n" + request.lines.map { |l|
|
|
15
|
+
"\t#{l[:lineno]}:#{l[:line_type]}: #{l.reject { |(k,v)| [:lineno, :line_type].include?(k) }.inspect}" }.join("\n")
|
|
11
16
|
end
|
|
12
|
-
|
|
17
|
+
|
|
18
|
+
# Capture all warnings during parsing
|
|
13
19
|
def warning(type, message, lineno)
|
|
14
|
-
@warnings << "WARNING #{type.inspect} on line #{lineno}: #{message}
|
|
20
|
+
@warnings << "WARNING #{type.inspect} on line #{lineno}: #{message}"
|
|
15
21
|
end
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
output
|
|
20
|
-
|
|
21
|
-
output << @warnings + "\n"
|
|
22
|
+
|
|
23
|
+
# Display every warning in the report when finished parsing
|
|
24
|
+
def report(output)
|
|
25
|
+
output.title("Warnings during parsing")
|
|
26
|
+
@warnings.each { |w| output.puts(w) }
|
|
22
27
|
end
|
|
23
28
|
|
|
24
29
|
end
|