greenhat 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +64 -0
  3. data/bin/greenhat +12 -0
  4. data/lib/greenhat.rb +80 -0
  5. data/lib/greenhat/accessors/disk.rb +27 -0
  6. data/lib/greenhat/accessors/logs/production.rb +41 -0
  7. data/lib/greenhat/accessors/logs/sidekiq.rb +41 -0
  8. data/lib/greenhat/accessors/memory.rb +46 -0
  9. data/lib/greenhat/accessors/network.rb +8 -0
  10. data/lib/greenhat/accessors/process.rb +8 -0
  11. data/lib/greenhat/archive.rb +108 -0
  12. data/lib/greenhat/cli.rb +448 -0
  13. data/lib/greenhat/host.rb +182 -0
  14. data/lib/greenhat/logbot.rb +86 -0
  15. data/lib/greenhat/pry_helpers.rb +51 -0
  16. data/lib/greenhat/settings.rb +51 -0
  17. data/lib/greenhat/shell.rb +92 -0
  18. data/lib/greenhat/shell/cat.rb +125 -0
  19. data/lib/greenhat/shell/disk.rb +68 -0
  20. data/lib/greenhat/shell/faststats.rb +195 -0
  21. data/lib/greenhat/shell/gitlab.rb +45 -0
  22. data/lib/greenhat/shell/help.rb +15 -0
  23. data/lib/greenhat/shell/helper.rb +514 -0
  24. data/lib/greenhat/shell/log.rb +344 -0
  25. data/lib/greenhat/shell/memory.rb +31 -0
  26. data/lib/greenhat/shell/network.rb +12 -0
  27. data/lib/greenhat/shell/process.rb +12 -0
  28. data/lib/greenhat/shell/report.rb +319 -0
  29. data/lib/greenhat/thing.rb +121 -0
  30. data/lib/greenhat/thing/file_types.rb +705 -0
  31. data/lib/greenhat/thing/formatters/api_json.rb +34 -0
  32. data/lib/greenhat/thing/formatters/bracket_log.rb +44 -0
  33. data/lib/greenhat/thing/formatters/clean_raw.rb +23 -0
  34. data/lib/greenhat/thing/formatters/colon_split_strip.rb +12 -0
  35. data/lib/greenhat/thing/formatters/dotenv.rb +10 -0
  36. data/lib/greenhat/thing/formatters/format.rb +12 -0
  37. data/lib/greenhat/thing/formatters/free_m.rb +29 -0
  38. data/lib/greenhat/thing/formatters/gitlab_ctl_tail.rb +51 -0
  39. data/lib/greenhat/thing/formatters/gitlab_status.rb +26 -0
  40. data/lib/greenhat/thing/formatters/json.rb +63 -0
  41. data/lib/greenhat/thing/formatters/json_shellwords.rb +44 -0
  42. data/lib/greenhat/thing/formatters/multiline_json.rb +10 -0
  43. data/lib/greenhat/thing/formatters/raw.rb +18 -0
  44. data/lib/greenhat/thing/formatters/shellwords.rb +23 -0
  45. data/lib/greenhat/thing/formatters/table.rb +26 -0
  46. data/lib/greenhat/thing/formatters/time_json.rb +21 -0
  47. data/lib/greenhat/thing/formatters/time_shellwords.rb +28 -0
  48. data/lib/greenhat/thing/formatters/time_space.rb +36 -0
  49. data/lib/greenhat/thing/helpers.rb +71 -0
  50. data/lib/greenhat/thing/history.rb +51 -0
  51. data/lib/greenhat/thing/info_format.rb +193 -0
  52. data/lib/greenhat/thing/kind.rb +97 -0
  53. data/lib/greenhat/thing/spinner.rb +52 -0
  54. data/lib/greenhat/thing/super_log.rb +102 -0
  55. data/lib/greenhat/tty/custom_line.rb +29 -0
  56. data/lib/greenhat/tty/line.rb +326 -0
  57. data/lib/greenhat/tty/reader.rb +110 -0
  58. data/lib/greenhat/version.rb +3 -0
  59. data/lib/greenhat/views/css.slim +126 -0
  60. data/lib/greenhat/views/disk_free.slim +18 -0
  61. data/lib/greenhat/views/index.slim +51 -0
  62. data/lib/greenhat/views/info.slim +39 -0
  63. data/lib/greenhat/views/manifest.slim +22 -0
  64. data/lib/greenhat/views/memory.slim +18 -0
  65. data/lib/greenhat/views/netstat.slim +20 -0
  66. data/lib/greenhat/views/process.slim +21 -0
  67. data/lib/greenhat/views/systemctl.slim +40 -0
  68. data/lib/greenhat/views/ulimit.slim +15 -0
  69. data/lib/greenhat/web.rb +46 -0
  70. 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,12 @@
1
+ # Top
2
+ module GreenHat
3
+ # Log
4
+ module Formatters
5
+ # Formatters for single json blobs in entire file
6
+ def format_colon_split_strip
7
+ self.result = raw.map do |row|
8
+ row.split(':', 2).map(&:strip)
9
+ end.to_h
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ # Top
2
+ module GreenHat
3
+ # Log
4
+ module Formatters
5
+ # Formatters for Dmesg
6
+ def format_dotenv
7
+ self.result = Dotenv::Parser.new(raw.join("\n")).call
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ module GreenHat
2
+ # Formatter
3
+ module Formatters
4
+ def log_format
5
+ self.result = send(SuperLog.type?(path)) if log_type
6
+ end
7
+
8
+ def log_type
9
+ SuperLog.type?(path)
10
+ end
11
+ end
12
+ 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,10 @@
1
+ # Top
2
+ module GreenHat
3
+ # Log
4
+ module Formatters
5
+ # Formatters for single json blobs in entire file
6
+ def format_multiline_json
7
+ self.result = Oj.load raw.join
8
+ end
9
+ end
10
+ 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