greenhat 0.1.5 → 0.3.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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/lib/greenhat/accessors/disk.rb +58 -2
  3. data/lib/greenhat/accessors/gitlab.rb +75 -0
  4. data/lib/greenhat/accessors/memory.rb +10 -10
  5. data/lib/greenhat/accessors/process.rb +10 -1
  6. data/lib/greenhat/cli.rb +148 -63
  7. data/lib/greenhat/color.rb +27 -0
  8. data/lib/greenhat/logbot.rb +9 -9
  9. data/lib/greenhat/settings.rb +51 -3
  10. data/lib/greenhat/shell/args.rb +146 -0
  11. data/lib/greenhat/shell/cat.rb +25 -73
  12. data/lib/greenhat/shell/color_string.rb +43 -0
  13. data/lib/greenhat/shell/disk.rb +30 -42
  14. data/lib/greenhat/shell/faststats.rb +104 -58
  15. data/lib/greenhat/shell/field_helper.rb +75 -0
  16. data/lib/greenhat/shell/filter_help.rb +162 -0
  17. data/lib/greenhat/shell/gitlab.rb +61 -2
  18. data/lib/greenhat/shell/help.rb +98 -15
  19. data/lib/greenhat/shell/list.rb +46 -0
  20. data/lib/greenhat/shell/log.rb +115 -209
  21. data/lib/greenhat/shell/page.rb +39 -0
  22. data/lib/greenhat/shell/process.rb +57 -2
  23. data/lib/greenhat/shell/report.rb +70 -60
  24. data/lib/greenhat/shell/shell_helper.rb +654 -0
  25. data/lib/greenhat/shell.rb +27 -13
  26. data/lib/greenhat/thing/file_types.rb +54 -7
  27. data/lib/greenhat/thing/formatters/json_shellwords.rb +0 -3
  28. data/lib/greenhat/thing/formatters/nginx.rb +44 -0
  29. data/lib/greenhat/thing/formatters/syslog.rb +39 -0
  30. data/lib/greenhat/thing/helpers.rb +4 -4
  31. data/lib/greenhat/thing/kind.rb +9 -2
  32. data/lib/greenhat/thing/spinner.rb +3 -3
  33. data/lib/greenhat/thing.rb +25 -3
  34. data/lib/greenhat/tty/columns.rb +44 -0
  35. data/lib/greenhat/version.rb +1 -1
  36. data/lib/greenhat.rb +16 -14
  37. metadata +42 -17
  38. data/lib/greenhat/shell/helper.rb +0 -541
