greenhat 0.3.1 → 0.3.5
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/lib/greenhat/accessors/disk.rb +41 -0
- data/lib/greenhat/accessors/gitlab.rb +26 -0
- data/lib/greenhat/accessors/memory.rb +1 -1
- data/lib/greenhat/archive.rb +4 -0
- data/lib/greenhat/cli.rb +21 -6
- data/lib/greenhat/shell/args.rb +2 -2
- data/lib/greenhat/shell/faststats.rb +27 -0
- data/lib/greenhat/shell/field_helper.rb +75 -0
- data/lib/greenhat/shell/filter_help.rb +224 -4
- data/lib/greenhat/shell/log.rb +52 -2
- data/lib/greenhat/shell/markdown.rb +344 -0
- data/lib/greenhat/shell/report.rb +67 -18
- data/lib/greenhat/shell/shell_helper.rb +88 -18
- data/lib/greenhat/thing/file_types.rb +98 -7
- data/lib/greenhat/thing/formatters/kube_json.rb +36 -0
- data/lib/greenhat/thing/formatters/kube_nginx.rb +48 -0
- data/lib/greenhat/thing/formatters/kube_webservice.rb +51 -0
- data/lib/greenhat/thing/formatters/nginx.rb +2 -2
- data/lib/greenhat/thing/formatters/registry.rb +47 -0
- data/lib/greenhat/thing.rb +22 -0
- data/lib/greenhat/version.rb +1 -1
- data/lib/greenhat.rb +1 -0
- metadata +22 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6ff63bc1345ac9a27d3fa6263fc3a68e9c851aa30f2b3bf58cdee484ce142cbb
|
4
|
+
data.tar.gz: a150c0d19b954883ef2372280b78a89606a5e9039944b794289c9541c3548ed3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7011298d19ac200f7ea4bd10686642ac30911cbd509eb7dd0152a29b88f4dedd942803fdbd4198a9374e868d060cdf7f3458860c407210d0aa4e5a3e812d63e9
|
7
|
+
data.tar.gz: 8a7cdc716bd4c7f6edddfae2488593f2ec17908203218df57d542057753973528262ff96d1b9986b7c02ec4a08f33a740e0ba162e32752c75725c2c2a60affb5
|
@@ -79,5 +79,46 @@ module GreenHat
|
|
79
79
|
output
|
80
80
|
end
|
81
81
|
# rubocop:enable Metrics/MethodLength
|
82
|
+
|
83
|
+
# Unified Output Handler
|
84
|
+
def self.markdown_format(file, name = false, limit = nil, filter = %w[tmpfs loop])
|
85
|
+
output = []
|
86
|
+
|
87
|
+
output << file.friendly_name if name
|
88
|
+
|
89
|
+
# Reject TMPFS
|
90
|
+
disks = file.data.sort_by { |x| x.use.to_i }.reverse
|
91
|
+
|
92
|
+
# Filter
|
93
|
+
disks.reject! { |x| filter.any? { |y| x.filesystem.include? y } }
|
94
|
+
|
95
|
+
disks = disks[0..limit - 1] if limit
|
96
|
+
|
97
|
+
pad_mount, pad_size, pad_used, pad_avail = GreenHat::Disk.padding(disks)
|
98
|
+
|
99
|
+
# Headers
|
100
|
+
output << [
|
101
|
+
'Mount'.ljust(pad_mount),
|
102
|
+
'Size'.ljust(pad_size),
|
103
|
+
'Used'.ljust(pad_used),
|
104
|
+
'Avail'.ljust(pad_avail),
|
105
|
+
'% Use'.ljust(pad_avail)
|
106
|
+
].join
|
107
|
+
|
108
|
+
# Table Summary
|
109
|
+
disks.map do |disk|
|
110
|
+
# Whole Thing
|
111
|
+
output << [
|
112
|
+
disk.mounted_on.ljust(pad_mount),
|
113
|
+
disk[:size].to_s.ljust(pad_size),
|
114
|
+
disk.used.to_s.ljust(pad_used),
|
115
|
+
disk.avail.to_s.ljust(pad_avail),
|
116
|
+
disk.use.rjust(5).ljust(5)
|
117
|
+
].join
|
118
|
+
end
|
119
|
+
|
120
|
+
output
|
121
|
+
end
|
122
|
+
# =
|
82
123
|
end
|
83
124
|
end
|
@@ -71,5 +71,31 @@ module GreenHat
|
|
71
71
|
|
72
72
|
table.render(:unicode, padding: [0, 1, 0, 1], indent: indent)
|
73
73
|
end
|
74
|
+
|
75
|
+
def self.services_markdown(archive)
|
76
|
+
# manifest = archive.things.find { |x| x.type == 'gitlab/version-manifest.json' }
|
77
|
+
gitlab_status = archive.things.find { |x| x.name == 'gitlab_status' }
|
78
|
+
|
79
|
+
list = gitlab_status.data.keys.sort.map do |service|
|
80
|
+
status = gitlab_status.data.dig(service, 0, :status) == 'run' ? '↑' : '!'
|
81
|
+
|
82
|
+
"#{service}#{status}"
|
83
|
+
end
|
84
|
+
|
85
|
+
# Keep Alphabetical Sort
|
86
|
+
groups = list.each_slice((list.size / 3.to_f).round).to_a
|
87
|
+
|
88
|
+
table = TTY::Table.new do |t|
|
89
|
+
loop do
|
90
|
+
break if groups.all?(&:empty?)
|
91
|
+
|
92
|
+
t << groups.map(&:shift)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
"```\n#{table.render(:basic)}\n```"
|
97
|
+
end
|
98
|
+
|
99
|
+
# ==
|
74
100
|
end
|
75
101
|
end
|
data/lib/greenhat/archive.rb
CHANGED
data/lib/greenhat/cli.rb
CHANGED
@@ -65,7 +65,9 @@ module GreenHat
|
|
65
65
|
# Auto Complete
|
66
66
|
# =========================================================
|
67
67
|
def self.auto
|
68
|
-
word =
|
68
|
+
word = @list.last
|
69
|
+
# This is being weird with auto complete
|
70
|
+
# word = reader.line.word
|
69
71
|
|
70
72
|
if word.blank?
|
71
73
|
help
|
@@ -74,6 +76,10 @@ module GreenHat
|
|
74
76
|
end
|
75
77
|
end
|
76
78
|
|
79
|
+
def self.file_matches(word)
|
80
|
+
files.select { |x| x[/^#{Regexp.escape(word)}/] }
|
81
|
+
end
|
82
|
+
|
77
83
|
def self.auto_match(matches, word)
|
78
84
|
matches.select! { |x| x[/^#{Regexp.escape(word)}/] }
|
79
85
|
|
@@ -88,11 +94,14 @@ module GreenHat
|
|
88
94
|
elsif matches.count > 1
|
89
95
|
puts matches.join("\t").pastel(:bright_green)
|
90
96
|
|
91
|
-
#
|
92
|
-
|
93
|
-
file_matches
|
94
|
-
auto_files(file_matches, word) unless file_matches.empty?
|
97
|
+
# General Filename Matching
|
98
|
+
elsif !file_matches(word).empty?
|
99
|
+
auto_files(file_matches(word), word)
|
95
100
|
|
101
|
+
# Submodule Autocompletion
|
102
|
+
elsif current_methods.include?('auto_complete')
|
103
|
+
update_text = current_location.auto_complete(@list, word)
|
104
|
+
auto_update(update_text, word) unless update_text.blank?
|
96
105
|
end
|
97
106
|
end
|
98
107
|
|
@@ -237,13 +246,17 @@ module GreenHat
|
|
237
246
|
@list.any? { |x| x.include?(cmd) } && current_methods.include?('default')
|
238
247
|
end
|
239
248
|
|
249
|
+
def self.current_commands
|
250
|
+
current_location.methods(false).map(&:to_s).sort - %w[auto_complete]
|
251
|
+
end
|
252
|
+
|
240
253
|
# General Helper
|
241
254
|
def self.help(long = true)
|
242
255
|
if current_location.methods(false).count.zero?
|
243
256
|
puts 'No Commands'.pastel(:red)
|
244
257
|
else
|
245
258
|
puts 'Commands: '
|
246
|
-
|
259
|
+
current_commands.each do |item|
|
247
260
|
next if %w[default help].any? { |x| x == item }
|
248
261
|
|
249
262
|
puts "=> #{item.to_s.pastel(:blue)}"
|
@@ -340,6 +353,7 @@ module GreenHat
|
|
340
353
|
puts
|
341
354
|
puts 'Usage'.pastel(:yellow)
|
342
355
|
puts ' greenhat <sos-archive.tgz> <sos-archive2.tgz> '
|
356
|
+
puts ' greenhat <sos-archive.tgz> -q --command=df'
|
343
357
|
puts
|
344
358
|
|
345
359
|
puts 'Options'.pastel(:yellow)
|
@@ -406,6 +420,7 @@ module GreenHat
|
|
406
420
|
|
407
421
|
# CTL Tails need to be parsed for new 'things'
|
408
422
|
Thing.where(kind: :gitlab_tail)&.map(&:process)
|
423
|
+
Thing.where(kind: :kube_webservice)&.map(&:process)
|
409
424
|
|
410
425
|
Thing.all.each(&:process) if flags?(%i[load l], flags)
|
411
426
|
end
|
data/lib/greenhat/shell/args.rb
CHANGED
@@ -70,8 +70,8 @@ module GreenHat
|
|
70
70
|
# Flags Anything that isn't sent as a key/filter
|
71
71
|
def self.arg_to_flag_list
|
72
72
|
%i[
|
73
|
-
archive end except exists json limit pluck reverse round slice sort start
|
74
|
-
truncate uniq page
|
73
|
+
archive end except exists json limit pluck reverse round slice sort start
|
74
|
+
stats truncate uniq page time_zone table_style
|
75
75
|
]
|
76
76
|
end
|
77
77
|
|
@@ -67,8 +67,20 @@ module GreenHat
|
|
67
67
|
end
|
68
68
|
# rubocop:enable Metrics/MethodLength)
|
69
69
|
|
70
|
+
def self.faststats_installation
|
71
|
+
puts "#{'Unable to find'.pastel(:red)} #{'fast-stats'.pastel(:blue)}"
|
72
|
+
puts ' Release Downloads here'
|
73
|
+
puts ' - https://gitlab.com/gitlab-com/support/toolbox/fast-stats/-/releases'.pastel(:yellow)
|
74
|
+
puts ''
|
75
|
+
end
|
76
|
+
|
70
77
|
# List Files Helpers
|
71
78
|
def self.list(args = [])
|
79
|
+
unless TTY::Which.exist? 'fast-stats'
|
80
|
+
faststats_installation
|
81
|
+
return false
|
82
|
+
end
|
83
|
+
|
72
84
|
all = false
|
73
85
|
all = true if args.include?('-a') || args.include?('--all')
|
74
86
|
|
@@ -96,6 +108,11 @@ module GreenHat
|
|
96
108
|
|
97
109
|
# Vanilla Fast Stats
|
98
110
|
def self.default(raw, _other = nil)
|
111
|
+
unless TTY::Which.exist? 'fast-stats'
|
112
|
+
faststats_installation
|
113
|
+
return false
|
114
|
+
end
|
115
|
+
|
99
116
|
files, flags, cmd = ShellHelper::Faststats.parse(raw)
|
100
117
|
|
101
118
|
LogBot.debug('FastStats CMD', cmd) if ENV['DEBUG']
|
@@ -121,6 +138,11 @@ module GreenHat
|
|
121
138
|
# --sort=count,fail,max,median,min,p95,p99,rps,score
|
122
139
|
# ========================================================================
|
123
140
|
def self.top(raw)
|
141
|
+
unless TTY::Which.exist? 'fast-stats'
|
142
|
+
faststats_installation
|
143
|
+
return false
|
144
|
+
end
|
145
|
+
|
124
146
|
files, flags, cmd = ShellHelper::Faststats.parse(raw)
|
125
147
|
|
126
148
|
LogBot.debug('FastStats CMD', cmd) if ENV['DEBUG']
|
@@ -141,6 +163,11 @@ module GreenHat
|
|
141
163
|
# ===== [ Fast Stats - Errors ] ====================
|
142
164
|
# ========================================================================
|
143
165
|
def self.errors(raw)
|
166
|
+
unless TTY::Which.exist? 'fast-stats'
|
167
|
+
faststats_installation
|
168
|
+
return false
|
169
|
+
end
|
170
|
+
|
144
171
|
# Add Color Output
|
145
172
|
raw.push '--color-output'
|
146
173
|
files, flags, cmd = ShellHelper::Faststats.parse(raw)
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module GreenHat
|
2
|
+
# Common Helpers
|
3
|
+
module FieldHelper
|
4
|
+
def self.fields_find(files, word, flags = {})
|
5
|
+
fields = ShellHelper.find_things(files, flags).map(&:fields).flatten.uniq
|
6
|
+
|
7
|
+
if word.blank?
|
8
|
+
puts 'Possible Fields:'.pastel(:bright_blue)
|
9
|
+
puts ShellHelper.field_table(fields)
|
10
|
+
|
11
|
+
return [] # Empty Result
|
12
|
+
end
|
13
|
+
|
14
|
+
list_select(fields, word)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.list_select(list, word)
|
18
|
+
list.select! { |x| x[/^#{Regexp.escape(word)}/] }
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.filter_flags(word)
|
22
|
+
if word.blank?
|
23
|
+
puts 'Filter Options:'.pastel(:bright_blue)
|
24
|
+
puts ShellHelper.field_table(filter_opts, 6)
|
25
|
+
puts
|
26
|
+
|
27
|
+
return []
|
28
|
+
end
|
29
|
+
|
30
|
+
list_select(filter_opts, word)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.filter_opts
|
34
|
+
%w[
|
35
|
+
archive case combine end exact except exists json limit or page pluck
|
36
|
+
raw reverse round slice sort start stats table_style text time_zone
|
37
|
+
total truncate uniq
|
38
|
+
]
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.filter_auto_completes
|
42
|
+
%w[
|
43
|
+
except exists pluck slice sort stats uniq
|
44
|
+
]
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.field_auto_complete?(word)
|
48
|
+
return false if word.blank?
|
49
|
+
|
50
|
+
filter_auto_completes.include? word.split('=', 2).first
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.field_auto_complete(word, files, flags = {})
|
54
|
+
# Prevent weird dupes
|
55
|
+
return nil if word[-1] == ','
|
56
|
+
|
57
|
+
# Command Manipulation
|
58
|
+
cmd, fields = word.split('=', 2)
|
59
|
+
complete = fields.split(',')[0..-2]
|
60
|
+
auto = fields.split(',').last
|
61
|
+
|
62
|
+
# Field Finder
|
63
|
+
matches = fields_find(files, auto, flags)
|
64
|
+
|
65
|
+
if matches.count == 1
|
66
|
+
"--#{cmd}=#{(complete + matches).join(',')}"
|
67
|
+
elsif matches.count > 1
|
68
|
+
puts "#{'Field Options:'.pastel(:bright_blue)} #{matches.join(' ').pastel(:bright_green)}"
|
69
|
+
|
70
|
+
list = [Cli.common_substr(matches.map(&:to_s))]
|
71
|
+
"--#{cmd}=#{(complete + list).join(',')}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -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
|
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)
|
@@ -11,7 +11,7 @@ module GreenHat
|
|
11
11
|
|
12
12
|
puts 'Options'.pastel(:blue)
|
13
13
|
puts '--raw'.pastel(:green)
|
14
|
-
puts '
|
14
|
+
puts ' Disable formatting and page/less'
|
15
15
|
puts
|
16
16
|
|
17
17
|
puts '--page'.pastel(:green)
|
@@ -41,6 +41,10 @@ module GreenHat
|
|
41
41
|
puts ' Print only total count of matching entries'
|
42
42
|
puts
|
43
43
|
|
44
|
+
puts '--fields'.pastel(:green)
|
45
|
+
puts ' Print only Available fields for selected files'
|
46
|
+
puts
|
47
|
+
|
44
48
|
puts '--slice'.pastel(:green)
|
45
49
|
puts ' Extract specific fields from entries (slice multiple with comma)'
|
46
50
|
puts ' Ex: --slice=path or --slice=path,params'
|
@@ -57,7 +61,7 @@ module GreenHat
|
|
57
61
|
puts
|
58
62
|
|
59
63
|
puts '--stats'.pastel(:green)
|
60
|
-
puts ' Order/Count occurrances by field'
|
64
|
+
puts ' Order/Count occurrances by field. Combine with `truncate` for key names'
|
61
65
|
puts ' Ex: --stats=params --except=params,path'
|
62
66
|
puts
|
63
67
|
|
@@ -113,6 +117,21 @@ module GreenHat
|
|
113
117
|
puts ' Ex: log filter --end="2021-06-22"'
|
114
118
|
puts
|
115
119
|
|
120
|
+
puts '--time_zone'.pastel(:green)
|
121
|
+
puts ' Manipulate the `time` field into a specific timezone'
|
122
|
+
puts ' Ex: log filter --time_zone=EDT'
|
123
|
+
puts
|
124
|
+
|
125
|
+
puts '--text'.pastel(:green)
|
126
|
+
puts ' Full entry text searching (slow)'
|
127
|
+
puts ' --text="anything here"'
|
128
|
+
puts
|
129
|
+
|
130
|
+
puts '--table_style'.pastel(:green)
|
131
|
+
puts ' Renderer used for formatted output. basic, ascii, or unicode(default)'
|
132
|
+
puts ' Ex: log filter --table_style=base'
|
133
|
+
puts
|
134
|
+
|
116
135
|
puts '--truncate'.pastel(:green)
|
117
136
|
puts ' Truncate field length. On by default (4 rows). Performance issues!'
|
118
137
|
puts ' Disable with --truncate=0'.pastel(:bright_red)
|
@@ -137,7 +156,208 @@ module GreenHat
|
|
137
156
|
|
138
157
|
puts
|
139
158
|
end
|
140
|
-
|
159
|
+
|
160
|
+
def self.help_index
|
161
|
+
{
|
162
|
+
title: [
|
163
|
+
"\u2500".pastel(:cyan) * 20,
|
164
|
+
'Filter'.pastel(:yellow),
|
165
|
+
"\u2500".pastel(:cyan) * 20
|
166
|
+
],
|
167
|
+
options: [
|
168
|
+
'Options'.pastel(:blue)
|
169
|
+
],
|
170
|
+
|
171
|
+
raw: [
|
172
|
+
'--raw'.pastel(:green),
|
173
|
+
' Disable formatting and page/less'
|
174
|
+
],
|
175
|
+
|
176
|
+
page: [
|
177
|
+
'--page'.pastel(:green),
|
178
|
+
' Specifically enable or disable paging',
|
179
|
+
' E.g. --page (default to true), --page=true, --page=false'
|
180
|
+
],
|
181
|
+
|
182
|
+
round: ['--round'.pastel(:green),
|
183
|
+
' Attempt to round all integers. Default: 2.',
|
184
|
+
' E.g. --round, --round=3, --round=0'],
|
185
|
+
|
186
|
+
limit: [
|
187
|
+
|
188
|
+
'--limit'.pastel(:green),
|
189
|
+
' Limit total output lines. Disabled by default. Default without value is based on screen height',
|
190
|
+
' E.g. --limit, --limit=5'
|
191
|
+
],
|
192
|
+
|
193
|
+
json: [
|
194
|
+
'--json'.pastel(:green),
|
195
|
+
' Print output back into JSON'
|
196
|
+
],
|
197
|
+
|
198
|
+
or: [
|
199
|
+
'--or'.pastel(:green),
|
200
|
+
' Filters will use OR instead of AND (all match vs any match)'
|
201
|
+
],
|
202
|
+
|
203
|
+
total: [
|
204
|
+
'--total'.pastel(:green),
|
205
|
+
' Print only total count of matching entries'
|
206
|
+
],
|
207
|
+
|
208
|
+
fields: [
|
209
|
+
'--fields'.pastel(:green),
|
210
|
+
' Print only Available fields for selected files'
|
211
|
+
],
|
212
|
+
|
213
|
+
slice: [
|
214
|
+
'--slice'.pastel(:green),
|
215
|
+
' Extract specific fields from entries (slice multiple with comma)',
|
216
|
+
' Ex: --slice=path or --slice=path,params'
|
217
|
+
|
218
|
+
],
|
219
|
+
|
220
|
+
except: [
|
221
|
+
'--except'.pastel(:green),
|
222
|
+
' Exclude specific fields (except multiple with comma)',
|
223
|
+
' Ex: --except=params --except=params,path'
|
224
|
+
|
225
|
+
],
|
226
|
+
|
227
|
+
exists: [
|
228
|
+
'--exists'.pastel(:green),
|
229
|
+
' Ensure field exists regardless of contents',
|
230
|
+
' Ex: --exists=params --exists=params,path'
|
231
|
+
|
232
|
+
],
|
233
|
+
|
234
|
+
stats: [
|
235
|
+
'--stats'.pastel(:green),
|
236
|
+
' Order/Count occurrances by field. Combine with `truncate` for key names',
|
237
|
+
' Ex: --stats=params --except=params,path'
|
238
|
+
|
239
|
+
],
|
240
|
+
|
241
|
+
uniq: [
|
242
|
+
'--uniq'.pastel(:green),
|
243
|
+
' Show unique values only',
|
244
|
+
' Ex: --uniq=params --uniq=params,path'
|
245
|
+
|
246
|
+
],
|
247
|
+
|
248
|
+
pluck: [
|
249
|
+
'--pluck'.pastel(:green),
|
250
|
+
' Extract values from entries',
|
251
|
+
' Ex: --pluck=params --pluck=params,path'
|
252
|
+
|
253
|
+
],
|
254
|
+
|
255
|
+
archive: [
|
256
|
+
'--archive'.pastel(:green),
|
257
|
+
' Limit to specific archvie name (partial matching /inclusive). Matching SOS tar.gz name',
|
258
|
+
' Ex: --archive=dev-gitlab_20210622154626, --archive=202106,202107'
|
259
|
+
|
260
|
+
],
|
261
|
+
|
262
|
+
sort: [
|
263
|
+
'--sort'.pastel(:green),
|
264
|
+
' Sort by multiple fields',
|
265
|
+
' Ex: --sort=duration_s,db_duration_s'
|
266
|
+
|
267
|
+
],
|
268
|
+
|
269
|
+
reverse: [
|
270
|
+
'--reverse'.pastel(:green),
|
271
|
+
' Reverse all results',
|
272
|
+
' Ex: --reverse'
|
273
|
+
|
274
|
+
],
|
275
|
+
|
276
|
+
combine: [
|
277
|
+
'--combine'.pastel(:green),
|
278
|
+
' Omit archive identifier dividers. Useful with sort or time filters',
|
279
|
+
' Ex: --combine'
|
280
|
+
|
281
|
+
],
|
282
|
+
|
283
|
+
case: [
|
284
|
+
'--case'.pastel(:green),
|
285
|
+
' Exact case match. Defaults to case insensitive',
|
286
|
+
' Ex: --case; --name=Jon, --name=jane --case'
|
287
|
+
|
288
|
+
],
|
289
|
+
|
290
|
+
exact: [
|
291
|
+
'--exact'.pastel(:green),
|
292
|
+
' Exact parameter/value match. Defaults to partial match',
|
293
|
+
' Ex: --field=CommonPartial --exact'
|
294
|
+
|
295
|
+
],
|
296
|
+
|
297
|
+
start: [
|
298
|
+
'--start'.pastel(:green),
|
299
|
+
' Show events after specified time. Filtered by the `time` field',
|
300
|
+
' Use with `--end` for between selections',
|
301
|
+
' Ex: log filter --start="2021-06-22 14:44 UTC" --end="2021-06-22 14:45 UTC"'
|
302
|
+
|
303
|
+
],
|
304
|
+
|
305
|
+
end: [
|
306
|
+
'--end'.pastel(:green),
|
307
|
+
' Show events before specified time. Filtered by the `time` field',
|
308
|
+
' Use with `--start` for between selections',
|
309
|
+
' Ex: log filter --end="2021-06-22"'
|
310
|
+
],
|
311
|
+
|
312
|
+
time_zone: [
|
313
|
+
'--time_zone'.pastel(:green),
|
314
|
+
' Manipulate the `time` field into a specific timezone',
|
315
|
+
' Ex: log filter --time_zone=EDT'
|
316
|
+
|
317
|
+
],
|
318
|
+
|
319
|
+
text: [
|
320
|
+
'--text'.pastel(:green),
|
321
|
+
' Full entry text searching (slow)',
|
322
|
+
' --text="anything here"'
|
323
|
+
],
|
324
|
+
|
325
|
+
table_style: [
|
326
|
+
'--table_style'.pastel(:green),
|
327
|
+
' Renderer used for formatted output. basic, ascii, or unicode(default)',
|
328
|
+
' Ex: log filter --table_style=base'
|
329
|
+
],
|
330
|
+
|
331
|
+
truncate: [
|
332
|
+
'--truncate'.pastel(:green),
|
333
|
+
' Truncate field length. On by default (4 rows). Performance issues!',
|
334
|
+
' Disable with --truncate=0'.pastel(:bright_red),
|
335
|
+
' Ex: --truncate=200, --truncate=2048"'
|
336
|
+
],
|
337
|
+
|
338
|
+
field: [
|
339
|
+
'Field Searching'.pastel(:blue),
|
340
|
+
' --[key]=[value]',
|
341
|
+
' Search in key for value',
|
342
|
+
' Example: --path=mirror/pull'
|
343
|
+
],
|
344
|
+
|
345
|
+
ls: [
|
346
|
+
'Search specific logs'.pastel(:blue),
|
347
|
+
' Any non dash parameters will be the log list to search from',
|
348
|
+
" Ex: log filter --path=api sidekiq/current (hint: use `#{'ls'.pastel(:yellow)}` for log names"
|
349
|
+
],
|
350
|
+
|
351
|
+
examples: [
|
352
|
+
'Example Queries'.pastel(:blue),
|
353
|
+
" Also see #{'examples'.pastel(:bright_blue)} for even more examples",
|
354
|
+
' log filter --class=BuildFinishedWorker sidekiq/current --slice=time,message',
|
355
|
+
' log filter gitlab-rails/api_json.log --slice=ua --uniq=ua --ua=gitlab-runner'
|
356
|
+
]
|
357
|
+
|
358
|
+
}
|
359
|
+
end
|
360
|
+
# rubocop:enable Metrics/MethodLength,Metrics/ModuleLength
|
141
361
|
end
|
142
362
|
end
|
143
363
|
end
|
data/lib/greenhat/shell/log.rb
CHANGED
@@ -3,6 +3,41 @@ module GreenHat
|
|
3
3
|
module Shell
|
4
4
|
# Logs
|
5
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
|
+
|
6
41
|
def self.help
|
7
42
|
puts "\u2500".pastel(:cyan) * 20
|
8
43
|
puts "#{'Logs'.pastel(:yellow)} find stuff"
|
@@ -12,6 +47,7 @@ module GreenHat
|
|
12
47
|
puts ' filter'.pastel(:green)
|
13
48
|
puts " Primary way for log searching within greenhat. See #{'filter_help'.pastel(:blue)}"
|
14
49
|
puts ' Time, round, slice/except, and/or, stats, uniq, sort'
|
50
|
+
puts " #{'filter_help'.pastel(:blue)} supports filtering Ex: #{'filter_help stats'.pastel(:blue)}"
|
15
51
|
puts
|
16
52
|
|
17
53
|
puts ' show'.pastel(:green)
|
@@ -27,8 +63,16 @@ module GreenHat
|
|
27
63
|
puts "See #{'examples'.pastel(:bright_blue)} for query examples"
|
28
64
|
end
|
29
65
|
|
30
|
-
def self.filter_help
|
31
|
-
|
66
|
+
def self.filter_help(args = {})
|
67
|
+
if args.empty?
|
68
|
+
ShellHelper::Filter.help
|
69
|
+
else
|
70
|
+
list = ShellHelper::Filter.help_index.select do |k, _v|
|
71
|
+
k.to_s.include? args.first
|
72
|
+
end
|
73
|
+
|
74
|
+
puts list.values.map { |x| x.join("\n") }.join("\n\n")
|
75
|
+
end
|
32
76
|
end
|
33
77
|
|
34
78
|
def self.ls(args = [])
|
@@ -73,6 +117,12 @@ module GreenHat
|
|
73
117
|
return true
|
74
118
|
end
|
75
119
|
|
120
|
+
# Skip and Print Total if set
|
121
|
+
if flags[:fields]
|
122
|
+
ShellHelper.fields_print(results)
|
123
|
+
return true
|
124
|
+
end
|
125
|
+
|
76
126
|
# Check Search Results
|
77
127
|
if results.instance_of?(Hash) && results.values.flatten.empty?
|
78
128
|
puts 'No results'.pastel(:red)
|