select_rails_log 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +13 -0
  3. data/CHANGELOG.md +22 -0
  4. data/CODE_OF_CONDUCT.md +132 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +93 -0
  7. data/Rakefile +16 -0
  8. data/exe/select_rails_log +5 -0
  9. data/images/boxplot.png +0 -0
  10. data/images/histgram.png +0 -0
  11. data/images/text.png +0 -0
  12. data/lib/select_rails_log/command_line_options.rb +71 -0
  13. data/lib/select_rails_log/constants.rb +36 -0
  14. data/lib/select_rails_log/extension.rb +59 -0
  15. data/lib/select_rails_log/filter/base_filter.rb +35 -0
  16. data/lib/select_rails_log/filter/controller_action_filter.rb +50 -0
  17. data/lib/select_rails_log/filter/duration_range_filter.rb +40 -0
  18. data/lib/select_rails_log/filter/http_method_filter.rb +26 -0
  19. data/lib/select_rails_log/filter/http_status_filter.rb +39 -0
  20. data/lib/select_rails_log/filter/logs_regexp_filter.rb +27 -0
  21. data/lib/select_rails_log/filter/params_regexp_filter.rb +27 -0
  22. data/lib/select_rails_log/filter/range_pattern.rb +32 -0
  23. data/lib/select_rails_log/filter/request_id_filter.rb +28 -0
  24. data/lib/select_rails_log/filter/time_range_filter.rb +43 -0
  25. data/lib/select_rails_log/filter.rb +16 -0
  26. data/lib/select_rails_log/options.rb +20 -0
  27. data/lib/select_rails_log/printer/base_printer.rb +117 -0
  28. data/lib/select_rails_log/printer/boxplot_printer.rb +83 -0
  29. data/lib/select_rails_log/printer/data_serializable.rb +43 -0
  30. data/lib/select_rails_log/printer/histgram_printer.rb +48 -0
  31. data/lib/select_rails_log/printer/json_printer.rb +43 -0
  32. data/lib/select_rails_log/printer/jsonl_printer.rb +27 -0
  33. data/lib/select_rails_log/printer/null_printer.rb +19 -0
  34. data/lib/select_rails_log/printer/raw_printer.rb +45 -0
  35. data/lib/select_rails_log/printer/statistics_printer.rb +84 -0
  36. data/lib/select_rails_log/printer/text_printer.rb +51 -0
  37. data/lib/select_rails_log/printer/tsv_printer.rb +54 -0
  38. data/lib/select_rails_log/printer.rb +17 -0
  39. data/lib/select_rails_log/runner.rb +151 -0
  40. data/lib/select_rails_log/scanner.rb +142 -0
  41. data/lib/select_rails_log/selector.rb +32 -0
  42. data/lib/select_rails_log/version.rb +5 -0
  43. data/lib/select_rails_log.rb +22 -0
  44. data/sig/select_rails_log.rbs +4 -0
  45. metadata +131 -0
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "enumerable/statistics"
4
+
5
+ module SelectRailsLog
6
+ module Printer
7
+ class StatisticsPrinter < BasePrinter
8
+ STAT_TOTAL_DURATION = "Total"
9
+
10
+ DEFAULT_TARGETS = [
11
+ STAT_TOTAL_DURATION,
12
+ PERFORMANCE_ACTIVE_RECORD,
13
+ PERFORMANCE_VIEWS,
14
+ PERFORMANCE_ALLOCATIONS
15
+ ].freeze
16
+
17
+ PERCENTILES = [25, 50, 75, 90, 95, 99].freeze
18
+
19
+ define_options :statistics_printer do
20
+ option :output, "--stats [FILE]", "-s", "Output statistics in TSV format", default: DEFAULT_OUTPUT
21
+ option :stats_targets,
22
+ "--stats-targets TARGETs",
23
+ " Statistics targets", Array,
24
+ " target can be one of #{DEFAULT_TARGETS.join(", ")}, or etc."
25
+ end
26
+
27
+ def initialize(*)
28
+ super
29
+
30
+ @stats_data = {}
31
+ @stats_targets = options[:stats_targets] || DEFAULT_TARGETS
32
+ end
33
+
34
+ def close
35
+ print_statistics
36
+ super
37
+ end
38
+
39
+ private
40
+
41
+ def init_output_destination
42
+ super
43
+ return unless output_directory?
44
+
45
+ raise CommandLineOptionError, "output to directory is not supported for statistics"
46
+ end
47
+
48
+ def build_stat_data
49
+ @stats_targets.each_with_object({}) do |target, hash|
50
+ hash[target] = []
51
+ end
52
+ end
53
+
54
+ def print_data(_output, data)
55
+ stat_data = @stats_data[data.values_at(CONTROLLER, ACTION)] ||= build_stat_data
56
+ stat_data.each do |target, values|
57
+ value = if target == STAT_TOTAL_DURATION
58
+ data[DURATION]
59
+ else
60
+ data[PERFORMANCE][target]
61
+ end
62
+ values << value if value
63
+ end
64
+ end
65
+
66
+ def print_statistics
67
+ print_row ["percentile", *PERCENTILES]
68
+
69
+ @stats_data.keys.sort.each do |(controller, action)|
70
+ @stats_data[[controller, action]].each do |target, values|
71
+ next if values.empty?
72
+
73
+ print_row ["#{controller}##{action} #{target}",
74
+ *PERCENTILES.map { |percentile| values.percentile(percentile) }]
75
+ end
76
+ end
77
+ end
78
+
79
+ def print_row(values)
80
+ @output_file.puts values.join("\t")
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SelectRailsLog
4
+ module Printer
5
+ class TextPrinter < BasePrinter
6
+ SUFFIX = ".txt"
7
+ DATETIME_FORMAT = "%FT%T.%6N"
8
+
9
+ define_options :text_printer do
10
+ option :output, "--text [PATH]", "Output in text format (default)", default: DEFAULT_OUTPUT
11
+ end
12
+
13
+ def initialize(options, standard_output, fallback_output: nil)
14
+ @fallback_output = fallback_output
15
+ @first = true
16
+ super(options, standard_output)
17
+ end
18
+
19
+ private
20
+
21
+ def output_option
22
+ options[:output] || @fallback_output
23
+ end
24
+
25
+ def print_data(output, data)
26
+ output.puts unless @first || output_directory?
27
+ @first = false if @first
28
+
29
+ print_header(output, data)
30
+ print_body(output, data)
31
+ end
32
+
33
+ def print_header(output, data)
34
+ output.puts "time: #{data[STARTED]&.strftime(DATETIME_FORMAT)} " \
35
+ ".. #{data[COMPLETED]&.strftime(DATETIME_FORMAT)}"
36
+ output.puts "request_id: #{data[REQUEST_ID]}" if data[REQUEST_ID]
37
+ output.print <<~END_OF_HEADER
38
+ pid: #{data[PID]}
39
+ status: #{data[HTTP_STATUS]}
40
+ duration: #{data[DURATION]}ms
41
+ END_OF_HEADER
42
+ end
43
+
44
+ def print_body(output, data)
45
+ each_log(data) do |log|
46
+ output.printf "[%<interval>8.3f] %<message>s\n", interval: log[INTERVAL] * 1_000, message: log[MESSAGE]
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "csv"
4
+
5
+ module SelectRailsLog
6
+ module Printer
7
+ class TsvPrinter < BasePrinter
8
+ DATETIME_FORMAT = "%F %T.%6N"
9
+
10
+ COLUMNS = [
11
+ STARTED, REQUEST_ID, "controller_action",
12
+ HTTP_STATUS, HTTP_METHOD, PATH,
13
+ "total_duration",
14
+ "active_record_duration",
15
+ "views_duration",
16
+ "allocations"
17
+ ].freeze
18
+
19
+ define_options :tsv_printer do
20
+ option :output, "--tsv [FILE]", "-t", "Output in TSV format", default: DEFAULT_OUTPUT
21
+ end
22
+
23
+ private
24
+
25
+ def init_output_destination
26
+ super
27
+ return unless output_directory?
28
+
29
+ raise CommandLineOptionError, "output to directory is not supported for TSV format"
30
+ end
31
+
32
+ def prepare
33
+ super
34
+ @csv = CSV.new(@output_file, col_sep: "\t", write_headers: true, headers: COLUMNS)
35
+ end
36
+
37
+ def print_data(_output, data)
38
+ @csv << row(data)
39
+ end
40
+
41
+ def row(data)
42
+ [
43
+ data[STARTED].strftime(DATETIME_FORMAT),
44
+ data[REQUEST_ID], "#{data[CONTROLLER]}##{data[ACTION]}",
45
+ data[HTTP_STATUS], data[HTTP_METHOD], data[PATH],
46
+ data[DURATION],
47
+ data[PERFORMANCE][PERFORMANCE_ACTIVE_RECORD],
48
+ data[PERFORMANCE][PERFORMANCE_VIEWS],
49
+ data[PERFORMANCE][PERFORMANCE_ALLOCATIONS]
50
+ ]
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "printer/base_printer"
4
+ require_relative "printer/text_printer"
5
+ require_relative "printer/raw_printer"
6
+ require_relative "printer/json_printer"
7
+ require_relative "printer/jsonl_printer"
8
+ require_relative "printer/tsv_printer"
9
+ require_relative "printer/statistics_printer"
10
+ require_relative "printer/histgram_printer"
11
+ require_relative "printer/boxplot_printer"
12
+ require_relative "printer/null_printer"
13
+
14
+ module SelectRailsLog
15
+ module Printer
16
+ end
17
+ end
@@ -0,0 +1,151 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SelectRailsLog
4
+ class Runner < Extension
5
+ include Constants
6
+
7
+ define_options :runner do
8
+ separator ""
9
+ separator "other options:"
10
+
11
+ option :help, "--help", "-h", "Show help"
12
+ option :version, "--version", "Show version"
13
+ option :debug, "--debug", "Enable debug print"
14
+ end
15
+
16
+ class << self
17
+ def run(argv, argf, out = $stdout)
18
+ runner = setup_runner(argv, out)
19
+
20
+ begin
21
+ runner.run(Scanner.new(argf)) if runner.runnable?
22
+ rescue StopIteration, Errno::EPIPE, Interrupt
23
+ # noop
24
+ end
25
+
26
+ runner.success?
27
+ rescue StandardError => e
28
+ raise e if runner&.debug?
29
+
30
+ warn e.message
31
+ false
32
+ end
33
+
34
+ private
35
+
36
+ def setup_runner(argv, out)
37
+ options = CommandLineOptions.new
38
+ options.parse!(argv)
39
+
40
+ runner = Runner.new(options, out)
41
+ if runner.help?
42
+ out.puts options.parser
43
+ elsif runner.version?
44
+ print_version(out)
45
+ end
46
+
47
+ runner
48
+ end
49
+
50
+ def print_version(io)
51
+ io.print <<~VERSION
52
+ select_rails_log #{VERSION}
53
+ - csv #{CSV::VERSION}
54
+ - enumerable-statistics #{EnumerableStatistics::VERSION}
55
+ - unicode_plot #{UnicodePlot::VERSION}
56
+ - #{RUBY_ENGINE} #{RUBY_VERSION} [#{RUBY_PLATFORM}]
57
+ VERSION
58
+ end
59
+ end
60
+
61
+ def initialize(options, standard_output)
62
+ super(options)
63
+ @count = 0
64
+ @standard_output = standard_output
65
+ end
66
+
67
+ def help?
68
+ options[:help]
69
+ end
70
+
71
+ def version?
72
+ options[:version]
73
+ end
74
+
75
+ def debug?
76
+ options[:debug]
77
+ end
78
+
79
+ def success?
80
+ help? || version? || @count.positive?
81
+ end
82
+
83
+ def runnable?
84
+ !help? && !version?
85
+ end
86
+
87
+ def run(scanner)
88
+ selector, printers = setup
89
+ counter_thread = counter_thread() if output_tty?(printers)
90
+
91
+ keep_raw = include_raw_printer?(printers)
92
+ scanner.select(selector, keep_raw:) do |data|
93
+ @count += 1
94
+ printers.each { _1.print(data) }
95
+ end
96
+ ensure
97
+ counter_thread&.kill
98
+ printers&.each(&:close)
99
+ end
100
+
101
+ private
102
+
103
+ def output_tty?(printers)
104
+ @standard_output.tty? && printers.none?(&:output_stdout?)
105
+ end
106
+
107
+ def setup
108
+ filters = setup_filters
109
+ printers = setup_printers
110
+ printers << default_printer if printers.empty?
111
+ selector = Selector.new(filters)
112
+
113
+ [selector, printers]
114
+ end
115
+
116
+ def setup_filters
117
+ @whole_options.extensions(:filter).filter_map do |ext_class|
118
+ ext = ext_class.new(@whole_options)
119
+ ext if ext.runnable?
120
+ end
121
+ end
122
+
123
+ def setup_printers
124
+ @whole_options.extensions(:printer).filter_map do |ext_class|
125
+ ext = ext_class.new(@whole_options, @standard_output)
126
+ ext if ext.runnable?
127
+ end
128
+ end
129
+
130
+ def default_printer
131
+ Printer::TextPrinter.new(@whole_options, @standard_output, fallback_output: DEFAULT_OUTPUT)
132
+ end
133
+
134
+ def include_raw_printer?(printers)
135
+ printers.any? { _1.is_a?(Printer::RawPrinter) }
136
+ end
137
+
138
+ def counter_thread
139
+ Thread.new do
140
+ lambda do
141
+ loop do
142
+ sleep 1
143
+ print "\r#{@count}"
144
+ end
145
+ ensure
146
+ puts "\r#{@count}"
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "time"
4
+
5
+ module SelectRailsLog
6
+ class Scanner
7
+ include Constants
8
+
9
+ reqid_regexp = /\[(?<reqid>\h{8}-\h{4}-\h{4}-\h{4}-\h{12})\]/
10
+ LOG_REGEXP = /\A., \[(?<time>\S+) #(?<pid>\d+)\] *(?<severity>\S+) -- :(?: #{reqid_regexp})? (?<message>.*)/
11
+ ANSI_ESCAPE_SEQ_REGEXP = /\e\[(?:\d{1,2}(?:;\d{1,2})?)?[mK]/
12
+
13
+ DATETIME_FORMAT = "%FT%T.%N"
14
+ REQUEST_FILTER_APPLIED = "request_filter_applied" # internal data keys
15
+ private_constant :DATETIME_FORMAT, :REQUEST_FILTER_APPLIED
16
+
17
+ def initialize(io)
18
+ @io = io
19
+ end
20
+
21
+ def select(selector, keep_raw: true)
22
+ buff = {}
23
+ prev_time = nil
24
+ prev_data = nil
25
+ found = false
26
+ stop_iteration = false
27
+
28
+ @io.each_line do |line|
29
+ m = LOG_REGEXP.match(line)
30
+ unless m
31
+ if prev_data && prev_data[LOGS].any?
32
+ prev_data[LOGS].last[MESSAGE] << "\n" << line.chomp.gsub(ANSI_ESCAPE_SEQ_REGEXP, "")
33
+ prev_data[RAW_LOGS].last << line if keep_raw
34
+ end
35
+ next
36
+ end
37
+
38
+ begin
39
+ time = Time.strptime(m[:time], DATETIME_FORMAT)
40
+ rescue ArgumentError
41
+ # ignore invalid time format
42
+ end
43
+
44
+ pid = m[:pid]
45
+ reqid = m[:reqid]
46
+ message = m[:message]
47
+ log = {
48
+ TIME => time,
49
+ MESSAGE => message,
50
+ SEVERITY => m[:severity]
51
+ }
52
+
53
+ ident = reqid || pid
54
+ data = prev_data = buff[ident] if buff.key?(ident)
55
+
56
+ if /\AStarted (?<http_method>\S+) "(?<path>[^"]*)" for (?<client>\S+)/ =~ message
57
+ buff.delete(ident)
58
+ if stop_iteration
59
+ prev_data = nil
60
+ buff.empty? ? break : next
61
+ end
62
+
63
+ log[INTERVAL] = 0.0
64
+ prev_time = time
65
+
66
+ data = {
67
+ ID => reqid || time.strftime("%Y%m%d-%H%M%S-%6N-#{pid}"),
68
+ STARTED => time,
69
+ PID => pid,
70
+ REQUEST_ID => reqid,
71
+ HTTP_METHOD => http_method,
72
+ PATH => path,
73
+ CLIENT => client,
74
+ LOGS => [log],
75
+ REQUEST_FILTER_APPLIED => false
76
+ }
77
+ data[RAW_LOGS] = [line] if keep_raw
78
+ buff[ident] = data
79
+ next
80
+ end
81
+
82
+ unless data
83
+ prev_data = nil
84
+ next
85
+ end
86
+
87
+ message.gsub!(ANSI_ESCAPE_SEQ_REGEXP, "")
88
+ log[INTERVAL] = (time && prev_time) ? time - prev_time : 0.0
89
+ prev_time = time
90
+
91
+ if /\AProcessing by (?<controller>[^\s#]+)#(?<action>\S+)/ =~ message
92
+ data[CONTROLLER] = controller
93
+ data[ACTION] = action
94
+ data[LOGS] << log
95
+ data[RAW_LOGS] << line if keep_raw
96
+
97
+ data.delete(REQUEST_FILTER_APPLIED)
98
+ begin
99
+ reqf_result = selector.run_request_filters(data)
100
+ rescue StopIteration
101
+ stop_iteration = true
102
+ end
103
+ if !reqf_result || stop_iteration
104
+ buff.delete(ident)
105
+ prev_data = nil
106
+ end
107
+ elsif /\A Parameters: (?<params>.*)/ =~ message
108
+ data[PARAMETERS] = params
109
+ data[LOGS] << log
110
+ data[RAW_LOGS] << line if keep_raw
111
+ elsif /\ACompleted (?<http_status>\d+) .* in (?<duration>\d+)ms \((?<durations>.*)\)/ =~ message
112
+ data[HTTP_STATUS] = http_status
113
+ data[DURATION] = duration.to_i
114
+ data[PERFORMANCE] = durations.scan(/(\S+): (\d+(\.\d+)?)/)
115
+ .to_h { |type, dur, dur_f| [type, dur_f ? dur.to_f : dur.to_i] }
116
+ data[COMPLETED] = time
117
+ data[LOGS] << log
118
+ data[RAW_LOGS] << line if keep_raw
119
+
120
+ if data.key?(REQUEST_FILTER_APPLIED)
121
+ data.delete(REQUEST_FILTER_APPLIED)
122
+ reqf_result = selector.run_request_filters(data)
123
+ else
124
+ reqf_result = true
125
+ end
126
+
127
+ reqf_result && selector.run_line_filters(data) do |i|
128
+ yield(i)
129
+ found = true
130
+ end
131
+ buff.delete(ident)
132
+ prev_data = nil
133
+ else
134
+ data[LOGS] << log
135
+ data[RAW_LOGS] << line if keep_raw
136
+ end
137
+ end
138
+
139
+ found
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SelectRailsLog
4
+ class Selector
5
+ def initialize(filters)
6
+ @request_filters = filters.select(&:request_filter?)
7
+ @line_filters = filters - @request_filters
8
+ end
9
+
10
+ def run_request_filters(data)
11
+ run_filters(data, @request_filters)
12
+ end
13
+
14
+ def run_line_filters(data, &)
15
+ run_filters(data, @line_filters, &)
16
+ end
17
+
18
+ private
19
+
20
+ def run_filters(data, filters)
21
+ result = if filters.empty?
22
+ true
23
+ else
24
+ filters.all? { |filter| filter.run(data) }
25
+ end
26
+
27
+ return yield(data) if result && block_given?
28
+
29
+ result
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SelectRailsLog
4
+ VERSION = "0.2.0"
5
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "select_rails_log/constants"
4
+ require_relative "select_rails_log/command_line_options"
5
+ require_relative "select_rails_log/extension"
6
+ require_relative "select_rails_log/filter"
7
+ require_relative "select_rails_log/printer"
8
+ require_relative "select_rails_log/selector"
9
+ require_relative "select_rails_log/runner"
10
+ require_relative "select_rails_log/scanner"
11
+ require_relative "select_rails_log/version"
12
+
13
+ module SelectRailsLog
14
+ class Error < RuntimeError; end
15
+ class CommandLineOptionError < Error; end
16
+
17
+ class << self
18
+ def run
19
+ exit(Runner.run(ARGV, ARGF) ? 0 : 1)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,4 @@
1
+ module SelectRailsLog
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: select_rails_log
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - akira yamada
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 2025-01-18 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: csv
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: enumerable-statistics
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: unicode_plot
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ description: select_rails_log is a tool for extracting request logs from Rails log
55
+ files.
56
+ email:
57
+ - akira@arika.org
58
+ executables:
59
+ - select_rails_log
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".rubocop.yml"
64
+ - CHANGELOG.md
65
+ - CODE_OF_CONDUCT.md
66
+ - LICENSE.txt
67
+ - README.md
68
+ - Rakefile
69
+ - exe/select_rails_log
70
+ - images/boxplot.png
71
+ - images/histgram.png
72
+ - images/text.png
73
+ - lib/select_rails_log.rb
74
+ - lib/select_rails_log/command_line_options.rb
75
+ - lib/select_rails_log/constants.rb
76
+ - lib/select_rails_log/extension.rb
77
+ - lib/select_rails_log/filter.rb
78
+ - lib/select_rails_log/filter/base_filter.rb
79
+ - lib/select_rails_log/filter/controller_action_filter.rb
80
+ - lib/select_rails_log/filter/duration_range_filter.rb
81
+ - lib/select_rails_log/filter/http_method_filter.rb
82
+ - lib/select_rails_log/filter/http_status_filter.rb
83
+ - lib/select_rails_log/filter/logs_regexp_filter.rb
84
+ - lib/select_rails_log/filter/params_regexp_filter.rb
85
+ - lib/select_rails_log/filter/range_pattern.rb
86
+ - lib/select_rails_log/filter/request_id_filter.rb
87
+ - lib/select_rails_log/filter/time_range_filter.rb
88
+ - lib/select_rails_log/options.rb
89
+ - lib/select_rails_log/printer.rb
90
+ - lib/select_rails_log/printer/base_printer.rb
91
+ - lib/select_rails_log/printer/boxplot_printer.rb
92
+ - lib/select_rails_log/printer/data_serializable.rb
93
+ - lib/select_rails_log/printer/histgram_printer.rb
94
+ - lib/select_rails_log/printer/json_printer.rb
95
+ - lib/select_rails_log/printer/jsonl_printer.rb
96
+ - lib/select_rails_log/printer/null_printer.rb
97
+ - lib/select_rails_log/printer/raw_printer.rb
98
+ - lib/select_rails_log/printer/statistics_printer.rb
99
+ - lib/select_rails_log/printer/text_printer.rb
100
+ - lib/select_rails_log/printer/tsv_printer.rb
101
+ - lib/select_rails_log/runner.rb
102
+ - lib/select_rails_log/scanner.rb
103
+ - lib/select_rails_log/selector.rb
104
+ - lib/select_rails_log/version.rb
105
+ - sig/select_rails_log.rbs
106
+ homepage: https://github.com/arika/select_rails_log
107
+ licenses:
108
+ - MIT
109
+ metadata:
110
+ homepage_uri: https://github.com/arika/select_rails_log
111
+ source_code_uri: https://github.com/arika/select_rails_log
112
+ changelog_uri: https://github.com/arika/select_rails_log/blob/main/CHANGELOG.md
113
+ rubygems_mfa_required: 'true'
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: 3.1.0
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubygems_version: 3.6.2
129
+ specification_version: 4
130
+ summary: Rails log selector
131
+ test_files: []