@@ -1,15 +1,98 @@
1
- # module GreenHat
2
- # module Shell
3
- # # CLI Helper
4
- # module Help
5
- # def self.help
6
- # puts 'Available Commands: '
7
- # puts '=> help'
8
-
9
- # ShellCommand.descendants_s.each do |item|
10
- # puts "-> #{item.colorize(:yellow)}"
11
- # end
12
- # end
13
- # end
14
- # end
15
- # end
1
+ module GreenHat
2
+ # Root Level Shell / Splitting Help into its own file
3
+ module Shell
4
+ # rubocop:disable Layout/LineLength
5
+ def self.help
6
+ puts 'Quickstart'.pastel(:blue)
7
+ puts " Commands are organized by submodule: #{'log'.pastel(:blue)}, #{'cat'.pastel(:blue)}, #{'faststats'.pastel(:blue)}"
8
+ puts " Use #{'help'.pastel(:bright_blue)} for available commands in each module"
9
+ puts
10
+
11
+ puts ' Example Commands'
12
+ puts ' log filter sidekiq/current'.pastel(:yellow)
13
+ puts ' disk free'.pastel(:yellow)
14
+ puts
15
+
16
+ puts 'Top Level Commands'.pastel(:blue)
17
+ puts ' report'.pastel(:green)
18
+ puts ' Show summary report of SOS Report. OS, CPU, Memory, Disk, and etc'
19
+ puts ' --raw, no pagination'
20
+ puts ' --archive=<redis/archive>, filter by archive name'
21
+ puts
22
+
23
+ puts ' ps,df,netstat,free,uptime,uname'.pastel(:green)
24
+ puts ' Show common files from archives / Emulate terminal commands'
25
+ puts
26
+
27
+ puts ' Noisy Output'.pastel(:green)
28
+ puts " Use #{'quiet'.pastel(:blue)} or to #{'debug'.pastel(:blue)} to toggle greenhat logging"
29
+ puts
30
+
31
+ cli_shortcuts
32
+
33
+ puts "See #{'about'.pastel(:bright_blue)} for more details about GreenHat"
34
+ end
35
+ # rubocop:enable Layout/LineLength
36
+
37
+ def self.cli_shortcuts
38
+ puts "\u2500".pastel(:cyan) * 25
39
+ puts 'Nav / Keyboard Shortcuts'.pastel(:blue)
40
+ puts "\u2500".pastel(:cyan) * 25
41
+ puts <<~BLOCK
42
+ | Hotkey | Description |
43
+ | ------------------- | ----------------------- |
44
+ | Ctrl + U | Clear Input |
45
+ | Ctrl + A | Go to beginning |
46
+ | Ctrl + E | Go to End |
47
+ | Ctrl + Left/Right | Move left/right by word |
48
+ | Ctrl + D, Ctrl + Z | Exit |
49
+ | Ctrl + C, Shift Tab | Up one module |
50
+ BLOCK
51
+ puts
52
+ end
53
+
54
+ def self.about
55
+ puts "\u2500".pastel(:cyan) * 20
56
+ puts "About GreenHat #{GreenHat::VERSION}".pastel(:yellow)
57
+ puts "\u2500".pastel(:cyan) * 20
58
+
59
+ puts 'TLDR; Put in SOS reports, run commands, and find stuffs'.pastel(:green)
60
+ puts
61
+
62
+ puts <<~BLOCK
63
+ General overview (OS, Memory, Disk, GitLab)
64
+ #{'report'.pastel(:bright_cyan)}
65
+
66
+ Log Searching
67
+ #{'log filter sidekiq/current --job_status=done --sort=duration_s,db_duration_s --slice=duration_s,db_duration_s --reverse'.pastel(:bright_cyan)}
68
+
69
+ Read File(s) across SOS archives
70
+ #{'cat uptime'.pastel(:bright_cyan)} or #{'cat mount etc/fstab'.pastel(:bright_cyan)}
71
+
72
+ BLOCK
73
+
74
+ puts 'What it does / How it works'.pastel(:blue)
75
+ puts
76
+ puts <<~BLOCK
77
+ GreenHat is a support utility to enhance troubleshooting with GitLabSOS Reports and log files. Make it easy to find stuff
78
+
79
+ Supplied input files are staged, unpacked, identified, and normalized.
80
+ This enables other utilities to automatically find and present data. (Faststats, report, and etc)
81
+
82
+ BLOCK
83
+
84
+ puts 'Commands and Submodules'.pastel(:blue)
85
+ puts
86
+ puts <<~BLOCK
87
+ Greenhat is broken down into different "modules". Each module has its own commands. For example: log, cat, and faststats.
88
+ You can "cd" into or execute commands directly against with their names.
89
+
90
+ - Direct: #{'log filter sidekiq/current'.pastel(:cyan)}
91
+ - Or within: First #{'log'.pastel(:cyan)}, then #{'filter sidekiq/current'.pastel(:cyan)}
92
+
93
+ You can find the list of commands and submodules of each with #{'help'.pastel(:yellow)}
94
+
95
+ BLOCK
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,46 @@
1
+ module GreenHat
2
+ module ShellHelper
3
+ # Helper to handle listing of files
4
+ module List
5
+ # List Files Helpers
6
+ def self.list(raw = [], files)
7
+ filter, flags, _args = Args.parse(raw)
8
+
9
+ # Sort
10
+ files.sort_by!(&:name)
11
+
12
+ # Simplified vs Full. Full file name/path / or just file kinds
13
+ all = flags.key?(:all) || flags.key?(:a)
14
+
15
+ # Short & Uniq
16
+ files.uniq!(&:name) unless all
17
+
18
+ # Filter / Pattern
19
+ files.select! { |f| filter.any? { |x| f.name.include? x } } unless filter.empty?
20
+
21
+ # Print
22
+ files.each do |log|
23
+ if all
24
+ puts "- #{log.friendly_name}"
25
+ else
26
+ puts "- #{log.name.pastel(:yellow)}"
27
+ end
28
+ end
29
+ end
30
+
31
+ # Unified Help
32
+ def self.help
33
+ puts ' ls'.pastel(:green)
34
+ puts ' List available files'
35
+ puts ' Options'.pastel(:cyan)
36
+ puts ' -a, --all, show full file name/path including source'
37
+ puts ' <string> filter available'
38
+ puts ' Examples'.pastel(:cyan)
39
+ puts ' ls -a rails'
40
+ puts ' ls sys'
41
+ puts
42
+ end
43
+ # ----
44
+ end
45
+ end
46
+ end
@@ -2,280 +2,187 @@ module GreenHat
2
2
  # CLI Helper
