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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bfa1c48eaba3ee835bbb027b9e7314fa8e64d17629d481c7c3aa73d7e00b83a4
4
- data.tar.gz: '0175799c24f2d5c43fda1d50e103446a73ee12600dca511d4d52327128a66767'
3
+ metadata.gz: e7caec2b171d012ac284044e1064b665f42aeddf026a56267d4e8fe6ae44c394
4
+ data.tar.gz: 24ec9744a8d27b56a6576d1f49edf22d1365349f86f6470f5f3c53cfac53bafc
5
5
  SHA512:
6
- metadata.gz: 95e6819b6e8f333c8537752d863ebc03fb3197e90be7ce92488bd68018c534be2d0db7593056cfa7c716ae43dae1ccf16d9f89ec84c72d4ef3b39fdb65734710
7
- data.tar.gz: db52e83d2c456cd5d217310223ad62ea380e4e27f72ccc2819fa63b4e7734460b121153aaaa318743f3700f9e63eafbe71cda38caac94361cc659b88618edd20
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
  ```
@@ -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
- FileUtils.rm(archive_path)
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
- FileUtils.rm(archive_path)
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
- output = Archive.all.map do |archive|
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,
@@ -21,7 +21,7 @@ module GreenHat
21
21
  def self.filter_flags(word)
22
22
  if word.blank?
23
23
  puts 'Filter Options:'.pastel(:bright_blue)
24
- puts ShellHelper.field_table(filter_opts, 6)
24
+ puts ShellHelper.field_table(filter_opts)
25
25
  puts
26
26
 
27
27
  return []
@@ -218,7 +218,7 @@ module GreenHat
218
218
 
219
219
  # Skip and Print Total if set
220
220
  if flags[:fields]
221
- ShellHelper.fields_print(results)
221
+ ShellHelper.fields_print(files)
222
222
  return true
223
223
  end
224
224
 
@@ -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!(&:empty?)
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
- # 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
247
+ # Table Printer Helper
248
+ def self.fields_print(files)
249
+ fields = ShellHelper.find_things(files).map(&:fields).flatten.uniq
254
250
 
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'
251
+ # truncate = (TTY::Screen.width - columns) / columns
252
+ # fields.map! { |f| f[0..truncate] }
253
+ puts ShellHelper.field_table(fields)
259
254
 
260
- # output = {}
261
- # output[:total] = results.count
262
- # output[:duration] = Query.calculate_duration(results)
255
+ # ShellHelper.fields_print(files)
256
+ end
263
257
 
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
258
+ # 5 Columns cause issues with resizing
259
+ def self.field_table(list, columns: 4)
260
+ return nil if list.empty?
270
261
 
271
- # # Hide empty results
272
- # output.reject! { |_k, v| v.blank? }
262
+ # Split list into groups based on columns
263
+ groups = list.each_slice((list.size / columns.to_f).ceil).to_a
273
264
 
274
- # render_table(output, flags)
275
- # end
265
+ # Max Width for Table
266
+ truncate = (TTY::Screen.width - groups.count) / groups.count
276
267
 
277
- # Table Printer Helper
278
- def self.fields_print(results)
279
- results.each do |k, v|
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
@@ -968,6 +968,12 @@ module GreenHat
968
968
  /rpm_verify/
969
969
  ]
970
970
  },
971
+ 'gitlab_system_status' => {
972
+ format: :raw,
973
+ pattern: [
974
+ /gitlab_system_status/
975
+ ]
976
+ },
971
977
  'gitlab-rails/application.log' => {
972
978
  format: :raw,
973
979
  pattern: [
@@ -14,6 +14,9 @@ module GreenHat
14
14
  { message: row }
15
15
  end
16
16
 
17
+ # Skip bad results
18
+ next if result.nil?
19
+
17
20
  # Parsing Time / Recusrive is really slow
18
21
  format_time(result)
19
22
 
@@ -1,3 +1,3 @@
1
1
  module GreenHat
2
- VERSION = '0.7.3'.freeze
2
+ VERSION = '0.8.0'.freeze
3
3
  end
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.7.3
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: 2023-11-14 00:00:00.000000000 Z
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: '1.6'
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: '1.6'
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.3.26
550
- signing_key:
561
+ rubygems_version: 3.6.2
551
562
  specification_version: 4
552
563
  summary: GitLab SOS Tool
553
564
  test_files: []