groonga-query-log 1.2.8 → 1.2.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/bin/groonga-query-log-analyze +3 -4
  3. data/bin/groonga-query-log-analyze-load +22 -0
  4. data/bin/groonga-query-log-check-command-version-compatibility +2 -2
  5. data/bin/groonga-query-log-check-crash +22 -0
  6. data/bin/groonga-query-log-detect-memory-leak +2 -2
  7. data/bin/groonga-query-log-extract +2 -2
  8. data/bin/groonga-query-log-format-regression-test-logs +2 -2
  9. data/bin/groonga-query-log-replay +3 -5
  10. data/bin/groonga-query-log-run-regression-test +2 -2
  11. data/bin/groonga-query-log-show-running-queries +2 -2
  12. data/bin/groonga-query-log-verify-server +2 -2
  13. data/doc/text/news.md +31 -0
  14. data/groonga-query-log.gemspec +5 -4
  15. data/lib/groonga-query-log.rb +42 -0
  16. data/lib/{groonga/query-log/command-line-utils.rb → groonga-query-log/command-line.rb} +25 -13
  17. data/lib/{groonga/query-log → groonga-query-log}/command-version-compatibility-checker.rb +3 -5
  18. data/lib/groonga-query-log/command/analyze-load.rb +188 -0
  19. data/lib/{groonga/query-log → groonga-query-log/command}/analyzer.rb +60 -44
  20. data/lib/{groonga/query-log → groonga-query-log/command}/analyzer/reporter.rb +15 -20
  21. data/lib/{groonga/query-log → groonga-query-log/command}/analyzer/reporter/console.rb +19 -18
  22. data/lib/groonga-query-log/command/analyzer/reporter/csv.rb +77 -0
  23. data/lib/{groonga/query-log → groonga-query-log/command}/analyzer/reporter/html.rb +32 -16
  24. data/lib/{groonga/query-log → groonga-query-log/command}/analyzer/reporter/json-stream.rb +4 -6
  25. data/lib/{groonga/query-log → groonga-query-log/command}/analyzer/reporter/json.rb +7 -7
  26. data/lib/{groonga/query-log → groonga-query-log/command}/analyzer/sized-grouped-operations.rb +3 -5
  27. data/lib/{groonga/query-log → groonga-query-log/command}/analyzer/sized-statistics.rb +4 -6
  28. data/lib/{groonga/query-log → groonga-query-log/command}/analyzer/streamer.rb +4 -6
  29. data/lib/groonga-query-log/command/check-command-version-compatibility.rb +69 -0
  30. data/lib/groonga-query-log/command/check-crash.rb +169 -0
  31. data/lib/groonga-query-log/command/detect-memory-leak.rb +89 -0
  32. data/lib/groonga-query-log/command/extract.rb +171 -0
  33. data/lib/groonga-query-log/command/format-regression-test-logs.rb +143 -0
  34. data/lib/groonga-query-log/command/replay.rb +117 -0
  35. data/lib/groonga-query-log/command/run-regression-test.rb +432 -0
  36. data/lib/groonga-query-log/command/show-running-queries.rb +78 -0
  37. data/lib/{groonga/query-log/command/replay.rb → groonga-query-log/command/verify-server.rb} +68 -37
  38. data/lib/{groonga/query-log → groonga-query-log}/incompatibility-detector.rb +3 -5
  39. data/lib/{groonga/query-log → groonga-query-log}/memory-leak-detector.rb +3 -7
  40. data/lib/groonga-query-log/parser.rb +173 -0
  41. data/lib/{groonga/query-log → groonga-query-log}/replayer.rb +7 -8
  42. data/lib/{groonga/query-log → groonga-query-log}/response-comparer.rb +3 -5
  43. data/lib/{groonga/query-log → groonga-query-log}/server-verifier.rb +3 -5
  44. data/lib/groonga-query-log/statistic.rb +192 -0
  45. data/lib/{groonga/query-log → groonga-query-log}/version.rb +2 -4
  46. data/lib/groonga/query-log.rb +21 -9
  47. data/lib/groonga/query-log/command/analyzer.rb +18 -0
  48. data/lib/groonga/query-log/command/check-command-version-compatibility.rb +2 -55
  49. data/lib/groonga/query-log/command/detect-memory-leak.rb +3 -78
  50. data/lib/groonga/query-log/command/extract.rb +5 -179
  51. data/lib/groonga/query-log/command/format-regression-test-logs.rb +3 -130
  52. data/lib/groonga/query-log/command/reply.rb +18 -0
  53. data/lib/groonga/query-log/command/run-regression-test.rb +2 -418
  54. data/lib/groonga/query-log/command/show-running-queries.rb +3 -65
  55. data/lib/groonga/query-log/command/verify-server.rb +2 -137
  56. data/test/{test-analyzer.rb → command/test-analyzer.rb} +17 -11
  57. data/test/command/test-extract.rb +9 -18
  58. data/test/command/test-format-regression-test-logs.rb +3 -3
  59. data/test/fixtures/reporter/html.expected +55 -20
  60. data/test/helper.rb +22 -7
  61. data/test/test-incompatibility-detector.rb +3 -3
  62. data/test/test-parser.rb +19 -4
  63. data/test/test-replayer.rb +4 -4
  64. data/test/test-response-comparer.rb +2 -2
  65. metadata +86 -97
  66. data/lib/groonga/query-log/analyzer/statistic.rb +0 -194
  67. data/lib/groonga/query-log/parser.rb +0 -125
  68. data/test/fixtures/run-regression-test/db.new/db +0 -0
  69. data/test/fixtures/run-regression-test/db.new/db.0000000 +0 -0
  70. data/test/fixtures/run-regression-test/db.new/db.0000100 +0 -0
  71. data/test/fixtures/run-regression-test/db.new/db.0000101 +0 -0
  72. data/test/fixtures/run-regression-test/db.new/db.0000102 +0 -0
  73. data/test/fixtures/run-regression-test/db.new/db.0000103 +0 -0
  74. data/test/fixtures/run-regression-test/db.new/db.0000103.c +0 -0
  75. data/test/fixtures/run-regression-test/db.new/db.001 +0 -0
  76. data/test/fixtures/run-regression-test/db.new/db.conf +0 -0
  77. data/test/fixtures/run-regression-test/db.new/groonga.log +0 -165
  78. data/test/fixtures/run-regression-test/db.old/db +0 -0
  79. data/test/fixtures/run-regression-test/db.old/db.0000000 +0 -0
  80. data/test/fixtures/run-regression-test/db.old/db.0000100 +0 -0
  81. data/test/fixtures/run-regression-test/db.old/db.0000101 +0 -0
  82. data/test/fixtures/run-regression-test/db.old/db.0000102 +0 -0
  83. data/test/fixtures/run-regression-test/db.old/db.0000103 +0 -0
  84. data/test/fixtures/run-regression-test/db.old/db.0000103.c +0 -0
  85. data/test/fixtures/run-regression-test/db.old/db.001 +0 -0
  86. data/test/fixtures/run-regression-test/db.old/db.conf +0 -0
  87. data/test/fixtures/run-regression-test/db.old/groonga.log +0 -79
  88. data/test/fixtures/run-regression-test/results/query.log +0 -0
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2011-2016 Kouhei Sutou <kou@clear-code.com>
1
+ # Copyright (C) 2011-2018 Kouhei Sutou <kou@clear-code.com>
2
2
  # Copyright (C) 2012 Haruka Yoshihara <yoshihara@clear-code.com>