3
3
  module Shell
4
4
  # Logs
5
- # rubocop:disable Metrics/ModuleLength
6
5
  module Log
6
+ def self.auto_complete(list, word)
7
+ # Argument Parsing
8
+ files, flags, _args = Args.parse(list)
9
+
10
+ # Don't try to autocomplete anything else
11
+ return nil unless word =~ /^-/
12
+
13
+ # Clean Up
14
+ word.delete!('-')
15
+ matches = FieldHelper.filter_flags(word)
16
+
17
+ if matches.count == 1
18
+ "--#{matches.first}"
19
+ elsif matches.count > 1
20
+ puts "#{'Filter Options:'.pastel(:bright_blue)} #{matches.join(' ').pastel(:bright_green)}"
21
+ "--#{Cli.common_substr(matches)}"
22
+ # -----------------------------------
23
+ # TODO: Fix Icky Double Nesting
24
+ elsif files.count.nonzero?
25
+ matches = FieldHelper.fields_find(files, word, flags)
26
+
27
+ return nil if matches.nil?
28
+
29
+ if matches.count == 1
30
+ "--#{matches.first}"
31
+ elsif matches.count > 1
32
+ puts "#{'Field Options:'.pastel(:bright_blue)} #{matches.join(' ').pastel(:bright_green)}"
33
+ "--#{Cli.common_substr(matches.map(&:to_s))}"
34
+ elsif FieldHelper.field_auto_complete?(word)
35
+ FieldHelper.field_auto_complete(word, files, flags)
36
+ end
37
+ # -----------------------------------
38
+ end
39
+ end
40
+
7
41
  def self.help
8
- puts "\u2500".colorize(:cyan) * 20
9
- puts "#{'Logs'.colorize(:yellow)} find stuff"
10
- puts "\u2500".colorize(:cyan) * 20
42
+ puts "\u2500".pastel(:cyan) * 20
43
+ puts "#{'Logs'.pastel(:yellow)} find stuff"
44
+ puts "\u2500".pastel(:cyan) * 20
45
+
46
+ puts 'Command Summary'.pastel(:blue)
47
+ puts ' filter'.pastel(:green)
48
+ puts " Primary way for log searching within greenhat. See #{'filter_help'.pastel(:blue)}"
49
+ puts ' Time, round, slice/except, and/or, stats, uniq, sort'
50
+ puts
11
51
 
12
- puts 'Command Summary'.colorize(:blue)
13
- puts ' show'.colorize(:green)
52
+ puts ' show'.pastel(:green)
14
53
  puts ' Just print selected logs'
15
- puts ' filter'.colorize(:green)
16
- puts ' Key/Field Filtering'
17
- puts ' search'.colorize(:green)
18
- puts ' General text by entry searching'
19
- puts ' ls'.colorize(:green)
20
- puts ' List available files'
21
54
  puts
22
55
 
23
- filter_help
24
-
56
+ puts ' search'.pastel(:green)
57
+ puts " General full text by file searching. See #{'search_help'.pastel(:blue)}"
25
58
  puts
26
- search_help
27
- end
28
-
29
- # List Files Helpers
30
- def self.list(args = [])
31
- all = false
32
- all = true if args.include?('-a') || args.include?('--all')
33
-
34
- files = ShellHelper::Log.list
35
59
 
36
- # Sort
37
- files.sort_by!(&:name)
60
+ puts ShellHelper::List.help
38
61
 
39
- # Short & Uniq
40
- files.uniq!(&:name) unless all
62
+ puts "See #{'examples'.pastel(:bright_blue)} for query examples"
63
+ end
41
64
 
