groonga-query-log 1.0.1 → 1.0.2

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0f47438cd5625ffcd0af39cc2d693f46df36fdd6
4
+ data.tar.gz: 039a16dd1e43c33fb2b9e6645152d20db726c0c0
5
+ SHA512:
6
+ metadata.gz: 69c52b48f51b1fe85f193a3426b340ebff7adfffc8f4f15416310ebb40e8b42e1930d17caa1dd733e4f229dd74661ff445c3ff5821a3142967bdb59686a477d3
7
+ data.tar.gz: 433ff8fbfa3bfddaf220a6311022459925b2c92082982bc6e959618d3b57fd88f2291154ee3352900d46c1cc00d56012a5f30641d188e73821e9399113287a62
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  # -*- mode: ruby; coding: utf-8 -*-
2
2
  #
3
- # Copyright (C) 2012 Kouhei Sutou <kou@clear-code.com>
3
+ # Copyright (C) 2012-2013 Kouhei Sutou <kou@clear-code.com>
4
4
  #
5
5
  # This library is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU Lesser General Public
@@ -16,6 +16,6 @@
16
16
  # License along with this library; if not, write to the Free Software
17
17
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 
19
- source :rubygems
19
+ source "https://rubygems.org/"
20
20
 
21
21
  gemspec
data/README.md CHANGED
@@ -1,12 +1,14 @@
1
1
  # README
2
2
 