3
3
  #
4
4
  # This library is free software; you can redistribute it and/or
@@ -17,26 +17,13 @@
17
17
 
18
18
  require "optparse"
19
19
  require "json"
20
- require "groonga/query-log/command-line-utils"
21
- require "groonga/query-log/parser"
22
- require "groonga/query-log/analyzer/streamer"
23
- require "groonga/query-log/analyzer/sized-statistics"
24
- require "groonga/query-log/analyzer/reporter/console"
25
- require "groonga/query-log/analyzer/reporter/html"
26
- require "groonga/query-log/analyzer/reporter/json"
27
- require "groonga/query-log/analyzer/reporter/json-stream"
28
20
 
29
- module Groonga
30
- module QueryLog
31
- class Analyzer
32
- include CommandLineUtils
33
-
34
- class Error < StandardError
35
- end
36
-
37
- class NoInputError < Error
38
- end
21
+ require "groonga-query-log"
22
+ require "groonga-query-log/command-line"
39
23
 
24
+ module GroongaQueryLog
25
+ module Command
26
+ class Analyzer < CommandLine
40
27
  class UnsupportedReporter < Error
41
28
  end
42
29
 
@@ -44,11 +31,11 @@ module Groonga
44
31
  setup_options
45
32
  end
46
33
 