42
- # Print
43
- files.each do |log|
44
- if all
45
- puts "- #{log.friendly_name}"
46
- else
47
- puts "- #{log.name.colorize(:yellow)}"
48
- end
49
- end
65
+ def self.filter_help
66
+ ShellHelper::Filter.help
50
67
  end
51
68
 
52
69
  def self.ls(args = [])
53
- list(args)
70
+ ShellHelper::List.list(args, ShellHelper::Log.list)
54
71
  end
55
72
 
56
- def self.show(log_list)
57
- # Prepare Log List
58
- log_list = ShellHelper.prepare_list(log_list)
59
-
60
- # Convert to Things
61
- logs = ShellHelper.find_things(log_list)
73
+ def self.show(raw = {})
74
+ # Extract Args
75
+ files_list, flags, _args = Args.parse(raw)
62
76
 
63
- logs.map!(&:data)
77
+ # Collect Files
78
+ files = ShellHelper.files(files_list, Thing.all, flags)
64
79
 
65
- ShellHelper.show logs.flatten
80
+ ShellHelper.show files.map(&:data).flatten
66
81
  end
67
82
 
68
83
  # ========================================================================
69
- # Filter
84
+ # Filter (See Filter Help)
70
85
  # ========================================================================
71
- # Supported Params
72
- # --or (Filter OR instead of AND)
73
- # --total Total Count Entries Only
74
- # --project=thingy --exclude_this!=asdf *
75
- # --slice: only grab specific fields --slice=path (slice multiple with comma)
76
- # --slice=time,path (E.g. log filter --path='mirror/pull' --slice=path,time )
77
- # --except: Exclude specific fields (except multiple with comma)
78
- # Example: log filter --path='mirror/pull' --except=params
79
86
  def self.default(raw_list)
80
87
  filter(raw_list)
81
88
  end
82
89
 
83
- def self.filter(raw_list)
90
+ def self.filter(raw)
84
91
  # Print Helper
85
- if raw_list == ['help']
92
+ if raw == ['help']
86
93
  filter_help
87
94
  return true
88
95
  end
89
96
 
90
- # Extract Args
91
- log_list, opts, args = ShellHelper.param_parse(raw_list)
97
+ # Argument Parsing
98
+ files, flags, args = Args.parse(raw)
92
99
 
93
100
  # Prepare Log List
94
- log_list = ShellHelper.prepare_list(log_list)
95
-
96
- # AND / OR Filtering
97
- filter_type = args.or ? :any? : :all?
101
+ files = ShellHelper.prepare_list(files, ShellHelper::Log.list, flags)
98
102
 
99
- results = ShellHelper.filter_start(log_list, filter_type, args, opts)
103
+ results = ShellHelper.filter_start(files, flags, args)
100
104
 
101
- # Skipo and Print Total if set
102
- if args.total
105
+ # Skip and Print Total if set
106
+ if flags[:total]
103
107
  ShellHelper.total_count(results)
104
108
  return true
105
109
  end
106
110
 
111
+ # Skip and Print Total if set
112
+ if flags[:fields]
113
+ ShellHelper.fields_print(results)
114
+ return true
115
+ end
116
+
107
117
  # Check Search Results
108
118
  if results.instance_of?(Hash) && results.values.flatten.empty?
109
- puts 'No results'.colorize(:red)
119
+ puts 'No results'.pastel(:red)
110
120
  else
111
121
  # This causes the key 'colorized' output to also be included
112
- ShellHelper.show(results.to_a.compact.flatten, args)
122
+ ShellHelper.show(results.to_a.compact.flatten, flags)
113
123
  end
114
124
 
115
125
  # log filter --path='cloud/gitlab-automation' --path='/pull' --all
116
- # cloud/gitlab-automation
117
126
  # log filter --project=thingy --other_filter=asdf *
118
127
  rescue StandardError => e
119
- binding.pry
120
- LogBot.fatal('Filter', message: e.message, backtrace: e.backtrace.first)
128
+ LogBot.fatal('Filter', message: e.message)
129
+ ap e.backtrace
121
130
  end
122
131
  # ========================================================================
123
132
 
