greenhat 0.5.1 → 0.6.1

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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/lib/greenhat/archive.rb +2 -0
  3. data/lib/greenhat/cli.rb +12 -2
  4. data/lib/greenhat/entrypoint.rb +36 -33
  5. data/lib/greenhat/logbot.rb +1 -1
  6. data/lib/greenhat/paper/flag_helper.rb +18 -0
  7. data/lib/greenhat/paper/paper_helper.rb +118 -0
  8. data/lib/greenhat/paper.rb +34 -0
  9. data/lib/greenhat/reports/builder.rb +98 -0
  10. data/lib/greenhat/reports/helpers.rb +101 -0
  11. data/lib/greenhat/reports/internal_methods.rb +156 -0
  12. data/lib/greenhat/reports/reports/errors.rb +49 -0
  13. data/lib/greenhat/reports/reports/faststats.rb +42 -0
  14. data/lib/greenhat/reports/reports/full.rb +143 -0
  15. data/lib/greenhat/reports/runner.rb +58 -0
  16. data/lib/greenhat/reports/shared.rb +37 -0
  17. data/lib/greenhat/reports/shell_helper.rb +34 -0
  18. data/lib/greenhat/reports.rb +79 -0
  19. data/lib/greenhat/settings.rb +6 -1
  20. data/lib/greenhat/shell/args.rb +9 -9
  21. data/lib/greenhat/shell/color_string.rb +1 -1
  22. data/lib/greenhat/shell/faststats.rb +24 -5
  23. data/lib/greenhat/shell/field_helper.rb +1 -1
  24. data/lib/greenhat/shell/filter_help.rb +36 -189
  25. data/lib/greenhat/shell/log.rb +18 -14
  26. data/lib/greenhat/shell/markdown.rb +355 -352
  27. data/lib/greenhat/shell/process.rb +11 -5
  28. data/lib/greenhat/shell/query.rb +183 -27
  29. data/lib/greenhat/shell/report.rb +415 -412
  30. data/lib/greenhat/shell/reports.rb +41 -0
  31. data/lib/greenhat/shell/shell_helper.rb +92 -34
  32. data/lib/greenhat/shell.rb +13 -2
  33. data/lib/greenhat/thing/file_types.rb +14 -0
  34. data/lib/greenhat/thing/formatters/clean_raw.rb +1 -1
  35. data/lib/greenhat/thing/formatters/runner_log.rb +70 -0
  36. data/lib/greenhat/thing/formatters/time_json.rb +12 -1
  37. data/lib/greenhat/thing/kind.rb +1 -1
  38. data/lib/greenhat/version.rb +1 -1
  39. data/lib/greenhat.rb +6 -8
  40. metadata +31 -4
  41. data/lib/greenhat/pry_helpers.rb +0 -51
  42. data/lib/greenhat/thing/super_log.rb +0 -1