47
- # Executes analyzer for groonga's query logs.
34
+ # Executes analyzer for Groonga's query logs.
48
35
  # "groonga-query-log-analyze" command run this method.
49
36
  #
50
37
  # @example
51
- # analyzer = Groonga::QueryLog::Analyzer.new
38
+ # analyzer = GroongaQueryLog::Command::Analyzer.new
52
39
  # analyzer.run("--output", "statistics.html",
53
40
  # "--reporter", "html",
54
41
  # "query.log")
@@ -60,7 +47,12 @@ module Groonga
60
47
  # groonga-query-log-analyze. Please execute
61
48
  # "groonga-query-log-analyze --help" or see #setup_options.
62
49
  def run(arguments)
63
- log_paths = @option_parser.parse!(arguments)
50
+ begin
51
+ log_paths = @option_parser.parse!(arguments)
52
+ rescue OptionParser::InvalidOption => error
53
+ $stderr.puts(error)
54
+ return false
55
+ end
64
56
 
65
57
  stream = @options[:stream]
66
58
  dynamic_sort = @options[:dynamic_sort]
@@ -68,11 +60,12 @@ module Groonga
68
60
  statistics.apply_options(@options)
69
61
  if stream
70
62
  reporter = create_reporter(statistics)
71
- reporter.apply_options(@options)
72
63
  streamer = Streamer.new(reporter)
73
64
  streamer.start
74
65
  process_statistic = lambda do |statistic|
75
- streamer << statistic
66
+ if @options[:stream_all] or statistic.slow?
67
+ streamer << statistic
68
+ end
76
69
  end
77
70
  elsif dynamic_sort
78
71
  process_statistic = lambda do |statistic|
@@ -89,6 +82,9 @@ module Groonga
89
82
  parse(log_paths, &process_statistic)
90
83
  rescue Interrupt
91
84
  raise unless stream
85
+ rescue Error
86
+ $stderr.puts($!.message)
87
+ return false
92
88
  end
93
89
 
94
90
  if stream
@@ -97,7 +93,6 @@ module Groonga
97
93
  statistics.replace(full_statistics) unless dynamic_sort
98
94
 
99
95
  reporter = create_reporter(statistics)
100
- reporter.apply_options(@options)
101
96
  reporter.report
102
97
  end
103
98
 
@@ -118,7 +113,9 @@ module Groonga
118
113
  @options[:reporter] = "console"
119
114
  @options[:dynamic_sort] = true
120
115
  @options[:stream] = false
116
+ @options[:stream_all] = false
121
117
  @options[:report_summary] = true
118
+ @options[:report_command_line] = nil
122
119
 
123
120
  @option_parser = OptionParser.new do |parser|
124
121
  parser.version = VERSION
@@ -197,7 +194,13 @@ module Groonga
197
194
  @options[:target_tables] = tables
198
195
  end
199
196
 