124
- # rubocop:disable Metrics/MethodLength
125
- def self.filter_help
126
- puts "\u2500".colorize(:cyan) * 20
127
- puts 'Log Filter'.colorize(:yellow)
128
- puts "\u2500".colorize(:cyan) * 20
129
-
130
- puts 'Options'.colorize(:blue)
131
- puts '--raw'.colorize(:green)
132
- puts ' Do not use less/paging'
133
- puts
134
-
135
- puts '--round'.colorize(:green)
136
- puts ' Attempt to round all integers. Default: 2.'
137
- puts ' E.g. --round, --round=3, --round=0'
138
- puts
139
-
140
- puts '--json'.colorize(:green)
141
- puts ' Print output back into JSON'
142
- puts
143
-
144
- puts '--or'.colorize(:green)
145
- puts ' Filters will use OR instead of AND'
146
- puts
147
-
148
- puts '--total'.colorize(:green)
149
- puts ' Print only total count of matching entries'
150
- puts
151
-
152
- puts '--slice'.colorize(:green)
153
- puts ' Extract specific fields from entries (slice multiple with comma)'
154
- puts ' Ex: --slice=path or --slice=path,params'
155
- puts
156
-
157
- puts '--except'.colorize(:green)
158
- puts ' Exclude specific fields (except multiple with comma)'
159
- puts ' Ex: --except=params --except=params,path'
160
- puts
161
-
162
- puts '--stats'.colorize(:green)
163
- puts ' Order/Count occurrances by field'
164
- puts ' Ex: --stats=params --except=params,path'
165
- puts
166
-
167
- puts '--uniq'.colorize(:green)
168
- puts ' Show unique values only'
169
- puts ' Ex: --uniq=params --uniq=params,path'
170
- puts
171
-
172
- puts '--pluck'.colorize(:green)
173
- puts ' Extract values from entries'
174
- puts ' Ex: --pluck=params --pluck=params,path'
175
- puts
176
-
177
- puts '--archive'.colorize(:green)
178
- puts ' Limit to specific archvie name (inclusive). Matching SOS tar.gz name'
179
- puts ' Ex: --archive=dev-gitlab_20210622154626, --archive=202106,202107'
180
- puts
181
-
182
- puts '--sort'.colorize(:green)
183
- puts ' Sort by multiple fields'
184
- puts ' Ex: --sort=duration_s,db_duration_s'
185
- puts
186
-
187
- puts '--reverse'.colorize(:green)
188
- puts ' Reverse all results'
189
- puts ' Ex: --reverse'
190
- puts
191
-
192
- puts '--combine'.colorize(:green)
193
- puts ' Omit archive identifier dividers. Useful with sort or time filters'
194
- puts ' Ex: --combine'
195
- puts
196
-
197
- puts '--start'.colorize(:green)
198
- puts ' Show events after specified time. Filtered by the `time` field'
199
- puts ' Use with `--end` for between selections'
200
- puts ' Ex: log filter --start="2021-06-22 14:44 UTC" --end="2021-06-22 14:45 UTC"'
133
+ # rubocop:disable Layout/LineLength
134
+ # TODO: Add a lot more examples
135
+ def self.examples
136
+ puts 'Find `done` job for sidekiq, sort by duration, only duration, and show longest first'.pastel(:bright_green)
137
+ puts 'log filter sidekiq/current --job_status=done --sort=duration_s,db_duration_s --slice=duration_s,db_duration_s --reverse'
201
138
  puts
202
139
 
203
- puts '--end'.colorize(:green)
204
- puts ' Show events before specified time. Filtered by the `time` field'
205
- puts ' Use with `--start` for between selections'
206
- puts ' Ex: log filter --end="2021-06-22"'
140
+ puts 'Find 500s only show exceptions'.pastel(:bright_green)
141
+ puts 'log filter --status=500 --slice=exception.message gitlab-rails/production_json.log'
207
142
  puts
208
143
 
209
- puts 'Field Searching'.colorize(:blue)
210
- puts ' --[key]=[value]'
211
- puts ' Search in key for value'
212
- puts ' Example: --path=mirror/pull'
144
+ puts 'Show unique sidekiq queue namespaces. Exclude Specifics'.pastel(:bright_green)
145
+ puts 'filter sidekiq/current --slice=queue_namespace --uniq=queue_namespace --queue_namespace!=jira_connect --queue_namespace!=hashed_storage'
213
146
  puts
214
147
 
