greenhat 0.3.3 → 0.4.0

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/bin/greenhat +1 -4
  3. data/lib/greenhat/accessors/disk.rb +42 -3
  4. data/lib/greenhat/accessors/gitlab.rb +30 -1
  5. data/lib/greenhat/accessors/memory.rb +1 -1
  6. data/lib/greenhat/archive.rb +19 -8
  7. data/lib/greenhat/cli.rb +24 -126
  8. data/lib/greenhat/entrypoint.rb +170 -0
  9. data/lib/greenhat/host.rb +25 -37
  10. data/lib/greenhat/settings.rb +6 -0
  11. data/lib/greenhat/shell/args.rb +22 -9
  12. data/lib/greenhat/shell/faststats.rb +23 -3
  13. data/lib/greenhat/shell/field_helper.rb +1 -1
  14. data/lib/greenhat/shell/filter_help.rb +232 -9
  15. data/lib/greenhat/shell/log.rb +153 -9
  16. data/lib/greenhat/shell/markdown.rb +352 -0
  17. data/lib/greenhat/shell/old_search_helper.rb +54 -0
  18. data/lib/greenhat/shell/page.rb +1 -1
  19. data/lib/greenhat/shell/pipe.rb +31 -0
  20. data/lib/greenhat/shell/platform.rb +28 -0
  21. data/lib/greenhat/shell/report.rb +106 -25
  22. data/lib/greenhat/shell/shell_helper.rb +115 -106
  23. data/lib/greenhat/shell.rb +10 -3
  24. data/lib/greenhat/thing/file_types.rb +136 -8
  25. data/lib/greenhat/thing/formatters/json.rb +4 -0
  26. data/lib/greenhat/thing/formatters/kube_json.rb +36 -0
  27. data/lib/greenhat/thing/formatters/kube_nginx.rb +48 -0
  28. data/lib/greenhat/thing/formatters/kube_webservice.rb +51 -0
  29. data/lib/greenhat/thing/formatters/nginx.rb +6 -2
  30. data/lib/greenhat/thing/formatters/registry.rb +47 -0
  31. data/lib/greenhat/thing/formatters/time_space.rb +0 -16
  32. data/lib/greenhat/thing/helpers.rb +12 -0
  33. data/lib/greenhat/thing/kind.rb +5 -0
  34. data/lib/greenhat/thing.rb +11 -0
  35. data/lib/greenhat/version.rb +1 -1
  36. data/lib/greenhat/views/api.slim +55 -0
  37. data/lib/greenhat/views/chart.slim +42 -0
  38. data/lib/greenhat/views/chart_template.slim +31 -0
  39. data/lib/greenhat/views/chartkick.js +21 -0
  40. data/lib/greenhat/views/css.slim +47 -0
  41. data/lib/greenhat/views/gitaly.slim +53 -0
  42. data/lib/greenhat/views/headers.slim +16 -0
  43. data/lib/greenhat/views/index-old.slim +51 -0
  44. data/lib/greenhat/views/index.slim +14 -14
  45. data/lib/greenhat/views/info.slim +17 -18
  46. data/lib/greenhat/views/production.slim +55 -0
  47. data/lib/greenhat/views/sidekiq.slim +55 -0
  48. data/lib/greenhat/views/time.slim +63 -0
  49. data/lib/greenhat/views/workhorse.slim +16 -0
  50. data/lib/greenhat/web/api.rb +94 -0
  51. data/lib/greenhat/web/chartkick_shim.rb +14 -0
  52. data/lib/greenhat/web/faststats.rb +44 -0
  53. data/lib/greenhat/web/gitaly.rb +65 -0
  54. data/lib/greenhat/web/helpers.rb +198 -0
  55. data/lib/greenhat/web/production.rb +104 -0
  56. data/lib/greenhat/web/sidekiq.rb +73 -0
  57. data/lib/greenhat/web/stats_helpers.rb +74 -0
  58. data/lib/greenhat/web/time.rb +36 -0
  59. data/lib/greenhat/web/workhorse.rb +43 -0
  60. data/lib/greenhat/web.rb +63 -19
  61. data/lib/greenhat.rb +2 -0
  62. metadata +78 -5
data/lib/greenhat/host.rb CHANGED
@@ -14,17 +14,23 @@ class Host < Teron
14
14
  # end
15
15
 
16
16
  def archive_name