200
- available_reporters = ["console", "json", "json-stream", "html"]
197
+ available_reporters = [
198
+ "console",
199
+ "csv",
200
+ "html",
201
+ "json",
202
+ "json-stream",
203
+ ]
201
204
  parser.on("--reporter=REPORTER",
202
205
  available_reporters,
203
206
  "Reports statistics by REPORTER.",
@@ -220,42 +223,55 @@ module Groonga
220
223
  @options[:stream] = stream
221
224
  end
222
225
 
226
+ parser.on("--[no-]stream-all",
227
+ "Outputs all analyzed queries in stream mode.",
228
+ "NOTE: This implies --stream.",
229
+ "(#{@options[:stream_all]})") do |stream_all|
230
+ @options[:stream] = stream_all
231
+ @options[:stream_all] = stream_all
232
+ end
233
+
223
234
  parser.on("--[no-]report-summary",
224
235
  "Reports summary at the end.",
225
236
  "(#{@options[:report_summary]})") do |report_summary|
226
237
  @options[:report_summary] = report_summary
227
238
  end
239
+
240
+ parser.on("--[no-]report-command-line",
241
+ "Reports command line.",
242
+ "(false for CSV reporter, true otherwise)") do |report|
243
+ @options[:report_command_line] = report
244
+ end
228
245
  end
229
246
  end
230
247
 
231
248
  def create_reporter(statistics)
232
249
  case @options[:reporter]
250
+ when "csv"
251
+ CSVReporter.new(statistics, @options)
252
+ when "html"
253
+ HTMLReporter.new(statistics, @options)
233
254
  when "json"
234
- JSONReporter.new(statistics)
255
+ JSONReporter.new(statistics, @options)
235
256
  when "json-stream"
236
- JSONStreamReporter.new(statistics)
237
- when "html"
238
- HTMLReporter.new(statistics)
257
+ JSONStreamReporter.new(statistics, @options)
239
258
  else
240
- ConsoleReporter.new(statistics)
259
+ ConsoleReporter.new(statistics, @options)
241
260
  end
242
261
  end
243
262
 
244
263
  def parse(log_paths, &process_statistic)
245
- parser = Groonga::QueryLog::Parser.new(@options)
246
- if log_paths.empty?
247
- unless log_via_stdin?
248
- raise(NoInputError, "Error: Please specify input log files.")
249
- end
250
- parser.parse($stdin, &process_statistic)
251
- end
252
-
253
- log_paths.each do |log_path|
254
- File.open(log_path) do |log|
255
- parser.parse(log, &process_statistic)
256
- end
257
- end
264
+ parser = Parser.new(@options)
265
+ parse_log(parser, log_paths, &process_statistic)
258
266
  end
259
267
  end
260
268
  end
261
269
  end
270
+
271
+ require "groonga-query-log/command/analyzer/streamer"
272
+ require "groonga-query-log/command/analyzer/sized-statistics"
273
+ require "groonga-query-log/command/analyzer/reporter/console"
274
+ require "groonga-query-log/command/analyzer/reporter/csv"
275
+ require "groonga-query-log/command/analyzer/reporter/html"
276
+ require "groonga-query-log/command/analyzer/reporter/json"
277
+ require "groonga-query-log/command/analyzer/reporter/json-stream"
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2011-2013 Kouhei Sutou <kou@clear-code.com>
1
+ # Copyright (C) 2011-2018 Kouhei Sutou <kou@clear-code.com>
4
2
  # Copyright (C) 2012 Haruka Yoshihara <yoshihara@clear-code.com>
5
3
  #
6
4
  # This library is free software; you can redistribute it and/or
@@ -17,35 +15,32 @@
17
15
  # License along with this library; if not, write to the Free Software
18
16
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
17
 
20
- module Groonga
21
- module QueryLog
18
+ require "time"
19
+
20
+ module GroongaQueryLog
21
+ module Command
22
22
  class Analyzer
23
23
  class Reporter
24
24
  include Enumerable
25
25
 
26
26
  attr_reader :output
27
27
  attr_accessor :slow_operation_threshold, :slow_response_threshold
28
- def initialize(statistics)
28
+ def initialize(statistics, options={})
29
29
  @statistics = statistics
30
- @report_summary = true
31
- @output = $stdout
30
+ @options = options
31
+ self.output = @options[:output] || $stdout
32
+ @report_summary = @options[:report_summary]
33
+ @report_summary = true if @report_summary.nil?
34
+ @report_command_line = @options[:report_command_line]
35
+ @report_command_line = true if @report_command_line.nil?
32
36
  @slow_operation_threshold =
37
+ @options[:slow_operation_threshold] ||
33
38
  Statistic::DEFAULT_SLOW_OPERATION_THRESHOLD
34
39
  @slow_response_threshold =
40
+ @options[:slow_response_threshold] ||
35
41
  Statistic::DEFAULT_SLOW_RESPONSE_THRESHOLD
36
42
  end
37
43
 
38
- def apply_options(options)
39
- self.output = options[:output] || @output
40
- unless options[:report_summary].nil?
41
- @report_summary = options[:report_summary]
42
- end
43
- @slow_operation_threshold =
44
- options[:slow_operation_threshold] || @slow_operation_threshold
45
- @slow_response_threshold =
46
- options[:slow_response_threshold] || @slow_response_threshold
47
- end
48
-
49
44
  def output=(output)
50
45
  @output = output
51
46
  @output = $stdout if @output == "-"
@@ -101,7 +96,7 @@ module Groonga
101
96
  if time.nil?
102
97
  "NaN"
103
98
  else
104
- time.strftime("%Y-%m-%d %H:%M:%S.%u")
99
+ time.iso8601(6)
105
100
  end
106
101
  end
107
102
  end
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2011-2014 Kouhei Sutou <kou@clear-code.com>
1
+ # Copyright (C) 2011-2017 Kouhei Sutou <kou@clear-code.com>
4
2
  # Copyright (C) 2012 Haruka Yoshihara <yoshihara@clear-code.com>
5
3
  #
6
4
  # This library is free software; you can redistribute it and/or
@@ -17,10 +15,10 @@
17
15
  # License along with this library; if not, write to the Free Software
18
16
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
17
 
20
- require "groonga/query-log/analyzer/reporter"
18
+ require "groonga-query-log/command/analyzer/reporter"
21
19
 
22
- module Groonga
23
- module QueryLog
20
+ module GroongaQueryLog
21
+ module Command
24
22
  class Analyzer
25
23
  class ConsoleReporter < Reporter
26
24
  class Color
@@ -124,9 +122,10 @@ module Groonga
124
122
  end
125
123
  end
126
124
 
127
- def initialize(statistics)
125
+ def initialize(statistics, options)
128
126
  super
129
- @color = :auto
127
+ @color = @options[:color]
128
+ @color = :auto if @color.nil?
130
129
  @reset_color = Color.new("reset")
131
130
  @color_schema = {
132
131
  :elapsed => {:foreground => :white, :background => :green},
@@ -135,11 +134,6 @@ module Groonga
135
134
  }
136
135
  end
137
136
 
138
- def apply_options(options)
139
- super
140
- @color = options[:color] unless options[:color].nil?
141
- end
142
-
143
137
  def report_statistics
144
138
  write("\n")
145
139
  write("Slow Queries:\n")
@@ -270,11 +264,18 @@ module Groonga
270
264
  def format_heading(statistic)
271
265
  formatted_elapsed = colorize("%8.8f" % statistic.elapsed_in_seconds,
272
266
  :elapsed)
273
- "[%s-%s (%s)](%d): %s" % [format_time(statistic.start_time),
274
- format_time(statistic.last_time),
275
- formatted_elapsed,
276
- statistic.return_code,
277
- statistic.raw_command]
267
+ data = [
268
+ format_time(statistic.start_time),
269
+ format_time(statistic.last_time),
270
+ formatted_elapsed,
271
+ statistic.return_code,
272
+ ]
273
+ if @report_command_line
274
+ data << statistic.raw_command
275
+ else
276
+ data << statistic.command.name
277
+ end
278
+ "[%s-%s (%s)](%d): %s" % data
278
279
  end
279
280
 
280
281
  def format_time(time)
@@ -0,0 +1,77 @@
1
+ # Copyright (C) 2018 Kouhei Sutou <kou@clear-code.com>
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License as published by the Free Software Foundation; either
6
+ # version 2.1 of the License, or (at your option) any later version.
7
+ #
8
+ # This library is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this library; if not, write to the Free Software
15
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+
17
+ require "csv"
18
+
19
+ require "groonga-query-log/command/analyzer/reporter"
20
+
21
+ module GroongaQueryLog
22
+ module Command
23
+ class Analyzer
24
+ class CSVReporter < Reporter
25
+ def initialize(statistics, options)
26
+ super
27
+ if @options[:report_command_line].nil?
28
+ @report_command_line = false
29
+ end
30
+ end
31
+
32
+ def start
33
+ @csv = CSV.new(@output)
34
+ header = [
35
+ "start_time",
36
+ "last_time",
37
+ "elapsed",
38
+ "return_code",
39
+ "slow",
40
+ "command_name",
41
+ ]
42
+ header << "command_line" if @report_command_line
43
+ @csv << header
44
+ end
45
+
46
+ def report_statistic(statistic)
47
+ record = [
48
+ format_time(statistic.start_time),
49
+ format_time(statistic.last_time),
50
+ statistic.elapsed_in_seconds,
51
+ statistic.return_code,
52
+ statistic.slow?,
53
+ statistic.command.command_name,
54
+ ]
55
+ record << statistic.raw_command if @report_command_line
56
+ @csv << record
57
+ end
58
+
59
+ def finish
60
+ @csv.close
61
+ end
62
+
63
+ def report_summary
64
+ end
65
+
66
+ private
67
+ def format_time(time)
68
+ if time.nil?
69
+ ""
70
+ else
71
+ super
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2011-2012 Kouhei Sutou <kou@clear-code.com>
1
+ # Copyright (C) 2011-2018 Kouhei Sutou <kou@clear-code.com>
4
2
  # Copyright (C) 2012 Haruka Yoshihara <yoshihara@clear-code.com>
5
3
  #
6
4
  # This library is free software; you can redistribute it and/or
@@ -18,10 +16,10 @@
18
16
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
17
 
20
18
  require "erb"
21
- require "groonga/query-log/analyzer/reporter"
19
+ require "groonga-query-log/command/analyzer/reporter"
22
20
 
23
- module Groonga
24
- module QueryLog
21
+ module GroongaQueryLog
22
+ module Command
25
23
  class Analyzer
26
24
  class HTMLReporter < Reporter
27
25
  include ERB::Util
@@ -66,7 +64,9 @@ module Groonga
66
64
  :slow? => statistic.slow?) %>)]
