groonga-query-log 1.5.8 → 1.5.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/doc/text/news.md +23 -0
- data/lib/groonga-query-log/command/replay.rb +23 -4
- data/lib/groonga-query-log/command/run-regression-test.rb +99 -19
- data/lib/groonga-query-log/command/verify-server.rb +12 -0
- data/lib/groonga-query-log/replayer.rb +173 -141
- data/lib/groonga-query-log/server-verifier.rb +12 -3
- data/lib/groonga-query-log/version.rb +1 -1
- data/test/command/test-run-regression-test.rb +15 -1
- metadata +40 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 99da1139f30806bb7ead68b469c2122368bcad8ea91586160096751e3919b4ab
|
4
|
+
data.tar.gz: ab791f07d33e784531372dd3c4cad59e57e1ae38d778529a3b65dbd8ea1d4466
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9ae76dd7338c155860f1b74dea49fc202baeaa4216018dda0e2c22144663c4ea93db08a4042f3487c429bd565281876d46d9348a4fa27e510c082f9dcb065507
|
7
|
+
data.tar.gz: 6d4f6912e00abd0a0ff41c18bcbbd3c251dab17a9d142974ab0719e5dbb5309e97f7fe174ec7cd239cddd0cf1b15c8940b7da2d31e4f8c7c723337d0902940a7
|
data/doc/text/news.md
CHANGED
@@ -1,5 +1,28 @@
|
|
1
1
|
# News
|
2
2
|
|
3
|
+
## 1.5.9: 2020-04-06
|
4
|
+
|
5
|
+
### Fixes
|
6
|
+
|
7
|
+
* `replay`: Added `--output-type` option.
|
8
|
+
|
9
|
+
* `replay`: Added support for outputting logs to stdout.
|
10
|
+
|
11
|
+
* `replay`: Fixed a bug that command name isn't processed correctly.
|
12
|
+
|
13
|
+
* `replay`: Added support for inputting from stdin.
|
14
|
+
|
15
|
+
* `run-regression-test`: Added `--old-groonga-env` option.
|
16
|
+
|
17
|
+
* `run-regression-test`: Added `--new-groonga-env` option.
|
18
|
+
|
19
|
+
* `run-regression-test`: Added support for checking the number of
|
20
|
+
leaked objects.
|
21
|
+
|
22
|
+
* `replay`: Added `--output-error-responses` option.
|
23
|
+
|
24
|
+
* `run-regression-test`: Added `--omit-rate` option.
|
25
|
+
|
3
26
|
## 1.5.8: 2020-02-14
|
4
27
|
|
5
28
|
### Fixes
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2013-
|
1
|
+
# Copyright (C) 2013-2020 Sutou Kouhei <kou@clear-code.com>
|
2
2
|
#
|
3
3
|
# This library is free software; you can redistribute it and/or
|
4
4
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -29,9 +29,13 @@ module GroongaQueryLog
|
|
29
29
|
def run(command_line)
|
30
30
|
input_paths = create_parser.parse(command_line)
|
31
31
|
replayer = Replayer.new(@options)
|
32
|
-
input_paths.
|
33
|
-
|
34
|
-
|
32
|
+
if input_paths.empty?
|
33
|
+
replayer.replay($stdin)
|
34
|
+
else
|
35
|
+
input_paths.each do |input_path|
|
36
|
+
File.open(input_path) do |input|
|
37
|
+
replayer.replay(input)
|
38
|
+
end
|
35
39
|
end
|
36
40
|
end
|
37
41
|
true
|
@@ -117,6 +121,21 @@ module GroongaQueryLog
|
|
117
121
|
"[not output]") do |path|
|
118
122
|
@options.responses_path = path
|
119
123
|
end
|
124
|
+
|
125
|
+
parser.on("--output-error-responses=PATH",
|
126
|
+
"Output only error responses to PATH",
|
127
|
+
"[not output]") do |path|
|
128
|
+
@options.error_responses_path = path
|
129
|
+
end
|
130
|
+
|
131
|
+
available_output_types = ["json", "msgpack", "apache-arrow"]
|
132
|
+
available_output_type_labels = available_output_types.join(", ")
|
133
|
+
parser.on("--output-type=TYPE", available_output_types,
|
134
|
+
"Use TYPE as the output type",
|
135
|
+
"(#{available_output_type_labels})",
|
136
|
+
"[use the original output type]") do |type|
|
137
|
+
@options.output_type = type
|
138
|
+
end
|
120
139
|
end
|
121
140
|
end
|
122
141
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
# Copyright (C) 2014-
|
2
|
-
# Copyright (C) 2019 Horimoto Yasuhiro <horimoto@clear-code.com>
|
1
|
+
# Copyright (C) 2014-2020 Sutou Kouhei <kou@clear-code.com>
|
2
|
+
# Copyright (C) 2019-2020 Horimoto Yasuhiro <horimoto@clear-code.com>
|
3
3
|
#
|
4
4
|
# This library is free software; you can redistribute it and/or
|
5
5
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -41,10 +41,12 @@ module GroongaQueryLog
|
|
41
41
|
@old_groonga = "groonga"
|
42
42
|
@old_database = "db.old/db"
|
43
43
|
@old_groonga_options = []
|
44
|
+
@old_groonga_env = {}
|
44
45
|
|
45
46
|
@new_groonga = "groonga"
|
46
47
|
@new_database = "db.new/db"
|
47
48
|
@new_groonga_options = []
|
49
|
+
@new_groonga_env = {}
|
48
50
|
|
49
51
|
@recreate_database = false
|
50
52
|
@load_data = true
|
@@ -60,6 +62,7 @@ module GroongaQueryLog
|
|
60
62
|
@rewrite_not_or_regular_expression = false
|
61
63
|
@rewrite_and_not_operator = false
|
62
64
|
@debug_rewrite = false
|
65
|
+
@omit_rate = 0.0
|
63
66
|
|
64
67
|
@care_order = true
|
65
68
|
@ignored_drilldown_keys = []
|
@@ -102,12 +105,16 @@ module GroongaQueryLog
|
|
102
105
|
tester_options)
|
103
106
|
success = tester.run
|
104
107
|
elapsed_time = Time.now - start_time
|
108
|
+
n_leaked_objects = tester.new.n_leaked_objects
|
105
109
|
|
106
|
-
report = format_report(success,
|
110
|
+
report = format_report(success,
|
111
|
+
elapsed_time,
|
112
|
+
n_leaked_objects,
|
113
|
+
tester.n_executed_commands)
|
107
114
|
notifier.notify_finished(success, report)
|
108
115
|
puts(report)
|
109
116
|
|
110
|
-
success
|
117
|
+
success and n_leaked_objects.zero?
|
111
118
|
end
|
112
119
|
|
113
120
|
private
|
@@ -153,11 +160,21 @@ module GroongaQueryLog
|
|
153
160
|
|
154
161
|
parser.on("--old-groonga-option=OPTION",
|
155
162
|
"Add an additional old groonga option",
|
156
|
-
"You can specify this option multiple times
|
163
|
+
"You can specify this option multiple times",
|
164
|
+
"to specify multiple groonga options",
|
157
165
|
"(no options)") do |groonga_option|
|
158
166
|
@old_groonga_options << groonga_option
|
159
167
|
end
|
160
168
|
|
169
|
+
parser.on("--old-groonga-env=KEY=VALUE",
|
170
|
+
"Use KEY=VALUE environment variable for old groonga",
|
171
|
+
"You can specify this option multiple times",
|
172
|
+
"to specify multiple environment variables",
|
173
|
+
"(no environment variables)") do |env|
|
174
|
+
key, value = env.split("=", 2)
|
175
|
+
@old_groonga_env[key] = value
|
176
|
+
end
|
177
|
+
|
161
178
|
parser.separator("")
|
162
179
|
parser.separator("New Groonga:")
|
163
180
|
parser.on("--new-groonga=GROONGA",
|
@@ -168,11 +185,21 @@ module GroongaQueryLog
|
|
168
185
|
|
169
186
|
parser.on("--new-groonga-option=OPTION",
|
170
187
|
"Add an additional new groonga option",
|
171
|
-
"You can specify this option multiple times
|
188
|
+
"You can specify this option multiple times",
|
189
|
+
"to specify multiple groonga options",
|
172
190
|
"(no options)") do |groonga_option|
|
173
191
|
@new_groonga_options << groonga_option
|
174
192
|
end
|
175
193
|
|
194
|
+
parser.on("--new-groonga-env=KEY=VALUE",
|
195
|
+
"Use KEY=VALUE environment variable for new groonga",
|
196
|
+
"You can specify this option multiple times",
|
197
|
+
"to specify multiple environment variables",
|
198
|
+
"(no environment variables)") do |env|
|
199
|
+
key, value = env.split("=", 2)
|
200
|
+
@new_groonga_env[key] = value
|
201
|
+
end
|
202
|
+
|
176
203
|
parser.separator("")
|
177
204
|
parser.separator("Operations:")
|
178
205
|
parser.on("--recreate-database",
|
@@ -252,6 +279,13 @@ module GroongaQueryLog
|
|
252
279
|
"(#{@debug_rewrite})") do |boolean|
|
253
280
|
@debug_rewrite = boolean
|
254
281
|
end
|
282
|
+
parser.on("--omit-rate=RATE", Float,
|
283
|
+
"You can specify rate for omitting execution queries." +
|
284
|
+
"For example, if you specify 0.9 in this option, " +
|
285
|
+
"execute queries with the probability of 1/10.",
|
286
|
+
"(#{@omit_rate})") do |rate|
|
287
|
+
@omit_rate = rate
|
288
|
+
end
|
255
289
|
|
256
290
|
parser.separator("")
|
257
291
|
parser.separator("Comparisons:")
|
@@ -398,6 +432,7 @@ module GroongaQueryLog
|
|
398
432
|
:rewrite_and_not_operator =>
|
399
433
|
@rewrite_and_not_operator,
|
400
434
|
:debug_rewrite => @debug_rewrite,
|
435
|
+
:omit_rate => @omit_rate,
|
401
436
|
:target_command_names => @target_command_names,
|
402
437
|
:verify_performance => @verify_performance,
|
403
438
|
:performance_verfifier_options => @performance_verfifier_options,
|
@@ -409,6 +444,7 @@ module GroongaQueryLog
|
|
409
444
|
def old_groonga_server
|
410
445
|
GroongaServer.new(@old_groonga,
|
411
446
|
@old_groonga_options,
|
447
|
+
@old_groonga_env,
|
412
448
|
@old_database,
|
413
449
|
server_options)
|
414
450
|
end
|
@@ -416,16 +452,26 @@ module GroongaQueryLog
|
|
416
452
|
def new_groonga_server
|
417
453
|
GroongaServer.new(@new_groonga,
|
418
454
|
@new_groonga_options,
|
455
|
+
@new_groonga_env,
|
419
456
|
@new_database,
|
420
457
|
server_options)
|
421
458
|
end
|
422
459
|
|
423
|
-
def format_report(success,
|
460
|
+
def format_report(success,
|
461
|
+
elapsed_time,
|
462
|
+
n_leaked_objects,
|
463
|
+
n_executed_commands)
|
424
464
|
formatted = format_elapsed_time(elapsed_time)
|
465
|
+
formatted << "Number of executed commands: #{n_executed_commands}\n"
|
425
466
|
if success
|
426
|
-
formatted << "Success"
|
467
|
+
formatted << "Success\n"
|
427
468
|
else
|
428
469
|
formatted << "Failure"
|
470
|
+
end
|
471
|
+
unless n_leaked_objects.zero?
|
472
|
+
formatted << "\nLeaked: #{n_leaked_objects}"
|
473
|
+
end
|
474
|
+
unless success
|
429
475
|
output = StringIO.new
|
430
476
|
formetter = FormatRegressionTestLogs.new(output: output)
|
431
477
|
formetter.run([results_directory])
|
@@ -459,11 +505,16 @@ module GroongaQueryLog
|
|
459
505
|
include Loggable
|
460
506
|
|
461
507
|
attr_reader :host, :port
|
462
|
-
def initialize(groonga,
|
508
|
+
def initialize(groonga,
|
509
|
+
groonga_options,
|
510
|
+
groonga_env,
|
511
|
+
database_path,
|
512
|
+
options)
|
463
513
|
@input_directory = options[:input_directory] || Pathname.new(".")
|
464
514
|
@working_directory = options[:working_directory] || Pathname.new(".")
|
465
515
|
@groonga = groonga
|
466
516
|
@groonga_options = groonga_options
|
517
|
+
@groonga_env = groonga_env
|
467
518
|
@database_path = @working_directory + database_path
|
468
519
|
@host = "127.0.0.1"
|
469
520
|
@port = find_unused_port
|
@@ -473,17 +524,20 @@ module GroongaQueryLog
|
|
473
524
|
def run
|
474
525
|
return unless @options[:run_queries]
|
475
526
|
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
527
|
+
spawn_args = []
|
528
|
+
spawn_args << @groonga_env if @groonga_env
|
529
|
+
spawn_args << @groonga
|
530
|
+
spawn_args.concat(@groonga_options)
|
531
|
+
spawn_args.concat(["--bind-address", @host])
|
532
|
+
spawn_args.concat(["--port", @port.to_s])
|
533
|
+
spawn_args.concat(["--protocol", "http"])
|
534
|
+
spawn_args.concat(["--log-path", log_path.to_s])
|
481
535
|
if @options[:output_query_log]
|
482
|
-
|
536
|
+
spawn_args.concat(["--query-log-path", query_log_path.to_s])
|
483
537
|
end
|
484
|
-
|
485
|
-
|
486
|
-
@pid = spawn(
|
538
|
+
spawn_args << "-s"
|
539
|
+
spawn_args << @database_path.to_s
|
540
|
+
@pid = spawn(*spawn_args)
|
487
541
|
|
488
542
|
n_retries = 10
|
489
543
|
begin
|
@@ -552,6 +606,19 @@ module GroongaQueryLog
|
|
552
606
|
Process.waitpid(@pid)
|
553
607
|
end
|
554
608
|
|
609
|
+
def n_leaked_objects
|
610
|
+
n = 0
|
611
|
+
File.open(log_path) do |log|
|
612
|
+
log.each_line do |line|
|
613
|
+
case line
|
614
|
+
when /grn_fin \((\d+)\)/
|
615
|
+
n += Integer($1, 10)
|
616
|
+
end
|
617
|
+
end
|
618
|
+
end
|
619
|
+
n
|
620
|
+
end
|
621
|
+
|
555
622
|
private
|
556
623
|
def find_unused_port
|
557
624
|
server = TCPServer.new(@host, 0)
|
@@ -600,6 +667,8 @@ module GroongaQueryLog
|
|
600
667
|
class Tester
|
601
668
|
include Loggable
|
602
669
|
|
670
|
+
attr_reader :old
|
671
|
+
attr_reader :new
|
603
672
|
def initialize(old, new, options)
|
604
673
|
@old = old
|
605
674
|
@new = new
|
@@ -611,6 +680,7 @@ module GroongaQueryLog
|
|
611
680
|
@stop_on_failure = options[:stop_on_failure]
|
612
681
|
@options = options
|
613
682
|
@n_ready_waits = 2
|
683
|
+
@n_executed_commands = 0
|
614
684
|
end
|
615
685
|
|
616
686
|
def run
|
@@ -634,6 +704,10 @@ module GroongaQueryLog
|
|
634
704
|
old_thread_success and new_thread_success
|
635
705
|
end
|
636
706
|
|
707
|
+
def n_executed_commands
|
708
|
+
@n_executed_commands
|
709
|
+
end
|
710
|
+
|
637
711
|
private
|
638
712
|
def run_test
|
639
713
|
@n_ready_waits -= 1
|
@@ -737,6 +811,10 @@ module GroongaQueryLog
|
|
737
811
|
if @options[:debug_rewrite]
|
738
812
|
command_line << "--debug-rewrite"
|
739
813
|
end
|
814
|
+
if @options[:omit_rate] < 1.0
|
815
|
+
command_line << "--omit-rate"
|
816
|
+
command_line << @options[:omit_rate].to_s
|
817
|
+
end
|
740
818
|
if @options[:target_command_names]
|
741
819
|
command_line << "--target-command-names"
|
742
820
|
command_line << @options[:target_command_names].join(",")
|
@@ -752,7 +830,9 @@ module GroongaQueryLog
|
|
752
830
|
command_line << @options[:read_timeout].to_s
|
753
831
|
end
|
754
832
|
verify_server = VerifyServer.new
|
755
|
-
verify_server.run(command_line, &callback)
|
833
|
+
same = verify_server.run(command_line, &callback)
|
834
|
+
@n_executed_commands = verify_server.n_executed_commands
|
835
|
+
same
|
756
836
|
end
|
757
837
|
|
758
838
|
def query_log_paths
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# Copyright (C) 2013-2018 Kouhei Sutou <kou@clear-code.com>
|
2
|
+
# Copyright (C) 2020 Horimoto Yasuhiro <horimoto@clear-code.com>
|
2
3
|
#
|
3
4
|
# This library is free software; you can redistribute it and/or
|
4
5
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -22,8 +23,10 @@ require "groonga-query-log"
|
|
22
23
|
module GroongaQueryLog
|
23
24
|
module Command
|
24
25
|
class VerifyServer
|
26
|
+
attr_reader :n_executed_commands
|
25
27
|
def initialize
|
26
28
|
@options = ServerVerifier::Options.new
|
29
|
+
@n_executed_commands = 0
|
27
30
|
end
|
28
31
|
|
29
32
|
def run(command_line, &callback)
|
@@ -50,6 +53,7 @@ module GroongaQueryLog
|
|
50
53
|
end
|
51
54
|
end
|
52
55
|
end
|
56
|
+
@n_executed_commands = verifier.n_executed_commands
|
53
57
|
same
|
54
58
|
end
|
55
59
|
|
@@ -254,6 +258,14 @@ module GroongaQueryLog
|
|
254
258
|
@options.debug_rewrite = boolean
|
255
259
|
end
|
256
260
|
|
261
|
+
parser.on("--omit-rate=RATE", Float,
|
262
|
+
"You can specify rate for omitting execution queries." +
|
263
|
+
"For example, if you specify 0.9 in this option, " +
|
264
|
+
"execute queries with the probability of 1/10.",
|
265
|
+
"(#{@options.omit_rate})") do |rate|
|
266
|
+
@options.omit_rate = rate
|
267
|
+
end
|
268
|
+
|
257
269
|
parser.on("--nullable-reference-number-accessor=ACCESSOR",
|
258
270
|
"Mark ACCESSOR as rewrite nullable reference number targets",
|
259
271
|
"You can specify multiple accessors by",
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2013-
|
1
|
+
# Copyright (C) 2013-2020 Sutou Kouhei <kou@clear-code.com>
|
2
2
|
#
|
3
3
|
# This library is free software; you can redistribute it and/or
|
4
4
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -22,186 +22,218 @@ require "groonga/client"
|
|
22
22
|
require "groonga-query-log/parser"
|
23
23
|
|
24
24
|
module GroongaQueryLog
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
class Replayer
|
26
|
+
def initialize(options)
|
27
|
+
@options = options
|
28
|
+
@queue = SizedQueue.new(@options.request_queue_size)
|
29
|
+
@responses = Queue.new
|
30
|
+
end
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
32
|
+
def replay(input)
|
33
|
+
producer = run_producer(input)
|
34
|
+
consumers = run_consumers
|
35
|
+
response_logger = run_response_logger
|
36
|
+
producer.join
|
37
|
+
consumers.each(&:join)
|
38
|
+
response_logger.join
|
39
|
+
end
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
41
|
+
private
|
42
|
+
def run_producer(input)
|
43
|
+
Thread.new do
|
44
|
+
parser = Parser.new
|
45
|
+
id = 0
|
46
|
+
@options.create_request_output do |output|
|
47
|
+
parser.parse(input) do |statistic|
|
48
|
+
next if statistic.command.nil?
|
49
|
+
next unless target_command?(statistic.command)
|
50
|
+
# TODO: validate orignal_source is one line
|
51
|
+
output.puts(statistic.command.original_source)
|
52
|
+
output.flush
|
53
|
+
if @options.output_type
|
54
|
+
statistic.command[:output_type] ||= @options.output_type
|
54
55
|
end
|
55
|
-
|
56
|
-
|
57
|
-
@queue.push(nil)
|
56
|
+
@queue.push([id, statistic])
|
57
|
+
id += 1
|
58
58
|
end
|
59
59
|
end
|
60
|
+
@options.n_clients.times do
|
61
|
+
@queue.push(nil)
|
62
|
+
end
|
60
63
|
end
|
64
|
+
end
|
61
65
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
end
|
66
|
+
def run_consumers
|
67
|
+
@options.n_clients.times.collect do
|
68
|
+
Thread.new do
|
69
|
+
loop do
|
70
|
+
break if run_consumer
|
68
71
|
end
|
69
72
|
end
|
70
73
|
end
|
74
|
+
end
|
71
75
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
end
|
76
|
+
def run_consumer
|
77
|
+
@options.create_client do |client|
|
78
|
+
loop do
|
79
|
+
id, statistic = @queue.pop
|
80
|
+
if id.nil?
|
81
|
+
@responses.push(nil)
|
82
|
+
return true
|
83
|
+
end
|
84
|
+
begin
|
85
|
+
replay_command(client, id, statistic.command)
|
86
|
+
rescue Groonga::Client::Error
|
87
|
+
# TODO: add error log mechanism
|
88
|
+
$stderr.puts(Time.now.iso8601(6))
|
89
|
+
$stderr.puts(statistic.command.original_source)
|
90
|
+
$stderr.puts($!.raw_error.message)
|
91
|
+
$stderr.puts($!.raw_error.backtrace)
|
92
|
+
return false
|
93
|
+
rescue
|
94
|
+
# TODO: add error log mechanism
|
95
|
+
$stderr.puts(Time.now.iso8601(6))
|
96
|
+
$stderr.puts(statistic.command.original_source)
|
97
|
+
$stderr.puts($!.message)
|
98
|
+
$stderr.puts($!.backtrace)
|
99
|
+
return false
|
97
100
|
end
|
98
101
|
end
|
99
102
|
end
|
103
|
+
end
|
100
104
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
+
def replay_command(client, id, command)
|
106
|
+
command["cache"] = "no" if @options.disable_cache?
|
107
|
+
response = client.execute(command)
|
108
|
+
case command.output_type
|
109
|
+
when :json, :xml, :tsv
|
110
|
+
response.raw << "\n" unless response.raw.end_with?("\n")
|
105
111
|
end
|
112
|
+
@responses.push(response)
|
113
|
+
end
|
106
114
|
|
107
|
-
|
108
|
-
|
109
|
-
|
115
|
+
def run_response_logger
|
116
|
+
Thread.new do
|
117
|
+
@options.create_responses_output do |output|
|
118
|
+
@options.create_responses_output do |error_output|
|
110
119
|
loop do
|
111
120
|
response = @responses.pop
|
112
121
|
break if response.nil?
|
113
|
-
# TODO: ensure response is one line
|
114
122
|
# TODO: reorder by ID
|
115
|
-
output.
|
123
|
+
output.print(response.raw)
|
124
|
+
output.flush
|
125
|
+
unless response.success?
|
126
|
+
error_output.print(response.raw)
|
127
|
+
error_output.flush
|
128
|
+
end
|
116
129
|
end
|
117
130
|
end
|
118
131
|
end
|
119
132
|
end
|
133
|
+
end
|
120
134
|
|
121
|
-
|
122
|
-
|
123
|
-
|
135
|
+
def target_command?(command)
|
136
|
+
@options.target_command_name?(command.command_name)
|
137
|
+
end
|
124
138
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
end
|
139
|
+
class NullOutput
|
140
|
+
class << self
|
141
|
+
def open
|
142
|
+
output = new
|
143
|
+
if block_given?
|
144
|
+
yield(output)
|
145
|
+
else
|
146
|
+
output
|
134
147
|
end
|
135
148
|
end
|
149
|
+
end
|
136
150
|
|
137
|
-
|
138
|
-
end
|
151
|
+
def puts(string)
|
139
152
|
end
|
140
153
|
|
141
|
-
|
142
|
-
|
143
|
-
attr_accessor :port
|
144
|
-
attr_accessor :protocol
|
145
|
-
attr_accessor :read_timeout
|
146
|
-
attr_accessor :n_clients
|
147
|
-
attr_writer :request_queue_size
|
148
|
-
attr_writer :disable_cache
|
149
|
-
attr_accessor :target_command_names
|
150
|
-
attr_accessor :requests_path
|
151
|
-
attr_accessor :responses_path
|
152
|
-
def initialize
|
153
|
-
@host = "127.0.0.1"
|
154
|
-
@port = 10041
|
155
|
-
@protocol = :http
|
156
|
-
@read_timeout = Groonga::Client::Default::READ_TIMEOUT
|
157
|
-
@n_clients = 8
|
158
|
-
@request_queue_size = nil
|
159
|
-
@disable_cache = false
|
160
|
-
@requests_path = nil
|
161
|
-
@responses_path = nil
|
162
|
-
@target_command_names = []
|
163
|
-
end
|
154
|
+
def print(string)
|
155
|
+
end
|
164
156
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
:protocol => @protocol,
|
169
|
-
:read_timeout => @read_timeout,
|
170
|
-
&block)
|
171
|
-
end
|
157
|
+
def flush
|
158
|
+
end
|
159
|
+
end
|
172
160
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
161
|
+
class Options
|
162
|
+
attr_accessor :host
|
163
|
+
attr_accessor :port
|
164
|
+
attr_accessor :protocol
|
165
|
+
attr_accessor :read_timeout
|
166
|
+
attr_accessor :n_clients
|
167
|
+
attr_writer :request_queue_size
|
168
|
+
attr_writer :disable_cache
|
169
|
+
attr_accessor :target_command_names
|
170
|
+
attr_accessor :requests_path
|
171
|
+
attr_accessor :responses_path
|
172
|
+
attr_accessor :error_responses_path
|
173
|
+
attr_accessor :output_type
|
174
|
+
def initialize
|
175
|
+
@host = "127.0.0.1"
|
176
|
+
@port = 10041
|
177
|
+
@protocol = :http
|
178
|
+
@read_timeout = Groonga::Client::Default::READ_TIMEOUT
|
179
|
+
@n_clients = 8
|
180
|
+
@request_queue_size = nil
|
181
|
+
@disable_cache = false
|
182
|
+
@target_command_names = []
|
183
|
+
@requests_path = nil
|
184
|
+
@responses_path = nil
|
185
|
+
@error_responses_path = nil
|
186
|
+
@output_type = nil
|
187
|
+
end
|
180
188
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
189
|
+
def create_client(&block)
|
190
|
+
Groonga::Client.open(:host => @host,
|
191
|
+
:port => @port,
|
192
|
+
:protocol => @protocol,
|
193
|
+
:read_timeout => @read_timeout,
|
194
|
+
&block)
|
195
|
+
end
|
188
196
|
|
189
|
-
|
190
|
-
|
191
|
-
|
197
|
+
def create_request_output(&block)
|
198
|
+
create_output(@requests_path, &block)
|
199
|
+
end
|
200
|
+
|
201
|
+
def create_responses_output(&block)
|
202
|
+
create_output(@responses_path, &block)
|
203
|
+
end
|
192
204
|
|
193
|
-
|
194
|
-
|
205
|
+
def create_error_responses_output(&block)
|
206
|
+
create_output(@error_responses_path, &block)
|
207
|
+
end
|
208
|
+
|
209
|
+
def request_queue_size
|
210
|
+
@request_queue_size || @n_clients * 3
|
211
|
+
end
|
212
|
+
|
213
|
+
def disable_cache?
|
214
|
+
@disable_cache
|
215
|
+
end
|
216
|
+
|
217
|
+
def target_command_name?(name)
|
218
|
+
return true if @target_command_names.empty?
|
219
|
+
@target_command_names.any? do |name_pattern|
|
220
|
+
flags = 0
|
221
|
+
flags |= File::FNM_EXTGLOB if File.const_defined?(:FNM_EXTGLOB)
|
222
|
+
File.fnmatch(name_pattern, name, flags)
|
195
223
|
end
|
224
|
+
end
|
196
225
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
226
|
+
private
|
227
|
+
def create_output(path, &block)
|
228
|
+
case path
|
229
|
+
when nil
|
230
|
+
NullOutput.open(&block)
|
231
|
+
when "-"
|
232
|
+
yield($stdout)
|
233
|
+
else
|
234
|
+
File.open(path, "w", &block)
|
204
235
|
end
|
205
236
|
end
|
206
237
|
end
|
238
|
+
end
|
207
239
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# Copyright (C) 2013-2018 Kouhei Sutou <kou@clear-code.com>
|
2
|
+
# Copyright (C) 2020 Horimoto Yasuhiro <horimoto@clear-code.com>
|
2
3
|
#
|
3
4
|
# This library is free software; you can redistribute it and/or
|
4
5
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -26,10 +27,12 @@ require "groonga-query-log/response-comparer"
|
|
26
27
|
|
27
28
|
module GroongaQueryLog
|
28
29
|
class ServerVerifier
|
30
|
+
attr_reader :n_executed_commands
|
29
31
|
def initialize(options)
|
30
32
|
@options = options
|
31
33
|
@queue = SizedQueue.new(@options.request_queue_size)
|
32
34
|
@events = Queue.new
|
35
|
+
@n_executed_commands = 0
|
33
36
|
end
|
34
37
|
|
35
38
|
def verify(input, &callback)
|
@@ -50,7 +53,6 @@ module GroongaQueryLog
|
|
50
53
|
consumers = run_consumers
|
51
54
|
|
52
55
|
parser = Parser.new
|
53
|
-
n_commands = 0
|
54
56
|
callback_per_n_commands = 100
|
55
57
|
parser.parse(input) do |statistic|
|
56
58
|
break if stop?
|
@@ -58,10 +60,11 @@ module GroongaQueryLog
|
|
58
60
|
command = statistic.command
|
59
61
|
next if command.nil?
|
60
62
|
next unless target_command?(command)
|
61
|
-
|
63
|
+
next if rand < @options.omit_rate
|
64
|
+
@n_executed_commands += 1
|
62
65
|
@queue.push(statistic)
|
63
66
|
|
64
|
-
if callback and (
|
67
|
+
if callback and (@n_executed_commands % callback_per_n_commands).zero?
|
65
68
|
@options.n_clients.times do
|
66
69
|
@queue.push(nil)
|
67
70
|
end
|
@@ -283,6 +286,7 @@ module GroongaQueryLog
|
|
283
286
|
attr_writer :verify_performance
|
284
287
|
attr_reader :performance_verifier_options
|
285
288
|
attr_writer :debug_rewrite
|
289
|
+
attr_writer :omit_rate
|
286
290
|
def initialize
|
287
291
|
@groonga1 = GroongaOptions.new
|
288
292
|
@groonga2 = GroongaOptions.new
|
@@ -316,6 +320,7 @@ module GroongaQueryLog
|
|
316
320
|
@verify_performance = false
|
317
321
|
@performance_verifier_options = PerformanceVerifier::Options.new
|
318
322
|
@debug_rewrite = false
|
323
|
+
@omit_rate = 0.0
|
319
324
|
end
|
320
325
|
|
321
326
|
def request_queue_size
|
@@ -411,6 +416,10 @@ module GroongaQueryLog
|
|
411
416
|
def debug_rewrite?
|
412
417
|
@debug_rewrite
|
413
418
|
end
|
419
|
+
|
420
|
+
def omit_rate
|
421
|
+
@omit_rate
|
422
|
+
end
|
414
423
|
end
|
415
424
|
|
416
425
|
class GroongaOptions
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# Copyright (C) 2019 Kentaro Hayashi <hayashi@clear-code.com>
|
2
|
-
# Copyright (C) 2019 Horimoto Yasuhiro <horimoto@clear-code.com>
|
2
|
+
# Copyright (C) 2019-2020 Horimoto Yasuhiro <horimoto@clear-code.com>
|
3
3
|
#
|
4
4
|
# This library is free software; you can redistribute it and/or
|
5
5
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -26,6 +26,7 @@ class RunRegressionTestCommandTest < Test::Unit::TestCase
|
|
26
26
|
FileUtils.rm_rf(fixture_path("db.old"))
|
27
27
|
FileUtils.rm_rf(fixture_path("db.new"))
|
28
28
|
setup_smtp_server
|
29
|
+
@n_commands = 238
|
29
30
|
end
|
30
31
|
|
31
32
|
def teardown
|
@@ -90,6 +91,10 @@ class RunRegressionTestCommandTest < Test::Unit::TestCase
|
|
90
91
|
.gsub(/^Elapsed: \d+days \d{2}:\d{2}:\d{2}$/, "Elapsed: 0days 00:00:00")
|
91
92
|
end
|
92
93
|
|
94
|
+
def n_executed_commands(output)
|
95
|
+
output.slice(/^Number of executed commands:\s+(\d+)/, 1).to_i
|
96
|
+
end
|
97
|
+
|
93
98
|
def fixture_path(*components)
|
94
99
|
super("run-regression-test", *components)
|
95
100
|
end
|
@@ -105,11 +110,20 @@ class RunRegressionTestCommandTest < Test::Unit::TestCase
|
|
105
110
|
assert_equal([
|
106
111
|
true,
|
107
112
|
"Elapsed: 0days 00:00:00\n" +
|
113
|
+
"Number of executed commands: #{@n_commands}\n" +
|
108
114
|
"Success\n"
|
109
115
|
],
|
110
116
|
[success, normalize_output(output)])
|
111
117
|
end
|
112
118
|
|
119
|
+
def test_reduce_execution_query
|
120
|
+
command_line = ["--omit-rate=0.9"]
|
121
|
+
_success, output = run_command(command_line)
|
122
|
+
assert do
|
123
|
+
n_executed_commands(output) < (@n_commands * 0.2)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
113
127
|
def test_mail_from
|
114
128
|
success, _output = run_command(["--smtp-server", @smtp_host,
|
115
129
|
"--smtp-port", @smtp_port.to_s,
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: groonga-query-log
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
4
|
+
version: 1.5.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kouhei Sutou
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-04-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: charty
|
@@ -169,17 +169,17 @@ email:
|
|
169
169
|
- kou@clear-code.com
|
170
170
|
executables:
|
171
171
|
- groonga-query-log-analyze
|
172
|
-
- groonga-query-log-verify-server
|
173
|
-
- groonga-query-log-replay
|
174
|
-
- groonga-query-log-check-crash
|
175
|
-
- groonga-query-log-run-regression-test
|
176
172
|
- groonga-query-log-analyze-load
|
177
|
-
- groonga-query-log-show-running-queries
|
178
173
|
- groonga-query-log-check-command-version-compatibility
|
174
|
+
- groonga-query-log-check-crash
|
175
|
+
- groonga-query-log-check-performance-regression
|
179
176
|
- groonga-query-log-detect-memory-leak
|
180
177
|
- groonga-query-log-extract
|
181
178
|
- groonga-query-log-format-regression-test-logs
|
182
|
-
- groonga-query-log-
|
179
|
+
- groonga-query-log-replay
|
180
|
+
- groonga-query-log-run-regression-test
|
181
|
+
- groonga-query-log-show-running-queries
|
182
|
+
- groonga-query-log-verify-server
|
183
183
|
extensions: []
|
184
184
|
extra_rdoc_files: []
|
185
185
|
files:
|
@@ -314,7 +314,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
314
314
|
- !ruby/object:Gem::Version
|
315
315
|
version: '0'
|
316
316
|
requirements: []
|
317
|
-
rubygems_version: 3.
|
317
|
+
rubygems_version: 3.2.0.pre1
|
318
318
|
signing_key:
|
319
319
|
specification_version: 4
|
320
320
|
summary: Groonga-query-log is a collection of library and tools to process [Groonga](http://groonga.org/)'s
|
@@ -322,49 +322,49 @@ summary: Groonga-query-log is a collection of library and tools to process [Groo
|
|
322
322
|
as a library. You can analyze your Groonga's queries and test with your Groonga's
|
323
323
|
query log by using groonga-query-log as a tool.
|
324
324
|
test_files:
|
325
|
-
- test/
|
326
|
-
- test/test-
|
327
|
-
- test/test-
|
325
|
+
- test/command/test-analyzer.rb
|
326
|
+
- test/command/test-check-performance-regression.rb
|
327
|
+
- test/command/test-extract.rb
|
328
|
+
- test/command/test-format-regression-test-logs.rb
|
329
|
+
- test/command/test-run-regression-test.rb
|
330
|
+
- test/fixtures/check-performance-regression/cache.log
|
331
|
+
- test/fixtures/check-performance-regression/different_operations1.log
|
332
|
+
- test/fixtures/check-performance-regression/different_operations2.log
|
333
|
+
- test/fixtures/check-performance-regression/nquery.log
|
334
|
+
- test/fixtures/check-performance-regression/nquery2.log
|
335
|
+
- test/fixtures/check-performance-regression/query1.log
|
336
|
+
- test/fixtures/check-performance-regression/query2.log
|
337
|
+
- test/fixtures/multi.expected
|
328
338
|
- test/fixtures/n_entries.expected
|
329
|
-
- test/fixtures/
|
339
|
+
- test/fixtures/no-report-summary.expected
|
330
340
|
- test/fixtures/order/-elapsed.expected
|
331
341
|
- test/fixtures/order/-start-time.expected
|
342
|
+
- test/fixtures/order/elapsed.expected
|
332
343
|
- test/fixtures/order/start-time.expected
|
333
|
-
- test/fixtures/target-tables.expected
|
334
344
|
- test/fixtures/other-query.log
|
335
|
-
- test/fixtures/
|
336
|
-
- test/fixtures/
|
337
|
-
- test/fixtures/check-performance-regression/nquery.log
|
338
|
-
- test/fixtures/check-performance-regression/query1.log
|
339
|
-
- test/fixtures/check-performance-regression/different_operations1.log
|
340
|
-
- test/fixtures/check-performance-regression/nquery2.log
|
341
|
-
- test/fixtures/check-performance-regression/cache.log
|
342
|
-
- test/fixtures/regression-test-logs/url-format.log
|
345
|
+
- test/fixtures/query.log
|
346
|
+
- test/fixtures/regression-test-logs/command-format.log
|
343
347
|
- test/fixtures/regression-test-logs/error.log
|
344
348
|
- test/fixtures/regression-test-logs/slow.log
|
345
|
-
- test/fixtures/regression-test-logs/
|
349
|
+
- test/fixtures/regression-test-logs/url-format.log
|
350
|
+
- test/fixtures/reporter/console.expected
|
351
|
+
- test/fixtures/reporter/html.expected
|
352
|
+
- test/fixtures/reporter/json-stream.expected
|
353
|
+
- test/fixtures/reporter/json.expected
|
354
|
+
- test/fixtures/run-regression-test/data/data.grn
|
346
355
|
- test/fixtures/run-regression-test/indexes/indexes.grn
|
356
|
+
- test/fixtures/run-regression-test/mail-notifier/failure.log
|
357
|
+
- test/fixtures/run-regression-test/mail-notifier/success.log
|
358
|
+
- test/fixtures/run-regression-test/query-logs/query.log
|
347
359
|
- test/fixtures/run-regression-test/results/query.log.log
|
348
|
-
- test/fixtures/run-regression-test/data/data.grn
|
349
360
|
- test/fixtures/run-regression-test/schema/schema.grn
|
350
|
-
- test/fixtures/run-regression-test/query-logs/query.log
|
351
|
-
- test/fixtures/run-regression-test/mail-notifier/success.log
|
352
|
-
- test/fixtures/run-regression-test/mail-notifier/failure.log
|
353
361
|
- test/fixtures/target-commands.expected
|
354
|
-
- test/fixtures/
|
355
|
-
- test/
|
356
|
-
- test/fixtures/no-report-summary.expected
|
357
|
-
- test/fixtures/reporter/html.expected
|
358
|
-
- test/fixtures/reporter/json.expected
|
359
|
-
- test/fixtures/reporter/console.expected
|
360
|
-
- test/fixtures/reporter/json-stream.expected
|
362
|
+
- test/fixtures/target-tables.expected
|
363
|
+
- test/helper.rb
|
361
364
|
- test/run-test.rb
|
362
|
-
- test/test-
|
365
|
+
- test/test-filter-rewriter.rb
|
363
366
|
- test/test-incompatibility-detector.rb
|
367
|
+
- test/test-parser.rb
|
368
|
+
- test/test-performance-verifier.rb
|
364
369
|
- test/test-replayer.rb
|
365
|
-
- test/command/test-run-regression-test.rb
|
366
|
-
- test/command/test-format-regression-test-logs.rb
|
367
|
-
- test/command/test-extract.rb
|
368
|
-
- test/command/test-analyzer.rb
|
369
|
-
- test/command/test-check-performance-regression.rb
|
370
370
|
- test/test-response-comparer.rb
|