17
- File.basename archive
17
+ archive.friendly_name
18
18
  end
19
19
 
20
20
  def find_file(file_name)
21
21
  files.find { |x| x.name == file_name }
22
22
  end
23
23
 
24
- def icon
25
- release_file = find_file files.map(&:name).grep(/_release/).first
24
+ def things
25
+ archive.things
26
+ end
26
27
 
27
- release = release_file.raw.join
28
+ def find_thing(param)
29
+ things.find { |x| x.name.include? param }
30
+ end
31
+
32
+ def icon
33
+ release = find_thing('etc/os-release').data['ID_LIKE']
28
34
 
29
35
  if release.include? 'ubuntu'
30
36
  'fa-ubuntu'
@@ -57,41 +63,36 @@ class Host < Teron
57
63
  end
58
64
  # ---------------------------
59
65
 
60
- def manifest
61
- file = find_file 'gitlab_version_manifest_json'
66
+ def gitlab_version
67
+ file = find_thing 'gitlab/version-manifest.json'
62
68
  return nil unless file
63
69
 
64
- Oj.load file.raw.join
70
+ file.data.build_version
65
71
  end
66
72
 
67
73
  def uptime
68
- file = find_file 'uptime'
74
+ file = find_thing 'uptime'
69
75
  return nil unless file
70
76
 
71
77
  file.raw
72
78
  end
73
79
 
74
80
  def uname
75
- file = find_file 'uname'
81
+ file = find_thing 'uname'
76
82
  return nil unless file
77
83
 
78
84
  file.raw.join
79
85
  end
80
86
 
81
87
  def cpuinfo
82
- file = find_file 'cpuinfo'
88
+ file = find_thing 'lscpu'
83
89
  return nil unless file
84
90
 
85
- file.raw.join("\n").split("\n\n").map do |cpu|
86
- all = cpu.split("\n").map do |row|
87
- row.delete("\t").split(': ')
88
- end
89
- { details: all[1..], order: all[0].last }
90
- end
91
+ file.data
91
92
  end
92
93
 
93
94
  def cpu_speed
94
- file = find_file 'lscpu'
95
+ file = find_thing 'lscpu'
95
96
  return nil unless file
96
97
 
97
98
  details = file.raw.find { |x| x.include? 'MHz' }
@@ -99,7 +100,7 @@ class Host < Teron
99
100
  end
100
101
 
101
102
  def total_memory
102
- file = find_file 'free_m'
103
+ file = find_thing 'free_m'
103
104
  return nil unless file
104
105
 
105
106
  value = file.raw.dig(1, 1).to_i
@@ -107,28 +108,28 @@ class Host < Teron
107
108
  end
108
109
 
109
110
  def free_m
110
- file = find_file 'free_m'
111
+ file = find_thing 'free_m'
111
112
  return nil unless file
112
113
 
113
114
  file.raw
114
115
  end
115
116
 
116
117
  def df_h
117
- file = find_file 'df_h'
118
+ file = find_thing 'df_h'
118
119
  return nil unless file
119
120
 
120
121
  file.raw
121
122
  end
122
123
 
123
124
  def netstat
124
- file = find_file 'netstat'
125
+ file = find_thing 'netstat'
125
126
  return nil unless file
126
127
 
127
128
  file.raw
128
129
  end
129
130
 
130
131
  def ulimit
131
- file = find_file 'ulimit'
132
+ file = find_thing 'ulimit'
132
133
  return nil unless file
133
134
 
134
135
  results = file.raw.map do |entry|
@@ -142,7 +143,7 @@ class Host < Teron
142
143
  end
143
144
 
144
145
  def processes
145
- file = find_file 'ps'
146
+ file = find_thing 'ps'
146
147
  return nil unless file
147
148
 
148
149
  headers = file.raw.first.split(' ', 11)
@@ -155,7 +156,7 @@ class Host < Teron
155
156
  end
156
157
 
157
158
  def systemctl_unit_files
158
- file = find_file 'systemctl_unit_files'
159
+ file = find_thing 'systemctl_unit_files'
159
160
  return nil unless file
160
161
 
161
162
  all = file.raw[1..-2].map do |x|
@@ -167,16 +168,3 @@ class Host < Teron
167
168
  all.sort_by(&:unit)
168
169
  end
169
170
  end