215
- puts 'Search specific logs'.colorize(:blue)
216
- puts ' Any non dash parameters will be the log list to search from'
217
- puts " Ex: log filter --path=api sidekiq/current (hint: use `#{'ls'.colorize(:yellow)}` for log names"
148
+ puts 'Show user,ip from API logs where `meta.user` field is present '.pastel(:bright_green)
149
+ puts 'gitlab-rails/api_json.log --slice=meta.user,meta.remote_ip --exists=meta.user'
218
150
  puts
219
151
 
220
- puts 'Example Queries'.colorize(:blue)
221
- puts " Also see #{'filter_examples'.colorize(:light_blue)} for even more examples"
222
- puts 'log filter --class=BuildFinishedWorker sidekiq/current --slice=time,message'
223
- puts 'log filter gitlab-rails/api_json.log --slice=ua --uniq=ua --ua=gitlab-runner'
224
-
152
+ puts 'Count/% occurences for both user and remote ip fields'.pastel(:bright_green)
153
+ puts 'gitlab-rails/api_json.log --stats=meta.user,meta.remote_ip --exists=meta.user'
225
154
  puts
226
155
  end
227
- # rubocop:enable Metrics/MethodLength
228
156
 
229
- # rubocop:disable Layout/LineLength
230
- # TODO: Add a lot more examples
231
- def self.filter_examples
232
- puts 'Find `done` job for sidekiq, sort by duration, only duration, and show longest first'.colorize(:light_green)
233
- puts 'log filter sidekiq/current --job_status=done --sort=duration_s,db_duration_s --slice=duration_s,db_duration_s --reverse'
234
- puts
235
- puts 'Find 500s only show exceptions'.colorize(:light_green)
236
- puts 'log filter --status=500 --slice=exception.message gitlab-rails/production_json.log'
237
- puts
238
- end
239
157
  # rubocop:enable Layout/LineLength
240
-
241
158
  # ========================================================================
242
159
  # Search (Full Text / String Search)
243
160
  # ========================================================================
244
- # Supported Params
245
- # --text='asdf'
246
- # --text!='asdf'
247
- # --regex='' # TODO?
248
- # --slice=time,path (E.g. log filter --path='mirror/pull' --slice=path,time )
249
- # --except: Exclude specific fields (except multiple with comma)
250
-
251
- # --total Total Count Entries Only
252
- def self.search(initial_param)
161
+ def self.search(raw)
253
162
  # Extract Args
254
- log_list, opts, args = ShellHelper.param_parse(initial_param)
163
+ files_list, flags, args = Args.parse(raw)
255
164
 
256
165
  # Prepare Log List
257
- log_list = ShellHelper.prepare_list(log_list)
258
-
259
- # AND / OR Filtering
260
- filter_type = args.or ? :any? : :all?
166
+ files = ShellHelper.prepare_list(files_list)
261
167
 
262
- results = ShellHelper.search_start(log_list, filter_type, args, opts)
168
+ results = ShellHelper.search_start(files, flags, args)
263
169
 
264
- # Skipo and Print Total if set
265
- if args.total
170
+ # Skip and Print Total if set
171
+ if flags[:total]
266
172
  ShellHelper.total_count(results)
267
173
  return true
268
174
  end
269
175
 
270
176
  # Check Search Results
271
177
  if results.values.flatten.empty?
272
- puts 'No results'.colorize(:red)
178
+ puts 'No results'.pastel(:red)
273
179
  else
274
180
  # This causes the key 'colorized' output to also be included
275
- ShellHelper.show(results.to_a.compact.flatten, args)
181
+ ShellHelper.show(results.to_a.compact.flatten, flags)
276
182
  end
277
183
  rescue StandardError => e
278
- LogBot.fatal('Filter', message: e.message, backtrace: e.backtrace.first)
184
+ LogBot.fatal('Search', message: e.message)
185
+ ap e.backtrace
279
186
  end
280
187
  # ========================================================================
281
188
 
@@ -287,48 +194,48 @@ module GreenHat
287
194
 
288
195
  # rubocop:disable Metrics/MethodLength
289
196
  def self.search_help
290
- puts "\u2500".colorize(:cyan) * 20
291
- puts 'Log Search'.colorize(:yellow)
292
- puts "\u2500".colorize(:cyan) * 20
197
+ puts "\u2500".pastel(:cyan) * 20
198
+ puts 'Log Search'.pastel(:yellow)
199
+ puts "\u2500".pastel(:cyan) * 20
293
200
 
