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.
- checksums.yaml +4 -4
- data/lib/greenhat/archive.rb +2 -0
- data/lib/greenhat/cli.rb +12 -2
- data/lib/greenhat/entrypoint.rb +36 -33
- data/lib/greenhat/logbot.rb +1 -1
- data/lib/greenhat/paper/flag_helper.rb +18 -0
- data/lib/greenhat/paper/paper_helper.rb +118 -0
- data/lib/greenhat/paper.rb +34 -0
- data/lib/greenhat/reports/builder.rb +98 -0
- data/lib/greenhat/reports/helpers.rb +101 -0
- data/lib/greenhat/reports/internal_methods.rb +156 -0
- data/lib/greenhat/reports/reports/errors.rb +49 -0
- data/lib/greenhat/reports/reports/faststats.rb +42 -0
- data/lib/greenhat/reports/reports/full.rb +143 -0
- data/lib/greenhat/reports/runner.rb +58 -0
- data/lib/greenhat/reports/shared.rb +37 -0
- data/lib/greenhat/reports/shell_helper.rb +34 -0
- data/lib/greenhat/reports.rb +79 -0
- data/lib/greenhat/settings.rb +6 -1
- data/lib/greenhat/shell/args.rb +9 -9
- data/lib/greenhat/shell/color_string.rb +1 -1
- data/lib/greenhat/shell/faststats.rb +24 -5
- data/lib/greenhat/shell/field_helper.rb +1 -1
- data/lib/greenhat/shell/filter_help.rb +36 -189
- data/lib/greenhat/shell/log.rb +18 -14
- data/lib/greenhat/shell/markdown.rb +355 -352
- data/lib/greenhat/shell/process.rb +11 -5
- data/lib/greenhat/shell/query.rb +183 -27
- data/lib/greenhat/shell/report.rb +415 -412
- data/lib/greenhat/shell/reports.rb +41 -0
- data/lib/greenhat/shell/shell_helper.rb +92 -34
- data/lib/greenhat/shell.rb +13 -2
- data/lib/greenhat/thing/file_types.rb +14 -0
- data/lib/greenhat/thing/formatters/clean_raw.rb +1 -1
- data/lib/greenhat/thing/formatters/runner_log.rb +70 -0
- data/lib/greenhat/thing/formatters/time_json.rb +12 -1
- data/lib/greenhat/thing/kind.rb +1 -1
- data/lib/greenhat/version.rb +1 -1
- data/lib/greenhat.rb +6 -8
- metadata +31 -4
- data/lib/greenhat/pry_helpers.rb +0 -51
- data/lib/greenhat/thing/super_log.rb +0 -1
@@ -0,0 +1,49 @@
|
|
1
|
+
archive_header
|
2
|
+
|
3
|
+
help do
|
4
|
+
header 'Error Reports'
|
5
|
+
puts 'This will collect errors from the exceptions, production, application, api, workhorse, and sidekiq logs'
|
6
|
+
puts 'Without arguments it will count and unique the error messages'
|
7
|
+
br
|
8
|
+
puts indent("#{'--verbose'.pastel(:green)} Print all of the error messages")
|
9
|
+
puts indent("#{'--filter'.pastel(:green)} Filter Error messages")
|
10
|
+
puts indent('Ex: --filter=exception,production'.pastel(:cyan), 4)
|
11
|
+
puts indent('Ex: --filter!=api'.pastel(:cyan), 4)
|
12
|
+
end
|
13
|
+
|
14
|
+
entries = [
|
15
|
+
{ header: 'Exceptions', base: 'gitlab-rails/exceptions_json.log', stats: 'exception.message,exception.class' },
|
16
|
+
{ header: 'Production', base: 'gitlab-rails/production_json.log --status=500 ',
|
17
|
+
stats: 'exception.message,exception.class' },
|
18
|
+
{
|
19
|
+
header: 'Application',
|
20
|
+
base: 'gitlab-rails/application_json.log --message!="Cannot obtain an exclusive lease" --severity=error',
|
21
|
+
stats: 'message'
|
22
|
+
},
|
23
|
+
{ header: 'Workhorse', base: 'gitlab-workhorse/current --level=error', stats: 'error' },
|
24
|
+
{ header: 'Sidekiq', base: 'sidekiq/current --severity=error', stats: 'message' },
|
25
|
+
{ header: 'API', base: 'gitlab-rails/api_json.log --severity=error',
|
26
|
+
stats: 'exception.class,exception.message,status' }
|
27
|
+
]
|
28
|
+
|
29
|
+
# Filter Logic
|
30
|
+
filters = args_select(:filter)
|
31
|
+
unless filters.empty?
|
32
|
+
entries.select! do |entry|
|
33
|
+
filters.any? do |filter|
|
34
|
+
!filter.bang if filter.value.split(',').any? { |x| entry.header.downcase.include? x }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Return output
|
40
|
+
entries.each do |entry|
|
41
|
+
query_string = flags.verbose ? entry.base : entry.base + " --stats=#{entry.stats}"
|
42
|
+
query(query_string, false) do |results|
|
43
|
+
next if results.map(&:values).map(&:first).sum.zero?
|
44
|
+
|
45
|
+
header entry.header
|
46
|
+
|
47
|
+
show results
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
archive_header
|
2
|
+
|
3
|
+
help do
|
4
|
+
header 'FastStats'
|
5
|
+
puts 'Run against all the things'
|
6
|
+
br
|
7
|
+
puts indent("#{'--filter'.pastel(:green)} Filter for specific files")
|
8
|
+
puts indent('Ex: --filter=gitaly,production'.pastel(:cyan), 4)
|
9
|
+
puts indent('Ex: --filter!=api'.pastel(:cyan), 4)
|
10
|
+
br
|
11
|
+
puts indent("#{'--top'.pastel(:green)} switch to `fast-stats top [filename]`")
|
12
|
+
puts indent("#{'--errors'.pastel(:green)} switch to `fast-stats errors [filename]`")
|
13
|
+
br
|
14
|
+
puts indent("#{'--all'.pastel(:green)} to attempt to faststats everything")
|
15
|
+
br
|
16
|
+
puts 'Combine all the args: `faststats --filter=sidekiq --top --errors`'
|
17
|
+
end
|
18
|
+
|
19
|
+
cmds = []
|
20
|
+
cmds.push 'top' if flags.top
|
21
|
+
cmds.push 'errors' if flags.errors
|
22
|
+
cmds.push nil if cmds.empty? # Assume Default
|
23
|
+
|
24
|
+
filters = args_select(:filter).flat_map { |x| x.value.split(',') }
|
25
|
+
|
26
|
+
if filters.empty?
|
27
|
+
# Add Defaults
|
28
|
+
filters = [
|
29
|
+
'gitaly/current',
|
30
|
+
'gitlab-rails/api_json.log',
|
31
|
+
'gitlab-rails/production_json.log',
|
32
|
+
'sidekiq/current'
|
33
|
+
]
|
34
|
+
end
|
35
|
+
|
36
|
+
filters = ['*'] if flags.all
|
37
|
+
|
38
|
+
filters.each do |filter|
|
39
|
+
cmds.each do |cmd|
|
40
|
+
faststats filter, cmd
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
quiet!
|
2
|
+
archive_header
|
3
|
+
header 'OS'
|
4
|
+
|
5
|
+
cat 'hostname' do |data|
|
6
|
+
indent "#{'Hostname:'.pastel(:cyan)} #{data.join}"
|
7
|
+
end
|
8
|
+
|
9
|
+
info 'etc/os-release' do |data|
|
10
|
+
ident = "[#{data.ID}] ".pastel(:bright_black)
|
11
|
+
pretty_name = data.PRETTY_NAME
|
12
|
+
" #{'Distro'.pastel(:cyan)} #{ident} #{pretty_name}"
|
13
|
+
end
|
14
|
+
|
15
|
+
cat 'uname' do |data|
|
16
|
+
value, build = data.first.split[2].split('-')
|
17
|
+
build = "(#{build})".pastel(:bright_black)
|
18
|
+
" #{'Kernel'.pastel(:cyan)} #{value} #{build}"
|
19
|
+
end
|
20
|
+
|
21
|
+
cat 'uptime' do |data|
|
22
|
+
init = data.join.split(', load average').first.strip.split('up ', 2).last
|
23
|
+
" #{'Uptime'.pastel(:cyan)} #{init}"
|
24
|
+
end
|
25
|
+
|
26
|
+
# Load Average
|
27
|
+
info 'lscpu' do |data|
|
28
|
+
uptime = archive.thing? 'uptime'
|
29
|
+
return unless uptime
|
30
|
+
|
31
|
+
cpu_count = data['CPU(s)'].to_i
|
32
|
+
intervals = uptime.data.first.split('load average: ', 2).last.split(', ').map(&:to_f)
|
33
|
+
|
34
|
+
intervals_text = intervals.map do |interval|
|
35
|
+
value = percent(interval, cpu_count)
|
36
|
+
color = value > 100 ? :red : :green
|
37
|
+
[
|
38
|
+
interval,
|
39
|
+
' (',
|
40
|
+
"#{value}%".pastel(color),
|
41
|
+
')'
|
42
|
+
].join
|
43
|
+
end
|
44
|
+
|
45
|
+
" #{'LoadAvg'.pastel(:cyan)} #{"[CPU #{cpu_count}] ".pastel(:bright_white)} #{intervals_text.join(', ')}"
|
46
|
+
end
|
47
|
+
|
48
|
+
br
|
49
|
+
header 'Memory'
|
50
|
+
|
51
|
+
info('meminfo') do |data|
|
52
|
+
total = human_size_to_number(data['MemTotal'])
|
53
|
+
free = human_size_to_number(data['MemFree'])
|
54
|
+
used = percent((total - free), total)
|
55
|
+
|
56
|
+
[
|
57
|
+
' ',
|
58
|
+
ljust('Usage', 13, :yellow),
|
59
|
+
'['.pastel(:bright_black),
|
60
|
+
'='.pastel(:green) * (used / 2),
|
61
|
+
' ' * (50 - (used / 2)),
|
62
|
+
']'.pastel(:bright_black),
|
63
|
+
" #{100 - percent(free, total)}%".pastel(:green) # Inverse
|
64
|
+
].join
|
65
|
+
end
|
66
|
+
|
67
|
+
info('free_m', false) do |data|
|
68
|
+
free = data.first
|
69
|
+
|
70
|
+
unless free.total.blank?
|
71
|
+
size = number_to_human_size(free.total.to_i * (1024**2))
|
72
|
+
puts " #{ljust('Total', 12, :cyan)} #{size}"
|
73
|
+
end
|
74
|
+
|
75
|
+
unless free.used.blank?
|
76
|
+
size = number_to_human_size(free.used.to_i * (1024**2))
|
77
|
+
|
78
|
+
puts " #{ljust('Used', 12, :yellow)} #{size}"
|
79
|
+
end
|
80
|
+
|
81
|
+
unless free.free.blank?
|
82
|
+
size = number_to_human_size(free.free.to_i * (1024**2))
|
83
|
+
puts " #{ljust('Free', 12, :blue)} #{size}"
|
84
|
+
end
|
85
|
+
|
86
|
+
unless free.available.blank?
|
87
|
+
size = number_to_human_size(free.available.to_i * (1024**2))
|
88
|
+
puts " #{ljust('Available', 12, :green)} #{size}"
|
89
|
+
end
|
90
|
+
|
91
|
+
br
|
92
|
+
data.map { |x| GreenHat::Memory.memory_row x }.each do |row|
|
93
|
+
puts indent(row)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
br
|
98
|
+
header 'GitLab'
|
99
|
+
info 'gitlab/version-manifest.json' do |data|
|
100
|
+
indent("#{'Version'.pastel(:cyan)}: #{data.build_version}")
|
101
|
+
end
|
102
|
+
|
103
|
+
info 'gitlab_status' do
|
104
|
+
indent(GreenHat::GitLab.services(archive, 3), 3)
|
105
|
+
end
|
106
|
+
|
107
|
+
br
|
108
|
+
puts indent('Errors'.pastel(:cyan))
|
109
|
+
|
110
|
+
query 'gitlab-rails/production_json.log --status=500' do |data|
|
111
|
+
color = data.count.zero? ? :green : :red
|
112
|
+
indent("#{ljust('Production:', 14, :magenta)} #{data.count.to_s.pastel(color)}", 4)
|
113
|
+
end
|
114
|
+
|
115
|
+
query 'gitlab-rails/application_json.log --message!="Cannot obtain an exclusive lease" --severity=error' do |data|
|
116
|
+
color = data.count.zero? ? :green : :red
|
117
|
+
indent("#{ljust('Application:', 14, :magenta)} #{data.count.to_s.pastel(color)}", 4)
|
118
|
+
end
|
119
|
+
|
120
|
+
query 'sidekiq/current --severity=error' do |data|
|
121
|
+
color = data.count.zero? ? :green : :red
|
122
|
+
indent("#{ljust('Sidekiq:', 14, :magenta)} #{data.count.to_s.pastel(color)}", 4)
|
123
|
+
end
|
124
|
+
|
125
|
+
query 'gitlab-rails/api_json.log --status=500' do |data|
|
126
|
+
color = data.count.zero? ? :green : :red
|
127
|
+
indent("#{ljust('API:', 14, :magenta)} #{data.count.to_s.pastel(color)}", 4)
|
128
|
+
end
|
129
|
+
|
130
|
+
query 'gitaly/current --level=error' do |data|
|
131
|
+
color = data.count.zero? ? :green : :red
|
132
|
+
indent("#{ljust('Gitaly:', 14, :magenta)} #{data.count.to_s.pastel(color)}", 4)
|
133
|
+
end
|
134
|
+
|
135
|
+
query 'gitlab-workhorse/current --level=error' do |data|
|
136
|
+
color = data.count.zero? ? :green : :red
|
137
|
+
indent("#{ljust('Workhorse:', 14, :magenta)} #{data.count.to_s.pastel(color)}", 4)
|
138
|
+
end
|
139
|
+
|
140
|
+
query 'gitlab-rails/exceptions_json.log' do |data|
|
141
|
+
color = data.count.zero? ? :green : :red
|
142
|
+
indent("#{ljust('Exceptions:', 14, :magenta)} #{data.count.to_s.pastel(color)}", 4)
|
143
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# GreenHat Namespace
|
2
|
+
module GreenHat
|
3
|
+
# Reports NameSpace
|
4
|
+
module Reports
|
5
|
+
# This guy actually runs the reports
|
6
|
+
class Runner
|
7
|
+
include ActionView::Helpers::DateHelper
|
8
|
+
include ActionView::Helpers::NumberHelper
|
9
|
+
|
10
|
+
include InternalMethods
|
11
|
+
include Shared
|
12
|
+
attr_accessor :store, :archive, :flags, :args, :output
|
13
|
+
|
14
|
+
# Make Pry Easier
|
15
|
+
def inspect
|
16
|
+
"#<Runner archive: '#{archive}'>"
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(archive:, store:, flags:, args:)
|
20
|
+
self.store = store
|
21
|
+
self.archive = archive
|
22
|
+
self.flags = flags
|
23
|
+
self.args = args
|
24
|
+
self.output = []
|
25
|
+
|
26
|
+
# Don't render paper new lines
|
27
|
+
# flags[:skip_new_line] = true
|
28
|
+
end
|
29
|
+
|
30
|
+
# Main Entrypoint for Triggering Reports Run
|
31
|
+
def run!
|
32
|
+
if flags.help
|
33
|
+
# Check for Help Flag
|
34
|
+
help_flag = store.find { |x| x.first == :help }
|
35
|
+
help_flag ? run_entry(help_flag) : puts('No Help :(')
|
36
|
+
return true
|
37
|
+
end
|
38
|
+
|
39
|
+
store.each do |entry|
|
40
|
+
next if entry.first == :help # Skip if no flags
|
41
|
+
|
42
|
+
run_entry(entry)
|
43
|
+
end
|
44
|
+
|
45
|
+
puts
|
46
|
+
rescue StandardError => e
|
47
|
+
puts e.message
|
48
|
+
puts e.backtrace
|
49
|
+
end
|
50
|
+
|
51
|
+
# Helper to evaluate Entry
|
52
|
+
def run_entry(entry)
|
53
|
+
method = entry[0]
|
54
|
+
send(method, *entry[1..])
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# GreenHat Namespace
|
2
|
+
module GreenHat
|
3
|
+
# Reports Parent Class
|
4
|
+
module Reports
|
5
|
+
# Method Helper Module
|
6
|
+
module Shared
|
7
|
+
# Indentation Helper
|
8
|
+
def indent(text, indent_value = 2)
|
9
|
+
if indent_value.zero?
|
10
|
+
text
|
11
|
+
else
|
12
|
+
"#{' ' * indent_value}#{text}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def percent(value, total)
|
17
|
+
((value / total.to_f) * 100).round
|
18
|
+
end
|
19
|
+
|
20
|
+
# Justify Text Helper / With Color!
|
21
|
+
def ljust(text, value = 14, color = nil)
|
22
|
+
color ? text.ljust(value).pastel(color) : text.ljust(value)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Number Helper
|
26
|
+
def human_size_to_number(value)
|
27
|
+
GreenHat::ShellHelper.human_size_to_number value
|
28
|
+
end
|
29
|
+
|
30
|
+
# Helper to filter arg selection
|
31
|
+
def args_select(field)
|
32
|
+
args.select { |x| x.field == field.to_sym }
|
33
|
+
end
|
34
|
+
# -=-=-=-=-=-
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module GreenHat
|
2
|
+
module ShellHelper
|
3
|
+
# Log Helpers
|
4
|
+
module Reports
|
5
|
+
# Make Running more consistent
|
6
|
+
def self.run(file:, args:, flags:)
|
7
|
+
report = GreenHat::Reports::Builder.new(file: file, args: args, flags: flags)
|
8
|
+
output = Archive.all.map do |archive|
|
9
|
+
runner = GreenHat::Reports::Runner.new(
|
10
|
+
archive: archive,
|
11
|
+
store: report.store.clone,
|
12
|
+
flags: flags,
|
13
|
+
args: args
|
14
|
+
)
|
15
|
+
|
16
|
+
runner.run!
|
17
|
+
|
18
|
+
runner
|
19
|
+
end
|
20
|
+
|
21
|
+
# Check for Pagination
|
22
|
+
flags[:page] = ENV['GREENHAT_PAGE'] == 'true' if ENV['GREENHAT_PAGE']
|
23
|
+
|
24
|
+
ShellHelper.show(output.flat_map(&:output), flags)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Collect everything from Built-in and local reports
|
28
|
+
def self.list
|
29
|
+
path = "#{File.dirname(__FILE__)}/reports"
|
30
|
+
Dir["#{path}/*.rb"] + Dir["#{GreenHat::Settings.reports_dir}/*.rb"]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'greenhat'
|
2
|
+
require 'greenhat/reports/internal_methods'
|
3
|
+
require 'greenhat/reports/helpers'
|
4
|
+
require 'greenhat/reports/runner'
|
5
|
+
|
6
|
+
GreenHat::Cli.quiet!
|
7
|
+
|
8
|
+
# GreenHat Namespace
|
9
|
+
module GreenHat
|
10
|
+
# Reports Parent Class
|
11
|
+
module Reports
|
12
|
+
# Method Storing
|
13
|
+
def self.store
|
14
|
+
@store ||= []
|
15
|
+
|
16
|
+
@store
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.output
|
20
|
+
@output ||= []
|
21
|
+
end
|
22
|
+
|
23
|
+
# Adding Methods
|
24
|
+
def self.add(*params)
|
25
|
+
store.push params
|
26
|
+
end
|
27
|
+
|
28
|
+
# Main Entrypoint for Triggering Reports Run
|
29
|
+
def self.run!
|
30
|
+
_list, flags, args = Args.parse(ARGV)
|
31
|
+
|
32
|
+
output = Archive.all.map do |archive|
|
33
|
+
runner = GreenHat::Reports::Runner.new(
|
34
|
+
archive: archive,
|
35
|
+
store: store.clone,
|
36
|
+
flags: flags,
|
37
|
+
args: args
|
38
|
+
)
|
39
|
+
|
40
|
+
runner.run!
|
41
|
+
|
42
|
+
break if flags.help # Only Run Once
|
43
|
+
|
44
|
+
runner
|
45
|
+
end
|
46
|
+
|
47
|
+
# Check for Pagination
|
48
|
+
flags[:page] = ENV['GREENHAT_PAGE'] == 'true' if ENV['GREENHAT_PAGE']
|
49
|
+
|
50
|
+
ShellHelper.show(output.flat_map(&:output), flags)
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.archive_run(archive)
|
54
|
+
store.each do |entry|
|
55
|
+
method = entry[0]
|
56
|
+
# Skip anything for Shim'd Puts
|
57
|
+
if method == :puts
|
58
|
+
send(method, *entry[1..])
|
59
|
+
else
|
60
|
+
send(method, archive, *entry[1..])
|
61
|
+
end
|
62
|
+
end
|
63
|
+
rescue StandardError => e
|
64
|
+
puts e.message
|
65
|
+
puts e.backtrace
|
66
|
+
end
|
67
|
+
# ==
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
at_exit do
|
72
|
+
Dir.mktmpdir('greenhat-sauce') do |tmp|
|
73
|
+
$TMP = tmp
|
74
|
+
$STDOUT_CLONE = $stdout.clone
|
75
|
+
ENV['GREENHAT_REPORT'] = 'true' # Flag to allow skipping of different entypoints
|
76
|
+
GreenHat::Entrypoint.start(ARGV, false, false)
|
77
|
+
GreenHat::Reports.run!
|
78
|
+
end
|
79
|
+
end
|
data/lib/greenhat/settings.rb
CHANGED
@@ -83,6 +83,7 @@ module GreenHat
|
|
83
83
|
|
84
84
|
def self.start
|
85
85
|
Dir.mkdir dir unless Dir.exist? dir
|
86
|
+
Dir.mkdir reports_dir unless Dir.exist? reports_dir
|
86
87
|
|
87
88
|
# Load User Settings
|
88
89
|
settings_load
|
@@ -92,7 +93,11 @@ module GreenHat
|
|
92
93
|
end
|
93
94
|
|
94
95
|
def self.dir
|
95
|
-
"#{
|
96
|
+
"#{Dir.home}/.greenhat"
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.reports_dir
|
100
|
+
"#{dir}/reports"
|
96
101
|
end
|
97
102
|
|
98
103
|
# ----------------------------------
|
data/lib/greenhat/shell/args.rb
CHANGED
@@ -70,11 +70,18 @@ module GreenHat
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
+
# Arguments that Accept multiple options / Comma Delimted
|
74
|
+
def self.arg_special_split
|
75
|
+
%i[
|
76
|
+
slice except uniq pluck sort archive stats exists transform
|
77
|
+
]
|
78
|
+
end
|
79
|
+
|
73
80
|
# Flags Anything that isn't sent as a key/filter
|
74
81
|
def self.arg_to_flag_list
|
75
82
|
%i[
|
76
|
-
archive end except exists json limit pluck reverse round slice sort start
|
77
|
-
stats truncate uniq page time_zone table_style
|
83
|
+
archive end except exists json limit pluck reverse round slice sort start total
|
84
|
+
stats truncate uniq page time_zone table_style percentile interval percentile transform
|
78
85
|
]
|
79
86
|
end
|
80
87
|
|
@@ -136,13 +143,6 @@ module GreenHat
|
|
136
143
|
end
|
137
144
|
end
|
138
145
|
|
139
|
-
# Arguments that Accept multiple options / Comma Delimted
|
140
|
-
def self.arg_special_split
|
141
|
-
%i[
|
142
|
-
slice except uniq pluck sort archive stats exists
|
143
|
-
]
|
144
|
-
end
|
145
|
-
|
146
146
|
# Arg Defaults
|
147
147
|
def self.flag_arg_defaults(field)
|
148
148
|
case field
|
@@ -3,7 +3,7 @@ module GreenHat
|
|
3
3
|
# Helper to colorize and make outtput easier to read
|
4
4
|
module StringColor
|
5
5
|
def self.do(key, entry)
|
6
|
-
LogBot.debug('Unknown Format', entry.class) if ENV
|
6
|
+
LogBot.debug('Unknown Format', entry.class) if ENV.fetch('DEBUG', nil) && !entry.instance_of?(String)
|
7
7
|
|
8
8
|
# Other Helpful colorizers
|
9
9
|
if pastel?(key)
|
@@ -100,6 +100,13 @@ module GreenHat
|
|
100
100
|
puts "- #{log.name.pastel(:yellow)}"
|
101
101
|
end
|
102
102
|
end
|
103
|
+
|
104
|
+
return unless all
|
105
|
+
|
106
|
+
puts "\n#{'Other / Unknown'.pastel(:red)}"
|
107
|
+
(Thing.all - files).each do |file|
|
108
|
+
puts "- #{file.name.pastel(:yellow)}"
|
109
|
+
end
|
103
110
|
end
|
104
111
|
|
105
112
|
def self.ls(args = [])
|
@@ -117,15 +124,23 @@ module GreenHat
|
|
117
124
|
|
118
125
|
LogBot.debug('FastStats CMD', cmd) if ENV['DEBUG']
|
119
126
|
|
127
|
+
# binding.pry
|
128
|
+
|
129
|
+
# Ignore Unknown Errors
|
120
130
|
results = ShellHelper.file_process(files) do |file|
|
131
|
+
output = `fast-stats #{cmd} #{file.file} 2>&1`
|
132
|
+
result = $CHILD_STATUS.success?
|
133
|
+
|
134
|
+
next unless result
|
135
|
+
|
121
136
|
[
|
122
137
|
file.friendly_name,
|
123
|
-
|
138
|
+
output.split("\n"),
|
124
139
|
"\n"
|
125
140
|
]
|
126
141
|
end
|
127
142
|
|
128
|
-
ShellHelper.show(results.flatten, flags)
|
143
|
+
ShellHelper.show(results.compact.flatten, flags)
|
129
144
|
end
|
130
145
|
|
131
146
|
# ========================================================================
|
@@ -219,11 +234,15 @@ module GreenHat
|
|
219
234
|
end
|
220
235
|
end.join(' ')
|
221
236
|
|
222
|
-
# Prepare Log List
|
223
|
-
file_list =
|
237
|
+
# Prepare Log List / Allow attempting of parsing everything
|
238
|
+
file_list = if file_list == ['*']
|
239
|
+
Thing.all.map(&:name)
|
240
|
+
else
|
241
|
+
ShellHelper.prepare_list(file_list, ShellHelper::Faststats.things)
|
242
|
+
end
|
224
243
|
|
225
244
|
# Convert to Things
|
226
|
-
files = ShellHelper.find_things(file_list)
|
245
|
+
files = ShellHelper.find_things(file_list, fuzzy_file_match: true)
|
227
246
|
|
228
247
|
[files, flags, cmd]
|
229
248
|
end
|