170
-
171
- # # Slim Wrapper
172
- # class List
173
- # attr_accessor :hosts
174
-
175
- # def initialize
176
- # self.hosts = []
177
- # end
178
-
179
- # def slim(file, host = nil)
180
- # Slim::Template.new("#{__dir__}/views/#{file}.slim").render(host)
181
- # end
182
- # end
@@ -6,12 +6,14 @@ module GreenHat
6
6
  @settings ||= {
7
7
  history: [],
8
8
  assume_json: true,
9
+ assume_raw: false,
9
10
  fuzzy_file_match: true,
10
11
 
11
12
  # round: [2],
12
13
  # page: [:true] Automatic,
13
14
  truncate: TTY::Screen.width * 4,
14
15
  color: true
16
+
15
17
  }
16
18
  end
17
19
 
@@ -19,6 +21,10 @@ module GreenHat
19
21
  settings.assume_json
20
22
  end
21
23
 
24
+ def self.assume_raw?
25
+ settings.assume_raw
26
+ end
27
+
22
28
  # Allow for future disabling of color output
23
29
  def self.color?
24
30
  settings.color
@@ -1,12 +1,5 @@
1
1
  module GreenHat
2
2
  # Module for Argument Parsing
3
- # Possible Args
4
- # --value=thing
5
- # --value / Default => --value=thing
6
- # --flag
7
- # --slice=value,value2
8
- # files
9
-
10
3
  # Variable Breakdown
11
4
  # Args:Array supplied or default values for entry looping action
12
5
  # Flags:Hash Key/Value filter Actionables
@@ -15,7 +8,14 @@ module GreenHat
15
8
  def self.parse(raw, skip_flags = [])
16
9
  # Don't affect original object / Better deep clone?
17
10
  cmd = raw.clone
18
- # cmd = Marshal.load(Marshal.dump(raw))
11
+
12
+ # Handle Pipe Params
13
+ pipe = nil
14
+ if cmd.include?('|')
15
+ list = cmd.split('|')
16
+ cmd = list.shift
17
+ pipe = list.map { |x| x.join(' ') }.join('|')
18
+ end
19
19
 
20
20
  # Extract Files
21
21
  files = cmd.grep_v(/^-+([^=]+)/)
@@ -33,6 +33,9 @@ module GreenHat
33
33
  # And / Or
34
34
  flag_defaults(flags, skip_flags)
35
35
 
36
+ # Set command includes
37
+ flags[:pipe] = pipe if pipe
38
+
36
39
  [files, flags, args]
37
40
  end
38
41
 
@@ -78,19 +81,29 @@ module GreenHat
78
81
  # Arg Scan (Split -- values into keys)
79
82
  def self.arg_scan(arg)
80
83
  arg.scan(/^-+([^=]+)=(.*)/).map do |field, value|
84
+ logic = :include?
81
85
  bang = false
86
+
87
+ # Exclude Logic
82
88
  if field.include? '!'
83
89
  field.delete!('!')
84
90
  bang = true
85
91
  end
86
92
 
93
+ # Numeric Magic Logic
94
+ logic = :<= if field.include? '<'
95
+ logic = :>= if field.include? '>'
96
+ field.delete!('<')
97
+ field.delete!('>')
98
+
87
99
  # Symbolize
88
100
  field = field.to_sym
89
101
 
90
102
  {
91
103
  field: field,
92
104
  value: arg_normalize(field, value),
93
- bang: bang
105
+ bang: bang,
106
+ logic: logic
94
107
  }
95
108
  end
96
109
  end
@@ -137,7 +137,7 @@ module GreenHat
137
137
  # --limit=X
138
138
  # --sort=count,fail,max,median,min,p95,p99,rps,score
139
139
  # ========================================================================
140
- def self.top(raw)
140
+ def self.top(raw = [], internal = false)
141
141
  unless TTY::Which.exist? 'fast-stats'
142
142
  faststats_installation
143
143
  return false
@@ -155,6 +155,9 @@ module GreenHat
155
155
  ]
156
156
  end
157
157
 
158
+ # Quick exit for internal processing
159
+ return results.flatten if internal
160
+
158
161
  ShellHelper.show(results.flatten, flags)
159
162
  end
160
163
  # ========================================================================
@@ -162,14 +165,14 @@ module GreenHat
162
165
  # ========================================================================
163
166
  # ===== [ Fast Stats - Errors ] ====================
164
167
  # ========================================================================