294
201
  puts 'Search will do a full line include or exclude text search'
295
202
 
296
- puts 'Options'.colorize(:blue)
297
- puts '--text'.colorize(:green)
203
+ puts 'Options'.pastel(:blue)
204
+ puts '--text'.pastel(:green)
298
205
  puts ' Primary parameter for searching. Include or ! to exclude'
299
206
  puts ' Ex: --text=BuildHooksWorker --text!=start sidekiq/current'
300
207
  puts
301
208
 
302
- puts '--total'.colorize(:green)
209
+ puts '--total'.pastel(:green)
303
210
  puts ' Print only total count of matching entries'
304
211
  puts
305
212
 
306
- puts '--slice'.colorize(:green)
213
+ puts '--slice'.pastel(:green)
307
214
  puts ' Extract specific fields from entries (slice multiple with comma)'
308
215
  puts ' Ex: --slice=path or --slice=path,params'
309
216
  puts
310
217
 
311
- puts '--except'.colorize(:green)
218
+ puts '--except'.pastel(:green)
312
219
  puts ' Exclude specific fields (except multiple with comma)'
313
220
  puts ' Ex: --except=params --except=params,path'
314
221
  puts
315
222
 
316
- puts '--archive'.colorize(:green)
317
- puts ' Limit to specific archvie name (inclusive). Matching SOS tar.gz name'
223
+ puts '--archive'.pastel(:green)
224
+ puts ' Limit to specific archive name (inclusive). Matching SOS tar.gz name'
318
225
  puts ' Ex: --archive=dev-gitlab_20210622154626, --archive=202106,202107'
319
226
  puts
320
227
 
321
- puts '--limit'.colorize(:green)
228
+ puts '--limit'.pastel(:green)
322
229
  puts ' Limit total number of results. Default to half total screen size'
323
230
  puts ' Ex: --limit; --limit=10'
324
231
  puts
325
232
 
326
- puts 'Search specific logs'.colorize(:blue)
233
+ puts 'Search specific logs'.pastel(:blue)
327
234
  puts ' Any non dash parameters will be the log list to search from'
328
- puts " Ex: log filter --path=api sidekiq/current (hint: use `#{'ls'.colorize(:yellow)}` for log names"
235
+ puts " Ex: log filter --path=api sidekiq/current (hint: use `#{'ls'.pastel(:yellow)}` for log names)"
329
236
  puts
330
237
 
331
- puts 'Example Queries'.colorize(:blue)
238
+ puts 'Example Queries'.pastel(:blue)
332
239
  puts 'log search --text=BuildHooksWorker --text!=start sidekiq/current --total'
333
240
  puts 'log search --text=BuildHooksWorker --text!=start --slice=enqueued_at sidekiq/current'
334
241
  puts
@@ -337,7 +244,6 @@ module GreenHat
337
244
 
338
245
  # ------------------------------------------------------------------------
339
246
  end
340
- # rubocop:enable Metrics/ModuleLength
341
247
  end
342
248
  end
343
249
 
@@ -0,0 +1,39 @@
1
+ module GreenHat
2
+ module ShellHelper
3
+ # Helper to organize page check / methods
4
+ module Page
5
+ # Check if paging should be skipped
6
+ # True / False / Not Set
7
+ def self.skip?(flags, data)
8
+ # Pass if Explicitly Set / Inverse for skip
9
+ return !flags[:page] if flags.key? :page
10
+
11
+ LogBot.debug('Page', count_rows(data, flags)) if ENV['DEBUG']
12
+
13
+ count_rows(data, flags)
14
+ end
15
+
16
+ # Array/Hash and String pagination check. Don't unncessarily loop through everything
17
+ def self.count_rows(data, flags)
18
+ height = TTY::Screen.height
19
+ size = 0
20
+
21
+ data.each do |entry|
22
+ size += case entry
23
+ when Hash then entry.keys.count
24
+ when Array then entry.count
25
+ else
26
+ # Each Boxed Entry is 3 Lines
27
+ flags.key?(:row_size) ? flags[:row_size] : 1
28
+
29
+ end
30
+
31
+ break if size > height
32
+ end
33
+
34
+ size < height
35
+ end
36
+ end
37
+ # ----
38
+ end
39
+ end