greenhat 0.7.3 → 0.8.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/README.md +4 -0
- data/lib/greenhat/archive.rb +22 -7
- data/lib/greenhat/reports/reports/errors.rb +2 -1
- data/lib/greenhat/reports/reports/full.rb +5 -0
- data/lib/greenhat/reports/shell_helper.rb +12 -1
- data/lib/greenhat/shell/field_helper.rb +1 -1
- data/lib/greenhat/shell/log.rb +1 -1
- data/lib/greenhat/shell/query.rb +1 -1
- data/lib/greenhat/shell/shell_helper.rb +19 -38
- data/lib/greenhat/thing/file_types.rb +6 -0
- data/lib/greenhat/thing/formatters/json.rb +3 -0
- data/lib/greenhat/version.rb +1 -1
- metadata +19 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e7caec2b171d012ac284044e1064b665f42aeddf026a56267d4e8fe6ae44c394
|
4
|
+
data.tar.gz: 24ec9744a8d27b56a6576d1f49edf22d1365349f86f6470f5f3c53cfac53bafc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 978d6fc74f1adb0fbab249a41d26efc01d0e0b9c1c1cccf4e5ef143c0405db02ad285c3ed20c6bcfd36432a1d3ecfc31b93325990a333123ea4ec271be4f8e6e
|
7
|
+
data.tar.gz: 72e3417a4011b35c0c3a4a9552d0ccf4321334ca901e74b4c7ae33b21d649644739bb08845cea1a9c5621e96aa40e641ff8a566f3d18d735fd4461d083651927
|
data/README.md
CHANGED
@@ -12,6 +12,8 @@ Experimental SOS and Log Parser for GitLab
|
|
12
12
|
|
13
13
|
`apt-get install libarchive-tools`
|
14
14
|
|
15
|
+
Ruby 3.0 or later, including the headers (such as package `ruby-dev`)
|
16
|
+
|
15
17
|
## Installation
|
16
18
|
|
17
19
|
```
|
@@ -27,6 +29,8 @@ greenhat production_json.log
|
|
27
29
|
>> help # the program is self-documented through the builtin help command
|
28
30
|
```
|
29
31
|
|
32
|
+
[Watch an introductory tutorial](https://www.youtube.com/watch?v=xyVQiKFgeP4) (recorded March 5, 2024, with Green Hat v0.7.3)
|
33
|
+
|
30
34
|
## Testing
|
31
35
|
|
32
36
|
```
|
data/lib/greenhat/archive.rb
CHANGED
@@ -50,23 +50,29 @@ module GreenHat
|
|
50
50
|
|
51
51
|
# Handle Different Types of Archives
|
52
52
|
def self.unpack(archive_path, path)
|
53
|
+
decompressed_successfully = false
|
54
|
+
|
53
55
|
case File.extname archive_path
|
54
|
-
when '.tgz'
|
55
|
-
base_path = archive_path.gsub(File.basename(archive_path), '')
|
56
|
-
`bsdtar -xzf "#{archive_path}" -C #{base_path}`
|
57
|
-
FileUtils.rm(archive_path)
|
58
|
-
when '.tar'
|
56
|
+
when '.tgz', '.tar'
|
59
57
|
base_path = archive_path.gsub(File.basename(archive_path), '')
|
60
58
|
`bsdtar -xf "#{archive_path}" -C #{base_path}`
|
61
|
-
|
59
|
+
|
60
|
+
decompressed_successfully = $CHILD_STATUS.success?
|
61
|
+
FileUtils.rm(archive_path) if decompressed_successfully
|
62
62
|
when '.gz'
|
63
63
|
`gzip -d "#{archive_path}"`
|
64
|
+
|
65
|
+
decompressed_successfully = $CHILD_STATUS.success?
|
64
66
|
when '.zip'
|
65
67
|
base_path = archive_path.gsub(File.basename(archive_path), '')
|
66
68
|
`unzip -o -d "#{base_path}" #{archive_path}`
|
67
|
-
|
69
|
+
|
70
|
+
decompressed_successfully = $CHILD_STATUS.success?
|
71
|
+
FileUtils.rm(archive_path) if decompressed_successfully
|
68
72
|
when '.bz2'
|
69
73
|
`bzip2 -d #{archive_path}`
|
74
|
+
|
75
|
+
decompressed_successfully = $CHILD_STATUS.success?
|
70
76
|
when '.s'
|
71
77
|
# Find Original Directory, Split Path, Rename to .gz
|
72
78
|
base_path = archive_path.gsub(File.basename(archive_path), '')
|
@@ -74,6 +80,15 @@ module GreenHat
|
|
74
80
|
else
|
75
81
|
FileUtils.cp(archive_path, "#{path}/#{archive_path}")
|
76
82
|
end
|
83
|
+
|
84
|
+
# if the archive is corrupt and doesn't uncompress properly, greenhat will keep looping on it endlessly,
|
85
|
+
# trying to decompress it. let's rename it on failure so it stops trying, but the SE can still try and
|
86
|
+
# extract it themselves.
|
87
|
+
return if decompressed_successfully
|
88
|
+
|
89
|
+
puts "#{'Decompress failed'.pastel(:red)}: #{archive_path.pastel(:green)}"
|
90
|
+
puts 'Renaming file so we can continue.'.pastel(:yellow)
|
91
|
+
FileUtils.mv(archive_path, "#{archive_path}.broken")
|
77
92
|
end
|
78
93
|
|
79
94
|
def self.archive?(file_name)
|
@@ -27,7 +27,8 @@ entries = [
|
|
27
27
|
{ header: 'Gitaly', base: 'gitaly/current --level=error --truncate=99', stats: 'error' },
|
28
28
|
{ header: 'Praefect', base: 'praefect/current --level=error --truncate=99', stats: 'error' },
|
29
29
|
{ header: 'Pages', base: 'gitlab-pages/current --level=error', stats: 'error' },
|
30
|
-
{ header: 'Geo', base: 'gitlab-rails/geo.log --severity=error', stats: 'message' }
|
30
|
+
{ header: 'Geo', base: 'gitlab-rails/geo.log --severity=error', stats: 'message' },
|
31
|
+
{ header: 'Elasticsearch', base: 'gitlab-rails/elasticsearch.log --severity=error', stats: 'message' }
|
31
32
|
]
|
32
33
|
|
33
34
|
# Filter Logic
|
@@ -164,3 +164,8 @@ query_if_exists 'gitlab-rails/geo.log --severity=error' do |data|
|
|
164
164
|
color = data.count.zero? ? :green : :red
|
165
165
|
indent("#{ljust('Geo:', 14, :magenta)} #{data.count.to_s.pastel(color)}", 4)
|
166
166
|
end
|
167
|
+
|
168
|
+
query_if_exists 'gitlab-rails/elasticsearch.log --severity=error' do |data|
|
169
|
+
color = data.count.zero? ? :green : :red
|
170
|
+
indent("#{ljust('Elasticsearch:', 14, :magenta)} #{data.count.to_s.pastel(color)}", 4)
|
171
|
+
end
|
@@ -5,7 +5,18 @@ module GreenHat
|
|
5
5
|
# Make Running more consistent
|
6
6
|
def self.run(file:, args:, flags:, raw_args:)
|
7
7
|
report = GreenHat::Reports::Builder.new(file:, args:, flags:, raw_args:)
|
8
|
-
|
8
|
+
|
9
|
+
# Fuzzy Match Archive Names
|
10
|
+
archives = Archive.all
|
11
|
+
if flags[:archive] && !flags[:archive].empty?
|
12
|
+
archives.select! do |a|
|
13
|
+
flags[:archive].any? do |x|
|
14
|
+
a.name.include? x.to_s
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
output = archives.map do |archive|
|
9
20
|
runner = GreenHat::Reports::Runner.new(
|
10
21
|
archive:,
|
11
22
|
store: report.store.clone,
|
data/lib/greenhat/shell/log.rb
CHANGED
data/lib/greenhat/shell/query.rb
CHANGED
@@ -191,7 +191,7 @@ module GreenHat
|
|
191
191
|
results = filter_except(results, flags[:except]) if flags.key?(:except)
|
192
192
|
|
193
193
|
# Remove Blank from either slice or except
|
194
|
-
results.reject!(&:
|
194
|
+
results.reject!(&:blank?)
|
195
195
|
|
196
196
|
# Sort / Reverse by default
|
197
197
|
if flags.key?(:sort)
|
@@ -244,50 +244,31 @@ module GreenHat
|
|
244
244
|
[output]
|
245
245
|
end
|
246
246
|
|
247
|
-
#
|
248
|
-
|
249
|
-
|
250
|
-
# results.flat_map do |k, values|
|
251
|
-
# [k, total_count_array(values, flags)]
|
252
|
-
# end
|
253
|
-
# end
|
247
|
+
# Table Printer Helper
|
248
|
+
def self.fields_print(files)
|
249
|
+
fields = ShellHelper.find_things(files).map(&:fields).flatten.uniq
|
254
250
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
# return results.count if flags[:total] == 'simple'
|
251
|
+
# truncate = (TTY::Screen.width - columns) / columns
|
252
|
+
# fields.map! { |f| f[0..truncate] }
|
253
|
+
puts ShellHelper.field_table(fields)
|
259
254
|
|
260
|
-
|
261
|
-
|
262
|
-
# output[:duration] = Query.calculate_duration(results)
|
255
|
+
# ShellHelper.fields_print(files)
|
256
|
+
end
|
263
257
|
|
264
|
-
#
|
265
|
-
|
266
|
-
|
267
|
-
# output[:start] = list.first
|
268
|
-
# output[:end] = list.last
|
269
|
-
# end
|
258
|
+
# 5 Columns cause issues with resizing
|
259
|
+
def self.field_table(list, columns: 4)
|
260
|
+
return nil if list.empty?
|
270
261
|
|
271
|
-
|
272
|
-
|
262
|
+
# Split list into groups based on columns
|
263
|
+
groups = list.each_slice((list.size / columns.to_f).ceil).to_a
|
273
264
|
|
274
|
-
|
275
|
-
|
265
|
+
# Max Width for Table
|
266
|
+
truncate = (TTY::Screen.width - groups.count) / groups.count
|
276
267
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
puts k
|
281
|
-
puts field_table(v.map(&:keys).flatten.uniq.sort)
|
282
|
-
puts
|
268
|
+
# Process Truncation
|
269
|
+
groups.each do |group|
|
270
|
+
group.map! { |f| f[0..truncate]&.to_sym }
|
283
271
|
end
|
284
|
-
end
|
285
|
-
|
286
|
-
def self.field_table(list, columns = 4)
|
287
|
-
return nil if list.empty?
|
288
|
-
|
289
|
-
# Keep Alphabetical Sort
|
290
|
-
groups = list.each_slice((list.size / columns.to_f).round).to_a
|
291
272
|
|
292
273
|
table = TTY::Table.new do |t|
|
293
274
|
loop do
|
@@ -297,7 +278,7 @@ module GreenHat
|
|
297
278
|
end
|
298
279
|
end
|
299
280
|
|
300
|
-
table.render(:unicode, padding: [0, 1, 0, 1])
|
281
|
+
table.render(:unicode, padding: [0, 1, 0, 1], resize: false)
|
301
282
|
end
|
302
283
|
|
303
284
|
# Unified Files Interface
|
data/lib/greenhat/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: greenhat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Davin Walker
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-03-04 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: actionview
|
@@ -66,20 +65,34 @@ dependencies:
|
|
66
65
|
- - "~>"
|
67
66
|
- !ruby/object:Gem::Version
|
68
67
|
version: '4.1'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: concurrent-ruby
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - '='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 1.3.4
|
75
|
+
type: :runtime
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - '='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 1.3.4
|
69
82
|
- !ruby/object:Gem::Dependency
|
70
83
|
name: did_you_mean
|
71
84
|
requirement: !ruby/object:Gem::Requirement
|
72
85
|
requirements:
|
73
86
|
- - "~>"
|
74
87
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
88
|
+
version: '2.0'
|
76
89
|
type: :runtime
|
77
90
|
prerelease: false
|
78
91
|
version_requirements: !ruby/object:Gem::Requirement
|
79
92
|
requirements:
|
80
93
|
- - "~>"
|
81
94
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
95
|
+
version: '2.0'
|
83
96
|
- !ruby/object:Gem::Dependency
|
84
97
|
name: dotenv
|
85
98
|
requirement: !ruby/object:Gem::Requirement
|
@@ -531,7 +544,6 @@ licenses:
|
|
531
544
|
- MIT
|
532
545
|
metadata:
|
533
546
|
rubygems_mfa_required: 'true'
|
534
|
-
post_install_message:
|
535
547
|
rdoc_options: []
|
536
548
|
require_paths:
|
537
549
|
- lib
|
@@ -546,8 +558,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
546
558
|
- !ruby/object:Gem::Version
|
547
559
|
version: '0'
|
548
560
|
requirements: []
|
549
|
-
rubygems_version: 3.
|
550
|
-
signing_key:
|
561
|
+
rubygems_version: 3.6.2
|
551
562
|
specification_version: 4
|
552
563
|
summary: GitLab SOS Tool
|
553
564
|
test_files: []
|