165
- def self.errors(raw)
168
+ def self.errors(raw = [], internal = false)
166
169
  unless TTY::Which.exist? 'fast-stats'
167
170
  faststats_installation
168
171
  return false
169
172
  end
170
173
 
171
174
  # Add Color Output
172
- raw.push '--color-output'
175
+ raw.push '--color-output' if Settings.settings.color?
173
176
  files, flags, cmd = ShellHelper::Faststats.parse(raw)
174
177
 
175
178
  LogBot.debug('FastStats CMD', cmd) if ENV['DEBUG']
@@ -182,6 +185,9 @@ module GreenHat
182
185
  ]
183
186
  end
184
187
 
188
+ # Quick exit for internal processing
189
+ return results.flatten if internal
190
+
185
191
  ShellHelper.show(results.flatten, flags)
186
192
  end
187
193
  # ========================================================================
@@ -236,6 +242,20 @@ module GreenHat
236
242
  files.any? { |x| thing.name.include? x }
237
243
  end
238
244
  end
245
+
246
+ # =====================================
247
+ # Internal Helpers
248
+ # =====================================
249
+ def self.faststats?
250
+ TTY::Which.exist?('fast-stats')
251
+ end
252
+
253
+ def self.run(thing, cmd = '')
254
+ # Blank return if cannot possibly run
255
+ return {} unless thing || !faststats?
256
+
257
+ Oj.load `fast-stats #{cmd} #{thing.file} --format=json`
258
+ end
239
259
  end
240
260
  end
241
261
  end
@@ -60,7 +60,7 @@ module GreenHat
60
60
  auto = fields.split(',').last
61
61
 
62
62
  # Field Finder
63
- matches = fields_find(files, auto, flags)
63
+ matches = fields_find(files, auto, flags).uniq
64
64
 
65
65
  if matches.count == 1
66
66
  "--#{cmd}=#{(complete + matches).join(',')}"
@@ -2,8 +2,8 @@ module GreenHat
2
2
  # CLI Helper
3
3
  module ShellHelper
4
4
  # Unify Filter / Filter Help
5
+ # rubocop:disable Metrics/MethodLength,Metrics/ModuleLength,Layout/LineLength
5
6
  module Filter
6
- # rubocop:disable Metrics/MethodLength
7
7
  def self.help
8
8
  puts "\u2500".pastel(:cyan) * 20
9
9
  puts 'Filter'.pastel(:yellow)
@@ -38,7 +38,7 @@ module GreenHat
38
38
  puts
39
39
 
40
40
  puts '--total'.pastel(:green)
41
- puts ' Print only total count of matching entries'
41
+ puts ' Show total count, duration, start/end time for matching entries'
42
42
  puts
43
43
 
44
44
  puts '--fields'.pastel(:green)
@@ -138,17 +138,39 @@ module GreenHat
138
138
  puts ' Ex: --truncate=200, --truncate=2048"'
139
139
  puts
140
140
 
141
- puts 'Field Searching'.pastel(:blue)
142
- puts ' --[key]=[value]'
143
- puts ' Search in key for value'
144
- puts ' Example: --path=mirror/pull'
145
- puts
146
-
147
141
  puts 'Search specific logs'.pastel(:blue)
148
142
  puts ' Any non dash parameters will be the log list to search from'
149
143
  puts " Ex: log filter --path=api sidekiq/current (hint: use `#{'ls'.pastel(:yellow)}` for log names"
150
144
  puts
151
145
 
