greenhat 0.3.4 → 0.5.0
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/bin/greenhat +2 -6
- data/lib/greenhat/accessors/disk.rb +1 -3
- data/lib/greenhat/accessors/gitlab.rb +7 -2
- data/lib/greenhat/accessors/memory.rb +1 -1
- data/lib/greenhat/archive.rb +19 -8
- data/lib/greenhat/cli.rb +35 -135
- data/lib/greenhat/entrypoint.rb +170 -0
- data/lib/greenhat/host.rb +25 -37
- data/lib/greenhat/settings.rb +33 -5
- data/lib/greenhat/shell/args.rb +22 -9
- data/lib/greenhat/shell/faststats.rb +23 -3
- data/lib/greenhat/shell/field_helper.rb +1 -1
- data/lib/greenhat/shell/filter_help.rb +217 -162
- data/lib/greenhat/shell/gitlab.rb +1 -0
- data/lib/greenhat/shell/log.rb +150 -25
- data/lib/greenhat/shell/markdown.rb +21 -25
- data/lib/greenhat/shell/old_search_helper.rb +54 -0
- data/lib/greenhat/shell/page.rb +1 -1
- data/lib/greenhat/shell/pipe.rb +31 -0
- data/lib/greenhat/shell/platform.rb +28 -0
- data/lib/greenhat/shell/query.rb +378 -0
- data/lib/greenhat/shell/report.rb +76 -24
- data/lib/greenhat/shell/shell_helper.rb +42 -393
- data/lib/greenhat/shell.rb +19 -4
- data/lib/greenhat/thing/file_types.rb +51 -1
- data/lib/greenhat/thing/formatters/api_json.rb +4 -2
- data/lib/greenhat/thing/formatters/bracket_log.rb +1 -1
- data/lib/greenhat/thing/formatters/colon_split_strip.rb +2 -2
- data/lib/greenhat/thing/formatters/dotenv.rb +1 -1
- data/lib/greenhat/thing/formatters/format.rb +0 -11
- data/lib/greenhat/thing/formatters/free_m.rb +2 -2
- data/lib/greenhat/thing/formatters/json.rb +43 -15
- data/lib/greenhat/thing/formatters/json_shellwords.rb +3 -2
- data/lib/greenhat/thing/formatters/kube_json.rb +3 -2
- data/lib/greenhat/thing/formatters/multiline_json.rb +1 -1
- data/lib/greenhat/thing/formatters/nginx.rb +11 -3
- data/lib/greenhat/thing/formatters/table.rb +3 -3
- data/lib/greenhat/thing/formatters/time_space.rb +0 -16
- data/lib/greenhat/thing/helpers.rb +12 -11
- data/lib/greenhat/thing/info_format.rb +4 -4
- data/lib/greenhat/thing/kind.rb +5 -0
- data/lib/greenhat/thing/super_log.rb +0 -101
- data/lib/greenhat/thing.rb +31 -25
- data/lib/greenhat/version.rb +1 -1
- data/lib/greenhat/views/api.slim +55 -0
- data/lib/greenhat/views/chart.slim +42 -0
- data/lib/greenhat/views/chart_template.slim +31 -0
- data/lib/greenhat/views/chartkick.js +21 -0
- data/lib/greenhat/views/css.slim +47 -0
- data/lib/greenhat/views/gitaly.slim +53 -0
- data/lib/greenhat/views/headers.slim +16 -0
- data/lib/greenhat/views/index-old.slim +51 -0
- data/lib/greenhat/views/index.slim +14 -14
- data/lib/greenhat/views/info.slim +17 -18
- data/lib/greenhat/views/production.slim +55 -0
- data/lib/greenhat/views/sidekiq.slim +55 -0
- data/lib/greenhat/views/time.slim +63 -0
- data/lib/greenhat/views/workhorse.slim +16 -0
- data/lib/greenhat/web/api.rb +94 -0
- data/lib/greenhat/web/chartkick_shim.rb +14 -0
- data/lib/greenhat/web/faststats.rb +44 -0
- data/lib/greenhat/web/gitaly.rb +65 -0
- data/lib/greenhat/web/helpers.rb +198 -0
- data/lib/greenhat/web/production.rb +104 -0
- data/lib/greenhat/web/sidekiq.rb +73 -0
- data/lib/greenhat/web/stats_helpers.rb +74 -0
- data/lib/greenhat/web/time.rb +36 -0
- data/lib/greenhat/web/workhorse.rb +43 -0
- data/lib/greenhat/web.rb +63 -19
- data/lib/greenhat.rb +2 -0
- metadata +74 -5
@@ -11,9 +11,10 @@ module GreenHat
|
|
11
11
|
result = Oj.load row
|
12
12
|
|
13
13
|
# Parsing Time
|
14
|
-
|
14
|
+
format_time(result)
|
15
15
|
|
16
|
-
flatten_hash(result).sort.to_h
|
16
|
+
# flatten_hash(result).sort.to_h
|
17
|
+
result
|
17
18
|
rescue StandardError => e
|
18
19
|
# TODO: Background Logger?
|
19
20
|
e.message
|
@@ -29,6 +30,7 @@ module GreenHat
|
|
29
30
|
v.is_a?(Hash) ? a.merge(flatten_hash(v, "#{prefix}#{k}.")) : a.merge("#{prefix}#{k}".to_sym => v)
|
30
31
|
end
|
31
32
|
end
|
33
|
+
|
32
34
|
# ==========================================================================
|
33
35
|
end
|
34
36
|
end
|
@@ -4,9 +4,9 @@ module GreenHat
|
|
4
4
|
module Formatters
|
5
5
|
# Formatters for single json blobs in entire file
|
6
6
|
def format_colon_split_strip
|
7
|
-
self.result =
|
7
|
+
self.result = raw_full.to_h do |row|
|
8
8
|
row.split(':', 2).map(&:strip)
|
9
|
-
end
|
9
|
+
end
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -5,7 +5,7 @@ module GreenHat
|
|
5
5
|
# Get Split Memory Table
|
6
6
|
def format_free_m
|
7
7
|
# Headers to Readable Symbol
|
8
|
-
headers =
|
8
|
+
headers = raw_full.first.split.map(&:downcase).map do |x|
|
9
9
|
x.gsub(/\s+/, '_').gsub(/[^0-9A-Za-z_]/, '')
|
10
10
|
end.map(&:to_sym)
|
11
11
|
|
@@ -15,7 +15,7 @@ module GreenHat
|
|
15
15
|
final = []
|
16
16
|
|
17
17
|
# Put fields into a Hash based on Location/Key
|
18
|
-
|
18
|
+
raw_full[1..].map(&:split).each do |row|
|
19
19
|
result = {}
|
20
20
|
row.each_with_index do |detail, i|
|
21
21
|
result[headers[i]] = detail.split(':').first
|
@@ -14,10 +14,10 @@ module GreenHat
|
|
14
14
|
{ message: row }
|
15
15
|
end
|
16
16
|
|
17
|
-
# Parsing Time
|
18
|
-
|
17
|
+
# Parsing Time / Recusrive is really slow
|
18
|
+
format_time(result)
|
19
19
|
|
20
|
-
result
|
20
|
+
result
|
21
21
|
rescue StandardError => e
|
22
22
|
# TODO: Background Logger?
|
23
23
|
e.message
|
@@ -27,11 +27,12 @@ module GreenHat
|
|
27
27
|
|
28
28
|
:ok
|
29
29
|
end
|
30
|
+
|
30
31
|
# ==========================================================================
|
31
32
|
|
32
|
-
# Recursively Navigate
|
33
|
+
# Recursively Navigate -- Recusrive is really slow
|
33
34
|
def format_json_traverse(result)
|
34
|
-
|
35
|
+
format_time(result)
|
35
36
|
|
36
37
|
result.each do |_key, value|
|
37
38
|
next unless value.instance_of? Hash
|
@@ -40,23 +41,50 @@ module GreenHat
|
|
40
41
|
end
|
41
42
|
end
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
44
|
+
def format_time_fields
|
45
|
+
%i[time timestamp created_at enqueued_at completed_at]
|
46
|
+
end
|
47
|
+
|
48
|
+
# Loop through potential fields and parse as needed
|
49
|
+
def format_time(result)
|
50
|
+
format_time_fields.each do |field|
|
51
|
+
result[field] = format_time_parse(result[field]) if result.key?(field)
|
52
|
+
rescue StandardError => e
|
53
|
+
LogBot.warn('JSON Format Time', e.message)
|
54
|
+
next
|
55
|
+
end
|
51
56
|
end
|
52
57
|
|
53
|
-
#
|
58
|
+
# Check for Common Fields
|
59
|
+
# def format_json_time(result)
|
60
|
+
# if result.key? :time
|
61
|
+
# result.time = format_time_parse(result.time)
|
62
|
+
# elsif result.key?(:timestamp)
|
63
|
+
# result.time = format_time_parse(result.timestamp)
|
64
|
+
# end
|
65
|
+
|
66
|
+
# result.created_at = format_time_parse(result.created_at) if result.key? :created_at
|
67
|
+
# result.enqueued_at = format_time_parse(result.enqueued_at) if result.key? :enqueued_at
|
68
|
+
# rescue StandardError => e
|
69
|
+
# LogBot.warn("JSON Time Parse", e.message)
|
70
|
+
# true
|
71
|
+
# end
|
72
|
+
|
54
73
|
def format_time_parse(time)
|
74
|
+
Time.parse time
|
75
|
+
rescue StandardError
|
76
|
+
# Handle Epoch Timestamps as well as string timestamps
|
77
|
+
format_time_numeric(time)
|
78
|
+
end
|
79
|
+
|
80
|
+
def format_time_numeric(time)
|
55
81
|
if time.numeric?
|
56
82
|
Time.at time
|
57
83
|
else
|
58
|
-
|
84
|
+
time
|
59
85
|
end
|
86
|
+
rescue StandardError => e
|
87
|
+
LogBot.warn('JSON Time Parse', e.message)
|
60
88
|
end
|
61
89
|
# ---
|
62
90
|
end
|
@@ -14,9 +14,9 @@ module GreenHat
|
|
14
14
|
end
|
15
15
|
|
16
16
|
# Parsing Time
|
17
|
-
|
17
|
+
format_time(result)
|
18
18
|
|
19
|
-
result
|
19
|
+
result
|
20
20
|
rescue StandardError => e
|
21
21
|
LogBot.warn('JSON Parse', e.message)
|
22
22
|
next
|
@@ -36,6 +36,7 @@ module GreenHat
|
|
36
36
|
|
37
37
|
result
|
38
38
|
end
|
39
|
+
|
39
40
|
# ==========================================================================
|
40
41
|
end
|
41
42
|
end
|
@@ -19,9 +19,9 @@ module GreenHat
|
|
19
19
|
end
|
20
20
|
|
21
21
|
# Parsing Time
|
22
|
-
|
22
|
+
format_time(result)
|
23
23
|
|
24
|
-
result
|
24
|
+
result
|
25
25
|
rescue StandardError => e
|
26
26
|
# TODO: Background Logger?
|
27
27
|
e.message
|
@@ -31,6 +31,7 @@ module GreenHat
|
|
31
31
|
|
32
32
|
:ok
|
33
33
|
end
|
34
|
+
|
34
35
|
# =========================================================================
|
35
36
|
end
|
36
37
|
end
|
@@ -6,11 +6,14 @@ module GreenHat
|
|
6
6
|
# Formatters
|
7
7
|
# ==========================================================================
|
8
8
|
def format_nginx
|
9
|
-
|
10
|
-
|
9
|
+
output = raw.map do |row|
|
10
|
+
next if row.chomp.empty?
|
11
|
+
|
12
|
+
conn_data, rest = row.split(' [', 2)
|
13
|
+
ip, _sym, remote_user = conn_data.split(' ', 3)
|
11
14
|
|
12
15
|
time, rest = rest.split(']', 2)
|
13
|
-
time = Time.strptime(time, '
|
16
|
+
time = Time.strptime(time, '%d/%b/%Y:%H:%M:%S %z')
|
14
17
|
|
15
18
|
verb, status, bytes, http_referer, http_user_agent, gzip_ratio = Shellwords.split(rest)
|
16
19
|
|
@@ -29,8 +32,13 @@ module GreenHat
|
|
29
32
|
gzip_ratio: gzip_ratio,
|
30
33
|
time: time
|
31
34
|
}
|
35
|
+
rescue StandardError => e
|
36
|
+
LogBot.warn('NGINX Parse', e.message)
|
37
|
+
{ msg: row }
|
32
38
|
end
|
33
39
|
|
40
|
+
# Remove Empty Entries
|
41
|
+
self.result = output.compact
|
34
42
|
:ok
|
35
43
|
end
|
36
44
|
|
@@ -2,17 +2,17 @@
|
|
2
2
|
module GreenHat
|
3
3
|
# Log
|
4
4
|
module Formatters
|
5
|
-
#
|
5
|
+
# Table Formatting
|
6
6
|
def format_table
|
7
7
|
# Headers to Readable Symbol
|
8
|
-
headers =
|
8
|
+
headers = raw_full.first.split(' ', 6).map(&:downcase).map do |x|
|
9
9
|
x.gsub(/\s+/, '_').gsub(/[^0-9A-Za-z_]/, '')
|
10
10
|
end.map(&:to_sym)
|
11
11
|
|
12
12
|
final = []
|
13
13
|
|
14
14
|
# Put fields into a Hash based on Location/Key
|
15
|
-
|
15
|
+
raw_full.map(&:split)[1..].each do |row|
|
16
16
|
result = {}
|
17
17
|
row.each_with_index do |detail, i|
|
18
18
|
result[headers[i]] = detail
|
@@ -18,19 +18,3 @@ module GreenHat
|
|
18
18
|
# ==========================================================================
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
22
|
-
# def time_space
|
23
|
-
# IO.foreach(file) do |row|
|
24
|
-
# time, msg = row.split(' ', 2)
|
25
|
-
# result = {
|
26
|
-
# time: parse_datetime(time), msg: msg, host: thing.host,
|
27
|
-
# source: path_format
|
28
|
-
# }
|
29
|
-
|
30
|
-
# result[:time] ||= datetime
|
31
|
-
# post result
|
32
|
-
# rescue StandardError => e
|
33
|
-
# puts "Unable to Parse, #{name}:#{e.message}"
|
34
|
-
# post(time: datetime, msg: row, source: path_format, host: thing.host)
|
35
|
-
# end
|
36
|
-
# end
|
@@ -25,17 +25,6 @@ module GreenHat
|
|
25
25
|
tmp_path.split('/').last(2).join(divider)
|
26
26
|
end
|
27
27
|
end
|
28
|
-
|
29
|
-
# Check what kind of file we have
|
30
|
-
def type_check
|
31
|
-
if info?
|
32
|
-
:info
|
33
|
-
elsif SuperLog.type?(path)
|
34
|
-
:log
|
35
|
-
else
|
36
|
-
:raw
|
37
|
-
end
|
38
|
-
end
|
39
28
|
end
|
40
29
|
end
|
41
30
|
|
@@ -69,3 +58,15 @@ class FalseClass
|
|
69
58
|
0
|
70
59
|
end
|
71
60
|
end
|
61
|
+
|
62
|
+
# https://stackoverflow.com/a/449322/1678507
|
63
|
+
class Time
|
64
|
+
# Time#round already exists with different meaning in Ruby 1.9
|
65
|
+
def round_off(seconds = 60)
|
66
|
+
Time.at((to_f / seconds).round * seconds).utc
|
67
|
+
end
|
68
|
+
|
69
|
+
def floor(seconds = 60)
|
70
|
+
Time.at((to_f / seconds).floor * seconds).utc
|
71
|
+
end
|
72
|
+
end
|
@@ -64,15 +64,15 @@ module GreenHat
|
|
64
64
|
conns, sockets = raw.split { |x| x.include? 'Active' }.reject(&:empty?)
|
65
65
|
|
66
66
|
formatted_conns = conns[1..].map do |entry|
|
67
|
-
entry.split(' ', 7).map(&:strip).each_with_index.
|
67
|
+
entry.split(' ', 7).map(&:strip).each_with_index.to_h do |field, idx|
|
68
68
|
[format_netstat_conn_headers[idx], field]
|
69
|
-
end
|
69
|
+
end
|
70
70
|
end
|
71
71
|
|
72
72
|
formatted_sockets = sockets[1..].map do |entry|
|
73
|
-
entry.split(' ').map(&:strip).reject(&:blank?).each_with_index.
|
73
|
+
entry.split(' ').map(&:strip).reject(&:blank?).each_with_index.to_h do |field, idx|
|
74
74
|
[format_netstat_socket_headers[idx], field]
|
75
|
-
end
|
75
|
+
end
|
76
76
|
end
|
77
77
|
|
78
78
|
{
|
data/lib/greenhat/thing/kind.rb
CHANGED
@@ -73,6 +73,11 @@ module GreenHat
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
+
if Settings.assume_raw?
|
77
|
+
self.type = 'raw'
|
78
|
+
return true
|
79
|
+
end
|
80
|
+
|
76
81
|
puts "Unable to determine file type for #{name.pastel(:yellow)}"
|
77
82
|
puts "Use '#{'json'.pastel(:cyan)}' or '#{'raw'.pastel(:cyan)}' if there are no matches (see file_types.rb)"
|
78
83
|
|
@@ -1,102 +1 @@
|
|
1
|
-
# TODO: Deprecate, was used specifically for Elk
|
2
|
-
# rubocop:disable /AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity, Metrics/
|
3
|
-
module GreenHat
|
4
|
-
# Log Identifier
|
5
|
-
module SuperLog
|
6
|
-
def self.log?(kind)
|
7
|
-
[
|
8
|
-
'gitaly/current',
|
9
|
-
'gitaly/gitaly_ruby_json.log',
|
10
|
-
'gitlab-rails/api_json.log',
|
11
|
-
'gitlab-rails/application_json.log',
|
12
|
-
'gitlab-rails/audit_json.log',
|
13
|
-
'gitlab-rails/graphql_json.log',
|
14
|
-
'gitlab-rails/integrations_json.log',
|
15
|
-
'gitlab-rails/production_json.log',
|
16
|
-
'gitlab-rails/sidekiq_client.log',
|
17
|
-
'gitlab-shell/gitlab-shell.log',
|
18
|
-
'gitlab-workhorse/current',
|
19
|
-
'puma/puma_stdout.log',
|
20
|
-
'sidekiq/current',
|
21
|
-
'gitlab-rails/importer.log',
|
22
|
-
'gitlabsos.log',
|
23
|
-
'nginx/gitlab_access.log',
|
24
|
-
'patroni/current'
|
25
|
-
].any? { |x| x.include? kind.to_s }
|
26
1
|
|
27
|
-
true
|
28
|
-
end
|
29
|
-
|
30
|
-
# ==========================================================================
|
31
|
-
# File Pattern Matching
|
32
|
-
# ==========================================================================
|
33
|
-
def self.api_json_format?(path)
|
34
|
-
['rails_api_json_log'].any? { |x| path.include? x }
|
35
|
-
end
|
36
|
-
|
37
|
-
def self.unicorn_stderr_format?(path)
|
38
|
-
%w[
|
39
|
-
unicorn_stderr
|
40
|
-
].any? { |x| path.include? x }
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.reconfigure_format?(path)
|
44
|
-
%w[
|
45
|
-
reconfigure
|
46
|
-
].any? { |x| path.include? x }
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.shellwords?(path)
|
50
|
-
%w[
|
51
|
-
gitlab_pages_current
|
52
|
-
alertmanager_current
|
53
|
-
registry_current
|
54
|
-
prometheus_current
|
55
|
-
|
56
|
-
].any? { |x| path.include? x }
|
57
|
-
end
|
58
|
-
|
59
|
-
def self.time_space?(path)
|
60
|
-
%w[
|
61
|
-
postgresql_current
|
62
|
-
redis_current
|
63
|
-
unicorn_current
|
64
|
-
gitlab_monitor_current
|
65
|
-
sidekiq_exporter_log
|
66
|
-
].any? { |x| path.include? x }
|
67
|
-
end
|
68
|
-
|
69
|
-
def self.json_format?(path)
|
70
|
-
%w[
|
71
|
-
production_json_log
|
72
|
-
gitaly_current
|
73
|
-
geo_log
|
74
|
-
sidekiq_current
|
75
|
-
sidekiq_log
|
76
|
-
gitlab_shell_gitlab_shell_log
|
77
|
-
gitlab_rails_audit_json_log
|
78
|
-
gitlab_rails_application_json_log
|
79
|
-
].any? { |x| path.include? x }
|
80
|
-
end
|
81
|
-
|
82
|
-
def self.dmesg_format?(path)
|
83
|
-
%w[
|
84
|
-
dmesg
|
85
|
-
].any? { |x| path.include? x }
|
86
|
-
end
|
87
|
-
# ==========================================================================
|
88
|
-
|
89
|
-
# Identify Formatter
|
90
|
-
def self.type?(path)
|
91
|
-
return :api_json_format if api_json_format?(path)
|
92
|
-
return :unicorn_stderr_format if unicorn_stderr_format?(path)
|
93
|
-
return :reconfigure_format if reconfigure_format?(path)
|
94
|
-
return :shellwords if shellwords?(path)
|
95
|
-
return :time_space if time_space?(path)
|
96
|
-
return :json_format if json_format?(path)
|
97
|
-
return :dmesg_format if dmesg_format?(path)
|
98
|
-
|
99
|
-
nil
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
data/lib/greenhat/thing.rb
CHANGED
@@ -24,8 +24,7 @@ class Thing < Teron
|
|
24
24
|
|
25
25
|
# Preloader Flags
|
26
26
|
field :parsed # Flag for Parsing
|
27
|
-
field :result # Processed Data
|
28
|
-
field :raw_result # Flag for reading raw data
|
27
|
+
field :result, dump: false # Processed Data
|
29
28
|
field :result_fields # All available fields
|
30
29
|
|
31
30
|
def friendly_name
|
@@ -57,10 +56,14 @@ class Thing < Teron
|
|
57
56
|
result_fields
|
58
57
|
end
|
59
58
|
|
59
|
+
# Readlines rather than putting whole thing into memory
|
60
60
|
def raw
|
61
|
-
|
61
|
+
File.foreach(file)
|
62
|
+
end
|
62
63
|
|
63
|
-
|
64
|
+
# Where full read is needed
|
65
|
+
def raw_full
|
66
|
+
File.read(file).split("\n")
|
64
67
|
end
|
65
68
|
|
66
69
|
# Filter / Archive Pattern Matching
|
@@ -73,32 +76,27 @@ class Thing < Teron
|
|
73
76
|
data.blank?
|
74
77
|
end
|
75
78
|
|
76
|
-
def raw_read
|
77
|
-
spin_start("Read #{name.pastel(:blue)} #{size.pastel(:bright_black)}")
|
78
|
-
self.raw_result = File.read(file).split("\n")
|
79
|
-
rescue StandardError => e
|
80
|
-
LogBot.fatal('Raw Read', message: e.message, backtrace: e.backtrace.first)
|
81
|
-
self.raw_result = ''
|
82
|
-
ensure
|
83
|
-
spin_done
|
84
|
-
end
|
85
|
-
|
86
79
|
def output(print_it = true)
|
87
80
|
if print_it
|
88
|
-
puts raw.
|
81
|
+
puts raw.map(&:to_s).map(&:chomp)
|
89
82
|
else
|
90
|
-
raw
|
83
|
+
raw.map(&:to_s).map(&:chomp)
|
91
84
|
end
|
92
85
|
end
|
93
86
|
|
94
|
-
#
|
95
|
-
def
|
96
|
-
|
87
|
+
# Hashed values searching
|
88
|
+
def process?
|
89
|
+
kind != :raw && methods.include?(formatter)
|
97
90
|
end
|
98
91
|
|
99
|
-
#
|
100
|
-
def
|
101
|
-
|
92
|
+
# Things that can be queried (Query Helper)
|
93
|
+
def query?
|
94
|
+
data.instance_of?(Array)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Helper for all things that can be hash/value filtered
|
98
|
+
def self.list
|
99
|
+
all.select.select(&:process?)
|
102
100
|
end
|
103
101
|
|
104
102
|
# Helper Formatter Method
|
@@ -107,9 +105,6 @@ class Thing < Teron
|
|
107
105
|
end
|
108
106
|
|
109
107
|
def process
|
110
|
-
# Read First if Needed (Spinner)
|
111
|
-
raw_read if raw_result.nil?
|
112
|
-
|
113
108
|
if methods.include? formatter
|
114
109
|
spin_start("Parse #{name.pastel(:blue)} #{kind.to_s.pastel(:bright_black)} ")
|
115
110
|
begin
|
@@ -140,4 +135,15 @@ class Thing < Teron
|
|
140
135
|
|
141
136
|
[]
|
142
137
|
end
|
138
|
+
|
139
|
+
def query_save(results, name)
|
140
|
+
self.archive = Archive.first
|
141
|
+
self.result = results
|
142
|
+
self.name = name
|
143
|
+
self.log = true
|
144
|
+
self.parsed = true
|
145
|
+
self.type = 'json'
|
146
|
+
self.result_fields = field_processing
|
147
|
+
save!
|
148
|
+
end
|
143
149
|
end
|
data/lib/greenhat/version.rb
CHANGED
@@ -0,0 +1,55 @@
|
|
1
|
+
== slim :chart_template
|
2
|
+
.row
|
3
|
+
.chart-menu
|
4
|
+
ul.section.table-of-contents
|
5
|
+
li
|
6
|
+
a href="#top" Top
|
7
|
+
li
|
8
|
+
a href="#path" Path
|
9
|
+
li
|
10
|
+
a href="#time" Time
|
11
|
+
|
12
|
+
h3.white-text.center API
|
13
|
+
|
14
|
+
h4.col.s12.white-text.center id="top" Top
|
15
|
+
.col.s12.card.padding.z-depth-4
|
16
|
+
== bubble_chart(faststats_top('gitlab-rails/api_json.log', :project_stats), xtitle:'Duration', ytitle:'% Count', label: "Total", title: 'by Project')
|
17
|
+
.col.s12.padding
|
18
|
+
.legend X: Duration
|
19
|
+
.legend.red Y: % of total calls
|
20
|
+
.legend.blue Size: Total Calls
|
21
|
+
|
22
|
+
|
23
|
+
.col.s12.card.padding.z-depth-4
|
24
|
+
== bubble_chart(faststats_top('gitlab-rails/api_json.log', :user_stats), xtitle:'Duration', ytitle:'% Count', label: "Total", title: 'by User')
|
25
|
+
.col.s12.padding
|
26
|
+
.legend X: Duration
|
27
|
+
.legend.red Y: % of total calls
|
28
|
+
.legend.blue Size: Total Calls
|
29
|
+
|
30
|
+
.col.s12.card.padding.z-depth-4
|
31
|
+
== pie_chart(api_duration_pie, title: 'Duration Total')
|
32
|
+
|
33
|
+
h4.col.s12.white-text.center id="path" Path
|
34
|
+
.col.s12.card.padding.z-depth-4
|
35
|
+
== pie_chart(faststats_field('gitlab-rails/api_json.log', :count), title: 'Total by Path')
|
36
|
+
|
37
|
+
.col.s12.card.padding.z-depth-4
|
38
|
+
== column_chart(faststats_field('gitlab-rails/api_json.log',:p95), title: 'p95', ytitle: 'ms')
|
39
|
+
|
40
|
+
.col.s12.card.padding.z-depth-4
|
41
|
+
== column_chart(faststats_field('gitlab-rails/api_json.log',:median), title: 'Median', ytitle: 'ms')
|
42
|
+
|
43
|
+
h4.col.s12.white-text.center id="time" Over Time
|
44
|
+
|
45
|
+
.col.s12.card.padding.z-depth-4
|
46
|
+
== area_chart(api_avg_path_duration_series, title: 'Path Duration', ytitle: 'seconds')
|
47
|
+
|
48
|
+
.col.s12.card.padding.z-depth-4
|
49
|
+
== area_chart(api_avg_duration_series, title: 'Avg Duration', ytitle: 'ms')
|
50
|
+
|
51
|
+
.col.s12.card.padding.z-depth-4
|
52
|
+
== column_chart(api_duration_series_stacked, stacked: true, title: 'Duration Breakdown', ytitle: 'seconds')
|
53
|
+
|
54
|
+
.col.s12.card.padding.z-depth-4
|
55
|
+
== area_chart(api_duration_series_stacked, stacked: true, title: 'Duration Breakdown', ytitle: 'seconds')
|
@@ -0,0 +1,42 @@
|
|
1
|
+
doctype html
|
2
|
+
html
|
3
|
+
head
|
4
|
+
== slim :headers
|
5
|
+
body.grey.darken-4
|
6
|
+
== slim :css
|
7
|
+
|
8
|
+
nav.blue-grey.darken-4
|
9
|
+
.nav-wrapper
|
10
|
+
a.brand-logo.center href="/" Charts Home
|
11
|
+
ul.left.white-text
|
12
|
+
li
|
13
|
+
a href ='/'
|
14
|
+
.btn-flat.white-text
|
15
|
+
i.fa.fa-home.left.line-height
|
16
|
+
| Home
|
17
|
+
|
18
|
+
li
|
19
|
+
a href ='/chart'
|
20
|
+
.btn-flat.white-text
|
21
|
+
i.fa.fa-chart-pie.left.line-height
|
22
|
+
| Charts
|
23
|
+
li
|
24
|
+
a href ='/chart/time'
|
25
|
+
.btn-flat.white-text
|
26
|
+
i.fa.fa-chart-line.left.line-height
|
27
|
+
| Time Query
|
28
|
+
|
29
|
+
.container.padding
|
30
|
+
.row
|
31
|
+
h5.white-text.center Dashboards
|
32
|
+
.row
|
33
|
+
.col.s4.padding
|
34
|
+
a.blue.btn-large.chart-btn href="/charts/gitaly" Gitaly
|
35
|
+
.col.s4.padding
|
36
|
+
a.green.btn-large.chart-btn href="/charts/sidekiq" Sidekiq
|
37
|
+
.col.s4.padding
|
38
|
+
a.red.btn-large.chart-btn href="/charts/api" Api
|
39
|
+
.col.s4.padding
|
40
|
+
a.purple.btn-large.chart-btn href="/charts/production" Production
|
41
|
+
.col.s4.padding
|
42
|
+
a.teal.btn-large.chart-btn href="/charts/workhorse" Workhorse
|