groonga-query-log 1.5.8 → 1.5.9
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.
- 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
|