146
+ puts 'General (Field) Searching'.pastel(:blue)
147
+ puts " There are different ways filter within specific keys/fields within log. The baseline is #{'--[key]=[value]'.pastel(:green)}"
148
+ puts ' This will, by default, select any entries with any partial match (case insensitive) of [value] in the entry [key]'
149
+ puts ' Example: --path=mirror/pull'
150
+ puts
151
+
152
+ puts " You can modify logic with params like: #{'case'.pastel(:green)}, #{'exact'.pastel(:green)}"
153
+ puts ' Ex Case turn on case sensitivity, exact will change from the inclusive to only exact matching.'
154
+ puts
155
+
156
+ puts " You can also use multiple #{'--[key]=[value]'.pastel(:green)} to narrow down, or combine it with #{'or'.pastel(:green)} to be more inclusive"
157
+ puts ' Ex nginx/gitlab_access.log --http_user_agent=gitlab-runner --path=/api/v4/jobs/request'
158
+ puts ' This will look through the access logs for anything that is a runner (user agent) and hitting the request endpoint'
159
+ puts
160
+
161
+ puts " You can also modify whether a field search excluded or a integer (and technically string) comparison by changing the operator: #{'(!= >= <=)'.pastel(:green)}"
162
+ puts ' Ex "nginx/gitlab_access.log --http_user_agent=gitlab-runner --http_user_agent!=13.12.0" will exclude any entries with 13.12.0/13.12 runners'
163
+ puts ' Ex "sidekiq/current --duration_s>=5 --class!=LdapSyncWorker" Duration over 5 that is not an ldap job'
164
+ puts
165
+
166
+ puts 'Pipe to Shell'.pastel(:blue)
167
+ puts ' This is very experimental! The idea is to take all the output from the search and allow a pipe into a traditional shell command.'
168
+ puts ' Due to the arg parsing its not a straight send to the terminal. You may need to escape quotes.'
169
+ puts ' Order is relevant, no arguments after the pipe'
170
+ puts
171
+ puts ' <files> <params> | grep path'
172
+ puts
173
+
152
174
  puts 'Example Queries'.pastel(:blue)
153
175
  puts " Also see #{'examples'.pastel(:bright_blue)} for even more examples"
154
176
  puts ' log filter --class=BuildFinishedWorker sidekiq/current --slice=time,message'
@@ -156,7 +178,208 @@ module GreenHat
156
178
 
157
179
  puts
158
180
  end