@@ -1,352 +1,355 @@
1
- module GreenHat
2
- # Root Level Shell / Report Helper
3
- module Shell
4
- def self.markdown_report(raw)
5
- _files, flags, _args = Args.parse(raw)
6
-
7
- archives = if flags.archive
8
- Archive.all.select do |archive|
9
- flags.archive.any? { |x| archive.name.include? x.to_s }
10
- end
11
- else
12
- Archive.all
13
- end
14
-
15
- ShellHelper.show(archives.map(&:report_markdown).map(&:show).flatten, flags)
16
- end
17
- end
18
- end
19
-
20
- module GreenHat
21
- # Report Generator Helper
22
- # rubocop:disable Metrics/ClassLength
23
- class ReportMarkdown
24
- include ActionView::Helpers::NumberHelper
25
-
26
- attr_accessor :archive, :host, :os_release, :selinux_status, :cpu, :uname,
27
- :timedatectl, :uptime, :meminfo, :gitlab_manifest, :gitlab_status,
28
- :production_log, :api_log, :application_log, :sidekiq_log,
29
- :exceptions_log, :gitaly_log, :free_m, :disk_free
30
-
31
- # Find Needed Files for Report
32
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
33
- def initialize(archive)
34
- self.archive = archive
35
- self.host = archive.things.find { |x| x.name == 'hostname' }
36
- self.os_release = archive.things.find { |x| x.name == 'etc/os-release' }
37
- self.selinux_status = archive.things.find { |x| x.name == 'sestatus' }
38
- self.cpu = archive.things.find { |x| x.name == 'lscpu' }
39
- self.uname = archive.things.find { |x| x.name == 'uname' }
40
- self.timedatectl = archive.things.find { |x| x.name == 'timedatectl' }
41
- self.uptime = archive.things.find { |x| x.name == 'uptime' }
42
- self.meminfo = archive.things.find { |x| x.name == 'meminfo' }
43
- self.free_m = archive.things.find { |x| x.name == 'free_m' }
44
- self.gitlab_manifest = archive.things.find { |x| x.name == 'gitlab/version-manifest.json' }
45
- self.gitlab_status = archive.things.find { |x| x.name == 'gitlab_status' }
46
- self.production_log = archive.things.find { |x| x.name == 'gitlab-rails/production_json.log' }
47
- self.api_log = archive.things.find { |x| x.name == 'gitlab-rails/api_json.log' }
48
- self.application_log = archive.things.find { |x| x.name == 'gitlab-rails/application_json.log' }
49
- self.exceptions_log = archive.things.find { |x| x.name == 'gitlab-rails/exceptions_json.log' }
50
- self.gitaly_log = archive.things.find { |x| x.name == 'gitaly/current' }
51
- self.sidekiq_log = archive.things.find { |x| x.name == 'sidekiq/current' }
52
- self.disk_free = archive.things.find { |x| x.name == 'df_hT' }
53
- end
54
-
55
- def show
56
- output = [
57
- archive.friendly_name,
58
- ''
59
- ]
60
-
61
- # GitLab Version
62
- output << "**GitLab #{gitlab_version}**\n" if gitlab_manifest || gitlab_status
63
-
64
- # OS
65
- output << "**OS**\n"
66
-
67
- output << collect_host
68
- output << ''
69
-
70
- # Memory
71
- if meminfo || free_m
72
- output << "**Memory**\n"
73
- # output << memory_perc if meminfo
74
- output << memory_free if free_m
75
- output << ''
76
- end
77
-
78
- # Disk
79
- if disk_free
80
- output << disks
81
- output << ''
82
- end
83
-
84
- # Gitlab
85
- output << gitlab_services if gitlab_status
86
-
87
- output << ''
88
-
89
- output << "**Errors**\n" if production_log || api_log || application_log || sidekiq_log
90
- output << collect_errors
91
-
92
- # Final Space / Return
93
- output << ''
94
- output
95
- end
96
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
97
-
98
- def collect_host
99
- output = []
100
- output << hostname if host
101
- output << distro if os_release
102
- output << selinux if selinux_status
103
- # output << arch if cpu
104
- output << kernel if uname
105
- output << sys_time if timedatectl
106
- output << sys_uptime if uptime
107
- output << load_average if uptime && cpu
108
-
109
- groups = output.each_slice((output.size / 2.to_f).round).to_a
110
-
111
- table = TTY::Table.new do |t|
112
- loop do
113
- break if groups.all?(&:empty?)
114
-
115
- t << groups.map(&:shift)
116
- end
117
- end
118
-
119
- "```\n#{table.render(:basic, padding: [0, 2, 0, 0])}\n```"
120
- end
121
-
122
- def collect_errors
123
- output = []
124
- output << production_errors if production_log
125
- output << application_errors if application_log
126
- output << sidekiq_errors if sidekiq_log
127
- output << api_errors if api_log
128
- output << exception_errors if exceptions_log
129
- output << gitaly_errors if gitaly_log
130
-
131
- # Keep Alphabetical Sort / Allow for only one
132
- slice_size = (output.size / 3.to_f).round
133
- slice_size = 1 unless slice_size.positive?
134
-
135
- groups = output.each_slice(slice_size).to_a
136
-
137
- table = TTY::Table.new do |t|
138
- loop do
139
- break if groups.all?(&:empty?)
140
-
141
- t << groups.map(&:shift)
142
- end
143
- end
144
-
145
- "```\n#{table.render(:basic, padding: [0, 2, 0, 0])}\n```"
146
- end
147
-
148
- def exception_errors
149
- count = exceptions_log.data.count
150
-
151
- "Exception: #{count}"
152
- end
153
-
154
- def gitaly_errors
155
- count = gitaly_log.data.count { |x| x.level == 'error' }
156
-
157
- "Gitaly: #{count}"
158
- end
159
-
160
- def production_errors
161
- count = production_log.data.count { |x| x.status == 500 }
162
-
163
- "Production: #{count}"
164
- end
165
-
166
- def api_errors
167
- count = api_log.data.count { |x| x.status == 500 }
168
-
169
- "API: #{count}"
170
- end
171
-
172
- def application_errors
173
- results = ShellHelper.filter_internal([
174
- 'gitlab-rails/application_json.log',
175
- '--message!="Cannot obtain an exclusive lease"',
176
- '--severity=error',
177
- "--archive=#{archive.name}"
178
- ].join(' '))
179
-
180
- "Application: #{results.count}"
181
- end
182
-
183
- def sidekiq_errors
184
- count = sidekiq_log.data.count { |x| x&.severity == 'ERROR' }
185
-
186
- "Sidekiq: #{count}"
187
- end
188
-
189
- def gitlab_services
190
- [
191
- "**Services**\n",
192
- "\n",
193
- GreenHat::GitLab.services_markdown(archive)
194
- ].join
195
- rescue StandardError => e
196
- LogBot.fatal('GitLab Services', message: e.message, backtrace: e.backtrace.first)
197
- end
198
-
199
- def gitlab_version
200
- txt = gitlab_manifest.data.dig(:software, :'gitlab-rails', :display_version) || gitlab_manifest.data.build_version
201
-
202
- if txt.include? '-ce'
203
- txt += ' - [😱 CE](https://about.gitlab.com/support/statement-of-support.html#free-and-community-edition-users)!'
204
- end
205
-
206
- "Version: #{txt}"
207
- end
208
-
209
- def hostname
210
- "Hostname: #{host.data.first}"
211
- end
212
-
213
- def distro
214
- [
215
- "Distro: [#{os_release.data.ID}] ",
216
- os_release.data.PRETTY_NAME
217
- ].join
218
- end
219
-
220
- def selinux
221
- status = selinux_status.data['SELinux status']
222
-
223
- [
224
- 'SeLinux: ',
225
- status,
226
- ' (',
227
- selinux_status.data['Current mode'],
228
- ')'
229
- ].join
230
- end
231
-
232
- def arch
233
- [
234
- 'Arch: ',
235
- cpu.data.Architecture
236
- ].join
237
- end
238
-
239
- def kernel
240
- # TODO: Better way to consistently get uname info?
241
- value, build = uname.data.first.split[2].split('-')
242
- [
243
- 'Kernel: ',
244
- value,
245
- " (#{build})"
246
- ].join
247
- end
248
-
249
- # Helper for finding if NTP is enabled
250
- def ntp_keys
251
- [
252
- 'Network time on', 'NTP enabled', 'NTP service', 'System clock synchronized'
253
- ]
254
- end
255
-
256
- def sys_time
257
- # Ignore if Empty
258
- return false if timedatectl.data.nil?
259
-
260
- ntp_statuses = timedatectl.data.slice(*ntp_keys).values.compact
261
-
262
- ntp_status = ntp_statuses.first
263
-
264
- # Fall Back
265
- ntp_status ||= 'unknown'
266
-
267
- [
268
- 'Sys Time: ',
269
- timedatectl.data['Local time'],
270
- "(ntp: #{ntp_status})"
271
- ].join
272
- end
273
-
274
- # Strip/Simplify Uptime
275
- def sys_uptime
276
- init = uptime.data.first.split(', load average').first.strip
277
-
278
- "Uptime: #{init.split('up ', 2).last}"
279
- end
280
-
281
- def load_average
282
- cpu_count = cpu.data['CPU(s)'].to_i
283
- intervals = uptime.data.first.split('load average: ', 2).last.split(', ').map(&:to_f)
284
-
285
- # Generate Colorized Text for Output
286
- intervals_text = intervals.map do |interval|
287
- value = percent(interval, cpu_count)
288
-
289
- "#{interval} (#{value}%)"
290
- end
291
-
292
- [
293
- 'LoadAvg: ',
294
- "[CPU #{cpu_count}] ",
295
- intervals_text.join(', ')
296
- ].join
297
- end
298
-
299
- def memory_free
300
- free = free_m.data.find { |x| x.kind == 'Mem' }
301
-
302
- return unless free
303
-
304
- pad = 6
305
- list = [
306
- "#{title('Total', pad)} #{number_to_human_size(free.total.to_i * (1024**2))}",
307
- "#{title('Used', pad)} #{number_to_human_size(free.used.to_i * (1024**2))}",
308
- "#{title('Free', pad)} #{number_to_human_size(free.free.to_i * (1024**2))}",
309
- "#{title('Avail', pad)} #{number_to_human_size(free.available.to_i * (1024**2))}"
310
- ]
311
-
312
- # Keep Alphabetical Sort
313
- groups = list.each_slice((list.size / 2.to_f).round).to_a
314
-
315
- table = TTY::Table.new do |t|
316
- loop do
317
- break if groups.all?(&:empty?)
318
-
319
- t << groups.map(&:shift)
320
- end
321
- end
322
-
323
- "```\n#{table.render(:basic, padding: [0, 2, 0, 0])}\n```"
324
- end
325
-
326
- def disks
327
- # GreenHat::Disk.df({archive: []})
328
- file = GreenHat::Disk.df({ archive: [archive.name] })
329
-
330
- disk_list = GreenHat::Disk.markdown_format(file.first, false, 3)
331
-
332
- # Preapre / Indent List
333
- [
334
- '**Disks**',
335
- "\n\n```\n#{disk_list.join("\n")}\n```"
336
- ].join
337
- end
338
-
339
- # ----------------------------
340
- # Helpers
341
- # ----------------------------
342
- def percent(value, total)
343
- ((value / total.to_f) * 100).round
344
- end
345
-
346
- # Helper to Make Cyan Titles
347
- def title(name, ljust = 16)
348
- "#{name}:".ljust(ljust)
349
- end
350
- end
351
- # rubocop:enable Metrics/ClassLength
352
- end
1
+ # Deprecated in favor of reports module
2
+ # TODO: Remove / Replace for markdown report
3
+ # module GreenHat
4
+ # # Root Level Shell / Report Helper
5
+ # module Shell
6
+ # def self.markdown_report(raw)
7
+ # _files, flags, _args = Args.parse(raw)
8
+
9
+ # archives = if flags.archive
10
+ # Archive.all.select do |archive|
11
+ # flags.archive.any? { |x| archive.name.include? x.to_s }
12
+ # end
13
+ # else
14
+ # Archive.all
15
+ # end
16
+
17
+ # ShellHelper.show(archives.map(&:report_markdown).map(&:show).flatten, flags)
18
+ # end
19
+ # end
20
+ # end
21
+
22
+ # module GreenHat
23
+ # # Report Generator Helper
24
+ #
25
+ # class ReportMarkdown
26
+ # include ActionView::Helpers::NumberHelper
27
+
28
+ # attr_accessor :archive, :host, :os_release, :selinux_status, :cpu, :uname,
29
+ # :timedatectl, :uptime, :meminfo, :gitlab_manifest, :gitlab_status,
30
+ # :production_log, :api_log, :application_log, :sidekiq_log,
31
+ # :exceptions_log, :gitaly_log, :free_m, :disk_free
32
+
33
+ # # Find Needed Files for Report
34
+ #
35
+ # def initialize(archive)
36
+ # self.archive = archive
37
+ # self.host = archive.things.find { |x| x.name == 'hostname' }
38
+ # self.os_release = archive.things.find { |x| x.name == 'etc/os-release' }
39
+ # self.selinux_status = archive.things.find { |x| x.name == 'sestatus' }
40
+ # self.cpu = archive.things.find { |x| x.name == 'lscpu' }
41
+ # self.uname = archive.things.find { |x| x.name == 'uname' }
42
+ # self.timedatectl = archive.things.find { |x| x.name == 'timedatectl' }
43
+ # self.uptime = archive.things.find { |x| x.name == 'uptime' }
44
+ # self.meminfo = archive.things.find { |x| x.name == 'meminfo' }
45
+ # self.free_m = archive.things.find { |x| x.name == 'free_m' }
46
+ # self.gitlab_manifest = archive.things.find { |x| x.name == 'gitlab/version-manifest.json' }
47
+ # self.gitlab_status = archive.things.find { |x| x.name == 'gitlab_status' }
48
+ # self.production_log = archive.things.find { |x| x.name == 'gitlab-rails/production_json.log' }
49
+ # self.api_log = archive.things.find { |x| x.name == 'gitlab-rails/api_json.log' }
50
+ # self.application_log = archive.things.find { |x| x.name == 'gitlab-rails/application_json.log' }
51
+ # self.exceptions_log = archive.things.find { |x| x.name == 'gitlab-rails/exceptions_json.log' }
52
+ # self.gitaly_log = archive.things.find { |x| x.name == 'gitaly/current' }
53
+ # self.sidekiq_log = archive.things.find { |x| x.name == 'sidekiq/current' }
54
+ # self.disk_free = archive.things.find { |x| x.name == 'df_hT' }
55
+ # end
56
+
57
+ # def show
58
+ # output = [
59
+ # archive.friendly_name,
60
+ # ''
61
+ # ]
62
+
63
+ # # GitLab Version
64
+ # output << "**GitLab #{gitlab_version}**\n" if gitlab_manifest || gitlab_status
65
+
66
+ # # OS
67
+ # output << "**OS**\n"
68
+
69
+ # output << collect_host
70
+ # output << ''
71
+
72
+ # # Memory
73
+ # if meminfo || free_m
74
+ # output << "**Memory**\n"
75
+ # # output << memory_perc if meminfo
76
+ # output << memory_free if free_m
77
+ # output << ''
78
+ # end
79
+
80
+ # # Disk
81
+ # if disk_free
82
+ # output << disks
83
+ # output << ''
84
+ # end
85
+
86
+ # # Gitlab
87
+ # output << gitlab_services if gitlab_status
88
+
89
+ # output << ''
90
+
91
+ # output << "**Errors**\n" if production_log || api_log || application_log || sidekiq_log
92
+ # output << collect_errors
93
+
94
+ # # Final Space / Return
95
+ # output << ''
96
+ # output
97
+ # end
98
+ # # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
99
+
100
+ # def collect_host
101
+ # output = []
102
+ # output << hostname if host
103
+ # output << distro if os_release
104
+ # output << selinux if selinux_status
105
+ # # output << arch if cpu
106
+ # output << kernel if uname
107
+ # output << sys_time if timedatectl
108
+ # output << sys_uptime if uptime
109
+ # output << load_average if uptime && cpu
110
+
111
+ # groups = output.each_slice((output.size / 2.to_f).round).to_a
112
+
113
+ # table = TTY::Table.new do |t|
114
+ # loop do
115
+ # break if groups.all?(&:empty?)
116
+
117
+ # t << groups.map(&:shift)
118
+ # end
119
+ # end
120
+
121
+ # "```\n#{table.render(:basic, padding: [0, 2, 0, 0])}\n```"
122
+ # end
123
+
124
+ # def collect_errors
125
+ # output = []
126
+ # output << production_errors if production_log
127
+ # output << application_errors if application_log
128
+ # output << sidekiq_errors if sidekiq_log
129
+ # output << api_errors if api_log
130
+ # output << exception_errors if exceptions_log
131
+ # output << gitaly_errors if gitaly_log
132
+
133
+ # # Keep Alphabetical Sort / Allow for only one
134
+ # slice_size = (output.size / 3.to_f).round
135
+ # slice_size = 1 unless slice_size.positive?
136
+
137
+ # groups = output.each_slice(slice_size).to_a
138
+
139
+ # table = TTY::Table.new do |t|
140
+ # loop do
141
+ # break if groups.all?(&:empty?)
142
+
143
+ # t << groups.map(&:shift)
144
+ # end
145
+ # end
146
+
147
+ # "```\n#{table.render(:basic, padding: [0, 2, 0, 0])}\n```"
148
+ # end
149
+
150
+ # def exception_errors
151
+ # count = exceptions_log.data.count
152
+
153
+ # "Exception: #{count}"
154
+ # end
155
+
156
+ # def gitaly_errors
157
+ # count = gitaly_log.data.count { |x| x.level == 'error' }
158
+
159
+ # "Gitaly: #{count}"
160
+ # end
161
+
162
+ # def production_errors
163
+ # count = production_log.data.count { |x| x.status == 500 }
164
+
165
+ # "Production: #{count}"
166
+ # end
167
+
168
+ # def api_errors
169
+ # count = api_log.data.count { |x| x.status == 500 }
170
+
171
+ # "API: #{count}"
172
+ # end
173
+
174
+ # def application_errors
175
+ # results = ShellHelper.filter_internal([
176
+ # 'gitlab-rails/application_json.log',
177
+ # '--message!="Cannot obtain an exclusive lease"',
178
+ # '--severity=error',
179
+ # "--archive=#{archive.name}"
180
+ # ].join(' '))
181
+
182
+ # "Application: #{results.count}"
183
+ # end
184
+
185
+ # def sidekiq_errors
186
+ # count = sidekiq_log.data.count { |x| x&.severity == 'ERROR' }
187
+
188
+ # "Sidekiq: #{count}"
189
+ # end
190
+
191
+ # def gitlab_services
192
+ # [
193
+ # "**Services**\n",
194
+ # "\n",
195
+ # GreenHat::GitLab.services_markdown(archive)
196
+ # ].join
197
+ # rescue StandardError => e
198
+ # LogBot.fatal('GitLab Services', message: e.message, backtrace: e.backtrace.first)
199
+ # end
200
+
201
+ # def gitlab_version
202
+ # txt = gitlab_manifest.data.dig(:software,
203
+ # :'gitlab-rails', :display_version) || gitlab_manifest.data.build_version
204
+
205
+ # if txt.include? '-ce'
206
+ # txt += ' - [😱 CE](https://about.gitlab.com/support/statement-of-support.html#free-and-community-edition-users)!'
207
+ # end
208
+
209
+ # "Version: #{txt}"
210
+ # end
211
+
212
+ # def hostname
213
+ # "Hostname: #{host.data.first}"
214
+ # end
215
+
216
+ # def distro
217
+ # [
218
+ # "Distro: [#{os_release.data.ID}] ",
219
+ # os_release.data.PRETTY_NAME
220
+ # ].join
221
+ # end
222
+
223
+ # def selinux
224
+ # status = selinux_status.data['SELinux status']
225
+
226
+ # [
227
+ # 'SeLinux: ',
228
+ # status,
229
+ # ' (',
230
+ # selinux_status.data['Current mode'],
231
+ # ')'
232
+ # ].join
233
+ # end
234
+
235
+ # def arch
236
+ # [
237
+ # 'Arch: ',
238
+ # cpu.data.Architecture
239
+ # ].join
240
+ # end
241
+
242
+ # def kernel
243
+ # # TODO: Better way to consistently get uname info?
244
+ # value, build = uname.data.first.split[2].split('-')
245
+ # [
246
+ # 'Kernel: ',
247
+ # value,
248
+ # " (#{build})"
249
+ # ].join
250
+ # end
251
+
252
+ # # Helper for finding if NTP is enabled
253
+ # def ntp_keys
254
+ # [
255
+ # 'Network time on', 'NTP enabled', 'NTP service', 'System clock synchronized'
256
+ # ]
257
+ # end
258
+
259
+ # def sys_time
260
+ # # Ignore if Empty
261
+ # return false if timedatectl.data.nil?
262
+
263
+ # ntp_statuses = timedatectl.data.slice(*ntp_keys).values.compact
264
+
265
+ # ntp_status = ntp_statuses.first
266
+
267
+ # # Fall Back
268
+ # ntp_status ||= 'unknown'
269
+
270
+ # [
271
+ # 'Sys Time: ',
272
+ # timedatectl.data['Local time'],
273
+ # "(ntp: #{ntp_status})"
274
+ # ].join
275
+ # end
276
+
277
+ # # Strip/Simplify Uptime
278
+ # def sys_uptime
279
+ # init = uptime.data.first.split(', load average').first.strip
280
+
281
+ # "Uptime: #{init.split('up ', 2).last}"
282
+ # end
283
+
284
+ # def load_average
285
+ # cpu_count = cpu.data['CPU(s)'].to_i
286
+ # intervals = uptime.data.first.split('load average: ', 2).last.split(', ').map(&:to_f)
287
+
288
+ # # Generate Colorized Text for Output
289
+ # intervals_text = intervals.map do |interval|
290
+ # value = percent(interval, cpu_count)
291
+
292
+ # "#{interval} (#{value}%)"
293
+ # end
294
+
295
+ # [
296
+ # 'LoadAvg: ',
297
+ # "[CPU #{cpu_count}] ",
298
+ # intervals_text.join(', ')
299
+ # ].join
300
+ # end
301
+
302
+ # def memory_free
303
+ # free = free_m.data.find { |x| x.kind == 'Mem' }
304
+
305
+ # return unless free
306
+
307
+ # pad = 6
308
+ # list = [
309
+ # "#{title('Total', pad)} #{number_to_human_size(free.total.to_i * (1024**2))}",
310
+ # "#{title('Used', pad)} #{number_to_human_size(free.used.to_i * (1024**2))}",
311
+ # "#{title('Free', pad)} #{number_to_human_size(free.free.to_i * (1024**2))}",
312
+ # "#{title('Avail', pad)} #{number_to_human_size(free.available.to_i * (1024**2))}"
313
+ # ]
314
+
315
+ # # Keep Alphabetical Sort
316
+ # groups = list.each_slice((list.size / 2.to_f).round).to_a
317
+
318
+ # table = TTY::Table.new do |t|
319
+ # loop do
320
+ # break if groups.all?(&:empty?)
321
+
322
+ # t << groups.map(&:shift)
323
+ # end
324
+ # end
325
+
326
+ # "```\n#{table.render(:basic, padding: [0, 2, 0, 0])}\n```"
327
+ # end
328
+
329
+ # def disks
330
+ # # GreenHat::Disk.df({archive: []})
331
+ # file = GreenHat::Disk.df({ archive: [archive.name] })
332
+
333
+ # disk_list = GreenHat::Disk.markdown_format(file.first, false, 3)
334
+
335
+ # # Preapre / Indent List
336
+ # [
337
+ # '**Disks**',
338
+ # "\n\n```\n#{disk_list.join("\n")}\n```"
339
+ # ].join
340
+ # end
341
+
342
+ # # ----------------------------
343
+ # # Helpers
344
+ # # ----------------------------
345
+ # def percent(value, total)
346
+ # ((value / total.to_f) * 100).round
347
+ # end
348
+
349
+ # # Helper to Make Cyan Titles
350
+ # def title(name, ljust = 16)
351
+ # "#{name}:".ljust(ljust)
352
+ # end
353
+ # end
354
+ # # rubocop:enable Metrics/ClassLength
355
+ # end