greenhat 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|