159
- # rubocop:enable Metrics/MethodLength
181
+
182
+ def self.help_index
183
+ {
184
+ title: [
185
+ "\u2500".pastel(:cyan) * 20,
186
+ 'Filter'.pastel(:yellow),
187
+ "\u2500".pastel(:cyan) * 20
188
+ ],
189
+ options: [
190
+ 'Options'.pastel(:blue)
191
+ ],
192
+
193
+ raw: [
194
+ '--raw'.pastel(:green),
195
+ ' Disable formatting and page/less'
196
+ ],
197
+
198
+ page: [
199
+ '--page'.pastel(:green),
200
+ ' Specifically enable or disable paging',
201
+ ' E.g. --page (default to true), --page=true, --page=false'
202
+ ],
203
+
204
+ round: ['--round'.pastel(:green),
205
+ ' Attempt to round all integers. Default: 2.',
206
+ ' E.g. --round, --round=3, --round=0'],
207
+
208
+ limit: [
209
+
210
+ '--limit'.pastel(:green),
211
+ ' Limit total output lines. Disabled by default. Default without value is based on screen height',
212
+ ' E.g. --limit, --limit=5'
213
+ ],
214
+
215
+ json: [
216
+ '--json'.pastel(:green),
217
+ ' Print output back into JSON'
218
+ ],
219
+
220
+ or: [
221
+ '--or'.pastel(:green),
222
+ ' Filters will use OR instead of AND (all match vs any match)'
223
+ ],
224
+
225
+ total: [
226
+ '--total'.pastel(:green),
227
+ ' Show total count, duration, start/end time for matching entries'
228
+ ],
229
+
230
+ fields: [
231
+ '--fields'.pastel(:green),
232
+ ' Print only Available fields for selected files'
233
+ ],
234
+
235
+ slice: [
236
+ '--slice'.pastel(:green),
237
+ ' Extract specific fields from entries (slice multiple with comma)',
238
+ ' Ex: --slice=path or --slice=path,params'
239
+
240
+ ],
241
+
242
+ except: [
243
+ '--except'.pastel(:green),
244
+ ' Exclude specific fields (except multiple with comma)',
245
+ ' Ex: --except=params --except=params,path'
246
+
247
+ ],
248
+
249
+ exists: [
250
+ '--exists'.pastel(:green),
251
+ ' Ensure field exists regardless of contents',
252
+ ' Ex: --exists=params --exists=params,path'
253
+
254
+ ],
255
+
256
+ stats: [
257
+ '--stats'.pastel(:green),
258
+ ' Order/Count occurrances by field. Combine with `truncate` for key names',
259
+ ' Ex: --stats=params --except=params,path'
260
+
261
+ ],
262
+
263
+ uniq: [
264
+ '--uniq'.pastel(:green),
265
+ ' Show unique values only',
266
+ ' Ex: --uniq=params --uniq=params,path'
267
+
268
+ ],
269
+
270
+ pluck: [
271
+ '--pluck'.pastel(:green),
272
+ ' Extract values from entries',
273
+ ' Ex: --pluck=params --pluck=params,path'
274
+
275
+ ],
276
+
277
+ archive: [
278
+ '--archive'.pastel(:green),
279
+ ' Limit to specific archvie name (partial matching /inclusive). Matching SOS tar.gz name',
280
+ ' Ex: --archive=dev-gitlab_20210622154626, --archive=202106,202107'
281
+
282
+ ],
283
+
284
+ sort: [
285
+ '--sort'.pastel(:green),
286
+ ' Sort by multiple fields',
287
+ ' Ex: --sort=duration_s,db_duration_s'
288
+
289
+ ],
290
+
291
+ reverse: [
292
+ '--reverse'.pastel(:green),
293
+ ' Reverse all results',
294
+ ' Ex: --reverse'
295
+
296
+ ],
297
+
298
+ combine: [
299
+ '--combine'.pastel(:green),
300
+ ' Omit archive identifier dividers. Useful with sort or time filters',
301
+ ' Ex: --combine'
302
+
303
+ ],
304
+
305
+ case: [
306
+ '--case'.pastel(:green),
307
+ ' Exact case match. Defaults to case insensitive',
308
+ ' Ex: --case; --name=Jon, --name=jane --case'
309
+
310
+ ],
311
+
312
+ exact: [
313
+ '--exact'.pastel(:green),
314
+ ' Exact parameter/value match. Defaults to partial match',
315
+ ' Ex: --field=CommonPartial --exact'
316
+
317
+ ],
318
+
319
+ start: [
320
+ '--start'.pastel(:green),
321
+ ' Show events after specified time. Filtered by the `time` field',
322
+ ' Use with `--end` for between selections',
323
+ ' Ex: log filter --start="2021-06-22 14:44 UTC" --end="2021-06-22 14:45 UTC"'
324
+
325
+ ],
326
+
327
+ end: [
328
+ '--end'.pastel(:green),
329
+ ' Show events before specified time. Filtered by the `time` field',
330
+ ' Use with `--start` for between selections',
331
+ ' Ex: log filter --end="2021-06-22"'
332
+ ],
333
+
334
+ time_zone: [
335
+ '--time_zone'.pastel(:green),
336
+ ' Manipulate the `time` field into a specific timezone',
337
+ ' Ex: log filter --time_zone=EDT'
338
+
339
+ ],
340
+
341
+ text: [
342
+ '--text'.pastel(:green),
343
+ ' Full entry text searching (slow)',
344
+ ' --text="anything here"'
345
+ ],
346
+
347
+ table_style: [
348
+ '--table_style'.pastel(:green),
349
+ ' Renderer used for formatted output. basic, ascii, or unicode(default)',
350
+ ' Ex: log filter --table_style=base'
351
+ ],
352
+
353
+ truncate: [
354
+ '--truncate'.pastel(:green),
355
+ ' Truncate field length. On by default (4 rows). Performance issues!',
356
+ ' Disable with --truncate=0'.pastel(:bright_red),
357
+ ' Ex: --truncate=200, --truncate=2048"'
358
+ ],
359
+
360
+ field: [
361
+ 'Field Searching'.pastel(:blue),
362
+ ' --[key]=[value]',
363
+ ' Search in key for value',
364
+ ' Example: --path=mirror/pull'
365
+ ],
366
+
367
+ ls: [
368
+ 'Search specific logs'.pastel(:blue),
369
+ ' Any non dash parameters will be the log list to search from',
370
+ " Ex: log filter --path=api sidekiq/current (hint: use `#{'ls'.pastel(:yellow)}` for log names"
371
+ ],
372
+
373
+ examples: [
374
+ 'Example Queries'.pastel(:blue),
375
+ " Also see #{'examples'.pastel(:bright_blue)} for even more examples",
376
+ ' log filter --class=BuildFinishedWorker sidekiq/current --slice=time,message',
377
+ ' log filter gitlab-rails/api_json.log --slice=ua --uniq=ua --ua=gitlab-runner'
378
+ ]
379
+
380
+ }
381
+ end
382
+ # rubocop:enable Metrics/MethodLength,Metrics/ModuleLength,Layout/LineLength
160
383
  end
161
384
  end
162
385
  end