greenhat 0.3.4 → 0.5.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.
- checksums.yaml +4 -4
- data/bin/greenhat +2 -6
- data/lib/greenhat/accessors/disk.rb +1 -3
- data/lib/greenhat/accessors/gitlab.rb +7 -2
- data/lib/greenhat/accessors/memory.rb +1 -1
- data/lib/greenhat/archive.rb +19 -8
- data/lib/greenhat/cli.rb +35 -135
- data/lib/greenhat/entrypoint.rb +170 -0
- data/lib/greenhat/host.rb +25 -37
- data/lib/greenhat/settings.rb +33 -5
- data/lib/greenhat/shell/args.rb +22 -9
- data/lib/greenhat/shell/faststats.rb +23 -3
- data/lib/greenhat/shell/field_helper.rb +1 -1
- data/lib/greenhat/shell/filter_help.rb +217 -162
- data/lib/greenhat/shell/gitlab.rb +1 -0
- data/lib/greenhat/shell/log.rb +150 -25
- data/lib/greenhat/shell/markdown.rb +21 -25
- data/lib/greenhat/shell/old_search_helper.rb +54 -0
- data/lib/greenhat/shell/page.rb +1 -1
- data/lib/greenhat/shell/pipe.rb +31 -0
- data/lib/greenhat/shell/platform.rb +28 -0
- data/lib/greenhat/shell/query.rb +378 -0
- data/lib/greenhat/shell/report.rb +76 -24
- data/lib/greenhat/shell/shell_helper.rb +42 -393
- data/lib/greenhat/shell.rb +19 -4
- data/lib/greenhat/thing/file_types.rb +51 -1
- data/lib/greenhat/thing/formatters/api_json.rb +4 -2
- data/lib/greenhat/thing/formatters/bracket_log.rb +1 -1
- data/lib/greenhat/thing/formatters/colon_split_strip.rb +2 -2
- data/lib/greenhat/thing/formatters/dotenv.rb +1 -1
- data/lib/greenhat/thing/formatters/format.rb +0 -11
- data/lib/greenhat/thing/formatters/free_m.rb +2 -2
- data/lib/greenhat/thing/formatters/json.rb +43 -15
- data/lib/greenhat/thing/formatters/json_shellwords.rb +3 -2
- data/lib/greenhat/thing/formatters/kube_json.rb +3 -2
- data/lib/greenhat/thing/formatters/multiline_json.rb +1 -1
- data/lib/greenhat/thing/formatters/nginx.rb +11 -3
- data/lib/greenhat/thing/formatters/table.rb +3 -3
- data/lib/greenhat/thing/formatters/time_space.rb +0 -16
- data/lib/greenhat/thing/helpers.rb +12 -11
- data/lib/greenhat/thing/info_format.rb +4 -4
- data/lib/greenhat/thing/kind.rb +5 -0
- data/lib/greenhat/thing/super_log.rb +0 -101
- data/lib/greenhat/thing.rb +31 -25
- data/lib/greenhat/version.rb +1 -1
- data/lib/greenhat/views/api.slim +55 -0
- data/lib/greenhat/views/chart.slim +42 -0
- data/lib/greenhat/views/chart_template.slim +31 -0
- data/lib/greenhat/views/chartkick.js +21 -0
- data/lib/greenhat/views/css.slim +47 -0
- data/lib/greenhat/views/gitaly.slim +53 -0
- data/lib/greenhat/views/headers.slim +16 -0
- data/lib/greenhat/views/index-old.slim +51 -0
- data/lib/greenhat/views/index.slim +14 -14
- data/lib/greenhat/views/info.slim +17 -18
- data/lib/greenhat/views/production.slim +55 -0
- data/lib/greenhat/views/sidekiq.slim +55 -0
- data/lib/greenhat/views/time.slim +63 -0
- data/lib/greenhat/views/workhorse.slim +16 -0
- data/lib/greenhat/web/api.rb +94 -0
- data/lib/greenhat/web/chartkick_shim.rb +14 -0
- data/lib/greenhat/web/faststats.rb +44 -0
- data/lib/greenhat/web/gitaly.rb +65 -0
- data/lib/greenhat/web/helpers.rb +198 -0
- data/lib/greenhat/web/production.rb +104 -0
- data/lib/greenhat/web/sidekiq.rb +73 -0
- data/lib/greenhat/web/stats_helpers.rb +74 -0
- data/lib/greenhat/web/time.rb +36 -0
- data/lib/greenhat/web/workhorse.rb +43 -0
- data/lib/greenhat/web.rb +63 -19
- data/lib/greenhat.rb +2 -0
- metadata +74 -5
@@ -55,12 +55,14 @@ module GreenHat
|
|
55
55
|
# Default Pager
|
56
56
|
TTY::Pager.page do |pager|
|
57
57
|
data.each do |entry|
|
58
|
-
output = entry_show(flags, entry)
|
58
|
+
output = "\n#{entry_show(flags, entry)}"
|
59
|
+
|
60
|
+
# output += "\n" if flags[:table_style] == 'basic'
|
59
61
|
|
60
62
|
# Breaks any intentional spaces
|
61
63
|
# next if output.blank?
|
62
64
|
|
63
|
-
pager.write(
|
65
|
+
pager.write(output) # write line to the pager
|
64
66
|
end
|
65
67
|
end
|
66
68
|
end
|
@@ -72,7 +74,7 @@ module GreenHat
|
|
72
74
|
when Hash then render_table(entry, flags)
|
73
75
|
when Float, Integer, Array
|
74
76
|
format_table_entry(flags, entry, key)
|
75
|
-
|
77
|
+
# Ignore Special Formatting for Strings / Usually already formatted
|
76
78
|
when String
|
77
79
|
entry
|
78
80
|
else
|
@@ -88,13 +90,12 @@ module GreenHat
|
|
88
90
|
when Float, Integer || entry.numeric?
|
89
91
|
flags.key?(:round) ? entry.to_f.round(flags.round).ai : entry.ai
|
90
92
|
|
91
|
-
|
93
|
+
# General Inspecting
|
92
94
|
when Hash then entry.ai(ruby19_syntax: true)
|
93
95
|
|
94
96
|
# Arrays often contain Hashes. Dangerous Recursive?
|
95
97
|
when Array
|
96
98
|
entry.map { |x| format_table_entry(flags, x) }.join("\n")
|
97
|
-
|
98
99
|
when Time
|
99
100
|
entry.to_s.pastel(:bright_white)
|
100
101
|
|
@@ -103,7 +104,8 @@ module GreenHat
|
|
103
104
|
StringColor.do(key, entry)
|
104
105
|
end
|
105
106
|
|
106
|
-
|
107
|
+
# Stats truncation handled separately
|
108
|
+
if flags[:truncate] && !flags[:stats]
|
107
109
|
entry_truncate(formatted_entry, flags[:truncate])
|
108
110
|
else
|
109
111
|
formatted_entry
|
@@ -117,7 +119,7 @@ module GreenHat
|
|
117
119
|
|
118
120
|
# Print the Table in a Nice way
|
119
121
|
def self.render_table(entry, flags)
|
120
|
-
entry = entry.
|
122
|
+
entry = entry.to_h { |k, v| [k, format_table_entry(flags, v, k)] }
|
121
123
|
# Pre-format Entry
|
122
124
|
|
123
125
|
table_style = flags[:table_style]&.to_sym || :unicode
|
@@ -125,10 +127,15 @@ module GreenHat
|
|
125
127
|
table = TTY::Table.new(header: entry.keys, rows: [entry], orientation: :vertical)
|
126
128
|
|
127
129
|
LogBot.debug('Rendering Entries') if ENV['DEBUG']
|
128
|
-
table.render(table_style, padding: [0, 1, 0, 1], multiline: true) do |renderer|
|
130
|
+
output = table.render(table_style, padding: [0, 1, 0, 1], multiline: true) do |renderer|
|
129
131
|
renderer.border.style = :cyan
|
130
132
|
end
|
131
133
|
|
134
|
+
# Line breaks for basic tables
|
135
|
+
output += "\n" if flags[:table_style] == 'basic'
|
136
|
+
|
137
|
+
output
|
138
|
+
|
132
139
|
# LogBot.debug('Finish Render Table') if ENV['DEBUG']
|
133
140
|
# Fall Back to Amazing Inspect
|
134
141
|
rescue StandardError => e
|
@@ -157,171 +164,10 @@ module GreenHat
|
|
157
164
|
files, flags, args = Args.parse(Shellwords.split(search))
|
158
165
|
flags[:combine] = true
|
159
166
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
# Main Entry Point for Filtering
|
164
|
-
def self.filter_start(files, flags = {}, args = {})
|
165
|
-
# Convert to Things
|
166
|
-
logs = ShellHelper.find_things(files, flags).select(&:processed?)
|
167
|
-
|
168
|
-
# Ignore Archive/Host Dividers
|
169
|
-
if flags[:combine]
|
170
|
-
results = logs.reject(&:blank?).map(&:data).flatten.compact
|
171
|
-
ShellHelper.filter(results, flags, args)
|
172
|
-
else
|
173
|
-
# Iterate and Preserve Archive/Host Index
|
174
|
-
logs.each_with_object({}) do |log, obj|
|
175
|
-
# Ignore Empty Results / No Thing
|
176
|
-
next if log&.blank?
|
177
|
-
|
178
|
-
# Include Total Count in Name
|
179
|
-
results = ShellHelper.filter(log.data, flags, args)
|
180
|
-
title = [
|
181
|
-
log.friendly_name,
|
182
|
-
" #{results.count}".pastel(:bright_black)
|
183
|
-
]
|
184
|
-
|
185
|
-
# Save unless empty
|
186
|
-
obj[title.join] = results unless results.count.zero?
|
187
|
-
|
188
|
-
obj
|
189
|
-
end
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
# Filter Logic
|
194
|
-
# TODO: Simplify
|
195
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
196
|
-
def self.filter(data, flags = {}, args = {})
|
197
|
-
# results = data.clone.flatten.compact
|
198
|
-
|
199
|
-
# Experimenting with deep clone
|
200
|
-
results = Marshal.load(Marshal.dump(data))
|
201
|
-
results.select! do |row|
|
202
|
-
args.send(flags.logic || :all?) do |arg|
|
203
|
-
filter_row_key(row, arg, flags)
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
# Ensure presecense of a specific field
|
208
|
-
results = filter_exists(results, flags[:exists]) if flags.key?(:exists)
|
209
|
-
|
210
|
-
# Time Zone
|
211
|
-
results = filter_modify_timezone(results, flags[:time_zone]) if flags.key?(:time_zone)
|
212
|
-
|
213
|
-
# Time Filtering
|
214
|
-
results = filter_time(results, flags) if flags.key?(:start) || flags.key?(:end)
|
215
|
-
|
216
|
-
# Strip Results if Slice is defined
|
217
|
-
results = filter_slice(results, flags[:slice]) if flags.key?(:slice)
|
218
|
-
|
219
|
-
# Strip Results if Except is defined
|
220
|
-
results = filter_except(results, flags[:except]) if flags.key?(:except)
|
221
|
-
|
222
|
-
# Remove Blank from either slice or except
|
223
|
-
results.reject!(&:empty?)
|
224
|
-
|
225
|
-
# Sort
|
226
|
-
results.sort_by! { |x| x.slice(*flags[:sort]).values } if flags.key?(:sort)
|
227
|
-
|
228
|
-
# JSON Formatting
|
229
|
-
results = results.map { |x| Oj.dump(x) } if flags.key?(:json)
|
230
|
-
|
231
|
-
# Show Unique Only
|
232
|
-
results = filter_uniq(results, flags[:uniq]) if flags.key?(:uniq)
|
233
|
-
|
234
|
-
# Reverse
|
235
|
-
results.reverse! if flags[:reverse]
|
236
|
-
|
237
|
-
# Count occurrences / Skip Results
|
238
|
-
return filter_stats(results, flags) if flags.key?(:stats)
|
239
|
-
|
240
|
-
# Limit before Pluck / Flattening
|
241
|
-
results = filter_limit(results, flags[:limit]) if flags.key?(:limit)
|
242
|
-
|
243
|
-
# Pluck
|
244
|
-
results = filter_pluck(results, flags[:pluck]) if flags.key?(:pluck)
|
245
|
-
|
246
|
-
results
|
247
|
-
end
|
248
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
249
|
-
|
250
|
-
# Limit / Ensure Exists and Valid Number
|
251
|
-
def self.filter_limit(results, limit)
|
252
|
-
return results unless limit.integer? && limit.positive?
|
253
|
-
|
254
|
-
results.shift limit
|
255
|
-
end
|
256
|
-
|
257
|
-
def self.filter_modify_timezone(results, time_zone)
|
258
|
-
results.each do |x|
|
259
|
-
next unless x.key? :time
|
167
|
+
# Default to everything
|
168
|
+
files = Thing.all.map(&:name) if files.empty?
|
260
169
|
|
261
|
-
|
262
|
-
end
|
263
|
-
|
264
|
-
results
|
265
|
-
end
|
266
|
-
|
267
|
-
# Filter Start and End Times
|
268
|
-
# rubocop:disable Metrics/MethodLength
|
269
|
-
# TODO: This is a bit icky, simplify/dry
|
270
|
-
def self.filter_time(results, flags)
|
271
|
-
if flags.key?(:start)
|
272
|
-
begin
|
273
|
-
time_start = Time.parse(flags[:start])
|
274
|
-
|
275
|
-
results.select! do |x|
|
276
|
-
if x.time
|
277
|
-
time_start < x.time
|
278
|
-
else
|
279
|
-
true
|
280
|
-
end
|
281
|
-
end
|
282
|
-
rescue StandardError
|
283
|
-
puts 'Unable to Process Start Time Filter'.pastel(:red)
|
284
|
-
end
|
285
|
-
end
|
286
|
-
|
287
|
-
if flags.key?(:end)
|
288
|
-
begin
|
289
|
-
time_start = Time.parse(flags[:end])
|
290
|
-
|
291
|
-
results.select! do |x|
|
292
|
-
if x.time
|
293
|
-
time_start > x.time
|
294
|
-
else
|
295
|
-
true
|
296
|
-
end
|
297
|
-
end
|
298
|
-
rescue StandardError
|
299
|
-
puts 'Unable to Process End Time Filter'.pastel(:red)
|
300
|
-
end
|
301
|
-
end
|
302
|
-
|
303
|
-
results
|
304
|
-
end
|
305
|
-
# rubocop:enable Metrics/MethodLength
|
306
|
-
|
307
|
-
def self.filter_except(results, except)
|
308
|
-
# Avoid Empty Results
|
309
|
-
if except.empty?
|
310
|
-
filter_empty_arg('except')
|
311
|
-
return results
|
312
|
-
end
|
313
|
-
|
314
|
-
results.map { |row| row.except(*except) }
|
315
|
-
end
|
316
|
-
|
317
|
-
def self.filter_exists(results, exists)
|
318
|
-
# Avoid Empty Results
|
319
|
-
if exists.empty?
|
320
|
-
filter_empty_arg('exists')
|
321
|
-
return results
|
322
|
-
end
|
323
|
-
|
324
|
-
results.select { |row| (exists - row.keys).empty? }
|
170
|
+
Query.start(files, flags, args)
|
325
171
|
end
|
326
172
|
|
327
173
|
def self.entry_truncate(entry, truncate)
|
@@ -335,156 +181,31 @@ module GreenHat
|
|
335
181
|
"#{entry.to_s[0..truncate]} #{'...'.pastel(:bright_blue)}"
|
336
182
|
end
|
337
183
|
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
results.map { |x| x.slice(*pluck).values }.flatten
|
356
|
-
end
|
357
|
-
|
358
|
-
def self.filter_uniq(results, unique)
|
359
|
-
# Avoid Empty Results
|
360
|
-
if unique.empty?
|
361
|
-
filter_empty_arg('uniq')
|
362
|
-
return results
|
363
|
-
end
|
364
|
-
|
365
|
-
unique.map do |field|
|
366
|
-
results.uniq { |x| x[field] }
|
367
|
-
end.inject(:&)
|
368
|
-
end
|
369
|
-
|
370
|
-
def self.filter_stats(results, flags)
|
371
|
-
stats = flags[:stats]
|
372
|
-
|
373
|
-
# Avoid Empty Results
|
374
|
-
if stats.empty?
|
375
|
-
filter_empty_arg('stats')
|
376
|
-
return results
|
377
|
-
end
|
378
|
-
|
379
|
-
# Loop through Stats, Separate Hash/Tables
|
380
|
-
stats.map do |field|
|
381
|
-
occurrences = filter_count_occurrences(results, field, flags)
|
382
|
-
|
383
|
-
# Total Occurences
|
384
|
-
total = occurrences.values.sum
|
385
|
-
|
386
|
-
# Percs
|
387
|
-
occurrences.transform_values! do |count|
|
388
|
-
[
|
389
|
-
count,
|
390
|
-
" #{percent(count, total)}%".pastel(:bright_black)
|
391
|
-
]
|
392
|
-
end
|
393
|
-
|
394
|
-
# Sort by total occurances / New Variable for Total
|
395
|
-
output = occurrences.sort_by(&:last).to_h.transform_values!(&:join).to_a
|
396
|
-
|
397
|
-
# Append Header / Total with field name
|
398
|
-
output.unshift([field.to_s.pastel(:bright_black), total])
|
399
|
-
|
400
|
-
# Use Truncate For Long Keys
|
401
|
-
if flags[:truncate]
|
402
|
-
output.map! do |key, value|
|
403
|
-
[key.to_s[0..flags[:truncate]], value]
|
404
|
-
end
|
405
|
-
end
|
406
|
-
|
407
|
-
# Format
|
408
|
-
output.to_h
|
409
|
-
end
|
410
|
-
end
|
411
|
-
|
412
|
-
# Percent Helper
|
413
|
-
def self.percent(value, total)
|
414
|
-
((value / total.to_f) * 100).round
|
415
|
-
end
|
416
|
-
|
417
|
-
# Helper to Count occurrences
|
418
|
-
def self.filter_count_occurrences(results, field, flags = {})
|
419
|
-
results.each_with_object(Hash.new(0)) do |entry, counts|
|
420
|
-
if entry.key? field
|
421
|
-
# Rounding in pagination breaks stats
|
422
|
-
key = if flags.key?(:round) && entry[field].numeric?
|
423
|
-
entry[field].to_f.round(flags.round)
|
424
|
-
else
|
425
|
-
entry[field]
|
426
|
-
end
|
427
|
-
|
428
|
-
counts[key] += 1
|
429
|
-
else
|
430
|
-
counts['None'.pastel(:bright_black)] += 1
|
184
|
+
# Total Count Helper
|
185
|
+
def self.total_count(results, flags)
|
186
|
+
results.map do |k, v|
|
187
|
+
puts k
|
188
|
+
# puts "Total: #{v.count.to_s.pastel(:blue)}"
|
189
|
+
# puts "Time Covered: #{calculate_duration(v).pastel(:cyan)}"
|
190
|
+
|
191
|
+
output = {}
|
192
|
+
output[:total] = v.count
|
193
|
+
output[:duration] = Query.calculate_duration(v)
|
194
|
+
|
195
|
+
# Sort / Get first and Last
|
196
|
+
list = v.select(&:time).map(&:time)
|
197
|
+
unless list.blank?
|
198
|
+
output[:start] = list.first
|
199
|
+
output[:end] = list.last
|
431
200
|
end
|
432
201
|
|
433
|
-
|
434
|
-
end
|
435
|
-
end
|
436
|
-
|
437
|
-
def self.filter_empty_arg(arg)
|
438
|
-
puts [
|
439
|
-
'Ignoring'.pastel(:bright_yellow),
|
440
|
-
"--#{arg}".pastel(:cyan),
|
441
|
-
'it requires an argument'.pastel(:red)
|
442
|
-
].join(' ')
|
443
|
-
end
|
444
|
-
|
445
|
-
# Break out filter row logic into separate method
|
446
|
-
|
447
|
-
def self.filter_row_key(row, arg, flags)
|
448
|
-
# Ignore Other Logic if Field isn't even included / Full Text Searching
|
449
|
-
return false unless row.key?(arg[:field]) || arg[:field] == :text
|
450
|
-
|
451
|
-
# Sensitivity Check / Check for Match / Full Text Searching
|
452
|
-
included = if arg[:field] == :text
|
453
|
-
filter_row_entry(row.to_s, arg, flags)
|
454
|
-
else
|
455
|
-
filter_row_entry(row[arg.field].to_s, arg, flags)
|
456
|
-
end
|
202
|
+
puts render_table(output, flags)
|
457
203
|
|
458
|
-
# Pivot of off include vs exclude
|
459
|
-
if arg.bang
|
460
|
-
!included
|
461
|
-
else
|
462
|
-
included
|
463
|
-
end
|
464
|
-
end
|
465
|
-
|
466
|
-
# Field Partial / Case / Exact search
|
467
|
-
def self.filter_row_entry(entry, arg, flags)
|
468
|
-
# Exact Matching / Unless doing full text search
|
469
|
-
return entry.to_s == arg.value.to_s if flags.key?(:exact) && arg.field != :text
|
470
|
-
|
471
|
-
if flags.key?(:case)
|
472
|
-
entry.include? arg.value.to_s
|
473
|
-
else
|
474
|
-
entry.downcase.include? arg.value.to_s.downcase
|
475
|
-
end
|
476
|
-
end
|
477
|
-
|
478
|
-
# Total Count Helper
|
479
|
-
def self.total_count(results)
|
480
|
-
results.each do |k, v|
|
481
|
-
puts k
|
482
|
-
puts "Total: #{v.count.to_s.pastel(:blue)}"
|
483
204
|
puts
|
484
205
|
end
|
485
206
|
end
|
486
207
|
|
487
|
-
#
|
208
|
+
# Table Printer Helper
|
488
209
|
def self.fields_print(results)
|
489
210
|
results.each do |k, v|
|
490
211
|
puts k
|
@@ -522,8 +243,8 @@ module GreenHat
|
|
522
243
|
end
|
523
244
|
|
524
245
|
# Total Log List Manipulator
|
525
|
-
def self.prepare_list(log_list, base_list = nil
|
526
|
-
base_list ||=
|
246
|
+
def self.prepare_list(log_list, base_list = nil)
|
247
|
+
base_list ||= Thing.list
|
527
248
|
|
528
249
|
# Assume all
|
529
250
|
log_list.push '*' if log_list.empty?
|
@@ -534,9 +255,9 @@ module GreenHat
|
|
534
255
|
log_list
|
535
256
|
end
|
536
257
|
|
537
|
-
# Fuzzy match for things
|
258
|
+
# Fuzzy match for things / List used for processable (Hash Entries)
|
538
259
|
def self.thing_list
|
539
|
-
@thing_list ||= Thing.
|
260
|
+
@thing_list ||= Thing.list.map(&:name)
|
540
261
|
|
541
262
|
@thing_list
|
542
263
|
end
|
@@ -548,7 +269,7 @@ module GreenHat
|
|
548
269
|
return file if file.instance_of?(Thing)
|
549
270
|
|
550
271
|
if flags.fuzzy_file_match
|
551
|
-
Thing.
|
272
|
+
Thing.list.select { |x| x.name.include?(file) || x.type.include?(file) }
|
552
273
|
else
|
553
274
|
Thing.where name: file
|
554
275
|
end
|
@@ -560,62 +281,6 @@ module GreenHat
|
|
560
281
|
things
|
561
282
|
end
|
562
283
|
|
563
|
-
# Main Entry Point for Searching
|
564
|
-
# def self.search_start(log_list, filter_type, args, opts)
|
565
|
-
def self.search_start(files, flags, args)
|
566
|
-
# Convert to Things
|
567
|
-
logs = ShellHelper.find_things(files, flags)
|
568
|
-
|
569
|
-
logs.each_with_object({}) do |log, obj|
|
570
|
-
# Ignore Empty Results / No Thing
|
571
|
-
next if log&.data.blank?
|
572
|
-
|
573
|
-
obj[log.friendly_name] = ShellHelper.search(log.data, flags, args)
|
574
|
-
|
575
|
-
obj
|
576
|
-
end
|
577
|
-
end
|
578
|
-
|
579
|
-
# Generic Search Helper / String/Regex
|
580
|
-
def self.search(data, flags = {}, args = {})
|
581
|
-
results = data.clone.flatten.compact
|
582
|
-
results.select! do |row|
|
583
|
-
args.send(flags.logic) do |arg|
|
584
|
-
search_row(row, arg, flags)
|
585
|
-
end
|
586
|
-
end
|
587
|
-
|
588
|
-
# Strip Results if Slice is defined
|
589
|
-
results.map! { |row| row.slice(*flags[:slice]) } if flags[:slice]
|
590
|
-
|
591
|
-
# Strip Results if Except is defined
|
592
|
-
results.map! { |row| row.except(*flags[:except]) } if flags[:except]
|
593
|
-
|
594
|
-
# Remove Blank from either slice or except
|
595
|
-
results.reject!(&:empty?)
|
596
|
-
|
597
|
-
results
|
598
|
-
end
|
599
|
-
|
600
|
-
# Break out filter row logic into separate method
|
601
|
-
def self.search_row(row, arg, flags)
|
602
|
-
# Sensitivity Check / Check for Match
|
603
|
-
included = filter_row_entry(row.to_s, arg, flags)
|
604
|
-
|
605
|
-
# Pivot of off include vs exclude
|
606
|
-
if arg.bang
|
607
|
-
!included
|
608
|
-
else
|
609
|
-
included
|
610
|
-
end
|
611
|
-
end
|
612
|
-
|
613
|
-
# TODO: Remove?
|
614
|
-
# Color Reader Helper
|
615
|
-
# def self.pastel
|
616
|
-
# @pastel ||= Pastel.new
|
617
|
-
# end
|
618
|
-
|
619
284
|
# Number Helper
|
620
285
|
# https://gitlab.com/zedtux/human_size_to_number/-/blob/master/lib/human_size_to_number/helper.rb
|
621
286
|
def self.human_size_to_number(string)
|
@@ -637,23 +302,6 @@ module GreenHat
|
|
637
302
|
number.round
|
638
303
|
end
|
639
304
|
|
640
|
-
# TODO: Needed?
|
641
|
-
def self.filter_and(data, params = {})
|
642
|
-
result = data.clone.flatten.compact
|
643
|
-
params.each do |k, v|
|
644
|
-
result.select! do |row|
|
645
|
-
if row.key? k.to_sym
|
646
|
-
row[k.to_sym].include? v
|
647
|
-
else
|
648
|
-
false
|
649
|
-
end
|
650
|
-
end
|
651
|
-
next
|
652
|
-
end
|
653
|
-
|
654
|
-
result
|
655
|
-
end
|
656
|
-
|
657
305
|
# General Helper for `show`
|
658
306
|
def self.common_opts
|
659
307
|
puts 'Common Options'.pastel(:blue)
|
@@ -667,5 +315,6 @@ module GreenHat
|
|
667
315
|
puts
|
668
316
|
end
|
669
317
|
end
|
318
|
+
|
670
319
|
# rubocop:enable Metrics/ModuleLength
|
671
320
|
end
|
data/lib/greenhat/shell.rb
CHANGED
@@ -7,10 +7,25 @@ module GreenHat
|
|
7
7
|
# rubocop:enable Lint/Debugger
|
8
8
|
end
|
9
9
|
|
10
|
+
def self.settings
|
11
|
+
Settings.configure_settings
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.web
|
15
|
+
# Load Required Files
|
16
|
+
require 'greenhat/web'
|
17
|
+
|
18
|
+
GreenHat::Web.toggle
|
19
|
+
end
|
20
|
+
|
10
21
|
def self.df
|
11
22
|
Disk.df
|
12
23
|
end
|
13
24
|
|
25
|
+
def self.quit(_raw = {})
|
26
|
+
exit 0
|
27
|
+
end
|
28
|
+
|
14
29
|
def self.ps(raw = {})
|
15
30
|
Process.ps raw
|
16
31
|
end
|
@@ -23,12 +38,12 @@ module GreenHat
|
|
23
38
|
Memory.free
|
24
39
|
end
|
25
40
|
|
26
|
-
def self.load_local
|
27
|
-
return false
|
41
|
+
def self.load_local(prompt = true)
|
42
|
+
return false if prompt && !TTY::Prompt.new.yes?('Load local Omnibus GitLab Instance files?')
|
28
43
|
|
29
44
|
archive_path = "#{$TMP}/#{Time.now.to_i}_local"
|
30
45
|
Dir.mkdir(archive_path)
|
31
|
-
|
46
|
+
|
32
47
|
archive = Archive.new(name: archive_path, path: archive_path)
|
33
48
|
|
34
49
|
file_list = Dir['/var/log/gitlab/*/current'] + Dir['/var/log/gitlab/*/*.log']
|
@@ -53,7 +68,7 @@ module GreenHat
|
|
53
68
|
end
|
54
69
|
|
55
70
|
def self.quiet
|
56
|
-
Cli.
|
71
|
+
Cli.quiet_toggle
|
57
72
|
|
58
73
|
if Cli.quiet
|
59
74
|
puts "GreenHat Quiet Logging #{'Off'.pastel(:red)}"
|
@@ -67,7 +67,8 @@ module GreenHat
|
|
67
67
|
'etc/fstab' => {
|
68
68
|
format: :clean_raw,
|
69
69
|
pattern: [
|
70
|
-
%r{etc/fstab}
|
70
|
+
%r{etc/fstab},
|
71
|
+
/fstab/
|
71
72
|
]
|
72
73
|
},
|
73
74
|
'etc/os-release' => {
|
@@ -94,6 +95,12 @@ module GreenHat
|
|
94
95
|
/getenforce/
|
95
96
|
]
|
96
97
|
},
|
98
|
+
'geo-logcursor/current' => {
|
99
|
+
format: :raw,
|
100
|
+
pattern: [
|
101
|
+
%r{geo-logcursor/current}
|
102
|
+
]
|
103
|
+
},
|
97
104
|
'gitaly/current' => {
|
98
105
|
format: :json_shell,
|
99
106
|
log: true,
|
@@ -102,6 +109,13 @@ module GreenHat
|
|
102
109
|
%r{gitaly/@.*}
|
103
110
|
]
|
104
111
|
},
|
112
|
+
'gitaly/gitaly_hooks.log' => {
|
113
|
+
format: :shellwords,
|
114
|
+
log: true,
|
115
|
+
pattern: [
|
116
|
+
%r{gitaly/gitaly_hooks\.log}
|
117
|
+
]
|
118
|
+
},
|
105
119
|
'consul/current' => {
|
106
120
|
format: :time_space,
|
107
121
|
log: true,
|
@@ -351,6 +365,13 @@ module GreenHat
|
|
351
365
|
/nginx-ingress.log/
|
352
366
|
]
|
353
367
|
},
|
368
|
+
'nginx/access.log' => {
|
369
|
+
format: :nginx,
|
370
|
+
log: true,
|
371
|
+
pattern: [
|
372
|
+
%r{nginx/access.log}
|
373
|
+
]
|
374
|
+
},
|
354
375
|
'nginx/gitlab_pages_access.log' => {
|
355
376
|
format: :nginx,
|
356
377
|
log: true,
|
@@ -358,6 +379,13 @@ module GreenHat
|
|
358
379
|
%r{nginx/gitlab_pages_access.log}
|
359
380
|
]
|
360
381
|
},
|
382
|
+
'nginx/gitlab_pages_error.log' => {
|
383
|
+
format: :raw,
|
384
|
+
log: true,
|
385
|
+
pattern: [
|
386
|
+
%r{nginx/gitlab_pages_error.log}
|
387
|
+
]
|
388
|
+
},
|
361
389
|
'nginx/gitlab_access.log' => {
|
362
390
|
format: :nginx,
|
363
391
|
log: true,
|
@@ -546,6 +574,20 @@ module GreenHat
|
|
546
574
|
%r{unicorn/current}
|
547
575
|
]
|
548
576
|
},
|
577
|
+
'unicorn_stats' => {
|
578
|
+
format: :time_space,
|
579
|
+
log: true,
|
580
|
+
pattern: [
|
581
|
+
/unicorn_stats/
|
582
|
+
]
|
583
|
+
},
|
584
|
+
'unicorn/unicorn_stdout.log' => {
|
585
|
+
format: :raw,
|
586
|
+
log: true,
|
587
|
+
pattern: [
|
588
|
+
%r{unicorn/unicorn_stdout.log}
|
589
|
+
]
|
590
|
+
},
|
549
591
|
'running_swappiness' => {
|
550
592
|
format: :raw,
|
551
593
|
pattern: [
|
@@ -583,6 +625,7 @@ module GreenHat
|
|
583
625
|
log: true,
|
584
626
|
pattern: [
|
585
627
|
%r{sidekiq/current},
|
628
|
+
/sidekiq_current/,
|
586
629
|
%r{sidekiq/@.*}
|
587
630
|
]
|
588
631
|
},
|
@@ -646,6 +689,12 @@ module GreenHat
|
|
646
689
|
/uname/
|
647
690
|
]
|
648
691
|
},
|
692
|
+
'gitlab_socket_stats' => {
|
693
|
+
format: :gitlab_socket_stats,
|
694
|
+
pattern: [
|
695
|
+
/gitlab_socket_stats/
|
696
|
+
]
|
697
|
+
},
|
649
698
|
'uptime' => {
|
650
699
|
format: :raw,
|
651
700
|
pattern: [
|
@@ -769,6 +818,7 @@ module GreenHat
|
|
769
818
|
'gitlab-rails/production.log' => {
|
770
819
|
format: :raw,
|
771
820
|
pattern: [
|
821
|
+
/production.log/,
|
772
822
|
%r{gitlab-rails/production.log},
|
773
823
|
%r{webservice.log/production.log}
|
774
824
|
]
|