greenhat 0.6.1 → 0.6.4
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 +42 -6
- data/lib/greenhat/accessors/gitlab.rb +1 -1
- data/lib/greenhat/cli.rb +0 -2
- data/lib/greenhat/reports/builder.rb +7 -2
- data/lib/greenhat/reports/helpers.rb +4 -0
- data/lib/greenhat/reports/internal_methods.rb +23 -0
- data/lib/greenhat/reports/reports/errors.rb +17 -3
- data/lib/greenhat/reports/reports/full.rb +20 -7
- data/lib/greenhat/reports/reports/full_markdown.rb +140 -0
- data/lib/greenhat/reports/runner.rb +3 -2
- data/lib/greenhat/reports/shared.rb +1 -0
- data/lib/greenhat/reports/shell_helper.rb +15 -3
- data/lib/greenhat/settings.rb +2 -2
- data/lib/greenhat/shell/gitlab.rb +1 -2
- data/lib/greenhat/shell/log.rb +10 -2
- data/lib/greenhat/shell/platform.rb +10 -3
- data/lib/greenhat/shell/query.rb +1 -1
- data/lib/greenhat/shell/reports.rb +16 -1
- data/lib/greenhat/shell/shell_helper.rb +137 -121
- data/lib/greenhat/shell.rb +12 -0
- data/lib/greenhat/thing/file_types.rb +79 -1
- data/lib/greenhat/thing/formatters/exporters.rb +48 -0
- data/lib/greenhat/thing/formatters/gitlab_ctl_tail.rb +1 -1
- data/lib/greenhat/thing/formatters/gitlab_status.rb +1 -1
- data/lib/greenhat/thing/formatters/identify_db.rb +32 -0
- data/lib/greenhat/thing/formatters/kube_webservice.rb +1 -1
- data/lib/greenhat/version.rb +1 -1
- data/lib/greenhat.rb +2 -2
- metadata +39 -23
- data/lib/greenhat/shell/report.rb +0 -415
@@ -1,6 +1,5 @@
|
|
1
1
|
module GreenHat
|
2
2
|
# Common Helpers
|
3
|
-
# rubocop:disable Metrics/ModuleLength
|
4
3
|
module ShellHelper
|
5
4
|
# Use File Process for Output
|
6
5
|
def self.file_output(files, flags = {})
|
@@ -95,109 +94,109 @@ module GreenHat
|
|
95
94
|
end
|
96
95
|
|
97
96
|
# Entry Shower / Top Level
|
98
|
-
def self.entry_show(flags, entry, key = nil)
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
end
|
97
|
+
# def self.entry_show(flags, entry, key = nil)
|
98
|
+
# LogBot.debug('Entry Show', entry.class) if ENV['DEBUG']
|
99
|
+
# case entry
|
100
|
+
# when Hash then render_table(entry, flags)
|
101
|
+
# when Float, Integer
|
102
|
+
# format_table_entry(flags, entry, key)
|
103
|
+
# # Ignore Special Formatting for Strings / Usually already formatted
|
104
|
+
# when String
|
105
|
+
# entry
|
106
|
+
# when Array
|
107
|
+
# render_array_table(entry, flags)
|
108
|
+
# else
|
109
|
+
# LogBot.warn('Shell Show', "Unknown #{entry.class}")
|
110
|
+
# nil
|
111
|
+
# end
|
112
|
+
# end
|
114
113
|
|
115
114
|
# Format Table Entries
|
116
|
-
def self.format_table_entry(flags, entry, key = nil)
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
rescue StandardError => e
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
end
|
148
|
-
|
149
|
-
def self.render_array_table(entry, flags)
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
end
|
164
|
-
|
165
|
-
# Print the Table in a Nice way
|
166
|
-
def self.render_table(entry, flags)
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
rescue StandardError => e
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
end
|
195
|
-
|
196
|
-
def self.render_table_entry(val, col_index, flags)
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
end
|
115
|
+
# def self.format_table_entry(flags, entry, key = nil)
|
116
|
+
# formatted_entry = case entry
|
117
|
+
# # Rounding
|
118
|
+
# when Float, Integer || entry.numeric?
|
119
|
+
# flags.key?(:round) ? entry.to_f.round(flags.round).ai : entry.ai
|
120
|
+
|
121
|
+
# # General Inspecting
|
122
|
+
# when Hash then entry.ai(ruby19_syntax: true)
|
123
|
+
|
124
|
+
# # Arrays often contain Hashes. Dangerous Recursive?
|
125
|
+
# when Array
|
126
|
+
# entry.map { |x| format_table_entry(flags, x) }.join("\n")
|
127
|
+
# when Time
|
128
|
+
# entry.to_s.pastel(:bright_white)
|
129
|
+
|
130
|
+
# # Default String Formatting
|
131
|
+
# else
|
132
|
+
# StringColor.do(key, entry)
|
133
|
+
# end
|
134
|
+
|
135
|
+
# # Stats truncation handled separately
|
136
|
+
# if flags[:truncate] && !flags[:stats]
|
137
|
+
# entry_truncate(formatted_entry, flags[:truncate])
|
138
|
+
# else
|
139
|
+
# formatted_entry
|
140
|
+
# end
|
141
|
+
# rescue StandardError => e
|
142
|
+
# if ENV['DEBUG']
|
143
|
+
# LogBot.warn('Table Format Entry', message: e.message)
|
144
|
+
# ap e.backtrace
|
145
|
+
# end
|
146
|
+
# end
|
147
|
+
|
148
|
+
# def self.render_array_table(entry, flags)
|
149
|
+
# table_style = flags[:table_style]&.to_sym || :unicode
|
150
|
+
# header, rows = entry
|
151
|
+
# table = TTY::Table.new(header: header, rows: rows)
|
152
|
+
|
153
|
+
# LogBot.debug('Rendering Entries') if ENV['DEBUG']
|
154
|
+
# output = table.render(table_style, padding: [0, 1, 0, 1], multiline: true) do |renderer|
|
155
|
+
# renderer.border.style = :cyan
|
156
|
+
# end
|
157
|
+
|
158
|
+
# # Line breaks for basic tables
|
159
|
+
# output += "\n" if flags[:table_style] == 'basic'
|
160
|
+
|
161
|
+
# output
|
162
|
+
# end
|
163
|
+
|
164
|
+
# # Print the Table in a Nice way
|
165
|
+
# def self.render_table(entry, flags)
|
166
|
+
# entry = entry.to_h { |k, v| [k, format_table_entry(flags, v, k)] }
|
167
|
+
# # Pre-format Entry
|
168
|
+
|
169
|
+
# table_style = flags[:table_style]&.to_sym || :unicode
|
170
|
+
|
171
|
+
# table = TTY::Table.new(header: entry.keys, rows: [entry], orientation: :vertical)
|
172
|
+
|
173
|
+
# LogBot.debug('Rendering Entries') if ENV['DEBUG']
|
174
|
+
# output = table.render(table_style, padding: [0, 1, 0, 1], multiline: true) do |renderer|
|
175
|
+
# renderer.border.style = :cyan
|
176
|
+
# end
|
177
|
+
|
178
|
+
# # Line breaks for basic tables
|
179
|
+
# output += "\n" if flags[:table_style] == 'basic'
|
180
|
+
|
181
|
+
# output
|
182
|
+
# rescue StandardError => e
|
183
|
+
# if ENV['DEBUG']
|
184
|
+
# LogBot.warn('Table', message: e.message)
|
185
|
+
# ap e.backtrace
|
186
|
+
# end
|
187
|
+
|
188
|
+
# [
|
189
|
+
# entry.ai,
|
190
|
+
# ('_' * (TTY::Screen.width / 3)).pastel(:cyan),
|
191
|
+
# "\n"
|
192
|
+
# ].join("\n")
|
193
|
+
# end
|
194
|
+
|
195
|
+
# def self.render_table_entry(val, col_index, flags)
|
196
|
+
# return val.to_s unless col_index == 1
|
197
|
+
|
198
|
+
# format_table_entry(flags, val)
|
199
|
+
# end
|
201
200
|
|
202
201
|
# Internal Query Helper
|
203
202
|
# query = 'gitlab-rails/application_json.log --message!="Cannot obtain an exclusive lease" --severity=error'
|
@@ -225,22 +224,6 @@ module GreenHat
|
|
225
224
|
|
226
225
|
# Total Count Helper
|
227
226
|
def self.total_count(results, flags)
|
228
|
-
# Support Combine Helper
|
229
|
-
# TODO I Believe this should be removed now
|
230
|
-
# total_count_hash(results, flags) if results.instance_of? Hash
|
231
|
-
|
232
|
-
total_count_array(results, flags) if results.instance_of? Array
|
233
|
-
end
|
234
|
-
|
235
|
-
# Hash Iteration
|
236
|
-
def self.total_count_hash(results, flags)
|
237
|
-
results.flat_map do |k, values|
|
238
|
-
[k, total_count_array(values, flags)]
|
239
|
-
end
|
240
|
-
end
|
241
|
-
|
242
|
-
# List Calculation
|
243
|
-
def self.total_count_array(results, flags)
|
244
227
|
# Option to only return the count
|
245
228
|
return results.count if flags[:total] == 'simple'
|
246
229
|
|
@@ -258,9 +241,39 @@ module GreenHat
|
|
258
241
|
# Hide empty results
|
259
242
|
output.reject! { |_k, v| v.blank? }
|
260
243
|
|
261
|
-
|
244
|
+
[output]
|
262
245
|
end
|
263
246
|
|
247
|
+
# TODO: Clean up -- Verify these aren't needed
|
248
|
+
# Hash Iteration
|
249
|
+
# def self.total_count_hash(results, flags)
|
250
|
+
# results.flat_map do |k, values|
|
251
|
+
# [k, total_count_array(values, flags)]
|
252
|
+
# end
|
253
|
+
# end
|
254
|
+
|
255
|
+
# List Calculation
|
256
|
+
# def self.total_count_array(results, flags)
|
257
|
+
# # Option to only return the count
|
258
|
+
# return results.count if flags[:total] == 'simple'
|
259
|
+
|
260
|
+
# output = {}
|
261
|
+
# output[:total] = results.count
|
262
|
+
# output[:duration] = Query.calculate_duration(results)
|
263
|
+
|
264
|
+
# # Sort / Get first and Last
|
265
|
+
# list = results.select(&:time).map(&:time)
|
266
|
+
# unless list.blank?
|
267
|
+
# output[:start] = list.first
|
268
|
+
# output[:end] = list.last
|
269
|
+
# end
|
270
|
+
|
271
|
+
# # Hide empty results
|
272
|
+
# output.reject! { |_k, v| v.blank? }
|
273
|
+
|
274
|
+
# render_table(output, flags)
|
275
|
+
# end
|
276
|
+
|
264
277
|
# Table Printer Helper
|
265
278
|
def self.fields_print(results)
|
266
279
|
results.each do |k, v|
|
@@ -318,6 +331,11 @@ module GreenHat
|
|
318
331
|
@thing_list
|
319
332
|
end
|
320
333
|
|
334
|
+
# Shortcut to see if any things exist
|
335
|
+
def self.any_things?(file_list, flags = {}, base_list = nil)
|
336
|
+
!find_things(file_list, flags, base_list).empty?
|
337
|
+
end
|
338
|
+
|
321
339
|
# Shortcut find things
|
322
340
|
def self.find_things(file_list, flags = {}, base_list = nil)
|
323
341
|
base_list ||= Thing.all
|
@@ -373,6 +391,4 @@ module GreenHat
|
|
373
391
|
puts
|
374
392
|
end
|
375
393
|
end
|
376
|
-
|
377
|
-
# rubocop:enable Metrics/ModuleLength
|
378
394
|
end
|
data/lib/greenhat/shell.rb
CHANGED
@@ -89,6 +89,18 @@ module GreenHat
|
|
89
89
|
Shell::Cat.default ['uptime']
|
90
90
|
end
|
91
91
|
|
92
|
+
def self.ip_address
|
93
|
+
Shell::Cat.default ['ip_address']
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.ifconfig
|
97
|
+
Shell::Cat.default ['ifconfig']
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.gitlab_rb
|
101
|
+
Shell::Cat.default ['gitlab/gitlab.rb', '--page']
|
102
|
+
end
|
103
|
+
|
92
104
|
def self.hostname
|
93
105
|
Shell::Cat.default ['hostname']
|
94
106
|
end
|
@@ -131,6 +131,13 @@ module GreenHat
|
|
131
131
|
%r{consul/current}
|
132
132
|
]
|
133
133
|
},
|
134
|
+
'consul/identify_primary_db_node.log' => {
|
135
|
+
format: :identify_db,
|
136
|
+
log: true,
|
137
|
+
pattern: [
|
138
|
+
%r{consul/identify_primary_db_node.log}
|
139
|
+
]
|
140
|
+
},
|
134
141
|
'gitlab-kas/current' => {
|
135
142
|
format: :time_space,
|
136
143
|
log: true,
|
@@ -223,12 +230,19 @@ module GreenHat
|
|
223
230
|
]
|
224
231
|
},
|
225
232
|
'gitlab-exporter/current' => {
|
226
|
-
format: :
|
233
|
+
format: :exporters,
|
227
234
|
log: true,
|
228
235
|
pattern: [
|
229
236
|
%r{gitlab-exporter/current}
|
230
237
|
]
|
231
238
|
},
|
239
|
+
'gitlab-rails/web_exporter' => {
|
240
|
+
format: :exporters,
|
241
|
+
log: true,
|
242
|
+
pattern: [
|
243
|
+
%r{gitlab-rails/web_exporter}
|
244
|
+
]
|
245
|
+
},
|
232
246
|
'gitlab-monitor/current' => {
|
233
247
|
format: :time_space,
|
234
248
|
log: true,
|
@@ -355,6 +369,18 @@ module GreenHat
|
|
355
369
|
/hostname/
|
356
370
|
]
|
357
371
|
},
|
372
|
+
'ifconfig' => {
|
373
|
+
format: :raw,
|
374
|
+
pattern: [
|
375
|
+
/ifconfig/
|
376
|
+
]
|
377
|
+
},
|
378
|
+
'ip_address' => {
|
379
|
+
format: :raw,
|
380
|
+
pattern: [
|
381
|
+
/ip_address/
|
382
|
+
]
|
383
|
+
},
|
358
384
|
'lscpu' => {
|
359
385
|
format: :colon_split_strip,
|
360
386
|
pattern: [
|
@@ -507,6 +533,27 @@ module GreenHat
|
|
507
533
|
/^ps/
|
508
534
|
]
|
509
535
|
},
|
536
|
+
'pressure_cpu.txt' => {
|
537
|
+
format: :raw,
|
538
|
+
log: false,
|
539
|
+
pattern: [
|
540
|
+
/pressure_cpu.txt/
|
541
|
+
]
|
542
|
+
},
|
543
|
+
'pressure_io.txt' => {
|
544
|
+
format: :raw,
|
545
|
+
log: false,
|
546
|
+
pattern: [
|
547
|
+
/pressure_io.txt/
|
548
|
+
]
|
549
|
+
},
|
550
|
+
'pressure_mem.txt' => {
|
551
|
+
format: :raw,
|
552
|
+
log: false,
|
553
|
+
pattern: [
|
554
|
+
/pressure_mem.txt/
|
555
|
+
]
|
556
|
+
},
|
510
557
|
'puma/puma_stderr.log' => {
|
511
558
|
format: :raw,
|
512
559
|
log: false,
|
@@ -515,6 +562,7 @@ module GreenHat
|
|
515
562
|
%r{webservice.log/puma.stderr.log}
|
516
563
|
]
|
517
564
|
},
|
565
|
+
|
518
566
|
'puma/puma_stdout.log' => {
|
519
567
|
format: :json,
|
520
568
|
log: true,
|
@@ -818,18 +866,48 @@ module GreenHat
|
|
818
866
|
/vmstat/
|
819
867
|
]
|
820
868
|
},
|
869
|
+
'gitlab-kas/config' => {
|
870
|
+
format: :raw,
|
871
|
+
pattern: [
|
872
|
+
%r{gitlab-kas/config}
|
873
|
+
]
|
874
|
+
},
|
875
|
+
'mailroom/config' => {
|
876
|
+
format: :raw,
|
877
|
+
pattern: [
|
878
|
+
%r{mailroom/config}
|
879
|
+
]
|
880
|
+
},
|
821
881
|
'iotop' => {
|
822
882
|
format: :raw,
|
823
883
|
pattern: [
|
824
884
|
/iotop/
|
825
885
|
]
|
826
886
|
},
|
887
|
+
'top_res' => {
|
888
|
+
format: :raw,
|
889
|
+
pattern: [
|
890
|
+
/top_res/
|
891
|
+
]
|
892
|
+
},
|
893
|
+
'top_cpu' => {
|
894
|
+
format: :raw,
|
895
|
+
pattern: [
|
896
|
+
/top_cpu/
|
897
|
+
]
|
898
|
+
},
|
827
899
|
'ntpq' => {
|
828
900
|
format: :raw,
|
829
901
|
pattern: [
|
830
902
|
/ntpq/
|
831
903
|
]
|
832
904
|
},
|
905
|
+
'rpm_verify' => {
|
906
|
+
format: :raw,
|
907
|
+
pattern: [
|
908
|
+
/rpm_verify/
|
909
|
+
]
|
910
|
+
},
|
833
911
|
'gitlab-rails/application.log' => {
|
834
912
|
format: :raw,
|
835
913
|
pattern: [
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Top
|
2
|
+
module GreenHat
|
3
|
+
# Log
|
4
|
+
module Formatters
|
5
|
+
# ==========================================================================
|
6
|
+
# General Exporter Parser
|
7
|
+
# https://gitlab.com/gitlab-com/support/toolbox/greenhat/-/issues/30
|
8
|
+
# [YYYY-MM-DDTHH:MM:SS.sss-HHMM] …ip… - - [DD/Mon/YYYY:HH:MM:SS ZON]
|
9
|
+
# "GET /metrics HTTP/1.1" 200 12345 "-" "Prometheus/2.25.0"
|
10
|
+
# ==========================================================================
|
11
|
+
def format_exporters
|
12
|
+
self.result = raw.map do |row|
|
13
|
+
result = {}
|
14
|
+
time, output = row.split(' ', 2)
|
15
|
+
result[:time] = Time.parse(time)
|
16
|
+
|
17
|
+
# Weird Edge Cases for when IP is not included
|
18
|
+
msg = ''
|
19
|
+
if output.include? '- - '
|
20
|
+
ip, msg = output.split('- -', 2)
|
21
|
+
result[:ip] = ip unless ip.empty?
|
22
|
+
else
|
23
|
+
msg = output
|
24
|
+
end
|
25
|
+
|
26
|
+
# Styrip Extra Time / Get Call Details
|
27
|
+
if msg&.include? ']'
|
28
|
+
_time, request = msg.split('] ', 2)
|
29
|
+
result[:msg] = request # Pass full request
|
30
|
+
|
31
|
+
# Breakout
|
32
|
+
method, path, protocol, status, bytes = request.gsub('"', '').split(' ', 5)
|
33
|
+
|
34
|
+
result.merge!(method: method, path: path, protocol: protocol, status: status, bytes: bytes)
|
35
|
+
|
36
|
+
else
|
37
|
+
result[:msg] = msg
|
38
|
+
end
|
39
|
+
|
40
|
+
result
|
41
|
+
rescue StandardError => e
|
42
|
+
# TODO: Background logger
|
43
|
+
LogBot.warn('Exporters', "Unable to Parse, #{row}:#{e.message}")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
# ==========================================================================
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Top
|
2
|
+
module GreenHat
|
3
|
+
# Log
|
4
|
+
module Formatters
|
5
|
+
# consul/identify_primary_db_node.log
|
6
|
+
# https://gitlab.com/gitlab-com/support/toolbox/greenhat/-/issues/33
|
7
|
+
# I, [YYYY-MM-DDThh:mm:ss.ssssss #12345] INFO -- : Found master: sub.domain.tld
|
8
|
+
def format_identify_db
|
9
|
+
self.result = raw.map do |row|
|
10
|
+
next if row.empty? || row == "\n"
|
11
|
+
|
12
|
+
level_abrv, row = row.split(', ', 2)
|
13
|
+
|
14
|
+
time, output = row.split('] ', 2)
|
15
|
+
time = Time.parse time.split('[', 2).last.strip
|
16
|
+
|
17
|
+
level, _a, _b, msg = output.split(' ', 4)
|
18
|
+
{
|
19
|
+
time: time,
|
20
|
+
i: level_abrv,
|
21
|
+
level: level,
|
22
|
+
message: msg
|
23
|
+
}
|
24
|
+
rescue StandardError => e
|
25
|
+
# TODO: Background logger
|
26
|
+
LogBot.warn('identify_db', "Unable to Parse, #{row}:#{e.message}")
|
27
|
+
end
|
28
|
+
|
29
|
+
result.compact!
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/greenhat/version.rb
CHANGED
data/lib/greenhat.rb
CHANGED
@@ -22,7 +22,7 @@ require 'tty-reader'
|
|
22
22
|
require 'tty-spinner'
|
23
23
|
require 'tty-table'
|
24
24
|
require 'tty-which'
|
25
|
-
require 'warning'
|
25
|
+
# require 'warning' # Ruby 3
|
26
26
|
require 'ruby_native_statistics'
|
27
27
|
require 'gitlab_chronic_duration'
|
28
28
|
|
@@ -79,4 +79,4 @@ require 'greenhat/tty/reader'
|
|
79
79
|
require 'greenhat/tty/custom_line'
|
80
80
|
require 'greenhat/tty/columns'
|
81
81
|
|
82
|
-
Warning.ignore(/The table size exceeds the currently set width/)
|
82
|
+
# Warning.ignore(/The table size exceeds the currently set width/) # Ruby 3
|