greenhat 0.1.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 +7 -0
- data/README.md +64 -0
- data/bin/greenhat +12 -0
- data/lib/greenhat.rb +80 -0
- data/lib/greenhat/accessors/disk.rb +27 -0
- data/lib/greenhat/accessors/logs/production.rb +41 -0
- data/lib/greenhat/accessors/logs/sidekiq.rb +41 -0
- data/lib/greenhat/accessors/memory.rb +46 -0
- data/lib/greenhat/accessors/network.rb +8 -0
- data/lib/greenhat/accessors/process.rb +8 -0
- data/lib/greenhat/archive.rb +108 -0
- data/lib/greenhat/cli.rb +448 -0
- data/lib/greenhat/host.rb +182 -0
- data/lib/greenhat/logbot.rb +86 -0
- data/lib/greenhat/pry_helpers.rb +51 -0
- data/lib/greenhat/settings.rb +51 -0
- data/lib/greenhat/shell.rb +92 -0
- data/lib/greenhat/shell/cat.rb +125 -0
- data/lib/greenhat/shell/disk.rb +68 -0
- data/lib/greenhat/shell/faststats.rb +195 -0
- data/lib/greenhat/shell/gitlab.rb +45 -0
- data/lib/greenhat/shell/help.rb +15 -0
- data/lib/greenhat/shell/helper.rb +514 -0
- data/lib/greenhat/shell/log.rb +344 -0
- data/lib/greenhat/shell/memory.rb +31 -0
- data/lib/greenhat/shell/network.rb +12 -0
- data/lib/greenhat/shell/process.rb +12 -0
- data/lib/greenhat/shell/report.rb +319 -0
- data/lib/greenhat/thing.rb +121 -0
- data/lib/greenhat/thing/file_types.rb +705 -0
- data/lib/greenhat/thing/formatters/api_json.rb +34 -0
- data/lib/greenhat/thing/formatters/bracket_log.rb +44 -0
- data/lib/greenhat/thing/formatters/clean_raw.rb +23 -0
- data/lib/greenhat/thing/formatters/colon_split_strip.rb +12 -0
- data/lib/greenhat/thing/formatters/dotenv.rb +10 -0
- data/lib/greenhat/thing/formatters/format.rb +12 -0
- data/lib/greenhat/thing/formatters/free_m.rb +29 -0
- data/lib/greenhat/thing/formatters/gitlab_ctl_tail.rb +51 -0
- data/lib/greenhat/thing/formatters/gitlab_status.rb +26 -0
- data/lib/greenhat/thing/formatters/json.rb +63 -0
- data/lib/greenhat/thing/formatters/json_shellwords.rb +44 -0
- data/lib/greenhat/thing/formatters/multiline_json.rb +10 -0
- data/lib/greenhat/thing/formatters/raw.rb +18 -0
- data/lib/greenhat/thing/formatters/shellwords.rb +23 -0
- data/lib/greenhat/thing/formatters/table.rb +26 -0
- data/lib/greenhat/thing/formatters/time_json.rb +21 -0
- data/lib/greenhat/thing/formatters/time_shellwords.rb +28 -0
- data/lib/greenhat/thing/formatters/time_space.rb +36 -0
- data/lib/greenhat/thing/helpers.rb +71 -0
- data/lib/greenhat/thing/history.rb +51 -0
- data/lib/greenhat/thing/info_format.rb +193 -0
- data/lib/greenhat/thing/kind.rb +97 -0
- data/lib/greenhat/thing/spinner.rb +52 -0
- data/lib/greenhat/thing/super_log.rb +102 -0
- data/lib/greenhat/tty/custom_line.rb +29 -0
- data/lib/greenhat/tty/line.rb +326 -0
- data/lib/greenhat/tty/reader.rb +110 -0
- data/lib/greenhat/version.rb +3 -0
- data/lib/greenhat/views/css.slim +126 -0
- data/lib/greenhat/views/disk_free.slim +18 -0
- data/lib/greenhat/views/index.slim +51 -0
- data/lib/greenhat/views/info.slim +39 -0
- data/lib/greenhat/views/manifest.slim +22 -0
- data/lib/greenhat/views/memory.slim +18 -0
- data/lib/greenhat/views/netstat.slim +20 -0
- data/lib/greenhat/views/process.slim +21 -0
- data/lib/greenhat/views/systemctl.slim +40 -0
- data/lib/greenhat/views/ulimit.slim +15 -0
- data/lib/greenhat/web.rb +46 -0
- metadata +476 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
# Top
|
2
|
+
module GreenHat
|
3
|
+
# Log
|
4
|
+
module Formatters
|
5
|
+
# ==========================================================================
|
6
|
+
# Formatters
|
7
|
+
# ==========================================================================
|
8
|
+
# Primarily for gitlab-rails/api_json.log
|
9
|
+
def format_api_json
|
10
|
+
self.result = raw.map do |row|
|
11
|
+
result = Oj.load row
|
12
|
+
|
13
|
+
# Parsing Time
|
14
|
+
format_json_traverse result
|
15
|
+
|
16
|
+
flatten_hash(result).sort.to_h
|
17
|
+
rescue StandardError => e
|
18
|
+
# TODO: Background Logger?
|
19
|
+
e.message
|
20
|
+
LogBot.warn('JSON Parse', e.message)
|
21
|
+
next
|
22
|
+
end
|
23
|
+
|
24
|
+
:ok
|
25
|
+
end
|
26
|
+
|
27
|
+
def flatten_hash(param, prefix = nil)
|
28
|
+
param.each_pair.reduce({}) do |a, (k, v)|
|
29
|
+
v.is_a?(Hash) ? a.merge(flatten_hash(v, "#{prefix}#{k}.")) : a.merge("#{prefix}#{k}".to_sym => v)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
# ==========================================================================
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Top
|
2
|
+
module GreenHat
|
3
|
+
# Log
|
4
|
+
module Formatters
|
5
|
+
# Formatters for bracket logs (dmesg, sos)
|
6
|
+
def format_bracket_log
|
7
|
+
self.result = raw.map do |row|
|
8
|
+
next if row.empty? || row == "\n"
|
9
|
+
|
10
|
+
result = {}
|
11
|
+
time, output = row.split(']', 2)
|
12
|
+
result[:time] = Time.parse time.split('[', 2).last.strip
|
13
|
+
|
14
|
+
if output.include? ': '
|
15
|
+
category, raw = output.split(': ', 2)
|
16
|
+
result[:category] = category.strip
|
17
|
+
|
18
|
+
result.merge! dmesg_split(raw) if raw.include? '='
|
19
|
+
|
20
|
+
result[:message] = raw.strip
|
21
|
+
else
|
22
|
+
result[:message] = output
|
23
|
+
end
|
24
|
+
|
25
|
+
result
|
26
|
+
rescue StandardError => e
|
27
|
+
# TODO: Background logger
|
28
|
+
LogBot.fatal('dmesg', "Unable to Parse, #{row}:#{e.message}")
|
29
|
+
end
|
30
|
+
|
31
|
+
self.result.compact!
|
32
|
+
end
|
33
|
+
|
34
|
+
def dmesg_split(raw)
|
35
|
+
Shellwords.split(raw).each_with_object({}) do |x, h|
|
36
|
+
key, value = x.split('=')
|
37
|
+
next if value.nil?
|
38
|
+
|
39
|
+
h[key] = value.numeric? ? value.to_f : value
|
40
|
+
h[key] = 0.0 if h[key].numeric? && h[key].zero?
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Top
|
2
|
+
module GreenHat
|
3
|
+
# Log
|
4
|
+
module Formatters
|
5
|
+
# Remove Comments / Empty Lines
|
6
|
+
def format_clean_raw
|
7
|
+
staging = raw.clone
|
8
|
+
|
9
|
+
# Empty
|
10
|
+
staging.reject!(&:empty?)
|
11
|
+
|
12
|
+
# Commented
|
13
|
+
staging.reject! { |x| x =~ /#.*$/ }
|
14
|
+
|
15
|
+
self.result = if staging.empty?
|
16
|
+
raw
|
17
|
+
else
|
18
|
+
staging
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
# ----------------------------------------
|
23
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Top
|
2
|
+
module GreenHat
|
3
|
+
# Log
|
4
|
+
module Formatters
|
5
|
+
# Get Split Memory Table
|
6
|
+
def format_free_m
|
7
|
+
# Headers to Readable Symbol
|
8
|
+
headers = raw.first.split(' ', 6).map(&:downcase).map do |x|
|
9
|
+
x.gsub(/\s+/, '_').gsub(/[^0-9A-Za-z_]/, '')
|
10
|
+
end.map(&:to_sym)
|
11
|
+
|
12
|
+
# Add Kind
|
13
|
+
headers.unshift(:kind)
|
14
|
+
|
15
|
+
final = []
|
16
|
+
|
17
|
+
# Put fields into a Hash based on Location/Key
|
18
|
+
raw[1..].map(&:split).each do |row|
|
19
|
+
result = {}
|
20
|
+
row.each_with_index do |detail, i|
|
21
|
+
result[headers[i]] = detail.split(':').first
|
22
|
+
end
|
23
|
+
final.push result
|
24
|
+
end
|
25
|
+
|
26
|
+
self.result = final
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Top
|
2
|
+
module GreenHat
|
3
|
+
# Log
|
4
|
+
module Formatters
|
5
|
+
# ==========================================================================
|
6
|
+
# Gitlab Tail Formatter
|
7
|
+
# ==========================================================================
|
8
|
+
def format_gitlab_tail
|
9
|
+
# Revert to raw for cats
|
10
|
+
self.kind = :raw
|
11
|
+
|
12
|
+
output = {}
|
13
|
+
current_log = nil
|
14
|
+
|
15
|
+
raw.each do |line|
|
16
|
+
next if line.blank?
|
17
|
+
|
18
|
+
if line.include? '==>'
|
19
|
+
current_log = /==> (.+?) <==/.match(line).captures.first
|
20
|
+
else
|
21
|
+
output[current_log] ||= []
|
22
|
+
output[current_log].push line
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Remove Empty Entries
|
27
|
+
output.reject { |_k, v| v.empty? }
|
28
|
+
|
29
|
+
# Root Dir
|
30
|
+
root_dir = "#{$TMP}/#{name}"
|
31
|
+
Dir.mkdir(root_dir)
|
32
|
+
|
33
|
+
# Write Files / Create Things
|
34
|
+
output.each do |k, v|
|
35
|
+
file_name = k.gsub('/var/log/gitlab/', '')
|
36
|
+
|
37
|
+
dir = "#{root_dir}/#{file_name.split('/').first}"
|
38
|
+
Dir.mkdir(dir) unless File.exist?(dir)
|
39
|
+
|
40
|
+
File.write("#{root_dir}/#{file_name}", v.join("\n"))
|
41
|
+
|
42
|
+
# Thing Setup
|
43
|
+
archive.things_create(file: "#{root_dir}/#{file_name}").setup
|
44
|
+
end
|
45
|
+
|
46
|
+
# Link
|
47
|
+
self.result = raw
|
48
|
+
end
|
49
|
+
# ==========================================================================
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Top
|
2
|
+
module GreenHat
|
3
|
+
# Log
|
4
|
+
module Formatters
|
5
|
+
# Remove Comments / Empty Lines
|
6
|
+
def format_gitlab_status
|
7
|
+
final = {}
|
8
|
+
raw.each do |row|
|
9
|
+
list = row.split('; ').map do |entry|
|
10
|
+
status, service, pid_uptime = entry.split(': ')
|
11
|
+
|
12
|
+
{
|
13
|
+
status: status,
|
14
|
+
name: service,
|
15
|
+
pid_uptime: pid_uptime
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
final[list.first.name] = list
|
20
|
+
end
|
21
|
+
|
22
|
+
self.result = final
|
23
|
+
end
|
24
|
+
end
|
25
|
+
# ----------------------------------------
|
26
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# Top
|
2
|
+
module GreenHat
|
3
|
+
# Log
|
4
|
+
module Formatters
|
5
|
+
# ==========================================================================
|
6
|
+
# Formatters
|
7
|
+
# Fallback to String
|
8
|
+
# ==========================================================================
|
9
|
+
def format_json
|
10
|
+
self.result = raw.map do |row|
|
11
|
+
result = begin
|
12
|
+
Oj.load row
|
13
|
+
rescue EncodingError
|
14
|
+
{ message: row }
|
15
|
+
end
|
16
|
+
|
17
|
+
# Parsing Time
|
18
|
+
format_json_traverse result
|
19
|
+
|
20
|
+
result.sort.to_h
|
21
|
+
rescue StandardError => e
|
22
|
+
# TODO: Background Logger?
|
23
|
+
e.message
|
24
|
+
LogBot.warn('JSON Parse', e.message)
|
25
|
+
next
|
26
|
+
end
|
27
|
+
|
28
|
+
:ok
|
29
|
+
end
|
30
|
+
# ==========================================================================
|
31
|
+
|
32
|
+
# Recursively Navigate
|
33
|
+
def format_json_traverse(result)
|
34
|
+
format_json_time(result)
|
35
|
+
|
36
|
+
result.each do |_key, value|
|
37
|
+
next unless value.instance_of? Hash
|
38
|
+
|
39
|
+
format_json_traverse(value)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Check for Common Fields
|
44
|
+
def format_json_time(result)
|
45
|
+
result.time = format_time_parse(result.time) if result.key? :time
|
46
|
+
result.created_at = format_time_parse(result.created_at) if result.key? :created_at
|
47
|
+
result.enqueued_at = format_time_parse(result.enqueued_at) if result.key? :enqueued_at
|
48
|
+
rescue StandardError => e
|
49
|
+
LogBot.warn('JSON Time Parse', e.message)
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
# Handle Epoch Timestamps as well as string timestamps
|
54
|
+
def format_time_parse(time)
|
55
|
+
if time.numeric?
|
56
|
+
Time.at time
|
57
|
+
else
|
58
|
+
Time.parse time
|
59
|
+
end
|
60
|
+
end
|
61
|
+
# ---
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Top
|
2
|
+
module GreenHat
|
3
|
+
# Log
|
4
|
+
module Formatters
|
5
|
+
# ==========================================================================
|
6
|
+
# Formatters
|
7
|
+
# ==========================================================================
|
8
|
+
def format_json_shell
|
9
|
+
self.result = raw.map do |row|
|
10
|
+
result = begin
|
11
|
+
Oj.load row
|
12
|
+
rescue EncodingError
|
13
|
+
json_shellwords_fallback row
|
14
|
+
end
|
15
|
+
|
16
|
+
# Parsing Time
|
17
|
+
format_json_traverse result
|
18
|
+
|
19
|
+
result.sort.to_h
|
20
|
+
rescue StandardError => e
|
21
|
+
binding.pry
|
22
|
+
# TODO: Background Logger?
|
23
|
+
e.message
|
24
|
+
LogBot.warn('JSON Parse', e.message)
|
25
|
+
next
|
26
|
+
end
|
27
|
+
|
28
|
+
:ok
|
29
|
+
end
|
30
|
+
|
31
|
+
def json_shellwords_fallback(row)
|
32
|
+
result = Shellwords.split(row).each_with_object({}) do |x, h|
|
33
|
+
key, value = x.split('=')
|
34
|
+
next if value.nil?
|
35
|
+
|
36
|
+
h[key] = value.numeric? ? value.to_f : value
|
37
|
+
end
|
38
|
+
result.time = Time.parse result.time if result.key? 'time'
|
39
|
+
|
40
|
+
result
|
41
|
+
end
|
42
|
+
# ==========================================================================
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Top
|
2
|
+
module GreenHat
|
3
|
+
# Log
|
4
|
+
module Formatters
|
5
|
+
# ==========================================================================
|
6
|
+
# Formatters Not Handled
|
7
|
+
# ==========================================================================
|
8
|
+
def mia
|
9
|
+
# TODO: Background Logger
|
10
|
+
LogBot.warn('Log Format', "No Formatter for #{name}::#{path}")
|
11
|
+
end
|
12
|
+
|
13
|
+
def format_raw
|
14
|
+
self.result = raw
|
15
|
+
end
|
16
|
+
# ==========================================================================
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Top
|
2
|
+
module GreenHat
|
3
|
+
# Log
|
4
|
+
module Formatters
|
5
|
+
# ==========================================================================
|
6
|
+
# Formatters Not Handled
|
7
|
+
# ==========================================================================
|
8
|
+
def format_shellwords
|
9
|
+
self.result = raw.map do |row|
|
10
|
+
result = Shellwords.split(row).each_with_object({}) do |x, h|
|
11
|
+
key, value = x.split('=')
|
12
|
+
next if value.nil?
|
13
|
+
|
14
|
+
h[key] = value.numeric? ? value.to_f : value
|
15
|
+
end
|
16
|
+
result.time = Time.parse result.time if result.key? 'time'
|
17
|
+
|
18
|
+
result
|
19
|
+
end
|
20
|
+
end
|
21
|
+
# ==========================================================================
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Top
|
2
|
+
module GreenHat
|
3
|
+
# Log
|
4
|
+
module Formatters
|
5
|
+
# Formatters for Dmesg
|
6
|
+
def format_table
|
7
|
+
# Headers to Readable Symbol
|
8
|
+
headers = raw.first.split(' ', 6).map(&:downcase).map do |x|
|
9
|
+
x.gsub(/\s+/, '_').gsub(/[^0-9A-Za-z_]/, '')
|
10
|
+
end.map(&:to_sym)
|
11
|
+
|
12
|
+
final = []
|
13
|
+
|
14
|
+
# Put fields into a Hash based on Location/Key
|
15
|
+
raw[1..].map(&:split).each do |row|
|
16
|
+
result = {}
|
17
|
+
row.each_with_index do |detail, i|
|
18
|
+
result[headers[i]] = detail
|
19
|
+
end
|
20
|
+
final.push result
|
21
|
+
end
|
22
|
+
|
23
|
+
self.result = final
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|