3
+ [![Build Status](https://travis-ci.org/groonga/groonga-query-log.png?branch=master)](https://travis-ci.org/groonga/groonga-query-log)
4
+
3
5
  ## Name
4
6
 
5
7
  groonga-query-log
6
8
 
7
9
  ## Description
8
10
 
9
- Groonga-query-log is a collection of libarary and tools to process
11
+ Groonga-query-log is a collection of library and tools to process
10
12
  [groonga](http://groonga.org/)'s query log. You can write a program to
11
13
  process query log by using groonga-query-log as a library. You can
12
14
  analyze your groonga's queries and test with your groonga's query log
data/Rakefile CHANGED
@@ -34,7 +34,7 @@ spec = helper.gemspec
34
34
 
35
35
  Packnga::DocumentTask.new(spec) do |task|
36
36
  task.original_language = "en"
37
- task.translate_languages = "ja"
37
+ task.translate_languages = ["ja"]
38
38
  end
39
39
 
40
40
  Packnga::ReleaseTask.new(spec) do
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ #
4
+ # Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com>
5
+ #
6
+ # This library is free software; you can redistribute it and/or
7
+ # modify it under the terms of the GNU Lesser General Public
8
+ # License as published by the Free Software Foundation; either
9
+ # version 2.1 of the License, or (at your option) any later version.
10
+ #
11
+ # This library is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ # Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public
17
+ # License along with this library; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+
20
+ require "groonga/query-log/command/detect-memory-leak"
21
+
22
+ detect_memory_leak_command = Groonga::QueryLog::Command::DetectMemoryLeak.new
23
+ detect_memory_leak_command.run(*ARGV)
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ #
4
+ # Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com>
5
+ #
6
+ # This library is free software; you can redistribute it and/or
7
+ # modify it under the terms of the GNU Lesser General Public
8
+ # License as published by the Free Software Foundation; either
9
+ # version 2.1 of the License, or (at your option) any later version.
10
+ #
11
+ # This library is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ # Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public
17
+ # License along with this library; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+
20
+ require "groonga/query-log/command/replay"
21
+
22
+ replay_command = Groonga::QueryLog::Command::Replay.new
23
+ replay_command.run(*ARGV)
@@ -1,5 +1,20 @@
1
1
  # News
2
2
 
3
+ ## 1.0.2: 2013-11-01
4
+
5
+ ### Improvements
6
+
7
+ * [GitHub#1] Add Travis CI status image to README.
8
+ Patch by Kengo Suzuki. Thanks!!!
9
+ * Dropped Ruby 1.8 support.
10
+ * Added groonga-query-log-replay that replays queries in query log.
11
+ * Added groonga-query-log-detect-memory-leak that detects
12
+ a memory leak by executing each query in query log.
13
+
14
+ ### Thanks
15
+
16
+ * Kengo Suzuki
17
+
3
18
  ## 1.0.1: 2012-12-21
4
19
 
5
20
  ### Improvements
@@ -1,6 +1,6 @@
1
1
  # -*- mode: ruby; coding: utf-8 -*-
2
2
  #
3
- # Copyright (C) 2012 Kouhei Sutou <kou@clear-code.com>
3
+ # Copyright (C) 2012-2013 Kouhei Sutou <kou@clear-code.com>
4
4
  #
5
5
  # This library is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU Lesser General Public
@@ -52,10 +52,12 @@ Gem::Specification.new do |spec|
52
52
  spec.licenses = ["LGPLv2.1+"]
53
53
  spec.require_paths = ["lib"]
54
54
 
55
- spec.add_runtime_dependency("groonga-command")
55
+ spec.add_runtime_dependency("groonga-command-parser")
56
+ spec.add_runtime_dependency("groonga-client")
56
57
 
57
58
  spec.add_development_dependency("test-unit")
58
59
  spec.add_development_dependency("test-unit-notify")
60
+ spec.add_development_dependency("test-unit-rr")
59
61
  spec.add_development_dependency("rake")
60
62
  spec.add_development_dependency("bundler")
61
63
  spec.add_development_dependency("packnga")
@@ -20,3 +20,4 @@ require "groonga/query-log/version"
20
20
  require "groonga/query-log/analyzer"
21
21
  require "groonga/query-log/extractor"
22
22
  require "groonga/query-log/parser"
23
+ require "groonga/query-log/replayer"
@@ -174,9 +174,9 @@ module Groonga
174
174
 
175
175
  parser.on("--slow-response-threshold=THRESHOLD",
176
176
  Float,
177
- "Use THRESHOLD seconds to detect slow operations.",
178
- "(#{@options[:sloq_response_threshold]})") do |threshold|
179
- @options[:sloq_response_threshold] = threshold
177
+ "Use THRESHOLD seconds to detect slow responses.",
178
+ "(#{@options[:slow_response_threshold]})") do |threshold|
179
+ @options[:slow_response_threshold] = threshold
180
180
  end
181
181
 
182
182
  available_reporters = ["console", "json", "html"]
@@ -54,6 +54,7 @@ module Groonga
54
54
 
55
55
  def report_statistic(statistic)
56
56
  command = statistic.command
57
+ _ = command # XXX: suppress warning
57
58
  statistic_html = erb(<<-EOH, __LINE__ + 1, binding)
58
59
  <div class="statistic-heading">
59
60
  <h3>Command</h3>
@@ -16,7 +16,7 @@
16
16
  # License along with this library; if not, write to the Free Software
17
17
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 
19
- require "groonga/command"
19
+ require "groonga/command/parser"
20
20
 
21
21
  module Groonga
22
22
  module QueryLog
@@ -0,0 +1,90 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com>
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License as published by the Free Software Foundation; either
8
+ # version 2.1 of the License, or (at your option) any later version.
9
+ #
10
+ # This library is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public
16
+ # License along with this library; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+
19
+ require "optparse"
20
+
21
+ require "groonga/query-log/memory-leak-detector"
22
+
23
+ module Groonga
24
+ module QueryLog
25
+ module Command
26
+ class DetectMemoryLeak
27
+ def initialize
28
+ @options = MemoryLeakDetector::Options.new
29
+ end
30
+
31
+ def run(*command_line)
32
+ input_paths = create_parser.parse(*command_line)
33
+ detector = MemoryLeakDetector.new(@options)
34
+ input_paths.each do |input_path|
35
+ File.open(input_path) do |input|
36
+ detector.detect(input)
37
+ end
38
+ end
39
+ end
40
+
41
+ private
42
+ def create_parser
43
+ parser = OptionParser.new
44
+ parser.banner += " QUERY_LOG"
45
+
46
+ parser.separator("")
47
+ parser.separator("Options:")
48
+
49
+ parser.on("--host=HOST",
50
+ "Host name or IP address of groonga server",
51
+ "[#{@options.host}]") do |host|
52
+ @options.host = host
53
+ end
54
+
55
+ parser.on("--port=PORT", Integer,
56
+ "Port number of groonga server",
57
+ "[#{@options.port}]") do |port|
58
+ @options.port = port
59
+ end
60
+
61
+ available_protocols = [:gqtp, :http]
62
+ available_protocols_label = "[#{available_protocols.join(', ')}]"
63
+ parser.on("--protocol=PROTOCOL", available_protocols,
64
+ "Protocol of groonga server",
65
+ available_protocols_label) do |protocol|
66
+ @options.protocol = protocol
67
+ end
68
+
69
+ parser.on("--pid=PID",
70
+ "The PID of groonga server",
71
+ "[#{@options.pid}]") do |pid|
72
+ @options.pid = pid
73
+ end
74
+
75
+ parser.on("--n-tries=N", Integer,
76
+ "The number of the same request tries",
77
+ "[#{@options.n_tries}]") do |n|
78
+ @options.n_tries = n
79
+ end
80
+
81
+ parser.on("--[no-]force-disable-cache",
82
+ "Force disable cache of select command by cache=no parameter",
83
+ "[#{@options.force_disable_cache?}]") do |boolean|
84
+ @options.force_disable_cache = boolean
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,117 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com>
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License as published by the Free Software Foundation; either
8
+ # version 2.1 of the License, or (at your option) any later version.
9
+ #
10
+ # This library is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public
16
+ # License along with this library; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+
19
+ require "optparse"
20
+
21
+ require "groonga/query-log/replayer"
22
+
23
+ module Groonga
24
+ module QueryLog
25
+ module Command
26
+ class Replay
27
+ def initialize
28
+ @options = Replayer::Options.new
29
+ end
30
+
31
+ def run(*command_line)
32
+ input_paths = create_parser.parse(*command_line)
33
+ replayer = Replayer.new(@options)
34
+ input_paths.each do |input_path|
35
+ File.open(input_path) do |input|
36
+ replayer.replay(input)
37
+ end
38
+ end
39
+ end
40
+
41
+ private
42
+ def create_parser
43
+ parser = OptionParser.new
44
+ parser.banner += " QUERY_LOG"
45
+
46
+ parser.separator("")
47
+ parser.separator("Options:")
48
+
49
+ parser.on("--host=HOST",
50
+ "Host name or IP address of groonga server",
51
+ "[#{@options.host}]") do |host|
52
+ @options.host = host
53
+ end
54
+
55
+ parser.on("--port=PORT", Integer,
56
+ "Port number of groonga server",
57
+ "[#{@options.port}]") do |port|
58
+ @options.port = port
59
+ end
60
+
61
+ available_protocols = [:gqtp, :http]
62
+ available_protocols_label = "[#{available_protocols.join(', ')}]"
63
+ parser.on("--protocol=PROTOCOL", available_protocols,
64
+ "Protocol of groonga server",
65
+ available_protocols_label) do |protocol|
66
+ @options.protocol = protocol
67
+ end
68
+
69
+ parser.on("--n-clients=N", Integer,
70
+ "The max number of concurrency",
71
+ "[#{@options.n_clients}]") do |n_clients|
72
+ @options.n_cilents = n_clients
73
+ end
74
+
75
+ parser.on("--request-queue-size=SIZE", Integer,
76
+ "The size of request queue",
77
+ "[auto]") do |size|
78
+ @options.request_queue_size = size
79
+ end
80
+
81
+ parser.on("--disable-cache",
82
+ "Add 'cache=no' parameter to request",
83
+ "[#{@options.disable_cache?}]") do
84
+ @options.disable_cache = true
85
+ end
86
+
87
+ parser.on("--target-command-name=NAME",
88
+ "Add NAME to target command names",
89
+ "You can specify this option zero or more times",
90
+ "See also --target-command-names") do |name|
91
+ @options.target_command_names << name
92
+ end
93
+
94
+ target_command_names_label = @options.target_command_names.join(", ")
95
+ parser.on("--target-command-names=NAME1,NAME2,...", Array,
96
+ "Replay only NAME1,NAME2,... commands",
97
+ "You can use glob to choose command name",
98
+ "[#{target_command_names_label}]") do |names|
99
+ @options.target_command_names = names
100
+ end
101
+
102
+ parser.on("--output-requests=PATH",
103
+ "Output requests to PATH",
104
+ "[not output]") do |path|
105
+ @options.requests_path = path
106
+ end
107
+
108
+ parser.on("--output-responses=PATH",
109
+ "Output responses to PATH",
110
+ "[not output]") do |path|
111
+ @options.responses_path = path
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
@@ -170,15 +170,15 @@ module Groonga
170
170
 
171
171
  def target?(command)
172
172
  name = command.name
173
- commands = @options.commands
173
+ target_commands = @options.commands
174
174
  exclude_commands = @options.exclude_commands
175
175
 
176
- unless commands.empty?
177
- return commands.any? {|command| command === name}
176
+ unless target_commands.empty?
177
+ return target_commands.any? {|target_command| target_command === name}
178
178
  end
179
179
 
180
180
  unless exclude_commands.empty?
181
- return (not exclude_commands.any? {|command| command === name})
181
+ return (not exclude_commands.any? {|exclude_command| exclude_command === name})
182
182
  end
183
183
 
184
184
  true
@@ -0,0 +1,126 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com>
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License as published by the Free Software Foundation; either
8
+ # version 2.1 of the License, or (at your option) any later version.
9
+ #
10
+ # This library is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public
16
+ # License along with this library; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+
19
+ require "time"
20
+
21
+ require "groonga/client"
22
+
23
+ require "groonga/query-log/parser"
24
+
25
+ module Groonga
26
+ module QueryLog
27
+ class MemoryLeakDetector
28
+ def initialize(options)
29
+ @options = options
30
+ end
31
+
32
+ def detect(input)
33
+ each_command(input) do |command|
34
+ @options.create_client do |client|
35
+ begin
36
+ check_command(client, command)
37
+ rescue Groonga::Client::Connection::Error
38
+ # TODO: add error log mechanism
39
+ $stderr.puts(Time.now.iso8601)
40
+ $stderr.puts(command.original_source)
41
+ $stderr.puts($!.raw_error.message)
42
+ $stderr.puts($!.raw_error.backtrace)
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ private
49
+ def each_command(input)
50
+ parser = Parser.new
51
+ parser.parse(input) do |statistic|
52
+ yield(statistic.command)
53
+ end
54
+ end
55
+
56
+ def check_command(client, command)
57
+ command["cache"] = "no" if @options.force_disable_cache?
58
+ current_n_allocations = nil
59
+ @options.n_tries.times do |i|
60
+ client.execute(command)
61
+ previous_n_allocations = current_n_allocations
62
+ current_n_allocations = n_allocations(client)
63
+ next if previous_n_allocations.nil?
64
+ if current_n_allocations > previous_n_allocations
65
+ max_n_digits = [
66
+ compute_n_digits(previous_n_allocations),
67
+ compute_n_digits(current_n_allocations),
68
+ ].max
69
+ puts("detect a memory leak:")
70
+ puts("Nth try: #{i}")
71
+ puts("previous: %*d" % [max_n_digits, previous_n_allocations])
72
+ puts(" current: %*d" % [max_n_digits, current_n_allocations])
73
+ puts(command.original_source)
74
+ end
75
+ end
76
+ end
77
+
78
+ def n_allocations(client)
79
+ client.status.n_allocations
80
+ end
81
+
82
+ def compute_n_digits(n)
83
+ (Math.log10(n) + 1).floor
84
+ end
85
+
86
+ class Options
87
+ attr_accessor :host
88
+ attr_accessor :port
89
+ attr_accessor :protocol
90
+ attr_accessor :pid
91
+ attr_accessor :n_tries
92
+ attr_writer :force_disable_cache
93
+ def initialize
94
+ @host = "127.0.0.1"
95
+ @port = 10041
96
+ @protocol = :gqtp
97
+ @pid = guess_groonga_server_pid
98
+ @n_tries = 10
99
+ @force_disable_cache = true
100
+ end
101
+
102
+ def force_disable_cache?
103
+ @force_disable_cache
104
+ end
105
+
106
+ def create_client(&block)
107
+ Groonga::Client.open(:host => @host,
108
+ :port => @port,
109
+ :protocol => @protocol,
110
+ &block)
111
+ end
112
+
113
+ private
114
+ def guess_groonga_server_pid
115
+ # This command line works only for ps by procps.
116
+ pid = `ps -o pid --no-header -C groonga`.strip
117
+ if pid.empty?
118
+ nil
119
+ else
120
+ pid.to_i
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end