67
65
  (<%= span({:class => "return-code"}, h(statistic.return_code)) %>)
68
66
  </div>
67
+ <% if @report_command_line %>
69
68
  <%= div({:class => "raw-command"}, h(statistic.raw_command)) %>
69
+ <% end %>
70
70
  </div>
71
71
  <div class="statistic-parameters">
72
72
  <h3>Parameters</h3>
@@ -81,16 +81,31 @@ module Groonga
81
81
  </div>
82
82
  <div class="statistic-operations">
83
83
  <h3>Operations</h3>
84
- <ol>
85
- <% statistic.each_operation do |operation| %>
86
- <li>
87
- <%= format_elapsed(operation[:relative_elapsed_in_seconds],
88
- :slow? => operation[:slow?]) %>:
89
- <%= span({:class => "name"}, h(operation[:name])) %>:
90
- <%= span({:class => "context"}, h(operation[:context])) %>
91
- </li>
84
+ <table>
85
+ <thead>
86
+ <tr>
87
+ <th>Nth</th>
88
+ <th>Elapsed(sec)</th>
89
+ <th>Name</th>
90
+ <th>N records</th>
91
+ <th>Context</th>
92
+ </tr>
93
+ </thead>
94
+ <tbody>
95
+ <% statistic.each_operation.with_index do |operation, i| %>
96
+ <tr>
97
+ <td class="n"><%= h(i + 1) %></td>
98
+ <td class="elapsed">
99
+ <%= format_elapsed(operation[:relative_elapsed_in_seconds],
100
+ :slow? => operation[:slow?]) %>
101
+ </td>
102
+ <td class="name"><%= h(operation[:name]) %></td>
103
+ <td class="n-records"><%= h(operation[:n_records]) %></td>
104
+ <td class="context"><%= h(operation[:context]) %></td>
105
+ </tr>
92
106
  <% end %>
93
- </ol>
107
+ </tbody>
108
+ </table>
94
109
  </div>
95
110
  EOH
96
111
  write(statistic_html)
@@ -145,7 +160,8 @@ div.statistics
145
160
 
146
161
  td.elapsed,
147
162
  td.ratio,
148
- td.n
163
+ td.n,
164
+ td.n-records
149
165
  {
150
166
  text-align: right;
151
167
  }